diff --git a/src/library/basetracktablemodel.cpp b/src/library/basetracktablemodel.cpp index 605691cd78c..352e5ed6bf8 100644 --- a/src/library/basetracktablemodel.cpp +++ b/src/library/basetracktablemodel.cpp @@ -400,19 +400,14 @@ QVariant BaseTrackTableModel::data( } if (role == Qt::BackgroundRole) { - QModelIndex colorIndex = index.sibling( - index.row(), - fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COLOR)); - if (!colorIndex.isValid()) { + const auto rgbColorValue = rawSiblingValue( + index, + ColumnCache::COLUMN_LIBRARYTABLE_COLOR); + const auto rgbColor = mixxx::RgbColor::fromQVariant(rgbColorValue); + if (!rgbColor) { return QVariant(); } - const auto trackColor = - mixxx::RgbColor::fromQVariant( - rawValue(colorIndex)); - if (!trackColor) { - return QVariant(); - } - auto bgColor = mixxx::RgbColor::toQColor(trackColor); + auto bgColor = mixxx::RgbColor::toQColor(rgbColor); DEBUG_ASSERT(bgColor.isValid()); DEBUG_ASSERT(m_backgroundColorOpacity >= 0.0); DEBUG_ASSERT(m_backgroundColorOpacity <= 1.0); @@ -431,23 +426,65 @@ QVariant BaseTrackTableModel::data( return roleValue(index, rawValue(index), role); } +QVariant BaseTrackTableModel::rawValue( + const QModelIndex& index) const { + VERIFY_OR_DEBUG_ASSERT(index.isValid()) { + return QVariant(); + } + const auto field = mapColumn(index.column()); + if (field == ColumnCache::COLUMN_LIBRARYTABLE_INVALID) { + return QVariant(); + } + return rawSiblingValue(index, field); +} + +QVariant BaseTrackTableModel::rawSiblingValue( + const QModelIndex& index, + ColumnCache::Column siblingField) const { + VERIFY_OR_DEBUG_ASSERT(index.isValid()) { + return QVariant(); + } + VERIFY_OR_DEBUG_ASSERT(siblingField != ColumnCache::COLUMN_LIBRARYTABLE_INVALID) { + return QVariant(); + } + const auto siblingColumn = fieldIndex(siblingField); + DEBUG_ASSERT(siblingColumn >= 0); + VERIFY_OR_DEBUG_ASSERT(siblingColumn != index.column()) { + // Prevent infinite recursion + return QVariant(); + } + const auto siblingIndex = index.sibling(index.row(), siblingColumn); + return rawValue(siblingIndex); +} + bool BaseTrackTableModel::setData( const QModelIndex& index, const QVariant& value, int role) { const int column = index.column(); - - // Override sets to TIMESPLAYED and redirect them to PLAYED if (role == Qt::CheckStateRole) { - const auto val = value.toInt() > 0; - if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED)) { - QModelIndex playedIndex = index.sibling(index.row(), fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED)); - return setData(playedIndex, val, Qt::EditRole); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM)) { - QModelIndex bpmLockindex = index.sibling(index.row(), fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK)); - return setData(bpmLockindex, val, Qt::EditRole); + const auto field = mapColumn(index.column()); + if (field == ColumnCache::COLUMN_LIBRARYTABLE_INVALID) { + return false; + } + const auto checked = value.toInt() > 0; + switch (field) { + case ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED: { + // Override sets to TIMESPLAYED and redirect them to PLAYED + QModelIndex playedIndex = index.sibling( + index.row(), + fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED)); + return setData(playedIndex, checked, Qt::EditRole); + } + case ColumnCache::COLUMN_LIBRARYTABLE_BPM: { + QModelIndex bpmLockedIndex = index.sibling( + index.row(), + fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK)); + return setData(bpmLockedIndex, checked, Qt::EditRole); + } + default: + return false; } - return false; } TrackPointer pTrack = getTrack(index); @@ -497,133 +534,263 @@ QVariant BaseTrackTableModel::roleValue( const QModelIndex& index, QVariant&& rawValue, int role) const { - const int column = index.column(); - // Format the value based on whether we are in a tooltip, - // display, or edit role + const auto field = mapColumn(index.column()); + if (field == ColumnCache::COLUMN_LIBRARYTABLE_INVALID) { + return std::move(rawValue); + } switch (role) { case Qt::ToolTipRole: - if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COLOR)) { + switch (field) { + case ColumnCache::COLUMN_LIBRARYTABLE_COLOR: return mixxx::RgbColor::toQString(mixxx::RgbColor::fromQVariant(rawValue)); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART)) { + case ColumnCache::COLUMN_LIBRARYTABLE_COVERART: return composeCoverArtToolTipHtml(index); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW)) { + case ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW: return QVariant(); + default: + // Same value as for Qt::DisplayRole (see below) + break; } M_FALLTHROUGH_INTENDED; case Qt::DisplayRole: - if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DURATION)) { - bool ok; - const auto duration = rawValue.toDouble(&ok); - if (ok && duration >= 0) { - return mixxx::Duration::formatTime( - duration, - mixxx::Duration::Precision::SECONDS); + switch (field) { + case ColumnCache::COLUMN_LIBRARYTABLE_DURATION: { + if (rawValue.isNull()) { + return QVariant(); + } + double durationInSeconds; + if (rawValue.canConvert()) { + const auto duration = rawValue.value(); + VERIFY_OR_DEBUG_ASSERT(duration >= mixxx::Duration::empty()) { + return QVariant(); + } + durationInSeconds = duration.toDoubleSeconds(); } else { + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { + return QVariant(); + } + bool ok; + durationInSeconds = rawValue.toDouble(&ok); + VERIFY_OR_DEBUG_ASSERT(ok && durationInSeconds >= 0) { + return QVariant(); + } + } + return mixxx::Duration::formatTime( + durationInSeconds, + mixxx::Duration::Precision::SECONDS); + } + case ColumnCache::COLUMN_LIBRARYTABLE_RATING: { + if (rawValue.isNull()) { return QVariant(); } - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_RATING)) { - VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert(QMetaType::Int)) { + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { return QVariant(); } - return QVariant::fromValue(StarRating(rawValue.toInt())); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED)) { - return rawValue.toBool(); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED)) { - VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert(QMetaType::Int)) { + bool ok; + const auto starCount = rawValue.toInt(&ok); + VERIFY_OR_DEBUG_ASSERT(ok && starCount >= StarRating::kMinStarCount) { + return QVariant(); + } + return QVariant::fromValue(StarRating(starCount)); + } + case ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED: { + if (rawValue.isNull()) { + return QVariant(); + } + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { return QVariant(); } - return QString("(%1)").arg(rawValue.toInt()); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED) || - column == fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_DATETIMEADDED)) { - return mixxx::localDateTimeFromUtc(mixxx::convertVariantToDateTime(rawValue)); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM)) { bool ok; - const auto bpmValue = rawValue.toDouble(&ok); - if (ok && bpmValue > 0.0) { - return QString("%1").arg(bpmValue, 0, 'f', 1); + const auto timesPlayed = rawValue.toInt(&ok); + VERIFY_OR_DEBUG_ASSERT(ok && timesPlayed >= 0) { + return QVariant(); + } + return QString("(%1)").arg(timesPlayed); + } + case ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED: + case ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_DATETIMEADDED: + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { + return QVariant(); + } + return mixxx::localDateTimeFromUtc(rawValue.toDateTime()); + case ColumnCache::COLUMN_LIBRARYTABLE_BPM: { + mixxx::Bpm bpm; + if (!rawValue.isNull()) { + if (rawValue.canConvert()) { + bpm = rawValue.value(); + } else { + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { + return QVariant(); + } + bool ok; + const auto bpmValue = rawValue.toDouble(&ok); + VERIFY_OR_DEBUG_ASSERT(ok) { + return QVariant(); + } + bpm = mixxx::Bpm(bpmValue); + } + } + if (bpm.hasValue()) { + return QString("%1").arg(bpm.getValue(), 0, 'f', 1); } else { return QChar('-'); } - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK)) { - return rawValue.toBool(); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_YEAR)) { - return mixxx::TrackMetadata::formatCalendarYear(rawValue.toString()); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TRACKNUMBER)) { - const auto trackNumber = rawValue.toInt(0); - if (trackNumber > 0) { - return std::move(rawValue); - } else { - // clear invalid values + } + case ColumnCache::COLUMN_LIBRARYTABLE_YEAR: { + if (rawValue.isNull()) { + return QVariant(); + } + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { + return QVariant(); + } + bool ok; + const auto year = mixxx::TrackMetadata::formatCalendarYear(rawValue.toString(), &ok); + if (!ok) { return QVariant(); } - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BITRATE)) { - int bitrateValue = rawValue.toInt(0); - if (bitrateValue > 0) { + return year; + } + case ColumnCache::COLUMN_LIBRARYTABLE_BITRATE: { + if (rawValue.isNull()) { + return QVariant(); + } + if (rawValue.canConvert()) { + // return value as is return std::move(rawValue); } else { - // clear invalid values - return QVariant(); + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { + return QVariant(); + } + bool ok; + const auto bitrateValue = rawValue.toInt(&ok); + VERIFY_OR_DEBUG_ASSERT(ok) { + return QVariant(); + } + if (mixxx::audio::Bitrate(bitrateValue).isValid()) { + // return value as is + return std::move(rawValue); + } else { + // clear invalid values + return QVariant(); + } } - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY)) { + } + case ColumnCache::COLUMN_LIBRARYTABLE_KEY: { // If we know the semantic key via the LIBRARYTABLE_KEY_ID // column (as opposed to the string representation of the key // currently stored in the DB) then lookup the key and render it // using the user's selected notation. - int keyIdColumn = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY_ID); - if (keyIdColumn == -1) { - // Otherwise, just use the column value + const QVariant keyCodeValue = rawSiblingValue( + index, + ColumnCache::COLUMN_LIBRARYTABLE_KEY_ID); + if (keyCodeValue.isNull()) { + // Otherwise, just use the column value as is return std::move(rawValue); } - mixxx::track::io::key::ChromaticKey key = - KeyUtils::keyFromNumericValue( - index.sibling(index.row(), keyIdColumn).data().toInt()); + // Convert or clear invalid values + VERIFY_OR_DEBUG_ASSERT(keyCodeValue.canConvert()) { + return QVariant(); + } + bool ok; + const auto keyCode = keyCodeValue.toInt(&ok); + VERIFY_OR_DEBUG_ASSERT(ok) { + return QVariant(); + } + const auto key = KeyUtils::keyFromNumericValue(keyCode); if (key == mixxx::track::io::key::INVALID) { - // clear invalid values return QVariant(); } - // Render this key with the user-provided notation. + // Render the key with the user-provided notation return KeyUtils::keyToString(key); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_REPLAYGAIN)) { - bool ok; - const auto gainValue = rawValue.toDouble(&ok); - return ok ? mixxx::ReplayGain::ratioToString(gainValue) : QString(); } - // Otherwise, just use the column value + case ColumnCache::COLUMN_LIBRARYTABLE_REPLAYGAIN: { + if (rawValue.isNull()) { + return QVariant(); + } + double rgRatio; + if (rawValue.canConvert()) { + rgRatio = rawValue.value().getRatio(); + } else { + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { + return QVariant(); + } + bool ok; + rgRatio = rawValue.toDouble(&ok); + VERIFY_OR_DEBUG_ASSERT(ok) { + return QVariant(); + } + } + return mixxx::ReplayGain::ratioToString(rgRatio); + } + case ColumnCache::COLUMN_LIBRARYTABLE_CHANNELS: + // Not yet supported + DEBUG_ASSERT(rawValue.isNull()); + break; + case ColumnCache::COLUMN_LIBRARYTABLE_SAMPLERATE: + // Not yet supported + DEBUG_ASSERT(rawValue.isNull()); + break; + case ColumnCache::COLUMN_LIBRARYTABLE_URL: + // Not yet supported + DEBUG_ASSERT(rawValue.isNull()); + break; + default: + // Otherwise, just use the column value + break; + } break; case Qt::EditRole: - if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM)) { + switch (field) { + case ColumnCache::COLUMN_LIBRARYTABLE_BPM: { bool ok; const auto bpmValue = rawValue.toDouble(&ok); - return ok ? bpmValue : 0.0; - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED)) { + return ok ? bpmValue : mixxx::Bpm().getValue(); + } + case ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED: return index.sibling( - index.row(), fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED)) - .data() - .toBool(); - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_RATING)) { - VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert(QMetaType::Int)) { + index.row(), + fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED)) + .data() + .toBool(); + case ColumnCache::COLUMN_LIBRARYTABLE_RATING: + VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert()) { return QVariant(); } return QVariant::fromValue(StarRating(rawValue.toInt())); + default: + // Otherwise, just use the column value + break; } - // Otherwise, just use the column value break; - case Qt::CheckStateRole: - if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED)) { - bool played = index.sibling( - index.row(), fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED)) - .data() - .toBool(); - return played ? Qt::Checked : Qt::Unchecked; - } else if (column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM)) { - bool locked = index.sibling( - index.row(), fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK)) - .data() - .toBool(); - return locked ? Qt::Checked : Qt::Unchecked; + case Qt::CheckStateRole: { + QVariant boolValue; + switch (field) { + case ColumnCache::COLUMN_LIBRARYTABLE_PREVIEW: + boolValue = rawValue; + break; + case ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED: + boolValue = rawSiblingValue( + index, + ColumnCache::COLUMN_LIBRARYTABLE_PLAYED); + break; + case ColumnCache::COLUMN_LIBRARYTABLE_BPM: + boolValue = rawSiblingValue( + index, + ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK); + break; + default: + // No check state supported + return QVariant(); } - // No check state supported - return QVariant(); + // Flags in the database are stored as integers that are + // convertible to bool. + if (!boolValue.isNull() && boolValue.canConvert()) { + return boolValue.toBool() ? Qt::Checked : Qt::Unchecked; + } else { + // Undecidable + return Qt::PartiallyChecked; + } + } default: DEBUG_ASSERT(!"unexpected role"); break; diff --git a/src/library/basetracktablemodel.h b/src/library/basetracktablemodel.h index 81b58337a09..f3fb96967bd 100644 --- a/src/library/basetracktablemodel.h +++ b/src/library/basetracktablemodel.h @@ -149,8 +149,58 @@ class BaseTrackTableModel : public QAbstractTableModel, public TrackModel { virtual Qt::ItemFlags readWriteFlags( const QModelIndex& index) const; + /// At least one of the following functions must be overridden, + /// because each default implementation will call the other + /// function!! + /// + /// Return the raw data value at the given index. + /// + /// Expected types by ColumnCache field (pass-through = not validated): + /// COLUMN_LIBRARYTABLE_ID: DbId::value_type (pass-through) + /// COLUMN_LIBRARYTABLE_ARTIST: QString (pass-through) + /// COLUMN_LIBRARYTABLE_TITLE: QString (pass-through) + /// COLUMN_LIBRARYTABLE_ALBUM: QString (pass-through) + /// COLUMN_LIBRARYTABLE_ALBUMARTIST: QString (pass-through) + /// COLUMN_LIBRARYTABLE_YEAR: QString (pass-through) + /// COLUMN_LIBRARYTABLE_GENRE: QString (pass-through) + /// COLUMN_LIBRARYTABLE_COMPOSER: QString (pass-through) + /// COLUMN_LIBRARYTABLE_GROUPING: QString (pass-through) + /// COLUMN_LIBRARYTABLE_TRACKNUMBER: QString (pass-through) + /// COLUMN_LIBRARYTABLE_FILETYPE: QString (pass-through) + /// COLUMN_LIBRARYTABLE_NATIVELOCATION: QString (pass-through) + /// COLUMN_LIBRARYTABLE_COMMENT: QString (pass-through) + /// COLUMN_LIBRARYTABLE_DURATION: double (seconds)/mixxx::Duration + /// COLUMN_LIBRARYTABLE_BITRATE: int (kbps)/mixxx::audio::Bitrate + /// COLUMN_LIBRARYTABLE_BPM: double (beats per minute)/mixxx::Bpm + /// COLUMN_LIBRARYTABLE_REPLAYGAIN: double (ratio)/mixxx::ReplayGain + /// COLUMN_LIBRARYTABLE_URL: QString (unsupported) + /// COLUMN_LIBRARYTABLE_SAMPLERATE: int (Hz)/mixxx::audio::SampleRate (unsupported) + /// COLUMN_LIBRARYTABLE_WAVESUMMARYHEX: QVariant (pass-through) + /// COLUMN_LIBRARYTABLE_CHANNELS: int/mixxx::audio::ChannelCount (unsupported) + /// COLUMN_LIBRARYTABLE_MIXXXDELETED: bool (pass-through) + /// COLUMN_LIBRARYTABLE_DATETIMEADDED: QDateTime + /// COLUMN_LIBRARYTABLE_HEADERPARSED: bool (pass-through) + /// COLUMN_LIBRARYTABLE_TIMESPLAYED: int + /// COLUMN_LIBRARYTABLE_PLAYED: bool + /// COLUMN_LIBRARYTABLE_RATING: int + /// COLUMN_LIBRARYTABLE_KEY: QString (literal key name, pass-through) + /// COLUMN_LIBRARYTABLE_KEY_ID: int (internal key code) + /// COLUMN_LIBRARYTABLE_BPM_LOCK: bool + /// COLUMN_LIBRARYTABLE_PREVIEW: bool + /// COLUMN_LIBRARYTABLE_COLOR: mixxx::RgbColor::code_t + /// COLUMN_LIBRARYTABLE_COVERART: virtual column for CoverArtDelegate + /// COLUMN_LIBRARYTABLE_COVERART_SOURCE: int (pass-through) + /// COLUMN_LIBRARYTABLE_COVERART_TYPE: int (pass-through) + /// COLUMN_LIBRARYTABLE_COVERART_LOCATION: QString (pass-through) + /// COLUMN_LIBRARYTABLE_COVERART_COLOR: mixxx::RgbColor::code_t (pass-through) + /// COLUMN_LIBRARYTABLE_COVERART_DIGEST: QByteArray (pass-through) + /// COLUMN_LIBRARYTABLE_COVERART_HASH: quint16 (pass-through) + /// COLUMN_PLAYLISTTABLE_DATETIMEADDED: QDateTime virtual QVariant rawValue( - const QModelIndex& index) const = 0; + const QModelIndex& index) const; + virtual QVariant rawSiblingValue( + const QModelIndex& index, + ColumnCache::Column siblingField) const; // Reimplement in derived classes to handle columns other // then COLUMN_LIBRARYTABLE diff --git a/src/library/starrating.cpp b/src/library/starrating.cpp index a64941482a6..c062b28b70a 100644 --- a/src/library/starrating.cpp +++ b/src/library/starrating.cpp @@ -8,9 +8,13 @@ // Magic number? Explain what this factor affects and how const int PaintingScaleFactor = 15; -StarRating::StarRating(int starCount, int maxStarCount) - : m_myStarCount(starCount), - m_myMaxStarCount(maxStarCount) { +StarRating::StarRating( + int starCount, + int maxStarCount) + : m_starCount(starCount), + m_maxStarCount(maxStarCount) { + DEBUG_ASSERT(m_starCount >= kMinStarCount); + DEBUG_ASSERT(m_starCount <= m_maxStarCount); // 1st star cusp at 0° of the unit circle whose center is shifted to adapt the 0,0-based paint area m_starPolygon << QPointF(1.0, 0.5); for (int i = 1; i < 5; ++i) { @@ -26,7 +30,7 @@ StarRating::StarRating(int starCount, int maxStarCount) } QSize StarRating::sizeHint() const { - return PaintingScaleFactor * QSize(m_myMaxStarCount, 1); + return PaintingScaleFactor * QSize(m_maxStarCount, 1); } void StarRating::paint(QPainter *painter, const QRect &rect) const { @@ -41,8 +45,8 @@ void StarRating::paint(QPainter *painter, const QRect &rect) const { //determine number of stars that are possible to paint int n = rect.width() / PaintingScaleFactor; - for (int i = 0; i < m_myMaxStarCount && idrawPolygon(m_starPolygon, Qt::WindingFill); } else { painter->drawPolygon(m_diamondPolygon, Qt::WindingFill); diff --git a/src/library/starrating.h b/src/library/starrating.h index df21447758f..2a7d1319450 100644 --- a/src/library/starrating.h +++ b/src/library/starrating.h @@ -4,6 +4,8 @@ #include #include +#include "track/trackrecord.h" + QT_FORWARD_DECLARE_CLASS(QPainter); QT_FORWARD_DECLARE_CLASS(QRect); @@ -18,21 +20,32 @@ class StarRating { public: enum EditMode { Editable, ReadOnly }; - StarRating(int starCount = 1, int maxStarCount = 5); + static constexpr int kMinStarCount = 0; + + explicit StarRating( + int starCount = kMinStarCount, + int maxStarCount = mixxx::TrackRecord::kMaxRating - mixxx::TrackRecord::kMinRating); void paint(QPainter* painter, const QRect& rect) const; QSize sizeHint() const; - int starCount() const { return m_myStarCount; } - int maxStarCount() const { return m_myMaxStarCount; } - void setStarCount(int starCount) { m_myStarCount = starCount; } - void setMaxStarCount(int maxStarCount) { m_myMaxStarCount = maxStarCount; } + int starCount() const { + return m_starCount; + } + int maxStarCount() const { + return m_maxStarCount; + } + void setStarCount(int starCount) { + DEBUG_ASSERT(starCount >= kMinStarCount); + DEBUG_ASSERT(starCount <= m_maxStarCount); + m_starCount = starCount; + } private: QPolygonF m_starPolygon; QPolygonF m_diamondPolygon; - int m_myStarCount; - int m_myMaxStarCount; + int m_starCount; + int m_maxStarCount; }; Q_DECLARE_METATYPE(StarRating) diff --git a/src/track/trackrecord.h b/src/track/trackrecord.h index 1a9d2ae369d..bf819acc647 100644 --- a/src/track/trackrecord.h +++ b/src/track/trackrecord.h @@ -66,8 +66,15 @@ class TrackRecord final { TrackRecord& operator=(TrackRecord&&) = default; TrackRecord& operator=(const TrackRecord&) = default; + static constexpr int kMinRating = 0; + static constexpr int kMaxRating = 5; + static constexpr int kNoRating = kMinRating; + + static bool isValidRating(int rating) { + return rating >= kMinRating && rating <= kMaxRating; + } bool hasRating() const { - return getRating() > 0; + return getRating() != kNoRating; } void setKeys(const Keys& keys);