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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Thu Nov 24 11:02:06 UTC 2011


Revision: 4049
          http://rkward.svn.sourceforge.net/rkward/?rev=4049&view=rev
Author:   tfry
Date:     2011-11-24 11:02:05 +0000 (Thu, 24 Nov 2011)
Log Message:
-----------
Start adding support for option sets.
This is still very incomplete, and in fact, the main chunk of code does not even get compiled, yet.

Modified Paths:
--------------
    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/plugin/rkstandardcomponent.h

Added Paths:
-----------
    trunk/rkward/rkward/plugin/rkoptionset.cpp
    trunk/rkward/rkward/plugin/rkoptionset.h

Modified: trunk/rkward/rkward/plugin/rkcomponent.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponent.h	2011-11-23 15:05:14 UTC (rev 4048)
+++ trunk/rkward/rkward/plugin/rkcomponent.h	2011-11-24 11:02:05 UTC (rev 4049)
@@ -40,6 +40,7 @@
 		PropertyRObjects = 5,
 		PropertyCode = 6,
 		PropertyLogic = 7,
+		PropertyStringList = 8,
 		PropertyUser = 1000,		/**< for user expansion */
 		PropertyEnd = 1999,
 		ComponentBase = 2001,
@@ -58,6 +59,7 @@
 		ComponentPreviewBox = 2014,
 		ComponentSaveObject = 2015,
 		ComponentFrame = 2016,
+		ComponentOptionSet = 2017,
 		ComponentStandard = 2100,
 		ComponentContextHandler = 2900,
 		ComponentUser = 3000	/**< for user expansion */
@@ -120,6 +122,7 @@
 @param include_top_level include direct properties of the component in the list (or only properties of children)
 @param prefix used during recursion to provide full ids for the added objects */
 	void fetchPropertyValuesRecursive (QMap<QString, QString> *list, bool include_top_level=false, const QString &prefix=QString::null) const;
+	friend class RKComponentBuilder;
 /** counterpart to fetchPropertyValuesRecursive (). Tries to apply all values from the list to properties of the given names. If some keys can not be found, or do not resolve to properties, the are ignored.
 @param list a list of id->value such as generated by fetchPropertyValuesRecursive () */
 	void setPropertyValues (QMap<QString, QString> *list, bool warn_internal=false);

Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.cpp	2011-11-23 15:05:14 UTC (rev 4048)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.cpp	2011-11-24 11:02:05 UTC (rev 4049)
@@ -149,6 +149,37 @@
 	RK_DO (qDebug ("Modifier '%s' not recognized.", modifier.toLatin1 (). data ()), PLUGIN, DL_ERROR);
 }
 
+
+///////////////////////////////////////// StringList ///////////////////////////////////////
+
+RKComponentPropertyStringList::RKComponentPropertyStringList (QObject *parent, bool required) : RKComponentPropertyBase (parent, required) {
+	RK_TRACE (PLUGIN);
+	sep = "\n";
+}
+
+RKComponentPropertyStringList::~RKComponentPropertyStringList () {
+	RK_TRACE (PLUGIN);
+}
+
+QString RKComponentPropertyStringList::value (const QString &modifier) {
+	RK_TRACE (PLUGIN);
+
+	if (!modifier.isEmpty ()) {
+		warnModifierNotRecognized (modifier);
+		return QString ();
+	}
+	if (_value.isNull ()) _value = storage.join (sep);	// _value acts as a cache
+	return _value;
+}
+
+void RKComponentPropertyStringList::setValueAt (int index, const QString& value) {
+	RK_TRACE (PLUGIN);
+	
+	while (index >= storage.size ()) storage.append (QString ());	// expand as needed
+	storage[index] = value;
+	doChange ();
+}
+
 ///////////////////////////////////////////// Bool //////////////////////////////////////////
 
 RKComponentPropertyBool::RKComponentPropertyBool (QObject *parent, bool required, bool default_state, const QString &value_true, const QString &value_false) : RKComponentPropertyBase (parent, required) {

Modified: trunk/rkward/rkward/plugin/rkcomponentproperties.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentproperties.h	2011-11-23 15:05:14 UTC (rev 4048)
+++ trunk/rkward/rkward/plugin/rkcomponentproperties.h	2011-11-24 11:02:05 UTC (rev 4049)
@@ -69,6 +69,35 @@
 };
 
 
+/////////////////////////////////////////////// StringList /////////////////////////////////////////////////////
+/** RKComponentProperty, which can handle lists of strings, better */
+class RKComponentPropertyStringList : public RKComponentPropertyBase {
+public:
+	RKComponentPropertyStringList (QObject *parent, bool required);
+/** destructor */
+	~RKComponentPropertyStringList ();
+/** for RTTI. see RKComponentBase::RKComponentTypes */
+	int type () { return PropertyStringList; };
+/** change separator string when concatenating strings for value (). Default separator string is "\n" */
+	void setSeparator (const QString &separator) { sep = separator; doChange (); };
+/** reimplemented to return all current strings joined by current separator (setSeparator) */
+	QString value (const QString &modifier=QString::null);
+/** return the string at the given index */
+	const QString valueAt (int index) const { return storage.value (index); };
+/** set the values in string form (values will be split by the current separator)
+ at returns false if the value is illegal (in this property, all strings are legal) */
+	bool setValue (const QString &string) { setValues (string.split (sep)); return true; };
+/** change only the string at the given index. List will be expanded, as necessary. */
+	void setValueAt (int index, const QString &value);
+/** 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 (); };
+private:
+	void doChange () { _value.clear (); emit (valueChanged (this)); };
+	QString sep;
+	QStringList storage;
+};
 
 ///////////////////////////////////////////////// Bool ////////////////////////////////////////////////////////
 

Added: trunk/rkward/rkward/plugin/rkoptionset.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkoptionset.cpp	                        (rev 0)
+++ trunk/rkward/rkward/plugin/rkoptionset.cpp	2011-11-24 11:02:05 UTC (rev 4049)
@@ -0,0 +1,109 @@
+/***************************************************************************
+                          rkoptionset  -  description
+                             -------------------
+    begin                : Mon Oct 31 2011
+    copyright            : (C) 2011 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "rkoptionset.h"
+
+#include <QVBoxLayout>
+
+#include <klocale.h>
+#include <kvbox.h>
+
+#include "rkstandardcomponent.h"
+#include "../misc/xmlhelper.h"
+
+#include "../debug.h"
+
+RKOptionSet::RKOptionSet (const QDomElement &element, RKComponent *parent_component, QWidget *parent_widget, RKStandardComponentBuilder *builder) {
+	RK_TRACE (PLUGIN);
+
+	XMLHelper *xml = XMLHelper::getStaticHelper ();
+
+	// create some meta properties
+	current_row = new RKComponentPropertyInt (this, false, -1);
+	row_count->setInternal (true);
+	addChild ("current_row", current_row);
+	connect (current_row, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (currentRowPropertyChanged(RKComponentPropertyBase*)));
+	row_count = new RKComponentPropertyInt (this, false, 0);
+	row_count->setInternal (true);
+	addChild ("row_count", row_count);
+
+	// first build the contents, as we will need to refer to the elements inside, later
+	QVBoxLayout *layout = new QVBoxLayout (this);
+	KVBox *contents_box = new KVBox (this);
+	layout->addWidget (contents_box);
+
+	display = 0;	// will be created from the builder, on demand -> createDisplay ()
+	container = new RKComponent (this, contents_box);
+	RKComponentBuilder *builder = new RKComponentBuilder (container, QDomElement ());
+	builder->buildElement (xml->getChildElement (element, "content", DL_ERROR), contents_box, false);
+	// take a snapshot of the default state
+	container->fetchPropertyValuesRecursive (&defaults);
+
+	// create columns
+	XMLChildList options = xml->getChildElements (element, "option", DL_WARNING);
+
+	int visible_columns = 0;
+	QQStringList column_labels;
+	QMap<QString, QString> columns_to_governors;
+	for (int i = 0; i < options.size (); ++i) {
+		QString id = xml->getStringAttribute (options.at (i), "id", QString (), DL_ERROR);
+		QString label = xml->getStringAttribute (options.at (i), "label", QString (), DL_DEBUG);
+		QString governor = xml->getStringAttribute (options.at (i), "governor", QString (), DL_WARNING);
+
+		while (columns_to_governors.contains (id) || child_map.contains (id)) {
+			RK_DO (qDebug ("optionset already contains a property named %s. Renaming to _%s", qPrintable (id), qPrintable (id)), PLUGIN, DL_ERROR);
+			id = "_" + id;
+		}
+		columns_to_governors.insert (id, governor);
+		if (!label.isEmpty ()) {
+			column_labels.append (label);
+			column_to_display_index_map.insert (id, visible_columns++);
+		}
+	}
+
+	keycolumn = xml->getStringAttribute (element, "keycolumn", QString (), DL_DEBUG);
+	if (!columns_to_governors.contains (keycolumn)) {
+		RK_DO (qDebug ("optionset does not contain a column named %s. Falling back to manual insertion mode", qPrintable (keycolumn)), PLUGIN, DL_ERROR);
+		keycolumn.clear ();
+	}
+
+	QMap<QString, QString>::const_iterator it = columns_to_governors.constBegin ();
+	for (; it != columns_to_governors.constEnd (); ++it) {
+		// add columns
+		RKComponentPropertyStringList *column_property = new RKComponentPropertyStringList (this, false);
+		addChild (it.key (), column_property);
+		connect (column_property, SIGNAL (valueChanged(RKComponentPropertyBase *)), this, SLOT (columnPropertyChanged(RKComponentPropertyBase *)));
+
+		if (!it ().value ().isEmpty ()) {		// there *can* be columns without governor. This allows to connect two option-sets, e.g. on different pages of a tabbook.
+			// Establish connections between columns and their respective governors. Since the format differs, the connection is done indirectly, through this component.
+			// So, here, we set up a map of properties to columns, and connect to the change signals.
+			QString modifier;
+			RKComponentBase *governor = container->lookupComponent (it.value (), &modifier);
+			if (governor && governor->isProperty ()) {
+				RKComponentPropertyBase *gov_prop = static_cast<RKComponentPropertyBase*> (governor);
+				ModifierAndColumn mac;
+				mac.modifier = modifier;
+				mac.column_name = it.key ();
+				property_to_column_map.insertMulti (gov_prop, mac);
+				connect (gov_prop, SIGNAL (valueChanged(RKComponentPropertyBase *)), this, SLOT (governingPropertyChanged(RKComponentPropertyBase *)));
+			} else {
+				RK_DO (qDebug ("did not find governing property %s for column %s of optionset", qPrintable (it.value ()), qPrintable (it.key ())), PLUGIN, DL_ERROR);
+			}
+		}
+	}
+}
+

Added: trunk/rkward/rkward/plugin/rkoptionset.h
===================================================================
--- trunk/rkward/rkward/plugin/rkoptionset.h	                        (rev 0)
+++ trunk/rkward/rkward/plugin/rkoptionset.h	2011-11-24 11:02:05 UTC (rev 4049)
@@ -0,0 +1,65 @@
+/***************************************************************************
+                          rkoptionset  -  description
+                             -------------------
+    begin                : Mon Oct 31 2011
+    copyright            : (C) 2011 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef RKOPTIONSET_H
+#define RKOPTIONSET_H
+
+#include <rkcomponent.h>
+
+#include <qmap.h>
+
+class QTableWidget;
+
+/** An RKOptionSet provides a group of options for an arbitrary number of "rows". E.g. different line colors for each of a group of variables.
+  *@author Thomas Friedrichsmeier
+  */
+class RKOptionSet : public RKComponent {
+	Q_OBJECT
+public:
+	RKOptionSet (const QDomElement &element, RKComponent *parent_component, QWidget *parent_widget, RKStandardComponentBuilder *builder);
+	~RKOptionSet ();
+	int type () { return ComponentOptionSet; };
+	QWidget *createDisplay (bool show_index);
+private slots:
+	void governingPropertyChanged (RKComponentPropertyBase *property);
+	void columnPropertyChanged (RKComponentPropertyBase *property);
+	void currentRowPropertyChanged (RKComponentPropertyBase *property);
+	void addRow ();
+	void removeRow (int index);
+private:
+	QMap<QString, QString> defaults;
+/** for option sets which are "driven" (i.e. the user cannot simply add / remove rows, directly), this holds the key column, controlling addition / removal of rows in the set.
+  * if this length (or order) is changed in this row, it will also be changed in the other rows. */
+	QString keycolumn;
+	struct ModifierAndColumn {
+		QString modifier;
+		QString column_name;
+	};
+	QMultiMap<RKComponentPropertyBase *, ModifierAndColumn> property_to_column_map;
+	QMap<RKComponentPropertyStringList *, int> column_to_display_index_map;
+	RKComponent *container;
+	QTableWidget *display;
+	bool display_show_index;
+	RKComponentPropertyInt *current_row;
+	RKComponentPropertyInt *row_count;
+
+	int min_rows;
+	int min_rows_if_any;
+	int max_rows;
+};
+
+#endif

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2011-11-23 15:05:14 UTC (rev 4048)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2011-11-24 11:02:05 UTC (rev 4049)
@@ -502,7 +502,7 @@
 
 #include <qpushbutton.h>
 
-RKComponentBuilder::RKComponentBuilder (RKStandardComponent *parent_component, const QDomElement &document_element) {
+RKComponentBuilder::RKComponentBuilder (RKComponent *parent_component, const QDomElement &document_element) {
 	RK_TRACE (PLUGIN);
 	parent = parent_component;
 	doc_elem = document_element;
@@ -512,6 +512,19 @@
 	RK_TRACE (PLUGIN);
 }
 
+RKStandardComponent *RKComponentBuilder::standardComponent (QString *id_adjust) {
+	RK_TRACE (PLUGIN);
+
+	RKComponent *p = parent;
+	while (p) {
+		if (p->type () == RKComponent::ComponentStandard) return static_cast<RKStandardComponent*> (p);
+		if (id_adjust) id_adjust->prepend (p->getIdInParent () + '.');
+		p = p->parentComponent ();
+	}
+	RK_ASSERT (false);
+	return 0;
+}
+
 QDomElement RKComponentBuilder::doElementCopy (const QString id, const QDomElement &copy) {
 	RK_TRACE (PLUGIN);
 
@@ -659,7 +672,8 @@
 			layout->setContentsMargins (0, 0, 0, 0);
 			KVBox *box = new KVBox (widget);
 			layout->addWidget (box);
-			component ()->scriptingProxy ()->addScriptableWidget (id, widget);
+			QString id_adjust;
+			standardComponent (&id_adjust)->scriptingProxy ()->addScriptableWidget (id_adjust + id, widget);
 		} else {
 			xml->displayError (&e, QString ("Invalid tagname '%1'").arg (e.tagName ()), DL_ERROR);
 		}
@@ -729,7 +743,7 @@
 	if (!e.isNull ()) {
 		QString file = xml->getStringAttribute (e, "file", QString (), DL_INFO);
 		QString inline_command = e.text ();
-		component ()->scriptingProxy ()->initialize (file, inline_command);
+		standardComponent ()->scriptingProxy ()->initialize (file, inline_command);
 	}
 }
 

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.h
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.h	2011-11-23 15:05:14 UTC (rev 4048)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.h	2011-11-24 11:02:05 UTC (rev 4049)
@@ -140,18 +140,18 @@
 @author Thomas Friedrichsmeier */
 class RKComponentBuilder {
 public:
-	RKComponentBuilder (RKStandardComponent *parent_component, const QDomElement &document_element);
+	RKComponentBuilder (RKComponent *parent_component, const QDomElement &document_element);
 	~RKComponentBuilder ();
 	void buildElement (const QDomElement &element, QWidget *parent_widget, bool allow_pages);
 	void parseLogic (const QDomElement &element);
 	void makeConnections ();
-	RKStandardComponent *component () const { return parent; };
+	RKComponent *component () const { return parent; };
 private:
 /** internal convenience function to schedule a property connection */
 	void addConnection (const QString &client_id, const QString &client_property, const QString &governor_id, const QString &governor_property, bool reconcile, const QDomElement &origin);
 	QDomElement doElementCopy (const QString id, const QDomElement &copy);
 	QDomElement doc_elem;
-	RKStandardComponent *parent;
+	RKComponent *parent;
 	struct RKComponentPropertyConnection {
 		QString governor_property;
 		QString client_property;
@@ -161,6 +161,7 @@
 	typedef QList <RKComponentPropertyConnection> ConnectionList;
 	ConnectionList connection_list;
 	QMap<QString, QString> initial_values;
+	RKStandardComponent *standardComponent (QString *id_adjust=0);
 };
 
 #endif

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