diff --git a/src/plotmanager.cpp b/src/plotmanager.cpp
new file mode 100644
--- /dev/null
+++ b/src/plotmanager.cpp
@@ -0,0 +1,366 @@
+/*
+  Copyright © 2016 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 .
+*/
+
+#include 
+
+#include "plot.h"
+#include "plotmanager.h"
+#include "utils.h"
+
+
+PlotManager::PlotManager(QWidget* plotArea, QObject *parent) :
+    QObject(parent),
+    _plotArea(plotArea),
+    showGridAction("Grid", this),
+    showMinorGridAction("Minor Grid", this),
+    unzoomAction("Unzoom", this),
+    darkBackgroundAction("Dark Background", this),
+    showLegendAction("Legend", this),
+    showMultiAction("Multi Plot", this)
+{
+    _autoScaled = true;
+    _yMin = 0;
+    _yMax = 1;
+    isDemoShown = false;
+
+    // initalize layout and single widget
+    isMulti = false;
+    scrollArea = NULL;
+    setupLayout(isMulti);
+    addPlotWidget();
+
+    // initialize menu actions
+    showGridAction.setToolTip("Show Grid");
+    showMinorGridAction.setToolTip("Show Minor Grid");
+    unzoomAction.setToolTip("Unzoom the Plot");
+    darkBackgroundAction.setToolTip("Enable Dark Plot Background");
+    showLegendAction.setToolTip("Display the Legend on Plot");
+    showMultiAction.setToolTip("Display All Channels Separately");
+
+    showGridAction.setShortcut(QKeySequence("G"));
+    showMinorGridAction.setShortcut(QKeySequence("M"));
+
+    showGridAction.setCheckable(true);
+    showMinorGridAction.setCheckable(true);
+    darkBackgroundAction.setCheckable(true);
+    showLegendAction.setCheckable(true);
+    showMultiAction.setCheckable(true);
+
+    showGridAction.setChecked(false);
+    showMinorGridAction.setChecked(false);
+    darkBackgroundAction.setChecked(false);
+    showLegendAction.setChecked(true);
+    showMultiAction.setChecked(false);
+
+    showMinorGridAction.setEnabled(false);
+
+    connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            this, &PlotManager::showGrid);
+    connect(&showGridAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            &showMinorGridAction, &QAction::setEnabled);
+    connect(&showMinorGridAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            this, &PlotManager::showMinorGrid);
+    connect(&unzoomAction, &QAction::triggered, this, &PlotManager::unzoom);
+    connect(&darkBackgroundAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            this, &PlotManager::darkBackground);
+    connect(&showLegendAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            this, &PlotManager::showLegend);
+    connect(&showLegendAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            this, &PlotManager::showLegend);
+    connect(&showMultiAction, SELECT::OVERLOAD_OF(&QAction::triggered),
+            this, &PlotManager::setMulti);
+}
+
+PlotManager::~PlotManager()
+{
+    while (curves.size())
+    {
+        delete curves.takeLast();
+    }
+
+    // remove all widgets
+    while (plotWidgets.size())
+    {
+        delete plotWidgets.takeLast();
+    }
+
+    if (scrollArea != NULL) delete scrollArea;
+}
+
+void PlotManager::setMulti(bool enabled)
+{
+    if (enabled == isMulti) return;
+
+    isMulti = enabled;
+
+    // detach all curves
+    for (auto curve : curves)
+    {
+        curve->detach();
+    }
+
+    // remove all widgets
+    while (plotWidgets.size())
+    {
+        delete plotWidgets.takeLast();
+    }
+
+    // setup new layout
+    setupLayout(isMulti);
+
+    if (isMulti)
+    {
+        // add new widgets and attach
+        for (auto curve : curves)
+        {
+            curve->attach(addPlotWidget());
+        }
+    }
+    else
+    {
+        // add a single widget
+        auto plot = addPlotWidget();
+
+        // attach all curves
+        for (auto curve : curves)
+        {
+            curve->attach(plot);
+        }
+    }
+}
+
+void PlotManager::setupLayout(bool multiPlot)
+{
+    // delete previous layout if it exists
+    if (_plotArea->layout() != 0)
+    {
+        delete _plotArea->layout();
+    }
+
+    if (multiPlot)
+    {
+        // setup a scroll area
+        scrollArea = new QScrollArea();
+        auto scrolledPlotArea = new QWidget(scrollArea);
+        scrollArea->setWidget(scrolledPlotArea);
+        scrollArea->setWidgetResizable(true);
+
+        _plotArea->setLayout(new QVBoxLayout());
+        _plotArea->layout()->addWidget(scrollArea);
+        _plotArea->layout()->setContentsMargins(0,0,0,0);
+
+        layout = new QVBoxLayout(scrolledPlotArea);
+    }
+    else
+    {
+        // delete scrollArea left from multi layout
+        if (scrollArea != NULL)
+        {
+            delete scrollArea;
+            scrollArea = NULL;
+        }
+
+        layout = new QVBoxLayout(_plotArea);
+    }
+
+    layout->setContentsMargins(2,2,2,2);
+    layout->setSpacing(1);
+}
+
+Plot* PlotManager::addPlotWidget()
+{
+    auto plot = new Plot();
+    plotWidgets.append(plot);
+    layout->addWidget(plot);
+
+    plot->darkBackground(darkBackgroundAction.isChecked());
+    plot->showGrid(showGridAction.isChecked());
+    plot->showMinorGrid(showMinorGridAction.isChecked());
+    plot->showLegend(showLegendAction.isChecked());
+    plot->showDemoIndicator(isDemoShown);
+    plot->setAxis(_autoScaled, _yMin, _yMax);
+
+    return plot;
+}
+
+void PlotManager::addCurve(QString title, FrameBuffer* buffer)
+{
+    auto curve = new QwtPlotCurve(title);
+    curve->setSamples(new FrameBufferSeries(buffer));
+    _addCurve(curve);
+}
+
+void PlotManager::addCurve(QString title, QVector data)
+{
+    auto curve = new QwtPlotCurve(title);
+    curve->setSamples(data);
+    _addCurve(curve);
+}
+
+void PlotManager::_addCurve(QwtPlotCurve* curve)
+{
+    // store and init the curve
+    curves.append(curve);
+
+    unsigned index = curves.size()-1;
+    curve->setPen(Plot::makeColor(index));
+
+    // create the plot for the curve if we are on multi display
+    Plot* plot;
+    if (isMulti)
+    {
+        // create a new plot widget
+        plot = addPlotWidget();
+    }
+    else
+    {
+        plot = plotWidgets[0];
+    }
+
+    // show the curve
+    curve->attach(plot);
+    plot->replot();
+}
+
+void PlotManager::removeCurves(unsigned number)
+{
+    for (unsigned i = 0; i < number; i++)
+    {
+        if (!curves.isEmpty())
+        {
+            delete curves.takeLast();
+            if (isMulti) // delete corresponding widget as well
+            {
+                delete plotWidgets.takeLast();
+            }
+        }
+    }
+}
+
+unsigned PlotManager::numOfCurves()
+{
+    return curves.size();
+}
+
+void PlotManager::setTitle(unsigned index, QString title)
+{
+    curves[index]->setTitle(title);
+
+    plotWidget(index)->replot();
+}
+
+Plot* PlotManager::plotWidget(unsigned curveIndex)
+{
+    if (isMulti)
+    {
+        return plotWidgets[curveIndex];
+    }
+    else
+    {
+        return plotWidgets[0];
+    }
+}
+
+void PlotManager::replot()
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->replot();
+    }
+}
+
+QList PlotManager::menuActions()
+{
+    QList actions;
+    actions << &showGridAction;
+    actions << &showMinorGridAction;
+    actions << &unzoomAction;
+    actions << &darkBackgroundAction;
+    actions << &showLegendAction;
+    actions << &showMultiAction;
+    return actions;
+}
+
+void PlotManager::showGrid(bool show)
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->showGrid(show);
+    }
+}
+
+void PlotManager::showMinorGrid(bool show)
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->showMinorGrid(show);
+    }
+}
+
+void PlotManager::showLegend(bool show)
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->showLegend(show);
+    }
+}
+
+void PlotManager::showDemoIndicator(bool show)
+{
+    isDemoShown = show;
+    for (auto plot : plotWidgets)
+    {
+        plot->showDemoIndicator(show);
+    }
+}
+
+void PlotManager::unzoom()
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->unzoom();
+    }
+}
+
+void PlotManager::darkBackground(bool enabled)
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->darkBackground(enabled);
+    }
+}
+
+void PlotManager::setAxis(bool autoScaled, double yAxisMin, double yAxisMax)
+{
+    _autoScaled = autoScaled;
+    _yMin = yAxisMin;
+    _yMax = yAxisMax;
+    for (auto plot : plotWidgets)
+    {
+        plot->setAxis(autoScaled, yAxisMin, yAxisMax);
+    }
+}
+
+void PlotManager::flashSnapshotOverlay()
+{
+    for (auto plot : plotWidgets)
+    {
+        plot->flashSnapshotOverlay(darkBackgroundAction.isChecked());
+    }
+}