Initial support from premium digitally imported streams.

NOTE: This has *not* been tested - as I have no account!!!
This commit is contained in:
craig.p.drummond
2013-07-01 21:03:28 +00:00
committed by craig.p.drummond
parent dffe99f038
commit 811c64d507
11 changed files with 712 additions and 34 deletions

View File

@@ -92,12 +92,12 @@ set(CANTATA_SRCS gui/application.cpp gui/main.cpp gui/initialsettingswizard.cpp
gui/settings.cpp gui/covers.cpp gui/filesettings.cpp gui/interfacesettings.cpp gui/playbacksettings.cpp
gui/serversettings.cpp gui/librarypage.cpp gui/albumspage.cpp gui/folderpage.cpp gui/playlistspage.cpp gui/trayitem.cpp
gui/cachesettings.cpp gui/coverdialog.cpp gui/stdactions.cpp
streams/streamspage.cpp streams/streamdialog.cpp streams/streamfetcher.cpp
streams/streamspage.cpp streams/streamdialog.cpp streams/streamfetcher.cpp streams/digitallyimportedsettings.cpp
models/musiclibraryitemroot.cpp models/musiclibraryitemartist.cpp models/musiclibraryitemalbum.cpp models/musiclibrarymodel.cpp
models/musiclibraryproxymodel.cpp models/playlistsmodel.cpp models/playlistsproxymodel.cpp models/playqueuemodel.cpp
models/playqueueproxymodel.cpp models/dirviewmodel.cpp models/dirviewproxymodel.cpp models/dirviewitem.cpp models/dirviewitemdir.cpp
models/streamsmodel.cpp models/streamsproxymodel.cpp models/albumsmodel.cpp models/albumsproxymodel.cpp models/proxymodel.cpp
models/actionmodel.cpp
models/actionmodel.cpp models/digitallyimported.cpp
mpd/mpdconnection.cpp mpd/mpdparseutils.cpp mpd/mpdstats.cpp mpd/mpdstatus.cpp mpd/song.cpp mpd/mpduser.cpp
dynamic/dynamic.cpp dynamic/dynamicpage.cpp dynamic/dynamicproxymodel.cpp dynamic/dynamicruledialog.cpp dynamic/dynamicrulesdialog.cpp
widgets/treeview.cpp widgets/listview.cpp widgets/itemview.cpp widgets/autohidingsplitter.cpp widgets/timeslider.cpp
@@ -114,10 +114,10 @@ set(CANTATA_MOC_HDRS
gui/initialsettingswizard.h gui/mainwindow.h gui/settings.h gui/covers.h gui/folderpage.h gui/librarypage.h gui/albumspage.h
gui/playlistspage.h gui/playbacksettings.h gui/serversettings.h gui/preferencesdialog.h gui/filesettings.h
gui/interfacesettings.h gui/cachesettings.h gui/trayitem.h gui/coverdialog.h
streams/streamspage.h streams/streamdialog.h streams/streamfetcher.h
streams/streamspage.h streams/streamdialog.h streams/streamfetcher.h streams/digitallyimportedsettings.h
models/musiclibrarymodel.h models/musiclibraryproxymodel.h models/playlistsmodel.h models/playlistsproxymodel.h models/playqueuemodel.h
models/playqueueproxymodel.h models/dirviewmodel.h models/dirviewproxymodel.h models/albumsmodel.h models/streamsmodel.h
models/actionmodel.h
models/actionmodel.h models/digitallyimported.h
mpd/mpdconnection.h mpd/mpdstats.h mpd/mpdstatus.h
dynamic/dynamic.h dynamic/dynamicpage.h dynamic/dynamicruledialog.h dynamic/dynamicrulesdialog.h
widgets/treeview.h widgets/listview.h widgets/itemview.h widgets/autohidingsplitter.h widgets/timeslider.h widgets/actionlabel.h
@@ -131,7 +131,7 @@ set(CANTATA_MOC_HDRS
set(CANTATA_UIS
gui/initialsettingswizard.ui gui/mainwindow.ui gui/folderpage.ui gui/librarypage.ui gui/albumspage.ui gui/playlistspage.ui
gui/filesettings.ui gui/interfacesettings.ui gui/playbacksettings.ui gui/serversettings.ui gui/coverdialog.ui
streams/streamspage.ui
streams/streamspage.ui streams/digitallyimportedsettings.ui
dynamic/dynamicpage.ui dynamic/dynamicrule.ui dynamic/dynamicrules.ui
context/togglelist.ui context/othersettings.ui
widgets/itemview.ui)

View File

@@ -0,0 +1,207 @@
/*
* Cantata
*
* Copyright (c) 2011-2013 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "digitallyimported.h"
#include "settings.h"
#include "networkaccessmanager.h"
#include "qjson/parser.h"
#include "localize.h"
#include <QNetworkRequest>
#include <QTime>
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KGlobal>
K_GLOBAL_STATIC(DigitallyImported, instance)
#endif
static const char * constDiGroup="DigitallyImported";
static const QStringList constPremiumValues=QStringList() << QLatin1String("premium_high") << QLatin1String("premium_medium") << QLatin1String("premium");
static const QUrl constAuthUrl(QLatin1String("http://api.audioaddict.com/v1/di/members/authenticate"));
const QString DigitallyImported::constApiUserName=QLatin1String("ephemeron");
const QString DigitallyImported::constApiPassword=QLatin1String("dayeiph0ne@pp");
const QString DigitallyImported::constPublicValue=QLatin1String("public3");
DigitallyImported * DigitallyImported::self()
{
#ifdef ENABLE_KDE_SUPPORT
return instance;
#else
static DigitallyImported *instance=0;
if(!instance) {
instance=new DigitallyImported;
}
return instance;
#endif
}
DigitallyImported::DigitallyImported()
: job(0)
, streamType(0)
{
load();
}
DigitallyImported::~DigitallyImported()
{
save();
}
void DigitallyImported::login()
{
if (job) {
job->deleteLater();
job=0;
}
QNetworkRequest req(constAuthUrl);
addAuthHeader(req);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
job=NetworkAccessManager::self()->post(req, "username="+QUrl::toPercentEncoding(userName)+"&password="+QUrl::toPercentEncoding(password));
connect(job, SIGNAL(finished()), SLOT(loginResponse()));
}
void DigitallyImported::addAuthHeader(QNetworkRequest &req) const
{
#if QT_VERSION < 0x050000
req.setRawHeader("Authorization", "Basic "+QString("%1:%2").arg(constApiUserName, constApiPassword).toAscii().toBase64());
#else
req.setRawHeader("Authorization", "Basic "+QString("%1:%2").arg(constApiUserName, constApiPassword).toLatin1().toBase64());
#endif
}
void DigitallyImported::load()
{
#ifdef ENABLE_KDE_SUPPORT
KConfigGroup cfg(KGlobal::config(), constDiGroup);
#else
QSettings cfg;
cfg.beginGroup(constDiGroup);
#endif
userName=GET_STRING("userName", userName);
password=GET_STRING("password", password);
listenHash=GET_STRING("listenHash", listenHash);
streamType=GET_INT("streamType", streamType);
QString ex=GET_STRING("expires", QString());
status=i18n("Not logged in");
if (ex.isEmpty()) {
listenHash=QString();
} else {
expires=QDateTime::fromString(ex, Qt::ISODate);
// If we have expired, or are about to expire in 5 minutes, then clear the hash...
if (QDateTime::currentDateTime().secsTo(expires)<(5*60)) {
listenHash=QString();
} else if (!listenHash.isEmpty()) {
status=i18n("Logged in");
}
}
}
void DigitallyImported::save()
{
#ifdef ENABLE_KDE_SUPPORT
KConfigGroup cfg(KGlobal::config(), constDiGroup);
#else
QSettings cfg;
cfg.beginGroup(constDiGroup);
#endif
SET_VALUE("userName", userName);
SET_VALUE("password", password);
SET_VALUE("listenHash", listenHash);
SET_VALUE("streamType", streamType);
SET_VALUE("expires", expires.toString(Qt::ISODate));
#ifndef ENABLE_KDE_SUPPORT
cfg.endGroup();
#endif
CFG_SYNC;
}
QString DigitallyImported::modifyUrl(const QString &u) const
{
if (listenHash.isEmpty()) {
return u;
}
QString premValue=constPremiumValues.at(streamType>0 && streamType<constPremiumValues.count() ? streamType : 0);
QString url=u;
return url.replace(constPublicValue, premValue)+QLatin1String("?hash=")+listenHash;
}
void DigitallyImported::loginResponse()
{
QNetworkReply *reply=dynamic_cast<QNetworkReply *>(sender());
if (!reply) {
return;
}
reply->deleteLater();
if (reply!=job) {
return;
}
job=0;
status=listenHash=QString();
const int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (403==httpStatus) {
status=reply->readAll();
emit loginStatus(false, status);
return;
} else if (200!=httpStatus) {
status=i18n("Unknown error");
emit loginStatus(false, status);
return;
}
QJson::Parser parser;
QVariantMap data = parser.parse(reply).toMap();
if (!data.contains("subscriptions")) {
status=i18n("No subscriptions");
emit loginStatus(false, status);
return;
}
QVariantList subscriptions = data.value("subscriptions", QVariantList()).toList();
if (subscriptions.isEmpty() || QLatin1String("active")!=subscriptions[0].toMap().value("status").toString()) {
status=i18n("You do not have an active subscription");
emit loginStatus(false, status);
return;
}
if (!subscriptions[0].toMap().contains("expires_on") || !data.contains("listen_key")) {
status=i18n("Unknown error");
emit loginStatus(false, status);
return;
}
QDateTime ex = QDateTime::fromString(subscriptions[0].toMap()["expires_on"].toString(), Qt::ISODate);
QString lh = data["listen_key"].toString();
if (ex!=expires || lh!=listenHash) {
expires=ex;
listenHash=lh;
save();
}
status=i18n("Logged in (expiry:%1)").arg(expires.toString(Qt::ISODate));
emit loginStatus(true, status);
}

View File

@@ -0,0 +1,83 @@
/*
* Cantata
*
* Copyright (c) 2011-2013 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef DIGITALLYIMPORTED_H
#define DIGITALLYIMPORTED_H
#include <QObject>
#include <QDateTime>
class QNetworkRequest;
class QNetworkReply;
class DigitallyImported : public QObject
{
Q_OBJECT
public:
static const QString constApiUserName;
static const QString constApiPassword;
static const QString constPublicValue;
static DigitallyImported * self();
DigitallyImported();
~DigitallyImported();
void addAuthHeader(QNetworkRequest &req) const;
void load();
void save();
bool haveAccount() const { return !userName.isEmpty() && !password.isEmpty(); }
bool loggedIn() const { return !listenHash.isEmpty(); }
const QString & user() const { return userName; }
const QString & pass() const { return password; }
int audioType() const { return streamType; }
const QDateTime & sessionExpiry() const { return expires; }
void setUser(const QString &u) { userName=u; }
void setPass(const QString &p) { password=p; }
void setAudioType(int a) { streamType=a; }
const QString & statusString() const { return status; }
QString modifyUrl(const QString &u) const;
public Q_SLOTS:
void login();
Q_SIGNALS:
void loginStatus(bool ok, const QString &msg);
private Q_SLOTS:
void loginResponse();
private:
QNetworkReply *job;
QString status;
QString userName;
QString password;
QString listenHash;
QDateTime expires;
int streamType;
};
#endif

View File

@@ -34,6 +34,7 @@
#include "itemview.h"
#include "action.h"
#include "stdactions.h"
#include "digitallyimported.h"
#include "qjson/parser.h"
#include "qtiocompressor/qtiocompressor.h"
#include <QModelIndex>
@@ -44,13 +45,14 @@
#include <QFile>
#include <QFileInfo>
#include <QTimer>
#if QT_VERSION >= 0x050000
#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif
#ifdef Q_OS_WIN
#include <QDesktopServices>
#endif
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KGlobal>
K_GLOBAL_STATIC(StreamsModel, instance)
#endif
@@ -82,9 +84,7 @@ static QString constJazzRadioUrl=QLatin1String("http://www.jazzradio.com");
static QString constRockRadioUrl=QLatin1String("http://www.rockradio.com");
static QString constSkyFmUrl=QLatin1String("http://www.sky.fm");
static QStringList constDiUrls=QStringList() << constDigitiallyImportedUrl << constJazzRadioUrl << constSkyFmUrl << constRockRadioUrl;
static const char * constDiApiUsername="ephemeron";
static const char * constDiApiPassword="dayeiph0ne@pp";
//static const QString constDiAuthUrl=QLatin1String("http://api.audioaddict.com/v1/%1/members/authenticate");
static const QString constDiChannelListHost=QLatin1String("api.v2.audioaddict.com");
static const QString constDiChannelListUrl=QLatin1String("http://")+constDiChannelListHost+("/v1/%1/mobile/batch_update?asset_group_key=mobile_icons&stream_set_key=");
static const QString constDiStdUrl=QLatin1String("http://%1/public3/%2.pls");
@@ -283,11 +283,7 @@ void StreamsModel::fetchMore(const QModelIndex &index)
QNetworkRequest req;
if (constDiUrls.contains(cat->url)) {
req=QNetworkRequest(constDiChannelListUrl.arg(cat->url.split(".").at(1)));
#if QT_VERSION < 0x050000
req.setRawHeader("Authorization", "Basic "+QString("%1:%2").arg(constDiApiUsername, constDiApiPassword).toAscii().toBase64());
#else
req.setRawHeader("Authorization", "Basic "+QString("%1:%2").arg(constDiApiUsername, constDiApiPassword).toLatin1().toBase64());
#endif
DigitallyImported::self()->addAuthHeader(req);
} else if (QUrl(item->url).host()==constShoutCastHost) {
req=QNetworkRequest(cat->url);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
@@ -459,13 +455,19 @@ QString StreamsModel::modifyUrl(const QString &u, bool addPrefix, const QString
return MPDParseUtils::addStreamName(!addPrefix || !u.startsWith("http:") ? u : (constPrefix+u), name);
}
static QString addDiHash(const StreamsModel::Item *item)
{
return item->parent && constDiUrls.contains(item->parent->url)
? DigitallyImported::self()->modifyUrl(item->url) : item->url;
}
static void filenames(QStringList &fn, bool addPrefix, const StreamsModel::CategoryItem *cat)
{
foreach (const StreamsModel::Item *i, cat->children) {
if (i->isCategory()) {
filenames(fn, addPrefix, static_cast<const StreamsModel::CategoryItem *>(i));
::filenames(fn, addPrefix, static_cast<const StreamsModel::CategoryItem *>(i));
} else if (!fn.contains(i->url) && StreamsModel::validProtocol(i->url)) {
fn << StreamsModel::modifyUrl(i->url, addPrefix, i->name);
fn << StreamsModel::modifyUrl(addDiHash(i), addPrefix, i->name);
}
}
}
@@ -479,7 +481,7 @@ QStringList StreamsModel::filenames(const QModelIndexList &indexes, bool addPref
if (item->isCategory()) {
::filenames(fnames, addPrefix, static_cast<const StreamsModel::CategoryItem *>(item));
} else if (!fnames.contains(item->url) && validProtocol(item->url)) {
fnames << modifyUrl(item->url, addPrefix, item->name);
fnames << modifyUrl(addDiHash(item), addPrefix, item->name);
}
}

View File

@@ -28,6 +28,7 @@
#include <QList>
#include <QMap>
#include <QIcon>
#include <QDateTime>
class QNetworkReply;
class QXmlStreamReader;

View File

@@ -0,0 +1,126 @@
/*
* Cantata
*
* Copyright (c) 2011-2013 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "digitallyimportedsettings.h"
#include "digitallyimported.h"
#include "localize.h"
#include "buddylabel.h"
#include "lineedit.h"
#include <QPushButton>
#include <QComboBox>
DigitallyImportedSettings::DigitallyImportedSettings(QWidget *parent)
: Dialog(parent)
{
setButtons(Ok|Cancel);
setCaption(i18n("Digitally Imported Settings"));
QWidget *mainWidet = new QWidget(this);
setupUi(mainWidet);
setMainWidget(mainWidet);
audio->addItem(i18n("MP3 256k"), 0);
audio->addItem(i18n("AAC 64k"), 1);
audio->addItem(i18n("AAC 128k"), 2);
connect(loginButton, SIGNAL(clicked()), this, SLOT(login()));
connect(DigitallyImported::self(), SIGNAL(loginStatus(bool,QString)), SLOT(loginStatus(bool,QString)));
adjustSize();
int h=fontMetrics().height();
resize(h*30, height());
}
void DigitallyImportedSettings::show()
{
prevUser=DigitallyImported::self()->user();
prevPass=DigitallyImported::self()->pass();
wasLoggedIn=DigitallyImported::self()->loggedIn();
prevAudioType=DigitallyImported::self()->audioType();
if (DigitallyImported::self()->sessionExpiry().isValid()) {
expiryLabel->setText(DigitallyImported::self()->sessionExpiry().toString(Qt::ISODate));
} else {
expiryLabel->setText(QString());
}
user->setText(prevUser);
pass->setText(prevPass);
for (int i=0; i<audio->count(); ++i) {
if (audio->itemData(i).toInt()==DigitallyImported::self()->audioType()) {
audio->setCurrentIndex(i);
break;
}
}
loginStatusLabel->setText(DigitallyImported::self()->statusString());
if (QDialog::Accepted==Dialog::exec()) {
QString u=user->text().trimmed();
QString p=pass->text().trimmed();
int at=audio->itemData(audio->currentIndex()).toInt();
bool changed=false;
bool needToLogin=false;
if (u!=DigitallyImported::self()->user()) {
DigitallyImported::self()->setUser(u);
needToLogin=changed=true;
}
if (p!=DigitallyImported::self()->pass()) {
DigitallyImported::self()->setPass(p);
needToLogin=changed=true;
}
if (DigitallyImported::self()->audioType()!=at) {
DigitallyImported::self()->setAudioType(at);
changed=true;
}
if (needToLogin) {
DigitallyImported::self()->login();
}
if (changed) {
DigitallyImported::self()->save();
}
} else {
DigitallyImported::self()->setUser(prevUser);
DigitallyImported::self()->setPass(prevPass);
DigitallyImported::self()->setAudioType(prevAudioType);
if (wasLoggedIn) {
DigitallyImported::self()->login();
}
}
}
void DigitallyImportedSettings::login()
{
loginStatusLabel->setText(i18n("Logging in..."));
DigitallyImported::self()->setUser(user->text().trimmed());
DigitallyImported::self()->setPass(pass->text().trimmed());
DigitallyImported::self()->login();
}
void DigitallyImportedSettings::loginStatus(bool, const QString &msg)
{
loginStatusLabel->setText(msg);
if (DigitallyImported::self()->sessionExpiry().isValid()) {
expiryLabel->setText(DigitallyImported::self()->sessionExpiry().toString(Qt::ISODate));
} else {
expiryLabel->setText(QString());
}
}

View File

@@ -0,0 +1,54 @@
/*
* Cantata
*
* Copyright (c) 2011-2013 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef DIGITALLYIMPORTED_SETTINGS_H
#define DIGITALLYIMPORTED_SETTINGS_H
#include "dialog.h"
#include "ui_digitallyimportedsettings.h"
class LineEdit;
class QComboBox;
class QPushButton;
class QLabel;
class DigitallyImportedSettings : public Dialog, public Ui::DigitallyImportedSettings
{
Q_OBJECT
public:
DigitallyImportedSettings(QWidget *parent);
void show();
private Q_SLOTS:
void login();
void loginStatus(bool, const QString &msg);
private:
bool wasLoggedIn;
QString prevUser;
QString prevPass;
int prevAudioType;
};
#endif

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DigitallyImportedSettings</class>
<widget class="QWidget" name="DigitallyImportedSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>518</width>
<height>252</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="QLabel" name="label">
<property name="text">
<string>To listen to higher quality streams, without advertisments, a premium account is required.&lt;br&gt;&lt;a href=\&quot;http://www.di.fm/premium/\&quot;&gt;Upgrade to Premium&lt;/a&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Premium Account</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="BuddyLabel" name="label_2">
<property name="text">
<string>Username:</string>
</property>
<property name="buddy">
<cstring>user</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LineEdit" name="user"/>
</item>
<item row="1" column="0">
<widget class="BuddyLabel" name="label_3">
<property name="text">
<string>Password:</string>
</property>
<property name="buddy">
<cstring>pass</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LineEdit" name="pass">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="BuddyLabel" name="label_4">
<property name="text">
<string>Stream type:</string>
</property>
<property name="buddy">
<cstring>audio</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="audio"/>
</item>
<item row="3" column="0">
<widget class="BuddyLabel" name="label_5">
<property name="text">
<string>Status:</string>
</property>
<property name="buddy">
<cstring>loginButton</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="loginButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Login</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="loginStatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Session expiry:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="expiryLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LineEdit</class>
<extends>QLineEdit</extends>
<header>lineedit.h</header>
</customwidget>
<customwidget>
<class>BuddyLabel</class>
<extends>QLabel</extends>
<header>buddylabel.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -33,6 +33,8 @@
#include "settings.h"
#include "streamsmodel.h"
#include "statuslabel.h"
#include "digitallyimported.h"
#include "digitallyimportedsettings.h"
#include <QToolButton>
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KFileDialog>
@@ -55,7 +57,7 @@ StreamsPage::StreamsPage(QWidget *p)
addAction = ActionCollection::get()->createAction("addstream", i18n("Add New Stream To Favourites"), Icons::self()->addRadioStreamIcon);
addToFavouritesAction = ActionCollection::get()->createAction("addtofavourites", i18n("Add Stream To Favourites"), Icons::self()->addRadioStreamIcon);
editAction = ActionCollection::get()->createAction("editstream", i18n("Edit"), Icons::self()->editIcon);
Action *settingsAct = new Action(i18n("Digitally Imported Settings"), this);
replacePlayQueue->setDefaultAction(StdActions::self()->replacePlayQueueAction);
// connect(view, SIGNAL(itemsSelected(bool)), addToPlaylist, SLOT(setEnabled(bool)));
connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(itemDoubleClicked(const QModelIndex &)));
@@ -66,16 +68,21 @@ StreamsPage::StreamsPage(QWidget *p)
connect(editAction, SIGNAL(triggered(bool)), this, SLOT(edit()));
connect(importAction, SIGNAL(triggered(bool)), this, SLOT(importXml()));
connect(exportAction, SIGNAL(triggered(bool)), this, SLOT(exportXml()));
connect(settingsAct, SIGNAL(triggered(bool)), this, SLOT(diSettings()));
connect(StreamsModel::self(), SIGNAL(error(const QString &)), this, SIGNAL(error(const QString &)));
connect(StreamsModel::self(), SIGNAL(loading()), view, SLOT(showSpinner()));
connect(StreamsModel::self(), SIGNAL(loaded()), view, SLOT(hideSpinner()));
connect(MPDConnection::self(), SIGNAL(dirChanged()), SLOT(mpdDirChanged()));
connect(DigitallyImported::self(), SIGNAL(loginStatus(bool,QString)), SLOT(updateDiStatus()));
QMenu *menu=new QMenu(this);
menu->addAction(addAction);
menu->addAction(StdActions::self()->removeAction);
menu->addAction(editAction);
menu->addSeparator();
menu->addAction(importAction);
menu->addAction(exportAction);
menu->addSeparator();
menu->addAction(settingsAct);
menuButton->setMenu(menu);
Icon::init(replacePlayQueue);
@@ -94,6 +101,7 @@ StreamsPage::StreamsPage(QWidget *p)
infoLabel->hide();
infoLabel->setType(StatusLabel::Locked);
updateDiStatus();
}
StreamsPage::~StreamsPage()
@@ -182,6 +190,12 @@ void StreamsPage::itemDoubleClicked(const QModelIndex &index)
}
}
void StreamsPage::diSettings()
{
DigitallyImportedSettings(this).show();
updateDiStatus();
}
void StreamsPage::importXml()
{
if (!StreamsModel::self()->isFavoritesWritable()) {
@@ -397,3 +411,13 @@ void StreamsPage::controlActions()
StdActions::self()->addWithPriorityAction->setEnabled(selected.count());
menuButton->controlState();
}
void StreamsPage::updateDiStatus()
{
if (DigitallyImported::self()->user().isEmpty() || DigitallyImported::self()->pass().isEmpty()) {
diStatusLabel->setVisible(false);
} else {
diStatusLabel->setVisible(true);
diStatusLabel->setText(DigitallyImported::self()->loggedIn() ? i18n("DI: Logged In") : i18n("DI: Not Logged In"));
}
}

View File

@@ -60,6 +60,7 @@ public Q_SLOTS:
void controlActions();
private Q_SLOTS:
void diSettings();
void importXml();
void exportXml();
void add();
@@ -67,6 +68,7 @@ private Q_SLOTS:
void edit();
void searchItems();
void itemDoubleClicked(const QModelIndex &index);
void updateDiStatus();
private:
void addItemsToPlayQueue(const QModelIndexList &indexes, bool replace, quint8 priorty=0);

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>310</width>
<height>387</height>
<width>277</width>
<height>259</height>
</rect>
</property>
<layout class="QVBoxLayout" name="vlayout">
@@ -29,25 +29,28 @@
</item>
<item>
<layout class="QHBoxLayout" name="hlayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<widget class="SqueezedTextLabel" name="diStatusLabel"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="MenuButton" name="menuButton"/>
</item>
@@ -59,6 +62,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SqueezedTextLabel</class>
<extends>QLabel</extends>
<header>squeezedtextlabel.h</header>
</customwidget>
<customwidget>
<class>ItemView</class>
<extends>QTreeView</extends>