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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Fri Oct 7 08:43:50 UTC 2011


Revision: 3898
          http://rkward.svn.sourceforge.net/rkward/?rev=3898&view=rev
Author:   tfry
Date:     2011-10-07 08:43:50 +0000 (Fri, 07 Oct 2011)
Log Message:
-----------
Do not silently purge invalid objects for objectlists

Modified Paths:
--------------
    trunk/rkward/ChangeLog
    trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
    trunk/rkward/rkward/plugin/rkcomponentproperties.h
    trunk/rkward/rkward/plugin/rkvarslot.cpp
    trunk/rkward/rkward/rbackend/rkrbackend.cpp

Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog	2011-10-06 21:30:28 UTC (rev 3897)
+++ trunk/rkward/ChangeLog	2011-10-07 08:43:50 UTC (rev 3898)
@@ -1,4 +1,6 @@
---- Version 0.5.7 - Oct-XX-2011
+- Objects, which are not acceptable in a varslot, will still be shown, there, with a warning		TODO: add a UI to override
+
+--- Version 0.5.7 - Oct-23-2011
 - Do not treat arrays (which are not a matrix) as hierarchical named objects in the object browser
 - Do not analyse more than 100000 name child-objects per object (avoids hangs on such extreme data)
 - Fix problems with using mclapply() inside RKWard

Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.cpp	2011-10-06 21:30:28 UTC (rev 3897)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.cpp	2011-10-07 08:43:50 UTC (rev 3898)
@@ -2,7 +2,7 @@
                           rkcomponentproperties  -  description
                              -------------------
     begin                : Fri Nov 25 2005
-    copyright            : (C) 2005, 2006, 2007, 2008, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2005, 2006, 2007, 2008, 2009, 2011 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -93,6 +93,8 @@
 
 #include "rkcomponentproperties.h"
 
+#include <klocale.h>
+
 #include "../debug.h"
 
 ///////////////////////////////////////////// Base //////////////////////////////////////////
@@ -652,24 +654,33 @@
 bool RKComponentPropertyRObjects::addObjectValue (RObject *object) {
 	RK_TRACE (PLUGIN);
 
-	if (object && isObjectValid (object)) {
-		if (!object_list.contains (object)) {
-			object_list.append (object);
-			listenForObject (object);
-			checkListLengthValid ();
-			emit (valueChanged (this));
-		}
+	if (appendObject (object)) {
+		updateValidity ();
+		emit (valueChanged (this));
 		return isValid ();
 	}
 	return false;
 }
 
+bool RKComponentPropertyRObjects::appendObject (RObject *object) {
+	if ((!object) || object_list.contains (object)) return false;
+
+	object_list.append (object);
+	QString probs = checkObjectProblems (object);
+	if (!probs.isEmpty ()) problems.insert (object, probs);
+	listenForObject (object);
+	return true;
+}
+
 void RKComponentPropertyRObjects::objectRemoved (RObject *object) {
 	RK_TRACE (PLUGIN);
 
-	if (object_list.removeAll (object)) {
+	int index = object_list.indexOf (object);
+	if (index >= 0) {
+		object_list.removeAt (index);
+		problems.remove (object);
 		stopListenForObject (object);
-		checkListLengthValid ();
+		updateValidity ();
 		emit (valueChanged (this));
 	}
 }
@@ -700,6 +711,7 @@
 bool RKComponentPropertyRObjects::setObjectValue (RObject *object) {
 	RK_TRACE (PLUGIN);
 
+	problems.clear ();
 	while (!object_list.isEmpty ()) {
 		stopListenForObject (object_list.takeAt (0));
 	}
@@ -715,6 +727,7 @@
 	for (int i = 0; i < object_list.size (); ++i) {
 		if (!newlist.contains (object_list[i])) {
 			stopListenForObject (object_list.takeAt (i));
+			problems.remove (object_list[i]);
 			--i;
 			changes = true;
 		}
@@ -723,32 +736,32 @@
 	// now add items from the new list that are not in the old list
 	for (int i = 0; i < newlist.size (); ++i) {
 		RObject *obj = newlist[i];
-		if (!object_list.contains (obj)) {
-			if (isObjectValid (obj)) {
-				object_list.append (obj);
-				listenForObject (obj);
-				changes = true;
-			}
-		}
+		if (appendObject (obj)) changes = true;
 	}
 
 	// emit a signal if there have been any changes
 	if (changes) {
-		checkListLengthValid ();
+		updateValidity ();
 		emit (valueChanged (this));
 	}
 }
 
-bool RKComponentPropertyRObjects::isObjectValid (RObject *object) {
+QString RKComponentPropertyRObjects::objectProblems (int list_index) const {
+	return problems.value (object_list.value (list_index));
+}
+
+QString RKComponentPropertyRObjects::checkObjectProblems (RObject *object) const {
 	RK_TRACE (PLUGIN);
 
+	QStringList probs;
+
 	// first check dimensionality
 	if (dims > 0) {
-		if (object->getDimensions ().size () != dims) return false;
+		if (object->getDimensions ().size () != dims) probs.append (i18n ("This object has %1 dimension(s), but %2 dimension(s) is/are expected.", object->getDimensions().size(), dims));
 	}
 	int olength = object->getLength ();
-	if ((min_length > 0) && (olength < min_length)) return false;
-	if ((max_length >= 0) && (olength > max_length)) return false;
+	if ((min_length > 0) && (olength < min_length)) probs.append (i18n ("This object has a length of %1, but a minimum length of %2 is expected.", olength, min_length));
+	if ((max_length >= 0) && (olength > max_length)) probs.append (i18n ("This object has a length of %1, but a maximum length of %2 is expected.", olength, max_length));
 
 	// next, check classes
 	if (!classes.isEmpty ()) {
@@ -760,22 +773,19 @@
 			}
 			++it;
 		}
-		if (!ok) return false;
+		if (!ok) probs.append (i18n ("This object does not appear to belong to any of the classes <i>%1</i>.", classes.join (", ")));
 	}
 
 	// finally, check type
 	if (!types.isEmpty ()) {
-		// TODO: this is not entirely correct, yet
-		if (object->isVariable ()) {
-			if (!types.contains (RObject::typeToText (object->getDataType ()).toLower ())) {
-				return false;
-			}
-		} else {
-			return false;
+		QString type = RObject::typeToText (object->getDataType ()).toLower ();
+		if (!types.contains (type)) {
+			probs.append (i18n ("This object's data type is <i>%1</i>, while allowed type(s) is/are <i>%2</i>.", type, types.join (", ")));
 		}
 	}
 
-	return true;
+	if (probs.isEmpty ()) return QString ();
+	return (QString ("<ul><li>") + probs.join ("</li><li>") + "</li></ul>");
 }
 
 RObject *RKComponentPropertyRObjects::objectValue () {
@@ -823,15 +833,10 @@
 
 	for (QStringList::const_iterator it = slist.begin (); it != slist.end (); ++it) {
 		RObject *obj = RObjectList::getObjectList ()->findObject (*it);
-		if (obj && isObjectValid (obj)) {
-			object_list.append (obj);
-			listenForObject (obj);
-		} else {
-			ok = false;
-		}
+		ok = ok && appendObject (obj);
 	}
 
-	checkListLengthValid ();
+	updateValidity ();
 	emit (valueChanged (this));
 	return (isValid () && ok);
 }
@@ -843,7 +848,7 @@
 
 	for (QStringList::const_iterator it = slist.begin (); it != slist.end (); ++it) {
 		RObject *obj = RObjectList::getObjectList ()->findObject (*it);
-		if (!(obj && isObjectValid (obj))) {
+		if (!(obj && checkObjectProblems (obj).isEmpty ())) {
 			return false;
 		}
 	}
@@ -953,12 +958,14 @@
 void RKComponentPropertyRObjects::objectMetaChanged (RObject *object) {
 	RK_TRACE (PLUGIN);
 
-	// if object list contains this object, check whether it is still valid. Otherwise remove it, revalidize and signal change.
+	// if object list contains this object, check whether it is still valid. Otherwise check, whether it's problem set has changed, revalidize and signal change.
 	int index = object_list.indexOf (object);
 	if (index >= 0) {
-		if (!isObjectValid (object)) {
-			stopListenForObject (object_list.takeAt (index));
-			checkListLengthValid ();
+		QString probs = checkObjectProblems (object);
+		if (probs != problems.value (object)) {
+			if (probs.isEmpty ()) problems.remove (object);
+			else problems.insert (object, probs);
+			updateValidity ();
 			emit (valueChanged (this));
 		}
 	}
@@ -970,24 +977,28 @@
 	bool changes = false;
 
 	for (int i = 0; i < object_list.size (); ++i) {
-		if (!isObjectValid (object_list[i])) {
-			stopListenForObject (object_list.takeAt (i));
-			--i;
+		RObject *object = object_list[i];
+		QString probs = checkObjectProblems (object);
+		if (probs != problems.value (object)) {
+			if (probs.isEmpty ()) problems.remove (object);
+			else problems.insert (object, probs);
 			changes = true;
 		}
 	}
 
-	checkListLengthValid ();		// we should do this even if there are no changes in the list. There might have still been changes in the filter!
+	updateValidity ();		// we should do this even if there are no changes in the list. There might have still been changes in the filter!
 	if (changes) {
 		if (!silent) emit (valueChanged (this));
 	}
 }
 
-void RKComponentPropertyRObjects::checkListLengthValid () {
+void RKComponentPropertyRObjects::updateValidity () {
 	RK_TRACE (PLUGIN);
 
 	is_valid = true;	// innocent until proven guilty
-	if ((min_num_objects > 0) || (max_num_objects > 0) || (min_num_objects_if_any > 0)) {
+
+	if (!problems.isEmpty ()) is_valid = false;
+	else if ((min_num_objects > 0) || (max_num_objects > 0) || (min_num_objects_if_any > 0)) {
 		int len = object_list.count ();
 		if (len < min_num_objects) is_valid = false;
 		if (len && (len < min_num_objects_if_any)) is_valid = false;

Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.h	2011-10-06 21:30:28 UTC (rev 3897)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.h	2011-10-07 08:43:50 UTC (rev 3898)
@@ -2,7 +2,7 @@
                           rkcomponentproperties  -  description
                              -------------------
     begin                : Fri Nov 25 2005
-    copyright            : (C) 2005, 2006, 2007, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2005, 2006, 2007, 2009, 2011 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -246,9 +246,8 @@
 	bool setObjectValue (RObject *object);
 /** set all the objects in the given new list (if valid), and only those. Emit a signal if there was any change */
 	void setObjectList (const RObject::ObjectList &newlist);
-/** Check whether an object is valid for this property.
- at returns false if the object does not qualify as a valid selection according to current settings (class/type/dimensions), true otherwise */
-	bool isObjectValid (RObject *object);
+/** Return a string describing the problems with the item at position list_index in the objectList(). An empty string, if there is nothing wrong with the object. */
+	QString objectProblems (int list_index) const;
 /** Get current object. If the property can hold several objects, only the first is returned. See objectList ().
 @returns 0 if no valid object is selected */
 	RObject *objectValue ();
@@ -279,11 +278,17 @@
 /** reimplemented from RObjectListener::objectMetaChanged (). This is so we get notified if the object currently selected is changed */
 	void objectMetaChanged (RObject *changed);
 private:
-/** check all objects currently in the list for validity. Remove invalid objects. Determine validity state depending on how many (valid) objects remain in the list. If the list was changed during validation, and silent!=false a valueChanged () signal is emitted */
+/** check all objects currently in the list for validity. And set validity state accordingly. */
 	void validizeAll (bool silent=false);
-/** simple helper function: Check whether the number of objects currently selected (and only that!), and set the valid state accordingly */
-	void checkListLengthValid ();
+/** simple helper function: Check whether the the list is valid (*after* each object had been validized!), and set the valid state accordingly */
+	void updateValidity ();
+/** internal helper to add the object (and check it for problems).
+ * @returns true, if the list was changed, false, if the object was already in the list or is 0. */
+	bool appendObject (RObject *object);
+/** Check any object for problems */
+	QString checkObjectProblems (RObject *object) const;
 	RObject::ObjectList object_list;
+	QMap<RObject*, QString> problems;
 	int dims;
 	int min_length;
 	int max_length;

Modified: trunk/rkward/rkward/plugin/rkvarslot.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkvarslot.cpp	2011-10-06 21:30:28 UTC (rev 3897)
+++ trunk/rkward/rkward/plugin/rkvarslot.cpp	2011-10-07 08:43:50 UTC (rev 3898)
@@ -130,14 +130,18 @@
 	RK_DO (qDebug ("contained in varslot: %s", available->value ().toLatin1 ().data ()), PLUGIN, DL_DEBUG);
 
 	RObject::ObjectList objlist = available->objectList ();
-	RObject::ObjectList::const_iterator it = objlist.begin ();
-	int i = 1;
-	while (it != objlist.end ()) {
+	for (int i = 0; i < objlist.count (); ++i) {
+		RObject *object = objlist[i];
+
 		QTreeWidgetItem *new_item = new QTreeWidgetItem (list);
-		new_item->setText (0, QString::number (i++));
-		new_item->setText (1, (*it)->getShortName ());
-		item_map.insert (new_item, *it);
-		++it;
+		new_item->setText (0, QString::number (i + 1));
+		new_item->setText (1, object->getShortName ());
+		QString probs = available->objectProblems (i);
+		if (!probs.isEmpty ()) {
+			new_item->setToolTip (1, i18n ("<p>This object is not allowed, here, for the following reason(s):</p>") + probs);
+			new_item->setIcon (1, RKStandardIcons::getIcon (RKStandardIcons::ActionDeleteVar));
+		}
+		item_map.insert (new_item, object);
 	}
 	if (multi) list->resizeColumnToContents (0);
 

Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-10-06 21:30:28 UTC (rev 3897)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-10-07 08:43:50 UTC (rev 3898)
@@ -1066,6 +1066,8 @@
 //	This was used to show a warning message. Unfortunately, however, forks also occur on every popen (i.e. in system(..., intern=TRUE).
 //	RKRBackend::this_pointer->handlePlainGenericRequest (QStringList ("forkNotification"), false);
 	RK_DO (qDebug ("Backend process forked (for the first time, this session)"), RBACKEND, DL_WARNING);
+//	NOTE: perhaps we can heuristically differentiate from popen by checking sys.calls() for something with "fork" in it. 
+//	esp., in case we discover adverse side-effects of blocking SIGCLD, we should attempt this
 }
 
 void completeForkChild () {

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