diff --git a/src/models/abstractmediaproxymodel.cpp b/src/models/abstractmediaproxymodel.cpp index 371620d9..46b4a2ab 100644 --- a/src/models/abstractmediaproxymodel.cpp +++ b/src/models/abstractmediaproxymodel.cpp @@ -1,88 +1,101 @@ /* * Copyright 2016-2017 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 "abstractmediaproxymodel.h" #include AbstractMediaProxyModel::AbstractMediaProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { setFilterCaseSensitivity(Qt::CaseInsensitive); mThreadPool.setMaxThreadCount(1); } AbstractMediaProxyModel::~AbstractMediaProxyModel() = default; QString AbstractMediaProxyModel::filterText() const { return mFilterText; } int AbstractMediaProxyModel::filterRating() const { return mFilterRating; } void AbstractMediaProxyModel::setFilterText(const QString &filterText) { QWriteLocker writeLocker(&mDataLock); if (mFilterText == filterText) return; mFilterText = filterText; mFilterExpression.setPattern(mFilterText); mFilterExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption); mFilterExpression.optimize(); invalidate(); Q_EMIT filterTextChanged(mFilterText); } void AbstractMediaProxyModel::setFilterRating(int filterRating) { QWriteLocker writeLocker(&mDataLock); if (mFilterRating == filterRating) { return; } mFilterRating = filterRating; invalidate(); Q_EMIT filterRatingChanged(filterRating); } bool AbstractMediaProxyModel::sortedAscending() const { return sortOrder() ? false : true; } void AbstractMediaProxyModel::sortModel(Qt::SortOrder order) { this->sort(0,order); Q_EMIT sortedAscendingChanged(); } +void AbstractMediaProxyModel::setGenreFilterText(const QString &filterText) +{ + if (mGenreFilterText == filterText) + { + return; + } + + mGenreFilterText = filterText; + invalidateFilter(); + + Q_EMIT genreFilterTextChanged(mGenreFilterText); +} + #include "moc_abstractmediaproxymodel.cpp" diff --git a/src/models/abstractmediaproxymodel.h b/src/models/abstractmediaproxymodel.h index c8e5a4bf..dfa16a9e 100644 --- a/src/models/abstractmediaproxymodel.h +++ b/src/models/abstractmediaproxymodel.h @@ -1,94 +1,112 @@ /* * Copyright 2016-2017 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 ABSTRACTMEDIAPROXYMODEL_H #define ABSTRACTMEDIAPROXYMODEL_H #include "elisaLib_export.h" #include #include #include #include class ELISALIB_EXPORT AbstractMediaProxyModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(QString filterText READ filterText WRITE setFilterText NOTIFY filterTextChanged) Q_PROPERTY(int filterRating READ filterRating WRITE setFilterRating NOTIFY filterRatingChanged) Q_PROPERTY(bool sortedAscending READ sortedAscending NOTIFY sortedAscendingChanged) + Q_PROPERTY(QString genreFilterText + READ genreFilterText + WRITE setGenreFilterText + NOTIFY genreFilterTextChanged) + public: explicit AbstractMediaProxyModel(QObject *parent = nullptr); ~AbstractMediaProxyModel() override; QString filterText() const; int filterRating() const; bool sortedAscending() const; + QString genreFilterText() const + { + return mGenreFilterText; + } + public Q_SLOTS: void setFilterText(const QString &filterText); void setFilterRating(int filterRating); void sortModel(Qt::SortOrder order); + void setGenreFilterText(const QString &filterText); + Q_SIGNALS: void filterTextChanged(const QString &filterText); void filterRatingChanged(int filterRating); void sortedAscendingChanged(); + void genreFilterTextChanged(QString genreFilterText); + protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override = 0; QString mFilterText; int mFilterRating = 0; QRegularExpression mFilterExpression; QReadWriteLock mDataLock; QThreadPool mThreadPool; +private: + + QString mGenreFilterText; + }; #endif // ABSTRACTMEDIAPROXYMODEL_H diff --git a/src/models/allalbumsmodel.cpp b/src/models/allalbumsmodel.cpp index 702ad135..e7c22e3a 100644 --- a/src/models/allalbumsmodel.cpp +++ b/src/models/allalbumsmodel.cpp @@ -1,361 +1,364 @@ /* * Copyright 2015-2017 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 "allalbumsmodel.h" #include "databaseinterface.h" #include "allartistsmodel.h" #include "albummodel.h" #include "elisautils.h" #include #include #include #include #include #include #include #include #include #include class AllAlbumsModelPrivate { public: AllAlbumsModelPrivate() { mThreadPool.setMaxThreadCount(1); } QVector mAllAlbums; QHash mAlbumsData; AllArtistsModel *mAllArtistsModel = nullptr; QReadWriteLock mDataLock; QThreadPool mThreadPool; }; AllAlbumsModel::AllAlbumsModel(QObject *parent) : QAbstractItemModel(parent), d(std::make_unique()) { } AllAlbumsModel::~AllAlbumsModel() = default; int AllAlbumsModel::albumCount() const { QReadLocker locker(&d->mDataLock); return d->mAllAlbums.size(); } int AllAlbumsModel::rowCount(const QModelIndex &parent) const { auto albumCount = 0; if (parent.isValid()) { return albumCount; } QReadLocker locker(&d->mDataLock); albumCount = d->mAllAlbums.size(); return albumCount; } QHash AllAlbumsModel::roleNames() const { auto roles = QAbstractItemModel::roleNames(); roles[static_cast(ElisaUtils::ColumnsRoles::TitleRole)] = "title"; //roles[static_cast(ElisaUtils::ColumnsRoles::AllTracksTitleRole)] = "tracksTitle"; roles[static_cast(ElisaUtils::ColumnsRoles::ArtistRole)] = "artist"; roles[static_cast(ElisaUtils::ColumnsRoles::AllArtistsRole)] = "allArtists"; roles[static_cast(ElisaUtils::ColumnsRoles::ImageRole)] = "image"; //roles[static_cast(ElisaUtils::ColumnsRoles::CountRole)] = "count"; roles[static_cast(ElisaUtils::ColumnsRoles::IsSingleDiscAlbumRole)] = "isSingleDiscAlbum"; roles[static_cast(ElisaUtils::ColumnsRoles::ContainerDataRole)] = "containerData"; roles[static_cast(ElisaUtils::ColumnsRoles::HighestTrackRating)] = "highestTrackRating"; roles[static_cast(ElisaUtils::ColumnsRoles::DatabaseIdRole)] = "databaseId"; 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"; //roles[static_cast(ElisaUtils::ColumnsRoles::IsTracksContainerRole)] = "isTracksContainer"; return roles; } Qt::ItemFlags AllAlbumsModel::flags(const QModelIndex &index) const { if (!index.isValid()) { return Qt::NoItemFlags; } return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } QVariant AllAlbumsModel::data(const QModelIndex &index, int role) const { auto result = QVariant(); QReadLocker locker(&d->mDataLock); const auto albumCount = d->mAllAlbums.size(); 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.internalId() != 0) { return result; } if (index.row() < 0 || index.row() >= albumCount) { return result; } result = internalDataAlbum(index.row(), role); return result; } QVariant AllAlbumsModel::internalDataAlbum(int albumIndex, int role) const { auto result = QVariant(); switch(role) { case Qt::DisplayRole: case ElisaUtils::ColumnsRoles::TitleRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].title(); break; /*case ElisaUtils::ColumnsRoles::AllTracksTitleRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].allTracksTitle(); break;*/ case ElisaUtils::ColumnsRoles::ArtistRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].artist(); break; case ElisaUtils::ColumnsRoles::AllArtistsRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].allArtists().join(QStringLiteral(", ")); break; case ElisaUtils::ColumnsRoles::ImageRole: { auto albumArt = d->mAlbumsData[d->mAllAlbums[albumIndex]].albumArtURI(); if (albumArt.isValid()) { result = albumArt; } break; } /*case ElisaUtils::ColumnsRoles::CountRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].tracksCount(); break;*/ case ElisaUtils::ColumnsRoles::IdRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].id(); break; case ElisaUtils::ColumnsRoles::IsSingleDiscAlbumRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].isSingleDiscAlbum(); break; case ElisaUtils::ColumnsRoles::ContainerDataRole: result = QVariant::fromValue(d->mAlbumsData[d->mAllAlbums[albumIndex]]); break; case ElisaUtils::ColumnsRoles::DatabaseIdRole: result = QVariant::fromValue(d->mAlbumsData[d->mAllAlbums[albumIndex]].databaseId()); break; case ElisaUtils::ColumnsRoles::HighestTrackRating: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].highestTrackRating(); break; case ElisaUtils::ColumnsRoles::SecondaryTextRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].artist(); break; case ElisaUtils::ColumnsRoles::ImageUrlRole: { auto albumArt = d->mAlbumsData[d->mAllAlbums[albumIndex]].albumArtURI(); if (albumArt.isValid()) { result = albumArt; } else { result = QUrl(QStringLiteral("image://icon/media-optical-audio")); } break; } case ElisaUtils::ColumnsRoles::ShadowForImageRole: result = d->mAlbumsData[d->mAllAlbums[albumIndex]].albumArtURI().isValid(); break; case ElisaUtils::ColumnsRoles::ChildModelRole: { auto albumData = d->mAlbumsData[d->mAllAlbums[albumIndex]]; result = QVariant::fromValue(albumData); break; } + case ElisaUtils::ColumnsRoles::GenreRole: + result = d->mAlbumsData[d->mAllAlbums[albumIndex]].genres(); + break; /*case ElisaUtils::ColumnsRoles::IsTracksContainerRole: result = true; break;*/ } return result; } QModelIndex AllAlbumsModel::index(int row, int column, const QModelIndex &parent) const { auto result = QModelIndex(); if (column != 0) { return result; } if (parent.isValid()) { return result; } result = createIndex(row, column); return result; } QModelIndex AllAlbumsModel::parent(const QModelIndex &child) const { Q_UNUSED(child) auto result = QModelIndex(); return result; } int AllAlbumsModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 1; } AllArtistsModel *AllAlbumsModel::allArtists() const { return d->mAllArtistsModel; } void AllAlbumsModel::albumsAdded(const QList &newAlbums) { QtConcurrent::run(&d->mThreadPool, [=] () { for (const auto &newAlbum : newAlbums) { if (newAlbum.isValid()) { beginInsertRows({}, d->mAllAlbums.size(), d->mAllAlbums.size()); { QWriteLocker locker(&d->mDataLock); d->mAllAlbums.push_back(newAlbum.databaseId()); d->mAlbumsData[newAlbum.databaseId()] = newAlbum; } endInsertRows(); Q_EMIT albumCountChanged(); } } }); } void AllAlbumsModel::albumRemoved(const MusicAlbum &removedAlbum) { QtConcurrent::run(&d->mThreadPool, [=] () { auto removedAlbumIterator = d->mAllAlbums.end(); { QReadLocker locker(&d->mDataLock); removedAlbumIterator = std::find(d->mAllAlbums.begin(), d->mAllAlbums.end(), removedAlbum.databaseId()); if (removedAlbumIterator == d->mAllAlbums.end()) { return; } int albumIndex = removedAlbumIterator - d->mAllAlbums.begin(); beginRemoveRows({}, albumIndex, albumIndex); } { QWriteLocker writeLocker(&d->mDataLock); d->mAlbumsData.remove(removedAlbum.databaseId()); d->mAllAlbums.erase(removedAlbumIterator); } endRemoveRows(); Q_EMIT albumCountChanged(); }); } void AllAlbumsModel::albumModified(const MusicAlbum &modifiedAlbum) { QtConcurrent::run(&d->mThreadPool, [=] () { auto modifiedAlbumIterator = d->mAllAlbums.end(); { QReadLocker locker(&d->mDataLock); modifiedAlbumIterator = std::find(d->mAllAlbums.begin(), d->mAllAlbums.end(), modifiedAlbum.databaseId()); } int albumIndex = 0; { QWriteLocker writeLocker(&d->mDataLock); if (modifiedAlbumIterator == d->mAllAlbums.end()) { return; } albumIndex = modifiedAlbumIterator - d->mAllAlbums.begin(); d->mAlbumsData[modifiedAlbum.databaseId()] = modifiedAlbum; } Q_EMIT dataChanged(index(albumIndex, 0), index(albumIndex, 0)); }); } void AllAlbumsModel::setAllArtists(AllArtistsModel *model) { if (d->mAllArtistsModel == model) { return; } d->mAllArtistsModel = model; Q_EMIT allArtistsChanged(); } #include "moc_allalbumsmodel.cpp" diff --git a/src/models/allalbumsproxymodel.cpp b/src/models/allalbumsproxymodel.cpp index e2720894..9485963e 100644 --- a/src/models/allalbumsproxymodel.cpp +++ b/src/models/allalbumsproxymodel.cpp @@ -1,119 +1,133 @@ /* * Copyright 2016-2017 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 "allalbumsproxymodel.h" #include "genericdatamodel.h" #include "musicalbum.h" #include #include AllAlbumsProxyModel::AllAlbumsProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(ElisaUtils::ColumnsRoles::TitleRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } AllAlbumsProxyModel::~AllAlbumsProxyModel() { } bool AllAlbumsProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); + const auto &genreValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::GenreRole); + + if (!genreFilterText().isNull() && !genreValue.isValid()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.canConvert()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { + continue; + } + const auto &titleValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::TitleRole).toString(); const auto &artistValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::ArtistRole).toString(); const auto &allArtistsValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::AllArtistsRole).toStringList(); const auto maximumRatingValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::HighestTrackRating).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } if (mFilterExpression.match(artistValue).hasMatch()) { result = true; continue; } for (const auto &oneArtist : allArtistsValue) { if (mFilterExpression.match(oneArtist).hasMatch()) { result = true; break; } } if (result) { continue; } if (!result) { break; } } return result; } void AllAlbumsProxyModel::enqueueToPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allAlbums = QList(); allAlbums.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allAlbums.push_back(data(currentIndex, ElisaUtils::ColumnsRoles::ContainerDataRole). value()); } Q_EMIT albumToEnqueue(allAlbums, ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); }); } void AllAlbumsProxyModel::replaceAndPlayOfPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allAlbums = QList(); allAlbums.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allAlbums.push_back(data(currentIndex, ElisaUtils::ColumnsRoles::ContainerDataRole). value()); } Q_EMIT albumToEnqueue(allAlbums, ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); }); } #include "moc_allalbumsproxymodel.cpp" diff --git a/src/models/allartistsproxymodel.cpp b/src/models/allartistsproxymodel.cpp index e8ea2b34..d25a9189 100644 --- a/src/models/allartistsproxymodel.cpp +++ b/src/models/allartistsproxymodel.cpp @@ -1,125 +1,112 @@ /* * Copyright 2017 Alexander Stippich * * 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 "allartistsproxymodel.h" #include "elisautils.h" #include #include #include AllArtistsProxyModel::AllArtistsProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(Qt::DisplayRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } AllArtistsProxyModel::~AllArtistsProxyModel() { } bool AllArtistsProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); const auto &genreValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::GenreRole); - if (!mGenreFilterText.isNull() && !genreValue.isValid()) { + if (!genreFilterText().isNull() && !genreValue.isValid()) { continue; } - if (!mGenreFilterText.isNull() && !genreValue.canConvert()) { + if (!genreFilterText().isNull() && !genreValue.canConvert()) { continue; } - if (!mGenreFilterText.isNull() && !genreValue.toStringList().contains(mGenreFilterText)) { + if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { continue; } const auto &artistValue = sourceModel()->data(currentIndex, Qt::DisplayRole).toString(); if (mFilterExpression.match(artistValue).hasMatch()) { result = true; continue; } if (result) { continue; } if (!result) { break; } } return result; } void AllArtistsProxyModel::enqueueToPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allArtists = QStringList(); allArtists.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allArtists.push_back(data(currentIndex, Qt::DisplayRole).toString()); } Q_EMIT artistToEnqueue(allArtists, ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); }); } void AllArtistsProxyModel::replaceAndPlayOfPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allArtists = QStringList(); allArtists.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allArtists.push_back(data(currentIndex, Qt::DisplayRole).toString()); } Q_EMIT artistToEnqueue(allArtists, ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); }); } -void AllArtistsProxyModel::setGenreFilterText(const QString &filterText) -{ - if (mGenreFilterText == filterText) - { - return; - } - - mGenreFilterText = filterText; - invalidateFilter(); - - Q_EMIT genreFilterTextChanged(mGenreFilterText); -} - #include "moc_allartistsproxymodel.cpp" diff --git a/src/models/allartistsproxymodel.h b/src/models/allartistsproxymodel.h index 23af00bb..c85e417e 100644 --- a/src/models/allartistsproxymodel.h +++ b/src/models/allartistsproxymodel.h @@ -1,76 +1,58 @@ /* * Copyright 2017 Alexander Stippich * 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 ALLARTISTSPROXYMODEL_H #define ALLARTISTSPROXYMODEL_H #include "elisaLib_export.h" #include "abstractmediaproxymodel.h" #include "elisautils.h" class ELISALIB_EXPORT AllArtistsProxyModel : public AbstractMediaProxyModel { Q_OBJECT - Q_PROPERTY(QString genreFilterText - READ genreFilterText - WRITE setGenreFilterText - NOTIFY genreFilterTextChanged) - public: explicit AllArtistsProxyModel(QObject *parent = nullptr); ~AllArtistsProxyModel() override; - QString genreFilterText() const - { - return mGenreFilterText; - } - Q_SIGNALS: void artistToEnqueue(QList artistNames, ElisaUtils::PlayListEnqueueMode enqueueMode, ElisaUtils::PlayListEnqueueTriggerPlay triggerPlay); - void genreFilterTextChanged(QString genreFilterText); - public Q_SLOTS: void enqueueToPlayList(); void replaceAndPlayOfPlayList(); - void setGenreFilterText(const QString &filterText); - protected: bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; -private: - - QString mGenreFilterText; - }; #endif // ALLARTISTSPROXYMODEL_H diff --git a/src/models/alltracksproxymodel.cpp b/src/models/alltracksproxymodel.cpp index 8b62de15..ccc13f95 100644 --- a/src/models/alltracksproxymodel.cpp +++ b/src/models/alltracksproxymodel.cpp @@ -1,109 +1,123 @@ /* * Copyright 2017 Alexander Stippich * * 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 "alltracksproxymodel.h" #include "genericdatamodel.h" #include #include AllTracksProxyModel::AllTracksProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(Qt::DisplayRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } AllTracksProxyModel::~AllTracksProxyModel() { } bool AllTracksProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); + const auto &genreValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::GenreRole); + + if (!genreFilterText().isNull() && !genreValue.isValid()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.canConvert()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { + continue; + } + const auto &titleValue = sourceModel()->data(currentIndex, Qt::DisplayRole).toString(); const auto &artistValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::ArtistRole).toString(); const auto maximumRatingValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::RatingRole).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } if (mFilterExpression.match(artistValue).hasMatch()) { result = true; continue; } if (result) { continue; } if (!result) { break; } } return result; } void AllTracksProxyModel::enqueueToPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allTracks = QList(); allTracks.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allTracks.push_back(data(currentIndex, ElisaUtils::ColumnsRoles::ContainerDataRole).value()); } Q_EMIT trackToEnqueue(allTracks, ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); }); } void AllTracksProxyModel::replaceAndPlayOfPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allTracks = QList(); allTracks.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allTracks.push_back(data(currentIndex, ElisaUtils::ColumnsRoles::ContainerDataRole).value()); } Q_EMIT trackToEnqueue(allTracks, ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); }); } #include "moc_alltracksproxymodel.cpp" diff --git a/src/models/singlealbumproxymodel.cpp b/src/models/singlealbumproxymodel.cpp index c45280e5..e971e2cb 100644 --- a/src/models/singlealbumproxymodel.cpp +++ b/src/models/singlealbumproxymodel.cpp @@ -1,105 +1,119 @@ /* * Copyright 2017 Alexander Stippich * * 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 "singlealbumproxymodel.h" #include "albummodel.h" #include #include SingleAlbumProxyModel::SingleAlbumProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { } SingleAlbumProxyModel::~SingleAlbumProxyModel() = default; bool SingleAlbumProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); + const auto &genreValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::GenreRole); + + if (!genreFilterText().isNull() && !genreValue.isValid()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.canConvert()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { + continue; + } + const auto &titleValue = sourceModel()->data(currentIndex, AlbumModel::TitleRole).toString(); const auto maximumRatingValue = sourceModel()->data(currentIndex, AlbumModel::RatingRole).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } if (result) { continue; } if (!result) { break; } } return result; } void SingleAlbumProxyModel::enqueueToPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allTracks = QList(); allTracks.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allTracks.push_back(data(currentIndex, AlbumModel::ContainerDataRole).value()); } Q_EMIT trackToEnqueue(allTracks, ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); }); } void SingleAlbumProxyModel::replaceAndPlayOfPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allTracks = QList(); allTracks.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allTracks.push_back(data(currentIndex, AlbumModel::ContainerDataRole).value()); } Q_EMIT trackToEnqueue(allTracks, ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); }); } void SingleAlbumProxyModel::loadAlbumData(qulonglong databaseId) { auto albumSourceModel = qobject_cast(this->sourceModel()); if(albumSourceModel) { albumSourceModel->loadAlbumData(databaseId); } } #include "moc_singlealbumproxymodel.cpp" diff --git a/src/models/singleartistproxymodel.cpp b/src/models/singleartistproxymodel.cpp index 20e6b5ce..88c08e3c 100644 --- a/src/models/singleartistproxymodel.cpp +++ b/src/models/singleartistproxymodel.cpp @@ -1,129 +1,143 @@ /* * Copyright 2016-2017 Matthieu Gallien * Copyright 2017 Alexander Stippich * * 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 "singleartistproxymodel.h" #include "genericdatamodel.h" #include "musicalbum.h" #include #include SingleArtistProxyModel::SingleArtistProxyModel(QObject *parent) : AbstractMediaProxyModel(parent) { this->setSortRole(ElisaUtils::ColumnsRoles::TitleRole); this->setSortCaseSensitivity(Qt::CaseInsensitive); this->sortModel(Qt::AscendingOrder); } SingleArtistProxyModel::~SingleArtistProxyModel() = default; QString SingleArtistProxyModel::artistFilter() const { return mArtistFilter; } void SingleArtistProxyModel::setArtistFilterText(const QString &filterText) { if (mArtistFilter == filterText) return; mArtistFilter = filterText; mArtistExpression.setPattern(QStringLiteral(".*") + mArtistFilter + QStringLiteral(".*")); mArtistExpression.setPatternOptions(QRegularExpression::CaseInsensitiveOption); mArtistExpression.optimize(); invalidate(); Q_EMIT artistFilterTextChanged(mArtistFilter); } bool SingleArtistProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { bool result = false; for (int column = 0, columnCount = sourceModel()->columnCount(source_parent); column < columnCount; ++column) { auto currentIndex = sourceModel()->index(source_row, column, source_parent); + const auto &genreValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::GenreRole); + + if (!genreFilterText().isNull() && !genreValue.isValid()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.canConvert()) { + continue; + } + + if (!genreFilterText().isNull() && !genreValue.toStringList().contains(genreFilterText())) { + continue; + } + const auto &titleValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::TitleRole).toString(); const auto &artistValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::AllArtistsRole).toString(); const auto maximumRatingValue = sourceModel()->data(currentIndex, ElisaUtils::ColumnsRoles::HighestTrackRating).toInt(); if (maximumRatingValue < mFilterRating) { result = false; continue; } if (mArtistExpression.match(artistValue).hasMatch()) { if (mFilterExpression.match(titleValue).hasMatch()) { result = true; continue; } } if (result) { continue; } if (!result) { break; } } return result; } void SingleArtistProxyModel::enqueueToPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allAlbums = QList(); allAlbums.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allAlbums.push_back(data(currentIndex, ElisaUtils::ColumnsRoles::ContainerDataRole). value()); } Q_EMIT albumToEnqueue(allAlbums, ElisaUtils::AppendPlayList, ElisaUtils::DoNotTriggerPlay); }); } void SingleArtistProxyModel::replaceAndPlayOfPlayList() { QtConcurrent::run(&mThreadPool, [=] () { QReadLocker locker(&mDataLock); auto allAlbums = QList(); allAlbums.reserve(rowCount()); for (int rowIndex = 0, maxRowCount = rowCount(); rowIndex < maxRowCount; ++rowIndex) { auto currentIndex = index(rowIndex, 0); allAlbums.push_back(data(currentIndex, ElisaUtils::ColumnsRoles::ContainerDataRole). value()); } Q_EMIT albumToEnqueue(allAlbums, ElisaUtils::ReplacePlayList, ElisaUtils::TriggerPlay); }); } #include "moc_singleartistproxymodel.cpp"