[education/rkward] rkward: Bye, bye, RCommandReceiver

Thomas Friedrichsmeier null at kde.org
Thu Jun 9 15:30:34 BST 2022


Git commit 564f8176e88121ff2fc8df86f85491bcd4a9fab0 by Thomas Friedrichsmeier.
Committed on 09/06/2022 at 14:29.
Pushed by tfry into branch 'master'.

Bye, bye, RCommandReceiver

M  +2    -1    rkward/agents/rkeditobjectagent.h
M  +1    -1    rkward/misc/rkoutputdirectory.cpp
M  +0    -1    rkward/rbackend/CMakeLists.txt
M  +1    -51   rkward/rbackend/rcommand.cpp
M  +12   -23   rkward/rbackend/rcommand.h
D  +0    -45   rkward/rbackend/rcommandreceiver.cpp
D  +0    -59   rkward/rbackend/rcommandreceiver.h
M  +2    -2    rkward/rbackend/rkrinterface.cpp
M  +7    -35   rkward/rbackend/rkrinterface.h
M  +1    -1    rkward/settings/rksettingsmodulegraphics.cpp
M  +1    -1    rkward/settings/rksettingsmoduleoutput.cpp
M  +3    -3    rkward/settings/rksettingsmoduler.cpp
M  +2    -2    rkward/windows/rkworkplace.cpp

https://invent.kde.org/education/rkward/commit/564f8176e88121ff2fc8df86f85491bcd4a9fab0

diff --git a/rkward/agents/rkeditobjectagent.h b/rkward/agents/rkeditobjectagent.h
index c44ece76..4a651e6d 100644
--- a/rkward/agents/rkeditobjectagent.h
+++ b/rkward/agents/rkeditobjectagent.h
@@ -8,11 +8,12 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #define RKEDITOBJECTAGENT_H
 
 #include <qobject.h>
-#include "../rbackend/rcommandreceiver.h"
 
 #include <qstring.h>
 #include <qstringlist.h>
 
+class RCommandChain;
+
 /** This agent gets called, when an rk.edit() command was run in the backend. The purpose is to first update the structure information for the object(s), and then try to open it/them.
 
 @author Thomas Friedrichsmeier
diff --git a/rkward/misc/rkoutputdirectory.cpp b/rkward/misc/rkoutputdirectory.cpp
index 8de7d777..431055c6 100644
--- a/rkward/misc/rkoutputdirectory.cpp
+++ b/rkward/misc/rkoutputdirectory.cpp
@@ -271,7 +271,7 @@ GenericRRequestResult RKOutputDirectory::activate(RCommandChain* chain) {
 	RK_TRACE (APP);
 
 	QString index_file = work_dir + "/index.html";
-	RInterface::issueCommand(QStringLiteral("rk.set.output.html.file(\"") + RKCommonFunctions::escape(index_file) + QStringLiteral("\")\n"), RCommand::App, QString(), 0, 0, chain);
+	RInterface::issueCommand(new RCommand(QStringLiteral("rk.set.output.html.file(\"") + RKCommonFunctions::escape(index_file) + QStringLiteral("\")\n"), RCommand::App), chain);
 	if (!initialized) {
 		// when an output directory is first initialized, we don't want that to count as a "modification". Therefore, update the "saved hash" _after_ initialization
 		RInterface::whenAllFinished(this, [this]() { updateSavedHash(); }, chain);
diff --git a/rkward/rbackend/CMakeLists.txt b/rkward/rbackend/CMakeLists.txt
index 94980e0d..0388ceb2 100644
--- a/rkward/rbackend/CMakeLists.txt
+++ b/rkward/rbackend/CMakeLists.txt
@@ -31,7 +31,6 @@ SET (
 	rbackend_frontend_SRCS
 	rkrinterface.cpp
 	rcommand.cpp
-	rcommandreceiver.cpp
 	rcommandstack.cpp
 	rkrbackendprotocol_frontend.cpp
 	rksessionvars.cpp
diff --git a/rkward/rbackend/rcommand.cpp b/rkward/rbackend/rcommand.cpp
index 5b4bcab8..bbae32f2 100644
--- a/rkward/rbackend/rcommand.cpp
+++ b/rkward/rbackend/rcommand.cpp
@@ -6,7 +6,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include "rcommand.h"
-#include "rcommandreceiver.h"
 #include "rkrinterface.h"
 #include "../windows/rkcommandlog.h"
 #include "rkrbackendprotocol_shared.h"
@@ -30,7 +29,7 @@ RCommandNotifier::~RCommandNotifier () {
 
 int RCommand::next_id = 0;
 
-RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags) : RData (), RCommandChain (false) {
+RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, int flags) : RData (), RCommandChain (false) {
 	RK_TRACE (RBACKEND);
 	_id = next_id++;
 // if we ever submit enough commands to get a buffer overflow, use only positive numbers.
@@ -46,10 +45,6 @@ RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, RC
 	has_been_run_up_to = 0;
 	_rk_equiv = rk_equiv;
 	_notifier = 0;
-	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) receivers[i] = 0;
-	if (!(type & Internal)) {
-		addReceiver (receiver);
-	}
 }
 
 RCommand::~RCommand(){
@@ -72,45 +67,9 @@ RCommandNotifier* RCommand::notifier () {
 	return _notifier;
 }
 
-void RCommand::addReceiver (RCommandReceiver *receiver) {
-	RK_TRACE (RBACKEND);
-
-	if (!receiver) return;
-
-	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
-		if (receivers[i] == 0) {
-			receivers[i] = receiver;
-			receiver->addCommand (this);
-			return;
-		}
-	}
-
-	RK_DEBUG (RBACKEND, DL_ERROR, "Too many receivers for command");
-}
-
-void RCommand::removeReceiver (RCommandReceiver *receiver) {
-	RK_TRACE (RBACKEND);
-
-	if (!receiver) return;
-
-	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
-		if (receivers[i] == receiver) {
-			receivers[i] = 0;
-			return;
-		}
-	}
-
-	RK_DEBUG (RBACKEND, DL_WARNING, "Was not a receiver in RCommand::removeReceiver: %p", receiver);
-}
-
 void RCommand::finished () {
 	RK_TRACE (RBACKEND);
 
-	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
-		if (receivers[i] == 0) continue;
-		receivers[i]->delCommand (this);
-		receivers[i]->rCommandDone (this);
-	}
 	RKCommandLog::getLog()->rCommandDone(this);
 	if (_notifier) _notifier->emitFinished (this);
 }
@@ -118,10 +77,6 @@ void RCommand::finished () {
 void RCommand::newOutput (ROutput *output) {
 	RK_TRACE (RBACKEND);
 
-	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
-		if (receivers[i] == 0) continue;
-		receivers[i]->newOutput (this, output);
-	}
 	RKCommandLog::getLog()->newOutput(this, output);
 	if (_notifier) _notifier->emitOutput(this, output);
 }
@@ -129,11 +84,6 @@ void RCommand::newOutput (ROutput *output) {
 void RCommand::commandLineIn () {
 	RK_TRACE (RBACKEND);
 	RK_ASSERT (_type & User);
-
-	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
-		if (receivers[i] == 0) continue;
-		receivers[i]->userCommandLineIn (this);
-	}
 	if (_notifier) _notifier->emitLineIn(this);
 }
 
diff --git a/rkward/rbackend/rcommand.h b/rkward/rbackend/rcommand.h
index 43dc982a..0b413ba9 100644
--- a/rkward/rbackend/rcommand.h
+++ b/rkward/rbackend/rcommand.h
@@ -14,9 +14,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "rdata.h"
 
-#define MAX_RECEIVERS_PER_RCOMMAND 3
-
-class RCommandReceiver;
 class RCommand;
 class RCommandProxy;
 class RObject;
@@ -61,16 +58,16 @@ typedef QList<ROutput*> ROutputList;
 
 /** Supplies signals for RCommands.
  * Obtain an instance of this using RCommand::notifier ();
- * Currently, only a single signal is available: When the command has finished. Further signals may be added, in the future.
- *
- * @Note You can also use this in connection with RCommandReceiver-based classes, if interested in RCommandReceiver::cancelOutstandingCommands().
+ * Provides signals for new output, command completion (with or without error), and, as a special case for the R console, a signal, when a new line of a command has started runnning.
  */
 class RCommandNotifier : public QObject {
 	Q_OBJECT
 signals:
 /** given command has finished (not necessarily successfully) */
 	void commandFinished(RCommand *command);
+/** new output for the given command */
 	void commandOutput(RCommand *command, const ROutput* output);
+/** a new line of the command has started being evaluate. Only emitted to RCommand::User-type commands */
 	void commandLineIn(RCommand *command);
 private:
 friend class RCommand;
@@ -86,16 +83,14 @@ friend class RCommand;
 	This class is used to encapsulate an R-command, so it can be easily identified
 	in a chain of commands. It is needed, since communication with R is asynchronous
 	and it is therefore not possible to get the result of an R-call right away.
-	Instead, create an object of this class, specifying the RCommandReceiver that should
-	be called when the command has finished. You can then retrieve all information
-	on the command (including the reply) from the object that is passed to your handler.
-	
-	There are several ways to identify a command when it's finished (needed, if a single RCommandReceiver needs to handle the results of
-	several different commands):
-		- storing the id () (each command is automatically assigned a unique id, TODO: do we need this functionality? Maybe remove it for redundancy)
-		- passing appropriate flags to know how to handle the command
-		- keeping the pointer (CAUTION: don't use that pointer except to compare it with the pointer of an incoming command. Commands get deleted when they are finished, and maybe (in the future) if they become obsolete etc. Hence the pointers you keep may be invalid!)
-		(- checking the command-string)
+
+	To track the status of a command, and work with the results, connect to the notifier() signals.
+	Usually, RCommand::whenFinished() is the most convenient way to connect a callback (typically a lambda function).
+
+	I case several commands a connected to a single function, the command id() can be stored to identify, which command
+	to deal with. Keeping a pointer is another options, but beware: don't use that pointer except to compare it with the pointer of an incoming command.
+	Commands get deleted when they are finished, and maybe (in the future) if they become obsolete etc. Hence the pointers you keep may be invalid!
+
 	Note that an RCommand carries a whole lot of information around. However, RCommands generally don't get
 	kept around very long, so they should not be a memory issue.
   *@author Thomas Friedrichsmeier
@@ -106,10 +101,9 @@ public:
 @param command The command (string) to be run in the backend. This may include newlines and ";". The command should be a complete statement. If it is an incomplete statement, the backend will not wait for the rest of the command to come in, but rather the command will fail with RCommand::errorIncomplete.
 @param type An integer being the result of a bit-wise OR combination of the values in RCommand::CommandTypes. The type-parameter is used to indicate the type of command, and also how the command should retrieve information (as a usual string, or as a data vector). See \ref RCommand::CommandTypes
 @param rk_equiv Not yet used: a short descriptive string attached to the RCommand, that allows the user to make some sense of what this command is all about.
- at param receiver The RCommandReceiver this command should be passed on to, when finished. @Note: consider connecting to the notifier(), instead!
 @param flags A freely assignable integer, that you can use to identify what the command was all about. Only the RCommandReceiver handling the results will have to know what exactly the flags mean.
 */
-	explicit RCommand (const QString &command, int type, const QString &rk_equiv = QString (), RCommandReceiver *receiver=0, int flags=0);
+	explicit RCommand (const QString &command, int type, const QString &rk_equiv = QString (), int flags=0);
 /** destructor. Note: you should not delete RCommands manually. This is done in RInterface. TODO: make protected */
 	~RCommand();
 /** @returns the type as specified in RCommand::RCommand */
@@ -188,10 +182,6 @@ public:
 	bool errorSyntax () const { return (status & ErrorSyntax); };
 /** return the flags associated with the command. Those are the same that you specified in the constructor, RKWard does not touch them. @see RCommand::RCommand */
 	int getFlags () const { return (_flags); };
-/** Add an additional listener to the command */
-	void addReceiver (RCommandReceiver *receiver);
-/** Remove a receiver from the list. This may be needed when a listener wants to self-destruct, to make sure we don't try to send any further info there */
-	void removeReceiver (RCommandReceiver *receiver);
 	void addTypeFlag (int flag) { _type |= flag; };
 	ROutputList &getOutput () { return output_list; };
 /** modify the command string. DO NOT CALL THIS after the command has been submitted! */
@@ -230,7 +220,6 @@ friend class RCommandStackModel;
 	QString _updated_object;
 	int _id;
 	static int next_id;
-	RCommandReceiver *receivers[MAX_RECEIVERS_PER_RCOMMAND];
 
 	RCommandNotifier *_notifier;
 };
diff --git a/rkward/rbackend/rcommandreceiver.cpp b/rkward/rbackend/rcommandreceiver.cpp
deleted file mode 100644
index 3d90e34b..00000000
--- a/rkward/rbackend/rcommandreceiver.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-rcommandreceiver - This file is part of RKWard (https://rkward.kde.org). Created: Thu Aug 19 2004
-SPDX-FileCopyrightText: 2004-2010 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 "rcommandreceiver.h"
-
-#include "rkrinterface.h"
-
-#include "../debug.h"
-
-RCommandReceiver::RCommandReceiver () {
-	RK_TRACE (RBACKEND);
-
-	delete_when_done = false;
-}
-
-RCommandReceiver::~RCommandReceiver () {
-	RK_TRACE (RBACKEND);
-
-	for (RCommandList::const_iterator it = outstanding_commands.constBegin (); it != outstanding_commands.constEnd (); ++it) {
-		(*it)->removeReceiver (this);
-	}
-}
-
-void RCommandReceiver::cancelOutstandingCommands () {
-	RK_TRACE (RBACKEND);
-
-	for (RCommandList::const_iterator it = outstanding_commands.constBegin (); it != outstanding_commands.constEnd (); ++it) {
-		RInterface::instance()->cancelCommand(*it);
-	}
-}
-
-void RCommandReceiver::addCommand (RCommand *command) {
-	RK_TRACE (RBACKEND);
-	outstanding_commands.append (command);
-}
-
-void RCommandReceiver::delCommand (RCommand *command) {
-	RK_TRACE (RBACKEND);
-	outstanding_commands.removeAll (command);
-
-	if (delete_when_done && outstanding_commands.isEmpty ()) delete this;
-}
diff --git a/rkward/rbackend/rcommandreceiver.h b/rkward/rbackend/rcommandreceiver.h
deleted file mode 100644
index 0db15c09..00000000
--- a/rkward/rbackend/rcommandreceiver.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-rcommandreceiver - This file is part of the RKWard project. Created: Thu Aug 19 2004
-SPDX-FileCopyrightText: 2004-2010 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 RCOMMANDRECEIVER_H
-#define RCOMMANDRECEIVER_H
-
-#include <qlist.h>
-
-#include "rcommand.h"
-
-/**
-Use this class as a base for classes that need to handle RCommands. Most importantly it provides a virtual function (rCommandDone ()) for handling of RCommand-results. Reimplement this to interpret the command-results.
-For windows/dialogs which interpret RCommand results, the receiver provides a special mechanism. The problem with those windows/dialogs is, that the user may close them, while there are still RCommands due to come in, i.e. they can't be deleted, but rather need to wait for the remaining results to come in.
-This class will keep track of which RCommands are still out there (and expected to return to this receiver). When deleting the object, it will unregister from all outstanding commands, so there are no invalid pointer operations.
-
-TODO: this mechanism may be slightly costly, if there are *many* commands outstanding. Maybe for special receivers like RKWatch, which are never destroyed at run-time, the mechanism should be disabled.
-
- at Note that the (younger) RCommandNotifier class provides much easier handling based on QObject slots in most situations. Of course, you can also combine both, if you are interested
-in the cancelOutstandingCommands() functionality.
-
- at author Thomas Friedrichsmeier
-*/
-
-class RCommand;
-struct ROutput;
-typedef QList<RCommand*> RCommandList;
-
-class RCommandReceiver {
-public:
-/** constructor. No args */
-	RCommandReceiver ();
-/** destructor */
-	virtual ~RCommandReceiver ();
-protected:
-	friend class RCommand;
-	friend class RInterface;
-/** This function is called when a command for this receiver is finished (and before it is deleted). You have to implement it in your subclass to do the actual handling.
- at param command A pointer to the command. The pointer is still valid during this call, but the RCommand will be deleted shortly after! */
-	virtual void rCommandDone (RCommand *) {};
-/** This function is called when there is new output for a command or this receiver. Default implementation does nothing. Reimplement if you want to get at a command's output immediately (i.e. before the command is fully completed).
- at param command A pointer to the command
- at param output The new output-fragment */
-	virtual void newOutput (RCommand *, ROutput *) {};
-/** This function is called when a new line of the given command has been fed to the backend. Note: This is only ever called for commands of type RCommand::User.
- at param command A pointer to the command */
-	virtual void userCommandLineIn (RCommand*) {};
-protected:
-	RCommandList outstanding_commands;
-	void cancelOutstandingCommands ();
-private:
-	bool delete_when_done;
-	void addCommand (RCommand *command);
-	void delCommand (RCommand *command);
-};
-
-#endif
diff --git a/rkward/rbackend/rkrinterface.cpp b/rkward/rbackend/rkrinterface.cpp
index ade15f95..fa535e58 100644
--- a/rkward/rbackend/rkrinterface.cpp
+++ b/rkward/rbackend/rkrinterface.cpp
@@ -116,9 +116,9 @@ RInterface::RInterface () {
 	whenAllFinished(this, []() { RKSettings::validateSettingsInteractive (); });
 }
 
-void RInterface::issueCommand (const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags, RCommandChain *chain) {
+void RInterface::issueCommand (const QString &command, int type, const QString &rk_equiv, int flags, RCommandChain *chain) {
 	RK_TRACE (RBACKEND);
-	issueCommand (new RCommand (command, type, rk_equiv, receiver, flags), chain);
+	issueCommand (new RCommand (command, type, rk_equiv, flags), chain);
 }
 
 RInterface::~RInterface(){
diff --git a/rkward/rbackend/rkrinterface.h b/rkward/rbackend/rkrinterface.h
index fd587207..dc2ce570 100644
--- a/rkward/rbackend/rkrinterface.h
+++ b/rkward/rbackend/rkrinterface.h
@@ -42,7 +42,7 @@ public:
 /** issues the given command in the given chain */
 	static void issueCommand(RCommand *command, RCommandChain *chain=0);
 /** convenience function to create a new command and issue it. See documentation on RCommand::RCommand() and RInterface::issueCommand() */
-	static void issueCommand(const QString &command, int type = 0, const QString &rk_equiv = QString(), RCommandReceiver *receiver=0, int flags=0, RCommandChain *chain=0);
+	static void issueCommand(const QString &command, int type = 0, const QString &rk_equiv = QString(), int flags=0, RCommandChain *chain=0);
 
 /** convenience function to call a function / lambda, once all commands issued in the given chain have finished (successfully or not). Internally, this works by queing an empty command. */
 	template<typename T> static void whenAllFinished(QObject *receiver, T func, RCommandChain *chain=nullptr) {
@@ -190,9 +190,6 @@ Ok, so how do you get informed, when your command was completed? Using RCommand:
 lambda expression that will be called. This function or expression @em may take an RCommand* as parameter. In some cases, all you want to know is when all commands that have been already queued up to now
 have been run. In this case, you can use RInterface::whenAllFinished().
 
- at Note that all this was much more complicated in the old days, and you will still find a lot of places, where classes are derived from RCommandReceiver, and the command is handled in an overridden
-rCommandDone() function.
-
 Example code:
 
 \code
@@ -226,45 +223,20 @@ So what happens is that the RCommand created with RInterface::issueCommand goes
 
 // TODO: Adjust this section to RCommandNotifier / RCommand::whenFinished().
 
-In many cases you don't just want to deal with a single RCommand in an RCommandReceiver, but rather you might submit a bunch of different commands (for instance to find out about several different properties of an object in R-space), and then use some special handling for each of those commands. So the problem is, how to find out, which of your commands you're currently dealing with in rCommandDone.
+In some cases you don't just want to deal with a single RCommand in a callback, and then use some special handling for each of those commands. So the problem is, how to find out, which of your commands you're currently dealing with ,in the callback.
 
 There are several ways to deal with this:
 
 	- storing the RCommand::id () (each command is automatically assigned a unique id)
-	- passing appropriate flags to know how to handle the command
+	- passing appropriate flags to know how to handle the command (Note that you can freely assign whatever flags you like. Only your own class will need to know how to interpret the flags.)
 	- keeping the pointer (CAUTION: don't use that pointer except to compare it with the pointer of an incoming command. Commands get deleted when they are finished, and maybe (in the future) if they become obsolete etc. Hence the pointers you keep may be invalid!)
 
-To illustrate the option of using "FLAGS", here is a reduced example of how RKVariable updates information about the dimensions and class of the corresponding object in R-space using two different RCommand s:
-
-\code
-#define UPDATE_DIM_COMMAND 1
-#define UPDATE_CLASS_COMMAND 2
-
-void RKVariable::updateFromR () {
-	//...
-	RCommand *command = new RCommand ("length (" + getFullName () + ")", RCommand::App | RCommand::Sync | RCommand::GetIntVector, QString (), this, UPDATE_DIM_COMMAND);
-	RInterface::issueCommand (command, RKGlobals::rObjectList()->getUpdateCommandChain ());
-}
-
-void RKVariable::rCommandDone (RCommand *command) {
-	//...
-	if (command->getFlags () == UPDATE_DIM_COMMAND) {
-		// ...
-		RCommand *ncommand = new RCommand ("class (" + getFullName () + ")", RCommand::App | RCommand::Sync | RCommand::GetStringVector, QString (), this, UPDATE_CLASS_COMMAND);
-		RInterface::issueCommand (ncommand, RKGlobals::rObjectList()->getUpdateCommandChain ());
-	} else if (command->getFlags () == UPDATE_CLASS_COMMAND) {
-		//...
-	}
-}
-\endcode
-
-Note that you can freely assign whatever flags you like. Only your own class will need to know how to interpret the flags.
 
 Now what about that RKGlobals::rObjectList()->getUpdateCommandChain ()? We'll talk about RCommandChain and what you need it for further down below. But first we'll have a look at how an RCommand is handled internally.
 
 \section UsingTheInterfaceToRInternalHandling What happens with an RCommand internally?
 
-So far we've discussed RInterface:issueCommand () and RCommandReceiver::rCommandDone (). But what happens in between?
+So far we've discussed RInterface:issueCommand () and the callback when it has finished. But what happens in between?
 
 First the RCommand is placed in a first-in-first-out stack. This stack is needed, since - as discussed - the commands get executed in a separate thread, so several command may get stacked up, before the first one gets run.
 
@@ -272,7 +244,7 @@ Then, in the backend thread (RThread) there is a loop running, which fetches tho
 
 Whenever the main thread becomes active again, it will find that QCustomEvent and handle it in RInterface::customEvent.
 
-The most important thing happening there, is a call to RCommand::finished (RCommand::finished basically just calls the responsible RCommandReceiver::rCommandDone), and right after that the RCommand gets deleted.
+The most important thing happening there, is a call to RCommand::finished (which cause the commandFinished()-signal to be emitted), and right after that the RCommand gets deleted.
 
 \section UsingTheInterfaceToRThreadingIssues Threading issues
 
@@ -366,7 +338,7 @@ Remember to close chains when you placed all the commands you needed to. If you
 There are a few special type-modifiers you can specify when creating an RCommand (as part of the second parameter to RCommand::RCommand or RInterface::issueCommand), that determine what will be done with the result:
 
 - RCommand::EmptyCommand
-This one tells the backend, that the command does not really need to be executed, and does not contain anything. You'll rarely need this flag, but sometimes it is useful to submit an empty command simply to find out when it is finished.
+This one tells the backend, that the command does not really need to be executed, and does not contain anything. You'll rarely need this flag, but sometimes it is useful to submit an empty command simply to find out when it is finished. @note: RInterface::whenAllFinished() is a more readable alternative to this.
 
 - RCommand::DirectToOutput
 This is typically used in plugins: When you specify this modifier, the plain text result of this command (i.e. whatever R prints out when evaluating the command) will be added to the HTML output file. Remember to call RKWardMainWindow::newOutput in order to refresh the output-window once the command has finished.
@@ -392,7 +364,7 @@ The following classes contain (or should contain) further important documentatio
 
 - \ref RInterface
 - \ref RCommand
-- \ref RCommandReceiver
+- \ref RCommandNotifier
 - \ref RCommandStack
 
 Even lower level API:
diff --git a/rkward/settings/rksettingsmodulegraphics.cpp b/rkward/settings/rksettingsmodulegraphics.cpp
index b0ba6277..12e67b36 100644
--- a/rkward/settings/rksettingsmodulegraphics.cpp
+++ b/rkward/settings/rksettingsmodulegraphics.cpp
@@ -171,7 +171,7 @@ void RKSettingsModuleGraphics::applyChanges () {
 
 	QStringList commands = makeRRunTimeOptionCommands ();
 	for (QStringList::const_iterator it = commands.cbegin (); it != commands.cend (); ++it) {
-		RInterface::issueCommand (*it, RCommand::App, QString (), 0, 0, commandChain ());
+		RInterface::issueCommand (*it, RCommand::App, QString (), 0, commandChain ());
 	}
 }
 
diff --git a/rkward/settings/rksettingsmoduleoutput.cpp b/rkward/settings/rksettingsmoduleoutput.cpp
index 24a8a185..8c80d204 100644
--- a/rkward/settings/rksettingsmoduleoutput.cpp
+++ b/rkward/settings/rksettingsmoduleoutput.cpp
@@ -199,7 +199,7 @@ void RKSettingsModuleOutput::applyChanges () {
 
 	QStringList commands = makeRRunTimeOptionCommands ();
 	for (QStringList::const_iterator it = commands.cbegin (); it != commands.cend (); ++it) {
-		RInterface::issueCommand (*it, RCommand::App, QString (), 0, 0, commandChain ());
+		RInterface::issueCommand (*it, RCommand::App, QString (), 0, commandChain ());
 	}
 
 	cc_settings->applyChanges ();
diff --git a/rkward/settings/rksettingsmoduler.cpp b/rkward/settings/rksettingsmoduler.cpp
index eaa9fec7..8cbc7e02 100755
--- a/rkward/settings/rksettingsmoduler.cpp
+++ b/rkward/settings/rksettingsmoduler.cpp
@@ -197,7 +197,7 @@ void RKSettingsModuleR::applyChanges () {
 // apply run time options in R
 	QStringList commands = makeRRunTimeOptionCommands ();
 	for (QStringList::const_iterator it = commands.cbegin (); it != commands.cend (); ++it) {
-		RInterface::issueCommand (*it, RCommand::App, QString (), 0, 0, commandChain ());
+		RInterface::issueCommand (*it, RCommand::App, QString (), 0, commandChain ());
 	}
 }
 
@@ -377,7 +377,7 @@ void RKSettingsModuleRPackages::addLibraryLocation (const QString& new_loc, RCom
 	if (!libraryLocations ().contains (new_loc)) liblocs.get().prepend (new_loc);
 
 	// update the backend in any case. User might have changed liblocs, there.
-	RInterface::issueCommand (".libPaths (unique (c (" + RObject::rQuote (new_loc) + ", .libPaths ())))", RCommand::App | RCommand::Sync, QString (), 0, 0, chain);
+	RInterface::issueCommand (".libPaths (unique (c (" + RObject::rQuote (new_loc) + ", .libPaths ())))", RCommand::App | RCommand::Sync, QString (), 0, chain);
 }
 
 QStringList expandLibLocs (const QStringList &in) {
@@ -547,7 +547,7 @@ void RKSettingsModuleRPackages::applyChanges () {
 // apply options in R
 	QStringList commands = makeRRunTimeOptionCommands ();
 	for (QStringList::const_iterator it = commands.cbegin (); it != commands.cend (); ++it) {
-		RInterface::issueCommand (*it, RCommand::App, QString (), 0, 0, commandChain ());
+		RInterface::issueCommand (*it, RCommand::App, QString (), 0, commandChain ());
 	}
 }
 
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index d4692c13..20a531b7 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -974,7 +974,7 @@ void RKWorkplace::saveWorkplace(const QUrl& for_url, RCommandChain *chain) {
 
 	QString file_param;
 	if (!for_url.isEmpty()) file_param = QString("file=") + RObject::rQuote(for_url.toLocalFile() + QStringLiteral(".rkworkplace")) + QStringLiteral(", ");
-	RInterface::issueCommand("rk.save.workplace(" + file_param + "description=" + RObject::rQuote (makeWorkplaceDescription().join ("\n")) + ')', RCommand::App, i18n ("Save Workplace layout"), 0, 0, chain);
+	RInterface::issueCommand("rk.save.workplace(" + file_param + "description=" + RObject::rQuote (makeWorkplaceDescription().join ("\n")) + ')', RCommand::App, i18n ("Save Workplace layout"), 0, chain);
 }
 
 void RKWorkplace::restoreWorkplace (RCommandChain *chain, bool merge) {
@@ -983,7 +983,7 @@ void RKWorkplace::restoreWorkplace (RCommandChain *chain, bool merge) {
 
 	QString no_close_windows;
 	if (merge) no_close_windows = "close.windows = FALSE";
-	RInterface::issueCommand ("rk.restore.workplace(" + no_close_windows + ')', RCommand::App, i18n ("Restore Workplace layout"), 0, 0, chain);
+	RInterface::issueCommand ("rk.restore.workplace(" + no_close_windows + ')', RCommand::App, i18n ("Restore Workplace layout"), 0, chain);
 }
 
 void RKWorkplace::restoreWorkplace (const QStringList &description) {



More information about the rkward-tracker mailing list