/*Copyright © 2017 Hasan Yavuz ÖzderyaThis file is part of serialplot.serialplot is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.serialplot is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with serialplot. If not, see <http://www.gnu.org/licenses/>.*/#include "mainwindow.h"#include "ui_mainwindow.h"#include <QByteArray>#include <QApplication>#include <QFileDialog>#include <QMessageBox>#include <QFile>#include <QTextStream>#include <QMenu>#include <QDesktopServices>#include <QMap>#include <QtDebug>#include <qwt_plot.h>#include <limits.h>#include <cmath>#include <iostream>#include <plot.h>#include <barplot.h>#include "framebufferseries.h"#include "utils.h"#include "defines.h"#include "version.h"#include "setting_defines.h"#if defined(Q_OS_WIN) && defined(QT_STATIC)#include <QtPlugin>Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)#endifconst QMap<int, QString> panelSettingMap({{0, "Port"},{1, "DataFormat"},{2, "Plot"},{3, "Commands"}});MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow),aboutDialog(this),portControl(&serialPort),channelMan(1, 1, this),secondaryPlot(NULL),snapshotMan(this, &channelMan),commandPanel(&serialPort),dataFormatPanel(&serialPort, &channelMan, &recorder),recordPanel(&recorder, &channelMan),updateCheckDialog(this){ui->setupUi(this);plotMan = new PlotManager(ui->plotArea, &plotMenu, channelMan.infoModel());ui->tabWidget->insertTab(0, &portControl, "Port");ui->tabWidget->insertTab(1, &dataFormatPanel, "Data Format");ui->tabWidget->insertTab(2, &plotControlPanel, "Plot");ui->tabWidget->insertTab(3, &commandPanel, "Commands");ui->tabWidget->insertTab(4, &recordPanel, "Record");ui->tabWidget->setCurrentIndex(0);auto tbPortControl = portControl.toolBar();addToolBar(tbPortControl);addToolBar(recordPanel.toolbar());ui->plotToolBar->addAction(snapshotMan.takeSnapshotAction());menuBar()->insertMenu(ui->menuHelp->menuAction(), snapshotMan.menu());menuBar()->insertMenu(ui->menuHelp->menuAction(), commandPanel.menu());connect(&commandPanel, &CommandPanel::focusRequested, [this](){this->ui->tabWidget->setCurrentWidget(&commandPanel);this->ui->tabWidget->showTabs();});tbPortControl->setObjectName("tbPortControl");ui->plotToolBar->setObjectName("tbPlot");setupAboutDialog();// init view menuui->menuBar->insertMenu(ui->menuSecondary->menuAction(), &plotMenu);plotMenu.addSeparator();QMenu* tbMenu = plotMenu.addMenu("Toolbars");tbMenu->addAction(ui->plotToolBar->toggleViewAction());tbMenu->addAction(portControl.toolBar()->toggleViewAction());// init secondary plot menuauto group = new QActionGroup(this);group->addAction(ui->actionVertical);group->addAction(ui->actionHorizontal);// init UI signals// Secondary plot menu signalsconnect(ui->actionBarPlot, &QAction::triggered,this, &MainWindow::showBarPlot);connect(ui->actionVertical, &QAction::triggered,[this](bool checked){if (checked) ui->splitter->setOrientation(Qt::Vertical);});connect(ui->actionHorizontal, &QAction::triggered,[this](bool checked){if (checked) ui->splitter->setOrientation(Qt::Horizontal);});// Help menu signalsQObject::connect(ui->actionHelpAbout, &QAction::triggered,&aboutDialog, &QWidget::show);QObject::connect(ui->actionCheckUpdate, &QAction::triggered,&updateCheckDialog, &QWidget::show);QObject::connect(ui->actionReportBug, &QAction::triggered,[](){QDesktopServices::openUrl(QUrl(BUG_REPORT_URL));});// File menu signalsQObject::connect(ui->actionExportCsv, &QAction::triggered,this, &MainWindow::onExportCsv);QObject::connect(ui->actionSaveSettings, &QAction::triggered,this, &MainWindow::onSaveSettings);QObject::connect(ui->actionLoadSettings, &QAction::triggered,this, &MainWindow::onLoadSettings);ui->actionQuit->setShortcutContext(Qt::ApplicationShortcut);QObject::connect(ui->actionQuit, &QAction::triggered,this, &MainWindow::close);// port control signalsQObject::connect(&portControl, &PortControl::portToggled,this, &MainWindow::onPortToggled);// plot control signalsconnect(&plotControlPanel, &PlotControlPanel::numOfSamplesChanged,this, &MainWindow::onNumOfSamplesChanged);connect(&plotControlPanel, &PlotControlPanel::numOfSamplesChanged,plotMan, &PlotManager::setNumOfSamples);connect(&plotControlPanel, &PlotControlPanel::yScaleChanged,plotMan, &PlotManager::setYAxis);connect(&plotControlPanel, &PlotControlPanel::xScaleChanged,plotMan, &PlotManager::setXAxis);connect(&plotControlPanel, &PlotControlPanel::plotWidthChanged,plotMan, &PlotManager::setPlotWidth);// plot toolbar signalsQObject::connect(ui->actionClear, SIGNAL(triggered(bool)),this, SLOT(clearPlot()));QObject::connect(snapshotMan.takeSnapshotAction(), &QAction::triggered,plotMan, &PlotManager::flashSnapshotOverlay);// init data format and readerQObject::connect(&channelMan, &ChannelManager::dataAdded,plotMan, &PlotManager::replot);QObject::connect(ui->actionPause, &QAction::triggered,&channelMan, &ChannelManager::pause);QObject::connect(&recordPanel, &RecordPanel::recordStarted,&dataFormatPanel, &DataFormatPanel::startRecording);QObject::connect(&recordPanel, &RecordPanel::recordStopped,&dataFormatPanel, &DataFormatPanel::stopRecording);QObject::connect(ui->actionPause, &QAction::triggered,[this](bool enabled){if (enabled && !recordPanel.recordPaused()){dataFormatPanel.pause(true);}else{dataFormatPanel.pause(false);}});QObject::connect(&recordPanel, &RecordPanel::recordPausedChanged,[this](bool enabled){if (ui->actionPause->isChecked() && enabled){dataFormatPanel.pause(false);}});connect(&serialPort, &QIODevice::aboutToClose,&recordPanel, &RecordPanel::onPortClose);// init data arrays and plotnumOfSamples = plotControlPanel.numOfSamples();unsigned numOfChannels = dataFormatPanel.numOfChannels();channelMan.setNumOfSamples(numOfSamples);channelMan.setNumOfChannels(dataFormatPanel.numOfChannels());connect(&dataFormatPanel, &DataFormatPanel::numOfChannelsChanged,&channelMan, &ChannelManager::setNumOfChannels);connect(&channelMan, &ChannelManager::numOfChannelsChanged,this, &MainWindow::onNumOfChannelsChanged);plotControlPanel.setChannelInfoModel(channelMan.infoModel());// init curve listfor (unsigned int i = 0; i < numOfChannels; i++){plotMan->addCurve(channelMan.channelName(i), channelMan.channelBuffer(i));}// init scalesplotMan->setYAxis(plotControlPanel.autoScale(),plotControlPanel.yMin(), plotControlPanel.yMax());plotMan->setXAxis(plotControlPanel.xAxisAsIndex(),plotControlPanel.xMin(), plotControlPanel.xMax());plotMan->setNumOfSamples(numOfSamples);plotMan->setPlotWidth(plotControlPanel.plotWidth());// Init sps (sample per second) counterspsLabel.setText("0sps");spsLabel.setToolTip("samples per second (per channel)");ui->statusBar->addPermanentWidget(&spsLabel);QObject::connect(&dataFormatPanel,&DataFormatPanel::samplesPerSecondChanged,this, &MainWindow::onSpsChanged);// init demoQObject::connect(ui->actionDemoMode, &QAction::toggled,this, &MainWindow::enableDemo);QObject::connect(ui->actionDemoMode, &QAction::toggled,plotMan, &PlotManager::showDemoIndicator);// load default settingsQSettings settings("serialplot", "serialplot");loadAllSettings(&settings);// ensure command panel has 1 command if none loadedif (!commandPanel.numOfCommands()){commandPanel.newCommandAction()->trigger();}// Important: This should be after newCommandAction is triggered// (above) we don't want user to be greeted with command panel on// the very first run.connect(commandPanel.newCommandAction(), &QAction::triggered, [this](){this->ui->tabWidget->setCurrentWidget(&commandPanel);this->ui->tabWidget->showTabs();});}MainWindow::~MainWindow(){if (serialPort.isOpen()){serialPort.close();}delete plotMan;delete ui;ui = NULL; // we check if ui is deleted in messageHandler}void MainWindow::closeEvent(QCloseEvent * event){// save snapshotsif (!snapshotMan.isAllSaved()){auto clickedButton = QMessageBox::warning(this, "Closing SerialPlot","There are un-saved snapshots. If you close you will loose the data.",QMessageBox::Discard, QMessageBox::Cancel);if (clickedButton == QMessageBox::Cancel){event->ignore();return;}}// save settingsQSettings settings("serialplot", "serialplot");saveAllSettings(&settings);settings.sync();if (settings.status() != QSettings::NoError){QString errorText;if (settings.status() == QSettings::AccessError){QString file = settings.fileName();errorText = QString("Serialplot cannot save settings due to access error. \This happens if you have run serialplot as root (with sudo for ex.) previously. \Try fixing the permissions of file: %1, or just delete it.").arg(file);}else{errorText = QString("Serialplot cannot save settings due to unknown error: %1").\arg(settings.status());}auto button = QMessageBox::critical(NULL,"Failed to save settings!", errorText,QMessageBox::Cancel | QMessageBox::Ok);if (button == QMessageBox::Cancel){event->ignore();return;}}QMainWindow::closeEvent(event);}void MainWindow::setupAboutDialog(){Ui_AboutDialog uiAboutDialog;uiAboutDialog.setupUi(&aboutDialog);QObject::connect(uiAboutDialog.pbAboutQt, &QPushButton::clicked,[](){ QApplication::aboutQt();});QString aboutText = uiAboutDialog.lbAbout->text();aboutText.replace("$VERSION_STRING$", VERSION_STRING);aboutText.replace("$VERSION_REVISION$", VERSION_REVISION);uiAboutDialog.lbAbout->setText(aboutText);}void MainWindow::onPortToggled(bool open){// make sure demo mode is disabledif (open && isDemoRunning()) enableDemo(false);ui->actionDemoMode->setEnabled(!open);}void MainWindow::clearPlot(){for (unsigned ci = 0; ci < channelMan.numOfChannels(); ci++){channelMan.channelBuffer(ci)->clear();}plotMan->replot();}void MainWindow::onNumOfSamplesChanged(int value){numOfSamples = value;channelMan.setNumOfSamples(value);plotMan->replot();}void MainWindow::onNumOfChannelsChanged(unsigned value){unsigned int oldNum = plotMan->numOfCurves();unsigned numOfChannels = value;if (numOfChannels > oldNum){// add new channelsfor (unsigned int i = oldNum; i < numOfChannels; i++){plotMan->addCurve(channelMan.channelName(i), channelMan.channelBuffer(i));}}else if(numOfChannels < oldNum){plotMan->removeCurves(oldNum - numOfChannels);}plotMan->replot();}void MainWindow::onSpsChanged(unsigned sps){spsLabel.setText(QString::number(sps) + "sps");}bool MainWindow::isDemoRunning(){return ui->actionDemoMode->isChecked();}void MainWindow::enableDemo(bool enabled){if (enabled){if (!serialPort.isOpen()){dataFormatPanel.enableDemo(true);}else{ui->actionDemoMode->setChecked(false);}}else{dataFormatPanel.enableDemo(false);ui->actionDemoMode->setChecked(false);}}void MainWindow::showSecondary(QWidget* wid){if (secondaryPlot != NULL){secondaryPlot->deleteLater();}secondaryPlot = wid;ui->splitter->addWidget(wid);ui->splitter->setStretchFactor(0, 1);ui->splitter->setStretchFactor(1, 0);}void MainWindow::hideSecondary(){if (secondaryPlot == NULL){qFatal("Secondary plot doesn't exist!");}secondaryPlot->deleteLater();secondaryPlot = NULL;}void MainWindow::showBarPlot(bool show){if (show){auto plot = new BarPlot(&channelMan, &plotMenu);plot->setYAxis(plotControlPanel.autoScale(),plotControlPanel.yMin(),plotControlPanel.yMax());connect(&plotControlPanel, &PlotControlPanel::yScaleChanged,plot, &BarPlot::setYAxis);showSecondary(plot);}else{hideSecondary();}}void MainWindow::onExportCsv(){bool wasPaused = ui->actionPause->isChecked();ui->actionPause->setChecked(true); // pause plottingQString fileName = QFileDialog::getSaveFileName(this, tr("Export CSV File"));if (fileName.isNull()) // user canceled export{ui->actionPause->setChecked(wasPaused);}else{Snapshot* snapshot = snapshotMan.makeSnapshot();snapshot->save(fileName);delete snapshot;}}PlotViewSettings MainWindow::viewSettings() const{return plotMenu.viewSettings();}void MainWindow::messageHandler(QtMsgType type,const QMessageLogContext &context,const QString &msg){QString logString;switch (type){#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))case QtInfoMsg:logString = "[Info] " + msg;break;#endifcase QtDebugMsg:logString = "[Debug] " + msg;break;case QtWarningMsg:logString = "[Warning] " + msg;break;case QtCriticalMsg:logString = "[Error] " + msg;break;case QtFatalMsg:logString = "[Fatal] " + msg;break;}if (ui != NULL) ui->ptLog->appendPlainText(logString);std::cerr << logString.toStdString() << std::endl;if (type != QtDebugMsg && ui != NULL){ui->statusBar->showMessage(msg, 5000);}if (type == QtFatalMsg){__builtin_trap();}}void MainWindow::saveAllSettings(QSettings* settings){saveMWSettings(settings);portControl.saveSettings(settings);dataFormatPanel.saveSettings(settings);channelMan.saveSettings(settings);plotControlPanel.saveSettings(settings);plotMenu.saveSettings(settings);commandPanel.saveSettings(settings);recordPanel.saveSettings(settings);updateCheckDialog.saveSettings(settings);}void MainWindow::loadAllSettings(QSettings* settings){loadMWSettings(settings);portControl.loadSettings(settings);dataFormatPanel.loadSettings(settings);channelMan.loadSettings(settings);plotControlPanel.loadSettings(settings);plotMenu.loadSettings(settings);commandPanel.loadSettings(settings);recordPanel.loadSettings(settings);updateCheckDialog.loadSettings(settings);}void MainWindow::saveMWSettings(QSettings* settings){// save window geometrysettings->beginGroup(SettingGroup_MainWindow);settings->setValue(SG_MainWindow_Size, size());settings->setValue(SG_MainWindow_Pos, pos());// save active panelsettings->setValue(SG_MainWindow_ActivePanel,panelSettingMap.value(ui->tabWidget->currentIndex()));// save panel minimizationsettings->setValue(SG_MainWindow_HidePanels,ui->tabWidget->hideAction.isChecked());// save window maximized statesettings->setValue(SG_MainWindow_Maximized,bool(windowState() & Qt::WindowMaximized));// save toolbar/dockwidgets statesettings->setValue(SG_MainWindow_State, saveState());settings->endGroup();}void MainWindow::loadMWSettings(QSettings* settings){settings->beginGroup(SettingGroup_MainWindow);// load window geometryresize(settings->value(SG_MainWindow_Size, size()).toSize());move(settings->value(SG_MainWindow_Pos, pos()).toPoint());// set active panelQString tabSetting =settings->value(SG_MainWindow_ActivePanel, QString()).toString();ui->tabWidget->setCurrentIndex(panelSettingMap.key(tabSetting, ui->tabWidget->currentIndex()));// hide panelsui->tabWidget->hideAction.setChecked(settings->value(SG_MainWindow_HidePanels,ui->tabWidget->hideAction.isChecked()).toBool());// maximize windowif (settings->value(SG_MainWindow_Maximized).toBool()){showMaximized();}// load toolbar/dockwidgets staterestoreState(settings->value(SG_MainWindow_State).toByteArray());settings->setValue(SG_MainWindow_State, saveState());settings->endGroup();}void MainWindow::onSaveSettings(){QString fileName = QFileDialog::getSaveFileName(this, tr("Save Settings"), QString(), "INI (*.ini)");if (!fileName.isNull()) // user canceled{QSettings settings(fileName, QSettings::IniFormat);saveAllSettings(&settings);}}void MainWindow::onLoadSettings(){QString fileName = QFileDialog::getOpenFileName(this, tr("Load Settings"), QString(), "INI (*.ini)");if (!fileName.isNull()) // user canceled{QSettings settings(fileName, QSettings::IniFormat);loadAllSettings(&settings);}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。