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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sun Oct 21 21:26:53 UTC 2007


Revision: 2099
          http://rkward.svn.sourceforge.net/rkward/?rev=2099&view=rev
Author:   tfry
Date:     2007-10-21 14:26:53 -0700 (Sun, 21 Oct 2007)

Log Message:
-----------
Start moving RControlWindow to model/view architecture.
This is not quite right, yet, and incomplete. Still fighting to get the mutex right.
Cleaned up the command stack (full hierarchy of commands/chains, and no premature deletion)

Modified Paths:
--------------
    branches/KDE4_port/rkward/dataeditor/rkeditordataframe.cpp
    branches/KDE4_port/rkward/rbackend/rcommand.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/rinterface.h
    branches/KDE4_port/rkward/rbackend/rthread.cpp
    branches/KDE4_port/rkward/rbackend/rthread.h
    branches/KDE4_port/rkward/windows/rcontrolwindow.cpp
    branches/KDE4_port/rkward/windows/rcontrolwindow.h

Modified: branches/KDE4_port/rkward/dataeditor/rkeditordataframe.cpp
===================================================================
--- branches/KDE4_port/rkward/dataeditor/rkeditordataframe.cpp	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/dataeditor/rkeditordataframe.cpp	2007-10-21 21:26:53 UTC (rev 2099)
@@ -139,7 +139,7 @@
 			}
 		}
 
-		open_chain = RKGlobals::rInterface ()->closeChain (open_chain);
+		RKGlobals::rInterface ()->closeChain (open_chain);
 		/* make sure enough rows are displayed. Note: Calling QTable::insertRows, since no data should be juggled around, only the number of visible rows is to be changed. */
 		if (dataview->numTrueRows () < getColObject (0)->getLength ()) {
 			dataview->Q3Table::insertRows (0, getColObject (0)->getLength () - dataview->numTrueRows ());

Modified: branches/KDE4_port/rkward/rbackend/rcommand.cpp
===================================================================
--- branches/KDE4_port/rkward/rbackend/rcommand.cpp	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rcommand.cpp	2007-10-21 21:26:53 UTC (rev 2099)
@@ -27,9 +27,25 @@
 
 #define MAX_RECEIVERS 3
 
+RCommandBase::RCommandBase (bool is_chain) {
+	is_command_chain = is_chain;
+	RCommandBase::parent = 0;
+}
+
+RCommand* RCommandBase::commandPointer () {
+	if (is_command_chain) return 0;
+	return static_cast<RCommand*> (this);
+}
+
+RCommandChain* RCommandBase::chainPointer () {
+	if (!is_command_chain) return 0;
+	return static_cast<RCommandChain*> (this);
+}
+
+
 int RCommand::next_id = 0;
 
-RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags) : RData () {
+RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags) : RData (), RCommandBase (false) {
 	RK_TRACE (RBACKEND);
 	_id = next_id++;
 // if we ever submit enough commands to get a buffer overflow, use only positive numbers.
@@ -52,7 +68,7 @@
 RCommand::~RCommand(){
 	RK_TRACE (RBACKEND);
 
-	for (Q3ValueList<ROutput*>::iterator it = output_list.begin (); it != output_list.end (); ++it) {
+	for (QList<ROutput*>::const_iterator it = output_list.constBegin (); it != output_list.constEnd (); ++it) {
 		delete (*it);
 	}
 	// The output_list itself is cleared automatically

Modified: branches/KDE4_port/rkward/rbackend/rcommand.h
===================================================================
--- branches/KDE4_port/rkward/rbackend/rcommand.h	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rcommand.h	2007-10-21 21:26:53 UTC (rev 2099)
@@ -21,39 +21,45 @@
 #include <qfile.h>
 #include <qstring.h>
 #include <qobject.h>
-#include <q3ptrlist.h>
-#include <q3valuelist.h>
+#include <QLinkedList>
 
 #include "rdata.h"
 
 class RCommandReceiver;
 class RCommand;
-class RChainOrCommand;
+class RCommandChain;
 
+/** Base class for RCommand and RCommandChain, to make it possible to store both in the same list */
+class RCommandBase {
+protected:
+friend class RCommandStack;
+friend class RCommandStackModel;
+	RCommandBase (bool is_chain);
+/** Returns the casted pointer, if this is a command, else 0 */
+	RCommand* commandPointer ();
+/** Returns the casted pointer, if this is a chain, else 0 */
+	RCommandChain* chainPointer ();
+	RCommandChain *parent;
+private:
+	bool is_command_chain;
+};
+
 /** this simple struct is used to ensure a sequence of RCommand s does not get interrupted by unrelated RCommands.
 @see \ref UsingTheInterfaceToR
 @see RInterface::startChain
 @see RInterface::closeChain */
-class RCommandChain {
+class RCommandChain : public RCommandBase {
 protected:
 friend class RControlWindow;
 friend class RControlWindowListViewItem;
 friend class RCommandStack;
-	Q3PtrList<RChainOrCommand> commands;
+friend class RCommandStackModel;
+	RCommandChain () : RCommandBase (true) {};
+	QList<RCommandBase*> commands;
 	bool closed;
-	RCommandChain *parent;
+	bool isStack () { return (parent == 0); }
 };
 
-/** this struct is needed by the RCommandStack. It is only a wrapper, which stores a pointer to _either_ a command _or_ a chain. Its sole purpose is to
-be able to insert either a command or a chain using the same mechanism, easily. You don't want to use this class outside of RCommandStack (TODO: move it to rcommandstack.h, then!) */
-class RChainOrCommand {
-private:
-friend class RControlWindow;
-friend class RCommandStack;
-	RCommand *command;
-	RCommandChain *chain;
-};
-
 /** this struct is used to pass on eval-requests (i.e. request for RKWard to do something, which may involve issuing further commands) from the
 backend-thread to the main thread. Do not use outside the backend-classes. */
 struct REvalRequest {
@@ -77,7 +83,7 @@
 	QString output;
 };
 
-typedef Q3ValueList<ROutput*> ROutputList;
+typedef QList<ROutput*> ROutputList;
 
 /*
 struct RGetValueRequest {
@@ -117,7 +123,7 @@
   *@author Thomas Friedrichsmeier
   */
   
-class RCommand : public RData {
+class RCommand : public RData, public RCommandBase {
 public:
 /** constructs an RCommand.
 @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.
@@ -207,6 +213,7 @@
 private:
 friend class RThread;
 friend class RInterface;
+friend class RCommandStack;
 /** 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-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rcommandstack.cpp	2007-10-21 21:26:53 UTC (rev 2099)
@@ -2,7 +2,7 @@
                           rcommandstack  -  description
                              -------------------
     begin                : Mon Sep 6 2004
-    copyright            : (C) 2004 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2007 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -16,6 +16,10 @@
  ***************************************************************************/
 #include "rcommandstack.h"
 
+#include <klocale.h>
+
+#include <QTimer>
+
 #include "rinterface.h"
 
 #include "../debug.h"
@@ -23,58 +27,71 @@
 //static
 RCommandStack *RCommandStack::regular_stack;
 
-RCommandStack::RCommandStack () : RCommandChain () {
+RCommandStack::RCommandStack (RCommand* parent_command) : RCommandChain () {
 	RK_TRACE (RBACKEND);
 	closed = true;
-	parent = 0;
 	current_chain = this;
+
+	RCommandStack::parent_command = parent_command;
+	if (parent_command) {
+		RCommandStack* parent_stack = stackForCommand (parent_command);
+		RK_ASSERT (parent_stack);
+		parent_stack->sub_stack = this;
+	}
 }
 
 RCommandStack::~RCommandStack () {
 	RK_TRACE (RBACKEND);
+
+	if (parent_command) {
+		RCommandStack* parent_stack = stackForCommand (parent_command);
+		RK_ASSERT (parent_stack);
+		parent_stack->sub_stack = 0;
+	}
 }
 
 void RCommandStack::issueCommand (RCommand *command, RCommandChain *chain) {
 	RK_TRACE (RBACKEND);
 	if (!chain) chain = regular_stack;
-	
-	RChainOrCommand *coc = new RChainOrCommand;
-	coc->command = command;
-	coc->chain = 0;
-	chain->commands.append (coc);
+
+	chain->commands.append (command);
+	command->parent = chain;
+
+	RCommandStackModel::getModel ()->newCommand ();
 }
 
 RCommandChain *RCommandStack::startChain (RCommandChain *parent) {
 	RK_TRACE (RBACKEND);
 	if (!parent) parent = regular_stack;
 
-	RChainOrCommand *coc = new RChainOrCommand;
-	coc->command = 0;
-	coc->chain = new RCommandChain;
-	coc->chain->closed = false;
-	coc->chain->parent = parent;
-	parent->commands.append (coc);
+	RCommandChain *chain = new RCommandChain ();
+	chain->closed = false;
+	chain->parent = parent;
+	parent->commands.append (chain);
 
-	return coc->chain;
+	RCommandStackModel::getModel ()->newChain ();
+
+	return chain;
 }
 
-RCommandChain *RCommandStack::closeChain (RCommandChain *chain) {
+void RCommandStack::closeChain (RCommandChain *chain) {
 	RK_TRACE (RBACKEND);
-	if (!chain) return 0;
+	if (!chain) return;
 
 	chain->closed = true;
-	RCommandChain *ret = chain->parent;
-	
-	RCommandStack *stack = chainStack (chain);
-	
-	// lets see, whether we can do some cleanup
-	while (stack->current_chain->commands.isEmpty () && stack->current_chain->closed && stack->current_chain->parent) {
-		RCommandChain *temp = stack->current_chain;
-		stack->current_chain = stack->current_chain->parent;
-		delete temp;
+	chainStack (chain)->clearFinishedChains ();
+}
+
+RCommand* RCommandStack::currentCommand () {
+	RK_TRACE (RBACKEND);
+
+	RCommandBase *coc = current_chain;
+	while (coc->chainPointer ()) {
+		current_chain = coc->chainPointer ();
+		if (current_chain->commands.isEmpty ()) return 0;
+		coc = current_chain->commands.first ();
 	}
-	
-	return ret;
+	return coc->commandPointer ();
 }
 
 bool RCommandStack::isEmpty () {
@@ -101,29 +118,271 @@
 	return static_cast<RCommandStack *> (child);
 }
 
-RCommand *RCommandStack::pop () {
+//static
+RCommandStack *RCommandStack::stackForCommand (RCommand *child) {
 	RK_TRACE (RBACKEND);
 
-	if (!isActive ()) return 0;
-	RCommand *command = 0;
-	
-	RChainOrCommand *coc = current_chain->commands.first ();
-	current_chain->commands.removeFirst ();
-	if (coc->command) {
-		command = coc->command;
-		delete coc;
-	} else {
-		current_chain = coc->chain;
-		delete coc;
-		command = pop ();
+	RCommandBase *chain = child;
+	while (chain->parent) {
+		chain = chain->parent;
 	}
+	return static_cast<RCommandStack *> (chain);
+}
 
+RCommandStack* RCommandStack::currentStack () {
+	RK_TRACE (RBACKEND);
+
+	RCommandStack* stack = regular_stack;
+	while (stack->sub_stack) {
+		stack = stack->sub_stack;
+	}
+	return stack;
+}
+
+void RCommandStack::pop () {
+	RK_TRACE (RBACKEND);
+
+	if (!isActive ()) return;
+	RCommandBase* popped = current_chain->commands.takeFirst ();
+	RK_ASSERT (popped->commandPointer ());
+
+	RCommandStackModel::getModel ()->commandPop (popped->commandPointer ());
+
+	clearFinishedChains ();
+}
+
+void RCommandStack::clearFinishedChains () {
+	RK_TRACE (RBACKEND);
+
 	// reached end of chain and chain is closed? walk up
 	while (current_chain->commands.isEmpty () && current_chain->closed && current_chain->parent) {
-		RCommandChain *temp = current_chain;
+		RCommandChain *prev_chain = current_chain;
+		current_chain->parent->commands.removeFirst ();
 		current_chain = current_chain->parent;
-		delete temp;
+		RCommandStackModel::getModel ()->chainPop (prev_chain);
+		delete prev_chain;
 	}
-	
-	return command;
 }
+
+/////////////////////// RCommandStackModel ////////////////////
+
+// static
+RCommandStackModel* RCommandStackModel::static_model = 0;
+
+RCommandStackModel::RCommandStackModel (QObject *parent) : QAbstractItemModel (parent) {
+	RK_TRACE (RBACKEND);
+	RK_ASSERT (static_model == 0);	// only one instance should be created
+
+	static_model = this;
+	listeners = 0;
+	have_mutex_lock = false;
+
+	connect (this, SIGNAL (change()), this, SLOT (relayChange()), Qt::BlockingQueuedConnection);
+}
+
+RCommandStackModel::~RCommandStackModel () {
+	RK_TRACE (RBACKEND);
+
+	static_model = 0;
+}
+
+QModelIndex RCommandStackModel::index (int row, int column, const QModelIndex& parent) const {
+	RK_ASSERT (listeners > 0);
+	RK_TRACE (RBACKEND);
+	lockMutex ();
+
+	RCommandBase* index_data = 0;
+
+	if (!parent.isValid ()) {
+		index_data = RCommandStack::regular_stack;
+	} else {
+		RCommandBase* parent_index = static_cast<RCommandBase*> (parent.internalPointer ());
+		RK_ASSERT (parent_index);
+
+		// parent is a command -> this must be a substack
+		if (parent_index->commandPointer ()) {
+			RK_ASSERT (parent.row () == 0);
+			index_data = RCommandStack::stackForCommand (parent_index->commandPointer ())->sub_stack;
+			RK_ASSERT (index_data);
+		} else {
+			// parent is a chain or stack
+			RCommandChain *chain = parent_index->chainPointer ();
+			RK_ASSERT (chain->commands.size () > row);
+			index_data = chain->commands[row];
+		}
+	}
+
+	return (createIndex (row, column, index_data));
+}
+
+QModelIndex RCommandStackModel::parent (const QModelIndex& child) const {
+	RK_ASSERT (listeners);
+	RK_TRACE (RBACKEND);
+	lockMutex ();
+
+	RCommandBase* index_data;
+	if (!child.isValid()) {
+		return QModelIndex ();
+	} else {
+		RCommandBase* child_index = static_cast<RCommandBase*> (child.internalPointer ());
+		RK_ASSERT (child_index);
+
+		if (child_index->chainPointer () && child_index->chainPointer ()->isStack ()) {
+			index_data = static_cast<RCommandStack*> (child_index->chainPointer ())->parent_command;
+			if (!index_data) {
+				return QModelIndex ();
+			}
+		} else {	// regular chains or commands
+			index_data = child_index->parent;
+		}
+	}
+
+	return (createIndex (0, 0, index_data));
+}
+
+int RCommandStackModel::rowCount (const QModelIndex& parent) const {
+	RK_ASSERT (listeners);
+	RK_TRACE (RBACKEND);
+	lockMutex ();
+
+	if (!parent.isValid ()) return 1;
+
+	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;
+		return 0;
+	}
+	if (index_data->chainPointer ()) {
+		return (index_data->chainPointer ()->commands.size ());
+	}
+	RK_ASSERT (false);
+	return 0;
+}
+
+int RCommandStackModel::columnCount (const QModelIndex&) const {
+	RK_ASSERT (listeners);
+	RK_TRACE (RBACKEND);
+	lockMutex ();
+
+	return 2;
+}
+
+QVariant RCommandStackModel::data (const QModelIndex& index, int role) const {
+	RK_ASSERT (listeners);
+	RK_TRACE (RBACKEND);
+	lockMutex ();
+
+	if (!index.isValid ()) return QVariant ();
+	RK_ASSERT (index.model () == this);
+
+	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");
+	}
+	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");
+		} else {
+			if ((index.column () == 0) && (role == Qt::DisplayRole)) return (i18n ("Command Group"));
+			if ((index.column () == 1) && (role == Qt::DisplayRole)) return ("Some flags");
+		}
+	}
+
+	return (QVariant ());
+}
+
+QVariant RCommandStackModel::headerData (int section, Qt::Orientation orientation, int role) const {
+	RK_ASSERT (listeners);
+	RK_TRACE (RBACKEND);
+	lockMutex ();
+
+	if ((orientation == Qt::Horizontal) && (role = Qt::DisplayRole)) {
+		if (section == 0) return (i18n ("Command"));
+		if (section == 1) return (i18n ("Flags"));
+	}
+
+	return QVariant ();
+}
+
+void RCommandStackModel::commandPop (RCommand* popped) {
+	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;
+}
+
+void RCommandStackModel::chainPop (RCommandChain* popped) {
+	if (!listeners) return;
+	RK_TRACE (RBACKEND);
+
+	// chains can be popped from both threads!
+	if (RInterface::inRThread ()) {
+		MUTEX_UNLOCK;
+		emit (change ());
+		MUTEX_LOCK;
+	} else {
+		relayChange ();
+	}
+}
+
+void RCommandStackModel::newCommand () {
+	if (!listeners) return;
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RInterface::inRThread ());
+	relayChange ();
+}
+
+void RCommandStackModel::newChain () {
+	if (!listeners) return;
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RInterface::inRThread ());
+	relayChange ();
+}
+
+void RCommandStackModel::lockMutex () const {
+	if (have_mutex_lock) return;
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RInterface::inRThread ());
+
+	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;
+}
+
+void RCommandStackModel::unlockMutex () {
+	if (!have_mutex_lock) return;
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RInterface::inRThread ());
+
+	MUTEX_UNLOCK;
+	have_mutex_lock = false;
+}
+
+void RCommandStackModel::relayChange () {
+	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 ());
+	emit (layoutChanged ());
+}
+
+
+#include "rcommandstack.moc"

Modified: branches/KDE4_port/rkward/rbackend/rcommandstack.h
===================================================================
--- branches/KDE4_port/rkward/rbackend/rcommandstack.h	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rcommandstack.h	2007-10-21 21:26:53 UTC (rev 2099)
@@ -2,7 +2,7 @@
                           rcommandstack  -  description
                              -------------------
     begin                : Mon Sep 6 2004
-    copyright            : (C) 2004 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2007 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -28,7 +28,7 @@
 */
 class RCommandStack : public RCommandChain {
 public:
-	RCommandStack ();
+	RCommandStack (RCommand *parent_command);
 
 	~RCommandStack ();
 
@@ -38,8 +38,8 @@
 /** add a sub-chain to the given chain (static, as it does no matter, which stack the chain belongs to) */
 	static RCommandChain *startChain (RCommandChain *parent);
 /** close the given chain, i.e. signal the chain may be deleted once its remaining commands are done
- (static, as it does no matter, which stack the chain belongs to).  @returns the parent of the closed chain. */
-	static RCommandChain *closeChain (RCommandChain *chain);
+ (static, as it does no matter, which stack the chain belongs to). */
+	static void closeChain (RCommandChain *chain);
 
 /** @returns true, if there are no commands or open chains waiting in this stack */
 	bool isEmpty ();
@@ -48,15 +48,81 @@
 /** @returns true, if there are commands to be processed in the current chain */
 	bool isActive ();
 
-/** removes the RCommand to be processed next from the stack and returns it. If there is no command to process right now, returns 0 */
-	RCommand *pop ();
+/** removes the RCommand to be processed next from the stack and sets it as the currentCommand(). If there is no command to process right now, currentCommand() will be 0. Note: we can't just return the popped command for internal reasons. */
+	void pop ();
 
+/** see pop() */
+	RCommand* currentCommand ();
+
 /** the regular command stack, i.e. not a callback */
 	static RCommandStack *regular_stack;
+
+	static RCommandStack* currentStack ();
+
 /** return the parent RCommandStack of the given RCommandChain */
 	static RCommandStack *chainStack (RCommandChain *child);
+/** return the parent RCommandStack of the given RCommand */
+	static RCommandStack *stackForCommand (RCommand *child);
 private:
+friend class RCommandStackModel;
 	RCommandChain *current_chain;
+/** super-ordinated command. 0 for the regular_stack */
+	RCommand *parent_command;
+/** pointer to any substack. Will only be non-zero, if the substack is active */
+	RCommandStack *sub_stack;
+	void clearFinishedChains ();
 };
 
+#include <QAbstractItemModel>
+
+/** The model used to fetch a representation of and signal changes in the RCommandStack. Used for RKControlWindow.
+
+- All insertions / removals are signalled to the (single) model
+- it is ok for the model to be slow. It will simply walk the entire stack to find the corresponding indices
+- the model keeps track of (the number of) listeners, and does not do anything unless there are any listeners (including walking the stack)
+- RControlWindow will only be constructed on show, and destructed on hide, so as not to eat ressources
+
+ at author Thomas Friedrichsmeier
+*/
+class RCommandStackModel : public QAbstractItemModel {
+	Q_OBJECT
+public:
+	RCommandStackModel (QObject *parent);
+	~RCommandStackModel ();
+
+	/** implements QAbstractItemModel::index() */
+	QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex ()) const;
+	/** implements QAbstractItemModel::parent() */
+	QModelIndex parent (const QModelIndex& index) const;
+	/** implements QAbstractItemModel::rowCount() */
+	int rowCount (const QModelIndex& parent = QModelIndex ()) const;
+	/** implements QAbstractItemModel::columnCount(). This is identical for all items */
+	int columnCount (const QModelIndex& parent = QModelIndex ()) const;
+	/** implements QAbstractItemModel::data() */
+	QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const;
+	/** reimplemented from  QAbstractItemModel::headerData() to provide column names */
+	QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+	/** static pointer to the model. Only one model will ever be around. */
+	static RCommandStackModel* getModel () { return static_model; };
+
+	void addListener () { ++listeners; };
+	void removeListener () { --listeners; };
+
+	void commandPop (RCommand* popped);
+	void chainPop (RCommandChain* popped);
+	void newCommand ();
+	void newChain ();
+private slots:
+	void unlockMutex ();
+	void relayChange ();
+signals:
+	void change ();
+private:
+	void lockMutex () const;
+	int listeners;
+	static RCommandStackModel* static_model;
+	bool have_mutex_lock;
+};
+
 #endif

Modified: branches/KDE4_port/rkward/rbackend/rinterface.cpp
===================================================================
--- branches/KDE4_port/rkward/rbackend/rinterface.cpp	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rinterface.cpp	2007-10-21 21:26:53 UTC (rev 2099)
@@ -75,7 +75,8 @@
 		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);
 	}
 
-	RCommandStack::regular_stack = new RCommandStack ();
+	RCommandStack::regular_stack = new RCommandStack (0);
+	new RCommandStackModel (this);
 	running_command_canceled = 0;
 
 	r_thread = new RThread ();
@@ -125,6 +126,10 @@
 	return (idle);
 }
 
+bool RInterface::inRThread () {
+	return (QThread::currentThread () == RKGlobals::rInterface ()->r_thread);
+}
+
 void RInterface::startThread () {
 	RK_TRACE (RBACKEND);
 	r_thread->start ();
@@ -150,7 +155,6 @@
 		}
 	} else if (e->type () == RCOMMAND_IN_EVENT) {
 		RKCommandLog::getLog ()->addInput (static_cast <RCommand *> (static_cast<QCustomEvent*> (e)->data ()));
-		RControlWindow::getControl ()->setCommandRunning (static_cast <RCommand *> (static_cast<QCustomEvent*> (e)->data ()));
 	} else if (e->type () == RCOMMAND_OUT_EVENT) {
 		RCommand *command = static_cast <RCommand *> (static_cast<QCustomEvent*> (e)->data ());
 		if (command->status & RCommand::Canceled) {
@@ -167,7 +171,6 @@
 				r_thread->unlock (RThread::Cancel);
 			}
 		}
-		RControlWindow::getControl ()->removeCommand (command);
 		command->finished ();
 		if (command->type () & RCommand::DirectToOutput) {
 			RKWorkplace::mainWorkplace ()->newOutput (false);
@@ -217,7 +220,6 @@
 	MUTEX_LOCK;
 	if (command->command ().isEmpty ()) command->_type |= RCommand::EmptyCommand;
 	RCommandStack::issueCommand (command, chain);
-	RControlWindow::getControl ()->addCommand (command, chain);
 	MUTEX_UNLOCK;
 }
 
@@ -226,19 +228,16 @@
 	RCommandChain *ret;
 	MUTEX_LOCK;
 	ret = RCommandStack::startChain (parent);
-	RControlWindow::getControl ()->addChain (ret);
 	MUTEX_UNLOCK;
 	return ret;
 };
 
-RCommandChain *RInterface::closeChain (RCommandChain *chain) {
+void RInterface::closeChain (RCommandChain *chain) {
 	RK_TRACE (RBACKEND);
-	RCommandChain *ret;
+
 	MUTEX_LOCK;
-	ret = RCommandStack::closeChain (chain);
-	RControlWindow::getControl ()->updateChain (chain);
+	RCommandStack::closeChain (chain);
 	MUTEX_UNLOCK;
-	return ret;
 };
 
 void RInterface::cancelCommand (RCommand *command) {
@@ -258,8 +257,9 @@
 	} else {
 		RK_ASSERT (false);
 	}
-	
-	RControlWindow::getControl ()->updateCommand (command);
+
+// KDE4 TODO: deal with this one
+//	RControlWindow::getControl ()->updateCommand (command);
 	MUTEX_UNLOCK;
 }
 
@@ -273,8 +273,6 @@
 void RInterface::processREvalRequest (REvalRequest *request) {
 	RK_TRACE (RBACKEND);
 
-	RControlWindow::getControl ()->addChain (request->in_chain);
-
 	// clear reply object
 	issueCommand (".rk.set.reply (NULL)", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
 	if (!request->call_length) {

Modified: branches/KDE4_port/rkward/rbackend/rinterface.h
===================================================================
--- branches/KDE4_port/rkward/rbackend/rinterface.h	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rinterface.h	2007-10-21 21:26:53 UTC (rev 2099)
@@ -70,8 +70,8 @@
 
 /** opens a new command chain. Returns a pointer to the new chain. If you specify a parent, the new chain will be a sub-chain of that chain. */
 	RCommandChain *startChain (RCommandChain *parent=0);
-/** closes the command chain returns pointer to parent chain */
-	RCommandChain *closeChain (RCommandChain *chain);
+/** closes the command chain. The chain (and even its parent, if it is already closed) may be deleted right afterwards! */
+	void closeChain (RCommandChain *chain);
 
 /** Ensures that the given command will not be executed, or, if it is already running, interrupts it. Note that commands marked RCommand::Sync can
 not be interrupted. */
@@ -91,6 +91,8 @@
 
 	bool backendIsDead ();
 	bool backendIsIdle ();
+
+	static bool inRThread ();
 public slots:
 /** called periodically to flush output buffer in RThread */
 	void flushOutput ();

Modified: branches/KDE4_port/rkward/rbackend/rthread.cpp
===================================================================
--- branches/KDE4_port/rkward/rbackend/rthread.cpp	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rthread.cpp	2007-10-21 21:26:53 UTC (rev 2099)
@@ -80,6 +80,11 @@
 	killed = false;
 	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;
+
 	if ((err = initialize ())) {
 		qApp->postEvent (RKGlobals::rInterface (), new QCustomEvent (RSTARTUP_ERROR_EVENT + err));
 	}
@@ -92,8 +97,9 @@
 
 	MUTEX_LOCK;
 	checkObjectUpdatesNeeded (true);
+	notifyCommandDone (current_command);
 	MUTEX_UNLOCK;
-	
+
 	while (1) {
 		MUTEX_LOCK;
 		processX11Events ();
@@ -106,16 +112,16 @@
 		}
 	
 		// while commands are in queue, don't wait
-		while (RCommandStack::regular_stack->isActive () && !locked) {
-			RCommand *command = RCommandStack::regular_stack->pop ();
+		while ((!locked) && RCommandStack::regular_stack->isActive () && !locked) {
+			RCommand *command = RCommandStack::regular_stack->currentCommand ();
 			
 			if (command) {
-				// store type. Inside doCommand, command may be deleted (if the other thread gets called)!
-				bool check_list = (command->type () & (RCommand::User | RCommand::ObjectListUpdate));
 				// mutex will be unlocked inside
 				doCommand (command);
-				checkObjectUpdatesNeeded (check_list);
+				checkObjectUpdatesNeeded (command->type () & (RCommand::User | RCommand::ObjectListUpdate));
 				processX11Events ();
+				notifyCommandDone (command);	// command may be deleted after this
+				RCommandStack::regular_stack->pop ();
 			}
 		
 			if (killed) {
@@ -243,9 +249,14 @@
 			MUTEX_LOCK;
 		}
 	}
+}
 
+
+void RThread::notifyCommandDone (RCommand *command) {
+	RK_TRACE (RBACKEND);
+
 	// notify GUI-thread that command was finished
-	event = new QCustomEvent (RCOMMAND_OUT_EVENT);
+	QCustomEvent* event = new QCustomEvent (RCOMMAND_OUT_EVENT);
 	event->setData (command);
 	qApp->postEvent (RKGlobals::rInterface (), event);
 }
@@ -382,7 +393,7 @@
 	request->call_length = call_length;
 	MUTEX_LOCK;
 	flushOutput ();
-	RCommandStack *reply_stack = new RCommandStack ();
+	RCommandStack *reply_stack = new RCommandStack (prev_command);
 	request->in_chain = reply_stack->startChain (reply_stack);
 	MUTEX_UNLOCK;
 
@@ -401,7 +412,7 @@
 				break;
 			}
 
-			RCommand *command = reply_stack->pop ();
+			RCommand *command = reply_stack->currentCommand ();
 			
 			if (command) {
 				// mutex will be unlocked inside
@@ -409,6 +420,8 @@
 				doCommand (command);
 				if (object_update_forced) checkObjectUpdatesNeeded (true);
 				processX11Events ();
+				notifyCommandDone (command);	// command may be deleted after this
+				reply_stack->pop ();
 			}
 		}
 
@@ -461,9 +474,6 @@
 int RThread::initialize () {
 	RK_TRACE (RBACKEND);
 
-	// 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"));
-
 	int argc = 2;
 	char* argv[2] = { qstrdup ("--slave"), qstrdup ("--no-save") };
 	RKWardStartupOptions *options = RKWardMainWindow::getStartupOptions ();
@@ -526,10 +536,6 @@
 	flushOutput ();
 	MUTEX_UNLOCK;
 
-	QCustomEvent *event = new QCustomEvent (RCOMMAND_OUT_EVENT);
-	event->setData (current_command);
-	qApp->postEvent (RKGlobals::rInterface (), event);
-
 	return status;
 }
 

Modified: branches/KDE4_port/rkward/rbackend/rthread.h
===================================================================
--- branches/KDE4_port/rkward/rbackend/rthread.h	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/rbackend/rthread.h	2007-10-21 21:26:53 UTC (rev 2099)
@@ -142,8 +142,8 @@
 
 	void currentCommandWasCancelled ();
 
-/** The command currently being executed. This is used from RInterface::cancelCommand to find out, whether the command to be cancelled is
-already/still running. */
+/** The command currently being executed. This is used from RInterface::cancelCommand to find out, whether the command to be cancelled is already/still running.
+TODO: check logic. RCommandStack holds current_command, too. But this may only be non-zero, when the command is actually inside the backend? */
 	RCommand *current_command;
 
 /** convenience struct for event passing */
@@ -169,6 +169,7 @@
 private:
 /** This is the function in which an RCommand actually gets processed. Basically it passes the command to REmbedInteranl::runCommandInternal () and sends RInterface some events about what is currently happening. */
 	void doCommand (RCommand *command);
+	void notifyCommandDone (RCommand *command);
 /** thread is locked. No new commands will be executed. @see LockType @see lock @see unlock */
 	int locked;
 /** thread is killed. Should exit as soon as possible. @see kill */

Modified: branches/KDE4_port/rkward/windows/rcontrolwindow.cpp
===================================================================
--- branches/KDE4_port/rkward/windows/rcontrolwindow.cpp	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/windows/rcontrolwindow.cpp	2007-10-21 21:26:53 UTC (rev 2099)
@@ -17,12 +17,9 @@
 
 #include "rcontrolwindow.h"
 
-#include <q3listview.h>
 #include <qpushbutton.h>
-#include <qlayout.h>
-//Added by qt3to4:
-#include <Q3HBoxLayout>
-#include <Q3VBoxLayout>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
 
 #include <klocale.h>
 #include <kmessagebox.h>
@@ -44,8 +41,8 @@
 	initializeActivationSignals ();
 	setFocusPolicy (Qt::ClickFocus);
 
-	Q3VBoxLayout *main_vbox = new Q3VBoxLayout (this, RKGlobals::marginHint ());
-	Q3HBoxLayout *button_hbox = new Q3HBoxLayout (main_vbox, RKGlobals::spacingHint ());
+	QVBoxLayout *main_vbox = new QVBoxLayout (this, RKGlobals::marginHint ());
+	QHBoxLayout *button_hbox = new QHBoxLayout (main_vbox, RKGlobals::spacingHint ());
 
 	QPushButton *configure_r_button = new QPushButton (i18n ("Configure R backend"), this);
 	connect (configure_r_button, SIGNAL (clicked ()), this, SLOT (configureButtonClicked ()));
@@ -61,13 +58,15 @@
 	connect (cancel_button, SIGNAL (clicked ()), this, SLOT (cancelButtonClicked ()));
 	button_hbox->addWidget (cancel_button);
 
-	commands_view = new Q3ListView (this);
-	commands_view->addColumn (i18n ("Command"));
+	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->setSorting (0);		// actually, we ignore the column, and do our own sorting
-	commands_view->setSelectionMode (Q3ListView::Extended);
+	commands_view->addColumn (i18n ("Description")); */
+	commands_view->setSortingEnabled (false);
+
+	commands_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
 	connect (commands_view, SIGNAL (selectionChanged ()), this, SLOT (commandSelectionChanged ()));
 	main_vbox->addWidget (commands_view);
 
@@ -77,6 +76,8 @@
 
 RControlWindow::~RControlWindow () {
 	RK_TRACE (APP);
+
+	RCommandStackModel::getModel ()->removeListener ();
 }
 
 bool RControlWindow::isActive () {
@@ -96,178 +97,14 @@
 
 	RKMDIWindow::showEvent (e);
 	if (!initialized) return;
-	MUTEX_LOCK;
-	refreshCommands ();
-	MUTEX_UNLOCK;
-}
 
-RControlWindowListViewItem *RControlWindow::itemForCommand (RCommand *command) {
-	QMap <RCommand *, RControlWindowListViewItem *>::const_iterator it = command_map.find (command);
-	if (it == command_map.constEnd ()) return 0;
-	return (*it);
+	RCommandStackModel::getModel ()->addListener ();
+	commands_view->setModel (RCommandStackModel::getModel ());
 }
 
-RControlWindowListViewItem *RControlWindow::itemForChain (RCommandChain *chain) {
-	QMap <RCommandChain *, RControlWindowListViewItem *>::const_iterator it = chain_map.find (chain);
-	if (it == chain_map.constEnd ()) return 0;
-	return (*it);
-}
-
-void RControlWindow::addChain (RCommandChain *chain) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	RChainOrCommand *dummy = new RChainOrCommand;
-	dummy->command = 0;
-	dummy->chain = chain;
-	addCommands (dummy, itemForChain (chain->parent));
-	delete dummy;
-}
-
-void RControlWindow::addCommand (RCommand *command, RCommandChain *parent) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	if (!parent) parent = RCommandStack::regular_stack;
-	addCommand (command, itemForChain (parent));
-}
-
-void RControlWindow::updateChain (RCommandChain *chain) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	RControlWindowListViewItem *chainitem = itemForChain (chain);
-	if (!chainitem) {
-		RK_ASSERT (false);
-		return;
-	}
-	chainitem->update (chain);
-	checkCleanChain (chainitem);
-}
-
-void RControlWindow::updateCommand (RCommand *command) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	RControlWindowListViewItem *item = itemForCommand (command);
-	if (!item) {
-		RK_ASSERT (false);
-		// unfortunately, yes, this can happen! Namely when the command is in the reply stack. We do not find commands in (the) reply stack(s), in refreshCommands.
-		// TODO: find a way to include reply stacks in refreshCommands!
-		return;
-	}
-	item->update (command);
-}
-
-void RControlWindow::removeCommand (RCommand *command) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	RControlWindowListViewItem *item = itemForCommand (command);
-	if (!item) {
-		RK_ASSERT (false);
-		// TODO: see updateCommand ()
-		return;
-	}
-	RControlWindowListViewItem *chain = static_cast<RControlWindowListViewItem *> (item->parent ());
-
-	delete item;
-	command_map.remove (command);
-
-	checkCleanChain (chain);
-}
-
-void RControlWindow::checkCleanChain (RControlWindowListViewItem *chain) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	while (chain && chain->chain_closed && chain->parent () && (!chain->firstChild ())) {
-		RControlWindowListViewItem *del = chain;
-		chain = static_cast<RControlWindowListViewItem *> (chain->parent ());
-		chain_map.remove (del->chain);
-		delete del;
-	}
-}
-
-void RControlWindow::setCommandRunning (RCommand *command) {
-	if (!isActive ()) return;	// do expensive GUI stuff only when visible
-	RK_TRACE (APP);
-
-	RControlWindowListViewItem *item = itemForCommand (command);
-	if (!item) {
-		RK_ASSERT (false);
-		// TODO: see updateCommand ()
-		return;
-	}
-	item->setText (2, "Running");
-}
-
-void RControlWindow::refreshCommands () {
-	RK_TRACE (APP);
-
-	commands_view->clear ();
-	command_map.clear ();
-	chain_map.clear ();
-
-	RChainOrCommand *dummy = new RChainOrCommand;
-	dummy->command = 0;
-	dummy->chain = RCommandStack::regular_stack;
-
-	addCommands (dummy, 0);
-
-	delete dummy;
-
-/* add the currently running command (if needed). It is not in the stack. */
-	RCommand *running = RKGlobals::rInterface ()->runningCommand ();
-	if (running && (!command_map.contains (running))) {
-		RControlWindowListViewItem *item = static_cast <RControlWindowListViewItem *> (commands_view->firstChild ());
-		while (item->chain && item->firstChild ()) {
-			item = static_cast <RControlWindowListViewItem *> (item->firstChild ());
-		}
-		addCommand (running, item);
-	}
-	if (running) setCommandRunning (running);
-
-	cancel_button->setEnabled (false);
-}
-
-void RControlWindow::addCommands (RChainOrCommand *coc, RControlWindowListViewItem *parent) {
-	RK_TRACE (APP);
-
-	if (coc->chain) {
-		RControlWindowListViewItem *item;
-		RCommandChain *chain = coc->chain;
-		if (!parent) {
-			item = new RControlWindowListViewItem (commands_view);
-			item->setText (0, i18n ("Command Stack"));
-		} else {
-			item = new RControlWindowListViewItem (parent);
-		}
-		item->setOpen (true);
-		chain_map.insert (chain, item);
-		item->update (chain);
-		for (RChainOrCommand *nc = chain->commands.first (); nc; nc = chain->commands.next ()) {
-			addCommands (nc, item);
-		}
-	} else {	// coc->command
-		RK_ASSERT (parent);
-		addCommand (coc->command, parent);
-	}
-}
-
-void RControlWindow::addCommand (RCommand *command, RControlWindowListViewItem *parent) {
-	RK_TRACE (APP);
-
-	RControlWindowListViewItem *item = new RControlWindowListViewItem (parent);
-	item->setMultiLinesEnabled (true);
-	command_map.insert (command, item);
-
-	item->update (command);
-}
-
 void RControlWindow::commandSelectionChanged () {
 	RK_TRACE (APP);
-
+/*
 	// we will make some modifications to the selection in here, so disconnect the SIGNAL first.
 	disconnect (commands_view, SIGNAL (selectionChanged ()), this, SLOT (commandSelectionChanged ()));
 
@@ -286,12 +123,12 @@
 
 	cancel_button->setEnabled (have_selection);
 
-	connect (commands_view, SIGNAL (selectionChanged ()), this, SLOT (commandSelectionChanged ()));
+	connect (commands_view, SIGNAL (selectionChanged ()), this, SLOT (commandSelectionChanged ())); */
 }
 
 void RControlWindow::cancelButtonClicked () {
 	RK_TRACE (APP);
-
+/*
 	bool some_not_cancelable = false;
 	// find out all the RCommands selected (not the chains)
 	for (QMap <RCommand *, RControlWindowListViewItem *>::const_iterator it = command_map.begin (); it != command_map.end (); ++it) {
@@ -306,7 +143,7 @@
 
 	if (some_not_cancelable) {
 		KMessageBox::information (this, i18n ("Some of the commands you were trying to cancel are marked as \"sync\" (letter 'S' in the type column). Cancelling such commands could lead to loss of data. These commands have _not_ been cancelled."), i18n ("Some commands not cancelled"), "cancel_sync");
-	}
+	} */
 }
 
 void RControlWindow::pauseButtonClicked () {
@@ -343,7 +180,7 @@
 
 //############# END RContolWindowPart #######################
 //############# BEGIN RContolWindowListViewItem #################
-
+/*
 // static
 unsigned int RControlWindowListViewItem::lid = 0;
 
@@ -369,16 +206,12 @@
 	if (ascending) {
 		if (comp_id > id) {
 			return -1;
-		} /* else if (comp_id == id) {		// all items have a unique id!
-			return 0;
-		}*/
+		}
 		return 1;
 	} else {
 		if (comp_id > id) {
 			return 1;
-		} /* else if (comp_id == id) {		// all items have a unique id!
-			return 0;
-		}*/
+		}
 		return -1;
 	}
 }
@@ -423,5 +256,5 @@
 		setText (2, i18n ("Open (Waiting)"));
 	}
 }
-
+*/
 #include "rcontrolwindow.moc"

Modified: branches/KDE4_port/rkward/windows/rcontrolwindow.h
===================================================================
--- branches/KDE4_port/rkward/windows/rcontrolwindow.h	2007-10-18 20:58:12 UTC (rev 2098)
+++ branches/KDE4_port/rkward/windows/rcontrolwindow.h	2007-10-21 21:26:53 UTC (rev 2099)
@@ -20,9 +20,8 @@
 
 #include <kparts/part.h>
 
-#include <qmap.h>
 #include <qlabel.h>
-#include <q3listview.h>
+#include <QTreeView>
 
 #include "rkmdiwindow.h"
 
@@ -40,11 +39,8 @@
 Do create an instance of this class directly. Create a RControlWindowPart instead. Also, probably RInterface should be the only class ever calling
 functions of RControlWindow.
 
-// TODO: probably the QListView of RCommands (and associated functionality) should be separted to an own class
-to allow reuse
+// KDE4 TODO: check, if everything is implemented
 
-// TODO: check, if everything is implemented
-
 @author Thomas Friedrichsmeier
 */
 class RControlWindow : public RKMDIWindow {
@@ -55,18 +51,6 @@
 	RControlWindow (QWidget *parent, bool tool_window, const char *name=0);
 /** destructor */
 	~RControlWindow ();
-/** Add new chain to the RControlWindow. Has no effect unless RControlWindow::isShown () */
-	void addChain (RCommandChain *chain);
-/** Add new command to the RControlWindow. The command is added to the given parent chain. Has no effect unless RControlWindow::isShown () */
-	void addCommand (RCommand *command, RCommandChain *parent);
-/** Update information on the given chain. Use esp, if the chain was set to closed. Has no effect unless RControlWindow::isShown () */
-	void updateChain (RCommandChain *chain);
-/** Update information on the given command. Use esp, if the command was cancelled. Has no effect unless RControlWindow::isShown () */
-	void updateCommand (RCommand *command);
-/** Remove given command from the RControlWindow. This will also check, whether the parent chain can be torn down, automatically. Has no effect unless RControlWindow::isShown ()*/
-	void removeCommand (RCommand *command);
-/** Set given command as running. Has no effect unless RControlWindow::isShown ()*/
-	void setCommandRunning (RCommand *command);
 
 /** 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. */
 	void showEvent (QShowEvent *e);
@@ -84,26 +68,10 @@
 /** configure button was clicked. Invoke settings dialog */
 	void configureButtonClicked ();
 private:
-	Q3ListView *commands_view;
+	QTreeView *commands_view;
 	QPushButton *cancel_button;
 	QPushButton *pause_button;
 
-	RControlWindowListViewItem *itemForCommand (RCommand *command);
-	RControlWindowListViewItem *itemForChain (RCommandChain *chain);
-
-/** internal: recursively add commands/chains */
-	void addCommands (RChainOrCommand *coc, RControlWindowListViewItem *parent);
-/** internal: add single command */
-	void addCommand (RCommand *command, RControlWindowListViewItem *parent);
-/** internal: delete chain(s) if applicable. This basically mimics the behavior in RCommandStack::pop () */
-	void checkCleanChain (RControlWindowListViewItem *chain);
-
-/** internal: causes the RControlWindow (if shown) to refresh it's entire list of commands. Warning! Does not lock the mutex. Lock the mutex before calling this! */
-	void refreshCommands ();
-
-	QMap <RCommand *, RControlWindowListViewItem *> command_map;
-	QMap <RCommandChain *, RControlWindowListViewItem *> chain_map;
-
 	bool paused;
 	bool isActive ();
 	bool initialized;
@@ -127,7 +95,7 @@
 /** destructor */
 	~RControlWindowPart ();
 };
-
+#if 0
 /**
 	\brief ListViewItem used in RControlWindow
 
@@ -158,5 +126,6 @@
 /** reimplemented to always have the top of the stack at the top */
 	int compare (Q3ListViewItem *i, int col, bool ascending) const;
 };
+#endif
 
 #endif


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