Commit 9e28b008 authored by Alexander Stippich's avatar Alexander Stippich

Make MediaPlayList responsible for remaining tracks

Summary:
Make MediaPlayList responsible for remaining tracks.
Allows simplification by only reacting to currentTrack
changes inside manageheaderbar.
Add tests for remainingTracks and cleanup manageheaderbar.
Fixes the remaining tracks showing when in playlist repeat
or shuffle mode.

Test Plan:
tests pass
Remaining tracks are only showed for when not in
shuffle or repeat mode

Reviewers: ngraham, mgallien

Reviewed By: mgallien

Tags: #elisa

Differential Revision: https://phabricator.kde.org/D22769
parent 999d10eb
This diff is collapsed.
......@@ -65,25 +65,9 @@ private Q_SLOTS:
void simpleInitialCase();
void setCurrentTrackCase();
void setCurrentTrackWithInvalidData();
void setCurrentTrackCaseFromNewAlbum();
void completeCase();
void setCurrentTrackAndInvalidCase();
void setCurrentTrackAndRemoveItCase();
void insertBeforeCurrentTrack();
void moveCurrentTrack();
void moveAnotherTrack();
void setCurrentTrackTest();
void setPlayListModelTest();
void setCurrentTrackWithData();
};
......
......@@ -6231,6 +6231,99 @@ void MediaPlayListTest::singleTrack()
QCOMPARE(myPlayList.currentTrack(), QPersistentModelIndex(myPlayList.index(0, 0)));
}
void MediaPlayListTest::remainingTracksTest()
{
MediaPlayList myPlayList;
QAbstractItemModelTester testModel(&myPlayList);
DatabaseInterface myDatabaseContent;
TracksListener myListener(&myDatabaseContent);
QSignalSpy currentTrackChangedSpy(&myPlayList, &MediaPlayList::currentTrackChanged);
QSignalSpy randomPlayChangedSpy(&myPlayList, &MediaPlayList::randomPlayChanged);
QSignalSpy repeatPlayChangedSpy(&myPlayList, &MediaPlayList::repeatPlayChanged);
QSignalSpy remainingTracksChangedSpy(&myPlayList, &MediaPlayList::remainingTracksChanged);
myDatabaseContent.init(QStringLiteral("testDbDirectContent"));
connect(&myListener, &TracksListener::trackHasChanged,
&myPlayList, &MediaPlayList::trackChanged,
Qt::QueuedConnection);
connect(&myListener, &TracksListener::tracksListAdded,
&myPlayList, &MediaPlayList::tracksListAdded,
Qt::QueuedConnection);
connect(&myPlayList, &MediaPlayList::newTrackByNameInList,
&myListener, &TracksListener::trackByNameInList,
Qt::QueuedConnection);
connect(&myPlayList, &MediaPlayList::newEntryInList,
&myListener, &TracksListener::newEntryInList,
Qt::QueuedConnection);
connect(&myDatabaseContent, &DatabaseInterface::tracksAdded,
&myListener, &TracksListener::tracksAdded);
myDatabaseContent.insertTracksList(mNewTracks, mNewCovers);
QCOMPARE(currentTrackChangedSpy.count(), 0);
QCOMPARE(randomPlayChangedSpy.count(), 0);
QCOMPARE(repeatPlayChangedSpy.count(), 0);
QCOMPARE(remainingTracksChangedSpy.count(), 0);
myPlayList.enqueue({myDatabaseContent.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album2"), 1, 1),
QStringLiteral("track1")},
ElisaUtils::Track);
myPlayList.enqueue({myDatabaseContent.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track3"), QStringLiteral("artist3"), QStringLiteral("album1"), 3, 3),
QStringLiteral("track3")},
ElisaUtils::Track);
myPlayList.enqueue({myDatabaseContent.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track4"), QStringLiteral("artist1"), QStringLiteral("album1"), 4, 4),
QStringLiteral("track4")},
ElisaUtils::Track);
myPlayList.enqueue({myDatabaseContent.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track2"), QStringLiteral("artist1"), QStringLiteral("album1"), 2, 2),
QStringLiteral("track2")},
ElisaUtils::Track);
myPlayList.enqueue({myDatabaseContent.trackIdFromTitleAlbumTrackDiscNumber(QStringLiteral("track1"), QStringLiteral("artist1"), QStringLiteral("album2"), 1, 1),
QStringLiteral("track1")},
ElisaUtils::Track);
QCOMPARE(currentTrackChangedSpy.count(), 0);
QCOMPARE(randomPlayChangedSpy.count(), 0);
QCOMPARE(repeatPlayChangedSpy.count(), 0);
QCOMPARE(remainingTracksChangedSpy.count(), 5);
QCOMPARE(currentTrackChangedSpy.wait(), true);
QCOMPARE(currentTrackChangedSpy.count(), 1);
QCOMPARE(randomPlayChangedSpy.count(), 0);
QCOMPARE(repeatPlayChangedSpy.count(), 0);
QCOMPARE(remainingTracksChangedSpy.count(), 6);
QCOMPARE(myPlayList.currentTrack(), QPersistentModelIndex(myPlayList.index(0, 0)));
QCOMPARE(myPlayList.remainingTracks(), 4);
myPlayList.skipNextTrack();
QCOMPARE(remainingTracksChangedSpy.count(), 7);
QCOMPARE(myPlayList.currentTrack(), QPersistentModelIndex(myPlayList.index(1, 0)));
QCOMPARE(myPlayList.remainingTracks(), 3);
myPlayList.setRandomPlay(true);
QCOMPARE(currentTrackChangedSpy.count(), 2);
QCOMPARE(randomPlayChangedSpy.count(), 1);
QCOMPARE(repeatPlayChangedSpy.count(), 0);
QCOMPARE(remainingTracksChangedSpy.count(), 8);
QCOMPARE(myPlayList.remainingTracks(), -1);
myPlayList.setRandomPlay(false);
myPlayList.setRepeatPlay(true);
QCOMPARE(currentTrackChangedSpy.count(), 2);
QCOMPARE(randomPlayChangedSpy.count(), 2);
QCOMPARE(repeatPlayChangedSpy.count(), 1);
QCOMPARE(remainingTracksChangedSpy.count(), 10);
QCOMPARE(myPlayList.remainingTracks(), -1);
}
void MediaPlayListTest::testBringUpAndRemoveLastCase()
{
MediaPlayList myPlayList;
......
......@@ -125,6 +125,8 @@ private Q_SLOTS:
void singleTrack();
void remainingTracksTest();
void testBringUpAndRemoveLastCase();
void testSaveAndRestoreSettings();
......
......@@ -393,7 +393,6 @@ void ElisaApplication::initializePlayer()
d->mManageHeaderBar->setDatabaseIdRole(MediaPlayList::DatabaseIdRole);
d->mManageHeaderBar->setAlbumIdRole(MediaPlayList::AlbumIdRole);
d->mManageHeaderBar->setIsValidRole(MediaPlayList::IsValidRole);
d->mManageHeaderBar->setPlayListModel(d->mMediaPlayList.get());
QObject::connect(d->mMediaPlayList.get(), &MediaPlayList::currentTrackChanged, d->mManageHeaderBar.get(), &ManageHeaderBar::setCurrentTrack);
if (!d->mArguments.isEmpty()) {
......
......@@ -19,9 +19,6 @@
#include <QTime>
#include <QTimer>
#include <QDebug>
#include <cstdlib>
ManageHeaderBar::ManageHeaderBar(QObject *parent)
: QObject(parent)
......@@ -206,15 +203,6 @@ bool ManageHeaderBar::isValid() const
return mCurrentTrack.data(mIsValidRole).toBool();
}
int ManageHeaderBar::remainingTracks() const
{
if (!mCurrentTrack.isValid()) {
return 0;
}
return mPlayListModel->rowCount(mCurrentTrack.parent()) - mCurrentTrack.row() - 1;
}
int ManageHeaderBar::isValidRole() const
{
return mIsValidRole;
......@@ -225,138 +213,6 @@ QPersistentModelIndex ManageHeaderBar::currentTrack() const
return mCurrentTrack;
}
void ManageHeaderBar::playListLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_UNUSED(parents);
Q_UNUSED(hint);
qDebug() << "ManageHeaderBar::playListLayoutChanged" << "not implemented";
}
void ManageHeaderBar::tracksInserted(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent);
Q_UNUSED(first);
Q_UNUSED(last);
if (!mCurrentTrack.isValid()) {
return;
}
if (mCurrentTrack.row() >= first) {
return;
}
Q_EMIT remainingTracksChanged();
mOldRemainingTracks = remainingTracks();
}
void ManageHeaderBar::tracksDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
if (!mCurrentTrack.isValid()) {
return;
}
if (mCurrentTrack.row() > bottomRight.row() || mCurrentTrack.row() < topLeft.row()) {
return;
}
if (mCurrentTrack.column() > bottomRight.column() || mCurrentTrack.column() < topLeft.column()) {
return;
}
if (roles.isEmpty()) {
notifyArtistProperty();
notifyTitleProperty();
notifyAlbumProperty();
notifyAlbumArtistProperty();
notifyFileNameProperty();
notifyImageProperty();
notifyDatabaseIdProperty();
notifyAlbumIdProperty();
notifyIsValidProperty();
} else {
for(auto oneRole : roles) {
if (oneRole == mArtistRole) {
notifyArtistProperty();
}
if (oneRole == mTitleRole) {
notifyTitleProperty();
}
if (oneRole == mAlbumRole) {
notifyAlbumProperty();
}
if (oneRole == mAlbumArtistRole) {
notifyAlbumArtistProperty();
}
if (oneRole == mFileNameRole) {
notifyFileNameProperty();
}
if (oneRole == mImageRole) {
notifyImageProperty();
}
if (oneRole == mDatabaseIdRole) {
notifyDatabaseIdProperty();
}
if (oneRole == mAlbumIdRole) {
notifyAlbumIdProperty();
}
if (oneRole == mIsValidRole) {
notifyIsValidProperty();
}
}
}
}
void ManageHeaderBar::tracksAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
{
Q_UNUSED(parent);
Q_UNUSED(start);
Q_UNUSED(end);
Q_UNUSED(destination);
Q_UNUSED(row);
mOldRemainingTracks = remainingTracks();
}
void ManageHeaderBar::tracksMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
{
Q_UNUSED(parent);
Q_UNUSED(start);
Q_UNUSED(end);
Q_UNUSED(destination);
Q_UNUSED(row);
auto newRemainingTracks = remainingTracks();
if (mOldRemainingTracks != newRemainingTracks) {
Q_EMIT remainingTracksChanged();
}
}
void ManageHeaderBar::tracksRemoved(const QModelIndex &parent, int first, int last)
{
Q_UNUSED(parent);
Q_UNUSED(first);
Q_UNUSED(last);
if (!mCurrentTrack.isValid()) {
notifyArtistProperty();
notifyTitleProperty();
notifyAlbumProperty();
notifyAlbumArtistProperty();
notifyFileNameProperty();
notifyImageProperty();
notifyDatabaseIdProperty();
notifyAlbumIdProperty();
notifyIsValidProperty();
notifyRemainingTracksProperty();
return;
}
notifyRemainingTracksProperty();
}
void ManageHeaderBar::notifyArtistProperty()
{
auto newArtistValue = mCurrentTrack.data(mArtistRole);
......@@ -457,16 +313,6 @@ void ManageHeaderBar::notifyIsValidProperty()
}
}
void ManageHeaderBar::notifyRemainingTracksProperty()
{
auto newRemainingTracksValue = remainingTracks();
if (mOldRemainingTracks != newRemainingTracksValue) {
Q_EMIT remainingTracksChanged();
mOldRemainingTracks = newRemainingTracksValue;
}
}
void ManageHeaderBar::setIsValidRole(int isValidRole)
{
mIsValidRole = isValidRole;
......@@ -475,20 +321,9 @@ void ManageHeaderBar::setIsValidRole(int isValidRole)
void ManageHeaderBar::setCurrentTrack(const QPersistentModelIndex &currentTrack)
{
if (mCurrentTrack == currentTrack) {
return;
}
auto oldRemainingTracksCount = remainingTracks();
mCurrentTrack = currentTrack;
Q_EMIT currentTrackChanged();
if (mCurrentTrack.isValid() && oldRemainingTracksCount != remainingTracks()) {
Q_EMIT remainingTracksChanged();
mOldRemainingTracks = remainingTracks();
}
notifyArtistProperty();
notifyTitleProperty();
notifyAlbumProperty();
......@@ -500,35 +335,4 @@ void ManageHeaderBar::setCurrentTrack(const QPersistentModelIndex &currentTrack)
notifyIsValidProperty();
}
void ManageHeaderBar::setPlayListModel(QAbstractItemModel *aPlayListModel)
{
if (mPlayListModel) {
disconnect(mPlayListModel, &QAbstractItemModel::rowsInserted, this, &ManageHeaderBar::tracksInserted);
disconnect(mPlayListModel, &QAbstractItemModel::rowsAboutToBeMoved, this, &ManageHeaderBar::tracksAboutToBeMoved);
disconnect(mPlayListModel, &QAbstractItemModel::rowsMoved, this, &ManageHeaderBar::tracksMoved);
disconnect(mPlayListModel, &QAbstractItemModel::rowsRemoved, this, &ManageHeaderBar::tracksRemoved);
disconnect(mPlayListModel, &QAbstractItemModel::dataChanged, this, &ManageHeaderBar::tracksDataChanged);
disconnect(mPlayListModel, &QAbstractItemModel::layoutChanged, this, &ManageHeaderBar::playListLayoutChanged);
}
mPlayListModel = aPlayListModel;
if (mPlayListModel) {
connect(mPlayListModel, &QAbstractItemModel::rowsInserted, this, &ManageHeaderBar::tracksInserted);
connect(mPlayListModel, &QAbstractItemModel::rowsAboutToBeMoved, this, &ManageHeaderBar::tracksAboutToBeMoved);
connect(mPlayListModel, &QAbstractItemModel::rowsMoved, this, &ManageHeaderBar::tracksMoved);
connect(mPlayListModel, &QAbstractItemModel::rowsRemoved, this, &ManageHeaderBar::tracksRemoved);
connect(mPlayListModel, &QAbstractItemModel::dataChanged, this, &ManageHeaderBar::tracksDataChanged);
connect(mPlayListModel, &QAbstractItemModel::layoutChanged, this, &ManageHeaderBar::playListLayoutChanged);
}
Q_EMIT playListModelChanged();
}
QAbstractItemModel *ManageHeaderBar::playListModel() const
{
return mPlayListModel;
}
#include "moc_manageheaderbar.cpp"
......@@ -36,11 +36,6 @@ class ELISALIB_EXPORT ManageHeaderBar : public QObject
WRITE setCurrentTrack
NOTIFY currentTrackChanged)
Q_PROPERTY(QAbstractItemModel* playListModel
READ playListModel
WRITE setPlayListModel
NOTIFY playListModelChanged)
Q_PROPERTY(int artistRole
READ artistRole
WRITE setArtistRole
......@@ -122,18 +117,12 @@ class ELISALIB_EXPORT ManageHeaderBar : public QObject
READ isValid
NOTIFY isValidChanged)
Q_PROPERTY(int remainingTracks
READ remainingTracks
NOTIFY remainingTracksChanged)
public:
explicit ManageHeaderBar(QObject *parent = nullptr);
QPersistentModelIndex currentTrack() const;
QAbstractItemModel* playListModel() const;
int artistRole() const;
int titleRole() const;
......@@ -170,14 +159,10 @@ public:
bool isValid() const;
int remainingTracks() const;
Q_SIGNALS:
void currentTrackChanged();
void playListModelChanged();
void artistRoleChanged();
void titleRoleChanged();
......@@ -208,8 +193,6 @@ Q_SIGNALS:
void imageChanged();
void remainingTracksChanged();
void databaseIdChanged();
void albumIdChanged();
......@@ -220,8 +203,6 @@ public Q_SLOTS:
void setCurrentTrack(const QPersistentModelIndex &currentTrack);
void setPlayListModel(QAbstractItemModel* aPlayListModel);
void setArtistRole(int value);
void setTitleRole(int value);
......@@ -240,18 +221,6 @@ public Q_SLOTS:
void setIsValidRole(int isValidRole);
void playListLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
void tracksInserted(const QModelIndex &parent, int first, int last);
void tracksDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
void tracksAboutToBeMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row);
void tracksMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row);
void tracksRemoved(const QModelIndex &parent, int first, int last);
private:
void notifyArtistProperty();
......@@ -272,12 +241,8 @@ private:
void notifyIsValidProperty();
void notifyRemainingTracksProperty();
QPersistentModelIndex mCurrentTrack;
QAbstractItemModel *mPlayListModel = nullptr;
int mArtistRole = Qt::DisplayRole;
int mTitleRole = Qt::DisplayRole;
......
......@@ -146,66 +146,66 @@ QVariant MediaPlayList::data(const QModelIndex &index, int role) const
}
case ColumnsRoles::AlbumSectionRole:
result = QJsonDocument{QJsonArray{d->mTrackData[index.row()][TrackDataType::key_type::AlbumRole].toString(),
d->mTrackData[index.row()][TrackDataType::key_type::AlbumArtistRole].toString(),
d->mTrackData[index.row()][TrackDataType::key_type::ImageUrlRole].toUrl().toString()}}.toJson();
break;
default:
const auto &trackData = d->mTrackData[index.row()];
auto roleEnum = static_cast<TrackDataType::key_type>(role);
auto itData = trackData.find(roleEnum);
if (itData != trackData.end()) {
result = itData.value();
} else {
result = {};
}
}
} else {
switch(role)
{
case ColumnsRoles::IsValidRole:
result = d->mData[index.row()].mIsValid;
break;
case ColumnsRoles::TitleRole:
result = d->mData[index.row()].mTitle;
break;
case ColumnsRoles::IsPlayingRole:
result = d->mData[index.row()].mIsPlaying;
break;
case ColumnsRoles::ArtistRole:
result = d->mData[index.row()].mArtist;
break;
case ColumnsRoles::AlbumArtistRole:
result = d->mData[index.row()].mArtist;
break;
case ColumnsRoles::AlbumRole:
result = d->mData[index.row()].mAlbum;
break;
case ColumnsRoles::TrackNumberRole:
result = -1;
break;
case ColumnsRoles::IsSingleDiscAlbumRole:
result = false;
break;
case Qt::DisplayRole:
result = d->mData[index.row()].mTitle;
break;
case ColumnsRoles::ImageUrlRole:
result = QUrl(QStringLiteral("image://icon/error"));
break;
case ColumnsRoles::ShadowForImageRole:
result = false;
break;
case ColumnsRoles::AlbumSectionRole:
result = QJsonDocument{QJsonArray{d->mData[index.row()].mAlbum.toString(),
d->mData[index.row()].mArtist.toString(),
QUrl(QStringLiteral("image://icon/error")).toString()}}.toJson();
break;
default:
d->mTrackData[index.row()][TrackDataType::key_type::AlbumArtistRole].toString(),
d->mTrackData[index.row()][TrackDataType::key_type::ImageUrlRole].toUrl().toString()}}.toJson();
break;
default:
const auto &trackData = d->mTrackData[index.row()];
auto roleEnum = static_cast<TrackDataType::key_type>(role);
auto itData = trackData.find(roleEnum);
if (itData != trackData.end()) {
result = itData.value();
} else {
result = {};
}
}
}
} else {
switch(role)
{
case ColumnsRoles::IsValidRole:
result = d->mData[index.row()].mIsValid;
break;
case ColumnsRoles::TitleRole:
result = d->mData[index.row()].mTitle;
break;
case ColumnsRoles::IsPlayingRole:
result = d->mData[index.row()].mIsPlaying;
break;
case ColumnsRoles::ArtistRole:
result = d->mData[index.row()].mArtist;
break;
case ColumnsRoles::AlbumArtistRole:
result = d->mData[index.row()].mArtist;
break;
case ColumnsRoles::AlbumRole:
result = d->mData[index.row()].mAlbum;
break;
case ColumnsRoles::TrackNumberRole:
result = -1;
break;
case ColumnsRoles::IsSingleDiscAlbumRole:
result = false;
break;
case Qt::DisplayRole:
result = d->mData[index.row()].mTitle;
break;
case ColumnsRoles::ImageUrlRole:
result = QUrl(QStringLiteral("image://icon/error"));
break;
case ColumnsRoles::ShadowForImageRole:
result = false;
break;
case ColumnsRoles::AlbumSectionRole:
result = QJsonDocument{QJsonArray{d->mData[index.row()].mAlbum.toString(),
d->mData[index.row()].mArtist.toString(),
QUrl(QStringLiteral("image://icon/error")).toString()}}.toJson();
break;
default:
result = {};
}
}
return result;
return result;
}
bool MediaPlayList::setData(const QModelIndex &index, const QVariant &value, int role)
......@@ -305,6 +305,7 @@ bool MediaPlayList::removeRows(int row, int count, const QModelIndex &parent)
}
Q_EMIT tracksCountChanged();
Q_EMIT remainingTracksChanged();
Q_EMIT persistentStateChanged();
return false;
......@@ -361,6 +362,7 @@ void MediaPlayList::enqueueRestoredEntry(const MediaPlayListEntry &newEntry)
}
Q_EMIT tracksCountChanged();
Q_EMIT remainingTracksChanged();
Q_EMIT persistentStateChanged();
if (!newEntry.mIsValid) {
......@@ -414,6 +416,7 @@ void MediaPlayList::enqueueArtist(const QString &artistName)
}
Q_EMIT tracksCountChanged();
Q_EMIT remainingTracksChanged();