Commit 805c258e authored by Matthieu Gallien's avatar Matthieu Gallien 🎵
Browse files

rewrite the dialog for metadata of tracks using a real model

parent e2dcdd56
......@@ -112,6 +112,21 @@ ecm_add_test(${albummodeltest_SOURCES}
target_include_directories(albummodeltest PRIVATE ${CMAKE_SOURCE_DIR}/src)
set(trackmetadatamodeltest_SOURCES
qabstractitemmodeltester.cpp
trackmetadatamodeltest.cpp
)
ecm_qt_declare_logging_category(trackmetadatamodeltest_SOURCES HEADER elisa_debug.h IDENTIFIER lcModelTest CATEGORY_NAME qt.modeltest)
ecm_add_test(${trackmetadatamodeltest_SOURCES}
TEST_NAME "trackmetadatamodeltest"
LINK_LIBRARIES
Qt5::Test elisaLib Qt5::CorePrivate
)
target_include_directories(trackmetadatamodeltest PRIVATE ${CMAKE_SOURCE_DIR}/src)
set(allartistsmodeltest_SOURCES
qabstractitemmodeltester.cpp
allartistsmodeltest.cpp
......
/*
* Copyright 2018 Matthieu Gallien <matthieu_gallien@yahoo.fr>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "models/trackmetadatamodel.h"
#include "qabstractitemmodeltester.h"
#include <QDebug>
#include <QtTest>
class TrackMetadataModelTests: public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase()
{
}
void loadOneTrackData()
{
TrackMetadataModel myModel;
QAbstractItemModelTester testModel(&myModel);
QSignalSpy beginResetSpy(&myModel, &TrackMetadataModel::modelAboutToBeReset);
QSignalSpy endResetSpy(&myModel, &TrackMetadataModel::modelReset);
QSignalSpy beginInsertRowsSpy(&myModel, &TrackMetadataModel::rowsAboutToBeInserted);
QSignalSpy endInsertRowsSpy(&myModel, &TrackMetadataModel::rowsInserted);
QSignalSpy dataChangedSpy(&myModel, &TrackMetadataModel::dataChanged);
QSignalSpy beginRemovedRowsSpy(&myModel, &TrackMetadataModel::rowsAboutToBeRemoved);
QSignalSpy endRemovedRowsSpy(&myModel, &TrackMetadataModel::rowsRemoved);
QCOMPARE(beginResetSpy.count(), 0);
QCOMPARE(endResetSpy.count(), 0);
QCOMPARE(beginInsertRowsSpy.count(), 0);
QCOMPARE(endInsertRowsSpy.count(), 0);
QCOMPARE(dataChangedSpy.count(), 0);
QCOMPARE(beginRemovedRowsSpy.count(), 0);
QCOMPARE(endRemovedRowsSpy.count(), 0);
QCOMPARE(myModel.rowCount(), 0);
auto trackData = TrackMetadataModel::TrackDataType{{DatabaseInterface::DatabaseIdRole, 1},
{DatabaseInterface::TitleRole, QStringLiteral("title")}};
myModel.trackData(trackData);
QCOMPARE(beginResetSpy.count(), 1);
QCOMPARE(endResetSpy.count(), 1);
QCOMPARE(beginInsertRowsSpy.count(), 0);
QCOMPARE(endInsertRowsSpy.count(), 0);
QCOMPARE(dataChangedSpy.count(), 0);
QCOMPARE(beginRemovedRowsSpy.count(), 0);
QCOMPARE(endRemovedRowsSpy.count(), 0);
QCOMPARE(myModel.rowCount(), 1);
}
};
QTEST_GUILESS_MAIN(TrackMetadataModelTests)
#include "trackmetadatamodeltest.moc"
......@@ -16,7 +16,6 @@ set(elisaLib_SOURCES
topnotificationmanager.cpp
elisautils.cpp
datatype.cpp
trackdatahelper.cpp
abstractfile/abstractfilelistener.cpp
abstractfile/abstractfilelisting.cpp
filescanner.cpp
......@@ -32,6 +31,7 @@ set(elisaLib_SOURCES
models/allartistsproxymodel.cpp
models/alltracksproxymodel.cpp
models/singlealbumproxymodel.cpp
models/trackmetadatamodel.cpp
)
if (LIBVLC_FOUND)
......
......@@ -17,6 +17,8 @@
#include "databaseinterface.h"
#include "musicaudiotrack.h"
#include <KI18n/KLocalizedString>
#include <QSqlDatabase>
......
......@@ -22,7 +22,6 @@
#include "datatype.h"
#include "elisautils.h"
#include "musicaudiotrack.h"
#include <QObject>
#include <QString>
......@@ -39,6 +38,7 @@ class DatabaseInterfacePrivate;
class QMutex;
class QSqlRecord;
class QSqlQuery;
class MusicAudioTrack;
class ELISALIB_EXPORT DatabaseInterface : public QObject
{
......
......@@ -20,6 +20,7 @@
#include "musiclistenersmanager.h"
#include "elisaimportapplication.h"
#include "elisa_settings.h"
#include "musicaudiotrack.h"
#include <QCoreApplication>
#include <QCommandLineParser>
......
......@@ -51,6 +51,7 @@
#include "models/alltracksproxymodel.h"
#include "models/allartistsproxymodel.h"
#include "models/singlealbumproxymodel.h"
#include "models/trackmetadatamodel.h"
#include "embeddedcoverageimageprovider.h"
#if defined KF5KIO_FOUND && KF5KIO_FOUND
......@@ -60,7 +61,6 @@
#include "audiowrapper.h"
#include "notificationitem.h"
#include "topnotificationmanager.h"
#include "trackdatahelper.h"
#include "elisautils.h"
#include "datatype.h"
......@@ -120,6 +120,7 @@ void ElisaQmlTestPlugin::registerTypes(const char *uri)
qmlRegisterType<AllGenresModel>(uri, 1, 0, "AllGenresModel");
qmlRegisterType<AllTracksModel>(uri, 1, 0, "AllTracksModel");
qmlRegisterType<AlbumModel>(uri, 1, 0, "AlbumModel");
qmlRegisterType<TrackMetadataModel>(uri, 1, 0, "TrackMetadataModel");
qmlRegisterType<AllAlbumsProxyModel>(uri, 1, 0, "AllAlbumsProxyModel");
qmlRegisterType<AllArtistsProxyModel>(uri, 1, 0, "AllArtistsProxyModel");
qmlRegisterType<AllTracksProxyModel>(uri, 1, 0, "AllTracksProxyModel");
......@@ -131,7 +132,6 @@ void ElisaQmlTestPlugin::registerTypes(const char *uri)
qmlRegisterType<AudioWrapper>(uri, 1, 0, "AudioWrapper");
qmlRegisterType<TopNotificationManager>(uri, 1, 0, "TopNotificationManager");
qmlRegisterType<TrackDataHelper>(uri, 1, 0, "TrackDataHelper");
qmlRegisterUncreatableMetaObject(DataUtils::staticMetaObject, uri, 1, 0, "DataUtils", QStringLiteral("Only enums"));
#if defined Qt5DBus_FOUND && Qt5DBus_FOUND
......
......@@ -82,6 +82,7 @@ QHash<int, QByteArray> MediaPlayList::roleNames() const
auto roles = QAbstractItemModel::roleNames();
roles[static_cast<int>(ColumnsRoles::IsValidRole)] = "isValid";
roles[static_cast<int>(ColumnsRoles::DatabaseIdRole)] = "databaseId";
roles[static_cast<int>(ColumnsRoles::TitleRole)] = "title";
roles[static_cast<int>(ColumnsRoles::StringDurationRole)] = "duration";
roles[static_cast<int>(ColumnsRoles::ArtistRole)] = "artist";
......
......@@ -17,38 +17,56 @@
#include "modeldataloader.h"
ModelDataLoader::ModelDataLoader(QObject *parent) : QObject(parent)
#include "filescanner.h"
#include <QMimeDatabase>
class ModelDataLoaderPrivate
{
public:
DatabaseInterface *mDatabase = nullptr;
QMimeDatabase mMimeDatabase;
FileScanner mFileScanner;
};
ModelDataLoader::ModelDataLoader(QObject *parent) : QObject(parent), d(std::make_unique<ModelDataLoaderPrivate>())
{
}
ModelDataLoader::~ModelDataLoader() = default;
void ModelDataLoader::setDatabase(DatabaseInterface *database)
{
mDatabase = database;
d->mDatabase = database;
}
void ModelDataLoader::loadData(ElisaUtils::PlayListEntryType dataType)
{
if (!mDatabase) {
if (!d->mDatabase) {
return;
}
switch (dataType)
{
case ElisaUtils::Album:
Q_EMIT allAlbumsData(mDatabase->allAlbumsData());
Q_EMIT allAlbumsData(d->mDatabase->allAlbumsData());
break;
case ElisaUtils::Artist:
Q_EMIT allArtistsData(mDatabase->allArtistsData());
Q_EMIT allArtistsData(d->mDatabase->allArtistsData());
break;
case ElisaUtils::Composer:
break;
case ElisaUtils::Genre:
Q_EMIT allGenresData(mDatabase->allGenresData());
Q_EMIT allGenresData(d->mDatabase->allGenresData());
break;
case ElisaUtils::Lyricist:
break;
case ElisaUtils::Track:
Q_EMIT allTracksData(mDatabase->allTracksData());
Q_EMIT allTracksData(d->mDatabase->allTracksData());
break;
case ElisaUtils::FileName:
case ElisaUtils::Unknown:
......@@ -58,14 +76,14 @@ void ModelDataLoader::loadData(ElisaUtils::PlayListEntryType dataType)
void ModelDataLoader::loadDataByGenre(ElisaUtils::PlayListEntryType dataType, const QString &genre)
{
if (!mDatabase) {
if (!d->mDatabase) {
return;
}
switch (dataType)
{
case ElisaUtils::Artist:
Q_EMIT allArtistsData(mDatabase->allArtistsDataByGenre(genre));
Q_EMIT allArtistsData(d->mDatabase->allArtistsDataByGenre(genre));
break;
case ElisaUtils::Album:
case ElisaUtils::Composer:
......@@ -80,14 +98,14 @@ void ModelDataLoader::loadDataByGenre(ElisaUtils::PlayListEntryType dataType, co
void ModelDataLoader::loadDataByArtist(ElisaUtils::PlayListEntryType dataType, const QString &artist)
{
if (!mDatabase) {
if (!d->mDatabase) {
return;
}
switch (dataType)
{
case ElisaUtils::Album:
Q_EMIT allAlbumsData(mDatabase->allAlbumsDataByArtist(artist));
Q_EMIT allAlbumsData(d->mDatabase->allAlbumsDataByArtist(artist));
break;
case ElisaUtils::Artist:
case ElisaUtils::Composer:
......@@ -102,14 +120,14 @@ void ModelDataLoader::loadDataByArtist(ElisaUtils::PlayListEntryType dataType, c
void ModelDataLoader::loadDataByGenreAndArtist(ElisaUtils::PlayListEntryType dataType, const QString &genre, const QString &artist)
{
if (!mDatabase) {
if (!d->mDatabase) {
return;
}
switch (dataType)
{
case ElisaUtils::Album:
Q_EMIT allAlbumsData(mDatabase->allAlbumsDataByGenreAndArtist(genre, artist));
Q_EMIT allAlbumsData(d->mDatabase->allAlbumsDataByGenreAndArtist(genre, artist));
break;
case ElisaUtils::Artist:
case ElisaUtils::Composer:
......@@ -122,5 +140,52 @@ void ModelDataLoader::loadDataByGenreAndArtist(ElisaUtils::PlayListEntryType dat
}
}
void ModelDataLoader::loadDataByDatabaseId(ElisaUtils::PlayListEntryType dataType, qulonglong databaseId)
{
if (!d->mDatabase) {
return;
}
switch (dataType)
{
case ElisaUtils::Track:
Q_EMIT allTrackData(d->mDatabase->trackDataFromDatabaseId(databaseId));
break;
case ElisaUtils::Album:
case ElisaUtils::Artist:
case ElisaUtils::Composer:
case ElisaUtils::Genre:
case ElisaUtils::Lyricist:
case ElisaUtils::FileName:
case ElisaUtils::Unknown:
break;
}
}
void ModelDataLoader::loadDataByFileName(ElisaUtils::PlayListEntryType dataType, const QUrl &fileName)
{
if (!d->mDatabase) {
return;
}
switch (dataType)
{
case ElisaUtils::FileName:
{
auto result = d->mFileScanner.scanOneFile(fileName, d->mMimeDatabase);
Q_EMIT allTrackData(result.toTrackData());
break;
}
case ElisaUtils::Track:
case ElisaUtils::Album:
case ElisaUtils::Artist:
case ElisaUtils::Composer:
case ElisaUtils::Genre:
case ElisaUtils::Lyricist:
case ElisaUtils::Unknown:
break;
}
}
#include "moc_modeldataloader.cpp"
......@@ -18,12 +18,18 @@
#ifndef MODELDATALOADER_H
#define MODELDATALOADER_H
#include <QObject>
#include "elisaLib_export.h"
#include "elisautils.h"
#include "databaseinterface.h"
class ModelDataLoader : public QObject
#include <QObject>
#include <memory>
class ModelDataLoaderPrivate;
class ELISALIB_EXPORT ModelDataLoader : public QObject
{
Q_OBJECT
......@@ -34,9 +40,12 @@ public:
using ListArtistDataType = DatabaseInterface::ListArtistDataType;
using ListGenreDataType = DatabaseInterface::ListGenreDataType;
using ListTrackDataType = DatabaseInterface::ListTrackDataType;
using TrackDataType = DatabaseInterface::TrackDataType;
explicit ModelDataLoader(QObject *parent = nullptr);
~ModelDataLoader() override;
void setDatabase(DatabaseInterface *database);
Q_SIGNALS:
......@@ -49,6 +58,8 @@ Q_SIGNALS:
void allTracksData(const ListTrackDataType &allData);
void allTrackData(const TrackDataType &allData);
public Q_SLOTS:
void loadData(ElisaUtils::PlayListEntryType dataType);
......@@ -62,9 +73,15 @@ public Q_SLOTS:
void loadDataByGenreAndArtist(ElisaUtils::PlayListEntryType dataType,
const QString &genre, const QString &artist);
void loadDataByDatabaseId(ElisaUtils::PlayListEntryType dataType,
qulonglong databaseId);
void loadDataByFileName(ElisaUtils::PlayListEntryType dataType,
const QUrl &fileName);
private:
DatabaseInterface *mDatabase = nullptr;
std::unique_ptr<ModelDataLoaderPrivate> d;
};
......
/*
* Copyright 2018 Matthieu Gallien <matthieu_gallien@yahoo.fr>
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "trackmetadatamodel.h"
#include "musiclistenersmanager.h"
#include <KI18n/KLocalizedString>
TrackMetadataModel::TrackMetadataModel(QObject *parent)
: QAbstractListModel(parent)
{
}
int TrackMetadataModel::rowCount(const QModelIndex &parent) const
{
// For list models only the root node (an invalid parent) should return the list's size. For all
// other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
if (parent.isValid()) {
return 0;
}
return mTrackData.count();
}
QVariant TrackMetadataModel::data(const QModelIndex &index, int role) const
{
auto result = QVariant{};
const auto currentKey = mTrackKeys[index.row()];
switch (role)
{
case Qt::DisplayRole:
result = mTrackData[currentKey];
break;
case ItemNameRole:
switch (currentKey)
{
case DatabaseInterface::TitleRole:
result = i18nc("Track title for track metadata view", "Title:");
break;
case DatabaseInterface::DurationRole:
result = i18nc("Duration label for track metadata view", "Duration:");
break;
case DatabaseInterface::ArtistRole:
result = i18nc("Track artist for track metadata view", "Artist:");
break;
case DatabaseInterface::AlbumRole:
result = i18nc("Album name for track metadata view", "Album:");
break;
case DatabaseInterface::AlbumArtistRole:
result = i18nc("Album artist for track metadata view", "Album Artist:");
break;
case DatabaseInterface::TrackNumberRole:
result = i18nc("Track number for track metadata view", "Track Number:");
break;
case DatabaseInterface::DiscNumberRole:
result = i18nc("Disc number for track metadata view", "Disc Number:");
break;
case DatabaseInterface::RatingRole:
result = i18nc("Rating label for information panel", "Rating:");
break;
case DatabaseInterface::GenreRole:
result = i18nc("Genre label for track metadata view", "Genre:");
break;
case DatabaseInterface::LyricistRole:
result = i18nc("Lyricist label for track metadata view", "Lyricist:");
break;
case DatabaseInterface::ComposerRole:
result = i18nc("Composer name for track metadata view", "Composer:");
break;
case DatabaseInterface::CommentRole:
result = i18nc("Comment label for track metadata view", "Comment:");
break;
case DatabaseInterface::YearRole:
result = i18nc("Year label for track metadata view", "Year:");
break;
case DatabaseInterface::ChannelsRole:
result = i18nc("Channels label for track metadata view", "Channels:");
break;
case DatabaseInterface::BitRateRole:
result = i18nc("Bit rate label for track metadata view", "Bit Rate:");
break;
case DatabaseInterface::SampleRateRole:
result = i18nc("Sample Rate label for track metadata view", "Sample Rate:");
break;
case DatabaseInterface::SecondaryTextRole:
case DatabaseInterface::ImageUrlRole:
case DatabaseInterface::ShadowForImageRole:
case DatabaseInterface::ChildModelRole:
case DatabaseInterface::StringDurationRole:
case DatabaseInterface::MilliSecondsDurationRole:
case DatabaseInterface::AllArtistsRole:
case DatabaseInterface::HighestTrackRating:
case DatabaseInterface::ResourceRole:
case DatabaseInterface::IdRole:
case DatabaseInterface::DatabaseIdRole:
case DatabaseInterface::IsSingleDiscAlbumRole:
case DatabaseInterface::ContainerDataRole:
case DatabaseInterface::IsPartialDataRole:
case DatabaseInterface::AlbumIdRole:
break;
}
break;
case ItemTypeRole:
switch (currentKey)
{
case DatabaseInterface::TitleRole:
result = TextEntry;
break;
case DatabaseInterface::ArtistRole:
result = TextEntry;
break;
case DatabaseInterface::AlbumRole:
result = TextEntry;
break;
case DatabaseInterface::AlbumArtistRole:
result = TextEntry;
break;
case DatabaseInterface::TrackNumberRole:
result = IntegerEntry;
break;
case DatabaseInterface::DiscNumberRole:
result = IntegerEntry;
break;
case DatabaseInterface::RatingRole:
result = RatingEntry;
break;
case DatabaseInterface::GenreRole:
result = TextEntry;
break;
case DatabaseInterface::LyricistRole:
result = TextEntry;
break;
case DatabaseInterface::ComposerRole:
result = TextEntry;
break;
case DatabaseInterface::CommentRole:
result = TextEntry;
break;
case DatabaseInterface::YearRole:
result = IntegerEntry;
break;
case DatabaseInterface::DurationRole:
case DatabaseInterface::SampleRateRole:
case DatabaseInterface::BitRateRole:
case DatabaseInterface::ChannelsRole:
case DatabaseInterface::SecondaryTextRole:
case DatabaseInterface::ImageUrlRole:
case DatabaseInterface::ShadowForImageRole:
case DatabaseInterface::ChildModelRole:
case DatabaseInterface::StringDurationRole:
case DatabaseInterface::MilliSecondsDurationRole:
case DatabaseInterface::AllArtistsRole:
case DatabaseInterface::HighestTrackRating:
case DatabaseInterface::ResourceRole:
case DatabaseInterface::IdRole:
case DatabaseInterface::DatabaseIdRole:
case DatabaseInterface::IsSingleDiscAlbumRole:
case DatabaseInterface::ContainerDataRole:
case DatabaseInterface::IsPartialDataRole:
case DatabaseInterface::AlbumIdRole:
break;
}
break;
}
return result;
}
bool TrackMetadataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (data(index, role) != value) {
// FIXME: Implement me!
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
QHash<int, QByteArray> TrackMetadataModel::roleNames() const
{
auto names = QAbstractListModel::roleNames();
names[ItemNameRole] = "name";
names[ItemTypeRole] = "type";
return names;
}