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
|
# 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>schema/schema-33.sql</file>
|
||||||
<file>spotify-core-logo-128x128.png</file>
|
<file>spotify-core-logo-128x128.png</file>
|
||||||
<file>icons/22x22/dialog-warning.png</file>
|
<file>icons/22x22/dialog-warning.png</file>
|
||||||
<file>icons/22x22/task-complete.png</file>
|
<file>icons/22x22/dialog-ok-apply.png</file>
|
||||||
<file>icons/22x22/task-reject.png</file>
|
|
||||||
<file>schema/schema-34.sql</file>
|
<file>schema/schema-34.sql</file>
|
||||||
<file>pythonlibs/uic/driver.py</file>
|
<file>pythonlibs/uic/driver.py</file>
|
||||||
<file>pythonlibs/uic/exceptions.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) {
|
void SpotifyClient::LoggedInCallback(sp_session* session, sp_error error) {
|
||||||
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(sp_session_userdata(session));
|
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(sp_session_userdata(session));
|
||||||
const bool success = error == SP_ERROR_OK;
|
const bool success = error == SP_ERROR_OK;
|
||||||
|
protobuf::LoginResponse_Error error_code = protobuf::LoginResponse_Error_Other;
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qLog(Warning) << "Failed to login" << sp_error_message(error);
|
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) {
|
if (success) {
|
||||||
sp_playlistcontainer_add_callbacks(
|
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_);
|
sp_error error = sp_session_create(&spotify_config_, &session_);
|
||||||
if (error != SP_ERROR_OK) {
|
if (error != SP_ERROR_OK) {
|
||||||
qLog(Warning) << "Failed to create session" << sp_error_message(error);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,13 +230,18 @@ void SpotifyClient::Login(const QString& username, const QString& password) {
|
|||||||
sp_session_login(session_, username.toUtf8().constData(), password.toUtf8().constData());
|
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::SpotifyMessage message;
|
||||||
|
|
||||||
protobuf::LoginResponse* response = message.mutable_login_response();
|
protobuf::LoginResponse* response = message.mutable_login_response();
|
||||||
response->set_success(success);
|
response->set_success(success);
|
||||||
response->set_error(DataCommaSizeFromQString(error));
|
response->set_error(DataCommaSizeFromQString(error));
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
response->set_error_code(error_code);
|
||||||
|
}
|
||||||
|
|
||||||
handler_->SendMessage(message);
|
handler_->SendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,8 @@ private slots:
|
|||||||
void MediaSocketDisconnected();
|
void MediaSocketDisconnected();
|
||||||
|
|
||||||
private:
|
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);
|
void SendPlaybackError(const QString& error);
|
||||||
|
|
||||||
// Spotify session callbacks.
|
// Spotify session callbacks.
|
||||||
|
@ -30,8 +30,16 @@ message LoginRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message LoginResponse {
|
message LoginResponse {
|
||||||
|
enum Error {
|
||||||
|
BadUsernameOrPassword = 1;
|
||||||
|
UserBanned = 2;
|
||||||
|
UserNeedsPremium = 3;
|
||||||
|
Other = 4;
|
||||||
|
}
|
||||||
|
|
||||||
required bool success = 1;
|
required bool success = 1;
|
||||||
required string error = 2;
|
required string error = 2;
|
||||||
|
optional Error error_code = 3 [default = Other];
|
||||||
}
|
}
|
||||||
|
|
||||||
message Playlists {
|
message Playlists {
|
||||||
|
@ -275,6 +275,7 @@ set(SOURCES
|
|||||||
widgets/groupediconview.cpp
|
widgets/groupediconview.cpp
|
||||||
widgets/lineedit.cpp
|
widgets/lineedit.cpp
|
||||||
widgets/linetextedit.cpp
|
widgets/linetextedit.cpp
|
||||||
|
widgets/loginstatewidget.cpp
|
||||||
widgets/multiloadingindicator.cpp
|
widgets/multiloadingindicator.cpp
|
||||||
widgets/nowplayingwidget.cpp
|
widgets/nowplayingwidget.cpp
|
||||||
widgets/osd.cpp
|
widgets/osd.cpp
|
||||||
@ -482,6 +483,7 @@ set(HEADERS
|
|||||||
widgets/groupediconview.h
|
widgets/groupediconview.h
|
||||||
widgets/lineedit.h
|
widgets/lineedit.h
|
||||||
widgets/linetextedit.h
|
widgets/linetextedit.h
|
||||||
|
widgets/loginstatewidget.h
|
||||||
widgets/multiloadingindicator.h
|
widgets/multiloadingindicator.h
|
||||||
widgets/nowplayingwidget.h
|
widgets/nowplayingwidget.h
|
||||||
widgets/osd.h
|
widgets/osd.h
|
||||||
@ -567,6 +569,7 @@ set(UI
|
|||||||
widgets/equalizerslider.ui
|
widgets/equalizerslider.ui
|
||||||
widgets/errordialog.ui
|
widgets/errordialog.ui
|
||||||
widgets/fileview.ui
|
widgets/fileview.ui
|
||||||
|
widgets/loginstatewidget.ui
|
||||||
widgets/osdpretty.ui
|
widgets/osdpretty.ui
|
||||||
widgets/trackslider.ui
|
widgets/trackslider.ui
|
||||||
|
|
||||||
|
@ -28,6 +28,12 @@ DigitallyImportedSettingsPage::DigitallyImportedSettingsPage(SettingsDialog* dia
|
|||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
setWindowIcon(QIcon(":/providers/digitallyimported-32.png"));
|
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() {
|
DigitallyImportedSettingsPage::~DigitallyImportedSettingsPage() {
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
<string>Digitally Imported</string>
|
<string>Digitally Imported</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_10">
|
<widget class="QGroupBox" name="groupBox_10">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -51,16 +54,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<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">
|
<widget class="QLabel" name="upgrade_link">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><a href="http://www.di.fm/premium/">Upgrade to Premium now</a></string>
|
<string><a href="http://www.di.fm/premium/">Upgrade to Premium now</a></string>
|
||||||
@ -157,6 +150,14 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>LoginStateWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets/loginstatewidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -329,6 +329,8 @@ void LastFMService::UpdateSubscriberStatusFinished() {
|
|||||||
Q_ASSERT(reply);
|
Q_ASSERT(reply);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
|
bool is_subscriber = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const lastfm::XmlQuery lfm = lastfm::ws::parse(reply);
|
const lastfm::XmlQuery lfm = lastfm::ws::parse(reply);
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
@ -338,26 +340,20 @@ void LastFMService::UpdateSubscriberStatusFinished() {
|
|||||||
|
|
||||||
connection_problems_ = false;
|
connection_problems_ = false;
|
||||||
QString subscriber = lfm["user"]["subscriber"].text();
|
QString subscriber = lfm["user"]["subscriber"].text();
|
||||||
const bool is_subscriber = (subscriber.toInt() == 1);
|
is_subscriber = (subscriber.toInt() == 1);
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup(kSettingsGroup);
|
settings.beginGroup(kSettingsGroup);
|
||||||
settings.setValue("Subscriber", is_subscriber);
|
settings.setValue("Subscriber", is_subscriber);
|
||||||
qLog(Info) << lastfm::ws::Username << "Subscriber status:" << is_subscriber;
|
qLog(Info) << lastfm::ws::Username << "Subscriber status:" << is_subscriber;
|
||||||
emit UpdatedSubscriberStatus(is_subscriber);
|
|
||||||
} catch (lastfm::ws::ParseError e) {
|
} catch (lastfm::ws::ParseError e) {
|
||||||
qLog(Error) << "Last.fm parse error: " << e.enumValue();
|
qLog(Error) << "Last.fm parse error: " << e.enumValue();
|
||||||
if (e.enumValue() == lastfm::ws::MalformedResponse) {
|
connection_problems_ = 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;
|
|
||||||
}
|
|
||||||
} catch (std::runtime_error& e) {
|
} catch (std::runtime_error& e) {
|
||||||
qLog(Error) << e.what();
|
qLog(Error) << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit UpdatedSubscriberStatus(is_subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl LastFMService::FixupUrl(const QUrl& url) {
|
QUrl LastFMService::FixupUrl(const QUrl& url) {
|
||||||
|
@ -27,32 +27,27 @@
|
|||||||
#include <QMovie>
|
#include <QMovie>
|
||||||
#include <QSettings>
|
#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)
|
LastFMSettingsPage::LastFMSettingsPage(SettingsDialog* dialog)
|
||||||
: SettingsPage(dialog),
|
: SettingsPage(dialog),
|
||||||
service_(static_cast<LastFMService*>(InternetModel::ServiceByName("Last.fm"))),
|
service_(static_cast<LastFMService*>(InternetModel::ServiceByName("Last.fm"))),
|
||||||
ui_(new Ui_LastFMSettingsPage),
|
ui_(new Ui_LastFMSettingsPage),
|
||||||
loading_icon_(new QMovie(kWaitingIcon, QByteArray(), this)),
|
|
||||||
waiting_for_auth_(false)
|
waiting_for_auth_(false)
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
ui_->busy->hide();
|
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
setWindowIcon(QIcon(":/last.fm/as.png"));
|
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(AuthenticationComplete(bool)), SLOT(AuthenticationComplete(bool)));
|
||||||
connect(service_, SIGNAL(UpdatedSubscriberStatus(bool)), SLOT(UpdatedSubscriberStatus(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()));
|
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"));
|
ui_->username->setMinimumWidth(QFontMetrics(QFont()).width("WWWWWWWWWWWW"));
|
||||||
resize(sizeHint());
|
resize(sizeHint());
|
||||||
}
|
}
|
||||||
@ -62,9 +57,9 @@ LastFMSettingsPage::~LastFMSettingsPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LastFMSettingsPage::Login() {
|
void LastFMSettingsPage::Login() {
|
||||||
ui_->busy->show();
|
|
||||||
waiting_for_auth_ = true;
|
waiting_for_auth_ = true;
|
||||||
|
|
||||||
|
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||||
service_->Authenticate(ui_->username->text(), ui_->password->text());
|
service_->Authenticate(ui_->username->text(), ui_->password->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +67,6 @@ void LastFMSettingsPage::AuthenticationComplete(bool success) {
|
|||||||
if (!waiting_for_auth_)
|
if (!waiting_for_auth_)
|
||||||
return; // Wasn't us that was waiting for auth
|
return; // Wasn't us that was waiting for auth
|
||||||
|
|
||||||
ui_->busy->hide();
|
|
||||||
waiting_for_auth_ = false;
|
waiting_for_auth_ = false;
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
@ -93,8 +87,6 @@ void LastFMSettingsPage::Load() {
|
|||||||
ui_->love_ban_->setChecked(service_->AreButtonsVisible());
|
ui_->love_ban_->setChecked(service_->AreButtonsVisible());
|
||||||
ui_->scrobble_button->setChecked(service_->IsScrobbleButtonVisible());
|
ui_->scrobble_button->setChecked(service_->IsScrobbleButtonVisible());
|
||||||
|
|
||||||
ui_->icon->setMovie(loading_icon_);
|
|
||||||
loading_icon_->start();
|
|
||||||
if (service_->IsAuthenticated()) {
|
if (service_->IsAuthenticated()) {
|
||||||
service_->UpdateSubscriberStatus();
|
service_->UpdateSubscriberStatus();
|
||||||
}
|
}
|
||||||
@ -103,21 +95,15 @@ void LastFMSettingsPage::Load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LastFMSettingsPage::UpdatedSubscriberStatus(bool is_subscriber) {
|
void LastFMSettingsPage::UpdatedSubscriberStatus(bool is_subscriber) {
|
||||||
const char* icon_path = is_subscriber ? kSubscribedIcon : kNotSubscribedIcon;
|
ui_->login_state->SetAccountTypeVisible(!is_subscriber);
|
||||||
ui_->icon->setPixmap(IconLoader::Load(icon_path).pixmap(16));
|
|
||||||
loading_icon_->stop();
|
|
||||||
|
|
||||||
if (is_subscriber) {
|
if (!is_subscriber) {
|
||||||
ui_->subscriber_warning->hide();
|
|
||||||
ui_->warn_icon->hide();
|
|
||||||
} else {
|
|
||||||
ui_->warn_icon->show();
|
|
||||||
if (service_->HasConnectionProblems()) {
|
if (service_->HasConnectionProblems()) {
|
||||||
ui_->subscriber_warning->setText(
|
ui_->login_state->SetAccountTypeText(
|
||||||
tr("Clementine couldn't fetch your subscription status since there are problems "
|
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."));
|
"with your connection. Played tracks will be cached and sent later to Last.fm."));
|
||||||
} else {
|
} else {
|
||||||
ui_->subscriber_warning->setText(
|
ui_->login_state->SetAccountTypeText(
|
||||||
tr("You will not be able to play Last.fm radio stations "
|
tr("You will not be able to play Last.fm radio stations "
|
||||||
"as you are not a Last.fm subscriber."));
|
"as you are not a Last.fm subscriber."));
|
||||||
}
|
}
|
||||||
@ -135,7 +121,7 @@ void LastFMSettingsPage::Save() {
|
|||||||
service_->ReloadSettings();
|
service_->ReloadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastFMSettingsPage::SignOut() {
|
void LastFMSettingsPage::Logout() {
|
||||||
ui_->username->clear();
|
ui_->username->clear();
|
||||||
ui_->password->clear();
|
ui_->password->clear();
|
||||||
RefreshControls(false);
|
RefreshControls(false);
|
||||||
@ -144,19 +130,15 @@ void LastFMSettingsPage::SignOut() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LastFMSettingsPage::RefreshControls(bool authenticated) {
|
void LastFMSettingsPage::RefreshControls(bool authenticated) {
|
||||||
ui_->groupBox->setVisible(!authenticated);
|
ui_->login_state->SetLoggedIn(authenticated ? LoginStateWidget::LoggedIn
|
||||||
ui_->sign_out->setVisible(authenticated);
|
: LoginStateWidget::LoggedOut,
|
||||||
if (authenticated) {
|
lastfm::ws::Username);
|
||||||
ui_->status->setText(QString(tr("You're logged in as <b>%1</b>")).arg(lastfm::ws::Username));
|
ui_->login_state->SetAccountTypeVisible(!authenticated);
|
||||||
} 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_->subscriber_warning->setText(
|
if (!authenticated) {
|
||||||
|
ui_->login_state->SetAccountTypeText(
|
||||||
tr("You can scrobble tracks for free, but only "
|
tr("You can scrobble tracks for free, but only "
|
||||||
"<span style=\" font-weight:600;\">paid subscribers</span> "
|
"<span style=\" font-weight:600;\">paid subscribers</span> "
|
||||||
"can stream Last.fm radio from Clementine."));
|
"can stream Last.fm radio from Clementine."));
|
||||||
ui_->subscriber_warning->show();
|
|
||||||
ui_->warn_icon->show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void Login();
|
void Login();
|
||||||
void AuthenticationComplete(bool success);
|
void AuthenticationComplete(bool success);
|
||||||
void SignOut();
|
void Logout();
|
||||||
void UpdatedSubscriberStatus(bool is_subscriber);
|
void UpdatedSubscriberStatus(bool is_subscriber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -15,64 +15,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="frame">
|
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||||
<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>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
@ -170,121 +113,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>BusyIndicator</class>
|
<class>LoginStateWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>widgets/busyindicator.h</header>
|
<header>widgets/loginstatewidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>username</tabstop>
|
<tabstop>username</tabstop>
|
||||||
<tabstop>password</tabstop>
|
<tabstop>password</tabstop>
|
||||||
<tabstop>login</tabstop>
|
<tabstop>login</tabstop>
|
||||||
<tabstop>sign_out</tabstop>
|
|
||||||
<tabstop>scrobble</tabstop>
|
<tabstop>scrobble</tabstop>
|
||||||
<tabstop>love_ban_</tabstop>
|
<tabstop>love_ban_</tabstop>
|
||||||
<tabstop>scrobble_button</tabstop>
|
<tabstop>scrobble_button</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<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>
|
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -30,23 +30,28 @@
|
|||||||
|
|
||||||
MagnatuneSettingsPage::MagnatuneSettingsPage(SettingsDialog* dialog)
|
MagnatuneSettingsPage::MagnatuneSettingsPage(SettingsDialog* dialog)
|
||||||
: SettingsPage(dialog),
|
: SettingsPage(dialog),
|
||||||
credentials_changed_(false),
|
|
||||||
network_(new NetworkAccessManager(this)),
|
network_(new NetworkAccessManager(this)),
|
||||||
ui_(new Ui_MagnatuneSettingsPage)
|
ui_(new Ui_MagnatuneSettingsPage),
|
||||||
|
logged_in_(false)
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
ui_->busy->hide();
|
|
||||||
setWindowIcon(QIcon(":/providers/magnatune.png"));
|
setWindowIcon(QIcon(":/providers/magnatune.png"));
|
||||||
|
|
||||||
connect(ui_->membership, SIGNAL(currentIndexChanged(int)), SLOT(MembershipChanged(int)));
|
connect(ui_->membership, SIGNAL(currentIndexChanged(int)), SLOT(MembershipChanged(int)));
|
||||||
|
|
||||||
connect(network_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
|
connect(network_, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
|
||||||
SLOT(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, 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() {
|
MagnatuneSettingsPage::~MagnatuneSettingsPage() {
|
||||||
@ -56,11 +61,14 @@ MagnatuneSettingsPage::~MagnatuneSettingsPage() {
|
|||||||
const char* kMagnatuneDownloadValidateUrl = "http://download.magnatune.com/";
|
const char* kMagnatuneDownloadValidateUrl = "http://download.magnatune.com/";
|
||||||
const char* kMagnatuneStreamingValidateUrl = "http://streaming.magnatune.com/";
|
const char* kMagnatuneStreamingValidateUrl = "http://streaming.magnatune.com/";
|
||||||
|
|
||||||
void MagnatuneSettingsPage::Login() {
|
void MagnatuneSettingsPage::UpdateLoginState() {
|
||||||
if (!credentials_changed_)
|
ui_->login_state->SetLoggedIn(logged_in_ ? LoginStateWidget::LoggedIn
|
||||||
return;
|
: LoginStateWidget::LoggedOut,
|
||||||
ui_->busy->show();
|
ui_->username->text());
|
||||||
|
ui_->login_state->SetAccountTypeVisible(!logged_in_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagnatuneSettingsPage::Login() {
|
||||||
MagnatuneService::MembershipType type =
|
MagnatuneService::MembershipType type =
|
||||||
MagnatuneService::MembershipType(ui_->membership->currentIndex());
|
MagnatuneService::MembershipType(ui_->membership->currentIndex());
|
||||||
|
|
||||||
@ -81,27 +89,33 @@ void MagnatuneSettingsPage::Login() {
|
|||||||
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
|
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
|
||||||
QNetworkRequest::AlwaysNetwork);
|
QNetworkRequest::AlwaysNetwork);
|
||||||
|
|
||||||
|
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||||
|
|
||||||
QNetworkReply* reply = network_->head(req);
|
QNetworkReply* reply = network_->head(req);
|
||||||
connect(reply, SIGNAL(finished()), SLOT(LoginFinished()));
|
connect(reply, SIGNAL(finished()), SLOT(LoginFinished()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MagnatuneSettingsPage::Logout() {
|
||||||
|
logged_in_ = false;
|
||||||
|
UpdateLoginState();
|
||||||
|
}
|
||||||
|
|
||||||
void MagnatuneSettingsPage::LoginFinished() {
|
void MagnatuneSettingsPage::LoginFinished() {
|
||||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
Q_ASSERT(reply);
|
Q_ASSERT(reply);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
ui_->busy->hide();
|
logged_in_ =
|
||||||
|
|
||||||
const bool success =
|
|
||||||
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200;
|
reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200;
|
||||||
credentials_changed_ = !success;
|
|
||||||
if (!success) {
|
if (!logged_in_) {
|
||||||
QMessageBox::warning(
|
QMessageBox::warning(
|
||||||
this, tr("Authentication failed"), tr("Your Magnatune credentials were incorrect"));
|
this, tr("Authentication failed"), tr("Your Magnatune credentials were incorrect"));
|
||||||
} else {
|
} else {
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
ui_->login->setEnabled(!success);
|
|
||||||
|
UpdateLoginState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagnatuneSettingsPage::AuthenticationRequired(
|
void MagnatuneSettingsPage::AuthenticationRequired(
|
||||||
@ -119,8 +133,11 @@ void MagnatuneSettingsPage::Load() {
|
|||||||
ui_->username->setText(s.value("username").toString());
|
ui_->username->setText(s.value("username").toString());
|
||||||
ui_->password->setText(s.value("password").toString());
|
ui_->password->setText(s.value("password").toString());
|
||||||
ui_->format->setCurrentIndex(s.value("format", MagnatuneService::Format_Ogg).toInt());
|
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() {
|
void MagnatuneSettingsPage::Save() {
|
||||||
@ -131,6 +148,7 @@ void MagnatuneSettingsPage::Save() {
|
|||||||
s.setValue("username", ui_->username->text());
|
s.setValue("username", ui_->username->text());
|
||||||
s.setValue("password", ui_->password->text());
|
s.setValue("password", ui_->password->text());
|
||||||
s.setValue("format", ui_->format->currentIndex());
|
s.setValue("format", ui_->format->currentIndex());
|
||||||
|
s.setValue("logged_in", logged_in_);
|
||||||
|
|
||||||
InternetModel::Service<MagnatuneService>()->ReloadSettings();
|
InternetModel::Service<MagnatuneService>()->ReloadSettings();
|
||||||
}
|
}
|
||||||
@ -141,7 +159,3 @@ void MagnatuneSettingsPage::MembershipChanged(int value) {
|
|||||||
ui_->login_container->setEnabled(enabled);
|
ui_->login_container->setEnabled(enabled);
|
||||||
ui_->preferences_group->setEnabled(enabled);
|
ui_->preferences_group->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagnatuneSettingsPage::CredentialsChanged() {
|
|
||||||
credentials_changed_ = true;
|
|
||||||
}
|
|
||||||
|
@ -37,15 +37,19 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void Login();
|
void Login();
|
||||||
|
void Logout();
|
||||||
void MembershipChanged(int value);
|
void MembershipChanged(int value);
|
||||||
void LoginFinished();
|
void LoginFinished();
|
||||||
void AuthenticationRequired(QNetworkReply* reply, QAuthenticator* auth);
|
void AuthenticationRequired(QNetworkReply* reply, QAuthenticator* auth);
|
||||||
void CredentialsChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool credentials_changed_;
|
void UpdateLoginState();
|
||||||
|
|
||||||
|
private:
|
||||||
NetworkAccessManager* network_;
|
NetworkAccessManager* network_;
|
||||||
Ui_MagnatuneSettingsPage* ui_;
|
Ui_MagnatuneSettingsPage* ui_;
|
||||||
|
|
||||||
|
bool logged_in_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAGNATUNESETTINGSPAGE_H
|
#endif // MAGNATUNESETTINGSPAGE_H
|
||||||
|
@ -14,12 +14,18 @@
|
|||||||
<string>Magnatune</string>
|
<string>Magnatune</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Account details</string>
|
<string>Account details</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout_3">
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -47,16 +53,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<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">
|
<widget class="QWidget" name="login_container" native="true">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -166,42 +162,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>BusyIndicator</class>
|
<class>LoginStateWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>widgets/busyindicator.h</header>
|
<header>widgets/loginstatewidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -98,7 +98,8 @@ void SpotifyServer::HandleMessage(const protobuf::SpotifyMessage& message) {
|
|||||||
queued_messages_.clear();
|
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()) {
|
} else if (message.has_playlists_updated()) {
|
||||||
emit PlaylistsUpdated(message.playlists_updated());
|
emit PlaylistsUpdated(message.playlists_updated());
|
||||||
} else if (message.has_load_playlist_response()) {
|
} else if (message.has_load_playlist_response()) {
|
||||||
|
@ -50,7 +50,8 @@ public:
|
|||||||
int server_port() const;
|
int server_port() const;
|
||||||
|
|
||||||
signals:
|
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 PlaylistsUpdated(const protobuf::Playlists& playlists);
|
||||||
|
|
||||||
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
|
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
|
||||||
|
@ -46,7 +46,8 @@ SpotifyService::SpotifyService(InternetModel* parent)
|
|||||||
login_task_id_(0),
|
login_task_id_(0),
|
||||||
pending_search_playlist_(NULL),
|
pending_search_playlist_(NULL),
|
||||||
context_menu_(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.
|
// Build the search path for the binary blob.
|
||||||
// Look for one distributed alongside clementine first, then check in the
|
// Look for one distributed alongside clementine first, then check in the
|
||||||
// user's home directory for any that have been downloaded.
|
// user's home directory for any that have been downloaded.
|
||||||
@ -124,23 +125,43 @@ QModelIndex SpotifyService::GetCurrentIndex() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SpotifyService::Login(const QString& username, const QString& password) {
|
void SpotifyService::Login(const QString& username, const QString& password) {
|
||||||
delete server_;
|
Logout();
|
||||||
delete blob_process_;
|
|
||||||
server_ = NULL;
|
|
||||||
blob_process_ = NULL;
|
|
||||||
|
|
||||||
EnsureServerCreated(username, password);
|
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_) {
|
if (login_task_id_) {
|
||||||
model()->task_manager()->SetTaskFinished(login_task_id_);
|
model()->task_manager()->SetTaskFinished(login_task_id_);
|
||||||
login_task_id_ = 0;
|
login_task_id_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
login_state_ = LoginState_LoggedIn;
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
QMessageBox::warning(NULL, tr("Spotify login error"), error, QMessageBox::Close);
|
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);
|
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,
|
void SpotifyService::EnsureServerCreated(const QString& username,
|
||||||
const QString& password) {
|
const QString& password) {
|
||||||
if (server_ && blob_process_) {
|
if (server_ && blob_process_) {
|
||||||
@ -164,7 +192,8 @@ void SpotifyService::EnsureServerCreated(const QString& username,
|
|||||||
delete server_;
|
delete server_;
|
||||||
server_ = new SpotifyServer(this);
|
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)),
|
connect(server_, SIGNAL(PlaylistsUpdated(protobuf::Playlists)),
|
||||||
SLOT(PlaylistsUpdated(protobuf::Playlists)));
|
SLOT(PlaylistsUpdated(protobuf::Playlists)));
|
||||||
connect(server_, SIGNAL(InboxLoaded(protobuf::LoadPlaylistResponse)),
|
connect(server_, SIGNAL(InboxLoaded(protobuf::LoadPlaylistResponse)),
|
||||||
@ -593,3 +622,12 @@ void SpotifyService::SyncPlaylistProgress(
|
|||||||
void SpotifyService::ShowConfig() {
|
void SpotifyService::ShowConfig() {
|
||||||
emit OpenSettingsAtPage(SettingsDialog::Page_Spotify);
|
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,
|
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* kServiceName;
|
||||||
static const char* kSettingsGroup;
|
static const char* kSettingsGroup;
|
||||||
static const char* kBlobDownloadUrl;
|
static const char* kBlobDownloadUrl;
|
||||||
static const int kSearchDelayMsec;
|
static const int kSearchDelayMsec;
|
||||||
|
|
||||||
|
void ReloadSettings();
|
||||||
|
|
||||||
QStandardItem* CreateRootItem();
|
QStandardItem* CreateRootItem();
|
||||||
void LazyPopulate(QStandardItem* parent);
|
void LazyPopulate(QStandardItem* parent);
|
||||||
void ShowContextMenu(const QModelIndex& index, const QPoint& global_pos);
|
void ShowContextMenu(const QModelIndex& index, const QPoint& global_pos);
|
||||||
void ItemDoubleClicked(QStandardItem* item);
|
void ItemDoubleClicked(QStandardItem* item);
|
||||||
PlaylistItem::Options playlistitem_options() const;
|
PlaylistItem::Options playlistitem_options() const;
|
||||||
|
|
||||||
|
void Logout();
|
||||||
void Login(const QString& username, const QString& password);
|
void Login(const QString& username, const QString& password);
|
||||||
void Search(const QString& text, Playlist* playlist, bool now = false);
|
void Search(const QString& text, Playlist* playlist, bool now = false);
|
||||||
Q_INVOKABLE void LoadImage(const QUrl& url);
|
Q_INVOKABLE void LoadImage(const QUrl& url);
|
||||||
@ -55,6 +67,9 @@ public:
|
|||||||
bool IsBlobInstalled() const;
|
bool IsBlobInstalled() const;
|
||||||
void InstallBlob();
|
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);
|
static void SongFromProtobuf(const protobuf::Track& track, Song* song);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -77,7 +92,8 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void BlobProcessError(QProcess::ProcessError error);
|
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 PlaylistsUpdated(const protobuf::Playlists& response);
|
||||||
void InboxLoaded(const protobuf::LoadPlaylistResponse& response);
|
void InboxLoaded(const protobuf::LoadPlaylistResponse& response);
|
||||||
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
|
void StarredLoaded(const protobuf::LoadPlaylistResponse& response);
|
||||||
@ -122,6 +138,8 @@ private:
|
|||||||
int inbox_sync_id_;
|
int inbox_sync_id_;
|
||||||
int starred_sync_id_;
|
int starred_sync_id_;
|
||||||
QMap<int, int> playlist_sync_ids_;
|
QMap<int, int> playlist_sync_ids_;
|
||||||
|
|
||||||
|
LoginState login_state_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,8 +37,6 @@ SpotifySettingsPage::SpotifySettingsPage(SettingsDialog* dialog)
|
|||||||
validated_(false)
|
validated_(false)
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
ui_->busy->hide();
|
|
||||||
ui_->warn_icon->setPixmap(IconLoader::Load("dialog-warning").pixmap(16));
|
|
||||||
|
|
||||||
setWindowIcon(QIcon(":/icons/svg/spotify.svg"));
|
setWindowIcon(QIcon(":/icons/svg/spotify.svg"));
|
||||||
|
|
||||||
@ -48,10 +46,16 @@ SpotifySettingsPage::SpotifySettingsPage(SettingsDialog* dialog)
|
|||||||
|
|
||||||
connect(ui_->download_blob, SIGNAL(clicked()), SLOT(DownloadBlob()));
|
connect(ui_->download_blob, SIGNAL(clicked()), SLOT(DownloadBlob()));
|
||||||
connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
|
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(LoginFinished(bool)), SLOT(LoginFinished(bool)));
|
||||||
connect(service_, SIGNAL(BlobStateChanged()), SLOT(BlobStateChanged()));
|
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();
|
BlobStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,15 +86,12 @@ void SpotifySettingsPage::Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ui_->username->text() == original_username_ &&
|
if (ui_->username->text() == original_username_ &&
|
||||||
ui_->password->text() == original_password_) {
|
ui_->password->text() == original_password_ &&
|
||||||
|
service_->login_state() == SpotifyService::LoginState_LoggedIn) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validated_) {
|
ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_->busy->show();
|
|
||||||
service_->Login(ui_->username->text(), ui_->password->text());
|
service_->Login(ui_->username->text(), ui_->password->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +105,8 @@ void SpotifySettingsPage::Load() {
|
|||||||
ui_->username->setText(original_username_);
|
ui_->username->setText(original_username_);
|
||||||
ui_->password->setText(original_password_);
|
ui_->password->setText(original_password_);
|
||||||
validated_ = false;
|
validated_ = false;
|
||||||
|
|
||||||
|
UpdateLoginState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpotifySettingsPage::Save() {
|
void SpotifySettingsPage::Save() {
|
||||||
@ -112,15 +115,41 @@ void SpotifySettingsPage::Save() {
|
|||||||
|
|
||||||
s.setValue("username", ui_->username->text());
|
s.setValue("username", ui_->username->text());
|
||||||
s.setValue("password", ui_->password->text());
|
s.setValue("password", ui_->password->text());
|
||||||
|
|
||||||
InternetModel::Service<SpotifyService>()->ReloadSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpotifySettingsPage::LoginFinished(bool success) {
|
void SpotifySettingsPage::LoginFinished(bool success) {
|
||||||
validated_ = success;
|
validated_ = success;
|
||||||
ui_->busy->hide();
|
|
||||||
ui_->login->setEnabled(!success);
|
|
||||||
|
|
||||||
// Save the settings
|
|
||||||
Save();
|
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:
|
private slots:
|
||||||
void Login();
|
void Login();
|
||||||
void LoginFinished(bool success);
|
void LoginFinished(bool success);
|
||||||
|
void Logout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateLoginState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetworkAccessManager* network_;
|
NetworkAccessManager* network_;
|
||||||
|
@ -14,50 +14,15 @@
|
|||||||
<string>Spotify</string>
|
<string>Spotify</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="LoginStateWidget" name="login_state" native="true"/>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="account_group">
|
<widget class="QGroupBox" name="account_group">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Account details</string>
|
<string>Account details</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<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>
|
<item>
|
||||||
<widget class="QWidget" name="login_container" native="true">
|
<widget class="QWidget" name="login_container" native="true">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
@ -206,42 +171,14 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>BusyIndicator</class>
|
<class>LoginStateWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>widgets/busyindicator.h</header>
|
<header>widgets/loginstatewidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -30,11 +30,14 @@ class SettingsPage : public QWidget {
|
|||||||
public:
|
public:
|
||||||
SettingsPage(SettingsDialog* dialog);
|
SettingsPage(SettingsDialog* dialog);
|
||||||
|
|
||||||
|
// Return false to grey out the page's item in the list.
|
||||||
virtual bool IsEnabled() const { return true; }
|
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 Load() = 0;
|
||||||
virtual void Save() = 0;
|
virtual void Save() = 0;
|
||||||
|
|
||||||
|
// The dialog that this page belongs to.
|
||||||
SettingsDialog* dialog() const { return dialog_; }
|
SettingsDialog* dialog() const { return dialog_; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -39,6 +39,7 @@ void BusyIndicator::Init(const QString& text) {
|
|||||||
icon->setMinimumSize(16, 16);
|
icon->setMinimumSize(16, 16);
|
||||||
|
|
||||||
label_->setWordWrap(true);
|
label_->setWordWrap(true);
|
||||||
|
label_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
|
||||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
@ -63,7 +64,10 @@ void BusyIndicator::hideEvent(QHideEvent*) {
|
|||||||
|
|
||||||
void BusyIndicator::set_text(const QString& text) {
|
void BusyIndicator::set_text(const QString& text) {
|
||||||
label_->setText(text);
|
label_->setText(text);
|
||||||
if (text.isEmpty())
|
label_->setVisible(!text.isEmpty());
|
||||||
label_->hide();
|
}
|
||||||
|
|
||||||
|
QString BusyIndicator::text() const {
|
||||||
|
return label_->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ class QMovie;
|
|||||||
|
|
||||||
class BusyIndicator : public QWidget {
|
class BusyIndicator : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString text READ text WRITE set_text)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BusyIndicator(const QString& text, QWidget* parent = 0);
|
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