diff --git a/src/channelinfomodel.cpp b/src/channelinfomodel.cpp --- a/src/channelinfomodel.cpp +++ b/src/channelinfomodel.cpp @@ -68,6 +68,7 @@ ChannelInfoModel::ChannelInfoModel(unsig ChannelInfoModel::ChannelInfoModel(const ChannelInfoModel& other) : ChannelInfoModel(other.rowCount(), other.parent()) { + // TODO: why not set (copy) info list directly instead? for (int i = 0; i < other.rowCount(); i++) { setData(index(i, COLUMN_NAME), @@ -76,10 +77,24 @@ ChannelInfoModel::ChannelInfoModel(const 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); - // TODO: gain and offset + + setData(index(i, COLUMN_GAIN), + other.data(other.index(i, COLUMN_GAIN), Qt::CheckStateRole), + Qt::CheckStateRole); + setData(index(i, COLUMN_GAIN), + other.data(other.index(i, COLUMN_GAIN), Qt::EditRole), + Qt::EditRole); + + setData(index(i, COLUMN_OFFSET), + other.data(other.index(i, COLUMN_OFFSET), Qt::CheckStateRole), + Qt::CheckStateRole); + setData(index(i, COLUMN_OFFSET), + other.data(other.index(i, COLUMN_OFFSET), Qt::EditRole), + Qt::EditRole); } } @@ -288,13 +303,13 @@ bool ChannelInfoModel::setData(const QMo } // set name + bool r = false; if (index.column() == COLUMN_NAME) { if (role == Qt::DisplayRole || role == Qt::EditRole) { info.name = value.toString(); - emit dataChanged(index, index, QVector({role})); - return true; + r = true; } } // set visibility else if (index.column() == COLUMN_VISIBILITY) @@ -303,8 +318,7 @@ bool ChannelInfoModel::setData(const QMo { bool checked = value.toInt() == Qt::Checked; info.visibility = checked; - emit dataChanged(index, index, QVector({role})); - return true; + r = true; } } else if (index.column() == COLUMN_GAIN) @@ -312,15 +326,14 @@ bool ChannelInfoModel::setData(const QMo if (role == Qt::DisplayRole || role == Qt::EditRole) { info.gain = value.toDouble(); - emit dataChanged(index, index, QVector({role})); - return true; + r = true; } else if (role == Qt::CheckStateRole) { bool checked = value.toInt() == Qt::Checked; info.gainEn = checked; - emit dataChanged(index, index, QVector({role})); - return true; + if (_gainOrOffsetEn != checked) updateGainOrOffsetEn(); + r = true; } } else if (index.column() == COLUMN_OFFSET) @@ -328,20 +341,23 @@ bool ChannelInfoModel::setData(const QMo if (role == Qt::DisplayRole || role == Qt::EditRole) { info.offset = value.toDouble(); - emit dataChanged(index, index, QVector({role})); - return true; + r = true; } else if (role == Qt::CheckStateRole) { bool checked = value.toInt() == Qt::Checked; info.offsetEn = checked; - emit dataChanged(index, index, QVector({role})); - return true; + if (_gainOrOffsetEn != checked) updateGainOrOffsetEn(); + r = true; } } - // invalid index/role - return false; + if (r) + { + emit dataChanged(index, index, QVector({role})); + } + + return r; } void ChannelInfoModel::setNumOfChannels(unsigned number) @@ -380,6 +396,7 @@ void ChannelInfoModel::setNumOfChannels( } _numOfChannels = number; + updateGainOrOffsetEn(); if (isInserting) { @@ -407,6 +424,7 @@ void ChannelInfoModel::resetNames() beginResetModel(); for (unsigned ci = 0; (int) ci < infos.length(); ci++) { + // TODO: do not create a full object every time (applies to other reset methods as well) infos[ci].name = ChannelInfo(ci).name; } endResetModel(); @@ -440,6 +458,7 @@ void ChannelInfoModel::resetGains() infos[ci].gain = ChannelInfo(ci).gain; infos[ci].gainEn = ChannelInfo(ci).gainEn; } + updateGainOrOffsetEn(); endResetModel(); } @@ -451,9 +470,25 @@ void ChannelInfoModel::resetOffsets() infos[ci].offset = ChannelInfo(ci).offset; infos[ci].offsetEn = ChannelInfo(ci).offsetEn; } + updateGainOrOffsetEn(); endResetModel(); } +bool ChannelInfoModel::gainOrOffsetEn() const +{ + return _gainOrOffsetEn; +} + +void ChannelInfoModel::updateGainOrOffsetEn() +{ + _gainOrOffsetEn = false; + for (int ci = 0; ci < _numOfChannels; ci++) + { + auto& info = infos[ci]; + _gainOrOffsetEn |= (info.gainEn || info.offsetEn); + } +} + void ChannelInfoModel::saveSettings(QSettings* settings) const { settings->beginGroup(SettingGroup_Channels); @@ -512,6 +547,8 @@ void ChannelInfoModel::loadSettings(QSet } } + updateGainOrOffsetEn(); + settings->endArray(); settings->endGroup(); } diff --git a/src/channelinfomodel.h b/src/channelinfomodel.h --- a/src/channelinfomodel.h +++ b/src/channelinfomodel.h @@ -50,6 +50,8 @@ public: double gain (unsigned i) const; bool offsetEn (unsigned i) const; double offset (unsigned i) const; + /// Returns true if any of the channels have gain or offset enabled + bool gainOrOffsetEn() const; /// Returns a list of channel names QStringList channelNames() const; @@ -100,6 +102,16 @@ private: * remember user entered info (names, colors etc.). */ QList infos; + + /** + * Cache for gain and offset enabled variables of channels. If gain and/or + * offset is not enabled for *any* of the channels this is false otherwise + * true. + */ + bool _gainOrOffsetEn; + + /// Updates `_gainOrOffsetEn` by scanning all channel infos. + void updateGainOrOffsetEn(); }; #endif // CHANNELINFOMODEL_H diff --git a/src/stream.cpp b/src/stream.cpp --- a/src/stream.cpp +++ b/src/stream.cpp @@ -144,23 +144,22 @@ void Stream::setNumChannels(unsigned nc, const SamplePack* Stream::applyGainOffset(const SamplePack& pack) const { - SamplePack* mPack = nullptr; + Q_ASSERT(infoModel()->gainOrOffsetEn()); + + SamplePack* mPack = new SamplePack(pack); unsigned ns = pack.numSamples(); for (unsigned ci = 0; ci < numChannels(); ci++) { - bool gainEn = channels[ci]->info()->gainEn(ci); - bool offsetEn = channels[ci]->info()->offsetEn(ci); - double* mdata; + // TODO: we could use some kind of map (int32, int64 would suffice) to speed things up + bool gainEn = infoModel()->gainEn(ci); + bool offsetEn = infoModel()->offsetEn(ci); if (gainEn || offsetEn) { - if (mPack == nullptr) - mPack = new SamplePack(pack); + double* mdata = mPack->data(ci); - mdata = mPack->data(ci); - - double gain = channels[ci]->info()->gain(ci); - double offset = channels[ci]->info()->offset(ci); + double gain = infoModel()->gain(ci); + double offset = infoModel()->offset(ci); if (gainEn) { @@ -196,7 +195,9 @@ void Stream::feedIn(const SamplePack& pa } // modified pack that gain and offset is applied to - const SamplePack* mPack = applyGainOffset(pack); + const SamplePack* mPack = nullptr; + if (infoModel()->gainOrOffsetEn()) + mPack = applyGainOffset(pack); for (unsigned ci = 0; ci < numChannels(); ci++) { diff --git a/src/stream.h b/src/stream.h --- a/src/stream.h +++ b/src/stream.h @@ -102,13 +102,13 @@ private: /** * Applies gain and offset to given pack. * - * If gain or offset isn't enabled this function returns `nullptr`. If gain - * or offset is enabled for at least 1 channel input pack is copied and - * modified. Result is returned. Caller is responsible for deleting - * returned `SamplePack`. + * Caller is responsible for deleting returned `SamplePack`. + * + * @note Should be called only when gain or offset is enabled. Guard with + * `ChannelInfoModel::gainOrOffsetEn()`. * * @param pack input data - * @return `nullptr` if no gain or offset is enabled otherwise modified data + * @return modified data */ const SamplePack* applyGainOffset(const SamplePack& pack) const; };