qpidctrl  0.7.1
qpidmainwindow.cpp
Go to the documentation of this file.
1 #include "qpidmainwindow.h"
2 #include "ui_qpidmainwindow.h"
3 #include "qextserialenumerator.h"
4 #include <stdio.h>
5 #include "qwt_legend.h"
6 #include "qwt_symbol.h"
7 #include "qpidcontroller.h"
8 #include "qpiddevice.h"
9 #include "qpiddevicethread.h"
10 #include <QMessageBox>
11 #include <QCloseEvent>
12 #include <QFileDialog>
13 #include "qpiddebug.h"
14 #include <QTableWidgetItem>
15 #include "qpidlogger.h"
16 
18  QMainWindow(parent),
19  ui(new Ui::QPidMainWindow),
20  m_Controller(ctl),
21  m_DeviceDefaultMapper(new QSignalMapper(this))
22 {
23  ui->setupUi(this);
24 
25  ui->m_TemperatureGraph->init(m_Controller);
26 
27  QwtLegend *x = new QwtLegend(ui->m_TemperatureGraph);
28 
29  ui->m_TemperatureGraph->enableAxis(QwtPlot::yRight, true);
30  ui->m_TemperatureGraph->insertLegend(x, QwtPlot::BottomLegend);
31 
32 // QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
33 
34 // foreach(QextPortInfo port, ports) {
35 // printf("Port %s : %s : %s : %s : %x : %x\n",
36 // qPrintable(port.portName), qPrintable(port.friendName),
37 // qPrintable(port.physName), qPrintable(port.enumName),
38 // port.vendorID, port.productID);
39 // }
40 
41  connect(ui->m_ActionQuit, SIGNAL(triggered()), this, SLOT(quitApplication()));
42  connect(ui->m_ActionSettings, SIGNAL(triggered()), this, SLOT(editSettings()));
43  connect(ui->m_ActionChangeSetpoint, SIGNAL(triggered()), this, SLOT(changeSetpoint()));
44  connect(ui->m_ActionAutoTune, SIGNAL(triggered()), this, SLOT(autoTune()));
45  connect(ui->m_ActionRampTemperature, SIGNAL(triggered()), this, SLOT(rampTemperature()));
46  connect(ui->m_ActionConfigureGraph, SIGNAL(triggered()), this, SLOT(configureGraph()));
47  connect(ui->m_ActionDeviceConfiguration, SIGNAL(triggered()), this, SLOT(deviceConfiguration()));
48  connect(ui->m_ActionLoadSettings, SIGNAL(triggered()), this, SLOT(loadSettings()));
49  connect(ui->m_ActionSaveSettings, SIGNAL(triggered()), this, SLOT(saveSettings()));
50 
51  connect(ui->m_ActionAutoScaleGraph, SIGNAL(triggered()), ui->m_TemperatureGraph, SLOT(autoScale()));
52 
53  connect(ui->m_CommandInput, SIGNAL(returnPressed()), this, SLOT(commandEntered()));
54 
55  connect(ui->m_LoggingButton, SIGNAL(clicked()), this, SLOT(chooseLoggingFile()));
56 
58 
59  if (ctrl) {
60  ctrl->prop_RampPoint()->linkTo(ui->m_SetPointDisplay);
61  ctrl->prop_Temperature()->linkTo(ui->m_TemperatureDisplay);
62  ctrl->prop_OutputLevel()->linkTo(ui->m_OutputLevelDisplay);
63  ctrl->prop_Enabled()->linkTo(ui->m_Enabled);
64  ctrl->prop_LoopEnabled()->linkTo(ui->m_LoopEnabled);
65 
66  ctrl->prop_SetPoint()->linkTo(ui->m_TargetSetPoint);
67  ctrl->prop_RampRate()->linkTo(ui->m_RampRate);
68 
69  connect(ctrl->prop_ControllerStatus(), SIGNAL(valueChanged(int,int)),
70  this, SLOT(onControllerStatusChanged(int)));
71  }
72 
73  ui->m_StartControllerButton->setDefaultAction(ui->m_ActionStartController);
74  ui->m_StopControllerButton->setDefaultAction(ui->m_ActionStopController);
75  ui->m_RestartControllerButton->setDefaultAction(ui->m_ActionRestartController);
76 
77  connect(ui->m_ActionStartController, SIGNAL(triggered()), this, SLOT(onStartController()));
78  connect(ui->m_ActionStopController, SIGNAL(triggered()), this, SLOT(onStopController()));
79  connect(ui->m_ActionRestartController, SIGNAL(triggered()), this, SLOT(onRestartController()));
80 
81  ui->m_CreateDeviceButton->setDefaultAction(ui->m_ActionCreateNewDevice);
82  ui->m_DeleteDeviceButton->setDefaultAction(ui->m_ActionDeleteDevice);
83 
84  connect(ui->m_ActionCreateNewDevice, SIGNAL(triggered()), ui->m_DevicesList, SLOT(doCreateNewDevice()));
85  connect(ui->m_ActionDeleteDevice, SIGNAL(triggered()), ui->m_DevicesList, SLOT(doDeleteDevice()));
86 
87  if (ctrl) {
88  onControllerStatusChanged(ctrl->get_ControllerStatus());
89  }
90 
91  ui->m_DevicesList->setController(m_Controller);
92 
93  connect(m_Controller.data(), SIGNAL(deviceListChanged()), this, SLOT(updateDevicesMenu())/*, Qt::QueuedConnection*/);
94 
95  ui->m_TemperatureGraph->autoScale();
96 
97  ui->m_DevicesList->updateDevicesList();
98 
99  connect(m_DeviceDefaultMapper, SIGNAL(mapped(int)), ui->m_DevicesList, SLOT(doSetDefaultDevice(int)));
100 }
101 
103 {
104  delete ui;
105 }
106 
108 {
110 
111  if (ctrl) {
112  QPidLoggerPtr log = ctrl->logger();
113 
114  if (log) {
115  log->prop_Enabled()->linkTo(ui->m_LoggingIndicator);
116  log->prop_FileName()->linkTo(ui->m_LoggingPath);
117  }
118  }
119 }
120 
121 void QPidMainWindow::printMessage(QString msg, QDateTime ts)
122 {
123  if (QThread::currentThread() != thread()) {
124  QMetaObject::invokeMethod(this, "printMessage", Q_ARG(QString, msg), Q_ARG(QDateTime, ts));
125  } else {
126  ui->m_OutputMessages->append(ts.toString("yyyy MMM dd hh:mm:ss.zzz: ")+msg);
127  }
128 }
129 
131 {
132  if (QThread::currentThread() != thread()) {
133  QMetaObject::invokeMethod(this, "criticalMessage", Q_ARG(QString, msg));
134  } else {
135  ui->m_OutputMessages->append("Error: " + msg);
136  }
137 }
138 
140 {
141  close();
142 }
143 
144 void QPidMainWindow::closeEvent ( QCloseEvent * event )
145 {
146  if (wantToClose()) {
148 
149  if (ctrl) {
150  ctrl->writeSettings();
151  }
152 
153  event -> accept();
154  } else {
155  event -> ignore();
156  }
157 }
158 
160 {
161  THREAD_CHECK;
162 
163  return QMessageBox::question(this, tr("Really Close?"),
164  tr("Do you really want to close the window?"),
165  QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok;
166 }
167 
169 {
170 // if (m_SettingsDialog == NULL) {
172 // }
173 
174  if (m_SettingsDialog) {
175  m_SettingsDialog -> show();
176  m_SettingsDialog -> raise();
177  }
178 }
179 
181 {
183 
184  if (ctrl) {
185  QPidLoggerPtr log = ctrl->logger();
186 
187  if (log) {
188  QString filePath = QFileDialog::getSaveFileName(this, "Save Log File as...", log->get_FileName(), "Log File (*.log);; Any file (* *.*)");
189 
190  if (filePath != "") {
191  log->set_FileName(filePath);
192  }
193  }
194  }
195 }
196 
198 {
200 
201  if (ctrl) {
202  QString filePath = QFileDialog::getOpenFileName(this, "Load Settings from...", ctrl->settingsFilePath(), "QPIDCTRL Settings (*.qpset);; Any file (* *.*)");
203 
204  if (filePath != "") {
205  ctrl->loadSettings(filePath);
206  }
207  }
208 }
209 
211 {
213 
214  if (ctrl) {
215  QString filePath = QFileDialog::getSaveFileName(this, "Save Settings as...", ctrl->settingsFilePath(), "QPIDCTRL Settings (*.qpset);; Any file (* *.*)");
216 
217  if (filePath != "") {
218  ctrl->saveSettings(filePath);
219  }
220  }
221 }
222 
223 void QPidMainWindow::enableControllerActions(int canStart, int canStop, int canRestart)
224 {
225  ui->m_ActionStartController->setEnabled(canStart);
226  ui->m_ActionStopController->setEnabled(canStop);
227  ui->m_ActionRestartController->setEnabled(canRestart);
228 }
229 
231 {
233 
234  if (ctrl) {
235  QString statusString = ctrl->controllerStatusString(newStatus);
236 
237  ui->m_ControllerStatusLabel->setText(statusString);
238 
239  switch (newStatus) {
242  enableControllerActions(true, false, true);
243  break;
244 
247  enableControllerActions(false, true, true);
248  break;
249 
251  enableControllerActions(true, false, true);
252  break;
253 
255  enableControllerActions(true, false, true);
256  break;
257 
259  enableControllerActions(true, false, true);
260  break;
261 
262  }
263  }
264 }
265 
267 {
269 
270  if (ctrl) {
271  ctrl -> startController();
272  }
273 }
274 
276 {
278 
279  if (ctrl) {
280  ctrl -> stopController();
281  }
282 }
283 
285 {
287 
288  if (ctrl) {
289  ctrl -> restartController();
290  }
291 }
292 
294 {
295  QString cmd = ui->m_CommandInput->text();
296 
298 
299  if (ctrl) {
300  ctrl->executeCommand(cmd);
301  }
302 }
303 
305 {
306  if (m_SetPoint == NULL) {
308  }
309 
310  if (m_SetPoint) {
311  m_SetPoint -> show();
312  m_SetPoint -> raise();
313  }
314 }
315 
317 {
318  if (m_AutoTune == NULL) {
320  }
321 
322  if (m_AutoTune) {
323  m_AutoTune -> show();
324  m_AutoTune -> raise();
325  }
326 }
327 
329 {
330  if (m_Ramp == NULL) {
331  m_Ramp = new QPidRampDialog(m_Controller, this);
332  }
333 
334  if (m_Ramp) {
335  m_Ramp -> show();
336  m_Ramp -> raise();
337  }
338 }
339 
341 {
342  if (m_ConfigureGraph == NULL) {
344  }
345 
346  if (m_ConfigureGraph) {
347  m_ConfigureGraph -> show();
348  m_ConfigureGraph -> raise();
349  }
350 }
351 
353 {
355 
356  if (ctrl) {
357  QPidDevicePtr dev = ctrl->defaultDevice();
358 
359  if (dev) {
360  dev->configurationDialog();
361  }
362  }
363 }
364 
365 void QPidMainWindow::onInputChannelChanged(QString name, QString units)
366 {
367  if (name.length()) {
368  if (units.length()) {
369  ui->m_TemperatureLabel->setText(tr("Input : %1 (%2)").arg(name).arg(units));
370  } else {
371  ui->m_TemperatureLabel->setText(name);
372  }
373  }
374 }
375 
376 void QPidMainWindow::onOutputChannelChanged(QString name, QString units)
377 {
378  if (name.length()) {
379  if (units.length()) {
380  ui->m_OutputLevelLabel->setText(tr("Output : %1 (%2)").arg(name).arg(units));
381  } else {
382  ui->m_OutputLevelLabel->setText(name);
383  }
384  }
385 }
386 
387 static const int NPENS = 3;
388 static const int NSYMS = 4;
389 
390 static Qt::GlobalColor PenColors[NPENS] = { Qt::red, Qt::blue, Qt::green };
391 static QwtSymbol::Style Symbols[NSYMS] = { QwtSymbol::Ellipse, QwtSymbol::Cross, QwtSymbol::Diamond, QwtSymbol::Rect };
392 
393 QwtPlotCurve *QPidMainWindow::newPlotCurve(int n, QString title)
394 {
395  QwtPlotCurve *pc = new QwtPlotCurve(title);
396 
397  int npen = n % NPENS;
398  int nsym = (n / NPENS) % NSYMS;
399 
400  Qt::GlobalColor color = PenColors[npen];
401  QwtSymbol::Style symbl = Symbols[nsym];
402 
403  pc->setPen(QPen(color));
404 
405  QwtSymbol symb;
406 
407  symb.setStyle(symbl);
408  symb.setSize(5,5);
409  symb.setPen(QPen(color));
410  symb.setBrush(QBrush(color));
411 
412  pc->setSymbol(&symb);
413 
414  return pc;
415 }
416 
418 {
419  if (QThread::currentThread() != thread()) {
420  INVOKE_CHECK(QMetaObject::invokeMethod(this, "updateGraphCurves"));
421  } else {
422  if (qcepDebug(DEBUG_GRAPHER)) {
423  printMessage(tr("QPidMainWindow::updateGraphCurves()"));
424  }
425 
427 
428  if (ctrl) {
429  QStringList names = ctrl->get_ColumnNames();
430 
431  int n = names.length();
432  int cvidx = 0;
433 
434  ui->m_TemperatureGraph->detachItems(QwtPlotItem::Rtti_PlotCurve);
435  ui->m_TemperatureGraph->detachItems(QwtPlotItem::Rtti_PlotMarker);
436 
437  m_Curves.clear();
438 
439  for (int i=0+ctrl->m_SkippedColumns; i<n; i++) {
440  QString name = names.value(i);
441 
442  if (ctrl->yChecked(i)) {
443  QwtPlotCurve *pc = newPlotCurve(cvidx++, name);
444 
445  pc->setSamples(ctrl->m_PlottedValues.value(0), ctrl->m_PlottedValues.value(i));
446  pc->attach(ui->m_TemperatureGraph);
447 
448  m_Curves.append(pc);
449  }
450 
451  if (ctrl->y2Checked(i)) {
452  QwtPlotCurve *pc = newPlotCurve(cvidx++, name);
453 
454  pc->setSamples(ctrl->m_PlottedValues.value(0), ctrl->m_PlottedValues.value(i));
455  pc->setAxes(QwtPlot::xBottom, QwtPlot::yRight);
456  pc->attach(ui->m_TemperatureGraph);
457 
458  m_Curves.append(pc);
459  }
460  }
461 
462  ui->m_TemperatureGraph->replot();
463  }
464  }
465 }
466 
467 void QPidMainWindow::graphChannelNames(QStringList names)
468 {
469  if (QThread::currentThread() != thread()) {
470  INVOKE_CHECK(QMetaObject::invokeMethod(this, "graphChannelNames", Q_ARG(QStringList, names)));
471  } else {
472  if (qcepDebug(DEBUG_GRAPHER)) {
473  printMessage(tr("QPidMainWindow::graphChannelNames %1 ,...").arg(names.value(0)));
474  }
475 
476  disconnect(ui->m_ColumnList, SIGNAL(cellChanged(int,int)), this, SLOT(onGraphSelectionChanged(int,int)));
477 
479 
480  if (ctrl) {
481  int n = names.length();
482  int ns = ctrl->m_SkippedColumns;
483 
484  ui->m_ColumnList->setRowCount(n-ns);
485  ui->m_ColumnList->setColumnWidth(0, 120);
486  ui->m_ColumnList->setColumnWidth(1, 30);
487  ui->m_ColumnList->setColumnWidth(2, 30);
488 
489  for (int i=0+ctrl->m_SkippedColumns; i<n; i++) {
490  QString name = names.value(i);
491 
492  ui->m_ColumnList->setItem(i-ns,0, new QTableWidgetItem(name));
493  ui->m_ColumnList->setItem(i-ns,1, new QTableWidgetItem());
494  ui->m_ColumnList->setItem(i-ns,2, new QTableWidgetItem());
495 
496  ui->m_ColumnList->item(i-ns,0)->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable);
497  ui->m_ColumnList->item(i-ns,1)->setFlags(Qt::ItemIsEnabled|Qt::ItemIsUserCheckable);
498  ui->m_ColumnList->item(i-ns,2)->setFlags(Qt::ItemIsEnabled|Qt::ItemIsUserCheckable);
499 
500  ui->m_ColumnList->item(i-ns,1)->setCheckState(ctrl->yChecked(i));
501  ui->m_ColumnList->item(i-ns,2)->setCheckState(ctrl->y2Checked(i));
502  }
503  }
504 
506 
507  connect(ui->m_ColumnList, SIGNAL(cellChanged(int,int)), this, SLOT(onGraphSelectionChanged(int,int)));
508  }
509 }
510 
511 void QPidMainWindow::graphChannelValues(QcepDoubleList values)
512 {
513  if (QThread::currentThread() != thread()) {
514  INVOKE_CHECK(QMetaObject::invokeMethod(this, "graphChannelValues", Q_ARG(QcepDoubleList, values)));
515  } else {
516  if (qcepDebug(DEBUG_GRAPHER)) {
517  printMessage(tr("QPidMainWindow::graphChannelValues %1 ,...").arg(values.value(0)));
518  }
519 
520  int n= values.length();
521  int cvidx = 0;
522 
524 
525  if (ctrl) {
526  for (int i=0+ctrl->m_SkippedColumns; i<n; i++) {
527  if (ctrl->yChecked(i)) {
528  QwtPlotCurve *pc = m_Curves.value(cvidx++);
529 
530  if (pc) {
531  pc->setSamples(ctrl->m_PlottedValues.value(0), ctrl->m_PlottedValues.value(i));
532  }
533  }
534 
535  if (ctrl->y2Checked(i)) {
536  QwtPlotCurve *pc = m_Curves.value(cvidx++);
537 
538  if (pc) {
539  pc->setSamples(ctrl->m_PlottedValues.value(0), ctrl->m_PlottedValues.value(i));
540  }
541  }
542  }
543  }
544 
545  ui->m_TemperatureGraph->replot();
546  }
547 }
548 
550 {
551  if (qcepDebug(DEBUG_GRAPHER)) {
552  printMessage(tr("onGraphSelectionChanged(R%1,C%2)").arg(row).arg(col));
553  }
554 
556 
557  if (ctrl) {
558  if (col == 1) {
559  ctrl->setYChecked(row+ctrl->m_SkippedColumns, ui->m_ColumnList->item(row,col)->checkState());
560  } else if (col == 2) {
561  ctrl->setY2Checked(row+ctrl->m_SkippedColumns, ui->m_ColumnList->item(row,col)->checkState());
562  }
563 
565  }
566 }
567 
569 {
570  settings->beginWriteArray("splitters");
571 
572  int counter=0;
573  saveObjectSplitterState(this, settings, &counter);
574 
575  settings->endArray();
576 }
577 
579 {
580  int nsplitters = settings->beginReadArray("splitters");
581 
582  int counter=0;
583  restoreObjectSplitterState(this, settings, &counter, nsplitters);
584 
585  settings->endArray();
586 }
587 
588 void QPidMainWindow::saveObjectSplitterState(QObject *object, QPidSettings *settings, int *counter)
589 {
590  if (object) {
591  QSplitter *splitter = qobject_cast<QSplitter*>(object);
592 
593  if (splitter) {
594  if (counter) {
595  settings->setArrayIndex(*counter);
596  QByteArray state = splitter->saveState();
597 
598  settings->setValue("state", state);
599 
600  (*counter) += 1;
601  }
602  }
603 
604  foreach (QObject *obj, object->children()) {
605  if (obj) {
606  saveObjectSplitterState(obj, settings, counter);
607  }
608  }
609  }
610 }
611 
612 void QPidMainWindow::restoreObjectSplitterState(QObject *object, QPidSettings *settings, int *counter, int nsplitters)
613 {
614  if (object) {
615  QSplitter *splitter = qobject_cast<QSplitter*>(object);
616 
617  if (splitter) {
618  if (counter) {
619  settings->setArrayIndex(*counter);
620  QByteArray state = settings->value("state").toByteArray();
621 
622  Qt::Orientation orient = splitter->orientation();
623 
624  splitter->restoreState(state);
625 
626  splitter->setOrientation(orient);
627 
628  (*counter) += 1;
629  }
630  }
631 
632  foreach (QObject *obj, object->children()) {
633  if (obj) {
634  restoreObjectSplitterState(obj, settings, counter, nsplitters);
635  }
636  }
637  }
638 }
639 
640 #define STRINGIFY(s) _str(s)
641 #define _str(s) #s
642 
644 {
645  ui->m_MenuDefaultDevice->clear();
646 
648 
649  if (ctrl) {
650  for (int i=0; i<ctrl->countDevices(); i++) {
651  QPidDevicePtr dev = ctrl->getDevice(i);
652 
653  if (dev) {
654  QAction *select = new QAction(tr("%1: %2 : %3").arg(i).arg(dev->get_DeviceName()).arg(dev->get_DeviceLongTypeName()), NULL);
655 
656  connect(select, SIGNAL(triggered()), m_DeviceDefaultMapper, SLOT(map()));
657  m_DeviceDefaultMapper->setMapping(select, i);
658 
659  select->setCheckable(true);
660  select->setChecked(ctrl->get_DefaultDeviceNumber() == i);
661 
662  ui->m_MenuDefaultDevice->addAction(select);
663  }
664  }
665 
666  QPidDevicePtr dev = ctrl->defaultDevice();
667 
668  if (dev) {
669  QString desc = tr("%1 : %2")
670  .arg(dev->get_DeviceName())
671  .arg(dev->get_DeviceLongTypeName());
672 
673  setWindowTitle(tr("QPidCtrl : Device %1 : %2 : %3")
674  .arg(ctrl->get_DefaultDeviceNumber())
675  .arg(STRINGIFY(QPIDCTRL_VERSION))
676  .arg(desc));
677 
678  ui->m_ActionStartController->setToolTip(tr("Start Device %1").arg(desc));
679  ui->m_ActionStopController->setToolTip(tr("Halt Device %1").arg(desc));
680  ui->m_ActionRestartController->setToolTip(tr("Restart Device %1").arg(desc));
681  } else {
682  setWindowTitle(tr("QPidCtrl : %1 : No Controller")
683  .arg(STRINGIFY(QPIDCTRL_VERSION)));
684 
685  ui->m_ActionStartController->setToolTip(tr("Start Device"));
686  ui->m_ActionStopController->setToolTip(tr("Halt Device"));
687  ui->m_ActionRestartController->setToolTip(tr("Restart Device"));
688  }
689  }
690 }
void restoreSplitterState(QPidSettings *settings)
void closeEvent(QCloseEvent *event)
QPointer< QPidRampDialog > m_Ramp
void onGraphSelectionChanged(int row, int col)
void criticalMessage(QString msg)
QSharedPointer< QPidDevice > QPidDevicePtr
Definition: qpiddevice-ptr.h:6
void printMessage(QString msg, QDateTime ts=QDateTime::currentDateTime())
void enableControllerActions(int canStart, int canStop, int canRestart)
QWeakPointer< QPidController > QPidControllerWPtr
void onInputChannelChanged(QString name, QString units)
void saveSplitterState(QPidSettings *settings)
QSharedPointer< QPidLogger > QPidLoggerPtr
Definition: qpidlogger-ptr.h:6
QSharedPointer< QPidController > QPidControllerPtr
void onRestartController()
static const int NSYMS
void graphChannelNames(QStringList names)
QPointer< QPidSetPointDialog > m_SetPoint
QPidControllerWPtr m_Controller
QList< QwtPlotCurve * > m_Curves
#define STRINGIFY(s)
QwtPlotCurve * newPlotCurve(int n, QString title)
static Qt::GlobalColor PenColors[NPENS]
void saveObjectSplitterState(QObject *object, QPidSettings *settings, int *counter)
static QwtSymbol::Style Symbols[NSYMS]
void graphChannelValues(QcepDoubleList values)
QSignalMapper * m_DeviceDefaultMapper
void onOutputChannelChanged(QString name, QString units)
void deviceConfiguration()
QPidMainWindow(QPidControllerWPtr ctl, QWidget *parent=0)
QPointer< QPidAutoTuneDialog > m_AutoTune
static const int NPENS
Ui::QPidMainWindow * ui
QPointer< QPidConfigureGraphDialog > m_ConfigureGraph
void onControllerStatusChanged(int newStatus)
QPointer< QPidSettingsDialog > m_SettingsDialog
void restoreObjectSplitterState(QObject *object, QPidSettings *settings, int *counter, int nsplitters)