From cd062f1d8bef97af76e79cee6f8a53fbc32705f0 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Thu, 11 Mar 2021 18:56:26 +0100 Subject: [PATCH] Added settings page --- src/CMakeLists.txt | 3 + src/internet/core/internetmodel.cpp | 3 +- .../radiobrowser/radiobrowserservice.cpp | 77 +++++++++++------- .../radiobrowser/radiobrowserservice.h | 12 ++- .../radiobrowser/radiobrowsersettingspage.cpp | 78 +++++++++++++++++++ .../radiobrowser/radiobrowsersettingspage.h | 48 ++++++++++++ .../radiobrowser/radiobrowsersettingspage.ui | 63 +++++++++++++++ src/ui/settingsdialog.cpp | 2 + src/ui/settingsdialog.h | 1 + 9 files changed, 253 insertions(+), 34 deletions(-) create mode 100644 src/internet/radiobrowser/radiobrowsersettingspage.cpp create mode 100644 src/internet/radiobrowser/radiobrowsersettingspage.h create mode 100644 src/internet/radiobrowser/radiobrowsersettingspage.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e347ddbe..b7236c71b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -193,6 +193,7 @@ set(SOURCES internet/intergalacticfm/intergalacticfmservice.cpp internet/intergalacticfm/intergalacticfmurlhandler.cpp internet/radiobrowser/radiobrowserservice.cpp + internet/radiobrowser/radiobrowsersettingspage.cpp internet/subsonic/subsonicservice.cpp internet/subsonic/subsonicsettingspage.cpp internet/subsonic/subsonicurlhandler.cpp @@ -510,6 +511,7 @@ set(HEADERS internet/intergalacticfm/intergalacticfmservice.h internet/intergalacticfm/intergalacticfmurlhandler.h internet/radiobrowser/radiobrowserservice.h + internet/radiobrowser/radiobrowsersettingspage.h internet/subsonic/subsonicservice.h internet/subsonic/subsonicsettingspage.h internet/subsonic/subsonicurlhandler.h @@ -718,6 +720,7 @@ set(UI internet/magnatune/magnatunesettingspage.ui internet/core/searchboxwidget.ui internet/subsonic/subsonicsettingspage.ui + internet/radiobrowser/radiobrowsersettingspage.ui library/groupbydialog.ui library/libraryfilterwidget.ui diff --git a/src/internet/core/internetmodel.cpp b/src/internet/core/internetmodel.cpp index 623403e12..4826186fd 100644 --- a/src/internet/core/internetmodel.cpp +++ b/src/internet/core/internetmodel.cpp @@ -333,8 +333,7 @@ QMimeData* InternetModel::mimeData(const QModelIndexList& indexes) const { if (urls.isEmpty()) return nullptr; for (const QModelIndex& index : new_indexes) { - InternetModel::ServiceForIndex(index) - ->ItemNowPlaying(itemFromIndex(index)); + InternetModel::ServiceForIndex(index)->ItemNowPlaying(itemFromIndex(index)); } InternetMimeData* data = new InternetMimeData(this); diff --git a/src/internet/radiobrowser/radiobrowserservice.cpp b/src/internet/radiobrowser/radiobrowserservice.cpp index 0aa1663fa..037346943 100644 --- a/src/internet/radiobrowser/radiobrowserservice.cpp +++ b/src/internet/radiobrowser/radiobrowserservice.cpp @@ -43,8 +43,9 @@ bool operator<(const RadioBrowserService::Stream& a, } const char* RadioBrowserService::kServiceName = "Radio-Browser.info"; -QString RadioBrowserService::SearchUrl = - "%1/json/stations/byname/%2?limit=%3"; +const char* RadioBrowserService::kSettingsGroup = "RadioBrowser"; + +QString RadioBrowserService::SearchUrl = "%1/json/stations/byname/%2?limit=%3"; QString RadioBrowserService::PlayClickUrl = "%1/json/url/%2"; QList RadioBrowserService::BranchList = { @@ -72,10 +73,8 @@ RadioBrowserService::RadioBrowserService(Application* app, context_menu_(nullptr), network_(new NetworkAccessManager(this)), name_(kServiceName), - main_server_url_(QStringLiteral("http://all.api.radio-browser.info")), homepage_url_(QUrl("https://www.radio-browser.info")), icon_(IconLoader::Load("radiobrowser", IconLoader::Provider)) { - ReloadSettings(); app_->global_search()->AddProvider( new RadioBrowserSearchProvider(app_, this, this)); } @@ -108,6 +107,11 @@ void RadioBrowserService::LazyPopulate(QStandardItem* item) { } void RadioBrowserService::RefreshRootItem() { + if (!EnsureServerConfig()) { + ShowConfig(); + return; + } + if (root_->hasChildren()) root_->removeRows(0, root_->rowCount()); for (auto branch : RadioBrowserService::BranchList) { QStandardItem* item = new QStandardItem( @@ -178,15 +182,17 @@ void RadioBrowserService::ShowContextMenu(const QPoint& global_pos) { context_menu_->addAction(IconLoader::Load("view-refresh", IconLoader::Base), tr("Refresh channels"), this, - SLOT(LazyPopulate(item))); + SLOT(ReloadSettings())); + context_menu_->addAction(IconLoader::Load("configure", IconLoader::Base), + tr("Configure..."), this, SLOT(ShowConfig())); } context_menu_->popup(global_pos); } void RadioBrowserService::RefreshCategoryFinished(QNetworkReply* reply, - int task_id, - QStandardItem* item) { + int task_id, + QStandardItem* item) { app_->task_manager()->SetTaskFinished(task_id); reply->deleteLater(); QJsonDocument document = ParseJsonReply(reply); @@ -203,8 +209,8 @@ void RadioBrowserService::RefreshCategoryFinished(QNetworkReply* reply, } void RadioBrowserService::RefreshStreamsFinished(QNetworkReply* reply, - int task_id, - QStandardItem* item) { + int task_id, + QStandardItem* item) { app_->task_manager()->SetTaskFinished(task_id); reply->deleteLater(); QJsonDocument document = ParseJsonReply(reply); @@ -255,7 +261,7 @@ PlaylistItem::Options RadioBrowserService::playlistitem_options() const { } void RadioBrowserService::PopulateCategory(QStandardItem* parentItem, - QStringList& elements) { + QStringList& elements) { if (parentItem->hasChildren()) parentItem->removeRows(0, parentItem->rowCount()); @@ -271,7 +277,7 @@ void RadioBrowserService::PopulateCategory(QStandardItem* parentItem, } void RadioBrowserService::PopulateStreams(QStandardItem* parentItem, - StreamList& streams) { + StreamList& streams) { if (parentItem->hasChildren()) parentItem->removeRows(0, parentItem->rowCount()); @@ -283,8 +289,7 @@ void RadioBrowserService::PopulateStreams(QStandardItem* parentItem, InternetModel::Role_SongMetadata); item->setData(InternetModel::PlayBehaviour_SingleItem, InternetModel::Role_PlayBehaviour); - item->setData(stream.uuid_, - RadioBrowserService::Role_StationUuid); + item->setData(stream.uuid_, RadioBrowserService::Role_StationUuid); parentItem->appendRow(item); } @@ -296,19 +301,38 @@ QDataStream& operator<<(QDataStream& out, return out; } -QDataStream& operator>>(QDataStream& in, - RadioBrowserService::Stream& stream) { +QDataStream& operator>>(QDataStream& in, RadioBrowserService::Stream& stream) { in >> stream.name_ >> stream.url_; return in; } -void RadioBrowserService::ReloadSettings() {} +void RadioBrowserService::ReloadSettings() { + QSettings s; + s.beginGroup(kSettingsGroup); + + main_server_url_ = s.value("server").toString(); + + if (root_ && root_->hasChildren()) { + root_->removeRows(0, root_->rowCount()); + root_->setData(true, InternetModel::Role_CanLazyLoad); + } +} + +bool RadioBrowserService::EnsureServerConfig() { + if (main_server_url_.isEmpty()) + return false; + else + return true; +} + +void RadioBrowserService::ShowConfig() { + app_->OpenSettingsDialogAtPage(SettingsDialog::Page_RadioBrowser); +} void RadioBrowserService::Search(int search_id, const QString& query, - const int limit) { + const int limit) { QString determinedUrl = - RadioBrowserService::SearchUrl.arg(main_server_url_, query) - .arg(limit); + RadioBrowserService::SearchUrl.arg(main_server_url_, query).arg(limit); QUrl url(determinedUrl); QNetworkReply* reply = network_->get(QNetworkRequest(url)); @@ -320,8 +344,7 @@ void RadioBrowserService::Search(int search_id, const QString& query, } void RadioBrowserService::SearchFinishedInternal(QNetworkReply* reply, - int task_id, - int search_id) { + int task_id, int search_id) { app_->task_manager()->SetTaskFinished(task_id); reply->deleteLater(); QJsonDocument document = ParseJsonReply(reply); @@ -338,9 +361,9 @@ void RadioBrowserService::SearchFinishedInternal(QNetworkReply* reply, } void RadioBrowserService::ItemNowPlaying(QStandardItem* item) { - QString station_uuid = item->data(RadioBrowserService::Role_StationUuid).toString(); - if(station_uuid.isEmpty()) - return; + QString station_uuid = + item->data(RadioBrowserService::Role_StationUuid).toString(); + if (station_uuid.isEmpty()) return; QString determinedUrl = RadioBrowserService::PlayClickUrl.arg(main_server_url_, station_uuid); @@ -348,8 +371,6 @@ void RadioBrowserService::ItemNowPlaying(QStandardItem* item) { qLog(Debug) << "RadioBrowser station played:" << determinedUrl; QNetworkReply* reply = network_->get(QNetworkRequest(url)); - connect(reply, &QNetworkReply::finished, [this, reply]() - { - reply->deleteLater(); - }); + connect(reply, &QNetworkReply::finished, + [this, reply]() { reply->deleteLater(); }); } \ No newline at end of file diff --git a/src/internet/radiobrowser/radiobrowserservice.h b/src/internet/radiobrowser/radiobrowserservice.h index 339d5335e..c2dd34cbb 100644 --- a/src/internet/radiobrowser/radiobrowserservice.h +++ b/src/internet/radiobrowser/radiobrowserservice.h @@ -76,6 +76,7 @@ class RadioBrowserService : public InternetService { typedef QList StreamList; static const char* kServiceName; + static const char* kSettingsGroup; const QIcon& icon() const { return icon_; } @@ -84,13 +85,14 @@ class RadioBrowserService : public InternetService { PlaylistItem::Options playlistitem_options() const; - void ReloadSettings(); void Search(int search_id, const QString& query, const int limit); void ItemNowPlaying(QStandardItem* item) override; signals: - void SearchFinished(int search_id, - RadioBrowserService::StreamList streams); + void SearchFinished(int search_id, RadioBrowserService::StreamList streams); + + public slots: + void ReloadSettings(); private slots: void LazyPopulate(QStandardItem* item); @@ -107,11 +109,13 @@ class RadioBrowserService : public InternetService { void SearchFinishedInternal(QNetworkReply* reply, int task_id, int search_id); void Homepage(); + void ShowConfig(); private: void ReadStation(QJsonObject& value, StreamList* ret); void PopulateCategory(QStandardItem* parentItem, QStringList& elements); void PopulateStreams(QStandardItem* parentItem, StreamList& streams); + bool EnsureServerConfig(); private: QStandardItem* root_; @@ -120,7 +124,7 @@ class RadioBrowserService : public InternetService { QNetworkAccessManager* network_; const QString name_; - const QString main_server_url_; + QString main_server_url_; const QUrl homepage_url_; const QIcon icon_; }; diff --git a/src/internet/radiobrowser/radiobrowsersettingspage.cpp b/src/internet/radiobrowser/radiobrowsersettingspage.cpp new file mode 100644 index 000000000..aeded75df --- /dev/null +++ b/src/internet/radiobrowser/radiobrowsersettingspage.cpp @@ -0,0 +1,78 @@ +/* This file is part of Clementine. + Copyright 2021, Fabio Bas + + Clementine 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. + + Clementine 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 Clementine. If not, see . +*/ + +#include "radiobrowsersettingspage.h" + +#include + +#include "core/logging.h" +#include "internet/core/internetmodel.h" +#include "ui/iconloader.h" +#include "ui_radiobrowsersettingspage.h" + +const QString RadioBrowserSettingsPage::defaultServer_ = + QStringLiteral("http://all.api.radio-browser.info"); + +RadioBrowserSettingsPage::RadioBrowserSettingsPage(SettingsDialog* dialog) + : SettingsPage(dialog), + ui_(new Ui_RadioBrowserSettingsPage), + service_(InternetModel::Service()) { + ui_->setupUi(this); + setWindowIcon(IconLoader::Load("radiobrowser", IconLoader::Provider)); + + connect(ui_->server, SIGNAL(editingFinished()), + SLOT(ServerEditingFinished())); + connect(ui_->restoreButton, SIGNAL(clicked()), this, + SLOT(RestoreDefaultServer())); +} + +RadioBrowserSettingsPage::~RadioBrowserSettingsPage() { delete ui_; } + +void RadioBrowserSettingsPage::Load() { + QSettings s; + s.beginGroup(RadioBrowserService::kSettingsGroup); + + ui_->server->setText( + s.value("server", RadioBrowserSettingsPage::defaultServer_).toString()); +} + +void RadioBrowserSettingsPage::Save() { + QSettings s; + s.beginGroup(RadioBrowserService::kSettingsGroup); + + s.setValue("server", ui_->server->text()); +} + +void RadioBrowserSettingsPage::ServerEditingFinished() { + QString input = ui_->server->text(); + QUrl url = QUrl::fromUserInput(input); + + // Veto things that don't get guessed as an HTTP URL, the result will be + // unhelpful + if (!url.scheme().startsWith("http")) { + return; + } + + ui_->server->setText(url.toString()); + qLog(Debug) << "URL fixed:" << input << "to" << url; + service_->ReloadSettings(); +} + +void RadioBrowserSettingsPage::RestoreDefaultServer() { + ui_->server->setText(RadioBrowserSettingsPage::defaultServer_); + service_->ReloadSettings(); +} \ No newline at end of file diff --git a/src/internet/radiobrowser/radiobrowsersettingspage.h b/src/internet/radiobrowser/radiobrowsersettingspage.h new file mode 100644 index 000000000..ab7e4d868 --- /dev/null +++ b/src/internet/radiobrowser/radiobrowsersettingspage.h @@ -0,0 +1,48 @@ +/* This file is part of Clementine. + Copyright 2021, Fabio Bas + + Clementine 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. + + Clementine 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 Clementine. If not, see . +*/ + +#ifndef INTERNET_RADIOBROWSER_RADIOBROWSERSETTINGSPAGE_H_ +#define INTERNET_RADIOBROWSER_RADIOBROWSERSETTINGSPAGE_H_ + +#include "radiobrowserservice.h" +#include "ui/settingspage.h" + +class Ui_RadioBrowserSettingsPage; + +class RadioBrowserSettingsPage : public SettingsPage { + Q_OBJECT + + public: + static const QString defaultServer_; + + public: + explicit RadioBrowserSettingsPage(SettingsDialog* dialog); + ~RadioBrowserSettingsPage(); + + void Load(); + void Save(); + + private slots: + void ServerEditingFinished(); + void RestoreDefaultServer(); + + private: + Ui_RadioBrowserSettingsPage* ui_; + RadioBrowserService* service_; +}; + +#endif // INTERNET_RADIOBROWSER_RADIOBROWSERSETTINGSPAGE_H_ diff --git a/src/internet/radiobrowser/radiobrowsersettingspage.ui b/src/internet/radiobrowser/radiobrowsersettingspage.ui new file mode 100644 index 000000000..6843c752a --- /dev/null +++ b/src/internet/radiobrowser/radiobrowsersettingspage.ui @@ -0,0 +1,63 @@ + + + RadioBrowserSettingsPage + + + + 0 + 0 + 607 + 282 + + + + RadioBrowser + + + + + + Server details + + + + + + Server URL + + + + + + + + + + Restore Default Server + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + server + + + + diff --git a/src/ui/settingsdialog.cpp b/src/ui/settingsdialog.cpp index 88870c9bd..a47d79720 100644 --- a/src/ui/settingsdialog.cpp +++ b/src/ui/settingsdialog.cpp @@ -35,6 +35,7 @@ #include "internet/digitally/digitallyimportedsettingspage.h" #include "internet/magnatune/magnatunesettingspage.h" #include "internet/podcasts/podcastsettingspage.h" +#include "internet/radiobrowser/radiobrowsersettingspage.h" #include "internet/subsonic/subsonicsettingspage.h" #include "library/librarysettingspage.h" #include "mainwindow.h" @@ -197,6 +198,7 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams, providers); AddPage(Page_Subsonic, new SubsonicSettingsPage(this), providers); AddPage(Page_Podcasts, new PodcastSettingsPage(this), providers); + AddPage(Page_RadioBrowser, new RadioBrowserSettingsPage(this), providers); providers->sortChildren(0, Qt::AscendingOrder); diff --git a/src/ui/settingsdialog.h b/src/ui/settingsdialog.h index 427944a20..6aa2e7b6f 100644 --- a/src/ui/settingsdialog.h +++ b/src/ui/settingsdialog.h @@ -86,6 +86,7 @@ class SettingsDialog : public QDialog { Page_Seafile, Page_InternetShow, Page_AmazonCloudDrive, + Page_RadioBrowser, }; enum Role { Role_IsSeparator = Qt::UserRole };