/* Copyright © 2018 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) const { return infos[i].name; } QColor ChannelInfoModel::color(unsigned i) const { return infos[i].color; } bool ChannelInfoModel::isVisible(unsigned i) const { return infos[i].visibility; } QStringList ChannelInfoModel::channelNames() const { QStringList r; for (unsigned ci = 0; ci < _numOfChannels; ci++) { r << name(ci); } return r; } 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 = infos.length(); 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(bool visible) { beginResetModel(); for (unsigned ci = 0; (int) ci < infos.length(); ci++) { infos[ci].visibility = visible; } endResetModel(); } void ChannelInfoModel::saveSettings(QSettings* settings) const { 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(); }