mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-04 21:27:58 +02:00
split out items in their own parts
make generic item take a funcptr so we keep the link going
This commit is contained in:
@@ -53,8 +53,12 @@ ENDIF(LIBLASTFM_FOUND)
|
|||||||
SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||||
sourcetree/sourcesmodel.cpp
|
sourcetree/sourcesmodel.cpp
|
||||||
sourcetree/sourcesproxymodel.cpp
|
sourcetree/sourcesproxymodel.cpp
|
||||||
sourcetree/sourcetreeitem.cpp
|
|
||||||
sourcetree/sourcetreeview.cpp
|
sourcetree/sourcetreeview.cpp
|
||||||
|
sourcetree/items/sourcetreeitem.cpp
|
||||||
|
sourcetree/items/collectionitem.cpp
|
||||||
|
sourcetree/items/playlistitems.cpp
|
||||||
|
sourcetree/items/categoryitems.cpp
|
||||||
|
sourcetree/items/genericpageitems.cpp
|
||||||
|
|
||||||
transferview.cpp
|
transferview.cpp
|
||||||
tomahawktrayicon.cpp
|
tomahawktrayicon.cpp
|
||||||
@@ -89,8 +93,12 @@ ENDIF(LIBLASTFM_FOUND)
|
|||||||
SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||||
sourcetree/sourcesmodel.h
|
sourcetree/sourcesmodel.h
|
||||||
sourcetree/sourcesproxymodel.h
|
sourcetree/sourcesproxymodel.h
|
||||||
sourcetree/sourcetreeitem.h
|
|
||||||
sourcetree/sourcetreeview.h
|
sourcetree/sourcetreeview.h
|
||||||
|
sourcetree/items/sourcetreeitem.h
|
||||||
|
sourcetree/items/collectionitem.h
|
||||||
|
sourcetree/items/playlistitems.h
|
||||||
|
sourcetree/items/categoryitems.h
|
||||||
|
sourcetree/items/genericpageitems.h
|
||||||
|
|
||||||
transferview.h
|
transferview.h
|
||||||
tomahawktrayicon.h
|
tomahawktrayicon.h
|
||||||
|
@@ -413,10 +413,10 @@ ViewManager::showSuperCollection()
|
|||||||
return shown;
|
return shown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Tomahawk::ViewPage*
|
||||||
ViewManager::showWelcomePage()
|
ViewManager::showWelcomePage()
|
||||||
{
|
{
|
||||||
show( m_welcomeWidget );
|
return show( m_welcomeWidget );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -123,7 +123,7 @@ signals:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Tomahawk::ViewPage* showSuperCollection();
|
Tomahawk::ViewPage* showSuperCollection();
|
||||||
void showWelcomePage();
|
Tomahawk::ViewPage* showWelcomePage();
|
||||||
void showCurrentTrack();
|
void showCurrentTrack();
|
||||||
|
|
||||||
void historyBack();
|
void historyBack();
|
||||||
|
136
src/sourcetree/items/categoryitems.cpp
Normal file
136
src/sourcetree/items/categoryitems.cpp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "categoryitems.h"
|
||||||
|
|
||||||
|
#include "utils/tomahawkutils.h"
|
||||||
|
#include "tomahawk/tomahawkapp.h"
|
||||||
|
#include "widgets/newplaylistwidget.h"
|
||||||
|
#include "viewmanager.h"
|
||||||
|
#include "viewpage.h"
|
||||||
|
|
||||||
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
/// CategoryAddItem
|
||||||
|
|
||||||
|
CategoryAddItem::CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type )
|
||||||
|
: SourceTreeItem( model, parent, SourcesModel::CategoryAdd )
|
||||||
|
, m_categoryType( type )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CategoryAddItem::~CategoryAddItem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
CategoryAddItem::text() const
|
||||||
|
{
|
||||||
|
switch( m_categoryType ) {
|
||||||
|
case SourcesModel::PlaylistsCategory:
|
||||||
|
return tr( "New Playlist" );
|
||||||
|
case SourcesModel::StationsCategory:
|
||||||
|
return tr( "New Station" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CategoryAddItem::activate()
|
||||||
|
{
|
||||||
|
switch( m_categoryType )
|
||||||
|
{
|
||||||
|
case SourcesModel::PlaylistsCategory:
|
||||||
|
// only show if none is shown yet
|
||||||
|
if( !ViewManager::instance()->isNewPlaylistPageVisible() ) {
|
||||||
|
ViewPage* p = ViewManager::instance()->show( new NewPlaylistWidget() );
|
||||||
|
model()->linkSourceItemToPage( this, p );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SourcesModel::StationsCategory:
|
||||||
|
APP->mainWindow()->createStation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags
|
||||||
|
CategoryAddItem::flags() const
|
||||||
|
{
|
||||||
|
switch( m_categoryType )
|
||||||
|
{
|
||||||
|
case SourcesModel::PlaylistsCategory:
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
case SourcesModel::StationsCategory:
|
||||||
|
default:
|
||||||
|
return Qt::ItemIsEnabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon
|
||||||
|
CategoryAddItem::icon() const
|
||||||
|
{
|
||||||
|
return QIcon( RESPATH "images/add.png" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CategoryItem
|
||||||
|
|
||||||
|
CategoryItem::CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem )
|
||||||
|
: SourceTreeItem( model, parent, SourcesModel::Category )
|
||||||
|
, m_category( category )
|
||||||
|
, m_addItem( 0 )
|
||||||
|
, m_showAdd( showAddItem )
|
||||||
|
{
|
||||||
|
// in the constructor we're still being added to the parent, so we don't exist to have rows addded yet. so this is safe.
|
||||||
|
// beginRowsAdded( 0, 0 );
|
||||||
|
if( m_showAdd ) {
|
||||||
|
m_addItem = new CategoryAddItem( model, this, m_category );
|
||||||
|
}
|
||||||
|
// endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CategoryItem::insertItem( SourceTreeItem* item )
|
||||||
|
{
|
||||||
|
insertItems( QList< SourceTreeItem* >() << item );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CategoryItem::insertItems( QList< SourceTreeItem* > items )
|
||||||
|
{
|
||||||
|
// add the items to the category, and connect to the signals
|
||||||
|
int curCount = children().size();
|
||||||
|
if( m_showAdd ) // if there's an add item, add it before that
|
||||||
|
curCount--;
|
||||||
|
beginRowsAdded( curCount, curCount + items.size() - 1 );
|
||||||
|
foreach( SourceTreeItem* item, items ) {
|
||||||
|
int index = m_showAdd ? children().count() - 1 : children().count();
|
||||||
|
insertChild( children().count() - 1, item );
|
||||||
|
}
|
||||||
|
endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CategoryItem::activate()
|
||||||
|
{
|
||||||
|
if( m_category == SourcesModel::StationsCategory ) {
|
||||||
|
// TODO activate stations page
|
||||||
|
}
|
||||||
|
}
|
70
src/sourcetree/items/categoryitems.h
Normal file
70
src/sourcetree/items/categoryitems.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CATEGORY_ITEM_H
|
||||||
|
#define CATEGORY_ITEM_H
|
||||||
|
|
||||||
|
#include "sourcetreeitem.h"
|
||||||
|
|
||||||
|
class CategoryAddItem : public SourceTreeItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type );
|
||||||
|
~CategoryAddItem();
|
||||||
|
|
||||||
|
virtual Qt::ItemFlags flags() const;
|
||||||
|
virtual QString text() const;
|
||||||
|
virtual void activate();
|
||||||
|
virtual QIcon icon() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SourcesModel::CategoryType m_categoryType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CategoryItem : public SourceTreeItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem );
|
||||||
|
|
||||||
|
virtual QString text() const {
|
||||||
|
switch( m_category )
|
||||||
|
{
|
||||||
|
case SourcesModel::PlaylistsCategory:
|
||||||
|
return tr( "Playlists" );
|
||||||
|
case SourcesModel::StationsCategory:
|
||||||
|
return tr( "Stations" );
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
virtual void activate();
|
||||||
|
virtual Qt::ItemFlags flags() const { return Qt::ItemIsEnabled; }
|
||||||
|
|
||||||
|
// inserts an item at the end, but before the category add item
|
||||||
|
void insertItem( SourceTreeItem* item );
|
||||||
|
void insertItems( QList< SourceTreeItem* > item );
|
||||||
|
|
||||||
|
SourcesModel::CategoryType categoryType() { return m_category; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SourcesModel::CategoryType m_category;
|
||||||
|
CategoryAddItem* m_addItem;
|
||||||
|
bool m_showAdd;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
231
src/sourcetree/items/collectionitem.cpp
Normal file
231
src/sourcetree/items/collectionitem.cpp
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "collectionitem.h"
|
||||||
|
|
||||||
|
#include "utils/tomahawkutils.h"
|
||||||
|
#include "categoryitems.h"
|
||||||
|
#include "playlistitems.h"
|
||||||
|
#include "viewmanager.h"
|
||||||
|
#include "playlist.h"
|
||||||
|
|
||||||
|
/// CollectionItem
|
||||||
|
|
||||||
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahawk::source_ptr& source )
|
||||||
|
: SourceTreeItem( mdl, parent, SourcesModel::Collection )
|
||||||
|
, m_source( source )
|
||||||
|
, m_playlists( 0 )
|
||||||
|
, m_stations( 0 )
|
||||||
|
{
|
||||||
|
if( m_source.isNull() ) { // super collection
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// create category items if there are playlists to show, or stations to show
|
||||||
|
QList< playlist_ptr > playlists = source->collection()->playlists();
|
||||||
|
QList< dynplaylist_ptr > autoplaylists = source->collection()->autoPlaylists();
|
||||||
|
QList< dynplaylist_ptr > stations = source->collection()->stations();
|
||||||
|
|
||||||
|
if( !playlists.isEmpty() || !autoplaylists.isEmpty() || source->isLocal() ) {
|
||||||
|
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() );
|
||||||
|
onPlaylistsAdded( playlists );
|
||||||
|
onAutoPlaylistsAdded( autoplaylists );
|
||||||
|
}
|
||||||
|
if( !stations.isEmpty() || source->isLocal() ) {
|
||||||
|
m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() );
|
||||||
|
onStationsAdded( stations );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ViewManager::instance()->pageForCollection( source->collection() ) )
|
||||||
|
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) );
|
||||||
|
|
||||||
|
// load auto playlists and stations!
|
||||||
|
|
||||||
|
connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) );
|
||||||
|
connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), this, SIGNAL( updated() ) );
|
||||||
|
connect( source.data(), SIGNAL( stateChanged() ), this, SIGNAL( updated() ) );
|
||||||
|
connect( source.data(), SIGNAL( offline() ), this, SIGNAL( updated() ) );
|
||||||
|
connect( source.data(), SIGNAL( online() ), this, SIGNAL( updated() ) );
|
||||||
|
|
||||||
|
connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
|
||||||
|
SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ), Qt::QueuedConnection );
|
||||||
|
connect( source->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ),
|
||||||
|
SLOT( onPlaylistsDeleted( QList<Tomahawk::playlist_ptr> ) ), Qt::QueuedConnection );
|
||||||
|
|
||||||
|
connect( source->collection().data(), SIGNAL( autoPlaylistsAdded( QList< Tomahawk::dynplaylist_ptr > ) ),
|
||||||
|
SLOT( onAutoPlaylistsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
||||||
|
connect( source->collection().data(), SIGNAL( autoPlaylistsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ),
|
||||||
|
SLOT( onAutoPlaylistsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
||||||
|
|
||||||
|
connect( source->collection().data(), SIGNAL( stationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ),
|
||||||
|
SLOT( onStationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
||||||
|
connect( source->collection().data(), SIGNAL( stationsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ),
|
||||||
|
SLOT( onStationsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
||||||
|
}
|
||||||
|
|
||||||
|
Tomahawk::source_ptr
|
||||||
|
CollectionItem::source() const
|
||||||
|
{
|
||||||
|
return m_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
CollectionItem::text() const
|
||||||
|
{
|
||||||
|
return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::activate()
|
||||||
|
{
|
||||||
|
if( source().isNull() ) {
|
||||||
|
ViewPage* p = ViewManager::instance()->showSuperCollection();
|
||||||
|
model()->linkSourceItemToPage( this, p );
|
||||||
|
} else {
|
||||||
|
ViewPage* p = ViewManager::instance()->show( source()->collection() );
|
||||||
|
model()->linkSourceItemToPage( this, p );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon
|
||||||
|
CollectionItem::icon() const
|
||||||
|
{
|
||||||
|
if( m_source.isNull() )
|
||||||
|
return QIcon( RESPATH "images/supercollection.png" );
|
||||||
|
else
|
||||||
|
return QIcon( RESPATH "images/user-avatar.png" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists )
|
||||||
|
{
|
||||||
|
QList< SourceTreeItem* > items;
|
||||||
|
int addOffset = playlists.first()->author()->isLocal() ? 1 : 0;
|
||||||
|
|
||||||
|
int from = parent->children().count() - addOffset;
|
||||||
|
parent->beginRowsAdded( from, from + playlists.count() - 1 );
|
||||||
|
foreach( const dynplaylist_ptr& p, playlists )
|
||||||
|
{
|
||||||
|
DynamicPlaylistItem* plItem = new DynamicPlaylistItem( model(), parent, p, parent->children().count() - addOffset );
|
||||||
|
qDebug() << "Dynamic Playlist added:" << p->title() << p->creator() << p->info();
|
||||||
|
p->loadRevision();
|
||||||
|
items << plItem;
|
||||||
|
}
|
||||||
|
parent->endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void
|
||||||
|
CollectionItem::playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists )
|
||||||
|
{
|
||||||
|
Q_ASSERT( parent ); // How can we delete playlists if we have none?
|
||||||
|
QList< SourceTreeItem* > items;
|
||||||
|
foreach( const T& playlist, playlists ) {
|
||||||
|
int curCount = parent->children().count();
|
||||||
|
for( int i = 0; i < curCount; i++ ) {
|
||||||
|
PlaylistItem* pl = qobject_cast< PlaylistItem* >( parent->children().at( i ) );
|
||||||
|
if( pl && pl->playlist() == playlist ) {
|
||||||
|
parent->beginRowsRemoved( i, i );
|
||||||
|
parent->removeChild( pl );
|
||||||
|
parent->endRowsRemoved();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
|
||||||
|
{
|
||||||
|
if( playlists.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !m_playlists ) { // add the category too
|
||||||
|
int cur = children().count();
|
||||||
|
beginRowsAdded( cur, cur );
|
||||||
|
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() );
|
||||||
|
endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList< SourceTreeItem* > items;
|
||||||
|
int addOffset = playlists.first()->author()->isLocal() ? 1 : 0;
|
||||||
|
|
||||||
|
int from = m_playlists->children().count() - addOffset;
|
||||||
|
m_playlists->beginRowsAdded( from, from + playlists.count() - 1 );
|
||||||
|
foreach( const playlist_ptr& p, playlists )
|
||||||
|
{
|
||||||
|
PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p, m_playlists->children().count() - addOffset );
|
||||||
|
qDebug() << "Playlist added:" << p->title() << p->creator() << p->info();
|
||||||
|
p->loadRevision();
|
||||||
|
items << plItem;
|
||||||
|
}
|
||||||
|
m_playlists->endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists )
|
||||||
|
{
|
||||||
|
playlistsDeletedInternal( m_playlists, playlists );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
|
||||||
|
{
|
||||||
|
if( playlists.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !m_playlists ) { // add the category too
|
||||||
|
int cur = children().count();
|
||||||
|
beginRowsAdded( cur, cur );
|
||||||
|
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() );
|
||||||
|
endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
playlistsAddedInternal( m_playlists, playlists );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::onAutoPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists )
|
||||||
|
{
|
||||||
|
if( !m_playlists )
|
||||||
|
qDebug() << "NO playlist category item for a deleting playlist..";
|
||||||
|
|
||||||
|
playlistsDeletedInternal( m_playlists, playlists );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations )
|
||||||
|
{
|
||||||
|
if( stations.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !m_stations ) { // add the category too
|
||||||
|
int cur = children().count();
|
||||||
|
beginRowsAdded( cur, cur );
|
||||||
|
m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source()->isLocal() );
|
||||||
|
endRowsAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
playlistsAddedInternal( m_stations, stations );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CollectionItem::onStationsDeleted( const QList< dynplaylist_ptr >& stations )
|
||||||
|
{
|
||||||
|
playlistsDeletedInternal( m_stations, stations );
|
||||||
|
}
|
59
src/sourcetree/items/collectionitem.h
Normal file
59
src/sourcetree/items/collectionitem.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COLLECTION_ITEM_H
|
||||||
|
#define COLLECTION_ITEM_H
|
||||||
|
|
||||||
|
#include "sourcetreeitem.h"
|
||||||
|
|
||||||
|
class CategoryItem;
|
||||||
|
|
||||||
|
class CollectionItem : public SourceTreeItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source );
|
||||||
|
|
||||||
|
virtual QString text() const;
|
||||||
|
virtual void activate();
|
||||||
|
virtual QIcon icon() const;
|
||||||
|
|
||||||
|
Tomahawk::source_ptr source() const;
|
||||||
|
|
||||||
|
CategoryItem* stationsCategory() const { return m_stations; }
|
||||||
|
CategoryItem* playlistsCategory() const { return m_playlists; }
|
||||||
|
void setStationsCategory( CategoryItem* item ) { m_stations = item; }
|
||||||
|
void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; }
|
||||||
|
private slots:
|
||||||
|
void onPlaylistsAdded( const QList<Tomahawk::playlist_ptr>& playlists );
|
||||||
|
void onPlaylistsDeleted( const QList<Tomahawk::playlist_ptr>& playlists );
|
||||||
|
void onAutoPlaylistsAdded( const QList<Tomahawk::dynplaylist_ptr>& playlists );
|
||||||
|
void onAutoPlaylistsDeleted( const QList<Tomahawk::dynplaylist_ptr>& playlists );
|
||||||
|
void onStationsAdded( const QList<Tomahawk::dynplaylist_ptr>& stations );
|
||||||
|
void onStationsDeleted( const QList<Tomahawk::dynplaylist_ptr>& stations );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists );
|
||||||
|
template< typename T >
|
||||||
|
void playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists );
|
||||||
|
|
||||||
|
Tomahawk::source_ptr m_source;
|
||||||
|
CategoryItem* m_playlists;
|
||||||
|
CategoryItem* m_stations;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
63
src/sourcetree/items/genericpageitems.cpp
Normal file
63
src/sourcetree/items/genericpageitems.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "genericpageitems.h"
|
||||||
|
|
||||||
|
#include "utils/tomahawkutils.h"
|
||||||
|
#include "viewmanager.h"
|
||||||
|
|
||||||
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
/// Generic page item
|
||||||
|
GenericPageItem::GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon, boost::function< ViewPage* () > func )
|
||||||
|
: SourceTreeItem( model, parent, SourcesModel::GenericPage )
|
||||||
|
, m_icon( icon )
|
||||||
|
, m_text( text )
|
||||||
|
, m_func( func )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericPageItem::~GenericPageItem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericPageItem::activate()
|
||||||
|
{
|
||||||
|
ViewPage* p = m_func();
|
||||||
|
model()->linkSourceItemToPage( this, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
GenericPageItem::text() const
|
||||||
|
{
|
||||||
|
return m_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon
|
||||||
|
GenericPageItem::icon() const
|
||||||
|
{
|
||||||
|
return m_icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
GenericPageItem::willAcceptDrag(const QMimeData* data) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
47
src/sourcetree/items/genericpageitems.h
Normal file
47
src/sourcetree/items/genericpageitems.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GENERIC_PAGE_ITEM_H
|
||||||
|
#define GENERIC_PAGE_ITEM_H
|
||||||
|
|
||||||
|
#include "sourcetreeitem.h"
|
||||||
|
|
||||||
|
#include "boost/function.hpp"
|
||||||
|
#include "boost/bind.hpp"
|
||||||
|
|
||||||
|
// generic item that has some name, some text, and calls a certain slot when activated. badabing!
|
||||||
|
class GenericPageItem : public SourceTreeItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon, boost::function<Tomahawk::ViewPage*()> func );
|
||||||
|
virtual ~GenericPageItem();
|
||||||
|
|
||||||
|
virtual QString text() const;
|
||||||
|
virtual void activate();
|
||||||
|
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
||||||
|
virtual QIcon icon() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void activated();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QIcon m_icon;
|
||||||
|
QString m_text;
|
||||||
|
boost::function< Tomahawk::ViewPage*() > m_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
260
src/sourcetree/items/playlistitems.cpp
Normal file
260
src/sourcetree/items/playlistitems.cpp
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "playlistitems.h"
|
||||||
|
|
||||||
|
#include "utils/tomahawkutils.h"
|
||||||
|
#include "viewmanager.h"
|
||||||
|
#include "playlist/dynamic/GeneratorInterface.h"
|
||||||
|
#include "categoryitems.h"
|
||||||
|
#include "collectionitem.h"
|
||||||
|
|
||||||
|
#include <QMimeData>
|
||||||
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
/// PlaylistItem
|
||||||
|
|
||||||
|
PlaylistItem::PlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const playlist_ptr& pl, int index )
|
||||||
|
: SourceTreeItem( mdl, parent, SourcesModel::StaticPlaylist, index )
|
||||||
|
, m_loaded( false )
|
||||||
|
, m_playlist( pl )
|
||||||
|
{
|
||||||
|
connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ),
|
||||||
|
SLOT( onPlaylistLoaded( Tomahawk::PlaylistRevision ) ), Qt::QueuedConnection );
|
||||||
|
connect( pl.data(), SIGNAL( changed() ),
|
||||||
|
SIGNAL( updated() ), Qt::QueuedConnection );
|
||||||
|
|
||||||
|
if( ViewManager::instance()->pageForPlaylist( pl ) )
|
||||||
|
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForPlaylist( pl ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
PlaylistItem::text() const
|
||||||
|
{
|
||||||
|
return m_playlist->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tomahawk::playlist_ptr
|
||||||
|
PlaylistItem::playlist() const
|
||||||
|
{
|
||||||
|
return m_playlist;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
PlaylistItem::onPlaylistLoaded( Tomahawk::PlaylistRevision revision )
|
||||||
|
{
|
||||||
|
m_loaded = true;
|
||||||
|
emit updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistItem::onPlaylistChanged()
|
||||||
|
{
|
||||||
|
emit updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags
|
||||||
|
PlaylistItem::flags() const
|
||||||
|
{
|
||||||
|
Qt::ItemFlags flags = SourceTreeItem::flags();
|
||||||
|
|
||||||
|
if( !m_loaded )
|
||||||
|
flags &= !Qt::ItemIsEnabled;
|
||||||
|
|
||||||
|
flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
||||||
|
if( playlist()->author()->isLocal() )
|
||||||
|
flags |= Qt::ItemIsEditable;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistItem::activate()
|
||||||
|
{
|
||||||
|
ViewPage* p = ViewManager::instance()->show( m_playlist );
|
||||||
|
model()->linkSourceItemToPage( this, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaylistItem::setLoaded( bool loaded )
|
||||||
|
{
|
||||||
|
m_loaded = loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PlaylistItem::willAcceptDrag( const QMimeData* data ) const
|
||||||
|
{
|
||||||
|
return !m_playlist.isNull() && m_playlist->author()->isLocal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action )
|
||||||
|
{
|
||||||
|
if( data->hasFormat( "application/tomahawk.query.list" ) ) {
|
||||||
|
if ( !m_playlist.isNull() && m_playlist->author()->isLocal() ) {
|
||||||
|
|
||||||
|
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
||||||
|
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||||
|
QList< Tomahawk::query_ptr > queries;
|
||||||
|
|
||||||
|
while ( !stream.atEnd() )
|
||||||
|
{
|
||||||
|
qlonglong qptr;
|
||||||
|
stream >> qptr;
|
||||||
|
|
||||||
|
Tomahawk::query_ptr* query = reinterpret_cast<Tomahawk::query_ptr*>(qptr);
|
||||||
|
if ( query && !query->isNull() )
|
||||||
|
{
|
||||||
|
qDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
||||||
|
queries << *query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "on playlist:" << m_playlist->title() << m_playlist->guid();
|
||||||
|
|
||||||
|
// TODO do we need to use this in the refactor?
|
||||||
|
// QString rev = item->currentlyLoadedPlaylistRevision( playlist->guid() );
|
||||||
|
m_playlist->addEntries( queries, m_playlist->currentrevision() );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon
|
||||||
|
PlaylistItem::icon() const
|
||||||
|
{
|
||||||
|
return QIcon( RESPATH "images/playlist-icon.png" );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PlaylistItem::setData(const QVariant& v, bool role)
|
||||||
|
{
|
||||||
|
if( m_playlist->author()->isLocal() ) {
|
||||||
|
m_playlist->rename( v.toString() );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPlaylistItem::DynamicPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl, int index )
|
||||||
|
: PlaylistItem( mdl, parent, pl.staticCast< Playlist >(), index )
|
||||||
|
, m_dynplaylist( pl )
|
||||||
|
{
|
||||||
|
setRowType( m_dynplaylist->mode() == Static ? SourcesModel::AutomaticPlaylist : SourcesModel::Station );
|
||||||
|
|
||||||
|
connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ),
|
||||||
|
SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection );
|
||||||
|
|
||||||
|
if( ViewManager::instance()->pageForDynPlaylist( pl ) )
|
||||||
|
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForDynPlaylist( pl ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPlaylistItem::~DynamicPlaylistItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DynamicPlaylistItem::activate()
|
||||||
|
{
|
||||||
|
ViewPage* p = ViewManager::instance()->show( m_dynplaylist );
|
||||||
|
model()->linkSourceItemToPage( this, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision )
|
||||||
|
{
|
||||||
|
setLoaded( true );
|
||||||
|
checkReparentHackNeeded( revision );
|
||||||
|
// END HACK
|
||||||
|
emit updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& revision )
|
||||||
|
{
|
||||||
|
// HACK HACK HACK workaround for an ugly hack where we have to be compatible with older tomahawks (pre-0.1.0) that created dynplaylists as OnDemand then changed them to Static if they were static.
|
||||||
|
// we need to reparent this playlist to the correct category :-/.
|
||||||
|
CategoryItem* cat = qobject_cast< CategoryItem* >( parent() );
|
||||||
|
qDebug() << "with category" << cat;
|
||||||
|
if( cat ) qDebug() << "and cat type:" << cat->categoryType();
|
||||||
|
if( cat ) {
|
||||||
|
CategoryItem* from = cat;
|
||||||
|
CategoryItem* to = 0;
|
||||||
|
if( cat->categoryType() == SourcesModel::PlaylistsCategory && revision.mode == OnDemand ) { // WRONG
|
||||||
|
CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() );
|
||||||
|
to = col->stationsCategory();
|
||||||
|
if( !to ) { // you have got to be fucking kidding me
|
||||||
|
int fme = col->children().count();
|
||||||
|
col->beginRowsAdded( fme, fme );
|
||||||
|
to = new CategoryItem( model(), col, SourcesModel::StationsCategory, false );
|
||||||
|
col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves
|
||||||
|
col->endRowsAdded();
|
||||||
|
col->setStationsCategory( to );
|
||||||
|
}
|
||||||
|
} else if( cat->categoryType() == SourcesModel::StationsCategory && revision.mode == Static ) { // WRONG
|
||||||
|
CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() );
|
||||||
|
to = col->playlistsCategory();
|
||||||
|
qDebug() << "TRYING TO HACK TO:" << to;
|
||||||
|
if( !to ) { // you have got to be fucking kidding me
|
||||||
|
int fme = col->children().count();
|
||||||
|
col->beginRowsAdded( fme, fme );
|
||||||
|
to = new CategoryItem( model(), col, SourcesModel::PlaylistsCategory, false );
|
||||||
|
col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves
|
||||||
|
col->endRowsAdded();
|
||||||
|
col->setPlaylistsCategory( to );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( to ) {
|
||||||
|
qDebug() << "HACKING! moving dynamic playlist from" << from->text() << "to:" << to->text();
|
||||||
|
// remove and add
|
||||||
|
int idx = from->children().indexOf( this );
|
||||||
|
from->beginRowsRemoved( idx, idx );
|
||||||
|
from->removeChild( this );
|
||||||
|
from->endRowsRemoved();
|
||||||
|
|
||||||
|
idx = to->children().count();
|
||||||
|
to->beginRowsAdded( idx, idx );
|
||||||
|
to->appendChild( this );
|
||||||
|
to->endRowsAdded();
|
||||||
|
|
||||||
|
setParentItem( to );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dynplaylist_ptr
|
||||||
|
DynamicPlaylistItem::dynPlaylist() const
|
||||||
|
{
|
||||||
|
return m_dynplaylist;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
DynamicPlaylistItem::text() const
|
||||||
|
{
|
||||||
|
return m_dynplaylist->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DynamicPlaylistItem::willAcceptDrag( const QMimeData* data ) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
73
src/sourcetree/items/playlistitems.h
Normal file
73
src/sourcetree/items/playlistitems.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLAYLIST_ITEM_H
|
||||||
|
#define PLAYLIST_ITEM_H
|
||||||
|
|
||||||
|
#include "sourcetreeitem.h"
|
||||||
|
#include "playlist/dynamic/DynamicPlaylist.h"
|
||||||
|
|
||||||
|
class PlaylistItem : public SourceTreeItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::playlist_ptr& pl, int index = -1 );
|
||||||
|
|
||||||
|
virtual QString text() const;
|
||||||
|
virtual Tomahawk::playlist_ptr playlist() const;
|
||||||
|
virtual Qt::ItemFlags flags() const;
|
||||||
|
virtual void activate();
|
||||||
|
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
||||||
|
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action );
|
||||||
|
virtual QIcon icon() const;
|
||||||
|
virtual bool setData(const QVariant& v, bool role);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setLoaded( bool loaded );
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onPlaylistLoaded( Tomahawk::PlaylistRevision revision );
|
||||||
|
void onPlaylistChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_loaded;
|
||||||
|
Tomahawk::playlist_ptr m_playlist;
|
||||||
|
};
|
||||||
|
|
||||||
|
// can be a station or an auto playlist
|
||||||
|
class DynamicPlaylistItem : public PlaylistItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DynamicPlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::dynplaylist_ptr& pl, int index = -1 );
|
||||||
|
virtual ~DynamicPlaylistItem();
|
||||||
|
|
||||||
|
virtual QString text() const;
|
||||||
|
Tomahawk::dynplaylist_ptr dynPlaylist() const;
|
||||||
|
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
||||||
|
virtual void activate();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkReparentHackNeeded( const Tomahawk::DynamicPlaylistRevision& rev );
|
||||||
|
|
||||||
|
Tomahawk::dynplaylist_ptr m_dynplaylist;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
48
src/sourcetree/items/sourcetreeitem.cpp
Normal file
48
src/sourcetree/items/sourcetreeitem.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
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, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "sourcetreeitem.h"
|
||||||
|
|
||||||
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index )
|
||||||
|
: QObject()
|
||||||
|
, m_type( thisType )
|
||||||
|
, m_parent( parent )
|
||||||
|
, m_model( model )
|
||||||
|
{
|
||||||
|
connect( this, SIGNAL( beginChildRowsAdded( int,int ) ), m_model, SLOT( onItemRowsAddedBegin( int,int ) ) );
|
||||||
|
connect( this, SIGNAL( beginChildRowsRemoved( int,int ) ), m_model, SLOT( onItemRowsRemovedBegin( int,int ) ) );
|
||||||
|
connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) );
|
||||||
|
connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) );
|
||||||
|
connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) );
|
||||||
|
|
||||||
|
if( !m_parent )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// caller must call begin/endInsertRows
|
||||||
|
if( index < 0 )
|
||||||
|
m_parent->appendChild( this );
|
||||||
|
else
|
||||||
|
m_parent->insertChild( index, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SourceTreeItem::~SourceTreeItem()
|
||||||
|
{
|
||||||
|
qDeleteAll( m_children );
|
||||||
|
}
|
84
src/sourcetree/items/sourcetreeitem.h
Normal file
84
src/sourcetree/items/sourcetreeitem.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
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, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SOURCETREEITEM_H
|
||||||
|
#define SOURCETREEITEM_H
|
||||||
|
|
||||||
|
#include "sourcesmodel.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
#include "playlist.h"
|
||||||
|
#include "playlist/dynamic/DynamicPlaylist.h"
|
||||||
|
#include "source.h"
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
class QMimeData;
|
||||||
|
class SourceTreeItem : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SourceTreeItem() : m_type( SourcesModel::Invalid ), m_parent( 0 ), m_model( 0 ) {}
|
||||||
|
SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index = -1 ); // if index is -1, append at end of parent's child list
|
||||||
|
virtual ~SourceTreeItem();
|
||||||
|
|
||||||
|
// generic info used by the tree model
|
||||||
|
SourcesModel::RowType type() const { return m_type; }
|
||||||
|
SourceTreeItem* parent() const { return m_parent; }
|
||||||
|
SourcesModel* model() const { return m_model; }
|
||||||
|
|
||||||
|
QList< SourceTreeItem* > children() const { return m_children; }
|
||||||
|
void appendChild( SourceTreeItem* item ) { m_children.append( item ); }
|
||||||
|
void insertChild( int index, SourceTreeItem* item ) { m_children.insert( index, item ); }
|
||||||
|
void removeChild( SourceTreeItem* item ) { m_children.removeAll( item ); }
|
||||||
|
|
||||||
|
// varies depending on the type of the item
|
||||||
|
virtual QString text() const { return QString(); }
|
||||||
|
virtual Qt::ItemFlags flags() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
|
||||||
|
virtual void activate() {}
|
||||||
|
virtual QIcon icon() const { return QIcon(); }
|
||||||
|
virtual bool willAcceptDrag( const QMimeData* data ) const { return false; }
|
||||||
|
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action ) { return false; }
|
||||||
|
virtual bool setData( const QVariant& v, bool role ) { return false; }
|
||||||
|
|
||||||
|
/// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend
|
||||||
|
void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); }
|
||||||
|
void endRowsAdded() { emit childRowsAdded(); }
|
||||||
|
void beginRowsRemoved( int from, int to ) { emit beginChildRowsRemoved( from, to ); }
|
||||||
|
void endRowsRemoved() { emit childRowsRemoved(); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void updated();
|
||||||
|
|
||||||
|
void beginChildRowsAdded( int fromRow, int toRow );
|
||||||
|
void childRowsAdded();
|
||||||
|
|
||||||
|
void beginChildRowsRemoved( int fromRow, int toRow );
|
||||||
|
void childRowsRemoved();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setRowType( SourcesModel::RowType t ) { m_type = t; }
|
||||||
|
void setParentItem( SourceTreeItem* item ) { m_parent = item; }
|
||||||
|
private:
|
||||||
|
SourcesModel::RowType m_type;
|
||||||
|
|
||||||
|
SourceTreeItem* m_parent;
|
||||||
|
QList< SourceTreeItem* > m_children;
|
||||||
|
SourcesModel* m_model;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE( SourceTreeItem* );
|
||||||
|
|
||||||
|
#endif // SOURCETREEITEM_H
|
@@ -18,7 +18,9 @@
|
|||||||
|
|
||||||
#include "sourcetree/sourcesmodel.h"
|
#include "sourcetree/sourcesmodel.h"
|
||||||
|
|
||||||
#include "sourcetree/sourcetreeitem.h"
|
#include "sourcetree/items/sourcetreeitem.h"
|
||||||
|
#include "sourcetree/items/collectionitem.h"
|
||||||
|
#include "sourcetree/items/genericpageitems.h"
|
||||||
#include "sourcelist.h"
|
#include "sourcelist.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
@@ -26,6 +28,8 @@
|
|||||||
#include "tomahawk/tomahawkapp.h"
|
#include "tomahawk/tomahawkapp.h"
|
||||||
#include "viewmanager.h"
|
#include "viewmanager.h"
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
|
||||||
@@ -40,8 +44,7 @@ SourcesModel::SourcesModel( QObject* parent )
|
|||||||
appendItem( source_ptr() );
|
appendItem( source_ptr() );
|
||||||
|
|
||||||
// add misc children of root node
|
// add misc children of root node
|
||||||
GenericPageItem* recent = new GenericPageItem( this, m_rootItem->children().at( 0 ), tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ) );
|
GenericPageItem* recent = new GenericPageItem( this, m_rootItem->children().at( 0 ), tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ), boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ) );
|
||||||
connect( recent, SIGNAL( activated() ), ViewManager::instance(), SLOT( showWelcomePage() ) );
|
|
||||||
|
|
||||||
onSourcesAdded( SourceList::instance()->sources() );
|
onSourcesAdded( SourceList::instance()->sources() );
|
||||||
|
|
||||||
@@ -388,16 +391,6 @@ SourcesModel::indexFromItem( SourceTreeItem* item ) const
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
playlist_ptr
|
|
||||||
SourcesModel::playlistFromItem( SourceTreeItem* item ) const
|
|
||||||
{
|
|
||||||
Q_ASSERT( item );
|
|
||||||
Q_ASSERT( item->type() == StaticPlaylist );
|
|
||||||
|
|
||||||
return dynamic_cast< PlaylistItem* >( item )->playlist();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
SourcesModel::rowForItem( SourceTreeItem* item ) const
|
SourcesModel::rowForItem( SourceTreeItem* item ) const
|
||||||
{
|
{
|
||||||
|
@@ -107,11 +107,7 @@ public slots:
|
|||||||
void onItemRowsRemovedDone();
|
void onItemRowsRemovedDone();
|
||||||
private:
|
private:
|
||||||
SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const;
|
SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const;
|
||||||
Tomahawk::playlist_ptr playlistFromItem( SourceTreeItem* item ) const;
|
|
||||||
int rowForItem( SourceTreeItem* item ) const;
|
int rowForItem( SourceTreeItem* item ) const;
|
||||||
// QModelIndex indexForSource( Tomahawk::Source* source ) const;
|
|
||||||
// QModelIndex indexForPlaylist( Tomahawk::Playlist* pl ) const;
|
|
||||||
// QModelIndex indexForCategory( const QModelIndex& sourceIndex, CategoryType type );
|
|
||||||
|
|
||||||
SourceTreeItem* m_rootItem;
|
SourceTreeItem* m_rootItem;
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
|
|
||||||
#include "sourcesmodel.h"
|
#include "sourcesmodel.h"
|
||||||
#include "sourcetree/sourcetreeitem.h"
|
#include "sourcetree/items/collectionitem.h"
|
||||||
|
|
||||||
|
|
||||||
SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
|
SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
|
||||||
|
@@ -1,698 +0,0 @@
|
|||||||
/*
|
|
||||||
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, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "sourcetreeitem.h"
|
|
||||||
|
|
||||||
#include "playlist.h"
|
|
||||||
#include "playlist/dynamic/DynamicPlaylist.h"
|
|
||||||
#include "source.h"
|
|
||||||
#include "viewmanager.h"
|
|
||||||
#include "tomahawk/tomahawkapp.h"
|
|
||||||
#include "widgets/newplaylistwidget.h"
|
|
||||||
|
|
||||||
#include <QMimeData>
|
|
||||||
|
|
||||||
using namespace Tomahawk;
|
|
||||||
|
|
||||||
SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index )
|
|
||||||
: QObject()
|
|
||||||
, m_type( thisType )
|
|
||||||
, m_parent( parent )
|
|
||||||
, m_model( model )
|
|
||||||
{
|
|
||||||
connect( this, SIGNAL( beginChildRowsAdded( int,int ) ), m_model, SLOT( onItemRowsAddedBegin( int,int ) ) );
|
|
||||||
connect( this, SIGNAL( beginChildRowsRemoved( int,int ) ), m_model, SLOT( onItemRowsRemovedBegin( int,int ) ) );
|
|
||||||
connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) );
|
|
||||||
connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) );
|
|
||||||
connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) );
|
|
||||||
|
|
||||||
if( !m_parent )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// caller must call begin/endInsertRows
|
|
||||||
if( index < 0 )
|
|
||||||
m_parent->appendChild( this );
|
|
||||||
else
|
|
||||||
m_parent->insertChild( index, this );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SourceTreeItem::~SourceTreeItem()
|
|
||||||
{
|
|
||||||
qDeleteAll( m_children );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Category item
|
|
||||||
|
|
||||||
void
|
|
||||||
CategoryItem::activate()
|
|
||||||
{
|
|
||||||
if( m_category == SourcesModel::StationsCategory ) {
|
|
||||||
// TODO activate stations page
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// PlaylistItem
|
|
||||||
|
|
||||||
PlaylistItem::PlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const playlist_ptr& pl, int index )
|
|
||||||
: SourceTreeItem( mdl, parent, SourcesModel::StaticPlaylist, index )
|
|
||||||
, m_loaded( false )
|
|
||||||
, m_playlist( pl )
|
|
||||||
{
|
|
||||||
connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ),
|
|
||||||
SLOT( onPlaylistLoaded( Tomahawk::PlaylistRevision ) ), Qt::QueuedConnection );
|
|
||||||
connect( pl.data(), SIGNAL( changed() ),
|
|
||||||
SIGNAL( updated() ), Qt::QueuedConnection );
|
|
||||||
|
|
||||||
if( ViewManager::instance()->pageForPlaylist( pl ) )
|
|
||||||
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForPlaylist( pl ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QString
|
|
||||||
PlaylistItem::text() const
|
|
||||||
{
|
|
||||||
return m_playlist->title();
|
|
||||||
}
|
|
||||||
|
|
||||||
Tomahawk::playlist_ptr
|
|
||||||
PlaylistItem::playlist() const
|
|
||||||
{
|
|
||||||
return m_playlist;
|
|
||||||
}
|
|
||||||
void
|
|
||||||
PlaylistItem::onPlaylistLoaded( Tomahawk::PlaylistRevision revision )
|
|
||||||
{
|
|
||||||
m_loaded = true;
|
|
||||||
emit updated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PlaylistItem::onPlaylistChanged()
|
|
||||||
{
|
|
||||||
emit updated();
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags
|
|
||||||
PlaylistItem::flags() const
|
|
||||||
{
|
|
||||||
Qt::ItemFlags flags = SourceTreeItem::flags();
|
|
||||||
|
|
||||||
if( !m_loaded )
|
|
||||||
flags &= !Qt::ItemIsEnabled;
|
|
||||||
|
|
||||||
flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
|
||||||
if( playlist()->author()->isLocal() )
|
|
||||||
flags |= Qt::ItemIsEditable;
|
|
||||||
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PlaylistItem::activate()
|
|
||||||
{
|
|
||||||
ViewPage* p = ViewManager::instance()->show( m_playlist );
|
|
||||||
model()->linkSourceItemToPage( this, p );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PlaylistItem::setLoaded( bool loaded )
|
|
||||||
{
|
|
||||||
m_loaded = loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PlaylistItem::willAcceptDrag( const QMimeData* data ) const
|
|
||||||
{
|
|
||||||
return !m_playlist.isNull() && m_playlist->author()->isLocal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action )
|
|
||||||
{
|
|
||||||
if( data->hasFormat( "application/tomahawk.query.list" ) ) {
|
|
||||||
if ( !m_playlist.isNull() && m_playlist->author()->isLocal() ) {
|
|
||||||
|
|
||||||
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
|
||||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
|
||||||
QList< Tomahawk::query_ptr > queries;
|
|
||||||
|
|
||||||
while ( !stream.atEnd() )
|
|
||||||
{
|
|
||||||
qlonglong qptr;
|
|
||||||
stream >> qptr;
|
|
||||||
|
|
||||||
Tomahawk::query_ptr* query = reinterpret_cast<Tomahawk::query_ptr*>(qptr);
|
|
||||||
if ( query && !query->isNull() )
|
|
||||||
{
|
|
||||||
qDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
|
||||||
queries << *query;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "on playlist:" << m_playlist->title() << m_playlist->guid();
|
|
||||||
|
|
||||||
// TODO do we need to use this in the refactor?
|
|
||||||
// QString rev = item->currentlyLoadedPlaylistRevision( playlist->guid() );
|
|
||||||
m_playlist->addEntries( queries, m_playlist->currentrevision() );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon
|
|
||||||
PlaylistItem::icon() const
|
|
||||||
{
|
|
||||||
return QIcon( RESPATH "images/playlist-icon.png" );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PlaylistItem::setData(const QVariant& v, bool role)
|
|
||||||
{
|
|
||||||
if( m_playlist->author()->isLocal() ) {
|
|
||||||
m_playlist->rename( v.toString() );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicPlaylistItem::DynamicPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl, int index )
|
|
||||||
: PlaylistItem( mdl, parent, pl.staticCast< Playlist >(), index )
|
|
||||||
, m_dynplaylist( pl )
|
|
||||||
{
|
|
||||||
setRowType( m_dynplaylist->mode() == Static ? SourcesModel::AutomaticPlaylist : SourcesModel::Station );
|
|
||||||
|
|
||||||
connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ),
|
|
||||||
SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection );
|
|
||||||
|
|
||||||
if( ViewManager::instance()->pageForDynPlaylist( pl ) )
|
|
||||||
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForDynPlaylist( pl ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicPlaylistItem::~DynamicPlaylistItem()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DynamicPlaylistItem::activate()
|
|
||||||
{
|
|
||||||
ViewPage* p = ViewManager::instance()->show( m_dynplaylist );
|
|
||||||
model()->linkSourceItemToPage( this, p );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision )
|
|
||||||
{
|
|
||||||
setLoaded( true );
|
|
||||||
checkReparentHackNeeded( revision );
|
|
||||||
// END HACK
|
|
||||||
emit updated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& revision )
|
|
||||||
{
|
|
||||||
// HACK HACK HACK workaround for an ugly hack where we have to be compatible with older tomahawks (pre-0.1.0) that created dynplaylists as OnDemand then changed them to Static if they were static.
|
|
||||||
// we need to reparent this playlist to the correct category :-/.
|
|
||||||
CategoryItem* cat = qobject_cast< CategoryItem* >( parent() );
|
|
||||||
qDebug() << "with category" << cat;
|
|
||||||
if( cat ) qDebug() << "and cat type:" << cat->categoryType();
|
|
||||||
if( cat ) {
|
|
||||||
CategoryItem* from = cat;
|
|
||||||
CategoryItem* to = 0;
|
|
||||||
if( cat->categoryType() == SourcesModel::PlaylistsCategory && revision.mode == OnDemand ) { // WRONG
|
|
||||||
CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() );
|
|
||||||
to = col->stationsCategory();
|
|
||||||
if( !to ) { // you have got to be fucking kidding me
|
|
||||||
int fme = col->children().count();
|
|
||||||
col->beginRowsAdded( fme, fme );
|
|
||||||
to = new CategoryItem( model(), col, SourcesModel::StationsCategory, false );
|
|
||||||
col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves
|
|
||||||
col->endRowsAdded();
|
|
||||||
col->setStationsCategory( to );
|
|
||||||
}
|
|
||||||
} else if( cat->categoryType() == SourcesModel::StationsCategory && revision.mode == Static ) { // WRONG
|
|
||||||
CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() );
|
|
||||||
to = col->playlistsCategory();
|
|
||||||
qDebug() << "TRYING TO HACK TO:" << to;
|
|
||||||
if( !to ) { // you have got to be fucking kidding me
|
|
||||||
int fme = col->children().count();
|
|
||||||
col->beginRowsAdded( fme, fme );
|
|
||||||
to = new CategoryItem( model(), col, SourcesModel::PlaylistsCategory, false );
|
|
||||||
col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves
|
|
||||||
col->endRowsAdded();
|
|
||||||
col->setPlaylistsCategory( to );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( to ) {
|
|
||||||
qDebug() << "HACKING! moving dynamic playlist from" << from->text() << "to:" << to->text();
|
|
||||||
// remove and add
|
|
||||||
int idx = from->children().indexOf( this );
|
|
||||||
from->beginRowsRemoved( idx, idx );
|
|
||||||
from->removeChild( this );
|
|
||||||
from->endRowsRemoved();
|
|
||||||
|
|
||||||
idx = to->children().count();
|
|
||||||
to->beginRowsAdded( idx, idx );
|
|
||||||
to->appendChild( this );
|
|
||||||
to->endRowsAdded();
|
|
||||||
|
|
||||||
setParentItem( to );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dynplaylist_ptr
|
|
||||||
DynamicPlaylistItem::dynPlaylist() const
|
|
||||||
{
|
|
||||||
return m_dynplaylist;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
DynamicPlaylistItem::text() const
|
|
||||||
{
|
|
||||||
return m_dynplaylist->title();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
DynamicPlaylistItem::willAcceptDrag( const QMimeData* data ) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Dynamic Playlist Item
|
|
||||||
/*
|
|
||||||
DynPlaylistItem::DynPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl )
|
|
||||||
: PlaylistItem( mdl, parent, pl.staticCast< Playlist >() )
|
|
||||||
{
|
|
||||||
setLoaded( false );
|
|
||||||
connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision) ),
|
|
||||||
SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection );
|
|
||||||
connect( pl.data(), SIGNAL( changed() ),
|
|
||||||
SIGNAL( updated() ), Qt::QueuedConnection );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QString
|
|
||||||
DynPlaylistItem::text()
|
|
||||||
{
|
|
||||||
return m_dynplaylist->title();
|
|
||||||
}
|
|
||||||
|
|
||||||
Tomahawk::playlist_ptr
|
|
||||||
DynPlaylistItem::playlist() const
|
|
||||||
{
|
|
||||||
return m_dynplaylist.staticCast<Tomahawk::Playlist>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tomahawk::dynplaylist_ptr
|
|
||||||
// DynPlaylistItem::playlist() const
|
|
||||||
// {
|
|
||||||
// return m_dynplaylist;
|
|
||||||
// }
|
|
||||||
|
|
||||||
void
|
|
||||||
DynPlaylistItem::activate()
|
|
||||||
{
|
|
||||||
ViewManager::instance()->show( m_playlist );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
DynPlaylistItem::onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision )
|
|
||||||
{
|
|
||||||
setLoaded( true );
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/// CategoryAddItem
|
|
||||||
|
|
||||||
CategoryAddItem::CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type )
|
|
||||||
: SourceTreeItem( model, parent, SourcesModel::CategoryAdd )
|
|
||||||
, m_categoryType( type )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CategoryAddItem::~CategoryAddItem()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
CategoryAddItem::text() const
|
|
||||||
{
|
|
||||||
switch( m_categoryType ) {
|
|
||||||
case SourcesModel::PlaylistsCategory:
|
|
||||||
return tr( "New Playlist" );
|
|
||||||
case SourcesModel::StationsCategory:
|
|
||||||
return tr( "New Station" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CategoryAddItem::activate()
|
|
||||||
{
|
|
||||||
switch( m_categoryType )
|
|
||||||
{
|
|
||||||
case SourcesModel::PlaylistsCategory:
|
|
||||||
// only show if none is shown yet
|
|
||||||
if( !ViewManager::instance()->isNewPlaylistPageVisible() ) {
|
|
||||||
ViewPage* p = ViewManager::instance()->show( new NewPlaylistWidget() );
|
|
||||||
model()->linkSourceItemToPage( this, p );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SourcesModel::StationsCategory:
|
|
||||||
APP->mainWindow()->createStation();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags
|
|
||||||
CategoryAddItem::flags() const
|
|
||||||
{
|
|
||||||
switch( m_categoryType )
|
|
||||||
{
|
|
||||||
case SourcesModel::PlaylistsCategory:
|
|
||||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
||||||
case SourcesModel::StationsCategory:
|
|
||||||
default:
|
|
||||||
return Qt::ItemIsEnabled;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon
|
|
||||||
CategoryAddItem::icon() const
|
|
||||||
{
|
|
||||||
return QIcon( RESPATH "images/add.png" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// CategoryItem
|
|
||||||
|
|
||||||
CategoryItem::CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem )
|
|
||||||
: SourceTreeItem( model, parent, SourcesModel::Category )
|
|
||||||
, m_category( category )
|
|
||||||
, m_addItem( 0 )
|
|
||||||
, m_showAdd( showAddItem )
|
|
||||||
{
|
|
||||||
// in the constructor we're still being added to the parent, so we don't exist to have rows addded yet. so this is safe.
|
|
||||||
// beginRowsAdded( 0, 0 );
|
|
||||||
if( m_showAdd ) {
|
|
||||||
m_addItem = new CategoryAddItem( model, this, m_category );
|
|
||||||
}
|
|
||||||
// endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CategoryItem::insertItem( SourceTreeItem* item )
|
|
||||||
{
|
|
||||||
insertItems( QList< SourceTreeItem* >() << item );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CategoryItem::insertItems( QList< SourceTreeItem* > items )
|
|
||||||
{
|
|
||||||
// add the items to the category, and connect to the signals
|
|
||||||
int curCount = children().size();
|
|
||||||
if( m_showAdd ) // if there's an add item, add it before that
|
|
||||||
curCount--;
|
|
||||||
beginRowsAdded( curCount, curCount + items.size() - 1 );
|
|
||||||
foreach( SourceTreeItem* item, items ) {
|
|
||||||
int index = m_showAdd ? children().count() - 1 : children().count();
|
|
||||||
insertChild( children().count() - 1, item );
|
|
||||||
}
|
|
||||||
endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// CollectionItem
|
|
||||||
|
|
||||||
CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahawk::source_ptr& source )
|
|
||||||
: SourceTreeItem( mdl, parent, SourcesModel::Collection )
|
|
||||||
, m_source( source )
|
|
||||||
, m_playlists( 0 )
|
|
||||||
, m_stations( 0 )
|
|
||||||
{
|
|
||||||
if( m_source.isNull() ) { // super collection
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// create category items if there are playlists to show, or stations to show
|
|
||||||
QList< playlist_ptr > playlists = source->collection()->playlists();
|
|
||||||
QList< dynplaylist_ptr > autoplaylists = source->collection()->autoPlaylists();
|
|
||||||
QList< dynplaylist_ptr > stations = source->collection()->stations();
|
|
||||||
|
|
||||||
if( !playlists.isEmpty() || !autoplaylists.isEmpty() || source->isLocal() ) {
|
|
||||||
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() );
|
|
||||||
onPlaylistsAdded( playlists );
|
|
||||||
onAutoPlaylistsAdded( autoplaylists );
|
|
||||||
}
|
|
||||||
if( !stations.isEmpty() || source->isLocal() ) {
|
|
||||||
m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() );
|
|
||||||
onStationsAdded( stations );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ViewManager::instance()->pageForCollection( source->collection() ) )
|
|
||||||
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) );
|
|
||||||
|
|
||||||
// load auto playlists and stations!
|
|
||||||
|
|
||||||
connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) );
|
|
||||||
connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), this, SIGNAL( updated() ) );
|
|
||||||
connect( source.data(), SIGNAL( stateChanged() ), this, SIGNAL( updated() ) );
|
|
||||||
connect( source.data(), SIGNAL( offline() ), this, SIGNAL( updated() ) );
|
|
||||||
connect( source.data(), SIGNAL( online() ), this, SIGNAL( updated() ) );
|
|
||||||
|
|
||||||
connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
|
|
||||||
SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ), Qt::QueuedConnection );
|
|
||||||
connect( source->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ),
|
|
||||||
SLOT( onPlaylistsDeleted( QList<Tomahawk::playlist_ptr> ) ), Qt::QueuedConnection );
|
|
||||||
|
|
||||||
connect( source->collection().data(), SIGNAL( autoPlaylistsAdded( QList< Tomahawk::dynplaylist_ptr > ) ),
|
|
||||||
SLOT( onAutoPlaylistsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
|
||||||
connect( source->collection().data(), SIGNAL( autoPlaylistsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ),
|
|
||||||
SLOT( onAutoPlaylistsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
|
||||||
|
|
||||||
connect( source->collection().data(), SIGNAL( stationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ),
|
|
||||||
SLOT( onStationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
|
||||||
connect( source->collection().data(), SIGNAL( stationsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ),
|
|
||||||
SLOT( onStationsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
|
||||||
}
|
|
||||||
|
|
||||||
Tomahawk::source_ptr
|
|
||||||
CollectionItem::source() const
|
|
||||||
{
|
|
||||||
return m_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
CollectionItem::text() const
|
|
||||||
{
|
|
||||||
return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::activate()
|
|
||||||
{
|
|
||||||
if( source().isNull() ) {
|
|
||||||
ViewPage* p = ViewManager::instance()->showSuperCollection();
|
|
||||||
model()->linkSourceItemToPage( this, p );
|
|
||||||
} else {
|
|
||||||
ViewPage* p = ViewManager::instance()->show( source()->collection() );
|
|
||||||
model()->linkSourceItemToPage( this, p );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon
|
|
||||||
CollectionItem::icon() const
|
|
||||||
{
|
|
||||||
if( m_source.isNull() )
|
|
||||||
return QIcon( RESPATH "images/supercollection.png" );
|
|
||||||
else
|
|
||||||
return QIcon( RESPATH "images/user-avatar.png" );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists )
|
|
||||||
{
|
|
||||||
QList< SourceTreeItem* > items;
|
|
||||||
int addOffset = playlists.first()->author()->isLocal() ? 1 : 0;
|
|
||||||
|
|
||||||
int from = parent->children().count() - addOffset;
|
|
||||||
parent->beginRowsAdded( from, from + playlists.count() - 1 );
|
|
||||||
foreach( const dynplaylist_ptr& p, playlists )
|
|
||||||
{
|
|
||||||
DynamicPlaylistItem* plItem = new DynamicPlaylistItem( model(), parent, p, parent->children().count() - addOffset );
|
|
||||||
qDebug() << "Dynamic Playlist added:" << p->title() << p->creator() << p->info();
|
|
||||||
p->loadRevision();
|
|
||||||
items << plItem;
|
|
||||||
}
|
|
||||||
parent->endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T >
|
|
||||||
void
|
|
||||||
CollectionItem::playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists )
|
|
||||||
{
|
|
||||||
Q_ASSERT( parent ); // How can we delete playlists if we have none?
|
|
||||||
QList< SourceTreeItem* > items;
|
|
||||||
foreach( const T& playlist, playlists ) {
|
|
||||||
int curCount = parent->children().count();
|
|
||||||
for( int i = 0; i < curCount; i++ ) {
|
|
||||||
PlaylistItem* pl = qobject_cast< PlaylistItem* >( parent->children().at( i ) );
|
|
||||||
if( pl && pl->playlist() == playlist ) {
|
|
||||||
parent->beginRowsRemoved( i, i );
|
|
||||||
parent->removeChild( pl );
|
|
||||||
parent->endRowsRemoved();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
|
|
||||||
{
|
|
||||||
if( playlists.isEmpty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !m_playlists ) { // add the category too
|
|
||||||
int cur = children().count();
|
|
||||||
beginRowsAdded( cur, cur );
|
|
||||||
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() );
|
|
||||||
endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList< SourceTreeItem* > items;
|
|
||||||
int addOffset = playlists.first()->author()->isLocal() ? 1 : 0;
|
|
||||||
|
|
||||||
int from = m_playlists->children().count() - addOffset;
|
|
||||||
m_playlists->beginRowsAdded( from, from + playlists.count() - 1 );
|
|
||||||
foreach( const playlist_ptr& p, playlists )
|
|
||||||
{
|
|
||||||
PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p, m_playlists->children().count() - addOffset );
|
|
||||||
qDebug() << "Playlist added:" << p->title() << p->creator() << p->info();
|
|
||||||
p->loadRevision();
|
|
||||||
items << plItem;
|
|
||||||
}
|
|
||||||
m_playlists->endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists )
|
|
||||||
{
|
|
||||||
playlistsDeletedInternal( m_playlists, playlists );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
|
|
||||||
{
|
|
||||||
if( playlists.isEmpty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !m_playlists ) { // add the category too
|
|
||||||
int cur = children().count();
|
|
||||||
beginRowsAdded( cur, cur );
|
|
||||||
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() );
|
|
||||||
endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
playlistsAddedInternal( m_playlists, playlists );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::onAutoPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists )
|
|
||||||
{
|
|
||||||
if( !m_playlists )
|
|
||||||
qDebug() << "NO playlist category item for a deleting playlist..";
|
|
||||||
|
|
||||||
playlistsDeletedInternal( m_playlists, playlists );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations )
|
|
||||||
{
|
|
||||||
if( stations.isEmpty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !m_stations ) { // add the category too
|
|
||||||
int cur = children().count();
|
|
||||||
beginRowsAdded( cur, cur );
|
|
||||||
m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source()->isLocal() );
|
|
||||||
endRowsAdded();
|
|
||||||
}
|
|
||||||
|
|
||||||
playlistsAddedInternal( m_stations, stations );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CollectionItem::onStationsDeleted( const QList< dynplaylist_ptr >& stations )
|
|
||||||
{
|
|
||||||
playlistsDeletedInternal( m_stations, stations );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Generic page item
|
|
||||||
GenericPageItem::GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon )
|
|
||||||
: SourceTreeItem( model, parent, SourcesModel::GenericPage )
|
|
||||||
, m_icon( icon )
|
|
||||||
, m_text( text )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericPageItem::~GenericPageItem()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GenericPageItem::activate()
|
|
||||||
{
|
|
||||||
emit activated();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
GenericPageItem::text() const
|
|
||||||
{
|
|
||||||
return m_text;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon
|
|
||||||
GenericPageItem::icon() const
|
|
||||||
{
|
|
||||||
return m_icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
GenericPageItem::willAcceptDrag(const QMimeData* data) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,235 +0,0 @@
|
|||||||
/*
|
|
||||||
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, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SOURCETREEITEM_H
|
|
||||||
#define SOURCETREEITEM_H
|
|
||||||
|
|
||||||
#include "sourcesmodel.h"
|
|
||||||
#include "typedefs.h"
|
|
||||||
#include "playlist.h"
|
|
||||||
#include "playlist/dynamic/DynamicPlaylist.h"
|
|
||||||
#include "source.h"
|
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
class QMimeData;
|
|
||||||
class SourceTreeItem : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
SourceTreeItem() : m_type( SourcesModel::Invalid ), m_parent( 0 ), m_model( 0 ) {}
|
|
||||||
SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index = -1 ); // if index is -1, append at end of parent's child list
|
|
||||||
virtual ~SourceTreeItem();
|
|
||||||
|
|
||||||
// generic info used by the tree model
|
|
||||||
SourcesModel::RowType type() const { return m_type; }
|
|
||||||
SourceTreeItem* parent() const { return m_parent; }
|
|
||||||
SourcesModel* model() const { return m_model; }
|
|
||||||
|
|
||||||
QList< SourceTreeItem* > children() const { return m_children; }
|
|
||||||
void appendChild( SourceTreeItem* item ) { m_children.append( item ); }
|
|
||||||
void insertChild( int index, SourceTreeItem* item ) { m_children.insert( index, item ); }
|
|
||||||
void removeChild( SourceTreeItem* item ) { m_children.removeAll( item ); }
|
|
||||||
|
|
||||||
// varies depending on the type of the item
|
|
||||||
virtual QString text() const { return QString(); }
|
|
||||||
virtual Qt::ItemFlags flags() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
|
|
||||||
virtual void activate() {}
|
|
||||||
virtual QIcon icon() const { return QIcon(); }
|
|
||||||
virtual bool willAcceptDrag( const QMimeData* data ) const { return false; }
|
|
||||||
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action ) { return false; }
|
|
||||||
virtual bool setData( const QVariant& v, bool role ) { return false; }
|
|
||||||
|
|
||||||
/// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend
|
|
||||||
void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); }
|
|
||||||
void endRowsAdded() { emit childRowsAdded(); }
|
|
||||||
void beginRowsRemoved( int from, int to ) { emit beginChildRowsRemoved( from, to ); }
|
|
||||||
void endRowsRemoved() { emit childRowsRemoved(); }
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void updated();
|
|
||||||
|
|
||||||
void beginChildRowsAdded( int fromRow, int toRow );
|
|
||||||
void childRowsAdded();
|
|
||||||
|
|
||||||
void beginChildRowsRemoved( int fromRow, int toRow );
|
|
||||||
void childRowsRemoved();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void setRowType( SourcesModel::RowType t ) { m_type = t; }
|
|
||||||
void setParentItem( SourceTreeItem* item ) { m_parent = item; }
|
|
||||||
private:
|
|
||||||
SourcesModel::RowType m_type;
|
|
||||||
|
|
||||||
SourceTreeItem* m_parent;
|
|
||||||
QList< SourceTreeItem* > m_children;
|
|
||||||
SourcesModel* m_model;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CategoryAddItem : public SourceTreeItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type );
|
|
||||||
~CategoryAddItem();
|
|
||||||
|
|
||||||
virtual Qt::ItemFlags flags() const;
|
|
||||||
virtual QString text() const;
|
|
||||||
virtual void activate();
|
|
||||||
virtual QIcon icon() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
SourcesModel::CategoryType m_categoryType;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CategoryItem : public SourceTreeItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem );
|
|
||||||
|
|
||||||
virtual QString text() const {
|
|
||||||
switch( m_category )
|
|
||||||
{
|
|
||||||
case SourcesModel::PlaylistsCategory:
|
|
||||||
return tr( "Playlists" );
|
|
||||||
case SourcesModel::StationsCategory:
|
|
||||||
return tr( "Stations" );
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
virtual void activate();
|
|
||||||
virtual Qt::ItemFlags flags() const { return Qt::ItemIsEnabled; }
|
|
||||||
|
|
||||||
// inserts an item at the end, but before the category add item
|
|
||||||
void insertItem( SourceTreeItem* item );
|
|
||||||
void insertItems( QList< SourceTreeItem* > item );
|
|
||||||
|
|
||||||
SourcesModel::CategoryType categoryType() { return m_category; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
SourcesModel::CategoryType m_category;
|
|
||||||
CategoryAddItem* m_addItem;
|
|
||||||
bool m_showAdd;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CollectionItem : public SourceTreeItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source );
|
|
||||||
|
|
||||||
virtual QString text() const;
|
|
||||||
virtual void activate();
|
|
||||||
virtual QIcon icon() const;
|
|
||||||
|
|
||||||
Tomahawk::source_ptr source() const;
|
|
||||||
|
|
||||||
CategoryItem* stationsCategory() const { return m_stations; }
|
|
||||||
CategoryItem* playlistsCategory() const { return m_playlists; }
|
|
||||||
void setStationsCategory( CategoryItem* item ) { m_stations = item; }
|
|
||||||
void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; }
|
|
||||||
private slots:
|
|
||||||
void onPlaylistsAdded( const QList<Tomahawk::playlist_ptr>& playlists );
|
|
||||||
void onPlaylistsDeleted( const QList<Tomahawk::playlist_ptr>& playlists );
|
|
||||||
void onAutoPlaylistsAdded( const QList<Tomahawk::dynplaylist_ptr>& playlists );
|
|
||||||
void onAutoPlaylistsDeleted( const QList<Tomahawk::dynplaylist_ptr>& playlists );
|
|
||||||
void onStationsAdded( const QList<Tomahawk::dynplaylist_ptr>& stations );
|
|
||||||
void onStationsDeleted( const QList<Tomahawk::dynplaylist_ptr>& stations );
|
|
||||||
|
|
||||||
private:
|
|
||||||
void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists );
|
|
||||||
template< typename T >
|
|
||||||
void playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists );
|
|
||||||
|
|
||||||
Tomahawk::source_ptr m_source;
|
|
||||||
CategoryItem* m_playlists;
|
|
||||||
CategoryItem* m_stations;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PlaylistItem : public SourceTreeItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
PlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::playlist_ptr& pl, int index = -1 );
|
|
||||||
|
|
||||||
virtual QString text() const;
|
|
||||||
virtual Tomahawk::playlist_ptr playlist() const;
|
|
||||||
virtual Qt::ItemFlags flags() const;
|
|
||||||
virtual void activate();
|
|
||||||
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
|
||||||
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action );
|
|
||||||
virtual QIcon icon() const;
|
|
||||||
virtual bool setData(const QVariant& v, bool role);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void setLoaded( bool loaded );
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onPlaylistLoaded( Tomahawk::PlaylistRevision revision );
|
|
||||||
void onPlaylistChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_loaded;
|
|
||||||
Tomahawk::playlist_ptr m_playlist;
|
|
||||||
};
|
|
||||||
|
|
||||||
// can be a station or an auto playlist
|
|
||||||
class DynamicPlaylistItem : public PlaylistItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
DynamicPlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::dynplaylist_ptr& pl, int index = -1 );
|
|
||||||
virtual ~DynamicPlaylistItem();
|
|
||||||
|
|
||||||
virtual QString text() const;
|
|
||||||
Tomahawk::dynplaylist_ptr dynPlaylist() const;
|
|
||||||
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
|
||||||
virtual void activate();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision );
|
|
||||||
|
|
||||||
private:
|
|
||||||
void checkReparentHackNeeded( const Tomahawk::DynamicPlaylistRevision& rev );
|
|
||||||
|
|
||||||
Tomahawk::dynplaylist_ptr m_dynplaylist;
|
|
||||||
};
|
|
||||||
|
|
||||||
// generic item that has some name, some text, and calls a certain slot when activated. badabing!
|
|
||||||
class GenericPageItem : public SourceTreeItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon );
|
|
||||||
virtual ~GenericPageItem();
|
|
||||||
|
|
||||||
virtual QString text() const;
|
|
||||||
virtual void activate();
|
|
||||||
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
|
||||||
virtual QIcon icon() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void activated();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QIcon m_icon;
|
|
||||||
QString m_text;
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE( SourceTreeItem* );
|
|
||||||
|
|
||||||
#endif // SOURCETREEITEM_H
|
|
@@ -22,7 +22,8 @@
|
|||||||
#include "viewmanager.h"
|
#include "viewmanager.h"
|
||||||
#include "sourcesproxymodel.h"
|
#include "sourcesproxymodel.h"
|
||||||
#include "sourcelist.h"
|
#include "sourcelist.h"
|
||||||
#include "sourcetree/sourcetreeitem.h"
|
#include "sourcetree/items/playlistitems.h"
|
||||||
|
#include "sourcetree/items/collectionitem.h"
|
||||||
#include "tomahawk/tomahawkapp.h"
|
#include "tomahawk/tomahawkapp.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
Reference in New Issue
Block a user