[rkward-cvs] SF.net SVN: rkward:[4396] trunk/rkward/rkward/plugin
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Tue Oct 30 12:09:07 UTC 2012
Revision: 4396
http://rkward.svn.sourceforge.net/rkward/?rev=4396&view=rev
Author: tfry
Date: 2012-10-30 12:09:06 +0000 (Tue, 30 Oct 2012)
Log Message:
-----------
Matrix input element mostly finished (in theory)
Modified Paths:
--------------
trunk/rkward/rkward/plugin/rkmatrixinput.cpp
trunk/rkward/rkward/plugin/rkmatrixinput.h
Modified: trunk/rkward/rkward/plugin/rkmatrixinput.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkmatrixinput.cpp 2012-10-27 13:50:50 UTC (rev 4395)
+++ trunk/rkward/rkward/plugin/rkmatrixinput.cpp 2012-10-30 12:09:06 UTC (rev 4396)
@@ -67,8 +67,8 @@
column_count->setInternal (true);
addChild (column_count);
addChild (tsv_data);
- connect (row_count, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (dimensionPropertyChanged()));
- connect (column_count, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (dimensionPropertyChanged()));
+ connect (row_count, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (dimensionPropertyChanged(RKComponentPropertyBase*)));
+ connect (column_count, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (dimensionPropertyChanged(RKComponentPropertyBase*)));
connect (tsv_data, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (tsvPropertyChanged()));
updating_tsv_data = false;
updating_dimensions = false;
@@ -97,16 +97,17 @@
int row = index.row ();
int column = index.column ();
+ // handle trailing rows / cols in user expandable tables
bool trailing = false;
if (row > row_count->intValue ()) {
- if ((!allow_user_resize_rows) || (row > row_count->intValue () + TRAILING_ROWS)) {
+ if ((!allow_user_resize_rows) || (row > row_count->intValue () + trailing_rows)) {
RK_ASSERT (false);
return QVariant ();
}
trailing = true;
}
if (column > column_count->intValue ()) {
- if ((!allow_user_resize_columns) || (column > column_count->intValue () + TRAILING_COLS)) {
+ if ((!allow_user_resize_columns) || (column > column_count->intValue () + trailing_columns)) {
RK_ASSERT (false);
return QVariant ();
}
@@ -117,10 +118,232 @@
if (role == Qt::ToolTipRole || role == Qt::StatusTipRole) return QVariant (i18n ("Type on these cells to expand the table"));
return QVariant ();
}
-#error TODO
+
+ // regular cells
+ QString value;
+ if (columns.size () > column) { // column >= columns.size() can happen, legally. In this case the value is simply missing.
+ value = columns[column].storage.value (row);
+ }
+ if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) {
+ return QVariant (value);
+ } else if (role == Qt::BackgroundRole) {
+ if (!is_valid && (value.isEmpty () && !allow_missings) || !isValueValid (value)) return QVariant (QBrush (Qt::red));
+ } else if ((role == Qt::ToolTipRole) || (role == Qt::StatusTipRole)) {
+ if (!is_valid && (value.isEmpty () && !allow_missings)) return QVariant (i18n ("Empty values are not allowed"));
+ if (!is_valid && !isValueValid (value)) return QVariant (i18n ("This value is not allowed, here"));
+ }
+ return QVariant ();
}
+bool RKMatrixInput::setData (const QModelIndex& index, const QVariant& value, int role) {
+ RK_TRACE (PLUGIN);
+ if (!index.isValid ()) return false;
+ if (role != Qt::EditRole) return false;
+ setCellValue (index.row (), index.column (), value.toString ());
+ return true;
+}
+
+bool RKMatrixInput::expandStorageForColumn (int column) {
+ RK_TRACE (PLUGIN);
+
+ if ((column < 0) || (column >= (column_count->intValue () + trailing_columns))) {
+ RK_ASSERT (false);
+ return false;
+ }
+
+ while (column >= columns.size ()) {
+ Column col;
+ col.valid_up_to_row = -1;
+ col.filled_up_to_row = -1;
+ columns.append (col);
+ }
+ return true;
+}
+
+void RKMatrixInput::setCellValue (int row, int column, const QString& value) {
+ RK_TRACE (PLUGIN);
+
+ if ((!expandStorageForColumn (column)) || (row < 0) || (row >= (row_count->intValue () + trailing_rows))) {
+ RK_ASSERT (false);
+ return;
+ }
+
+ Column &col = columns[col];
+ while (row >= col.storage.size ()) {
+ col.storage.append (QString ());
+ }
+ col.storage[row] = value;
+ updateColumn (row, column);
+}
+
+void RKMatrixInput::setColumnValue (int column, const QString& value) {
+ RK_TRACE (PLUGIN);
+
+ if (!expandStorageForColumn (column)) return;
+ columns[column].storage = value.split ('\t', QString::KeepEmptyParts);
+ updateColumn (0, column);
+}
+
+void RKMatrixInput::updateColumn (int offset, int column) {
+ RK_TRACE (PLUGIN);
+ RK_ASSERT ((column >= 0) && (column < columns.size ()));
+
+ Column &col = columns[column];
+
+ // check for trailing empty rows:
+ int last_row = col.storage.size () - 1;
+ while ((last_row >= 0) && col.storage[last_row].isEmpty ()) {
+ --last_row;
+ }
+ col.filled_up_to_row = last_row;
+
+ offset = qMax (0, qMin (offset, col.valid_up_to_row));
+ while (offset < col.storage.size ()) {
+ if (!isValueValid (col.storage[offset])) break;
+ offset++;
+ }
+ col.valid_up_to_row = offset - 1;
+ col.cached_tab_joined_string.clear (); // == no valid cache
+
+ updateDataAndDimensions ();
+ updateValidityFlag ();
+}
+
+void RKMatrixInput::updateValidityFlag () {
+ RK_TRACE (PLUGIN);
+
+ 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;
+ }
+
+ Column &col = columns[i];
+ if (col.valid_up_to_row >= (row_count->intValue () - 1)) continue;
+ else if (allow_missings && (col.valid_up_to_row >= (col.storage.size () - 1))) continue;
+ else {
+ is_valid = false;
+ return;
+ }
+ }
+ is_valid = true;
+}
+
+void RKMatrixInput::updateDataAndDimensions () {
+ RK_TRACE (PLUGIN);
+
+ if (updating_tsv_data) return;
+ updating_tsv_data = true;
+
+ int max_row = row_count->intValue () - 1;
+ if (allow_user_resize_rows) {
+ max_row = -1;
+ for (int i = columns.size () - 1; i >= 0; --i) {
+ max_row = qMax (max_row, columns[i].filled_up_to_row);
+ }
+ if (max_row != row_count->intValue () - 1) {
+ updating_dimensions = true;
+ row_count->setIntValue (max_row);
+ updating_dimensions = false;
+ }
+ }
+
+ 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 {
+ break;
+ }
+ }
+ if (max_col != column_count->intValue () - 1) {
+ updating_dimensions = true;
+ column_count->setIntValue (max_col);
+ 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 = 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);
+ }
+ }
+ tsv_data->setValue (tsv);
+
+ updating_tsv_data = false;
+}
+
+void RKMatrixInput::dimensionPropertyChanged (RKComponentPropertyBase *property) {
+ RK_TRACE (PLUGIN);
+
+ if (updating_dimensions) return;
+ if (allow_user_resize_rows && (property == row_count)) {
+ RK_ASSERT (false);
+ return;
+ }
+ if (allow_user_resize_columns && (property == column_count)) {
+ RK_ASSERT (false);
+ return;
+ }
+
+ if (property == row_count) { // invalidates column caches
+ for (int i = columns.size () - 1; i >= 0; --i) {
+ columns[i].cached_tab_joined_string.clear ();
+ }
+ }
+
+ updateValidityFlag ();
+ updateDataAndDimensions ();
+}
+
+void RKMatrixInput::tsvPropertyChanged () {
+ RK_TRACE (PLUGIN);
+
+ bool old_updating_tsv_data = updating_tsv_data;
+ updating_tsv_data = true;
+
+ columns.clear ();
+ QStringList coldata = tsv_data->value ().split ('\n', QString::KeepEmptyParts);
+ for (int i = 0; i < coldata.size (); ++i) {
+ setColumnValue (i, coldata[i]);
+ }
+
+ updating_tsv_data = old_updating_tsv_data;
+ updateDataAndDimensions ();
+}
+
+bool RKMatrixInput::isValueValid (const QString& value) const {
+ if (mode == String) return true;
+ if (value.isEmpty ()) return allow_missings;
+
+ bool number_ok;
+ double val;
+ if (mode == Integer) {
+ val = value.toInt (&number_ok);
+ } else {
+ val = value.toDouble (&number_ok);
+ }
+ if (!number_ok) return false;
+ if (val < min) return false;
+ return (val < max);
+}
+
#error TODO
+#error TODO signal model layout and data changes
#include "rkmatrixinput.moc"
Modified: trunk/rkward/rkward/plugin/rkmatrixinput.h
===================================================================
--- trunk/rkward/rkward/plugin/rkmatrixinput.h 2012-10-27 13:50:50 UTC (rev 4395)
+++ trunk/rkward/rkward/plugin/rkmatrixinput.h 2012-10-30 12:09:06 UTC (rev 4396)
@@ -22,6 +22,7 @@
#include <QAbstractTableModel>
#include <QDomElement>
+#include <QStringList>
class QTableView;
@@ -37,7 +38,7 @@
bool isValid () { return is_valid; };
QString value (const QString &modifier);
private slots:
- void dimensionPropertyChanged ();
+ void dimensionPropertyChanged (RKComponentPropertyBase *property);
void tsvPropertyChanged ();
private:
RKComponentPropertyInt *row_count;
@@ -66,10 +67,12 @@
bool isValueValid (const QString &value) const;
void updateValidityFlag ();
+ void updateDataAndDimensions ();
- bool setCellValue (int row, int column, const QString& value);
- bool setColumnValue (int column, const QString& value);
- bool setTableValue (const QString& value);
+ void setCellValue (int row, int column, const QString& value);
+ void setColumnValue (int column, const QString& value);
+ void updateColumn (int offset, int column);
+ bool expandStorageForColumn (int column);
bool is_valid;
@@ -77,6 +80,7 @@
// lost, if a user shrinks a table, accidentally, then re-grows it.
struct Column {
int valid_up_to_row; // to save validizing the entire table on each change, we keep track of validity per column
+ int filled_up_to_row;
QStringList storage;
QString cached_tab_joined_string;
};
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