[rkward-cvs] SF.net SVN: rkward-code:[4739] trunk/rkward
tfry at users.sf.net
tfry at users.sf.net
Fri May 3 14:49:27 UTC 2013
Revision: 4739
http://sourceforge.net/p/rkward/code/4739
Author: tfry
Date: 2013-05-03 14:49:21 +0000 (Fri, 03 May 2013)
Log Message:
-----------
Add option allow_duplicates in <varslot>
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/doc/rkwardplugins/index.docbook
trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
trunk/rkward/rkward/plugin/rkcomponentproperties.h
trunk/rkward/rkward/plugin/rkvarslot.cpp
trunk/rkward/rkward/plugin/rkvarslot.h
trunk/rkward/rkward/plugins/plots/scatterplot.xml
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/ChangeLog 2013-05-03 14:49:21 UTC (rev 4739)
@@ -1,3 +1,4 @@
+- <varslots> can be set to accept the same object several times. Used in scatterplot plugin.
- New R function rk.embed.device() for manually embedding graphics devices in RKWard
- Fixed: R backend would exit immediately, without meaningful error message, if there is an error in .Rprofile (or Rprofile.site)
- Fixed: Installing suggested packages from the package installation dialog was broken
Modified: trunk/rkward/doc/rkwardplugins/index.docbook
===================================================================
--- trunk/rkward/doc/rkwardplugins/index.docbook 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/doc/rkwardplugins/index.docbook 2013-05-03 14:49:21 UTC (rev 4739)
@@ -56,8 +56,8 @@
and in the FDL itself on how to use it. -->
<legalnotice>&FDLNotice;</legalnotice>
-<date>2012-11-28</date>
-<releaseinfo>0.6.1.00</releaseinfo>
+<date>2013-05-03</date>
+<releaseinfo>0.6.2.00</releaseinfo>
<abstract>
<para>
@@ -2545,6 +2545,10 @@
<listitem><para>Whether the varslot holds only one (default, "false"), or several objects</para></listitem>
</varlistentry>
<varlistentry>
+ <term><parameter>allow_duplicates</parameter></term>
+ <listitem><para>Whether the varslot may accept only unique objects (default, "false"), or if the same object may be added several times.</para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><parameter>min_vars</parameter></term>
<listitem><para>Only meaningful if multi="true": Minimum number of vars to be selected for the selection to be considered valid (optional, defaults to "1")</para></listitem>
</varlistentry>
Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.cpp 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.cpp 2013-05-03 14:49:21 UTC (rev 4739)
@@ -158,6 +158,7 @@
RKComponentPropertyAbstractList::RKComponentPropertyAbstractList (QObject* parent, bool required) : RKComponentPropertyBase (parent, required) {
RK_TRACE (PLUGIN);
setAllowedLength ();
+ setStripDuplicates (false);
}
RKComponentPropertyAbstractList::~RKComponentPropertyAbstractList () {
@@ -252,6 +253,8 @@
void RKComponentPropertyStringList::setValueAt (int index, const QString& value) {
RK_TRACE (PLUGIN);
+ if (getStripDuplicates () && storage.contains (value)) return;
+
while (index >= storage.size ()) storage.append (QString ()); // expand as needed
storage[index] = value;
doChange ();
@@ -266,6 +269,27 @@
}
}
+void RKComponentPropertyStringList::checkStripDuplicates () {
+ if (!getStripDuplicates ()) return;
+ RK_TRACE (PLUGIN);
+
+ QStringList unique;
+ for (int i = 0; i < storage.size (); ++i) {
+ if (!unique.contains (storage[i])) unique.append (storage[i]);
+ }
+ storage = unique;
+}
+
+void RKComponentPropertyStringList::removeAt (int index) {
+ RK_TRACE (PLUGIN);
+ if ((index < 0) || (index >= storage.size ())) {
+ RK_ASSERT (false);
+ return;
+ }
+ storage.removeAt (index);
+ doChange ();
+}
+
///////////////////////////////////////////// Bool //////////////////////////////////////////
RKComponentPropertyBool::RKComponentPropertyBool (QObject *parent, bool required, bool default_state, const QString &value_true, const QString &value_false) : RKComponentPropertyBase (parent, required) {
@@ -753,6 +777,7 @@
// no initial requirements
dims = min_length = max_length;
+ setStripDuplicates (true); // legacy default
addNotificationType (RObjectListener::ObjectRemoved);
addNotificationType (RObjectListener::MetaChanged);
@@ -761,13 +786,13 @@
RKComponentPropertyRObjects::~RKComponentPropertyRObjects () {
RK_TRACE (PLUGIN);
- setObjectValue (0);
+ setObjectValueSilent (0);
}
bool RKComponentPropertyRObjects::addObjectValue (RObject *object) {
RK_TRACE (PLUGIN);
- if (appendObject (object)) {
+ if (addObjectValueSilent (object)) {
updateValidity ();
emit (valueChanged (this));
return isValid ();
@@ -775,22 +800,25 @@
return false;
}
-bool RKComponentPropertyRObjects::appendObject (RObject *object) {
- if ((!object) || object_list.contains (object)) return false;
+bool RKComponentPropertyRObjects::addObjectValueSilent (RObject *object) {
+ if (!object) return false;
+ bool is_dupe = object_list.contains (object);
+ if (getStripDuplicates () && is_dupe) return false;
object_list.append (object);
- QString probs = checkObjectProblems (object);
- if (!probs.isEmpty ()) problems.insert (object, probs);
- listenForObject (object);
+ if (!is_dupe) {
+ QString probs = checkObjectProblems (object);
+ if (!probs.isEmpty ()) problems.insert (object, probs);
+ listenForObject (object);
+ }
return true;
}
void RKComponentPropertyRObjects::objectRemoved (RObject *object) {
RK_TRACE (PLUGIN);
- int index = object_list.indexOf (object);
- if (index >= 0) {
- object_list.removeAt (index);
+ int removals = object_list.removeAll (object);
+ if (removals) {
problems.remove (object);
stopListenForObject (object);
updateValidity ();
@@ -798,6 +826,18 @@
}
}
+void RKComponentPropertyRObjects::removeAt (int index) {
+ RK_TRACE (PLUGIN);
+ if ((index < 0) || (index >= object_list.size ())) {
+ RK_ASSERT (false);
+ return;
+ }
+ RObject* obj = object_list.takeAt (index);
+ if (!object_list.contains (obj)) stopListenForObject (obj);
+ updateValidity ();
+ emit (valueChanged (this));
+}
+
void RKComponentPropertyRObjects::setClassFilter (const QStringList &classes) {
RK_TRACE (PLUGIN);
@@ -821,40 +861,33 @@
validizeAll ();
}
-bool RKComponentPropertyRObjects::setObjectValue (RObject *object) {
+bool RKComponentPropertyRObjects::setObjectValueSilent (RObject* object) {
RK_TRACE (PLUGIN);
problems.clear ();
- while (!object_list.isEmpty ()) {
- stopListenForObject (object_list.takeAt (0));
+ QSet<RObject*> unique = object_list.toSet ();
+ foreach (RObject *obj, unique) {
+ stopListenForObject (obj);
}
- return (addObjectValue (object));
+ object_list.clear ();
+ return (addObjectValueSilent (object));
}
+bool RKComponentPropertyRObjects::setObjectValue (RObject *object) {
+ setObjectValueSilent (object);
+ updateValidity ();
+ emit (valueChanged (this));
+ return isValid ();
+}
+
void RKComponentPropertyRObjects::setObjectList (const RObject::ObjectList &newlist) {
RK_TRACE (PLUGIN);
- bool changes = false;
-
- // remove items from the old list that are not in the new list
- for (int i = 0; i < object_list.size (); ++i) {
- RObject *object = object_list[i];
- if (!newlist.contains (object)) {
- stopListenForObject (object_list.takeAt (i));
- problems.remove (object);
- --i;
- changes = true;
+ if (newlist != object_list) {
+ setObjectValueSilent (0);
+ for (int i = 0; i < newlist.size (); ++i) {
+ addObjectValueSilent (newlist[i]);
}
- }
-
- // 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 (appendObject (obj)) changes = true;
- }
-
- // emit a signal if there have been any changes
- if (changes) {
updateValidity ();
emit (valueChanged (this));
}
@@ -945,7 +978,7 @@
bool ok = true;
for (int i = 0; i < values.size (); ++i) {
RObject *obj = RObjectList::getObjectList ()->findObject (values[i]);
- ok = ok && appendObject (obj);
+ ok = ok && addObjectValueSilent (obj);
}
updateValidity ();
Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.h 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.h 2013-05-03 14:49:21 UTC (rev 4739)
@@ -85,7 +85,11 @@
bool atMaxLength () const { return (max_num_items && (max_num_items <= listLength ())); };
/** reimplemented from RKComponentPropertyBase to actually reconcile requirements with other list properties */
void connectToGovernor (RKComponentPropertyBase *governor, const QString &modifier=QString::null, bool reconcile_requirements=true);
+/** If set to true, duplicate values are dropped, silently */
+ void setStripDuplicates (bool strip) { strip_duplicates = strip; };
+ virtual void removeAt (int index) = 0;
protected:
+ bool getStripDuplicates () const { return strip_duplicates; };
bool checkListLength ();
virtual int listLength () const = 0;
void reconcileLengthRequirements (RKComponentPropertyAbstractList *governor);
@@ -94,6 +98,7 @@
int min_num_items;
int min_num_items_if_any;
int max_num_items;
+ bool strip_duplicates;
};
/////////////////////////////////////////////// StringList /////////////////////////////////////////////////////
@@ -117,12 +122,14 @@
/** get all current strings as a QStringList */
const QStringList& values () const { return storage; };
/** set current strings as a QStringList */
- void setValues (const QStringList &new_values) { storage = new_values; doChange (); };
+ void setValues (const QStringList &new_values) { storage = new_values; checkStripDuplicates (); doChange (); };
/** reimplemented from RKComponentPropertyBase to use special handling for list properties */
void governorValueChanged (RKComponentPropertyBase *property);
int listLength () const { return (storage.size ()); };
+ void removeAt (int index);
private:
void doChange () { _value.clear (); emit (valueChanged (this)); };
+ void checkStripDuplicates ();
QStringList storage;
};
@@ -323,7 +330,7 @@
void connectToGovernor (RKComponentPropertyBase *governor, const QString &modifier=QString::null, bool reconcile_requirements=true);
/** reimplemented from RKComponentPropertyBase to use special handling for object properties */
void governorValueChanged (RKComponentPropertyBase *property);
- void removeObjectValue (RObject* object) { objectRemoved (object); };
+ void removeAt (int index);
int listLength () const { return (object_list.size ()); };
protected:
/** remove an object value. reimplemented from RObjectListener::objectRemoved (). This is so we get notified if the object currently selected is removed TODO: is this effectively a duplication of setFromList? */
@@ -337,7 +344,8 @@
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);
+ bool addObjectValueSilent (RObject *object);
+ bool setObjectValueSilent (RObject *object);
/** Check any object for problems */
QString checkObjectProblems (RObject *object) const;
RObject::ObjectList object_list;
Modified: trunk/rkward/rkward/plugin/rkvarslot.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkvarslot.cpp 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/rkward/plugin/rkvarslot.cpp 2013-05-03 14:49:21 UTC (rev 4739)
@@ -37,6 +37,7 @@
RK_TRACE (PLUGIN);
XMLHelper *xml = XMLHelper::getStaticHelper ();
+ updating = false;
// basic layout
QGridLayout *g_layout = new QGridLayout (this);
@@ -91,6 +92,7 @@
setRequired (xml->getBoolAttribute (element, "required", false, DL_INFO));
available->setTypeFilter (xml->getStringAttribute (element, "types", QString::null, DL_INFO).split (" ", QString::SkipEmptyParts));
available->setDimensionFilter (xml->getIntAttribute (element, "num_dimensions", 0, DL_INFO), xml->getIntAttribute (element, "min_length", 0, DL_INFO), xml->getIntAttribute (element, "max_length", INT_MAX, DL_INFO));
+ available->setStripDuplicates (!xml->getBoolAttribute (element, "allow_duplicates", false, DL_INFO));
connect (available, SIGNAL (valueChanged (RKComponentPropertyBase *)), this, SLOT (availablePropertyChanged (RKComponentPropertyBase *)));
availablePropertyChanged (available); // initialize
@@ -125,6 +127,8 @@
void RKVarSlot::availablePropertyChanged (RKComponentPropertyBase *) {
RK_TRACE (PLUGIN);
+ if (updating) return;
+
list->clear ();
item_map.clear ();
@@ -173,6 +177,7 @@
RK_DEBUG (PLUGIN, DL_DEBUG, "select press in varslot: mode %d, source %s, selected %s", add_mode, qPrintable (fetchStringValue (source)), qPrintable (fetchStringValue (selected)));
+ updating = true;
// first update the properties
if (add_mode) {
if (multi) {
@@ -186,20 +191,19 @@
if (source->objectValue ()) available->setObjectValue (source->objectValue ());
}
} else { // remove-mode
- RObject::ObjectList objlist;
- if (multi) {
- objlist = selected->objectList ();
- } else {
- objlist = available->objectList ();
+ QModelIndexList removed = list->selectionModel ()->selectedRows (0); // Note: list contains no dupes, but is unsorted.
+ QList<int> removed_rows;
+ for (int i = 0; i < removed.size (); ++i) {
+ removed_rows.append (removed[i].row ());
}
-
- RObject::ObjectList::const_iterator it = objlist.begin ();
- while (it != objlist.end ()) {
- available->removeObjectValue (*it);
- selected->removeObjectValue (*it);
- ++it;
+ qSort (removed_rows);
+ for (int i = removed_rows.size () - 1; i >= 0; --i) {
+ available->removeAt (removed_rows[i]);
}
+ selected->setObjectValue (0);
}
+ updating = false;
+ availablePropertyChanged (available);
}
#include "rkvarslot.moc"
Modified: trunk/rkward/rkward/plugin/rkvarslot.h
===================================================================
--- trunk/rkward/rkward/plugin/rkvarslot.h 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/rkward/plugin/rkvarslot.h 2013-05-03 14:49:21 UTC (rev 4739)
@@ -59,6 +59,7 @@
void setSelectButton (bool add);
bool add_mode;
bool multi;
+ bool updating;
/** the available objects (typically a copy of the property of the varselector) */
RKComponentPropertyRObjects *source;
Modified: trunk/rkward/rkward/plugins/plots/scatterplot.xml
===================================================================
--- trunk/rkward/rkward/plugins/plots/scatterplot.xml 2013-05-01 17:56:55 UTC (rev 4738)
+++ trunk/rkward/rkward/plugins/plots/scatterplot.xml 2013-05-03 14:49:21 UTC (rev 4739)
@@ -21,8 +21,8 @@
<varselector id="vars" />
<column>
<row>
- <varslot multi="true" duplicate="true" types="number unknown" id="x" source="vars" label="'X' variables" required="true" />
- <varslot multi="true" duplicate="true" types="number unknown" id="y" source="vars" label="'Y' variables" required="true" />
+ <varslot multi="true" allow_duplicates="true" types="number unknown" id="x" source="vars" label="'X' variables" required="true" />
+ <varslot multi="true" allow_duplicates="true" types="number unknown" id="y" source="vars" label="'Y' variables" required="true" />
</row>
<preview id="preview"/>
</column>
More information about the rkward-tracker
mailing list