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

tfry at users.sf.net tfry at users.sf.net
Thu Feb 28 12:25:32 UTC 2013


Revision: 4566
          http://sourceforge.net/p/rkward/code/4566
Author:   tfry
Date:     2013-02-28 12:25:30 +0000 (Thu, 28 Feb 2013)
Log Message:
-----------
Add support for loaded namespaces that do not belong to a package on the search path. Does not update, automatically, yet.

Modified Paths:
--------------
    trunk/rkward/ChangeLog
    trunk/rkward/rkward/core/renvironmentobject.cpp
    trunk/rkward/rkward/core/renvironmentobject.h
    trunk/rkward/rkward/core/rkmodificationtracker.h
    trunk/rkward/rkward/core/rkpseudoobjects.cpp
    trunk/rkward/rkward/core/rkpseudoobjects.h
    trunk/rkward/rkward/core/robject.cpp
    trunk/rkward/rkward/core/robjectlist.cpp
    trunk/rkward/rkward/core/robjectlist.h

Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/ChangeLog	2013-02-28 12:25:30 UTC (rev 4566)
@@ -1,5 +1,6 @@
+- Added support for loaded namespaces that are not attached to a loaded package
+	- TODO: Currently works only after clicking "Update" in the workspace view. Make it work automatically!
 - Pluginmaps can specify their "priority". Pluginmaps with low priority will not be added automatically, when found.
-	- TODO: test
 - Pluginmaps can <require> other pluginmaps based on their id (for cross-package inclusion)
 	- TODO: test
 - Added new element <dependency_check> for dynamic version checks within a plugin (R and RKWard versions, only, so far)

Modified: trunk/rkward/rkward/core/renvironmentobject.cpp
===================================================================
--- trunk/rkward/rkward/core/renvironmentobject.cpp	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/renvironmentobject.cpp	2013-02-28 12:25:30 UTC (rev 4566)
@@ -49,6 +49,7 @@
 
 QString REnvironmentObject::packageName () const {
 	RK_ASSERT (isType (PackageEnv));
+	if (!isType (PackageEnv)) RK_DEBUG (OBJECTS, DL_WARNING, "%s", qPrintable (name));
 	return name.section (':', 1);
 }
 

Modified: trunk/rkward/rkward/core/renvironmentobject.h
===================================================================
--- trunk/rkward/rkward/core/renvironmentobject.h	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/renvironmentobject.h	2013-02-28 12:25:30 UTC (rev 4566)
@@ -34,7 +34,7 @@
 
 	void updateFromR (RCommandChain *chain);
 /** like updateFromR, but only update new / removed symbols from R. Theoretically this could be defined in RContainerObject, but the only use case is for environments. */
-	void updateFromR (RCommandChain *chain, const QStringList &current_symbols);
+	virtual void updateFromR (RCommandChain *chain, const QStringList &current_symbols);
 
 	QString getFullName () const;
 	QString makeChildName (const QString &short_child_name, bool misplaced=false) const;

Modified: trunk/rkward/rkward/core/rkmodificationtracker.h
===================================================================
--- trunk/rkward/rkward/core/rkmodificationtracker.h	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/rkmodificationtracker.h	2013-02-28 12:25:30 UTC (rev 4566)
@@ -145,6 +145,7 @@
 
 friend class RContainerObject;
 friend class REnvironmentObject;
+friend class RKOrphanNamespacesObject;
 friend class RObject;
 friend class RObjectList;
 /** essentially like the above function(s). All objects listening for child additions on the parent will be notified */

Modified: trunk/rkward/rkward/core/rkpseudoobjects.cpp
===================================================================
--- trunk/rkward/rkward/core/rkpseudoobjects.cpp	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/rkpseudoobjects.cpp	2013-02-28 12:25:30 UTC (rev 4566)
@@ -17,10 +17,13 @@
 
 #include "rkpseudoobjects.h"
 
+#include <klocale.h>
+
 #include "../debug.h"
 
 RSlotsPseudoObject::RSlotsPseudoObject (RObject *parent) : RContainerObject (parent, "SLOTS") {
 	RK_TRACE (OBJECTS);
+	type |= PseudoObject;
 	pseudo_object_types.insert (this, SlotsObject);
 }
 
@@ -43,9 +46,12 @@
 	return (parent->getFullName () + "@" + safe_name);
 }
 
-RKNamespaceObject::RKNamespaceObject (REnvironmentObject* package) : REnvironmentObject (package, "NAMESPACE") {
+RKNamespaceObject::RKNamespaceObject (REnvironmentObject* package, const QString name) : REnvironmentObject (package, name.isNull () ? "NAMESPACE" : name) {
 	RK_TRACE (OBJECTS);
+	type |= PseudoObject;
 	pseudo_object_types.insert (this, NamespaceObject);
+	if (name.isNull ()) namespace_name = package->packageName ();
+	else namespace_name = name;
 }
 
 RKNamespaceObject::~RKNamespaceObject () {
@@ -55,17 +61,92 @@
 
 QString RKNamespaceObject::getFullName () const {
 	RK_TRACE (OBJECTS);
-	return ("asNamespace (" + rQuote (static_cast<REnvironmentObject*>(parent)->packageName ()) + ")");
+	return ("asNamespace (" + rQuote (namespace_name) + ")");
 }
 
 QString RKNamespaceObject::makeChildName (const QString& short_child_name, bool) const {
 	RK_TRACE (OBJECTS);
 	QString safe_name = short_child_name;
 	if (irregularShortName (safe_name)) safe_name = rQuote (short_child_name);
-	return (static_cast<REnvironmentObject*>(parent)->packageName () + ":::" + safe_name);
+	return (namespace_name + ":::" + safe_name);
 }
 
 QString RKNamespaceObject::makeChildBaseName (const QString& short_child_name) const {
 	RK_TRACE (OBJECTS);
-	return (static_cast<REnvironmentObject*>(parent)->packageName () + ":::" + short_child_name);
+	// since namespaces reside at top level, this is the same as makeChildName()
+	return (makeChildName (short_child_name, false));
 }
+
+#include "robjectlist.h"
+#include "rkmodificationtracker.h"
+#include "../rkglobals.h"
+
+RKOrphanNamespacesObject::RKOrphanNamespacesObject (RObjectList* parent) : REnvironmentObject (parent, "." + i18nc ("Note: namespaces is a technical term, should not be translated", "Orphan Namespaces")) {	// HACK: Name prefixed with "." to treat object as hidden.
+	RK_TRACE (OBJECTS);
+	type |= PseudoObject;
+	pseudo_object_types.insert (this, OrphanNamespacesObject);
+}
+
+RKOrphanNamespacesObject::~RKOrphanNamespacesObject () {
+	RK_TRACE (OBJECTS);
+	pseudo_object_types.remove (this);
+}
+
+QString RKOrphanNamespacesObject::getFullName () const {
+	RK_TRACE (OBJECTS);
+	return ("loadedNamespaces ()");
+}
+
+QString RKOrphanNamespacesObject::makeChildName (const QString& short_child_name, bool) const {
+	RK_TRACE (OBJECTS);
+	return ("asNamespace (" + rQuote (short_child_name) + ")");
+}
+
+QString RKOrphanNamespacesObject::makeChildBaseName (const QString& short_child_name) const {
+	RK_TRACE (OBJECTS);
+	return (makeChildName (short_child_name, false));
+}
+
+void RKOrphanNamespacesObject::updateFromR (RCommandChain* chain) {
+	RK_TRACE (OBJECTS);
+	RK_ASSERT (false);
+}
+
+void RKOrphanNamespacesObject::updateFromR (RCommandChain* chain, const QStringList& current_symbols) {
+	RK_TRACE (OBJECTS);
+
+	// which former children are missing?
+	for (int i = childmap.size () - 1; i >= 0; --i) {
+		RObject *object = childmap[i];
+		if (!current_symbols.contains (object->getShortName ())) {
+			RKGlobals::tracker ()->removeObject (object, 0, true);
+		}
+	}
+
+	// which ones are new in the list?
+	for (int i = 0; i < current_symbols.size (); ++i) {
+		if (!findOrphanNamespace (current_symbols[i])) {
+			RKNamespaceObject *nso = new RKNamespaceObject (this, current_symbols[i]);
+			nso->type |= Incomplete;
+			RKGlobals::tracker ()->beginAddObject (nso, this, i);
+			childmap.insert (i, nso);
+			RKGlobals::tracker ()->endAddObject (nso, this, i);
+		}
+	}
+
+	RK_ASSERT (current_symbols.size () == childmap.size ());
+}
+
+RKNamespaceObject* RKOrphanNamespacesObject::findOrphanNamespace (const QString& name) const {
+	RK_TRACE (OBJECTS);
+
+	for (int i = childmap.size () - 1; i >= 0; --i) {
+		RObject *obj = childmap[i];
+		if (obj->getShortName () == name) {
+			RK_ASSERT (obj->isPackageNamespace ());
+			return static_cast<RKNamespaceObject*> (obj);
+		}
+	}
+	return 0;
+}
+

Modified: trunk/rkward/rkward/core/rkpseudoobjects.h
===================================================================
--- trunk/rkward/rkward/core/rkpseudoobjects.h	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/rkpseudoobjects.h	2013-02-28 12:25:30 UTC (rev 4566)
@@ -21,10 +21,8 @@
 #include "renvironmentobject.h"
 
 /** TODO:
- * - implement OrphanNamepacesObject
+ * - fix automatic updating of loadedNamespaces()
  * - override getObjectDescription()
- * - namespace objects should keep track of their namespace name, themselves
- * - internally store namespace objects by name, not attached to a package
  * */
 
 /**
@@ -50,13 +48,43 @@
 */
 class RKNamespaceObject : public REnvironmentObject {
 public:
-	RKNamespaceObject (REnvironmentObject* package);
+	RKNamespaceObject (REnvironmentObject* package, const QString name = QString ());
 	~RKNamespaceObject ();
 
 	QString getFullName () const;
 	QString makeChildName (const QString &short_child_name, bool misplaced=false) const;
 	QString makeChildBaseName (const QString &short_child_name) const;
+	QString namespaceName () const { return namespace_name; };
+private:
+	QString namespace_name;
 };
 
+class RObjectList;
+/**
+This class represents the list of namespace environments which are loaded, but do not belong to a package on the search path.
+
+(TODO: Actually, we should relax the assumption that objects can only be at one place in the hierarchy, and turn this into a list of
+all namespace environemnts!)
+
+It exists only once, as a direct child of the RObjectList.
+
+ at author Thomas Friedrichsmeier
+*/
+class RKOrphanNamespacesObject : public REnvironmentObject {
+public:
+	RKOrphanNamespacesObject (RObjectList *parent);
+	~RKOrphanNamespacesObject ();
+
+	QString getFullName () const;
+	QString makeChildName (const QString &short_child_name, bool misplaced=false) const;
+	QString makeChildBaseName (const QString &short_child_name) const;
+
+	RKNamespaceObject *findOrphanNamespace (const QString &name) const;
+
+	/** should not be called on this object. Reimplemented to raise an assert, and do nothing else. */
+	void updateFromR (RCommandChain *chain);
+	/** reimplemented from REnvironmentObject */
+	void updateFromR (RCommandChain *chain, const QStringList &current_symbols);
+};
+
 #endif
-

Modified: trunk/rkward/rkward/core/robject.cpp
===================================================================
--- trunk/rkward/rkward/core/robject.cpp	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/robject.cpp	2013-02-28 12:25:30 UTC (rev 4566)
@@ -516,6 +516,10 @@
 		if (child == namespaceEnvironment ()) return offset;
 		offset += 1;
 	}
+	if (isType (Workspace)) {
+		if (child == static_cast<const RObjectList*> (this)->orphanNamespacesObject ()) return offset;
+		offset += 1;
+	}
 	return -1;
 }
 
@@ -525,6 +529,7 @@
 	int ret = isContainer () ? static_cast<const RContainerObject*>(this)->numChildren () : 0;
 	if (hasPseudoObject (SlotsObject)) ret += 1;
 	if (hasPseudoObject (NamespaceObject)) ret += 1;
+	if (isType (Workspace)) ret += 1;	// for the RKOrphanNamespacesObject
 	return ret;
 }
 
@@ -542,6 +547,10 @@
 		if (index == 0) return namespaceEnvironment ();
 		--index;
 	}
+	if (isType (Workspace)) {
+		if (index == 0) return static_cast<const RObjectList *> (this)->orphanNamespacesObject ();
+		--index;
+	}
 	return 0;
 }
 
@@ -595,15 +604,17 @@
 	if (isPseudoObject ()) {
 		RK_ASSERT (removed_in_workspace);
 		PseudoObjectType type = getPseudoObjectType ();
-		if (type == SlotsObject) slots_objects.remove (parent);
-		else if (type == NamespaceObject) namespace_objects.remove (parent);
-		else if (type == RowNamesObject) rownames_objects.remove (parent);
-		RK_ASSERT (parent->contained_objects & type);
-		parent->contained_objects -= type;
-		delete this;
-	} else {
-		static_cast<RContainerObject*> (parent)->removeChild (this, removed_in_workspace);
+		if (parent->hasPseudoObject (type)) {	// not always true for NamespaceObjects, which the RKOrphanNamespacesObject keeps as regular children!
+			if (type == SlotsObject) slots_objects.remove (parent);
+			else if (type == NamespaceObject) namespace_objects.remove (parent);
+			else if (type == RowNamesObject) rownames_objects.remove (parent);
+			parent->contained_objects -= type;
+			delete this;
+			return;
+		}
 	}
+
+	static_cast<RContainerObject*> (parent)->removeChild (this, removed_in_workspace);
 }
 
 //static

Modified: trunk/rkward/rkward/core/robjectlist.cpp
===================================================================
--- trunk/rkward/rkward/core/robjectlist.cpp	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/robjectlist.cpp	2013-02-28 12:25:30 UTC (rev 4566)
@@ -2,7 +2,7 @@
                           robjectlist  -  description
                              -------------------
     begin                : Wed Aug 18 2004
-    copyright            : (C) 2004, 2006, 2007, 2009, 2010, 2011 by Thomas Friedrichsmeier
+    copyright            : (C) 2004-2013 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -31,6 +31,7 @@
 #include "rkmodificationtracker.h"
 #include "../misc/rkprogresscontrol.h"
 #include "../settings/rksettingsmoduler.h"
+#include "rkpseudoobjects.h"
 
 #include "../rkglobals.h"
 
@@ -54,13 +55,19 @@
 	update_chain = 0;
 
 	RObject *globalenv = createTopLevelEnvironment (".GlobalEnv");
-	RKGlobals::tracker ()->beginAddObject (globalenv, this, 0);
+	RKGlobals::tracker ()->beginAddObject (globalenv, this, 0);	// 1 == first child after GlobalEnv
 	childmap.insert (0, globalenv);
 	RKGlobals::tracker ()->endAddObject (globalenv, this, 0);
+
+	RKOrphanNamespacesObject *obj = new RKOrphanNamespacesObject (this);
+	RKGlobals::tracker ()->beginAddObject (obj, this, 1);	// 1 == first child after GlobalEnv
+	orphan_namespaces = obj;
+	RKGlobals::tracker ()->endAddObject (obj, this, 1);
 }
 
 RObjectList::~RObjectList () {
 	RK_TRACE (OBJECTS);
+	delete orphan_namespaces;
 }
 
 QStringList RObjectList::detachPackages (const QStringList &packages, RCommandChain *chain, RKProgressControl* control) {
@@ -103,7 +110,7 @@
 	emit (updateStarted ());
 	update_chain = RKGlobals::rInterface ()->startChain (chain);
 
-	RCommand *command = new RCommand ("search ()", RCommand::App | RCommand::Sync | RCommand::GetStringVector, QString::null, this, ROBJECTLIST_UDPATE_ENVIRONMENTS_COMMAND);
+	RCommand *command = new RCommand ("list (search (), loadedNamespaces ())", RCommand::App | RCommand::Sync | RCommand::GetStructuredData, QString::null, this, ROBJECTLIST_UDPATE_ENVIRONMENTS_COMMAND);
 	RKGlobals::rInterface ()->issueCommand (command, update_chain);
 }
 
@@ -122,7 +129,13 @@
 	update_chain = RKGlobals::rInterface ()->startChain (chain);
 
 	updateEnvironments (current_searchpath, false);
-
+#warning TODO
+#warning TODO
+#warning TODO
+#warning TODO
+#warning TODO
+#warning TODO
+#warning TODO
 	RKGlobals::rInterface ()->issueCommand (QString (), RCommand::App | RCommand::Sync | RCommand::EmptyCommand, QString (), this, ROBJECTLIST_UDPATE_COMPLETE_COMMAND, update_chain);
 }
 
@@ -130,11 +143,15 @@
 	RK_TRACE (OBJECTS);
 
 	if (command->getFlags () == ROBJECTLIST_UDPATE_ENVIRONMENTS_COMMAND) {
-		RK_ASSERT (command->getDataType () == RData::StringVector);
-		QStringList new_environments = command->stringVector ();
+		RK_ASSERT (command->getDataType () == RData::StructureVector);
+		const RData::RDataStorage & data = command->structureVector ();
+		RK_ASSERT (data.size () == 2);
+		
+		QStringList new_environments = data[0]->stringVector ();
 		RK_ASSERT (new_environments.size () >= 2);
 
 		updateEnvironments (new_environments, true);
+		updateNamespaces (data[1]->stringVector ());
 
 		RKGlobals::rInterface ()->issueCommand (QString (), RCommand::App | RCommand::Sync | RCommand::EmptyCommand, QString (), this, ROBJECTLIST_UDPATE_COMPLETE_COMMAND, update_chain);
 	} else if (command->getFlags () == ROBJECTLIST_UDPATE_COMPLETE_COMMAND) {
@@ -194,6 +211,16 @@
 	RK_DO (RK_ASSERT (childmap == newchildmap), OBJECTS, DL_DEBUG);	// this is an expensive assert, hence wrapping it inside RK_DO
 }
 
+void RObjectList::updateNamespaces (const QStringList namespace_names) {
+	RK_TRACE (OBJECTS);
+
+	QStringList orphan_namespace_names;
+	for (int i = 0; i < namespace_names.size (); ++i) {
+		if (!findPackage (namespace_names[i])) orphan_namespace_names.append (namespace_names[i]);
+	}
+	orphan_namespaces->updateFromR (update_chain, orphan_namespace_names);
+}
+
 REnvironmentObject *RObjectList::createTopLevelEnvironment (const QString &name) {
 	RK_TRACE (OBJECTS);
 
@@ -207,13 +234,14 @@
 	RK_ASSERT (op == "$");
 
 	if (path.value (1) == "::") {
-		RObject *environment = findChildByNamespace (path[0]);
+		RObject *environment = findPackage (path[0]);
 		if (!environment) return 0;
 		
 		return environment->findObjects (path.mid (2), matches, "$");
 	} else if (path.value (1) == ":::") {
-		RObject *environment = findChildByNamespace (path[0]);
+		RObject *environment = findPackage (path[0]);
 		if (environment) environment = static_cast<REnvironmentObject*> (environment)->namespaceEnvironment ();
+		if (!environment) environment = orphan_namespaces->findOrphanNamespace (path[0]);
 		if (!environment) return 0;
 
 		return environment->findObjects (path.mid (2), matches, "$");
@@ -231,12 +259,12 @@
 	return 0;
 }
 
-REnvironmentObject* RObjectList::findChildByNamespace (const QString &namespacename) const {
+REnvironmentObject* RObjectList::findPackage (const QString &namespacename) const {
 	RK_TRACE (OBJECTS);
 
 	for (int i = childmap.size () - 1; i >= 1; --i) {	// NOTE: childmap[0] is the .GlobalEnv
 		RObject* child = childmap[i];
-		RK_ASSERT (child->isType (Environment));
+		if (!child->isType (PackageEnv)) continue;	// Skip Autoloads
 		REnvironmentObject* env = static_cast<REnvironmentObject *> (child);
 		if (env->packageName () == namespacename) {
 			return env;
@@ -287,3 +315,4 @@
 }
 
 #include "robjectlist.moc"
+

Modified: trunk/rkward/rkward/core/robjectlist.h
===================================================================
--- trunk/rkward/rkward/core/robjectlist.h	2013-02-26 21:07:01 UTC (rev 4565)
+++ trunk/rkward/rkward/core/robjectlist.h	2013-02-28 12:25:30 UTC (rev 4566)
@@ -2,7 +2,7 @@
                           robjectlist  -  description
                              -------------------
     begin                : Wed Aug 18 2004
-    copyright            : (C) 2004, 2006, 2007, 2009, 2010, 2011 by Thomas Friedrichsmeier
+    copyright            : (C) 2004-2013 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -32,6 +32,7 @@
 class RKEditor;
 class REnvironmentObject;
 class RKProgressControl;
+class RKOrphanNamespacesObject;
 
 /**
 This class is responsible for keeping and updating a list of objects in the R-workspace.
@@ -56,7 +57,7 @@
 	/** reimplemented from RContainerObject: do nothing. The object-list has no meta data. */
 	void writeMetaData (RCommandChain *) {};
 
-	REnvironmentObject* findChildByNamespace (const QString &namespacename) const;
+	REnvironmentObject* findPackage (const QString &namespacename) const;
 
 	static RObjectList *getObjectList () { return object_list; };
 	static REnvironmentObject *getGlobalEnv ();
@@ -64,6 +65,8 @@
 	/** detach the given list of packages (if the packages are loaded, and safe to remove)
 	@returns a list of error messages (usually empty) */
 	QStringList detachPackages (const QStringList &packages, RCommandChain *chain = 0, RKProgressControl *control = 0);
+	/** A pseudo object containing as children all loaded namespaces which do not belong to a package on the search path */
+	RKOrphanNamespacesObject* orphanNamespacesObject () const { return orphan_namespaces; };
 public slots:
 	void timeout ();
 signals:
@@ -84,12 +87,14 @@
 	bool updateStructure (RData *new_data);
 	void rCommandDone (RCommand *command);
 	void updateEnvironments (const QStringList &env_names, bool force_globalenv_update);
+	void updateNamespaces (const QStringList namespace_names);
 private:
 	friend class RKLoadAgent;
 	friend class RKSaveAgent;
 	QTimer *update_timer;
 	
 	RCommandChain *update_chain;
+	RKOrphanNamespacesObject *orphan_namespaces;
 
 	REnvironmentObject *createTopLevelEnvironment (const QString &name);
 





More information about the rkward-tracker mailing list