[rkward-cvs] SF.net SVN: rkward:[3731] trunk/rkward/rkward

tfry at users.sourceforge.net tfry at users.sourceforge.net
Thu Sep 8 09:36:57 UTC 2011


Revision: 3731
          http://rkward.svn.sourceforge.net/rkward/?rev=3731&view=rev
Author:   tfry
Date:     2011-09-08 09:36:57 +0000 (Thu, 08 Sep 2011)
Log Message:
-----------
- Add signal / slot based notification of finished RCommands
- Add storage for R session info. For now, only the list of installed packages is stored.
- Use the global list of installed packages in RKHelpSearchWindow.

Modified Paths:
--------------
    trunk/rkward/rkward/rbackend/CMakeLists.txt
    trunk/rkward/rkward/rbackend/rcommand.cpp
    trunk/rkward/rkward/rbackend/rcommand.h
    trunk/rkward/rkward/rbackend/rcommandreceiver.h
    trunk/rkward/rkward/rbackend/rinterface.cpp
    trunk/rkward/rkward/windows/rkhelpsearchwindow.cpp
    trunk/rkward/rkward/windows/rkhelpsearchwindow.h

Added Paths:
-----------
    trunk/rkward/rkward/rbackend/rksessionvars.cpp
    trunk/rkward/rkward/rbackend/rksessionvars.h

Modified: trunk/rkward/rkward/rbackend/CMakeLists.txt
===================================================================
--- trunk/rkward/rkward/rbackend/CMakeLists.txt	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/rbackend/CMakeLists.txt	2011-09-08 09:36:57 UTC (rev 3731)
@@ -32,6 +32,7 @@
 	rcommandreceiver.cpp
 	rcommandstack.cpp
 	rkrbackendprotocol_frontend.cpp
+	rksessionvars.cpp
 )
 
 SET(RBACKEND_SPLIT 1)

Modified: trunk/rkward/rkward/rbackend/rcommand.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rcommand.cpp	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/rbackend/rcommand.cpp	2011-09-08 09:36:57 UTC (rev 3731)
@@ -40,6 +40,14 @@
 }
 
 
+RCommandNotifier::RCommandNotifier () : QObject () {
+	RK_TRACE (RBACKEND);
+}
+
+RCommandNotifier::~RCommandNotifier () {
+	RK_TRACE (RBACKEND);
+}
+
 int RCommand::next_id = 0;
 
 RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags) : RData (), RCommandBase (false) {
@@ -57,6 +65,7 @@
 	status = 0;
 	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);
@@ -71,8 +80,19 @@
 		delete (*it);
 	}
 	// The output_list itself is cleared automatically
+
+	if (_notifier) delete _notifier;
 }
 
+RCommandNotifier* RCommand::notifier () {
+	if (!_notifier) {
+		RK_TRACE (RBACKEND);
+		_notifier = new RCommandNotifier ();
+		RK_ASSERT (_notifier);
+	}
+	return _notifier;
+}
+
 void RCommand::addReceiver (RCommandReceiver *receiver) {
 	RK_TRACE (RBACKEND);
 
@@ -112,6 +132,7 @@
 		receivers[i]->delCommand (this);
 		receivers[i]->rCommandDone (this);
 	}
+	if (_notifier) _notifier->emitFinished (this);
 }
 
 void RCommand::newOutput (ROutput *output) {
@@ -211,3 +232,5 @@
 	ret->has_been_run_up_to = has_been_run_up_to;
 	return ret;
 }
+
+#include "rcommand.moc"

Modified: trunk/rkward/rkward/rbackend/rcommand.h
===================================================================
--- trunk/rkward/rkward/rbackend/rcommand.h	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/rbackend/rcommand.h	2011-09-08 09:36:57 UTC (rev 3731)
@@ -18,9 +18,8 @@
 #ifndef RCOMMAND_H
 #define RCOMMAND_H
 
-#include <qfile.h>
-#include <qstring.h>
-#include <qobject.h>
+#include <QString>
+#include <QObject>
 #include <QList>
 
 #include "rdata.h"
@@ -79,6 +78,23 @@
 
 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().
+ */
+class RCommandNotifier : public QObject {
+	Q_OBJECT
+signals:
+	void commandFinished (RCommand *command);
+private:
+friend class RCommand;
+	RCommandNotifier ();
+	~RCommandNotifier ();
+	void emitFinished (RCommand *command) { emit commandFinished (command); };
+};
+
 /** For introductory information on using RCommand, see \ref UsingTheInterfaceToR 
 
 	This class is used to encapsulate an R-command, so it can be easily identified
@@ -104,7 +120,7 @@
 @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.
+ 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::null, RCommandReceiver *receiver=0, int flags=0);
@@ -196,6 +212,9 @@
 /** creates a proxy for this RCommand */
 	RCommandProxy* makeProxy () const;
 	void mergeAndDeleteProxy (RCommandProxy *proxy);
+
+/** returns a notifier for this command (creating it, if needed). You can connect to the notifiers signals. */
+	RCommandNotifier* notifier ();
 private:
 friend class RInterface;
 friend class RCommandStack;
@@ -216,6 +235,8 @@
 	int _id;
 	static int next_id;
 	RCommandReceiver *receivers[MAX_RECEIVERS_PER_RCOMMAND];
+
+	RCommandNotifier *_notifier;
 };
 
 #endif

Modified: trunk/rkward/rkward/rbackend/rcommandreceiver.h
===================================================================
--- trunk/rkward/rkward/rbackend/rcommandreceiver.h	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/rbackend/rcommandreceiver.h	2011-09-08 09:36:57 UTC (rev 3731)
@@ -22,12 +22,15 @@
 #include "rcommand.h"
 
 /**
-Use this class as a base for all 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.
+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.
+
 @author Thomas Friedrichsmeier
 */
 

Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp	2011-09-08 09:36:57 UTC (rev 3731)
@@ -41,6 +41,7 @@
 #include "../windows/rkhtmlwindow.h"
 #include "../plugin/rkcomponentmap.h"
 #include "../misc/rkcommonfunctions.h"
+#include "rksessionvars.h"
 
 #include "../windows/rkwindowcatcher.h"
 
@@ -102,6 +103,7 @@
 	// create a fake init command
 	RCommand *fake = new RCommand (i18n ("R Startup"), RCommand::App | RCommand::Sync | RCommand::ObjectListUpdate, i18n ("R Startup"), this, STARTUP_PHASE2_COMPLETE);
 	issueCommand (fake);
+	new RKSessionVars (this);
 
 	new RKRBackendProtocolFrontend (this);
 	RKRBackendProtocolFrontend::instance ()->setupBackend ();

Added: trunk/rkward/rkward/rbackend/rksessionvars.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rksessionvars.cpp	                        (rev 0)
+++ trunk/rkward/rkward/rbackend/rksessionvars.cpp	2011-09-08 09:36:57 UTC (rev 3731)
@@ -0,0 +1,59 @@
+/***************************************************************************
+                          rksessionvars  -  description
+                             -------------------
+    begin                : Thu Sep 08 2011
+    copyright            : (C) 2011 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "rksessionvars.h"
+
+#include "rinterface.h"
+
+#include "../debug.h"
+
+RKSessionVars* RKSessionVars::_instance = 0;
+
+RKSessionVars::RKSessionVars (RInterface *parent) : QObject (parent) {
+	RK_TRACE (RBACKEND);
+	RK_ASSERT (!_instance);
+
+	_instance = this;
+
+	RCommand *initc = new RCommand (".rk.get.installed.packages()[[1]]", RCommand::App | RCommand::Sync | RCommand::GetStringVector);
+	connect (initc->notifier (), SIGNAL (commandFinished(RCommand*)), this, SLOT (installedPackagesCommandFinished(RCommand*)));
+	parent->issueCommand (initc);
+}
+
+RKSessionVars::~RKSessionVars () {
+	RK_TRACE (RBACKEND);
+}
+
+void RKSessionVars::setInstalledPackages (const QStringList &new_list) {
+	RK_TRACE (RBACKEND);
+
+	installed_packages = new_list;
+	emit (installedPackagesChanged ());
+}
+
+void RKSessionVars::installedPackagesCommandFinished (RCommand *command) {
+	RK_TRACE (RBACKEND);
+
+	if (command->succeeded () && (command->getDataType () == RData::StringVector)) {
+		setInstalledPackages (command->getStringVector ());
+		return;
+	}
+
+	RK_ASSERT (false);
+}
+
+#include "rksessionvars.moc"

Added: trunk/rkward/rkward/rbackend/rksessionvars.h
===================================================================
--- trunk/rkward/rkward/rbackend/rksessionvars.h	                        (rev 0)
+++ trunk/rkward/rkward/rbackend/rksessionvars.h	2011-09-08 09:36:57 UTC (rev 3731)
@@ -0,0 +1,48 @@
+/***************************************************************************
+                          rksessionvars  -  description
+                             -------------------
+    begin                : Thu Sep 08 2011
+    copyright            : (C) 2011 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef RKSESSIONVARS_H
+#define RKSESSIONVARS_H
+
+#include <QObject>
+#include <QStringList>
+
+class RInterface;
+class RCommand;
+
+/** Singleton for storing information about the running R session, and - for some of the info - notifying about changes. */
+class RKSessionVars : public QObject {
+	Q_OBJECT
+public:
+	static RKSessionVars* instance () { return _instance; };
+	QStringList installedPackages () const { return installed_packages; };
+	void setInstalledPackages (const QStringList &new_list);
+signals:
+	void installedPackagesChanged ();
+protected:
+friend class RInterface;
+	RKSessionVars (RInterface *parent);
+	~RKSessionVars ();
+private:
+	static RKSessionVars* _instance;
+
+	QStringList installed_packages;
+private slots:
+	void installedPackagesCommandFinished (RCommand *command);
+};
+
+#endif

Modified: trunk/rkward/rkward/windows/rkhelpsearchwindow.cpp
===================================================================
--- trunk/rkward/rkward/windows/rkhelpsearchwindow.cpp	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/windows/rkhelpsearchwindow.cpp	2011-09-08 09:36:57 UTC (rev 3731)
@@ -35,6 +35,7 @@
 
 #include "../rbackend/rinterface.h"
 #include "../rbackend/rcommandreceiver.h"
+#include "../rbackend/rksessionvars.h"
 #include "../debug.h"
 #include "../rkglobals.h"
 #include "../rkward.h"
@@ -45,7 +46,6 @@
 
 #define GET_HELP 1
 #define HELP_SEARCH 2
-#define GET_INSTALLED_PACKAGES 3
 
 // result columns
 #define COL_TYPE 0
@@ -103,12 +103,9 @@
 
 	packagesList = new QComboBox (this);
 	packagesList->setEditable (false);
-	packagesList->addItem (i18n("All installed packages"));
-	packagesList->addItem (i18n("All loaded packages"));
-#if QT_VERSION >= 0x040400
-	packagesList->insertSeparator (2);
-#endif
 	fields_packages_layout->addWidget (packagesList);
+	connect (RKSessionVars::instance (), SIGNAL (installedPackagesChanged()), this, SLOT (updateInstalledPackages()));
+	updateInstalledPackages ();
 
 	QVBoxLayout* checkboxes_layout = new QVBoxLayout ();
 	selection_layout->addLayout (checkboxes_layout);
@@ -134,8 +131,6 @@
 	connect (results_view, SIGNAL (doubleClicked(const QModelIndex&)), this, SLOT (resultDoubleClicked(const QModelIndex&)));
 	main_layout->addWidget (results_view);
 
-	RKGlobals::rInterface ()->issueCommand (".rk.get.installed.packages ()[[1]]", RCommand::App | RCommand::Sync | RCommand::GetStringVector, QString::null, this, GET_INSTALLED_PACKAGES, 0);
-
 	setCaption (i18n ("Help search"));
 }
 
@@ -225,6 +220,25 @@
 	getFunctionHelp (topic, package, type);
 }
 
+void RKHelpSearchWindow::updateInstalledPackages () {
+	RK_TRACE (APP);
+
+	QString old_value = packagesList->currentText ();
+
+	packagesList->clear ();
+	packagesList->addItem (i18n("All installed packages"));
+	packagesList->addItem (i18n("All loaded packages"));
+#if QT_VERSION >= 0x040400
+	packagesList->insertSeparator (2);
+#endif
+	packagesList->addItems (RKSessionVars::instance ()->installedPackages ());
+
+	int index = 0;
+	if (!old_value.isEmpty ()) index = packagesList->findText (old_value);
+	if (index < 0) index = 0;
+	packagesList->setCurrentIndex (index);
+}
+
 void RKHelpSearchWindow::rCommandDone (RCommand *command) {
 	RK_TRACE (APP);
 	if (command->getFlags () == HELP_SEARCH) {
@@ -242,12 +256,6 @@
 		if (command->failed ()) {
 			KMessageBox::sorry (this, i18n ("No help found on '%1'. Maybe the corresponding package is not installed/loaded, or maybe you mistyped the command. Try using Help->Search R Help for more options.", command->command ().section ("\"", 1, 1)), i18n ("No help found"));
 		}
-	} else if (command->getFlags () == GET_INSTALLED_PACKAGES) {
-		RK_ASSERT (command->getDataType () == RData::StringVector);
-		unsigned int count = command->getDataLength ();
-		for (unsigned int i=0; i < count; ++i) {
-			packagesList->addItem (command->getStringVector ()[i]);
-		}
 	} else {
 		RK_ASSERT (false);
 	}

Modified: trunk/rkward/rkward/windows/rkhelpsearchwindow.h
===================================================================
--- trunk/rkward/rkward/windows/rkhelpsearchwindow.h	2011-09-07 08:21:54 UTC (rev 3730)
+++ trunk/rkward/rkward/windows/rkhelpsearchwindow.h	2011-09-08 09:36:57 UTC (rev 3731)
@@ -52,6 +52,7 @@
 public slots:
 	void slotFindButtonClicked();
 	void resultDoubleClicked (const QModelIndex& index);
+	void updateInstalledPackages ();
 protected:
 /** reimplemnented from QWidget to make the input focus default to the input field */
 	void focusInEvent (QFocusEvent *e);

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.





More information about the rkward-tracker mailing list