|
@@ -0,0 +1,498 @@
|
|
1
|
+@** Collecting Measurements from Scales.
|
|
2
|
+
|
|
3
|
+\noindent When a computer connected scale is available, it can be useful to
|
|
4
|
+eliminate manual transcription from the data entry for batches. In general it
|
|
5
|
+is difficult to determine where a measurement should go automatically, but
|
|
6
|
+there are a number of situations where the ability to drag a measurement from a
|
|
7
|
+label and drop it to whatever input widget is appropriate would be a useful
|
|
8
|
+operation to support.
|
|
9
|
+
|
|
10
|
+To support this, we need to subclass |QLabel| to allow it to initiate a drag
|
|
11
|
+and drop operation.
|
|
12
|
+
|
|
13
|
+@(draglabel.h@>=
|
|
14
|
+#ifndef TypicaDragLabelInclude
|
|
15
|
+#define TypicaDragLabelInclude
|
|
16
|
+
|
|
17
|
+#include <QLabel>
|
|
18
|
+
|
|
19
|
+class DragLabel : public QLabel
|
|
20
|
+{
|
|
21
|
+ Q_OBJECT
|
|
22
|
+ public:
|
|
23
|
+ explicit DragLabel(const QString &labelText, QWidget *parent = NULL);
|
|
24
|
+ protected:
|
|
25
|
+ void mousePressEvent(QMouseEvent *event);
|
|
26
|
+};
|
|
27
|
+
|
|
28
|
+#endif
|
|
29
|
+
|
|
30
|
+@ The font size of the label is increased by default to make it easier to
|
|
31
|
+manipulate on a touch screen. Otherwise, there is little to do in this class.
|
|
32
|
+
|
|
33
|
+@(draglabel.cpp@>=
|
|
34
|
+#include "draglabel.h"
|
|
35
|
+
|
|
36
|
+#include <QDrag>
|
|
37
|
+#include <QMouseEvent>
|
|
38
|
+
|
|
39
|
+DragLabel::DragLabel(const QString &labelText, QWidget *parent) :
|
|
40
|
+ QLabel(labelText, parent)
|
|
41
|
+{
|
|
42
|
+ QFont labelFont = font();
|
|
43
|
+ labelFont.setPointSize(14);
|
|
44
|
+ setFont(labelFont);
|
|
45
|
+}
|
|
46
|
+
|
|
47
|
+void DragLabel::mousePressEvent(QMouseEvent *event)
|
|
48
|
+{
|
|
49
|
+ if(event->button() == Qt::LeftButton)
|
|
50
|
+ {
|
|
51
|
+ QDrag *drag = new QDrag(this);
|
|
52
|
+ QMimeData *mimeData = new QMimeData;
|
|
53
|
+ mimeData->setText(text());
|
|
54
|
+ drag->setMimeData(mimeData);
|
|
55
|
+ drag->exec();
|
|
56
|
+ }
|
|
57
|
+}
|
|
58
|
+
|
|
59
|
+@ We require the ability to create these labels from the host environment.
|
|
60
|
+First we include the appropriate header.
|
|
61
|
+
|
|
62
|
+@<Header files to include@>=
|
|
63
|
+#include "draglabel.h"
|
|
64
|
+
|
|
65
|
+@ Next, a pair of function prototypes.
|
|
66
|
+
|
|
67
|
+@<Function prototypes for scripting@>=
|
|
68
|
+QScriptValue constructDragLabel(QScriptContext *context, QScriptEngine *engine);
|
|
69
|
+void setDragLabelProperties(QScriptValue value, QScriptEngine *engine);
|
|
70
|
+
|
|
71
|
+@ These are made known to the host environment as usual.
|
|
72
|
+
|
|
73
|
+@<Set up the scripting engine@>=
|
|
74
|
+constructor = engine->newFunction(constructDragLabel);
|
|
75
|
+value = engine->newQMetaObject(&DragLabel::staticMetaObject, constructor);
|
|
76
|
+engine->globalObject().setProperty("DragLabel", value);
|
|
77
|
+
|
|
78
|
+@ The implementation is trivial.
|
|
79
|
+
|
|
80
|
+@<Functions for scripting@>=
|
|
81
|
+QScriptValue constructDragLabel(QScriptContext *context, QScriptEngine *engine)
|
|
82
|
+{
|
|
83
|
+ QScriptValue object;
|
|
84
|
+ QString labelText = "";
|
|
85
|
+ if(context->argumentCount() == 1)
|
|
86
|
+ {
|
|
87
|
+ labelText = argument<QString>(0, context);
|
|
88
|
+ }
|
|
89
|
+ object = engine->newQObject(new DragLabel(labelText));
|
|
90
|
+ setDragLabelProperties(object, engine);
|
|
91
|
+ return object;
|
|
92
|
+}
|
|
93
|
+
|
|
94
|
+void setDragLabelProperties(QScriptValue value, QScriptEngine *engine)
|
|
95
|
+{
|
|
96
|
+ setQLabelProperties(value, engine);
|
|
97
|
+}
|
|
98
|
+
|
|
99
|
+@ An object is also required to communicate with a scale. This is responsible
|
|
100
|
+for setting up a connection over a serial port, sending commands out to the
|
|
101
|
+scale, buffering and interpreting the response, and signaling new measurements.
|
|
102
|
+
|
|
103
|
+@(scale.h@>=
|
|
104
|
+#ifndef TypicaScaleInclude
|
|
105
|
+#define TypicaScaleInclude
|
|
106
|
+
|
|
107
|
+#include "3rdparty/qextserialport/src/qextserialport.h"
|
|
108
|
+#include "units.h"
|
|
109
|
+
|
|
110
|
+class SerialScale : public QextSerialPort
|
|
111
|
+{
|
|
112
|
+ Q_OBJECT
|
|
113
|
+ public:
|
|
114
|
+ SerialScale(const QString &port);
|
|
115
|
+ public slots:
|
|
116
|
+ void tare();
|
|
117
|
+ void weigh();
|
|
118
|
+ signals:
|
|
119
|
+ void newMeasurement(double weight, Units::Unit unit);
|
|
120
|
+ private slots:
|
|
121
|
+ void dataAvailable();
|
|
122
|
+ private:
|
|
123
|
+ QByteArray responseBuffer;
|
|
124
|
+};
|
|
125
|
+
|
|
126
|
+#endif
|
|
127
|
+
|
|
128
|
+@ The constructor tells the port that this should be event driven and connects
|
|
129
|
+a signal to buffer data..
|
|
130
|
+
|
|
131
|
+@(scale.cpp@>=
|
|
132
|
+#include "scale.h"
|
|
133
|
+#include <QStringList>
|
|
134
|
+
|
|
135
|
+SerialScale::SerialScale(const QString &port) :
|
|
136
|
+ QextSerialPort(port, QextSerialPort::EventDriven)
|
|
137
|
+{
|
|
138
|
+ connect(this, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
|
|
139
|
+}
|
|
140
|
+
|
|
141
|
+@ The |dataAvailable| method handles buffering incoming data and processing
|
|
142
|
+responses when they have come in. Serial port communications are likely to be
|
|
143
|
+very slow in comparison to everything else so it is likely that only one
|
|
144
|
+character will come in at a time.
|
|
145
|
+
|
|
146
|
+Note that this currently only understands single line output and a limited
|
|
147
|
+selection of units.
|
|
148
|
+
|
|
149
|
+@(scale.cpp@>=
|
|
150
|
+void SerialScale::dataAvailable()
|
|
151
|
+{
|
|
152
|
+ responseBuffer.append(readAll());
|
|
153
|
+ if(responseBuffer.contains("\x0D"))
|
|
154
|
+ {
|
|
155
|
+ if(responseBuffer.contains("!"))
|
|
156
|
+ {
|
|
157
|
+ responseBuffer.clear();
|
|
158
|
+ }
|
|
159
|
+ else
|
|
160
|
+ {
|
|
161
|
+ @<Process weight measurement@>@;
|
|
162
|
+ responseBuffer.clear();
|
|
163
|
+ }
|
|
164
|
+ }
|
|
165
|
+}
|
|
166
|
+
|
|
167
|
+@ Each line of data consists of an optional sign character possibly followed
|
|
168
|
+by a space followed by characters representing a number followed by a
|
|
169
|
+space followed by characters indicating a unit. This may be preceeded and
|
|
170
|
+followed by a variable amount of white space. To process a new measurement, we
|
|
171
|
+must remove the excess white space, split the number from the unit, prepend the
|
|
172
|
+sign to the number if it is present, convert the string representing the number
|
|
173
|
+to a numeric type, and determine which unit the measurement is in.
|
|
174
|
+
|
|
175
|
+\medskip
|
|
176
|
+
|
|
177
|
+\settabs 8 \columns
|
|
178
|
+\+&&&{\tt |"lb"|}&|Units::Pound|\cr
|
|
179
|
+\+&&&{\tt |"kg"|}&|Units::Kilogram|\cr
|
|
180
|
+\+&&&{\tt |"g"|}&|Units::Gram|\cr
|
|
181
|
+\+&&&{\tt |"oz"|}&|Units::Ounce|\cr
|
|
182
|
+
|
|
183
|
+\smallskip
|
|
184
|
+
|
|
185
|
+\centerline{Table \secno: Unit Strings and Representative Unit Enumeration}
|
|
186
|
+
|
|
187
|
+\medskip
|
|
188
|
+
|
|
189
|
+@<Process weight measurement@>=
|
|
190
|
+QStringList responseParts = QString(responseBuffer.simplified()).split(' ');
|
|
191
|
+if(responseParts.size() > 2)
|
|
192
|
+{
|
|
193
|
+ responseParts.removeFirst();
|
|
194
|
+ responseParts.replace(0, QString("-%1").arg(responseParts[0]));
|
|
195
|
+}
|
|
196
|
+double weight = responseParts[0].toDouble();
|
|
197
|
+Units::Unit unit = Units::Unitless;
|
|
198
|
+if(responseParts[1] == "lb")
|
|
199
|
+{
|
|
200
|
+ unit = Units::Pound;
|
|
201
|
+}
|
|
202
|
+else if(responseParts[1] == "kg")
|
|
203
|
+{
|
|
204
|
+ unit = Units::Kilogram;
|
|
205
|
+}
|
|
206
|
+else if(responseParts[1] == "g")
|
|
207
|
+{
|
|
208
|
+ unit = Units::Gram;
|
|
209
|
+}
|
|
210
|
+else if(responseParts[1] == "oz")
|
|
211
|
+{
|
|
212
|
+ unit = Units::Ounce;
|
|
213
|
+}
|
|
214
|
+emit newMeasurement(weight, unit);
|
|
215
|
+
|
|
216
|
+@ Two methods are used to send commands to the scale. I am unsure of how well
|
|
217
|
+standardized remote key operation of scales are. The class may need to be
|
|
218
|
+extended to support more devices.
|
|
219
|
+
|
|
220
|
+@(scale.cpp@>=
|
|
221
|
+void SerialScale::tare()
|
|
222
|
+{
|
|
223
|
+ write("!KT\x0D");
|
|
224
|
+}
|
|
225
|
+
|
|
226
|
+void SerialScale::weigh()
|
|
227
|
+{
|
|
228
|
+ write("!KP\x0D");
|
|
229
|
+}
|
|
230
|
+
|
|
231
|
+@ This must be available to the host environment.
|
|
232
|
+
|
|
233
|
+@<Function prototypes for scripting@>=
|
|
234
|
+QScriptValue constructSerialScale(QScriptContext *context, QScriptEngine *engine);
|
|
235
|
+void setSerialScaleProperties(QScriptValue value, QScriptEngine *engine);
|
|
236
|
+
|
|
237
|
+@ These functions are made known to the scripting engine in the usual way.
|
|
238
|
+
|
|
239
|
+@<Set up the scripting engine@>=
|
|
240
|
+constructor = engine->newFunction(constructSerialScale);
|
|
241
|
+value = engine->newQMetaObject(&SerialScale::staticMetaObject, constructor);
|
|
242
|
+engine->globalObject().setProperty("SerialScale", value);
|
|
243
|
+
|
|
244
|
+@ If we are to set up the serial ports from the host environment, a few
|
|
245
|
+enumerated types must be made known to the meta-object system.
|
|
246
|
+
|
|
247
|
+@<Class declarations@>=
|
|
248
|
+Q_DECLARE_METATYPE(BaudRateType)
|
|
249
|
+Q_DECLARE_METATYPE(DataBitsType)
|
|
250
|
+Q_DECLARE_METATYPE(ParityType)
|
|
251
|
+Q_DECLARE_METATYPE(StopBitsType)
|
|
252
|
+Q_DECLARE_METATYPE(FlowType)
|
|
253
|
+
|
|
254
|
+@ For each of these, a pair of functions converts values to script values and
|
|
255
|
+back. This is a very annoying aspect of the version of QextSerialPort currently
|
|
256
|
+used by \pn{}.
|
|
257
|
+
|
|
258
|
+@<Function prototypes for scripting@>=
|
|
259
|
+QScriptValue BaudRateType_toScriptValue(QScriptEngine *engine, const BaudRateType &value);
|
|
260
|
+void BaudRateType_fromScriptValue(const QScriptValue &sv, BaudRateType &value);
|
|
261
|
+QScriptValue DataBitsType_toScriptValue(QScriptEngine *engine, const DataBitsType &value);
|
|
262
|
+void DataBitsType_fromScriptValue(const QScriptValue &sv, DataBitsType &value);
|
|
263
|
+QScriptValue ParityType_toScriptValue(QScriptEngine *engine, const ParityType &value);
|
|
264
|
+void ParityType_fromScriptValue(const QScriptValue &sv, ParityType &value);
|
|
265
|
+QScriptValue StopBitsType_toScriptValue(QScriptEngine *engine, const StopBitsType &value);
|
|
266
|
+void StopBitsType_fromScriptValue(const QScriptValue &sv, StopBitsType &value);
|
|
267
|
+QScriptValue FlowType_toScriptValue(QScriptEngine *engine, const FlowType &value);
|
|
268
|
+void FlowType_fromScriptValue(const QScriptValue &sv, FlowType &value);
|
|
269
|
+
|
|
270
|
+@ These are implemented thusly.
|
|
271
|
+
|
|
272
|
+@<Functions for scripting@>=
|
|
273
|
+QScriptValue BaudRateType_toScriptValue(QScriptEngine *engine, const BaudRateType &value)
|
|
274
|
+{
|
|
275
|
+ return engine->newVariant(QVariant((int)(value)));
|
|
276
|
+}
|
|
277
|
+
|
|
278
|
+void BaudRateType_fromScriptValue(const QScriptValue &sv, BaudRateType &value)
|
|
279
|
+{
|
|
280
|
+ value = (BaudRateType)(sv.toVariant().toInt());
|
|
281
|
+}
|
|
282
|
+
|
|
283
|
+QScriptValue DataBitsType_toScriptValue(QScriptEngine *engine, const DataBitsType &value)
|
|
284
|
+{
|
|
285
|
+ return engine->newVariant(QVariant((int)(value)));
|
|
286
|
+}
|
|
287
|
+
|
|
288
|
+void DataBitsType_fromScriptValue(const QScriptValue &sv, DataBitsType &value)
|
|
289
|
+{
|
|
290
|
+ value = (DataBitsType)(sv.toVariant().toInt());
|
|
291
|
+}
|
|
292
|
+
|
|
293
|
+QScriptValue ParityType_toScriptValue(QScriptEngine *engine, const ParityType &value)
|
|
294
|
+{
|
|
295
|
+ return engine->newVariant(QVariant((int)(value)));
|
|
296
|
+}
|
|
297
|
+
|
|
298
|
+void ParityType_fromScriptValue(const QScriptValue &sv, ParityType &value)
|
|
299
|
+{
|
|
300
|
+ value = (ParityType)(sv.toVariant().toInt());
|
|
301
|
+}
|
|
302
|
+
|
|
303
|
+QScriptValue StopBitsType_toScriptValue(QScriptEngine *engine, const StopBitsType &value)
|
|
304
|
+{
|
|
305
|
+ return engine->newVariant(QVariant((int)(value)));
|
|
306
|
+}
|
|
307
|
+
|
|
308
|
+void StopBitsType_fromScriptValue(const QScriptValue &sv, StopBitsType &value)
|
|
309
|
+{
|
|
310
|
+ value = (StopBitsType)(sv.toVariant().toInt());
|
|
311
|
+}
|
|
312
|
+
|
|
313
|
+QScriptValue FlowType_toScriptValue(QScriptEngine *engine, const FlowType &value)
|
|
314
|
+{
|
|
315
|
+ return engine->newVariant(QVariant((int)(value)));
|
|
316
|
+}
|
|
317
|
+
|
|
318
|
+void FlowType_fromScriptValue(const QScriptValue &sv, FlowType &value)
|
|
319
|
+{
|
|
320
|
+ value = (FlowType)(sv.toVariant().toInt());
|
|
321
|
+}
|
|
322
|
+
|
|
323
|
+@ These conversion functions are then registered.
|
|
324
|
+
|
|
325
|
+@<Set up the scripting engine@>=
|
|
326
|
+qScriptRegisterMetaType(engine, BaudRateType_toScriptValue, BaudRateType_fromScriptValue);
|
|
327
|
+qScriptRegisterMetaType(engine, DataBitsType_toScriptValue, DataBitsType_fromScriptValue);
|
|
328
|
+qScriptRegisterMetaType(engine, ParityType_toScriptValue, ParityType_fromScriptValue);
|
|
329
|
+qScriptRegisterMetaType(engine, StopBitsType_toScriptValue, StopBitsType_fromScriptValue);
|
|
330
|
+qScriptRegisterMetaType(engine, FlowType_toScriptValue, FlowType_fromScriptValue);
|
|
331
|
+
|
|
332
|
+@ In order to make this class available to the host environment, we must also
|
|
333
|
+include the appropriate header file.
|
|
334
|
+
|
|
335
|
+@<Header files to include@>=
|
|
336
|
+#include "scale.h"
|
|
337
|
+
|
|
338
|
+@ Most of the properties of interest should be added automatically, however
|
|
339
|
+there are non-slot methods in |QIODevice| that we require.
|
|
340
|
+
|
|
341
|
+@<Functions for scripting@>=
|
|
342
|
+void setSerialScaleProperties(QScriptValue value, QScriptEngine *engine)
|
|
343
|
+{
|
|
344
|
+ setQIODeviceProperties(value, engine);
|
|
345
|
+}
|
|
346
|
+
|
|
347
|
+@ The script constructor should seem familiar.
|
|
348
|
+
|
|
349
|
+@<Functions for scripting@>=
|
|
350
|
+QScriptValue constructSerialScale(QScriptContext *context, QScriptEngine *engine)
|
|
351
|
+{
|
|
352
|
+ QScriptValue object;
|
|
353
|
+ if(context->argumentCount() == 1)
|
|
354
|
+ {
|
|
355
|
+ object = engine->newQObject(new SerialScale(argument<QString>(0, context)));
|
|
356
|
+ setSerialScaleProperties(object, engine);
|
|
357
|
+ }
|
|
358
|
+ else
|
|
359
|
+ {
|
|
360
|
+ context->throwError("Incorrect number of arguments passed to "
|
|
361
|
+ "SerialScale. The constructor takes one string "
|
|
362
|
+ "as an argument specifying a port name.");
|
|
363
|
+ }
|
|
364
|
+ return object;
|
|
365
|
+}
|
|
366
|
+
|
|
367
|
+@ In order to allow configuration of scales from within \pn{}, a configuration
|
|
368
|
+widget must be provided.
|
|
369
|
+
|
|
370
|
+@<Class declarations@>=
|
|
371
|
+class SerialScaleConfWidget : public BasicDeviceConfigurationWidget
|
|
372
|
+{
|
|
373
|
+ Q_OBJECT
|
|
374
|
+ public:
|
|
375
|
+ Q_INVOKABLE SerialScaleConfWidget(DeviceTreeModel *model,
|
|
376
|
+ const QModelIndex &index);
|
|
377
|
+ private slots:
|
|
378
|
+ void updatePort(const QString &newPort);
|
|
379
|
+ void updateBaudRate(const QString &rate);
|
|
380
|
+ void updateParity(int index);
|
|
381
|
+ void updateFlowControl(int index);
|
|
382
|
+ void updateStopBits(int index);
|
|
383
|
+ private:
|
|
384
|
+ PortSelector *port;
|
|
385
|
+ BaudSelector *baud;
|
|
386
|
+ ParitySelector *parity;
|
|
387
|
+ FlowSelector *flow;
|
|
388
|
+ StopSelector *stop;
|
|
389
|
+};
|
|
390
|
+
|
|
391
|
+@ This is very similar to other configuration widgets.
|
|
392
|
+
|
|
393
|
+@<SerialScaleConfWidget implementation@>=
|
|
394
|
+SerialScaleConfWidget::SerialScaleConfWidget(DeviceTreeModel *model,
|
|
395
|
+ const QModelIndex &index)
|
|
396
|
+: BasicDeviceConfigurationWidget(model, index),
|
|
397
|
+ port(new PortSelector), baud(new BaudSelector), parity(new ParitySelector),
|
|
398
|
+ flow(new FlowSelector), stop(new StopSelector)
|
|
399
|
+{
|
|
400
|
+ QFormLayout *layout = new QFormLayout;
|
|
401
|
+ layout->addRow(tr("Port:"), port);
|
|
402
|
+ connect(port, SIGNAL(currentIndexChanged(QString)),
|
|
403
|
+ this, SLOT(updatePort(QString)));
|
|
404
|
+ connect(port, SIGNAL(editTextChanged(QString)),
|
|
405
|
+ this, SLOT(updatePort(QString)));
|
|
406
|
+ layout->addRow(tr("Baud:"), baud);
|
|
407
|
+ connect(baud, SIGNAL(currentIndexChanged(QString)),
|
|
408
|
+ this, SLOT(updateBaudRate(QString)));
|
|
409
|
+ layout->addRow(tr("Parity:"), parity);
|
|
410
|
+ connect(parity, SIGNAL(currentIndexChanged(int)),
|
|
411
|
+ this, SLOT(updateParity(int)));
|
|
412
|
+ layout->addRow(tr("Flow Control:"), flow);
|
|
413
|
+ connect(flow, SIGNAL(currentIndexChanged(int)),
|
|
414
|
+ this, SLOT(updateFlowControl(int)));
|
|
415
|
+ layout->addRow(tr("Stop Bits:"), stop);
|
|
416
|
+ connect(stop, SIGNAL(currentIndexChanged(int)),
|
|
417
|
+ this, SLOT(updateStopBits(int)));
|
|
418
|
+ @<Get device configuration data for current node@>@;
|
|
419
|
+ for(int i = 0; i < configData.size(); i++)
|
|
420
|
+ {
|
|
421
|
+ node = configData.at(i).toElement();
|
|
422
|
+ if(node.attribute("name") == "port")
|
|
423
|
+ {
|
|
424
|
+ int j = port->findText(node.attribute("value"));
|
|
425
|
+ if(j >= 0)
|
|
426
|
+ {
|
|
427
|
+ port->setCurrentIndex(j);
|
|
428
|
+ }
|
|
429
|
+ else
|
|
430
|
+ {
|
|
431
|
+ port->insertItem(0, node.attribute("value"));
|
|
432
|
+ port->setCurrentIndex(0);
|
|
433
|
+ }
|
|
434
|
+ }
|
|
435
|
+ else if(node.attribute("name") == "baudrate")
|
|
436
|
+ {
|
|
437
|
+ baud->setCurrentIndex(baud->findText(node.attribute("value")));
|
|
438
|
+ }
|
|
439
|
+ else if(node.attribute("name") == "parity")
|
|
440
|
+ {
|
|
441
|
+ parity->setCurrentIndex(parity->findData(node.attribute("value")));
|
|
442
|
+ }
|
|
443
|
+ else if(node.attribute("name") == "flowcontrol")
|
|
444
|
+ {
|
|
445
|
+ flow->setCurrentIndex(flow->findData(node.attribute("value")));
|
|
446
|
+ }
|
|
447
|
+ else if(node.attribute("name") == "stopbits")
|
|
448
|
+ {
|
|
449
|
+ stop->setCurrentIndex(stop->findData(node.attribute("value")));
|
|
450
|
+ }
|
|
451
|
+ }
|
|
452
|
+ updatePort(port->currentText());
|
|
453
|
+ updateBaudRate(baud->currentText());
|
|
454
|
+ updateParity(parity->currentIndex());
|
|
455
|
+ updateFlowControl(flow->currentIndex());
|
|
456
|
+ updateStopBits(stop->currentIndex());
|
|
457
|
+ setLayout(layout);
|
|
458
|
+}
|
|
459
|
+
|
|
460
|
+@ Update methods are the same as were used in |ModbusRtuPortConfWidget|.
|
|
461
|
+
|
|
462
|
+@<SerialScaleConfWidget implementation@>=
|
|
463
|
+void SerialScaleConfWidget::updatePort(const QString &newPort)
|
|
464
|
+{
|
|
465
|
+ updateAttribute("port", newPort);
|
|
466
|
+}
|
|
467
|
+
|
|
468
|
+void SerialScaleConfWidget::updateBaudRate(const QString &rate)
|
|
469
|
+{
|
|
470
|
+ updateAttribute("baudrate", rate);
|
|
471
|
+}
|
|
472
|
+
|
|
473
|
+void SerialScaleConfWidget::updateParity(int index)
|
|
474
|
+{
|
|
475
|
+ updateAttribute("parity", parity->itemData(index).toString());
|
|
476
|
+}
|
|
477
|
+
|
|
478
|
+void SerialScaleConfWidget::updateFlowControl(int index)
|
|
479
|
+{
|
|
480
|
+ updateAttribute("flowcontrol", flow->itemData(index).toString());
|
|
481
|
+}
|
|
482
|
+
|
|
483
|
+void SerialScaleConfWidget::updateStopBits(int index)
|
|
484
|
+{
|
|
485
|
+ updateAttribute("stopbits", stop->itemData(index).toString());
|
|
486
|
+}
|
|
487
|
+
|
|
488
|
+@ The configuration widget is registered with the configuration system.
|
|
489
|
+
|
|
490
|
+@<Register device configuration widgets@>=
|
|
491
|
+app.registerDeviceConfigurationWidget("scale", SerialScaleConfWidget::staticMetaObject);
|
|
492
|
+
|
|
493
|
+@ A |NodeInserter| is also added.
|
|
494
|
+
|
|
495
|
+@<Register top level device configuration nodes@>=
|
|
496
|
+inserter = new NodeInserter(tr("Serial Scale"), tr("Scale"), "scale", NULL);
|
|
497
|
+topLevelNodeInserters.append(inserter);
|
|
498
|
+
|