/*
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"
const QColor colors[8] =
{
QColor(237,97,68),
QColor(92,200,96),
QColor(225,98,207),
QColor(163,195,58),
QColor(148,123,239),
QColor(212,182,52),
QColor(238,82,133),
QColor(219,136,44)
};
ChannelInfoModel::ChannelInfoModel(unsigned numberOfChannels, QObject* parent) :
QAbstractTableModel(parent)
{
_numOfChannels = 0;
setNumOfChannels(numberOfChannels);
}
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({QString("Channel %1").arg(ci+1), true, colors[ci % 8]});
}
}
// 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::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;
chanInfo.name = settings->value(SG_Channels_Name,
QString(tr("Channel %1")).arg(ci+1)).toString();
chanInfo.color = settings->value(SG_Channels_Color, colors[ci % 8]).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();
}