|
@@ -4155,6 +4155,7 @@ QScriptValue setTabOrder(QScriptContext *context, QScriptEngine *)
|
4155
|
4155
|
return QScriptValue();
|
4156
|
4156
|
}
|
4157
|
4157
|
|
|
4158
|
+
|
4158
|
4159
|
@** Application Configuration.
|
4159
|
4160
|
|
4160
|
4161
|
\noindent While \pn{} is intended as a data logging application, the diversity
|
|
@@ -10554,6 +10555,7 @@ Q_PROPERTY(bool running READ isRunning)@/
|
10554
|
10555
|
Q_PROPERTY(QTime resetValue READ resetValue WRITE setResetValue)@/
|
10555
|
10556
|
Q_PROPERTY(QString displayFormat READ displayFormat WRITE setDisplayFormat)@/
|
10556
|
10557
|
Q_PROPERTY(bool autoReset READ autoReset WRITE setAutoReset)@/
|
|
10558
|
+Q_PROPERTY(QString value READ value)@/
|
10557
|
10559
|
|
10558
|
10560
|
@ A number of private variables are used to implement this class.
|
10559
|
10561
|
|
|
@@ -10673,6 +10675,8 @@ if(s > QTime(0, 0, 0))@/
|
10673
|
10675
|
s = nt;
|
10674
|
10676
|
emit valueChanged(s);
|
10675
|
10677
|
}
|
|
10678
|
+} else {
|
|
10679
|
+ stopTimer();
|
10676
|
10680
|
}
|
10677
|
10681
|
|
10678
|
10682
|
@ The clock mode is the simplest case as it just needs to find out if the time
|
|
@@ -10867,6 +10871,7 @@ void TimerDisplay::updateDisplay()
|
10867
|
10871
|
QScriptValue constructTimerDisplay(QScriptContext *context,
|
10868
|
10872
|
QScriptEngine *engine);
|
10869
|
10873
|
void setTimerDisplayProperties(QScriptValue value, QScriptEngine *engine);
|
|
10874
|
+QScriptValue TimerDisplay_setTimerMode(QScriptContext *context, QScriptEngine *engine);
|
10870
|
10875
|
|
10871
|
10876
|
@ The engine must be informed of the script constructor.
|
10872
|
10877
|
|
|
@@ -10888,6 +10893,36 @@ QScriptValue constructTimerDisplay(QScriptContext *, QScriptEngine *engine)
|
10888
|
10893
|
void setTimerDisplayProperties(QScriptValue value, QScriptEngine *engine)
|
10889
|
10894
|
{
|
10890
|
10895
|
setQLCDNumberProperties(value, engine);
|
|
10896
|
+ value.setProperty("setTimerMode", engine->newFunction(TimerDisplay_setTimerMode));
|
|
10897
|
+}
|
|
10898
|
+
|
|
10899
|
+@ A new feature in \pn{} 1.6.4 benefits from having the ability to set the
|
|
10900
|
+timer mode from a script. Rather than exposing the |enum| responsible for this
|
|
10901
|
+to the host environment, a new function is provided to allow integer based
|
|
10902
|
+setting.
|
|
10903
|
+
|
|
10904
|
+@<Functions for scripting@>=
|
|
10905
|
+QScriptValue TimerDisplay_setTimerMode(QScriptContext *context, QScriptEngine *)
|
|
10906
|
+{
|
|
10907
|
+ TimerDisplay *self = getself<TimerDisplay *>(context);
|
|
10908
|
+ if(self)
|
|
10909
|
+ {
|
|
10910
|
+ switch(argument<int>(0, context))
|
|
10911
|
+ {
|
|
10912
|
+ case 0:
|
|
10913
|
+ self->setMode(TimerDisplay::CountUp);
|
|
10914
|
+ break;
|
|
10915
|
+ case 1:
|
|
10916
|
+ self->setMode(TimerDisplay::CountDown);
|
|
10917
|
+ break;
|
|
10918
|
+ case 2:
|
|
10919
|
+ self->setMode(TimerDisplay::Clock);
|
|
10920
|
+ break;
|
|
10921
|
+ default:
|
|
10922
|
+ break;
|
|
10923
|
+ }
|
|
10924
|
+ }
|
|
10925
|
+ return QScriptValue();
|
10891
|
10926
|
}
|
10892
|
10927
|
|
10893
|
10928
|
|
|
@@ -16004,6 +16039,24 @@ RoasterConfWidget::RoasterConfWidget(DeviceTreeModel *model, const QModelIndex &
|
16004
|
16039
|
@<Add annotation control node inserters@>@;
|
16005
|
16040
|
addAnnotationControlButton->setMenu(annotationMenu);
|
16006
|
16041
|
layout->addWidget(addAnnotationControlButton);
|
|
16042
|
+
|
|
16043
|
+ QPushButton *timersButton = new QPushButton(tr("Extra Timers"));
|
|
16044
|
+ QMenu *timersMenu = new QMenu;
|
|
16045
|
+ NodeInserter *coolingTimerInserter = new NodeInserter(tr("Cooling Timer"), tr("Cooling Timer"), "coolingtimer");
|
|
16046
|
+ NodeInserter *rangeTimerInserter = new NodeInserter(tr("Range Timer"), tr("Range Timer"), "rangetimer");
|
|
16047
|
+ NodeInserter *multirangeTimerInserter = new NodeInserter(tr("Multi-Range Timer"), tr("Multi-Range Timer"), "multirangetimer");
|
|
16048
|
+ timersMenu->addAction(coolingTimerInserter);
|
|
16049
|
+ timersMenu->addAction(rangeTimerInserter);
|
|
16050
|
+ timersMenu->addAction(multirangeTimerInserter);
|
|
16051
|
+ connect(coolingTimerInserter, SIGNAL(triggered(QString, QString)),
|
|
16052
|
+ this, SLOT(insertChildNode(QString, QString)));
|
|
16053
|
+ connect(rangeTimerInserter, SIGNAL(triggered(QString, QString)),
|
|
16054
|
+ this, SLOT(insertChildNode(QString, QString)));
|
|
16055
|
+ connect(multirangeTimerInserter, SIGNAL(triggered(QString, QString)),
|
|
16056
|
+ this, SLOT(insertChildNode(QString, QString)));
|
|
16057
|
+ timersButton->setMenu(timersMenu);
|
|
16058
|
+ layout->addWidget(timersButton);
|
|
16059
|
+
|
16007
|
16060
|
QPushButton *advancedButton = new QPushButton(tr("Advanced Features"));
|
16008
|
16061
|
QMenu *advancedMenu = new QMenu;
|
16009
|
16062
|
NodeInserter *linearsplineinserter = new NodeInserter(tr("Linear Spline Interpolated Series"), tr("Linear Spline Interpolated Series"), "linearspline");
|
|
@@ -16015,6 +16068,7 @@ RoasterConfWidget::RoasterConfWidget(DeviceTreeModel *model, const QModelIndex &
|
16015
|
16068
|
@<Add node inserters to advanced features menu@>@;
|
16016
|
16069
|
advancedButton->setMenu(advancedMenu);
|
16017
|
16070
|
layout->addWidget(advancedButton);
|
|
16071
|
+
|
16018
|
16072
|
QHBoxLayout *idLayout = new QHBoxLayout;
|
16019
|
16073
|
QLabel *idLabel = new QLabel(tr("Machine ID for database:"));
|
16020
|
16074
|
idLayout->addWidget(idLabel);
|
|
@@ -19123,10 +19177,10 @@ QStringList itemList = data.split(",");
|
19123
|
19177
|
model.
|
19124
|
19178
|
|
19125
|
19179
|
@<Populate model column from list@>=
|
19126
|
|
-for(int i = 0; i < itemList.size(); i++)
|
|
19180
|
+for(int j = 0; j < itemList.size(); j++)
|
19127
|
19181
|
{
|
19128
|
|
- tablemodel->setData(tablemodel->index(i, column),
|
19129
|
|
- QVariant(itemList.at(i).toDouble()),
|
|
19182
|
+ tablemodel->setData(tablemodel->index(j, column),
|
|
19183
|
+ QVariant(itemList.at(j).toDouble()),
|
19130
|
19184
|
Qt::DisplayRole);
|
19131
|
19185
|
}
|
19132
|
19186
|
|
|
@@ -19155,6 +19209,432 @@ void LinearSplineInterpolationConfWidget::updateDestinationColumn(const QString
|
19155
|
19209
|
@<Register device configuration widgets@>=
|
19156
|
19210
|
app.registerDeviceConfigurationWidget("linearspline", LinearSplineInterpolationConfWidget::staticMetaObject);
|
19157
|
19211
|
|
|
19212
|
+@* Additional Timers.
|
|
19213
|
+
|
|
19214
|
+\noindent \pn{} 1.6.4 adds support for more timer indicators than just the
|
|
19215
|
+default batch timer. Three new timer types are supported. The first is a
|
|
19216
|
+cooling timer. This is a timer that is initially set to 0, but at the end of a
|
|
19217
|
+batch this is set to a configured time and starts counting down. There are no
|
|
19218
|
+data logging requirements and this is purely a convenience feature, but one
|
|
19219
|
+that supports product and personnel safety best practices as it helps to
|
|
19220
|
+eliminate the practice of a person reaching into the cooling tray as it
|
|
19221
|
+agitates to test if the coffee has cooled.
|
|
19222
|
+
|
|
19223
|
+@<Class declarations@>=
|
|
19224
|
+class CoolingTimerConfWidget : public BasicDeviceConfigurationWidget
|
|
19225
|
+{
|
|
19226
|
+ @[Q_OBJECT@]@/
|
|
19227
|
+ public:@/
|
|
19228
|
+ @[Q_INVOKABLE@]@, CoolingTimerConfWidget(DeviceTreeModel *model,
|
|
19229
|
+ const QModelIndex &index);
|
|
19230
|
+ @[private slots@]:@/
|
|
19231
|
+ void updateResetTime(QTime time);
|
|
19232
|
+};
|
|
19233
|
+
|
|
19234
|
+@ The only configurable detail is the vaue the timer should reset to. For this
|
|
19235
|
+a |QTimeEdit| is fine.
|
|
19236
|
+
|
|
19237
|
+@<CoolingTimerConfWidget implementation@>=
|
|
19238
|
+CoolingTimerConfWidget::CoolingTimerConfWidget(DeviceTreeModel *model,
|
|
19239
|
+ const QModelIndex &index)
|
|
19240
|
+: BasicDeviceConfigurationWidget(model, index)
|
|
19241
|
+{
|
|
19242
|
+ QHBoxLayout *layout = new QHBoxLayout;
|
|
19243
|
+ QLabel *label = new QLabel(tr("Cooling Time: "));
|
|
19244
|
+ QTimeEdit *editor = new QTimeEdit;
|
|
19245
|
+ editor->setDisplayFormat("mm:ss");
|
|
19246
|
+ @<Get device configuration data for current node@>@;
|
|
19247
|
+ for(int i = 0; i < configData.size(); i++)
|
|
19248
|
+ {
|
|
19249
|
+ node = configData.at(i).toElement();
|
|
19250
|
+ if(node.attribute("name") == "reset")
|
|
19251
|
+ {
|
|
19252
|
+ editor->setTime(QTime::fromString(node.attribute("value"), "mm:ss"));
|
|
19253
|
+ }
|
|
19254
|
+ }
|
|
19255
|
+ updateResetTime(editor->time());
|
|
19256
|
+ connect(editor, SIGNAL(timeChanged(QTime)),
|
|
19257
|
+ this, SLOT(updateResetTime(QTime)));
|
|
19258
|
+ layout->addWidget(label);
|
|
19259
|
+ layout->addWidget(editor);
|
|
19260
|
+ setLayout(layout);
|
|
19261
|
+}
|
|
19262
|
+
|
|
19263
|
+void CoolingTimerConfWidget::updateResetTime(QTime time)
|
|
19264
|
+{
|
|
19265
|
+ updateAttribute("reset", time.toString("mm:ss"));
|
|
19266
|
+}
|
|
19267
|
+
|
|
19268
|
+@ The widget is registered with the configuration system.
|
|
19269
|
+@<Register device configuration widgets@>=
|
|
19270
|
+app.registerDeviceConfigurationWidget("coolingtimer",
|
|
19271
|
+CoolingTimerConfWidget::staticMetaObject);
|
|
19272
|
+
|
|
19273
|
+@ The implementation chunk for now is in the main source file.
|
|
19274
|
+
|
|
19275
|
+@<Class implementations@>=
|
|
19276
|
+@<CoolingTimerConfWidget implementation@>
|
|
19277
|
+
|
|
19278
|
+@ The other two timer types are intended for measuring ranges of interest
|
|
19279
|
+within a batch. These have more configuration options. First is the range
|
|
19280
|
+timer. Someone setting this up needs to decide how the timer is started.
|
|
19281
|
+Sensible options include starting the timer at the start of the batch,
|
|
19282
|
+starting the timer when a button is pressed, or starting the timer when a set
|
|
19283
|
+point is reached on the ascent of a named data series. Stopping the timer is
|
|
19284
|
+also a configurable concern. This will be stopped at the end of the batch,
|
|
19285
|
+but it might be stopped sooner on reaching some threshold or when a button is
|
|
19286
|
+pressed. There are also questions of how the information is persisted with the
|
|
19287
|
+roasting records.
|
|
19288
|
+
|
|
19289
|
+@<Class declarations@>=
|
|
19290
|
+class RangeTimerConfWidget : public BasicDeviceConfigurationWidget
|
|
19291
|
+{
|
|
19292
|
+ @[Q_OBJECT@]@;
|
|
19293
|
+ public:@/
|
|
19294
|
+ @[Q_INVOKABLE@]@, RangeTimerConfWidget(DeviceTreeModel *model, const QModelIndex &index);
|
|
19295
|
+ @[private slots@]:@/
|
|
19296
|
+ void updateStartButtonText(const QString &text);
|
|
19297
|
+ void updateStopButtonText(const QString &text);
|
|
19298
|
+ void updateStartColumnName(const QString &text);
|
|
19299
|
+ void updateStopColumnName(const QString &text);
|
|
19300
|
+ void updateStartValue(const QString &text);
|
|
19301
|
+ void updateStopValue(const QString &text);
|
|
19302
|
+ void updateStartTrigger(int option);
|
|
19303
|
+ void updateStopTrigger(int option);
|
|
19304
|
+};
|
|
19305
|
+
|
|
19306
|
+@ The constructor sets up controls for configuring these details.
|
|
19307
|
+
|
|
19308
|
+@<RangeTimerConfWidget implementation@>=
|
|
19309
|
+RangeTimerConfWidget::RangeTimerConfWidget(DeviceTreeModel *model, const QModelIndex &index)
|
|
19310
|
+: BasicDeviceConfigurationWidget(model, index)
|
|
19311
|
+{
|
|
19312
|
+ QVBoxLayout *layout = new QVBoxLayout;
|
|
19313
|
+
|
|
19314
|
+ QGroupBox *startConfigurationGroup = new QGroupBox(tr("Start trigger"));
|
|
19315
|
+ QRadioButton *startBatchOption = new QRadioButton(tr("Start of batch"));
|
|
19316
|
+ QRadioButton *buttonOption = new QRadioButton(tr("Manual"));
|
|
19317
|
+ QRadioButton *thresholdOption = new QRadioButton(tr("At temperature"));
|
|
19318
|
+ QButtonGroup *startOptionGroup = new QButtonGroup;
|
|
19319
|
+ startOptionGroup->addButton(startBatchOption, 1);
|
|
19320
|
+ startOptionGroup->addButton(buttonOption, 2);
|
|
19321
|
+ startOptionGroup->addButton(thresholdOption, 3);
|
|
19322
|
+ startBatchOption->setChecked(true);
|
|
19323
|
+ QGridLayout *startOptions = new QGridLayout;
|
|
19324
|
+ startOptions->addWidget(startBatchOption, 0, 0);
|
|
19325
|
+ startOptions->addWidget(buttonOption, 1, 0);
|
|
19326
|
+ startOptions->addWidget(thresholdOption, 2, 0);
|
|
19327
|
+ QLabel *buttonTextLabel = new QLabel(tr("Button Text: "));
|
|
19328
|
+ QLineEdit *buttonTextEdit = new QLineEdit;
|
|
19329
|
+ QHBoxLayout *buttonTextOptions = new QHBoxLayout;
|
|
19330
|
+ buttonTextOptions->addWidget(buttonTextLabel);
|
|
19331
|
+ buttonTextOptions->addWidget(buttonTextEdit);
|
|
19332
|
+ startOptions->addLayout(buttonTextOptions, 1, 1);
|
|
19333
|
+ QFormLayout *thresholdOptions = new QFormLayout;
|
|
19334
|
+ QLineEdit *startColumnName = new QLineEdit;
|
|
19335
|
+ QLineEdit *startValue = new QLineEdit;
|
|
19336
|
+ thresholdOptions->addRow(tr("Column Name: "), startColumnName);
|
|
19337
|
+ thresholdOptions->addRow(tr("Value: "), startValue);
|
|
19338
|
+ startOptions->addLayout(thresholdOptions, 2, 1);
|
|
19339
|
+ startConfigurationGroup->setLayout(startOptions);
|
|
19340
|
+ layout->addWidget(startConfigurationGroup);
|
|
19341
|
+
|
|
19342
|
+ QGroupBox *stopConfigurationGroup = new QGroupBox(tr("Stop trigger"));
|
|
19343
|
+ QRadioButton *stopBatchOption = new QRadioButton(tr("End of batch"));
|
|
19344
|
+ QRadioButton *stopButtonOption = new QRadioButton(tr("Manual"));
|
|
19345
|
+ QRadioButton *stopThresholdOption = new QRadioButton(tr("At temperature"));
|
|
19346
|
+ QButtonGroup *stopOptionGroup = new QButtonGroup;
|
|
19347
|
+ stopOptionGroup->addButton(stopBatchOption, 1);
|
|
19348
|
+ stopOptionGroup->addButton(stopButtonOption, 2);
|
|
19349
|
+ stopOptionGroup->addButton(stopThresholdOption, 3);
|
|
19350
|
+ stopBatchOption->setChecked(true);
|
|
19351
|
+ QGridLayout *stopOptions = new QGridLayout;
|
|
19352
|
+ stopOptions->addWidget(stopBatchOption, 0, 0);
|
|
19353
|
+ stopOptions->addWidget(stopButtonOption, 1, 0);
|
|
19354
|
+ stopOptions->addWidget(stopThresholdOption, 2, 0);
|
|
19355
|
+ QLabel *stopButtonLabel = new QLabel(tr("Button Text: "));
|
|
19356
|
+ QLineEdit *stopButtonEdit = new QLineEdit;
|
|
19357
|
+ QHBoxLayout *stopButtonTextOptions = new QHBoxLayout;
|
|
19358
|
+ stopButtonTextOptions->addWidget(stopButtonLabel);
|
|
19359
|
+ stopButtonTextOptions->addWidget(stopButtonEdit);
|
|
19360
|
+ stopOptions->addLayout(stopButtonTextOptions, 1, 1);
|
|
19361
|
+ QLineEdit *stopColumnName = new QLineEdit;
|
|
19362
|
+ QLineEdit *stopValue = new QLineEdit;
|
|
19363
|
+ QFormLayout *stopThresholdOptions = new QFormLayout;
|
|
19364
|
+ stopThresholdOptions->addRow(tr("Column Name: "), stopColumnName);
|
|
19365
|
+ stopThresholdOptions->addRow(tr("Value: "), stopValue);
|
|
19366
|
+ stopOptions->addLayout(stopThresholdOptions, 2, 1);
|
|
19367
|
+ stopConfigurationGroup->setLayout(stopOptions);
|
|
19368
|
+ layout->addWidget(stopConfigurationGroup);
|
|
19369
|
+
|
|
19370
|
+ @<Get device configuration data for current node@>@;
|
|
19371
|
+ for(int i = 0; i < configData.size(); i++)
|
|
19372
|
+ {
|
|
19373
|
+ node = configData.at(i).toElement();
|
|
19374
|
+ if(node.attribute("name") == "startbuttontext")
|
|
19375
|
+ {
|
|
19376
|
+ buttonTextEdit->setText(node.attribute("value"));
|
|
19377
|
+ }
|
|
19378
|
+ else if(node.attribute("name") == "stopbuttontext")
|
|
19379
|
+ {
|
|
19380
|
+ stopButtonEdit->setText(node.attribute("value"));
|
|
19381
|
+ }
|
|
19382
|
+ else if(node.attribute("name") == "startcolumnname")
|
|
19383
|
+ {
|
|
19384
|
+ startColumnName->setText(node.attribute("value"));
|
|
19385
|
+ }
|
|
19386
|
+ else if(node.attribute("name") == "stopcolumnname")
|
|
19387
|
+ {
|
|
19388
|
+ stopColumnName->setText(node.attribute("value"));
|
|
19389
|
+ }
|
|
19390
|
+ else if(node.attribute("name") == "startvalue")
|
|
19391
|
+ {
|
|
19392
|
+ startValue->setText(node.attribute("value"));
|
|
19393
|
+ }
|
|
19394
|
+ else if(node.attribute("name") == "stopvalue")
|
|
19395
|
+ {
|
|
19396
|
+ stopValue->setText(node.attribute("value"));
|
|
19397
|
+ }
|
|
19398
|
+ else if(node.attribute("name") == "starttrigger")
|
|
19399
|
+ {
|
|
19400
|
+ if(node.attribute("value") == "batch")
|
|
19401
|
+ {
|
|
19402
|
+ startBatchOption->setChecked(true);
|
|
19403
|
+ }
|
|
19404
|
+ else if(node.attribute("value") == "manual")
|
|
19405
|
+ {
|
|
19406
|
+ buttonOption->setChecked(true);
|
|
19407
|
+ }
|
|
19408
|
+ else if(node.attribute("value") == "value")
|
|
19409
|
+ {
|
|
19410
|
+ thresholdOption->setChecked(true);
|
|
19411
|
+ }
|
|
19412
|
+ }
|
|
19413
|
+ else if(node.attribute("name") == "stoptrigger")
|
|
19414
|
+ {
|
|
19415
|
+ if(node.attribute("value") == "batch")
|
|
19416
|
+ {
|
|
19417
|
+ stopBatchOption->setChecked(true);
|
|
19418
|
+ }
|
|
19419
|
+ else if(node.attribute("value") == "manual")
|
|
19420
|
+ {
|
|
19421
|
+ stopButtonOption->setChecked(true);
|
|
19422
|
+ }
|
|
19423
|
+ else if(node.attribute("value") == "value")
|
|
19424
|
+ {
|
|
19425
|
+ stopThresholdOption->setChecked(true);
|
|
19426
|
+ }
|
|
19427
|
+ }
|
|
19428
|
+ }
|
|
19429
|
+ updateStartButtonText(buttonTextEdit->text());
|
|
19430
|
+ updateStopButtonText(stopButtonEdit->text());
|
|
19431
|
+ updateStartColumnName(startColumnName->text());
|
|
19432
|
+ updateStopColumnName(stopColumnName->text());
|
|
19433
|
+ updateStartValue(startValue->text());
|
|
19434
|
+ updateStopValue(stopValue->text());
|
|
19435
|
+ updateStartTrigger(startOptionGroup->checkedId());
|
|
19436
|
+ updateStopTrigger(stopOptionGroup->checkedId());
|
|
19437
|
+
|
|
19438
|
+ setLayout(layout);
|
|
19439
|
+
|
|
19440
|
+ connect(buttonTextEdit, SIGNAL(textChanged(QString)),
|
|
19441
|
+ this, SLOT(updateStartButtonText(QString)));
|
|
19442
|
+ connect(stopButtonEdit, SIGNAL(textChanged(QString)),
|
|
19443
|
+ this, SLOT(updateStopButtonText(QString)));
|
|
19444
|
+ connect(startColumnName, SIGNAL(textChanged(QString)),
|
|
19445
|
+ this, SLOT(updateStartColumnName(QString)));
|
|
19446
|
+ connect(stopColumnName, SIGNAL(textChanged(QString)),
|
|
19447
|
+ this, SLOT(updateStopColumnName(QString)));
|
|
19448
|
+ connect(startValue, SIGNAL(textChanged(QString)),
|
|
19449
|
+ this, SLOT(updateStartValue(QString)));
|
|
19450
|
+ connect(stopValue, SIGNAL(textChanged(QString)),
|
|
19451
|
+ this, SLOT(updateStopValue(QString)));
|
|
19452
|
+ connect(startOptionGroup, SIGNAL(buttonClicked(int)),
|
|
19453
|
+ this, SLOT(updateStartTrigger(int)));
|
|
19454
|
+ connect(stopOptionGroup, SIGNAL(buttonClicked(int)),
|
|
19455
|
+ this, SLOT(updateStopTrigger(int)));
|
|
19456
|
+}
|
|
19457
|
+
|
|
19458
|
+@ Small methods update the configuration as usual.
|
|
19459
|
+
|
|
19460
|
+@<RangeTimerConfWidget implementation@>=
|
|
19461
|
+void RangeTimerConfWidget::updateStartButtonText(const QString &text)
|
|
19462
|
+{
|
|
19463
|
+ updateAttribute("startbuttontext", text);
|
|
19464
|
+}
|
|
19465
|
+
|
|
19466
|
+void RangeTimerConfWidget::updateStopButtonText(const QString &text)
|
|
19467
|
+{
|
|
19468
|
+ updateAttribute("stopbuttontext", text);
|
|
19469
|
+}
|
|
19470
|
+
|
|
19471
|
+void RangeTimerConfWidget::updateStartColumnName(const QString &text)
|
|
19472
|
+{
|
|
19473
|
+ updateAttribute("startcolumnname", text);
|
|
19474
|
+}
|
|
19475
|
+
|
|
19476
|
+void RangeTimerConfWidget::updateStopColumnName(const QString &text)
|
|
19477
|
+{
|
|
19478
|
+ updateAttribute("stopcolumnname", text);
|
|
19479
|
+}
|
|
19480
|
+
|
|
19481
|
+void RangeTimerConfWidget::updateStartValue(const QString &text)
|
|
19482
|
+{
|
|
19483
|
+ updateAttribute("startvalue", text);
|
|
19484
|
+}
|
|
19485
|
+
|
|
19486
|
+void RangeTimerConfWidget::updateStopValue(const QString &text)
|
|
19487
|
+{
|
|
19488
|
+ updateAttribute("stopvalue", text);
|
|
19489
|
+}
|
|
19490
|
+
|
|
19491
|
+void RangeTimerConfWidget::updateStartTrigger(int option)
|
|
19492
|
+{
|
|
19493
|
+ switch(option)
|
|
19494
|
+ {
|
|
19495
|
+ case 1:
|
|
19496
|
+ updateAttribute("starttrigger", "batch");
|
|
19497
|
+ break;
|
|
19498
|
+ case 2:
|
|
19499
|
+ updateAttribute("starttrigger", "manual");
|
|
19500
|
+ break;
|
|
19501
|
+ case 3:
|
|
19502
|
+ updateAttribute("starttrigger", "value");
|
|
19503
|
+ break;
|
|
19504
|
+ default:
|
|
19505
|
+ break;
|
|
19506
|
+ }
|
|
19507
|
+}
|
|
19508
|
+
|
|
19509
|
+void RangeTimerConfWidget::updateStopTrigger(int option)
|
|
19510
|
+{
|
|
19511
|
+ switch(option)
|
|
19512
|
+ {
|
|
19513
|
+ case 1:
|
|
19514
|
+ updateAttribute("stoptrigger", "batch");
|
|
19515
|
+ break;
|
|
19516
|
+ case 2:
|
|
19517
|
+ updateAttribute("stoptrigger", "manual");
|
|
19518
|
+ break;
|
|
19519
|
+ case 3:
|
|
19520
|
+ updateAttribute("stoptrigger", "value");
|
|
19521
|
+ break;
|
|
19522
|
+ default:
|
|
19523
|
+ break;
|
|
19524
|
+ }
|
|
19525
|
+}
|
|
19526
|
+
|
|
19527
|
+@ The widget is registered with the configuration system.
|
|
19528
|
+@<Register device configuration widgets@>=
|
|
19529
|
+app.registerDeviceConfigurationWidget("rangetimer",
|
|
19530
|
+RangeTimerConfWidget::staticMetaObject);
|
|
19531
|
+
|
|
19532
|
+@ The implementation chunk for now is in the main source file.
|
|
19533
|
+
|
|
19534
|
+@<Class implementations@>=
|
|
19535
|
+@<RangeTimerConfWidget implementation@>
|
|
19536
|
+
|
|
19537
|
+@ The multirange timer is a little different. To keep configuration tractible,
|
|
19538
|
+this is slightly less general purpose than the range timer and only supports
|
|
19539
|
+automatic triggering on a single data series.
|
|
19540
|
+
|
|
19541
|
+@<Class declarations@>=
|
|
19542
|
+class MultiRangeTimerConfWidget : public BasicDeviceConfigurationWidget
|
|
19543
|
+{
|
|
19544
|
+ @[Q_OBJECT@]@/
|
|
19545
|
+ public:@/
|
|
19546
|
+ @[Q_INVOKABLE@]@, MultiRangeTimerConfWidget(DeviceTreeModel *model,
|
|
19547
|
+ const QModelIndex &index);
|
|
19548
|
+ @[private slots@]:@/
|
|
19549
|
+ void updateColumnName(const QString &text);
|
|
19550
|
+ void updateRangeData();
|
|
19551
|
+ private:@/
|
|
19552
|
+ SaltModel *tablemodel;
|
|
19553
|
+};
|
|
19554
|
+
|
|
19555
|
+@ These limitations allow a rather small set of controls for configuration. A
|
|
19556
|
+line edit to specify the data series used for automatic triggering and a table
|
|
19557
|
+which specifies the name of the timed range and an ending temperature.
|
|
19558
|
+
|
|
19559
|
+@<MultiRangeTimerConfWidget implementation@>=
|
|
19560
|
+MultiRangeTimerConfWidget::MultiRangeTimerConfWidget(DeviceTreeModel *model,
|
|
19561
|
+ const QModelIndex &index)
|
|
19562
|
+: BasicDeviceConfigurationWidget(model, index), tablemodel(new SaltModel(2))
|
|
19563
|
+{
|
|
19564
|
+ QFormLayout *layout = new QFormLayout;
|
|
19565
|
+ QLineEdit *trigger = new QLineEdit;
|
|
19566
|
+ layout->addRow(tr("Trigger column name:"), trigger);
|
|
19567
|
+ tablemodel->setHeaderData(0, Qt::Horizontal, "Range Name");
|
|
19568
|
+ tablemodel->setHeaderData(1, Qt::Horizontal, "End Temperature");
|
|
19569
|
+ QTableView *rangeTable = new QTableView;
|
|
19570
|
+ rangeTable->setModel(tablemodel);
|
|
19571
|
+ layout->addRow(tr("Range data:"), rangeTable);
|
|
19572
|
+ @<Get device configuration data for current node@>@;
|
|
19573
|
+ for(int i = 0; i < configData.size(); i++)
|
|
19574
|
+ {
|
|
19575
|
+ node = configData.at(i).toElement();
|
|
19576
|
+ if(node.attribute("name") == "trigger")
|
|
19577
|
+ {
|
|
19578
|
+ trigger->setText(node.attribute("value"));
|
|
19579
|
+ }
|
|
19580
|
+ else if(node.attribute("name") == "rangenames")
|
|
19581
|
+ {
|
|
19582
|
+ QString data = node.attribute("value");
|
|
19583
|
+ if(data.length() > 3)
|
|
19584
|
+ {
|
|
19585
|
+ data.chop(2);
|
|
19586
|
+ data = data.remove(0, 2);
|
|
19587
|
+ }
|
|
19588
|
+ QStringList itemList = data.split(", ");
|
|
19589
|
+ for(int j = 0; j < itemList.size(); j++)
|
|
19590
|
+ {
|
|
19591
|
+ QString item = itemList.at(j);
|
|
19592
|
+ item.chop(1);
|
|
19593
|
+ item = item.remove(0, 1);
|
|
19594
|
+ tablemodel->setData(tablemodel->index(j, 0),
|
|
19595
|
+ QVariant(item), Qt::DisplayRole);
|
|
19596
|
+ }
|
|
19597
|
+ }
|
|
19598
|
+ else if(node.attribute("name") == "endtemps")
|
|
19599
|
+ {
|
|
19600
|
+ @<Convert numeric array literal to list@>@;
|
|
19601
|
+ int column = 1;
|
|
19602
|
+ @<Populate model column from list@>@;
|
|
19603
|
+ }
|
|
19604
|
+ }
|
|
19605
|
+ updateColumnName(trigger->text());
|
|
19606
|
+ updateRangeData();
|
|
19607
|
+ connect(trigger, SIGNAL(textEdited(QString)), this, SLOT(updateColumnName(QString)));
|
|
19608
|
+ connect(tablemodel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(updateRangeData()));
|
|
19609
|
+ setLayout(layout);
|
|
19610
|
+}
|
|
19611
|
+
|
|
19612
|
+@ The update mechanisms are reasonably straightforward. Table updates just
|
|
19613
|
+refresh the entire table instead of attempting to be clever about updating only
|
|
19614
|
+the element that changed.
|
|
19615
|
+
|
|
19616
|
+@<MultiRangeTimerConfWidget implementation@>=
|
|
19617
|
+void MultiRangeTimerConfWidget::updateRangeData()
|
|
19618
|
+{
|
|
19619
|
+ updateAttribute("rangenames", tablemodel->quotedArrayLiteral(0, Qt::DisplayRole));
|
|
19620
|
+ updateAttribute("endtemps", tablemodel->arrayLiteral(1, Qt::DisplayRole));
|
|
19621
|
+}
|
|
19622
|
+
|
|
19623
|
+void MultiRangeTimerConfWidget::updateColumnName(const QString &text)
|
|
19624
|
+{
|
|
19625
|
+ updateAttribute("trigger", text);
|
|
19626
|
+}
|
|
19627
|
+
|
|
19628
|
+@ The widget is registered with the configuration system.
|
|
19629
|
+@<Register device configuration widgets@>=
|
|
19630
|
+app.registerDeviceConfigurationWidget("multirangetimer",
|
|
19631
|
+MultiRangeTimerConfWidget::staticMetaObject);
|
|
19632
|
+
|
|
19633
|
+@ The implementation is in the main source file.
|
|
19634
|
+
|
|
19635
|
+@<Class implementations@>=
|
|
19636
|
+@<MultiRangeTimerConfWidget implementation@>
|
|
19637
|
+
|
19158
|
19638
|
@* Profile Translation Configuration Widget.
|
19159
|
19639
|
|
19160
|
19640
|
\noindent Configuring profile translation requires knowing which column to use
|