diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,7 @@ topnotificationmanager.cpp elisautils.cpp trackdatahelper.cpp + modeldatacache.cpp abstractfile/abstractfilelistener.cpp abstractfile/abstractfilelisting.cpp file/filelistener.cpp @@ -32,6 +33,7 @@ models/alltracksproxymodel.cpp models/singleartistproxymodel.cpp models/singlealbumproxymodel.cpp + models/genericdatamodel.cpp ) if (KF5Baloo_FOUND) diff --git a/src/databaseinterface.h b/src/databaseinterface.h --- a/src/databaseinterface.h +++ b/src/databaseinterface.h @@ -22,6 +22,7 @@ #include "elisaLib_export.h" +#include "elisautils.h" #include "musicalbum.h" #include "musicaudiotrack.h" #include "musicartist.h" @@ -41,6 +42,7 @@ class DatabaseInterfacePrivate; class QMutex; class QSqlRecord; +class QSqlQuery; class ELISALIB_EXPORT DatabaseInterface : public QObject { @@ -56,14 +58,24 @@ Id, }; + enum PropertyType { + DatabaseId, + DisplayRole, + SecondaryRole, + }; + + Q_ENUMS(PropertyType) + explicit DatabaseInterface(QObject *parent = nullptr); ~DatabaseInterface() override; Q_INVOKABLE void init(const QString &dbName, const QString &databaseFileName = {}); MusicAlbum albumFromTitleAndArtist(const QString &title, const QString &artist); + QList> allData(ElisaUtils::DataType aType); + QList allTracks(); QList allTracksFromSource(const QString &musicSource); @@ -95,6 +107,8 @@ void tracksAdded(const QList &allTracks); + void genreAdded(QString genreName); + void artistRemoved(const MusicArtist &removedArtist); void albumRemoved(const MusicAlbum &removedAlbum, qulonglong removedAlbumId); @@ -111,8 +125,6 @@ void requestsInitDone(); - void genreAdded(QString genreName); - void databaseError(); void restoredTracks(const QString &musicSource, QHash allFiles); @@ -233,8 +245,24 @@ QHash internalAllFileNameFromSource(qulonglong sourceId); + QList> internalAllGenericPartialData(QSqlQuery &query, int nbFields); + + QList> internalAllArtistsPartialData(); + + QList> internalAllAlbumsPartialData(); + + QList> internalAllTracksPartialData(); + + QList> internalAllGenresPartialData(); + + QList> internalAllComposersPartialData(); + + QList> internalAllLyricistsPartialData(); + std::unique_ptr d; }; + + #endif // DATABASEINTERFACE_H diff --git a/src/databaseinterface.cpp b/src/databaseinterface.cpp --- a/src/databaseinterface.cpp +++ b/src/databaseinterface.cpp @@ -66,7 +66,8 @@ mSelectComposerQuery(mTracksDatabase), mInsertLyricistQuery(mTracksDatabase), mSelectLyricistByNameQuery(mTracksDatabase), mSelectLyricistQuery(mTracksDatabase), mInsertGenreQuery(mTracksDatabase), mSelectGenreByNameQuery(mTracksDatabase), - mSelectGenreQuery(mTracksDatabase) + mSelectGenreQuery(mTracksDatabase), mSelectAllTracksShortQuery(mTracksDatabase), + mSelectAllAlbumsShortQuery(mTracksDatabase) { } @@ -182,6 +183,10 @@ QSqlQuery mSelectGenreQuery; + QSqlQuery mSelectAllTracksShortQuery; + + QSqlQuery mSelectAllAlbumsShortQuery; + qulonglong mAlbumId = 1; qulonglong mArtistId = 1; @@ -261,6 +266,45 @@ return result; } +QList> DatabaseInterface::allData(ElisaUtils::DataType aType) +{ + auto result = QList>{}; + + auto transactionResult = startTransaction(); + if (!transactionResult) { + return result; + } + + switch (aType) + { + case ElisaUtils::AllArtists: + result = internalAllArtistsPartialData(); + break; + case ElisaUtils::AllAlbums: + result = internalAllAlbumsPartialData(); + break; + case ElisaUtils::AllTracks: + result = internalAllTracksPartialData(); + break; + case ElisaUtils::AllGenres: + result = internalAllGenresPartialData(); + break; + case ElisaUtils::AllComposers: + result = internalAllComposersPartialData(); + break; + case ElisaUtils::AllLyricists: + result = internalAllLyricistsPartialData(); + break; + }; + + transactionResult = finishTransaction(); + if (!transactionResult) { + return result; + } + + return result; +} + QList DatabaseInterface::allTracks() { @@ -1340,6 +1384,30 @@ } } + { + auto selectAllAlbumsText = QStringLiteral("SELECT " + "album.`ID`, " + "album.`Title`, " + "artist.`Name` " + "FROM `Albums` album " + "LEFT JOIN `AlbumsArtists` albumArtist " + "ON " + "albumArtist.`AlbumID` = album.`ID` " + "LEFT JOIN `Artists` artist " + "ON " + "albumArtist.`ArtistID` = artist.`ID` " + "ORDER BY album.`Title` COLLATE NOCASE"); + + auto result = d->mSelectAllAlbumsShortQuery.prepare(selectAllAlbumsText); + + if (!result) { + qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsShortQuery.lastQuery(); + qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllAlbumsShortQuery.lastError(); + + Q_EMIT databaseError(); + } + } + { auto selectAllArtistsWithFilterText = QStringLiteral("SELECT `ID`, " "`Name` " @@ -1405,6 +1473,29 @@ } } + { + auto selectAllTracksShortText = QStringLiteral("SELECT " + "tracks.`ID`, " + "tracks.`Title`, " + "artistAlbum.`Name` " + "FROM " + "`Tracks` tracks, " + "`Albums` album " + "LEFT JOIN `AlbumsArtists` artistAlbumMapping ON artistAlbumMapping.`AlbumID` = album.`ID` " + "LEFT JOIN `Artists` artistAlbum ON artistAlbum.`ID` = artistAlbumMapping.`ArtistID` " + "WHERE " + "tracks.`AlbumID` = album.`ID`"); + + auto result = d->mSelectAllTracksShortQuery.prepare(selectAllTracksShortText); + + if (!result) { + qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksShortQuery.lastQuery(); + qDebug() << "DatabaseInterface::initRequest" << d->mSelectAllTracksShortQuery.lastError(); + + Q_EMIT databaseError(); + } + } + { auto selectAllTracksFromSourceQueryText = QStringLiteral("SELECT " "tracks.`ID`, " @@ -3460,6 +3551,49 @@ return allFileNames; } +QList > DatabaseInterface::internalAllGenericPartialData(QSqlQuery &query, + int nbFields) +{ + auto result = QList>{}; + + auto queryResult = query.exec(); + + if (!queryResult || !query.isSelect() || !query.isActive()) { + Q_EMIT databaseError(); + + qDebug() << "DatabaseInterface::allArtists" << query.lastQuery(); + qDebug() << "DatabaseInterface::allArtists" << query.boundValues(); + qDebug() << "DatabaseInterface::allArtists" << query.lastError(); + + query.finish(); + + auto transactionResult = finishTransaction(); + if (!transactionResult) { + return result; + } + + return result; + } + + while(query.next()) { + auto newData = QMap{}; + + const auto ¤tRecord = query.record(); + + newData[DatabaseId] = currentRecord.value(0); + newData[DisplayRole] = currentRecord.value(1); + if (nbFields == 2) { + newData[SecondaryRole] = currentRecord.value(2); + } + + result.push_back(newData); + } + + query.finish(); + + return result; +} + MusicArtist DatabaseInterface::internalComposerFromId(qulonglong composerId) { auto result = MusicArtist(); @@ -4242,5 +4376,35 @@ return allAlbumIds; } +QList> DatabaseInterface::internalAllArtistsPartialData() +{ + return internalAllGenericPartialData(d->mSelectAllArtistsQuery, 1); +} + +QList > DatabaseInterface::internalAllAlbumsPartialData() +{ + return internalAllGenericPartialData(d->mSelectAllAlbumsShortQuery, 2); +} + +QList > DatabaseInterface::internalAllTracksPartialData() +{ + return internalAllGenericPartialData(d->mSelectAllTracksShortQuery, 2); +} + +QList > DatabaseInterface::internalAllGenresPartialData() +{ + return internalAllGenericPartialData(d->mSelectGenreQuery, 1); +} + +QList > DatabaseInterface::internalAllComposersPartialData() +{ + return internalAllGenericPartialData(d->mSelectComposerQuery, 1); +} + +QList > DatabaseInterface::internalAllLyricistsPartialData() +{ + return internalAllGenericPartialData(d->mSelectLyricistQuery, 1); +} + #include "moc_databaseinterface.cpp" diff --git a/src/elisaqmlplugin.cpp b/src/elisaqmlplugin.cpp --- a/src/elisaqmlplugin.cpp +++ b/src/elisaqmlplugin.cpp @@ -136,6 +136,7 @@ qRegisterMetaType>("QMap"); qRegisterMetaType("ElisaUtils::PlayListEnqueueMode"); qRegisterMetaType("ElisaUtils::PlayListEnqueueTriggerPlay"); + qRegisterMetaType("ElisaUtils::DataType"); qRegisterMetaTypeStreamOperators("PlayListControler::PlayerState"); diff --git a/src/elisautils.h b/src/elisautils.h --- a/src/elisautils.h +++ b/src/elisautils.h @@ -55,6 +55,50 @@ Q_ENUM_NS(PlayListEnqueueTriggerPlay) +enum ColumnsRoles { + TitleRole = Qt::UserRole + 1, + SecondaryTextRole, + ImageUrlRole, + ShadowForImageRole, + ChildModelRole, + DurationRole, + MilliSecondsDurationRole, + ArtistRole, + AlbumRole, + AlbumArtistRole, + TrackNumberRole, + DiscNumberRole, + RatingRole, + GenreRole, + LyricistRole, + ComposerRole, + CommentRole, + YearRole, + ChannelsRole, + BitRateRole, + SampleRateRole, + ImageRole, + ResourceRole, + IdRole, + DatabaseIdRole, + IsSingleDiscAlbumRole, + ContainerDataRole, +}; + +Q_ENUM_NS(ColumnsRoles) + +enum DataType { + AllArtists, + AllAlbums, + AllTracks, + AllGenres, + AllComposers, + AllLyricists, + UnknownType, +}; + +Q_ENUM_NS(DataType) + } #endif // ELISAUTILS_H diff --git a/src/modeldatacache.h b/src/modeldatacache.h new file mode 100644 --- /dev/null +++ b/src/modeldatacache.h @@ -0,0 +1,88 @@ +/* + * Copyright 2018 Matthieu Gallien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef MODELDATACACHE_H +#define MODELDATACACHE_H + +#include "elisautils.h" + +#include + +#include + +class ModelDataCachePrivate; +class DatabaseInterface; + +class ModelDataCache : public QObject +{ + + Q_OBJECT + + Q_PROPERTY(ElisaUtils::DataType dataType READ dataType WRITE setDataType NOTIFY dataTypeChanged) + + Q_PROPERTY(DatabaseInterface* database READ database WRITE setDatabase NOTIFY databaseChanged) + +public: + + enum CallMode { + CannotBlock, + CanBlock, + }; + + explicit ModelDataCache(QObject *parent = nullptr); + + ElisaUtils::DataType dataType() const; + + int dataCount() const; + + QVariant data(int row, ElisaUtils::ColumnsRoles role) const; + + DatabaseInterface* database() const; + +Q_SIGNALS: + + void dataTypeChanged(ElisaUtils::DataType dataType); + + void receiveData(qulonglong databaseId, QMap cacheData); + + void databaseChanged(DatabaseInterface* database); + + void dataChanged(); + +public Q_SLOTS: + + void neededData(qulonglong databaseId) const; + + void setDataType(ElisaUtils::DataType dataType); + + void setDatabase(DatabaseInterface* database); + +private Q_SLOTS: + + void databaseChanged(); + +private: + + void fetchPartialData(); + + std::unique_ptr d; + +}; + +#endif // MODELDATACACHE_H diff --git a/src/modeldatacache.cpp b/src/modeldatacache.cpp new file mode 100644 --- /dev/null +++ b/src/modeldatacache.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2018 Matthieu Gallien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "modeldatacache.h" + +#include "databaseinterface.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +class ModelDataCachePrivate +{ +public: + + QReadWriteLock mLock; + + QList> mPartialData; + + DatabaseInterface *mDatabase = nullptr; + + QAtomicInt mDataCount; + + ElisaUtils::DataType mDataType = ElisaUtils::UnknownType; + +}; + +ModelDataCache::ModelDataCache(QObject *parent) + : QObject(parent), d(std::make_unique()) +{ +} + +ElisaUtils::DataType ModelDataCache::dataType() const +{ + return d->mDataType; +} + +int ModelDataCache::dataCount() const +{ + int result = d->mDataCount; + + return result; +} + +QVariant ModelDataCache::data(int row, ElisaUtils::ColumnsRoles role) const +{ + QReadLocker vLocker(&d->mLock); + + auto result = QVariant{}; + + switch (role) + { + case ElisaUtils::TitleRole: + result = d->mPartialData[row][DatabaseInterface::DisplayRole]; + break; + case ElisaUtils::SecondaryTextRole: + result = d->mPartialData[row][DatabaseInterface::SecondaryRole]; + break; + case ElisaUtils::DatabaseIdRole: + result = d->mPartialData[row][DatabaseInterface::DatabaseId]; + break; + }; + + return result; +} + +DatabaseInterface *ModelDataCache::database() const +{ + return d->mDatabase; +} + +void ModelDataCache::neededData(qulonglong databaseId) const +{ +} + +void ModelDataCache::setDataType(ElisaUtils::DataType dataType) +{ + if (d->mDataType == dataType) { + return; + } + + d->mDataType = dataType; + Q_EMIT dataTypeChanged(d->mDataType); + + fetchPartialData(); +} + +void ModelDataCache::setDatabase(DatabaseInterface *database) +{ + if (d->mDatabase == database) { + return; + } + + d->mDatabase = database; + Q_EMIT databaseChanged(d->mDatabase); + +} + +void ModelDataCache::databaseChanged() +{ + fetchPartialData(); +} + +void ModelDataCache::fetchPartialData() +{ + if (!d->mDatabase) { + return; + } + + { + QWriteLocker vLocker(&d->mLock); + + d->mPartialData = d->mDatabase->allData(d->mDataType); + + d->mDataCount = d->mPartialData.count(); + } + + Q_EMIT dataChanged(); +} + + +#include "moc_modeldatacache.cpp" diff --git a/src/models/genericdatamodel.h b/src/models/genericdatamodel.h new file mode 100644 --- /dev/null +++ b/src/models/genericdatamodel.h @@ -0,0 +1,93 @@ +/* + * Copyright 2018 Matthieu Gallien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GENERICDATAMODEL_H +#define GENERICDATAMODEL_H + +#include "elisautils.h" + +#include + +#include + +class GenericDataModelPrivate; +class ModelDataCache; + +class GenericDataModel : public QAbstractListModel +{ + + Q_OBJECT + + Q_PROPERTY(ElisaUtils::DataType dataType READ dataType WRITE setDataType NOTIFY dataTypeChanged) + + Q_PROPERTY(ModelDataCache* modelCache READ modelCache WRITE setModelCache NOTIFY modelCacheChanged) + + Q_PROPERTY(bool isBusy READ isBusy NOTIFY isBusyChanged) + +public: + + explicit GenericDataModel(QObject *parent = nullptr); + + ~GenericDataModel() override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + QHash roleNames() const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + QModelIndex parent(const QModelIndex &child) const override; + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + ElisaUtils::DataType dataType() const; + + ModelDataCache *modelCache() const; + + bool isBusy() const; + +Q_SIGNALS: + + void neededData(qulonglong databaseId) const; + + void dataTypeChanged(ElisaUtils::DataType dataType); + + void modelCacheChanged(ModelDataCache* modelCache); + + void isBusyChanged(bool isBusy); + +public Q_SLOTS: + + void receiveData(qulonglong databaseId, QMap cacheData); + + void setDataType(ElisaUtils::DataType dataType); + + void setModelCache(ModelDataCache* modelCache); + + void modelDataChanged(); + +private: + + void resetModelType(); + + std::unique_ptr d; + +}; + +#endif // GENERICDATAMODEL_H diff --git a/src/models/genericdatamodel.cpp b/src/models/genericdatamodel.cpp new file mode 100644 --- /dev/null +++ b/src/models/genericdatamodel.cpp @@ -0,0 +1,223 @@ +/* + * Copyright 2018 Matthieu Gallien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "genericdatamodel.h" + +#include "databaseinterface.h" +#include "modeldatacache.h" + +#include +#include +#include + +class GenericDataModelPrivate +{ +public: + + QHash mDataPositionCache; + + QHash> mDataCache; + + ModelDataCache *mModelCache = nullptr; + + ElisaUtils::DataType mDataType = ElisaUtils::UnknownType; + + bool mIsBusy = true; + +}; + +GenericDataModel::GenericDataModel(QObject *parent) + : QAbstractListModel(parent), d(std::make_unique()) +{ +} + +GenericDataModel::~GenericDataModel() = default; + +int GenericDataModel::rowCount(const QModelIndex &parent) const +{ + auto rowCount = 0; + + if (parent.isValid()) { + return rowCount; + } + + rowCount = d->mModelCache->dataCount(); + + return rowCount; +} + +QHash GenericDataModel::roleNames() const +{ + auto roles = QAbstractItemModel::roleNames(); + + roles[static_cast(ElisaUtils::ColumnsRoles::SecondaryTextRole)] = "secondaryText"; + roles[static_cast(ElisaUtils::ColumnsRoles::ImageUrlRole)] = "imageUrl"; + roles[static_cast(ElisaUtils::ColumnsRoles::ShadowForImageRole)] = "shadowForImage"; + roles[static_cast(ElisaUtils::ColumnsRoles::ChildModelRole)] = "childModel"; + + return roles; +} + +QVariant GenericDataModel::data(const QModelIndex &index, int role) const +{ + auto result = QVariant(); + + const auto albumCount = d->mModelCache->dataCount(); + + if (!index.isValid()) { + return result; + } + + if (index.column() != 0) { + return result; + } + + if (index.row() < 0) { + return result; + } + + if (index.parent().isValid()) { + return result; + } + + if (index.row() < 0 || index.row() >= albumCount) { + return result; + } + + if (role != Qt::DisplayRole && (role < ElisaUtils::SecondaryTextRole || role > ElisaUtils::ContainerDataRole)) { + return result; + } + + switch(role) + { + case Qt::DisplayRole: + result = d->mModelCache->data(index.row(), ElisaUtils::TitleRole); + break; + case ElisaUtils::SecondaryTextRole: + result = d->mModelCache->data(index.row(), ElisaUtils::SecondaryTextRole); + break; + default: + { +// auto realRole = static_cast(role); +// auto databaseId = d->mPartialData[index.row()][DatabaseInterface::DatabaseId].toULongLong(); +// auto itCacheData = d->mDataCache.find(databaseId); +// if (itCacheData == d->mDataCache.end()) { +// d->mDataPositionCache[databaseId] = index.row(); +// Q_EMIT neededData(databaseId); +// } else { +// result = itCacheData.value()[realRole]; +// } + } + }; + + return result; +} + +QModelIndex GenericDataModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child) + + return {}; +} + +int GenericDataModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 1; +} + +ElisaUtils::DataType GenericDataModel::dataType() const +{ + return d->mDataType; +} + +ModelDataCache *GenericDataModel::modelCache() const +{ + return d->mModelCache; +} + +bool GenericDataModel::isBusy() const +{ + return d->mIsBusy; +} + +void GenericDataModel::receiveData(qulonglong databaseId, QMap cacheData) +{ + d->mDataCache[databaseId] = cacheData; + + auto modifiedIndex = index(d->mDataPositionCache[databaseId]); + + Q_EMIT dataChanged(modifiedIndex, modifiedIndex, {}); +} + +void GenericDataModel::setDataType(ElisaUtils::DataType dataType) +{ + if (d->mDataType == dataType) { + return; + } + + resetModelType(); + + d->mDataType = dataType; + Q_EMIT dataTypeChanged(d->mDataType); +} + +void GenericDataModel::setModelCache(ModelDataCache *modelCache) +{ + if (d->mModelCache == modelCache) { + return; + } + + d->mModelCache = modelCache; + Q_EMIT modelCacheChanged(d->mModelCache); + + connect(this, &GenericDataModel::neededData, + d->mModelCache, &ModelDataCache::neededData); + connect(d->mModelCache, &ModelDataCache::receiveData, + this, &GenericDataModel::receiveData); + connect(this, &GenericDataModel::dataTypeChanged, + d->mModelCache, &ModelDataCache::setDataType); + connect(d->mModelCache, &ModelDataCache::dataChanged, + this, &GenericDataModel::modelDataChanged); +} + +void GenericDataModel::modelDataChanged() +{ + beginResetModel(); + endResetModel(); + + d->mIsBusy = false; + Q_EMIT isBusyChanged(d->mIsBusy); +} + +void GenericDataModel::resetModelType() +{ + beginResetModel(); + d->mDataCache.clear(); + d->mDataPositionCache.clear(); + + d->mIsBusy = true; + Q_EMIT isBusyChanged(d->mIsBusy); + + endResetModel(); +} + + +#include "moc_genericdatamodel.cpp" diff --git a/src/musiclistenersmanager.cpp b/src/musiclistenersmanager.cpp --- a/src/musiclistenersmanager.cpp +++ b/src/musiclistenersmanager.cpp @@ -37,17 +37,17 @@ #include "notificationitem.h" #include "elisaapplication.h" #include "elisa_settings.h" -#include "models/allalbumsmodel.h" -#include "models/allartistsmodel.h" -#include "models/alltracksmodel.h" #include "models/albummodel.h" #include "models/abstractmediaproxymodel.h" #include "models/allalbumsproxymodel.h" #include "models/allartistsproxymodel.h" #include "models/alltracksproxymodel.h" #include "models/singleartistproxymodel.h" #include "models/singlealbumproxymodel.h" +#include "modeldatacache.h" +#include "models/genericdatamodel.h" + #include #include @@ -88,11 +88,11 @@ ElisaApplication *mElisaApplication = nullptr; - AllAlbumsModel mAllAlbumsModel; + GenericDataModel mAllAlbumsModel; - AllArtistsModel mAllArtistsModel; + GenericDataModel mAllArtistsModel; - AllTracksModel mAllTracksModel; + GenericDataModel mAllTracksModel; AlbumModel mAlbumModel; @@ -150,29 +150,23 @@ d->mConfigFileWatcher.addPath(Elisa::ElisaConfiguration::self()->config()->name()); - d->mAllAlbumsModel.setAllArtists(&d->mAllArtistsModel); - d->mAllArtistsModel.setAllAlbums(&d->mAllAlbumsModel); - - connect(&d->mDatabaseInterface, &DatabaseInterface::albumsAdded, - &d->mAllAlbumsModel, &AllAlbumsModel::albumsAdded); - connect(&d->mDatabaseInterface, &DatabaseInterface::albumModified, - &d->mAllAlbumsModel, &AllAlbumsModel::albumModified); - connect(&d->mDatabaseInterface, &DatabaseInterface::albumRemoved, - &d->mAllAlbumsModel, &AllAlbumsModel::albumRemoved); - - connect(&d->mDatabaseInterface, &DatabaseInterface::artistsAdded, - &d->mAllArtistsModel, &AllArtistsModel::artistsAdded); - connect(&d->mDatabaseInterface, &DatabaseInterface::artistModified, - &d->mAllArtistsModel, &AllArtistsModel::artistModified); - connect(&d->mDatabaseInterface, &DatabaseInterface::artistRemoved, - &d->mAllArtistsModel, &AllArtistsModel::artistRemoved); - - connect(&d->mDatabaseInterface, &DatabaseInterface::tracksAdded, - &d->mAllTracksModel, &AllTracksModel::tracksAdded); - connect(&d->mDatabaseInterface, &DatabaseInterface::trackModified, - &d->mAllTracksModel, &AllTracksModel::trackModified); - connect(&d->mDatabaseInterface, &DatabaseInterface::trackRemoved, - &d->mAllTracksModel, &AllTracksModel::trackRemoved); + auto modelData = new ModelDataCache; + modelData->setDatabase(&d->mDatabaseInterface); + modelData->moveToThread(&d->mDatabaseThread); + d->mAllAlbumsModel.setModelCache(modelData); + d->mAllAlbumsModel.setDataType(ElisaUtils::AllAlbums); + + modelData = new ModelDataCache; + modelData->setDatabase(&d->mDatabaseInterface); + modelData->moveToThread(&d->mDatabaseThread); + d->mAllArtistsModel.setModelCache(modelData); + d->mAllArtistsModel.setDataType(ElisaUtils::AllArtists); + + modelData = new ModelDataCache; + modelData->setDatabase(&d->mDatabaseInterface); + modelData->moveToThread(&d->mDatabaseThread); + d->mAllTracksModel.setModelCache(modelData); + d->mAllTracksModel.setDataType(ElisaUtils::AllTracks); connect(&d->mDatabaseInterface, &DatabaseInterface::albumModified, &d->mAlbumModel, &AlbumModel::albumModified);