[rkward-cvs] SF.net SVN: rkward: [2102] branches/KDE4_port

tfry at users.sourceforge.net tfry at users.sourceforge.net
Mon Oct 22 16:19:56 UTC 2007


Revision: 2102
          http://rkward.svn.sourceforge.net/rkward/?rev=2102&view=rev
Author:   tfry
Date:     2007-10-22 09:19:56 -0700 (Mon, 22 Oct 2007)

Log Message:
-----------
RControlWindow mostly functional

Modified Paths:
--------------
    branches/KDE4_port/TODO_KDE4
    branches/KDE4_port/rkward/debug.h
    branches/KDE4_port/rkward/main.cpp
    branches/KDE4_port/rkward/rbackend/rcommand.h
    branches/KDE4_port/rkward/rbackend/rcommandstack.cpp
    branches/KDE4_port/rkward/rbackend/rcommandstack.h
    branches/KDE4_port/rkward/rbackend/rinterface.cpp
    branches/KDE4_port/rkward/rbackend/rthread.cpp
    branches/KDE4_port/rkward/rkward.cpp
    branches/KDE4_port/rkward/rkward.h
    branches/KDE4_port/rkward/windows/rcontrolwindow.cpp
    branches/KDE4_port/rkward/windows/rcontrolwindow.h

Modified: branches/KDE4_port/TODO_KDE4
===================================================================
--- branches/KDE4_port/TODO_KDE4	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/TODO_KDE4	2007-10-22 16:19:56 UTC (rev 2102)
@@ -25,6 +25,7 @@
 	- look out for all failed signal/slot connections
 	- grep sources for "KDE4"
 	- remove all the passing around of KGlobal::config() as a parameter
+	- the whole idea of having a single mutex for everything is flawed. We should use several specialized ones
 
 rkcommandeditorwindow
 	- code completion will be broken. Fix after porting.

Modified: branches/KDE4_port/rkward/debug.h
===================================================================
--- branches/KDE4_port/rkward/debug.h	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/debug.h	2007-10-22 16:19:56 UTC (rev 2102)
@@ -19,6 +19,7 @@
 
 extern int RK_Debug_Level;
 extern int RK_Debug_Flags;
+extern int RK_Debug_CommandStep;
 
 // Debug-levels
 #define DL_TRACE 0

Modified: branches/KDE4_port/rkward/main.cpp
===================================================================
--- branches/KDE4_port/rkward/main.cpp	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/main.cpp	2007-10-22 16:19:56 UTC (rev 2102)
@@ -65,6 +65,7 @@
 
 int RK_Debug_Level = 0;
 int RK_Debug_Flags = ALL;
+int RK_Debug_CommandStep = 0;
 
 static KCmdLineOptions options;
 

Modified: branches/KDE4_port/rkward/rbackend/rcommand.h
===================================================================
--- branches/KDE4_port/rkward/rbackend/rcommand.h	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rbackend/rcommand.h	2007-10-22 16:19:56 UTC (rev 2102)
@@ -174,11 +174,12 @@
 		QuitCommand=32768		/**< The R backend should be killed */
 	};
 	enum CommandStatus {
-		WasTried=1,						/**< the command has been passed to the backend. */
-		Failed=2,							/**< the command failed */
-		HasOutput=4,					/**< command has a string output retrievable via RCommand::output () */
-		HasError=8,						/**< command has an error-message retrievable via RCommand::error () */
-		HasWarnings=16,			/**< command has warning-message(s) retrievable via RCommand::warnings () */
+		Running=1,						/**< command is currently running */
+		WasTried=2,						/**< the command has been passed to the backend. */
+		Failed=4,							/**< the command failed */
+		HasOutput=8,					/**< command has a string output retrievable via RCommand::output () */
+		HasError=16,						/**< command has an error-message retrievable via RCommand::error () */
+		HasWarnings=32,			/**< command has warning-message(s) retrievable via RCommand::warnings () */
 		ErrorIncomplete=512,		/**< backend rejected command as being incomplete */
 		ErrorSyntax=1024,			/**< backend rejected command as having a syntax error */
 		ErrorOther=2048,			/**< another error (not incomplete, not syntax error) has occurred while trying to execute the command */
@@ -214,6 +215,7 @@
 friend class RThread;
 friend class RInterface;
 friend class RCommandStack;
+friend class RCommandStackModel;
 /** internal function will be called by the backend, as the command gets passed through. Takes care of sending this command (back) to its receiver(s) */
 	void finished ();
 /** new output was generated. Pass on to receiver(s) */

Modified: branches/KDE4_port/rkward/rbackend/rcommandstack.cpp
===================================================================
--- branches/KDE4_port/rkward/rbackend/rcommandstack.cpp	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rbackend/rcommandstack.cpp	2007-10-22 16:19:56 UTC (rev 2102)
@@ -19,6 +19,7 @@
 #include <klocale.h>
 
 #include <QTimer>
+#include <QTime>
 
 #include "rinterface.h"
 
@@ -31,35 +32,40 @@
 	RK_TRACE (RBACKEND);
 	closed = true;
 	current_chain = this;
+	sub_stack = 0;
 
+	RCommandStackModel::getModel ()->aboutToAdd (parent_command);
 	RCommandStack::parent_command = parent_command;
 	if (parent_command) {
 		RCommandStack* parent_stack = stackForCommand (parent_command);
 		RK_ASSERT (parent_stack);
 		parent_stack->sub_stack = this;
 	}
+	RCommandStackModel::getModel ()->addComplete ();
 }
 
 RCommandStack::~RCommandStack () {
 	RK_TRACE (RBACKEND);
 
+	RCommandStackModel::getModel ()->aboutToPop (parent_command);
 	if (parent_command) {
 		RCommandStack* parent_stack = stackForCommand (parent_command);
 		RK_ASSERT (parent_stack);
 		parent_stack->sub_stack = 0;
 	}
+	RCommandStackModel::getModel ()->popComplete ();
 }
 
 void RCommandStack::issueCommand (RCommand *command, RCommandChain *chain) {
 	RK_TRACE (RBACKEND);
 	if (!chain) chain = regular_stack;
 
-	RCommandStackModel::getModel ()->aboutToAdd (command);
+	RCommandStackModel::getModel ()->aboutToAdd (chain);
 
 	chain->commands.append (command);
 	command->parent = chain;
 
-	RCommandStackModel::getModel ()->addComplete (command);
+	RCommandStackModel::getModel ()->addComplete ();
 }
 
 RCommandChain *RCommandStack::startChain (RCommandChain *parent) {
@@ -67,13 +73,12 @@
 	if (!parent) parent = regular_stack;
 
 	RCommandChain *chain = new RCommandChain ();
-	RCommandStackModel::getModel ()->aboutToAdd (chain);
-
+	RCommandStackModel::getModel ()->aboutToAdd (parent);
 	chain->closed = false;
 	chain->parent = parent;
 	parent->commands.append (chain);
 
-	RCommandStackModel::getModel ()->addComplete (chain);
+	RCommandStackModel::getModel ()->addComplete ();
 
 	return chain;
 }
@@ -83,11 +88,20 @@
 	if (!chain) return;
 
 	chain->closed = true;
+	RCommandStackModel::getModel ()->itemChange (chain);
 }
 
 RCommand* RCommandStack::currentCommand () {
 	RK_TRACE (RBACKEND);
 
+	if (RK_Debug_CommandStep) {
+		MUTEX_UNLOCK;
+		QTime t;
+		t.start ();
+		while (t.elapsed () < RK_Debug_CommandStep) {}
+		MUTEX_LOCK;
+	}
+
 	clearFinishedChains ();
 	RCommandBase *coc = current_chain;
 	while (coc->chainPointer ()) {
@@ -149,9 +163,9 @@
 	if (!isActive ()) return;
 	RCommandBase* popped = current_chain->commands.first ();
 	RK_ASSERT (popped->commandPointer ());
-	RCommandStackModel::getModel ()->aboutToPop (popped->commandPointer ());
+	RCommandStackModel::getModel ()->aboutToPop (popped->parent);
 	current_chain->commands.removeFirst ();
-	RCommandStackModel::getModel ()->popComplete (popped->commandPointer ());
+	RCommandStackModel::getModel ()->popComplete ();
 }
 
 void RCommandStack::clearFinishedChains () {
@@ -160,16 +174,22 @@
 	// reached end of chain and chain is closed? walk up
 	while (current_chain->commands.isEmpty () && current_chain->closed && current_chain->parent) {
 		RCommandChain *prev_chain = current_chain;
-		RCommandStackModel::getModel ()->aboutToPop (prev_chain);
+		RCommandStackModel::getModel ()->aboutToPop (current_chain->parent);
 		current_chain->parent->commands.removeFirst ();
 		current_chain = current_chain->parent;
 		delete prev_chain;
-		RCommandStackModel::getModel ()->popComplete (prev_chain);
+		RCommandStackModel::getModel ()->popComplete ();
 	}
 }
 
 /////////////////////// RCommandStackModel ////////////////////
 
+#define MAIN_COL 0
+#define STATUS_COL 1
+#define FLAGS_COL 2
+#define DESC_COL 3
+#define NUM_COLS 4
+
 // static
 RCommandStackModel* RCommandStackModel::static_model = 0;
 
@@ -181,8 +201,11 @@
 	listeners = 0;
 	have_mutex_lock = false;
 
-	connect (this, SIGNAL (change()), this, SLOT (relayChange()), Qt::BlockingQueuedConnection);
-	connect (this, SIGNAL (aboutToChange()), this, SLOT (relayAboutToChange()), Qt::BlockingQueuedConnection);
+	connect (this, SIGNAL (itemAboutToBeAdded(RCommandBase*)), this, SLOT (relayItemAboutToBeAdded(RCommandBase*)), Qt::BlockingQueuedConnection);
+	connect (this, SIGNAL (itemAdded()), this, SLOT (relayItemAdded()), Qt::BlockingQueuedConnection);
+	connect (this, SIGNAL (itemAboutToBeRemoved(RCommandBase*)), this, SLOT (relayItemAboutToBeRemoved(RCommandBase*)), Qt::BlockingQueuedConnection);
+	connect (this, SIGNAL (itemRemoved()), this, SLOT (relayItemRemoved()), Qt::BlockingQueuedConnection);
+	connect (this, SIGNAL (itemChanged(RCommandBase*)), this, SLOT (relayItemChanged(RCommandBase*)), Qt::BlockingQueuedConnection);
 }
 
 RCommandStackModel::~RCommandStackModel () {
@@ -192,9 +215,16 @@
 	RK_ASSERT (!listeners);
 }
 
+void RCommandStackModel::addListener () {
+	RK_TRACE (RBACKEND);
+	lockMutex ();	// this should make sure, a listener is not added in the middle of a beginRowsXXX and endRowsXXX signal pair
+
+	++listeners;
+}
+
 void RCommandStackModel::removeListener () {
 	RK_TRACE (RBACKEND);
-qDebug ("remove");
+
 	--listeners;
 	if (!listeners) unlockMutex ();
 }
@@ -220,7 +250,10 @@
 		} else {
 			// parent is a chain or stack
 			RCommandChain *chain = parent_index->chainPointer ();
-			RK_ASSERT (chain->commands.size () > row);
+			if (chain->commands.size () <= row) {
+				RK_ASSERT (false);
+				return QModelIndex ();
+			}
 			index_data = chain->commands[row];
 		}
 	}
@@ -263,7 +296,13 @@
 	RCommandBase* index_data = static_cast<RCommandBase*> (parent.internalPointer ());
 	RK_ASSERT (index_data);
 	if (index_data->commandPointer ()) {
-		if (RCommandStack::stackForCommand (index_data->commandPointer ())->sub_stack) return 1;
+		RCommandStack *substack = RCommandStack::stackForCommand (index_data->commandPointer ())->sub_stack;
+		if (substack) {
+			if (substack->parent_command == index_data) {
+				RK_ASSERT (parent.row () == 0);
+				return 1;
+			}
+		}
 		return 0;
 	}
 	if (index_data->chainPointer ()) {
@@ -278,7 +317,7 @@
 	RK_TRACE (RBACKEND);
 	lockMutex ();
 
-	return 2;
+	return NUM_COLS;
 }
 
 QVariant RCommandStackModel::data (const QModelIndex& index, int role) const {
@@ -292,17 +331,43 @@
 	RCommandBase* index_data = static_cast<RCommandBase*> (index.internalPointer ());
 
 	if (index_data->commandPointer ()) {
-		if ((index.column () == 0) && (role == Qt::DisplayRole)) return (index_data->commandPointer ()->command ());
-		if ((index.column () == 1) && (role == Qt::DisplayRole)) return ("Some flags");
+		RCommand *command = index_data->commandPointer ();
+		if ((index.column () == MAIN_COL) && (role == Qt::DisplayRole)) return (command->command ());
+		if ((index.column () == FLAGS_COL) && (role == Qt::DisplayRole)) {
+			QString ret;
+			if (command->type () & RCommand::User) ret += 'U';
+			if (command->type () & RCommand::Plugin) ret += 'P';
+			if (command->type () & RCommand::PluginCom) ret += 'C';
+			if (command->type () & RCommand::App) ret += 'A';
+			if (command->type () & RCommand::Sync) ret += 'S';
+			if (command->type () & RCommand::EmptyCommand) ret += 'E';
+			if (command->type () & (RCommand::GetIntVector | RCommand::GetRealVector | RCommand::GetStringVector)) ret += 'D';
+			if (command->type () & RCommand::DirectToOutput) ret += 'O';
+			return (ret);
+		}
+		if ((index.column () == STATUS_COL) && (role == Qt::DisplayRole)) {
+			QString ret;
+			if (command->status & RCommand::Running) ret += i18n ("Running");
+			if (command->status & RCommand::Canceled) {
+				if (!ret.isEmpty ()) ret += ", ";
+				ret += i18n ("Cancelled");
+			}
+			return (ret);
+		}
+		if ((index.column () == DESC_COL) && (role == Qt::DisplayRole)) {
+			return (command->rkEquivalent ());
+		}
 	}
 	if (index_data->chainPointer ()) {
 		RCommandChain* chain = index_data->chainPointer ();
 		if (chain->isStack ()) {
-			if ((index.column () == 0) && (role == Qt::DisplayRole)) return (i18n ("Command Stack"));
-			if ((index.column () == 1) && (role == Qt::DisplayRole)) return ("Some flags");
+			if ((index.column () == MAIN_COL) && (role == Qt::DisplayRole)) return (i18n ("Command Stack"));
 		} else {
-			if ((index.column () == 0) && (role == Qt::DisplayRole)) return (i18n ("Command Group"));
-			if ((index.column () == 1) && (role == Qt::DisplayRole)) return ("Some flags");
+			if ((index.column () == MAIN_COL) && (role == Qt::DisplayRole)) return (i18n ("Command Chain"));
+			if ((index.column () == STATUS_COL) && (role == Qt::DisplayRole)) {
+				if (chain->closed) return (i18n ("Closed"));
+				return (i18n ("Waiting"));
+			}
 		}
 	}
 
@@ -314,50 +379,101 @@
 	RK_TRACE (RBACKEND);
 	lockMutex ();
 
-	if ((orientation == Qt::Horizontal) && (role = Qt::DisplayRole)) {
-		if (section == 0) return (i18n ("Command"));
-		if (section == 1) return (i18n ("Flags"));
+	if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) {
+		if (section == MAIN_COL) return (i18n ("Command"));
+		if (section == FLAGS_COL) return (i18n ("Type"));
+		if (section == STATUS_COL) return (i18n ("Status"));
+		if (section == DESC_COL) return (i18n ("Description"));
 	}
 
 	return QVariant ();
 }
 
-void RCommandStackModel::aboutToPop (RCommandBase* popped) {
+QModelIndex RCommandStackModel::indexFor (RCommandBase *item) {
+	RK_ASSERT (listeners);
+	RK_TRACE (RBACKEND);
+
+	if (!item) return (QModelIndex ());
+
+	if (item->chainPointer () && item->chainPointer ()->isStack ()) {
+		// stacks are always the first (and only) child of their parent
+		return (createIndex (0, 0, item));
+	}
+
+	RK_ASSERT (item->parent);
+	int row = item->parent->commands.indexOf (item);
+	if (row < 0) {
+		RK_ASSERT (false);
+		return (QModelIndex ());
+	}
+	return (createIndex (row, 0, item));
+}
+
+void RCommandStackModel::aboutToPop (RCommandBase* parent) {
 	if (!listeners) return;
 	RK_TRACE (RBACKEND);
 
-	RK_ASSERT (RInterface::inRThread ());
-	MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
-	emit (aboutToChange ());
-	MUTEX_LOCK;
+	if (RInterface::inRThread ()) {
+		MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
+		emit (itemAboutToBeRemoved (parent));
+		MUTEX_LOCK;
+	} else {
+		relayItemAboutToBeRemoved (parent);
+	}
 }
 
-void RCommandStackModel::popComplete (RCommandBase* popped) {
+void RCommandStackModel::popComplete () {
 	if (!listeners) return;
 	RK_TRACE (RBACKEND);
 
-	RK_ASSERT (RInterface::inRThread ());
-	MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
-	emit (change ());
-	MUTEX_LOCK;
+	if (RInterface::inRThread ()) {
+		MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
+		emit (itemRemoved ());
+		MUTEX_LOCK;
+	} else {
+		relayItemRemoved ();
+	}
 }
 
-void RCommandStackModel::aboutToAdd (RCommandBase* added) {
+void RCommandStackModel::aboutToAdd (RCommandBase* parent) {
 	if (!listeners) return;
 	RK_TRACE (RBACKEND);
 
-	RK_ASSERT (!RInterface::inRThread ());
-	relayAboutToChange ();
+	if (RInterface::inRThread ()) {
+		MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
+		emit (itemAboutToBeAdded (parent));
+		MUTEX_LOCK;
+	} else {
+		relayItemAboutToBeAdded (parent);
+	}
 }
 
-void RCommandStackModel::addComplete (RCommandBase* added) {
+void RCommandStackModel::addComplete () {
 	if (!listeners) return;
 	RK_TRACE (RBACKEND);
 
-	RK_ASSERT (!RInterface::inRThread ());
-	relayChange ();
+	if (RInterface::inRThread ()) {
+		MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
+		emit (itemAdded ());
+		MUTEX_LOCK;
+	} else {
+		relayItemAdded ();
+	}
 }
 
+void RCommandStackModel::itemChange (RCommandBase* item) {
+	if (!listeners) return;
+	RK_TRACE (RBACKEND);
+
+	if (RInterface::inRThread ()) {
+		MUTEX_UNLOCK;	// release the mutex in the R thread, as the main thread will need it.
+		emit (itemChanged (item));
+		MUTEX_LOCK;
+	} else {
+		relayItemChanged (item);
+	}
+}
+
 void RCommandStackModel::lockMutex () const {
 	if (have_mutex_lock) return;
 	RK_TRACE (RBACKEND);
@@ -367,10 +483,10 @@
 	MUTEX_LOCK;
 // We're playing silly const games, here, as the reimplemenations from QAbstractItemModel need to be const.
 // Well, we're not really changing anything, though, just keeping track of the mutex lock.
-	QTimer::singleShot (0, const_cast<RCommandStackModel*> (this), SLOT (unlockMutex()));
-
 	bool *cheat = const_cast<bool*> (&have_mutex_lock);
 	*cheat = true;
+
+	QTimer::singleShot (0, const_cast<RCommandStackModel*> (this), SLOT (unlockMutex()));
 }
 
 void RCommandStackModel::unlockMutex () {
@@ -383,25 +499,54 @@
 	have_mutex_lock = false;
 }
 
-void RCommandStackModel::relayChange () {
+void RCommandStackModel::relayItemAboutToBeAdded (RCommandBase* parent) {
 	RK_TRACE (RBACKEND);
 
 	RK_ASSERT (!RInterface::inRThread ());
-// TODO: for now we update everything on every change
-// TODO: will need mutex locking for real solution
 
-	emit (layoutChanged ());
+	QModelIndex parent_index = indexFor (parent);
+	if (parent->commandPointer ()) {
+		beginInsertRows (parent_index, 0, 0);
+	} else {
+		// items are always added at the end
+		int row = parent->chainPointer ()->commands.size ();
+		beginInsertRows (parent_index, row, row);
+	}
 }
 
-void RCommandStackModel::relayAboutToChange () {
+void RCommandStackModel::relayItemAdded () {
 	RK_TRACE (RBACKEND);
 
 	RK_ASSERT (!RInterface::inRThread ());
-// TODO: for now we update everything on every change
-// TODO: will need mutex locking for real solution
 
-	emit (layoutAboutToBeChanged ());
+	endInsertRows ();
 }
 
+void RCommandStackModel::relayItemAboutToBeRemoved (RCommandBase* parent) {
+	RK_TRACE (RBACKEND);
 
+	RK_ASSERT (!RInterface::inRThread ());
+
+	QModelIndex parent_index = indexFor (parent);
+	// items are always removed at the front
+	beginRemoveRows (parent_index, 0, 0);
+}
+
+void RCommandStackModel::relayItemRemoved () {
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RInterface::inRThread ());
+
+	endRemoveRows ();
+}
+
+void RCommandStackModel::relayItemChanged (RCommandBase* item) {
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RInterface::inRThread ());
+
+	QModelIndex item_index = indexFor (item);
+	emit (dataChanged (item_index, item_index));
+}
+
 #include "rcommandstack.moc"

Modified: branches/KDE4_port/rkward/rbackend/rcommandstack.h
===================================================================
--- branches/KDE4_port/rkward/rbackend/rcommandstack.h	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rbackend/rcommandstack.h	2007-10-22 16:19:56 UTC (rev 2102)
@@ -29,7 +29,6 @@
 class RCommandStack : public RCommandChain {
 public:
 	RCommandStack (RCommand *parent_command);
-
 	~RCommandStack ();
 
 /** add a command to the given chain (static, as it does no matter, which stack the chain belongs to) */
@@ -106,25 +105,34 @@
 	/** static pointer to the model. Only one model will ever be around. */
 	static RCommandStackModel* getModel () { return static_model; };
 
-	void addListener () { ++listeners; };
+	void addListener ();
 	void removeListener ();
 
-	void aboutToPop (RCommandBase* popped);
-	void popComplete (RCommandBase* popped);
-	void aboutToAdd (RCommandBase* added);
-	void addComplete (RCommandBase* added);
+	void aboutToPop (RCommandBase* parent);
+	void popComplete ();
+	void aboutToAdd (RCommandBase* parent);
+	void addComplete ();
+	void itemChange (RCommandBase* item);
 private slots:
 	void unlockMutex ();
-	void relayAboutToChange ();
-	void relayChange ();
+	void relayItemAboutToBeAdded (RCommandBase* parent);
+	void relayItemAdded ();
+	void relayItemAboutToBeRemoved (RCommandBase* parent);
+	void relayItemRemoved ();
+	void relayItemChanged (RCommandBase* item);
 signals:
-	void change ();
-	void aboutToChange ();
+	void itemAboutToBeAdded (RCommandBase* parent);
+	void itemAdded ();
+	void itemAboutToBeRemoved (RCommandBase* parent);
+	void itemRemoved ();
+	void itemChanged (RCommandBase* item);
 private:
 	void lockMutex () const;
 	int listeners;
 	static RCommandStackModel* static_model;
 	bool have_mutex_lock;
+
+	QModelIndex indexFor (RCommandBase *item);
 };
 
 #endif

Modified: branches/KDE4_port/rkward/rbackend/rinterface.cpp
===================================================================
--- branches/KDE4_port/rkward/rbackend/rinterface.cpp	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rbackend/rinterface.cpp	2007-10-22 16:19:56 UTC (rev 2102)
@@ -75,12 +75,15 @@
 		RK_DO (qDebug ("No R_HOME environment variable set. RKWard will quit in a moment. Always start rkward in the default way unless you know what you're doing."), RBACKEND, DL_ERROR);
 	}
 
+	new RCommandStackModel (this);
 	RCommandStack::regular_stack = new RCommandStack (0);
-	new RCommandStackModel (this);
 	running_command_canceled = 0;
 
 	r_thread = new RThread ();
 
+	// create a fake init command
+	issueCommand (new RCommand (i18n ("R Startup"), RCommand::App, i18n ("R Startup")));
+
 	flush_timer = new QTimer (this);
 	connect (flush_timer, SIGNAL (timeout ()), this, SLOT (flushOutput ()));
 	flush_timer->start (FLUSH_INTERVAL);

Modified: branches/KDE4_port/rkward/rbackend/rthread.cpp
===================================================================
--- branches/KDE4_port/rkward/rbackend/rthread.cpp	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rbackend/rthread.cpp	2007-10-22 16:19:56 UTC (rev 2102)
@@ -81,9 +81,11 @@
 	int err;
 	bool previously_idle = false;
 
-	// we create a fake RCommand to capture all the output/errors during startup
-	current_command = new RCommand (i18n ("R Startup"), RCommand::App, i18n ("R Startup"));
-	current_command->parent = RCommandStack::regular_stack;
+	// in RInterface::RInterface() we create a fake RCommand to capture all the output/errors during startup
+	MUTEX_LOCK;
+	current_command = RCommandStack::regular_stack->currentCommand ();
+	RK_ASSERT (current_command);
+	MUTEX_UNLOCK;
 
 	if ((err = initialize ())) {
 		qApp->postEvent (RKGlobals::rInterface (), new QCustomEvent (RSTARTUP_ERROR_EVENT + err));
@@ -97,7 +99,9 @@
 
 	MUTEX_LOCK;
 	checkObjectUpdatesNeeded (true);
+	RCommandStack::regular_stack->pop ();	// remove the fake command
 	notifyCommandDone (current_command);
+	current_command = 0;
 	MUTEX_UNLOCK;
 
 	while (1) {
@@ -113,15 +117,15 @@
 	
 		// while commands are in queue, don't wait
 		while ((!locked) && RCommandStack::regular_stack->isActive () && !locked) {
-			RCommand *command = RCommandStack::regular_stack->currentCommand ();
+			current_command = RCommandStack::regular_stack->currentCommand ();
 			
-			if (command) {
+			if (current_command) {
 				// mutex will be unlocked inside
-				doCommand (command);
-				checkObjectUpdatesNeeded (command->type () & (RCommand::User | RCommand::ObjectListUpdate));
+				doCommand (current_command);
+				checkObjectUpdatesNeeded (current_command->type () & (RCommand::User | RCommand::ObjectListUpdate));
 				processX11Events ();
-				notifyCommandDone (command);	// command may be deleted after this
 				RCommandStack::regular_stack->pop ();
+				notifyCommandDone (current_command);	// command may be deleted after this
 			}
 		
 			if (killed) {
@@ -155,7 +159,6 @@
 	QCustomEvent *event = new QCustomEvent (RCOMMAND_IN_EVENT);
 	event->setData (command);
 	qApp->postEvent (RKGlobals::rInterface (), event);
-	current_command = command;
 
 	// step 2: actual handling
 	if (!((command->type () & RCommand::EmptyCommand) || (command->status & RCommand::Canceled))) {
@@ -171,6 +174,8 @@
 			runCommandInternal (".rk.cat.output (\"<hr>\\n\")", &error, false);
 			RK_ASSERT (!error);
 		}
+		command->status |= RCommand::Running;
+		RCommandStackModel::getModel ()->itemChange (command);
 
 		MUTEX_UNLOCK;
 	
@@ -249,6 +254,9 @@
 			MUTEX_LOCK;
 		}
 	}
+
+	command->status -= (command->status & RCommand::Running);
+	RCommandStackModel::getModel ()->itemChange (command);
 }
 
 
@@ -412,16 +420,16 @@
 				break;
 			}
 
-			RCommand *command = reply_stack->currentCommand ();
+			current_command = reply_stack->currentCommand ();
 			
-			if (command) {
+			if (current_command) {
 				// mutex will be unlocked inside
-				bool object_update_forced = (command->type () & RCommand::ObjectListUpdate);
-				doCommand (command);
+				bool object_update_forced = (current_command->type () & RCommand::ObjectListUpdate);
+				doCommand (current_command);
 				if (object_update_forced) checkObjectUpdatesNeeded (true);
 				processX11Events ();
-				notifyCommandDone (command);	// command may be deleted after this
 				reply_stack->pop ();
+				notifyCommandDone (current_command);	// command may be deleted after this
 			}
 		}
 
@@ -435,7 +443,9 @@
 		msleep (10);
 	}
 
+	MUTEX_LOCK;
 	delete reply_stack;
+	MUTEX_UNLOCK;
 }
 
 void RThread::handleStandardCallback (RCallbackArgs *args) {
@@ -629,4 +639,5 @@
 		changed_symbol_names.clear ();
 	}
 
+	RKWardMainWindow::discardStartupOptions ();
 }

Modified: branches/KDE4_port/rkward/rkward.cpp
===================================================================
--- branches/KDE4_port/rkward/rkward.cpp	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rkward.cpp	2007-10-22 16:19:56 UTC (rev 2102)
@@ -171,6 +171,7 @@
 	RK_TRACE (APP);
 
 	// these would not be strictly necessary, as we're exiting the app, anyway.
+	delete RControlWindow::getControl ();
 	delete RKGlobals::rInterface ();
 	delete RObjectList::getObjectList ();
 	delete RObjectBrowser::mainBrowser ();
@@ -206,8 +207,6 @@
 	//It's necessary to give a different name to all tool windows, or they won't be properly displayed
 	RObjectBrowser::object_browser = new RObjectBrowser (0, true, "workspace");
 
-	RControlWindow::control_window = new RControlWindow (0, true, "rcontrol");		// the control window needs to be initialized before startR () is called.
-
 	RKCommandLog *log = new RKCommandLog (0, true, "Command log");
 	log->setWindowIcon (SmallIcon ("format-justify-left"));
 	RKWorkplace::mainWorkplace ()->placeInToolWindowBar (log, KMultiTabBar::Bottom);
@@ -229,6 +228,7 @@
 	RKFileBrowser::main_browser->setCaption (i18n ("Files"));
 	RKWorkplace::mainWorkplace ()->placeInToolWindowBar (RKFileBrowser::main_browser, KMultiTabBar::Left);
 
+	RControlWindow::control_window = new RControlWindow (0, true, "rcontrol");
 	RControlWindow::getControl ()->setCaption (i18n ("Pending Jobs"));
 	RControlWindow::getControl ()->setWindowIcon (SmallIcon ("system-run"));
 	RKWorkplace::mainWorkplace ()->placeInToolWindowBar (RControlWindow::getControl (), KMultiTabBar::Bottom);
@@ -247,7 +247,6 @@
 	show ();
 
 	RKOutputWindow::initialize ();
-	RControlWindow::getControl ()->initialize ();
 
 	if (startup_options->initial_url) {
 		openWorkspace (*(startup_options->initial_url));
@@ -277,9 +276,6 @@
 	}
 
 	setCaption (QString ());	// our version of setCaption takes care of creating a correct caption, so we do not need to provide it here
-
-	delete startup_options;
-	startup_options = 0;
 }
 
 void RKWardMainWindow::initPlugins () {

Modified: branches/KDE4_port/rkward/rkward.h
===================================================================
--- branches/KDE4_port/rkward/rkward.h	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/rkward.h	2007-10-22 16:19:56 UTC (rev 2102)
@@ -99,6 +99,10 @@
 
 /** return pointer to startup options. WARNING: The options are deleted shortly after startup */
 	static RKWardStartupOptions* getStartupOptions () { return getMain()->startup_options; };
+	static void discardStartupOptions () {
+		delete (getMain()->startup_options);
+		getMain()->startup_options = 0;
+	};
 
 /** (try to) close all windows, and ask whether it is ok to quit */
 	bool doQueryQuit ();

Modified: branches/KDE4_port/rkward/windows/rcontrolwindow.cpp
===================================================================
--- branches/KDE4_port/rkward/windows/rcontrolwindow.cpp	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/windows/rcontrolwindow.cpp	2007-10-22 16:19:56 UTC (rev 2102)
@@ -20,6 +20,7 @@
 #include <qpushbutton.h>
 #include <QHBoxLayout>
 #include <QVBoxLayout>
+#include <QHeaderView>
 
 #include <klocale.h>
 #include <kmessagebox.h>
@@ -60,46 +61,45 @@
 
 	commands_view = new QTreeView (this);
 
-/*	commands_view->addColumn (i18n ("Command"));
-	commands_view->addColumn (i18n ("Type"));
-	commands_view->addColumn (i18n ("Flags"));
-	commands_view->addColumn (i18n ("Description")); */
 	commands_view->setSortingEnabled (false);
+	commands_view->header ()->setMovable (false);
+	commands_view->header ()->setStretchLastSection (false);
 
 	commands_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
-	connect (commands_view, SIGNAL (selectionChanged ()), this, SLOT (commandSelectionChanged ()));
 	main_vbox->addWidget (commands_view);
 
 	paused = false;
-	initialized = false;
 }
 
 RControlWindow::~RControlWindow () {
 	RK_TRACE (APP);
 
+	commands_view->setModel (0);
 	RCommandStackModel::getModel ()->removeListener ();
 }
 
-bool RControlWindow::isActive () {
-	// don't trace!
-	return (initialized && isShown ());
-}
-
-void RControlWindow::initialize () {
+void RControlWindow::showEvent (QShowEvent *e) {
 	RK_TRACE (APP);
-	initialized = true;
 
-	if (isShown ()) show ();	// refreshes the commands
+	if (!commands_view->model ()) {
+		RCommandStackModel::getModel ()->addListener ();
+		commands_view->setModel (RCommandStackModel::getModel ());
+		commands_view->header ()->setResizeMode (0, QHeaderView::Stretch);
+		commands_view->expandAll ();
+	}
+
+	RKMDIWindow::showEvent (e);
 }
 
-void RControlWindow::showEvent (QShowEvent *e) {
+void RControlWindow::hideEvent (QHideEvent *e) {
 	RK_TRACE (APP);
 
-	RKMDIWindow::showEvent (e);
-	if (!initialized) return;
+	if (commands_view->model ()) {
+		commands_view->setModel (0);
+		RCommandStackModel::getModel ()->removeListener ();
+	}
 
-	RCommandStackModel::getModel ()->addListener ();
-	commands_view->setModel (RCommandStackModel::getModel ());
+	RKMDIWindow::hideEvent (e);
 }
 
 void RControlWindow::commandSelectionChanged () {

Modified: branches/KDE4_port/rkward/windows/rcontrolwindow.h
===================================================================
--- branches/KDE4_port/rkward/windows/rcontrolwindow.h	2007-10-22 00:05:56 UTC (rev 2101)
+++ branches/KDE4_port/rkward/windows/rcontrolwindow.h	2007-10-22 16:19:56 UTC (rev 2102)
@@ -52,10 +52,9 @@
 /** destructor */
 	~RControlWindow ();
 
-/** reimplemented to refresh list of commands when showing. This is needed, as the RControlWindow is only kept up to date as long as it is shown. Hence, if it was hidden, and then gets shown, it will have to update the entire list. */
+/** reimplemented to refresh list of commands when showing. This is needed, as the RControlWindow is only kept up to date as long as it is shown. */
 	void showEvent (QShowEvent *e);
-/** Call this once, when the RInterface is ready, and it is ok to try showing commands */
-	void initialize ();
+	void hideEvent (QHideEvent *e);
 /** Static reference to the control window */
 	static RControlWindow* getControl () { return control_window; };
 public slots:
@@ -73,8 +72,6 @@
 	QPushButton *pause_button;
 
 	bool paused;
-	bool isActive ();
-	bool initialized;
 friend class RKWardMainWindow;
 	static RControlWindow *control_window;
 };


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