[education/rkward/releases/0.8.3] rkward: Add wrapper around QCoreApplication::applicationDirPath()

Thomas Friedrichsmeier null at kde.org
Fri Oct 30 15:06:43 GMT 2026


Git commit 7679584436cc93fcfdcc9683b8b19a5d3d266089 by Thomas Friedrichsmeier.
Committed on 30/10/2026 at 15:06.
Pushed by tfry into branch 'releases/0.8.3'.

Add wrapper around QCoreApplication::applicationDirPath()

With newer builds, this would return a wrong path when running from AppImage.

M  +3    -3    rkward/main.cpp
M  +14   -1    rkward/misc/rkcommonfunctions.cpp
M  +3    -0    rkward/misc/rkcommonfunctions.h
M  +12   -11   rkward/rbackend/rkfrontendtransmitter.cpp

https://invent.kde.org/education/rkward/-/commit/7679584436cc93fcfdcc9683b8b19a5d3d266089

diff --git a/rkward/main.cpp b/rkward/main.cpp
index ada3a2d31..36af23404 100644
--- a/rkward/main.cpp
+++ b/rkward/main.cpp
@@ -242,7 +242,7 @@ int main(int argc, char *argv[]) {
 	}
 #elif defined(Q_OS_UNIX)
 	QStringList data_dirs = QString::fromLocal8Bit(qgetenv("XDG_DATA_DIRS")).split(PATH_VAR_SEP);
-	QString reldatadir = QDir::cleanPath(QDir(app.applicationDirPath()).absoluteFilePath(QStringLiteral(REL_PATH_TO_DATA)));
+	QString reldatadir = QDir::cleanPath(QDir(RKCommonFunctions::getRKWardAppDir()).absoluteFilePath(QStringLiteral(REL_PATH_TO_DATA)));
 	if (!data_dirs.contains(reldatadir)) {
 		RK_DEBUG(APP, DL_WARNING, "Running from non-standard path? Adding %s to XDG_DATA_DIRS", qPrintable(reldatadir));
 		data_dirs.prepend(reldatadir);
@@ -251,8 +251,8 @@ int main(int argc, char *argv[]) {
 #endif
 	// This is _not_ the same path adjustment as above: Make sure to add the current dir to the path, before launching R and backend.
 	QStringList syspaths = QString::fromLocal8Bit(qgetenv("PATH")).split(PATH_VAR_SEP);
-	if (!syspaths.contains(app.applicationDirPath())) {
-		syspaths.prepend(app.applicationDirPath());
+	if (!syspaths.contains(RKCommonFunctions::getRKWardAppDir())) {
+		syspaths.prepend(RKCommonFunctions::getRKWardAppDir());
 		qputenv("PATH", syspaths.join(PATH_VAR_SEP).toLocal8Bit());
 	}
 
diff --git a/rkward/misc/rkcommonfunctions.cpp b/rkward/misc/rkcommonfunctions.cpp
index 07cfd89bf..e46a015fc 100644
--- a/rkward/misc/rkcommonfunctions.cpp
+++ b/rkward/misc/rkcommonfunctions.cpp
@@ -162,7 +162,7 @@ void getCurrentSymbolOffset(const QString &context_line, int cursor_pos, bool st
 
 static QString findPathFromAppDir(const QStringList &candidates) {
 	for (int i = 0; i < candidates.size(); ++i) {
-		QString candidate = QCoreApplication::applicationDirPath() + u'/' + candidates[i] + u'/';
+		QString candidate = getRKWardAppDir() + u'/' + candidates[i] + u'/';
 		if (QFile::exists(candidate)) return candidate;
 	}
 	return QString();
@@ -192,6 +192,19 @@ QString getRKWardDataDir() {
 	return rkward_data_dir;
 }
 
+QString getRKWardAppDir() {
+	static QString rkward_app_dir;
+	if (rkward_app_dir.isNull()) {
+		rkward_app_dir = QCoreApplication::applicationDirPath();
+		const auto appdir = QString::fromLocal8Bit(qgetenv("APPDIR"));
+		if (rkward_app_dir.startsWith(appdir) && !appdir.isEmpty() && !QFile::exists(rkward_app_dir + u"/rkward"_s)) {
+			RK_DEBUG(APP, DL_INFO, "Running in Appimage with bad applicationDirPath() - workaround applied");
+			rkward_app_dir = appdir + u"/usr/bin"_s;
+		}
+	}
+	return rkward_app_dir;
+}
+
 QString escape(const QString &in) {
 	QString out;
 
diff --git a/rkward/misc/rkcommonfunctions.h b/rkward/misc/rkcommonfunctions.h
index 737fe032c..b78df3f86 100644
--- a/rkward/misc/rkcommonfunctions.h
+++ b/rkward/misc/rkcommonfunctions.h
@@ -32,6 +32,9 @@ void moveContainer(KXMLGUIClient *client, const QString &tagname, const QString
 /** Get the base directory where RKWard data files are stored */
 QString getRKWardDataDir();
 
+/** Get the directory of the RKWard binary (usually the same as QCoreApplication::applicationDirPath(), but may differ in AppImage) */
+QString getRKWardAppDir();
+
 /** given a context line, find the end of a quote started by quote_char. @returns -1 if not end of quote was found. */
 int quoteEndPosition(const QChar &quote_char, const QString &haystack, int from = 0);
 
diff --git a/rkward/rbackend/rkfrontendtransmitter.cpp b/rkward/rbackend/rkfrontendtransmitter.cpp
index d349f0041..e4887519b 100644
--- a/rkward/rbackend/rkfrontendtransmitter.cpp
+++ b/rkward/rbackend/rkfrontendtransmitter.cpp
@@ -8,6 +8,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "rkfrontendtransmitter.h"
 
 #include "../misc/rkcommandlineargs.h"
+#include "../misc/rkcommonfunctions.h"
 #include "../settings/rksettingsmodulegeneral.h"
 #include "../settings/rksettingsmoduler.h"
 #include "rkrbackendprotocol_frontend.h"
@@ -142,7 +143,7 @@ void RKFrontendTransmitter::detectAndCheckRBinary() {
 		RK_DEBUG(APP, DL_DEBUG, "Using R as previously user-configured");
 		r_exe = RKSettingsModuleR::userConfiguredRBinary();
 	} else {
-		QDir frontend_path = qApp->applicationDirPath();
+		QDir frontend_path = RKCommonFunctions::getRKWardAppDir();
 		QFileInfo rkward_ini_file(frontend_path.absoluteFilePath(QStringLiteral("rkward.ini")));
 		if (rkward_ini_file.isReadable()) {
 			QSettings rkward_ini(rkward_ini_file.absoluteFilePath(), QSettings::IniFormat);
@@ -204,24 +205,24 @@ void RKFrontendTransmitter::run() {
 		args += debugger.split(u' ');
 	}
 
-	QString backend_executable = findBackendAtPath(QCoreApplication::applicationDirPath());
+	QString backend_executable = findBackendAtPath(RKCommonFunctions::getRKWardAppDir());
 #ifdef Q_OS_MACOS
 	if (backend_executable.isEmpty())
 		backend_executable =
-		    findBackendAtPath(QCoreApplication::applicationDirPath() + u"/../Resources"_s); // an appropriate location in a standalone app-bundle
+		    findBackendAtPath(RKCommonFunctions::getRKWardAppDir() + u"/../Resources"_s); // an appropriate location in a standalone app-bundle
 #endif
 	if (backend_executable.isEmpty())
-		backend_executable = findBackendAtPath(QCoreApplication::applicationDirPath() + u"/rbackend"_s); // for running directly from the build-dir
+		backend_executable = findBackendAtPath(RKCommonFunctions::getRKWardAppDir() + u"/rbackend"_s); // for running directly from the build-dir
 	if (backend_executable.isEmpty())
-		backend_executable = findBackendAtPath(QCoreApplication::applicationDirPath() + u"/../rbackend"_s); // for running directly from the build-test-dir
+		backend_executable = findBackendAtPath(RKCommonFunctions::getRKWardAppDir() + u"/../rbackend"_s); // for running directly from the build-test-dir
 	if (backend_executable.isEmpty())
 		backend_executable =
-		    findBackendAtPath(QCoreApplication::applicationDirPath() + u"/"_s + QStringLiteral(REL_PATH_TO_LIBEXEC)); // as calculated from cmake
+		    findBackendAtPath(RKCommonFunctions::getRKWardAppDir() + u"/"_s + QStringLiteral(REL_PATH_TO_LIBEXEC)); // as calculated from cmake
 #ifdef Q_OS_MACOS
-	if (backend_executable.isEmpty()) backend_executable = findBackendAtPath(QCoreApplication::applicationDirPath() + u"/../../../rbackend"_s);
+	if (backend_executable.isEmpty()) backend_executable = findBackendAtPath(RKCommonFunctions::getRKWardAppDir() + u"/../../../rbackend"_s);
 	if (backend_executable.isEmpty())
 		backend_executable =
-		    findBackendAtPath(QCoreApplication::applicationDirPath() + u"/../Frameworks/libexec"_s); // For running from .dmg created by craft --package rkward
+		    findBackendAtPath(RKCommonFunctions::getRKWardAppDir() + u"/../Frameworks/libexec"_s); // For running from .dmg created by craft --package rkward
 #endif
 	if (backend_executable.isEmpty()) backend_executable = findBackendAtPath(QStringLiteral(RKWARD_BACKEND_PATH));
 	if (backend_executable.isEmpty()) {
@@ -232,14 +233,14 @@ void RKFrontendTransmitter::run() {
 
 #if defined(RK_DLOPEN_LIBRSO)
 	/** NOTE: For a description of the rationale for this involved loading procedure rkapi.h ! */
-	QString backend_lib = findBackendLibAtPath(QCoreApplication::applicationDirPath()); // for running directly from the build tree, but also covers windows
+	QString backend_lib = findBackendLibAtPath(RKCommonFunctions::getRKWardAppDir()); // for running directly from the build tree, but also covers windows
 	if (backend_lib.isEmpty())
-		backend_lib = findBackendLibAtPath(QCoreApplication::applicationDirPath() + u"/"_s + QStringLiteral(REL_PATH_TO_LIB)); // regular installation; rel path between bin and lib dir is calculated in cmake
+		backend_lib = findBackendLibAtPath(RKCommonFunctions::getRKWardAppDir() + u"/"_s + QStringLiteral(REL_PATH_TO_LIB)); // regular installation; rel path between bin and lib dir is calculated in cmake
 	if (backend_lib.isEmpty())
 		backend_lib = findBackendLibAtPath(QFileInfo(backend_executable).absolutePath()); // backend and lib both installed in libexec or similar
 #	if defined(Q_OS_MACOS)
 	if (backend_lib.isEmpty())
-		backend_lib = findBackendLibAtPath(QCoreApplication::applicationDirPath() + u"/../Frameworks"_s); // MacOS bundle: rkward in /MacOS, lib in /Framweorks
+		backend_lib = findBackendLibAtPath(RKCommonFunctions::getRKWardAppDir() + u"/../Frameworks"_s); // MacOS bundle: rkward in /MacOS, lib in /Framweorks
 #	endif
 #	if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
 	env.append(QStringLiteral("RK_BACKEND_LIB=") + backend_lib);


More information about the rkward-tracker mailing list