[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 ¤t_symbols);
+ virtual void updateFromR (RCommandChain *chain, const QStringList ¤t_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 ¤t_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