1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-05 13:47:26 +02:00

Move drop handling into source model

Add a Add Station item (needs flag change)
Cleanup
restore dynamic playlists to wo rking though hidden so we don't crash
fix lots of minor things in the sourcelist
This commit is contained in:
Leo Franchi
2011-03-29 23:51:48 -04:00
parent 4f5948db71
commit ed27dcdeec
14 changed files with 330 additions and 137 deletions

View File

@@ -84,7 +84,7 @@ Collection::addDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p )
qDebug() << Q_FUNC_INFO << "Collection name" << name() qDebug() << Q_FUNC_INFO << "Collection name" << name()
<< "from source id" << source()->id() << "from source id" << source()->id()
<< "numplaylists:" << m_playlists.length(); << "numplaylists:" << m_playlists.length();
// emit dynamicPlaylistsAdded( toadd ); emit dynamicPlaylistsAdded( toadd );
} }
@@ -114,7 +114,7 @@ Collection::deleteDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p )
qDebug() << Q_FUNC_INFO << "Collection name" << name() qDebug() << Q_FUNC_INFO << "Collection name" << name()
<< "from source id" << source()->id() << "from source id" << source()->id()
<< "numplaylists:" << m_playlists.length(); << "numplaylists:" << m_playlists.length();
// emit dynamicPlaylistsDeleted( todelete ); emit dynamicPlaylistsDeleted( todelete );
} }

View File

@@ -82,10 +82,10 @@ signals:
void playlistsAdded( const QList<Tomahawk::playlist_ptr>& ); void playlistsAdded( const QList<Tomahawk::playlist_ptr>& );
void playlistsDeleted( const QList<Tomahawk::playlist_ptr>& ); void playlistsDeleted( const QList<Tomahawk::playlist_ptr>& );
void automaticPlaylistsAdded( const QList<Tomahawk::dynplaylist_ptr>& ); void dynamicPlaylistsAdded( const QList<Tomahawk::dynplaylist_ptr>& );
void automaticPlaylistsDeleted( const QList<Tomahawk::dynplaylist_ptr>& ); void dynamicPlaylistsDeleted( const QList<Tomahawk::dynplaylist_ptr>& );
void stationsAdded( const QList<Tomahawk::dynplaylist_ptr>& ); // void stationsAdded( const QList<Tomahawk::dynplaylist_ptr>& );
void stationsDeleted( const QList<Tomahawk::dynplaylist_ptr>& ); // void stationsDeleted( const QList<Tomahawk::dynplaylist_ptr>& );
public slots: public slots:
virtual void addTracks( const QList<QVariant>& newitems ) = 0; virtual void addTracks( const QList<QVariant>& newitems ) = 0;

View File

@@ -53,10 +53,12 @@ DatabaseCollection::loadDynamicPlaylists()
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
DatabaseCommand_LoadAllDynamicPlaylists* cmd = new DatabaseCommand_LoadAllDynamicPlaylists( source() ); DatabaseCommand_LoadAllDynamicPlaylists* cmd = new DatabaseCommand_LoadAllDynamicPlaylists( source() );
connect( cmd, SIGNAL( dynamicPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ),
SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );/*
connect( cmd, SIGNAL( autoPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ), connect( cmd, SIGNAL( autoPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ),
SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );
connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ), connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ),
SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );*/
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) ); Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
} }

View File

@@ -51,7 +51,7 @@ public slots:
virtual void removeTracks( const QDir& dir ); virtual void removeTracks( const QDir& dir );
private slots: private slots:
// void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data );
}; };
#endif // DATABASECOLLECTION_H #endif // DATABASECOLLECTION_H

View File

@@ -49,10 +49,12 @@ void DatabaseCommand_LoadAllDynamicPlaylists::exec( DatabaseImpl* dbi )
<< query.value(6).toBool() //shared << query.value(6).toBool() //shared
<< query.value(5).toInt() //lastmod << query.value(5).toInt() //lastmod
<< query.value(0).toString(); //GUID << query.value(0).toString(); //GUID
emit dynamicPlaylistLoaded( source(), data );
/*
if( static_cast<GeneratorMode>( query.value(8).toInt() ) == Static ) if( static_cast<GeneratorMode>( query.value(8).toInt() ) == Static )
emit autoPlaylistLoaded( source(), data ); emit autoPlaylistLoaded( source(), data );
else else
emit stationLoaded( source(), data ); emit stationLoaded( source(), data );*/
} }
emit done(); emit done();

View File

@@ -39,8 +39,7 @@ public:
virtual QString commandname() const { return "loadalldynamicplaylists"; } virtual QString commandname() const { return "loadalldynamicplaylists"; }
signals: signals:
void autoPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); void dynamicPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data );
void stationLoaded( const Tomahawk::source_ptr& source, const QVariantList& data );
void done(); void done();
}; };

View File

@@ -47,6 +47,7 @@
#include "widgets/welcomewidget.h" #include "widgets/welcomewidget.h"
#include "widgets/infowidgets/sourceinfowidget.h" #include "widgets/infowidgets/sourceinfowidget.h"
#include <widgets/newplaylistwidget.h>
#define FILTER_TIMEOUT 280 #define FILTER_TIMEOUT 280
@@ -567,13 +568,16 @@ PlaylistManager::setPage( ViewPage* page, bool trackHistory )
if ( !playlistForInterface( currentPlaylistInterface() ).isNull() ) if ( !playlistForInterface( currentPlaylistInterface() ).isNull() )
emit playlistActivated( playlistForInterface( currentPlaylistInterface() ) ); emit playlistActivated( playlistForInterface( currentPlaylistInterface() ) );
if ( !dynamicPlaylistForInterface( currentPlaylistInterface() ).isNull() )
else if ( dynamicPlaylistForInterface( currentPlaylistInterface() ) )
emit dynamicPlaylistActivated( dynamicPlaylistForInterface( currentPlaylistInterface() ) ); emit dynamicPlaylistActivated( dynamicPlaylistForInterface( currentPlaylistInterface() ) );
if ( !collectionForInterface( currentPlaylistInterface() ).isNull() ) else if ( collectionForInterface( currentPlaylistInterface() ) )
emit collectionActivated( collectionForInterface( currentPlaylistInterface() ) ); emit collectionActivated( collectionForInterface( currentPlaylistInterface() ) );
if ( isSuperCollectionVisible() ) else if ( isSuperCollectionVisible() )
emit superCollectionActivated(); emit superCollectionActivated();
if ( !currentPlaylistInterface() ) else if( isNewPlaylistPageVisible() )
emit newPlaylistActivated();
else if ( !currentPlaylistInterface() )
emit tempPageActivated(); emit tempPageActivated();
if ( !AudioEngine::instance()->isPlaying() ) if ( !AudioEngine::instance()->isPlaying() )
@@ -597,6 +601,12 @@ PlaylistManager::setPage( ViewPage* page, bool trackHistory )
updateView(); updateView();
} }
bool
PlaylistManager::isNewPlaylistPageVisible() const
{
return dynamic_cast< NewPlaylistWidget* >( currentPage() ) != 0;
}
void void
PlaylistManager::unlinkPlaylist() PlaylistManager::unlinkPlaylist()

View File

@@ -68,6 +68,7 @@ public:
PlaylistView* queue() const; PlaylistView* queue() const;
bool isSuperCollectionVisible() const; bool isSuperCollectionVisible() const;
bool isNewPlaylistPageVisible() const;
PlaylistInterface* currentPlaylistInterface() const; PlaylistInterface* currentPlaylistInterface() const;
Tomahawk::ViewPage* currentPage() const; Tomahawk::ViewPage* currentPage() const;
@@ -108,6 +109,8 @@ signals:
void playlistActivated( const Tomahawk::playlist_ptr& playlist ); void playlistActivated( const Tomahawk::playlist_ptr& playlist );
void dynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); void dynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist );
void newPlaylistActivated();
public slots: public slots:
bool showSuperCollection(); bool showSuperCollection();
void showWelcomePage(); void showWelcomePage();

View File

@@ -67,6 +67,8 @@ SourcesModel::data( const QModelIndex& index, int role ) const
return itemFromIndex( index )->type(); return itemFromIndex( index )->type();
case Qt::DisplayRole: case Qt::DisplayRole:
return itemFromIndex( index )->text(); return itemFromIndex( index )->text();
case Qt::DecorationRole:
return itemFromIndex( index )->icon();
} }
return QVariant(); return QVariant();
} }
@@ -162,8 +164,15 @@ SourcesModel::mimeData( const QModelIndexList& indexes ) const
bool bool
SourcesModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ) SourcesModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
{ {
// TODO SourceTreeItem* item;
return false; if( row == -1 && column == -1 )
item = itemFromIndex( parent );
else
item = itemFromIndex( index( row, column, parent ) );
Q_ASSERT( item );
return item->dropMimeData( data, action );
} }
Qt::DropActions Qt::DropActions
@@ -241,6 +250,37 @@ SourcesModel::removeItem( const Tomahawk::source_ptr& source )
return false; return false;
} }
QModelIndex
SourcesModel::indexFromPlaylist( const playlist_ptr& playlist )
{
QModelIndex idx;
// No option but to iterate through everything... lame
for( int i = 0; i < rowCount(); i++ ) {
QModelIndex source = index( i, 0, QModelIndex() );
CollectionItem* col = qobject_cast< CollectionItem* >( m_rootItem->children().at( i ) );
if( col->source().isNull() )
continue; // skip super collection
// get the playlist item and look through its children
for( int k = 0; k < col->children().count(); k++ ) {
CategoryItem* cat = qobject_cast< CategoryItem* >( col->children().at( k ) );
if( cat && cat->categoryType() == SourcesModel::PlaylistsCategory ) { // this is it
// now find the playlist itself
foreach( SourceTreeItem* plItem, cat->children() ) {
PlaylistItem* plI = qobject_cast< PlaylistItem* >( plItem );
if( plI && plI->playlist() == playlist ) {
return indexFromItem( plI );
}
}
break; // only one playlist category per source anyway, stop looking here
}
}
}
qDebug() << "FAILED to find playlist in source tree:" << playlist->title();
return idx;
}
void void
SourcesModel::onSourceChanged() { SourcesModel::onSourceChanged() {

View File

@@ -44,14 +44,13 @@ public:
Category = 1, Category = 1,
StaticPlaylist = 2, CategoryAdd = 2,
NewStaticPlaylist = 3,
StaticPlaylist = 3,
AutomaticPlaylist = 4, AutomaticPlaylist = 4,
Stations = 5, Stations = 5,
NewStation = 6
}; };
enum CategoryType { enum CategoryType {
@@ -81,9 +80,14 @@ public:
virtual Qt::DropActions supportedDropActions() const; virtual Qt::DropActions supportedDropActions() const;
virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual Qt::ItemFlags flags(const QModelIndex& index) const;
void appendItem( const Tomahawk::source_ptr& source ); void appendItem( const Tomahawk::source_ptr& source );
bool removeItem( const Tomahawk::source_ptr& source ); bool removeItem( const Tomahawk::source_ptr& source );
// HACK i don't like this
// SLOW DON'T USE IF YOU CAN AVOID IT
QModelIndex indexFromPlaylist( const Tomahawk::playlist_ptr& playlist );
QModelIndex indexFromItem( SourceTreeItem* item ) const;
signals: signals:
void clicked( const QModelIndex& ); void clicked( const QModelIndex& );
@@ -104,8 +108,6 @@ public slots:
void onItemRowsRemovedDone(); void onItemRowsRemovedDone();
private: private:
SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const; SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const;
QModelIndex indexFromItem( SourceTreeItem* item ) const;
Tomahawk::playlist_ptr playlistFromItem( SourceTreeItem* item ) 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 indexForSource( Tomahawk::Source* source ) const;

View File

@@ -19,8 +19,11 @@
#include "playlist.h" #include "playlist.h"
#include "playlist/dynamic/DynamicPlaylist.h" #include "playlist/dynamic/DynamicPlaylist.h"
#include <source.h> #include "source.h"
#include <playlist/playlistmanager.h> #include <playlist/playlistmanager.h>
#include "tomahawk/tomahawkapp.h"
#include <QMimeData>
#include <widgets/newplaylistwidget.h>
using namespace Tomahawk; using namespace Tomahawk;
@@ -30,6 +33,8 @@ SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, Sou
, m_parent( parent ) , m_parent( parent )
, m_model( model ) , m_model( model )
{ {
// connect( this, SIGNAL( selectRequest() ), m_model, SLOT( onItemSelectRequest() ) );
connect( this, SIGNAL( beginChildRowsAdded( int,int ) ), m_model, SLOT( onItemRowsAddedBegin( int,int ) ) ); 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( beginChildRowsRemoved( int,int ) ), m_model, SLOT( onItemRowsRemovedBegin( int,int ) ) );
connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) ); connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) );
@@ -92,9 +97,8 @@ PlaylistItem::onPlaylistChanged()
emit updated(); emit updated();
} }
Qt::ItemFlags Qt::ItemFlags
PlaylistItem::flags() PlaylistItem::flags() const
{ {
Qt::ItemFlags flags = SourceTreeItem::flags(); Qt::ItemFlags flags = SourceTreeItem::flags();
@@ -120,6 +124,49 @@ PlaylistItem::setLoaded( bool loaded )
m_loaded = 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;
}
/// Dynamic Playlist Item /// Dynamic Playlist Item
/* /*
@@ -165,6 +212,98 @@ DynPlaylistItem::onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revi
setLoaded( true ); 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( !PlaylistManager::instance()->isNewPlaylistPageVisible() )
PlaylistManager::instance()->show( new NewPlaylistWidget() );
break;
case SourcesModel::StationsCategory:
// TODO
break;
}
}
Qt::ItemFlags
CategoryAddItem::flags() const
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QIcon
CategoryAddItem::icon() const
{
return QIcon( RESPATH "images/list-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 );
appendChild( m_addItem );
}
// 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
@@ -176,10 +315,10 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
return; return;
} }
// create category item // create category item
m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory ); m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() );
appendChild( m_playlists ); appendChild( m_playlists );
m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory ); m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() );
appendChild( m_stations ); appendChild( m_stations );
// ugh :( we're being added by the model, no need to notify for added rows now // ugh :( we're being added by the model, no need to notify for added rows now
@@ -187,6 +326,9 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
onPlaylistsAdded( source->collection()->playlists() ); onPlaylistsAdded( source->collection()->playlists() );
m_playlists->blockSignals( false ); m_playlists->blockSignals( false );
// HACK to load only for now
source->collection()->dynamicPlaylists();
connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ), connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ) ); SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ) );
connect( source->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ), connect( source->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ),
@@ -202,7 +344,7 @@ CollectionItem::source() const
QString QString
CollectionItem::text() const CollectionItem::text() const
{ {
return m_source.isNull() ? "Super Collection" : m_source->friendlyName(); return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName();
} }
void void
@@ -222,24 +364,21 @@ CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
if( playlists.isEmpty() ) if( playlists.isEmpty() )
return; return;
// add the items to the category, and connect to the signals QList< SourceTreeItem* > items;
int curCount = m_playlists->children().size();
// TODO add items to one-minus the end of the category. this leaves room for the [ + New Playlist ] item
m_playlists->beginRowsAdded( curCount, curCount + playlists.size() - 1 );
foreach( const playlist_ptr& p, playlists ) foreach( const playlist_ptr& p, playlists )
{ {
PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p ); PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p );
m_playlists->appendChild( plItem );
qDebug() << "Playlist added:" << p->title() << p->creator() << p->info(); qDebug() << "Playlist added:" << p->title() << p->creator() << p->info();
p->loadRevision(); p->loadRevision();
items << plItem;
} }
m_playlists->endRowsAdded(); m_playlists->insertItems( items );
} }
void void
CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists ) CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists )
{ {
QList< SourceTreeItem* > items;
foreach( const playlist_ptr& playlist, playlists ) { foreach( const playlist_ptr& playlist, playlists ) {
int curCount = m_playlists->children().count(); int curCount = m_playlists->children().count();
for( int i = 0; i < curCount; i++ ) { for( int i = 0; i < curCount; i++ ) {
@@ -253,4 +392,3 @@ CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists )
} }
} }
} }

View File

@@ -23,7 +23,9 @@
#include "playlist.h" #include "playlist.h"
#include "playlist/dynamic/DynamicPlaylist.h" #include "playlist/dynamic/DynamicPlaylist.h"
#include "source.h" #include "source.h"
#include <QIcon>
class QMimeData;
class SourceTreeItem : public QObject class SourceTreeItem : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -39,12 +41,16 @@ public:
QList< SourceTreeItem* > children() const { return m_children; } QList< SourceTreeItem* > children() const { return m_children; }
void appendChild( SourceTreeItem* item ) { m_children.append( item ); } 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 ); } void removeChild( SourceTreeItem* item ) { m_children.removeAll( item ); }
// varies depending on the type of the item // varies depending on the type of the item
virtual QString text() const { return QString(); } virtual QString text() const { return QString(); }
virtual Qt::ItemFlags flags() { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } virtual Qt::ItemFlags flags() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; }
virtual void activate() {} 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; }
/// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend /// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend
void beginRowsAdded( int from, int num ) { emit beginChildRowsAdded( from, num ); } void beginRowsAdded( int from, int num ) { emit beginChildRowsAdded( from, num ); }
@@ -53,6 +59,7 @@ public:
void endRowsRemoved() { emit childRowsRemoved(); } void endRowsRemoved() { emit childRowsRemoved(); }
signals: signals:
void updated(); void updated();
void selectRequest();
void beginChildRowsAdded( int fromRow, int num ); void beginChildRowsAdded( int fromRow, int num );
void childRowsAdded(); void childRowsAdded();
@@ -67,12 +74,27 @@ private:
SourcesModel* m_model; 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 class CategoryItem : public SourceTreeItem
{ {
Q_OBJECT Q_OBJECT
public: public:
CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category ) : SourceTreeItem( model, parent, SourcesModel::Category ), m_category( category ) {} CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem );
virtual QString text() const { virtual QString text() const {
switch( m_category ) switch( m_category )
@@ -85,15 +107,20 @@ public:
return QString(); return QString();
} }
virtual void activate(); virtual void activate();
virtual Qt::ItemFlags flags() { return Qt::ItemIsEnabled; } 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; } SourcesModel::CategoryType categoryType() { return m_category; }
private: private:
SourcesModel::CategoryType m_category; SourcesModel::CategoryType m_category;
CategoryAddItem* m_addItem;
bool m_showAdd;
}; };
class CollectionItem : public SourceTreeItem class CollectionItem : public SourceTreeItem
{ {
Q_OBJECT Q_OBJECT
@@ -101,9 +128,10 @@ public:
CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source ); CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source );
virtual QString text() const; virtual QString text() const;
Tomahawk::source_ptr source() const;
virtual void activate(); virtual void activate();
Tomahawk::source_ptr source() const;
private slots: private slots:
void onPlaylistsAdded( const QList<Tomahawk::playlist_ptr>& playlists ); void onPlaylistsAdded( const QList<Tomahawk::playlist_ptr>& playlists );
void onPlaylistsDeleted( const QList<Tomahawk::playlist_ptr>& playlists ); void onPlaylistsDeleted( const QList<Tomahawk::playlist_ptr>& playlists );
@@ -114,6 +142,7 @@ private:
CategoryItem* m_playlists; CategoryItem* m_playlists;
CategoryItem* m_stations; CategoryItem* m_stations;
}; };
class PlaylistItem : public SourceTreeItem class PlaylistItem : public SourceTreeItem
{ {
Q_OBJECT Q_OBJECT
@@ -122,8 +151,10 @@ public:
virtual QString text() const; virtual QString text() const;
virtual Tomahawk::playlist_ptr playlist() const; virtual Tomahawk::playlist_ptr playlist() const;
virtual Qt::ItemFlags flags(); virtual Qt::ItemFlags flags() const;
virtual void activate(); virtual void activate();
virtual bool willAcceptDrag( const QMimeData* data ) const;
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action );
protected: protected:
void setLoaded( bool loaded ); void setLoaded( bool loaded );

View File

@@ -94,23 +94,25 @@ SourceTreeView::SourceTreeView( QWidget* parent )
header()->setStretchLastSection( false ); header()->setStretchLastSection( false );
header()->setResizeMode( 0, QHeaderView::Stretch ); header()->setResizeMode( 0, QHeaderView::Stretch );
connect( m_proxyModel, SIGNAL( clicked( QModelIndex ) ), SIGNAL( clicked( QModelIndex ) ) ); connect( m_model, SIGNAL( clicked( QModelIndex ) ), SIGNAL( clicked( QModelIndex ) ) );
connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) ); connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
connect( this, SIGNAL( expanded( QModelIndex ) ), this, SLOT( onItemExpanded( QModelIndex ) ) );
connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) ); // connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) );
hideOfflineSources(); hideOfflineSources();
// connect( PlaylistManager::instance(), SIGNAL( playlistActivated( Tomahawk::playlist_ptr ) ), connect( PlaylistManager::instance(), SIGNAL( playlistActivated( Tomahawk::playlist_ptr ) ),
// SLOT( onPlaylistActivated( Tomahawk::playlist_ptr ) ) ); SLOT( onPlaylistActivated( Tomahawk::playlist_ptr ) ) );
// connect( PlaylistManager::instance(), SIGNAL( dynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ), // connect( PlaylistManager::instance(), SIGNAL( dynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ),
// SLOT( onDynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ) ); // SLOT( onDynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ) );
// connect( PlaylistManager::instance(), SIGNAL( collectionActivated( Tomahawk::collection_ptr ) ), connect( PlaylistManager::instance(), SIGNAL( collectionActivated( Tomahawk::collection_ptr ) ),
// SLOT( onCollectionActivated( Tomahawk::collection_ptr ) ) ); SLOT( onCollectionActivated( Tomahawk::collection_ptr ) ) );
// connect( PlaylistManager::instance(), SIGNAL( superCollectionActivated() ), connect( PlaylistManager::instance(), SIGNAL( superCollectionActivated() ),
// SLOT( onSuperCollectionActivated() ) ); SLOT( onSuperCollectionActivated() ) );
// connect( PlaylistManager::instance(), SIGNAL( tempPageActivated() ), connect( PlaylistManager::instance(), SIGNAL( tempPageActivated() ),
// SLOT( onTempPageActivated() ) ); SLOT( onTempPageActivated() ) );
connect( PlaylistManager::instance(), SIGNAL( newPlaylistActivated() ),
SLOT( onNewPlaylistPageActivated() ) );
} }
@@ -159,18 +161,19 @@ SourceTreeView::hideOfflineSources()
m_proxyModel->hideOfflineSources(); m_proxyModel->hideOfflineSources();
} }
/*
void void
SourceTreeView::onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ) SourceTreeView::onPlaylistActivated( const Tomahawk::playlist_ptr& playlist )
{ {
QModelIndex idx = m_proxyModel->mapFromSource( m_model->playlistToIndex( playlist ) ); QModelIndex idx = m_proxyModel->mapFromSource( m_model->indexFromPlaylist( playlist ) );
if ( idx.isValid() ) if ( idx.isValid() )
{ {
setCurrentIndex( idx ); selectionModel()->select( idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current );
// setCurrentIndex( idx );
} }
} }
/*
void void
SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ) SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist )
{ {
@@ -179,28 +182,28 @@ SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& pla
{ {
setCurrentIndex( idx ); setCurrentIndex( idx );
} }
} }*/
void void
SourceTreeView::onCollectionActivated( const Tomahawk::collection_ptr& collection ) SourceTreeView::onCollectionActivated( const Tomahawk::collection_ptr& collection )
{ {
QModelIndex idx = m_proxyModel->mapFromSource( m_model->collectionToIndex( collection ) ); // QModelIndex idx = m_proxyModel->mapFromSource( m_model->collectionToIndex( collection ) );
if ( idx.isValid() ) // if ( idx.isValid() )
{ // {
setCurrentIndex( idx ); // setCurrentIndex( idx );
} // }
} }
void void
SourceTreeView::onSuperCollectionActivated() SourceTreeView::onSuperCollectionActivated()
{ {
QModelIndex idx = m_proxyModel->index( 0, 0 ); // QModelIndex idx = m_proxyModel->index( 0, 0 );
if ( idx.isValid() ) // if ( idx.isValid() )
{ // {
setCurrentIndex( idx ); // setCurrentIndex( idx );
} // }
} }
@@ -208,7 +211,13 @@ void
SourceTreeView::onTempPageActivated() SourceTreeView::onTempPageActivated()
{ {
clearSelection(); clearSelection();
} */ }
void
SourceTreeView::onNewPlaylistPageActivated()
{
// nothing atm
}
void void
@@ -222,6 +231,18 @@ SourceTreeView::onItemActivated( const QModelIndex& index )
} }
void
SourceTreeView::onItemExpanded( const QModelIndex& idx )
{
// make sure to expand children nodes for collections
if( idx.data( SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Collection ) {
for( int i = 0; i < model()->rowCount( idx ); i++ ) {
expand( model()->index( i, 0, idx ) );
}
}
}
void void
SourceTreeView::loadPlaylist() SourceTreeView::loadPlaylist()
{ {
@@ -322,14 +343,9 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
const QRect rect = visualRect( index ); const QRect rect = visualRect( index );
m_dropRect = rect; m_dropRect = rect;
const SourceTreeItem* item = itemFromIndex< SourceTreeItem >( index );
if ( model()->data( index, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist ) if( item->willAcceptDrag( event->mimeData() ) )
{ accept = true;
PlaylistItem* item = itemFromIndex< PlaylistItem >( index );
playlist_ptr playlist = item->playlist();
if ( !playlist.isNull() && playlist->author()->isLocal() )
accept = true;
}
} else { } else {
m_dropRect = QRect(); m_dropRect = QRect();
} }
@@ -350,59 +366,6 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
void void
SourceTreeView::dropEvent( QDropEvent* event ) SourceTreeView::dropEvent( QDropEvent* event )
{ {
bool accept = false;
const QPoint pos = event->pos();
const QModelIndex index = indexAt( pos );
if ( event->mimeData()->hasFormat( "application/tomahawk.query.list" ) )
{
const QPoint pos = event->pos();
const QModelIndex index = indexAt( pos );
if ( index.isValid() )
{
if ( model()->data( index, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist )
{
PlaylistItem* item = itemFromIndex< PlaylistItem >( index );
playlist_ptr playlist = item->playlist();
if ( !playlist.isNull() && playlist->author()->isLocal() )
{
accept = true;
QByteArray itemData = event->mimeData()->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:" << playlist->title() << playlist->guid();
// TODO do we need to use this in the refactor?
// QString rev = item->currentlyLoadedPlaylistRevision( playlist->guid() );
playlist->addEntries( queries, playlist->currentrevision() );
}
}
}
if ( accept )
{
event->setDropAction( Qt::CopyAction );
event->accept();
}
else
event->ignore();
}
QTreeView::dropEvent( event ); QTreeView::dropEvent( event );
m_dragging = false; m_dragging = false;
} }

View File

@@ -37,7 +37,6 @@ Q_OBJECT
public: public:
explicit SourceTreeView( QWidget* parent = 0 ); explicit SourceTreeView( QWidget* parent = 0 );
public slots:
void showOfflineSources(); void showOfflineSources();
void hideOfflineSources(); void hideOfflineSources();
@@ -46,11 +45,15 @@ signals:
void onOffline( const QModelIndex& index ); void onOffline( const QModelIndex& index );
private slots: private slots:
// void onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ); void onPlaylistActivated( const Tomahawk::playlist_ptr& playlist );
// void onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); // void onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist );
// void onCollectionActivated( const Tomahawk::collection_ptr& collection );
// void onSuperCollectionActivated(); void onCollectionActivated( const Tomahawk::collection_ptr& collection );
// void onTempPageActivated(); void onSuperCollectionActivated();
void onTempPageActivated();
void onNewPlaylistPageActivated();
void onItemExpanded( const QModelIndex& idx );
void onItemActivated( const QModelIndex& index ); void onItemActivated( const QModelIndex& index );