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