mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-25 02:09:48 +01:00
Add spotify context menu action for local playlists
This also adds a generic way for runtime components to register actions to be shown for a certain category of items (e.g. playlists, tracks, artists, etc). Initiating a sync from Tomahawk is still a TODO
This commit is contained in:
parent
6ffaa1450e
commit
03c57d3a0f
@ -19,13 +19,17 @@
|
||||
|
||||
#include "SpotifyAccount.h"
|
||||
#include "playlist.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "playlist/PlaylistUpdaterInterface.h"
|
||||
#include "sourcelist.h"
|
||||
#include "SpotifyAccountConfig.h"
|
||||
#include "SpotifyPlaylistUpdater.h"
|
||||
#include "resolvers/scriptresolver.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "actioncollection.h"
|
||||
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QAction>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
@ -95,6 +99,83 @@ SpotifyAccount::init()
|
||||
msg[ "_msgtype" ] = "getCredentials";
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
}
|
||||
|
||||
QAction* action = new QAction( 0 );
|
||||
action->setIcon( QIcon( RESPATH "images/spotify-logo.png" ) );
|
||||
connect( action, SIGNAL( triggered( bool ) ), this, SLOT( syncActionTriggered( bool ) ) );
|
||||
ActionCollection::instance()->addAction( ActionCollection::LocalPlaylists, action, this );
|
||||
m_customActions.append( action );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::aboutToShow( QAction* action, const playlist_ptr& playlist )
|
||||
{
|
||||
if ( !m_customActions.contains( action ) )
|
||||
return;
|
||||
|
||||
// If it's not being synced, allow the option to sync
|
||||
SpotifyPlaylistUpdater* updater = qobject_cast< SpotifyPlaylistUpdater* >( playlist->updater() );
|
||||
if ( !updater || !updater->sync() )
|
||||
{
|
||||
action->setText( tr( "Sync with Spotify" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
action->setText( tr( "Stop syncing with Spotify" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::syncActionTriggered( bool checked )
|
||||
{
|
||||
Q_UNUSED( checked );
|
||||
QAction* action = qobject_cast< QAction* >( sender() );
|
||||
|
||||
if ( !action || !m_customActions.contains( action ) )
|
||||
return;
|
||||
|
||||
const playlist_ptr playlist = action->property( "payload" ).value< playlist_ptr >();
|
||||
if ( playlist.isNull() )
|
||||
{
|
||||
qWarning() << "Got context menu spotify sync action triggered, but invalid playlist payload!";
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
|
||||
SpotifyPlaylistUpdater* updater = qobject_cast< SpotifyPlaylistUpdater* >( playlist->updater() );
|
||||
|
||||
if ( !updater )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
SpotifyPlaylistInfo* info = 0;
|
||||
foreach ( SpotifyPlaylistInfo* ifo, m_allSpotifyPlaylists )
|
||||
{
|
||||
if ( ifo->plid == updater->spotifyId() )
|
||||
{
|
||||
info = ifo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !updater->sync() )
|
||||
{
|
||||
info->sync = true;
|
||||
if ( m_configWidget.data() )
|
||||
m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists );
|
||||
|
||||
startPlaylistSync( info );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
stopPlaylistSync( info, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -303,12 +384,7 @@ SpotifyAccount::saveConfig()
|
||||
if ( pl->sync )
|
||||
{
|
||||
// Fetch full playlist contents, then begin the sync
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "getPlaylist";
|
||||
msg[ "playlistid" ] = pl->plid;
|
||||
msg[ "sync" ] = pl->sync;
|
||||
|
||||
sendMessage( msg, this, "startPlaylistSyncWithPlaylist" );
|
||||
startPlaylistSync( pl );
|
||||
}
|
||||
else
|
||||
stopPlaylistSync( pl );
|
||||
@ -318,6 +394,18 @@ SpotifyAccount::saveConfig()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::startPlaylistSync( SpotifyPlaylistInfo* playlist )
|
||||
{
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "getPlaylist";
|
||||
msg[ "playlistid" ] = playlist->plid;
|
||||
msg[ "sync" ] = playlist->sync;
|
||||
|
||||
sendMessage( msg, this, "startPlaylistSyncWithPlaylist" );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg )
|
||||
{
|
||||
@ -409,7 +497,7 @@ SpotifyAccount::deleteOnUnsync() const
|
||||
}
|
||||
|
||||
void
|
||||
SpotifyAccount::stopPlaylistSync( SpotifyPlaylistInfo* playlist )
|
||||
SpotifyAccount::stopPlaylistSync( SpotifyPlaylistInfo* playlist, bool forceDontDelete )
|
||||
{
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "removeFromSyncList";
|
||||
@ -422,7 +510,7 @@ SpotifyAccount::stopPlaylistSync( SpotifyPlaylistInfo* playlist )
|
||||
SpotifyPlaylistUpdater* updater = m_updaters[ playlist->plid ];
|
||||
updater->setSync( false );
|
||||
|
||||
if ( deleteOnUnsync() )
|
||||
if ( deleteOnUnsync() && !forceDontDelete )
|
||||
{
|
||||
playlist_ptr tomahawkPl = updater->playlist();
|
||||
|
||||
|
@ -20,11 +20,13 @@
|
||||
#ifndef SpotifyAccount_H
|
||||
#define SpotifyAccount_H
|
||||
|
||||
#include "accounts/ResolverAccount.h"
|
||||
#include "sourcelist.h"
|
||||
#include "playlist.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "sourcelist.h"
|
||||
#include "accounts/ResolverAccount.h"
|
||||
#include "utils/SmartPointerList.h"
|
||||
|
||||
class QAction;
|
||||
class SpotifyPlaylistUpdater;
|
||||
class QTimer;
|
||||
|
||||
@ -91,6 +93,11 @@ public:
|
||||
void unregisterUpdater( const QString& plid );
|
||||
|
||||
bool deleteOnUnsync() const;
|
||||
|
||||
public slots:
|
||||
void aboutToShow( QAction* action, const Tomahawk::playlist_ptr& playlist );
|
||||
void syncActionTriggered( bool );
|
||||
|
||||
private slots:
|
||||
void resolverMessage( const QString& msgType, const QVariantMap& msg );
|
||||
|
||||
@ -102,7 +109,8 @@ private:
|
||||
void init();
|
||||
void loadPlaylists();
|
||||
|
||||
void stopPlaylistSync( SpotifyPlaylistInfo* playlist );
|
||||
void startPlaylistSync( SpotifyPlaylistInfo* playlist );
|
||||
void stopPlaylistSync( SpotifyPlaylistInfo* playlist, bool forceDontDelete = false );
|
||||
void fetchFullPlaylist( SpotifyPlaylistInfo* playlist );
|
||||
|
||||
void setSyncForPlaylist( const QString& spotifyPlaylistId, bool sync );
|
||||
@ -116,6 +124,7 @@ private:
|
||||
QList< SpotifyPlaylistInfo* > m_allSpotifyPlaylists;
|
||||
QHash< QString, SpotifyPlaylistUpdater* > m_updaters;
|
||||
|
||||
SmartPointerList< QAction > m_customActions;
|
||||
friend class ::SpotifyPlaylistUpdater;
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
bool sync() const;
|
||||
void setSync( bool sync );
|
||||
|
||||
QString spotifyId() const { return m_spotifyId; }
|
||||
|
||||
/// Spotify callbacks when we are directly instructed from the resolver
|
||||
void spotifyTracksAdded( const QVariantList& tracks, const QString& startPosId, const QString& newRev, const QString& oldRev );
|
||||
void spotifyTracksRemoved( const QVariantList& tracks, const QString& newRev, const QString& oldRev );
|
||||
|
@ -121,6 +121,7 @@ set( libGuiSources
|
||||
utils/tomahawkutilsgui.cpp
|
||||
utils/closure.cpp
|
||||
utils/PixmapDelegateFader.cpp
|
||||
utils/SmartPointerList.h
|
||||
|
||||
widgets/animatedcounterlabel.cpp
|
||||
widgets/checkdirtree.cpp
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright 2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -37,6 +38,14 @@ ActionCollection::ActionCollection( QObject *parent )
|
||||
}
|
||||
|
||||
|
||||
ActionCollection::~ActionCollection()
|
||||
{
|
||||
s_instance = 0;
|
||||
foreach( QString key, m_actionCollection.keys() )
|
||||
delete m_actionCollection[ key ];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ActionCollection::initActions()
|
||||
{
|
||||
@ -76,18 +85,54 @@ ActionCollection::initActions()
|
||||
}
|
||||
|
||||
|
||||
ActionCollection::~ActionCollection()
|
||||
void
|
||||
ActionCollection::addAction( ActionCollection::ActionDestination category, QAction* action, QObject* notify )
|
||||
{
|
||||
s_instance = 0;
|
||||
foreach( QString key, m_actionCollection.keys() )
|
||||
delete m_actionCollection[ key ];
|
||||
QList< QAction* > actions = m_categoryActions.value( category );
|
||||
actions.append( action );
|
||||
m_categoryActions[ category ] = actions;
|
||||
|
||||
if ( notify )
|
||||
m_actionNotifiers[ action ] = notify;
|
||||
}
|
||||
|
||||
|
||||
QAction*
|
||||
ActionCollection::getAction( const QString& name )
|
||||
{
|
||||
return m_actionCollection.contains( name ) ? m_actionCollection[ name ] : 0;
|
||||
return m_actionCollection.value( name, 0 );
|
||||
}
|
||||
|
||||
|
||||
QObject*
|
||||
ActionCollection::actionNotifier( QAction* action )
|
||||
{
|
||||
return m_actionNotifiers.value( action, 0 );
|
||||
}
|
||||
|
||||
|
||||
QList< QAction* >
|
||||
ActionCollection::getAction( ActionCollection::ActionDestination category )
|
||||
{
|
||||
return m_categoryActions.value( category );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ActionCollection::removeAction( QAction* action )
|
||||
{
|
||||
removeAction( action, LocalPlaylists );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ActionCollection::removeAction( QAction* action, ActionCollection::ActionDestination category )
|
||||
{
|
||||
QList< QAction* > actions = m_categoryActions.value( category );
|
||||
actions.removeAll( action );
|
||||
m_categoryActions[ category ] = actions;
|
||||
|
||||
m_actionNotifiers.remove( action );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>>
|
||||
* Copyright 2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -29,6 +30,12 @@ class DLLEXPORT ActionCollection : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Categories for custom-registered actions
|
||||
enum ActionDestination {
|
||||
// Tracks, TODO
|
||||
LocalPlaylists = 0
|
||||
};
|
||||
|
||||
static ActionCollection* instance();
|
||||
|
||||
ActionCollection( QObject *parent);
|
||||
@ -37,6 +44,34 @@ public:
|
||||
void initActions();
|
||||
|
||||
QAction* getAction( const QString& name );
|
||||
QList< QAction* > getAction( ActionDestination category );
|
||||
QObject* actionNotifier( QAction* );
|
||||
|
||||
/**
|
||||
* Add an action for a specific category. The action will show up
|
||||
* where the relevant category is displayed.
|
||||
*
|
||||
* e.g. if you register a Playlist action, it will be shown when
|
||||
* there is a context menu shown for a playlist.
|
||||
*
|
||||
* When the QAction* is shown, it will have a "payload" property that is set
|
||||
* to the <specific type> that is being shown.
|
||||
*
|
||||
* Additionally you can pass a QObject* that will be notified before the given
|
||||
* action is shown. The slot "aboutToShow( QAction*, <specific type> ) will be called,
|
||||
*
|
||||
*
|
||||
* <specific type> corresponds to the category: playlist_ptr for Playlists, etc.
|
||||
*
|
||||
* The Action Collection takes ownership of the action. It's time to let go.
|
||||
*/
|
||||
void addAction( ActionDestination category, QAction* action, QObject* notify = 0 );
|
||||
|
||||
/**
|
||||
* Remove an action from one or all specific categories
|
||||
*/
|
||||
void removeAction( QAction* action );
|
||||
void removeAction( QAction* action, ActionDestination category );
|
||||
|
||||
public slots:
|
||||
void togglePrivateListeningMode();
|
||||
@ -48,6 +83,8 @@ private:
|
||||
static ActionCollection* s_instance;
|
||||
|
||||
QHash< QString, QAction* > m_actionCollection;
|
||||
QHash< ActionDestination, QList< QAction* > > m_categoryActions;
|
||||
QHash< QAction*, QObject* > m_actionNotifiers;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -33,9 +33,8 @@
|
||||
namespace Tomahawk
|
||||
{
|
||||
/**
|
||||
* If a playlist needs updating, implement a updater interface.
|
||||
*
|
||||
* Default is auto-updating and on a periodic timer.
|
||||
* PlaylistUpdaters are attached to playlists. They usually manipulate the playlist in some way
|
||||
* due to external input (spotify syncing) or timers (xspf updating)
|
||||
*/
|
||||
|
||||
class PlaylistUpdaterFactory;
|
||||
|
204
src/libtomahawk/utils/SmartPointerList.h
Normal file
204
src/libtomahawk/utils/SmartPointerList.h
Normal file
@ -0,0 +1,204 @@
|
||||
/****************************************************************************************
|
||||
* Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org> *
|
||||
* Copyright (c) 2009 Ian Monroe <ian@monroe.nu> *
|
||||
* Copyright (c) 2009 Max Howell <max@last.fm> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it under *
|
||||
* the terms of the GNU General Public License as published by the Free Software *
|
||||
* Foundation; either version 2 of the License, or (at your option) any later *
|
||||
* version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License along with *
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef SMART_POINTER_LIST_H
|
||||
#define SMART_POINTER_LIST_H
|
||||
|
||||
#include <QList> //baseclass
|
||||
#include <QObject> //baseclass
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class DLLEXPORT SmartPointerListDaddy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QList<QObject*>& m_list;
|
||||
|
||||
public:
|
||||
SmartPointerListDaddy( QList<QObject*>* list ) : m_list( *list )
|
||||
{}
|
||||
|
||||
private slots:
|
||||
void onDestroyed()
|
||||
{
|
||||
m_list.removeAll( sender() );
|
||||
}
|
||||
};
|
||||
|
||||
/** QList has no virtual functions, so we inherit privately and define the
|
||||
* interface exactly to ensure users can't write code that breaks the
|
||||
* class's internal behaviour.
|
||||
*
|
||||
* I deliberately didn't define clear. I worried people would assume it
|
||||
* deleted the pointers. Or assume it didn't. I didn't expose a few other
|
||||
* functions for that reason.
|
||||
*
|
||||
* non-const iterator functions are not exposed as they access the QList
|
||||
* baseclass, and then the Daddy wouldn't be watching newly inserted items.
|
||||
*
|
||||
* --mxcl
|
||||
* Exposed clear. This class doesn't have a QPtrList autodelete functionality
|
||||
* ever, so if people think that, they're really confused! -- Ian Monroe
|
||||
*
|
||||
*/
|
||||
template <class T> class SmartPointerList : private QList<T*>
|
||||
{
|
||||
class SmartPointerListDaddy* m_daddy;
|
||||
|
||||
public:
|
||||
SmartPointerList() : m_daddy( new SmartPointerListDaddy( (QList<QObject*>*)this ) )
|
||||
{}
|
||||
|
||||
~SmartPointerList()
|
||||
{
|
||||
delete m_daddy;
|
||||
}
|
||||
|
||||
SmartPointerList( const SmartPointerList<T>& that )
|
||||
: QList<T*>()
|
||||
, m_daddy( new SmartPointerListDaddy( (QList<QObject*>*)this ) )
|
||||
{
|
||||
QListIterator<T*> i( that );
|
||||
while (i.hasNext())
|
||||
append( i.next() );
|
||||
}
|
||||
|
||||
SmartPointerList& operator=( const SmartPointerList<T>& that )
|
||||
{
|
||||
QListIterator<T*> i( *this);
|
||||
while (i.hasNext())
|
||||
QObject::disconnect( m_daddy, 0, i.next(), 0 );
|
||||
|
||||
QList<T*>::operator=( that );
|
||||
|
||||
if (this != &that) {
|
||||
QListIterator<T*> i( that );
|
||||
while (i.hasNext())
|
||||
m_daddy->connect( i.next(), SIGNAL(destroyed()), SLOT(onDestroyed()) );
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// keep same function names as Qt
|
||||
void append( T* o )
|
||||
{
|
||||
m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
|
||||
QList<T*>::append( o );
|
||||
}
|
||||
|
||||
void prepend( T* o )
|
||||
{
|
||||
m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
|
||||
QList<T*>::prepend( o );
|
||||
}
|
||||
|
||||
SmartPointerList& operator+=( T* o )
|
||||
{
|
||||
append( o );
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmartPointerList& operator<<( T* o )
|
||||
{
|
||||
return operator+=( o );
|
||||
}
|
||||
|
||||
SmartPointerList operator+( const SmartPointerList that )
|
||||
{
|
||||
SmartPointerList<T> copy = *this;
|
||||
QListIterator<T*> i( that );
|
||||
while (i.hasNext())
|
||||
copy.append( i.next() );
|
||||
return copy;
|
||||
}
|
||||
|
||||
SmartPointerList& operator+=( const SmartPointerList that )
|
||||
{
|
||||
QListIterator<T*> i( that );
|
||||
while (i.hasNext())
|
||||
append( i.next() );
|
||||
return *this;
|
||||
}
|
||||
|
||||
void push_back( T* o )
|
||||
{
|
||||
append( o );
|
||||
}
|
||||
|
||||
void push_front( T* o )
|
||||
{
|
||||
prepend( o );
|
||||
}
|
||||
|
||||
void replace( int i, T* o )
|
||||
{
|
||||
QList<T*>::replace( i, o );
|
||||
m_daddy->connect( o, SIGNAL(destroyed()), SLOT(onDestroyed()) );
|
||||
}
|
||||
|
||||
/** this is a "safe" class. We always bounds check */
|
||||
inline T* operator[]( int index ) const { return QList<T*>::value( index ); }
|
||||
inline T* at( int index ) const { return QList<T*>::value( index ); }
|
||||
|
||||
// make public safe functions again
|
||||
using QList<T*>::back;
|
||||
using QList<T*>::constBegin;
|
||||
using QList<T*>::constEnd;
|
||||
using typename QList<T*>::const_iterator;
|
||||
using QList<T*>::contains;
|
||||
using QList<T*>::count;
|
||||
using QList<T*>::empty;
|
||||
using QList<T*>::erase;
|
||||
using QList<T*>::first;
|
||||
using QList<T*>::front;
|
||||
using QList<T*>::indexOf;
|
||||
using QList<T*>::insert;
|
||||
using QList<T*>::isEmpty;
|
||||
using QList<T*>::last;
|
||||
using QList<T*>::lastIndexOf;
|
||||
using QList<T*>::mid;
|
||||
using QList<T*>::move;
|
||||
using QList<T*>::pop_back;
|
||||
using QList<T*>::pop_front;
|
||||
using QList<T*>::size;
|
||||
using QList<T*>::swap;
|
||||
using QList<T*>::value;
|
||||
using QList<T*>::operator!=;
|
||||
using QList<T*>::operator==;
|
||||
|
||||
// can't use using directive here since we only want the const versions
|
||||
typename QList<T*>::const_iterator begin() const { return QList<T*>::constBegin(); }
|
||||
typename QList<T*>::const_iterator end() const { return QList<T*>::constEnd(); }
|
||||
|
||||
// it can lead to poor performance situations if we don't disconnect
|
||||
// but I think it's not worth making this class more complicated for such
|
||||
// an edge case
|
||||
using QList<T*>::clear;
|
||||
using QList<T*>::removeAll;
|
||||
using QList<T*>::removeAt;
|
||||
using QList<T*>::removeFirst;
|
||||
using QList<T*>::removeLast;
|
||||
using QList<T*>::removeOne;
|
||||
using QList<T*>::takeAt;
|
||||
using QList<T*>::takeFirst;
|
||||
using QList<T*>::takeLast;
|
||||
};
|
||||
|
||||
#endif //HEADER_GUARD
|
||||
|
@ -143,11 +143,13 @@ SourceTreeView::setupMenus()
|
||||
|
||||
bool readonly = true;
|
||||
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
|
||||
|
||||
const PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex );
|
||||
const playlist_ptr playlist = item->playlist();
|
||||
|
||||
if ( type == SourcesModel::StaticPlaylist || type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station )
|
||||
{
|
||||
|
||||
PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex );
|
||||
playlist_ptr playlist = item->playlist();
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
readonly = !playlist->author()->isLocal();
|
||||
@ -190,7 +192,7 @@ SourceTreeView::setupMenus()
|
||||
|
||||
QString addToText = QString( "Add to my %1" );
|
||||
if ( type == SourcesModel::StaticPlaylist )
|
||||
addToText = addToText.arg( "Playlists" );
|
||||
addToText = addToText.arg( "playlists" );
|
||||
if ( type == SourcesModel::AutomaticPlaylist )
|
||||
addToText = addToText.arg( "Automatic Playlists" );
|
||||
else if ( type == SourcesModel::Station )
|
||||
@ -203,6 +205,24 @@ SourceTreeView::setupMenus()
|
||||
renamePlaylistAction->setEnabled( !readonly );
|
||||
addToLocalAction->setEnabled( readonly );
|
||||
|
||||
// Handle any custom actions registered for playlists
|
||||
if ( !ActionCollection::instance()->getAction( ActionCollection::LocalPlaylists ).isEmpty() )
|
||||
{
|
||||
m_playlistMenu.addSeparator();
|
||||
|
||||
foreach ( QAction* action, ActionCollection::instance()->getAction( ActionCollection::LocalPlaylists ) )
|
||||
{
|
||||
if ( QObject* notifier = ActionCollection::instance()->actionNotifier( action ) )
|
||||
{
|
||||
QMetaObject::invokeMethod( notifier, "aboutToShow", Qt::DirectConnection, Q_ARG( QAction*, action ), Q_ARG( Tomahawk::playlist_ptr, playlist ) );
|
||||
}
|
||||
|
||||
action->setProperty( "payload", QVariant::fromValue< playlist_ptr >( playlist ) );
|
||||
m_playlistMenu.addAction( action );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( type == SourcesModel::StaticPlaylist )
|
||||
copyPlaylistAction->setText( tr( "&Export Playlist" ) );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user