[education/rkward] rkward: Some more restructuring, and start adding backend selection page.

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


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

Some more restructuring, and start adding backend selection page.

M  +60   -36   rkward/dialogs/rksetupwizard.cpp
M  +0    -4    rkward/dialogs/rksetupwizard.h
M  +3    -14   rkward/misc/rkprogresscontrol.cpp
M  +0    -1    rkward/misc/rkprogresscontrol.h
M  +19   -0    rkward/misc/rkstandardicons.cpp
M  +4    -1    rkward/misc/rkstandardicons.h

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

diff --git a/rkward/dialogs/rksetupwizard.cpp b/rkward/dialogs/rksetupwizard.cpp
index 15724be59..37af06084 100644
--- a/rkward/dialogs/rksetupwizard.cpp
+++ b/rkward/dialogs/rksetupwizard.cpp
@@ -18,6 +18,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include <QTimer>
 #include <QFileInfo>
 #include <QStandardPaths>
+#include <QRadioButton>
+#include <QGroupBox>
 
 #include <KLocalizedString>
 #include <KMessageBox>
@@ -85,15 +87,18 @@ public:
 
 bool RKSetupWizard::has_been_run = false;
 
-void RKSetupWizardItem::createWidget(QGridLayout *layout, int row) {
+static auto iconForStatus(RKSetupWizardItem::Status status) {
 	QString icon_id;
-	if (status == Good) icon_id = QLatin1String("dialog-positive");
-	else if (status == Warning) icon_id = QLatin1String("dialog-warning");
+	if (status == RKSetupWizardItem::Good) icon_id = QLatin1String("dialog-positive");
+	else if (status == RKSetupWizardItem::Warning) icon_id = QLatin1String("dialog-warning");
 	else icon_id = QLatin1String("dialog-error");
+	return (QIcon::fromTheme(icon_id).pixmap(32, 32));  // TODO: Correct way to not hardcode size?
+}
+
+void RKSetupWizardItem::createWidget(QGridLayout *layout, int row) {
 	auto label = new QLabel();
-	label->setPixmap(QIcon::fromTheme(icon_id).pixmap(32, 32));  // TODO: Correct way to not hardcode size?
+	label->setPixmap(iconForStatus(status));
 	layout->addWidget(label, row, 0);
-
 	layout->addWidget(new QLabel(shortlabel + ": " + shortstatuslabel), row, 1);
 
 	if (options.isEmpty()) {
@@ -165,8 +170,8 @@ RKSetupWizard::RKSetupWizard(QWidget* parent, InvokationReason reason, const QLi
 	RK_TRACE (DIALOGS);
 
 	// Cover page
-	auto firstpage = new RKSetupWizardPage(this, i18n("RKWard Setup Assistant"));
-	auto l = new QVBoxLayout(firstpage);
+	auto page = new RKSetupWizardPage(this, i18n("RKWard Setup Assistant"));
+	auto l = new QVBoxLayout(page);
 	QString intro = i18n("<p>This dialog will guide you through a quick check of the basic setup of the required (or recommended) components.</p>");
 	if (reason == NewVersionRKWard) {
 		intro += i18n("<p>The setup assistant has been invoked, automatically, because a new version of RKWard has been detected.</p>");
@@ -177,13 +182,10 @@ RKSetupWizard::RKSetupWizard(QWidget* parent, InvokationReason reason, const QLi
 		intro += i18n("<p>The setup assistant has been invoked, automatically, because a problem has been detected in your setup.</p>");
 	}
 	l->addWidget(RKCommonFunctions::wordWrappedLabel(intro));
-	waiting_to_start_label = RKCommonFunctions::wordWrappedLabel(i18n("<b>Waiting for R backend...</b>") + "<p> </p><p> </p>");
-	l->addWidget(waiting_to_start_label);
-	firstpageref = firstpage->ref;;
-	setValid(firstpageref, false);
+	l->addStretch();
 
 	// Basic installation page
-	auto page = new RKSetupWizardPage(this, i18n("Basic installation"));
+	page = new RKSetupWizardPage(this, i18n("Basic installation"));
 	reinstallation_required = false;
 	auto idir = new RKSetupWizardItem(i18n("Installation directory"));
 	if (RKCommonFunctions::getRKWardDataDir ().isEmpty ()) {
@@ -239,13 +241,56 @@ RKSetupWizard::RKSetupWizard(QWidget* parent, InvokationReason reason, const QLi
 	page->addStretch();
 
 	// The following pages need the R backend, and are thus initialized lazily
-
 	// R backend page
 	page = new RKSetupWizardPage(this, i18n("R Backend"));
-	page->lazyInitOnce([](RKSetupWizardPage *p) {
+	page->lazyInitOnce([this](RKSetupWizardPage *p) {
 		auto l = new QVBoxLayout(p);
-		l->addWidget(new QLabel(i18n("R backend info, here")));
+		l->addWidget(new QLabel(i18n("RKWard is currently using the R installation at <nobr>%1</nobr>.", RKSessionVars::RBinary())));
+		auto h = new QHBoxLayout();
+		l->addLayout(h);
+		auto rstatus_label = RKCommonFunctions::wordWrappedLabel(i18n("<b>Waiting for R backend...</b>"));
+		auto rstatus_icon = new QLabel();
+		auto anim = RKStandardIcons::busyAnimation(rstatus_icon, [rstatus_icon](const QIcon& icon) {
+			rstatus_icon->setPixmap(icon.pixmap(32, 32));
+		});
+		h->addWidget(rstatus_icon);
+		h->addWidget(rstatus_label);
+		h->setStretch(1, 2);
 		l->addStretch();
+		auto pageref = p->ref;
+		setValid(pageref, false);
+		auto statuslambda = [this, pageref, rstatus_label, rstatus_icon, anim, l]() {
+			if (!(RInterface::instance()->backendIsDead() || RInterface::instance()->backendIsIdle())) return;
+
+			anim->stop();
+			if (RInterface::instance()->backendIsDead()) {
+				rstatus_icon->setPixmap(iconForStatus(RKSetupWizardItem::Error));
+				rstatus_label->setText(i18n("<b>R backend has crashed.</b>"));
+			} else {
+				RK_ASSERT(RInterface::instance()->backendIsIdle());
+				QString statustext = i18n("<b>R version %1 started, successfully.</b>", RKSessionVars::RVersion(false));
+				if (RKSessionVars::isPathInAppImage(RKSessionVars::RBinary())) {
+					rstatus_icon->setPixmap(iconForStatus(RKSetupWizardItem::Warning));
+					statustext.append(i18n("<p>You are using the R version bundled inside the RKWard AppImage.</p>"
+					                       "<p>This version comes with several technical limitations. Importantly, "
+					                       "yu will not be able to install most R addon packages. "
+					                       "In general, it is therefore recommended to select a system-installed "
+					                       "version of R, instead, below.</p>"));
+				} else {
+					rstatus_icon->setPixmap(iconForStatus(RKSetupWizardItem::Good));
+				}
+				rstatus_label->setText(statustext);
+				setValid(pageref, true);
+			}
+
+			auto box = new QGroupBox(i18n("R version to use"));
+			l->addWidget(box);
+			auto bl = new QVBoxLayout(box);
+			auto button = new QRadioButton(i18n("Keep current version"), box); bl->addWidget(button);
+			button = new QRadioButton(i18n("Some dummy option, TODO"), box); bl->addWidget(button);
+		};
+		connect(RInterface::instance(), &RInterface::backendStatusChanged, this, statuslambda);
+		statuslambda();
 	});
 
 	// R packages page
@@ -312,27 +357,6 @@ RKSetupWizard::RKSetupWizard(QWidget* parent, InvokationReason reason, const QLi
 		int new_height = qMax(height(), spare_height+last_page_label->minimumSizeHint().height());
 		resize(width(), new_height);
 	});
-
-	// Next we'll want to wait for the R backend to start up. Previous solution was to set Qt::ApplicationModal, and wait, calling processEvents().
-	// This does not seem to work well on mac, however, so instead we return, here, so exec will be called from outside, then fire a timer to finish constuction.
-	QTimer::singleShot(10, this, &RKSetupWizard::setupWizardPhase2);
-}
-
-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);
-		}
-		return;
-	}
-	RK_TRACE(APP);
-
-	waiting_to_start_label->setText(i18n("<b>R backend has started. Click \"Next\" to continue.</b>"));
-	setValid(firstpageref, true);
 }
 
 RKSetupWizard::~RKSetupWizard() {
diff --git a/rkward/dialogs/rksetupwizard.h b/rkward/dialogs/rksetupwizard.h
index fad6831c3..aa0494a01 100644
--- a/rkward/dialogs/rksetupwizard.h
+++ b/rkward/dialogs/rksetupwizard.h
@@ -37,10 +37,6 @@ public:
 	void markSoftwareForInstallation(const QString &name, const QString &download_url, bool install);
 	void markRPackageForInstallation(const QString &name, bool install);
 private:
-	void setupWizardPhase2();
-	KPageWidgetItem* firstpageref;
-	QLabel* waiting_to_start_label;
-
 	QStringList software_to_install;
 	QStringList software_to_install_urls;
 	QStringList packages_to_install;
diff --git a/rkward/misc/rkprogresscontrol.cpp b/rkward/misc/rkprogresscontrol.cpp
index d4c1e9bd5..2cd30d03e 100644
--- a/rkward/misc/rkprogresscontrol.cpp
+++ b/rkward/misc/rkprogresscontrol.cpp
@@ -1,6 +1,6 @@
 /*
 rkprogresscontol - This file is part of RKWard (https://rkward.kde.org). Created: Sun Sep 10 2006
-SPDX-FileCopyrightText: 2006-2011 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+SPDX-FileCopyrightText: 2006-2024 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
 SPDX-FileContributor: The RKWard Team <rkward-devel at kde.org>
 SPDX-License-Identifier: GPL-2.0-or-later
 */
@@ -503,20 +503,9 @@ void RKInlineProgressControl::show(int delay_ms) {
 	} else {
 		wrapper->show();
 	}
-	animation_step = 0;
-	message_widget->setIcon(RKStandardIcons::getIcon(RKStandardIcons::RKWardIcon));
-	auto t = new QTimer(this);
-	t->setInterval(750);
-	connect(t, &QTimer::timeout, this, [this]() {
-		if (is_done) return;
-		animation_step = (animation_step + 1) % 2;
-		if (animation_step) {
-			message_widget->setIcon(QIcon::fromTheme("computer-symbolic"));
-		} else {
-			message_widget->setIcon(RKStandardIcons::getIcon(RKStandardIcons::RKWardIcon));
-		}
+	RKStandardIcons::busyAnimation(this, [this](const QIcon &icon) {
+		if (!is_done) message_widget->setIcon(icon);
 	});
-	t->start();
 }
 
 bool RKInlineProgressControl::eventFilter(QObject *w, QEvent *e) {
diff --git a/rkward/misc/rkprogresscontrol.h b/rkward/misc/rkprogresscontrol.h
index 81bf250a5..c1b184577 100644
--- a/rkward/misc/rkprogresscontrol.h
+++ b/rkward/misc/rkprogresscontrol.h
@@ -125,7 +125,6 @@ private:
 	bool allow_cancel;
 	bool is_done;
 	bool any_failed;
-	int animation_step;
 	QWidget* wrapper;
 	QWidget* display_area;
 	KMessageWidget *message_widget;
diff --git a/rkward/misc/rkstandardicons.cpp b/rkward/misc/rkstandardicons.cpp
index 58f6099a4..a63fd3d23 100644
--- a/rkward/misc/rkstandardicons.cpp
+++ b/rkward/misc/rkstandardicons.cpp
@@ -186,3 +186,22 @@ QIcon RKStandardIcons::iconForWindow (const RKMDIWindow* window) {
 	RK_ASSERT (false);
 	return QIcon ();
 }
+
+QTimer *RKStandardIcons::busyAnimation(QObject *parent, std::function<void (const QIcon &)> setter) {
+	RK_TRACE (APP);
+
+	setter(getIcon(RKWardIcon));
+	auto t = new QTimer(parent);
+	t->setInterval(750);
+	int animation_step = 0;
+	QObject::connect(t, &QTimer::timeout, parent, [setter, animation_step]() mutable {
+		animation_step = (animation_step + 1) % 2;
+		if (animation_step) {
+			setter(QIcon::fromTheme("computer-symbolic"));
+		} else {
+			setter(getIcon(RKWardIcon));
+		}
+	});
+	t->start();
+	return t;
+}
diff --git a/rkward/misc/rkstandardicons.h b/rkward/misc/rkstandardicons.h
index 610476c8f..0c7078018 100644
--- a/rkward/misc/rkstandardicons.h
+++ b/rkward/misc/rkstandardicons.h
@@ -1,6 +1,6 @@
 /*
 rkstandardicons - This file is part of the RKWard project. Created: Wed Oct 24 2007
-SPDX-FileCopyrightText: 2007-2018 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+SPDX-FileCopyrightText: 2007-2024 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
 SPDX-FileContributor: The RKWard Team <rkward-devel at kde.org>
 SPDX-License-Identifier: GPL-2.0-or-later
 */
@@ -120,6 +120,9 @@ public:
 
 	/** convenience function to get the icon most suited for the given RKMDIWindow */
 	static QIcon iconForWindow (const RKMDIWindow* window);
+
+	/** create a "busy" animation that will cycle through appropriate items using the "setter" function */
+	static QTimer* busyAnimation(QObject *parent, std::function<void(const QIcon &)> setter);
 private:
 	// NOTE: Using a static array of QIcons lead to crashes on exit (Qt 5.4.1). Moving that inside a class instance seems to fix the issue.
 	QIcon icons[Last];



More information about the rkward-tracker mailing list