Add a Podcasts settings page and the start of some gpodder.net syncing
This commit is contained in:
parent
b9e08bbfe6
commit
1abf059d16
|
@ -233,6 +233,7 @@ set(SOURCES
|
|||
podcasts/addpodcastpage.cpp
|
||||
podcasts/fixedopmlpage.cpp
|
||||
podcasts/gpoddersearchpage.cpp
|
||||
podcasts/gpoddersync.cpp
|
||||
podcasts/gpoddertoptagsmodel.cpp
|
||||
podcasts/gpoddertoptagspage.cpp
|
||||
podcasts/itunessearchpage.cpp
|
||||
|
@ -242,6 +243,7 @@ set(SOURCES
|
|||
podcasts/podcastepisode.cpp
|
||||
podcasts/podcastinfowidget.cpp
|
||||
podcasts/podcastservice.cpp
|
||||
podcasts/podcastsettingspage.cpp
|
||||
podcasts/podcastparser.cpp
|
||||
podcasts/podcastupdater.cpp
|
||||
podcasts/podcasturlloader.cpp
|
||||
|
@ -341,7 +343,6 @@ set(SOURCES
|
|||
widgets/ratingwidget.cpp
|
||||
widgets/renametablineedit.cpp
|
||||
widgets/sliderwidget.cpp
|
||||
widgets/spinbox.cpp
|
||||
widgets/stickyslider.cpp
|
||||
widgets/stretchheaderview.cpp
|
||||
widgets/stylehelper.cpp
|
||||
|
@ -487,6 +488,7 @@ set(HEADERS
|
|||
podcasts/addpodcastpage.h
|
||||
podcasts/fixedopmlpage.h
|
||||
podcasts/gpoddersearchpage.h
|
||||
podcasts/gpoddersync.h
|
||||
podcasts/gpoddertoptagsmodel.h
|
||||
podcasts/gpoddertoptagspage.h
|
||||
podcasts/itunessearchpage.h
|
||||
|
@ -494,6 +496,7 @@ set(HEADERS
|
|||
podcasts/podcastdiscoverymodel.h
|
||||
podcasts/podcastinfowidget.h
|
||||
podcasts/podcastservice.h
|
||||
podcasts/podcastsettingspage.h
|
||||
podcasts/podcastupdater.h
|
||||
podcasts/podcasturlloader.h
|
||||
|
||||
|
@ -580,7 +583,6 @@ set(HEADERS
|
|||
widgets/ratingwidget.h
|
||||
widgets/renametablineedit.h
|
||||
widgets/sliderwidget.h
|
||||
widgets/spinbox.h
|
||||
widgets/stickyslider.h
|
||||
widgets/stretchheaderview.h
|
||||
widgets/trackslider.h
|
||||
|
@ -620,6 +622,7 @@ set(UI
|
|||
podcasts/gpoddersearchpage.ui
|
||||
podcasts/itunessearchpage.ui
|
||||
podcasts/podcastinfowidget.ui
|
||||
podcasts/podcastsettingspage.ui
|
||||
|
||||
remote/remotesettingspage.ui
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "library/librarybackend.h"
|
||||
#include "playlist/playlistbackend.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "podcasts/gpoddersync.h"
|
||||
#include "podcasts/podcastbackend.h"
|
||||
#include "podcasts/podcastupdater.h"
|
||||
|
||||
|
@ -51,7 +52,8 @@ Application::Application(QObject* parent)
|
|||
internet_model_(NULL),
|
||||
library_(NULL),
|
||||
device_manager_(NULL),
|
||||
podcast_updater_(NULL)
|
||||
podcast_updater_(NULL),
|
||||
gpodder_sync_(NULL)
|
||||
{
|
||||
tag_reader_client_ = new TagReaderClient(this);
|
||||
MoveToNewThread(tag_reader_client_);
|
||||
|
@ -80,7 +82,7 @@ Application::Application(QObject* parent)
|
|||
library_ = new Library(this, this);
|
||||
device_manager_ = new DeviceManager(this, this);
|
||||
podcast_updater_ = new PodcastUpdater(this, this);
|
||||
|
||||
gpodder_sync_ = new GPodderSync(this, this);
|
||||
|
||||
library_->Init();
|
||||
library_->StartThreads();
|
||||
|
|
|
@ -27,6 +27,7 @@ class CurrentArtLoader;
|
|||
class Database;
|
||||
class DeviceManager;
|
||||
class GlobalSearch;
|
||||
class GPodderSync;
|
||||
class InternetModel;
|
||||
class Library;
|
||||
class LibraryBackend;
|
||||
|
@ -63,6 +64,7 @@ public:
|
|||
Library* library() const { return library_; }
|
||||
DeviceManager* device_manager() const { return device_manager_; }
|
||||
PodcastUpdater* podcast_updater() const { return podcast_updater_; }
|
||||
GPodderSync* gpodder_sync() const { return gpodder_sync_; }
|
||||
|
||||
LibraryBackend* library_backend() const;
|
||||
LibraryModel* library_model() const;
|
||||
|
@ -95,6 +97,7 @@ private:
|
|||
Library* library_;
|
||||
DeviceManager* device_manager_;
|
||||
PodcastUpdater* podcast_updater_;
|
||||
GPodderSync* gpodder_sync_;
|
||||
|
||||
QList<QObject*> objects_in_threads_;
|
||||
QList<QThread*> threads_;
|
||||
|
|
|
@ -480,6 +480,26 @@ int GetThreadId() {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool IsLaptop() {
|
||||
#ifdef Q_OS_WIN
|
||||
LPSYSTEM_POWER_STATUS status;
|
||||
if (!GetSystemPowerStatus(&status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(status.BatteryFlag & 128); // 128 = no system battery
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
return !QDir("/proc/acpi/battery").entryList(QDir::Dirs | QDir::NoDotAndDotDot).isEmpty();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
Q_ASSERT("Fixit John" == 0);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Utilities
|
||||
|
||||
|
||||
|
|
|
@ -130,6 +130,9 @@ namespace Utilities {
|
|||
|
||||
int SetThreadIOPriority(IoPriority priority);
|
||||
int GetThreadId();
|
||||
|
||||
// Returns true if this machine has a battery.
|
||||
bool IsLaptop();
|
||||
}
|
||||
|
||||
class ScopedWCharArray {
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gpoddersync.h"
|
||||
#include "core/application.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/network.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include <ApiRequest.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QHostInfo>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QSettings>
|
||||
|
||||
const char* GPodderSync::kSettingsGroup = "Podcasts";
|
||||
|
||||
GPodderSync::GPodderSync(Application* app, QObject* parent)
|
||||
: QObject(parent),
|
||||
app_(app),
|
||||
network_(new NetworkAccessManager(this))
|
||||
{
|
||||
ReloadSettings();
|
||||
connect(app_, SIGNAL(SettingsChanged()), SLOT(ReloadSettings()));
|
||||
}
|
||||
|
||||
GPodderSync::~GPodderSync() {
|
||||
}
|
||||
|
||||
QString GPodderSync::DeviceId() {
|
||||
return QString("%1-%2").arg(qApp->applicationName(),
|
||||
QHostInfo::localHostName()).toLower();
|
||||
}
|
||||
|
||||
QString GPodderSync::DefaultDeviceName() {
|
||||
return tr("%1 on %2").arg(qApp->applicationName(),
|
||||
QHostInfo::localHostName());
|
||||
}
|
||||
|
||||
bool GPodderSync::is_logged_in() const {
|
||||
return !username_.isEmpty() && !password_.isEmpty() && api_;
|
||||
}
|
||||
|
||||
void GPodderSync::ReloadSettings() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
username_ = s.value("gpodder_username").toString();
|
||||
password_ = s.value("gpodder_password").toString();
|
||||
|
||||
if (!username_.isEmpty() && !password_.isEmpty()) {
|
||||
api_.reset(new mygpo::ApiRequest(username_, password_, network_));
|
||||
}
|
||||
}
|
||||
|
||||
QNetworkReply* GPodderSync::Login(const QString& username, const QString& password,
|
||||
const QString& device_name) {
|
||||
api_.reset(new mygpo::ApiRequest(username, password, network_));
|
||||
|
||||
QNetworkReply* reply = api_->renameDevice(
|
||||
username, DeviceId(), device_name,
|
||||
Utilities::IsLaptop() ? mygpo::Device::LAPTOP
|
||||
: mygpo::Device::DESKTOP);
|
||||
NewClosure(reply, SIGNAL(finished()),
|
||||
this, SLOT(LoginFinished(QNetworkReply*,QString,QString)),
|
||||
reply, username, password);
|
||||
return reply;
|
||||
}
|
||||
|
||||
void GPodderSync::LoginFinished(QNetworkReply* reply,
|
||||
const QString& username, const QString& password) {
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
username_ = username;
|
||||
password_ = password;
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("gpodder_username", username);
|
||||
s.setValue("gpodder_password", password);
|
||||
} else {
|
||||
api_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void GPodderSync::Logout() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.remove("gpodder_username");
|
||||
s.remove("gpodder_password");
|
||||
|
||||
api_.reset();
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPODDERSYNC_H
|
||||
#define GPODDERSYNC_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QScopedPointer>
|
||||
|
||||
class Application;
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
|
||||
namespace mygpo {
|
||||
class ApiRequest;
|
||||
}
|
||||
|
||||
class GPodderSync : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GPodderSync(Application* app, QObject* parent = 0);
|
||||
~GPodderSync();
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
static QString DefaultDeviceName();
|
||||
static QString DeviceId();
|
||||
|
||||
bool is_logged_in() const;
|
||||
|
||||
// Tries to login using the given username and password. Also sets the
|
||||
// device name and type on gpodder.net. You do NOT need to deleteLater()
|
||||
// the QNetworkReply returned from this function.
|
||||
// If login succeeds the username and password will be saved in QSettings.
|
||||
QNetworkReply* Login(const QString& username, const QString& password,
|
||||
const QString& device_name);
|
||||
|
||||
// Clears any saved username and password from QSettings.
|
||||
void Logout();
|
||||
|
||||
private slots:
|
||||
void ReloadSettings();
|
||||
void LoginFinished(QNetworkReply* reply,
|
||||
const QString& username, const QString& password);
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
QNetworkAccessManager* network_;
|
||||
QScopedPointer<mygpo::ApiRequest> api_;
|
||||
|
||||
QString username_;
|
||||
QString password_;
|
||||
};
|
||||
|
||||
#endif // GPODDERSYNC_H
|
|
@ -0,0 +1,107 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gpoddersync.h"
|
||||
#include "podcastsettingspage.h"
|
||||
#include "ui_podcastsettingspage.h"
|
||||
#include "core/application.h"
|
||||
#include "core/closure.h"
|
||||
#include "ui/settingsdialog.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QSettings>
|
||||
|
||||
const char* PodcastSettingsPage::kSettingsGroup = "Podcasts";
|
||||
|
||||
PodcastSettingsPage::PodcastSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog),
|
||||
ui_(new Ui_PodcastSettingsPage)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
connect(ui_->login, SIGNAL(clicked()), SLOT(LoginClicked()));
|
||||
connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(LoginClicked()));
|
||||
connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(LogoutClicked()));
|
||||
|
||||
ui_->login_state->AddCredentialField(ui_->username);
|
||||
ui_->login_state->AddCredentialField(ui_->password);
|
||||
ui_->login_state->AddCredentialField(ui_->device_name);
|
||||
ui_->login_state->AddCredentialGroup(ui_->login_group);
|
||||
|
||||
ui_->check_interval->setItemData(0, 0); // manually
|
||||
ui_->check_interval->setItemData(1, 10*60); // 10 minutes
|
||||
ui_->check_interval->setItemData(2, 20*60); // 20 minutes
|
||||
ui_->check_interval->setItemData(3, 30*60); // 30 minutes
|
||||
ui_->check_interval->setItemData(4, 60*60); // 1 hour
|
||||
ui_->check_interval->setItemData(5, 2*60*60); // 2 hours
|
||||
ui_->check_interval->setItemData(6, 6*60*60); // 6 hours
|
||||
ui_->check_interval->setItemData(7, 12*60*60); // 12 hours
|
||||
}
|
||||
|
||||
PodcastSettingsPage::~PodcastSettingsPage() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void PodcastSettingsPage::Load() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
const int update_interval = s.value("update_interval_secs", 0).toInt();
|
||||
ui_->check_interval->setCurrentIndex(ui_->check_interval->findData(update_interval));
|
||||
|
||||
ui_->auto_download->setChecked(s.value("auto_download", false).toBool());
|
||||
ui_->delete_after->setValue(s.value("delete_after", 0).toInt() / (24*60*60));
|
||||
ui_->delete_unplayed->setChecked(s.value("delete_unplayed", false).toBool());
|
||||
ui_->username->setText(s.value("gpodder_username").toString());
|
||||
|
||||
ui_->device_name->setText(s.value("gpodder_device_name", GPodderSync::DefaultDeviceName()).toString());
|
||||
}
|
||||
|
||||
void PodcastSettingsPage::Save() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
s.setValue("update_interval_secs",
|
||||
ui_->check_interval->itemData(ui_->check_interval->currentIndex()));
|
||||
s.setValue("auto_download", ui_->auto_download->isChecked());
|
||||
s.setValue("delete_after", ui_->delete_after->value());
|
||||
s.setValue("delete_unplayed", ui_->delete_unplayed->isChecked());
|
||||
s.setValue("gpodder_device_name", ui_->device_name->text());
|
||||
}
|
||||
|
||||
void PodcastSettingsPage::LoginClicked() {
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||
|
||||
QNetworkReply* reply = dialog()->app()->gpodder_sync()->Login(
|
||||
ui_->username->text(), ui_->password->text(), ui_->device_name->text());
|
||||
|
||||
NewClosure(reply, SIGNAL(finished()),
|
||||
this, SLOT(LoginFinished(QNetworkReply*)),
|
||||
reply);
|
||||
}
|
||||
|
||||
void PodcastSettingsPage::LoginFinished(QNetworkReply* reply) {
|
||||
const bool success = reply->error() == QNetworkReply::NoError;
|
||||
ui_->login_state->SetLoggedIn(success ? LoginStateWidget::LoggedIn
|
||||
: LoginStateWidget::LoggedOut,
|
||||
ui_->username->text());
|
||||
}
|
||||
|
||||
void PodcastSettingsPage::LogoutClicked() {
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoggedOut);
|
||||
ui_->password->clear();
|
||||
dialog()->app()->gpodder_sync()->Logout();
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PODCASTSETTINGSPAGE_H
|
||||
#define PODCASTSETTINGSPAGE_H
|
||||
|
||||
#include "ui/settingspage.h"
|
||||
|
||||
class Ui_PodcastSettingsPage;
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
class PodcastSettingsPage : public SettingsPage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PodcastSettingsPage(SettingsDialog* dialog);
|
||||
~PodcastSettingsPage();
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private slots:
|
||||
void LoginClicked();
|
||||
void LoginFinished(QNetworkReply* reply);
|
||||
void LogoutClicked();
|
||||
|
||||
private:
|
||||
Ui_PodcastSettingsPage* ui_;
|
||||
};
|
||||
|
||||
#endif // PODCASTSETTINGSPAGE_H
|
|
@ -0,0 +1,237 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PodcastSettingsPage</class>
|
||||
<widget class="QWidget" name="PodcastSettingsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>616</width>
|
||||
<height>656</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Podcasts</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Updating</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Check for new episodes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="check_interval">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Manually</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every 10 minutes</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every 20 minutes</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every 30 minutes</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every hour</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every 2 hours</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every 6 hours</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Every 12 hours</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="auto_download">
|
||||
<property name="text">
|
||||
<string>Download new episodes automatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Cleaning up</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Delete played episodes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="delete_after">
|
||||
<property name="specialValueText">
|
||||
<string>manually</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> days</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>after </string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="empty_text" stdset="0">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="delete_unplayed">
|
||||
<property name="text">
|
||||
<string>Also delete unplayed episodes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>gpodder.net</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Clementine can synchronize your subscription list with your other computers and podcast applications. <a href="https://gpodder.net/register/">Create an account</a></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="login_group" native="true">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="login">
|
||||
<property name="text">
|
||||
<string>Sign in</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Device name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="device_name"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>217</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LoginStateWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/loginstatewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>check_interval</tabstop>
|
||||
<tabstop>auto_download</tabstop>
|
||||
<tabstop>delete_after</tabstop>
|
||||
<tabstop>delete_unplayed</tabstop>
|
||||
<tabstop>username</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
<tabstop>device_name</tabstop>
|
||||
<tabstop>login</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1901,13 +1901,9 @@ void MainWindow::EnsureSettingsDialogCreated() {
|
|||
if (settings_dialog_)
|
||||
return;
|
||||
|
||||
settings_dialog_.reset(new SettingsDialog(background_streams_));
|
||||
settings_dialog_->SetLibraryDirectoryModel(app_->library_model()->directory_model());
|
||||
settings_dialog_->SetGstEngine(qobject_cast<GstEngine*>(app_->player()->engine()));
|
||||
settings_dialog_.reset(new SettingsDialog(app_, background_streams_));
|
||||
settings_dialog_->SetGlobalShortcutManager(global_shortcuts_);
|
||||
settings_dialog_->SetGlobalSearch(app_->global_search());
|
||||
settings_dialog_->SetSongInfoView(song_info_view_);
|
||||
settings_dialog_->SetAppearance(app_->appearance());
|
||||
|
||||
// Settings
|
||||
connect(settings_dialog_.get(), SIGNAL(accepted()), SLOT(ReloadAllSettings()));
|
||||
|
|
|
@ -26,9 +26,11 @@
|
|||
#include "notificationssettingspage.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingsdialog.h"
|
||||
#include "core/application.h"
|
||||
#include "core/backgroundstreams.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/networkproxyfactory.h"
|
||||
#include "core/player.h"
|
||||
#include "engines/enginebase.h"
|
||||
#include "engines/gstengine.h"
|
||||
#include "globalsearch/globalsearchsettingspage.h"
|
||||
|
@ -37,6 +39,7 @@
|
|||
#include "internet/magnatunesettingspage.h"
|
||||
#include "library/librarysettingspage.h"
|
||||
#include "playlist/playlistview.h"
|
||||
#include "podcasts/podcastsettingspage.h"
|
||||
#include "songinfo/songinfosettingspage.h"
|
||||
#include "transcoder/transcodersettingspage.h"
|
||||
#include "widgets/groupediconview.h"
|
||||
|
@ -96,13 +99,15 @@ void SettingsItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem&
|
|||
}
|
||||
|
||||
|
||||
SettingsDialog::SettingsDialog(BackgroundStreams* streams, QWidget* parent)
|
||||
SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams, QWidget* parent)
|
||||
: QDialog(parent),
|
||||
model_(NULL),
|
||||
gst_engine_(NULL),
|
||||
app_(app),
|
||||
model_(app_->library_model()->directory_model()),
|
||||
gst_engine_(qobject_cast<GstEngine*>(app_->player()->engine())),
|
||||
song_info_view_(NULL),
|
||||
streams_(streams),
|
||||
global_search_(NULL),
|
||||
global_search_(app_->global_search()),
|
||||
appearance_(app_->appearance()),
|
||||
ui_(new Ui_SettingsDialog),
|
||||
loading_settings_(false)
|
||||
{
|
||||
|
@ -149,6 +154,7 @@ SettingsDialog::SettingsDialog(BackgroundStreams* streams, QWidget* parent)
|
|||
AddPage(Page_Magnatune, new MagnatuneSettingsPage(this), providers);
|
||||
AddPage(Page_DigitallyImported, new DigitallyImportedSettingsPage(this), providers);
|
||||
AddPage(Page_BackgroundStreams, new BackgroundStreamsSettingsPage(this), providers);
|
||||
AddPage(Page_Podcasts, new PodcastSettingsPage(this), providers);
|
||||
|
||||
// List box
|
||||
connect(ui_->list, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
|
||||
|
|
|
@ -53,7 +53,7 @@ class SettingsDialog : public QDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsDialog(BackgroundStreams* streams, QWidget* parent = 0);
|
||||
SettingsDialog(Application* app, BackgroundStreams* streams, QWidget* parent = 0);
|
||||
~SettingsDialog();
|
||||
|
||||
enum Page {
|
||||
|
@ -75,21 +75,19 @@ public:
|
|||
Page_Transcoding,
|
||||
Page_Remote,
|
||||
Page_Wiimotedev,
|
||||
Page_Podcasts,
|
||||
};
|
||||
|
||||
enum Role {
|
||||
Role_IsSeparator = Qt::UserRole
|
||||
};
|
||||
|
||||
void SetLibraryDirectoryModel(LibraryDirectoryModel* model) { model_ = model; }
|
||||
void SetGlobalShortcutManager(GlobalShortcuts* manager) { manager_ = manager; }
|
||||
void SetGstEngine(const GstEngine* engine) { gst_engine_ = engine; }
|
||||
void SetSongInfoView(SongInfoView* view) { song_info_view_ = view; }
|
||||
void SetGlobalSearch(GlobalSearch* global_search) { global_search_ = global_search; }
|
||||
void SetAppearance(Appearance* appearance) { appearance_ = appearance; }
|
||||
|
||||
bool is_loading_settings() const { return loading_settings_; }
|
||||
|
||||
Application* app() const { return app_; }
|
||||
LibraryDirectoryModel* library_directory_model() const { return model_; }
|
||||
GlobalShortcuts* global_shortcuts_manager() const { return manager_; }
|
||||
const GstEngine* gst_engine() const { return gst_engine_; }
|
||||
|
@ -125,6 +123,7 @@ private:
|
|||
void AddPage(Page id, SettingsPage* page, QTreeWidgetItem* parent = NULL);
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
LibraryDirectoryModel* model_;
|
||||
GlobalShortcuts* manager_;
|
||||
const GstEngine* gst_engine_;
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "spinbox.h"
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
SpinBox::SpinBox(QWidget *parent)
|
||||
: QSpinBox(parent),
|
||||
empty_value_(0)
|
||||
{
|
||||
}
|
||||
|
||||
int SpinBox::valueFromText(const QString &text) const {
|
||||
if (text.isEmpty())
|
||||
return empty_value_;
|
||||
return QSpinBox::valueFromText(text);
|
||||
}
|
||||
|
||||
QString SpinBox::textFromValue(int val) const {
|
||||
if (val == empty_value_)
|
||||
return "";
|
||||
return QSpinBox::textFromValue(val);
|
||||
}
|
||||
|
||||
void SpinBox::fixup(QString &str) const {
|
||||
if (str.isEmpty())
|
||||
return;
|
||||
QSpinBox::fixup(str);
|
||||
}
|
||||
|
||||
QValidator::State SpinBox::validate(QString &input, int &pos) const {
|
||||
if (input.isEmpty())
|
||||
return QValidator::Acceptable;
|
||||
return QSpinBox::validate(input, pos);
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SPINBOX_H
|
||||
#define SPINBOX_H
|
||||
|
||||
#include <QSpinBox>
|
||||
|
||||
// A spinbox that accepts the empty string as input
|
||||
class SpinBox : public QSpinBox {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int empty_value READ empty_value WRITE set_empty_value);
|
||||
|
||||
public:
|
||||
SpinBox(QWidget *parent = 0);
|
||||
|
||||
// The empty_value must still be within the range of the spinbox.
|
||||
// Defaults to 0
|
||||
int empty_value() const { return empty_value_; }
|
||||
void set_empty_value(int v) { empty_value_ = v; }
|
||||
|
||||
protected:
|
||||
int valueFromText(const QString &text) const;
|
||||
QString textFromValue(int val) const;
|
||||
void fixup(QString &str) const;
|
||||
QValidator::State validate(QString &input, int &pos) const;
|
||||
|
||||
private:
|
||||
int empty_value_;
|
||||
};
|
||||
|
||||
#endif // SPINBOX_H
|
Loading…
Reference in New Issue