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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Tue Oct 30 18:37:23 UTC 2012


Revision: 4400
          http://rkward.svn.sourceforge.net/rkward/?rev=4400&view=rev
Author:   tfry
Date:     2012-10-30 18:37:23 +0000 (Tue, 30 Oct 2012)
Log Message:
-----------
Matrix input element is basically working.
Quirks:
 - Should remove values on Backspace / Delete
 - Should move to next cell on cursor right, even when editing a cell
 - Cursor placement after expanding table
 - When columns=1, should appear slim
Missing features:
 - Cut / Copy / Paste

Modified Paths:
--------------
    trunk/rkward/rkward/plugin/rkmatrixinput.cpp
    trunk/rkward/rkward/plugin/rkmatrixinput.h
    trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
    trunk/rkward/rkward/plugins/under_development.pluginmap

Added Paths:
-----------
    trunk/rkward/rkward/plugins/testing/matrix1.js
    trunk/rkward/rkward/plugins/testing/matrix1.xml

Modified: trunk/rkward/rkward/plugin/rkmatrixinput.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkmatrixinput.cpp	2012-10-30 15:59:36 UTC (rev 4399)
+++ trunk/rkward/rkward/plugin/rkmatrixinput.cpp	2012-10-30 18:37:23 UTC (rev 4400)
@@ -49,7 +49,7 @@
 		max = xml->getIntAttribute (element, "max", INT_MAX, DL_INFO) + .1;
 	} else if (mode == Real) {
 		min = xml->getDoubleAttribute (element, "min", -FLT_MAX, DL_INFO);
-		max = xml->getDoubleAttribute (element, "min", FLT_MAX, DL_INFO);
+		max = xml->getDoubleAttribute (element, "max", FLT_MAX, DL_INFO);
 	} else {
 		min = -FLT_MAX;
 		max = FLT_MAX;
@@ -58,8 +58,8 @@
 	allow_missings = xml->getBoolAttribute (element, "allow_missings", false, DL_INFO);
 	allow_user_resize_columns = xml->getBoolAttribute (element, "allow_user_resize_columns", true, DL_INFO);
 	allow_user_resize_rows = xml->getBoolAttribute (element, "allow_user_resize_rows", true, DL_INFO);
-	trailing_rows = allow_user_resize_rows ? 1 :0;
-	trailing_columns = allow_user_resize_columns ? 1 :0;
+	trailing_rows = allow_user_resize_rows ? 1 : 0;
+	trailing_columns = allow_user_resize_columns ? 1 : 0;
 
 	row_count = new RKComponentPropertyInt (this, false, xml->getIntAttribute (element, "rows", 2, DL_INFO));
 	column_count = new RKComponentPropertyInt (this, false, xml->getIntAttribute (element, "columns", 2, DL_INFO));
@@ -76,14 +76,33 @@
 	updating_dimensions = false;
 
 	model = new RKMatrixInputModel (this);
+	QString headers = xml->getStringAttribute (element, "horiz_headers", QString (), DL_INFO);
+	if (!headers.isEmpty ()) model->horiz_header = headers.split (';');
+	headers = xml->getStringAttribute (element, "vert_headers", QString (), DL_INFO);
+	if (!headers.isEmpty ()) model->vert_header = headers.split (';');
+	updateDataAndDimensions ();
 	display->setModel (model);
 }
 
-
 RKMatrixInput::~RKMatrixInput () {
 	RK_TRACE (PLUGIN);
 }
 
+QString RKMatrixInput::value (const QString& modifier) {
+	if (modifier == "cbind") {
+		QStringList ret;
+		for (int i = 0; i < column_count->intValue (); ++i) {
+			ret.append ("\tc (" + makeColumnString (i, ", ") + ")");
+		}
+		return QString ("cbind (\n" + ret.join ("\n") + "\n)");
+	}
+
+	bool ok;
+	int col = modifier.toInt (&ok);
+	if ((col >= 0) && ok) return makeColumnString (col, "\t");
+	return tsv_data->value (modifier);
+}
+
 bool RKMatrixInput::expandStorageForColumn (int column) {
 	RK_TRACE (PLUGIN);
 
@@ -149,16 +168,16 @@
 	col.cached_tab_joined_string.clear (); // == no valid cache
 
 	updateDataAndDimensions ();
-	updateValidityFlag ();
 }
 
 void RKMatrixInput::updateValidityFlag () {
 	RK_TRACE (PLUGIN);
 
+	is_valid = true;
 	for (int i = 0; i < column_count->intValue (); ++i) {
 		if (i >= columns.size ()) {	// hit end of data, before hitting any invalid strings
 			is_valid = allow_missings;
-			return;
+			break;
 		}
 
 		Column &col = columns[i];
@@ -166,12 +185,27 @@
 		else if (allow_missings && (col.valid_up_to_row >= (col.storage.size () - 1))) continue;
 		else {
 			is_valid = false;
-			return;
+			break;
 		}
 	}
-	is_valid = true;
+	changed ();
 }
 
+QString RKMatrixInput::makeColumnString (int column, const QString& sep) {
+	RK_TRACE (PLUGIN);
+
+	QStringList storage;
+	if (column < columns.size ()) {
+		storage = columns[column].storage;
+	}
+	QString ret;
+	if (!storage.isEmpty ()) ret = QStringList (storage.mid (0, row_count->intValue ())).join (sep);
+	for (int i = storage.size (); i < row_count->intValue (); ++i) {
+		ret.append (sep);
+	}
+	return ret;
+}
+
 void RKMatrixInput::updateDataAndDimensions () {
 	RK_TRACE (PLUGIN);
 
@@ -187,7 +221,7 @@
 		if (max_row != row_count->intValue () - 1) {
 			updating_dimensions = true;
 			model->layoutAboutToBeChanged ();
-			row_count->setIntValue (max_row);
+			row_count->setIntValue (max_row + 1);
 			model->layoutChanged ();
 			updating_dimensions = false;
 		}
@@ -196,42 +230,35 @@
 	int max_col = column_count->intValue () - 1;
 	if (allow_user_resize_columns) {
 		for (max_col = columns.size () - 1; max_col >= 0; --max_col) {
-			if (columns[max_col].filled_up_to_row < 0) {
-				columns.pop_back ();
-			} else {
+			if (columns[max_col].filled_up_to_row >= 0) {
 				break;
 			}
 		}
 		if (max_col != column_count->intValue () - 1) {
 			updating_dimensions = true;
 			model->layoutAboutToBeChanged ();
-			column_count->setIntValue (max_col);
+			column_count->setIntValue (max_col + 1);
 			model->layoutChanged ();
 			updating_dimensions = false;
 		}
 	}
 
 	QStringList tsv;
-	QString empty_column (max_row, '\t');	// NOTE: *Not* max_row+1, as the number of seps is rows - 1
-	for (int i = 0; i < max_col; ++i) {
-		if (i > (columns.size () - 1)) {
-			tsv.append (empty_column);
-		} else {
-			Column& col = columns[i];
-			if (col.cached_tab_joined_string.isNull ()) {
-				QString cache = QStringList (col.storage.mid (0, max_row + 1)).join ("\t");
-				if (col.storage.size () < max_row) {
-					QString empty_trail (max_row - col.storage.size (), '\t');
-					cache.append (empty_trail);
-				}
-				col.cached_tab_joined_string = cache;
-			}
-			tsv.append (col.cached_tab_joined_string);
+	int i = 0;
+	for (; i < columns.size (); ++i) {
+		Column& col = columns[i];
+		if (col.cached_tab_joined_string.isEmpty ()) {
+			col.cached_tab_joined_string = makeColumnString (i, "\t");
 		}
+		tsv.append (col.cached_tab_joined_string);
 	}
+	for (; i < max_col; ++i) {
+		tsv.append (QString (max_row, '\t'));
+	}
 	tsv_data->setValue (tsv.join ("\n"));
 
 	updating_tsv_data = false;
+	updateValidityFlag ();
 }
 
 void RKMatrixInput::dimensionPropertyChanged (RKComponentPropertyBase *property) {
@@ -253,14 +280,15 @@
 		}
 	}
 
-	updateValidityFlag ();
+	model->layoutAboutToBeChanged ();
 	updateDataAndDimensions ();
+	model->layoutChanged ();
 }
 
 void RKMatrixInput::tsvPropertyChanged () {
 	RK_TRACE (PLUGIN);
 
-	bool old_updating_tsv_data = updating_tsv_data;
+	if (updating_tsv_data) return;
 	updating_tsv_data = true;
 
 	columns.clear ();
@@ -269,7 +297,7 @@
 		setColumnValue (i, coldata[i]);
 	}
 
-	updating_tsv_data = old_updating_tsv_data;
+	updating_tsv_data = false;
 	updateDataAndDimensions ();
 }
 
@@ -282,7 +310,7 @@
 	if (mode == Integer) {
 		val = value.toInt (&number_ok);
 	} else {
-		val = value.toDouble (&number_ok);
+		val = value.toFloat (&number_ok);
 	}
 	if (!number_ok) return false;
 	if (val < min) return false;
@@ -321,22 +349,22 @@
 
 	// handle trailing rows / cols in user expandable tables
 	bool trailing = false;
-	if (row > matrix->row_count->intValue ()) {
-		if ((!matrix->allow_user_resize_rows) || (row > matrix->row_count->intValue () + matrix->trailing_rows)) {
+	if (row >= matrix->row_count->intValue ()) {
+		if ((!matrix->allow_user_resize_rows) || (row >= matrix->row_count->intValue () + matrix->trailing_rows)) {
 			RK_ASSERT (false);
 			return QVariant ();
 		}
 		trailing = true;
 	}
-	if (column > matrix->column_count->intValue ()) {
-		if ((!matrix->allow_user_resize_columns) || (column > matrix->column_count->intValue () + matrix->trailing_columns)) {
+	if (column >= matrix->column_count->intValue ()) {
+		if ((!matrix->allow_user_resize_columns) || (column >= matrix->column_count->intValue () + matrix->trailing_columns)) {
 			RK_ASSERT (false);
 			return QVariant ();
 		}
 		trailing = true;
 	};
 	if (trailing) {
-		if (role == Qt::BackgroundRole) return QVariant (QBrush (Qt::lightGray));
+		if (role == Qt::BackgroundRole) return QVariant (QBrush (Qt::gray));
 		if (role == Qt::ToolTipRole || role == Qt::StatusTipRole) return QVariant (i18n ("Type on these cells to expand the table"));
 		return QVariant ();
 	}
@@ -357,6 +385,25 @@
 	return QVariant ();
 }
 
+Qt::ItemFlags RKMatrixInputModel::flags (const QModelIndex& index) const {
+	// handle trailing rows / cols in user expandable tables
+	if ((index.row () > matrix->row_count->intValue ()) || (index.column () > matrix->column_count->intValue ())) {
+		return (Qt::ItemIsEditable | Qt::ItemIsEnabled);
+	}
+	return (Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+}
+
+QVariant RKMatrixInputModel::headerData (int section, Qt::Orientation orientation, int role) const {
+	if (role == Qt::DisplayRole) {
+		const QStringList* list;
+		if (orientation == Qt::Horizontal) list = &horiz_header;
+		else list = &vert_header;
+		if (section < list->size ()) return QVariant ((*list)[section]);
+		return QVariant (QString::number (section + 1));
+	}
+	return QVariant ();
+}
+
 bool RKMatrixInputModel::setData (const QModelIndex& index, const QVariant& value, int role) {
 	RK_TRACE (PLUGIN);
 

Modified: trunk/rkward/rkward/plugin/rkmatrixinput.h
===================================================================
--- trunk/rkward/rkward/plugin/rkmatrixinput.h	2012-10-30 15:59:36 UTC (rev 4399)
+++ trunk/rkward/rkward/plugin/rkmatrixinput.h	2012-10-30 18:37:23 UTC (rev 4400)
@@ -69,6 +69,7 @@
 	void setColumnValue (int column, const QString& value);
 	void updateColumn (int offset, int column);
 	bool expandStorageForColumn (int column);
+	QString makeColumnString (int column, const QString& sep);
 
 	bool is_valid;
 
@@ -101,8 +102,12 @@
 	int columnCount (const QModelIndex &parent = QModelIndex()) const; // implemented for QAbstractTableModel
 	QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const; // re-implemented for QAbstractTableModel
 	bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); // re-implemented for QAbstractTableModel
+	Qt::ItemFlags flags (const QModelIndex &index) const; // re-implemented for QAbstractTableModel
+	QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;  // re-implemented for QAbstractTableModel
 
 	RKMatrixInput *matrix;
+	QStringList horiz_header;
+	QStringList vert_header;
 };
 
 #endif

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2012-10-30 15:59:36 UTC (rev 4399)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2012-10-30 18:37:23 UTC (rev 4400)
@@ -47,6 +47,7 @@
 #include "rkdropdown.h"
 #include "rkcheckbox.h"
 #include "rkpluginspinbox.h"
+#include "rkmatrixinput.h"
 #include "rkinput.h"
 #include "rkpluginbrowser.h"
 #include "rkpluginsaveobject.h"
@@ -622,6 +623,8 @@
 			widget = new RKCheckBox (e, component (), parent_widget);
 		} else if (e.tagName () == "spinbox") {
 			widget = new RKPluginSpinBox (e, component (), parent_widget);
+		} else if (e.tagName () == "matrix") {
+			widget = new RKMatrixInput (e, component (), parent_widget);
 		} else if (e.tagName () == "input") {
 			widget = new RKInput (e, component (), parent_widget);
 		} else if (e.tagName () == "browser") {

Added: trunk/rkward/rkward/plugins/testing/matrix1.js
===================================================================
--- trunk/rkward/rkward/plugins/testing/matrix1.js	                        (rev 0)
+++ trunk/rkward/rkward/plugins/testing/matrix1.js	2012-10-30 18:37:23 UTC (rev 4400)
@@ -0,0 +1,11 @@
+function calculate () {
+	echo ("Matrix A:\n");
+	echo (getValue ("matrixa.cbind"));
+	echo ("\nMatrix B:\n");
+	echo (getValue ("matrixb.cbind"));
+	echo ("\nMatrix C:\n");
+	echo (getValue ("matrixc.cbind"));
+	echo ("\nMatrix C, column 2:\n");
+	echo (getValue ("matrixc.2"));
+}
+

Added: trunk/rkward/rkward/plugins/testing/matrix1.xml
===================================================================
--- trunk/rkward/rkward/plugins/testing/matrix1.xml	                        (rev 0)
+++ trunk/rkward/rkward/plugins/testing/matrix1.xml	2012-10-30 18:37:23 UTC (rev 4400)
@@ -0,0 +1,33 @@
+<!DOCTYPE rkplugin>
+
+<document>
+	<code file="matrix1.js"/>
+
+	<logic>
+		<connect governor="c_rows.int" client="matrixc.rows"/>
+		<connect governor="c_columns.int" client="matrixc.columns"/>
+	</logic>
+
+	<dialog label="Testing Matrix input element">
+		<text id="text">
+			This plugin is bogus! Do not use!
+		</text>
+		<tabbook>
+			<tab label="User resizable matrix">
+				<matrix id="matrixa" allow_missings="false" mode="string" label="Enter data"/>
+			</tab>
+			<tab label="User resizable vector">
+				<row>
+					<matrix id="matrixb" mode="real" columns="1" allow_user_resize_columns="false" label="Enter data (0.0 .. 1.0)" min="0" max="1"/>
+					<stretch/>
+				</row>
+			</tab>
+			<tab label="Dimension controlled matrix">
+				<spinbox id="c_rows" type="integer" min="0" label="Number of rows" initial="3"/>
+				<spinbox id="c_columns" type="integer" min="0" label="Number of columns" initial="4"/>
+				<matrix id="matrixc"  allow_user_resize_columns="false"  allow_user_resize_rows="false" mode="integer" min="1" max="10" allow_missings="true" label="Enter data (integer 1 to 10 or missing)"/>
+			</tab>
+		</tabbook>
+	</dialog>
+
+</document> 

Modified: trunk/rkward/rkward/plugins/under_development.pluginmap
===================================================================
--- trunk/rkward/rkward/plugins/under_development.pluginmap	2012-10-30 15:59:36 UTC (rev 4399)
+++ trunk/rkward/rkward/plugins/under_development.pluginmap	2012-10-30 18:37:23 UTC (rev 4400)
@@ -10,6 +10,7 @@
 		<component type="standard" id="qtscript_test1" file="testing/test1.xml" label="QtScript Test 1" />
 		<component type="standard" id="qtscript_test2" file="testing/test2.xml" label="QtScript Test 2" />
 		<component type="standard" id="optionset_test" file="testing/optionset.xml" label="Optionset Test" />
+		<component type="standard" id="matrix_test1" file="testing/matrix1.xml" label="Input Matrix Test" />
 <!-- End -->
 
 		<component type="standard" id="import_xls" file="00saveload/import/import_xls.xml" label="Import MS EXCEL">
@@ -36,6 +37,7 @@
 			<entry component="simple_anova" index="9"/>
 			<entry component="qtscript_test1" index="1"/>
 			<entry component="optionset_test" index="1"/>
+			<entry component="matrix_test1" index="1"/>
 		</menu>
 		<menu id="plots" label="Plots" index="5">
 			<entry component="sieve_plot" />

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