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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Mon Jun 28 14:39:45 UTC 2010


Revision: 2908
          http://rkward.svn.sourceforge.net/rkward/?rev=2908&view=rev
Author:   tfry
Date:     2010-06-28 14:39:45 +0000 (Mon, 28 Jun 2010)

Log Message:
-----------
X11 windows gain a status-display. Closing X11 windows now always uses dev.off(), and thus saves the current plot to the history.

Modified Paths:
--------------
    trunk/rkward/rkward/rbackend/rcommandreceiver.h
    trunk/rkward/rkward/rkward.cpp
    trunk/rkward/rkward/windows/rkwindowcatcher.cpp
    trunk/rkward/rkward/windows/rkwindowcatcher.h

Modified: trunk/rkward/rkward/rbackend/rcommandreceiver.h
===================================================================
--- trunk/rkward/rkward/rbackend/rcommandreceiver.h	2010-06-27 12:09:23 UTC (rev 2907)
+++ trunk/rkward/rkward/rbackend/rcommandreceiver.h	2010-06-28 14:39:45 UTC (rev 2908)
@@ -24,7 +24,7 @@
 /**
 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.
 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 invalid pointer operations.
+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.
 

Modified: trunk/rkward/rkward/rkward.cpp
===================================================================
--- trunk/rkward/rkward/rkward.cpp	2010-06-27 12:09:23 UTC (rev 2907)
+++ trunk/rkward/rkward/rkward.cpp	2010-06-28 14:39:45 UTC (rev 2908)
@@ -506,9 +506,11 @@
 	RKWorkplace::RKWorkplaceObjectList map = RKWorkplace::mainWorkplace ()->getObjectList ();
 	for (RKWorkplace::RKWorkplaceObjectList::const_iterator it = map.constBegin (); it != map.constEnd (); ++it){
 		if (!(*it)->close (true)) {
-			// If a child refuses to close, we return false.
-			slotSetStatusReady ();
-			return false;
+			if (!(*it)->isType (RKMDIWindow::X11Window)) {	// X11 windows have a delayed close
+				// If a child refuses to close, we return false.
+				slotSetStatusReady ();
+				return false;
+			}
 		}
 	}
 

Modified: trunk/rkward/rkward/windows/rkwindowcatcher.cpp
===================================================================
--- trunk/rkward/rkward/windows/rkwindowcatcher.cpp	2010-06-27 12:09:23 UTC (rev 2907)
+++ trunk/rkward/rkward/windows/rkwindowcatcher.cpp	2010-06-28 14:39:45 UTC (rev 2908)
@@ -84,6 +84,7 @@
 
 	RKCaughtX11Window* window = RKCaughtX11Window::getWindow (device_number);
 	if (window) {
+		window->setKilledInR ();
 		window->close (true);
 		QApplication::syncX ();
 	}
@@ -103,6 +104,7 @@
 #	include <QX11EmbedContainer>
 #endif
 #include <QTimer>
+#include <QCloseEvent>
 
 #include <ktoggleaction.h>
 #include <kdialog.h>
@@ -110,6 +112,7 @@
 #include <kvbox.h>
 #include <kwindowsystem.h>
 #include <kactioncollection.h>
+#include <kpassivepopup.h>
 
 #include "../rkglobals.h"
 #include "../rbackend/rinterface.h"
@@ -121,9 +124,10 @@
 // static
 QHash<int, RKCaughtX11Window*> RKCaughtX11Window::device_windows;
 
-RKCaughtX11Window::RKCaughtX11Window (WId window_to_embed, int device_number) : RKMDIWindow (0, X11Window) {
+RKCaughtX11Window::RKCaughtX11Window (WId window_to_embed, int device_number) : RKMDIWindow (0, X11Window), RCommandReceiver () {
 	RK_TRACE (MISC);
 
+	killed_in_r = false;
 	embedded = window_to_embed;
 	RKCaughtX11Window::device_number = device_number;
 	RK_ASSERT (!device_windows.contains (device_number));
@@ -135,6 +139,10 @@
 	setFocusPolicy (Qt::ClickFocus);
 	updateHistoryActions (0, 0);
 
+	status_popup = new KPassivePopup (this);
+	status_popup->setTimeout (0);
+	disconnect (status_popup, SIGNAL (clicked()), status_popup, SLOT (hide()));	// no auto-hiding, please
+
 	QVBoxLayout *layout = new QVBoxLayout (this);
 	layout->setContentsMargins (0, 0, 0, 0);
 	box_widget = new KVBox (this);
@@ -208,8 +216,23 @@
 	RKWardApplication::getApp ()->unregisterNameWatcher (embedded);
 #endif
 	error_dialog->autoDeleteWhenDone ();
+	delete status_popup;
 }
 
+bool RKCaughtX11Window::close (bool also_delete) {
+	RK_TRACE (MISC);
+
+	if (killed_in_r || RKGlobals::rInterface ()->backendIsDead ()) {
+		return RKMDIWindow::close (also_delete);
+	}
+
+	RCommand* c = new RCommand ("dev.off (" + QString::number (device_number) + ')', RCommand::App, i18n ("Shutting down device number %1", device_number), error_dialog);
+	setStatusMessage (i18n ("Closing device (saving history)"), c);
+	RKGlobals::rInterface ()->issueCommand (c);
+
+	return false;
+}
+
 void RKCaughtX11Window::prepareToBeAttached () {
 	RK_TRACE (MISC);
 
@@ -358,29 +381,37 @@
 void RKCaughtX11Window::nextPlot () {
 	RK_TRACE (MISC);
 
-	RKGlobals::rInterface ()->issueCommand ("rk.next.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load next plot in device number %1", device_number), error_dialog);
+	RCommand* c = new RCommand ("rk.next.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load next plot in device number %1", device_number), error_dialog);
 	updateHistoryActions (history_length, history_position+1);
+	setStatusMessage (i18n ("Loading plot from history"), c);
+	RKGlobals::rInterface ()->issueCommand (c);
 }
 
 void RKCaughtX11Window::previousPlot () {
 	RK_TRACE (MISC);
 
-	RKGlobals::rInterface ()->issueCommand ("rk.previous.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load previous plot in device number %1", device_number), error_dialog);
+	RCommand* c = new RCommand ("rk.previous.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load previous plot in device number %1", device_number), error_dialog);
 	updateHistoryActions (history_length, history_position-1);
+	setStatusMessage (i18n ("Loading plot from history"), c);
+	RKGlobals::rInterface ()->issueCommand (c);
 }
 
 void RKCaughtX11Window::firstPlot () {
 	RK_TRACE (MISC);
 
-	RKGlobals::rInterface ()->issueCommand ("rk.first.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load first plot in device number %1", device_number), error_dialog);
+	RCommand* c = new RCommand ("rk.first.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load first plot in device number %1", device_number), error_dialog);
 	updateHistoryActions (history_length, 1);
+	setStatusMessage (i18n ("Loading plot from history"), c);
+	RKGlobals::rInterface ()->issueCommand (c);
 }
 
 void RKCaughtX11Window::lastPlot () {
 	RK_TRACE (MISC);
 
-	RKGlobals::rInterface ()->issueCommand ("rk.last.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load last plot in device number %1", device_number), error_dialog);
+	RCommand* c = new RCommand ("rk.last.plot (" + QString::number (device_number) + ')', RCommand::App, i18n ("Load last plot in device number %1", device_number), error_dialog);
 	updateHistoryActions (history_length, history_length);
+	setStatusMessage (i18n ("Loading plot from history"), c);
+	RKGlobals::rInterface ()->issueCommand (c);
 }
 
 void RKCaughtX11Window::recordCurrentPlot () {
@@ -411,6 +442,30 @@
 	plot_last_action->setEnabled ((history_length > 0) && (position < history_length));
 }
 
+void RKCaughtX11Window::setStatusMessage (const QString& message, RCommand *command) {
+	RK_TRACE (MISC);
+
+	status_change_command = command;
+	if (command) command->addReceiver (this);
+	if (!message.isEmpty ()) {
+		status_popup->setView (QString (), message);
+		status_popup->show (xembed_container->mapToGlobal (QPoint (20, 20)));
+	} else {
+		status_popup->hide ();
+	}
+}
+
+void RKCaughtX11Window::rCommandDone (RCommand *command) {
+	RK_TRACE (MISC);
+
+	if (command == status_change_command) {
+		setStatusMessage (QString ());
+		status_popup->hide();
+	}
+	RCommandReceiver::rCommandDone (command);
+}
+
+
 ///////////////////////////////// END RKCaughtX11Window ///////////////////////////////
 /**************************************************************************************/
 //////////////////////////////// BEGIN RKCaughtX11WindowPart //////////////////////////

Modified: trunk/rkward/rkward/windows/rkwindowcatcher.h
===================================================================
--- trunk/rkward/rkward/windows/rkwindowcatcher.h	2010-06-27 12:09:23 UTC (rev 2907)
+++ trunk/rkward/rkward/windows/rkwindowcatcher.h	2010-06-28 14:39:45 UTC (rev 2908)
@@ -80,6 +80,7 @@
 
 
 #include "rkmdiwindow.h"
+#include "../rbackend/rcommandreceiver.h"
 
 #include <QHash>
 
@@ -92,9 +93,10 @@
 class RKProgressControl;
 class QX11EmbedContainer;
 class QWinHost;
+class KPassivePopup;
 
 /** An R X11 device window managed by rkward. */
-class RKCaughtX11Window : public RKMDIWindow {
+class RKCaughtX11Window : public RKMDIWindow, public RCommandReceiver {
 	Q_OBJECT
 public:
 /** ctor
@@ -115,6 +117,10 @@
 /** returns the window corresponding the to given R device number (or 0 if no such window exists) */
 	static RKCaughtX11Window* getWindow (int device_number) { return device_windows.value (device_number); };
 	void updateHistoryActions (int history_length, int position);
+/** Set a status message to be shown in a popup inside the window. The message persists until the given R command has finished, or until this function is called with an empty string.
+This should be used, when the plot is currently out-of-date (e.g. when loading a plot from history), _not_ when the window
+is simply busy (e.g. when saving the current plot to history). */
+	void setStatusMessage (const QString& message, RCommand* command=0);
 public slots:
 /** Fixed size action was (potentially) toggled. Update to the new state */
 	void fixedSizeToggled ();
@@ -145,11 +151,17 @@
 	void recordCurrentPlot ();
 /** history navigation */
 	void clearHistory ();
+
+/** reimplemented to keep window alive while saving history */
+	bool close (bool also_delete);
+	void setKilledInR () { killed_in_r = true; };
 private slots:
 	void doEmbed ();
 private:
+	void rCommandDone (RCommand *command);
 	friend class RKCaughtX11WindowPart;	// needs access to the actions
 	int device_number;
+	bool killed_in_r;
 	WId embedded;
 	KVBox *xembed_container;
 	QScrollArea *scroll_widget;
@@ -173,6 +185,9 @@
 	KAction *plot_first_action;
 	KAction *plot_last_action;
 
+	KPassivePopup* status_popup;
+	RCommand* status_change_command;
+
 	int history_length;
 	int history_position;
 };


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