[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 "e_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