diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,8 +54,10 @@ else (BUILD_QWT)
   endif (QWT_USE_STATIC)
 endif (BUILD_QWT)
 
+include(BuildQColorWidgets)
+
 # includes
-include_directories("./src" ${QWT_INCLUDE_DIR})
+include_directories("./src" ${QWT_INCLUDE_DIR} ${QCW_INCLUDE_DIR})
 
 # wrap UI and resource files
 qt5_wrap_ui(UI_FILES
@@ -103,6 +105,7 @@ add_executable(${PROGRAM_NAME} WIN32
   src/tooltipfilter.cpp
   src/sneakylineedit.cpp
   src/channelmanager.cpp
+  src/channelinfomodel.cpp
   src/framebufferseries.cpp
   src/numberformatbox.cpp
   src/endiannessbox.cpp
@@ -122,7 +125,7 @@ add_executable(${PROGRAM_NAME} WIN32
   )
 
 # Use the Widgets module from Qt 5.
-target_link_libraries(${PROGRAM_NAME} ${QWT_LIBRARY})
+target_link_libraries(${PROGRAM_NAME} ${QWT_LIBRARY} ${QCW_LIBRARY})
 qt5_use_modules(${PROGRAM_NAME} Widgets SerialPort)
 
 if (BUILD_QWT)
diff --git a/cmake/modules/BuildQColorWidgets.cmake b/cmake/modules/BuildQColorWidgets.cmake
new file mode 100644
--- /dev/null
+++ b/cmake/modules/BuildQColorWidgets.cmake
@@ -0,0 +1,31 @@
+#
+# 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 .
+#
+
+include(ExternalProject)
+
+ExternalProject_Add(QCW
+  PREFIX qcw
+  GIT_REPOSITORY https://github.com/mbasaglia/Qt-Color-Widgets
+  PATCH_COMMAND patch -t -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/qt_5_2_moc_creation_namespace_fix.diff
+  UPDATE_COMMAND ""
+  INSTALL_COMMAND "")
+
+ExternalProject_Get_Property(QCW binary_dir source_dir)
+set(QCW_LIBRARY ${binary_dir}/libColorWidgets-qt5.a)
+set(QCW_INCLUDE_DIR ${source_dir}/include)
diff --git a/cmake/modules/BuildQwt.cmake b/cmake/modules/BuildQwt.cmake
--- a/cmake/modules/BuildQwt.cmake
+++ b/cmake/modules/BuildQwt.cmake
@@ -28,7 +28,8 @@ ExternalProject_Add(QWT
                           -e "s/QWT_CONFIG\\s*\\+=\\s*QwtSvg/#&/"
                           -e "s/QWT_CONFIG\\s*\\+=\\s*QwtOpenGL/#&/"
 						  -e "s|QWT_INSTALL_PREFIX\\s*=.*|QWT_INSTALL_PREFIX = |"
-							 /qwtconfig.pri
+                             /qwtconfig.pri
+  UPDATE_COMMAND ""
   CONFIGURE_COMMAND qmake /qwt.pro
   )
 
diff --git a/cmake/modules/qt_5_2_moc_creation_namespace_fix.diff b/cmake/modules/qt_5_2_moc_creation_namespace_fix.diff
new file mode 100644
--- /dev/null
+++ b/cmake/modules/qt_5_2_moc_creation_namespace_fix.diff
@@ -0,0 +1,39 @@
+diff --git a/include/color_dialog.hpp b/include/color_dialog.hpp
+index 5c7653d..895215c 100644
+--- a/include/color_dialog.hpp
++++ b/include/color_dialog.hpp
+@@ -30,6 +30,8 @@
+ 
+ class QAbstractButton;
+ 
++using namespace color_widgets;
++
+ namespace color_widgets {
+ 
+ class QCP_EXPORT ColorDialog : public QDialog
+diff --git a/include/color_list_widget.hpp b/include/color_list_widget.hpp
+index 282bea5..7d8e0c5 100644
+--- a/include/color_list_widget.hpp
++++ b/include/color_list_widget.hpp
+@@ -25,6 +25,8 @@
+ #include "abstract_widget_list.hpp"
+ #include "color_wheel.hpp"
+ 
++using namespace color_widgets;
++
+ namespace color_widgets {
+ 
+ class QCP_EXPORT ColorListWidget : public AbstractWidgetList
+diff --git a/include/color_selector.hpp b/include/color_selector.hpp
+index db817d5..48b374d 100644
+--- a/include/color_selector.hpp
++++ b/include/color_selector.hpp
+@@ -25,6 +25,8 @@
+ #include "color_preview.hpp"
+ #include "color_wheel.hpp"
+ 
++using namespace color_widgets;
++
+ namespace color_widgets {
+ 
+ /**
diff --git a/src/channelinfomodel.cpp b/src/channelinfomodel.cpp
new file mode 100644
--- /dev/null
+++ b/src/channelinfomodel.cpp
@@ -0,0 +1,380 @@
+/*
+  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 .
+*/
+
+#include "channelinfomodel.h"
+#include "setting_defines.h"
+
+#define NUMOF_COLORS  (32)
+
+const QColor colors[NUMOF_COLORS] =
+{
+    QColor("#ff0056"),
+    QColor("#7e2dd2"),
+    QColor("#00ae7e"),
+    QColor("#fe8900"),
+    QColor("#ff937e"),
+    QColor("#6a826c"),
+    QColor("#ff029d"),
+    QColor("#00b917"),
+    QColor("#7a4782"),
+    QColor("#85a900"),
+    QColor("#a42400"),
+    QColor("#683d3b"),
+    QColor("#bdc6ff"),
+    QColor("#263400"),
+    QColor("#bdd393"),
+    QColor("#d5ff00"),
+    QColor("#9e008e"),
+    QColor("#001544"),
+    QColor("#c28c9f"),
+    QColor("#ff74a3"),
+    QColor("#01d0ff"),
+    QColor("#004754"),
+    QColor("#e56ffe"),
+    QColor("#788231"),
+    QColor("#0e4ca1"),
+    QColor("#91d0cb"),
+    QColor("#be9970"),
+    QColor("#968ae8"),
+    QColor("#bb8800"),
+    QColor("#43002c"),
+    QColor("#deff74"),
+    QColor("#00ffc6")
+};
+
+ChannelInfoModel::ChannelInfoModel(unsigned numberOfChannels, QObject* parent) :
+    QAbstractTableModel(parent)
+{
+    _numOfChannels = 0;
+    setNumOfChannels(numberOfChannels);
+}
+
+ChannelInfoModel::ChannelInfoModel(const ChannelInfoModel& other) :
+    ChannelInfoModel(other.rowCount(), other.parent())
+{
+    for (int i = 0; i < other.rowCount(); i++)
+    {
+        setData(index(i, COLUMN_NAME),
+                other.data(other.index(i, COLUMN_NAME), Qt::EditRole),
+                Qt::EditRole);
+        setData(index(i, COLUMN_NAME),
+                other.data(other.index(i, COLUMN_NAME), Qt::ForegroundRole),
+                Qt::ForegroundRole);
+        setData(index(i, COLUMN_VISIBILITY),
+                other.data(other.index(i, COLUMN_VISIBILITY), Qt::CheckStateRole),
+                Qt::CheckStateRole);
+    }
+}
+
+ChannelInfoModel::ChannelInfoModel(const QStringList& channelNames) :
+    ChannelInfoModel(channelNames.length(), NULL)
+{
+    for (int i = 0; i < channelNames.length(); i++)
+    {
+        setData(index(i, COLUMN_NAME), channelNames[i], Qt::EditRole);
+    }
+}
+
+ChannelInfoModel::ChannelInfo::ChannelInfo(unsigned index)
+{
+    name = tr("Channel %1").arg(index + 1);
+    visibility = true;
+    color = colors[index % NUMOF_COLORS];
+}
+
+QString ChannelInfoModel::name(unsigned i)
+{
+    return infos[i].name;
+}
+
+QColor ChannelInfoModel::color(unsigned i)
+{
+    return infos[i].color;
+}
+
+bool ChannelInfoModel::isVisible(unsigned i)
+{
+    return infos[i].visibility;
+}
+
+int ChannelInfoModel::rowCount(const QModelIndex &parent) const
+{
+    return _numOfChannels;
+}
+
+int ChannelInfoModel::columnCount(const QModelIndex & parent) const
+{
+    return COLUMN_COUNT;
+}
+
+Qt::ItemFlags ChannelInfoModel::flags(const QModelIndex &index) const
+{
+    if (index.column() == COLUMN_NAME)
+    {
+        return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+    }
+    else if (index.column() == COLUMN_VISIBILITY)
+    {
+        return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+    }
+
+    return Qt::NoItemFlags;
+}
+
+QVariant ChannelInfoModel::data(const QModelIndex &index, int role) const
+{
+    // check index
+    if (index.row() >= (int) _numOfChannels || index.row() < 0)
+    {
+        return QVariant();
+    }
+
+    // get color
+    if (role == Qt::ForegroundRole)
+    {
+        return infos[index.row()].color;
+    }
+
+    // get name
+    if (index.column() == COLUMN_NAME)
+    {
+        if (role == Qt::DisplayRole || role == Qt::EditRole)
+        {
+            return QVariant(infos[index.row()].name);
+        }
+    } // get visibility
+    else if (index.column() == COLUMN_VISIBILITY)
+    {
+        if (role == Qt::CheckStateRole)
+        {
+            bool visible = infos[index.row()].visibility;
+            return visible ? Qt::Checked : Qt::Unchecked;
+        }
+    }
+
+    return QVariant();
+}
+
+QVariant ChannelInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if (orientation == Qt::Horizontal)
+    {
+        if (role == Qt::DisplayRole)
+        {
+            if (section == COLUMN_NAME)
+            {
+                return tr("Channel");
+            }
+            else if (section == COLUMN_VISIBILITY)
+            {
+                return tr("Visible");
+            }
+        }
+    }
+    else                        // vertical
+    {
+        if (section < (int) _numOfChannels && role == Qt::DisplayRole)
+        {
+            return QString::number(section + 1);
+        }
+    }
+
+    return QVariant();
+}
+
+bool ChannelInfoModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+    // check index
+    if (index.row() >= (int) _numOfChannels || index.row() < 0)
+    {
+        return false;
+    }
+
+    // set color
+    if (role == Qt::ForegroundRole)
+    {
+        infos[index.row()].color = value.value();
+        emit dataChanged(index, index, QVector({Qt::ForegroundRole}));
+        return true;
+    }
+
+    // set name
+    if (index.column() == COLUMN_NAME)
+    {
+        if (role == Qt::DisplayRole || role == Qt::EditRole)
+        {
+            infos[index.row()].name = value.toString();
+            emit dataChanged(index, index, QVector({role}));
+            return true;
+        }
+    } // set visibility
+    else if (index.column() == COLUMN_VISIBILITY)
+    {
+        if (role == Qt::CheckStateRole)
+        {
+            bool checked = value.toInt() == Qt::Checked;
+            infos[index.row()].visibility = checked;
+            emit dataChanged(index, index, QVector({role}));
+            return true;
+        }
+    }
+
+    // invalid index/role
+    return false;
+}
+
+void ChannelInfoModel::setNumOfChannels(unsigned number)
+{
+    if (number == _numOfChannels) return;
+
+    bool isInserting = number > _numOfChannels;
+    if (isInserting)
+    {
+        beginInsertRows(QModelIndex(), _numOfChannels, number-1);
+    }
+    else
+    {
+        beginRemoveRows(QModelIndex(), number, _numOfChannels-1);
+    }
+
+    // we create channel info but never remove channel info to
+    // remember user entered info
+    if ((int) number > infos.length())
+    {
+        for (unsigned ci = _numOfChannels; ci < number; ci++)
+        {
+            infos.append(ChannelInfo(ci));
+        }
+    }
+
+    // make sure newly available channels are visible, we don't
+    // remember visibility option intentionally so that user doesn't
+    // get confused
+    if (number > _numOfChannels)
+    {
+        for (unsigned ci = _numOfChannels; ci < number; ci++)
+        {
+            infos[ci].visibility = true;
+        }
+    }
+
+    _numOfChannels = number;
+
+    if (isInserting)
+    {
+        endInsertRows();
+    }
+    else
+    {
+        endRemoveRows();
+    }
+}
+
+void ChannelInfoModel::resetInfos()
+{
+    beginResetModel();
+    for (unsigned ci = 0; (int) ci < infos.length(); ci++)
+    {
+        infos[ci] = ChannelInfo(ci);
+    }
+    endResetModel();
+}
+
+void ChannelInfoModel::resetNames()
+{
+    beginResetModel();
+    for (unsigned ci = 0; (int) ci < infos.length(); ci++)
+    {
+        infos[ci].name = ChannelInfo(ci).name;
+    }
+    endResetModel();
+}
+
+void ChannelInfoModel::resetColors()
+{
+    beginResetModel();
+    for (unsigned ci = 0; (int) ci < infos.length(); ci++)
+    {
+        infos[ci].color = ChannelInfo(ci).color;
+    }
+    endResetModel();
+}
+
+void ChannelInfoModel::resetVisibility()
+{
+    beginResetModel();
+    for (unsigned ci = 0; (int) ci < infos.length(); ci++)
+    {
+        infos[ci].visibility = true;
+    }
+    endResetModel();
+}
+
+void ChannelInfoModel::saveSettings(QSettings* settings)
+{
+    settings->beginGroup(SettingGroup_Channels);
+    settings->beginWriteArray(SG_Channels_Channel);
+
+    // save all channel information regardless of current number of channels
+    for (unsigned ci = 0; (int) ci < infos.length(); ci++)
+    {
+        settings->setArrayIndex(ci);
+        settings->setValue(SG_Channels_Name, infos[ci].name);
+        settings->setValue(SG_Channels_Color, infos[ci].color);
+        settings->setValue(SG_Channels_Visible, infos[ci].visibility);
+    }
+
+    settings->endArray();
+    settings->endGroup();
+}
+
+void ChannelInfoModel::loadSettings(QSettings* settings)
+{
+    settings->beginGroup(SettingGroup_Channels);
+    unsigned size = settings->beginReadArray(SG_Channels_Channel);
+
+    for (unsigned ci = 0; ci < size; ci++)
+    {
+        settings->setArrayIndex(ci);
+
+        ChannelInfo chanInfo(ci);
+        chanInfo.name       = settings->value(SG_Channels_Name, chanInfo.name).toString();
+        chanInfo.color      = settings->value(SG_Channels_Color, chanInfo.color).value();
+        chanInfo.visibility = settings->value(SG_Channels_Visible, true).toBool();
+
+        if ((int) ci < infos.size())
+        {
+            infos[ci] = chanInfo;
+
+            if (ci < _numOfChannels)
+            {
+                auto roles = QVector({
+                    Qt::DisplayRole, Qt::EditRole, Qt::ForegroundRole, Qt::CheckStateRole});
+                emit dataChanged(index(ci, 0), index(ci, COLUMN_COUNT-1), roles);
+            }
+        }
+        else
+        {
+            infos.append(chanInfo);
+        }
+    }
+
+    settings->endArray();
+    settings->endGroup();
+}
diff --git a/src/channelinfomodel.h b/src/channelinfomodel.h
new file mode 100644
--- /dev/null
+++ b/src/channelinfomodel.h
@@ -0,0 +1,91 @@
+/*
+  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 .
+*/
+
+#ifndef CHANNELINFOMODEL_H
+#define CHANNELINFOMODEL_H
+
+#include 
+#include 
+#include 
+#include 
+
+class ChannelInfoModel : public QAbstractTableModel
+{
+    Q_OBJECT
+
+public:
+    enum ChannelInfoColumn
+    {
+        COLUMN_NAME = 0,
+        COLUMN_VISIBILITY,
+        COLUMN_COUNT
+    };
+
+    explicit ChannelInfoModel(unsigned numberOfChannels, QObject *parent = 0);
+    ChannelInfoModel(const ChannelInfoModel& other);
+    explicit ChannelInfoModel(const QStringList& channelNames);
+
+    QString name     (unsigned i);
+    QColor  color    (unsigned i);
+    bool    isVisible(unsigned i);
+
+    // implemented from QAbstractItemModel
+    int           rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int           columnCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant      data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+    bool          setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+    QVariant      headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+    void setNumOfChannels(unsigned number);
+    /// Stores all channel info into a `QSettings`
+    void saveSettings(QSettings* settings);
+    /// Loads all channel info from a `QSettings`.
+    void loadSettings(QSettings* settings);
+
+public slots:
+    /// reset all channel info (names, color etc.)
+    void resetInfos();
+    /// reset all channel names
+    void resetNames();
+    /// reset all channel colors
+    void resetColors();
+    /// reset visibility
+    void resetVisibility();
+
+private:
+    struct ChannelInfo
+    {
+        explicit ChannelInfo(unsigned index);
+
+        QString name;
+        bool visibility;
+        QColor color;
+    };
+
+    unsigned _numOfChannels;     ///< @note this is not necessarily the length of `infos`
+
+    /**
+     * Channel info is added here but never removed so that we can
+     * remember user entered info (names, colors etc.).
+     */
+    QList infos;
+};
+
+#endif // CHANNELINFOMODEL_H
diff --git a/src/channelmanager.cpp b/src/channelmanager.cpp
--- a/src/channelmanager.cpp
+++ b/src/channelmanager.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -17,30 +17,27 @@
   along with serialplot.  If not, see .
 */
 
-#include 
 #include 
 
+#include 
+
 #include "channelmanager.h"
 #include "setting_defines.h"
 
 ChannelManager::ChannelManager(unsigned numberOfChannels, unsigned numberOfSamples, QObject *parent) :
-    QObject(parent)
+    QObject(parent),
+    _infoModel(numberOfChannels)
 {
     _numOfChannels = numberOfChannels;
     _numOfSamples = numberOfSamples;
 
-    QStringList channelNamesList;
-
     for (unsigned int i = 0; i < numberOfChannels; i++)
     {
         channelBuffers.append(new FrameBuffer(numberOfSamples));
-        channelNamesList << QString("Channel %1").arg(i+1);
     }
 
-    _channelNames.setStringList(channelNamesList);
-
-    connect(&_channelNames, &QStringListModel::dataChanged,
-            this, &ChannelManager::onChannelNameDataChange);
+    connect(&_infoModel, &ChannelInfoModel::dataChanged,
+            this, &ChannelManager::onChannelInfoChanged);
 }
 
 ChannelManager::~ChannelManager()
@@ -71,7 +68,6 @@ void ChannelManager::setNumOfChannels(un
         for (unsigned int i = 0; i < number - oldNum; i++)
         {
             channelBuffers.append(new FrameBuffer(_numOfSamples));
-            addChannelName(QString("Channel %1").arg(oldNum+i+1));
         }
     }
     else if(number < oldNum)
@@ -80,10 +76,12 @@ void ChannelManager::setNumOfChannels(un
         for (unsigned int i = oldNum-1; i > number-1; i--)
         {
             delete channelBuffers.takeLast();
-            _channelNames.removeRow(i);
         }
     }
 
+    _numOfChannels = number;
+    _infoModel.setNumOfChannels(number);
+
     emit numOfChannelsChanged(number);
 }
 
@@ -104,39 +102,62 @@ FrameBuffer* ChannelManager::channelBuff
     return channelBuffers[channel];
 }
 
-QStringListModel* ChannelManager::channelNames()
+ChannelInfoModel* ChannelManager::infoModel()
 {
-    return &_channelNames;
+    return &_infoModel;
 }
 
 QString ChannelManager::channelName(unsigned channel)
 {
-    return _channelNames.data(_channelNames.index(channel, 0), Qt::DisplayRole).toString();
+    return _infoModel.data(_infoModel.index(channel, ChannelInfoModel::COLUMN_NAME),
+                           Qt::DisplayRole).toString();
 }
 
-void ChannelManager::setChannelName(unsigned channel, QString name)
+QStringList ChannelManager::channelNames()
 {
-    _channelNames.setData(_channelNames.index(channel, 0), QVariant(name), Qt::DisplayRole);
+    QStringList list;
+    for (unsigned ci = 0; ci < _numOfChannels; ci++)
+    {
+        list << channelName(ci);
+    }
+    return list;
 }
 
-void ChannelManager::addChannelName(QString name)
+void ChannelManager::onChannelInfoChanged(const QModelIndex & topLeft,
+                                          const QModelIndex & bottomRight,
+                                          const QVector & roles)
 {
-    _channelNames.insertRow(_channelNames.rowCount());
-    setChannelName(_channelNames.rowCount()-1, name);
-}
-
-void ChannelManager::onChannelNameDataChange(const QModelIndex & topLeft,
-                                             const QModelIndex & bottomRight,
-                                             const QVector & roles)
-{
-    Q_UNUSED(roles);
     int start = topLeft.row();
     int end = bottomRight.row();
+    int col = topLeft.column();
 
-    // TODO: maybe check `roles` parameter, can't think of a reason for current use case
-    for (int i = start; i <= end; i++)
+    for (int ci = start; ci <= end; ci++)
     {
-        emit channelNameChanged(i, channelName(i));
+        for (auto role : roles)
+        {
+            switch (role)
+            {
+                case Qt::EditRole:
+                    if (col == ChannelInfoModel::COLUMN_NAME)
+                    {
+                        emit channelNameChanged(ci, channelName(ci));
+                    }
+                    break;
+                case Qt::ForegroundRole:
+                    if (col == ChannelInfoModel::COLUMN_NAME)
+                    {
+                        // TODO: emit channel color changed
+                    }
+                    break;
+                case Qt::CheckStateRole:
+                    if (col == ChannelInfoModel::COLUMN_VISIBILITY)
+                    {
+                        // TODO: emit visibility
+                    }
+                    break;
+            }
+        }
+        // emit channelNameChanged(i, channelName(i));
     }
 }
 
@@ -147,26 +168,10 @@ void ChannelManager::addChannelData(unsi
 
 void ChannelManager::saveSettings(QSettings* settings)
 {
-    settings->beginGroup(SettingGroup_Channels);
-    settings->beginWriteArray(SG_Channels_Channel);
-    for (unsigned i = 0; i < numOfChannels(); i++)
-    {
-        settings->setArrayIndex(i);
-        settings->setValue(SG_Channels_Name, channelName(i));
-    }
-    settings->endArray();
-    settings->endGroup();
+    _infoModel.saveSettings(settings);
 }
 
 void ChannelManager::loadSettings(QSettings* settings)
 {
-    settings->beginGroup(SettingGroup_Channels);
-    settings->beginReadArray(SG_Channels_Channel);
-    for (unsigned i = 0; i < numOfChannels(); i++)
-    {
-        settings->setArrayIndex(i);
-        setChannelName(i, settings->value(SG_Channels_Name, channelName(i)).toString());
-    }
-    settings->endArray();
-    settings->endGroup();
+    _infoModel.loadSettings(settings);
 }
diff --git a/src/channelmanager.h b/src/channelmanager.h
--- a/src/channelmanager.h
+++ b/src/channelmanager.h
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -21,12 +21,13 @@
 #define CHANNELMANAGER_H
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 
 #include "framebuffer.h"
+#include "channelinfomodel.h"
 
 class ChannelManager : public QObject
 {
@@ -38,12 +39,16 @@ public:
     unsigned numOfChannels();
     unsigned numOfSamples();
     FrameBuffer* channelBuffer(unsigned channel);
-    QStringListModel* channelNames();
+    // QStringListModel* channelNames();
     QString channelName(unsigned channel);
     /// Stores channel names into a `QSettings`
     void saveSettings(QSettings* settings);
     /// Loads channel names from a `QSettings`.
     void loadSettings(QSettings* settings);
+    /// Returns a model that manages channel information (name, color etc)
+    ChannelInfoModel* infoModel();
+    /// Returns a list of channel names
+    QStringList channelNames();
 
 signals:
     void numOfChannelsChanged(unsigned value);
@@ -53,21 +58,21 @@ signals:
 public slots:
     void setNumOfChannels(unsigned number);
     void setNumOfSamples(unsigned number);
-    void setChannelName(unsigned channel, QString name);
     void addChannelData(unsigned channel, double* data, unsigned size);
 
 private:
     unsigned _numOfChannels;
     unsigned _numOfSamples;
     QList channelBuffers;
-    QStringListModel _channelNames;
+    // QStringListModel _channelNames;
+    ChannelInfoModel _infoModel;
 
     void addChannelName(QString name); ///< appends a new channel name at the end of list
 
 private slots:
-    void onChannelNameDataChange(const QModelIndex & topLeft,
-                                 const QModelIndex & bottomRight,
-                                 const QVector & roles = QVector ());
+    void onChannelInfoChanged(const QModelIndex & topLeft,
+                              const QModelIndex & bottomRight,
+                              const QVector & roles = QVector ());
 };
 
 #endif // CHANNELMANAGER_H
diff --git a/src/main.cpp b/src/main.cpp
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2015 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -24,7 +24,6 @@
 #include "tooltipfilter.h"
 #include "version.h"
 
-
 MainWindow* pMainWindow;
 
 void messageHandler(QtMsgType type, const QMessageLogContext &context,
@@ -50,5 +49,6 @@ int main(int argc, char *argv[])
     qDebug() << "Revision" << VERSION_REVISION;
 
     w.show();
+
     return a.exec();
 }
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -66,7 +66,7 @@ MainWindow::MainWindow(QWidget *parent) 
 {
     ui->setupUi(this);
 
-    plotMan = new PlotManager(ui->plotArea);
+    plotMan = new PlotManager(ui->plotArea, channelMan.infoModel());
 
     ui->tabWidget->insertTab(0, &portControl, "Port");
     ui->tabWidget->insertTab(1, &dataFormatPanel, "Data Format");
@@ -172,7 +172,7 @@ MainWindow::MainWindow(QWidget *parent) 
     connect(&channelMan, &ChannelManager::channelNameChanged,
             this, &MainWindow::onChannelNameChanged);
 
-    plotControlPanel.setChannelNamesModel(channelMan.channelNames());
+    plotControlPanel.setChannelInfoModel(channelMan.infoModel());
 
     // init curve list
     for (unsigned int i = 0; i < numOfChannels; i++)
@@ -376,7 +376,7 @@ void MainWindow::onChannelNameChanged(un
     // since `onNumOfChannelsChanged` slot will update curve list.
     if (channel < plotMan->numOfCurves()) // check if channel exists in curve list
     {
-        plotMan->setTitle(channel, name);
+        // plotMan->setTitle(channel, name);
     }
 }
 
@@ -463,6 +463,11 @@ void MainWindow::messageHandler(QtMsgTyp
     {
         ui->statusBar->showMessage(msg, 5000);
     }
+
+    if (type == QtFatalMsg)
+    {
+        __builtin_trap();
+    }
 }
 
 void MainWindow::saveAllSettings(QSettings* settings)
diff --git a/src/plot.h b/src/plot.h
--- a/src/plot.h
+++ b/src/plot.h
@@ -37,28 +37,14 @@ class Plot : public QwtPlot
 {
     Q_OBJECT
 
+    friend class PlotManager;
+
 public:
     Plot(QWidget* parent = 0);
     ~Plot();
 
     static QColor makeColor(unsigned int channelIndex);
 
-private:
-    bool isAutoScaled;
-    double yMin, yMax;
-    int symbolSize;
-    Zoomer zoomer;
-    ScaleZoomer sZoomer;
-    QwtPlotGrid grid;
-    PlotSnapshotOverlay* snapshotOverlay;
-    QwtPlotLegendItem legend;
-    QwtPlotTextLabel demoIndicator;
-
-    /// update the display of symbols depending on `symbolSize`
-    void updateSymbols();
-    void resetAxes();
-    void resizeEvent(QResizeEvent * event);
-
 public slots:
     void showGrid(bool show = true);
     void showMinorGrid(bool show = true);
@@ -77,6 +63,24 @@ public slots:
 
     void onNumOfSamplesChanged(unsigned value);
 
+protected:
+    /// update the display of symbols depending on `symbolSize`
+    void updateSymbols();
+
+private:
+    bool isAutoScaled;
+    double yMin, yMax;
+    int symbolSize;
+    Zoomer zoomer;
+    ScaleZoomer sZoomer;
+    QwtPlotGrid grid;
+    PlotSnapshotOverlay* snapshotOverlay;
+    QwtPlotLegendItem legend;
+    QwtPlotTextLabel demoIndicator;
+
+    void resetAxes();
+    void resizeEvent(QResizeEvent * event);
+
 private slots:
     void unzoomed();
     void onXScaleChanged();
diff --git a/src/plotcontrolpanel.cpp b/src/plotcontrolpanel.cpp
--- a/src/plotcontrolpanel.cpp
+++ b/src/plotcontrolpanel.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -23,6 +23,7 @@
 
 #include 
 
+#include "color_selector.hpp"
 #include "plotcontrolpanel.h"
 #include "ui_plotcontrolpanel.h"
 #include "setting_defines.h"
@@ -41,7 +42,12 @@ Q_DECLARE_METATYPE(Range);
 
 PlotControlPanel::PlotControlPanel(QWidget *parent) :
     QWidget(parent),
-    ui(new Ui::PlotControlPanel)
+    ui(new Ui::PlotControlPanel),
+    resetAct(tr("Reset"), this),
+    resetNamesAct(tr("Reset Names"), this),
+    resetColorsAct(tr("Reset Colors"), this),
+    showAllAct(tr("Show All"), this),
+    resetMenu(tr("Reset Menu"), this)
 {
     ui->setupUi(this);
 
@@ -92,6 +98,18 @@ PlotControlPanel::PlotControlPanel(QWidg
 
     QObject::connect(ui->cbRangePresets, SIGNAL(activated(int)),
                      this, SLOT(onRangeSelected()));
+
+    // color selector starts disabled until a channel is selected
+    ui->colorSelector->setColor(QColor(0,0,0,0));
+    ui->colorSelector->setDisplayMode(color_widgets::ColorPreview::AllAlpha);
+    ui->colorSelector->setDisabled(true);
+
+    // reset button
+    resetMenu.addAction(&resetNamesAct);
+    resetMenu.addAction(&resetColorsAct);
+    resetMenu.addAction(&showAllAct);
+    resetAct.setMenu(&resetMenu);
+    ui->tbReset->setDefaultAction(&resetAct);
 }
 
 PlotControlPanel::~PlotControlPanel()
@@ -204,9 +222,77 @@ void PlotControlPanel::onRangeSelected()
     ui->cbAutoScale->setChecked(false);
 }
 
-void PlotControlPanel::setChannelNamesModel(QAbstractItemModel * model)
+void PlotControlPanel::setChannelInfoModel(ChannelInfoModel* model)
 {
-    ui->lvChannelNames->setModel(model);
+    ui->tvChannelInfo->setModel(model);
+
+    // channel color selector
+    connect(ui->tvChannelInfo->selectionModel(), &QItemSelectionModel::currentRowChanged,
+            [this](const QModelIndex ¤t, const QModelIndex &previous)
+            {
+                // TODO: duplicate with below lambda
+                QColor color(0,0,0,0); // transparent
+
+                if (current.isValid())
+                {
+                    ui->colorSelector->setEnabled(true);
+                    auto model = ui->tvChannelInfo->model();
+                    color = model->data(current, Qt::ForegroundRole).value();
+                }
+                else
+                {
+                    ui->colorSelector->setDisabled(true);
+                }
+
+                // temporarily block signals because `setColor` emits `colorChanged`
+                bool wasBlocked = ui->colorSelector->blockSignals(true);
+                ui->colorSelector->setColor(color);
+                ui->colorSelector->blockSignals(wasBlocked);
+            });
+
+    connect(ui->tvChannelInfo->selectionModel(), &QItemSelectionModel::selectionChanged,
+            [this](const QItemSelection & selected, const QItemSelection & deselected)
+            {
+                if (!selected.length())
+                {
+                    ui->colorSelector->setDisabled(true);
+
+                    // temporarily block signals because `setColor` emits `colorChanged`
+                    bool wasBlocked = ui->colorSelector->blockSignals(true);
+                    ui->colorSelector->setColor(QColor(0,0,0,0));
+                    ui->colorSelector->blockSignals(wasBlocked);
+                }
+            });
+
+    connect(ui->colorSelector, &color_widgets::ColorSelector::colorChanged,
+            [this](QColor color)
+            {
+                auto index = ui->tvChannelInfo->selectionModel()->currentIndex();
+                ui->tvChannelInfo->model()->setData(index, color, Qt::ForegroundRole);
+            });
+
+    connect(model, &QAbstractItemModel::dataChanged,
+            [this](const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector & roles = QVector ())
+            {
+                auto current = ui->tvChannelInfo->selectionModel()->currentIndex();
+
+                // no current selection
+                if (!current.isValid()) return;
+
+                auto mod = ui->tvChannelInfo->model();
+                QColor color = mod->data(current, Qt::ForegroundRole).value();
+
+                // temporarily block signals because `setColor` emits `colorChanged`
+                bool wasBlocked = ui->colorSelector->blockSignals(true);
+                ui->colorSelector->setColor(color);
+                ui->colorSelector->blockSignals(wasBlocked);
+            });
+
+    // reset actions
+    connect(&resetAct, &QAction::triggered, model, &ChannelInfoModel::resetInfos);
+    connect(&resetNamesAct, &QAction::triggered, model, &ChannelInfoModel::resetNames);
+    connect(&resetColorsAct, &QAction::triggered, model, &ChannelInfoModel::resetColors);
+    connect(&showAllAct, &QAction::triggered, model, &ChannelInfoModel::resetVisibility);
 }
 
 void PlotControlPanel::saveSettings(QSettings* settings)
diff --git a/src/plotcontrolpanel.h b/src/plotcontrolpanel.h
--- a/src/plotcontrolpanel.h
+++ b/src/plotcontrolpanel.h
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -21,8 +21,11 @@
 #define PLOTCONTROLPANEL_H
 
 #include 
-#include 
 #include 
+#include 
+#include 
+
+#include "channelinfomodel.h"
 
 namespace Ui {
 class PlotControlPanel;
@@ -41,7 +44,7 @@ public:
     double yMax();
     double yMin();
 
-    void setChannelNamesModel(QAbstractItemModel * model);
+    void setChannelInfoModel(ChannelInfoModel* model);
 
     /// Stores plot settings into a `QSettings`
     void saveSettings(QSettings* settings);
@@ -60,6 +63,9 @@ private:
     /// User can disable this setting in the checkbox
     bool warnNumOfSamples;
 
+    QAction resetAct, resetNamesAct, resetColorsAct, showAllAct;
+    QMenu resetMenu;
+
     /// Show a confirmation dialog before setting #samples to a big value
     bool askNSConfirmation(int value);
 
diff --git a/src/plotcontrolpanel.ui b/src/plotcontrolpanel.ui
--- a/src/plotcontrolpanel.ui
+++ b/src/plotcontrolpanel.ui
@@ -15,28 +15,112 @@
   
   
    - 
-    
-     
- 
-      
-       
-        font-weight: bold;
-       
-       
-        Channel Names:
-       
-      
-     
 
-     - 
-      
-       
-        
-         16777215
-         170
-        
-       
-      
-     
 
-    
+    
+     
+      
+       0
+       0
+      
+     
+     
+      
+       3
+      
+      
+       0
+      
+      
+       0
+      
+      
+       0
+      
+      
+       0
+      
+      - 
+       
+        
+         
+          0
+          0
+         
+        
+        
+         
+          300
+          170
+         
+        
+        
+         QAbstractItemView::SingleSelection
+        
+        
+         QAbstractItemView::SelectRows
+        
+       
+      
 
+      - 
+       
+        
+         QLayout::SetMaximumSize
+        
+        
- 
+         
+          
+           
+            0
+            0
+           
+          
+          
+           
+            20
+            20
+           
+          
+          
+           
+            20
+            20
+           
+          
+          tbReset
+         
+        
 
+        - 
+         
+          
+           Qt::Horizontal
+          
+          
+           
+            1
+            20
+           
+          
+         
+        
 
+        - 
+         
+          
+           Reset
+          
+          
+           QToolButton::MenuButtonPopup
+          
+          
+           Qt::NoArrow
+          
+         
+        
 
+       
+       
+     
+     tbReset
+     horizontalLayoutWidget
+     tvChannelInfo
+    
     
    - 
     
@@ -48,7 +132,7 @@
    
- 
     
      
-      QFormLayout::AllNonFixedFieldsGrow
+      QFormLayout::FieldsStayAtSizeHint
      
      
- 
       
@@ -159,8 +243,32 @@
      
 
     
     
+   - 
+    
+     
+      Qt::Horizontal
+     
+     
+      QSizePolicy::MinimumExpanding
+     
+     
+      
+       1
+       20
+      
+     
+    
+   
 
    
  
+ 
+  
+   color_widgets::ColorSelector
+   QWidget
+   
+   1
+  
+ 
  
  
 
diff --git a/src/plotmanager.cpp b/src/plotmanager.cpp
--- a/src/plotmanager.cpp
+++ b/src/plotmanager.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -18,13 +18,14 @@
 */
 
 #include 
+#include "qwt_symbol.h"
 
 #include "plot.h"
 #include "plotmanager.h"
 #include "utils.h"
 #include "setting_defines.h"
 
-PlotManager::PlotManager(QWidget* plotArea, QObject *parent) :
+PlotManager::PlotManager(QWidget* plotArea, ChannelInfoModel* infoModel, QObject *parent) :
     QObject(parent),
     _plotArea(plotArea),
     showGridAction("&Grid", this),
@@ -38,6 +39,7 @@ PlotManager::PlotManager(QWidget* plotAr
     _yMin = 0;
     _yMax = 1;
     isDemoShown = false;
+    _infoModel = infoModel;
 
     // initalize layout and single widget
     isMulti = false;
@@ -85,6 +87,21 @@ PlotManager::PlotManager(QWidget* plotAr
             this, &PlotManager::showLegend);
     connect(&showMultiAction, SELECT::OVERLOAD_OF(&QAction::triggered),
             this, &PlotManager::setMulti);
+
+    // connect to channel info model
+    if (_infoModel != NULL)     // TODO: remove when snapshots have infomodel
+    {
+        connect(_infoModel, &QAbstractItemModel::dataChanged,
+                this, &PlotManager::onChannelInfoChanged);
+
+        connect(_infoModel, &QAbstractItemModel::modelReset,
+                [this]()
+                {
+                    onChannelInfoChanged(_infoModel->index(0, 0), // start
+                                         _infoModel->index(_infoModel->rowCount()-1, 0), // end
+                                         {}); // roles ignored
+                });
+    }
 }
 
 PlotManager::~PlotManager()
@@ -103,6 +120,46 @@ PlotManager::~PlotManager()
     if (scrollArea != NULL) delete scrollArea;
 }
 
+void PlotManager::onChannelInfoChanged(const QModelIndex &topLeft,
+                                       const QModelIndex &bottomRight,
+                                       const QVector &roles)
+{
+    int start = topLeft.row();
+    int end = bottomRight.row();
+
+    for (int ci = start; ci <= end; ci++)
+    {
+        QString name = topLeft.sibling(ci, ChannelInfoModel::COLUMN_NAME).data(Qt::EditRole).toString();
+        QColor color = topLeft.sibling(ci, ChannelInfoModel::COLUMN_NAME).data(Qt::ForegroundRole).value();
+        bool visible = topLeft.sibling(ci, ChannelInfoModel::COLUMN_VISIBILITY).data(Qt::CheckStateRole).toBool();
+
+        curves[ci]->setTitle(name);
+        curves[ci]->setPen(color);
+        curves[ci]->setVisible(visible);
+        curves[ci]->setItemAttribute(QwtPlotItem::Legend, visible);
+
+        // replot only updated widgets
+        if (isMulti)
+        {
+            plotWidgets[ci]->updateSymbols(); // required for color change
+            plotWidgets[ci]->updateLegend(curves[ci]);
+            plotWidgets[ci]->setVisible(visible);
+            if (visible)
+            {
+                plotWidgets[ci]->replot();
+            }
+        }
+    }
+
+    // replot single widget
+    if (!isMulti)
+    {
+        plotWidgets[0]->updateSymbols();
+        plotWidgets[0]->updateLegend();
+        replot();
+    }
+}
+
 void PlotManager::setMulti(bool enabled)
 {
     if (enabled == isMulti) return;
@@ -219,7 +276,8 @@ void PlotManager::_addCurve(QwtPlotCurve
     curves.append(curve);
 
     unsigned index = curves.size()-1;
-    curve->setPen(Plot::makeColor(index));
+    auto color = _infoModel->color(index);
+    curve->setPen(color);
 
     // create the plot for the curve if we are on multi display
     Plot* plot;
diff --git a/src/plotmanager.h b/src/plotmanager.h
--- a/src/plotmanager.h
+++ b/src/plotmanager.h
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2016 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -30,13 +30,14 @@
 #include 
 #include "plot.h"
 #include "framebufferseries.h"
+#include "channelinfomodel.h"
 
 class PlotManager : public QObject
 {
     Q_OBJECT
 
 public:
-    explicit PlotManager(QWidget* plotArea, QObject *parent = 0);
+    explicit PlotManager(QWidget* plotArea, ChannelInfoModel* infoModel = NULL, QObject *parent = 0);
     ~PlotManager();
     /// Add a new curve with title and buffer. A color is
     /// automatically chosen for curve.
@@ -77,6 +78,7 @@ private:
     QScrollArea* scrollArea;
     QList curves;
     QList plotWidgets;
+    ChannelInfoModel* _infoModel;
     bool isDemoShown;
     bool _autoScaled;
     double _yMin;
@@ -104,6 +106,10 @@ private slots:
     void showLegend(bool show = true);
     void unzoom();
     void darkBackground(bool enabled = true);
+
+    void onChannelInfoChanged(const QModelIndex & topLeft,
+                              const QModelIndex & bottomRight,
+                              const QVector & roles = QVector ());
 };
 
 #endif // PLOTMANAGER_H
diff --git a/src/setting_defines.h b/src/setting_defines.h
--- a/src/setting_defines.h
+++ b/src/setting_defines.h
@@ -70,6 +70,8 @@ const char SG_CustomFrame_DebugMode[] = 
 // channel manager keys
 const char SG_Channels_Channel[] = "channel";
 const char SG_Channels_Name[] = "name";
+const char SG_Channels_Color[] = "color";
+const char SG_Channels_Visible[] = "visible";
 
 // plot settings keys
 const char SG_Plot_NumOfSamples[] = "numOfSamples";
diff --git a/src/snapshot.cpp b/src/snapshot.cpp
--- a/src/snapshot.cpp
+++ b/src/snapshot.cpp
@@ -24,8 +24,9 @@
 #include "snapshot.h"
 #include "snapshotview.h"
 
-Snapshot::Snapshot(QMainWindow* parent, QString name) :
+Snapshot::Snapshot(QMainWindow* parent, QString name, ChannelInfoModel infoModel) :
     QObject(parent),
+    cInfoModel(infoModel),
     _showAction(this),
     _deleteAction("&Delete", this)
 {
@@ -106,14 +107,14 @@ void Snapshot::setName(QString name)
     emit nameChanged(this);
 }
 
-void Snapshot::setChannelNames(QStringList names)
+ChannelInfoModel* Snapshot::infoModel()
 {
-    _channelNames = names;
+    return &cInfoModel;
 }
 
 QString Snapshot::channelName(unsigned channel)
 {
-    return _channelNames[channel];
+    return cInfoModel.name(channel);
 }
 
 void Snapshot::save(QString fileName)
diff --git a/src/snapshot.h b/src/snapshot.h
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -27,6 +27,8 @@
 #include 
 #include 
 
+#include "channelinfomodel.h"
+
 class SnapshotView;
 
 class Snapshot : public QObject
@@ -34,7 +36,7 @@ class Snapshot : public QObject
     Q_OBJECT
 
 public:
-    Snapshot(QMainWindow* parent, QString name);
+    Snapshot(QMainWindow* parent, QString name, ChannelInfoModel infoModel);
     ~Snapshot();
 
     QVector> data;
@@ -43,8 +45,8 @@ public:
 
     QString name();
     QString displayName(); ///< `name()` plus '*' if snapshot is not saved
+    ChannelInfoModel* infoModel();
     void setName(QString name);
-    void setChannelNames(QStringList names); // must be called when setting data!
     QString channelName(unsigned channel);
 
     void save(QString fileName); ///< save snapshot data as CSV
@@ -56,7 +58,7 @@ signals:
 
 private:
     QString _name;
-    QStringList _channelNames;
+    ChannelInfoModel cInfoModel;
     QAction _showAction;
     QAction _deleteAction;
     QMainWindow* mainWindow;
diff --git a/src/snapshotmanager.cpp b/src/snapshotmanager.cpp
--- a/src/snapshotmanager.cpp
+++ b/src/snapshotmanager.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright © 2015 Hasan Yavuz Özderya
+  Copyright © 2017 Hasan Yavuz Özderya
 
   This file is part of serialplot.
 
@@ -63,7 +63,7 @@ SnapshotManager::~SnapshotManager()
 Snapshot* SnapshotManager::makeSnapshot()
 {
     QString name = QTime::currentTime().toString("'Snapshot ['HH:mm:ss']'");
-    auto snapshot = new Snapshot(_mainWindow, name);
+    auto snapshot = new Snapshot(_mainWindow, name, *(_channelMan->infoModel()));
 
     unsigned numOfChannels = _channelMan->numOfChannels();
     unsigned numOfSamples = _channelMan->numOfSamples();
@@ -76,7 +76,6 @@ Snapshot* SnapshotManager::makeSnapshot(
             snapshot->data[ci][i] = QPointF(i, _channelMan->channelBuffer(ci)->sample(i));
         }
     }
-    snapshot->setChannelNames(_channelMan->channelNames()->stringList());
 
     return snapshot;
 }
@@ -189,9 +188,11 @@ void SnapshotManager::loadSnapshotFromFi
         lineNum++;
     }
 
-    auto snapshot = new Snapshot(_mainWindow, QFileInfo(fileName).baseName());
+    ChannelInfoModel channelInfo(channelNames);
+
+    auto snapshot = new Snapshot(
+        _mainWindow, QFileInfo(fileName).baseName(), ChannelInfoModel(channelNames));
     snapshot->data = data;
-    snapshot->setChannelNames(channelNames);
 
     addSnapshot(snapshot, false);
 }
diff --git a/src/snapshotview.cpp b/src/snapshotview.cpp
--- a/src/snapshotview.cpp
+++ b/src/snapshotview.cpp
@@ -29,7 +29,7 @@ SnapshotView::SnapshotView(QWidget *pare
 
     ui->setupUi(this);
 
-    plotMan = new PlotManager(ui->plotArea);
+    plotMan = new PlotManager(ui->plotArea, snapshot->infoModel());
 
     ui->menuSnapshot->insertAction(ui->actionClose, snapshot->deleteAction());
     this->setWindowTitle(snapshot->displayName());