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(); +}