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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Wed Mar 2 16:48:59 UTC 2011


Revision: 3459
          http://rkward.svn.sourceforge.net/rkward/?rev=3459&view=rev
Author:   tfry
Date:     2011-03-02 16:48:59 +0000 (Wed, 02 Mar 2011)

Log Message:
-----------
Automatically fetch deeper levels of environments, if needed in object browser or completion.

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

Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/ChangeLog	2011-03-02 16:48:59 UTC (rev 3459)
@@ -1,3 +1,5 @@
+- Allow to browse arbitrarily deeply nested environments in the object browser
+
 --- Version 0.5.5 - XXX-XX-2011
 - Fixed: Crash when several environments on the search path have the same name
 - Re-organize the default toolbar actions of the main window

Modified: trunk/rkward/rkward/core/rcontainerobject.cpp
===================================================================
--- trunk/rkward/rkward/core/rcontainerobject.cpp	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/rcontainerobject.cpp	2011-03-02 16:48:59 UTC (rev 3459)
@@ -2,7 +2,7 @@
                           rcontainerobject  -  description
                              -------------------
     begin                : Thu Aug 19 2004
-    copyright            : (C) 2004, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2006, 2007, 2009, 2010, 2011 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -137,6 +137,9 @@
 
 void RContainerObject::updateChildren (RData *new_children) {
 	RK_TRACE (OBJECTS);
+
+	if (type & Incomplete) return;	// If the (new!) type is "Incomplete", it means, the structure getter simply stopped at this point. Existing child info may or may not be out of date, but probably the old data we have is still more acurate than having nothing.
+
 	RK_ASSERT (new_children->getDataType () == RData::StructureVector);
 	unsigned int new_child_count = new_children->getDataLength ();
 
@@ -279,10 +282,12 @@
 	return (found->findObject (remainder, true));
 }
 
-void RContainerObject::findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified) const {
+void RContainerObject::findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified) {
 	RK_TRACE (OBJECTS);
 	RK_ASSERT (current_list);
 
+	fetchMoreIfNeeded ();
+
 	QString canonified = partial_name;
 	if (!name_is_canonified) canonified = canonifyName (partial_name);
 
@@ -290,13 +295,7 @@
 	QString current_level = canonified.section (QChar ('$'), 0, 0);
 	QString remainder = canonified.section (QChar ('$'), 1);
 
-	if (canonified.endsWith (QChar ('$'))) {
-		RObject* found = findChildByName (current_level);
-		if (found) found->findObjectsMatching (QString (), current_list, true);
-		return;
-	}
-
-	if (remainder.isEmpty ()) {
+	if (remainder.isEmpty () && !canonified.endsWith (QChar ('$'))) {
 		for (int i = 0; i < childmap.size (); ++i) {
 			RObject* child = childmap[i];
 			if (child->getShortName ().startsWith (current_level)) {

Modified: trunk/rkward/rkward/core/rcontainerobject.h
===================================================================
--- trunk/rkward/rkward/core/rcontainerobject.h	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/rcontainerobject.h	2011-03-02 16:48:59 UTC (rev 3459)
@@ -65,7 +65,7 @@
 	virtual RObject *findObject (const QString &name, bool is_canonified=false) const;
 
 	/** reimplemented from RObject to actually search for matching objects */
-	void findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified=false) const;
+	void findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified=false);
 
 	void moveChild (RObject* child, int from_index, int to_index);
 

Modified: trunk/rkward/rkward/core/renvironmentobject.cpp
===================================================================
--- trunk/rkward/rkward/core/renvironmentobject.cpp	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/renvironmentobject.cpp	2011-03-02 16:48:59 UTC (rev 3459)
@@ -60,19 +60,24 @@
 QString REnvironmentObject::makeChildName (const QString &short_child_name, bool misplaced) const {
 	RK_TRACE (OBJECTS);
 
-	if (type & GlobalEnv) {
-		if (irregularShortName (short_child_name)) {
-			return (getShortName () + "$" + RObject::rQuote (short_child_name));
-		}
-		return (short_child_name);
+	QString safe_name;
+	bool irregular = false;
+	if (irregularShortName (short_child_name)) {
+		irregular = true;
+		safe_name = rQuote (short_child_name);
+	} else safe_name = short_child_name;
+
+	if (type & GlobalEnv) {		// don't print as ".GlobalEnv$something" unless childname needs fixing
+		if (irregular) return (getShortName () + "$" + safe_name);
+		return (safe_name);
 	}
 	if (type & ToplevelEnv) {
 /* Some items are placed outside of their native namespace. E.g. in package:boot item "motor". It can be retrieved using as.environment ("package:boot")$motor. This is extremly ugly. We need to give them (and only them) this special treatment. */
 // TODO: hopefully one day operator "::" will work even in those cases. So check back later, and remove after a sufficient amount of backwards compatibility time
-		if ((type & PackageEnv) && (!misplaced)) return (namespace_name + "::" + RObject::rQuote (short_child_name));
-		return (getFullName () + '$' + RObject::rQuote (short_child_name));
+		if ((type & PackageEnv) && (!misplaced)) return (namespace_name + "::" + safe_name);
+		return (getFullName () + '$' + safe_name);
 	}
-	return (name + '$' + short_child_name);
+	return (getFullName () + '$' + safe_name);
 }
 
 QString REnvironmentObject::makeChildBaseName (const QString &short_child_name) const {
@@ -106,6 +111,8 @@
 
 	RCommand *command = new RCommand (".rk.get.structure (" + getFullName () + ", " + rQuote (getShortName ()) + options + ')', RCommand::App | RCommand::Sync | RCommand::GetStructuredData, QString::null, this, ROBJECT_UDPATE_STRUCTURE_COMMAND);
 	RKGlobals::rInterface ()->issueCommand (command, chain);
+
+	type |= Updating;
 }
 
 void REnvironmentObject::updateFromR (RCommandChain *chain, const QStringList &current_symbols) {

Modified: trunk/rkward/rkward/core/rkmodificationtracker.cpp
===================================================================
--- trunk/rkward/rkward/core/rkmodificationtracker.cpp	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/rkmodificationtracker.cpp	2011-03-02 16:48:59 UTC (rev 3459)
@@ -2,7 +2,7 @@
                           rkmodificationtracker  -  description
                              -------------------
     begin                : Tue Aug 31 2004
-    copyright            : (C) 2004, 2007, 2009, 2010 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2007, 2009, 2010, 2011 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -337,6 +337,32 @@
 	return QVariant ();
 }
 
+bool RKObjectListModel::hasChildren(const QModelIndex& parent) const {
+	RK_TRACE (OBJECTS);
+
+	RObject* parent_object = 0;
+	if (parent.isValid ()) parent_object = static_cast<RObject*> (parent.internalPointer ());
+	else return true;		// the root item
+
+	if (!(parent_object && parent_object->isContainer ())) return false;
+	return (parent_object->isType (RObject::Incomplete) || static_cast<RContainerObject*> (parent_object)->numChildren ());
+}
+
+bool RKObjectListModel::canFetchMore (const QModelIndex &parent) const {
+	RK_TRACE (OBJECTS);
+
+	RObject *object = static_cast<RObject*> (parent.internalPointer ());
+	return (object && object->isType (RObject::Incomplete));
+}
+
+void RKObjectListModel::fetchMore (const QModelIndex &parent) {
+	RK_TRACE (OBJECTS);
+
+	RObject *object = static_cast<RObject*> (parent.internalPointer ());
+	RK_ASSERT (object && object->isType (RObject::Incomplete));
+	object->fetchMoreIfNeeded ();
+}
+
 QModelIndex RKObjectListModel::indexFor (RObject *object) const {
 	RK_TRACE (OBJECTS);
 

Modified: trunk/rkward/rkward/core/rkmodificationtracker.h
===================================================================
--- trunk/rkward/rkward/core/rkmodificationtracker.h	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/rkmodificationtracker.h	2011-03-02 16:48:59 UTC (rev 3459)
@@ -2,7 +2,7 @@
                           rkmodificationtracker  -  description
                              -------------------
     begin                : Tue Aug 31 2004
-    copyright            : (C) 2004, 2007 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2007, 2011 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -98,6 +98,13 @@
 	/** reimplemented from  QAbstractItemModel::headerData() to provide column names */
 	QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
 
+	/** reimplemented from  QAbstractItemModel::canFetchMore() */
+	bool canFetchMore (const QModelIndex &parent) const;
+	/** reimplemented from  QAbstractItemModel::fetchMore() */
+	void fetchMore (const QModelIndex &parent);
+	/** reimplemented from  QAbstractItemModel::hasChildren() */
+	bool hasChildren (const QModelIndex &parent = QModelIndex ()) const; 
+
 	/** convenience function to create an index for a particular object */
 	QModelIndex indexFor (RObject *object) const;
 };

Modified: trunk/rkward/rkward/core/robject.cpp
===================================================================
--- trunk/rkward/rkward/core/robject.cpp	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/robject.cpp	2011-03-02 16:48:59 UTC (rev 3459)
@@ -80,7 +80,7 @@
 	return 0;
 }
 
-void RObject::findObjectsMatching (const QString &, RObjectSearchMap *, bool) const {
+void RObject::findObjectsMatching (const QString &, RObjectSearchMap *, bool) {
 	RK_TRACE (OBJECTS);
 	return;
 }
@@ -250,8 +250,23 @@
 		command = new RCommand (".rk.get.structure (" + getFullName () + ", " + rQuote (getShortName ()) + ')', RCommand::App | RCommand::Sync | RCommand::GetStructuredData, QString::null, this, ROBJECT_UDPATE_STRUCTURE_COMMAND);
 	}
 	RKGlobals::rInterface ()->issueCommand (command, chain);
+
+	type |= Updating;	// will be cleared, implicitly, when the new structure gets set
 }
 
+void RObject::fetchMoreIfNeeded (int levels) {
+	RK_TRACE (OBJECTS);
+
+	if (isType (Updating)) return;
+	if (isType (Incomplete)) updateFromR (0);
+	if (levels <= 0) return;
+	if (!isContainer ()) return;
+	const RObjectMap children = static_cast<RContainerObject*> (this)->childmap;
+	foreach (RObject* child, children) {
+		child->fetchMoreIfNeeded (levels - 1);
+	}
+}
+
 void RObject::rCommandDone (RCommand *command) {
 	RK_TRACE (OBJECTS);
 

Modified: trunk/rkward/rkward/core/robject.h
===================================================================
--- trunk/rkward/rkward/core/robject.h	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/robject.h	2011-03-02 16:48:59 UTC (rev 3459)
@@ -2,7 +2,7 @@
                           robject  -  description
                              -------------------
     begin                : Thu Aug 19 2004
-    copyright            : (C) 2004, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2006, 2007, 2009, 2010, 2011 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -63,6 +63,8 @@
 		Character=3 << 14,
 		Logical=4 << 14,
 		DataTypeMask=Numeric | Factor | Character | Logical,
+		Updating=1 << 27, /** < The object is about to be updated from R */
+		Incomplete=1 << 28,	/** < The information on this object is not complete (typically, it's children have not been scanned, yet). */
 		NonVisibleObject=1 << 29,	/** < the object is not listed in the object list. Currently, this is only the case for row.names()-objects */
 		NeedDataUpdate=1 << 30,	/** < the object's data should be (re-) fetched from R. The main purpose of this flag is to make sure the data is synced *after* the structure has been synced */
 		Pending=1 << 31		/** < the object is pending, i.e. it has been created in the object list, but we have not seen it in R, yet. This is used by data editors to create the illusion that a new object was added immediately, while in fact it takes some time to create it in the backend. */
@@ -168,8 +170,12 @@
 @param partial_name The partial name to look up
 @param current_list A pointer to a valid (but probably initially empty) RObjectMap. Matches will be added to this list
 @param name_is_canonified internal parameter. Set to true, if the name to match is already canonfied (else it will be canonified internally) */
-	virtual void findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified=false) const;
+	virtual void findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified=false);
 
+/** Fetch more levels of object representation (if needed). Note: Data is fetched asynchronously. 
+ at param levels levels to recurse (0 = only direct children). */
+	void fetchMoreIfNeeded (int levels=1);
+
 /// For now, the ChangeSet only handles RKVariables!
 	struct ChangeSet {
 		int from_index;

Modified: trunk/rkward/rkward/core/robjectlist.cpp
===================================================================
--- trunk/rkward/rkward/core/robjectlist.cpp	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/robjectlist.cpp	2011-03-02 16:48:59 UTC (rev 3459)
@@ -238,7 +238,7 @@
 	return 0;
 }
 
-void RObjectList::findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified) const {
+void RObjectList::findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified) {
 	RK_TRACE (OBJECTS);
 	RK_ASSERT (current_list);
 

Modified: trunk/rkward/rkward/core/robjectlist.h
===================================================================
--- trunk/rkward/rkward/core/robjectlist.h	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/core/robjectlist.h	2011-03-02 16:48:59 UTC (rev 3459)
@@ -60,7 +60,7 @@
 	RObject *findObject (const QString &name, bool canonified=false) const;
 
 	/** reimplemented from RContainerObject to search the environments in search order */
-	void findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified=false) const;
+	void findObjectsMatching (const QString &partial_name, RObjectSearchMap *current_list, bool name_is_canonified=false);
 
 	KUrl getWorkspaceURL () const { return current_url; };
 

Modified: trunk/rkward/rkward/rbackend/rkstructuregetter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkstructuregetter.cpp	2011-03-01 17:36:43 UTC (rev 3458)
+++ trunk/rkward/rkward/rbackend/rkstructuregetter.cpp	2011-03-02 16:48:59 UTC (rev 3459)
@@ -170,6 +170,7 @@
 	bool is_function = false;
 	bool is_container = false;
 	bool is_environment = false;
+	bool no_recurse = false;
 	unsigned int type = 0;
 
 	RK_DO (qDebug ("fetching '%s': %p, s-type %d", name.toLatin1().data(), val, TYPEOF (val)), RBACKEND, DL_DEBUG);
@@ -227,6 +228,10 @@
 			is_container = true;
 			type |= RObject::Environment;
 			is_environment = true;
+			if (++envir_depth >= 2) {
+				no_recurse = true;
+				type |= RObject::Incomplete;
+			}
 		} else {
 			type |= RObject::Variable;
 			if (RKRSupport::callSimpleBool (is_factor_fun, value, R_BaseEnv)) type |= RObject::Factor;
@@ -295,7 +300,7 @@
 
 	// now add the extra info for containers and functions
 	if (is_container) {
-		bool do_env = (is_environment && (++envir_depth < 2));
+		bool do_env = (is_environment && (!no_recurse));
 		bool do_cont = is_container && (!is_environment);
 
 		// fetch list of child names


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