[education/rkward] rkward: Move all command-line option handling to dedicated class
Thomas Friedrichsmeier
null at kde.org
Sat Jun 8 23:21:01 BST 2024
Git commit cd57c549ca32c7e514e220fcd0929234d14f2b69 by Thomas Friedrichsmeier.
Committed on 08/06/2024 at 22:08.
Pushed by tfry into branch 'master'.
Move all command-line option handling to dedicated class
M +12 -40 rkward/main.cpp
M +1 -0 rkward/misc/CMakeLists.txt
A +63 -0 rkward/misc/rkcommandlineargs.cpp [License: GPL(v2.0+)]
A +51 -0 rkward/misc/rkcommandlineargs.h [License: GPL(v2.0+)]
M +3 -2 rkward/rbackend/rkfrontendtransmitter.cpp
M +5 -4 rkward/rkward.cpp
M +0 -2 rkward/settings/rksettingsmodulegeneral.cpp
M +0 -6 rkward/settings/rksettingsmodulegeneral.h
https://invent.kde.org/education/rkward/-/commit/cd57c549ca32c7e514e220fcd0929234d14f2b69
diff --git a/rkward/main.cpp b/rkward/main.cpp
index 000e28fb2..b16d7a9b1 100644
--- a/rkward/main.cpp
+++ b/rkward/main.cpp
@@ -1,6 +1,6 @@
/*
main.cpp - This file is part of RKWard (https://rkward.kde.org). Created: Tue Oct 29 2002
-SPDX-FileCopyrightText: 2002-2023 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+SPDX-FileCopyrightText: 2002-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
*/
@@ -60,7 +60,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include <QThread>
#include <QApplication>
#include <QUrl>
-#include <QCommandLineParser>
#include <QTime>
#include <QSettings>
#include <QStandardPaths>
@@ -83,6 +82,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include "windows/rkdebugmessagewindow.h"
#include "misc/rkcommonfunctions.h"
#include "../3rdparty/KDSingleApplication/kdsingleapplication.h"
+#include "misc/rkcommandlineargs.h"
#ifdef Q_OS_WIN
// these are needed for the exit hack.
@@ -279,51 +279,23 @@ int main (int argc, char *argv[]) {
aboutData.setOtherText(QString("<p><b>%1</b></p><ul><li><a href=\"https://www.jstatsoft.org/article/view/v049i09\">%2</a></li><li>Friedrichsmeier, T. & the RKWard Team (%3). RKWard: %4. Version %5. %6</li></ul>").arg(i18n("How to cite:"), i18n("Peer-reviewed article in the Journal of Statistical Software"), aboutData.copyrightStatement().right(4), aboutData.shortDescription(), aboutData.version(), aboutData.homepage()));
KAboutData::setApplicationData (aboutData);
- QCommandLineParser parser;
- aboutData.setupCommandLine(&parser);
- parser.addOption (QCommandLineOption ("evaluate", i18n ("After starting (and after loading the specified workspace, if applicable), evaluate the given R code."), "Rcode", QString ()));
- parser.addOption (QCommandLineOption ("debug-level", i18n ("Verbosity of debug messages (0-5)"), "level", "2"));
- parser.addOption (QCommandLineOption ("debug-flags", i18n ("Mask for components to debug (see debug.h)"), "flags", QString::number (DEBUG_ALL)));
- parser.addOption (QCommandLineOption ("debug-output", i18n ("Where to send debug message (file|terminal)"), "where", "file"));
- parser.addOption (QCommandLineOption ("backend-debugger", i18n ("Debugger for the backend. (Enclose any debugger arguments in single quotes ('') together with the command. Make sure to re-direct stdout!)"), "command", QString ()));
- parser.addOption (QCommandLineOption ("r-executable", i18n ("Use specified R installation, instead of the one configured at compile time (note: rkward R library must be installed to that installation of R)"), "command", QString ()));
- parser.addOption (QCommandLineOption ("reuse", i18n ("Reuse a running RKWard instance (if available). If a running instance is reused, only the file arguments will be interpreted, all other options will be ignored.")));
- parser.addOption (QCommandLineOption ("autoreuse", i18n ("Behaves like --reuse, if any file arguments are also given, starts a new instance, otherwise. Intended for use in the .desktop file.")));
- parser.addOption (QCommandLineOption ("nowarn-external", i18n ("When used in conjunction with rkward://runplugin/-URLs specified on the command line, suppresses the warning about application-external (untrusted) links.")));
- parser.addOption(QCommandLineOption("quirkmode", i18n("Disable some startup validation code. Experimental option, not intended for regular use.")));
- parser.addPositionalArgument ("files", i18n ("File or files to open, typically a workspace, or an R script file. When loading several things, you should specify the workspace, first."), "[Files...]");
-
- parser.process (app);
- aboutData.processCommandLine (&parser);
+ RKCommandLineArgs args(&aboutData, app);
// Set up debugging
- RK_Debug::RK_Debug_Level = DL_FATAL - QString (parser.value ("debug-level")).toInt ();
- RK_Debug::RK_Debug_Flags = QString (parser.value ("debug-flags")).toInt ();
- RK_Debug_Terminal = QString (parser.value ("debug-output")) == "terminal";
- if (RK_Debug::setupLogFile (QDir::tempPath () + "/rkward.frontend")) {
- RK_DEBUG (APP, DL_INFO, "Full debug output is at %s", qPrintable (RK_Debug::debug_file->fileName ()));
+ RK_Debug::RK_Debug_Level = DL_FATAL - args[RKCommandLineArgs::DebugLevel].toInt();
+ RK_Debug::RK_Debug_Flags = args[RKCommandLineArgs::DebugFlags].toInt();
+ RK_Debug_Terminal = args[RKCommandLineArgs::DebugOutput].toString() == QLatin1String("terminal");
+ if (RK_Debug::setupLogFile(QDir::tempPath() + "/rkward.frontend")) {
+ RK_DEBUG(APP, DL_INFO, "Full debug output is at %s", qPrintable(RK_Debug::debug_file->fileName()));
} else {
RK_Debug_Terminal = true;
- RK_DEBUG (APP, DL_INFO, "Failed to open debug file %s", qPrintable (RK_Debug::debug_file->fileName ()));
+ RK_DEBUG(APP, DL_INFO, "Failed to open debug file %s", qPrintable(RK_Debug::debug_file->fileName()));
}
- qInstallMessageHandler (RKDebugMessageOutput);
+ qInstallMessageHandler(RKDebugMessageOutput);
RK_DO({
RK_DEBUG(APP, DL_DEBUG, "Basic runtime info (expected to be incomplete at this stage):\n%s", qPrintable(RKSessionVars::frontendSessionInfo().join("\n")));
}, APP, DL_DEBUG);
- // handle positional (file) arguments, first
- QStringList url_args = parser.positionalArguments ();
- if (!url_args.isEmpty ()) {
- for (int i = 0; i < url_args.size (); ++i) {
- url_args[i] = QUrl::fromUserInput (url_args[i], QDir::currentPath (), QUrl::AssumeLocalFile).toString ();
- }
- RKSettingsModuleGeneral::setStartupOption("initial_urls", url_args);
- RKSettingsModuleGeneral::setStartupOption("warn_external", !parser.isSet("nowarn-external"));
- }
- RKSettingsModuleGeneral::setStartupOption("evaluate", parser.value("evaluate"));
- RKSettingsModuleGeneral::setStartupOption("backend-debugger", parser.value("backend-debugger"));
- RKSettingsModuleGeneral::setStartupOption("quirkmode", parser.isSet("quirkmode"));
-
// MacOS may need some path adjustments, first
#if defined(Q_OS_MACOS)
QString oldpath = qgetenv ("PATH");
@@ -349,7 +321,7 @@ int main (int argc, char *argv[]) {
}
// Handle --reuse option, by forwarding url arguments to existing RKWard process (if any) and exiting
- if (parser.isSet ("reuse") || (parser.isSet ("autoreuse") && !url_args.isEmpty ())) {
+ if (args[RKCommandLineArgs::Reuse].toBool() || (args[RKCommandLineArgs::AutoReuse].toBool() && !args[RKCommandLineArgs::UrlArgs].toStringList().isEmpty())) {
if (!app_singleton.isPrimaryInstance()) {
QByteArray call;
QDataStream stream(&call, QIODevice::WriteOnly);
@@ -369,7 +341,7 @@ int main (int argc, char *argv[]) {
//- command line parameter
//- Specified in cfg file next to rkward executable
//- compile-time default
- QString r_exe = parser.value ("r-executable");
+ QString r_exe = args[RKCommandLineArgs::RExecutable].toString();
if (!r_exe.isNull ()) {
r_exe = resolveRSpecOrFail (r_exe, i18n ("The R executable specified on the command line (%1) does not exist or is not executable.", r_exe));
RK_DEBUG (APP, DL_DEBUG, "Using R specified on command line");
diff --git a/rkward/misc/CMakeLists.txt b/rkward/misc/CMakeLists.txt
index 7575d7303..b040ab9cf 100644
--- a/rkward/misc/CMakeLists.txt
+++ b/rkward/misc/CMakeLists.txt
@@ -10,6 +10,7 @@ SET(misc_STAT_SRCS
rkobjectlistview.cpp
xmlhelper.cpp
multistringselector.cpp
+ rkcommandlineargs.cpp
rkcommonfunctions.cpp
rkprogresscontrol.cpp
rksaveobjectchooser.cpp
diff --git a/rkward/misc/rkcommandlineargs.cpp b/rkward/misc/rkcommandlineargs.cpp
new file mode 100644
index 000000000..6fdb06ae4
--- /dev/null
+++ b/rkward/misc/rkcommandlineargs.cpp
@@ -0,0 +1,63 @@
+/*
+rkcommandlineargs - This file is part of the RKWard project. Created: Tue May 21 2024
+SPDX-FileCopyrightText: 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
+*/
+
+#include "rkcommandlineargs.h"
+
+#include <KLocalizedString>
+#include <KAboutData>
+#include <QCommandLineParser>
+#include <QUrl>
+#include <QDir>
+
+#include "../debug.h"
+
+RKCommandLineArgs* RKCommandLineArgs::instance = nullptr;
+
+RKCommandLineArgs::RKCommandLineArgs(KAboutData *about, QCoreApplication &app) {
+ RK_TRACE(MISC);
+ RK_ASSERT(instance == nullptr);
+
+ instance = this;
+ QCommandLineParser parser;
+ about->setupCommandLine(&parser);
+
+ parser.addOption(QCommandLineOption("evaluate", i18n("After starting (and after loading the specified workspace, if applicable), evaluate the given R code."), "Rcode", QString()));
+ parser.addOption(QCommandLineOption("debug-level", i18n("Verbosity of debug messages (0-5)"), "level", "2"));
+ parser.addOption(QCommandLineOption("debug-flags", i18n("Mask for components to debug (see debug.h)"), "flags", QString::number(DEBUG_ALL)));
+ parser.addOption(QCommandLineOption("debug-output", i18n("Where to send debug message (file|terminal)"), "where", "file"));
+ parser.addOption(QCommandLineOption("backend-debugger", i18n("Debugger for the backend. (Enclose any debugger arguments in single quotes ('') together with the command. Make sure to re-direct stdout!)"), "command", QString()));
+ parser.addOption(QCommandLineOption("r-executable", i18n("Use specified R installation, instead of the one configured at compile time (note: rkward R library must be installed to that installation of R)"), "command", QString()));
+ parser.addOption(QCommandLineOption("reuse", i18n("Reuse a running RKWard instance (if available). If a running instance is reused, only the file arguments will be interpreted, all other options will be ignored.")));
+ parser.addOption(QCommandLineOption("autoreuse", i18n("Behaves like --reuse, if any file arguments are also given, starts a new instance, otherwise. Intended for use in the .desktop file.")));
+ parser.addOption(QCommandLineOption("nowarn-external", i18n("When used in conjunction with rkward://runplugin/-URLs specified on the command line, suppresses the warning about application-external (untrusted) links.")));
+ parser.addOption(QCommandLineOption("quirkmode", i18n("Disable some startup validation code. Experimental option, not intended for regular use.")));
+ parser.addPositionalArgument("files", i18n("File or files to open, typically a workspace, or an R script file. When loading several things, you should specify the workspace, first."), "[Files...]");
+
+ parser.process(app);
+ about->processCommandLine(&parser);
+
+ storage.resize(NUM_OPTIONS);
+ storage[Evaluate] = parser.value("evaluate");
+ storage[DebugLevel] = parser.value("debug-level").toInt();
+ storage[DebugFlags] = parser.value("debug-flags").toInt();
+ storage[DebugOutput] = parser.value("debug-output");
+ storage[BackendDebugger] = parser.value("backend-debugger");
+ storage[RExecutable] = parser.value("r-executable");
+ storage[Reuse] = parser.isSet("reuse");
+ storage[AutoReuse] = parser.isSet("autoreuse");
+ storage[NoWarnExternal] = parser.isSet("nowarn-external");
+ storage[QuirkMode] = parser.isSet("quirkmode");
+ QStringList url_args = parser.positionalArguments ();
+ if (!url_args.isEmpty ()) {
+ for (int i = 0; i < url_args.size(); ++i) {
+ url_args[i] = QUrl::fromUserInput(url_args[i], QDir::currentPath(), QUrl::AssumeLocalFile).toString();
+ }
+ }
+ storage[UrlArgs] = url_args;
+}
+
+#include "../debug.h"
diff --git a/rkward/misc/rkcommandlineargs.h b/rkward/misc/rkcommandlineargs.h
new file mode 100644
index 000000000..55bdca6bd
--- /dev/null
+++ b/rkward/misc/rkcommandlineargs.h
@@ -0,0 +1,51 @@
+/*
+rkcommandlineargs - This file is part of the RKWard project. Created: Tue May 21 2024
+SPDX-FileCopyrightText: 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
+*/
+
+#ifndef RKCOMMANDLINEARGS_H
+#define RKCOMMANDLINEARGS_H
+
+#include <QVariant>
+#include <QMap>
+#include <QCommandLineOption>
+
+class QCommandLineParser;
+class KAboutData;
+class QCoreApplication;
+
+class RKCommandLineArgs {
+public:
+ explicit RKCommandLineArgs(KAboutData *about, QCoreApplication &app);
+ ~RKCommandLineArgs() {};
+ enum Option {
+ UrlArgs,
+ Evaluate,
+ DebugLevel,
+ DebugFlags,
+ DebugOutput,
+ BackendDebugger,
+ RExecutable,
+ Reuse,
+ AutoReuse,
+ NoWarnExternal,
+ QuirkMode,
+ Setup,
+
+ NUM_OPTIONS
+ };
+ void parseArgs( QCommandLineParser *parser);
+ QVariant operator[](const Option op) const {
+ return storage[op];
+ }
+ static QVariant get(const Option op) {
+ return instance->storage[op];
+ };
+private:
+ QList<QVariant> storage;
+ static RKCommandLineArgs *instance;
+};
+
+#endif
diff --git a/rkward/rbackend/rkfrontendtransmitter.cpp b/rkward/rbackend/rkfrontendtransmitter.cpp
index 90d833a6d..cc8a6d9a7 100644
--- a/rkward/rbackend/rkfrontendtransmitter.cpp
+++ b/rkward/rbackend/rkfrontendtransmitter.cpp
@@ -10,6 +10,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include "rkrbackendprotocol_frontend.h"
#include "rkwarddevice/rkgraphicsdevice_frontendtransmitter.h"
#include "rksessionvars.h"
+#include "../misc/rkcommandlineargs.h"
#include "../settings/rksettingsmodulegeneral.h"
#include <KLocalizedString>
@@ -107,7 +108,7 @@ QString localeDir () {
void RKFrontendTransmitter::run () {
RK_TRACE (RBACKEND);
- quirkmode = RKSettingsModuleGeneral::startupOption("quirkmode").toBool();
+ quirkmode = RKCommandLineArgs::get(RKCommandLineArgs::QuirkMode).toBool();
// start server
server = new QLocalServer (this);
@@ -135,7 +136,7 @@ void RKFrontendTransmitter::run () {
QStringList args;
args.append("CMD");
- QString debugger = RKSettingsModuleGeneral::startupOption("backend-debugger").toString();
+ QString debugger = RKCommandLineArgs::get(RKCommandLineArgs::BackendDebugger).toString();
if (!debugger.isEmpty()) {
args += debugger.split(' ');
}
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index ac1628b80..a750416e8 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -53,6 +53,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include "core/robjectlist.h"
#include "core/renvironmentobject.h"
#include "misc/rkstandardicons.h"
+#include "misc/rkcommandlineargs.h"
#include "misc/rkcommonfunctions.h"
#include "misc/rkxmlguisyncer.h"
#include "misc/rkdialogbuttonbox.h"
@@ -222,9 +223,9 @@ void RKWardMainWindow::closeEvent (QCloseEvent *e) {
void RKWardMainWindow::doPostInit () {
RK_TRACE (APP);
- QStringList open_urls = RKSettingsModuleGeneral::takeStartupOption("initial_urls").toStringList();
- bool warn_external = RKSettingsModuleGeneral::takeStartupOption("warn_external").toBool();
- QString evaluate_code = RKSettingsModuleGeneral::takeStartupOption("evaluate").toString();
+ QStringList open_urls = RKCommandLineArgs::get(RKCommandLineArgs::UrlArgs).toStringList();
+ bool warn_external = !RKCommandLineArgs::get(RKCommandLineArgs::NoWarnExternal).toBool();
+ QString evaluate_code = RKCommandLineArgs::get(RKCommandLineArgs::Evaluate).toString();
initPlugins ();
gui_rebuild_locked = false;
@@ -650,7 +651,7 @@ void RKWardMainWindow::initActions() {
RKConsole::mainConsole()->resetConsole();
restart_now();
} else {
- RCommand *c = new RCommand(QString("# Quit (restarting)"), RCommand::App | RCommand::EmptyCommand || RCommand::QuitCommand);
+ RCommand *c = new RCommand(QString("# Quit (restarting)"), RCommand::App | RCommand::EmptyCommand | RCommand::QuitCommand);
c->whenFinished(this, [this, restart_now]() { QTimer::singleShot(0, this, restart_now); });
RInterface::issueCommand(c);
}
diff --git a/rkward/settings/rksettingsmodulegeneral.cpp b/rkward/settings/rksettingsmodulegeneral.cpp
index ccea0e091..27b8207fc 100644
--- a/rkward/settings/rksettingsmodulegeneral.cpp
+++ b/rkward/settings/rksettingsmodulegeneral.cpp
@@ -51,8 +51,6 @@ bool RKSettingsModuleGeneral::installation_moved = false;
QString RKSettingsModuleGeneral::previous_rkward_data_dir;
RKConfigValue<int> RKSettingsModuleGeneral::num_recent_files { "Max number of recent files", 8 };
-QVariantMap RKSettingsModuleGeneral::startup_options;
-
RKSettingsModuleGeneral::RKSettingsModuleGeneral (RKSettings *gui, QWidget *parent) : RKSettingsModule (gui, parent) {
RK_TRACE (SETTINGS);
diff --git a/rkward/settings/rksettingsmodulegeneral.h b/rkward/settings/rksettingsmodulegeneral.h
index 099c1af29..073937d07 100644
--- a/rkward/settings/rksettingsmodulegeneral.h
+++ b/rkward/settings/rksettingsmodulegeneral.h
@@ -92,10 +92,6 @@ public:
static bool rkwardVersionChanged () { return rkward_version_changed; };
/** Returns true, if rkward seems to have started from a different path than on the previous run. */
static bool installationMoved () { return installation_moved; };
-
- static void setStartupOption(const QString &key, const QVariant &value) { startup_options[key] = value; };
- static QVariant startupOption(const QString &key) { return startup_options.value(key); };
- static QVariant takeStartupOption(const QString &key) { return startup_options.take(key); };
private:
GetFileNameWidget *files_choser;
QButtonGroup *workplace_save_chooser;
@@ -117,8 +113,6 @@ private:
static bool rkward_version_changed;
static bool installation_moved;
static RKConfigValue<int> num_recent_files;
-
- static QVariantMap startup_options;
};
#endif
More information about the rkward-tracker
mailing list