1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3 #include "workerthread.h"
4 #include <QString>
5 #include <QClipboard>
6 #include <QAction>
7 #include <QMessageBox>
8 #include <QFileDialog>
9 #include <QDesktopServices>
10 #include <QtCharts/QChartView>
11 #include <QtCharts/QLineSeries>
12 #include <QtCharts/QValueAxis>
13 #include <QTimer>
14 #include <QTime>
15 #include <QThread>
16 #include <QInputDialog>
17 #include <QTextStream>
18 #include <iostream>
19 #include <lxi.h>
20 #include "../../include/config.h"
21 #include "../../include/scpi.h"
22 #include "../../include/benchmark.h"
23 #include "../../include/screenshot.h"
24 
25 extern void lxi_discover_(int timeout, lxi_discover_t type);
26 extern void benchmark_progress(void);
27 
28 QT_CHARTS_USE_NAMESPACE
29 
MainWindow(QWidget * parent)30 MainWindow::MainWindow(QWidget *parent) :
31     QMainWindow(parent),
32     ui(new Ui::MainWindow)
33 {
34     ui->setupUi(this);
35 
36     // Create message box for error messages etc.
37     messageBox = new QMessageBox(this);
38 
39     // Setup instrument table widget
40     ui->tableWidget_InstrumentList->setEditTriggers(QAbstractItemView::NoEditTriggers);
41     ui->tableWidget_InstrumentList->verticalHeader()->setVisible(false);
42     ui->tableWidget_InstrumentList->setShowGrid(false);
43     ui->tableWidget_InstrumentList->setContextMenuPolicy(Qt::ActionsContextMenu);
44     QAction* copyIDAction = new QAction("Copy ID", this);
45     QAction* copyIPAction = new QAction("Copy IP", this);
46     QAction* openBrowserAction = new QAction("Open in browser", this);
47     connect(copyIDAction, SIGNAL(triggered()), this, SLOT(InstrumentList_copyID()));
48     connect(copyIPAction, SIGNAL(triggered()), this, SLOT(InstrumentList_copyIP()));
49     connect(openBrowserAction, SIGNAL(triggered()), this, SLOT(InstrumentList_openBrowser()));
50     ui->tableWidget_InstrumentList->addAction(copyIDAction);
51     ui->tableWidget_InstrumentList->addAction(copyIPAction);
52     ui->tableWidget_InstrumentList->addAction(openBrowserAction);
53 
54     // Set up SCPI send action for line edit box
55     lineEdit = ui->comboBox_SCPI_Command->lineEdit();
56     connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(SCPIsendCommand()));
57 
58     // Setup Screenshot page
59     ui->graphicsView_Screenshot->setStyleSheet("background: transparent");
60     q_pixmap = new QPixmap(":/images/photo-camera.png");
61     scene = new QGraphicsScene();
62     ui->graphicsView_Screenshot->setScene(scene);
63     scene->addPixmap(*q_pixmap);
64     ui->graphicsView_Screenshot->show();
65     live_view_active = false;
66 
67     // Set up About page labels
68     ui->label_10->setText("<a href=\"https://lxi-tools.github.io/\"><span style=\"color:darkorange;\">Website</span></a>");
69     ui->label_10->setTextFormat(Qt::RichText);
70     ui->label_10->setTextInteractionFlags(Qt::TextBrowserInteraction);
71     ui->label_10->setOpenExternalLinks(true);
72     QString string_version;
73     string_version.sprintf("%s (BETA)", VERSION);
74     ui->label_11->setText(string_version);
75 
76     // Set search button icon
77     //ui->pushButton->setIcon(ui->pushButton->style()->standardIcon(QStyle::SP_DialogApplyButton));
78 
79     // Setup Data Recorder page
80     datarecorder_chart = new QChart();
81     datarecorder_chart->legend()->hide();
82     datarecorder_chart->setBackgroundVisible(false);
83     datarecorder_chart->setPlotAreaBackgroundVisible(true);
84     datarecorder_chart->setContentsMargins(0, 0, 0, 0);
85     datarecorder_chart->setBackgroundRoundness(0);
86     QBrush brush;
87     brush.setStyle(Qt::SolidPattern);
88     brush.setColor(Qt::white);
89     datarecorder_chart->setPlotAreaBackgroundBrush(brush);
90     line_series0 = new QLineSeries();
91     line_series1 = new QLineSeries();
92     line_series0->setName("Series 0");
93     line_series1->setName("Series 1");
94     datarecorder_chart->addSeries(line_series0);
95     datarecorder_chart->addSeries(line_series1);
96     axisX = new QValueAxis();
97     axisX->setTitleText("Time [s]");
98     datarecorder_chart->setAxisX(axisX, line_series0);
99     datarecorder_chart->setAxisX(axisX, line_series1);
100     axisX->setRange(0, 1);
101     axisY = new QValueAxis();
102     //axisY->setTitleText("Value");
103     datarecorder_chart->setAxisY(axisY, line_series0);
104     datarecorder_chart->setAxisY(axisY, line_series1);
105     axisY->setRange(0, 1);
106     //datarecorder_chart->setTitle("Data recorder chart");
107     ui->chartView->setChart(datarecorder_chart);
108     timer = new QTimer(this);
109     connect(timer, SIGNAL(timeout()), this, SLOT(DataRecorder_Update()));
110     data_recorder_active = false;
111     data_recorder_sample_counter = 0;
112     ui->chartView->setRenderHint(QPainter::Antialiasing);
113     ui->chartView->setRubberBand(QChartView::HorizontalRubberBand);
114     ui->chartView->setContextMenuPolicy(Qt::ActionsContextMenu);
115     QPalette pal;
116     pal.setColor(QPalette::Window, QColor(0,0,0,0));
117     ui->chartView->setPalette(pal);
118     ui->chartView->setBackgroundRole(QPalette::Window);
119     QAction* zoomInAction = new QAction("Zoom In", this);
120     QAction* zoomOutAction = new QAction("Zoom Out", this);
121     QAction* zoomResetAction = new QAction("Zoom Reset", this);
122     connect(zoomInAction, SIGNAL(triggered()), this, SLOT(DataRecorder_zoomIn()));
123     connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(DataRecorder_zoomOut()));
124     connect(zoomResetAction, SIGNAL(triggered()), this, SLOT(DataRecorder_zoomReset()));
125     ui->chartView->addAction(zoomInAction);
126     ui->chartView->addAction(zoomOutAction);
127     ui->chartView->addAction(zoomResetAction);
128     ui->pushButton_DataRecorder_Save->setEnabled(false);
129 
130     // Register screenshot plugins
131     screenshot_register_plugins();
132 }
133 
134 // Handle resize events
resizeEvent(QResizeEvent * event)135 void MainWindow::resizeEvent(QResizeEvent *event)
136 {
137     resize();
138     QMainWindow::resizeEvent(event);
139 }
140 
141 // Handle resize
resize()142 void MainWindow::resize()
143 {
144     ui->tableWidget_InstrumentList->setColumnWidth(0, ui->tableWidget_InstrumentList->width()*4/5);
145     ui->tableWidget_InstrumentList->setColumnWidth(1, ui->tableWidget_InstrumentList->width()/5-1);
146 }
147 
148 // Connect
LXI_connect()149 int MainWindow::LXI_connect()
150 {
151     int timeout = ui->spinBox_SCPITimeout->value() * 1000;
152     char *ip = (char *) IP.toUtf8().data();
153 
154     // Connect
155     lxi_device = lxi_connect(ip, 0, NULL, timeout, VXI11);
156     if (lxi_device == LXI_ERROR)
157     {
158         messageBox->critical(this, "Error", "Failed to connect!");
159         return -1;
160     }
161 
162     return 0;
163 }
164 
165 // Send command
LXI_send_receive(QString * command,QString * response,int timeout)166 int MainWindow::LXI_send_receive(QString *command, QString *response, int timeout)
167 {
168     char response_buffer[10000] = "";
169     char command_buffer[10000] = "";
170     int length;
171 
172     if (command->size() > 0)
173     {
174         // Prepare SCPI command string
175         strcpy(command_buffer, command->toUtf8().constData());
176         strip_trailing_space(command_buffer);
177 
178         // Send command
179         lxi_send(lxi_device, command_buffer, strlen(command_buffer), timeout);
180 
181         // If command is a question then receive response
182         if (question(command_buffer))
183         {
184             length = lxi_receive(lxi_device, response_buffer, 10000, timeout);
185             if (length < 0)
186             {
187                 messageBox->critical(this, "Error", "Failed to receive message!");
188                 lxi_disconnect(lxi_device);
189                 return -1;
190             }
191 
192             // Return response
193             *response = QString::fromStdString(response_buffer);
194         }
195     }
196 
197     return 0;
198 }
199 
200 // Disconnect
LXI_disconnect()201 int MainWindow::LXI_disconnect()
202 {
203     if (lxi_disconnect(lxi_device) != LXI_OK)
204         return -1;
205     else
206         return 0;
207 }
208 
SCPIsendCommand(QString * command)209 void MainWindow::SCPIsendCommand(QString *command)
210 {
211     int timeout = ui->spinBox_SCPITimeout->value() * 1000;
212     QString request, response;
213     int status;
214 
215     if (IP.isEmpty())
216     {
217         messageBox->warning(this, "Warning", "Please select instrument!");
218         return;
219     }
220 
221     LXI_connect();
222 
223     // Print request
224     request = "<span style=\" font-size:10pt; font-weight:600; color:#808080;\">";
225     request.append(*command);
226     request.append("<br></span>");
227     ui->textBrowser_SCPI_Response->insertHtml(request);
228     ui->textBrowser_SCPI_Response->ensureCursorVisible();
229 
230     status = LXI_send_receive(command, &response, timeout);
231     if (status == 0)
232     {
233         if (response.size() > 0)
234         {
235             // Print response
236             response.insert(0, "<span style=\" font-size:10pt; font-weight:600; color:#000000;\">");
237             response.append("<br></span>");
238             ui->textBrowser_SCPI_Response->insertHtml(response);
239             ui->textBrowser_SCPI_Response->ensureCursorVisible();
240         }
241 
242         LXI_disconnect();
243     }
244 }
245 
SCPIsendCommand()246 void MainWindow::SCPIsendCommand()
247 {
248     if (IP.isEmpty())
249     {
250         messageBox->warning(this, "Warning", "Please select instrument!");
251         return;
252     }
253 
254     QString command(ui->comboBox_SCPI_Command->currentText());
255     SCPIsendCommand(&command);
256 }
257 
SCPIsendCommand(const char * command)258 void MainWindow::SCPIsendCommand(const char *command)
259 {
260     if (IP.isEmpty())
261     {
262         messageBox->warning(this, "Warning", "Please select instrument!");
263         return;
264     }
265 
266     QString *command_ = new QString(command);
267     SCPIsendCommand(command_);
268 }
269 
InstrumentList_copyID()270 void MainWindow::InstrumentList_copyID()
271 {
272     QClipboard *clipboard = QApplication::clipboard();
273     QTableWidgetItem *item = ui->tableWidget_InstrumentList->item(ui->tableWidget_InstrumentList->currentRow(), 0);
274     clipboard->setText(item->text());
275 }
276 
InstrumentList_copyIP()277 void MainWindow::InstrumentList_copyIP()
278 {
279     QClipboard *clipboard = QApplication::clipboard();
280     QTableWidgetItem *item = ui->tableWidget_InstrumentList->item(ui->tableWidget_InstrumentList->currentRow(), 1);
281     clipboard->setText(item->text());
282 }
283 
InstrumentList_openBrowser()284 void MainWindow::InstrumentList_openBrowser()
285 {
286     QTableWidgetItem *item = ui->tableWidget_InstrumentList->item(ui->tableWidget_InstrumentList->currentRow(), 1);
287     QString URL = "http://" + item->text();
288     QDesktopServices::openUrl(QUrl(URL));
289 }
290 
~MainWindow()291 MainWindow::~MainWindow()
292 {
293     delete ui;
294 }
295 
296 // Search button
on_pushButton_Search_clicked()297 void MainWindow::on_pushButton_Search_clicked()
298 {
299     int timeout = ui->spinBox_SearchTimeout->value() * 1000;
300 
301     ui->tableWidget_InstrumentList->clearContents();
302     ui->tableWidget_InstrumentList->setRowCount(0);
303     ui->pushButton_Search->setText("Searching");
304     ui->pushButton_Search->repaint();
305     lxi_discover_(timeout, ui->checkBox_mDNS->isChecked() ? DISCOVER_MDNS : DISCOVER_VXI11);
306     ui->statusBar->clearMessage();
307     ui->pushButton_Search->setText("Search");
308     IP.clear();
309 }
310 
add_instrument(const char * id,const char * address)311 void MainWindow::add_instrument(const char *id, const char *address)
312 {
313     QString instrument_id = QString::fromStdString(id);
314     QString instrument_address = QString::fromStdString(address);
315 
316     ui->tableWidget_InstrumentList->insertRow(0);
317     ui->tableWidget_InstrumentList->setItem(0,0, new QTableWidgetItem(instrument_id));
318     ui->tableWidget_InstrumentList->setItem(0,1, new QTableWidgetItem(instrument_address));
319     ui->tableWidget_InstrumentList->item(0,1)->setTextAlignment(Qt::AlignCenter);
320 }
321 
update_statusbar(const char * message)322 void MainWindow::update_statusbar(const char *message)
323 {
324     QString status_message = QString::fromStdString(message);
325     ui->statusBar->showMessage(status_message);
326 }
327 
328 // SCPI Send button
on_pushButton_SCPI_Send_clicked()329 void MainWindow::on_pushButton_SCPI_Send_clicked()
330 {
331     SCPIsendCommand();
332 }
333 
on_tableWidget_InstrumentList_cellClicked(int row,int column)334 void MainWindow::on_tableWidget_InstrumentList_cellClicked(__attribute__((unused)) int row, __attribute__((unused)) int column)
335 {
336     QTableWidgetItem *item = ui->tableWidget_InstrumentList->item(ui->tableWidget_InstrumentList->currentRow(), 1);
337 
338     // Update IP
339     IP = item->text();
340 }
341 
update_progressbar()342 void MainWindow::update_progressbar()
343 {
344     ui->progressBar->setValue(ui->progressBar->value() + 1);
345 }
346 
347 // Benchmark start
on_pushButton_Benchmark_Start_clicked()348 void MainWindow::on_pushButton_Benchmark_Start_clicked()
349 {
350     double result;
351     QString q_result;
352     QMessageBox messageBox(this);
353 
354     if (IP.isEmpty())
355     {
356         messageBox.warning(this, "Warning", "Please select instrument!");
357         return;
358     }
359 
360     // Reset
361     ui->label_6->clear();
362     ui->progressBar->setValue(0);
363     ui->progressBar->setMaximum(ui->spinBox_BenchmarkRequests->value());
364 
365     // Run benchmark
366     ui->pushButton_Benchmark_Start->setText("Testing");
367     ui->pushButton_Benchmark_Start->repaint();
368     benchmark(IP.toUtf8().data(), 0, 1000, VXI11, ui->spinBox_BenchmarkRequests->value(), false, &result, benchmark_progress);
369     ui->pushButton_Benchmark_Start->setText("Start");
370     ui->pushButton_Benchmark_Start->repaint();
371 
372     // Print result
373     q_result = QString::number(result, 'f', 1);
374     ui->label_6->setText(q_result + " requests/second");
375 }
376 
Screenshot_UpdateUI(QPixmap pixmap,QString image_format,QString image_filename)377 void MainWindow::Screenshot_UpdateUI(QPixmap pixmap, QString image_format, QString image_filename)
378 {
379     // Update UI
380     // TODO: Refactor common screenshot code
381 
382     int width = ui->graphicsView_Screenshot->width();
383     int height = ui->graphicsView_Screenshot->height() - 2;
384 
385     screenshotImageFormat.clear();
386     screenshotImageFormat.append(image_format);
387 
388     screenshotImageFilename.clear();
389     screenshotImageFilename.append(image_filename);
390 
391     pixmap = pixmap.scaled(QSize(std::min(width, pixmap.width()), std::min(height, pixmap.height())), Qt::KeepAspectRatio, Qt::SmoothTransformation);
392     *q_pixmap = pixmap;
393 
394     if (!pixmapItem)
395         pixmapItem = scene->addPixmap(pixmap);
396     else
397         pixmapItem->setPixmap(pixmap);
398 
399     ui->graphicsView_Screenshot->show();
400 }
401 
402 // Live View
on_pushButton_Screenshot_LiveView_clicked()403 void MainWindow::on_pushButton_Screenshot_LiveView_clicked()
404 {
405     static WorkerThread *workerthread;
406     QMessageBox messageBox(this);
407 
408     if (IP.isEmpty())
409     {
410         messageBox.warning(this, "Warning", "Please select instrument!");
411         return;
412     }
413 
414     if (live_view_active)
415     {
416         // Stop live view
417 
418         // Wait for worker thread to finish
419         workerthread->live = false;
420         workerthread->wait();
421         delete workerthread;
422 
423         ui->pushButton_Screenshot_LiveView->setText("Live View");
424         ui->pushButton_Screenshot_LiveView->repaint();
425 
426         // Enable buttons
427         ui->pushButton_Screenshot_Save->setEnabled(true);
428         ui->pushButton_Screenshot_TakeScreenshot->setEnabled(true);
429 
430         live_view_active = false;
431     } else
432     {
433         // Start live view
434         ui->pushButton_Screenshot_LiveView->setText("Stop");
435         ui->pushButton_Screenshot_LiveView->repaint();
436 
437         // Disable buttons
438         ui->pushButton_Screenshot_Save->setEnabled(false);
439         ui->pushButton_Screenshot_TakeScreenshot->setEnabled(false);
440 
441         // Start worker thread
442         int timeout = ui->spinBox_ScreenshotTimeout->value() * 1000;
443         workerthread = new WorkerThread;
444         connect(workerthread, SIGNAL(requestUpdateUI(QPixmap, QString, QString)), this, SLOT(Screenshot_UpdateUI(QPixmap, QString, QString)));
445         workerthread->startLiveUpdate(IP, timeout);
446 
447         live_view_active = true;
448     }
449 }
450 
451 // Take screenshot
on_pushButton_Screenshot_TakeScreenshot_clicked()452 void MainWindow::on_pushButton_Screenshot_TakeScreenshot_clicked()
453 {
454     char image_buffer[0x200000];
455     int image_size = 0;
456     char image_format[10];
457     char image_filename[1000];
458     int timeout = ui->spinBox_ScreenshotTimeout->value() * 1000;
459 
460     QMessageBox messageBox(this);
461 
462     if (IP.isEmpty())
463     {
464         messageBox.warning(this, "Warning", "Please select instrument!");
465         return;
466     }
467 
468     // Capture screenshot
469     screenshot(IP.toUtf8().data(), "", "", timeout, false, image_buffer, &image_size, image_format, image_filename);
470 
471     screenshotImageFormat.clear();
472     screenshotImageFormat.append(image_format);
473 
474     screenshotImageFilename.clear();
475     screenshotImageFilename.append(image_filename);
476 
477     int width = ui->graphicsView_Screenshot->width();
478     int height = ui->graphicsView_Screenshot->height() - 2;
479 
480     q_pixmap->loadFromData((const uchar*) image_buffer, image_size, "", Qt::AutoColor);
481     *q_pixmap = q_pixmap->scaled(QSize(std::min(width, q_pixmap->width()), std::min(height, q_pixmap->height())), Qt::KeepAspectRatio, Qt::SmoothTransformation);
482 
483     if (!pixmapItem)
484         pixmapItem = scene->addPixmap(*q_pixmap);
485     else
486         pixmapItem->setPixmap(*q_pixmap);
487 
488     ui->graphicsView_Screenshot->show();
489 
490     // Enable buttons
491     ui->pushButton_Screenshot_Save->setEnabled(true);
492 }
493 
494 // Save screenshot
on_pushButton_Screenshot_Save_clicked()495 void MainWindow::on_pushButton_Screenshot_Save_clicked()
496 {
497     QString filename = QFileDialog::getSaveFileName(this, "Save file", screenshotImageFilename, "." + screenshotImageFormat);
498     QFile file(filename);
499     file.open(QIODevice::WriteOnly);
500     q_pixmap->save(&file, screenshotImageFormat.toUtf8().constData());
501     file.close();
502 }
503 
504 // *CLS
on_pushButton_SCPI_CLS_clicked()505 void MainWindow::on_pushButton_SCPI_CLS_clicked()
506 {
507     SCPIsendCommand("*CLS");
508 }
509 
510 // *ESE
on_pushButton_SCPI_ESE_clicked()511 void MainWindow::on_pushButton_SCPI_ESE_clicked()
512 {
513     QString command;
514     bool ok;
515     int i = QInputDialog::getInt(this, "*ESE <value>", "Value:", 0, 0, 255, 1, &ok);
516     if (ok)
517     {
518         command = tr("*ESE %1").arg(i);
519         SCPIsendCommand(&command);
520     }
521 }
522 
523 // *ESE?
on_pushButton_SCPI_ESEQuestion_clicked()524 void MainWindow::on_pushButton_SCPI_ESEQuestion_clicked()
525 {
526     SCPIsendCommand("*ESE?");
527 }
528 
529 // *ESR?
on_pushButton_SCPI_ESRQuestion_clicked()530 void MainWindow::on_pushButton_SCPI_ESRQuestion_clicked()
531 {
532     SCPIsendCommand("*ESR?");
533 }
534 
535 // *IDN?
on_pushButton_SCPI_IDNQuestion_clicked()536 void MainWindow::on_pushButton_SCPI_IDNQuestion_clicked()
537 {
538     SCPIsendCommand("*IDN?");
539 }
540 
541 // *OPC
on_pushButton_SCPI_OPC_clicked()542 void MainWindow::on_pushButton_SCPI_OPC_clicked()
543 {
544     SCPIsendCommand("*OPC");
545 }
546 
547 // *OPC?
on_pushButton_SCPI_OPCQuestion_clicked()548 void MainWindow::on_pushButton_SCPI_OPCQuestion_clicked()
549 {
550     SCPIsendCommand("*OPC?");
551 }
552 
553 // Blank button
on_pushButton_SCPI_Blank_clicked()554 void MainWindow::on_pushButton_SCPI_Blank_clicked()
555 {
556 }
557 
558 // *RST
on_pushButton_SCPI_RST_clicked()559 void MainWindow::on_pushButton_SCPI_RST_clicked()
560 {
561     SCPIsendCommand("*RST");
562 }
563 
564 // *SRE
on_pushButton_SCPI_SRE_clicked()565 void MainWindow::on_pushButton_SCPI_SRE_clicked()
566 {
567     QString command;
568     bool ok;
569     int i = QInputDialog::getInt(this, "*SRE <value>", "Value:", 0, 0, 255, 1, &ok);
570     if (ok)
571     {
572         command = tr("*SRE %1").arg(i);
573         SCPIsendCommand(&command);
574     }
575 }
576 
577 // *SRE?
on_pushButton_SCPI_SREQuestion_clicked()578 void MainWindow::on_pushButton_SCPI_SREQuestion_clicked()
579 {
580     SCPIsendCommand("*SRE?");
581 }
582 
583 // *STB?
on_pushButton_SCPI_STBQuestion_clicked()584 void MainWindow::on_pushButton_SCPI_STBQuestion_clicked()
585 {
586     SCPIsendCommand("*STB?");
587 }
588 
589 // *TST?
on_pushButton_SCPI_TSTQuestion_clicked()590 void MainWindow::on_pushButton_SCPI_TSTQuestion_clicked()
591 {
592     SCPIsendCommand("*TST?");
593 }
594 
595 // *WAI
on_pushButton_SCPI_WAI_clicked()596 void MainWindow::on_pushButton_SCPI_WAI_clicked()
597 {
598     SCPIsendCommand("*WAI");
599 }
600 
on_pushButton_SCPI_SystemVersionQuery_clicked()601 void MainWindow::on_pushButton_SCPI_SystemVersionQuery_clicked()
602 {
603     SCPIsendCommand(":SYSTem:VERSion?");
604 }
605 
on_pushButton_SCPI_SystemErrorQuery_clicked()606 void MainWindow::on_pushButton_SCPI_SystemErrorQuery_clicked()
607 {
608     SCPIsendCommand(":SYSTem:ERRor?");
609 }
610 
on_pushButton_SCPI_SystemErrorNextQuery_clicked()611 void MainWindow::on_pushButton_SCPI_SystemErrorNextQuery_clicked()
612 {
613     SCPIsendCommand(":SYSTem:ERRor:NEXT?");
614 }
615 
on_pushButton_SCPIP_StatusOperationQuery_clicked()616 void MainWindow::on_pushButton_SCPIP_StatusOperationQuery_clicked()
617 {
618     SCPIsendCommand(":STATus:OPERation?");
619 }
620 
on_pushButton_SCPI_StatusPreset_clicked()621 void MainWindow::on_pushButton_SCPI_StatusPreset_clicked()
622 {
623     SCPIsendCommand(":SYSTem:PRESet");
624 }
625 
626 // Data recorder start
on_pushButton_DataRecorder_Start_clicked()627 void MainWindow::on_pushButton_DataRecorder_Start_clicked()
628 {
629     if (IP.isEmpty())
630     {
631         messageBox->warning(this, "Warning", "Please select instrument!");
632         return;
633     }
634 
635     if (data_recorder_active)
636     {
637         // Stop recording
638         timer->stop();
639         ui->pushButton_DataRecorder_Start->setText("Start");
640         LXI_disconnect();
641 
642         // Enable inputs
643         ui->lineEdit->setEnabled(true);
644         ui->lineEdit_2->setEnabled(true);
645         if (line_series0->count() || line_series1->count())
646             ui->pushButton_DataRecorder_Save->setEnabled(true);
647         else
648             ui->pushButton_DataRecorder_Save->setEnabled(false);
649         ui->spinBox_DataRecorderRate->setEnabled(true);
650     }
651     else
652     {
653         // Reset
654         line_series0->clear();
655         line_series1->clear();
656         axisX->setRange(0, 1);
657         axisY->setRange(0, 1);
658         data_recorder_first_sample = true;
659         data_recorder_sample_counter = 0;
660 
661         // Start recording
662         time.start();
663         data_recorder_time_slice = 1000 / ui->spinBox_DataRecorderRate->value();
664         timer->start(data_recorder_time_slice);
665         ui->pushButton_DataRecorder_Start->setText("Stop");
666 
667         LXI_connect();
668 
669         // Disable inputs
670         ui->lineEdit->setEnabled(false);
671         ui->lineEdit_2->setEnabled(false);
672         ui->pushButton_DataRecorder_Save->setEnabled(false);
673         ui->spinBox_DataRecorderRate->setEnabled(false);
674     }
675 
676     ui->pushButton_DataRecorder_Start->repaint();
677 
678     data_recorder_active = !data_recorder_active;
679 }
680 
DataRecorder_Update()681 void MainWindow::DataRecorder_Update()
682 {
683     QString response;
684     double elapsed_time = 0;
685     double sample_max, sample0 = 0, sample1 = 0;
686 
687     if (!ui->lineEdit->text().isEmpty())
688     {
689         // Retrieve sample 1
690         QString command = ui->lineEdit->text();
691         LXI_send_receive(&command, &response, 1000);
692         elapsed_time = ((double) time.elapsed()) / 1000;
693         sample0 = response.toDouble();
694         line_series0->append(elapsed_time, sample0);
695     }
696 
697     if (!ui->lineEdit_2->text().isEmpty())
698     {
699         // Retrieve sample 2
700         QString command = ui->lineEdit_2->text();
701         LXI_send_receive(&command, &response, 1000);
702         elapsed_time = ((double) time.elapsed()) / 1000;
703         sample1 = response.toDouble();
704         line_series1->append(elapsed_time, sample1);
705     }
706 
707     // Update chart
708     sample_max = sample0 < sample1 ? sample1 : sample0;
709 
710     if (data_recorder_first_sample)
711     {
712         axisY->setMax(sample_max);
713         data_recorder_first_sample = false;
714     }
715 
716     if (sample_max > axisY->max())
717     {
718         axisY->setMax(sample_max);
719         axisY->applyNiceNumbers();
720     }
721 
722     axisX->setMax(elapsed_time);
723 
724     data_recorder_sample_counter++;
725 }
726 
727 // Data recorder save
on_pushButton_DataRecorder_Save_clicked()728 void MainWindow::on_pushButton_DataRecorder_Save_clicked()
729 {
730     int i;
731 
732     QString filename = QFileDialog::getSaveFileName(this, "Save file", "data.csv", "Text CSV (.csv)");
733     QFile file(filename);
734     file.open(QIODevice::WriteOnly|QFile::Truncate);
735     QTextStream stream(&file);
736     for (i=0;i<data_recorder_sample_counter; i++)
737     {
738         stream << line_series0->at(i).x();
739 
740         if (line_series0->count())
741             stream << "," << line_series0->at(i).y();
742 
743         if (line_series1->count())
744             stream << "," << line_series1->at(i).y();
745 
746         stream << "\n";
747     }
748     file.close();
749 }
750 
DataRecorder_zoomOut()751 void MainWindow::DataRecorder_zoomOut()
752 {
753     ui->chartView->chart()->zoomOut();
754 }
755 
DataRecorder_zoomIn()756 void MainWindow::DataRecorder_zoomIn()
757 {
758     ui->chartView->chart()->zoomIn();
759 }
760 
DataRecorder_zoomReset()761 void MainWindow::DataRecorder_zoomReset()
762 {
763     ui->chartView->chart()->zoomReset();
764 }
765 
on_pushButton_SCPI_Clear_clicked()766 void MainWindow::on_pushButton_SCPI_Clear_clicked()
767 {
768     ui->comboBox_SCPI_Command->lineEdit()->clear();
769 }
770