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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Fri May 18 09:25:42 UTC 2012


Revision: 4254
          http://rkward.svn.sourceforge.net/rkward/?rev=4254&view=rev
Author:   tfry
Date:     2012-05-18 09:25:42 +0000 (Fri, 18 May 2012)
Log Message:
-----------
More bits for the optionset. Most of the internal logic is done, now (but completely untested, of course).

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

Modified: trunk/rkward/rkward/plugin/rkoptionset.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkoptionset.cpp	2012-05-16 14:34:46 UTC (rev 4253)
+++ trunk/rkward/rkward/plugin/rkoptionset.cpp	2012-05-18 09:25:42 UTC (rev 4254)
@@ -32,18 +32,23 @@
 	RK_TRACE (PLUGIN);
 
 	XMLHelper *xml = XMLHelper::getStaticHelper ();
-	updating_from_contents = changing_row = false;
+	updating_from_contents = updating_from_storage = false;
+	connect (&update_timer, SIGNAL (timeout()), this, SLOT (updateContents()));
+	update_timer->setSingleShot (true);
+	update_timer->setTimeout (0);
 
-	connect (standardComponent (), SIGNAL (componentChanged(RKComponent*)), this, SLOT (componentChangeComplete(RKComponent*)));
+	min_rows = xml->getIntAttribute (e, "min_rows", 0, DL_INFO);
+	min_rows_if_any = xml->getIntAttribute (e, "min_rows_if_any", 0, DL_INFO);
+	max_rows = xml->getIntAttribute (e, "max", INT_MAX, DL_INFO);
 
 	// create some meta properties
 	current_row = new RKComponentPropertyInt (this, false, -1);
 	row_count->setInternal (true);
-	addChild ("current_row", current_row);
+	addChild ("current_row", current_row);		// NOTE: read-write
 	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);
+	addChild ("row_count", row_count);		// NOTE: read-only
 
 	// first build the contents, as we will need to refer to the elements inside, later
 	QVBoxLayout *layout = new QVBoxLayout (this);
@@ -51,12 +56,13 @@
 	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 ());
+	contents_container = new RKComponent (this, contents_box);
+	RKComponentBuilder *builder = new RKComponentBuilder (contents_container, QDomElement ());
 	builder->buildElement (xml->getChildElement (element, "content", DL_ERROR), contents_box, false);
 #warning TOOD: do we need this? or is the per-column default good enough?
+#warning TOOD: should we wait until the (top level) plugin initial state has settled, before fetching the defaults?
 	// take a snapshot of the default state of the contents
-	container->fetchPropertyValuesRecursive (&content_defaults);
+	contents_container->fetchPropertyValuesRecursive (&content_defaults);
 
 	// create columns
 	XMLChildList options = xml->getChildElements (element, "option", DL_WARNING);
@@ -79,7 +85,8 @@
 		col_inf.restorable = restorable;
 		col_inf.governor = governor;
 #warning TODO: Do we have to wait for the parent component to settle before (re-)fetching defaults?
-		if (!governor.isEmpty ()) col_inf.default_value = fetchStringValue (governor);
+		if (e.hasAttribute ("default")) col_inf.default_value = xml->getStringAttribute (e, "default", QString (), DL_ERROR);
+		else if (!governor.isEmpty ()) col_inf.default_value = fetchStringValue (governor);
 		if (!label.isEmpty ()) {
 			col_inf.display_index = visible_columns++;
 			col_inf.column_label = label;
@@ -109,7 +116,7 @@
 		if (!ci.governor.isEmpty ()) {		// there *can* be columns without governor. This allows to connect two option-sets, e.g. on different pages of a tabbook, manually
 			// 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.
-			RKComponentBase *governor = container->lookupComponent (ci.governor, &ci.governor_modifier);
+			RKComponentBase *governor = contents_container->lookupComponent (ci.governor, &ci.governor_modifier);
 			if (governor && governor->isProperty ()) {
 				RKComponentPropertyBase *gov_prop = static_cast<RKComponentPropertyBase*> (governor);
 				if (ci.restorable) {
@@ -165,7 +172,7 @@
 void RKOptionSet::governingPropertyChanged (RKComponentPropertyBase *property) {
 	RK_TRACE (PLUGIN);
 
-	if (changing_row) return;
+	if (updating_from_storage) return;
 	updating_from_contents = true;
 
 	int row = current_row->intValue ();
@@ -195,13 +202,19 @@
 	RK_TRACE (PLUGIN);
 
 	if (updating_from_contents) return;
-
+	
 	RKComponentPropertyStringList *target = static_cast<RKComponentPropertyStringList *> (property);
+	RK_ASSERT (column_map.contains (target));
 	const ColumnInfo &inf = column_map[target];
-	if (inf.display_index >= 0) {
-		QString value = property->value (inf.display_modifier);
-		display->setItem (row, inf.display_index, new QTableWidgetItem (value));
+	if (display && (inf.display_index >= 0)) {
+		display->removeColumn (inf.display_index);
+		display->insertColumn (inf.display_index);
+		QStringList values = property->values ();
+		for (int row = 0; row < values.size (); ++row) {
+			display->setItem (row, inf.display_index, new QTableWidgetItem (values[row]));
+		}
 	}
+	if (inf.restorable) update_timer.start ();
 
 	if (target == keycolumn) {
 		QStringList new_keys = property->values ();;
@@ -215,13 +228,16 @@
 			}
 		}
 
-		if (position_changes.isEmpty () && (old_keys.size () == new_keys.size ())) return;	// no change
+		if (position_changes.isEmpty () && (old_keys.size () == new_keys.size ())) {
+			columns_which_have_been_updated_externally.clear ();
+			return;	// no change
+		}
 
 		QMap<RKComponentPropertyStringList *, ColumnInfo>::const_iterator it = column_map.constBegin ();
 		for (; it != column_map.constEnd (); ++it) {
 			RKComponentPropertyStringList* col = it.key ();
 			ColumnInfo &column = it.value ();
-			if (columns_which_have_been_updated_externally.contains (col)) {
+			if (columns_which_have_been_updated_externally.contains (col) || col == keycolumn) {
 				continue;
 			}
 
@@ -248,12 +264,56 @@
 			// strip excess length (if any), and apply
 			new_values = new_values.left (new_keys.size ());
 			col->setValues (new_values);
+			// NOTE: this will recurse into the current function, triggering an update of display and contents
 		}
+
+		columns_which_have_been_updated_externally.clear ();
+
+		int nrows = new_keys.size ();
+		row_count->setIntValue (nrows);
+		int crow = current_row->intValue ();
+		if ((crow < 0) && nrows) current_row->setIntValue (0);
+		else if (crow >= nrows) current_row->setIntValue (nrows - 1);
 	} else {
+		if (!columns_which_have_been_updated_externally.isEmpty ()) {	// add clearing timer for the first entry, only
+			update_timer.start ();		 // NOTE: only has an effect, if column is neither restorable nor shown in the display. Otherwise, an update has already been triggered
+		}
 		columns_which_have_been_updated_externally.insert (target);
-#error TODO: single shot timer to clear this list? 
 	}
-#error TODO
 }
 
-void RKOptionSet::currentRowPropertyChanged (RKComponentPropertyBase *property);
+void RKOptionSet::updateContents () {
+	RK_TRACE (PLUGIN);
+	columns_which_have_been_updated_externally.clear ();
+
+	RK_ASSERT (!updating_from_contents);
+	RK_ASSERT (!updating_from_storage);
+	updating_from_storage = true;
+
+	int row = current_row->intValue ();
+	if (row < 0) {
+		contents_container->setPropertyValuesRecursive (defaults);
+	} else {
+		QMap<RKComponentPropertyStringList *, ColumnInfo>::const_iterator it = column_map.constBegin ();
+		for (; it != column_map.constEnd (); ++it) {
+			RKComponentPropertyStringList* col = it.key ();
+			ColumnInfo &ci = it.value ();
+			if (!ci.restorable) continue;
+			RKComponentBase *governor = contents_container->lookupComponent (ci.governor);
+			if (governor) {
+				governor->setValue (col->valueAt (row));
+			} else {
+				RK_ASSERT (false);
+			}
+		}
+	}
+
+	updating_from_storage = false;
+}
+
+void RKOptionSet::currentRowPropertyChanged (RKComponentPropertyBase *property) {
+	RK_TRACE (PLUGIN);
+
+	RK_ASSERT (property == current_row);
+	update_timer.start ();
+}

Modified: trunk/rkward/rkward/plugin/rkoptionset.h
===================================================================
--- trunk/rkward/rkward/plugin/rkoptionset.h	2012-05-16 14:34:46 UTC (rev 4253)
+++ trunk/rkward/rkward/plugin/rkoptionset.h	2012-05-18 09:25:42 UTC (rev 4254)
@@ -40,7 +40,7 @@
 	void currentRowPropertyChanged (RKComponentPropertyBase *property);
 	void addRow ();
 	void removeRow (int index);
-	void componentChangeComplete (RKComponent *component);
+	void updateContents ();
 private:
 	void initDisplay ();
 
@@ -60,18 +60,19 @@
 		bool restorable;
 	};
 	QMap<RKComponentPropertyStringList *, ColumnInfo> column_map;
-	RKComponent *container;
+	RKComponent *contents_container;
 	QTableWidget *display;
 	bool display_show_index;
 	RKComponentPropertyInt *current_row;
 	RKComponentPropertyInt *row_count;
+	QTimer update_timer;
 
 	int min_rows;
 	int min_rows_if_any;
 	int max_rows;
 
 	bool updating_from_contents;
-	bool changing_row;
+	bool udpating_from_storage;
 	QSet<RKComponentPropertyStringList *> columns_which_have_been_updated_externally;
 };
 

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