extragear/multimedia/amarok/src/playlist/view/listview

Bart Cerneels bart.cerneels at kde.org
Wed Feb 4 23:23:09 CET 2009


SVN commit 921376 by shanachie:

Add PUD to The Playlist.
By making the PUD contain all the actions that would otherwise be only accesible from the contextmenu it becomes a perfect alternative for touchscreens.
This will also allow dragging from The Playlist with the convenience of the PUD.

This is far from a perfect commit. I will attempt to fix what is broken and cleanup later this week. The Playlist is not really my speciality so might need some help.

CCMAIL:amarok-devel at kde.org

 M  +163 -16   PrettyListView.cpp  
 M  +8 -1      PrettyListView.h  


--- trunk/extragear/multimedia/amarok/src/playlist/view/listview/PrettyListView.cpp #921375:921376
@@ -22,17 +22,26 @@
 
 #include "PrettyListView.h"
 
+#include "context/ContextView.h"
+#include "context/popupdropper/libpud/PopupDropperAction.h"
+#include "context/popupdropper/libpud/PopupDropperItem.h"
+#include "context/popupdropper/libpud/PopupDropper.h"
 #include "Debug.h"
 #include "PrettyItemDelegate.h"
 #include "dialogs/TagDialog.h"
+#include "GlobalCurrentTrackActions.h"
+#include "meta/capabilities/CurrentTrackActionsCapability.h"
 #include "meta/Meta.h"
 #include "PaletteHandler.h"
 #include "playlist/GroupingProxy.h"
 #include "playlist/PlaylistActions.h"
 #include "playlist/PlaylistController.h"
 #include "playlist/view/PlaylistViewCommon.h"
+#include "PopupDropperFactory.h"
+#include "SvgHandler.h"
 
 #include <KApplication>
+#include <KMenu>
 
 #include <QContextMenuEvent>
 #include <QDropEvent>
@@ -50,6 +59,7 @@
         : QListView( parent )
         , m_headerPressIndex( QModelIndex() )
         , m_mousePressInHeader( false )
+        , m_pd( 0 )
 {
     setModel( GroupingProxy::instance() );
     setItemDelegate( new PrettyItemDelegate( this ) );
@@ -65,7 +75,7 @@
     setAlternatingRowColors( true) ;
     The::paletteHandler()->updateItemView( this );
     connect( The::paletteHandler(), SIGNAL( newPalette( const QPalette & ) ), SLOT( newPalette( const QPalette & ) ) );
-    
+
     setAutoFillBackground( false );
 
     // signal connections
@@ -139,15 +149,15 @@
 Playlist::PrettyListView::contextMenuEvent( QContextMenuEvent* event )
 {
     QModelIndex index = indexAt( event->pos() );
-    
+
     if ( !index.isValid() )
         return;
-    
+
     //Ctrl + Right Click is used for queuing
     if( event->modifiers() & Qt::ControlModifier )
         return;
 
-    ViewCommon::trackMenu( this, &index, event->globalPos(), true );
+    trackMenu( this, index, event->globalPos(), true );
     event->accept();
 }
 
@@ -267,8 +277,8 @@
 
     // This should always be forwarded, as it is used to determine the offset
     // relative to the mouse of the selection we are dragging!
-    QListView::mousePressEvent( event ); 
-    
+    QListView::mousePressEvent( event );
+
     // This must go after the call to the super class as the current index is not yet selected otherwise
     // Queueing support for Ctrl Right click
     if( event->button() == Qt::RightButton && event->modifiers() & Qt::ControlModifier )
@@ -326,6 +336,143 @@
     QListView::paintEvent( event );
 }
 
+void
+Playlist::PrettyListView::startDrag( Qt::DropActions supportedActions )
+{
+    DEBUG_BLOCK
+
+    //Waah? when a parent item is dragged, startDrag is called a bunch of times
+    static bool ongoingDrags = false;
+    if( ongoingDrags )
+        return;
+    ongoingDrags = true;
+
+    if( !m_pd )
+        m_pd = The::popupDropperFactory()->createPopupDropper( Context::ContextView::self() );
+
+    if( m_pd && m_pd->isHidden() )
+    {
+
+        QModelIndexList indices = selectedIndexes();
+
+        QList<PopupDropperAction*> actions =
+                actionsFor( indices.first(), true );
+
+        foreach( PopupDropperAction * action, actions ) {
+            m_pd->addItem( The::popupDropperFactory()->createItem( action ), false );
+        }
+
+        m_pd->show();
+    }
+
+    QListView::startDrag( supportedActions );
+    debug() << "After the drag!";
+
+    if( m_pd )
+    {
+        debug() << "clearing PUD";
+        connect( m_pd, SIGNAL( fadeHideFinished() ), m_pd, SLOT( clear() ) );
+        m_pd->hide();
+    }
+    ongoingDrags = false;
+}
+
+void
+Playlist::PrettyListView::trackMenu( QWidget *parent, const QModelIndex &index, const QPoint &pos, bool coverActions )
+{
+    DEBUG_BLOCK
+    KMenu *menu = new KMenu( parent );
+
+    QList<PopupDropperAction *> actions = actionsFor( index, coverActions );
+    foreach( PopupDropperAction *action, actions )
+    {
+        menu->addAction( action );
+    }
+    menu->exec( pos );
+}
+
+QList<PopupDropperAction *>
+Playlist::PrettyListView::actionsFor( const QModelIndex &index, bool coverActions )
+{
+    DEBUG_BLOCK
+    QList<PopupDropperAction *> actions;
+
+    Meta::TrackPtr track = index.data( Playlist::TrackRole ).value< Meta::TrackPtr >();
+
+    const bool isCurrentTrack = index.data( Playlist::ActiveTrackRole ).toBool();
+
+    PopupDropperAction *playAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "play", KIcon( "media-playback-start-amarok" ), i18n( "&Play" ), this );
+    connect( playAction, SIGNAL( triggered() ), The::engineController(), SLOT( playPause() ) );
+
+    PopupDropperAction *pauseAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "pause", KIcon( "media-playback-pause-amarok" ), i18n( "&Pause" ), this );
+    connect( pauseAction, SIGNAL( triggered() ), The::engineController(), SLOT( playPause() ) );
+
+    const bool isPaused = The::engineController()->isPaused();
+    if( isCurrentTrack && !isPaused )
+        actions << pauseAction;
+    else
+        actions << playAction;
+
+    PopupDropperAction *queueAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "queue", KIcon( "media-track-queue-amarok" ), i18n( "Queue Track" ), this );
+    connect( queueAction, SIGNAL( triggered() ), this, SLOT( queueSelection() ) );
+
+    PopupDropperAction *dequeueAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "dequeue", KIcon( "media-track-queue-amarok" ), i18n( "Queue Track" ), this );
+    connect( dequeueAction, SIGNAL( triggered() ), this, SLOT( dequeueSelection() ) );
+
+    const bool isQueued = index.data( Playlist::StateRole ).toInt() & Item::Queued;
+    if( isQueued )
+        actions << dequeueAction;
+    else
+        actions << queueAction;
+
+    PopupDropperAction *stopAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "stop", KIcon( "media-playback-stop-amarok" ), i18n( "Stop Playing After This Track" ), this );
+    connect( stopAction, SIGNAL( triggered() ), this, SLOT( stopAfterTrack() ) );
+    actions << stopAction;
+
+    PopupDropperAction *removeAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "remove", KIcon( "media-track-remove-amarok" ), i18n( "Remove From Playlist" ), this );
+    connect( removeAction, SIGNAL( triggered() ), this, SLOT( removeSelection() ) );
+    actions << removeAction;
+
+    PopupDropperAction *editAction = new PopupDropperAction( The::svgHandler()->getRenderer( "amarok/images/pud_items.svg" ), "edit", KIcon( "media-track-edit-amarok" ), i18n( "Edit Track Details" ), this );
+    connect( editAction, SIGNAL( triggered() ), this, SLOT( editTrackInformation() ) );
+    actions << editAction;
+
+    //lets see if this is the currently playing tracks, and if it has CurrentTrackActionsCapability
+    if( isCurrentTrack )
+    {
+
+        QList<QAction *> globalCurrentTrackActions = The::globalCurrentTrackActions()->actions();
+        foreach( QAction *action, globalCurrentTrackActions )
+            actions << PopupDropperAction::from( action );
+
+        if ( track->hasCapabilityInterface( Meta::Capability::CurrentTrackActions ) )
+        {
+            Meta::CurrentTrackActionsCapability *cac = track->as<Meta::CurrentTrackActionsCapability>();
+            if ( cac )
+            {
+                foreach( PopupDropperAction *action, cac->customActions() )
+                    actions << PopupDropperAction::from( action );
+            }
+        }
+    }
+
+    if ( coverActions )
+    {
+        Meta::AlbumPtr album = track->album();
+        if ( album )
+        {
+            Meta::CustomActionsCapability *cac = album->as<Meta::CustomActionsCapability>();
+            if ( cac )
+            {
+                foreach( PopupDropperAction *action, cac->customActions() )
+                    actions << PopupDropperAction::from( action );
+            }
+        }
+    }
+
+    return actions;
+}
+
 QItemSelectionModel::SelectionFlags
 Playlist::PrettyListView::headerPressSelectionCommand( const QModelIndex& index, const QMouseEvent* event ) const
 {
@@ -336,13 +483,13 @@
     //const bool controlKeyPressed = event->modifiers() & Qt::ControlModifier;
     const bool indexIsSelected = selectionModel()->isSelected( index );
     const bool controlKeyPressed = event->modifiers() & Qt::ControlModifier;
-    
+
     if ( shiftKeyPressed )
         return QItemSelectionModel::SelectCurrent;
 
     if ( indexIsSelected && controlKeyPressed ) //make this consistent with how single items work. This also makes it possible to drag the header
         return QItemSelectionModel::Deselect;
-    
+
     return QItemSelectionModel::Select;
 }
 
@@ -387,13 +534,13 @@
     bool updateProxy = false;
     if ( ( GroupingProxy::instance()->currentSearchFields() != fields ) || ( GroupingProxy::instance()->currentSearchTerm() != searchTerm ) )
         updateProxy = true;
-            
+
     int row = GroupingProxy::instance()->find( searchTerm, fields );
     if( row != -1 )
     {
         //select this track
         debug() << "Got match at row: " << row;
-        
+
         QModelIndex index = model()->index( row, 0 );
         QItemSelection selItems( index, index );
         selectionModel()->select( selItems, QItemSelectionModel::SelectCurrent );
@@ -431,12 +578,12 @@
         currentRow = selected.last();
 
     debug() << "current row is: " << currentRow;
-    
+
     int row = GroupingProxy::instance()->findNext( searchTerm, currentRow, fields );
     if( row != -1 ) {
         //select this track
         debug() << "Got match at row: " << row;
-        
+
         QModelIndex index = model()->index( row, 0 );
         QItemSelection selItems( index, index );
         selectionModel()->select( selItems, QItemSelectionModel::SelectCurrent );
@@ -444,7 +591,7 @@
         QModelIndex foundIndex = model()->index( row, 0, QModelIndex() );
         if ( foundIndex.isValid() )
             scrollTo( foundIndex, QAbstractItemView::PositionAtCenter );
-        
+
         emit( found() );
     } else {
         emit( notFound() );
@@ -468,12 +615,12 @@
         currentRow = selected.first();
 
     debug() << "current row is: " << currentRow;
-    
+
     int row = GroupingProxy::instance()->findPrevious( searchTerm, currentRow, fields );
     if( row != -1 ) {
         //select this track
         debug() << "Got match at row: " << row;
-        
+
         QModelIndex index = model()->index( row, 0 );
         QItemSelection selItems( index, index );
         selectionModel()->select( selItems, QItemSelectionModel::SelectCurrent );
@@ -481,7 +628,7 @@
         QModelIndex foundIndex = model()->index( row, 0, QModelIndex() );
         if ( foundIndex.isValid() )
             scrollTo( foundIndex, QAbstractItemView::PositionAtCenter );
-        
+
         emit( found() );
     } else {
         emit( notFound() );
--- trunk/extragear/multimedia/amarok/src/playlist/view/listview/PrettyListView.h #921375:921376
@@ -26,6 +26,8 @@
 #include <QPersistentModelIndex>
 #include <QRect>
 
+class PopupDropper;
+class PopupDropperAction;
 class QContextMenuEvent;
 class QDragLeaveEvent;
 class QDragMoveEvent;
@@ -47,7 +49,7 @@
 
 signals:
     void found();
-    void notFound(); 
+    void notFound();
 
     // these slots are used by the ContextMenu
 public slots:
@@ -81,6 +83,7 @@
     void mousePressEvent( QMouseEvent* );
     void mouseReleaseEvent( QMouseEvent* );
     void paintEvent( QPaintEvent* );
+    void startDrag( Qt::DropActions supportedActions );
 
     bool mouseEventInHeader( const QMouseEvent* ) const;
     QItemSelectionModel::SelectionFlags headerPressSelectionCommand( const QModelIndex&, const QMouseEvent* ) const;
@@ -90,11 +93,15 @@
 
     void startProxyUpdateTimeout();
 
+    void trackMenu( QWidget *, const QModelIndex &, const QPoint &pos, bool coverActions = false );
+    QList<PopupDropperAction *> actionsFor( const QModelIndex &index, bool coverActions );
+
     QRect m_dropIndicator;
     QPersistentModelIndex m_headerPressIndex;
     bool m_mousePressInHeader;
 
     QTimer * m_proxyUpdateTimer;
+    PopupDropper* m_pd;
 };
 }
 #endif


More information about the Amarok-devel mailing list