diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 70eb252d3..97ffb515c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -264,22 +264,16 @@ set(SOURCES internet/internetmodel.cpp internet/internetservice.cpp internet/internetplaylistitem.cpp + internet/internetsearch.cpp + internet/internetsearchview.cpp + internet/internetsearchmodel.cpp + internet/internetsearchsortmodel.cpp + internet/internetsearchitemdelegate.cpp internet/localredirectserver.cpp tidal/tidalservice.cpp - tidal/tidalsearch.cpp - tidal/tidalsearchview.cpp - tidal/tidalsearchmodel.cpp - tidal/tidalsearchsortmodel.cpp - tidal/tidalsearchitemdelegate.cpp tidal/tidalurlhandler.cpp - deezer/deezerservice.cpp - deezer/deezersearch.cpp - deezer/deezersearchview.cpp - deezer/deezersearchmodel.cpp - deezer/deezersearchsortmodel.cpp - deezer/deezersearchitemdelegate.cpp deezer/deezerurlhandler.cpp ) @@ -439,18 +433,14 @@ set(HEADERS internet/internetservice.h internet/internetmimedata.h internet/internetsongmimedata.h + internet/internetsearch.h + internet/internetsearchview.h + internet/internetsearchmodel.h internet/localredirectserver.h tidal/tidalservice.h - tidal/tidalsearch.h - tidal/tidalsearchview.h - tidal/tidalsearchmodel.h tidal/tidalurlhandler.h - deezer/deezerservice.h - deezer/deezersearch.h - deezer/deezersearchview.h - deezer/deezersearchmodel.h deezer/deezerurlhandler.h ) @@ -507,8 +497,7 @@ set(UI globalshortcuts/globalshortcutgrabber.ui - tidal/tidalsearchview.ui - deezer/deezersearchview.ui + internet/internetsearchview.ui ) diff --git a/src/core/application.cpp b/src/core/application.cpp index 42bc8cd41..d8868773c 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -31,6 +31,7 @@ #include "core/closure.h" #include "core/lazy.h" #include "core/tagreaderclient.h" +#include "core/song.h" #include "database.h" #include "taskmanager.h" @@ -59,8 +60,7 @@ #include "lyrics/apiseedslyricsprovider.h" #include "internet/internetmodel.h" -#include "tidal/tidalsearch.h" -#include "deezer/deezersearch.h" +#include "internet/internetsearch.h" bool Application::kIsPortable = false; @@ -116,8 +116,8 @@ class ApplicationImpl { return lyrics_providers; }), internet_model_([=]() { return new InternetModel(app, app); }), - tidal_search_([=]() { return new TidalSearch(app, app); }), - deezer_search_([=]() { return new DeezerSearch(app, app); }) + tidal_search_([=]() { return new InternetSearch(app, Song::Source_Tidal, app); }), + deezer_search_([=]() { return new InternetSearch(app, Song::Source_Deezer, app); }) {} Lazy tag_reader_client_; @@ -137,8 +137,8 @@ class ApplicationImpl { Lazy current_art_loader_; Lazy lyrics_providers_; Lazy internet_model_; - Lazy tidal_search_; - Lazy deezer_search_; + Lazy tidal_search_; + Lazy deezer_search_; }; @@ -206,5 +206,5 @@ LyricsProviders *Application::lyrics_providers() const { return p_->lyrics_provi PlaylistBackend *Application::playlist_backend() const { return p_->playlist_backend_.get(); } PlaylistManager *Application::playlist_manager() const { return p_->playlist_manager_.get(); } InternetModel *Application::internet_model() const { return p_->internet_model_.get(); } -TidalSearch *Application::tidal_search() const { return p_->tidal_search_.get(); } -DeezerSearch *Application::deezer_search() const { return p_->deezer_search_.get(); } +InternetSearch *Application::tidal_search() const { return p_->tidal_search_.get(); } +InternetSearch *Application::deezer_search() const { return p_->deezer_search_.get(); } diff --git a/src/core/application.h b/src/core/application.h index 11ad8acb4..261e3c9ac 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -53,8 +53,7 @@ class AlbumCoverLoader; class CurrentArtLoader; class LyricsProviders; class InternetModel; -class TidalSearch; -class DeezerSearch; +class InternetSearch; class Application : public QObject { Q_OBJECT @@ -89,8 +88,8 @@ class Application : public QObject { LyricsProviders *lyrics_providers() const; InternetModel *internet_model() const; - TidalSearch *tidal_search() const; - DeezerSearch *deezer_search() const; + InternetSearch *tidal_search() const; + InternetSearch *deezer_search() const; void MoveToNewThread(QObject *object); void MoveToThread(QObject *object, QThread *thread); diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index 844bbc3cb..a1a9d9245 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -129,16 +129,16 @@ # include "device/deviceviewcontainer.h" #endif #include "transcoder/transcodedialog.h" +#include "settings/settingsdialog.h" #include "settings/behavioursettingspage.h" #include "settings/playbacksettingspage.h" #include "settings/playlistsettingspage.h" -#include "settings/settingsdialog.h" +#include "settings/tidalsettingspage.h" +#include "settings/deezersettingspage.h" #include "internet/internetmodel.h" #include "internet/internetservice.h" - -#include "tidal/tidalsearchview.h" -#include "deezer/deezersearchview.h" +#include "internet/internetsearchview.h" #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT) # include "musicbrainz/tagfetcher.h" @@ -203,8 +203,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co manager->SetPlaylistManager(app->playlist_manager()); return manager; }), - tidal_search_view_(new TidalSearchView(app_, this)), - deezer_search_view_(new DeezerSearchView(app_, this)), + tidal_search_view_(new InternetSearchView(app_, app_->tidal_search(), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)), + deezer_search_view_(new InternetSearchView(app_, app_->deezer_search(), DeezerSettingsPage::kSettingsGroup, SettingsDialog::Page_Deezer, this)), playlist_menu_(new QMenu(this)), playlist_add_to_another_(nullptr), playlistitem_actions_separator_(nullptr), diff --git a/src/core/mainwindow.h b/src/core/mainwindow.h index 52846708f..3f7a956fd 100644 --- a/src/core/mainwindow.h +++ b/src/core/mainwindow.h @@ -88,8 +88,7 @@ class TranscodeDialog; #endif class Ui_MainWindow; class Windows7ThumbBar; -class TidalSearchView; -class DeezerSearchView; +class InternetSearchView; class MainWindow : public QMainWindow, public PlatformInterface { Q_OBJECT @@ -337,8 +336,8 @@ signals: PlaylistItemList autocomplete_tag_items_; #endif - TidalSearchView *tidal_search_view_; - DeezerSearchView *deezer_search_view_; + InternetSearchView *tidal_search_view_; + InternetSearchView *deezer_search_view_; QAction *collection_show_all_; QAction *collection_show_duplicates_; diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index 592b704c4..a0d5eb429 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -60,8 +60,7 @@ # include "dbus/metatypes.h" #endif -#include "tidal/tidalsearch.h" -#include "deezer/deezersearch.h" +#include "internet/internetsearch.h" void RegisterMetaTypes() { @@ -116,10 +115,7 @@ void RegisterMetaTypes() { #endif #endif - qRegisterMetaType("TidalSearch::ResultList"); - qRegisterMetaType("TidalSearch::Result"); - - qRegisterMetaType("DeezerSearch::ResultList"); - qRegisterMetaType("DeezerSearch::Result"); + qRegisterMetaType("InternetSearch::ResultList"); + qRegisterMetaType("InternetSearch::Result"); } diff --git a/src/deezer/deezersearch.cpp b/src/deezer/deezersearch.cpp deleted file mode 100644 index 41f1fa374..000000000 --- a/src/deezer/deezersearch.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2010, David Sansome - * Copyright 2018, Jonas Kvinge - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#include "config.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/application.h" -#include "core/logging.h" -#include "core/closure.h" -#include "core/iconloader.h" -#include "covermanager/albumcoverloader.h" -#include "internet/internetsongmimedata.h" -#include "playlist/songmimedata.h" -#include "deezersearch.h" -#include "deezerservice.h" -#include "settings/deezersettingspage.h" - -const int DeezerSearch::kDelayedSearchTimeoutMs = 200; -const int DeezerSearch::kMaxResultsPerEmission = 2000; -const int DeezerSearch::kArtHeight = 32; - -DeezerSearch::DeezerSearch(Application *app, QObject *parent) - : QObject(parent), - app_(app), - service_(app->internet_model()->Service()), - name_("Deezer"), - id_("deezer"), - icon_(IconLoader::Load("deezer")), - searches_next_id_(1), - art_searches_next_id_(1) { - - cover_loader_options_.desired_height_ = kArtHeight; - cover_loader_options_.pad_output_image_ = true; - cover_loader_options_.scale_output_image_ = true; - - connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)), SLOT(AlbumArtLoaded(quint64, QImage))); - connect(this, SIGNAL(SearchAsyncSig(int, QString, DeezerSettingsPage::SearchBy)), this, SLOT(DoSearchAsync(int, QString, DeezerSettingsPage::SearchBy))); - connect(this, SIGNAL(ResultsAvailable(int, DeezerSearch::ResultList)), SLOT(ResultsAvailableSlot(int, DeezerSearch::ResultList))); - connect(this, SIGNAL(ArtLoaded(int, QImage)), SLOT(ArtLoadedSlot(int, QImage))); - connect(service_, SIGNAL(UpdateStatus(QString)), SLOT(UpdateStatusSlot(QString))); - connect(service_, SIGNAL(ProgressSetMaximum(int)), SLOT(ProgressSetMaximumSlot(int))); - connect(service_, SIGNAL(UpdateProgress(int)), SLOT(UpdateProgressSlot(int))); - connect(service_, SIGNAL(SearchResults(int, SongList)), SLOT(SearchDone(int, SongList))); - connect(service_, SIGNAL(SearchError(int, QString)), SLOT(HandleError(int, QString))); - - icon_as_image_ = QImage(icon_.pixmap(48, 48).toImage()); - -} - -DeezerSearch::~DeezerSearch() {} - -QStringList DeezerSearch::TokenizeQuery(const QString &query) { - - QStringList tokens(query.split(QRegExp("\\s+"))); - - for (QStringList::iterator it = tokens.begin(); it != tokens.end(); ++it) { - (*it).remove('('); - (*it).remove(')'); - (*it).remove('"'); - - const int colon = (*it).indexOf(":"); - if (colon != -1) { - (*it).remove(0, colon + 1); - } - } - - return tokens; - -} - -bool DeezerSearch::Matches(const QStringList &tokens, const QString &string) { - - for (const QString &token : tokens) { - if (!string.contains(token, Qt::CaseInsensitive)) { - return false; - } - } - - return true; - -} - -int DeezerSearch::SearchAsync(const QString &query, DeezerSettingsPage::SearchBy searchby) { - - const int id = searches_next_id_++; - - emit SearchAsyncSig(id, query, searchby); - - return id; - -} - -void DeezerSearch::SearchAsync(int id, const QString &query, DeezerSettingsPage::SearchBy searchby) { - - const int service_id = service_->Search(query, searchby); - pending_searches_[service_id] = PendingState(id, TokenizeQuery(query)); - -} - -void DeezerSearch::DoSearchAsync(int id, const QString &query, DeezerSettingsPage::SearchBy searchby) { - - int timer_id = startTimer(kDelayedSearchTimeoutMs); - delayed_searches_[timer_id].id_ = id; - delayed_searches_[timer_id].query_ = query; - delayed_searches_[timer_id].searchby_ = searchby; - -} - -void DeezerSearch::SearchDone(int service_id, const SongList &songs) { - - // Map back to the original id. - const PendingState state = pending_searches_.take(service_id); - const int search_id = state.orig_id_; - - ResultList ret; - for (const Song &song : songs) { - Result result; - result.metadata_ = song; - ret << result; - } - - emit ResultsAvailable(search_id, ret); - MaybeSearchFinished(search_id); - -} - -void DeezerSearch::HandleError(const int id, const QString error) { - - emit SearchError(id, error); - -} - -void DeezerSearch::MaybeSearchFinished(int id) { - - if (pending_searches_.keys(PendingState(id, QStringList())).isEmpty()) { - emit SearchFinished(id); - } - -} - -void DeezerSearch::CancelSearch(int id) { - QMap::iterator it; - for (it = delayed_searches_.begin(); it != delayed_searches_.end(); ++it) { - if (it.value().id_ == id) { - killTimer(it.key()); - delayed_searches_.erase(it); - return; - } - } - service_->CancelSearch(); -} - -void DeezerSearch::timerEvent(QTimerEvent *e) { - QMap::iterator it = delayed_searches_.find(e->timerId()); - if (it != delayed_searches_.end()) { - SearchAsync(it.value().id_, it.value().query_, it.value().searchby_); - delayed_searches_.erase(it); - return; - } - - QObject::timerEvent(e); -} - -void DeezerSearch::ResultsAvailableSlot(int id, DeezerSearch::ResultList results) { - - if (results.isEmpty()) return; - - // Limit the number of results that are used from each emission. - if (results.count() > kMaxResultsPerEmission) { - DeezerSearch::ResultList::iterator begin = results.begin(); - std::advance(begin, kMaxResultsPerEmission); - results.erase(begin, results.end()); - } - - // Load cached pixmaps into the results - for (DeezerSearch::ResultList::iterator it = results.begin(); it != results.end(); ++it) { - it->pixmap_cache_key_ = PixmapCacheKey(*it); - } - - emit AddResults(id, results); - -} - -QString DeezerSearch::PixmapCacheKey(const DeezerSearch::Result &result) const { - return "deezer:" % result.metadata_.url().toString(); -} - -bool DeezerSearch::FindCachedPixmap(const DeezerSearch::Result &result, QPixmap *pixmap) const { - return pixmap_cache_.find(result.pixmap_cache_key_, pixmap); -} - -int DeezerSearch::LoadArtAsync(const DeezerSearch::Result &result) { - - const int id = art_searches_next_id_++; - - pending_art_searches_[id] = result.pixmap_cache_key_; - - quint64 loader_id = app_->album_cover_loader()->LoadImageAsync(cover_loader_options_, result.metadata_); - cover_loader_tasks_[loader_id] = id; - - return id; - -} - -void DeezerSearch::ArtLoadedSlot(int id, const QImage &image) { - HandleLoadedArt(id, image); -} - -void DeezerSearch::AlbumArtLoaded(quint64 id, const QImage &image) { - - if (!cover_loader_tasks_.contains(id)) return; - int orig_id = cover_loader_tasks_.take(id); - - HandleLoadedArt(orig_id, image); - -} - -void DeezerSearch::HandleLoadedArt(int id, const QImage &image) { - - const QString key = pending_art_searches_.take(id); - - QPixmap pixmap = QPixmap::fromImage(image); - pixmap_cache_.insert(key, pixmap); - - emit ArtLoaded(id, pixmap); - -} - -QImage DeezerSearch::ScaleAndPad(const QImage &image) { - - if (image.isNull()) return QImage(); - - const QSize target_size = QSize(kArtHeight, kArtHeight); - - if (image.size() == target_size) return image; - - // Scale the image down - QImage copy; - copy = image.scaled(target_size, Qt::KeepAspectRatio, Qt::SmoothTransformation); - - // Pad the image to kHeight x kHeight - if (copy.size() == target_size) return copy; - - QImage padded_image(kArtHeight, kArtHeight, QImage::Format_ARGB32); - padded_image.fill(0); - - QPainter p(&padded_image); - p.drawImage((kArtHeight - copy.width()) / 2, (kArtHeight - copy.height()) / 2, copy); - p.end(); - - return padded_image; - -} - -MimeData *DeezerSearch::LoadTracks(const ResultList &results) { - - if (results.isEmpty()) { - return nullptr; - } - - ResultList results_copy; - for (const Result &result : results) { - results_copy << result; - } - - SongList songs; - for (const Result &result : results) { - songs << result.metadata_; - } - - InternetSongMimeData *internet_song_mime_data = new InternetSongMimeData(service_); - internet_song_mime_data->songs = songs; - MimeData *mime_data = internet_song_mime_data; - - QList urls; - for (const Result &result : results) { - urls << result.metadata_.url(); - } - mime_data->setUrls(urls); - - return mime_data; - -} - -void DeezerSearch::UpdateStatusSlot(QString text) { - emit UpdateStatus(text); -} - -void DeezerSearch::ProgressSetMaximumSlot(int max) { - emit ProgressSetMaximum(max); -} - -void DeezerSearch::UpdateProgressSlot(int progress) { - emit UpdateProgress(progress); -} diff --git a/src/deezer/deezersearch.h b/src/deezer/deezersearch.h deleted file mode 100644 index b0f4b0f46..000000000 --- a/src/deezer/deezersearch.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2010, David Sansome - * Copyright 2018, Jonas Kvinge - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#ifndef DEEZERSEARCH_H -#define DEEZERSEARCH_H - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "core/song.h" -#include "covermanager/albumcoverloaderoptions.h" -#include "settings/deezersettingspage.h" - -class Application; -class MimeData; -class AlbumCoverLoader; -class InternetService; -class DeezerService; - -class DeezerSearch : public QObject { - Q_OBJECT - - public: - DeezerSearch(Application *app, QObject *parent = nullptr); - ~DeezerSearch(); - - struct Result { - Song metadata_; - QString pixmap_cache_key_; - }; - typedef QList ResultList; - - static const int kDelayedSearchTimeoutMs; - static const int kMaxResultsPerEmission; - - Application *application() const { return app_; } - DeezerService *service() const { return service_; } - - int SearchAsync(const QString &query, DeezerSettingsPage::SearchBy searchby); - int LoadArtAsync(const DeezerSearch::Result &result); - - void CancelSearch(int id); - void CancelArt(int id); - - // Loads tracks for results that were previously emitted by ResultsAvailable. - // The implementation creates a SongMimeData with one Song for each Result. - MimeData *LoadTracks(const ResultList &results); - - signals: - void SearchAsyncSig(int id, const QString &query, DeezerSettingsPage::SearchBy searchby); - void ResultsAvailable(int id, const DeezerSearch::ResultList &results); - void AddResults(int id, const DeezerSearch::ResultList &results); - void SearchError(const int id, const QString error); - void SearchFinished(int id); - void UpdateStatus(QString text); - void ProgressSetMaximum(int progress); - void UpdateProgress(int max); - - void ArtLoaded(int id, const QPixmap &pixmap); - void ArtLoaded(int id, const QImage &image); - - protected: - - struct PendingState { - PendingState() : orig_id_(-1) {} - PendingState(int orig_id, QStringList tokens) - : orig_id_(orig_id), tokens_(tokens) {} - int orig_id_; - QStringList tokens_; - - bool operator<(const PendingState &b) const { - return orig_id_ < b.orig_id_; - } - - bool operator==(const PendingState &b) const { - return orig_id_ == b.orig_id_; - } - }; - - void timerEvent(QTimerEvent *e); - - // These functions treat queries in the same way as LibraryQuery. - // They're useful for figuring out whether you got a result because it matched in the song title or the artist/album name. - static QStringList TokenizeQuery(const QString &query); - static bool Matches(const QStringList &tokens, const QString &string); - - private slots: - void DoSearchAsync(int id, const QString &query, DeezerSettingsPage::SearchBy searchby); - void SearchDone(int id, const SongList &songs); - void HandleError(const int id, const QString error); - void ResultsAvailableSlot(int id, DeezerSearch::ResultList results); - - void ArtLoadedSlot(int id, const QImage &image); - void AlbumArtLoaded(quint64 id, const QImage &image); - - void UpdateStatusSlot(QString text); - void ProgressSetMaximumSlot(int progress); - void UpdateProgressSlot(int max); - - private: - void SearchAsync(int id, const QString &query, DeezerSettingsPage::SearchBy searchby); - void HandleLoadedArt(int id, const QImage &image); - bool FindCachedPixmap(const DeezerSearch::Result &result, QPixmap *pixmap) const; - QString PixmapCacheKey(const DeezerSearch::Result &result) const; - void MaybeSearchFinished(int id); - void ShowConfig() {} - static QImage ScaleAndPad(const QImage &image); - - private: - struct DelayedSearch { - int id_; - QString query_; - DeezerSettingsPage::SearchBy searchby_; - }; - - static const int kArtHeight; - - Application *app_; - DeezerService *service_; - Song::Source source_; - QString name_; - QString id_; - QIcon icon_; - QImage icon_as_image_; - int searches_next_id_; - int art_searches_next_id_; - - QMap delayed_searches_; - QMap pending_art_searches_; - QPixmapCache pixmap_cache_; - AlbumCoverLoaderOptions cover_loader_options_; - QMap cover_loader_tasks_; - - QMap pending_searches_; - -}; - -Q_DECLARE_METATYPE(DeezerSearch::Result) -Q_DECLARE_METATYPE(DeezerSearch::ResultList) - -#endif // DEEZERSEARCH_H diff --git a/src/deezer/deezersearchitemdelegate.cpp b/src/deezer/deezersearchitemdelegate.cpp deleted file mode 100644 index e1639d7f7..000000000 --- a/src/deezer/deezersearchitemdelegate.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2012, David Sansome - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#include -#include - -#include "deezersearchitemdelegate.h" -#include "deezersearchview.h" - -DeezerSearchItemDelegate::DeezerSearchItemDelegate(DeezerSearchView* view) - : CollectionItemDelegate(view), view_(view) {} - -void DeezerSearchItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - // Tell the view we painted this item so it can lazy load some art. - const_cast(view_)->LazyLoadArt(index); - - CollectionItemDelegate::paint(painter, option, index); -} diff --git a/src/deezer/deezersearchitemdelegate.h b/src/deezer/deezersearchitemdelegate.h deleted file mode 100644 index d00a3906b..000000000 --- a/src/deezer/deezersearchitemdelegate.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2012, David Sansome - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#ifndef DEEZERSEARCHITEMDELEGATE_H -#define DEEZERSEARCHITEMDELEGATE_H - -#include -#include - -#include "collection/collectionview.h" - -class DeezerSearchView; - -class DeezerSearchItemDelegate : public CollectionItemDelegate { - public: - DeezerSearchItemDelegate(DeezerSearchView *view); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; - - private: - DeezerSearchView* view_; -}; - -#endif // DEEZERSEARCHITEMDELEGATE_H diff --git a/src/deezer/deezersearchview.cpp b/src/deezer/deezersearchview.cpp deleted file mode 100644 index e30276035..000000000 --- a/src/deezer/deezersearchview.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2012, David Sansome - * Copyright 2018, Jonas Kvinge - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#include "config.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/application.h" -#include "core/logging.h" -#include "core/mimedata.h" -#include "core/timeconstants.h" -#include "core/iconloader.h" -#include "internet/internetsongmimedata.h" -#include "collection/collectionfilterwidget.h" -#include "collection/collectionmodel.h" -#include "collection/groupbydialog.h" -#include "playlist/songmimedata.h" -#include "deezersearch.h" -#include "deezersearchitemdelegate.h" -#include "deezersearchmodel.h" -#include "deezersearchsortmodel.h" -#include "deezersearchview.h" -#include "ui_deezersearchview.h" -#include "settings/deezersettingspage.h" - -using std::placeholders::_1; -using std::placeholders::_2; -using std::swap; - -const int DeezerSearchView::kSwapModelsTimeoutMsec = 250; - -DeezerSearchView::DeezerSearchView(Application *app, QWidget *parent) - : QWidget(parent), - app_(app), - engine_(app_->deezer_search()), - ui_(new Ui_DeezerSearchView), - context_menu_(nullptr), - last_search_id_(0), - front_model_(new DeezerSearchModel(engine_, this)), - back_model_(new DeezerSearchModel(engine_, this)), - current_model_(front_model_), - front_proxy_(new DeezerSearchSortModel(this)), - back_proxy_(new DeezerSearchSortModel(this)), - current_proxy_(front_proxy_), - swap_models_timer_(new QTimer(this)), - search_icon_(IconLoader::Load("search")), - warning_icon_(IconLoader::Load("dialog-warning")), - error_(false) { - - ui_->setupUi(this); - ui_->progressbar->hide(); - ui_->progressbar->reset(); - - front_model_->set_proxy(front_proxy_); - back_model_->set_proxy(back_proxy_); - - ui_->search->installEventFilter(this); - ui_->results_stack->installEventFilter(this); - - ui_->settings->setIcon(IconLoader::Load("configure")); - - // Must be a queued connection to ensure the DeezerSearch handles it first. - connect(app_, SIGNAL(SettingsChanged()), SLOT(ReloadSettings()), Qt::QueuedConnection); - - connect(ui_->search, SIGNAL(textChanged(QString)), SLOT(TextEdited(QString))); - connect(ui_->results, SIGNAL(AddToPlaylistSignal(QMimeData*)), SIGNAL(AddToPlaylist(QMimeData*))); - connect(ui_->results, SIGNAL(FocusOnFilterSignal(QKeyEvent*)), SLOT(FocusOnFilter(QKeyEvent*))); - - // Set the appearance of the results list - ui_->results->setItemDelegate(new DeezerSearchItemDelegate(this)); - ui_->results->setAttribute(Qt::WA_MacShowFocusRect, false); - ui_->results->setStyleSheet("QTreeView::item{padding-top:1px;}"); - - // Show the help page initially - ui_->results_stack->setCurrentWidget(ui_->help_page); - ui_->help_frame->setBackgroundRole(QPalette::Base); - - // Set the colour of the help text to the disabled window text colour - QPalette help_palette = ui_->label_helptext->palette(); - const QColor help_color = help_palette.color(QPalette::Disabled, QPalette::WindowText); - help_palette.setColor(QPalette::Normal, QPalette::WindowText, help_color); - help_palette.setColor(QPalette::Inactive, QPalette::WindowText, help_color); - ui_->label_helptext->setPalette(help_palette); - - // Make it bold - QFont help_font = ui_->label_helptext->font(); - help_font.setBold(true); - ui_->label_helptext->setFont(help_font); - - // Set up the sorting proxy model - front_proxy_->setSourceModel(front_model_); - front_proxy_->setDynamicSortFilter(true); - front_proxy_->sort(0); - - back_proxy_->setSourceModel(back_model_); - back_proxy_->setDynamicSortFilter(true); - back_proxy_->sort(0); - - swap_models_timer_->setSingleShot(true); - swap_models_timer_->setInterval(kSwapModelsTimeoutMsec); - connect(swap_models_timer_, SIGNAL(timeout()), SLOT(SwapModels())); - - // Add actions to the settings menu - group_by_actions_ = CollectionFilterWidget::CreateGroupByActions(this); - QMenu *settings_menu = new QMenu(this); - settings_menu->addActions(group_by_actions_->actions()); - settings_menu->addSeparator(); - settings_menu->addAction(IconLoader::Load("configure"), tr("Configure Deezer..."), this, SLOT(OpenSettingsDialog())); - ui_->settings->setMenu(settings_menu); - - connect(ui_->radiobutton_searchbyalbums, SIGNAL(clicked(bool)), SLOT(SearchByAlbumsClicked(bool))); - connect(ui_->radiobutton_searchbysongs, SIGNAL(clicked(bool)), SLOT(SearchBySongsClicked(bool))); - - connect(group_by_actions_, SIGNAL(triggered(QAction*)), SLOT(GroupByClicked(QAction*))); - - // These have to be queued connections because they may get emitted before our call to Search() (or whatever) returns and we add the ID to the map. - - connect(engine_, SIGNAL(UpdateStatus(QString)), SLOT(UpdateStatus(QString))); - connect(engine_, SIGNAL(ProgressSetMaximum(int)), SLOT(ProgressSetMaximum(int)), Qt::QueuedConnection); - connect(engine_, SIGNAL(UpdateProgress(int)), SLOT(UpdateProgress(int)), Qt::QueuedConnection); - - connect(engine_, SIGNAL(AddResults(int, DeezerSearch::ResultList)), SLOT(AddResults(int, DeezerSearch::ResultList)), Qt::QueuedConnection); - connect(engine_, SIGNAL(SearchError(int, QString)), SLOT(SearchError(int, QString)), Qt::QueuedConnection); - connect(engine_, SIGNAL(ArtLoaded(int, QPixmap)), SLOT(ArtLoaded(int, QPixmap)), Qt::QueuedConnection); - - ReloadSettings(); - -} - -DeezerSearchView::~DeezerSearchView() { delete ui_; } - -void DeezerSearchView::ReloadSettings() { - - QSettings s; - - // Collection settings - - s.beginGroup(DeezerSettingsPage::kSettingsGroup); - const bool pretty = s.value("pretty_covers", true).toBool(); - front_model_->set_use_pretty_covers(pretty); - back_model_->set_use_pretty_covers(pretty); - s.endGroup(); - - // Deezer search settings - - s.beginGroup(DeezerSettingsPage::kSettingsGroup); - searchby_ = DeezerSettingsPage::SearchBy(s.value("searchby", int(DeezerSettingsPage::SearchBy_Songs)).toInt()); - switch (searchby_) { - case DeezerSettingsPage::SearchBy_Songs: - ui_->radiobutton_searchbysongs->setChecked(true); - break; - case DeezerSettingsPage::SearchBy_Albums: - ui_->radiobutton_searchbyalbums->setChecked(true); - break; - } - - SetGroupBy(CollectionModel::Grouping( - CollectionModel::GroupBy(s.value("group_by1", int(CollectionModel::GroupBy_Artist)).toInt()), - CollectionModel::GroupBy(s.value("group_by2", int(CollectionModel::GroupBy_Album)).toInt()), - CollectionModel::GroupBy(s.value("group_by3", int(CollectionModel::GroupBy_None)).toInt()))); - s.endGroup(); - -} - -void DeezerSearchView::StartSearch(const QString &query) { - - ui_->search->setText(query); - TextEdited(query); - - // Swap models immediately - swap_models_timer_->stop(); - SwapModels(); - -} - -void DeezerSearchView::TextEdited(const QString &text) { - - const QString trimmed(text.trimmed()); - - error_ = false; - - // Add results to the back model, switch models after some delay. - back_model_->Clear(); - current_model_ = back_model_; - current_proxy_ = back_proxy_; - swap_models_timer_->start(); - - // Cancel the last search (if any) and start the new one. - engine_->CancelSearch(last_search_id_); - // If text query is empty, don't start a new search - if (trimmed.isEmpty()) { - last_search_id_ = -1; - ui_->label_helptext->setText("Enter search terms above to find music"); - ui_->label_status->clear(); - ui_->progressbar->hide(); - ui_->progressbar->reset(); - } - else { - ui_->progressbar->reset(); - last_search_id_ = engine_->SearchAsync(trimmed, searchby_); - } - -} - -void DeezerSearchView::AddResults(int id, const DeezerSearch::ResultList &results) { - if (id != last_search_id_) return; - if (results.isEmpty()) return; - ui_->label_status->clear(); - ui_->progressbar->reset(); - ui_->progressbar->hide(); - current_model_->AddResults(results); -} - -void DeezerSearchView::SearchError(const int id, const QString error) { - error_ = true; - ui_->label_helptext->setText(error); - ui_->label_status->clear(); - ui_->progressbar->reset(); - ui_->progressbar->hide(); - ui_->results_stack->setCurrentWidget(ui_->help_page); -} - -void DeezerSearchView::SwapModels() { - - art_requests_.clear(); - - std::swap(front_model_, back_model_); - std::swap(front_proxy_, back_proxy_); - - ui_->results->setModel(front_proxy_); - - if (ui_->search->text().trimmed().isEmpty() || error_) { - ui_->results_stack->setCurrentWidget(ui_->help_page); - } - else { - ui_->results_stack->setCurrentWidget(ui_->results_page); - } - -} - -void DeezerSearchView::LazyLoadArt(const QModelIndex &proxy_index) { - - if (!proxy_index.isValid() || proxy_index.model() != front_proxy_) { - return; - } - - // Already loading art for this item? - if (proxy_index.data(DeezerSearchModel::Role_LazyLoadingArt).isValid()) { - return; - } - - // Should we even load art at all? - if (!app_->collection_model()->use_pretty_covers()) { - return; - } - - // Is this an album? - const CollectionModel::GroupBy container_type = CollectionModel::GroupBy(proxy_index.data(CollectionModel::Role_ContainerType).toInt()); - if (container_type != CollectionModel::GroupBy_Album && - container_type != CollectionModel::GroupBy_AlbumArtist && - container_type != CollectionModel::GroupBy_YearAlbum && - container_type != CollectionModel::GroupBy_OriginalYearAlbum) { - return; - } - - // Mark the item as loading art - const QModelIndex source_index = front_proxy_->mapToSource(proxy_index); - QStandardItem *item = front_model_->itemFromIndex(source_index); - item->setData(true, DeezerSearchModel::Role_LazyLoadingArt); - - // Walk down the item's children until we find a track - while (item->rowCount()) { - item = item->child(0); - } - - // Get the track's Result - const DeezerSearch::Result result = item->data(DeezerSearchModel::Role_Result).value(); - - // Load the art. - int id = engine_->LoadArtAsync(result); - art_requests_[id] = source_index; - -} - -void DeezerSearchView::ArtLoaded(int id, const QPixmap &pixmap) { - - if (!art_requests_.contains(id)) return; - QModelIndex index = art_requests_.take(id); - - if (!pixmap.isNull()) { - front_model_->itemFromIndex(index)->setData(pixmap, Qt::DecorationRole); - } - -} - -MimeData *DeezerSearchView::SelectedMimeData() { - - if (!ui_->results->selectionModel()) return nullptr; - - // Get all selected model indexes - QModelIndexList indexes = ui_->results->selectionModel()->selectedRows(); - if (indexes.isEmpty()) { - // There's nothing selected - take the first thing in the model that isn't a divider. - for (int i = 0; i < front_proxy_->rowCount(); ++i) { - QModelIndex index = front_proxy_->index(i, 0); - if (!index.data(CollectionModel::Role_IsDivider).toBool()) { - indexes << index; - ui_->results->setCurrentIndex(index); - break; - } - } - } - - // Still got nothing? Give up. - if (indexes.isEmpty()) { - return nullptr; - } - - // Get items for these indexes - QList items; - for (const QModelIndex &index : indexes) { - items << (front_model_->itemFromIndex(front_proxy_->mapToSource(index))); - } - - // Get a MimeData for these items - return engine_->LoadTracks(front_model_->GetChildResults(items)); - -} - -bool DeezerSearchView::eventFilter(QObject *object, QEvent *event) { - - if (object == ui_->search && event->type() == QEvent::KeyRelease) { - if (SearchKeyEvent(static_cast(event))) { - return true; - } - } - else if (object == ui_->results_stack && event->type() == QEvent::ContextMenu) { - if (ResultsContextMenuEvent(static_cast(event))) { - return true; - } - } - - return QWidget::eventFilter(object, event); - -} - -bool DeezerSearchView::SearchKeyEvent(QKeyEvent *event) { - - switch (event->key()) { - case Qt::Key_Up: - ui_->results->UpAndFocus(); - break; - - case Qt::Key_Down: - ui_->results->DownAndFocus(); - break; - - case Qt::Key_Escape: - ui_->search->clear(); - break; - - case Qt::Key_Return: - TextEdited(ui_->search->text()); - break; - - default: - return false; - } - - event->accept(); - return true; - -} - -bool DeezerSearchView::ResultsContextMenuEvent(QContextMenuEvent *event) { - - context_menu_ = new QMenu(this); - context_actions_ << context_menu_->addAction( IconLoader::Load("media-play"), tr("Append to current playlist"), this, SLOT(AddSelectedToPlaylist())); - context_actions_ << context_menu_->addAction( IconLoader::Load("media-play"), tr("Replace current playlist"), this, SLOT(LoadSelected())); - context_actions_ << context_menu_->addAction( IconLoader::Load("document-new"), tr("Open in new playlist"), this, SLOT(OpenSelectedInNewPlaylist())); - - context_menu_->addSeparator(); - context_actions_ << context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, SLOT(AddSelectedToPlaylistEnqueue())); - - context_menu_->addSeparator(); - - if (ui_->results->selectionModel() && ui_->results->selectionModel()->selectedRows().length() == 1) { - context_actions_ << context_menu_->addAction(IconLoader::Load("search"), tr("Search for this"), this, SLOT(SearchForThis())); - } - - context_menu_->addSeparator(); - context_menu_->addMenu(tr("Group by"))->addActions(group_by_actions_->actions()); - context_menu_->addAction(IconLoader::Load("configure"), tr("Configure Deezer..."), this, SLOT(OpenSettingsDialog())); - - const bool enable_context_actions = ui_->results->selectionModel() && ui_->results->selectionModel()->hasSelection(); - - for (QAction *action : context_actions_) { - action->setEnabled(enable_context_actions); - } - - context_menu_->popup(event->globalPos()); - - return true; - -} - -void DeezerSearchView::AddSelectedToPlaylist() { - emit AddToPlaylist(SelectedMimeData()); -} - -void DeezerSearchView::LoadSelected() { - MimeData *data = SelectedMimeData(); - if (!data) return; - - data->clear_first_ = true; - emit AddToPlaylist(data); -} - -void DeezerSearchView::AddSelectedToPlaylistEnqueue() { - MimeData *data = SelectedMimeData(); - if (!data) return; - - data->enqueue_now_ = true; - emit AddToPlaylist(data); -} - -void DeezerSearchView::OpenSelectedInNewPlaylist() { - MimeData *data = SelectedMimeData(); - if (!data) return; - - data->open_in_new_playlist_ = true; - emit AddToPlaylist(data); -} - -void DeezerSearchView::SearchForThis() { - StartSearch(ui_->results->selectionModel()->selectedRows().first().data().toString()); -} - -void DeezerSearchView::showEvent(QShowEvent *e) { - QWidget::showEvent(e); - FocusSearchField(); -} - -void DeezerSearchView::FocusSearchField() { - ui_->search->setFocus(); - ui_->search->selectAll(); -} - -void DeezerSearchView::hideEvent(QHideEvent *e) { - QWidget::hideEvent(e); -} - -void DeezerSearchView::FocusOnFilter(QKeyEvent *event) { - ui_->search->setFocus(); - QApplication::sendEvent(ui_->search, event); -} - -void DeezerSearchView::OpenSettingsDialog() { - app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Deezer); -} - -void DeezerSearchView::GroupByClicked(QAction *action) { - - if (action->property("group_by").isNull()) { - if (!group_by_dialog_) { - group_by_dialog_.reset(new GroupByDialog); - connect(group_by_dialog_.data(), SIGNAL(Accepted(CollectionModel::Grouping)), SLOT(SetGroupBy(CollectionModel::Grouping))); - } - - group_by_dialog_->show(); - return; - } - - SetGroupBy(action->property("group_by").value()); - -} - -void DeezerSearchView::SetGroupBy(const CollectionModel::Grouping &g) { - - // Clear requests: changing "group by" on the models will cause all the items to be removed/added again, - // so all the QModelIndex here will become invalid. New requests will be created for those - // songs when they will be displayed again anyway (when DeezerSearchItemDelegate::paint will call LazyLoadArt) - art_requests_.clear(); - // Update the models - front_model_->SetGroupBy(g, true); - back_model_->SetGroupBy(g, false); - - // Save the setting - QSettings s; - s.beginGroup(DeezerSettingsPage::kSettingsGroup); - s.setValue("group_by1", int(g.first)); - s.setValue("group_by2", int(g.second)); - s.setValue("group_by3", int(g.third)); - s.endGroup(); - - // Make sure the correct action is checked. - for (QAction *action : group_by_actions_->actions()) { - if (action->property("group_by").isNull()) continue; - - if (g == action->property("group_by").value()) { - action->setChecked(true); - return; - } - } - - // Check the advanced action - group_by_actions_->actions().last()->setChecked(true); - -} - -void DeezerSearchView::SearchBySongsClicked(bool checked) { - SetSearchBy(DeezerSettingsPage::SearchBy_Songs); -} - -void DeezerSearchView::SearchByAlbumsClicked(bool checked) { - SetSearchBy(DeezerSettingsPage::SearchBy_Albums); -} - -void DeezerSearchView::SetSearchBy(DeezerSettingsPage::SearchBy searchby) { - searchby_ = searchby; - QSettings s; - s.beginGroup(DeezerSettingsPage::kSettingsGroup); - s.setValue("searchby", int(searchby)); - s.endGroup(); - TextEdited(ui_->search->text()); -} - -void DeezerSearchView::UpdateStatus(QString text) { - ui_->progressbar->show(); - ui_->label_status->setText(text); -} - -void DeezerSearchView::ProgressSetMaximum(int max) { - ui_->progressbar->setMaximum(max); -} - -void DeezerSearchView::UpdateProgress(int progress) { - ui_->progressbar->setValue(progress); -} diff --git a/src/deezer/deezersearchview.h b/src/deezer/deezersearchview.h deleted file mode 100644 index 24b3d35f3..000000000 --- a/src/deezer/deezersearchview.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2012, David Sansome - * Copyright 2018, Jonas Kvinge - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#ifndef DEEZERSEARCHVIEW_H -#define DEEZERSEARCHVIEW_H - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "collection/collectionmodel.h" -#include "settings/settingsdialog.h" -#include "playlist/playlistmanager.h" -#include "deezersearch.h" -#include "settings/deezersettingspage.h" - -class Application; -class GroupByDialog; -class DeezerSearchModel; -class Ui_DeezerSearchView; - -class DeezerSearchView : public QWidget { - Q_OBJECT - - public: - DeezerSearchView(Application *app, QWidget *parent = nullptr); - ~DeezerSearchView(); - - static const int kSwapModelsTimeoutMsec; - - void LazyLoadArt(const QModelIndex &index); - - void showEvent(QShowEvent *e); - void hideEvent(QHideEvent *e); - bool eventFilter(QObject *object, QEvent *event); - - public slots: - void ReloadSettings(); - void StartSearch(const QString &query); - void FocusSearchField(); - void OpenSettingsDialog(); - -signals: - void AddToPlaylist(QMimeData *data); - - private slots: - void SwapModels(); - void TextEdited(const QString &text); - void UpdateStatus(QString text); - void ProgressSetMaximum(int progress); - void UpdateProgress(int max); - void AddResults(int id, const DeezerSearch::ResultList &results); - void SearchError(const int id, const QString error); - void ArtLoaded(int id, const QPixmap &pixmap); - - void FocusOnFilter(QKeyEvent *event); - - void AddSelectedToPlaylist(); - void LoadSelected(); - void OpenSelectedInNewPlaylist(); - void AddSelectedToPlaylistEnqueue(); - - void SearchForThis(); - - void SearchBySongsClicked(bool); - void SearchByAlbumsClicked(bool); - void GroupByClicked(QAction *action); - void SetSearchBy(DeezerSettingsPage::SearchBy searchby); - void SetGroupBy(const CollectionModel::Grouping &g); - - private: - MimeData *SelectedMimeData(); - - bool SearchKeyEvent(QKeyEvent *event); - bool ResultsContextMenuEvent(QContextMenuEvent *event); - - Application *app_; - DeezerSearch *engine_; - Ui_DeezerSearchView *ui_; - QScopedPointer group_by_dialog_; - - QMenu *context_menu_; - QList context_actions_; - QActionGroup *group_by_actions_; - - int last_search_id_; - - // Like graphics APIs have a front buffer and a back buffer, there's a front model and a back model - // The front model is the one that's shown in the UI and the back model is the one that lies in wait. - // current_model_ will point to either the front or the back model. - DeezerSearchModel *front_model_; - DeezerSearchModel *back_model_; - DeezerSearchModel *current_model_; - - QSortFilterProxyModel *front_proxy_; - QSortFilterProxyModel *back_proxy_; - QSortFilterProxyModel *current_proxy_; - - QMap art_requests_; - - QTimer *swap_models_timer_; - - QIcon search_icon_; - QIcon warning_icon_; - - DeezerSettingsPage::SearchBy searchby_; - bool error_; - -}; - -#endif // DEEZERSEARCHVIEW_H diff --git a/src/deezer/deezersearchview.ui b/src/deezer/deezersearchview.ui deleted file mode 100644 index 357891442..000000000 --- a/src/deezer/deezersearchview.ui +++ /dev/null @@ -1,283 +0,0 @@ - - - DeezerSearchView - - - - 0 - 0 - 400 - 660 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - - - - - - - - - Search for anything - - - - - - - - 20 - 0 - - - - QToolButton::InstantPopup - - - true - - - - - - - - - QLayout::SetFixedSize - - - - - true - - - Search by - - - 10 - - - - - - - a&lbums - - - - - - - son&gs - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - true - - - - - - - 0 - - - - - - - - - - - - - - 1 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::DragOnly - - - QAbstractItemView::ExtendedSelection - - - true - - - false - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 398 - 502 - - - - - - - - 32 - - - 16 - - - 32 - - - 64 - - - - - Enter search terms above to find music - - - Qt::AlignCenter - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - - - - - QSearchField - QWidget -
3rdparty/qocoa/qsearchfield.h
-
- - AutoExpandingTreeView - QTreeView -
widgets/autoexpandingtreeview.h
-
-
- - -
diff --git a/src/deezer/deezerservice.cpp b/src/deezer/deezerservice.cpp index 9af97cb44..4caa9fb56 100644 --- a/src/deezer/deezerservice.cpp +++ b/src/deezer/deezerservice.cpp @@ -55,9 +55,9 @@ #include "core/timeconstants.h" #include "core/utilities.h" #include "internet/internetmodel.h" +#include "internet/internetsearch.h" #include "internet/localredirectserver.h" #include "deezerservice.h" -#include "deezersearch.h" #include "deezerurlhandler.h" #include "settings/deezersettingspage.h" @@ -408,7 +408,7 @@ QJsonValue DeezerService::ExtractData(QByteArray &data) { } -int DeezerService::Search(const QString &text, DeezerSettingsPage::SearchBy searchby) { +int DeezerService::Search(const QString &text, InternetSearch::SearchBy searchby) { pending_search_id_ = next_pending_search_id_; pending_search_text_ = text; @@ -466,11 +466,11 @@ void DeezerService::SendSearch() { parameters << Param("q", search_text_); QString searchparam; switch (pending_searchby_) { - case DeezerSettingsPage::SearchBy_Songs: + case InternetSearch::SearchBy_Songs: searchparam = "search/track"; parameters << Param("limit", QString::number(songssearchlimit_)); break; - case DeezerSettingsPage::SearchBy_Albums: + case InternetSearch::SearchBy_Albums: default: searchparam = "search/album"; parameters << Param("limit", QString::number(albumssearchlimit_)); diff --git a/src/deezer/deezerservice.h b/src/deezer/deezerservice.h index 10e047db0..16d270ef0 100644 --- a/src/deezer/deezerservice.h +++ b/src/deezer/deezerservice.h @@ -41,7 +41,7 @@ #include "core/song.h" #include "internet/internetmodel.h" #include "internet/internetservice.h" -#include "settings/deezersettingspage.h" +#include "internet/internetsearch.h" class NetworkAccessManager; class LocalRedirectServer; @@ -70,7 +70,7 @@ class DeezerService : public InternetService { void ReloadSettings(); void Logout(); - int Search(const QString &query, DeezerSettingsPage::SearchBy searchby); + int Search(const QString &query, InternetSearch::SearchBy searchby); void CancelSearch(); const bool app_id() { return kAppID; } @@ -146,7 +146,7 @@ class DeezerService : public InternetService { int pending_search_id_; int next_pending_search_id_; QString pending_search_text_; - DeezerSettingsPage::SearchBy pending_searchby_; + InternetSearch::SearchBy pending_searchby_; int search_id_; QString search_text_; diff --git a/src/internet/internetmodel.h b/src/internet/internetmodel.h index 2cd832580..3e8d69375 100644 --- a/src/internet/internetmodel.h +++ b/src/internet/internetmodel.h @@ -124,7 +124,6 @@ class InternetModel : public QStandardItemModel { void ServiceDeleted(); private: - //static QMap *sServices; static QMap *sServices; Application *app_; diff --git a/src/tidal/tidalsearch.cpp b/src/internet/internetsearch.cpp similarity index 72% rename from src/tidal/tidalsearch.cpp rename to src/internet/internetsearch.cpp index 7960a87cb..71683f08b 100644 --- a/src/tidal/tidalsearch.cpp +++ b/src/internet/internetsearch.cpp @@ -42,24 +42,23 @@ #include "core/logging.h" #include "core/closure.h" #include "core/iconloader.h" +#include "core/song.h" #include "covermanager/albumcoverloader.h" #include "internet/internetsongmimedata.h" #include "playlist/songmimedata.h" -#include "tidalsearch.h" -#include "tidalservice.h" -#include "settings/tidalsettingspage.h" +#include "internetsearch.h" +#include "internetservice.h" +#include "internetmodel.h" -const int TidalSearch::kDelayedSearchTimeoutMs = 200; -const int TidalSearch::kMaxResultsPerEmission = 2000; -const int TidalSearch::kArtHeight = 32; +const int InternetSearch::kDelayedSearchTimeoutMs = 200; +const int InternetSearch::kMaxResultsPerEmission = 2000; +const int InternetSearch::kArtHeight = 32; -TidalSearch::TidalSearch(Application *app, QObject *parent) +InternetSearch::InternetSearch(Application *app, Song::Source source, QObject *parent) : QObject(parent), app_(app), - service_(app->internet_model()->Service()), - name_("Tidal"), - id_("tidal"), - icon_(IconLoader::Load("tidal")), + source_(source), + service_(app->internet_model()->ServiceBySource(source)), searches_next_id_(1), art_searches_next_id_(1) { @@ -68,8 +67,8 @@ TidalSearch::TidalSearch(Application *app, QObject *parent) cover_loader_options_.scale_output_image_ = true; connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)), SLOT(AlbumArtLoaded(quint64, QImage))); - connect(this, SIGNAL(SearchAsyncSig(int, QString, TidalSettingsPage::SearchBy)), this, SLOT(DoSearchAsync(int, QString, TidalSettingsPage::SearchBy))); - connect(this, SIGNAL(ResultsAvailable(int, TidalSearch::ResultList)), SLOT(ResultsAvailableSlot(int, TidalSearch::ResultList))); + connect(this, SIGNAL(SearchAsyncSig(int, QString, SearchBy)), this, SLOT(DoSearchAsync(int, QString, SearchBy))); + connect(this, SIGNAL(ResultsAvailable(int, InternetSearch::ResultList)), SLOT(ResultsAvailableSlot(int, InternetSearch::ResultList))); connect(this, SIGNAL(ArtLoaded(int, QImage)), SLOT(ArtLoadedSlot(int, QImage))); connect(service_, SIGNAL(UpdateStatus(QString)), SLOT(UpdateStatusSlot(QString))); connect(service_, SIGNAL(ProgressSetMaximum(int)), SLOT(ProgressSetMaximumSlot(int))); @@ -77,13 +76,11 @@ TidalSearch::TidalSearch(Application *app, QObject *parent) connect(service_, SIGNAL(SearchResults(int, SongList)), SLOT(SearchDone(int, SongList))); connect(service_, SIGNAL(SearchError(int, QString)), SLOT(HandleError(int, QString))); - icon_as_image_ = QImage(icon_.pixmap(48, 48).toImage()); - } -TidalSearch::~TidalSearch() {} +InternetSearch::~InternetSearch() {} -QStringList TidalSearch::TokenizeQuery(const QString &query) { +QStringList InternetSearch::TokenizeQuery(const QString &query) { QStringList tokens(query.split(QRegExp("\\s+"))); @@ -102,7 +99,7 @@ QStringList TidalSearch::TokenizeQuery(const QString &query) { } -bool TidalSearch::Matches(const QStringList &tokens, const QString &string) { +bool InternetSearch::Matches(const QStringList &tokens, const QString &string) { for (const QString &token : tokens) { if (!string.contains(token, Qt::CaseInsensitive)) { @@ -114,7 +111,7 @@ bool TidalSearch::Matches(const QStringList &tokens, const QString &string) { } -int TidalSearch::SearchAsync(const QString &query, TidalSettingsPage::SearchBy searchby) { +int InternetSearch::SearchAsync(const QString &query, SearchBy searchby) { const int id = searches_next_id_++; @@ -124,14 +121,14 @@ int TidalSearch::SearchAsync(const QString &query, TidalSettingsPage::SearchBy s } -void TidalSearch::SearchAsync(int id, const QString &query, TidalSettingsPage::SearchBy searchby) { +void InternetSearch::SearchAsync(int id, const QString &query, SearchBy searchby) { const int service_id = service_->Search(query, searchby); pending_searches_[service_id] = PendingState(id, TokenizeQuery(query)); } -void TidalSearch::DoSearchAsync(int id, const QString &query, TidalSettingsPage::SearchBy searchby) { +void InternetSearch::DoSearchAsync(int id, const QString &query, SearchBy searchby) { int timer_id = startTimer(kDelayedSearchTimeoutMs); delayed_searches_[timer_id].id_ = id; @@ -140,7 +137,7 @@ void TidalSearch::DoSearchAsync(int id, const QString &query, TidalSettingsPage: } -void TidalSearch::SearchDone(int service_id, const SongList &songs) { +void InternetSearch::SearchDone(int service_id, const SongList &songs) { // Map back to the original id. const PendingState state = pending_searches_.take(service_id); @@ -158,13 +155,13 @@ void TidalSearch::SearchDone(int service_id, const SongList &songs) { } -void TidalSearch::HandleError(const int id, const QString error) { +void InternetSearch::HandleError(const int id, const QString error) { emit SearchError(id, error); } -void TidalSearch::MaybeSearchFinished(int id) { +void InternetSearch::MaybeSearchFinished(int id) { if (pending_searches_.keys(PendingState(id, QStringList())).isEmpty()) { emit SearchFinished(id); @@ -172,7 +169,7 @@ void TidalSearch::MaybeSearchFinished(int id) { } -void TidalSearch::CancelSearch(int id) { +void InternetSearch::CancelSearch(int id) { QMap::iterator it; for (it = delayed_searches_.begin(); it != delayed_searches_.end(); ++it) { if (it.value().id_ == id) { @@ -184,7 +181,7 @@ void TidalSearch::CancelSearch(int id) { service_->CancelSearch(); } -void TidalSearch::timerEvent(QTimerEvent *e) { +void InternetSearch::timerEvent(QTimerEvent *e) { QMap::iterator it = delayed_searches_.find(e->timerId()); if (it != delayed_searches_.end()) { SearchAsync(it.value().id_, it.value().query_, it.value().searchby_); @@ -195,19 +192,19 @@ void TidalSearch::timerEvent(QTimerEvent *e) { QObject::timerEvent(e); } -void TidalSearch::ResultsAvailableSlot(int id, TidalSearch::ResultList results) { +void InternetSearch::ResultsAvailableSlot(int id, InternetSearch::ResultList results) { if (results.isEmpty()) return; // Limit the number of results that are used from each emission. if (results.count() > kMaxResultsPerEmission) { - TidalSearch::ResultList::iterator begin = results.begin(); + InternetSearch::ResultList::iterator begin = results.begin(); std::advance(begin, kMaxResultsPerEmission); results.erase(begin, results.end()); } // Load cached pixmaps into the results - for (TidalSearch::ResultList::iterator it = results.begin(); it != results.end(); ++it) { + for (InternetSearch::ResultList::iterator it = results.begin(); it != results.end(); ++it) { it->pixmap_cache_key_ = PixmapCacheKey(*it); } @@ -215,15 +212,15 @@ void TidalSearch::ResultsAvailableSlot(int id, TidalSearch::ResultList results) } -QString TidalSearch::PixmapCacheKey(const TidalSearch::Result &result) const { - return "tidal:" % result.metadata_.url().toString(); +QString InternetSearch::PixmapCacheKey(const InternetSearch::Result &result) const { + return "internet:" % result.metadata_.url().toString(); } -bool TidalSearch::FindCachedPixmap(const TidalSearch::Result &result, QPixmap *pixmap) const { +bool InternetSearch::FindCachedPixmap(const InternetSearch::Result &result, QPixmap *pixmap) const { return pixmap_cache_.find(result.pixmap_cache_key_, pixmap); } -int TidalSearch::LoadArtAsync(const TidalSearch::Result &result) { +int InternetSearch::LoadArtAsync(const InternetSearch::Result &result) { const int id = art_searches_next_id_++; @@ -236,11 +233,11 @@ int TidalSearch::LoadArtAsync(const TidalSearch::Result &result) { } -void TidalSearch::ArtLoadedSlot(int id, const QImage &image) { +void InternetSearch::ArtLoadedSlot(int id, const QImage &image) { HandleLoadedArt(id, image); } -void TidalSearch::AlbumArtLoaded(quint64 id, const QImage &image) { +void InternetSearch::AlbumArtLoaded(quint64 id, const QImage &image) { if (!cover_loader_tasks_.contains(id)) return; int orig_id = cover_loader_tasks_.take(id); @@ -249,7 +246,7 @@ void TidalSearch::AlbumArtLoaded(quint64 id, const QImage &image) { } -void TidalSearch::HandleLoadedArt(int id, const QImage &image) { +void InternetSearch::HandleLoadedArt(int id, const QImage &image) { const QString key = pending_art_searches_.take(id); @@ -260,7 +257,7 @@ void TidalSearch::HandleLoadedArt(int id, const QImage &image) { } -QImage TidalSearch::ScaleAndPad(const QImage &image) { +QImage InternetSearch::ScaleAndPad(const QImage &image) { if (image.isNull()) return QImage(); @@ -286,7 +283,7 @@ QImage TidalSearch::ScaleAndPad(const QImage &image) { } -MimeData *TidalSearch::LoadTracks(const ResultList &results) { +MimeData *InternetSearch::LoadTracks(const ResultList &results) { if (results.isEmpty()) { return nullptr; @@ -316,14 +313,14 @@ MimeData *TidalSearch::LoadTracks(const ResultList &results) { } -void TidalSearch::UpdateStatusSlot(QString text) { +void InternetSearch::UpdateStatusSlot(QString text) { emit UpdateStatus(text); } -void TidalSearch::ProgressSetMaximumSlot(int max) { +void InternetSearch::ProgressSetMaximumSlot(int max) { emit ProgressSetMaximum(max); } -void TidalSearch::UpdateProgressSlot(int progress) { +void InternetSearch::UpdateProgressSlot(int progress) { emit UpdateProgress(progress); } diff --git a/src/tidal/tidalsearch.h b/src/internet/internetsearch.h similarity index 74% rename from src/tidal/tidalsearch.h rename to src/internet/internetsearch.h index 8d2b05cf9..ff22a1c10 100644 --- a/src/tidal/tidalsearch.h +++ b/src/internet/internetsearch.h @@ -19,8 +19,8 @@ * */ -#ifndef TIDALSEARCH_H -#define TIDALSEARCH_H +#ifndef INTERNETSEARCH_H +#define INTERNETSEARCH_H #include "config.h" @@ -32,20 +32,23 @@ #include "core/song.h" #include "covermanager/albumcoverloaderoptions.h" -#include "settings/tidalsettingspage.h" class Application; class MimeData; class AlbumCoverLoader; class InternetService; -class TidalService; -class TidalSearch : public QObject { +class InternetSearch : public QObject { Q_OBJECT public: - TidalSearch(Application *app, QObject *parent = nullptr); - ~TidalSearch(); + InternetSearch(Application *app, Song::Source source, QObject *parent = nullptr); + ~InternetSearch(); + + enum SearchBy { + SearchBy_Songs = 1, + SearchBy_Albums = 2, + }; struct Result { Song metadata_; @@ -57,10 +60,11 @@ class TidalSearch : public QObject { static const int kMaxResultsPerEmission; Application *application() const { return app_; } - TidalService *service() const { return service_; } + Song::Source source() const { return source_; } + InternetService *service() const { return service_; } - int SearchAsync(const QString &query, TidalSettingsPage::SearchBy searchby); - int LoadArtAsync(const TidalSearch::Result &result); + int SearchAsync(const QString &query, SearchBy searchby); + int LoadArtAsync(const InternetSearch::Result &result); void CancelSearch(int id); void CancelArt(int id); @@ -70,9 +74,9 @@ class TidalSearch : public QObject { MimeData *LoadTracks(const ResultList &results); signals: - void SearchAsyncSig(int id, const QString &query, TidalSettingsPage::SearchBy searchby); - void ResultsAvailable(int id, const TidalSearch::ResultList &results); - void AddResults(int id, const TidalSearch::ResultList &results); + void SearchAsyncSig(int id, const QString &query, SearchBy searchby); + void ResultsAvailable(int id, const InternetSearch::ResultList &results); + void AddResults(int id, const InternetSearch::ResultList &results); void SearchError(const int id, const QString error); void SearchFinished(int id); void UpdateStatus(QString text); @@ -108,10 +112,10 @@ class TidalSearch : public QObject { static bool Matches(const QStringList &tokens, const QString &string); private slots: - void DoSearchAsync(int id, const QString &query, TidalSettingsPage::SearchBy searchby); + void DoSearchAsync(int id, const QString &query, SearchBy searchby); void SearchDone(int id, const SongList &songs); void HandleError(const int id, const QString error); - void ResultsAvailableSlot(int id, TidalSearch::ResultList results); + void ResultsAvailableSlot(int id, InternetSearch::ResultList results); void ArtLoadedSlot(int id, const QImage &image); void AlbumArtLoaded(quint64 id, const QImage &image); @@ -121,10 +125,10 @@ class TidalSearch : public QObject { void UpdateProgressSlot(int max); private: - void SearchAsync(int id, const QString &query, TidalSettingsPage::SearchBy searchby); + void SearchAsync(int id, const QString &query, SearchBy searchby); void HandleLoadedArt(int id, const QImage &image); - bool FindCachedPixmap(const TidalSearch::Result &result, QPixmap *pixmap) const; - QString PixmapCacheKey(const TidalSearch::Result &result) const; + bool FindCachedPixmap(const InternetSearch::Result &result, QPixmap *pixmap) const; + QString PixmapCacheKey(const InternetSearch::Result &result) const; void MaybeSearchFinished(int id); void ShowConfig() {} static QImage ScaleAndPad(const QImage &image); @@ -133,18 +137,14 @@ class TidalSearch : public QObject { struct DelayedSearch { int id_; QString query_; - TidalSettingsPage::SearchBy searchby_; + SearchBy searchby_; }; static const int kArtHeight; Application *app_; - TidalService *service_; Song::Source source_; - QString name_; - QString id_; - QIcon icon_; - QImage icon_as_image_; + InternetService *service_; int searches_next_id_; int art_searches_next_id_; @@ -158,7 +158,7 @@ class TidalSearch : public QObject { }; -Q_DECLARE_METATYPE(TidalSearch::Result) -Q_DECLARE_METATYPE(TidalSearch::ResultList) +Q_DECLARE_METATYPE(InternetSearch::Result) +Q_DECLARE_METATYPE(InternetSearch::ResultList) -#endif // TIDALSEARCH_H +#endif // INTERNETSEARCH_H diff --git a/src/tidal/tidalsearchitemdelegate.cpp b/src/internet/internetsearchitemdelegate.cpp similarity index 74% rename from src/tidal/tidalsearchitemdelegate.cpp rename to src/internet/internetsearchitemdelegate.cpp index 4ef724712..20ce6c4f6 100644 --- a/src/tidal/tidalsearchitemdelegate.cpp +++ b/src/internet/internetsearchitemdelegate.cpp @@ -21,15 +21,15 @@ #include #include -#include "tidalsearchitemdelegate.h" -#include "tidalsearchview.h" +#include "internetsearchitemdelegate.h" +#include "internetsearchview.h" -TidalSearchItemDelegate::TidalSearchItemDelegate(TidalSearchView* view) +InternetSearchItemDelegate::InternetSearchItemDelegate(InternetSearchView* view) : CollectionItemDelegate(view), view_(view) {} -void TidalSearchItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { +void InternetSearchItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { // Tell the view we painted this item so it can lazy load some art. - const_cast(view_)->LazyLoadArt(index); + const_cast(view_)->LazyLoadArt(index); CollectionItemDelegate::paint(painter, option, index); } diff --git a/src/tidal/tidalsearchitemdelegate.h b/src/internet/internetsearchitemdelegate.h similarity index 77% rename from src/tidal/tidalsearchitemdelegate.h rename to src/internet/internetsearchitemdelegate.h index 777899010..42e825370 100644 --- a/src/tidal/tidalsearchitemdelegate.h +++ b/src/internet/internetsearchitemdelegate.h @@ -18,24 +18,24 @@ * */ -#ifndef TIDALSEARCHITEMDELEGATE_H -#define TIDALSEARCHITEMDELEGATE_H +#ifndef INTERNETSEARCHITEMDELEGATE_H +#define INTERNETSEARCHITEMDELEGATE_H #include #include #include "collection/collectionview.h" -class TidalSearchView; +class InternetSearchView; -class TidalSearchItemDelegate : public CollectionItemDelegate { +class InternetSearchItemDelegate : public CollectionItemDelegate { public: - TidalSearchItemDelegate(TidalSearchView *view); + InternetSearchItemDelegate(InternetSearchView *view); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: - TidalSearchView* view_; + InternetSearchView* view_; }; -#endif // TIDALSEARCHITEMDELEGATE_H +#endif // INTERNETSEARCHITEMDELEGATE_H diff --git a/src/deezer/deezersearchmodel.cpp b/src/internet/internetsearchmodel.cpp similarity index 86% rename from src/deezer/deezersearchmodel.cpp rename to src/internet/internetsearchmodel.cpp index 21f5c4375..5ce96b374 100644 --- a/src/deezer/deezersearchmodel.cpp +++ b/src/internet/internetsearchmodel.cpp @@ -33,10 +33,10 @@ #include "core/mimedata.h" #include "core/iconloader.h" #include "core/logging.h" -#include "deezersearch.h" -#include "deezersearchmodel.h" +#include "internetsearch.h" +#include "internetsearchmodel.h" -DeezerSearchModel::DeezerSearchModel(DeezerSearch *engine, QObject *parent) +InternetSearchModel::InternetSearchModel(InternetSearch *engine, QObject *parent) : QStandardItemModel(parent), engine_(engine), proxy_(nullptr), @@ -55,11 +55,11 @@ DeezerSearchModel::DeezerSearchModel(DeezerSearch *engine, QObject *parent) } -void DeezerSearchModel::AddResults(const DeezerSearch::ResultList &results) { +void InternetSearchModel::AddResults(const InternetSearch::ResultList &results) { int sort_index = 0; - for (const DeezerSearch::Result &result : results) { + for (const InternetSearch::Result &result : results) { QStandardItem *parent = invisibleRootItem(); // Find (or create) the container nodes for this result if we can. @@ -79,7 +79,7 @@ void DeezerSearchModel::AddResults(const DeezerSearch::ResultList &results) { } -QStandardItem *DeezerSearchModel::BuildContainers(const Song &s, QStandardItem *parent, ContainerKey *key, int level) { +QStandardItem *InternetSearchModel::BuildContainers(const Song &s, QStandardItem *parent, ContainerKey *key, int level) { if (level >= 3) { return parent; @@ -210,12 +210,12 @@ QStandardItem *DeezerSearchModel::BuildContainers(const Song &s, QStandardItem * } -void DeezerSearchModel::Clear() { +void InternetSearchModel::Clear() { containers_.clear(); clear(); } -DeezerSearch::ResultList DeezerSearchModel::GetChildResults(const QModelIndexList &indexes) const { +InternetSearch::ResultList InternetSearchModel::GetChildResults(const QModelIndexList &indexes) const { QList items; for (const QModelIndex &index : indexes) { @@ -225,9 +225,9 @@ DeezerSearch::ResultList DeezerSearchModel::GetChildResults(const QModelIndexLis } -DeezerSearch::ResultList DeezerSearchModel::GetChildResults(const QList &items) const { +InternetSearch::ResultList InternetSearchModel::GetChildResults(const QList &items) const { - DeezerSearch::ResultList results; + InternetSearch::ResultList results; QSet visited; for (QStandardItem *item : items) { @@ -238,7 +238,7 @@ DeezerSearch::ResultList DeezerSearchModel::GetChildResults(const QList *visited) const { +void InternetSearchModel::GetChildResults(const QStandardItem *item, InternetSearch::ResultList *results, QSet *visited) const { if (visited->contains(item)) { return; @@ -261,7 +261,7 @@ void DeezerSearchModel::GetChildResults(const QStandardItem *item, DeezerSearch: // No - maybe it's a song, add its result if valid QVariant result = item->data(Role_Result); if (result.isValid()) { - results->append(result.value()); + results->append(result.value()); } else { // Maybe it's a provider then? @@ -282,16 +282,16 @@ void DeezerSearchModel::GetChildResults(const QStandardItem *item, DeezerSearch: } -QMimeData *DeezerSearchModel::mimeData(const QModelIndexList &indexes) const { +QMimeData *InternetSearchModel::mimeData(const QModelIndexList &indexes) const { return engine_->LoadTracks(GetChildResults(indexes)); } namespace { -void GatherResults(const QStandardItem *parent, DeezerSearch::ResultList *results) { +void GatherResults(const QStandardItem *parent, InternetSearch::ResultList *results) { - QVariant result_variant = parent->data(DeezerSearchModel::Role_Result); + QVariant result_variant = parent->data(InternetSearchModel::Role_Result); if (result_variant.isValid()) { - DeezerSearch::Result result = result_variant.value(); + InternetSearch::Result result = result_variant.value(); (*results).append(result); } @@ -301,14 +301,14 @@ void GatherResults(const QStandardItem *parent, DeezerSearch::ResultList *result } } -void DeezerSearchModel::SetGroupBy(const CollectionModel::Grouping &grouping, bool regroup_now) { +void InternetSearchModel::SetGroupBy(const CollectionModel::Grouping &grouping, bool regroup_now) { const CollectionModel::Grouping old_group_by = group_by_; group_by_ = grouping; if (regroup_now && group_by_ != old_group_by) { // Walk the tree gathering the results we have already - DeezerSearch::ResultList results; + InternetSearch::ResultList results; GatherResults(invisibleRootItem(), &results); // Reset the model and re-add all the results using the new grouping. diff --git a/src/deezer/deezersearchmodel.h b/src/internet/internetsearchmodel.h similarity index 74% rename from src/deezer/deezersearchmodel.h rename to src/internet/internetsearchmodel.h index 6b5ec1924..1a416546a 100644 --- a/src/deezer/deezersearchmodel.h +++ b/src/internet/internetsearchmodel.h @@ -18,8 +18,8 @@ * */ -#ifndef DEEZERSEARCHMODEL_H -#define DEEZERSEARCHMODEL_H +#ifndef INTERNETSEARCHMODEL_H +#define INTERNETSEARCHMODEL_H #include "config.h" @@ -38,13 +38,13 @@ #include #include "collection/collectionmodel.h" -#include "deezersearch.h" +#include "internetsearch.h" -class DeezerSearchModel : public QStandardItemModel { +class InternetSearchModel : public QStandardItemModel { Q_OBJECT public: - DeezerSearchModel(DeezerSearch *engine, QObject *parent = nullptr); + InternetSearchModel(InternetSearch *engine, QObject *parent = nullptr); enum Role { Role_Result = CollectionModel::LastRole, @@ -64,20 +64,20 @@ class DeezerSearchModel : public QStandardItemModel { void Clear(); - DeezerSearch::ResultList GetChildResults(const QModelIndexList &indexes) const; - DeezerSearch::ResultList GetChildResults(const QList &items) const; + InternetSearch::ResultList GetChildResults(const QModelIndexList &indexes) const; + InternetSearch::ResultList GetChildResults(const QList &items) const; QMimeData *mimeData(const QModelIndexList &indexes) const; public slots: - void AddResults(const DeezerSearch::ResultList &results); + void AddResults(const InternetSearch::ResultList &results); private: QStandardItem *BuildContainers(const Song &metadata, QStandardItem *parent, ContainerKey *key, int level = 0); - void GetChildResults(const QStandardItem *item, DeezerSearch::ResultList *results, QSet *visited) const; + void GetChildResults(const QStandardItem *item, InternetSearch::ResultList *results, QSet *visited) const; private: - DeezerSearch *engine_; + InternetSearch *engine_; QSortFilterProxyModel *proxy_; bool use_pretty_covers_; QIcon artist_icon_; @@ -88,11 +88,11 @@ class DeezerSearchModel : public QStandardItemModel { }; -inline uint qHash(const DeezerSearchModel::ContainerKey &key) { +inline uint qHash(const InternetSearchModel::ContainerKey &key) { return qHash(key.provider_index_) ^ qHash(key.group_[0]) ^ qHash(key.group_[1]) ^ qHash(key.group_[2]); } -inline bool operator<(const DeezerSearchModel::ContainerKey &left, const DeezerSearchModel::ContainerKey &right) { +inline bool operator<(const InternetSearchModel::ContainerKey &left, const InternetSearchModel::ContainerKey &right) { #define CMP(field) \ if (left.field < right.field) return true; \ if (left.field > right.field) return false @@ -106,4 +106,4 @@ inline bool operator<(const DeezerSearchModel::ContainerKey &left, const DeezerS #undef CMP } -#endif // DEEZERSEARCHMODEL_H +#endif // INTERNETSEARCHMODEL_H diff --git a/src/deezer/deezersearchsortmodel.cpp b/src/internet/internetsearchsortmodel.cpp similarity index 80% rename from src/deezer/deezersearchsortmodel.cpp rename to src/internet/internetsearchsortmodel.cpp index 8a400db01..fc2f4a3d5 100644 --- a/src/deezer/deezersearchsortmodel.cpp +++ b/src/internet/internetsearchsortmodel.cpp @@ -25,16 +25,16 @@ #include #include "core/logging.h" -#include "deezersearchmodel.h" -#include "deezersearchsortmodel.h" +#include "internetsearchmodel.h" +#include "internetsearchsortmodel.h" -DeezerSearchSortModel::DeezerSearchSortModel(QObject *parent) +InternetSearchSortModel::InternetSearchSortModel(QObject *parent) : QSortFilterProxyModel(parent) {} -bool DeezerSearchSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { +bool InternetSearchSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { // Compare the provider sort index first. - const int index_left = left.data(DeezerSearchModel::Role_ProviderIndex).toInt(); - const int index_right = right.data(DeezerSearchModel::Role_ProviderIndex).toInt(); + const int index_left = left.data(InternetSearchModel::Role_ProviderIndex).toInt(); + const int index_right = right.data(InternetSearchModel::Role_ProviderIndex).toInt(); if (index_left < index_right) return true; if (index_left > index_right) return false; @@ -54,8 +54,8 @@ bool DeezerSearchSortModel::lessThan(const QModelIndex &left, const QModelIndex } // Otherwise we're comparing songs. Sort by disc, track, then title. - const DeezerSearch::Result r1 = left.data(DeezerSearchModel::Role_Result).value(); - const DeezerSearch::Result r2 = right.data(DeezerSearchModel::Role_Result).value(); + const InternetSearch::Result r1 = left.data(InternetSearchModel::Role_Result).value(); + const InternetSearch::Result r2 = right.data(InternetSearchModel::Role_Result).value(); #define CompareInt(field) \ if (r1.metadata_.field() < r2.metadata_.field()) return true; \ diff --git a/src/deezer/deezersearchsortmodel.h b/src/internet/internetsearchsortmodel.h similarity index 80% rename from src/deezer/deezersearchsortmodel.h rename to src/internet/internetsearchsortmodel.h index 437b7b9cb..8f59bbedb 100644 --- a/src/deezer/deezersearchsortmodel.h +++ b/src/internet/internetsearchsortmodel.h @@ -18,18 +18,18 @@ * */ -#ifndef DEEZERSEARCHSORTMODEL_H -#define DEEZERSEARCHSORTMODEL_H +#ifndef INTERNETSEARCHSORTMODEL_H +#define INTERNETSEARCHSORTMODEL_H #include #include -class DeezerSearchSortModel : public QSortFilterProxyModel { +class InternetSearchSortModel : public QSortFilterProxyModel { public: - DeezerSearchSortModel(QObject *parent = nullptr); + InternetSearchSortModel(QObject *parent = nullptr); protected: bool lessThan(const QModelIndex &left, const QModelIndex &right) const; }; -#endif // DEEZERSEARCHSORTMODEL_H +#endif // INTERNETSEARCHSORTMODEL_H diff --git a/src/tidal/tidalsearchview.cpp b/src/internet/internetsearchview.cpp similarity index 77% rename from src/tidal/tidalsearchview.cpp rename to src/internet/internetsearchview.cpp index 0354dcfc6..c31183a71 100644 --- a/src/tidal/tidalsearchview.cpp +++ b/src/internet/internetsearchview.cpp @@ -50,37 +50,37 @@ #include "collection/collectionmodel.h" #include "collection/groupbydialog.h" #include "playlist/songmimedata.h" -#include "tidalsearch.h" -#include "tidalsearchitemdelegate.h" -#include "tidalsearchmodel.h" -#include "tidalsearchsortmodel.h" -#include "tidalsearchview.h" -#include "ui_tidalsearchview.h" -#include "settings/tidalsettingspage.h" +#include "internetsearch.h" +#include "internetsearchitemdelegate.h" +#include "internetsearchmodel.h" +#include "internetsearchsortmodel.h" +#include "internetsearchview.h" +#include "ui_internetsearchview.h" using std::placeholders::_1; using std::placeholders::_2; using std::swap; -const int TidalSearchView::kSwapModelsTimeoutMsec = 250; +const int InternetSearchView::kSwapModelsTimeoutMsec = 250; -TidalSearchView::TidalSearchView(Application *app, QWidget *parent) +InternetSearchView::InternetSearchView(Application *app, InternetSearch *engine, QString settings_group, SettingsDialog::Page settings_page, QWidget *parent) : QWidget(parent), app_(app), - engine_(app_->tidal_search()), - ui_(new Ui_TidalSearchView), + engine_(engine), + settings_group_(settings_group), + settings_page_(settings_page), + ui_(new Ui_InternetSearchView), context_menu_(nullptr), last_search_id_(0), - front_model_(new TidalSearchModel(engine_, this)), - back_model_(new TidalSearchModel(engine_, this)), + front_model_(new InternetSearchModel(engine_, this)), + back_model_(new InternetSearchModel(engine_, this)), current_model_(front_model_), - front_proxy_(new TidalSearchSortModel(this)), - back_proxy_(new TidalSearchSortModel(this)), + front_proxy_(new InternetSearchSortModel(this)), + back_proxy_(new InternetSearchSortModel(this)), current_proxy_(front_proxy_), swap_models_timer_(new QTimer(this)), - search_icon_(IconLoader::Load("search")), - warning_icon_(IconLoader::Load("dialog-warning")), - error_(false) { + error_(false) + { ui_->setupUi(this); ui_->progressbar->hide(); @@ -94,7 +94,7 @@ TidalSearchView::TidalSearchView(Application *app, QWidget *parent) ui_->settings->setIcon(IconLoader::Load("configure")); - // Must be a queued connection to ensure the TidalSearch handles it first. + // Must be a queued connection to ensure the InternetSearch handles it first. connect(app_, SIGNAL(SettingsChanged()), SLOT(ReloadSettings()), Qt::QueuedConnection); connect(ui_->search, SIGNAL(textChanged(QString)), SLOT(TextEdited(QString))); @@ -102,7 +102,7 @@ TidalSearchView::TidalSearchView(Application *app, QWidget *parent) connect(ui_->results, SIGNAL(FocusOnFilterSignal(QKeyEvent*)), SLOT(FocusOnFilter(QKeyEvent*))); // Set the appearance of the results list - ui_->results->setItemDelegate(new TidalSearchItemDelegate(this)); + ui_->results->setItemDelegate(new InternetSearchItemDelegate(this)); ui_->results->setAttribute(Qt::WA_MacShowFocusRect, false); ui_->results->setStyleSheet("QTreeView::item{padding-top:1px;}"); @@ -140,7 +140,7 @@ TidalSearchView::TidalSearchView(Application *app, QWidget *parent) QMenu *settings_menu = new QMenu(this); settings_menu->addActions(group_by_actions_->actions()); settings_menu->addSeparator(); - settings_menu->addAction(IconLoader::Load("configure"), tr("Configure Tidal..."), this, SLOT(OpenSettingsDialog())); + settings_menu->addAction(IconLoader::Load("configure"), QString("Configure %1...").arg(Song::TextForSource(engine->source())), this, SLOT(OpenSettingsDialog())); ui_->settings->setMenu(settings_menu); connect(ui_->radiobutton_searchbyalbums, SIGNAL(clicked(bool)), SLOT(SearchByAlbumsClicked(bool))); @@ -154,7 +154,7 @@ TidalSearchView::TidalSearchView(Application *app, QWidget *parent) connect(engine_, SIGNAL(ProgressSetMaximum(int)), SLOT(ProgressSetMaximum(int)), Qt::QueuedConnection); connect(engine_, SIGNAL(UpdateProgress(int)), SLOT(UpdateProgress(int)), Qt::QueuedConnection); - connect(engine_, SIGNAL(AddResults(int, TidalSearch::ResultList)), SLOT(AddResults(int, TidalSearch::ResultList)), Qt::QueuedConnection); + connect(engine_, SIGNAL(AddResults(int, InternetSearch::ResultList)), SLOT(AddResults(int, InternetSearch::ResultList)), Qt::QueuedConnection); connect(engine_, SIGNAL(SearchError(int, QString)), SLOT(SearchError(int, QString)), Qt::QueuedConnection); connect(engine_, SIGNAL(ArtLoaded(int, QPixmap)), SLOT(ArtLoaded(int, QPixmap)), Qt::QueuedConnection); @@ -162,29 +162,29 @@ TidalSearchView::TidalSearchView(Application *app, QWidget *parent) } -TidalSearchView::~TidalSearchView() { delete ui_; } +InternetSearchView::~InternetSearchView() { delete ui_; } -void TidalSearchView::ReloadSettings() { +void InternetSearchView::ReloadSettings() { QSettings s; // Collection settings - s.beginGroup(TidalSettingsPage::kSettingsGroup); + s.beginGroup(settings_group_); const bool pretty = s.value("pretty_covers", true).toBool(); front_model_->set_use_pretty_covers(pretty); back_model_->set_use_pretty_covers(pretty); s.endGroup(); - // Tidal search settings + // Internet search settings - s.beginGroup(TidalSettingsPage::kSettingsGroup); - searchby_ = TidalSettingsPage::SearchBy(s.value("searchby", int(TidalSettingsPage::SearchBy_Songs)).toInt()); + s.beginGroup(settings_group_); + searchby_ = InternetSearch::SearchBy(s.value("searchby", int(InternetSearch::SearchBy_Songs)).toInt()); switch (searchby_) { - case TidalSettingsPage::SearchBy_Songs: + case InternetSearch::SearchBy_Songs: ui_->radiobutton_searchbysongs->setChecked(true); break; - case TidalSettingsPage::SearchBy_Albums: + case InternetSearch::SearchBy_Albums: ui_->radiobutton_searchbyalbums->setChecked(true); break; } @@ -197,7 +197,7 @@ void TidalSearchView::ReloadSettings() { } -void TidalSearchView::StartSearch(const QString &query) { +void InternetSearchView::StartSearch(const QString &query) { ui_->search->setText(query); TextEdited(query); @@ -208,7 +208,7 @@ void TidalSearchView::StartSearch(const QString &query) { } -void TidalSearchView::TextEdited(const QString &text) { +void InternetSearchView::TextEdited(const QString &text) { const QString trimmed(text.trimmed()); @@ -237,7 +237,7 @@ void TidalSearchView::TextEdited(const QString &text) { } -void TidalSearchView::AddResults(int id, const TidalSearch::ResultList &results) { +void InternetSearchView::AddResults(int id, const InternetSearch::ResultList &results) { if (id != last_search_id_) return; if (results.isEmpty()) return; ui_->label_status->clear(); @@ -246,7 +246,7 @@ void TidalSearchView::AddResults(int id, const TidalSearch::ResultList &results) current_model_->AddResults(results); } -void TidalSearchView::SearchError(const int id, const QString error) { +void InternetSearchView::SearchError(const int id, const QString error) { error_ = true; ui_->label_helptext->setText(error); ui_->label_status->clear(); @@ -255,7 +255,7 @@ void TidalSearchView::SearchError(const int id, const QString error) { ui_->results_stack->setCurrentWidget(ui_->help_page); } -void TidalSearchView::SwapModels() { +void InternetSearchView::SwapModels() { art_requests_.clear(); @@ -273,14 +273,14 @@ void TidalSearchView::SwapModels() { } -void TidalSearchView::LazyLoadArt(const QModelIndex &proxy_index) { +void InternetSearchView::LazyLoadArt(const QModelIndex &proxy_index) { if (!proxy_index.isValid() || proxy_index.model() != front_proxy_) { return; } // Already loading art for this item? - if (proxy_index.data(TidalSearchModel::Role_LazyLoadingArt).isValid()) { + if (proxy_index.data(InternetSearchModel::Role_LazyLoadingArt).isValid()) { return; } @@ -301,7 +301,7 @@ void TidalSearchView::LazyLoadArt(const QModelIndex &proxy_index) { // Mark the item as loading art const QModelIndex source_index = front_proxy_->mapToSource(proxy_index); QStandardItem *item = front_model_->itemFromIndex(source_index); - item->setData(true, TidalSearchModel::Role_LazyLoadingArt); + item->setData(true, InternetSearchModel::Role_LazyLoadingArt); // Walk down the item's children until we find a track while (item->rowCount()) { @@ -309,7 +309,7 @@ void TidalSearchView::LazyLoadArt(const QModelIndex &proxy_index) { } // Get the track's Result - const TidalSearch::Result result = item->data(TidalSearchModel::Role_Result).value(); + const InternetSearch::Result result = item->data(InternetSearchModel::Role_Result).value(); // Load the art. int id = engine_->LoadArtAsync(result); @@ -317,7 +317,7 @@ void TidalSearchView::LazyLoadArt(const QModelIndex &proxy_index) { } -void TidalSearchView::ArtLoaded(int id, const QPixmap &pixmap) { +void InternetSearchView::ArtLoaded(int id, const QPixmap &pixmap) { if (!art_requests_.contains(id)) return; QModelIndex index = art_requests_.take(id); @@ -328,7 +328,7 @@ void TidalSearchView::ArtLoaded(int id, const QPixmap &pixmap) { } -MimeData *TidalSearchView::SelectedMimeData() { +MimeData *InternetSearchView::SelectedMimeData() { if (!ui_->results->selectionModel()) return nullptr; @@ -362,7 +362,7 @@ MimeData *TidalSearchView::SelectedMimeData() { } -bool TidalSearchView::eventFilter(QObject *object, QEvent *event) { +bool InternetSearchView::eventFilter(QObject *object, QEvent *event) { if (object == ui_->search && event->type() == QEvent::KeyRelease) { if (SearchKeyEvent(static_cast(event))) { @@ -379,7 +379,7 @@ bool TidalSearchView::eventFilter(QObject *object, QEvent *event) { } -bool TidalSearchView::SearchKeyEvent(QKeyEvent *event) { +bool InternetSearchView::SearchKeyEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Up: @@ -407,7 +407,7 @@ bool TidalSearchView::SearchKeyEvent(QKeyEvent *event) { } -bool TidalSearchView::ResultsContextMenuEvent(QContextMenuEvent *event) { +bool InternetSearchView::ResultsContextMenuEvent(QContextMenuEvent *event) { context_menu_ = new QMenu(this); context_actions_ << context_menu_->addAction( IconLoader::Load("media-play"), tr("Append to current playlist"), this, SLOT(AddSelectedToPlaylist())); @@ -425,7 +425,7 @@ bool TidalSearchView::ResultsContextMenuEvent(QContextMenuEvent *event) { context_menu_->addSeparator(); context_menu_->addMenu(tr("Group by"))->addActions(group_by_actions_->actions()); - context_menu_->addAction(IconLoader::Load("configure"), tr("Configure Tidal..."), this, SLOT(OpenSettingsDialog())); + context_menu_->addAction(IconLoader::Load("configure"), tr("Configure Internet..."), this, SLOT(OpenSettingsDialog())); const bool enable_context_actions = ui_->results->selectionModel() && ui_->results->selectionModel()->hasSelection(); @@ -439,11 +439,11 @@ bool TidalSearchView::ResultsContextMenuEvent(QContextMenuEvent *event) { } -void TidalSearchView::AddSelectedToPlaylist() { +void InternetSearchView::AddSelectedToPlaylist() { emit AddToPlaylist(SelectedMimeData()); } -void TidalSearchView::LoadSelected() { +void InternetSearchView::LoadSelected() { MimeData *data = SelectedMimeData(); if (!data) return; @@ -451,7 +451,7 @@ void TidalSearchView::LoadSelected() { emit AddToPlaylist(data); } -void TidalSearchView::AddSelectedToPlaylistEnqueue() { +void InternetSearchView::AddSelectedToPlaylistEnqueue() { MimeData *data = SelectedMimeData(); if (!data) return; @@ -459,7 +459,7 @@ void TidalSearchView::AddSelectedToPlaylistEnqueue() { emit AddToPlaylist(data); } -void TidalSearchView::OpenSelectedInNewPlaylist() { +void InternetSearchView::OpenSelectedInNewPlaylist() { MimeData *data = SelectedMimeData(); if (!data) return; @@ -467,34 +467,34 @@ void TidalSearchView::OpenSelectedInNewPlaylist() { emit AddToPlaylist(data); } -void TidalSearchView::SearchForThis() { +void InternetSearchView::SearchForThis() { StartSearch(ui_->results->selectionModel()->selectedRows().first().data().toString()); } -void TidalSearchView::showEvent(QShowEvent *e) { +void InternetSearchView::showEvent(QShowEvent *e) { QWidget::showEvent(e); FocusSearchField(); } -void TidalSearchView::FocusSearchField() { +void InternetSearchView::FocusSearchField() { ui_->search->setFocus(); ui_->search->selectAll(); } -void TidalSearchView::hideEvent(QHideEvent *e) { +void InternetSearchView::hideEvent(QHideEvent *e) { QWidget::hideEvent(e); } -void TidalSearchView::FocusOnFilter(QKeyEvent *event) { +void InternetSearchView::FocusOnFilter(QKeyEvent *event) { ui_->search->setFocus(); QApplication::sendEvent(ui_->search, event); } -void TidalSearchView::OpenSettingsDialog() { - app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Tidal); +void InternetSearchView::OpenSettingsDialog() { + app_->OpenSettingsDialogAtPage(settings_page_); } -void TidalSearchView::GroupByClicked(QAction *action) { +void InternetSearchView::GroupByClicked(QAction *action) { if (action->property("group_by").isNull()) { if (!group_by_dialog_) { @@ -510,11 +510,11 @@ void TidalSearchView::GroupByClicked(QAction *action) { } -void TidalSearchView::SetGroupBy(const CollectionModel::Grouping &g) { +void InternetSearchView::SetGroupBy(const CollectionModel::Grouping &g) { // Clear requests: changing "group by" on the models will cause all the items to be removed/added again, // so all the QModelIndex here will become invalid. New requests will be created for those - // songs when they will be displayed again anyway (when TidalSearchItemDelegate::paint will call LazyLoadArt) + // songs when they will be displayed again anyway (when InternetSearchItemDelegate::paint will call LazyLoadArt) art_requests_.clear(); // Update the models front_model_->SetGroupBy(g, true); @@ -522,7 +522,7 @@ void TidalSearchView::SetGroupBy(const CollectionModel::Grouping &g) { // Save the setting QSettings s; - s.beginGroup(TidalSettingsPage::kSettingsGroup); + s.beginGroup(settings_group_); s.setValue("group_by1", int(g.first)); s.setValue("group_by2", int(g.second)); s.setValue("group_by3", int(g.third)); @@ -543,32 +543,32 @@ void TidalSearchView::SetGroupBy(const CollectionModel::Grouping &g) { } -void TidalSearchView::SearchBySongsClicked(bool checked) { - SetSearchBy(TidalSettingsPage::SearchBy_Songs); +void InternetSearchView::SearchBySongsClicked(bool checked) { + SetSearchBy(InternetSearch::SearchBy_Songs); } -void TidalSearchView::SearchByAlbumsClicked(bool checked) { - SetSearchBy(TidalSettingsPage::SearchBy_Albums); +void InternetSearchView::SearchByAlbumsClicked(bool checked) { + SetSearchBy(InternetSearch::SearchBy_Albums); } -void TidalSearchView::SetSearchBy(TidalSettingsPage::SearchBy searchby) { +void InternetSearchView::SetSearchBy(InternetSearch::SearchBy searchby) { searchby_ = searchby; QSettings s; - s.beginGroup(TidalSettingsPage::kSettingsGroup); + s.beginGroup(settings_group_); s.setValue("searchby", int(searchby)); s.endGroup(); TextEdited(ui_->search->text()); } -void TidalSearchView::UpdateStatus(QString text) { +void InternetSearchView::UpdateStatus(QString text) { ui_->progressbar->show(); ui_->label_status->setText(text); } -void TidalSearchView::ProgressSetMaximum(int max) { +void InternetSearchView::ProgressSetMaximum(int max) { ui_->progressbar->setMaximum(max); } -void TidalSearchView::UpdateProgress(int progress) { +void InternetSearchView::UpdateProgress(int progress) { ui_->progressbar->setValue(progress); } diff --git a/src/tidal/tidalsearchview.h b/src/internet/internetsearchview.h similarity index 79% rename from src/tidal/tidalsearchview.h rename to src/internet/internetsearchview.h index 2341e35de..064d3a8e9 100644 --- a/src/tidal/tidalsearchview.h +++ b/src/internet/internetsearchview.h @@ -19,8 +19,8 @@ * */ -#ifndef TIDALSEARCHVIEW_H -#define TIDALSEARCHVIEW_H +#ifndef INTERNETSEARCHVIEW_H +#define INTERNETSEARCHVIEW_H #include "config.h" @@ -42,20 +42,20 @@ #include "collection/collectionmodel.h" #include "settings/settingsdialog.h" #include "playlist/playlistmanager.h" -#include "tidalsearch.h" -#include "settings/tidalsettingspage.h" +#include "internetsearch.h" +//#include "settings/internetsettingspage.h" class Application; class GroupByDialog; -class TidalSearchModel; -class Ui_TidalSearchView; +class InternetSearchModel; +class Ui_InternetSearchView; -class TidalSearchView : public QWidget { +class InternetSearchView : public QWidget { Q_OBJECT public: - TidalSearchView(Application *app, QWidget *parent = nullptr); - ~TidalSearchView(); + InternetSearchView(Application *app, InternetSearch *engine, QString settings_group, SettingsDialog::Page settings_page, QWidget *parent = nullptr); + ~InternetSearchView(); static const int kSwapModelsTimeoutMsec; @@ -80,7 +80,7 @@ signals: void UpdateStatus(QString text); void ProgressSetMaximum(int progress); void UpdateProgress(int max); - void AddResults(int id, const TidalSearch::ResultList &results); + void AddResults(int id, const InternetSearch::ResultList &results); void SearchError(const int id, const QString error); void ArtLoaded(int id, const QPixmap &pixmap); @@ -96,7 +96,7 @@ signals: void SearchBySongsClicked(bool); void SearchByAlbumsClicked(bool); void GroupByClicked(QAction *action); - void SetSearchBy(TidalSettingsPage::SearchBy searchby); + void SetSearchBy(InternetSearch::SearchBy searchby); void SetGroupBy(const CollectionModel::Grouping &g); private: @@ -106,8 +106,10 @@ signals: bool ResultsContextMenuEvent(QContextMenuEvent *event); Application *app_; - TidalSearch *engine_; - Ui_TidalSearchView *ui_; + InternetSearch *engine_; + QString settings_group_; + SettingsDialog::Page settings_page_; + Ui_InternetSearchView *ui_; QScopedPointer group_by_dialog_; QMenu *context_menu_; @@ -119,9 +121,9 @@ signals: // Like graphics APIs have a front buffer and a back buffer, there's a front model and a back model // The front model is the one that's shown in the UI and the back model is the one that lies in wait. // current_model_ will point to either the front or the back model. - TidalSearchModel *front_model_; - TidalSearchModel *back_model_; - TidalSearchModel *current_model_; + InternetSearchModel *front_model_; + InternetSearchModel *back_model_; + InternetSearchModel *current_model_; QSortFilterProxyModel *front_proxy_; QSortFilterProxyModel *back_proxy_; @@ -131,12 +133,9 @@ signals: QTimer *swap_models_timer_; - QIcon search_icon_; - QIcon warning_icon_; - - TidalSettingsPage::SearchBy searchby_; + InternetSearch::SearchBy searchby_; bool error_; }; -#endif // TIDALSEARCHVIEW_H +#endif // INTERNETSEARCHVIEW_H diff --git a/src/tidal/tidalsearchview.ui b/src/internet/internetsearchview.ui similarity index 98% rename from src/tidal/tidalsearchview.ui rename to src/internet/internetsearchview.ui index b94672f53..3d0bdb85b 100644 --- a/src/tidal/tidalsearchview.ui +++ b/src/internet/internetsearchview.ui @@ -1,7 +1,7 @@ - TidalSearchView - + InternetSearchView + 0 diff --git a/src/internet/internetservice.h b/src/internet/internetservice.h index 71f23a9f2..7ce63a925 100644 --- a/src/internet/internetservice.h +++ b/src/internet/internetservice.h @@ -33,6 +33,7 @@ #include "core/iconloader.h" #include "playlist/playlistitem.h" #include "settings/settingsdialog.h" +#include "internetsearch.h" class Application; class InternetModel; @@ -44,14 +45,16 @@ class InternetService : public QObject { public: InternetService(Song::Source source, const QString &name, const QString &url_scheme, Application *app, InternetModel *model, QObject *parent = nullptr); virtual ~InternetService() {} - Song::Source source() const { return source_; } - QString name() const { return name_; } - QString url_scheme() const { return url_scheme_; } - InternetModel *model() const { return model_; } + virtual Song::Source source() const { return source_; } + virtual QString name() const { return name_; } + virtual QString url_scheme() const { return url_scheme_; } + virtual InternetModel *model() const { return model_; } virtual bool has_initial_load_settings() const { return false; } virtual void InitialLoadSettings() {} virtual void ReloadSettings() {} virtual QIcon Icon() { return Song::IconForSource(source_); } + virtual int Search(const QString &query, InternetSearch::SearchBy searchby) = 0; + virtual void CancelSearch() = 0; public slots: virtual void ShowConfig() {} diff --git a/src/settings/deezersettingspage.h b/src/settings/deezersettingspage.h index ae1618575..19c8c06bc 100644 --- a/src/settings/deezersettingspage.h +++ b/src/settings/deezersettingspage.h @@ -36,11 +36,6 @@ class DeezerSettingsPage : public SettingsPage { explicit DeezerSettingsPage(SettingsDialog* parent = nullptr); ~DeezerSettingsPage(); - enum SearchBy { - SearchBy_Songs = 1, - SearchBy_Albums = 2, - }; - static const char *kSettingsGroup; void Load(); @@ -50,7 +45,6 @@ class DeezerSettingsPage : public SettingsPage { signals: void Login(); - void Login(const QString &username, const QString &password); private slots: void LoginClicked(); diff --git a/src/settings/tidalsettingspage.cpp b/src/settings/tidalsettingspage.cpp index 98429f8a2..f3c08b9b9 100644 --- a/src/settings/tidalsettingspage.cpp +++ b/src/settings/tidalsettingspage.cpp @@ -37,6 +37,7 @@ const char *TidalSettingsPage::kSettingsGroup = "Tidal"; TidalSettingsPage::TidalSettingsPage(SettingsDialog *parent) : SettingsPage(parent), ui_(new Ui::TidalSettingsPage), + //service_(dialog()->app()->internet_model()->Service()) { service_(dialog()->app()->internet_model()->Service()) { ui_->setupUi(this); diff --git a/src/settings/tidalsettingspage.h b/src/settings/tidalsettingspage.h index 9526e03fe..d71ac4abc 100644 --- a/src/settings/tidalsettingspage.h +++ b/src/settings/tidalsettingspage.h @@ -36,11 +36,6 @@ class TidalSettingsPage : public SettingsPage { explicit TidalSettingsPage(SettingsDialog* parent = nullptr); ~TidalSettingsPage(); - enum SearchBy { - SearchBy_Songs = 1, - SearchBy_Albums = 2, - }; - static const char *kSettingsGroup; void Load(); diff --git a/src/tidal/tidalsearchmodel.cpp b/src/tidal/tidalsearchmodel.cpp deleted file mode 100644 index edb62ad58..000000000 --- a/src/tidal/tidalsearchmodel.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2012, David Sansome - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/mimedata.h" -#include "core/iconloader.h" -#include "core/logging.h" -#include "tidalsearch.h" -#include "tidalsearchmodel.h" - -TidalSearchModel::TidalSearchModel(TidalSearch *engine, QObject *parent) - : QStandardItemModel(parent), - engine_(engine), - proxy_(nullptr), - use_pretty_covers_(true), - artist_icon_(IconLoader::Load("folder-sound")) { - - group_by_[0] = CollectionModel::GroupBy_Artist; - group_by_[1] = CollectionModel::GroupBy_Album; - group_by_[2] = CollectionModel::GroupBy_None; - - QIcon nocover = IconLoader::Load("cdcase"); - no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(CollectionModel::kPrettyCoverSize, CollectionModel::kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); - - //no_cover_icon_ = QPixmap(":/pictures/noalbumart.png").scaled(CollectionModel::kPrettyCoverSize, CollectionModel::kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); - album_icon_ = no_cover_icon_; - -} - -void TidalSearchModel::AddResults(const TidalSearch::ResultList &results) { - - int sort_index = 0; - - for (const TidalSearch::Result &result : results) { - QStandardItem *parent = invisibleRootItem(); - - // Find (or create) the container nodes for this result if we can. - ContainerKey key; - key.provider_index_ = sort_index; - parent = BuildContainers(result.metadata_, parent, &key); - - // Create the item - QStandardItem *item = new QStandardItem; - item->setText(result.metadata_.TitleWithCompilationArtist()); - item->setData(QVariant::fromValue(result), Role_Result); - item->setData(sort_index, Role_ProviderIndex); - - parent->appendRow(item); - - } - -} - -QStandardItem *TidalSearchModel::BuildContainers(const Song &s, QStandardItem *parent, ContainerKey *key, int level) { - - if (level >= 3) { - return parent; - } - - bool has_artist_icon = false; - bool has_album_icon = false; - QString display_text; - QString sort_text; - int unique_tag = -1; - int year = 0; - - switch (group_by_[level]) { - case CollectionModel::GroupBy_Artist: - if (s.is_compilation()) { - display_text = tr("Various artists"); - sort_text = "aaaaaa"; - } - else { - display_text = CollectionModel::TextOrUnknown(s.artist()); - sort_text = CollectionModel::SortTextForArtist(s.artist()); - } - has_artist_icon = true; - break; - - case CollectionModel::GroupBy_YearAlbum: - year = qMax(0, s.year()); - display_text = CollectionModel::PrettyYearAlbum(year, s.album()); - sort_text = CollectionModel::SortTextForNumber(year) + s.album(); - unique_tag = s.album_id(); - has_album_icon = true; - break; - - case CollectionModel::GroupBy_OriginalYearAlbum: - year = qMax(0, s.effective_originalyear()); - display_text = CollectionModel::PrettyYearAlbum(year, s.album()); - sort_text = CollectionModel::SortTextForNumber(year) + s.album(); - unique_tag = s.album_id(); - has_album_icon = true; - break; - - case CollectionModel::GroupBy_Year: - year = qMax(0, s.year()); - display_text = QString::number(year); - sort_text = CollectionModel::SortTextForNumber(year) + " "; - break; - - case CollectionModel::GroupBy_OriginalYear: - year = qMax(0, s.effective_originalyear()); - display_text = QString::number(year); - sort_text = CollectionModel::SortTextForNumber(year) + " "; - break; - - case CollectionModel::GroupBy_Composer: - display_text = s.composer(); - case CollectionModel::GroupBy_Performer: - display_text = s.performer(); - case CollectionModel::GroupBy_Disc: - display_text = s.disc(); - case CollectionModel::GroupBy_Grouping: - display_text = s.grouping(); - case CollectionModel::GroupBy_Genre: - if (display_text.isNull()) display_text = s.genre(); - case CollectionModel::GroupBy_Album: - unique_tag = s.album_id(); - if (display_text.isNull()) { - display_text = s.album(); - } - // fallthrough - case CollectionModel::GroupBy_AlbumArtist: - if (display_text.isNull()) display_text = s.effective_albumartist(); - display_text = CollectionModel::TextOrUnknown(display_text); - sort_text = CollectionModel::SortTextForArtist(display_text); - has_album_icon = true; - break; - - case CollectionModel::GroupBy_FileType: - display_text = s.TextForFiletype(); - sort_text = display_text; - break; - - case CollectionModel::GroupBy_Bitrate: - display_text = QString(s.bitrate(), 1); - sort_text = display_text; - break; - - case CollectionModel::GroupBy_Samplerate: - display_text = QString(s.samplerate(), 1); - sort_text = display_text; - break; - - case CollectionModel::GroupBy_Bitdepth: - display_text = QString(s.bitdepth(), 1); - sort_text = display_text; - break; - - case CollectionModel::GroupBy_None: - return parent; - } - - // Find a container for this level - key->group_[level] = display_text + QString::number(unique_tag); - QStandardItem *container = containers_[*key]; - if (!container) { - container = new QStandardItem(display_text); - container->setData(key->provider_index_, Role_ProviderIndex); - container->setData(sort_text, CollectionModel::Role_SortText); - container->setData(group_by_[level], CollectionModel::Role_ContainerType); - - if (has_artist_icon) { - container->setIcon(artist_icon_); - } - else if (has_album_icon) { - if (use_pretty_covers_) { - container->setData(no_cover_icon_, Qt::DecorationRole); - } - else { - container->setIcon(album_icon_); - } - } - - parent->appendRow(container); - containers_[*key] = container; - } - - // Create the container for the next level. - return BuildContainers(s, container, key, level + 1); - -} - -void TidalSearchModel::Clear() { - containers_.clear(); - clear(); -} - -TidalSearch::ResultList TidalSearchModel::GetChildResults(const QModelIndexList &indexes) const { - - QList items; - for (const QModelIndex &index : indexes) { - items << itemFromIndex(index); - } - return GetChildResults(items); - -} - -TidalSearch::ResultList TidalSearchModel::GetChildResults(const QList &items) const { - - TidalSearch::ResultList results; - QSet visited; - - for (QStandardItem *item : items) { - GetChildResults(item, &results, &visited); - } - - return results; - -} - -void TidalSearchModel::GetChildResults(const QStandardItem *item, TidalSearch::ResultList *results, QSet *visited) const { - - if (visited->contains(item)) { - return; - } - visited->insert(item); - - // Does this item have children? - if (item->rowCount()) { - const QModelIndex parent_proxy_index = proxy_->mapFromSource(item->index()); - - // Yes - visit all the children, but do so through the proxy so we get them - // in the right order. - for (int i = 0; i < item->rowCount(); ++i) { - const QModelIndex proxy_index = parent_proxy_index.child(i, 0); - const QModelIndex index = proxy_->mapToSource(proxy_index); - GetChildResults(itemFromIndex(index), results, visited); - } - } - else { - // No - maybe it's a song, add its result if valid - QVariant result = item->data(Role_Result); - if (result.isValid()) { - results->append(result.value()); - } - else { - // Maybe it's a provider then? - bool is_provider; - const int sort_index = item->data(Role_ProviderIndex).toInt(&is_provider); - if (is_provider) { - // Go through all the items (through the proxy to keep them ordered) and add the ones belonging to this provider to our list - for (int i = 0; i < proxy_->rowCount(invisibleRootItem()->index()); ++i) { - QModelIndex child_index = proxy_->index(i, 0, invisibleRootItem()->index()); - const QStandardItem *child_item = itemFromIndex(proxy_->mapToSource(child_index)); - if (child_item->data(Role_ProviderIndex).toInt() == sort_index) { - GetChildResults(child_item, results, visited); - } - } - } - } - } - -} - -QMimeData *TidalSearchModel::mimeData(const QModelIndexList &indexes) const { - return engine_->LoadTracks(GetChildResults(indexes)); -} - -namespace { -void GatherResults(const QStandardItem *parent, TidalSearch::ResultList *results) { - - QVariant result_variant = parent->data(TidalSearchModel::Role_Result); - if (result_variant.isValid()) { - TidalSearch::Result result = result_variant.value(); - (*results).append(result); - } - - for (int i = 0; i < parent->rowCount(); ++i) { - GatherResults(parent->child(i), results); - } -} -} - -void TidalSearchModel::SetGroupBy(const CollectionModel::Grouping &grouping, bool regroup_now) { - - const CollectionModel::Grouping old_group_by = group_by_; - group_by_ = grouping; - - if (regroup_now && group_by_ != old_group_by) { - // Walk the tree gathering the results we have already - TidalSearch::ResultList results; - GatherResults(invisibleRootItem(), &results); - - // Reset the model and re-add all the results using the new grouping. - Clear(); - AddResults(results); - } - -} diff --git a/src/tidal/tidalsearchmodel.h b/src/tidal/tidalsearchmodel.h deleted file mode 100644 index d142516b1..000000000 --- a/src/tidal/tidalsearchmodel.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2012, David Sansome - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#ifndef TIDALSEARCHMODEL_H -#define TIDALSEARCHMODEL_H - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "collection/collectionmodel.h" -#include "tidalsearch.h" - -class TidalSearchModel : public QStandardItemModel { - Q_OBJECT - - public: - TidalSearchModel(TidalSearch *engine, QObject *parent = nullptr); - - enum Role { - Role_Result = CollectionModel::LastRole, - Role_LazyLoadingArt, - Role_ProviderIndex, - LastRole - }; - - struct ContainerKey { - int provider_index_; - QString group_[3]; - }; - - void set_proxy(QSortFilterProxyModel *proxy) { proxy_ = proxy; } - void set_use_pretty_covers(bool pretty) { use_pretty_covers_ = pretty; } - void SetGroupBy(const CollectionModel::Grouping &grouping, bool regroup_now); - - void Clear(); - - TidalSearch::ResultList GetChildResults(const QModelIndexList &indexes) const; - TidalSearch::ResultList GetChildResults(const QList &items) const; - - QMimeData *mimeData(const QModelIndexList &indexes) const; - - public slots: - void AddResults(const TidalSearch::ResultList &results); - - private: - QStandardItem *BuildContainers(const Song &metadata, QStandardItem *parent, ContainerKey *key, int level = 0); - void GetChildResults(const QStandardItem *item, TidalSearch::ResultList *results, QSet *visited) const; - - private: - TidalSearch *engine_; - QSortFilterProxyModel *proxy_; - bool use_pretty_covers_; - QIcon artist_icon_; - QPixmap no_cover_icon_; - QIcon album_icon_; - CollectionModel::Grouping group_by_; - QMap containers_; - -}; - -inline uint qHash(const TidalSearchModel::ContainerKey &key) { - return qHash(key.provider_index_) ^ qHash(key.group_[0]) ^ qHash(key.group_[1]) ^ qHash(key.group_[2]); -} - -inline bool operator<(const TidalSearchModel::ContainerKey &left, const TidalSearchModel::ContainerKey &right) { -#define CMP(field) \ - if (left.field < right.field) return true; \ - if (left.field > right.field) return false - - CMP(provider_index_); - CMP(group_[0]); - CMP(group_[1]); - CMP(group_[2]); - return false; - -#undef CMP -} - -#endif // TIDALSEARCHMODEL_H diff --git a/src/tidal/tidalsearchsortmodel.cpp b/src/tidal/tidalsearchsortmodel.cpp deleted file mode 100644 index f516998d0..000000000 --- a/src/tidal/tidalsearchsortmodel.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2010, David Sansome - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#include "config.h" - -#include -#include -#include - -#include "core/logging.h" -#include "tidalsearchmodel.h" -#include "tidalsearchsortmodel.h" - -TidalSearchSortModel::TidalSearchSortModel(QObject *parent) - : QSortFilterProxyModel(parent) {} - -bool TidalSearchSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { - // Compare the provider sort index first. - const int index_left = left.data(TidalSearchModel::Role_ProviderIndex).toInt(); - const int index_right = right.data(TidalSearchModel::Role_ProviderIndex).toInt(); - if (index_left < index_right) return true; - if (index_left > index_right) return false; - - // Dividers always go first - if (left.data(CollectionModel::Role_IsDivider).toBool()) return true; - if (right.data(CollectionModel::Role_IsDivider).toBool()) return false; - - // Containers go before songs if they're at the same level - const bool left_is_container = left.data(CollectionModel::Role_ContainerType).isValid(); - const bool right_is_container = right.data(CollectionModel::Role_ContainerType).isValid(); - if (left_is_container && !right_is_container) return true; - if (right_is_container && !left_is_container) return false; - - // Containers get sorted on their sort text. - if (left_is_container) { - return QString::localeAwareCompare(left.data(CollectionModel::Role_SortText).toString(), right.data(CollectionModel::Role_SortText).toString()) < 0; - } - - // Otherwise we're comparing songs. Sort by disc, track, then title. - const TidalSearch::Result r1 = left.data(TidalSearchModel::Role_Result).value(); - const TidalSearch::Result r2 = right.data(TidalSearchModel::Role_Result).value(); - -#define CompareInt(field) \ - if (r1.metadata_.field() < r2.metadata_.field()) return true; \ - if (r1.metadata_.field() > r2.metadata_.field()) return false - - int ret = 0; - -#define CompareString(field) \ - ret = QString::localeAwareCompare(r1.metadata_.field(), r2.metadata_.field()); \ - if (ret < 0) return true; \ - if (ret > 0) return false - - CompareInt(disc); - CompareInt(track); - CompareString(title); - - return false; - -#undef CompareInt -#undef CompareString -} diff --git a/src/tidal/tidalsearchsortmodel.h b/src/tidal/tidalsearchsortmodel.h deleted file mode 100644 index 66a6ca9b3..000000000 --- a/src/tidal/tidalsearchsortmodel.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Strawberry Music Player - * This code was part of Clementine (GlobalSearch) - * Copyright 2010, David Sansome - * - * Strawberry is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Strawberry 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Strawberry. If not, see . - * - */ - -#ifndef TIDALSEARCHSORTMODEL_H -#define TIDALSEARCHSORTMODEL_H - -#include -#include - -class TidalSearchSortModel : public QSortFilterProxyModel { - public: - TidalSearchSortModel(QObject *parent = nullptr); - - protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const; -}; - -#endif // TIDALSEARCHSORTMODEL_H diff --git a/src/tidal/tidalservice.cpp b/src/tidal/tidalservice.cpp index 71ef727d7..047a50b45 100644 --- a/src/tidal/tidalservice.cpp +++ b/src/tidal/tidalservice.cpp @@ -50,8 +50,8 @@ #include "core/timeconstants.h" #include "core/utilities.h" #include "internet/internetmodel.h" +#include "internet/internetsearch.h" #include "tidalservice.h" -#include "tidalsearch.h" #include "tidalurlhandler.h" #include "settings/tidalsettingspage.h" @@ -446,7 +446,7 @@ QJsonValue TidalService::ExtractItems(QByteArray &data) { } -int TidalService::Search(const QString &text, TidalSettingsPage::SearchBy searchby) { +int TidalService::Search(const QString &text, InternetSearch::SearchBy searchby) { pending_search_id_ = next_pending_search_id_; pending_search_text_ = text; @@ -506,11 +506,11 @@ void TidalService::SendSearch() { QString searchparam; switch (pending_searchby_) { - case TidalSettingsPage::SearchBy_Songs: + case InternetSearch::SearchBy_Songs: searchparam = "search/tracks"; parameters << Param("limit", QString::number(songssearchlimit_)); break; - case TidalSettingsPage::SearchBy_Albums: + case InternetSearch::SearchBy_Albums: default: searchparam = "search/albums"; parameters << Param("limit", QString::number(albumssearchlimit_)); diff --git a/src/tidal/tidalservice.h b/src/tidal/tidalservice.h index 9c0f15e06..6356112b5 100644 --- a/src/tidal/tidalservice.h +++ b/src/tidal/tidalservice.h @@ -37,7 +37,7 @@ #include "core/song.h" #include "internet/internetmodel.h" #include "internet/internetservice.h" -#include "settings/tidalsettingspage.h" +#include "internet/internetsearch.h" class NetworkAccessManager; class TidalUrlHandler; @@ -54,7 +54,7 @@ class TidalService : public InternetService { void ReloadSettings(); void Logout(); - int Search(const QString &query, TidalSettingsPage::SearchBy searchby); + int Search(const QString &query, InternetSearch::SearchBy searchby); void CancelSearch(); const bool login_sent() { return login_sent_; } @@ -130,7 +130,7 @@ class TidalService : public InternetService { int pending_search_id_; int next_pending_search_id_; QString pending_search_text_; - TidalSettingsPage::SearchBy pending_searchby_; + InternetSearch::SearchBy pending_searchby_; int search_id_; QString search_text_;