[rkward-cvs] SF.net SVN: rkward:[4485] trunk/rkward
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Fri Dec 7 11:07:11 UTC 2012
Revision: 4485
http://rkward.svn.sourceforge.net/rkward/?rev=4485&view=rev
Author: tfry
Date: 2012-12-07 11:07:10 +0000 (Fri, 07 Dec 2012)
Log Message:
-----------
Add <switch> element for implementing switch() statements, or remapping values.
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/doc/rkwardplugins/index.docbook
trunk/rkward/rkward/plugin/rkcomponent.cpp
trunk/rkward/rkward/plugin/rkcomponent.h
trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
trunk/rkward/rkward/plugin/rkcomponentproperties.h
trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
trunk/rkward/rkward/plugins/data/sort.xml
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/ChangeLog 2012-12-07 11:07:10 UTC (rev 4485)
@@ -1,3 +1,4 @@
+- Added <switch> logic element to switch between several target properties (or fixed values) based on the value of a condition property
- Sort plugin gains option to sort data.frames by more than one column at a time, and options for type conversion TODO: adjust test(s)
- Add in-application debug message viewer (targetted at (plugin) developers)
- Add setting to customize initial working directory
@@ -4,12 +5,12 @@
- Windows only: Add UI-checkbox for R's "internet2"-option
- New functions getString(), getList() and getBoolean() for fetching data in plugin scripts TODO: more testing, convert at least some plugins
- Boolean properties now return a numeric, not labelled representation of their value, by default. <checkbox>es should be unaffected. TODO: when announcing release, link to explanation mail.
-- Added GUI element for entering a set of options for an arbitrary number of items TODO: document
+- Added <optionset> GUI element for entering a set of options for an arbitrary number of items
- Reduce CPU usage of pluings while idle
- Fix conversion from Numeric to Factor in the data editor
- In the data.frame editor, columns containing invalid values are now highlighted in red
- Fixed: If none of the previous plugin maps could be found on startup, re-add the default
-- Added GUI element for entering matrix or vector data in plugins
+- Added <matrix> GUI element for entering matrix or vector data in plugins
- Improve key handling while editing factor levels in a data.frame
- Added utiltity function rk.flush.output()
- RKWard is now categorized as Science/Math/Numerical Analysis in its .desktop file
Modified: trunk/rkward/doc/rkwardplugins/index.docbook
===================================================================
--- trunk/rkward/doc/rkwardplugins/index.docbook 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/doc/rkwardplugins/index.docbook 2012-12-07 11:07:10 UTC (rev 4485)
@@ -809,44 +809,37 @@
<logic>
<convert id="varmode" mode="equals" sources="mode.string" standard="variable" />
- <convert id="constmode" mode="equals" sources="mode.string" standard="constant" />
<connect client="y.visible" governor="varmode" />
- <connect client="constant.visible" governor="constmode" />
+ <connect client="constant.visible" governor="varmode.not" />
</logic>
<dialog label="T-Test">
[...]
</programlisting>
<para>
- The first two lines inside the logic section are <command><convert></command> tags. Those basically provide two new boolean (on or off, true or false) properties, which can be used later on. The first property (<replaceable>"varmode"</replaceable>) is true, whenever the upper radio button is selected and the second whenever the lower radio button is selected. How is this done?
+ The first line inside the logic section is a <command><convert></command> tag. Basically, this provides a new boolean (on or off, true or false) property, which can be used later on. This property (<replaceable>"varmode"</replaceable>) is true, whenever the upper radio button is selected and false whenever the lower radio button is selected. How is this done?
</para>
<para>
First, under <parameter>sources</parameter>, the source properties to work on are listed (in this case only one each; you could list several as <parameter>sources=</parameter><replaceable>"mode.string;somethingelse"</replaceable>, then <replaceable>"varmode"</replaceable> would only be true, if both <replaceable>"mode.string"</replaceable> and <replaceable>"somethingelse"</replaceable> are equal to the string <replaceable>"variable"</replaceable>). Note that in this case we don't just write <replaceable>"mode"</replaceable> (as we would in <function>getString("mode")</function>, but <replaceable>"mode.string"</replaceable>. This is actually the internal way a radio control works: It has a property <quote>string</quote>, which holds its string value. <function>getString("mode")</function> is just a shorthand, and equivalent to <function>getString("mode.string")</function>. See the reference for all properties of the different GUI elements.
</para>
<para>
- Second, we set the mode of conversion to <parameter>mode=</parameter><replaceable>"equals"</replaceable>. This means, we want to check, whether the sources are equal to a certain value. Finally standard is the value to compare against, so with <parameter>standard=</parameter><replaceable>"variable"</replaceable>, we check whether the property <replaceable>"mode.string"</replaceable> is equal to the string <replaceable>"variable"</replaceable> (the value of the upper radio option). If it is equal, then the property varmode is true, else it is false.
+ Second, we set the mode of conversion to <parameter>mode=</parameter><replaceable>"equals"</replaceable>. This means, we want to check, whether the source(s) is (are) equal to a certain value. Finally standard is the value to compare against, so with <parameter>standard=</parameter><replaceable>"variable"</replaceable>, we check whether the property <replaceable>"mode.string"</replaceable> is equal to the string <replaceable>"variable"</replaceable> (the value of the upper radio option). If it is equal, then the property varmode is true, else it is false.
</para>
<para>
- The next line is basically the same, but reversed. Here we define a property (<replaceable>"constmode"</replaceable>) which becomes true, if the second radio option is selected.
+ Now to the real stuff: We <command><connect></command> the <replaceable>"varmode"</replaceable> property to y.visible, which controls whether the varslot <replaceable>"y"</replaceable> is shown or not. Note that any element which is made invisible is implicitly non-required. Thus, if the upper radio-option is selected, the varslot <replaceable>"y"</replaceable> is required, and visible. Else it is not required and hidden.
</para>
<para>
- Now to the real stuff: We <command><connect></command> the <replaceable>"varmode"</replaceable> property to y.visible, which controls whether the varslot <replaceable>"y"</replaceable> is shown or not. Note that any element which is made invisible is implicitly non-required. Thus, if the upper radio-option is selected, the varslot <replaceable>"y"</replaceable> is required, and visible. Else it is not required and hidden.
+ For the spinbox, we want the exact reverse. Fortunately, we do not need another <command><convert></command> for this: Boolean
+ properties can be negated very easily by appending the modifier <replaceable>"not"</replaceable>, so we <command><connect></command> <replaceable>"varmode.not"</replaceable> to the spinbox's visibility property. In effect, either
+ the varslot is shown and required, <emphasis>or</emphasis> the spinbox is shown and required - depending on which option is selected in the radio control. The GUI is changing itself according to the radio option. Try the example, if you like.
</para>
<para>
- We do just the reverse for the spinbox. So in effect, either the varslot is shown and required, <emphasis>or</emphasis> the spinbox is shown and required - depending on which option is selected in the radio control. The GUI is changing itself according to the radio option. Try the example, if you like.
+ For a complete list of properties, refer to the <link linkend="reference">reference</link>. One more property, however, is special in that all GUI elements have it: <quote>enabled</quote>. This is slightly less drastic that <quote>visible</quote>. It does not show/hide the GUI element, but only enables/disables it. Disabled elements are typically shown grayed out, and do not react to user input.
</para>
<note>
- <para>
- In the above example, instead of defining two properties <replaceable>"varmode"</replaceable> and <replaceable>"constmode"</replaceable>, we could also have used the negation of <replaceable>"varmode"</replaceable>, like this:
- </para>
+ <para>Besides <command><convert></command> and <command><connect></command>, there are several further elements for use in the <command><logic></command> section. E.g. conditional constructs can also be implemented using the <command><switch></command>-element. Refer to the <link linkend="logicelements">reference on logic elements</link> for details.</para>
</note>
- <programlisting>
- <connect client="constant.visible" governor="varmode.not" />
- </programlisting>
- <para>
- Once again, for a complete list of properties, refer to the <link linkend="reference">reference</link>. One more property, however, is special in that all GUI elements have it: <quote>enabled</quote>. This is slightly less drastic that <quote>visible</quote>. It does not show/hide the GUI element, but only enables/disables it. Disabled elements are typically shown grayed out, and do not react to user input.
- </para>
</sect1>
<sect1 id="logic_scripted">
<title>Scripted GUI logic</title>
@@ -856,7 +849,7 @@
<programlisting>
[...]
<code file="code.js"/>
-
+'
<logic>
<script><![CDATA[
// ECMAScript code in this block
@@ -2691,16 +2684,16 @@
<term><optioncolumn></term>
<listitem><para>Declares one optioncolumn of the set. For each value that you want to fetch from the optionset, you must declare a separate <optioncolumn>. Attributes:
<variablelist>
- <varlistentry><term>id</term>
+ <varlistentry><term><parameter>id</parameter></term>
<listitem><para>The id of the optioncolumn (required, string).</para></listitem></varlistentry>
- <varlistentry><term>external</term>
+ <varlistentry><term><parameter>external</parameter></term>
<listitem><para>Set to true, if the optioncolumn is controlled from outside the optionset (optional, boolean, defaults to false).</para></listitem></varlistentry>
- <varlistentry><term>label</term>
+ <varlistentry><term><parameter>label</parameter></term>
<listitem><para>If given, the optioncolumn will be displayed in the <optiondisplay> in a column by that label (optional, string, defaults to not displayed).</para></listitem></varlistentry>
- <varlistentry><term>connect</term>
+ <varlistentry><term><parameter>connect</parameter></term>
<listitem><para>The property to connect this optioncolumn to, given as id inside the <content>-area. For external <optioncolumn>s, the corresponding value will be set to the externally set value. For regular (non-external) <optioncolumn>s,
the corresponding row of the <optioncolumn>-property, will be set when the property changes inside the content-area. (optional, string, defaults to not connected).</para></listitem></varlistentry>
- <varlistentry><term>default</term>
+ <varlistentry><term><parameter>default</parameter></term>
<listitem><para>Only for external columns: The value to assume for this column, if no value is known for an entry. Rarely useful. (Optional, defaults to empty string)</para></listitem></varlistentry>
</variablelist>
</para></listitem></varlistentry>
@@ -2939,6 +2932,57 @@
</varlistentry>
<varlistentry>
+<term><switch></term>
+<listitem><para>Create a new property that will relay to different target properties (or fixed strings) based on the value of a condition property. This allows to create logic similar to <function>if()</function> or <function>switch()</function> constructs. Attributes:
+ <variablelist>
+ <varlistentry>
+ <term><parameter>id</parameter></term>
+ <listitem><para>The ID of the new property (required)</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>condition</parameter></term>
+ <listitem><para>The id of the condition property (required)</para></listitem>
+ </varlistentry>
+ </variablelist>
+Child elements:
+ <variablelist>
+ <varlistentry>
+ <term><true></term>
+ <listitem><para>If the condition property is boolean, you can specify the two child elements <true> and <false> (and only these). (Required, if <false> is also given)</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><false></term>
+ <listitem><para>If the condition property is boolean, you can specify the two child elements <true> and <false> (and only these). (Required, if <true> is also given)</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><case></term>
+ <listitem><para>If the condition property is not boolean, you can supply and arbitrary number of <case>-elements, one for each
+ value of the condition property that you want to match (at least one such element is required, if the condition property is not boolean)</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><default></term>
+ <listitem><para>If the condition property is not boolean, the optional <default>-element, allows to specify the behavior, if no
+ <case> element is matches the value of the condition property (optional, allowed only once, in combination with one or more <case> elements).</para></listitem>
+ </varlistentry>
+ </variablelist>
+Child elements <true>, <false>, <case>, and <default> take the following attributes:
+ <variablelist>
+ <varlistentry>
+ <term><parameter>standard</parameter></term>
+ <listitem><para>Only for <case>-elements: The value to match the condition property against (required, string).</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>fixed_value</parameter></term>
+ <listitem><para>A fixed string that should be supplied as the value of the <switch> property, if the current condition matches (required, if dynamic_value is not supplied).</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>dynamic_value</parameter></term>
+ <listitem><para>The <parameter>id</parameter> of the target property that should be supplied as the value of the <switch> property, if the current condition matches (required, if fixed_value is not supplied).</para></listitem>
+ </varlistentry>
+ </variablelist></para></listitem>
+</varlistentry>
+
+<varlistentry>
<term><connect></term>
<listitem><para>Connects two properties. The client property will be changed whenever the governor property changes (but not the other way around!). Attributes:
<variablelist>
@@ -3262,6 +3306,14 @@
<term><convert></term>
<listitem><para>This element (used in the <logic> section) is special, in that is technically *is* a property, instead of just holding one or more properties. It is of boolean kind. Note that useful modifiers of this property (as of all boolean properties) are "not" and "numeric" (see <link linkend="propertytypes">types of properties</link>)</para></listitem>
</varlistentry>
+
+<varlistentry>
+<term><switch></term>
+<listitem><para>This element (used in the <logic> section) is special, in that is technically *is* a (string) property, instead of just holding one or more properties. It allows to switch between several target properties depending on the value of a condition property, or to re-map values of the condition property. Any modifiers that you supply are passed on to the target properties, thus, e.g. if all target
+properties are RObject properties, you can use the "shortname" modifier on the switch, too. However, if the target properties are of
+different types, using modifiers may lead to errors. For <replaceable>fixed_value</replaceable>s, any modifier is dropped, silently. Note that target properties, when accessed through a switch, are always read-only!</para></listitem>
+</varlistentry>
+
</variablelist>
</sect1>
Modified: trunk/rkward/rkward/plugin/rkcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponent.cpp 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/rkward/plugin/rkcomponent.cpp 2012-12-07 11:07:10 UTC (rev 4485)
@@ -41,6 +41,7 @@
}
RKComponentPropertyBase* RKComponentBase::lookupProperty (const QString &identifier, QString *remainder, bool warn) {
+ RK_TRACE (PLUGIN);
QString _remainder;
QString* p_remainder = remainder;
if (!remainder) p_remainder = &_remainder;
Modified: trunk/rkward/rkward/plugin/rkcomponent.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponent.h 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/rkward/plugin/rkcomponent.h 2012-12-07 11:07:10 UTC (rev 4485)
@@ -40,8 +40,9 @@
PropertyDouble = 4,
PropertyRObjects = 5,
PropertyCode = 6,
- PropertyLogic = 7,
+ PropertyConvert = 7,
PropertyStringList = 8,
+ PropertySwitch = 9,
PropertyUser = 1000, /**< for user expansion */
PropertyEnd = 1999,
ComponentBase = 2001,
Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.cpp 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.cpp 2012-12-07 11:07:10 UTC (rev 4485)
@@ -1150,11 +1150,10 @@
sourcePropertyChanged (0);
}
-void RKComponentPropertyConvert::setSources (const QString &source_string) {
+void RKComponentPropertyConvert::setSources (const QStringList &source_ids) {
RK_TRACE (PLUGIN);
sources.clear ();
- QStringList source_ids = source_string.split (";");
for (QStringList::const_iterator it = source_ids.constBegin (); it != source_ids.constEnd (); ++it) {
Source s;
RKComponentBase *prop = c_parent->lookupComponent (*it, &(s.modifier));
@@ -1277,4 +1276,99 @@
return is_valid;
}
+void RKComponentPropertyConvert::connectToGovernor (RKComponentPropertyBase*, const QString&, bool) {
+ RK_DEBUG (PLUGIN, DL_ERROR, "Cannot connect a <convert> property to a governor");
+}
+
+bool RKComponentPropertyConvert::setValue (const QString&) {
+ RK_DEBUG (PLUGIN, DL_ERROR, "Cannot set value for a <convert> property");
+ return false;
+}
+
+/////////////////////////////////////////// Switch ////////////////////////////////////////////////
+
+RKComponentPropertySwitch::RKComponentPropertySwitch (RKComponent* parent, const QStringList& def_values, const QStringList& standards) : RKComponentPropertyBase (parent, false) {
+ RK_TRACE (PLUGIN);
+
+ RKComponentPropertySwitch::def_values = def_values;
+ RKComponentPropertySwitch::standards = standards;
+ condition_prop = 0;
+ c_parent = parent;
+
+ connect (this, SIGNAL(valueChanged(RKComponentPropertyBase*)), this, SLOT(selfChanged(RKComponentPropertyBase*)));
+}
+
+RKComponentPropertySwitch::~RKComponentPropertySwitch () {
+ RK_TRACE (PLUGIN);
+}
+
+void RKComponentPropertySwitch::connectToGovernor (RKComponentPropertyBase*, const QString&, bool) {
+ RK_DEBUG (PLUGIN, DL_ERROR, "Cannot connect a <switch> property to a governor");
+}
+
+bool RKComponentPropertySwitch::setValue (const QString& value) {
+ RK_DEBUG (PLUGIN, DL_ERROR, "Cannot set value for a <switch> property");
+ return false;
+}
+
+void RKComponentPropertySwitch::selfChanged (RKComponentPropertyBase *) {
+ RK_TRACE (PLUGIN);
+ c_parent->changed ();
+}
+
+void RKComponentPropertySwitch::sourcePropertyChanged (RKComponentPropertyBase*) {
+ RK_TRACE (PLUGIN);
+ valueChanged (this); // new value will be pulled by anyone interested
+}
+
+QVariant RKComponentPropertySwitch::value (const QString& modifier) {
+ RK_TRACE (PLUGIN);
+
+ if (!condition_prop) {
+ RK_ASSERT (false);
+ return QVariant ();
+ }
+ QVariant cond = condition_prop->value (condition_prop_modifier);
+ int index = 0;
+ if (standards.isEmpty ()) {
+ if (RKComponentPropertyBool::variantToBool (cond, 0)) index = 1;
+ } else {
+ index = standards.indexOf (cond.toString ()); // NOTE: list search. Could use a hash, instead, but in general there won't be more than a hand full of standards
+ if (index < 0) index = standards.size (); // remainder-category
+ }
+
+ // First try to return matching property
+ RKComponentPropertyBase *p = value_props.value (index);
+ if (p) {
+ QString mod = value_prop_mods.value (index);
+ if (!(mod.isEmpty () || modifier.isEmpty ())) mod.append (".");
+ mod.append (modifier);
+ return p->value (mod);
+ }
+
+ // If that fails, try to find a static default string
+ if (index < def_values.size ()) {
+ return def_values[index]; // NOTE: silently dropping modifier. This is useful for static "other" strings.
+ }
+
+ RK_DEBUG (PLUGIN, DL_ERROR, "Neither a fixed value, nor a property is defined for value %s (element %d/%d of standards)", qPrintable (cond.toString ()), index + 1, standards.size ());
+ return QVariant ();
+}
+
+void RKComponentPropertySwitch::setSources (const QString& _condition_prop, const QStringList& _value_props) {
+ RK_TRACE (PLUGIN);
+ RK_ASSERT (!condition_prop); // must only be called once
+
+ condition_prop = c_parent->lookupProperty (_condition_prop, &condition_prop_modifier, true);
+ if (!condition_prop) RK_DEBUG (PLUGIN, DL_ERROR, "Not a valid condition to connect <switch> property to: %s", qPrintable (_condition_prop));
+
+ for (int i = 0; i < _value_props.size (); ++i) {
+ QString mod;
+ RKComponentPropertyBase *p = c_parent->lookupProperty (_value_props[i], &mod, true);
+ value_props.append (p); // NOTE: Even if it is 0. value() takes care of that.
+ value_prop_mods.append (mod);
+ if (p) connect (p, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (sourcePropertyChanged(RKComponentPropertyBase*)));
+ }
+}
+
#include "rkcomponentproperties.moc"
Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.h 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.h 2012-12-07 11:07:10 UTC (rev 4485)
@@ -387,6 +387,7 @@
/** constructor. Note that this property *requires* an RKComponent as parent (the one at the top of all the source properties) */
RKComponentPropertyConvert (RKComponent *parent);
~RKComponentPropertyConvert ();
+ int type () { return PropertyConvert; };
/** Mode of operation. see setMode () */
enum ConvertMode {
@@ -400,7 +401,7 @@
/** set the mode. Usually you will only call this once, after construction, and usually followed by setSources () - if applicable - setStandard () or setRange (). */
void setMode (ConvertMode mode);
/** set the sources, i.e. the properties to check against. To specify multiple sources, separate their IDs with ";" */
- void setSources (const QString &source_string);
+ void setSources (const QStringList &sources);
/** set the standard for comparison. Only meaningful in Equals mode */
void setStandard (const QString &standard);
/** set the range for comparison. Only meaningful in Range mode */
@@ -413,6 +414,10 @@
/** string represenation of the options in ConvertMode. For use in XMLHelper::getMultiChoiceAttribute */
static QString convertModeOptionString () { return ("equals;notequals;range;and;or"); };
+/** reimplemented to do raise a warning, and do nothing else. */
+ void connectToGovernor (RKComponentPropertyBase *governor, const QString &modifier=QString::null, bool reconcile_requirements=true);
+/** reimplemented to do raise a warning, and do nothing else. */
+ bool setValue (const QString &value);
public slots:
/** unfortuntely, as the parent component likely does not know about us, we have to notify it manually of any changes. That's done from this slot */
void selfChanged (RKComponentPropertyBase *);
@@ -431,5 +436,38 @@
QList<Source> sources;
};
+/** This special property corresponds to a switch-statement, switching between two or more separate governing props based on the value of a condition prop. */
+class RKComponentPropertySwitch : public RKComponentPropertyBase {
+ Q_OBJECT
+public:
+/** constructor. Note that this property *requires* an RKComponent as parent (the one at the top of all the source properties)
+ @param standards the values to match against. Note: Providing an empty list make the switch operate in boolean mode,
+ switching between the first two sources / values, based on the boolean value of the condition_prop. */
+ RKComponentPropertySwitch (RKComponent *parent, const QStringList& def_values, const QStringList& standards);
+ ~RKComponentPropertySwitch ();
+
+/** set the sources, i.e. the properties to operate on */
+ void setSources (const QString &condition_prop, const QStringList &value_props);
+/** reimplemented to do raise a warning, and do nothing else. */
+ void connectToGovernor (RKComponentPropertyBase *governor, const QString &modifier=QString::null, bool reconcile_requirements=true);
+/** reimplemented to do raise a warning, and do nothing else. */
+ bool setValue (const QString &value);
+
+ QVariant value (const QString &modifier=QString ());
+ int type () { return PropertySwitch; };
+public slots:
+/** unfortuntely, as the parent component likely does not know about us, we have to notify it manually of any changes. That's done from this slot */
+ void selfChanged (RKComponentPropertyBase *);
+/** a source property changed. Check the state */
+ void sourcePropertyChanged (RKComponentPropertyBase *);
+private:
+ RKComponent *c_parent; // actually the same as parent (), but without the hassle of conversion
+ QStringList def_values;
+ QStringList standards;
+ RKComponentPropertyBase *condition_prop;
+ QString condition_prop_modifier;
+ QList<RKComponentPropertyBase*> value_props;
+ QStringList value_prop_mods;
+};
+
#endif
-
Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp 2012-12-07 11:07:10 UTC (rev 4485)
@@ -721,6 +721,7 @@
}
// find convert elements
+ QMap<RKComponentPropertyBase*, QStringList> switch_convert_sources;
children = xml->getChildElements (element, "convert", DL_INFO);
for (it = children.constBegin (); it != children.constEnd (); ++it) {
RKComponentPropertyConvert *convert = new RKComponentPropertyConvert (component ());
@@ -733,12 +734,72 @@
} else if (mode == RKComponentPropertyConvert::Range) {
convert->setRange (xml->getDoubleAttribute (*it, "min", -FLT_MAX, DL_INFO), xml->getDoubleAttribute (*it, "max", FLT_MAX, DL_INFO));
}
- QString sources = xml->getStringAttribute (*it, "sources", QString::null, DL_WARNING);
- convert->setSources (sources);
+ switch_convert_sources.insert (convert, xml->getStringAttribute (*it, "sources", QString::null, DL_WARNING).split (';'));
convert->setRequireTrue (xml->getBoolAttribute (*it, "require_true", false, DL_INFO));
component ()->addChild (id, convert);
}
+ // find switch elements
+ children = xml->getChildElements (element, "switch", DL_INFO);
+ for (it = children.constBegin (); it != children.constEnd (); ++it) {
+ QDomElement t = xml->getChildElement (*it, "true", DL_INFO);
+ QDomElement f = xml->getChildElement (*it, "false", DL_INFO);
+ if (t.isNull () != f.isNull ()) {
+ xml->displayError (&(*it), "One of <true> / <false> was provided for boolean <switch>, but not the other. Skipping switch.", DL_ERROR);
+ continue;
+ }
+
+ XMLChildList case_elems = xml->getChildElements (*it, "case", DL_INFO);
+ QDomElement default_elem = xml->getChildElement (*it, "default", DL_INFO);
+ if (!default_elem.isNull ()) case_elems.append (default_elem);
+
+ if (t.isNull ()) {
+ if (case_elems.isEmpty ()) {
+ xml->displayError (&(*it), "Neither <true> / <false> nor <case> / <default> were provided. Skipping switch.", DL_ERROR);
+ continue;
+ }
+ } else {
+ if (!case_elems.isEmpty ()) {
+ xml->displayError (&(*it), "One <true> / <false> *or* <case> / <default> may be provided a <switch>. Proceeding with boolean switch.", DL_ERROR);
+ case_elems.clear ();
+ }
+ case_elems.append (f);
+ case_elems.append (t);
+ }
+
+ QStringList def_strings;
+ QStringList standards;
+ QStringList sources;
+ sources.append (xml->getStringAttribute (*it, "condition", QString (), DL_ERROR)); // store condition prop as first "source"
+
+ for (XMLChildList::const_iterator cit = case_elems.constBegin (); cit != case_elems.constEnd (); ++cit) {
+ def_strings.append (xml->getStringAttribute (*cit, "fixed_value", QString (), DL_INFO));
+ sources.append (xml->getStringAttribute (*cit, "dynamic_value", QString (), DL_INFO));
+ if ((*cit).tagName () == "case") standards.append (xml->getStringAttribute (*cit, "standard", QString (), DL_WARNING));
+ }
+
+ QString id = xml->getStringAttribute (*it, "id", "#noid#", DL_WARNING);
+ RKComponentPropertySwitch *switchel = new RKComponentPropertySwitch (component (), def_strings, standards);
+ switchel->setInternal (true);
+ switch_convert_sources.insert (switchel, sources);
+ component ()->addChild (id, switchel);
+ }
+
+ // resolve source properties for switch and convert elements, *after* all properties have been created
+ for (QMap<RKComponentPropertyBase*, QStringList>::const_iterator it = switch_convert_sources.constBegin (); it != switch_convert_sources.constEnd (); ++it) {
+ if (it.key ()->type () == RKComponentBase::PropertyConvert) {
+ static_cast<RKComponentPropertyConvert*> (it.key ())->setSources (it.value ());
+ } else {
+ RK_ASSERT (it.key ()->type () == RKComponentBase::PropertySwitch);
+ QStringList sources = it.value ();
+ if (sources.isEmpty ()) {
+ RK_ASSERT (!sources.isEmpty ());
+ continue;
+ }
+ static_cast<RKComponentPropertySwitch*> (it.key ())->setSources (sources.takeFirst (), sources);
+ }
+ }
+
QDomElement e = xml->getChildElement (element, "script", DL_INFO);
if (!e.isNull () && allow_script_tag) {
QString file = xml->getStringAttribute (e, "file", QString (), DL_INFO);
Modified: trunk/rkward/rkward/plugins/data/sort.xml
===================================================================
--- trunk/rkward/rkward/plugins/data/sort.xml 2012-12-07 10:08:59 UTC (rev 4484)
+++ trunk/rkward/rkward/plugins/data/sort.xml 2012-12-07 11:07:10 UTC (rev 4485)
@@ -77,6 +77,10 @@
<logic>
<convert id="custom_conversion" mode="equals" sources="conversion.string" standard="custom"/>
<connect governor="custom_conversion" client="conversion_custom.enabled"/>
+ <switch id="conversion_label" condition="custom_conversion">
+ <false dynamic_value="conversion.string"/>
+ <true dynamic_value="conversion_custom.text"/>
+ </switch>
</logic>
<content>
<optiondisplay index="true"/>
@@ -86,7 +90,8 @@
<optioncolumn id="object" external="true"/>
<optioncolumn id="objectshort" external="true" label="Object"/>
<optioncolumn id="reverse" label="Order" connect="reverse.state.labeled"/>
- <optioncolumn id="conversion" label="Sort mode" connect="conversion.string"/>
+ <optioncolumn id="conversion" connect="conversion.string"/>
+ <optioncolumn id="conversion_label" label="Sort mode" connect="conversion_label"/>
<optioncolumn id="conversion_custom" connect="conversion_custom.text"/>
</optionset>
<stretch/>
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