[education/rkward] rkward: Move appimage detection logic to RKSessionVars

Thomas Friedrichsmeier null at kde.org
Sat Jun 8 23:21:01 BST 2024


Git commit ab82673c4b4f9a701d0fefe1082882f45831e40e by Thomas Friedrichsmeier.
Committed on 08/06/2024 at 22:10.
Pushed by tfry into branch 'master'.

Move appimage detection logic to RKSessionVars

M  +7    -1    rkward/dialogs/rksetupwizard.cpp
M  +1    -0    rkward/main.cpp
M  +8    -7    rkward/rbackend/rkfrontendtransmitter.cpp
M  +9    -0    rkward/rbackend/rksessionvars.cpp
M  +3    -0    rkward/rbackend/rksessionvars.h

https://invent.kde.org/education/rkward/-/commit/ab82673c4b4f9a701d0fefe1082882f45831e40e

diff --git a/rkward/dialogs/rksetupwizard.cpp b/rkward/dialogs/rksetupwizard.cpp
index 044a5eb24..b220a97ff 100644
--- a/rkward/dialogs/rksetupwizard.cpp
+++ b/rkward/dialogs/rksetupwizard.cpp
@@ -202,6 +202,7 @@ void RKSetupWizard::setupWizardPhase2() {
 	// Wait for R Interface, then enable dialog
 	if (!RInterface::instance()->backendIsIdle()) {
 		if (RInterface::instance()->backendIsDead()) {
+			// TODO
 			waiting_to_start_label->setText(i18n("<b>R backend has crashed. Click \"Cancel\" to exit setup assistant.</b>"));
 		} else {
 			QTimer::singleShot(100, this, &RKSetupWizard::setupWizardPhase2);
@@ -213,9 +214,14 @@ void RKSetupWizard::setupWizardPhase2() {
 	waiting_to_start_label->setText(i18n("<b>R backend has started. Click \"Next\" to continue.</b>"));
 	setValid(firstpageref, true);
 
-	// R packages page
+	// R backend page
 	// This must be created _after_ the backend has started, for obvious reasons.
 	createStandardPage();
+	current_layout->addWidget(new QLabel(i18n("R backend info, here")));
+	addPage(current_page, i18n("R Backend"));
+
+	// R packages page
+	createStandardPage();
 
 	appendItem(makeRPackageCheck("R2HTML", i18n("The R2HTML package is used by nearly all RKWard output functions, and thus required."), RKSetupWizardItem::Error));
 	appendItem(makeRPackageCheck("rmarkdown", i18n("The rmarkdown package is required for rendering .Rmd files (including preview rendering), which is an optional but recommended feature."), RKSetupWizardItem::Warning));
diff --git a/rkward/main.cpp b/rkward/main.cpp
index 8029ccbb3..5f1ecb07d 100644
--- a/rkward/main.cpp
+++ b/rkward/main.cpp
@@ -391,6 +391,7 @@ int main (int argc, char *argv[]) {
 			stream >> urls;
 			stream >> nowarn;
 			if (call == QStringLiteral("openAnyUrl")) {
+				// We must not block while the frontend may potentially show a warning message (causing long delay)
 				QTimer::singleShot(0, main, [nowarn, urls, main]() {
 					main->openUrlsFromCommandLineOrExternal(nowarn.toBool(), urls.toStringList());
 				});
diff --git a/rkward/rbackend/rkfrontendtransmitter.cpp b/rkward/rbackend/rkfrontendtransmitter.cpp
index 8b4307e7c..43210b006 100644
--- a/rkward/rbackend/rkfrontendtransmitter.cpp
+++ b/rkward/rbackend/rkfrontendtransmitter.cpp
@@ -64,7 +64,7 @@ bool pathIsChildOf(const QString &parent, const QString &child) {
 	return QFileInfo(child).canonicalFilePath().startsWith(QFileInfo(parent).canonicalFilePath());
 }
 
-void removeFromPathList (const char* varname, const QString &path) {
+void removeFromPathList (const char* varname, bool (*shouldRemove)(const QString &path)) {
 #ifdef Q_OS_WIN
 #	define PATH_VAR_SEP ';'
 #else
@@ -76,7 +76,9 @@ void removeFromPathList (const char* varname, const QString &path) {
 	const auto list = QString::fromLocal8Bit(var).split(PATH_VAR_SEP);
 	QStringList newlist;
 	for(const auto &str : list) {
-		if (!pathIsChildOf(path, str)) {
+		if (shouldRemove(str)) {
+			RK_DEBUG(RBACKEND, DL_DEBUG, "Removing path %s from $%s", qPrintable(str), varname);
+		} else {
 			newlist.append(str);
 		}
 	}
@@ -127,11 +129,10 @@ void RKFrontendTransmitter::run () {
 	if (index >= 0) env.removeAt (index);
 	env.append ("LANGUAGE=" + QLocale ().name ().section ('_', 0, 0));
 
-	const auto appdir = QString::fromLocal8Bit(qgetenv("APPDIR"));
-	if (!appdir.isEmpty() && pathIsChildOf(appdir, RKSessionVars::RBinary())) {
-		RK_DEBUG(RBACKEND, DL_DEBUG, "Detected running from AppImage with external R. Removing paths in %s from (LD_LIBRARY_)PATH", qPrintable(appdir));
-		removeFromPathList("LD_LIBRARY_PATH", appdir);
-		removeFromPathList("PATH", appdir);
+	if (RKSessionVars::runningInAppImage() && RKSessionVars::isPathInAppImage(RKSessionVars::RBinary())) {
+		RK_DEBUG(RBACKEND, DL_DEBUG, "Detected running from AppImage with external R.");
+		removeFromPathList("LD_LIBRARY_PATH", RKSessionVars::isPathInAppImage);
+		removeFromPathList("PATH", RKSessionVars::isPathInAppImage);
 	}
 
 	QStringList args;
diff --git a/rkward/rbackend/rksessionvars.cpp b/rkward/rbackend/rksessionvars.cpp
index dd8fe89fc..b89c683ba 100644
--- a/rkward/rbackend/rksessionvars.cpp
+++ b/rkward/rbackend/rksessionvars.cpp
@@ -18,6 +18,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include <QTemporaryFile>
 #include <QStandardPaths>
 #include <QSysInfo>
+#include <QFileInfo>
 
 #include "../debug.h"
 
@@ -26,12 +27,15 @@ RKParsedVersion RKSessionVars::rkward_version(RKWARD_VERSION);
 RKParsedVersion RKSessionVars::r_version;
 QString RKSessionVars::r_version_string;
 QString RKSessionVars::r_binary;
+QString RKSessionVars::appimagedir;
 
 RKSessionVars::RKSessionVars (RInterface *parent) : QObject (parent) {
 	RK_TRACE (RBACKEND);
 	RK_ASSERT (!_instance);
 
 	_instance = this;
+	auto appdir = qgetenv("APPDIR");
+	if (!appdir.isEmpty()) appimagedir = QFileInfo(QString::fromLocal8Bit(appdir)).canonicalFilePath();
 }
 
 RKSessionVars::~RKSessionVars () {
@@ -40,6 +44,11 @@ RKSessionVars::~RKSessionVars () {
 	_instance = nullptr;
 }
 
+bool RKSessionVars::isPathInAppImage(const QString &path) {
+	if (!runningInAppImage()) return false;
+	return QFileInfo(path).canonicalFilePath().startsWith(appimagedir);
+}
+
 void RKSessionVars::setInstalledPackages (const QStringList &new_list) {
 	RK_TRACE (RBACKEND);
 
diff --git a/rkward/rbackend/rksessionvars.h b/rkward/rbackend/rksessionvars.h
index c60ba3809..e88832d85 100644
--- a/rkward/rbackend/rksessionvars.h
+++ b/rkward/rbackend/rksessionvars.h
@@ -35,6 +35,8 @@ Anything else (everything after the fourth dot, or after the first character tha
 is returned as suffix (via the suffix pointer; if that is 0, an error is reported, instead). */
 	static QStringList frontendSessionInfo ();
 	static QString RBinary() { return r_binary; }
+	static bool runningInAppImage() { return !appimagedir.isNull(); }
+	static bool isPathInAppImage(const QString &path);
 Q_SIGNALS:
 	void installedPackagesChanged ();
 protected:
@@ -48,6 +50,7 @@ private:
 	static RKParsedVersion rkward_version;
 	static RKParsedVersion r_version;
 	static QString r_version_string;
+	static QString appimagedir;
 friend int main(int, char**);
 friend class RKWardCoreTest;
 	static QString r_binary;



More information about the rkward-tracker mailing list