mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-30 19:00:12 +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}
|
||||
sourcetree/sourcesmodel.cpp
|
||||
sourcetree/sourcesproxymodel.cpp
|
||||
sourcetree/sourcetreeitem.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
|
||||
tomahawktrayicon.cpp
|
||||
@@ -89,8 +93,12 @@ ENDIF(LIBLASTFM_FOUND)
|
||||
SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
sourcetree/sourcesmodel.h
|
||||
sourcetree/sourcesproxymodel.h
|
||||
sourcetree/sourcetreeitem.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
|
||||
tomahawktrayicon.h
|
||||
|
@@ -413,10 +413,10 @@ ViewManager::showSuperCollection()
|
||||
return shown;
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::ViewPage*
|
||||
ViewManager::showWelcomePage()
|
||||
{
|
||||
show( m_welcomeWidget );
|
||||
return show( m_welcomeWidget );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -123,7 +123,7 @@ signals:
|
||||
|
||||
public slots:
|
||||
Tomahawk::ViewPage* showSuperCollection();
|
||||
void showWelcomePage();
|
||||
Tomahawk::ViewPage* showWelcomePage();
|
||||
void showCurrentTrack();
|
||||
|
||||
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/sourcetreeitem.h"
|
||||
#include "sourcetree/items/sourcetreeitem.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
#include "sourcetree/items/genericpageitems.h"
|
||||
#include "sourcelist.h"
|
||||
#include "playlist.h"
|
||||
#include "collection.h"
|
||||
@@ -26,6 +28,8 @@
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "viewmanager.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <QMimeData>
|
||||
#include <QSize>
|
||||
|
||||
@@ -40,8 +44,7 @@ SourcesModel::SourcesModel( QObject* parent )
|
||||
appendItem( source_ptr() );
|
||||
|
||||
// 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" ) );
|
||||
connect( recent, SIGNAL( activated() ), ViewManager::instance(), SLOT( showWelcomePage() ) );
|
||||
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() ) );
|
||||
|
||||
onSourcesAdded( SourceList::instance()->sources() );
|
||||
|
||||
@@ -388,16 +391,6 @@ SourcesModel::indexFromItem( SourceTreeItem* item ) const
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
playlist_ptr
|
||||
SourcesModel::playlistFromItem( SourceTreeItem* item ) const
|
||||
{
|
||||
Q_ASSERT( item );
|
||||
Q_ASSERT( item->type() == StaticPlaylist );
|
||||
|
||||
return dynamic_cast< PlaylistItem* >( item )->playlist();
|
||||
}
|
||||
|
||||
int
|
||||
SourcesModel::rowForItem( SourceTreeItem* item ) const
|
||||
{
|
||||
|
@@ -107,11 +107,7 @@ public slots:
|
||||
void onItemRowsRemovedDone();
|
||||
private:
|
||||
SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const;
|
||||
Tomahawk::playlist_ptr playlistFromItem( 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;
|
||||
|
||||
|
@@ -22,7 +22,7 @@
|
||||
#include <QTreeView>
|
||||
|
||||
#include "sourcesmodel.h"
|
||||
#include "sourcetree/sourcetreeitem.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
|
||||
|
||||
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 "sourcesproxymodel.h"
|
||||
#include "sourcelist.h"
|
||||
#include "sourcetree/sourcetreeitem.h"
|
||||
#include "sourcetree/items/playlistitems.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
|
||||
#include <QAction>
|
||||
|
Reference in New Issue
Block a user