Skip to content

Commit

Permalink
Merge pull request #10 from uklotzde/last-played-squashed
Browse files Browse the repository at this point in the history
Fix reading/writing of library.last_played_at
  • Loading branch information
ywwg authored Dec 28, 2020
2 parents 70b0738 + 2ffbd01 commit 57ac9c8
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 4 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/util/db/fwdsqlquery.cpp
src/util/db/fwdsqlqueryselectresult.cpp
src/util/db/sqllikewildcardescaper.cpp
src/util/db/sqlite.cpp
src/util/db/sqlqueryfinisher.cpp
src/util/db/sqlstringformatter.cpp
src/util/db/sqltransaction.cpp
Expand Down
9 changes: 9 additions & 0 deletions res/schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,15 @@ METADATA
<description>
Add last_played_at column to library table
</description>
<sql>
-- Add new column
ALTER TABLE library ADD COLUMN last_played_at DATETIME DEFAULT NULL;
</sql>
</revision>
<revision version="36" min_compatible="3">
<description>
Populate last_played_at column in library table from play history
</description>
<sql>
-- Add new column
ALTER TABLE library ADD COLUMN last_played_at DATETIME DEFAULT NULL;
Expand Down
14 changes: 13 additions & 1 deletion src/library/basetracktablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "util/assert.h"
#include "util/compatibility.h"
#include "util/datetime.h"
#include "util/db/sqlite.h"
#include "util/logger.h"
#include "widget/wlibrary.h"
#include "widget/wtracktableview.h"
Expand Down Expand Up @@ -618,12 +619,23 @@ QVariant BaseTrackTableModel::roleValue(
return QString("(%1)").arg(timesPlayed);
}
case ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED:
case ColumnCache::COLUMN_LIBRARYTABLE_LAST_PLAYED_AT:
case ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_DATETIMEADDED:
VERIFY_OR_DEBUG_ASSERT(rawValue.canConvert<QDateTime>()) {
return QVariant();
}
return mixxx::localDateTimeFromUtc(rawValue.toDateTime());
case ColumnCache::COLUMN_LIBRARYTABLE_LAST_PLAYED_AT: {
QDateTime lastPlayedAt;
if (rawValue.type() == QVariant::String) {
// column value
lastPlayedAt = mixxx::sqlite::readGeneratedTimestamp(rawValue);
} else {
// cached in memory (local time)
lastPlayedAt = rawValue.toDateTime().toUTC();
}
DEBUG_ASSERT(lastPlayedAt.timeSpec() == Qt::UTC);
return mixxx::localDateTimeFromUtc(lastPlayedAt);
}
case ColumnCache::COLUMN_LIBRARYTABLE_BPM: {
mixxx::Bpm bpm;
if (!rawValue.isNull()) {
Expand Down
9 changes: 6 additions & 3 deletions src/library/dao/trackdao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "util/compatibility.h"
#include "util/datetime.h"
#include "util/db/fwdsqlquery.h"
#include "util/db/sqlite.h"
#include "util/db/sqllikewildcardescaper.h"
#include "util/db/sqllikewildcards.h"
#include "util/db/sqlstringformatter.h"
Expand Down Expand Up @@ -554,7 +555,8 @@ void bindTrackLibraryValues(

const PlayCounter& playCounter = track.getPlayCounter();
pTrackLibraryQuery->bindValue(":timesplayed", playCounter.getTimesPlayed());
pTrackLibraryQuery->bindValue(":last_played_at", playCounter.getLastPlayedAt());
pTrackLibraryQuery->bindValue(":last_played_at",
mixxx::sqlite::writeGeneratedTimestamp(playCounter.getLastPlayedAt()));
pTrackLibraryQuery->bindValue(":played", playCounter.isPlayed() ? 1 : 0);

const CoverInfoRelative& coverInfo = track.getCoverInfo();
Expand Down Expand Up @@ -1170,8 +1172,9 @@ bool setTrackPlayed(const QSqlRecord& record, const int column,
}

bool setTrackLastPlayedAt(const QSqlRecord& record, const int column, TrackPointer pTrack) {
PlayCounter playCounter(pTrack->getPlayCounter());
playCounter.setLastPlayedAt(record.value(column).toDateTime());
auto playCounter = pTrack->getPlayCounter();
playCounter.setLastPlayedAt(
mixxx::sqlite::readGeneratedTimestamp(record.value(column)));
pTrack->setPlayCounter(playCounter);
return false;
}
Expand Down
52 changes: 52 additions & 0 deletions src/util/db/sqlite.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "util/db/sqlite.h"

#include "util/assert.h"

namespace {

/// Date/time formate generated by SQLite CURRENT_TIMESTAMP (UTC) that is
/// used for library.last_played_at and PlalistTracks.pl_datetime_added.
/// QStringBuilder cannot be used to compose this constant at compile time!
const QString kGeneratedTimestampFormat =
QStringLiteral("yyyy-MM-dd hh:mm:ss"); // date + separator + time
const QString kGeneratedTimestampDateFormat = QStringLiteral("yyyy-MM-dd");
const QString kGeneratedTimestampTimeFormat = QStringLiteral("hh:mm:ss");
const QChar kGeneratedTimestampDateTimeSeparator = QChar(' ');

} // namespace

namespace mixxx {

namespace sqlite {

QDateTime readGeneratedTimestamp(const QVariant& value) {
DEBUG_ASSERT(kGeneratedTimestampFormat ==
kGeneratedTimestampDateFormat +
kGeneratedTimestampDateTimeSeparator +
kGeneratedTimestampTimeFormat);
const auto timestamp = value.toString();
if (timestamp.isEmpty()) {
return QDateTime();
}
const auto parts = timestamp.split(kGeneratedTimestampDateTimeSeparator);
VERIFY_OR_DEBUG_ASSERT(parts.size() == 2) {
return QDateTime();
}
const auto date = QDate::fromString(parts[0], kGeneratedTimestampDateFormat);
VERIFY_OR_DEBUG_ASSERT(date.isValid()) {
return QDateTime();
}
const auto time = QTime::fromString(parts[1], kGeneratedTimestampTimeFormat);
VERIFY_OR_DEBUG_ASSERT(time.isValid()) {
return QDateTime();
}
return QDateTime(date, time, Qt::UTC);
}

QVariant writeGeneratedTimestamp(const QDateTime& value) {
return value.toUTC().toString(kGeneratedTimestampFormat);
}

} // namespace sqlite

} // namespace mixxx
15 changes: 15 additions & 0 deletions src/util/db/sqlite.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <QDateTime>
#include <QVariant>

namespace mixxx {
namespace sqlite {

QDateTime readGeneratedTimestamp(const QVariant& value);

QVariant writeGeneratedTimestamp(const QDateTime& value);

} // namespace sqlite

} // namespace mixxx

0 comments on commit 57ac9c8

Please sign in to comment.