Browse Source

Improve excess row handling in new batch window

Neal Wilson 10 years ago
parent
commit
3c471ec307
2 changed files with 164 additions and 5 deletions
  1. 16
    1
      config/Windows/newbatch.xml
  2. 148
    4
      src/typica.w

+ 16
- 1
config/Windows/newbatch.xml View File

@@ -21,7 +21,7 @@
21 21
         </layout>
22 22
         <label>Green Coffee:</label>
23 23
         <sqltablearray columns="2" id="greens">
24
-            <column name="Coffee" delegate="sql" showdata="true" null="false" data="0" display="1">SELECT id, name FROM coffees WHERE quantity &lt;&gt; 0 ORDER BY name</column>
24
+            <column name="Coffee" delegate="sql" showdata="true" null="true" nulltext="Delete" nulldata="delete" data="0" display="1">SELECT id, name FROM coffees WHERE quantity &lt;&gt; 0 ORDER BY name</column>
25 25
             <column name="Weight" />
26 26
         </sqltablearray>
27 27
         <layout type="horizontal">
@@ -119,6 +119,20 @@
119 119
 				}
120 120
 			}
121 121
 			model.dataChanged.connect(function() {
122
+				var deleteRow = -1;
123
+				/* The combo box delegate updates user data before display data
124
+				   and this code is executed before the model update is fully
125
+				   complete. Rather than rely on this behavior continuing, we
126
+				   check that the display value has also been updated and defer
127
+				   row removal until both updates are complete.
128
+				*/
129
+				while((deleteRow = table.findData("delete", 0)) > -1) {
130
+					if(table.data(deleteRow, 0, 0) == "Delete") {
131
+						table.removeRow(table.findData("delete", 0));
132
+					} else {
133
+						break;
134
+					}
135
+				}
122 136
 				green.text = table.columnSum(1, 0);
123 137
 				table.resizeColumnToContents(0);
124 138
                 if(parseFloat(green.text) > 0)
@@ -160,6 +174,7 @@
160 174
             var profilebutton = findChildObject(this, 'load');
161 175
             profilebutton.setEnabled(false);
162 176
             roasted['currentIndexChanged(int)'].connect(function() {
177
+				table.clear();
163 178
                 var query = new QSqlQuery();
164 179
                 var q = "SELECT EXISTS(SELECT 1 FROM item_files WHERE item = ";
165 180
                 q = q + roasted.currentData();

+ 148
- 4
src/typica.w View File

@@ -5114,6 +5114,14 @@ of presenting a human readable list of choices.
5114 5114
 @<Assign column delegate from SQL@>=
5115 5115
 SqlComboBoxDelegate *delegate = new SqlComboBoxDelegate;
5116 5116
 SqlComboBox *widget = new SqlComboBox();
5117
+if(currentElement.hasAttribute("nulltext"))
5118
+{
5119
+	widget->setNullText(currentElement.attribute("nulltext"));
5120
+}
5121
+if(currentElement.hasAttribute("nulldata"))
5122
+{
5123
+	widget->setNullData(QVariant(currentElement.attribute("nulldata")));
5124
+}
5117 5125
 if(currentElement.hasAttribute("null"))
5118 5126
 {
5119 5127
 	if(currentElement.attribute("null") == "true")
@@ -5567,6 +5575,9 @@ QScriptValue SaltTable_model(QScriptContext *context, QScriptEngine *engine);
5567 5575
 QScriptValue SaltTable_quotedColumnArray(QScriptContext *context,
5568 5576
                                          QScriptEngine *engine);
5569 5577
 QScriptValue SaltTable_setData(QScriptContext *context, QScriptEngine *engine);
5578
+QScriptValue SaltTable_clear(QScriptContext *context, QScriptEngine *engine);
5579
+QScriptValue SaltTable_removeRow(QScriptContext *context, QScriptEngine *engine);
5580
+QScriptValue SaltTable_findData(QScriptContext *context, QScriptEngine *engine);
5570 5581
 
5571 5582
 @ There are times when it is useful to obtain the sum of values in a column of
5572 5583
 a SaltTable object. For example, when a column represents the weight of the
@@ -5697,6 +5708,46 @@ QScriptValue SaltTable_data(QScriptContext *context, QScriptEngine *engine)
5697 5708
 	return retval;
5698 5709
 }
5699 5710
 
5711
+@ There are times when it is useful to clear the content of a table. This is
5712
+used, for example, in the green coffees table after changing the roasted coffee
5713
+item to eliminate excess rows in the case where the previously selected item
5714
+was a pre-roast blend.
5715
+
5716
+@<Functions for scripting@>=
5717
+QScriptValue SaltTable_clear(QScriptContext *context, QScriptEngine *)
5718
+{
5719
+	QTableView *self = getself<QTableView *>(context);
5720
+	SaltModel *model = qobject_cast<SaltModel *>(self->model());
5721
+	model->clear();
5722
+	return QScriptValue();
5723
+}
5724
+
5725
+@ It is sometimes useful to remove a row from a table. This is done in the new
5726
+batch window when the coffee for a row is set to a NULL item.
5727
+
5728
+@<Functions for scripting@>=
5729
+QScriptValue SaltTable_removeRow(QScriptContext *context, QScriptEngine *engine)
5730
+{
5731
+	QTableView *self = getself<QTableView *>(context);
5732
+	SaltModel *model = qobject_cast<SaltModel *>(self->model());
5733
+	int row = argument<int>(0, context);
5734
+	return engine->newVariant(model->removeRow(row));
5735
+}
5736
+
5737
+@ To remove the correct row, it is sometimes useful to query the table for
5738
+special values. This is done with the |findData()| method on the underlying
5739
+model.
5740
+
5741
+@<Functions for scripting@>=
5742
+QScriptValue SaltTable_findData(QScriptContext *context, QScriptEngine *engine)
5743
+{
5744
+	QTableView *self = getself<QTableView *>(context);
5745
+	SaltModel *model = qobject_cast<SaltModel *>(self->model());
5746
+	QVariant value = argument<QVariant>(0, context);
5747
+	int column = argument<int>(1, context);
5748
+	return engine->newVariant(model->findData(value, column));
5749
+}
5750
+
5700 5751
 @ These functions need to be added as properties of the table when it is passed
5701 5752
 to the host environment.
5702 5753
 
@@ -5716,6 +5767,9 @@ void setSaltTableProperties(QScriptValue value, QScriptEngine *engine)
5716 5767
 	value.setProperty("data", engine->newFunction(SaltTable_data));
5717 5768
 	value.setProperty("model", engine->newFunction(SaltTable_model));
5718 5769
 	value.setProperty("setData", engine->newFunction(SaltTable_setData));
5770
+	value.setProperty("clear", engine->newFunction(SaltTable_clear));
5771
+	value.setProperty("removeRow", engine->newFunction(SaltTable_removeRow));
5772
+	value.setProperty("findData", engine->newFunction(SaltTable_findData));
5719 5773
 }
5720 5774
 
5721 5775
 @ The |SqlComboBox| is another class that is not constructed from scripts but is
@@ -11896,6 +11950,10 @@ class SaltModel : public QAbstractItemModel@/
11896 11950
 		QModelIndex parent(const QModelIndex &index) const;
11897 11951
 		QString arrayLiteral(int column, int role) const;
11898 11952
 		QString quotedArrayLiteral(int column, int role) const;
11953
+		void clear();
11954
+		bool removeRows(int row, int count,
11955
+		                const QModelIndex &parent = QModelIndex());
11956
+		int findData(const QVariant &value, int column, int role = Qt::UserRole);
11899 11957
 };
11900 11958
 
11901 11959
 @ The only unique methods in this class are the |arrayLiteral| and
@@ -12166,6 +12224,74 @@ QModelIndex SaltModel::index(int row, int column,
12166 12224
 	return QModelIndex();
12167 12225
 }
12168 12226
 
12227
+@ There are some times when it is useful to clear the model data. Note that
12228
+column header data is retained and the table will contain a single empty row
12229
+after this method is called.
12230
+
12231
+@<SaltModel Implementation@>=
12232
+void SaltModel::clear()
12233
+{
12234
+	beginResetModel();
12235
+	modelData.clear();
12236
+	@<Expand the SaltModel@>@;
12237
+	endResetModel();
12238
+}
12239
+
12240
+@ Another commonly useful operation is the ability to remove rows from the
12241
+model. The new batch window uses this feature to eliminate rows in which the
12242
+coffee is set to NULL. Note that if all rows of the model are removed, a new
12243
+empty row will be created.
12244
+
12245
+@<SaltModel Implementation@>=
12246
+bool SaltModel::removeRows(int row, int count,
12247
+                           const QModelIndex &parent)
12248
+{
12249
+	if(parent == QModelIndex())
12250
+	{
12251
+		if(row >= 0 && count > 0 && (row + count - 1) < modelData.size())
12252
+		{
12253
+			beginRemoveRows(parent, row, row + count - 1);
12254
+			for(int i = 0; i < count; i++)
12255
+			{
12256
+				modelData.removeAt(row);
12257
+			}
12258
+			endRemoveRows();
12259
+			if(modelData.size() == 0)
12260
+			{
12261
+				beginInsertRows(parent, 0, 0);
12262
+				@<Expand the SaltModel@>@;
12263
+				endInsertRows();
12264
+			}
12265
+			return true;
12266
+		}
12267
+	}
12268
+	return false;
12269
+}
12270
+
12271
+@ To find the row number for removal operations it is useful to search for
12272
+special values on a given role. The |findData()| method returns the first row
12273
+in which the given value matches for a particular column and a particular role
12274
+or |-1| if no such match exists.
12275
+
12276
+@<SaltModel Implementation@>=
12277
+int SaltModel::findData(const QVariant &value, int column, int role)
12278
+{
12279
+	for(int i = 0; i < modelData.size(); i++)
12280
+	{
12281
+		if(modelData.at(i).size() > column)
12282
+		{
12283
+			if(modelData.at(i).at(column).contains(role))
12284
+			{
12285
+				if(modelData.at(i).at(column).value(role) == value)
12286
+				{
12287
+					return i;
12288
+				}
12289
+			}
12290
+		}
12291
+	}
12292
+	return -1;
12293
+}
12294
+
12169 12295
 @* A Delegate for SQL Relations.
12170 12296
 
12171 12297
 \noindent The first column of the table view being described is responsible for
@@ -12191,6 +12317,8 @@ class SqlComboBox : public QComboBox@/
12191 12317
 	int dataColumn;
12192 12318
 	int displayColumn;
12193 12319
 	bool dataColumnShown;
12320
+	QString specialNullText;
12321
+	QVariant specialNullData;
12194 12322
 	public:@/
12195 12323
 		SqlComboBox();
12196 12324
 		~SqlComboBox();
@@ -12200,7 +12328,9 @@ class SqlComboBox : public QComboBox@/
12200 12328
 		void addSqlOptions(QString query);
12201 12329
 		void setDataColumn(int column);
12202 12330
 		void setDisplayColumn(int column);
12203
-		void showData(bool show);@t\2@>@/
12331
+		void showData(bool show);
12332
+		void setNullText(QString nullText);
12333
+		void setNullData(QVariant nullData);@t\2@>@/
12204 12334
 }@t\kern-3pt@>;
12205 12335
 
12206 12336
 @ In order to make this class work a little more nicely as an item delegate,
@@ -12233,12 +12363,25 @@ void SqlComboBox::showData(bool show)
12233 12363
 @ Next, there is a need to know if the NULL value may legally be selected. Where
12234 12364
 this is the case, we generally want this to be inserted first. As the
12235 12365
 |QComboBox| supports storing both display and user data, much of the code is a
12236
-thin wrapper around calls to the base class.
12366
+thin wrapper around calls to the base class. The text and data for the NULL
12367
+value can be set arbitrarily, which can be useful in certain cases. Note that
12368
+any customization of the NULL text or data must be set before a call to
12369
+|addNullOption()|.
12237 12370
 
12238 12371
 @<SqlComboBox Implementation@>=
12239 12372
 void SqlComboBox::addNullOption()
12240 12373
 {
12241
-	addItem(tr("Unknown"), QVariant(QVariant::String));
12374
+	addItem(specialNullText, specialNullData);
12375
+}
12376
+
12377
+void SqlComboBox::setNullText(QString nullText)
12378
+{
12379
+	specialNullText = nullText;
12380
+}
12381
+
12382
+void SqlComboBox::setNullData(QVariant nullData)
12383
+{
12384
+	specialNullData = nullData;
12242 12385
 }
12243 12386
 
12244 12387
 @ Typically, the SQL query used to populate this widget will request two columns
@@ -12300,7 +12443,8 @@ The destructor is trivial.
12300 12443
 
12301 12444
 @<SqlComboBox Implementation@>=
12302 12445
 SqlComboBox::SqlComboBox() :
12303
-	dataColumn(0), displayColumn(0), dataColumnShown(false)
12446
+	dataColumn(0), displayColumn(0), dataColumnShown(false),
12447
+	specialNullText(tr("Unknown")), specialNullData(QVariant::String)
12304 12448
 {
12305 12449
 	view()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
12306 12450
 }

Loading…
Cancel
Save