Refactor the last.fm, magnatune, spotify and di.fm settings pages - moving the login state display into a separate widget.
This commit is contained in:
parent
143bbb4019
commit
13fc24f6c6
@ -1,2 +1,2 @@
|
||||
# Increment this whenever the user needs to download a new blob
|
||||
set(SPOTIFY_BLOB_VERSION 2)
|
||||
set(SPOTIFY_BLOB_VERSION 3)
|
||||
|
@ -320,8 +320,7 @@
|
||||
<file>schema/schema-33.sql</file>
|
||||
<file>spotify-core-logo-128x128.png</file>
|
||||
<file>icons/22x22/dialog-warning.png</file>
|
||||
<file>icons/22x22/task-complete.png</file>
|
||||
<file>icons/22x22/task-reject.png</file>
|
||||
<file>icons/22x22/dialog-ok-apply.png</file>
|
||||
<file>schema/schema-34.sql</file>
|
||||
<file>pythonlibs/uic/driver.py</file>
|
||||
<file>pythonlibs/uic/exceptions.py</file>
|
||||
|
BIN
data/icons/22x22/dialog-ok-apply.png
Normal file
BIN
data/icons/22x22/dialog-ok-apply.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 794 B |
Binary file not shown.
Before Width: | Height: | Size: 1023 B |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
@ -108,12 +108,25 @@ void SpotifyClient::Init(quint16 port) {
|
||||
void SpotifyClient::LoggedInCallback(sp_session* session, sp_error error) {
|
||||
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(sp_session_userdata(session));
|
||||
const bool success = error == SP_ERROR_OK;
|
||||
protobuf::LoginResponse_Error error_code = protobuf::LoginResponse_Error_Other;
|
||||
|
||||
if (!success) {
|
||||
qLog(Warning) << "Failed to login" << sp_error_message(error);
|
||||
}
|
||||
|
||||
me->SendLoginCompleted(success, sp_error_message(error));
|
||||
switch (error) {
|
||||
case SP_ERROR_BAD_USERNAME_OR_PASSWORD:
|
||||
error_code = protobuf::LoginResponse_Error_BadUsernameOrPassword;
|
||||
break;
|
||||
case SP_ERROR_USER_BANNED:
|
||||
error_code = protobuf::LoginResponse_Error_UserBanned;
|
||||
break;
|
||||
case SP_ERROR_USER_NEEDS_PREMIUM :
|
||||
error_code = protobuf::LoginResponse_Error_UserNeedsPremium;
|
||||
break;
|
||||
}
|
||||
|
||||
me->SendLoginCompleted(success, sp_error_message(error), error_code);
|
||||
|
||||
if (success) {
|
||||
sp_playlistcontainer_add_callbacks(
|
||||
@ -208,7 +221,7 @@ void SpotifyClient::Login(const QString& username, const QString& password) {
|
||||
sp_error error = sp_session_create(&spotify_config_, &session_);
|
||||
if (error != SP_ERROR_OK) {
|
||||
qLog(Warning) << "Failed to create session" << sp_error_message(error);
|
||||
SendLoginCompleted(false, sp_error_message(error));
|
||||
SendLoginCompleted(false, sp_error_message(error), protobuf::LoginResponse_Error_Other);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -217,13 +230,18 @@ void SpotifyClient::Login(const QString& username, const QString& password) {
|
||||
sp_session_login(session_, username.toUtf8().constData(), password.toUtf8().constData());
|
||||
}
|
||||
|
||||
void SpotifyClient::SendLoginCompleted(bool success, const QString& error) {
|
||||
void SpotifyClient::SendLoginCompleted(bool success, const QString& error,
|
||||
protobuf::LoginResponse_Error error_code) {
|
||||
protobuf::SpotifyMessage message;
|
||||
|
||||
protobuf::LoginResponse* response = message.mutable_login_response();
|
||||
response->set_success(success);
|
||||
response->set_error(DataCommaSizeFromQString(error));
|
||||
|
||||
if (!success) {
|
||||
response->set_error_code(error_code);
|
||||
}
|
||||
|
||||
handler_->SendMessage(message);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,8 @@ private slots:
|
||||
void MediaSocketDisconnected();
|
||||
|
||||
private:
|
||||
void SendLoginCompleted(bool success, const QString& error);
|
||||
void SendLoginCompleted(bool success, const QString& error,
|
||||
protobuf::LoginResponse_Error error_code);
|
||||
void SendPlaybackError(const QString& error);
|
||||
|
||||
// Spotify session callbacks.
|
||||
|
@ -30,8 +30,16 @@ message LoginRequest {
|
||||
}
|
||||
|
||||
message LoginResponse {
|
||||
enum Error {
|
||||
BadUsernameOrPassword = 1;
|
||||
UserBanned = 2;
|
||||
UserNeedsPremium = 3;
|
||||
Other = 4;
|
||||
}
|
||||
|
||||
required bool success = 1;
|
||||
required string error = 2;
|
||||
optional Error error_code = 3 [default = Other];
|
||||
}
|
||||
|
||||
message Playlists {
|
||||
|
@ -275,6 +275,7 @@ set(SOURCES
|
||||
widgets/groupediconview.cpp
|
||||
widgets/lineedit.cpp
|
||||
widgets/linetextedit.cpp
|
||||
widgets/loginstatewidget.cpp
|
||||
widgets/multiloadingindicator.cpp
|
||||
widgets/nowplayingwidget.cpp
|
||||
widgets/osd.cpp
|
||||
@ -482,6 +483,7 @@ set(HEADERS
|
||||
widgets/groupediconview.h
|
||||
widgets/lineedit.h
|
||||
widgets/linetextedit.h
|
||||
widgets/loginstatewidget.h
|
||||
widgets/multiloadingindicator.h
|
||||
widgets/nowplayingwidget.h
|
||||
widgets/osd.h
|
||||
@ -567,6 +569,7 @@ set(UI
|
||||
widgets/equalizerslider.ui
|
||||
widgets/errordialog.ui
|
||||
widgets/fileview.ui
|
||||
widgets/loginstatewidget.ui
|
||||
widgets/osdpretty.ui
|
||||
widgets/trackslider.ui
|
||||
|
||||
|
@ -28,6 +28,12 @@ DigitallyImportedSettingsPage::DigitallyImportedSettingsPage(SettingsDialog* dia
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
setWindowIcon(QIcon(":/providers/digitallyimported-32.png"));
|
||||
|
||||
ui_->login_state->SetAccountTypeText(tr(
|
||||
"You can listen for free without an account, but Premium members can "
|
||||
"listen to higher quality streams without advertisements."));
|
||||
ui_->login_state->SetAccountTypeVisible(true);
|
||||
ui_->login_state->HideLoggedInState();
|
||||
}
|
||||
|
||||
DigitallyImportedSettingsPage::~DigitallyImportedSettingsPage() {
|
||||
|
@ -14,6 +14,9 @@
|
||||
<string>Digitally Imported</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="sizePolicy">
|
||||
@ -51,16 +54,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>You can <b>listen for free</b> without an account, but Premium members can listen to <b>higher quality</b> streams without advertisements.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="upgrade_link">
|
||||
<property name="text">
|
||||
<string><a href="http://www.di.fm/premium/">Upgrade to Premium now</a></string>
|
||||
@ -157,6 +150,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LoginStateWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/loginstatewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -329,6 +329,8 @@ void LastFMService::UpdateSubscriberStatusFinished() {
|
||||
Q_ASSERT(reply);
|
||||
reply->deleteLater();
|
||||
|
||||
bool is_subscriber = false;
|
||||
|
||||
try {
|
||||
const lastfm::XmlQuery lfm = lastfm::ws::parse(reply);
|
||||
#ifdef Q_OS_WIN32
|
||||
@ -338,26 +340,20 @@ void LastFMService::UpdateSubscriberStatusFinished() {
|
||||
|
||||
connection_problems_ = false;
|
||||
QString subscriber = lfm["user"]["subscriber"].text();
|
||||
const bool is_subscriber = (subscriber.toInt() == 1);
|
||||
is_subscriber = (subscriber.toInt() == 1);
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
settings.setValue("Subscriber", is_subscriber);
|
||||
qLog(Info) << lastfm::ws::Username << "Subscriber status:" << is_subscriber;
|
||||
emit UpdatedSubscriberStatus(is_subscriber);
|
||||
} catch (lastfm::ws::ParseError e) {
|
||||
qLog(Error) << "Last.fm parse error: " << e.enumValue();
|
||||
if (e.enumValue() == lastfm::ws::MalformedResponse) {
|
||||
// The connection to the server is unavailable
|
||||
connection_problems_ = true;
|
||||
emit UpdatedSubscriberStatus(false);
|
||||
} else {
|
||||
// Errors not related to connection
|
||||
connection_problems_ = false;
|
||||
}
|
||||
connection_problems_ = e.enumValue() == lastfm::ws::MalformedResponse;
|
||||
} catch (std::runtime_error& e) {
|
||||
qLog(Error) << e.what();
|
||||
}
|
||||
|
||||
emit UpdatedSubscriberStatus(is_subscriber);
|
||||
}
|
||||
|
||||
QUrl LastFMService::FixupUrl(const QUrl& url) {
|
||||
|
@ -27,32 +27,27 @@
|
||||
#include <QMovie>
|
||||
#include <QSettings>
|
||||
|
||||
// Use Qt specific icons, since freedesktop doesn't seem to have suitable icons.
|
||||
const char* kSubscribedIcon = "task-complete";
|
||||
const char* kNotSubscribedIcon = "dialog-warning";
|
||||
const char* kWaitingIcon = ":spinner.gif";
|
||||
|
||||
LastFMSettingsPage::LastFMSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog),
|
||||
service_(static_cast<LastFMService*>(InternetModel::ServiceByName("Last.fm"))),
|
||||
ui_(new Ui_LastFMSettingsPage),
|
||||
loading_icon_(new QMovie(kWaitingIcon, QByteArray(), this)),
|
||||
waiting_for_auth_(false)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
ui_->busy->hide();
|
||||
|
||||
// Icons
|
||||
setWindowIcon(QIcon(":/last.fm/as.png"));
|
||||
ui_->sign_out->setIcon(IconLoader::Load("list-remove"));
|
||||
ui_->warn_icon->setPixmap(IconLoader::Load("dialog-warning").pixmap(16));
|
||||
ui_->warn_icon->setMinimumSize(16, 16);
|
||||
|
||||
connect(service_, SIGNAL(AuthenticationComplete(bool)), SLOT(AuthenticationComplete(bool)));
|
||||
connect(service_, SIGNAL(UpdatedSubscriberStatus(bool)), SLOT(UpdatedSubscriberStatus(bool)));
|
||||
connect(ui_->sign_out, SIGNAL(clicked()), SLOT(SignOut()));
|
||||
connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout()));
|
||||
connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login()));
|
||||
connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
|
||||
|
||||
ui_->login_state->AddCredentialField(ui_->username);
|
||||
ui_->login_state->AddCredentialField(ui_->password);
|
||||
ui_->login_state->AddCredentialGroup(ui_->groupBox);
|
||||
|
||||
ui_->username->setMinimumWidth(QFontMetrics(QFont()).width("WWWWWWWWWWWW"));
|
||||
resize(sizeHint());
|
||||
}
|
||||
@ -62,9 +57,9 @@ LastFMSettingsPage::~LastFMSettingsPage() {
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::Login() {
|
||||
ui_->busy->show();
|
||||
waiting_for_auth_ = true;
|
||||
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||
service_->Authenticate(ui_->username->text(), ui_->password->text());
|
||||
}
|
||||
|
||||
@ -72,7 +67,6 @@ void LastFMSettingsPage::AuthenticationComplete(bool success) {
|
||||
if (!waiting_for_auth_)
|
||||
return; // Wasn't us that was waiting for auth
|
||||
|
||||
ui_->busy->hide();
|
||||
waiting_for_auth_ = false;
|
||||
|
||||
if (success) {
|
||||
@ -93,8 +87,6 @@ void LastFMSettingsPage::Load() {
|
||||
ui_->love_ban_->setChecked(service_->AreButtonsVisible());
|
||||
ui_->scrobble_button->setChecked(service_->IsScrobbleButtonVisible());
|
||||
|
||||
ui_->icon->setMovie(loading_icon_);
|
||||
loading_icon_->start();
|
||||
if (service_->IsAuthenticated()) {
|
||||
service_->UpdateSubscriberStatus();
|
||||
}
|
||||
@ -103,21 +95,15 @@ void LastFMSettingsPage::Load() {
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::UpdatedSubscriberStatus(bool is_subscriber) {
|
||||
const char* icon_path = is_subscriber ? kSubscribedIcon : kNotSubscribedIcon;
|
||||
ui_->icon->setPixmap(IconLoader::Load(icon_path).pixmap(16));
|
||||
loading_icon_->stop();
|
||||
ui_->login_state->SetAccountTypeVisible(!is_subscriber);
|
||||
|
||||
if (is_subscriber) {
|
||||
ui_->subscriber_warning->hide();
|
||||
ui_->warn_icon->hide();
|
||||
} else {
|
||||
ui_->warn_icon->show();
|
||||
if (!is_subscriber) {
|
||||
if (service_->HasConnectionProblems()) {
|
||||
ui_->subscriber_warning->setText(
|
||||
ui_->login_state->SetAccountTypeText(
|
||||
tr("Clementine couldn't fetch your subscription status since there are problems "
|
||||
"with your connection. Played tracks will be cached and sent later to Last.fm."));
|
||||
} else {
|
||||
ui_->subscriber_warning->setText(
|
||||
ui_->login_state->SetAccountTypeText(
|
||||
tr("You will not be able to play Last.fm radio stations "
|
||||
"as you are not a Last.fm subscriber."));
|
||||
}
|
||||
@ -135,7 +121,7 @@ void LastFMSettingsPage::Save() {
|
||||
service_->ReloadSettings();
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::SignOut() {
|
||||
void LastFMSettingsPage::Logout() {
|
||||
ui_->username->clear();
|
||||
ui_->password->clear();
|
||||
RefreshControls(false);
|
||||
@ -144,19 +130,15 @@ void LastFMSettingsPage::SignOut() {
|
||||
}
|
||||
|
||||
void LastFMSettingsPage::RefreshControls(bool authenticated) {
|
||||
ui_->groupBox->setVisible(!authenticated);
|
||||
ui_->sign_out->setVisible(authenticated);
|
||||
if (authenticated) {
|
||||
ui_->status->setText(QString(tr("You're logged in as <b>%1</b>")).arg(lastfm::ws::Username));
|
||||
} else {
|
||||
ui_->icon->setPixmap(IconLoader::Load("task-reject").pixmap(16));
|
||||
ui_->status->setText(tr("Please fill in the blanks to login into Last.fm"));
|
||||
ui_->login_state->SetLoggedIn(authenticated ? LoginStateWidget::LoggedIn
|
||||
: LoginStateWidget::LoggedOut,
|
||||
lastfm::ws::Username);
|
||||
ui_->login_state->SetAccountTypeVisible(!authenticated);
|
||||
|
||||
ui_->subscriber_warning->setText(
|
||||
if (!authenticated) {
|
||||
ui_->login_state->SetAccountTypeText(
|
||||
tr("You can scrobble tracks for free, but only "
|
||||
"<span style=\" font-weight:600;\">paid subscribers</span> "
|
||||
"can stream Last.fm radio from Clementine."));
|
||||
ui_->subscriber_warning->show();
|
||||
ui_->warn_icon->show();
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
private slots:
|
||||
void Login();
|
||||
void AuthenticationComplete(bool success);
|
||||
void SignOut();
|
||||
void Logout();
|
||||
void UpdatedSubscriberStatus(bool is_subscriber);
|
||||
|
||||
private:
|
||||
|
@ -15,64 +15,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="icon">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="status">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sign_out">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sign out</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
@ -170,121 +113,24 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="warn_icon">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="subscriber_warning">
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="busy" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Authenticating...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BusyIndicator" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<class>LoginStateWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/busyindicator.h</header>
|
||||
<header>widgets/loginstatewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>username</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
<tabstop>login</tabstop>
|
||||
<tabstop>sign_out</tabstop>
|
||||
<tabstop>scrobble</tabstop>
|
||||
<tabstop>love_ban_</tabstop>
|
||||
<tabstop>scrobble_button</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>username</sender>
|
||||
<signal>returnPressed()</signal>
|
||||
<receiver>login</receiver>
|
||||
<slot>click()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>332</x>
|
||||
<y>104</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>706</x>
|
||||
<y>103</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>password</sender>
|
||||
<signal>returnPressed()</signal>
|
||||
<receiver>login</receiver>
|
||||
<slot>click()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>719</x>
|
||||
<y>137</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>725</x>
|
||||
<y>108</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -30,23 +30,28 @@
|
||||
|
||||
MagnatuneSettingsPage::MagnatuneSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog),
|
||||
credentials_changed_(false),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
ui_(new Ui_MagnatuneSettingsPage)
|
||||
ui_(new Ui_MagnatuneSettingsPage),
|
||||
logged_in_(false)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
ui_->busy->hide();
|
||||
setWindowIcon(QIcon(":/providers/magnatune.png"));
|
||||
|
||||
connect(ui_->membership, SIGNAL(currentIndexChanged(int)), SLOT(MembershipChanged(int)));
|
||||
|
||||
connect(network_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
|
||||
SLOT(AuthenticationRequired(QNetworkReply*, QAuthenticator*)));
|
||||
connect(ui_->username, SIGNAL(textEdited(const QString&)),
|
||||
SLOT(CredentialsChanged()));
|
||||
connect(ui_->password, SIGNAL(textEdited(const QString&)),
|
||||
SLOT(CredentialsChanged()));
|
||||
connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
|
||||
connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login()));
|
||||
connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout()));
|
||||
|
||||
ui_->login_state->AddCredentialField(ui_->username);
|
||||
ui_->login_state->AddCredentialField(ui_->password);
|
||||
ui_->login_state->AddCredentialGroup(ui_->login_container);
|
||||
|
||||
ui_->login_state->SetAccountTypeText(tr(
|
||||
"You can listen to Magnatune songs for free without an account. "
|
||||
"Purchasing a membership removes the messages at the end of each track."));
|
||||
}
|
||||
|
||||
MagnatuneSettingsPage::~MagnatuneSettingsPage() {
|
||||
@ -56,11 +61,14 @@ MagnatuneSettingsPage::~MagnatuneSettingsPage() {
|
||||
const char* kMagnatuneDownloadValidateUrl = "http://download.magnatune.com/";
|
||||
const char* kMagnatuneStreamingValidateUrl = "http://streaming.magnatune.com/";
|
||||
|
||||
void MagnatuneSettingsPage::Login() {
|
||||
if (!credentials_changed_)
|
||||
return;
|
||||
ui_->busy->show();
|
||||
void MagnatuneSettingsPage::UpdateLoginState() {
|
||||
ui_->login_state->SetLoggedIn(logged_in_ ? LoginStateWidget::LoggedIn
|
||||
: LoginStateWidget::LoggedOut,
|
||||
ui_->username->text());
|
||||
ui_->login_state->SetAccountTypeVisible(!logged_in_);
|
||||
}
|
||||
|
||||
void MagnatuneSettingsPage::Login() {
|
||||
MagnatuneService::MembershipType type =
|
||||
MagnatuneService::MembershipType(ui_->membership->currentIndex());
|
||||
|
||||
@ -81,27 +89,33 @@ void MagnatuneSettingsPage::Login() {
|
||||
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
|
||||
QNetworkRequest::AlwaysNetwork);
|
||||
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||
|
||||
QNetworkReply* reply = network_->head(req);
|
||||
connect(reply, SIGNAL(finished()), SLOT(LoginFinished()));
|
||||
}
|
||||
|
||||
void MagnatuneSettingsPage::Logout() {
|
||||
logged_in_ = false;
|
||||
UpdateLoginState();
|
||||
}
|
||||
|
||||
void MagnatuneSettingsPage::LoginFinished() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
Q_ASSERT(reply);
|
||||
reply->deleteLater();
|
||||
|
||||
ui_->busy->hide();
|
||||
|
||||
const bool success =
|
||||
logged_in_ =
|
||||
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200;
|
||||
credentials_changed_ = !success;
|
||||
if (!success) {
|
||||
|
||||
if (!logged_in_) {
|
||||
QMessageBox::warning(
|
||||
this, tr("Authentication failed"), tr("Your Magnatune credentials were incorrect"));
|
||||
} else {
|
||||
Save();
|
||||
}
|
||||
ui_->login->setEnabled(!success);
|
||||
|
||||
UpdateLoginState();
|
||||
}
|
||||
|
||||
void MagnatuneSettingsPage::AuthenticationRequired(
|
||||
@ -119,8 +133,11 @@ void MagnatuneSettingsPage::Load() {
|
||||
ui_->username->setText(s.value("username").toString());
|
||||
ui_->password->setText(s.value("password").toString());
|
||||
ui_->format->setCurrentIndex(s.value("format", MagnatuneService::Format_Ogg).toInt());
|
||||
logged_in_ = s.value("logged_in",
|
||||
!ui_->username->text().isEmpty() &&
|
||||
!ui_->password->text().isEmpty()).toBool();
|
||||
|
||||
credentials_changed_ = false;
|
||||
UpdateLoginState();
|
||||
}
|
||||
|
||||
void MagnatuneSettingsPage::Save() {
|
||||
@ -131,6 +148,7 @@ void MagnatuneSettingsPage::Save() {
|
||||
s.setValue("username", ui_->username->text());
|
||||
s.setValue("password", ui_->password->text());
|
||||
s.setValue("format", ui_->format->currentIndex());
|
||||
s.setValue("logged_in", logged_in_);
|
||||
|
||||
InternetModel::Service<MagnatuneService>()->ReloadSettings();
|
||||
}
|
||||
@ -141,7 +159,3 @@ void MagnatuneSettingsPage::MembershipChanged(int value) {
|
||||
ui_->login_container->setEnabled(enabled);
|
||||
ui_->preferences_group->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void MagnatuneSettingsPage::CredentialsChanged() {
|
||||
credentials_changed_ = true;
|
||||
}
|
||||
|
@ -37,15 +37,19 @@ public:
|
||||
|
||||
private slots:
|
||||
void Login();
|
||||
void Logout();
|
||||
void MembershipChanged(int value);
|
||||
void LoginFinished();
|
||||
void AuthenticationRequired(QNetworkReply* reply, QAuthenticator* auth);
|
||||
void CredentialsChanged();
|
||||
|
||||
private:
|
||||
bool credentials_changed_;
|
||||
void UpdateLoginState();
|
||||
|
||||
private:
|
||||
NetworkAccessManager* network_;
|
||||
Ui_MagnatuneSettingsPage* ui_;
|
||||
|
||||
bool logged_in_;
|
||||
};
|
||||
|
||||
#endif // MAGNATUNESETTINGSPAGE_H
|
||||
|
@ -14,12 +14,18 @@
|
||||
<string>Magnatune</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Account details</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
@ -47,16 +53,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>You can listen to Magnatune songs for free without an account. Purchasing a membership removes the messages at the end of each track.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QWidget" name="login_container" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@ -166,42 +162,14 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="busy" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Authenticating...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BusyIndicator" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<class>LoginStateWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/busyindicator.h</header>
|
||||
<header>widgets/loginstatewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@ -98,7 +98,8 @@ void SpotifyServer::HandleMessage(const protobuf::SpotifyMessage& message) {
|
||||
queued_messages_.clear();
|
||||
}
|
||||
|
||||
emit LoginCompleted(response.success(), QStringFromStdString(response.error()));
|
||||
emit LoginCompleted(response.success(), QStringFromStdString(response.error()),
|
||||
response.error_code());
|
||||
} else if (message.has_playlists_updated()) {
|
||||
emit PlaylistsUpdated(message.playlists_updated());
|
||||
} else if (message.has_load_playlist_response()) {
|
||||
|
@ -50,7 +50,8 @@ public:
|
||||
int server_port() const;
|
||||
|
||||
signals:
|
||||
void LoginCompleted(bool success, const QString& error);
|
||||
void LoginCompleted(bool success, const QString& error,
|
||||
protobuf::LoginResponse_Error error_code);
|
||||
void PlaylistsUpdated(const protobuf::Playlists& playlists);
|
||||
|
||||
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
|
||||
|
@ -46,7 +46,8 @@ SpotifyService::SpotifyService(InternetModel* parent)
|
||||
login_task_id_(0),
|
||||
pending_search_playlist_(NULL),
|
||||
context_menu_(NULL),
|
||||
search_delay_(new QTimer(this)) {
|
||||
search_delay_(new QTimer(this)),
|
||||
login_state_(LoginState_OtherError) {
|
||||
// Build the search path for the binary blob.
|
||||
// Look for one distributed alongside clementine first, then check in the
|
||||
// user's home directory for any that have been downloaded.
|
||||
@ -124,24 +125,44 @@ QModelIndex SpotifyService::GetCurrentIndex() {
|
||||
}
|
||||
|
||||
void SpotifyService::Login(const QString& username, const QString& password) {
|
||||
delete server_;
|
||||
delete blob_process_;
|
||||
server_ = NULL;
|
||||
blob_process_ = NULL;
|
||||
|
||||
Logout();
|
||||
EnsureServerCreated(username, password);
|
||||
}
|
||||
|
||||
void SpotifyService::LoginCompleted(bool success, const QString& error) {
|
||||
void SpotifyService::LoginCompleted(bool success, const QString& error,
|
||||
protobuf::LoginResponse_Error error_code) {
|
||||
if (login_task_id_) {
|
||||
model()->task_manager()->SetTaskFinished(login_task_id_);
|
||||
login_task_id_ = 0;
|
||||
}
|
||||
|
||||
login_state_ = LoginState_LoggedIn;
|
||||
|
||||
if (!success) {
|
||||
QMessageBox::warning(NULL, tr("Spotify login error"), error, QMessageBox::Close);
|
||||
|
||||
switch (error_code) {
|
||||
case protobuf::LoginResponse_Error_BadUsernameOrPassword:
|
||||
login_state_ = LoginState_BadCredentials;
|
||||
break;
|
||||
|
||||
case protobuf::LoginResponse_Error_UserBanned:
|
||||
login_state_ = LoginState_Banned;
|
||||
break;
|
||||
|
||||
case protobuf::LoginResponse_Error_UserNeedsPremium:
|
||||
login_state_ = LoginState_NoPremium;
|
||||
break;
|
||||
|
||||
default:
|
||||
login_state_ = LoginState_OtherError;
|
||||
}
|
||||
}
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("login_state", login_state_);
|
||||
|
||||
emit LoginFinished(success);
|
||||
}
|
||||
|
||||
@ -155,6 +176,13 @@ void SpotifyService::BlobProcessError(QProcess::ProcessError error) {
|
||||
}
|
||||
}
|
||||
|
||||
void SpotifyService::ReloadSettings() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
login_state_ = LoginState(s.value("login_state", LoginState_OtherError).toInt());
|
||||
}
|
||||
|
||||
void SpotifyService::EnsureServerCreated(const QString& username,
|
||||
const QString& password) {
|
||||
if (server_ && blob_process_) {
|
||||
@ -164,7 +192,8 @@ void SpotifyService::EnsureServerCreated(const QString& username,
|
||||
delete server_;
|
||||
server_ = new SpotifyServer(this);
|
||||
|
||||
connect(server_, SIGNAL(LoginCompleted(bool,QString)), SLOT(LoginCompleted(bool,QString)));
|
||||
connect(server_, SIGNAL(LoginCompleted(bool,QString,protobuf::LoginResponse_Error)),
|
||||
SLOT(LoginCompleted(bool,QString,protobuf::LoginResponse_Error)));
|
||||
connect(server_, SIGNAL(PlaylistsUpdated(protobuf::Playlists)),
|
||||
SLOT(PlaylistsUpdated(protobuf::Playlists)));
|
||||
connect(server_, SIGNAL(InboxLoaded(protobuf::LoadPlaylistResponse)),
|
||||
@ -593,3 +622,12 @@ void SpotifyService::SyncPlaylistProgress(
|
||||
void SpotifyService::ShowConfig() {
|
||||
emit OpenSettingsAtPage(SettingsDialog::Page_Spotify);
|
||||
}
|
||||
|
||||
void SpotifyService::Logout() {
|
||||
delete server_;
|
||||
delete blob_process_;
|
||||
server_ = NULL;
|
||||
blob_process_ = NULL;
|
||||
|
||||
login_state_ = LoginState_OtherError;
|
||||
}
|
||||
|
@ -35,17 +35,29 @@ public:
|
||||
Role_UserPlaylistIndex = InternetModel::RoleCount,
|
||||
};
|
||||
|
||||
// Values are persisted - don't change.
|
||||
enum LoginState {
|
||||
LoginState_LoggedIn = 1,
|
||||
LoginState_Banned = 2,
|
||||
LoginState_BadCredentials = 3,
|
||||
LoginState_NoPremium = 4,
|
||||
LoginState_OtherError = 5
|
||||
};
|
||||
|
||||
static const char* kServiceName;
|
||||
static const char* kSettingsGroup;
|
||||
static const char* kBlobDownloadUrl;
|
||||
static const int kSearchDelayMsec;
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
QStandardItem* CreateRootItem();
|
||||
void LazyPopulate(QStandardItem* parent);
|
||||
void ShowContextMenu(const QModelIndex& index, const QPoint& global_pos);
|
||||
void ItemDoubleClicked(QStandardItem* item);
|
||||
PlaylistItem::Options playlistitem_options() const;
|
||||
|
||||
void Logout();
|
||||
void Login(const QString& username, const QString& password);
|
||||
void Search(const QString& text, Playlist* playlist, bool now = false);
|
||||
Q_INVOKABLE void LoadImage(const QUrl& url);
|
||||
@ -55,6 +67,9 @@ public:
|
||||
bool IsBlobInstalled() const;
|
||||
void InstallBlob();
|
||||
|
||||
// Persisted in the settings and updated on each Login().
|
||||
LoginState login_state() const { return login_state_; }
|
||||
|
||||
static void SongFromProtobuf(const protobuf::Track& track, Song* song);
|
||||
|
||||
signals:
|
||||
@ -77,7 +92,8 @@ private:
|
||||
|
||||
private slots:
|
||||
void BlobProcessError(QProcess::ProcessError error);
|
||||
void LoginCompleted(bool success, const QString& error);
|
||||
void LoginCompleted(bool success, const QString& error,
|
||||
protobuf::LoginResponse_Error error_code);
|
||||
void PlaylistsUpdated(const protobuf::Playlists& response);
|
||||
void InboxLoaded(const protobuf::LoadPlaylistResponse& response);
|
||||
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
|
||||
@ -122,6 +138,8 @@ private:
|
||||
int inbox_sync_id_;
|
||||
int starred_sync_id_;
|
||||
QMap<int, int> playlist_sync_ids_;
|
||||
|
||||
LoginState login_state_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -37,8 +37,6 @@ SpotifySettingsPage::SpotifySettingsPage(SettingsDialog* dialog)
|
||||
validated_(false)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
ui_->busy->hide();
|
||||
ui_->warn_icon->setPixmap(IconLoader::Load("dialog-warning").pixmap(16));
|
||||
|
||||
setWindowIcon(QIcon(":/icons/svg/spotify.svg"));
|
||||
|
||||
@ -48,10 +46,16 @@ SpotifySettingsPage::SpotifySettingsPage(SettingsDialog* dialog)
|
||||
|
||||
connect(ui_->download_blob, SIGNAL(clicked()), SLOT(DownloadBlob()));
|
||||
connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
|
||||
connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout()));
|
||||
connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login()));
|
||||
|
||||
connect(service_, SIGNAL(LoginFinished(bool)), SLOT(LoginFinished(bool)));
|
||||
connect(service_, SIGNAL(BlobStateChanged()), SLOT(BlobStateChanged()));
|
||||
|
||||
ui_->login_state->AddCredentialField(ui_->username);
|
||||
ui_->login_state->AddCredentialField(ui_->password);
|
||||
ui_->login_state->AddCredentialGroup(ui_->account_group);
|
||||
|
||||
BlobStateChanged();
|
||||
}
|
||||
|
||||
@ -82,15 +86,12 @@ void SpotifySettingsPage::Login() {
|
||||
}
|
||||
|
||||
if (ui_->username->text() == original_username_ &&
|
||||
ui_->password->text() == original_password_) {
|
||||
ui_->password->text() == original_password_ &&
|
||||
service_->login_state() == SpotifyService::LoginState_LoggedIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validated_) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui_->busy->show();
|
||||
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||
service_->Login(ui_->username->text(), ui_->password->text());
|
||||
}
|
||||
|
||||
@ -104,6 +105,8 @@ void SpotifySettingsPage::Load() {
|
||||
ui_->username->setText(original_username_);
|
||||
ui_->password->setText(original_password_);
|
||||
validated_ = false;
|
||||
|
||||
UpdateLoginState();
|
||||
}
|
||||
|
||||
void SpotifySettingsPage::Save() {
|
||||
@ -112,15 +115,41 @@ void SpotifySettingsPage::Save() {
|
||||
|
||||
s.setValue("username", ui_->username->text());
|
||||
s.setValue("password", ui_->password->text());
|
||||
|
||||
InternetModel::Service<SpotifyService>()->ReloadSettings();
|
||||
}
|
||||
|
||||
void SpotifySettingsPage::LoginFinished(bool success) {
|
||||
validated_ = success;
|
||||
ui_->busy->hide();
|
||||
ui_->login->setEnabled(!success);
|
||||
|
||||
// Save the settings
|
||||
Save();
|
||||
UpdateLoginState();
|
||||
}
|
||||
|
||||
void SpotifySettingsPage::UpdateLoginState() {
|
||||
const bool logged_in =
|
||||
service_->login_state() == SpotifyService::LoginState_LoggedIn;
|
||||
|
||||
ui_->login_state->SetLoggedIn(logged_in ? LoginStateWidget::LoggedIn
|
||||
: LoginStateWidget::LoggedOut,
|
||||
ui_->username->text());
|
||||
ui_->login_state->SetAccountTypeVisible(!logged_in);
|
||||
|
||||
switch (service_->login_state()) {
|
||||
case SpotifyService::LoginState_NoPremium:
|
||||
ui_->login_state->SetAccountTypeText(tr("You do not have a Spotify Premium account."));
|
||||
break;
|
||||
|
||||
case SpotifyService::LoginState_Banned:
|
||||
case SpotifyService::LoginState_BadCredentials:
|
||||
ui_->login_state->SetAccountTypeText(tr("Your username or password was incorrect."));
|
||||
break;
|
||||
|
||||
default:
|
||||
ui_->login_state->SetAccountTypeText(tr("A Spotify Premium account is required."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SpotifySettingsPage::Logout() {
|
||||
service_->Logout();
|
||||
UpdateLoginState();
|
||||
}
|
||||
|
@ -41,6 +41,10 @@ public slots:
|
||||
private slots:
|
||||
void Login();
|
||||
void LoginFinished(bool success);
|
||||
void Logout();
|
||||
|
||||
private:
|
||||
void UpdateLoginState();
|
||||
|
||||
private:
|
||||
NetworkAccessManager* network_;
|
||||
|
@ -14,50 +14,15 @@
|
||||
<string>Spotify</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="account_group">
|
||||
<property name="title">
|
||||
<string>Account details</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="warn_icon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A Spotify Premium account is required.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="login_container" native="true">
|
||||
<property name="enabled">
|
||||
@ -206,42 +171,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="busy" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Authenticating...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BusyIndicator" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<class>LoginStateWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/busyindicator.h</header>
|
||||
<header>widgets/loginstatewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
|
@ -30,11 +30,14 @@ class SettingsPage : public QWidget {
|
||||
public:
|
||||
SettingsPage(SettingsDialog* dialog);
|
||||
|
||||
// Return false to grey out the page's item in the list.
|
||||
virtual bool IsEnabled() const { return true; }
|
||||
|
||||
// Load is called when the dialog is shown, Save when the user clicks OK.
|
||||
virtual void Load() = 0;
|
||||
virtual void Save() = 0;
|
||||
|
||||
// The dialog that this page belongs to.
|
||||
SettingsDialog* dialog() const { return dialog_; }
|
||||
|
||||
signals:
|
||||
|
@ -39,6 +39,7 @@ void BusyIndicator::Init(const QString& text) {
|
||||
icon->setMinimumSize(16, 16);
|
||||
|
||||
label_->setWordWrap(true);
|
||||
label_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
@ -63,7 +64,10 @@ void BusyIndicator::hideEvent(QHideEvent*) {
|
||||
|
||||
void BusyIndicator::set_text(const QString& text) {
|
||||
label_->setText(text);
|
||||
if (text.isEmpty())
|
||||
label_->hide();
|
||||
label_->setVisible(!text.isEmpty());
|
||||
}
|
||||
|
||||
QString BusyIndicator::text() const {
|
||||
return label_->text();
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ class QMovie;
|
||||
|
||||
class BusyIndicator : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString text READ text WRITE set_text)
|
||||
|
||||
public:
|
||||
explicit BusyIndicator(const QString& text, QWidget* parent = 0);
|
||||
|
104
src/widgets/loginstatewidget.cpp
Normal file
104
src/widgets/loginstatewidget.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/* 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 "loginstatewidget.h"
|
||||
#include "ui_loginstatewidget.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
LoginStateWidget::LoginStateWidget(QWidget* parent)
|
||||
: QWidget(parent),
|
||||
ui_(new Ui_LoginStateWidget)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
ui_->signed_in->hide();
|
||||
ui_->account_type->hide();
|
||||
ui_->busy->hide();
|
||||
|
||||
ui_->sign_out->setIcon(IconLoader::Load("list-remove"));
|
||||
|
||||
QFont bold_font(font());
|
||||
bold_font.setBold(true);
|
||||
ui_->signed_out_label->setFont(bold_font);
|
||||
|
||||
connect(ui_->sign_out, SIGNAL(clicked()), SLOT(Logout()));
|
||||
}
|
||||
|
||||
LoginStateWidget::~LoginStateWidget() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void LoginStateWidget::Logout() {
|
||||
SetLoggedIn(LoggedOut);
|
||||
emit LogoutClicked();
|
||||
}
|
||||
|
||||
void LoginStateWidget::SetAccountTypeText(const QString& text) {
|
||||
ui_->account_type_label->setText(text);
|
||||
}
|
||||
|
||||
void LoginStateWidget::SetAccountTypeVisible(bool visible) {
|
||||
ui_->account_type->setVisible(visible);
|
||||
}
|
||||
|
||||
void LoginStateWidget::SetLoggedIn(State state, const QString& account_name) {
|
||||
ui_->signed_in->setVisible(state == LoggedIn);
|
||||
ui_->signed_out->setVisible(state != LoggedIn);
|
||||
ui_->busy->setVisible(state == LoginInProgress);
|
||||
|
||||
if (account_name.isEmpty())
|
||||
ui_->signed_in_label->setText("<b>" + tr("You are signed in.") + "</b>");
|
||||
else
|
||||
ui_->signed_in_label->setText(tr("You are signed in as %1.").arg("<b>" + account_name + "</b>"));
|
||||
|
||||
foreach (QWidget* widget, credential_groups_) {
|
||||
widget->setVisible(state != LoggedIn);
|
||||
widget->setEnabled(state != LoginInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
void LoginStateWidget::HideLoggedInState() {
|
||||
ui_->signed_in->hide();
|
||||
ui_->signed_out->hide();
|
||||
}
|
||||
|
||||
void LoginStateWidget::AddCredentialField(QWidget* widget) {
|
||||
widget->installEventFilter(this);
|
||||
credential_fields_ << widget;
|
||||
}
|
||||
|
||||
void LoginStateWidget::AddCredentialGroup(QWidget* widget) {
|
||||
credential_groups_ << widget;
|
||||
}
|
||||
|
||||
bool LoginStateWidget::eventFilter(QObject* object, QEvent* event) {
|
||||
if (!credential_fields_.contains(object))
|
||||
return QWidget::eventFilter(object, event);
|
||||
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent* key_event = static_cast<QKeyEvent*>(event);
|
||||
if (key_event->key() == Qt::Key_Enter ||
|
||||
key_event->key() == Qt::Key_Return) {
|
||||
emit LoginClicked();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(object, event);
|
||||
}
|
||||
|
74
src/widgets/loginstatewidget.h
Normal file
74
src/widgets/loginstatewidget.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* 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 LOGINSTATEWIDGET_H
|
||||
#define LOGINSTATEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class Ui_LoginStateWidget;
|
||||
|
||||
class LoginStateWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LoginStateWidget(QWidget* parent = 0);
|
||||
~LoginStateWidget();
|
||||
|
||||
enum State {
|
||||
LoggedIn,
|
||||
LoginInProgress,
|
||||
LoggedOut
|
||||
};
|
||||
|
||||
// Installs an event handler on the field so that pressing enter will emit
|
||||
// LoginClicked() instead of doing the default action (closing the dialog).
|
||||
void AddCredentialField(QWidget* widget);
|
||||
|
||||
// This widget (usually a QGroupBox) will be hidden when SetLoggedIn(true)
|
||||
// is called.
|
||||
void AddCredentialGroup(QWidget* widget);
|
||||
|
||||
// QObject
|
||||
bool eventFilter(QObject* object, QEvent* event);
|
||||
|
||||
public slots:
|
||||
// Changes the "You are logged in/out" label, shows/hides any QGroupBoxes
|
||||
// added with AddCredentialGroup.
|
||||
void SetLoggedIn(State state, const QString& account_name = QString::null);
|
||||
|
||||
// Hides the "You are logged in/out" label completely.
|
||||
void HideLoggedInState();
|
||||
|
||||
void SetAccountTypeText(const QString& text);
|
||||
void SetAccountTypeVisible(bool visible);
|
||||
|
||||
signals:
|
||||
void LogoutClicked();
|
||||
void LoginClicked();
|
||||
|
||||
private slots:
|
||||
void Logout();
|
||||
|
||||
private:
|
||||
Ui_LoginStateWidget* ui_;
|
||||
|
||||
QList<QObject*> credential_fields_;
|
||||
QList<QWidget*> credential_groups_;
|
||||
};
|
||||
|
||||
#endif // LOGINSTATEWIDGET_H
|
162
src/widgets/loginstatewidget.ui
Normal file
162
src/widgets/loginstatewidget.ui
Normal file
@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoginStateWidget</class>
|
||||
<widget class="QWidget" name="LoginStateWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>526</width>
|
||||
<height>187</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="signed_out" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="signed_out_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>You are not signed in.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="signed_in" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../data/data.qrc">:/icons/22x22/dialog-ok-apply.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="signed_in_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sign_out">
|
||||
<property name="text">
|
||||
<string>Sign out</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="account_type" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../data/data.qrc">:/icons/22x22/dialog-warning.png</pixmap>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="account_type_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BusyIndicator" name="busy" native="true">
|
||||
<property name="text" stdset="0">
|
||||
<string>Signing in...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/busyindicator.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user