diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -10,3 +10,4 @@ 27b0354ca2c5ea7b3870156417ce7e04e799bbf7 fd5f1eb480ec372b49df58b497458de05c30057c v0.8.0 9c9a11cd15fd094e2b2b65dc51805fd8fd1d2460 v0.8.1 4cf9a1ee1f107a38e03dbe17c4f2882c43d827c9 v0.9.0 +ef003f7af8f37f760c22dae776f5ff8e1b526deb v0.9.1 diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ # along with serialplot. If not, see . # -cmake_minimum_required(VERSION 2.8.11) +cmake_minimum_required(VERSION 3.2.2) project(serialplot) @@ -161,25 +161,14 @@ else() message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif() -# get revision number from mercurial -find_program(MERCURIAL hg) +# default version +set(VERSION_STRING "0.9.1") +set(VERSION_REVISION "0") -if (MERCURIAL) - execute_process(COMMAND ${MERCURIAL} id -i - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE MERCURIAL_RESULT - OUTPUT_VARIABLE VERSION_REVISION - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT MERCURIAL_RESULT EQUAL 0) - set(VERSION_SCM_REVISION false) - endif(NOT MERCURIAL_RESULT EQUAL 0) -endif (MERCURIAL) +# get revision number from mercurial and parse version string +include(GetVersion) -if (NOT VERSION_REVISION) - set(VERSION_REVISION "0") -endif (NOT VERSION_REVISION) - -message("SCM revision: ${VERSION_REVISION}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_STRING=\\\"${VERSION_STRING}\\\" ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_REVISION=\\\"${VERSION_REVISION}\\\" ") # add make run target @@ -199,20 +188,19 @@ if (WIN32) install(FILES ${WINDOWS_INSTALL_LIBRARIES} DESTINATION bin) endif (WIN32) -# install menu item and icon +# prepare menu item and icon configure_file("${CMAKE_CURRENT_SOURCE_DIR}/misc/program_name.desktop.in" "${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.desktop") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/misc/program_name.png" "${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.png" COPYONLY) +set(DESKTOP_FILE ${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.desktop) +set(ICON_FILE ${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.png) + +# install menu item and icon if (UNIX) - # first copy files to share/serialplot/ - install(FILES - ${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.desktop - DESTINATION share/applications/) - install(FILES - ${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.png - DESTINATION share/icons/hicolor/256x256/apps/) + install(FILES ${DESKTOP_FILE} DESTINATION share/applications/) + install(FILES ${ICON_FILE} DESTINATION share/icons/hicolor/256x256/apps/) endif (UNIX) # uninstalling @@ -227,6 +215,8 @@ if (UNIX) endif (UNIX) # packaging +include(BuildLinuxAppImage) + if (UNIX) set(CPACK_GENERATOR "DEB") elseif (WIN32) @@ -238,9 +228,9 @@ include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_NAME "${PROGRAM_NAME}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Small and simple software for plotting data from serial port") set(CPACK_PACKAGE_CONTACT "Hasan Yavuz Özderya ") -set(CPACK_PACKAGE_VERSION_MAJOR ${MAJOR_VERSION}) -set(CPACK_PACKAGE_VERSION_MINOR ${MINOR_VERSION}) -set(CPACK_PACKAGE_VERSION_PATCH ${PATCH_VERSION}) +set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH}) set(CPACK_STRIP_FILES TRUE) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5widgets5 (>= 5.2.1), libqt5svg5 (>= 5.2.1), libqt5serialport5 (>= 5.2.1), libc6 (>= 2.19)") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Small and simple software for plotting data from serial port diff --git a/Dockerfile b/Dockerfile new file mode 100644 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM ubuntu:trusty + +WORKDIR /serialplot +ADD . /serialplot + +# Install build dependencies +RUN apt-get update +RUN apt-get -y install software-properties-common +RUN add-apt-repository -y ppa:beineri/opt-qt562-trusty +RUN add-apt-repository -y ppa:george-edison55/cmake-3.x +RUN apt-get update +RUN apt-get -y install build-essential mesa-common-dev qt56base qt56serialport cmake mercurial subversion git wget libfuse2 + +# Define environment variable +ENV PATH /opt/qt56/bin/:$PATH diff --git a/cmake/modules/BuildLinuxAppImage.cmake b/cmake/modules/BuildLinuxAppImage.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/BuildLinuxAppImage.cmake @@ -0,0 +1,36 @@ +# Based on: https://github.com/mhoeher/opentodolist + +set(LINUXDEPLOYQT_URL "https://github.com/probonopd/linuxdeployqt/releases/download/4/linuxdeployqt-4-x86_64.AppImage") +set(LINUXDEPLOYQT_TOOL ${CMAKE_CURRENT_BINARY_DIR}/linuxdeployqt-4-x86_64.AppImage) + +set(APPIMAGE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROGRAM_NAME}-${VERSION_STRING}-${CMAKE_HOST_SYSTEM_PROCESSOR}) + +add_custom_command( + OUTPUT + ${LINUXDEPLOYQT_TOOL} + COMMAND + wget ${LINUXDEPLOYQT_URL} + COMMAND + chmod a+x ${LINUXDEPLOYQT_TOOL}) + +add_custom_target( + appimage + + DEPENDS ${LINUXDEPLOYQT_TOOL} + + COMMAND + ${CMAKE_COMMAND} -E remove_directory ${APPIMAGE_DIR} + COMMAND + ${CMAKE_COMMAND} -E make_directory ${APPIMAGE_DIR} + COMMAND + ${CMAKE_COMMAND} -E copy $ ${APPIMAGE_DIR} + COMMAND + ${CMAKE_COMMAND} -E copy ${DESKTOP_FILE} ${APPIMAGE_DIR} + COMMAND + ${CMAKE_COMMAND} -E copy ${ICON_FILE} ${APPIMAGE_DIR} + COMMAND + ${CMAKE_COMMAND} -E env PATH=${QT_INSTALL_PREFIX}/bin:$ENV{PATH} ${LINUXDEPLOYQT_TOOL} + ${APPIMAGE_DIR}/${PROGRAM_NAME} -appimage + -always-overwrite -bundle-non-qt-libs -verbose=2 + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/cmake/modules/GetVersion.cmake b/cmake/modules/GetVersion.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/GetVersion.cmake @@ -0,0 +1,80 @@ +# +# Copyright © 2017 Hasan Yavuz Özderya +# +# This file is part of serialplot. +# +# serialplot is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the 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 of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with serialplot. If not, see . +# + +# try to get latest version from mercurial +find_program(HG hg) + +if (HG) + # get latest tag + execute_process(COMMAND ${HG} parents --template {latesttag} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE HG_RESULT + OUTPUT_VARIABLE HG_LATEST_TAG + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(HG_RESULT EQUAL 0) + if (NOT HG_LATEST_TAG MATCHES "v[0-9.]+") + unset(HG_LATEST_TAG) + endif() + else() + unset(HG_LATEST_TAG) + endif() + + # get revision + execute_process(COMMAND ${HG} id -i + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE HG_RESULT + OUTPUT_VARIABLE HG_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT HG_RESULT EQUAL 0) + unset(HG_REVISION) + endif(NOT HG_RESULT EQUAL 0) +endif (HG) + +# Try to get version from .hg_archival file +if (NOT HG_LATEST_TAG) + set(HG_ARCHIVAL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/.hg_archival.txt) + if (EXISTS ${HG_ARCHIVAL_FILE}) + # get latest tag + file(STRINGS ${HG_ARCHIVAL_FILE} HG_ARCHIVAL_LATEST_TAG REGEX "^latesttag:.+") + string(REGEX REPLACE "latesttag:[ \t]*(.+)" "\\1" HG_LATEST_TAG ${HG_ARCHIVAL_LATEST_TAG}) + + # get latest revision + file(STRINGS ${HG_ARCHIVAL_FILE} HG_ARCHIVAL_REV REGEX "^node:.+") + string(REGEX REPLACE "node:[ \t]*([a-fA-F0-9]+)" "\\1" HG_ARCHIVAL_REV ${HG_ARCHIVAL_REV}) + string(SUBSTRING ${HG_ARCHIVAL_REV} 0 12 HG_REVISION) + endif() +endif () + +# extract version information from tag (remove 'v' prefix) +if (HG_LATEST_TAG) + string(REPLACE "v" "" HG_VERSION ${HG_LATEST_TAG}) + message("Version from mercurial: ${HG_VERSION} (${HG_REVISION})") + + # replace version string + set(VERSION_STRING ${HG_VERSION}) + set(VERSION_REVISION ${HG_REVISION}) +else () + message("Failed to find version information from mercurial.") +endif () + +# parse version numbers +string(REPLACE "." ";" VERSION_LIST ${VERSION_STRING}) +list(GET VERSION_LIST 0 VERSION_MAJOR) +list(GET VERSION_LIST 1 VERSION_MINOR) +list(GET VERSION_LIST 2 VERSION_PATCH) diff --git a/src/channelinfomodel.cpp b/src/channelinfomodel.cpp --- a/src/channelinfomodel.cpp +++ b/src/channelinfomodel.cpp @@ -267,7 +267,7 @@ void ChannelInfoModel::setNumOfChannels( // remember user entered info if ((int) number > infos.length()) { - for (unsigned ci = _numOfChannels; ci < number; ci++) + for (unsigned ci = infos.length(); ci < number; ci++) { infos.append(ChannelInfo(ci)); } diff --git a/src/framebufferseries.cpp b/src/framebufferseries.cpp --- a/src/framebufferseries.cpp +++ b/src/framebufferseries.cpp @@ -25,6 +25,8 @@ FrameBufferSeries::FrameBufferSeries(Fra _xmin = 0; _xmax = 1; _buffer = buffer; + int_index_start = 0; + int_index_end = 0; } void FrameBufferSeries::setXAxis(bool asIndex, double xmin, double xmax) @@ -36,18 +38,19 @@ void FrameBufferSeries::setXAxis(bool as size_t FrameBufferSeries::size() const { - return _buffer->size(); + return int_index_end - int_index_start; } QPointF FrameBufferSeries::sample(size_t i) const { + i += int_index_start; if (xAsIndex) { return QPointF(i, _buffer->sample(i)); } else { - return QPointF(i * (_xmax - _xmin) / size() + _xmin, _buffer->sample(i)); + return QPointF(i * (_xmax - _xmin) / _buffer->size() + _xmin, _buffer->sample(i)); } } @@ -65,3 +68,22 @@ QRectF FrameBufferSeries::boundingRect() return rect; } } + +void FrameBufferSeries::setRectOfInterest(const QRectF& rect) +{ + if (xAsIndex) + { + int_index_start = rect.left(); + int_index_end = rect.right(); + } + else + { + double xsize = _xmax - _xmin; + size_t bsize = _buffer->size(); + int_index_start = bsize * (rect.left()-_xmin) / xsize; + int_index_end = bsize * (rect.right()-_xmin) / xsize; + } + + int_index_start = std::max(int_index_start, (size_t) 0); + int_index_end = std::min(_buffer->size(), int_index_end); +} diff --git a/src/framebufferseries.h b/src/framebufferseries.h --- a/src/framebufferseries.h +++ b/src/framebufferseries.h @@ -44,12 +44,16 @@ public: size_t size() const; QPointF sample(size_t i) const; QRectF boundingRect() const; + void setRectOfInterest(const QRectF& rect); private: FrameBuffer* _buffer; bool xAsIndex; double _xmin; double _xmax; + + size_t int_index_start; ///< starting index of "rectangle of interest" + size_t int_index_end; ///< ending index of "rectangle of interest" }; #endif // FRAMEBUFFERSERIES_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -139,7 +139,7 @@ MainWindow::MainWindow(QWidget *parent) this, &MainWindow::onNumOfSamplesChanged); connect(&plotControlPanel, &PlotControlPanel::numOfSamplesChanged, - plotMan, &PlotManager::onNumOfSamplesChanged); + plotMan, &PlotManager::setNumOfSamples); connect(&plotControlPanel, &PlotControlPanel::yScaleChanged, plotMan, &PlotManager::setYAxis); @@ -221,7 +221,7 @@ MainWindow::MainWindow(QWidget *parent) plotControlPanel.yMin(), plotControlPanel.yMax()); plotMan->setXAxis(plotControlPanel.xAxisAsIndex(), plotControlPanel.xMin(), plotControlPanel.xMax()); - plotMan->onNumOfSamplesChanged(numOfSamples); + plotMan->setNumOfSamples(numOfSamples); // Init sps (sample per second) counter spsLabel.setText("0sps"); @@ -490,6 +490,11 @@ void MainWindow::onExportCsv() } } +PlotViewSettings MainWindow::viewSettings() const +{ + return plotMan->viewSettings(); +} + void MainWindow::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) diff --git a/src/mainwindow.h b/src/mainwindow.h --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -58,6 +58,8 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); + PlotViewSettings viewSettings() const; + void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); diff --git a/src/plot.cpp b/src/plot.cpp --- a/src/plot.cpp +++ b/src/plot.cpp @@ -39,6 +39,7 @@ Plot::Plot(QWidget* parent) : isAutoScaled = true; symbolSize = 0; numOfSamples = 1; + showSymbols = Plot::ShowSymbolsAuto; QObject::connect(&zoomer, &Zoomer::unzoomed, this, &Plot::unzoomed); @@ -247,8 +248,38 @@ void Plot::flashSnapshotOverlay(bool lig }); } +void Plot::setSymbols(ShowSymbols shown) +{ + showSymbols = shown; + + if (showSymbols == Plot::ShowSymbolsAuto) + { + calcSymbolSize(); + } + else if (showSymbols == Plot::ShowSymbolsShow) + { + symbolSize = SYMBOL_SIZE_MAX; + } + else + { + symbolSize = 0; + } + + updateSymbols(); + replot(); +} + void Plot::onXScaleChanged() { + if (showSymbols == Plot::ShowSymbolsAuto) + { + calcSymbolSize(); + updateSymbols(); + } +} + +void Plot::calcSymbolSize() +{ auto sw = axisWidget(QwtPlot::xBottom); auto paintDist = sw->scaleDraw()->scaleMap().pDist(); auto scaleDist = sw->scaleDraw()->scaleMap().sDist(); @@ -265,8 +296,6 @@ void Plot::onXScaleChanged() { symbolSize = std::min(SYMBOL_SIZE_MAX, symDisPx-SYMBOL_SHOW_AT_WIDTH+1); } - - updateSymbols(); } void Plot::updateSymbols() @@ -297,7 +326,7 @@ void Plot::resizeEvent(QResizeEvent * ev onXScaleChanged(); } -void Plot::onNumOfSamplesChanged(unsigned value) +void Plot::setNumOfSamples(unsigned value) { numOfSamples = value; onXScaleChanged(); diff --git a/src/plot.h b/src/plot.h --- a/src/plot.h +++ b/src/plot.h @@ -40,6 +40,13 @@ class Plot : public QwtPlot friend class PlotManager; public: + enum ShowSymbols + { + ShowSymbolsAuto, + ShowSymbolsShow, + ShowSymbolsHide + }; + Plot(QWidget* parent = 0); ~Plot(); @@ -54,6 +61,7 @@ public slots: void darkBackground(bool enabled = true); void setYAxis(bool autoScaled, double yMin = 0, double yMax = 1); void setXAxis(double xMin, double xMax); + void setSymbols(ShowSymbols shown); /** * Displays an animation for snapshot. @@ -62,7 +70,7 @@ public slots: */ void flashSnapshotOverlay(bool light); - void onNumOfSamplesChanged(unsigned value); + void setNumOfSamples(unsigned value); protected: /// update the display of symbols depending on `symbolSize` @@ -80,9 +88,11 @@ private: PlotSnapshotOverlay* snapshotOverlay; QwtPlotLegendItem legend; QwtPlotTextLabel demoIndicator; + ShowSymbols showSymbols; void resetAxes(); void resizeEvent(QResizeEvent * event); + void calcSymbolSize(); private slots: void unzoomed(); diff --git a/src/plotmanager.cpp b/src/plotmanager.cpp --- a/src/plotmanager.cpp +++ b/src/plotmanager.cpp @@ -17,6 +17,9 @@ along with serialplot. If not, see . */ +#include +#include +#include #include "qwt_symbol.h" #include "plot.h" @@ -32,14 +35,17 @@ PlotManager::PlotManager(QWidget* plotAr unzoomAction("&Unzoom", this), darkBackgroundAction("&Dark Background", this), showLegendAction("&Legend", this), - showMultiAction("Multi &Plot", this) + showMultiAction("Multi &Plot", this), + setSymbolsAction("Symbols", this) { _autoScaled = true; _yMin = 0; _yMax = 1; + _xAxisAsIndex = true; isDemoShown = false; _infoModel = infoModel; _numOfSamples = 1; + showSymbols = Plot::ShowSymbolsAuto; // initalize layout and single widget isMulti = false; @@ -54,6 +60,7 @@ PlotManager::PlotManager(QWidget* plotAr darkBackgroundAction.setToolTip("Enable Dark Plot Background"); showLegendAction.setToolTip("Display the Legend on Plot"); showMultiAction.setToolTip("Display All Channels Separately"); + setSymbolsAction.setToolTip("Show/Hide symbols"); showGridAction.setShortcut(QKeySequence("G")); showMinorGridAction.setShortcut(QKeySequence("M")); @@ -72,6 +79,37 @@ PlotManager::PlotManager(QWidget* plotAr showMinorGridAction.setEnabled(false); + // setup symbols menu + setSymbolsAutoAct = setSymbolsMenu.addAction("Show When Zoomed"); + setSymbolsAutoAct->setCheckable(true); + setSymbolsAutoAct->setChecked(true); + connect(setSymbolsAutoAct, SELECT::OVERLOAD_OF(&QAction::triggered), + [this](bool checked) + { + if (checked) setSymbols(Plot::ShowSymbolsAuto); + }); + setSymbolsShowAct = setSymbolsMenu.addAction("Always Show"); + setSymbolsShowAct->setCheckable(true); + connect(setSymbolsShowAct, SELECT::OVERLOAD_OF(&QAction::triggered), + [this](bool checked) + { + if (checked) setSymbols(Plot::ShowSymbolsShow); + }); + setSymbolsHideAct = setSymbolsMenu.addAction("Always Hide"); + setSymbolsHideAct->setCheckable(true); + connect(setSymbolsHideAct, SELECT::OVERLOAD_OF(&QAction::triggered), + [this](bool checked) + { + if (checked) setSymbols(Plot::ShowSymbolsHide); + }); + setSymbolsAction.setMenu(&setSymbolsMenu); + + // add symbol actions to same group so that they appear as radio buttons + auto group = new QActionGroup(this); + group->addAction(setSymbolsAutoAct); + group->addAction(setSymbolsShowAct); + group->addAction(setSymbolsHideAct); + connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), this, &PlotManager::showGrid); connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered), @@ -252,6 +290,8 @@ Plot* PlotManager::addPlotWidget() plot->showLegend(showLegendAction.isChecked()); plot->showDemoIndicator(isDemoShown); plot->setYAxis(_autoScaled, _yMin, _yMax); + plot->setNumOfSamples(_numOfSamples); + plot->setSymbols(showSymbols); if (_xAxisAsIndex) { @@ -363,6 +403,7 @@ QList PlotManager::menuActions actions << &darkBackgroundAction; actions << &showLegendAction; actions << &showMultiAction; + actions << &setSymbolsAction; return actions; } @@ -415,6 +456,15 @@ void PlotManager::darkBackground(bool en } } +void PlotManager::setSymbols(Plot::ShowSymbols shown) +{ + showSymbols = shown; + for (auto plot : plotWidgets) + { + plot->setSymbols(shown); + } +} + void PlotManager::setYAxis(bool autoScaled, double yAxisMin, double yAxisMax) { _autoScaled = autoScaled; @@ -459,16 +509,57 @@ void PlotManager::flashSnapshotOverlay() } } -void PlotManager::onNumOfSamplesChanged(unsigned value) +void PlotManager::setNumOfSamples(unsigned value) { _numOfSamples = value; for (auto plot : plotWidgets) { - plot->onNumOfSamplesChanged(value); + plot->setNumOfSamples(value); if (_xAxisAsIndex) plot->setXAxis(0, value); } } +PlotViewSettings PlotManager::viewSettings() const +{ + return PlotViewSettings( + { + showGridAction.isChecked(), + showMinorGridAction.isChecked(), + darkBackgroundAction.isChecked(), + showLegendAction.isChecked(), + showMultiAction.isChecked(), + showSymbols + }); +} + +void PlotManager::setViewSettings(const PlotViewSettings& settings) +{ + showGridAction.setChecked(settings.showGrid); + showGrid(settings.showGrid); + showMinorGridAction.setChecked(settings.showMinorGrid); + showMinorGrid(settings.showMinorGrid); + darkBackgroundAction.setChecked(settings.darkBackground); + darkBackground(settings.darkBackground); + showLegendAction.setChecked(settings.showLegend); + showLegend(settings.showLegend); + showMultiAction.setChecked(settings.showMulti); + setMulti(settings.showMulti); + + setSymbols(settings.showSymbols); + if (showSymbols == Plot::ShowSymbolsAuto) + { + setSymbolsAutoAct->setChecked(true); + } + else if (showSymbols == Plot::ShowSymbolsShow) + { + setSymbolsShowAct->setChecked(true); + } + else + { + setSymbolsHideAct->setChecked(true); + } +} + void PlotManager::saveSettings(QSettings* settings) { settings->beginGroup(SettingGroup_Plot); @@ -477,6 +568,22 @@ void PlotManager::saveSettings(QSettings settings->setValue(SG_Plot_MinorGrid, showMinorGridAction.isChecked()); settings->setValue(SG_Plot_Legend, showLegendAction.isChecked()); settings->setValue(SG_Plot_MultiPlot, showMultiAction.isChecked()); + + QString showSymbolsStr; + if (showSymbols == Plot::ShowSymbolsAuto) + { + showSymbolsStr = "auto"; + } + else if (showSymbols == Plot::ShowSymbolsShow) + { + showSymbolsStr = "show"; + } + else + { + showSymbolsStr = "hide"; + } + settings->setValue(SG_Plot_Symbols, showSymbolsStr); + settings->endGroup(); } @@ -499,5 +606,27 @@ void PlotManager::loadSettings(QSettings showMultiAction.setChecked( settings->value(SG_Plot_MultiPlot, showMultiAction.isChecked()).toBool()); setMulti(showMultiAction.isChecked()); + + QString showSymbolsStr = settings->value(SG_Plot_Symbols, QString()).toString(); + if (showSymbolsStr == "auto") + { + setSymbols(Plot::ShowSymbolsAuto); + setSymbolsAutoAct->setChecked(true); + } + else if (showSymbolsStr == "show") + { + setSymbols(Plot::ShowSymbolsShow); + setSymbolsShowAct->setChecked(true); + } + else if (showSymbolsStr == "hide") + { + setSymbols(Plot::ShowSymbolsHide); + setSymbolsHideAct->setChecked(true); + } + else + { + qCritical() << "Invalid symbol setting:" << showSymbolsStr; + } + settings->endGroup(); } diff --git a/src/plotmanager.h b/src/plotmanager.h --- a/src/plotmanager.h +++ b/src/plotmanager.h @@ -26,12 +26,24 @@ #include #include #include +#include +#include #include #include "plot.h" #include "framebufferseries.h" #include "channelinfomodel.h" +struct PlotViewSettings +{ + bool showGrid; + bool showMinorGrid; + bool darkBackground; + bool showLegend; + bool showMulti; + Plot::ShowSymbols showSymbols; +}; + class PlotManager : public QObject { Q_OBJECT @@ -52,6 +64,10 @@ public: unsigned numOfCurves(); /// Returns the list of actions to be inserted into the `View` menu QList menuActions(); + /// Returns current status of menu actions + PlotViewSettings viewSettings() const; + /// Set the current state of view + void setViewSettings(const PlotViewSettings& settings); /// Stores plot settings into a `QSettings`. void saveSettings(QSettings* settings); /// Loads plot settings from a `QSettings`. @@ -71,7 +87,7 @@ public slots: /// Display an animation for snapshot void flashSnapshotOverlay(); /// Should be called to update zoom base - void onNumOfSamplesChanged(unsigned value); + void setNumOfSamples(unsigned value); private: bool isMulti; @@ -89,6 +105,7 @@ private: double _xMin; double _xMax; unsigned _numOfSamples; + Plot::ShowSymbols showSymbols; // menu actions QAction showGridAction; @@ -97,6 +114,11 @@ private: QAction darkBackgroundAction; QAction showLegendAction; QAction showMultiAction; + QAction setSymbolsAction; + QMenu setSymbolsMenu; + QAction* setSymbolsAutoAct; + QAction* setSymbolsShowAct; + QAction* setSymbolsHideAct; void setupLayout(bool multiPlot); /// Inserts a new plot widget to the current layout. @@ -105,6 +127,7 @@ private: Plot* plotWidget(unsigned curveIndex); /// Common part of overloaded `addCurve` functions void _addCurve(QwtPlotCurve* curve); + void setSymbols(Plot::ShowSymbols shown); private slots: void showGrid(bool show = true); diff --git a/src/setting_defines.h b/src/setting_defines.h --- a/src/setting_defines.h +++ b/src/setting_defines.h @@ -87,6 +87,7 @@ const char SG_Plot_Grid[] = "grid"; const char SG_Plot_MinorGrid[] = "minorGrid"; const char SG_Plot_Legend[] = "legend"; const char SG_Plot_MultiPlot[] = "multiPlot"; +const char SG_Plot_Symbols[] = "symbols"; // command setting keys const char SG_Commands_Command[] = "command"; diff --git a/src/snapshot.cpp b/src/snapshot.cpp --- a/src/snapshot.cpp +++ b/src/snapshot.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2015 Hasan Yavuz Özderya + Copyright © 2017 Hasan Yavuz Özderya This file is part of serialplot. @@ -21,10 +21,11 @@ #include #include +#include "mainwindow.h" #include "snapshot.h" #include "snapshotview.h" -Snapshot::Snapshot(QMainWindow* parent, QString name, ChannelInfoModel infoModel) : +Snapshot::Snapshot(MainWindow* parent, QString name, ChannelInfoModel infoModel) : QObject(parent), cInfoModel(infoModel), _showAction(this), diff --git a/src/snapshot.h b/src/snapshot.h --- a/src/snapshot.h +++ b/src/snapshot.h @@ -1,5 +1,5 @@ /* - Copyright © 2015 Hasan Yavuz Özderya + Copyright © 2017 Hasan Yavuz Özderya This file is part of serialplot. @@ -21,7 +21,6 @@ #define SNAPSHOT_H #include -#include #include #include #include @@ -30,13 +29,14 @@ #include "channelinfomodel.h" class SnapshotView; +class MainWindow; class Snapshot : public QObject { Q_OBJECT public: - Snapshot(QMainWindow* parent, QString name, ChannelInfoModel infoModel); + Snapshot(MainWindow* parent, QString name, ChannelInfoModel infoModel); ~Snapshot(); QVector> data; @@ -61,7 +61,7 @@ private: ChannelInfoModel cInfoModel; QAction _showAction; QAction _deleteAction; - QMainWindow* mainWindow; + MainWindow* mainWindow; SnapshotView* view; bool _saved; diff --git a/src/snapshotmanager.cpp b/src/snapshotmanager.cpp --- a/src/snapshotmanager.cpp +++ b/src/snapshotmanager.cpp @@ -27,9 +27,10 @@ #include #include +#include "mainwindow.h" #include "snapshotmanager.h" -SnapshotManager::SnapshotManager(QMainWindow* mainWindow, +SnapshotManager::SnapshotManager(MainWindow* mainWindow, ChannelManager* channelMan) : _menu("&Snapshots"), _takeSnapshotAction("&Take Snapshot", this), diff --git a/src/snapshotmanager.h b/src/snapshotmanager.h --- a/src/snapshotmanager.h +++ b/src/snapshotmanager.h @@ -1,5 +1,5 @@ /* - Copyright © 2015 Hasan Yavuz Özderya + Copyright © 2017 Hasan Yavuz Özderya This file is part of serialplot. @@ -28,12 +28,14 @@ #include "channelmanager.h" #include "snapshot.h" +class MainWindow; + class SnapshotManager : public QObject { Q_OBJECT public: - SnapshotManager(QMainWindow* mainWindow, ChannelManager* channelMan); + SnapshotManager(MainWindow* mainWindow, ChannelManager* channelMan); ~SnapshotManager(); QMenu* menu(); @@ -46,7 +48,7 @@ public: bool isAllSaved(); ///< returns `true` if all snapshots are saved to a file private: - QMainWindow* _mainWindow; + MainWindow* _mainWindow; ChannelManager* _channelMan; QList snapshots; diff --git a/src/snapshotview.cpp b/src/snapshotview.cpp --- a/src/snapshotview.cpp +++ b/src/snapshotview.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2015 Hasan Yavuz Özderya + Copyright © 2017 Hasan Yavuz Özderya This file is part of serialplot. @@ -20,7 +20,7 @@ #include "snapshotview.h" #include "ui_snapshotview.h" -SnapshotView::SnapshotView(QWidget *parent, Snapshot* snapshot) : +SnapshotView::SnapshotView(MainWindow* parent, Snapshot* snapshot) : QMainWindow(parent), ui(new Ui::SnapshotView), renameDialog(this) @@ -29,17 +29,20 @@ SnapshotView::SnapshotView(QWidget *pare ui->setupUi(this); - plotMan = new PlotManager(ui->plotArea, snapshot->infoModel()); + plotMan = new PlotManager(ui->plotArea, snapshot->infoModel(), this); + plotMan->setViewSettings(parent->viewSettings()); ui->menuSnapshot->insertAction(ui->actionClose, snapshot->deleteAction()); this->setWindowTitle(snapshot->displayName()); // initialize curves unsigned numOfChannels = snapshot->data.size(); + unsigned numOfSamples = snapshot->data[0].size(); for (unsigned ci = 0; ci < numOfChannels; ci++) { plotMan->addCurve(snapshot->channelName(ci), snapshot->data[ci]); } + plotMan->setNumOfSamples(numOfSamples); renameDialog.setWindowTitle("Rename Snapshot"); renameDialog.setLabelText("Enter new name:"); @@ -62,6 +65,7 @@ SnapshotView::~SnapshotView() { delete curve; } + delete plotMan; delete ui; } diff --git a/src/snapshotview.h b/src/snapshotview.h --- a/src/snapshotview.h +++ b/src/snapshotview.h @@ -1,5 +1,5 @@ /* - Copyright © 2015 Hasan Yavuz Özderya + Copyright © 2017 Hasan Yavuz Özderya This file is part of serialplot. @@ -29,6 +29,7 @@ #include #include +#include "mainwindow.h" #include "plotmanager.h" #include "snapshot.h" @@ -41,7 +42,7 @@ class SnapshotView : public QMainWindow Q_OBJECT public: - explicit SnapshotView(QWidget *parent, Snapshot* snapshot); + explicit SnapshotView(MainWindow* parent, Snapshot* snapshot); ~SnapshotView(); signals: diff --git a/src/version.h b/src/version.h --- a/src/version.h +++ b/src/version.h @@ -21,7 +21,8 @@ #define VERSION_H #ifndef VERSION_STRING -#define VERSION_STRING "0.9.0" +#warning VERSION_STRING not defined! +#define VERSION_STRING "0.0.0" #endif #ifndef VERSION_REVISION