* Popups
authorClément Stenac <zorglub@videolan.org>
Sat, 26 Aug 2006 15:36:45 +0000 (15:36 +0000)
committerClément Stenac <zorglub@videolan.org>
Sat, 26 Aug 2006 15:36:45 +0000 (15:36 +0000)
* Fix a nasty playlist crash

modules/gui/qt4/Modules.am
modules/gui/qt4/components/playlist/panels.hpp
modules/gui/qt4/components/playlist/selector.cpp
modules/gui/qt4/components/playlist/standardpanel.cpp
modules/gui/qt4/playlist_model.cpp
modules/gui/qt4/playlist_model.hpp
modules/gui/qt4/util/directslider.hpp
modules/gui/qt4/util/views.hpp [new file with mode: 0644]

index 5e401e1..2e4da3c 100644 (file)
@@ -32,7 +32,8 @@ TOMOC = main_interface \
        components/video_widget \
        components/playlist/panels \
        components/playlist/selector \
-       util/input_slider
+       util/input_slider \
+       util/views
 MOCCPP = $(TOMOC:%=%.moc.cpp)
 
 nodist_SOURCES_qt4 = \
@@ -54,6 +55,7 @@ nodist_SOURCES_qt4 = \
                components/playlist/panels.moc.cpp \
                components/playlist/selector.moc.cpp \
                util/input_slider.moc.cpp \
+               util/views.moc.cpp \
                resources.cpp
 
 if ENABLE_QT4
@@ -116,16 +118,17 @@ EXTRA_DIST += \
        components/open.hpp \
        components/video_widget.hpp \
        components/playlist/panels.hpp \
-    components/playlist/selector.hpp \
+       components/playlist/selector.hpp \
        util/input_slider.hpp \
        util/directslider.hpp \
+       util/views.hpp \
        util/qvlcframe.hpp \
        ui/input_stats.ui \
        ui/file_open.ui \
        ui/main_interface.ui \
-    ui/logindialog.ui \
-    ui/inputdialog.ui \
-    ui/progressdialog.ui \
+       ui/logindialog.ui \
+       ui/inputdialog.ui \
+       ui/progressdialog.ui \
        pixmaps/advanced.xpm \
        pixmaps/audio.xpm \
        pixmaps/codec.xpm \
index c3fb88a..3af5d0c 100644 (file)
@@ -33,9 +33,6 @@ class QTreeView;
 class PLModel;
 class QPushButton;
 class QKeyEvent;
-/**
- * \todo Share a single model between views using a filterproxy
- */
 
 class PLPanel: public QWidget
 {
@@ -73,6 +70,7 @@ private slots:
     void handleExpansion( const QModelIndex& );
     void toggleRandom();
     void toggleRepeat();
+    void doPopup( QModelIndex index, QPoint point );
 };
 
 #endif
index 87ed50e..d982682 100644 (file)
@@ -31,7 +31,6 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf,
                         playlist_t *p_playlist ) : QWidget( p ), p_intf(_p_intf)
 {
     model = new PLModel( THEPL, THEPL->p_root_category, 1, this );
-    model->Rebuild();
     view = new QTreeView( 0 );
     view->setIndentation( 0 );
     view->header()->hide();
index 891f497..8f306eb 100644 (file)
 #include <assert.h>
 #include <QModelIndexList>
 
+#include "util/views.hpp"
+
 StandardPLPanel::StandardPLPanel( QWidget *_parent, intf_thread_t *_p_intf,
                                   playlist_t *p_playlist,
                                   playlist_item_t *p_root ):
                                   PLPanel( _parent, _p_intf )
 {
     model = new PLModel( p_playlist, p_root, -1, this );
-    view = new QTreeView( 0 );
+    view = new QVLCTreeView( 0 );
     view->setModel(model);
     view->header()->resizeSection( 0, 300 );
     view->setSelectionMode( QAbstractItemView::ExtendedSelection );
@@ -47,12 +49,13 @@ StandardPLPanel::StandardPLPanel( QWidget *_parent, intf_thread_t *_p_intf,
     connect( view, SIGNAL( activated( const QModelIndex& ) ), model,
              SLOT( activateItem( const QModelIndex& ) ) );
 
+    connect( view, SIGNAL( rightClicked( QModelIndex , QPoint ) ),
+             this, SLOT( doPopup( QModelIndex, QPoint ) ) );
+
     connect( model,
              SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
              this, SLOT( handleExpansion( const QModelIndex& ) ) );
 
-    model->Rebuild();
-
     QVBoxLayout *layout = new QVBoxLayout();
     layout->setSpacing( 0 ); layout->setMargin( 0 );
 
@@ -117,12 +120,19 @@ void StandardPLPanel::handleExpansion( const QModelIndex &index )
     }
 }
 
+void StandardPLPanel::doPopup( QModelIndex index, QPoint point )
+{
+    assert( index.isValid() );
+    QItemSelectionModel *selection = view->selectionModel();
+    QModelIndexList list = selection->selectedIndexes();
+    model->popup( index, point, list );
+}
+
 void StandardPLPanel::setRoot( int i_root_id )
 {
     playlist_item_t *p_item = playlist_ItemGetById( THEPL, i_root_id );
     assert( p_item );
-    model->rebuildRoot( p_item );
-    model->Rebuild();
+    model->rebuild( p_item );
 }
 
 void StandardPLPanel::keyPressEvent( QKeyEvent *e )
index d7fad4e..df87126 100644 (file)
@@ -27,6 +27,7 @@
 #include <QApplication>
 #include "playlist_model.hpp"
 #include <assert.h>
+#include <QMenu>
 
 #include "pixmaps/type_unknown.xpm"
 #include "pixmaps/type_afile.xpm"
@@ -141,6 +142,7 @@ PLModel::PLModel( playlist_t *_p_playlist,
     b_need_update     = false;
     i_cached_id       = -1;
     i_cached_input_id = -1;
+    i_popup_item = i_popup_parent = -1;
 
 #define ADD_ICON(type, x) icons[ITEM_TYPE_##type] = QIcon( QPixmap( type_##x##_xpm ) );
     ADD_ICON( UNKNOWN , unknown );
@@ -155,18 +157,10 @@ PLModel::PLModel( playlist_t *_p_playlist,
     ADD_ICON( NODE, node );
 
     rootItem = NULL;
-    rebuildRoot( p_root );
+    rebuild( p_root );
     addCallbacks();
-
 }
 
-void PLModel::rebuildRoot( playlist_item_t *p_root )
-{
-    if( rootItem ) delete rootItem;
-    rootItem = new PLItem( p_root, NULL, this );
-    rootItem->strings[0] = qtr("Name");
-    rootItem->strings[1] = qtr("Artist");
-}
 
 PLModel::~PLModel()
 {
@@ -202,6 +196,13 @@ void PLModel::activateItem( const QModelIndex &index )
     assert( item );
     PL_LOCK;
     playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
+    activateItem( p_item );
+    PL_UNLOCK;
+}
+/* Must be entered with lock */
+void PLModel::activateItem( playlist_item_t *p_item )
+{
+    if( !p_item ) return;
     playlist_item_t *p_parent = p_item;
     while( p_parent )
     {
@@ -209,10 +210,7 @@ void PLModel::activateItem( const QModelIndex &index )
         p_parent = p_parent->p_parent;
     }
     if( p_parent )
-    {
         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_parent, p_item );
-    }
-    PL_UNLOCK;
 }
 
 /****************** Base model mandatory implementations *****************/
@@ -296,10 +294,11 @@ QModelIndex PLModel::parent(const QModelIndex &index) const
     if( !index.isValid() ) return QModelIndex();
 
     PLItem *childItem = static_cast<PLItem*>(index.internalPointer());
+    if( !childItem ) { msg_Err( p_playlist, "NULL CHILD \n" ); return QModelIndex(); }
     PLItem *parentItem = childItem->parent();
-
-    if (parentItem == rootItem) return QModelIndex();
-    return createIndex(parentItem->row(), 0, parentItem);
+    if( !parentItem || parentItem == rootItem ) return QModelIndex();
+    QModelIndex ind = createIndex(parentItem->row(), 0, parentItem);
+    return ind;
 }
 
 int PLModel::columnCount( const QModelIndex &i) const
@@ -485,7 +484,13 @@ end:
     return;
 }
 
-void PLModel::Rebuild()
+
+void PLModel::rebuild()
+{
+    rebuild( NULL );
+}
+
+void PLModel::rebuild( playlist_item_t *p_root )
 {
     /* Remove callbacks before locking to avoid deadlocks */
     delCallbacks();
@@ -494,17 +499,30 @@ void PLModel::Rebuild()
 
     PL_LOCK;
     /* Clear the tree */
-    qDeleteAll( rootItem->children );
+    if( rootItem )
+    {
+        PLItem *deleted;
+        beginRemoveRows( index( rootItem, 0 ), 0,
+                         rootItem->children.size() -1 );
+        qDeleteAll( rootItem->children );
+        endRemoveRows();
+    }
+    if( p_root )
+    {
+        //if( rootItem ) delete rootItem;
+        rootItem = new PLItem( p_root, NULL, this );
+        rootItem->strings[0] = qtr("Name");
+        rootItem->strings[1] = qtr("Artist");
+    }
+    assert( rootItem );
     /* Recreate from root */
     UpdateNodeChildren( rootItem );
     if( p_playlist->status.p_item )
     {
-        fprintf( stderr, "Playlist is playing" );
         PLItem *currentItem = FindByInput( rootItem,
                                      p_playlist->status.p_item->p_input->i_id );
         if( currentItem )
         {
-            fprintf( stderr, "Updating item\n" );
             UpdateTreeItem( p_playlist->status.p_item, currentItem,
                             true, false );
         }
@@ -610,6 +628,49 @@ void PLModel::doDeleteItem( PLItem *item, QModelIndexList *fullList )
     PL_UNLOCK;
 }
 
+/*********** Popup *********/
+void PLModel::popup( QModelIndex & index, QPoint &point, QModelIndexList list )
+{
+    assert( index.isValid() );
+    PL_LOCK;
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
+                                                    itemId( index ) );
+    if( p_item )
+    {
+        i_popup_item = p_item->i_id;
+        i_popup_parent = p_item->p_parent ? p_item->p_parent->i_id : -1;
+        PL_UNLOCK;
+        current_selection = list;
+        QMenu *menu = new QMenu;
+        menu->addAction( qtr("Play"), this, SLOT( popupPlay() ) );
+        menu->addAction( qtr("Fetch information"), this,
+                             SLOT( popupPreparse() ) );
+        menu->addAction( qtr("Delete"), this, SLOT( popupDel() ) );
+        menu->addAction( qtr("Information"), this, SLOT( popupInfo() ) );
+        if( p_item->i_children > -1 )
+        {
+            menu->addSeparator();
+            menu->addAction( qtr("Sort"), this, SLOT( popupSort() ) );
+            menu->addAction( qtr("Add node"), this, SLOT( popupAdd() ) );
+        }
+        menu->popup( point );
+    }
+    else
+        PL_UNLOCK;
+}
+
+void PLModel::popupDel()
+{
+    doDelete( current_selection );
+}
+void PLModel::popupPlay()
+{
+    PL_LOCK;
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_popup_item );
+    activateItem( p_item );
+    PL_UNLOCK;
+}
+
 /**********************************************************************
  * Playlist callbacks
  **********************************************************************/
index 615934c..119c1f9 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef _PLAYLIST_MODEL_H_
 #define _PLAYLIST_MODEL_H_
 
+#include <QModelIndex>
 #include <QObject>
 #include <QEvent>
 #include <vlc/vlc.h>
@@ -85,7 +86,6 @@ public:
 };
 
 #include <QAbstractItemModel>
-#include <QModelIndex>
 #include <QVariant>
 
 class PLModel : public QAbstractItemModel
@@ -96,19 +96,15 @@ public:
     PLModel( playlist_t *, playlist_item_t *, int, QObject *parent = 0);
     ~PLModel();
 
-    void customEvent( QEvent * );
-
-    /* QModel stuff */
+    /* All types of lookups / QModel stuff */
     QVariant data( const QModelIndex &index, int role) const;
     Qt::ItemFlags flags( const QModelIndex &index) const;
     QVariant headerData( int section, Qt::Orientation orientation,
                          int role = Qt::DisplayRole) const;
-
     QModelIndex index( int r, int c, const QModelIndex &parent ) const;
     QModelIndex index( PLItem *, int c ) const;
     int itemId( const QModelIndex &index ) const;
     bool isCurrent( const QModelIndex &index );
-
     QModelIndex parent( const QModelIndex &index) const;
     int childrenCount( const QModelIndex &parent = QModelIndex() ) const;
     int rowCount( const QModelIndex &parent = QModelIndex() ) const;
@@ -116,14 +112,17 @@ public:
 
     bool b_need_update;
     int i_items_to_append;
-    void Rebuild();
-    void rebuildRoot( playlist_item_t * );
+    void rebuild(); void rebuild( playlist_item_t *);
     bool hasRandom(); bool hasLoop(); bool hasRepeat();
 
+    /* Actions made by the views */
+    void popup( QModelIndex & index, QPoint &point, QModelIndexList list );
     void doDelete( QModelIndexList selected );
 private:
     void addCallbacks();
     void delCallbacks();
+    void customEvent( QEvent * );
+
     PLItem *rootItem;
 
     playlist_t *p_playlist;
@@ -145,6 +144,10 @@ private:
     void recurseDelete( QList<PLItem*> children, QModelIndexList *fullList);
     void doDeleteItem( PLItem *item, QModelIndexList *fullList );
 
+    /* Popup */
+    int i_popup_item, i_popup_parent;
+    QModelIndexList current_selection;
+
     /* Lookups */
     PLItem *FindById( PLItem *, int );
     PLItem *FindByInput( PLItem *, int );
@@ -155,9 +158,13 @@ private:
     int i_cached_input_id;
 public slots:
     void activateItem( const QModelIndex &index );
+    void activateItem( playlist_item_t *p_item );
     void setRandom( bool );
     void setLoop( bool );
     void setRepeat( bool );
+private slots:
+    void popupPlay();
+    void popupDel();
 friend class PLItem;
 };
 
index c363d9f..5d487f3 100644 (file)
@@ -31,8 +31,8 @@
 class DirectSlider : public QSlider
 {
 public:
-DirectSlider( QWidget *_parent ) : QSlider( _parent ) {};
-DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent )
+    DirectSlider( QWidget *_parent ) : QSlider( _parent ) {};
+    DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent )
     {};
     virtual ~DirectSlider()   {};
 
@@ -46,7 +46,7 @@ DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent )
 #else
             int width1 = width();
 #endif
-            int pos = (int)(minimum() + 
+            int pos = (int)(minimum() +
                           (double)(event->x())/width1*(maximum()-minimum()) );
             setSliderPosition( pos );
             QSlider::mousePressEvent(event);
diff --git a/modules/gui/qt4/util/views.hpp b/modules/gui/qt4/util/views.hpp
new file mode 100644 (file)
index 0000000..5ad0f1e
--- /dev/null
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * views.hpp : Custom views
+ ****************************************************************************
+ * Copyright (C) 2006 the VideoLAN team
+ * $Id: qvlcframe.hpp 16283 2006-08-17 18:16:09Z zorglub $
+ *
+ * Authors: Clément Stenac <zorglub@videolan.org>
+ *
+ * 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 _QVLCVIEWS_H_
+#define _QVLCVIEWS_H_
+
+#include <QMouseEvent>
+#include <QTreeView>
+#include <QCursor>
+#include <QPoint>
+#include <QModelIndex>
+
+class QVLCTreeView : public QTreeView
+{
+    Q_OBJECT;
+public:
+    QVLCTreeView( QWidget * parent ) : QTreeView( parent )
+    {
+    };
+    virtual ~QVLCTreeView()   {};
+
+    void mouseReleaseEvent(QMouseEvent* e )
+    {
+        if( e->button() & Qt::RightButton )
+        {
+            emit rightClicked( indexAt( QPoint( e->x(), e->y() ) ), QCursor::pos() );
+        }
+    }
+signals:
+    void rightClicked( QModelIndex, QPoint  );
+};
+#endif