600 lines
24 KiB
C++
600 lines
24 KiB
C++
#include "importmidi_trmodel.h"
|
|
#include "importmidi_operations.h"
|
|
|
|
|
|
namespace Ms {
|
|
|
|
TracksModel::TracksModel()
|
|
: trackCount_(0)
|
|
, colCount_(TrackCol::COL_COUNT)
|
|
{
|
|
}
|
|
|
|
void TracksModel::reset(const QList<TrackMeta> &tracksMeta)
|
|
{
|
|
beginResetModel();
|
|
trackCount_ = tracksMeta.size();
|
|
tracksData_.clear();
|
|
int i = 0;
|
|
for (const auto &meta: tracksMeta) {
|
|
TrackOperations ops; // initialized by default values - see ctor
|
|
ops.reorderedIndex = i++;
|
|
ops.lyricTrackIndex = meta.initLyricTrackIndex;
|
|
tracksData_.push_back({meta, ops});
|
|
}
|
|
endResetModel();
|
|
}
|
|
|
|
void TracksModel::reset(const QList<TrackData> &tracksData)
|
|
{
|
|
beginResetModel();
|
|
trackCount_ = tracksData.size();
|
|
tracksData_ = tracksData;
|
|
endResetModel();
|
|
}
|
|
|
|
void TracksModel::clear()
|
|
{
|
|
beginResetModel();
|
|
trackCount_ = 0;
|
|
tracksData_.clear();
|
|
endResetModel();
|
|
}
|
|
|
|
void TracksModel::setOperation(int row, MidiOperation::Type operType, const QVariant &operValue)
|
|
{
|
|
const int trackIndex = trackIndexFromRow(row);
|
|
if (trackIndex == -1)
|
|
setOperationForAllTracks(operType, operValue);
|
|
else if (isTrackIndexValid(trackIndex))
|
|
setTrackOperation(trackIndex, operType, operValue);
|
|
}
|
|
|
|
void TracksModel::setTrackReorderedIndex(int trackIndex, int reorderIndex)
|
|
{
|
|
if (!isTrackIndexValid(trackIndex))
|
|
return;
|
|
tracksData_[trackIndex].opers.reorderedIndex = reorderIndex;
|
|
}
|
|
|
|
void TracksModel::setLyricsList(const QList<std::string> &list)
|
|
{
|
|
lyricsList_ = list;
|
|
}
|
|
|
|
void TracksModel::setOperationForAllTracks(MidiOperation::Type operType,
|
|
const QVariant &operValue)
|
|
{
|
|
for (int i = 0; i != trackCount_; ++i)
|
|
setTrackOperation(i, operType, operValue);
|
|
}
|
|
|
|
void TracksModel::setTrackOperation(int trackIndex, MidiOperation::Type operType,
|
|
const QVariant &operValue)
|
|
{
|
|
if (!operValue.isValid() || !isTrackIndexValid(trackIndex))
|
|
return;
|
|
TrackData &trackData = tracksData_[trackIndex];
|
|
|
|
switch (operType) {
|
|
case MidiOperation::Type::QUANT_VALUE:
|
|
trackData.opers.quantize.value = (MidiOperation::QuantValue)operValue.toInt();
|
|
break;
|
|
case MidiOperation::Type::QUANT_REDUCE:
|
|
trackData.opers.quantize.reduceToShorterNotesInBar = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::QUANT_HUMAN:
|
|
trackData.opers.quantize.humanPerformance = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::DO_LHRH_SEPARATION:
|
|
trackData.opers.LHRH.doIt = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::SPLIT_DRUMS:
|
|
trackData.opers.splitDrums.doSplit = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::SHOW_STAFF_BRACKET:
|
|
trackData.opers.splitDrums.showStaffBracket = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::REMOVE_DRUM_RESTS:
|
|
trackData.opers.removeDrumRests = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::LHRH_METHOD:
|
|
trackData.opers.LHRH.method = (MidiOperation::LHRHMethod)operValue.toInt();
|
|
break;
|
|
case MidiOperation::Type::LHRH_SPLIT_OCTAVE:
|
|
trackData.opers.LHRH.splitPitchOctave
|
|
= (MidiOperation::Octave)operValue.toInt();
|
|
break;
|
|
case MidiOperation::Type::LHRH_SPLIT_NOTE:
|
|
trackData.opers.LHRH.splitPitchNote = (MidiOperation::Note)operValue.toInt();
|
|
break;
|
|
case MidiOperation::Type::USE_DOTS:
|
|
trackData.opers.useDots = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::SWING:
|
|
trackData.opers.swing = (MidiOperation::Swing)operValue.toInt();
|
|
break;
|
|
case MidiOperation::Type::USE_MULTIPLE_VOICES:
|
|
trackData.opers.useMultipleVoices = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_SEARCH:
|
|
trackData.opers.tuplets.doSearch = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_2:
|
|
trackData.opers.tuplets.duplets = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_3:
|
|
trackData.opers.tuplets.triplets = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_4:
|
|
trackData.opers.tuplets.quadruplets = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_5:
|
|
trackData.opers.tuplets.quintuplets = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_7:
|
|
trackData.opers.tuplets.septuplets = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::TUPLET_9:
|
|
trackData.opers.tuplets.nonuplets = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::CHANGE_CLEF:
|
|
trackData.opers.changeClef = operValue.toBool();
|
|
break;
|
|
case MidiOperation::Type::PICKUP_MEASURE:
|
|
trackData.opers.pickupMeasure = operValue.toBool();
|
|
break;
|
|
|
|
case MidiOperation::Type::DO_IMPORT:
|
|
case MidiOperation::Type::LYRIC_TRACK_INDEX:
|
|
break;
|
|
}
|
|
}
|
|
|
|
DefinedTrackOperations TracksModel::trackOperations(int row) const
|
|
{
|
|
DefinedTrackOperations opers;
|
|
const int trackIndex = trackIndexFromRow(row);
|
|
opers.allTracksSelected = (trackIndex == -1 || trackCount_ == 1);
|
|
|
|
if (trackIndex == -1) {
|
|
// all tracks row case
|
|
// find tracks that operation values are different
|
|
// and mark them as undefined
|
|
|
|
opers.opers = tracksData_.front().opers;
|
|
opers.isDrumTrack = false;
|
|
|
|
// MidiOperation::Type::QUANT_VALUE
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.quantize.value != opers.opers.quantize.value) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::QUANT_VALUE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::QUANT_REDUCE
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.quantize.reduceToShorterNotesInBar
|
|
!= opers.opers.quantize.reduceToShorterNotesInBar) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::QUANT_REDUCE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::QUANT_HUMAN
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.quantize.humanPerformance
|
|
!= opers.opers.quantize.humanPerformance) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::QUANT_HUMAN);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::DO_LHRH_SEPARATION
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.LHRH.doIt != opers.opers.LHRH.doIt) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::DO_LHRH_SEPARATION);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::SPLIT_DRUMS
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.splitDrums.doSplit != opers.opers.splitDrums.doSplit) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::SPLIT_DRUMS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::SHOW_STAFF_BRACKET
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.splitDrums.showStaffBracket != opers.opers.splitDrums.showStaffBracket) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::SHOW_STAFF_BRACKET);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::REMOVE_DRUM_RESTS
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.removeDrumRests != opers.opers.removeDrumRests) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::REMOVE_DRUM_RESTS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::LHRH_METHOD
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.LHRH.method != opers.opers.LHRH.method) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::LHRH_METHOD);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::LHRH_SPLIT_OCTAVE
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.LHRH.splitPitchOctave
|
|
!= opers.opers.LHRH.splitPitchOctave) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::LHRH_SPLIT_OCTAVE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::LHRH_SPLIT_NOTE
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.LHRH.splitPitchNote
|
|
!= opers.opers.LHRH.splitPitchNote) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::LHRH_SPLIT_NOTE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::USE_DOTS
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.useDots != opers.opers.useDots) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::USE_DOTS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::SWING
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.swing != opers.opers.swing) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::SWING);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::USE_MULTIPLE_VOICES
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.useMultipleVoices != opers.opers.useMultipleVoices) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::USE_MULTIPLE_VOICES);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::TUPLET_SEARCH
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.doSearch != opers.opers.tuplets.doSearch) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_SEARCH);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::TUPLET_2
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.duplets != opers.opers.tuplets.duplets) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::TUPLET_3
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.triplets != opers.opers.tuplets.triplets) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_3);
|
|
break;
|
|
}
|
|
}
|
|
// MidiOperation::Type::TUPLET_4
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.quadruplets != opers.opers.tuplets.quadruplets) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::TUPLET_5
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.quintuplets != opers.opers.tuplets.quintuplets) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_5);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::TUPLET_7
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.septuplets != opers.opers.tuplets.septuplets) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_7);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::TUPLET_9
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.tuplets.nonuplets != opers.opers.tuplets.nonuplets) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::TUPLET_9);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::CHANGE_CLEF
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.changeClef != opers.opers.changeClef) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::CHANGE_CLEF);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// MidiOperation::Type::PICKUP_MEASURE
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.pickupMeasure != opers.opers.pickupMeasure) {
|
|
opers.undefinedOpers.insert((int)MidiOperation::Type::PICKUP_MEASURE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
opers.opers = tracksData_[trackIndex].opers;
|
|
opers.isDrumTrack = tracksData_[trackIndex].meta.isDrumTrack;
|
|
}
|
|
|
|
return opers;
|
|
}
|
|
|
|
int TracksModel::rowFromTrackIndex(int trackIndex) const
|
|
{
|
|
// first row reserved for all tracks if track count > 1
|
|
return (trackCount_ > 1) ? trackIndex + 1 : trackIndex;
|
|
}
|
|
|
|
int TracksModel::trackIndexFromRow(int row) const
|
|
{
|
|
// first row reserved for all tracks if track count > 1
|
|
// return -1 if row is all tracks row
|
|
return (trackCount_ > 1) ? row - 1 : row;
|
|
}
|
|
|
|
int TracksModel::numberOfTracksForImport() const
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.doImport)
|
|
++count;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
int TracksModel::rowCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return (trackCount_ > 1) ? trackCount_ + 1 : trackCount_;
|
|
}
|
|
|
|
int TracksModel::columnCount(const QModelIndex &/*parent*/) const
|
|
{
|
|
return colCount_;
|
|
}
|
|
|
|
Qt::CheckState TracksModel::areAllTracksForImport() const
|
|
{
|
|
if (trackCount_ == 0)
|
|
return Qt::Unchecked;
|
|
const bool doFirstTrackImport = tracksData_[0].opers.doImport;
|
|
for (int i = 1; i != trackCount_; ++i) {
|
|
if (tracksData_[i].opers.doImport != doFirstTrackImport)
|
|
return Qt::PartiallyChecked;
|
|
}
|
|
return (doFirstTrackImport) ? Qt::Checked : Qt::Unchecked;
|
|
}
|
|
|
|
QVariant TracksModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid())
|
|
return QVariant();
|
|
|
|
const int trackIndex = trackIndexFromRow(index.row());
|
|
switch (role) {
|
|
case Qt::DisplayRole:
|
|
switch (index.column()) {
|
|
case TrackCol::TRACK_NUMBER:
|
|
if (trackIndex == -1)
|
|
return QCoreApplication::translate("MIDI import operations", "All");
|
|
return trackIndex + 1;
|
|
case TrackCol::LYRICS:
|
|
{
|
|
if (trackIndex == -1)
|
|
return "";
|
|
int lyricTrack = tracksData_[trackIndex].opers.lyricTrackIndex;
|
|
if (lyricTrack == -1)
|
|
return "";
|
|
if (lyricTrack >= 0 && lyricTrack < lyricsList_.size())
|
|
return MidiCharset::convertToCharset(lyricsList_[lyricTrack]);
|
|
}
|
|
break;
|
|
case TrackCol::STAFF_NAME:
|
|
if (trackIndex == -1)
|
|
return "";
|
|
return MidiCharset::convertToCharset(
|
|
tracksData_[trackIndex].meta.staffName);
|
|
case TrackCol::INSTRUMENT:
|
|
if (trackIndex == -1)
|
|
return "";
|
|
return tracksData_[trackIndex].meta.instrumentName;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case Qt::EditRole:
|
|
if (index.column() == TrackCol::LYRICS && trackIndex != -1) {
|
|
if (!lyricsList_.isEmpty()) {
|
|
auto list = QStringList("");
|
|
for (const auto &lyric: lyricsList_)
|
|
list.append(MidiCharset::convertToCharset(lyric));
|
|
return list;
|
|
}
|
|
}
|
|
break;
|
|
case Qt::CheckStateRole:
|
|
switch (index.column()) {
|
|
case TrackCol::DO_IMPORT:
|
|
if (trackIndex == -1)
|
|
return areAllTracksForImport();
|
|
return (tracksData_[trackIndex].opers.doImport)
|
|
? Qt::Checked : Qt::Unchecked;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case Qt::TextAlignmentRole:
|
|
if (index.column() == TrackCol::LYRICS)
|
|
return Qt::AlignLeft + Qt::AlignVCenter;
|
|
else
|
|
return Qt::AlignCenter;
|
|
break;
|
|
case Qt::ToolTipRole:
|
|
if (trackIndex != -1) {
|
|
switch (index.column()) {
|
|
case TrackCol::STAFF_NAME:
|
|
return MidiCharset::convertToCharset(
|
|
tracksData_[trackIndex].meta.staffName);
|
|
case TrackCol::INSTRUMENT:
|
|
return tracksData_[trackIndex].meta.instrumentName;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
Qt::ItemFlags TracksModel::flags(const QModelIndex &index) const
|
|
{
|
|
if (!index.isValid())
|
|
return 0;
|
|
Qt::ItemFlags flags = Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
|
if (index.column() == TrackCol::DO_IMPORT)
|
|
flags |= Qt::ItemIsUserCheckable;
|
|
if (index.column() == TrackCol::LYRICS
|
|
&& !lyricsList_.isEmpty()
|
|
&& trackIndexFromRow(index.row()) != -1) {
|
|
flags |= Qt::ItemIsEditable;
|
|
}
|
|
return flags;
|
|
}
|
|
|
|
void TracksModel::forceColumnDataChanged(int col)
|
|
{
|
|
const auto begIndex = this->index(0, col);
|
|
const auto endIndex = this->index(rowCount(QModelIndex()), col);
|
|
emit dataChanged(begIndex, endIndex);
|
|
}
|
|
|
|
bool TracksModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
|
{
|
|
bool result = false;
|
|
const int trackIndex = trackIndexFromRow(index.row());
|
|
|
|
if (trackIndex == -1) { // all tracks row
|
|
if (index.column() == TrackCol::DO_IMPORT && role == Qt::CheckStateRole) {
|
|
for (auto &trackData: tracksData_)
|
|
trackData.opers.doImport = value.toBool();
|
|
result = true;
|
|
}
|
|
if (result) {
|
|
// update checkboxes of all tracks
|
|
// because we've changed option for all tracks simultaneously
|
|
forceColumnDataChanged(TrackCol::DO_IMPORT);
|
|
}
|
|
}
|
|
else {
|
|
TrackData *trackData = trackDataFromIndex(index);
|
|
if (!trackData)
|
|
return false;
|
|
if (index.column() == TrackCol::DO_IMPORT && role == Qt::CheckStateRole) {
|
|
trackData->opers.doImport = value.toBool();
|
|
result = true;
|
|
}
|
|
else if (index.column() == TrackCol::LYRICS && role == Qt::EditRole) {
|
|
trackData->opers.lyricTrackIndex = value.toInt() - 1;
|
|
result = true;
|
|
}
|
|
if (result) {
|
|
// update checkbox of current track row
|
|
emit dataChanged(index, index);
|
|
// update checkbox of <all tracks> row
|
|
const auto allIndex = this->index(0, TrackCol::DO_IMPORT);
|
|
emit dataChanged(allIndex, allIndex);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QVariant TracksModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
|
switch (section) {
|
|
case TrackCol::DO_IMPORT:
|
|
return QCoreApplication::translate("MIDI import track list", "Import");
|
|
case TrackCol::TRACK_NUMBER:
|
|
return QCoreApplication::translate("MIDI import track list", "Track");
|
|
case TrackCol::LYRICS:
|
|
return QCoreApplication::translate("MIDI import track list", "Lyrics");
|
|
case TrackCol::STAFF_NAME:
|
|
return QCoreApplication::translate("MIDI import track list", "Staff Name");
|
|
case TrackCol::INSTRUMENT:
|
|
return QCoreApplication::translate("MIDI import track list", "Sound");
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
TrackData TracksModel::trackData(int trackIndex) const
|
|
{
|
|
if (isTrackIndexValid(trackIndex))
|
|
return tracksData_[trackIndex];
|
|
return TrackData();
|
|
}
|
|
|
|
TrackData* TracksModel::trackDataFromIndex(const QModelIndex &index)
|
|
{
|
|
if (index.isValid()) {
|
|
if (!isMappingRowToTrackValid(index.row()) || !isColumnValid(index.column()))
|
|
return nullptr;
|
|
return &tracksData_[trackIndexFromRow(index.row())];
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool TracksModel::isMappingRowToTrackValid(int row) const
|
|
{
|
|
if (trackCount_ > 1) // first row is reserved for all tracks
|
|
return (row > 0 && row <= trackCount_);
|
|
return row >= 0 && row < trackCount_;
|
|
}
|
|
|
|
bool TracksModel::isColumnValid(int column) const
|
|
{
|
|
return (column >= 0 && column < colCount_);
|
|
}
|
|
|
|
bool TracksModel::isTrackIndexValid(int trackIndex) const
|
|
{
|
|
return trackIndex >= 0 && trackIndex < trackCount_;
|
|
}
|
|
|
|
} // namespace Ms
|