diff --git a/data/images/back.png b/data/images/back.png
new file mode 100644
index 000000000..88db1dc23
Binary files /dev/null and b/data/images/back.png differ
diff --git a/data/images/forward.png b/data/images/forward.png
new file mode 100644
index 000000000..3e0c42476
Binary files /dev/null and b/data/images/forward.png differ
diff --git a/data/images/home.png b/data/images/home.png
new file mode 100644
index 000000000..e36f187f6
Binary files /dev/null and b/data/images/home.png differ
diff --git a/data/www/auth.html b/data/www/auth.html
new file mode 100644
index 000000000..a8aac4c37
--- /dev/null
+++ b/data/www/auth.html
@@ -0,0 +1,64 @@
+
+
+
+
+
You have allowed access to Tomahawk from <%NAME%>
+
Copy and paste this authentication token into the status bar then close this window.
+
Token:
+
+
diff --git a/data/www/playdar_auth_logo.gif b/data/www/playdar_auth_logo.gif
new file mode 100644
index 000000000..22b06bfa3
Binary files /dev/null and b/data/www/playdar_auth_logo.gif differ
diff --git a/resources.qrc b/resources.qrc
index e1bc45cf5..fc3705795 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -70,6 +70,9 @@
./data/images/volume-slider-level.png
./data/images/echonest_logo.png
./data/images/loading-animation.gif
+./data/images/home.png
+./data/images/back.png
+./data/images/forward.png
./data/topbar-radiobuttons.css
./data/icons/tomahawk-icon-16x16.png
./data/icons/tomahawk-icon-32x32.png
@@ -80,5 +83,7 @@
./data/icons/audio-x-generic-22x22.png
./data/icons/audio-x-generic-32x32.png
./data/icons/audio-x-generic-16x16.png
+./data/www/auth.html
+./data/www/auth.na.html
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index de0164864..90c3ec204 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -25,6 +25,7 @@ set( libSources
query.cpp
result.cpp
source.cpp
+ viewpage.cpp
sip/SipPlugin.cpp
@@ -65,6 +66,8 @@ set( libSources
database/databasecommand_loaddynamicplaylist.cpp
database/databasecommand_loadalldynamicplaylists.cpp
database/databasecommand_deletedynamicplaylist.cpp
+ database/databasecommand_addclientauth.cpp
+ database/databasecommand_clientauthvalid.cpp
database/database.cpp
playlist/collectionmodel.cpp
@@ -156,6 +159,7 @@ set( libHeaders
resolver.h
result.h
source.h
+ viewpage.h
artist.h
album.h
@@ -200,6 +204,8 @@ set( libHeaders
database/databasecommand_loaddynamicplaylist.h
database/databasecommand_deletedynamicplaylist.h
database/databasecommand_loadalldynamicplaylists.h
+ database/databasecommand_addclientauth.h
+ database/databasecommand_clientauthvalid.h
network/bufferiodevice.h
network/msgprocessor.h
diff --git a/src/libtomahawk/database/databasecommand_addclientauth.cpp b/src/libtomahawk/database/databasecommand_addclientauth.cpp
new file mode 100644
index 000000000..d8e705952
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_addclientauth.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************************
+ * Copyright (c) 2011 Leo Franchi *
+ * *
+ * 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. If not, see . *
+ ****************************************************************************************/
+
+#include "databasecommand_addclientauth.h"
+
+DatabaseCommand_AddClientAuth::DatabaseCommand_AddClientAuth( const QString& clientToken,
+ const QString& website,
+ const QString& name,
+ const QString& userAgent,
+ QObject* parent )
+ : DatabaseCommand( parent )
+ , m_clientToken( clientToken )
+ , m_website( website )
+ , m_name( name )
+ , m_userAgent( userAgent )
+{
+}
+
+void DatabaseCommand_AddClientAuth::exec(DatabaseImpl* lib)
+{
+ TomahawkSqlQuery q = lib->newquery();
+ q.prepare( "INSERT INTO http_client_auth (token, website, name, ua, mtime, permissions) VALUES (?, ?, ?, ?, ?, ?)" );
+ q.addBindValue( m_clientToken );
+ q.addBindValue( m_website );
+ q.addBindValue( m_name );
+ q.addBindValue( m_userAgent );
+ q.addBindValue( 0 );
+ q.addBindValue( "*" );
+
+ if( !q.exec() ) {
+ qWarning() << "Failed to insert http client into auth table!";
+ }
+}
diff --git a/src/libtomahawk/database/databasecommand_addclientauth.h b/src/libtomahawk/database/databasecommand_addclientauth.h
new file mode 100644
index 000000000..fccec5947
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_addclientauth.h
@@ -0,0 +1,45 @@
+/****************************************************************************************
+ * Copyright (c) 2011 Leo Franchi *
+ * *
+ * 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. If not, see . *
+ ****************************************************************************************/
+
+#ifndef DATABASECOMMAND_ADDCLIENTAUTH_H
+#define DATABASECOMMAND_ADDCLIENTAUTH_H
+
+#include "databaseimpl.h"
+#include "databasecommand.h"
+#include "dllmacro.h"
+
+#include
+
+class DLLEXPORT DatabaseCommand_AddClientAuth : public DatabaseCommand
+{
+ Q_OBJECT
+public:
+ explicit DatabaseCommand_AddClientAuth( QObject* parent = 0 )
+ : DatabaseCommand( parent )
+ {}
+
+ explicit DatabaseCommand_AddClientAuth( const QString& clientToken, const QString& website, const QString& name, const QString& userAgent, QObject* parent = 0 );
+
+ QString commandname() const { return "addclientauth"; }
+
+ virtual void exec( DatabaseImpl* lib );
+ virtual bool doesMutates() const { return true; }
+
+private:
+ QString m_clientToken, m_website, m_name, m_userAgent;
+};
+
+#endif // DATABASECOMMAND_ADDCLIENTAUTH_H
diff --git a/src/libtomahawk/database/databasecommand_clientauthvalid.cpp b/src/libtomahawk/database/databasecommand_clientauthvalid.cpp
new file mode 100644
index 000000000..e751748bf
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_clientauthvalid.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************************
+ * Copyright (c) 2011 Leo Franchi *
+ * *
+ * 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. If not, see . *
+ ****************************************************************************************/
+
+#include "databasecommand_clientauthvalid.h"
+
+DatabaseCommand_ClientAuthValid::DatabaseCommand_ClientAuthValid( const QString& clientToken, QObject* parent )
+ : DatabaseCommand( parent )
+ , m_clientToken( clientToken )
+{
+
+}
+
+void DatabaseCommand_ClientAuthValid::exec(DatabaseImpl* lib)
+{
+ TomahawkSqlQuery q = lib->newquery();
+ q.prepare( "SELECT name FROM http_client_auth WHERE token = ?" );
+ q.addBindValue( m_clientToken );
+
+ if( q.exec() ) {
+ if( q.next() ) {
+ QString name = q.value( 0 ).toString();
+ emit authValid( m_clientToken, name, true );
+ } else {
+ emit authValid( m_clientToken, QString(), false );
+ }
+ } else {
+ qWarning() << "Failed to query http auth table for client:" << m_clientToken;
+ }
+}
diff --git a/src/libtomahawk/database/databasecommand_clientauthvalid.h b/src/libtomahawk/database/databasecommand_clientauthvalid.h
new file mode 100644
index 000000000..efb3c7bb1
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_clientauthvalid.h
@@ -0,0 +1,49 @@
+/****************************************************************************************
+ * Copyright (c) 2011 Leo Franchi *
+ * *
+ * 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. If not, see . *
+ ****************************************************************************************/
+
+#ifndef DATABASECOMMAND_CLIENTAUTHVALID_H
+#define DATABASECOMMAND_CLIENTAUTHVALID_H
+
+#include "databaseimpl.h"
+#include "databasecommand.h"
+#include "dllmacro.h"
+
+#include
+
+class DLLEXPORT DatabaseCommand_ClientAuthValid : public DatabaseCommand
+{
+ Q_OBJECT
+public:
+ explicit DatabaseCommand_ClientAuthValid( QObject* parent = 0 )
+ : DatabaseCommand( parent )
+ {}
+
+ explicit DatabaseCommand_ClientAuthValid( const QString& clientToken, QObject* parent = 0 );
+
+ QString commandname() const { return "clientauthvalid"; }
+
+ virtual void exec( DatabaseImpl* lib );
+ virtual bool doesMutates() const { return false; }
+
+signals:
+ // if auth is invalid name is empty
+ void authValid( const QString& clientToken, const QString& name, bool valid );
+
+private:
+ QString m_clientToken;
+};
+
+#endif // DATABASECOMMAND_CLIENTAUTHVALID_H
diff --git a/src/libtomahawk/database/databaseimpl.cpp b/src/libtomahawk/database/databaseimpl.cpp
index 7746f8a0f..5652dfae8 100644
--- a/src/libtomahawk/database/databaseimpl.cpp
+++ b/src/libtomahawk/database/databaseimpl.cpp
@@ -16,8 +16,7 @@
*/
#include "schema.sql.h"
-#define CURRENT_SCHEMA_VERSION 20
-
+#define CURRENT_SCHEMA_VERSION 21
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
: QObject( (QObject*) parent )
diff --git a/src/libtomahawk/database/schema.sql b/src/libtomahawk/database/schema.sql
index ad8b000d1..c30132ab9 100644
--- a/src/libtomahawk/database/schema.sql
+++ b/src/libtomahawk/database/schema.sql
@@ -241,6 +241,16 @@ CREATE TABLE IF NOT EXISTS playback_log (
CREATE INDEX playback_log_source ON playback_log(source);
CREATE INDEX playback_log_track ON playback_log(track);
+-- auth information for http clients
+
+CREATE TABLE IF NOT EXISTS http_client_auth (
+ token TEXT NOT NULL PRIMARY KEY,
+ website TEXT NOT NULL,
+ name TEXT NOT NULL,
+ ua TEXT,
+ mtime INTEGER,
+ permissions TEXT NOT NULL
+);
-- Schema version, and misc tomahawk settings relating to the collection db
@@ -250,4 +260,4 @@ CREATE TABLE IF NOT EXISTS settings (
v TEXT NOT NULL DEFAULT ''
);
-INSERT INTO settings(k,v) VALUES('schema_version', '20');
+INSERT INTO settings(k,v) VALUES('schema_version', '21');
diff --git a/src/libtomahawk/database/schema.sql.h b/src/libtomahawk/database/schema.sql.h
index a580c1851..9283091f3 100644
--- a/src/libtomahawk/database/schema.sql.h
+++ b/src/libtomahawk/database/schema.sql.h
@@ -1,5 +1,5 @@
/*
- This file was automatically generated from ./schema.sql on Wed Feb 23 12:39:07 CET 2011.
+ This file was automatically generated from schema.sql on Thu Feb 24 19:05:46 EST 2011.
*/
static const char * tomahawk_schema_sql =
@@ -161,11 +161,19 @@ static const char * tomahawk_schema_sql =
");"
"CREATE INDEX playback_log_source ON playback_log(source);"
"CREATE INDEX playback_log_track ON playback_log(track);"
+"CREATE TABLE IF NOT EXISTS http_client_auth ("
+" token TEXT NOT NULL PRIMARY KEY,"
+" website TEXT NOT NULL,"
+" name TEXT NOT NULL,"
+" ua TEXT,"
+" mtime INTEGER,"
+" permissions TEXT NOT NULL"
+");"
"CREATE TABLE IF NOT EXISTS settings ("
" k TEXT NOT NULL PRIMARY KEY,"
" v TEXT NOT NULL DEFAULT ''"
");"
-"INSERT INTO settings(k,v) VALUES('schema_version', '20');"
+"INSERT INTO settings(k,v) VALUES('schema_version', '21');"
;
const char * get_tomahawk_sql()
diff --git a/src/libtomahawk/network/controlconnection.cpp b/src/libtomahawk/network/controlconnection.cpp
index d2cf61004..cb7fcb647 100644
--- a/src/libtomahawk/network/controlconnection.cpp
+++ b/src/libtomahawk/network/controlconnection.cpp
@@ -104,7 +104,7 @@ ControlConnection::registerSource()
void
ControlConnection::setupDbSyncConnection( bool ondemand )
{
- if( m_dbsyncconn != NULL || ! m_registered )
+ if( m_dbsyncconn != NULL || !m_registered )
return;
qDebug() << Q_FUNC_INFO << ondemand << m_source->id();
@@ -115,12 +115,6 @@ ControlConnection::setupDbSyncConnection( bool ondemand )
qDebug() << "Connecting to DBSync offer from peer...";
m_dbsyncconn = new DBSyncConnection( m_servent, m_source );
- connect( m_dbsyncconn, SIGNAL( finished() ),
- m_dbsyncconn, SLOT( deleteLater() ) );
-
- connect( m_dbsyncconn, SIGNAL( destroyed( QObject* ) ),
- SLOT( dbSyncConnFinished( QObject* ) ), Qt::DirectConnection );
-
m_servent->createParallelConnection( this, m_dbsyncconn, m_dbconnkey );
m_dbconnkey.clear();
}
@@ -129,12 +123,6 @@ ControlConnection::setupDbSyncConnection( bool ondemand )
qDebug() << "Offering a DBSync key to peer...";
m_dbsyncconn = new DBSyncConnection( m_servent, m_source );
- connect( m_dbsyncconn, SIGNAL( finished() ),
- m_dbsyncconn, SLOT( deleteLater()) );
-
- connect( m_dbsyncconn, SIGNAL( destroyed(QObject* ) ),
- SLOT( dbSyncConnFinished( QObject* ) ), Qt::DirectConnection );
-
QString key = uuid();
m_servent->registerOffer( key, m_dbsyncconn );
QVariantMap m;
@@ -142,6 +130,12 @@ ControlConnection::setupDbSyncConnection( bool ondemand )
m.insert( "key", key );
sendMsg( m );
}
+
+ connect( m_dbsyncconn, SIGNAL( finished() ),
+ m_dbsyncconn, SLOT( deleteLater() ) );
+
+ connect( m_dbsyncconn, SIGNAL( destroyed( QObject* ) ),
+ SLOT( dbSyncConnFinished( QObject* ) ), Qt::DirectConnection );
}
diff --git a/src/libtomahawk/network/dbsyncconnection.cpp b/src/libtomahawk/network/dbsyncconnection.cpp
index 3172a5252..334fe86d9 100644
--- a/src/libtomahawk/network/dbsyncconnection.cpp
+++ b/src/libtomahawk/network/dbsyncconnection.cpp
@@ -92,7 +92,7 @@ DBSyncConnection::trigger()
qDebug() << Q_FUNC_INFO;
// if we're still setting up the connection, do nothing - we sync on first connect anyway:
- if ( !this->isRunning() )
+ if ( !isRunning() )
return;
QMetaObject::invokeMethod( this, "sendMsg", Qt::QueuedConnection,
@@ -195,7 +195,7 @@ DBSyncConnection::handleMsg( msg_ptr msg )
QVariantMap m = msg->json().toMap();
if ( m.empty() )
{
- qDebug() << "Failed to parse msg in dbsync";
+ qDebug() << "Failed to parse msg in dbsync" << m_source->id() << m_source->friendlyName();
Q_ASSERT( false );
return;
}
diff --git a/src/libtomahawk/network/servent.cpp b/src/libtomahawk/network/servent.cpp
index e3eb71a9e..24407f087 100644
--- a/src/libtomahawk/network/servent.cpp
+++ b/src/libtomahawk/network/servent.cpp
@@ -707,8 +707,8 @@ Servent::triggerDBSync()
QList sources = SourceList::instance()->sources();
foreach( const source_ptr& src, sources )
{
- // local src doesnt have a control connection, skip it:
- if( src.isNull() || src->isLocal() )
+ // skip local source
+ if ( src.isNull() || src->isLocal() )
continue;
if ( src->controlConnection() ) // source online?
diff --git a/src/libtomahawk/playlist/albummodel.cpp b/src/libtomahawk/playlist/albummodel.cpp
index f22d389d8..fbbad77bd 100644
--- a/src/libtomahawk/playlist/albummodel.cpp
+++ b/src/libtomahawk/playlist/albummodel.cpp
@@ -225,6 +225,8 @@ AlbumModel::addCollection( const collection_ptr& collection )
SLOT( onAlbumsAdded( QList, Tomahawk::collection_ptr ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
+
+ m_title = tr( "All albums from %1" ).arg( collection->source()->friendlyName() );
}
@@ -245,6 +247,8 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in
SLOT( onAlbumsAdded( QList, Tomahawk::collection_ptr ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
+
+ m_title = tr( "All albums from %1" ).arg( collection->source()->friendlyName() );
}
diff --git a/src/libtomahawk/playlist/albummodel.h b/src/libtomahawk/playlist/albummodel.h
index 445538b86..f25724ad4 100644
--- a/src/libtomahawk/playlist/albummodel.h
+++ b/src/libtomahawk/playlist/albummodel.h
@@ -40,9 +40,6 @@ public:
virtual void removeIndex( const QModelIndex& index );
virtual void removeIndexes( const QList& indexes );
- virtual PlaylistInterface::RepeatMode repeatMode() const { return PlaylistInterface::NoRepeat; }
- virtual bool shuffled() const { return false; }
-
virtual QMimeData* mimeData( const QModelIndexList& indexes ) const;
virtual QStringList mimeTypes() const;
virtual Qt::ItemFlags flags( const QModelIndex& index ) const;
@@ -50,6 +47,11 @@ public:
void addCollection( const Tomahawk::collection_ptr& collection );
void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order );
+ virtual QString title() const { return m_title; }
+ virtual QString description() const { return m_description; }
+ virtual void setTitle( const QString& title ) { m_title = title; }
+ virtual void setDescription( const QString& description ) { m_description = description; }
+
AlbumItem* itemFromIndex( const QModelIndex& index ) const
{
if ( index.isValid() )
@@ -81,6 +83,9 @@ private:
QPersistentModelIndex m_currentIndex;
AlbumItem* m_rootItem;
QPixmap m_defaultCover;
+
+ QString m_title;
+ QString m_description;
};
#endif // ALBUMMODEL_H
diff --git a/src/libtomahawk/playlist/albumproxymodel.h b/src/libtomahawk/playlist/albumproxymodel.h
index d87c855db..3e694e2a6 100644
--- a/src/libtomahawk/playlist/albumproxymodel.h
+++ b/src/libtomahawk/playlist/albumproxymodel.h
@@ -33,7 +33,8 @@ public:
virtual PlaylistInterface::RepeatMode repeatMode() const { return m_repeatMode; }
virtual bool shuffled() const { return m_shuffled; }
-
+ virtual PlaylistInterface::ViewMode viewMode() const { return PlaylistInterface::Album; }
+
signals:
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
void shuffleModeChanged( bool enabled );
diff --git a/src/libtomahawk/playlist/albumview.cpp b/src/libtomahawk/playlist/albumview.cpp
index 9e954cc7f..83ecb28b9 100644
--- a/src/libtomahawk/playlist/albumview.cpp
+++ b/src/libtomahawk/playlist/albumview.cpp
@@ -10,8 +10,6 @@
#include "tomahawksettings.h"
#include "albumitemdelegate.h"
-#include "albummodel.h"
-#include "albumproxymodel.h"
#include "playlistmanager.h"
using namespace Tomahawk;
diff --git a/src/libtomahawk/playlist/albumview.h b/src/libtomahawk/playlist/albumview.h
index a2445971f..d4616cd3c 100644
--- a/src/libtomahawk/playlist/albumview.h
+++ b/src/libtomahawk/playlist/albumview.h
@@ -4,12 +4,13 @@
#include
#include
+#include "albummodel.h"
+#include "albumproxymodel.h"
+#include "viewpage.h"
+
#include "dllmacro.h"
-class AlbumModel;
-class AlbumProxyModel;
-
-class DLLEXPORT AlbumView : public QListView
+class DLLEXPORT AlbumView : public QListView, public Tomahawk::ViewPage
{
Q_OBJECT
@@ -19,12 +20,22 @@ public:
void setProxyModel( AlbumProxyModel* model );
- AlbumModel* model() { return m_model; }
- AlbumProxyModel* proxyModel() { return m_proxyModel; }
+ AlbumModel* model() const { return m_model; }
+ AlbumProxyModel* proxyModel() const { return m_proxyModel; }
// PlaylistItemDelegate* delegate() { return m_delegate; }
void setModel( AlbumModel* model );
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return proxyModel(); }
+
+ virtual QString title() const { return m_model->title(); }
+ virtual QString description() const { return m_model->description(); }
+
+ virtual bool showModes() const { return true; }
+
+ virtual bool jumpToCurrentTrack() { return false; }
+
public slots:
void onItemActivated( const QModelIndex& index );
diff --git a/src/libtomahawk/playlist/collectionflatmodel.cpp b/src/libtomahawk/playlist/collectionflatmodel.cpp
index 54c4bdc04..6e63feeba 100644
--- a/src/libtomahawk/playlist/collectionflatmodel.cpp
+++ b/src/libtomahawk/playlist/collectionflatmodel.cpp
@@ -60,6 +60,11 @@ CollectionFlatModel::addCollection( const collection_ptr& collection )
SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) );
connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
+
+ if ( collection->source()->isLocal() )
+ setTitle( tr( "Your Collection" ) );
+ else
+ setTitle( tr( "Collection of %1" ).arg( collection->source()->friendlyName() ) );
}
diff --git a/src/libtomahawk/playlist/collectionproxymodel.h b/src/libtomahawk/playlist/collectionproxymodel.h
index e6ea9311d..af46be8c4 100644
--- a/src/libtomahawk/playlist/collectionproxymodel.h
+++ b/src/libtomahawk/playlist/collectionproxymodel.h
@@ -12,6 +12,8 @@ Q_OBJECT
public:
explicit CollectionProxyModel( QObject* parent = 0 );
+ virtual PlaylistInterface::ViewMode viewMode() const { return PlaylistInterface::Flat; }
+
protected:
bool lessThan( const QModelIndex& left, const QModelIndex& right ) const;
};
diff --git a/src/libtomahawk/playlist/collectionview.cpp b/src/libtomahawk/playlist/collectionview.cpp
index dc1490595..09b557611 100644
--- a/src/libtomahawk/playlist/collectionview.cpp
+++ b/src/libtomahawk/playlist/collectionview.cpp
@@ -45,7 +45,6 @@ CollectionView::setModel( TrackModel* model )
void
CollectionView::dragEnterEvent( QDragEnterEvent* event )
{
- qDebug() << Q_FUNC_INFO;
event->ignore();
}
@@ -94,3 +93,10 @@ CollectionView::onTrackCountChanged( unsigned int tracks )
else
overlay()->hide();
}
+
+
+bool
+CollectionView::jumpToCurrentTrack()
+{
+ scrollTo( proxyModel()->currentItem(), QAbstractItemView::PositionAtCenter );
+}
diff --git a/src/libtomahawk/playlist/collectionview.h b/src/libtomahawk/playlist/collectionview.h
index 9fd3f3483..cddd1e98c 100644
--- a/src/libtomahawk/playlist/collectionview.h
+++ b/src/libtomahawk/playlist/collectionview.h
@@ -3,11 +3,14 @@
#include
+#include "trackproxymodel.h"
+#include "trackmodel.h"
#include "trackview.h"
+#include "viewpage.h"
#include "dllmacro.h"
-class DLLEXPORT CollectionView : public TrackView
+class DLLEXPORT CollectionView : public TrackView, public Tomahawk::ViewPage
{
Q_OBJECT
@@ -17,6 +20,16 @@ public:
virtual void setModel( TrackModel* model );
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return proxyModel(); }
+
+ virtual QString title() const { return model()->title(); }
+ virtual QString description() const { return model()->description(); }
+
+ virtual bool showModes() const { return true; }
+
+ virtual bool jumpToCurrentTrack();
+
private slots:
void onCustomContextMenu( const QPoint& pos );
void onTrackCountChanged( unsigned int tracks );
diff --git a/src/libtomahawk/playlist/dynamic/DynamicView.h b/src/libtomahawk/playlist/dynamic/DynamicView.h
index d7ad8103e..26a63e4f1 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicView.h
+++ b/src/libtomahawk/playlist/dynamic/DynamicView.h
@@ -45,7 +45,7 @@ public:
void setDynamicWorking( bool working );
- virtual void paintEvent(QPaintEvent* event);
+ virtual void paintEvent( QPaintEvent* event );
public slots:
void showMessageTimeout( const QString& title, const QString& body );
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
index 8bea35d94..20ec27727 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
@@ -386,3 +386,9 @@ DynamicWidget::paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qre
p.setPen( pen );
p.drawRoundedRect( r, 10, 10 );
}
+
+bool
+DynamicWidget::jumpToCurrentTrack()
+{
+ m_view->scrollTo( m_view->proxyModel()->currentItem(), QAbstractItemView::PositionAtCenter );
+}
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
index 17d31d882..e8653b2b7 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
@@ -20,8 +20,11 @@
#include
#include "typedefs.h"
+#include "viewpage.h"
+
#include "dynamic/DynamicPlaylist.h"
#include "dynamic/DynamicControl.h"
+#include "dynamic/DynamicModel.h"
class LoadingSpinner;
class QShowEvent;
@@ -43,20 +46,15 @@ namespace Tomahawk
class DynamicSetupWidget;
-
-class DynamicModel;
-
-
class DynamicView;
-
class CollapsibleControls;
/**
* This class contains the dynamic playlist config and the playlist view itself
*/
-class DynamicWidget : public QWidget
+class DynamicWidget : public QWidget, public Tomahawk::ViewPage
{
Q_OBJECT
public:
@@ -65,7 +63,7 @@ public:
void loadDynamicPlaylist( const dynplaylist_ptr& playlist );
- PlaylistInterface* playlistInterface() const;
+ virtual PlaylistInterface* playlistInterface() const;
virtual QSize sizeHint() const;
virtual void resizeEvent( QResizeEvent* );
@@ -73,6 +71,14 @@ public:
virtual void showEvent(QShowEvent* );
static void paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qreal opacity = .95 );
+
+ virtual QWidget* widget() { return this; }
+
+ virtual QString title() const { return m_model->title(); }
+ virtual QString description() const { return m_model->description(); }
+
+ virtual bool jumpToCurrentTrack();
+
public slots:
void onRevisionLoaded( const Tomahawk::DynamicPlaylistRevision& rev );
void playlistTypeChanged(QString);
@@ -94,6 +100,7 @@ private slots:
void controlChanged( const Tomahawk::dyncontrol_ptr& control );
void layoutFloatingWidgets();
+
private:
dynplaylist_ptr m_playlist;
QVBoxLayout* m_layout;
diff --git a/src/libtomahawk/playlist/infobar/infobar.cpp b/src/libtomahawk/playlist/infobar/infobar.cpp
index bb2121e09..8ebd5893f 100644
--- a/src/libtomahawk/playlist/infobar/infobar.cpp
+++ b/src/libtomahawk/playlist/infobar/infobar.cpp
@@ -7,6 +7,8 @@
#include "utils/tomahawkutils.h"
+#define IMAGE_HEIGHT 64
+
InfoBar::InfoBar( QWidget* parent )
: QWidget( parent )
@@ -58,7 +60,7 @@ InfoBar::setDescription( const QString& s )
void
InfoBar::setPixmap( const QPixmap& p )
{
- ui->imageLabel->setPixmap( p.scaledToHeight( ui->imageLabel->height(), Qt::SmoothTransformation ) );
+ ui->imageLabel->setPixmap( p.scaledToHeight( IMAGE_HEIGHT, Qt::SmoothTransformation ) );
}
diff --git a/src/libtomahawk/playlist/playlistmanager.cpp b/src/libtomahawk/playlist/playlistmanager.cpp
index 6b5fac73a..7eceac460 100644
--- a/src/libtomahawk/playlist/playlistmanager.cpp
+++ b/src/libtomahawk/playlist/playlistmanager.cpp
@@ -7,6 +7,7 @@
#include "infobar/infobar.h"
#include "topbar/topbar.h"
#include "widgets/infowidgets/sourceinfowidget.h"
+#include "widgets/welcomewidget.h"
#include "collectionmodel.h"
#include "collectionflatmodel.h"
@@ -29,6 +30,8 @@
#define FILTER_TIMEOUT 280
+using namespace Tomahawk;
+
PlaylistManager* PlaylistManager::s_instance = 0;
@@ -42,14 +45,13 @@ PlaylistManager::instance()
PlaylistManager::PlaylistManager( QObject* parent )
: QObject( parent )
, m_widget( new QWidget() )
- , m_currentInterface( 0 )
+ , m_welcomeWidget( new WelcomeWidget() )
, m_currentMode( 0 )
, m_superCollectionVisible( true )
- , m_statsAvailable( false )
- , m_modesAvailable( false )
{
s_instance = this;
+ setHistoryPosition( -1 );
m_widget->setLayout( new QVBoxLayout() );
m_topbar = new TopBar();
@@ -89,49 +91,28 @@ PlaylistManager::PlaylistManager( QObject* parent )
m_superAlbumView = new AlbumView();
m_superAlbumModel = new AlbumModel( m_superAlbumView );
m_superAlbumView->setModel( m_superAlbumModel );
-
- m_stack->addWidget( m_superCollectionView );
- m_stack->addWidget( m_superAlbumView );
-
- m_currentInterface = m_superCollectionView->proxyModel();
+ m_superAlbumView->setFrameShape( QFrame::NoFrame );
+ m_superAlbumView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
m_stack->setContentsMargins( 0, 0, 0, 0 );
m_widget->setContentsMargins( 0, 0, 0, 0 );
m_widget->layout()->setContentsMargins( 0, 0, 0, 0 );
m_widget->layout()->setMargin( 0 );
m_widget->layout()->setSpacing( 0 );
-
+
connect( &m_filterTimer, SIGNAL( timeout() ), SLOT( applyFilter() ) );
connect( m_topbar, SIGNAL( filterTextChanged( QString ) ),
- this, SLOT( setFilter( QString ) ) );
-
- connect( this, SIGNAL( numSourcesChanged( unsigned int ) ),
- m_topbar, SLOT( setNumSources( unsigned int ) ) );
-
- connect( this, SIGNAL( numTracksChanged( unsigned int ) ),
- m_topbar, SLOT( setNumTracks( unsigned int ) ) );
-
- connect( this, SIGNAL( numArtistsChanged( unsigned int ) ),
- m_topbar, SLOT( setNumArtists( unsigned int ) ) );
-
- connect( this, SIGNAL( numShownChanged( unsigned int ) ),
- m_topbar, SLOT( setNumShown( unsigned int ) ) );
+ SLOT( setFilter( QString ) ) );
connect( m_topbar, SIGNAL( flatMode() ),
- this, SLOT( setTableMode() ) );
-
+ SLOT( setTableMode() ) );
+
connect( m_topbar, SIGNAL( artistMode() ),
- this, SLOT( setTreeMode() ) );
-
+ SLOT( setTreeMode() ) );
+
connect( m_topbar, SIGNAL( albumMode() ),
- this, SLOT( setAlbumMode() ) );
-
- connect( this, SIGNAL( statsAvailable( bool ) ),
- m_topbar, SLOT( setStatsVisible( bool ) ) );
-
- connect( this, SIGNAL( modesAvailable( bool ) ),
- m_topbar, SLOT( setModesVisible( bool ) ) );
+ SLOT( setAlbumMode() ) );
}
@@ -151,11 +132,10 @@ PlaylistManager::queue() const
bool
PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
{
- unlinkPlaylist();
-
+ PlaylistView* view;
if ( !m_playlistViews.contains( playlist ) )
{
- PlaylistView* view = new PlaylistView();
+ view = new PlaylistView();
PlaylistModel* model = new PlaylistModel();
view->setModel( model );
view->setFrameShape( QFrame::NoFrame );
@@ -163,27 +143,15 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
model->loadPlaylist( playlist );
playlist->resolve();
- m_currentInterface = view->proxyModel();
m_playlistViews.insert( playlist, view );
-
- m_stack->addWidget( view );
- m_stack->setCurrentWidget( view );
}
else
{
- PlaylistView* view = m_playlistViews.value( playlist );
- m_stack->setCurrentWidget( view );
- m_currentInterface = view->proxyModel();
+ view = m_playlistViews.value( playlist );
}
- m_queueView->show();
- m_infobar->setCaption( playlist->title() );
- m_infobar->setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) );
-
+ setPage( view );
m_superCollectionVisible = false;
- m_statsAvailable = true;
- m_modesAvailable = false;
- linkPlaylist();
TomahawkSettings::instance()->appendRecentlyPlayedPlaylist( playlist );
@@ -195,34 +163,25 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
bool
PlaylistManager::show( const Tomahawk::dynplaylist_ptr& playlist )
{
- unlinkPlaylist();
-
- if( !m_dynamicWidgets.contains( playlist ) )
+ if ( !m_dynamicWidgets.contains( playlist ) )
{
m_dynamicWidgets[ playlist ] = new Tomahawk::DynamicWidget( playlist, m_stack );
- m_stack->addWidget( m_dynamicWidgets[ playlist ] );
+
playlist->resolve();
}
- m_stack->setCurrentWidget( m_dynamicWidgets.value( playlist ) );
- m_currentInterface = m_dynamicWidgets.value( playlist )->playlistInterface();
+ setPage( m_dynamicWidgets.value( playlist ) );
- m_infobar->setCaption( playlist->title() );
- m_infobar->setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) );
-
- if( playlist->mode() == Tomahawk::OnDemand )
+ if ( playlist->mode() == Tomahawk::OnDemand )
m_queueView->hide();
-
+ else
+ m_queueView->show();
m_superCollectionVisible = false;
- m_statsAvailable = true;
- m_modesAvailable = false;
- linkPlaylist();
TomahawkSettings::instance()->appendRecentlyPlayedPlaylist( playlist );
emit numSourcesChanged( SourceList::instance()->count() );
-
return true;
}
@@ -230,39 +189,26 @@ PlaylistManager::show( const Tomahawk::dynplaylist_ptr& playlist )
bool
PlaylistManager::show( const Tomahawk::artist_ptr& artist )
{
- qDebug() << Q_FUNC_INFO << &artist << artist.data();
- unlinkPlaylist();
+ PlaylistView* view;
if ( !m_artistViews.contains( artist ) )
{
- PlaylistView* view = new PlaylistView();
+ view = new PlaylistView();
PlaylistModel* model = new PlaylistModel();
view->setModel( model );
view->setFrameShape( QFrame::NoFrame );
view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
model->append( artist );
- m_currentInterface = view->proxyModel();
m_artistViews.insert( artist, view );
-
- m_stack->addWidget( view );
- m_stack->setCurrentWidget( view );
}
else
{
- PlaylistView* view = m_artistViews.value( artist );
- m_stack->setCurrentWidget( view );
- m_currentInterface = view->proxyModel();
+ view = m_artistViews.value( artist );
}
- m_queueView->show();
- m_infobar->setCaption( tr( "All tracks by %1" ).arg( artist->name() ) );
- m_infobar->setDescription( "" );
-
+ setPage( view );
m_superCollectionVisible = false;
- m_statsAvailable = false;
- m_modesAvailable = false;
- linkPlaylist();
emit numSourcesChanged( 1 );
return true;
@@ -272,39 +218,25 @@ PlaylistManager::show( const Tomahawk::artist_ptr& artist )
bool
PlaylistManager::show( const Tomahawk::album_ptr& album )
{
- qDebug() << Q_FUNC_INFO << &album << album.data();
- unlinkPlaylist();
-
+ PlaylistView* view;
if ( !m_albumViews.contains( album ) )
{
- PlaylistView* view = new PlaylistView();
+ view = new PlaylistView();
PlaylistModel* model = new PlaylistModel();
view->setModel( model );
view->setFrameShape( QFrame::NoFrame );
view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
model->append( album );
- m_currentInterface = view->proxyModel();
m_albumViews.insert( album, view );
-
- m_stack->addWidget( view );
- m_stack->setCurrentWidget( view );
}
else
{
- PlaylistView* view = m_albumViews.value( album );
- m_stack->setCurrentWidget( view );
- m_currentInterface = view->proxyModel();
+ view = m_albumViews.value( album );
}
- m_queueView->show();
- m_infobar->setCaption( tr( "All tracks on %1 by %2" ).arg( album->name() ).arg( album->artist()->name() ) );
- m_infobar->setDescription( "" );
-
+ setPage( view );
m_superCollectionVisible = false;
- m_statsAvailable = false;
- m_modesAvailable = false;
- linkPlaylist();
emit numSourcesChanged( 1 );
return true;
@@ -314,70 +246,52 @@ PlaylistManager::show( const Tomahawk::album_ptr& album )
bool
PlaylistManager::show( const Tomahawk::collection_ptr& collection )
{
- unlinkPlaylist();
-
m_currentCollection = collection;
if ( m_currentMode == 0 )
{
+ CollectionView* view;
if ( !m_collectionViews.contains( collection ) )
{
- CollectionView* view = new CollectionView();
+ view = new CollectionView();
CollectionFlatModel* model = new CollectionFlatModel();
view->setModel( model );
view->setFrameShape( QFrame::NoFrame );
view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
model->addCollection( collection );
- m_currentInterface = view->proxyModel();
m_collectionViews.insert( collection, view );
-
- m_stack->addWidget( view );
- m_stack->setCurrentWidget( view );
}
else
{
- CollectionView* view = m_collectionViews.value( collection );
- m_stack->setCurrentWidget( view );
- m_currentInterface = view->proxyModel();
+ view = m_collectionViews.value( collection );
}
+
+ setPage( view );
}
if ( m_currentMode == 2 )
{
+ AlbumView* aview;
if ( !m_collectionAlbumViews.contains( collection ) )
{
- AlbumView* aview = new AlbumView();
+ aview = new AlbumView();
AlbumModel* amodel = new AlbumModel( aview );
aview->setModel( amodel );
aview->setFrameShape( QFrame::NoFrame );
aview->setAttribute( Qt::WA_MacShowFocusRect, 0 );
amodel->addCollection( collection );
- m_currentInterface = aview->proxyModel();
m_collectionAlbumViews.insert( collection, aview );
-
- m_stack->addWidget( aview );
- m_stack->setCurrentWidget( aview );
}
else
{
- AlbumView* view = m_collectionAlbumViews.value( collection );
- m_stack->setCurrentWidget( view );
- m_currentInterface = view->proxyModel();
+ aview = m_collectionAlbumViews.value( collection );
}
+
+ setPage( aview );
}
- m_infobar->setDescription( "" );
- if ( collection->source()->isLocal() )
- m_infobar->setCaption( tr( "Your Collection" ) );
- else
- m_infobar->setCaption( tr( "Collection of %1" ).arg( collection->source()->friendlyName() ) );
-
- m_queueView->show();
m_superCollectionVisible = false;
- m_statsAvailable = ( m_currentMode == 0 );
- m_modesAvailable = true;
- linkPlaylist();
emit numSourcesChanged( 1 );
return true;
@@ -387,32 +301,19 @@ PlaylistManager::show( const Tomahawk::collection_ptr& collection )
bool
PlaylistManager::show( const Tomahawk::source_ptr& source )
{
- unlinkPlaylist();
-
- m_currentInterface = 0;
-
+ SourceInfoWidget* swidget;
if ( !m_sourceViews.contains( source ) )
{
- SourceInfoWidget* swidget = new SourceInfoWidget( source );
- m_currentInfoWidget = swidget;
- m_stack->addWidget( m_currentInfoWidget );
+ swidget = new SourceInfoWidget( source );
m_sourceViews.insert( source, swidget );
}
else
{
- m_currentInfoWidget = m_sourceViews.value( source );
+ swidget = m_sourceViews.value( source );
}
- m_infobar->setCaption( tr( "Info about %1" ).arg( source->isLocal() ? tr( "Your Collection" ) : source->friendlyName() ) );
- m_infobar->setDescription( "" );
-
- m_queueView->show();
- m_stack->setCurrentWidget( m_currentInfoWidget );
+ setPage( swidget );
m_superCollectionVisible = false;
- m_statsAvailable = false;
- m_modesAvailable = false;
-
- linkPlaylist();
emit numSourcesChanged( 1 );
return true;
@@ -420,26 +321,15 @@ PlaylistManager::show( const Tomahawk::source_ptr& source )
bool
-PlaylistManager::show( QWidget* widget, const QString& title, const QString& desc, const QPixmap& pixmap )
+PlaylistManager::show( ViewPage* page )
{
- unlinkPlaylist();
+ if ( m_stack->indexOf( page->widget() ) < 0 )
+ {
+ connect( page->widget(), SIGNAL( destroyed( QWidget* ) ), SLOT( onWidgetDestroyed( QWidget* ) ) );
+ }
- connect( widget, SIGNAL( destroyed( QWidget* ) ), SLOT( onWidgetDestroyed( QWidget* ) ) );
-
- m_stack->addWidget( widget );
- m_stack->setCurrentWidget( widget );
-
- m_infobar->setCaption( title );
- m_infobar->setDescription( desc );
- m_infobar->setPixmap( pixmap );
-
- m_queueView->show();
+ setPage( page );
m_superCollectionVisible = false;
- m_statsAvailable = false;
- m_modesAvailable = false;
- m_currentInterface = 0;
-
- linkPlaylist();
return true;
}
@@ -456,33 +346,34 @@ PlaylistManager::showSuperCollection()
m_superCollectionFlatModel->addCollection( source->collection() );
m_superAlbumModel->addCollection( source->collection() );
}
+
+ m_superCollectionFlatModel->setTitle( tr( "All available tracks" ) );
+ m_superAlbumModel->setTitle( tr( "All available albums" ) );
}
if ( m_currentMode == 0 )
{
- m_stack->setCurrentWidget( m_superCollectionView );
- m_currentInterface = m_superCollectionView->proxyModel();
+ setPage( m_superCollectionView );
}
else if ( m_currentMode == 2 )
{
- m_stack->setCurrentWidget( m_superAlbumView );
- m_currentInterface = m_superAlbumView->proxyModel();
+ setPage( m_superAlbumView );
}
- m_infobar->setCaption( tr( "Super Collection" ) );
- m_infobar->setDescription( tr( "All available tracks" ) );
-
- m_queueView->show();
m_superCollectionVisible = true;
- m_statsAvailable = ( m_currentMode == 0 );
- m_modesAvailable = true;
- linkPlaylist();
emit numSourcesChanged( m_superCollections.count() );
return true;
}
+void
+PlaylistManager::showWelcomePage()
+{
+ show( m_welcomeWidget );
+}
+
+
void
PlaylistManager::setTableMode()
{
@@ -533,8 +424,7 @@ PlaylistManager::showQueue()
if ( QThread::currentThread() != thread() )
{
qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
- QMetaObject::invokeMethod( this, "showQueue",
- Qt::QueuedConnection );
+ QMetaObject::invokeMethod( this, "showQueue", Qt::QueuedConnection );
return;
}
@@ -548,8 +438,7 @@ PlaylistManager::hideQueue()
if ( QThread::currentThread() != thread() )
{
qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
- QMetaObject::invokeMethod( this, "hideQueue",
- Qt::QueuedConnection );
+ QMetaObject::invokeMethod( this, "hideQueue", Qt::QueuedConnection );
return;
}
@@ -557,6 +446,42 @@ PlaylistManager::hideQueue()
}
+void
+PlaylistManager::historyBack()
+{
+ if ( m_historyPosition < 1 )
+ return;
+
+ showHistory( m_historyPosition - 1 );
+}
+
+
+void
+PlaylistManager::historyForward()
+{
+ if ( m_historyPosition >= m_pageHistory.count() - 1 )
+ return;
+
+ showHistory( m_historyPosition + 1 );
+}
+
+
+void
+PlaylistManager::showHistory( int historyPosition )
+{
+ if ( historyPosition < 0 || historyPosition >= m_pageHistory.count() )
+ {
+ qDebug() << "History position out of bounds!" << historyPosition << m_pageHistory.count();
+ Q_ASSERT( false );
+ return;
+ }
+
+ setHistoryPosition( historyPosition );
+ ViewPage* page = m_pageHistory.at( historyPosition );
+ setPage( page, false );
+}
+
+
void
PlaylistManager::setFilter( const QString& filter )
{
@@ -574,67 +499,114 @@ PlaylistManager::applyFilter()
{
qDebug() << Q_FUNC_INFO;
- if ( m_currentInterface && m_currentInterface->filter() != m_filter )
- m_currentInterface->setFilter( m_filter );
+ if ( currentPlaylistInterface() && currentPlaylistInterface()->filter() != m_filter )
+ currentPlaylistInterface()->setFilter( m_filter );
+}
+
+
+void
+PlaylistManager::setPage( ViewPage* page, bool trackHistory )
+{
+ unlinkPlaylist();
+
+ if ( !m_pageHistory.contains( page ) )
+ {
+ m_stack->addWidget( page->widget() );
+ }
+ else
+ {
+ if ( trackHistory )
+ m_pageHistory.removeAll( page );
+ }
+
+ if ( trackHistory )
+ {
+ m_pageHistory << page;
+ setHistoryPosition( m_pageHistory.count() - 1 );
+ }
+
+ if ( playlistForInterface( currentPlaylistInterface() ) )
+ emit playlistActivated( playlistForInterface( currentPlaylistInterface() ) );
+ if ( dynamicPlaylistForInterface( currentPlaylistInterface() ) )
+ emit dynamicPlaylistActivated( dynamicPlaylistForInterface( currentPlaylistInterface() ) );
+ if ( collectionForInterface( currentPlaylistInterface() ) )
+ emit collectionActivated( collectionForInterface( currentPlaylistInterface() ) );
+ if ( !currentPlaylistInterface() )
+ emit tempPageActivated();
+
+ if ( !AudioEngine::instance()->playlist() )
+ AudioEngine::instance()->setPlaylist( currentPlaylistInterface() );
+
+ m_stack->setCurrentWidget( page->widget() );
+ updateView();
}
void
PlaylistManager::unlinkPlaylist()
{
- if ( m_currentInterface )
+ if ( currentPlaylistInterface() )
{
- disconnect( m_currentInterface->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ),
- this, SIGNAL( numTracksChanged( unsigned int ) ) );
+ disconnect( currentPlaylistInterface()->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ),
+ this, SIGNAL( numTracksChanged( unsigned int ) ) );
- disconnect( m_currentInterface->object(), SIGNAL( trackCountChanged( unsigned int ) ),
- this, SIGNAL( numShownChanged( unsigned int ) ) );
+ disconnect( currentPlaylistInterface()->object(), SIGNAL( trackCountChanged( unsigned int ) ),
+ this, SIGNAL( numShownChanged( unsigned int ) ) );
- disconnect( m_currentInterface->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ),
- this, SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) );
+ disconnect( currentPlaylistInterface()->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ),
+ this, SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) );
- disconnect( m_currentInterface->object(), SIGNAL( shuffleModeChanged( bool ) ),
- this, SIGNAL( shuffleModeChanged( bool ) ) );
+ disconnect( currentPlaylistInterface()->object(), SIGNAL( shuffleModeChanged( bool ) ),
+ this, SIGNAL( shuffleModeChanged( bool ) ) );
}
}
void
-PlaylistManager::linkPlaylist()
+PlaylistManager::updateView()
{
- if ( m_currentInterface )
+ if ( currentPlaylistInterface() )
{
- connect( m_currentInterface->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ),
- this, SIGNAL( numTracksChanged( unsigned int ) ) );
+ connect( currentPlaylistInterface()->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ),
+ SIGNAL( numTracksChanged( unsigned int ) ) );
- connect( m_currentInterface->object(), SIGNAL( trackCountChanged( unsigned int ) ),
- this, SIGNAL( numShownChanged( unsigned int ) ) );
+ connect( currentPlaylistInterface()->object(), SIGNAL( trackCountChanged( unsigned int ) ),
+ SIGNAL( numShownChanged( unsigned int ) ) );
- connect( m_currentInterface->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ),
- this, SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) );
+ connect( currentPlaylistInterface()->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ),
+ SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) );
- connect( m_currentInterface->object(), SIGNAL( shuffleModeChanged( bool ) ),
- this, SIGNAL( shuffleModeChanged( bool ) ) );
+ connect( currentPlaylistInterface()->object(), SIGNAL( shuffleModeChanged( bool ) ),
+ SIGNAL( shuffleModeChanged( bool ) ) );
- m_interfaceHistory.removeAll( m_currentInterface );
- m_interfaceHistory << m_currentInterface;
+ m_topbar->setFilter( currentPlaylistInterface()->filter() );
}
- AudioEngine::instance()->setPlaylist( m_currentInterface );
-
- if ( m_currentInterface && m_statsAvailable )
+ if ( currentPage()->showStatsBar() && currentPlaylistInterface() )
{
- m_topbar->setFilter( m_currentInterface->filter() );
-
- emit numTracksChanged( m_currentInterface->unfilteredTrackCount() );
- emit numShownChanged( m_currentInterface->trackCount() );
- emit repeatModeChanged( m_currentInterface->repeatMode() );
- emit shuffleModeChanged( m_currentInterface->shuffled() );
-
+ emit numTracksChanged( currentPlaylistInterface()->unfilteredTrackCount() );
+ emit numShownChanged( currentPlaylistInterface()->trackCount() );
+ emit repeatModeChanged( currentPlaylistInterface()->repeatMode() );
+ emit shuffleModeChanged( currentPlaylistInterface()->shuffled() );
+ emit modeChanged( currentPlaylistInterface()->viewMode() );
}
- emit statsAvailable( m_statsAvailable );
- emit modesAvailable( m_modesAvailable );
+ if ( currentPage()->queueVisible() )
+ m_queueView->show();
+ else
+ m_queueView->hide();
+
+ emit statsAvailable( currentPage()->showStatsBar() );
+ emit modesAvailable( currentPage()->showModes() );
+
+ if ( !currentPage()->showStatsBar() && !currentPage()->showModes() )
+ m_topbar->setVisible( false );
+ else
+ m_topbar->setVisible( true );
+
+ m_infobar->setCaption( currentPage()->title() );
+ m_infobar->setDescription( currentPage()->description() );
+ m_infobar->setPixmap( currentPage()->pixmap() );
}
@@ -646,17 +618,20 @@ PlaylistManager::onWidgetDestroyed( QWidget* widget )
bool resetWidget = ( m_stack->currentWidget() == widget );
m_stack->removeWidget( widget );
- if ( resetWidget && m_interfaceHistory.count() )
+ for ( int i = 0; i < m_pageHistory.count(); i++ )
{
- unlinkPlaylist();
+ ViewPage* page = m_pageHistory.at( i );
+ if ( page->widget() == widget )
+ {
+ m_pageHistory.removeAt( i );
+ break;
+ }
+ }
- m_currentInterface = m_interfaceHistory.last();
- qDebug() << "Last interface:" << m_currentInterface << m_currentInterface->widget();
-
- if ( m_currentInterface->widget() )
- m_stack->setCurrentWidget( m_currentInterface->widget() );
-
- linkPlaylist();
+ if ( resetWidget )
+ {
+ if ( m_pageHistory.count() )
+ showHistory( m_pageHistory.count() - 1 );
}
}
@@ -664,16 +639,16 @@ PlaylistManager::onWidgetDestroyed( QWidget* widget )
void
PlaylistManager::setRepeatMode( PlaylistInterface::RepeatMode mode )
{
- if ( m_currentInterface )
- m_currentInterface->setRepeatMode( mode );
+ if ( currentPlaylistInterface() )
+ currentPlaylistInterface()->setRepeatMode( mode );
}
void
PlaylistManager::setShuffled( bool enabled )
{
- if ( m_currentInterface )
- m_currentInterface->setShuffled( enabled );
+ if ( currentPlaylistInterface() )
+ currentPlaylistInterface()->setShuffled( enabled );
}
@@ -697,20 +672,121 @@ PlaylistManager::createDynamicPlaylist( const Tomahawk::source_ptr& src,
}
+ViewPage*
+PlaylistManager::pageForInterface( PlaylistInterface* interface ) const
+{
+ for ( int i = 0; i < m_pageHistory.count(); i++ )
+ {
+ ViewPage* page = m_pageHistory.at( i );
+ if ( page->playlistInterface() == interface )
+ return page;
+ }
+
+ return 0;
+}
+
+
+int
+PlaylistManager::positionInHistory( ViewPage* page ) const
+{
+ for ( int i = 0; i < m_pageHistory.count(); i++ )
+ {
+ if ( page == m_pageHistory.at( i ) )
+ return i;
+ }
+
+ return -1;
+}
+
+
+PlaylistInterface*
+PlaylistManager::currentPlaylistInterface() const
+{
+ if ( currentPage() )
+ return currentPage()->playlistInterface();
+ else
+ return 0;
+}
+
+
+Tomahawk::ViewPage*
+PlaylistManager::currentPage() const
+{
+ if ( m_historyPosition >= 0 )
+ return m_pageHistory.at( m_historyPosition );
+ else
+ return 0;
+}
+
+
+void
+PlaylistManager::setHistoryPosition( int position )
+{
+ m_historyPosition = position;
+
+ emit historyBackAvailable( m_historyPosition > 0 );
+ emit historyForwardAvailable( m_historyPosition < m_pageHistory.count() - 1 );
+}
+
+
+Tomahawk::playlist_ptr
+PlaylistManager::playlistForInterface( PlaylistInterface* interface ) const
+{
+ foreach ( PlaylistView* view, m_playlistViews.values() )
+ {
+ if ( view->playlistInterface() == interface )
+ {
+ return m_playlistViews.key( view );
+ }
+ }
+
+ return playlist_ptr();
+}
+
+
+Tomahawk::dynplaylist_ptr
+PlaylistManager::dynamicPlaylistForInterface( PlaylistInterface* interface ) const
+{
+ foreach ( DynamicWidget* view, m_dynamicWidgets.values() )
+ {
+ if ( view->playlistInterface() == interface )
+ {
+ return m_dynamicWidgets.key( view );
+ }
+ }
+
+ return dynplaylist_ptr();
+}
+
+
+Tomahawk::collection_ptr
+PlaylistManager::collectionForInterface( PlaylistInterface* interface ) const
+{
+ foreach ( CollectionView* view, m_collectionViews.values() )
+ {
+ if ( view->playlistInterface() == interface )
+ {
+ return m_collectionViews.key( view );
+ }
+ }
+ foreach ( AlbumView* view, m_collectionAlbumViews.values() )
+ {
+ if ( view->playlistInterface() == interface )
+ {
+ return m_collectionAlbumViews.key( view );
+ }
+ }
+
+ return collection_ptr();
+}
+
+
void
PlaylistManager::showCurrentTrack()
{
- unlinkPlaylist();
-
- m_currentInterface = AudioEngine::instance()->currentTrackPlaylist();
-
- if ( m_currentInterface->widget() )
- m_stack->setCurrentWidget( m_currentInterface->widget() );
-
- linkPlaylist();
-
-/* if ( m_currentView && m_currentProxyModel )
- m_currentView->scrollTo( m_currentProxyModel->currentItem(), QAbstractItemView::PositionAtCenter );*/
+ ViewPage* page = pageForInterface( AudioEngine::instance()->currentTrackPlaylist() );
+ setPage( page );
+ page->jumpToCurrentTrack();
}
@@ -725,4 +801,4 @@ void
PlaylistManager::onPauseClicked()
{
emit pauseClicked();
-}
\ No newline at end of file
+}
diff --git a/src/libtomahawk/playlist/playlistmanager.h b/src/libtomahawk/playlist/playlistmanager.h
index 0c327e494..722f7286e 100644
--- a/src/libtomahawk/playlist/playlistmanager.h
+++ b/src/libtomahawk/playlist/playlistmanager.h
@@ -7,6 +7,7 @@
#include "collection.h"
#include "playlistinterface.h"
+#include "viewpage.h"
#include "dllmacro.h"
@@ -25,8 +26,10 @@ class TrackView;
class SourceInfoWidget;
class InfoBar;
class TopBar;
+class WelcomeWidget;
-namespace Tomahawk {
+namespace Tomahawk
+{
class DynamicWidget;
}
@@ -45,7 +48,10 @@ public:
bool isSuperCollectionVisible() const { return true; }
- PlaylistInterface* currentPlaylistInterface() const { return m_currentInterface; }
+ PlaylistInterface* currentPlaylistInterface() const;
+ Tomahawk::ViewPage* currentPage() const;
+ Tomahawk::ViewPage* pageForInterface( PlaylistInterface* interface ) const;
+ int positionInHistory( Tomahawk::ViewPage* page ) const;
bool show( const Tomahawk::playlist_ptr& playlist );
bool show( const Tomahawk::dynplaylist_ptr& playlist );
@@ -54,10 +60,7 @@ public:
bool show( const Tomahawk::collection_ptr& collection );
bool show( const Tomahawk::source_ptr& source );
- bool show( QWidget* widget, const QString& title = QString(), const QString& desc = QString(), const QPixmap& pixmap = QPixmap() );
-
- bool showSuperCollection();
- void showCurrentTrack();
+ bool show( Tomahawk::ViewPage* page );
signals:
void numSourcesChanged( unsigned int sources );
@@ -70,10 +73,29 @@ signals:
void statsAvailable( bool b );
void modesAvailable( bool b );
+ void modeChanged( PlaylistInterface::ViewMode mode );
void playClicked();
void pauseClicked();
+
+ void historyBackAvailable( bool avail );
+ void historyForwardAvailable( bool avail );
+
+ void tempPageActivated();
+ void superCollectionActivated();
+ void collectionActivated( const Tomahawk::collection_ptr& collection );
+ void playlistActivated( const Tomahawk::playlist_ptr& playlist );
+ void dynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist );
+
public slots:
+ bool showSuperCollection();
+ void showWelcomePage();
+ void showCurrentTrack();
+
+ void historyBack();
+ void historyForward();
+ void showHistory( int historyPosition );
+
void setTreeMode();
void setTableMode();
void setAlbumMode();
@@ -100,9 +122,15 @@ private slots:
void onWidgetDestroyed( QWidget* widget );
private:
+ void setHistoryPosition( int position );
+ void setPage( Tomahawk::ViewPage* page, bool trackHistory = true );
+ void updateView();
void unlinkPlaylist();
- void linkPlaylist();
+ Tomahawk::playlist_ptr playlistForInterface( PlaylistInterface* interface ) const;
+ Tomahawk::dynplaylist_ptr dynamicPlaylistForInterface( PlaylistInterface* interface ) const;
+ Tomahawk::collection_ptr collectionForInterface( PlaylistInterface* interface ) const;
+
QWidget* m_widget;
InfoBar* m_infobar;
TopBar* m_topbar;
@@ -115,7 +143,8 @@ private:
AlbumModel* m_superAlbumModel;
AlbumView* m_superAlbumView;
CollectionFlatModel* m_superCollectionFlatModel;
- CollectionView* m_superCollectionView;
+ CollectionView* m_superCollectionView;
+ WelcomeWidget* m_welcomeWidget;
QList< Tomahawk::collection_ptr > m_superCollections;
@@ -126,19 +155,15 @@ private:
QHash< Tomahawk::album_ptr, PlaylistView* > m_albumViews;
QHash< Tomahawk::playlist_ptr, PlaylistView* > m_playlistViews;
QHash< Tomahawk::source_ptr, SourceInfoWidget* > m_sourceViews;
-
- PlaylistInterface* m_currentInterface;
- QList m_interfaceHistory;
-
- QWidget* m_currentInfoWidget;
+
+ QList m_pageHistory;
+ int m_historyPosition;
Tomahawk::collection_ptr m_currentCollection;
int m_currentMode;
bool m_superCollectionVisible;
- bool m_statsAvailable;
- bool m_modesAvailable;
-
+
QTimer m_filterTimer;
QString m_filter;
diff --git a/src/libtomahawk/playlist/playlistmodel.cpp b/src/libtomahawk/playlist/playlistmodel.cpp
index 620cc240b..660e9a1a7 100644
--- a/src/libtomahawk/playlist/playlistmodel.cpp
+++ b/src/libtomahawk/playlist/playlistmodel.cpp
@@ -67,8 +67,10 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn
connect( playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), SLOT( onRevisionLoaded( Tomahawk::PlaylistRevision ) ) );
setReadOnly( !m_playlist->author()->isLocal() );
+ setTitle( playlist->title() );
+ setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) );
- if( !loadEntries )
+ if ( !loadEntries )
return;
PlItem* plitem;
diff --git a/src/libtomahawk/playlist/playlistview.cpp b/src/libtomahawk/playlist/playlistview.cpp
index b2a367dfc..18abb0d01 100644
--- a/src/libtomahawk/playlist/playlistview.cpp
+++ b/src/libtomahawk/playlist/playlistview.cpp
@@ -4,7 +4,6 @@
#include
#include
-#include "playlist/playlistmodel.h"
#include "playlist/playlistproxymodel.h"
#include "widgets/overlaywidget.h"
@@ -129,3 +128,10 @@ PlaylistView::onTrackCountChanged( unsigned int tracks )
else
overlay()->hide();
}
+
+
+bool
+PlaylistView::jumpToCurrentTrack()
+{
+ scrollTo( proxyModel()->currentItem(), QAbstractItemView::PositionAtCenter );
+}
diff --git a/src/libtomahawk/playlist/playlistview.h b/src/libtomahawk/playlist/playlistview.h
index 1e7c80c70..26a543316 100644
--- a/src/libtomahawk/playlist/playlistview.h
+++ b/src/libtomahawk/playlist/playlistview.h
@@ -3,13 +3,16 @@
#include
+#include "playlist/trackproxymodel.h"
+#include "playlist/playlistmodel.h"
#include "trackview.h"
+#include "viewpage.h"
#include "dllmacro.h"
class PlaylistModel;
-class DLLEXPORT PlaylistView : public TrackView
+class DLLEXPORT PlaylistView : public TrackView, public Tomahawk::ViewPage
{
Q_OBJECT
@@ -20,6 +23,14 @@ public:
PlaylistModel* playlistModel() const { return m_model; }
virtual void setModel( PlaylistModel* model );
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return proxyModel(); }
+
+ virtual QString title() const { return playlistModel()->title(); }
+ virtual QString description() const { return m_model->description(); }
+
+ virtual bool jumpToCurrentTrack();
+
protected:
void keyPressEvent( QKeyEvent* event );
diff --git a/src/libtomahawk/playlist/topbar/topbar.cpp b/src/libtomahawk/playlist/topbar/topbar.cpp
index dd6705bfd..3aa584bf5 100644
--- a/src/libtomahawk/playlist/topbar/topbar.cpp
+++ b/src/libtomahawk/playlist/topbar/topbar.cpp
@@ -65,7 +65,28 @@ TopBar::TopBar( QWidget* parent )
setNumArtists( 0 );
setNumShown( 0 );
- ui->radioNormal->setChecked( true );
+ onFlatMode();
+
+ connect( PlaylistManager::instance(), SIGNAL( numSourcesChanged( unsigned int ) ),
+ SLOT( setNumSources( unsigned int ) ) );
+
+ connect( PlaylistManager::instance(), SIGNAL( numTracksChanged( unsigned int ) ),
+ SLOT( setNumTracks( unsigned int ) ) );
+
+ connect( PlaylistManager::instance(), SIGNAL( numArtistsChanged( unsigned int ) ),
+ SLOT( setNumArtists( unsigned int ) ) );
+
+ connect( PlaylistManager::instance(), SIGNAL( numShownChanged( unsigned int ) ),
+ SLOT( setNumShown( unsigned int ) ) );
+
+ connect( PlaylistManager::instance(), SIGNAL( statsAvailable( bool ) ),
+ SLOT( setStatsVisible( bool ) ) );
+
+ connect( PlaylistManager::instance(), SIGNAL( modesAvailable( bool ) ),
+ SLOT( setModesVisible( bool ) ) );
+
+ connect( PlaylistManager::instance(), SIGNAL( modeChanged( PlaylistInterface::ViewMode ) ),
+ SLOT( onModeChanged( PlaylistInterface::ViewMode ) ) );
}
@@ -238,3 +259,48 @@ TopBar::setFilter( const QString& filter )
{
ui->filterEdit->setText( filter );
}
+
+
+void
+TopBar::onModeChanged( PlaylistInterface::ViewMode mode )
+{
+ qDebug() << Q_FUNC_INFO << mode;
+ switch ( mode )
+ {
+ case PlaylistInterface::Flat:
+ onFlatMode();
+ break;
+
+ case PlaylistInterface::Tree:
+ onArtistMode();
+ break;
+
+ case PlaylistInterface::Album:
+ onAlbumMode();
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+void
+TopBar::onFlatMode()
+{
+ ui->radioNormal->setChecked( true );
+}
+
+
+void
+TopBar::onArtistMode()
+{
+ ui->radioDetailed->setChecked( true );
+}
+
+
+void
+TopBar::onAlbumMode()
+{
+ ui->radioCloud->setChecked( true );
+}
diff --git a/src/libtomahawk/playlist/topbar/topbar.h b/src/libtomahawk/playlist/topbar/topbar.h
index f51b27e30..439768029 100644
--- a/src/libtomahawk/playlist/topbar/topbar.h
+++ b/src/libtomahawk/playlist/topbar/topbar.h
@@ -5,6 +5,7 @@
#include
#include
+#include "playlist/playlistmanager.h"
#include "sourcelist.h"
#include "dllmacro.h"
@@ -42,6 +43,12 @@ public slots:
void setFilter( const QString& filter );
+private slots:
+ void onModeChanged( PlaylistInterface::ViewMode mode );
+ void onFlatMode();
+ void onArtistMode();
+ void onAlbumMode();
+
protected:
void changeEvent( QEvent* e );
void resizeEvent( QResizeEvent* e );
diff --git a/src/libtomahawk/playlist/trackmodel.h b/src/libtomahawk/playlist/trackmodel.h
index ad43006be..f67b6631a 100644
--- a/src/libtomahawk/playlist/trackmodel.h
+++ b/src/libtomahawk/playlist/trackmodel.h
@@ -35,6 +35,11 @@ public:
virtual bool isReadOnly() const { return m_readOnly; }
+ virtual QString title() const { return m_title; }
+ virtual void setTitle( const QString& title ) { m_title = title; }
+ virtual QString description() const { return m_description; }
+ virtual void setDescription( const QString& description ) { m_description = description; }
+
virtual int trackCount() const { return rowCount( QModelIndex() ); }
virtual int rowCount( const QModelIndex& parent ) const;
@@ -84,6 +89,9 @@ private slots:
private:
QPersistentModelIndex m_currentIndex;
bool m_readOnly;
+
+ QString m_title;
+ QString m_description;
};
#endif // TRACKMODEL_H
diff --git a/src/libtomahawk/playlist/trackview.cpp b/src/libtomahawk/playlist/trackview.cpp
index c2a972ed1..bdc139773 100644
--- a/src/libtomahawk/playlist/trackview.cpp
+++ b/src/libtomahawk/playlist/trackview.cpp
@@ -73,7 +73,6 @@ void
TrackView::setProxyModel( TrackProxyModel* model )
{
m_proxyModel = model;
- m_proxyModel->setWidget( this );
m_delegate = new PlaylistItemDelegate( this, m_proxyModel );
setItemDelegate( m_delegate );
diff --git a/src/libtomahawk/playlistinterface.h b/src/libtomahawk/playlistinterface.h
index 7ef4fefd1..f8a56fa32 100644
--- a/src/libtomahawk/playlistinterface.h
+++ b/src/libtomahawk/playlistinterface.h
@@ -13,8 +13,9 @@ class DLLEXPORT PlaylistInterface
{
public:
enum RepeatMode { NoRepeat, RepeatOne, RepeatAll };
-
- PlaylistInterface( QObject* parent = 0 ) : m_widget( 0 ), m_object( parent ) {}
+ enum ViewMode { Unknown, Flat, Tree, Album };
+
+ PlaylistInterface( QObject* parent = 0 ) : m_object( parent ) {}
virtual ~PlaylistInterface() {}
virtual QList< Tomahawk::query_ptr > tracks() = 0;
@@ -28,13 +29,11 @@ public:
virtual PlaylistInterface::RepeatMode repeatMode() const = 0;
virtual bool shuffled() const = 0;
+ virtual PlaylistInterface::ViewMode viewMode() const { return Unknown; }
virtual QString filter() const { return m_filter; }
virtual void setFilter( const QString& pattern ) { m_filter = pattern; }
- QWidget* widget() const { return m_widget; }
- void setWidget( QWidget* widget ) { m_widget = widget; }
-
QObject* object() const { return m_object; }
public slots:
@@ -48,7 +47,6 @@ signals:
virtual void sourceTrackCountChanged( unsigned int tracks ) = 0;
private:
- QWidget* m_widget;
QObject* m_object;
QString m_filter;
diff --git a/src/libtomahawk/source.cpp b/src/libtomahawk/source.cpp
index e6400344f..0c24deb26 100644
--- a/src/libtomahawk/source.cpp
+++ b/src/libtomahawk/source.cpp
@@ -159,7 +159,7 @@ Source::scanningProgress( unsigned int files )
void
Source::scanningFinished( unsigned int files )
{
- m_textStatus = tr( "Online" );
+ m_textStatus = QString();
emit stateChanged();
}
@@ -183,14 +183,14 @@ Source::onStateChanged( DBSyncConnection::State newstate, DBSyncConnection::Stat
msg = tr( "Saving" );
break;
case DBSyncConnection::SYNCED:
- msg = tr( "Online" );
+ msg = QString();
break;
case DBSyncConnection::SCANNING:
msg = tr( "Scanning (%L1 tracks)" ).arg( info );
break;
default:
- msg = "???";
+ msg = QString();
}
m_textStatus = msg;
diff --git a/src/libtomahawk/source.h b/src/libtomahawk/source.h
index 3e598c4aa..f1719cfce 100644
--- a/src/libtomahawk/source.h
+++ b/src/libtomahawk/source.h
@@ -42,7 +42,7 @@ public:
void addCollection( const Tomahawk::collection_ptr& c );
void removeCollection( const Tomahawk::collection_ptr& c );
- unsigned int id() const { return m_id; }
+ int id() const { return m_id; }
ControlConnection* controlConnection() const { return m_cc; }
void setControlConnection( ControlConnection* cc );
@@ -90,7 +90,7 @@ private:
bool m_isLocal;
bool m_online;
QString m_username, m_friendlyname;
- unsigned int m_id;
+ int m_id;
QList< QSharedPointer > m_collections;
QVariantMap m_stats;
QString m_lastOpGuid;
diff --git a/src/libtomahawk/sourcelist.cpp b/src/libtomahawk/sourcelist.cpp
index 20be81298..45a2c74ce 100644
--- a/src/libtomahawk/sourcelist.cpp
+++ b/src/libtomahawk/sourcelist.cpp
@@ -86,10 +86,11 @@ SourceList::setLocal( const Tomahawk::source_ptr& localSrc )
void
SourceList::add( const source_ptr& source )
{
- Q_ASSERT( source->id() );
-
+ qDebug() << "Adding to sources:" << source->userName() << source->id();
m_sources.insert( source->userName(), source );
- m_sources_id2name.insert( source->id(), source->userName() );
+
+ if ( source->id() > 0 )
+ m_sources_id2name.insert( source->id(), source->userName() );
connect( source.data(), SIGNAL( syncedWithDatabase() ), SLOT( sourceSynced() ) );
collection_ptr coll( new RemoteCollection( source ) );
@@ -102,14 +103,11 @@ SourceList::add( const source_ptr& source )
void
SourceList::removeAllRemote()
{
- foreach( source_ptr s, m_sources )
+ foreach( const source_ptr& s, m_sources )
{
- if( s != m_local )
+ if ( !s->isLocal() && s->controlConnection() )
{
- if ( s->controlConnection() )
- {
- s->controlConnection()->shutdown( true );
- }
+ s->controlConnection()->shutdown( true );
}
}
}
@@ -132,7 +130,7 @@ SourceList::sources( bool onlyOnline ) const
source_ptr
-SourceList::get( unsigned int id ) const
+SourceList::get( int id ) const
{
QMutexLocker lock( &m_mut );
return m_sources.value( m_sources_id2name.value( id ) );
@@ -163,8 +161,6 @@ SourceList::sourceSynced()
{
Source* src = qobject_cast< Source* >( sender() );
- Q_ASSERT( m_sources_id2name.values().contains( src->userName() ) );
- m_sources_id2name.remove( m_sources_id2name.key( src->userName() ) );
m_sources_id2name.insert( src->id(), src->userName() );
}
diff --git a/src/libtomahawk/sourcelist.h b/src/libtomahawk/sourcelist.h
index aeabad234..8b1861476 100644
--- a/src/libtomahawk/sourcelist.h
+++ b/src/libtomahawk/sourcelist.h
@@ -28,7 +28,7 @@ public:
unsigned int count() const;
Tomahawk::source_ptr get( const QString& username, const QString& friendlyName = QString() );
- Tomahawk::source_ptr get( unsigned int id ) const;
+ Tomahawk::source_ptr get( int id ) const;
signals:
void ready();
@@ -45,7 +45,7 @@ private:
void add( const Tomahawk::source_ptr& source );
QMap< QString, Tomahawk::source_ptr > m_sources;
- QMap< unsigned int, QString > m_sources_id2name;
+ QMap< int, QString > m_sources_id2name;
Tomahawk::source_ptr m_local;
mutable QMutex m_mut; // mutable so const methods can use a lock
diff --git a/src/libtomahawk/utils/tomahawkutils.cpp b/src/libtomahawk/utils/tomahawkutils.cpp
index 45238a542..1b5db86fe 100644
--- a/src/libtomahawk/utils/tomahawkutils.cpp
+++ b/src/libtomahawk/utils/tomahawkutils.cpp
@@ -205,7 +205,7 @@ filesizeToString( unsigned int size )
if ( mb )
{
- return QString( "%1.%2 Mb" ).arg( mb ).arg( int( ( kb % 1024 ) / 100 ) );
+ return QString( "%1.%2 Mb" ).arg( mb ).arg( int( ( kb % 1024 ) / 102.4 ) );
}
else if ( kb )
{
diff --git a/src/libtomahawk/viewpage.cpp b/src/libtomahawk/viewpage.cpp
new file mode 100644
index 000000000..321bbbdf8
--- /dev/null
+++ b/src/libtomahawk/viewpage.cpp
@@ -0,0 +1,6 @@
+#include "viewpage.h"
+
+#include
+
+using namespace Tomahawk;
+
diff --git a/src/libtomahawk/viewpage.h b/src/libtomahawk/viewpage.h
new file mode 100644
index 000000000..af087c669
--- /dev/null
+++ b/src/libtomahawk/viewpage.h
@@ -0,0 +1,38 @@
+#ifndef VIEWPAGE_H
+#define VIEWPAGE_H
+
+#include
+
+#include "typedefs.h"
+#include "playlistinterface.h"
+#include "utils/tomahawkutils.h"
+
+#include "dllmacro.h"
+
+namespace Tomahawk
+{
+
+class DLLEXPORT ViewPage
+{
+public:
+ ViewPage() {}
+
+ virtual QWidget* widget() = 0;
+ virtual PlaylistInterface* playlistInterface() const = 0;
+
+ virtual QString title() const = 0;
+ virtual QString description() const = 0;
+ virtual QPixmap pixmap() const { return QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ); }
+
+ virtual bool showStatsBar() const { return true; }
+ virtual bool showModes() const { return false; }
+ virtual bool queueVisible() const { return true; }
+
+ virtual bool jumpToCurrentTrack() = 0;
+
+private:
+};
+
+}; // ns
+
+#endif //VIEWPAGE_H
diff --git a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp
index ad57103d2..80469499e 100644
--- a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp
+++ b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp
@@ -43,6 +43,8 @@ SourceInfoWidget::SourceInfoWidget( const Tomahawk::source_ptr& source, QWidget*
m_recentAlbumModel = new AlbumModel( ui->recentAlbumView );
ui->recentAlbumView->setModel( m_recentAlbumModel );
m_recentAlbumModel->addFilteredCollection( source->collection(), 20, DatabaseCommand_AllAlbums::ModificationTime );
+
+ m_title = tr( "Info about %1" ).arg( source->isLocal() ? tr( "Your Collection" ) : source->friendlyName() );
}
diff --git a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h
index 8d369a97e..f12fd942d 100644
--- a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h
+++ b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h
@@ -6,6 +6,7 @@
#include "album.h"
#include "result.h"
#include "playlistinterface.h"
+#include "viewpage.h"
#include "dllmacro.h"
@@ -18,7 +19,7 @@ namespace Ui
class SourceInfoWidget;
}
-class DLLEXPORT SourceInfoWidget : public QWidget
+class DLLEXPORT SourceInfoWidget : public QWidget, public Tomahawk::ViewPage
{
Q_OBJECT
@@ -26,6 +27,16 @@ public:
SourceInfoWidget( const Tomahawk::source_ptr& source, QWidget* parent = 0 );
~SourceInfoWidget();
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return 0; }
+
+ virtual QString title() const { return m_title; }
+ virtual QString description() const { return m_description; }
+
+ virtual bool showStatsBar() const { return false; }
+
+ virtual bool jumpToCurrentTrack() { return false; }
+
protected:
void changeEvent( QEvent* e );
@@ -38,6 +49,9 @@ private:
CollectionFlatModel* m_recentCollectionModel;
PlaylistModel* m_historyModel;
AlbumModel* m_recentAlbumModel;
+
+ QString m_title;
+ QString m_description;
};
#endif // SOURCEINFOWIDGET_H
diff --git a/src/libtomahawk/widgets/newplaylistwidget.h b/src/libtomahawk/widgets/newplaylistwidget.h
index f19590aa7..dfe54a988 100644
--- a/src/libtomahawk/widgets/newplaylistwidget.h
+++ b/src/libtomahawk/widgets/newplaylistwidget.h
@@ -7,6 +7,7 @@
#include "album.h"
#include "result.h"
#include "playlistinterface.h"
+#include "viewpage.h"
#include "dllmacro.h"
@@ -18,7 +19,7 @@ namespace Ui
class NewPlaylistWidget;
}
-class DLLEXPORT NewPlaylistWidget : public QWidget
+class DLLEXPORT NewPlaylistWidget : public QWidget, public Tomahawk::ViewPage
{
Q_OBJECT
@@ -26,6 +27,16 @@ public:
NewPlaylistWidget( QWidget* parent = 0 );
~NewPlaylistWidget();
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return 0; }
+
+ virtual QString title() const { return tr( "Create a new playlist" ); }
+ virtual QString description() const { return QString(); }
+
+ virtual bool showStatsBar() const { return false; }
+
+ virtual bool jumpToCurrentTrack() { return false; }
+
protected:
void changeEvent( QEvent* e );
diff --git a/src/libtomahawk/widgets/newplaylistwidget.ui b/src/libtomahawk/widgets/newplaylistwidget.ui
index 8b30f4780..6a2701ee8 100644
--- a/src/libtomahawk/widgets/newplaylistwidget.ui
+++ b/src/libtomahawk/widgets/newplaylistwidget.ui
@@ -11,28 +11,11 @@
- -
-
-
-
- 20
- 75
- true
-
-
-
- Create A New Playlist
-
-
- false
-
-
-
-
- 14
+ 13
@@ -54,7 +37,7 @@
- 14
+ 13
@@ -69,7 +52,7 @@
- 14
+ 13
diff --git a/src/libtomahawk/widgets/welcomewidget.h b/src/libtomahawk/widgets/welcomewidget.h
index 79f700448..9d14859e8 100644
--- a/src/libtomahawk/widgets/welcomewidget.h
+++ b/src/libtomahawk/widgets/welcomewidget.h
@@ -9,6 +9,7 @@
#include "playlist.h"
#include "result.h"
+#include "viewpage.h"
#include "utils/tomahawkutils.h"
@@ -73,7 +74,7 @@ private:
};
-class DLLEXPORT WelcomeWidget : public QWidget
+class DLLEXPORT WelcomeWidget : public QWidget, public Tomahawk::ViewPage
{
Q_OBJECT
@@ -81,6 +82,16 @@ public:
WelcomeWidget( QWidget* parent = 0 );
~WelcomeWidget();
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return 0; }
+
+ virtual QString title() const { return tr( "Welcome to Tomahawk" ); }
+ virtual QString description() const { return QString(); }
+
+ virtual bool showStatsBar() const { return false; }
+
+ virtual bool jumpToCurrentTrack() { return false; }
+
protected:
void changeEvent( QEvent* e );
diff --git a/src/sip/jabber/jabber_p.cpp b/src/sip/jabber/jabber_p.cpp
index a891973a9..cf090c107 100644
--- a/src/sip/jabber/jabber_p.cpp
+++ b/src/sip/jabber/jabber_p.cpp
@@ -526,7 +526,7 @@ Jabber_p::handleRosterPresence( const RosterItem& item, const std::string& resou
// convert to QString to get proper regex support
QString res( jid.resource().c_str() );
QRegExp regex( "tomahawk\\d+" );
- if( res != "tomahawk-tomahawk" && !res.contains( regex ) )
+ if( res != "tomahawk-tomahawk" && !res.startsWith( "tomahawk" ) )
{
//qDebug() << "not considering resource of" << res;
// Disco them to check if they are tomahawk-capable
diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp
index 3a8cf60ce..e2a95de0c 100644
--- a/src/sourcetree/sourcesmodel.cpp
+++ b/src/sourcetree/sourcesmodel.cpp
@@ -58,7 +58,8 @@ SourcesModel::flags( const QModelIndex& index ) const
playlist_ptr playlist = indexToPlaylist( index );
if ( !playlist.isNull() && playlist->author()->isLocal() )
defaultFlags |= Qt::ItemIsEditable;
- } else if ( indexType( index ) == DynamicPlaylistSource )
+ }
+ else if ( indexType( index ) == DynamicPlaylistSource )
{
dynplaylist_ptr playlist = indexToDynamicPlaylist( index );
if ( !playlist.isNull() && playlist->author()->isLocal() )
@@ -124,13 +125,15 @@ SourcesModel::appendItem( const source_ptr& source )
// qDebug() << "Appending source item:" << item->source()->username();
invisibleRootItem()->appendRow( item->columns() );
-// m_parent->setIndexWidget( m_parent->model()->index( rowCount() - 1, 0 ), item->widget() );
- connect( source.data(), SIGNAL( offline() ), SLOT( onSourceChanged() ) );
- connect( source.data(), SIGNAL( online() ), SLOT( onSourceChanged() ) );
- connect( source.data(), SIGNAL( stats( QVariantMap ) ), SLOT( onSourceChanged() ) );
- connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), SLOT( onSourceChanged() ) );
- connect( source.data(), SIGNAL( stateChanged() ), SLOT( onSourceChanged() ) );
+ if ( !source.isNull() )
+ {
+ connect( source.data(), SIGNAL( offline() ), SLOT( onSourceChanged() ) );
+ connect( source.data(), SIGNAL( online() ), SLOT( onSourceChanged() ) );
+ connect( source.data(), SIGNAL( stats( QVariantMap ) ), SLOT( onSourceChanged() ) );
+ connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), SLOT( onSourceChanged() ) );
+ connect( source.data(), SIGNAL( stateChanged() ), SLOT( onSourceChanged() ) );
+ }
return true; // FIXME
}
@@ -259,6 +262,75 @@ SourcesModel::indexToTreeItem( const QModelIndex& index )
}
+QModelIndex
+SourcesModel::playlistToIndex( const Tomahawk::playlist_ptr& playlist )
+{
+ for ( int i = 0; i < rowCount(); i++ )
+ {
+ QModelIndex pidx = index( i, 0 );
+
+ for ( int j = 0; j < rowCount( pidx ); j++ )
+ {
+ QModelIndex idx = index( j, 0, pidx );
+ SourcesModel::SourceType type = SourcesModel::indexType( idx );
+
+ if ( type == SourcesModel::PlaylistSource )
+ {
+ playlist_ptr p = SourcesModel::indexToPlaylist( idx );
+ if ( playlist.data() == p.data() )
+ return idx;
+ }
+ }
+ }
+
+ return QModelIndex();
+}
+
+
+QModelIndex
+SourcesModel::dynamicPlaylistToIndex( const Tomahawk::dynplaylist_ptr& playlist )
+{
+ for ( int i = 0; i < rowCount(); i++ )
+ {
+ QModelIndex pidx = index( i, 0 );
+
+ for ( int j = 0; j < rowCount( pidx ); j++ )
+ {
+ QModelIndex idx = index( j, 0, pidx );
+ SourcesModel::SourceType type = SourcesModel::indexType( idx );
+
+ if ( type == SourcesModel::DynamicPlaylistSource )
+ {
+ playlist_ptr p = SourcesModel::indexToDynamicPlaylist( idx );
+ if ( playlist.data() == p.data() )
+ return idx;
+ }
+ }
+ }
+
+ return QModelIndex();
+}
+
+
+QModelIndex
+SourcesModel::collectionToIndex( const Tomahawk::collection_ptr& collection )
+{
+ for ( int i = 0; i < rowCount(); i++ )
+ {
+ QModelIndex idx = index( i, 0 );
+ SourcesModel::SourceType type = SourcesModel::indexType( idx );
+ if ( type == SourcesModel::CollectionSource )
+ {
+ SourceTreeItem* sti = SourcesModel::indexToTreeItem( idx );
+ if ( sti && !sti->source().isNull() && sti->source()->collection().data() == collection.data() )
+ return idx;
+ }
+ }
+
+ return QModelIndex();
+}
+
+
bool
SourcesModel::setData( const QModelIndex& index, const QVariant& value, int role )
{
diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h
index 2b761637b..e258e73ff 100644
--- a/src/sourcetree/sourcesmodel.h
+++ b/src/sourcetree/sourcesmodel.h
@@ -37,6 +37,10 @@ public:
static Tomahawk::dynplaylist_ptr indexToDynamicPlaylist( const QModelIndex& index );
static SourceTreeItem* indexToTreeItem( const QModelIndex& index );
+ QModelIndex playlistToIndex( const Tomahawk::playlist_ptr& playlist );
+ QModelIndex dynamicPlaylistToIndex( const Tomahawk::dynplaylist_ptr& playlist );
+ QModelIndex collectionToIndex( const Tomahawk::collection_ptr& collection );
+
signals:
void clicked( const QModelIndex& );
diff --git a/src/sourcetree/sourcetreeitem.cpp b/src/sourcetree/sourcetreeitem.cpp
index 0e4ec8748..96fa06a8d 100644
--- a/src/sourcetree/sourcetreeitem.cpp
+++ b/src/sourcetree/sourcetreeitem.cpp
@@ -237,8 +237,8 @@ void SourceTreeItem::playlistAddedInternal( qlonglong ptr, const Tomahawk::playl
subitem->setData( (qlonglong)this, SourceItemPointer );
m_columns.at( 0 )->appendRow( subitem );
- Q_ASSERT( qobject_cast((parent()->parent()) ) );
- qobject_cast((parent()->parent()))->expandAll();
+// Q_ASSERT( qobject_cast((parent()->parent()) ) );
+// qobject_cast((parent()->parent()))->expandAll();
p->loadRevision();
}
diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp
index dbee09d92..177482a61 100644
--- a/src/sourcetree/sourcetreeview.cpp
+++ b/src/sourcetree/sourcetreeview.cpp
@@ -67,7 +67,7 @@ SourceTreeView::SourceTreeView( QWidget* parent )
setItemDelegate( new SourceDelegate( this ) );
setContextMenuPolicy( Qt::CustomContextMenu );
- connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
+ connect( this, SIGNAL( customContextMenuRequested( QPoint ) ), SLOT( onCustomContextMenu( QPoint ) ) );
m_model = new SourcesModel( this );
m_proxyModel = new SourcesProxyModel( m_model, this );
@@ -77,14 +77,25 @@ SourceTreeView::SourceTreeView( QWidget* parent )
header()->setResizeMode( 0, QHeaderView::Stretch );
connect( m_model, SIGNAL( clicked( QModelIndex ) ), SIGNAL( clicked( QModelIndex ) ) );
- connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
+ connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
- connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ), SLOT( onSelectionChanged() ) );
+ connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) );
connect( SourceList::instance(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) );
m_model->appendItem( source_ptr() );
hideOfflineSources();
+
+ connect( PlaylistManager::instance(), SIGNAL( playlistActivated( Tomahawk::playlist_ptr ) ),
+ SLOT( onPlaylistActivated( Tomahawk::playlist_ptr ) ) );
+ connect( PlaylistManager::instance(), SIGNAL( dynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ),
+ SLOT( onDynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ) );
+ connect( PlaylistManager::instance(), SIGNAL( collectionActivated( Tomahawk::collection_ptr ) ),
+ SLOT( onCollectionActivated( Tomahawk::collection_ptr ) ) );
+ connect( PlaylistManager::instance(), SIGNAL( superCollectionActivated() ),
+ SLOT( onSuperCollectionActivated() ) );
+ connect( PlaylistManager::instance(), SIGNAL( tempPageActivated() ),
+ SLOT( onTempPageActivated() ) );
}
@@ -143,6 +154,57 @@ SourceTreeView::onSourceOffline( Tomahawk::source_ptr src )
}
+void
+SourceTreeView::onPlaylistActivated( const Tomahawk::playlist_ptr& playlist )
+{
+ QModelIndex idx = m_proxyModel->mapFromSource( m_model->playlistToIndex( playlist ) );
+ if ( idx.isValid() )
+ {
+ setCurrentIndex( idx );
+ }
+}
+
+
+void
+SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist )
+{
+ QModelIndex idx = m_proxyModel->mapFromSource( m_model->dynamicPlaylistToIndex( playlist ) );
+ if ( idx.isValid() )
+ {
+ setCurrentIndex( idx );
+ }
+}
+
+
+void
+SourceTreeView::onCollectionActivated( const Tomahawk::collection_ptr& collection )
+{
+ QModelIndex idx = m_proxyModel->mapFromSource( m_model->collectionToIndex( collection ) );
+ if ( idx.isValid() )
+ {
+ setCurrentIndex( idx );
+ }
+}
+
+
+void
+SourceTreeView::onSuperCollectionActivated()
+{
+ QModelIndex idx = m_proxyModel->index( 0, 0 );
+ if ( idx.isValid() )
+ {
+ setCurrentIndex( idx );
+ }
+}
+
+
+void
+SourceTreeView::onTempPageActivated()
+{
+ clearSelection();
+}
+
+
void
SourceTreeView::onItemActivated( const QModelIndex& index )
{
@@ -469,7 +531,7 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
QString desc = status ? sti->source()->textStatus() : tr( "Offline" );
if ( sti->source().isNull() )
desc = tr( "All available tracks" );
- if ( status && !sti->source()->currentTrack().isNull() )
+ if ( status && desc.isEmpty() && !sti->source()->currentTrack().isNull() )
desc = sti->source()->currentTrack()->artist() + " - " + sti->source()->currentTrack()->track();
if ( desc.isEmpty() )
desc = tr( "Online" );
@@ -479,41 +541,39 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
text = painter->fontMetrics().elidedText( desc, Qt::ElideRight, textRect.width() );
painter->drawText( textRect, text );
- if ( !status )
+ if ( status )
{
- painter->restore();
- return;
+ painter->setRenderHint( QPainter::Antialiasing );
+
+ QRect figRect = o.rect.adjusted( o.rect.width() - figWidth - 18, 0, -10, -o.rect.height() + 16 );
+ int hd = ( option.rect.height() - figRect.height() ) / 2;
+ figRect.adjust( 0, hd, 0, hd );
+
+ QColor figColor( 167, 183, 211 );
+ painter->setPen( figColor );
+ painter->setBrush( figColor );
+
+ QPen origpen = painter->pen();
+ QPen pen = origpen;
+ pen.setWidth( 1.0 );
+ painter->setPen( pen );
+ painter->drawRect( figRect );
+
+ QPainterPath ppath;
+ ppath.moveTo( QPoint( figRect.x(), figRect.y() ) );
+ ppath.quadTo( QPoint( figRect.x() - 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x(), figRect.y() + figRect.height() ) );
+ painter->drawPath( ppath );
+ ppath.moveTo( QPoint( figRect.x() + figRect.width(), figRect.y() ) );
+ ppath.quadTo( QPoint( figRect.x() + figRect.width() + 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x() + figRect.width(), figRect.y() + figRect.height() ) );
+ painter->drawPath( ppath );
+
+ painter->setPen( origpen );
+
+ QTextOption to( Qt::AlignCenter );
+ painter->setFont( bold );
+ painter->setPen( Qt::white );
+ painter->drawText( figRect, tracks, to );
}
- painter->setRenderHint( QPainter::Antialiasing );
-
- QRect figRect = o.rect.adjusted( o.rect.width() - figWidth - 18, 0, -10, -o.rect.height() + 16 );
- int hd = ( option.rect.height() - figRect.height() ) / 2;
- figRect.adjust( 0, hd, 0, hd );
-
- QColor figColor( 167, 183, 211 );
- painter->setPen( figColor );
- painter->setBrush( figColor );
-
- QPen origpen = painter->pen();
- QPen pen = origpen;
- pen.setWidth( 1.0 );
- painter->setPen( pen );
- painter->drawRect( figRect );
-
- QPainterPath ppath;
- ppath.moveTo( QPoint( figRect.x(), figRect.y() ) );
- ppath.quadTo( QPoint( figRect.x() - 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x(), figRect.y() + figRect.height() ) );
- painter->drawPath( ppath );
- ppath.moveTo( QPoint( figRect.x() + figRect.width(), figRect.y() ) );
- ppath.quadTo( QPoint( figRect.x() + figRect.width() + 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x() + figRect.width(), figRect.y() + figRect.height() ) );
- painter->drawPath( ppath );
-
- painter->setPen( origpen );
-
- QTextOption to( Qt::AlignCenter );
- painter->setFont( bold );
- painter->setPen( Qt::white );
- painter->drawText( figRect, tracks, to );
painter->restore();
}
diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h
index 10df5d54d..077fb2937 100644
--- a/src/sourcetree/sourcetreeview.h
+++ b/src/sourcetree/sourcetreeview.h
@@ -27,6 +27,12 @@ signals:
void onOffline( const QModelIndex& index );
private slots:
+ void onPlaylistActivated( const Tomahawk::playlist_ptr& playlist );
+ void onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist );
+ void onCollectionActivated( const Tomahawk::collection_ptr& collection );
+ void onSuperCollectionActivated();
+ void onTempPageActivated();
+
void onItemActivated( const QModelIndex& index );
void onSelectionChanged();
diff --git a/src/tomahawk.protocol b/src/tomahawk.protocol
new file mode 100644
index 000000000..3a393aa61
--- /dev/null
+++ b/src/tomahawk.protocol
@@ -0,0 +1,12 @@
+[Protocol]
+exec=/home/leo/kde/tomahawk/build/tomahawk "%u"
+protocol=tomahawk
+input=none
+output=none
+helper=true
+listing=
+reading=false
+writing=false
+makedir=false
+deleting=false
+
diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp
index 45b4053c8..4d68b8aa7 100644
--- a/src/tomahawkapp.cpp
+++ b/src/tomahawkapp.cpp
@@ -175,6 +175,10 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
Tomahawk::setShortcutHandler( static_cast( m_shortcutHandler) );
Tomahawk::setApplicationHandler( this );
+
+ QFont f( QApplication::font() );
+ f.setPointSize( f.pointSize() - 2 );
+ QApplication::setFont( f );
#endif
// Connect up shortcuts
diff --git a/src/tomahawkwindow.cpp b/src/tomahawkwindow.cpp
index 0767af108..0fb8fd67d 100644
--- a/src/tomahawkwindow.cpp
+++ b/src/tomahawkwindow.cpp
@@ -29,7 +29,6 @@
#include "utils/widgetdragfilter.h"
#include "utils/xspfloader.h"
#include "widgets/newplaylistwidget.h"
-#include "widgets/welcomewidget.h"
#include "audiocontrols.h"
#include "settingsdialog.h"
@@ -57,6 +56,8 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
#endif
PlaylistManager* pm = new PlaylistManager( this );
+ connect( pm, SIGNAL( historyBackAvailable( bool ) ), SLOT( onHistoryBackAvailable( bool ) ) );
+ connect( pm, SIGNAL( historyForwardAvailable( bool ) ), SLOT( onHistoryForwardAvailable( bool ) ) );
connect( m_audioControls, SIGNAL( playPressed() ), pm, SLOT( onPlayClicked() ) );
connect( m_audioControls, SIGNAL( pausePressed() ), pm, SLOT( onPauseClicked() ) );
@@ -115,12 +116,17 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
ui->splitter->setCollapsible( 1, false );
ui->splitter->setHandleWidth( 1 );
-/* QToolBar* toolbar = addToolBar( "TomahawkToolbar" );
+ QToolBar* toolbar = addToolBar( "TomahawkToolbar" );
toolbar->setObjectName( "TomahawkToolbar" );
- toolbar->addWidget( m_topbar );
toolbar->setMovable( false );
toolbar->setFloatable( false );
- toolbar->installEventFilter( new WidgetDragFilter( toolbar ) );*/
+ toolbar->setIconSize( QSize( 32, 32 ) );
+ toolbar->setToolButtonStyle( Qt::ToolButtonFollowStyle );
+ toolbar->installEventFilter( new WidgetDragFilter( toolbar ) );
+
+ m_backAvailable = toolbar->addAction( QIcon( RESPATH "images/back.png" ), tr( "Back" ), PlaylistManager::instance(), SLOT( historyBack() ) );
+ m_forwardAvailable = toolbar->addAction( QIcon( RESPATH "images/forward.png" ), tr( "Forward" ), PlaylistManager::instance(), SLOT( historyForward() ) );
+ toolbar->addAction( QIcon( RESPATH "images/home.png" ), tr( "Home" ), PlaylistManager::instance(), SLOT( showWelcomePage() ) );
statusBar()->addPermanentWidget( m_audioControls, 1 );
@@ -135,8 +141,7 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
loadSettings();
setupSignals();
-
- PlaylistManager::instance()->show( new WelcomeWidget(), tr( "Welcome to Tomahawk!" ), QString(), QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ) );
+ PlaylistManager::instance()->showWelcomePage();
}
@@ -354,6 +359,20 @@ TomahawkWindow::onPlaybackLoading( const Tomahawk::result_ptr& result )
}
+void
+TomahawkWindow::onHistoryBackAvailable( bool avail )
+{
+ m_backAvailable->setEnabled( avail );
+}
+
+
+void
+TomahawkWindow::onHistoryForwardAvailable( bool avail )
+{
+ m_forwardAvailable->setEnabled( avail );
+}
+
+
void
TomahawkWindow::onSipConnected()
{
diff --git a/src/tomahawkwindow.h b/src/tomahawkwindow.h
index 5e6a24472..766066cd8 100644
--- a/src/tomahawkwindow.h
+++ b/src/tomahawkwindow.h
@@ -54,7 +54,9 @@ private slots:
void addPeerManually();
void onPlaybackLoading( const Tomahawk::result_ptr& result );
-
+ void onHistoryBackAvailable( bool avail );
+ void onHistoryForwardAvailable( bool avail );
+
void showAboutTomahawk();
private:
@@ -68,6 +70,9 @@ private:
QNetworkAccessManager m_nam;
QPushButton* m_statusButton;
+ QAction* m_backAvailable;
+ QAction* m_forwardAvailable;
+
Tomahawk::result_ptr m_currentTrack;
QString m_windowTitle;
};
diff --git a/src/web/api_v1.h b/src/web/api_v1.h
index 6d89beddd..daaacc4fb 100644
--- a/src/web/api_v1.h
+++ b/src/web/api_v1.h
@@ -17,8 +17,15 @@
#include
#include
+#include
#include "network/servent.h"
+#include "tomahawkutils.h"
+#include "tomahawk/tomahawkapp.h"
+#include
+#include
+#include
+#include
class Api_v1 : public QxtWebSlotService
{
@@ -32,7 +39,81 @@ public:
}
public slots:
+
+ // authenticating uses /auth_1
+ // we redirect to /auth_2 for the callback
+ void auth_1( QxtWebRequestEvent* event ) {
+ qDebug() << "AUTH_1 HTTP" << event->url.toString();
+
+ if( !event->url.hasQueryItem( "website" ) || !event->url.hasQueryItem( "name" ) ) {
+ qDebug() << "Malformed HTTP resolve request";
+ send404( event );
+ }
+
+ QString formToken = uuid();
+
+ if( event->url.hasQueryItem( "json" ) ) { // JSON response
+ QVariantMap m;
+ m[ "formtoken" ] = formToken;
+ sendJSON( m, event );
+ } else { // webpage request
+ QString authPage = RESPATH "www/auth.html";
+ QHash< QString, QString > args;
+ if( event->url.hasQueryItem( "receiverurl" ) )
+ args[ "url" ] = QUrl::fromPercentEncoding( event->url.queryItemValue( "receiverurl" ).toUtf8() );
+ args[ "formtoken" ] = formToken;
+ args[ "website" ] = QUrl::fromPercentEncoding( event->url.queryItemValue( "website" ).toUtf8() );
+ args[ "name" ] = QUrl::fromPercentEncoding( event->url.queryItemValue( "name" ).toUtf8() );
+ sendWebpageWithArgs( event, authPage, args );
+ }
+ }
+
+ void auth_2( QxtWebRequestEvent* event ) {
+
+ qDebug() << "AUTH_2 HTTP" << event->url.toString();
+ QUrl url = event->url;
+ url.setEncodedQuery( event->content->readAll() );
+ if( !url.hasQueryItem( "website" ) || !url.hasQueryItem( "name" ) || !url.hasQueryItem( "formtoken" ) ) {
+ qDebug() << "Malformed HTTP resolve request";
+ qDebug() << url.hasQueryItem( "website" ) << url.hasQueryItem( "name" ) << url.hasQueryItem( "formtoken" );
+ send404( event );
+ return;
+ }
+
+ QString website = QUrl::fromPercentEncoding( url.queryItemValue( "website" ).toUtf8() );
+ QString name = QUrl::fromPercentEncoding( url.queryItemValue( "name" ).toUtf8() );
+ QByteArray authtoken = uuid().toLatin1();
+ qDebug() << "HEADERS:" << event->headers;
+ if( !url.hasQueryItem( "receiverurl" ) && url.queryItemValue( "receiverurl" ).isEmpty() ) { //no receiver url, so do it ourselves
+ QString receiverUrl = QUrl::fromPercentEncoding( url.queryItemValue( "receiverurl" ).toUtf8() );
+ if( url.hasQueryItem( "json" ) ) {
+ QVariantMap m;
+ m[ "authtoken" ] = authtoken;
+
+ sendJSON( m, event );
+ } else {
+ QString authPage = RESPATH "www/auth.na.html";
+ QHash< QString, QString > args;
+ args[ "authcode" ] = authPage;
+ args[ "website" ] = QUrl::fromPercentEncoding( url.queryItemValue( "website" ).toUtf8() );
+ args[ "name" ] = QUrl::fromPercentEncoding( url.queryItemValue( "name" ).toUtf8() );
+ sendWebpageWithArgs( event, authPage, args );
+ }
+ } else { // do what the client wants
+ QUrl receiverurl = QUrl( url.queryItemValue( "receiverurl" ).toUtf8(), QUrl::TolerantMode );
+ receiverurl.addEncodedQueryItem( "authtoken", "#" + authtoken );
+ qDebug() << "Got receiver url:" << receiverurl.toString();
+
+ QxtWebRedirectEvent* e = new QxtWebRedirectEvent( event->sessionID, event->requestID, receiverurl.toString() );
+ postEvent( e );
+ // TODO validation of receiverurl?
+ }
+
+ DatabaseCommand_AddClientAuth* dbcmd = new DatabaseCommand_AddClientAuth( authtoken, website, name, event->headers.key( "ua" ) );
+ Database::instance()->enqueue( QSharedPointer(dbcmd) );
+ }
+
// all v1 api calls go to /api/
void api(QxtWebRequestEvent* event)
{
@@ -80,18 +161,35 @@ public slots:
qDebug() << "404" << event->url.toString();
QxtWebPageEvent* wpe = new QxtWebPageEvent(event->sessionID, event->requestID, "
Not Found
");
wpe->status = 404;
- wpe->statusMessage = "not found";
+ wpe->statusMessage = "not feventound";
postEvent( wpe );
}
void stat( QxtWebRequestEvent* event )
{
+ qDebug() << "Got Stat request:" << event->url.toString();
+ m_storedEvent = event;
+ if( !event->content.isNull() )
+ qDebug() << "BODY:" << event->content->readAll();
+ if( event->url.hasQueryItem( "auth" ) ) { // check for auth status
+ DatabaseCommand_ClientAuthValid* dbcmd = new DatabaseCommand_ClientAuthValid( event->url.queryItemValue( "auth" ), this );
+ connect( dbcmd, SIGNAL( authValid( QString, QString, bool ) ), this, SLOT( statResult( QString, QString, bool ) ) );
+ Database::instance()->enqueue( QSharedPointer(dbcmd) );
+
+ } else {
+ statResult( QString(), QString(), false );
+ }
+ }
+
+ void statResult( const QString& clientToken, const QString& name, bool valid ) {
QVariantMap m;
m.insert( "name", "playdar" );
m.insert( "version", "0.1.1" ); // TODO (needs to be >=0.1.1 for JS to work)
- m.insert( "authenticated", true ); // TODO
+ m.insert( "authenticated", valid ); // TODO
m.insert( "capabilities", QVariantList() );
- sendJSON( m, event );
+ sendJSON( m, m_storedEvent );
+
+ m_storedEvent = 0;
}
void resolve( QxtWebRequestEvent* event )
@@ -119,6 +217,12 @@ public slots:
sendJSON( r, event );
}
+ void staticdata( QxtWebRequestEvent* event ) {
+ if( event->url.path().contains( "playdar_auth_logo.gif" ) ) {
+ // TODO handle
+ }
+ }
+
void get_results( QxtWebRequestEvent* event )
{
if( !event->url.hasQueryItem("qid") )
@@ -174,6 +278,23 @@ public slots:
qDebug() << "JSON response" << event->url.toString() << body;
}
+ // load an html template from a file, replace args from map
+ // then serve
+ void sendWebpageWithArgs( QxtWebRequestEvent* event, const QString& filenameSource, const QHash< QString, QString >& args ) {
+ if( !QFile::exists( filenameSource ) )
+ qWarning() << "Passed invalid file for html source:" << filenameSource;
+
+ QFile f( filenameSource );
+ f.open( QIODevice::ReadOnly );
+ QByteArray html = f.readAll();
+
+ foreach( const QString& param, args.keys() ) {
+ html.replace( QString( "<%%1%>" ).arg( param.toUpper() ), args.value( param ).toUtf8() );
+ }
+
+ QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, html );
+ postEvent( e );
+ }
void index(QxtWebRequestEvent* event)
{
@@ -182,6 +303,8 @@ public slots:
}
+private:
+ QxtWebRequestEvent* m_storedEvent;
};
#endif