|
@@ -2256,6 +2256,7 @@ QScriptValue constructXQuery(QScriptContext *context, QScriptEngine *engine);
|
2256
|
2256
|
QScriptValue XQuery_bind(QScriptContext *context, QScriptEngine *engine);
|
2257
|
2257
|
QScriptValue XQuery_exec(QScriptContext *context, QScriptEngine *engine);
|
2258
|
2258
|
QScriptValue XQuery_setQuery(QScriptContext *context, QScriptEngine *engine);
|
|
2259
|
+QScriptValue XQuery_invalidate(QScriptContext *context, QScriptEngine *engine);
|
2259
|
2260
|
void setXQueryProperties(QScriptValue value, QScriptEngine *engine);
|
2260
|
2261
|
|
2261
|
2262
|
@ The constructor must be registered with the host environment. This is done a
|
|
@@ -2266,7 +2267,7 @@ constructor = engine->newFunction(constructXQuery);
|
2266
|
2267
|
engine->globalObject().setProperty("XQuery", constructor);
|
2267
|
2268
|
|
2268
|
2269
|
@ The constructor just needs to make sure the functions we want to make
|
2269
|
|
-available are applied.
|
|
2270
|
+available are applied. A method is also provided to free the |QXmlQuery|.
|
2270
|
2271
|
|
2271
|
2272
|
@<Functions for scripting@>=
|
2272
|
2273
|
QScriptValue constructXQuery(QScriptContext *, QScriptEngine *engine)
|
|
@@ -2276,11 +2277,19 @@ QScriptValue constructXQuery(QScriptContext *, QScriptEngine *engine)
|
2276
|
2277
|
return object;
|
2277
|
2278
|
}
|
2278
|
2279
|
|
|
2280
|
+QScriptValue XQuery_invalidate(QScriptContext *context, QScriptEngine *)
|
|
2281
|
+{
|
|
2282
|
+ QXmlQuery *self = getself<QXmlQuery *>(context);
|
|
2283
|
+ delete self;
|
|
2284
|
+ return QScriptValue();
|
|
2285
|
+}
|
|
2286
|
+
|
2279
|
2287
|
void setXQueryProperties(QScriptValue value, QScriptEngine *engine)
|
2280
|
2288
|
{
|
2281
|
2289
|
value.setProperty("bind", engine->newFunction(XQuery_bind));
|
2282
|
2290
|
value.setProperty("exec", engine->newFunction(XQuery_exec));
|
2283
|
2291
|
value.setProperty("setQuery", engine->newFunction(XQuery_setQuery));
|
|
2292
|
+ value.setProperty("invalidate", engine->newFunction(XQuery_invalidate));
|
2284
|
2293
|
}
|
2285
|
2294
|
|
2286
|
2295
|
@ The |bind()| property can be used to specify a |QIODevice| to be referenced by
|
|
@@ -3369,7 +3378,7 @@ class SqlQueryConnection : public QSqlQuery@/
|
3369
|
3378
|
public:@/
|
3370
|
3379
|
SqlQueryConnection(const QString &query = QString());
|
3371
|
3380
|
~SqlQueryConnection();
|
3372
|
|
- QSqlQuery* operator->();
|
|
3381
|
+ QSqlQuery* operator->() const;
|
3373
|
3382
|
private:@/
|
3374
|
3383
|
QString connection;
|
3375
|
3384
|
QSqlQuery *q;
|
|
@@ -3409,7 +3418,7 @@ SqlQueryConnection::~SqlQueryConnection()
|
3409
|
3418
|
object.
|
3410
|
3419
|
|
3411
|
3420
|
@<SqlQueryConnection implementation@>=
|
3412
|
|
-QSqlQuery* SqlQueryConnection::operator->()
|
|
3421
|
+QSqlQuery* SqlQueryConnection::operator->() const
|
3413
|
3422
|
{
|
3414
|
3423
|
return q;
|
3415
|
3424
|
}
|
|
@@ -3448,8 +3457,9 @@ value.
|
3448
|
3457
|
@<Functions for scripting@>=
|
3449
|
3458
|
QScriptValue constructQSqlQuery(QScriptContext *, QScriptEngine *engine)
|
3450
|
3459
|
{
|
|
3460
|
+ SqlQueryConnection *obj = new SqlQueryConnection();
|
3451
|
3461
|
QScriptValue object =
|
3452
|
|
- engine->toScriptValue<void *>(new SqlQueryConnection());
|
|
3462
|
+ engine->toScriptValue<void *>(obj);
|
3453
|
3463
|
setQSqlQueryProperties(object, engine);
|
3454
|
3464
|
return object;
|
3455
|
3465
|
}
|
|
@@ -3478,40 +3488,40 @@ void setQSqlQueryProperties(QScriptValue value, QScriptEngine *engine)
|
3478
|
3488
|
@<Functions for scripting@>=
|
3479
|
3489
|
QScriptValue QSqlQuery_exec(QScriptContext *context, QScriptEngine *engine)
|
3480
|
3490
|
{
|
3481
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3491
|
+ QSqlQuery *q = getself<SqlQueryConnection *>(context)->operator->();
|
3482
|
3492
|
QScriptValue retval;
|
3483
|
3493
|
if(context->argumentCount() == 1)
|
3484
|
3494
|
{
|
3485
|
3495
|
retval = QScriptValue(engine,
|
3486
|
|
- query->exec(argument<QString>(0, context)));
|
|
3496
|
+ q->exec(argument<QString>(0, context)));
|
3487
|
3497
|
}
|
3488
|
3498
|
else
|
3489
|
3499
|
{
|
3490
|
|
- retval = QScriptValue(engine, query->exec());
|
|
3500
|
+ retval = QScriptValue(engine, q->exec());
|
3491
|
3501
|
}
|
3492
|
|
- if(query->lastError().isValid())
|
|
3502
|
+ if(q->lastError().isValid())
|
3493
|
3503
|
{
|
3494
|
|
- qDebug() << query->lastQuery();
|
3495
|
|
- qDebug() << query->lastError().text();
|
|
3504
|
+ qDebug() << q->lastQuery();
|
|
3505
|
+ qDebug() << q->lastError().text();
|
3496
|
3506
|
}
|
3497
|
3507
|
return retval;
|
3498
|
3508
|
}
|
3499
|
3509
|
|
3500
|
3510
|
QScriptValue QSqlQuery_executedQuery(QScriptContext *context, QScriptEngine *)
|
3501
|
3511
|
{
|
3502
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3512
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3503
|
3513
|
return QScriptValue(query->lastQuery());
|
3504
|
3514
|
}
|
3505
|
3515
|
|
3506
|
3516
|
QScriptValue QSqlQuery_next(QScriptContext *context, QScriptEngine *engine)
|
3507
|
3517
|
{
|
3508
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3518
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3509
|
3519
|
return QScriptValue(engine, query->next());
|
3510
|
3520
|
}
|
3511
|
3521
|
|
3512
|
3522
|
QScriptValue QSqlQuery_value(QScriptContext *context, QScriptEngine *engine)
|
3513
|
3523
|
{
|
3514
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3524
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3515
|
3525
|
return QScriptValue(engine,
|
3516
|
3526
|
query->value(argument<int>(0, context)).toString());
|
3517
|
3527
|
}
|
|
@@ -3522,13 +3532,13 @@ data available in a named file, or data from any open |QIODevice|.
|
3522
|
3532
|
@<Functions for scripting@>=
|
3523
|
3533
|
QScriptValue QSqlQuery_prepare(QScriptContext *context, QScriptEngine *engine)
|
3524
|
3534
|
{
|
3525
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3535
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3526
|
3536
|
return QScriptValue(engine, query->prepare(argument<QString>(0, context)));
|
3527
|
3537
|
}
|
3528
|
3538
|
|
3529
|
3539
|
QScriptValue QSqlQuery_bind(QScriptContext *context, QScriptEngine *)
|
3530
|
3540
|
{
|
3531
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3541
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3532
|
3542
|
query->bindValue(argument<QString>(0, context),
|
3533
|
3543
|
argument<QVariant>(1, context));
|
3534
|
3544
|
return QScriptValue();
|
|
@@ -3537,7 +3547,7 @@ QScriptValue QSqlQuery_bind(QScriptContext *context, QScriptEngine *)
|
3537
|
3547
|
QScriptValue QSqlQuery_bindFileData(QScriptContext *context,
|
3538
|
3548
|
QScriptEngine *)
|
3539
|
3549
|
{
|
3540
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3550
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3541
|
3551
|
QString placeholder = argument<QString>(0, context);
|
3542
|
3552
|
QString filename = argument<QString>(1, context);
|
3543
|
3553
|
QFile file(filename);
|
|
@@ -3554,7 +3564,7 @@ QScriptValue QSqlQuery_bindFileData(QScriptContext *context,
|
3554
|
3564
|
QScriptValue QSqlQuery_bindDeviceData(QScriptContext *context,
|
3555
|
3565
|
QScriptEngine *)
|
3556
|
3566
|
{
|
3557
|
|
- SqlQueryConnection *query = getself<SqlQueryConnection *>(context);
|
|
3567
|
+ QSqlQuery *query = getself<SqlQueryConnection *>(context)->operator->();
|
3558
|
3568
|
QString placeholder = argument<QString>(0, context);
|
3559
|
3569
|
QIODevice *device = argument<QIODevice *>(1, context);
|
3560
|
3570
|
device->reset();
|
|
@@ -3680,13 +3690,14 @@ host environment. The function is now depreciated and should not be used.
|
3680
|
3690
|
@<Functions for scripting@>=
|
3681
|
3691
|
QScriptValue annotationFromRecord(QScriptContext *context, QScriptEngine *)
|
3682
|
3692
|
{
|
3683
|
|
- SqlQueryConnection query;
|
|
3693
|
+ SqlQueryConnection h;
|
|
3694
|
+ QSqlQuery *query = h.operator->();
|
3684
|
3695
|
QString q = "SELECT file FROM files WHERE id = :file";
|
3685
|
|
- query.prepare(q);
|
3686
|
|
- query.bindValue(":file", argument<int>(0, context));
|
3687
|
|
- query.exec();
|
3688
|
|
- query.next();
|
3689
|
|
- QByteArray array = query.value(0).toByteArray();
|
|
3696
|
+ query->prepare(q);
|
|
3697
|
+ query->bindValue(":file", argument<int>(0, context));
|
|
3698
|
+ query->exec();
|
|
3699
|
+ query->next();
|
|
3700
|
+ QByteArray array = query->value(0).toByteArray();
|
3690
|
3701
|
QBuffer buffer(&array);
|
3691
|
3702
|
buffer.open(QIODevice::ReadOnly);
|
3692
|
3703
|
QXmlQuery xquery;
|
|
@@ -3866,12 +3877,16 @@ any {\tt <program>} elements that are immediate children of the
|
3866
|
3877
|
{\tt <window>} element into a window displayed on screen, the script in the
|
3867
|
3878
|
{\tt <program>} elements must call a function to display a specified window.
|
3868
|
3879
|
|
|
3880
|
+Report windows can be produced by scripts in a similar, but slightly different
|
|
3881
|
+manner.
|
|
3882
|
+
|
3869
|
3883
|
\danger This design works, but it'@q'@>s not particularly good design. It was written
|
3870
|
3884
|
under severe time constraints and should be redesigned or at least cleaned up
|
3871
|
3885
|
and reorganized.\endanger
|
3872
|
3886
|
|
3873
|
3887
|
@<Function prototypes for scripting@>=
|
3874
|
3888
|
QScriptValue createWindow(QScriptContext *context, QScriptEngine *engine);
|
|
3889
|
+QScriptValue createReport(QScriptContext *context, QScriptEngine *engine);
|
3875
|
3890
|
void addLayoutToWidget(QDomElement element, QStack<QWidget*> *widgetStack,
|
3876
|
3891
|
QStack<QLayout*> *layoutStack);
|
3877
|
3892
|
void addLayoutToLayout(QDomElement element, QStack<QWidget *> *widgetStack,
|
|
@@ -3931,12 +3946,14 @@ void addCalendarToLayout(QDomElement element, QStack<QWidget *> *widgetStack,
|
3931
|
3946
|
void addSpinBoxToLayout(QDomElement element, QStack<QWidget *> *widgetStack,
|
3932
|
3947
|
QStack<QLayout *> *layoutStack);
|
3933
|
3948
|
|
3934
|
|
-@ The function for creating the window must be made available to the scripting
|
|
3949
|
+@ The functions for creating windows must be made available to the scripting
|
3935
|
3950
|
engine.
|
3936
|
3951
|
|
3937
|
3952
|
@<Set up the scripting engine@>=
|
3938
|
3953
|
engine->globalObject().setProperty("createWindow",
|
3939
|
3954
|
engine->newFunction(createWindow));
|
|
3955
|
+engine->globalObject().setProperty("createReport",
|
|
3956
|
+ engine->newFunction(createReport));
|
3940
|
3957
|
|
3941
|
3958
|
@ This function must examine the configuration document in search of the
|
3942
|
3959
|
appropriate window element, parse the contents of that element, and create a
|
|
@@ -3956,6 +3973,32 @@ QScriptValue createWindow(QScriptContext *context, QScriptEngine *engine)@/
|
3956
|
3973
|
return object;
|
3957
|
3974
|
}
|
3958
|
3975
|
|
|
3976
|
+@ Report files are not part of the configuration document and must be created
|
|
3977
|
+differently. While there is a special menu type that handles all of this
|
|
3978
|
+without involving the host environment, scripted generation and manipulation of
|
|
3979
|
+report windows requires another function. This function will only work after a
|
|
3980
|
+window with a reports menu has been created.
|
|
3981
|
+
|
|
3982
|
+@<Functions for scripting@>=
|
|
3983
|
+QScriptValue createReport(QScriptContext *context, QScriptEngine *engine)
|
|
3984
|
+{
|
|
3985
|
+ QString targetID = argument<QString>(0, context);
|
|
3986
|
+ QFile file(QString("reports:%1").arg(targetID));
|
|
3987
|
+ QScriptValue object;
|
|
3988
|
+ if(file.open(QIODevice::ReadOnly))
|
|
3989
|
+ {
|
|
3990
|
+ QDomDocument document;
|
|
3991
|
+ document.setContent(&file, true);
|
|
3992
|
+ QDomElement element = document.documentElement();
|
|
3993
|
+ if(!element.isNull())
|
|
3994
|
+ {
|
|
3995
|
+ @<Display the window@>@;
|
|
3996
|
+ }
|
|
3997
|
+ file.close();
|
|
3998
|
+ }
|
|
3999
|
+ return object;
|
|
4000
|
+}
|
|
4001
|
+
|
3959
|
4002
|
@ First we must locate the {\tt <window>} element. The most sensible way to do
|
3960
|
4003
|
this would require that each {\tt <window>} element has an ID attribute and
|
3961
|
4004
|
search the DOM tree for that ID. Unfortunately, as of this writing,
|
|
@@ -5103,6 +5146,14 @@ of presenting a human readable list of choices.
|
5103
|
5146
|
@<Assign column delegate from SQL@>=
|
5104
|
5147
|
SqlComboBoxDelegate *delegate = new SqlComboBoxDelegate;
|
5105
|
5148
|
SqlComboBox *widget = new SqlComboBox();
|
|
5149
|
+if(currentElement.hasAttribute("nulltext"))
|
|
5150
|
+{
|
|
5151
|
+ widget->setNullText(currentElement.attribute("nulltext"));
|
|
5152
|
+}
|
|
5153
|
+if(currentElement.hasAttribute("nulldata"))
|
|
5154
|
+{
|
|
5155
|
+ widget->setNullData(QVariant(currentElement.attribute("nulldata")));
|
|
5156
|
+}
|
5106
|
5157
|
if(currentElement.hasAttribute("null"))
|
5107
|
5158
|
{
|
5108
|
5159
|
if(currentElement.attribute("null") == "true")
|
|
@@ -5556,6 +5607,9 @@ QScriptValue SaltTable_model(QScriptContext *context, QScriptEngine *engine);
|
5556
|
5607
|
QScriptValue SaltTable_quotedColumnArray(QScriptContext *context,
|
5557
|
5608
|
QScriptEngine *engine);
|
5558
|
5609
|
QScriptValue SaltTable_setData(QScriptContext *context, QScriptEngine *engine);
|
|
5610
|
+QScriptValue SaltTable_clear(QScriptContext *context, QScriptEngine *engine);
|
|
5611
|
+QScriptValue SaltTable_removeRow(QScriptContext *context, QScriptEngine *engine);
|
|
5612
|
+QScriptValue SaltTable_findData(QScriptContext *context, QScriptEngine *engine);
|
5559
|
5613
|
|
5560
|
5614
|
@ There are times when it is useful to obtain the sum of values in a column of
|
5561
|
5615
|
a SaltTable object. For example, when a column represents the weight of the
|
|
@@ -5686,6 +5740,46 @@ QScriptValue SaltTable_data(QScriptContext *context, QScriptEngine *engine)
|
5686
|
5740
|
return retval;
|
5687
|
5741
|
}
|
5688
|
5742
|
|
|
5743
|
+@ There are times when it is useful to clear the content of a table. This is
|
|
5744
|
+used, for example, in the green coffees table after changing the roasted coffee
|
|
5745
|
+item to eliminate excess rows in the case where the previously selected item
|
|
5746
|
+was a pre-roast blend.
|
|
5747
|
+
|
|
5748
|
+@<Functions for scripting@>=
|
|
5749
|
+QScriptValue SaltTable_clear(QScriptContext *context, QScriptEngine *)
|
|
5750
|
+{
|
|
5751
|
+ QTableView *self = getself<QTableView *>(context);
|
|
5752
|
+ SaltModel *model = qobject_cast<SaltModel *>(self->model());
|
|
5753
|
+ model->clear();
|
|
5754
|
+ return QScriptValue();
|
|
5755
|
+}
|
|
5756
|
+
|
|
5757
|
+@ It is sometimes useful to remove a row from a table. This is done in the new
|
|
5758
|
+batch window when the coffee for a row is set to a NULL item.
|
|
5759
|
+
|
|
5760
|
+@<Functions for scripting@>=
|
|
5761
|
+QScriptValue SaltTable_removeRow(QScriptContext *context, QScriptEngine *engine)
|
|
5762
|
+{
|
|
5763
|
+ QTableView *self = getself<QTableView *>(context);
|
|
5764
|
+ SaltModel *model = qobject_cast<SaltModel *>(self->model());
|
|
5765
|
+ int row = argument<int>(0, context);
|
|
5766
|
+ return engine->newVariant(model->removeRow(row));
|
|
5767
|
+}
|
|
5768
|
+
|
|
5769
|
+@ To remove the correct row, it is sometimes useful to query the table for
|
|
5770
|
+special values. This is done with the |findData()| method on the underlying
|
|
5771
|
+model.
|
|
5772
|
+
|
|
5773
|
+@<Functions for scripting@>=
|
|
5774
|
+QScriptValue SaltTable_findData(QScriptContext *context, QScriptEngine *engine)
|
|
5775
|
+{
|
|
5776
|
+ QTableView *self = getself<QTableView *>(context);
|
|
5777
|
+ SaltModel *model = qobject_cast<SaltModel *>(self->model());
|
|
5778
|
+ QVariant value = argument<QVariant>(0, context);
|
|
5779
|
+ int column = argument<int>(1, context);
|
|
5780
|
+ return engine->newVariant(model->findData(value, column));
|
|
5781
|
+}
|
|
5782
|
+
|
5689
|
5783
|
@ These functions need to be added as properties of the table when it is passed
|
5690
|
5784
|
to the host environment.
|
5691
|
5785
|
|
|
@@ -5705,6 +5799,9 @@ void setSaltTableProperties(QScriptValue value, QScriptEngine *engine)
|
5705
|
5799
|
value.setProperty("data", engine->newFunction(SaltTable_data));
|
5706
|
5800
|
value.setProperty("model", engine->newFunction(SaltTable_model));
|
5707
|
5801
|
value.setProperty("setData", engine->newFunction(SaltTable_setData));
|
|
5802
|
+ value.setProperty("clear", engine->newFunction(SaltTable_clear));
|
|
5803
|
+ value.setProperty("removeRow", engine->newFunction(SaltTable_removeRow));
|
|
5804
|
+ value.setProperty("findData", engine->newFunction(SaltTable_findData));
|
5708
|
5805
|
}
|
5709
|
5806
|
|
5710
|
5807
|
@ The |SqlComboBox| is another class that is not constructed from scripts but is
|
|
@@ -5719,6 +5816,7 @@ QScriptValue QComboBox_currentData(QScriptContext *context,
|
5719
|
5816
|
QScriptValue QComboBox_addItem(QScriptContext *context, QScriptEngine *engine);
|
5720
|
5817
|
QScriptValue QComboBox_setModel(QScriptContext *context, QScriptEngine *engine);
|
5721
|
5818
|
QScriptValue QComboBox_findText(QScriptContext *context, QScriptEngine *engine);
|
|
5819
|
+QScriptValue QComboBox_findData(QScriptContext *context, QScriptEngine *engine);
|
5722
|
5820
|
|
5723
|
5821
|
@ These functions should seem familiar by now.
|
5724
|
5822
|
|
|
@@ -5736,6 +5834,7 @@ void setQComboBoxProperties(QScriptValue value, QScriptEngine *engine)
|
5736
|
5834
|
value.setProperty("addItem", engine->newFunction(QComboBox_addItem));
|
5737
|
5835
|
value.setProperty("setModel", engine->newFunction(QComboBox_setModel));
|
5738
|
5836
|
value.setProperty("findText", engine->newFunction(QComboBox_findText));
|
|
5837
|
+ value.setProperty("findData", engine->newFunction(QComboBox_findData));
|
5739
|
5838
|
}
|
5740
|
5839
|
|
5741
|
5840
|
QScriptValue QComboBox_currentData(QScriptContext *context,
|
|
@@ -5766,6 +5865,12 @@ QScriptValue QComboBox_findText(QScriptContext *context, QScriptEngine *engine)
|
5766
|
5865
|
return QScriptValue(engine, self->findText(argument<QString>(0, context)));
|
5767
|
5866
|
}
|
5768
|
5867
|
|
|
5868
|
+QScriptValue QComboBox_findData(QScriptContext *context, QScriptEngine *engine)
|
|
5869
|
+{
|
|
5870
|
+ QComboBox *self = getself<QComboBox *>(context);
|
|
5871
|
+ return QScriptValue(engine, self->findData(argument<QVariant>(0, context)));
|
|
5872
|
+}
|
|
5873
|
+
|
5769
|
5874
|
@i abouttypica.w
|
5770
|
5875
|
|
5771
|
5876
|
@** A representation of temperature measurements.
|
|
@@ -11802,12 +11907,13 @@ database aware widgets.
|
11802
|
11907
|
QSqlDatabase Application::database()
|
11803
|
11908
|
{
|
11804
|
11909
|
QString connectionName;
|
11805
|
|
- QSqlDatabase connection = QSqlDatabase::database();
|
|
11910
|
+ QSqlDatabase connection =
|
|
11911
|
+ QSqlDatabase::database(QLatin1String(QSqlDatabase::defaultConnection), false);
|
11806
|
11912
|
do
|
11807
|
11913
|
{
|
11808
|
11914
|
connectionName = QUuid::createUuid().toString();
|
11809
|
11915
|
} while (QSqlDatabase::connectionNames().contains(connectionName));
|
11810
|
|
- return QSqlDatabase::cloneDatabase(connection, connectionName);
|
|
11916
|
+ return QSqlDatabase::cloneDatabase(connection, QString(connectionName));
|
11811
|
11917
|
}
|
11812
|
11918
|
|
11813
|
11919
|
@** Table editor for ordered arrays with SQL relations.
|
|
@@ -11884,6 +11990,10 @@ class SaltModel : public QAbstractItemModel@/
|
11884
|
11990
|
QModelIndex parent(const QModelIndex &index) const;
|
11885
|
11991
|
QString arrayLiteral(int column, int role) const;
|
11886
|
11992
|
QString quotedArrayLiteral(int column, int role) const;
|
|
11993
|
+ void clear();
|
|
11994
|
+ bool removeRows(int row, int count,
|
|
11995
|
+ const QModelIndex &parent = QModelIndex());
|
|
11996
|
+ int findData(const QVariant &value, int column, int role = Qt::UserRole);
|
11887
|
11997
|
};
|
11888
|
11998
|
|
11889
|
11999
|
@ The only unique methods in this class are the |arrayLiteral| and
|
|
@@ -12154,6 +12264,74 @@ QModelIndex SaltModel::index(int row, int column,
|
12154
|
12264
|
return QModelIndex();
|
12155
|
12265
|
}
|
12156
|
12266
|
|
|
12267
|
+@ There are some times when it is useful to clear the model data. Note that
|
|
12268
|
+column header data is retained and the table will contain a single empty row
|
|
12269
|
+after this method is called.
|
|
12270
|
+
|
|
12271
|
+@<SaltModel Implementation@>=
|
|
12272
|
+void SaltModel::clear()
|
|
12273
|
+{
|
|
12274
|
+ beginResetModel();
|
|
12275
|
+ modelData.clear();
|
|
12276
|
+ @<Expand the SaltModel@>@;
|
|
12277
|
+ endResetModel();
|
|
12278
|
+}
|
|
12279
|
+
|
|
12280
|
+@ Another commonly useful operation is the ability to remove rows from the
|
|
12281
|
+model. The new batch window uses this feature to eliminate rows in which the
|
|
12282
|
+coffee is set to NULL. Note that if all rows of the model are removed, a new
|
|
12283
|
+empty row will be created.
|
|
12284
|
+
|
|
12285
|
+@<SaltModel Implementation@>=
|
|
12286
|
+bool SaltModel::removeRows(int row, int count,
|
|
12287
|
+ const QModelIndex &parent)
|
|
12288
|
+{
|
|
12289
|
+ if(parent == QModelIndex())
|
|
12290
|
+ {
|
|
12291
|
+ if(row >= 0 && count > 0 && (row + count - 1) < modelData.size())
|
|
12292
|
+ {
|
|
12293
|
+ beginRemoveRows(parent, row, row + count - 1);
|
|
12294
|
+ for(int i = 0; i < count; i++)
|
|
12295
|
+ {
|
|
12296
|
+ modelData.removeAt(row);
|
|
12297
|
+ }
|
|
12298
|
+ endRemoveRows();
|
|
12299
|
+ if(modelData.size() == 0)
|
|
12300
|
+ {
|
|
12301
|
+ beginInsertRows(parent, 0, 0);
|
|
12302
|
+ @<Expand the SaltModel@>@;
|
|
12303
|
+ endInsertRows();
|
|
12304
|
+ }
|
|
12305
|
+ return true;
|
|
12306
|
+ }
|
|
12307
|
+ }
|
|
12308
|
+ return false;
|
|
12309
|
+}
|
|
12310
|
+
|
|
12311
|
+@ To find the row number for removal operations it is useful to search for
|
|
12312
|
+special values on a given role. The |findData()| method returns the first row
|
|
12313
|
+in which the given value matches for a particular column and a particular role
|
|
12314
|
+or |-1| if no such match exists.
|
|
12315
|
+
|
|
12316
|
+@<SaltModel Implementation@>=
|
|
12317
|
+int SaltModel::findData(const QVariant &value, int column, int role)
|
|
12318
|
+{
|
|
12319
|
+ for(int i = 0; i < modelData.size(); i++)
|
|
12320
|
+ {
|
|
12321
|
+ if(modelData.at(i).size() > column)
|
|
12322
|
+ {
|
|
12323
|
+ if(modelData.at(i).at(column).contains(role))
|
|
12324
|
+ {
|
|
12325
|
+ if(modelData.at(i).at(column).value(role) == value)
|
|
12326
|
+ {
|
|
12327
|
+ return i;
|
|
12328
|
+ }
|
|
12329
|
+ }
|
|
12330
|
+ }
|
|
12331
|
+ }
|
|
12332
|
+ return -1;
|
|
12333
|
+}
|
|
12334
|
+
|
12157
|
12335
|
@* A Delegate for SQL Relations.
|
12158
|
12336
|
|
12159
|
12337
|
\noindent The first column of the table view being described is responsible for
|
|
@@ -12179,6 +12357,8 @@ class SqlComboBox : public QComboBox@/
|
12179
|
12357
|
int dataColumn;
|
12180
|
12358
|
int displayColumn;
|
12181
|
12359
|
bool dataColumnShown;
|
|
12360
|
+ QString specialNullText;
|
|
12361
|
+ QVariant specialNullData;
|
12182
|
12362
|
public:@/
|
12183
|
12363
|
SqlComboBox();
|
12184
|
12364
|
~SqlComboBox();
|
|
@@ -12188,7 +12368,9 @@ class SqlComboBox : public QComboBox@/
|
12188
|
12368
|
void addSqlOptions(QString query);
|
12189
|
12369
|
void setDataColumn(int column);
|
12190
|
12370
|
void setDisplayColumn(int column);
|
12191
|
|
- void showData(bool show);@t\2@>@/
|
|
12371
|
+ void showData(bool show);
|
|
12372
|
+ void setNullText(QString nullText);
|
|
12373
|
+ void setNullData(QVariant nullData);@t\2@>@/
|
12192
|
12374
|
}@t\kern-3pt@>;
|
12193
|
12375
|
|
12194
|
12376
|
@ In order to make this class work a little more nicely as an item delegate,
|
|
@@ -12221,12 +12403,25 @@ void SqlComboBox::showData(bool show)
|
12221
|
12403
|
@ Next, there is a need to know if the NULL value may legally be selected. Where
|
12222
|
12404
|
this is the case, we generally want this to be inserted first. As the
|
12223
|
12405
|
|QComboBox| supports storing both display and user data, much of the code is a
|
12224
|
|
-thin wrapper around calls to the base class.
|
|
12406
|
+thin wrapper around calls to the base class. The text and data for the NULL
|
|
12407
|
+value can be set arbitrarily, which can be useful in certain cases. Note that
|
|
12408
|
+any customization of the NULL text or data must be set before a call to
|
|
12409
|
+|addNullOption()|.
|
12225
|
12410
|
|
12226
|
12411
|
@<SqlComboBox Implementation@>=
|
12227
|
12412
|
void SqlComboBox::addNullOption()
|
12228
|
12413
|
{
|
12229
|
|
- addItem(tr("Unknown"), QVariant(QVariant::String));
|
|
12414
|
+ addItem(specialNullText, specialNullData);
|
|
12415
|
+}
|
|
12416
|
+
|
|
12417
|
+void SqlComboBox::setNullText(QString nullText)
|
|
12418
|
+{
|
|
12419
|
+ specialNullText = nullText;
|
|
12420
|
+}
|
|
12421
|
+
|
|
12422
|
+void SqlComboBox::setNullData(QVariant nullData)
|
|
12423
|
+{
|
|
12424
|
+ specialNullData = nullData;
|
12230
|
12425
|
}
|
12231
|
12426
|
|
12232
|
12427
|
@ Typically, the SQL query used to populate this widget will request two columns
|
|
@@ -12253,7 +12448,8 @@ the combo box with the results.
|
12253
|
12448
|
@<SqlComboBox Implementation@>=
|
12254
|
12449
|
void SqlComboBox::addSqlOptions(QString query)
|
12255
|
12450
|
{
|
12256
|
|
- SqlQueryConnection *dbquery = new SqlQueryConnection;
|
|
12451
|
+ SqlQueryConnection h;
|
|
12452
|
+ QSqlQuery *dbquery = h.operator->();
|
12257
|
12453
|
if(!dbquery->exec(query))
|
12258
|
12454
|
{
|
12259
|
12455
|
QSqlError error = dbquery->lastError();
|
|
@@ -12273,7 +12469,6 @@ void SqlComboBox::addSqlOptions(QString query)
|
12273
|
12469
|
}
|
12274
|
12470
|
addItem(displayValue, dataValue);
|
12275
|
12471
|
}
|
12276
|
|
- delete dbquery;
|
12277
|
12472
|
}
|
12278
|
12473
|
|
12279
|
12474
|
@ The constructor initializes some private member data. A size policy is also
|
|
@@ -12288,7 +12483,8 @@ The destructor is trivial.
|
12288
|
12483
|
|
12289
|
12484
|
@<SqlComboBox Implementation@>=
|
12290
|
12485
|
SqlComboBox::SqlComboBox() :
|
12291
|
|
- dataColumn(0), displayColumn(0), dataColumnShown(false)
|
|
12486
|
+ dataColumn(0), displayColumn(0), dataColumnShown(false),
|
|
12487
|
+ specialNullText(tr("Unknown")), specialNullData(QVariant::String)
|
12292
|
12488
|
{
|
12293
|
12489
|
view()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
12294
|
12490
|
}
|
|
@@ -12562,6 +12758,7 @@ void SqlConnectionSetup::testConnection()
|
12562
|
12758
|
settings.setValue("database/dbname", dbname->text());
|
12563
|
12759
|
settings.setValue("database/user", user->text());
|
12564
|
12760
|
settings.setValue("database/password", password->text());
|
|
12761
|
+ database.close();
|
12565
|
12762
|
accept();
|
12566
|
12763
|
}
|
12567
|
12764
|
else
|
|
@@ -12597,6 +12794,10 @@ if(!database.open())
|
12597
|
12794
|
{
|
12598
|
12795
|
settings.setValue("database/exists", "false");
|
12599
|
12796
|
}
|
|
12797
|
+else
|
|
12798
|
+{
|
|
12799
|
+ database.close();
|
|
12800
|
+}
|
12600
|
12801
|
|
12601
|
12802
|
@** Viewing a record of batches.
|
12602
|
12803
|
|
|
@@ -12721,8 +12922,6 @@ void SqlQueryView::openRow(const QModelIndex &index)
|
12721
|
12922
|
|
12722
|
12923
|
@ The other functions are wrappers around model methods.
|
12723
|
12924
|
|
12724
|
|
-\danger |setQuery()| leaks database connections.
|
12725
|
|
-
|
12726
|
12925
|
@<SqlQueryView implementation@>=
|
12727
|
12926
|
void SqlQueryView::setQuery(const QString &query)
|
12728
|
12927
|
{
|
|
@@ -12730,6 +12929,7 @@ void SqlQueryView::setQuery(const QString &query)
|
12730
|
12929
|
database.open();
|
12731
|
12930
|
QSqlQuery q(query, database);
|
12732
|
12931
|
((QSqlQueryModel*)model())->setQuery(q);
|
|
12932
|
+ database.close();
|
12733
|
12933
|
}
|
12734
|
12934
|
|
12735
|
12935
|
bool SqlQueryView::setHeaderData(int section, Qt::Orientation@, orientation,
|
|
@@ -12841,10 +13041,18 @@ presently distributed with Typica, the approach taken to implementing this menu
|
12841
|
13041
|
type is highly inefficient. There are many optimizations available if this
|
12842
|
13042
|
becomes problematic.\endanger
|
12843
|
13043
|
|
|
13044
|
+When a report menu is generated, the directory used for this is added as a
|
|
13045
|
+search path for the |"reports"| prefix. This is used by the |createReport()|
|
|
13046
|
+script method and is intended to allow access to reports from outside of the
|
|
13047
|
+Report menu.
|
|
13048
|
+
|
12844
|
13049
|
@<Populate reports menu@>=
|
12845
|
13050
|
QSettings settings;
|
12846
|
|
-QDir directory(QString("%1/%2").arg(settings.value("config").toString()).
|
12847
|
|
- arg(element.attribute("src")));
|
|
13051
|
+QString reportDirectory = QString("%1/%2").arg(settings.value("config").
|
|
13052
|
+ toString()).
|
|
13053
|
+ arg(element.attribute("src"));
|
|
13054
|
+QDir::addSearchPath("reports", reportDirectory);
|
|
13055
|
+QDir directory(reportDirectory);
|
12848
|
13056
|
directory.setFilter(QDir::Files);
|
12849
|
13057
|
directory.setSorting(QDir::Name);
|
12850
|
13058
|
QStringList nameFilter;
|
|
@@ -13191,36 +13399,37 @@ placeholders that have not yet had values bound to them), there will be no
|
13191
|
13399
|
change to the table and the next child element, if any, will be processed.
|
13192
|
13400
|
|
13193
|
13401
|
@<Add SQL query results to report table@>=
|
13194
|
|
-SqlQueryConnection query;
|
13195
|
|
-query.prepare(currentElement.text());
|
|
13402
|
+SqlQueryConnection h;
|
|
13403
|
+QSqlQuery *query = h.operator->();
|
|
13404
|
+query->prepare(currentElement.text());
|
13196
|
13405
|
foreach(QString key, bindings.uniqueKeys())
|
13197
|
13406
|
{
|
13198
|
13407
|
if(currentElement.text().contains(key))
|
13199
|
13408
|
{
|
13200
|
|
- query.bindValue(key, bindings.value(key));
|
|
13409
|
+ query->bindValue(key, bindings.value(key));
|
13201
|
13410
|
}
|
13202
|
13411
|
}
|
13203
|
|
-query.exec();
|
13204
|
|
-if(!query.next())
|
|
13412
|
+query->exec();
|
|
13413
|
+if(!query->next())
|
13205
|
13414
|
{
|
13206
|
13415
|
continue;
|
13207
|
13416
|
}
|
13208
|
|
-if(query.record().count() > columns)
|
|
13417
|
+if(query->record().count() > columns)
|
13209
|
13418
|
{
|
13210
|
|
- table->appendColumns(query.record().count() - columns);
|
|
13419
|
+ table->appendColumns(query->record().count() - columns);
|
13211
|
13420
|
}
|
13212
|
13421
|
do
|
13213
|
13422
|
{
|
13214
|
13423
|
table->appendRows(1);
|
13215
|
13424
|
rows++;
|
13216
|
13425
|
currentRow++;
|
13217
|
|
- for(int j = 0; j < query.record().count(); j++)
|
|
13426
|
+ for(int j = 0; j < query->record().count(); j++)
|
13218
|
13427
|
{
|
13219
|
13428
|
QTextTableCell cell = table->cellAt(currentRow, j);
|
13220
|
13429
|
cursor = cell.firstCursorPosition();
|
13221
|
|
- cursor.insertText(query.value(j).toString());
|
|
13430
|
+ cursor.insertText(query->value(j).toString());
|
13222
|
13431
|
}
|
13223
|
|
-} while(query.next());
|
|
13432
|
+} while(query->next());
|
13224
|
13433
|
|
13225
|
13434
|
@ It is sometimes desirable to add fixed data such as column headers to a table.
|
13226
|
13435
|
This is done with the {\tt <row>} element.
|