Commit abd5dd87 authored by Clément Stenac's avatar Clément Stenac

* Popups

* Fix a nasty playlist crash
parent 1157ad6b
...@@ -32,7 +32,8 @@ TOMOC = main_interface \ ...@@ -32,7 +32,8 @@ TOMOC = main_interface \
components/video_widget \ components/video_widget \
components/playlist/panels \ components/playlist/panels \
components/playlist/selector \ components/playlist/selector \
util/input_slider util/input_slider \
util/views
MOCCPP = $(TOMOC:%=%.moc.cpp) MOCCPP = $(TOMOC:%=%.moc.cpp)
nodist_SOURCES_qt4 = \ nodist_SOURCES_qt4 = \
...@@ -54,6 +55,7 @@ nodist_SOURCES_qt4 = \ ...@@ -54,6 +55,7 @@ nodist_SOURCES_qt4 = \
components/playlist/panels.moc.cpp \ components/playlist/panels.moc.cpp \
components/playlist/selector.moc.cpp \ components/playlist/selector.moc.cpp \
util/input_slider.moc.cpp \ util/input_slider.moc.cpp \
util/views.moc.cpp \
resources.cpp resources.cpp
if ENABLE_QT4 if ENABLE_QT4
...@@ -119,6 +121,7 @@ EXTRA_DIST += \ ...@@ -119,6 +121,7 @@ EXTRA_DIST += \
components/playlist/selector.hpp \ components/playlist/selector.hpp \
util/input_slider.hpp \ util/input_slider.hpp \
util/directslider.hpp \ util/directslider.hpp \
util/views.hpp \
util/qvlcframe.hpp \ util/qvlcframe.hpp \
ui/input_stats.ui \ ui/input_stats.ui \
ui/file_open.ui \ ui/file_open.ui \
......
...@@ -33,9 +33,6 @@ class QTreeView; ...@@ -33,9 +33,6 @@ class QTreeView;
class PLModel; class PLModel;
class QPushButton; class QPushButton;
class QKeyEvent; class QKeyEvent;
/**
* \todo Share a single model between views using a filterproxy
*/
class PLPanel: public QWidget class PLPanel: public QWidget
{ {
...@@ -73,6 +70,7 @@ private slots: ...@@ -73,6 +70,7 @@ private slots:
void handleExpansion( const QModelIndex& ); void handleExpansion( const QModelIndex& );
void toggleRandom(); void toggleRandom();
void toggleRepeat(); void toggleRepeat();
void doPopup( QModelIndex index, QPoint point );
}; };
#endif #endif
...@@ -31,7 +31,6 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf, ...@@ -31,7 +31,6 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf,
playlist_t *p_playlist ) : QWidget( p ), p_intf(_p_intf) playlist_t *p_playlist ) : QWidget( p ), p_intf(_p_intf)
{ {
model = new PLModel( THEPL, THEPL->p_root_category, 1, this ); model = new PLModel( THEPL, THEPL->p_root_category, 1, this );
model->Rebuild();
view = new QTreeView( 0 ); view = new QTreeView( 0 );
view->setIndentation( 0 ); view->setIndentation( 0 );
view->header()->hide(); view->header()->hide();
......
...@@ -33,13 +33,15 @@ ...@@ -33,13 +33,15 @@
#include <assert.h> #include <assert.h>
#include <QModelIndexList> #include <QModelIndexList>
#include "util/views.hpp"
StandardPLPanel::StandardPLPanel( QWidget *_parent, intf_thread_t *_p_intf, StandardPLPanel::StandardPLPanel( QWidget *_parent, intf_thread_t *_p_intf,
playlist_t *p_playlist, playlist_t *p_playlist,
playlist_item_t *p_root ): playlist_item_t *p_root ):
PLPanel( _parent, _p_intf ) PLPanel( _parent, _p_intf )
{ {
model = new PLModel( p_playlist, p_root, -1, this ); model = new PLModel( p_playlist, p_root, -1, this );
view = new QTreeView( 0 ); view = new QVLCTreeView( 0 );
view->setModel(model); view->setModel(model);
view->header()->resizeSection( 0, 300 ); view->header()->resizeSection( 0, 300 );
view->setSelectionMode( QAbstractItemView::ExtendedSelection ); view->setSelectionMode( QAbstractItemView::ExtendedSelection );
...@@ -47,12 +49,13 @@ StandardPLPanel::StandardPLPanel( QWidget *_parent, intf_thread_t *_p_intf, ...@@ -47,12 +49,13 @@ StandardPLPanel::StandardPLPanel( QWidget *_parent, intf_thread_t *_p_intf,
connect( view, SIGNAL( activated( const QModelIndex& ) ), model, connect( view, SIGNAL( activated( const QModelIndex& ) ), model,
SLOT( activateItem( const QModelIndex& ) ) ); SLOT( activateItem( const QModelIndex& ) ) );
connect( view, SIGNAL( rightClicked( QModelIndex , QPoint ) ),
this, SLOT( doPopup( QModelIndex, QPoint ) ) );
connect( model, connect( model,
SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
this, SLOT( handleExpansion( const QModelIndex& ) ) ); this, SLOT( handleExpansion( const QModelIndex& ) ) );
model->Rebuild();
QVBoxLayout *layout = new QVBoxLayout(); QVBoxLayout *layout = new QVBoxLayout();
layout->setSpacing( 0 ); layout->setMargin( 0 ); layout->setSpacing( 0 ); layout->setMargin( 0 );
...@@ -117,12 +120,19 @@ void StandardPLPanel::handleExpansion( const QModelIndex &index ) ...@@ -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 ) void StandardPLPanel::setRoot( int i_root_id )
{ {
playlist_item_t *p_item = playlist_ItemGetById( THEPL, i_root_id ); playlist_item_t *p_item = playlist_ItemGetById( THEPL, i_root_id );
assert( p_item ); assert( p_item );
model->rebuildRoot( p_item ); model->rebuild( p_item );
model->Rebuild();
} }
void StandardPLPanel::keyPressEvent( QKeyEvent *e ) void StandardPLPanel::keyPressEvent( QKeyEvent *e )
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <QApplication> #include <QApplication>
#include "playlist_model.hpp" #include "playlist_model.hpp"
#include <assert.h> #include <assert.h>
#include <QMenu>
#include "pixmaps/type_unknown.xpm" #include "pixmaps/type_unknown.xpm"
#include "pixmaps/type_afile.xpm" #include "pixmaps/type_afile.xpm"
...@@ -141,6 +142,7 @@ PLModel::PLModel( playlist_t *_p_playlist, ...@@ -141,6 +142,7 @@ PLModel::PLModel( playlist_t *_p_playlist,
b_need_update = false; b_need_update = false;
i_cached_id = -1; i_cached_id = -1;
i_cached_input_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 ) ); #define ADD_ICON(type, x) icons[ITEM_TYPE_##type] = QIcon( QPixmap( type_##x##_xpm ) );
ADD_ICON( UNKNOWN , unknown ); ADD_ICON( UNKNOWN , unknown );
...@@ -155,18 +157,10 @@ PLModel::PLModel( playlist_t *_p_playlist, ...@@ -155,18 +157,10 @@ PLModel::PLModel( playlist_t *_p_playlist,
ADD_ICON( NODE, node ); ADD_ICON( NODE, node );
rootItem = NULL; rootItem = NULL;
rebuildRoot( p_root ); rebuild( p_root );
addCallbacks(); 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() PLModel::~PLModel()
{ {
...@@ -202,6 +196,13 @@ void PLModel::activateItem( const QModelIndex &index ) ...@@ -202,6 +196,13 @@ void PLModel::activateItem( const QModelIndex &index )
assert( item ); assert( item );
PL_LOCK; PL_LOCK;
playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id ); 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; playlist_item_t *p_parent = p_item;
while( p_parent ) while( p_parent )
{ {
...@@ -209,10 +210,7 @@ void PLModel::activateItem( const QModelIndex &index ) ...@@ -209,10 +210,7 @@ void PLModel::activateItem( const QModelIndex &index )
p_parent = p_parent->p_parent; p_parent = p_parent->p_parent;
} }
if( p_parent ) if( p_parent )
{
playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_parent, p_item ); playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, p_parent, p_item );
}
PL_UNLOCK;
} }
/****************** Base model mandatory implementations *****************/ /****************** Base model mandatory implementations *****************/
...@@ -296,10 +294,11 @@ QModelIndex PLModel::parent(const QModelIndex &index) const ...@@ -296,10 +294,11 @@ QModelIndex PLModel::parent(const QModelIndex &index) const
if( !index.isValid() ) return QModelIndex(); if( !index.isValid() ) return QModelIndex();
PLItem *childItem = static_cast<PLItem*>(index.internalPointer()); PLItem *childItem = static_cast<PLItem*>(index.internalPointer());
if( !childItem ) { msg_Err( p_playlist, "NULL CHILD \n" ); return QModelIndex(); }
PLItem *parentItem = childItem->parent(); PLItem *parentItem = childItem->parent();
if( !parentItem || parentItem == rootItem ) return QModelIndex();
if (parentItem == rootItem) return QModelIndex(); QModelIndex ind = createIndex(parentItem->row(), 0, parentItem);
return createIndex(parentItem->row(), 0, parentItem); return ind;
} }
int PLModel::columnCount( const QModelIndex &i) const int PLModel::columnCount( const QModelIndex &i) const
...@@ -485,7 +484,13 @@ end: ...@@ -485,7 +484,13 @@ end:
return; return;
} }
void PLModel::Rebuild()
void PLModel::rebuild()
{
rebuild( NULL );
}
void PLModel::rebuild( playlist_item_t *p_root )
{ {
/* Remove callbacks before locking to avoid deadlocks */ /* Remove callbacks before locking to avoid deadlocks */
delCallbacks(); delCallbacks();
...@@ -494,17 +499,30 @@ void PLModel::Rebuild() ...@@ -494,17 +499,30 @@ void PLModel::Rebuild()
PL_LOCK; PL_LOCK;
/* Clear the tree */ /* Clear the tree */
if( rootItem )
{
PLItem *deleted;
beginRemoveRows( index( rootItem, 0 ), 0,
rootItem->children.size() -1 );
qDeleteAll( rootItem->children ); 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 */ /* Recreate from root */
UpdateNodeChildren( rootItem ); UpdateNodeChildren( rootItem );
if( p_playlist->status.p_item ) if( p_playlist->status.p_item )
{ {
fprintf( stderr, "Playlist is playing" );
PLItem *currentItem = FindByInput( rootItem, PLItem *currentItem = FindByInput( rootItem,
p_playlist->status.p_item->p_input->i_id ); p_playlist->status.p_item->p_input->i_id );
if( currentItem ) if( currentItem )
{ {
fprintf( stderr, "Updating item\n" );
UpdateTreeItem( p_playlist->status.p_item, currentItem, UpdateTreeItem( p_playlist->status.p_item, currentItem,
true, false ); true, false );
} }
...@@ -610,6 +628,49 @@ void PLModel::doDeleteItem( PLItem *item, QModelIndexList *fullList ) ...@@ -610,6 +628,49 @@ void PLModel::doDeleteItem( PLItem *item, QModelIndexList *fullList )
PL_UNLOCK; 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 * Playlist callbacks
**********************************************************************/ **********************************************************************/
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#ifndef _PLAYLIST_MODEL_H_ #ifndef _PLAYLIST_MODEL_H_
#define _PLAYLIST_MODEL_H_ #define _PLAYLIST_MODEL_H_
#include <QModelIndex>
#include <QObject> #include <QObject>
#include <QEvent> #include <QEvent>
#include <vlc/vlc.h> #include <vlc/vlc.h>
...@@ -85,7 +86,6 @@ public: ...@@ -85,7 +86,6 @@ public:
}; };
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant> #include <QVariant>
class PLModel : public QAbstractItemModel class PLModel : public QAbstractItemModel
...@@ -96,19 +96,15 @@ public: ...@@ -96,19 +96,15 @@ public:
PLModel( playlist_t *, playlist_item_t *, int, QObject *parent = 0); PLModel( playlist_t *, playlist_item_t *, int, QObject *parent = 0);
~PLModel(); ~PLModel();
void customEvent( QEvent * ); /* All types of lookups / QModel stuff */
/* QModel stuff */
QVariant data( const QModelIndex &index, int role) const; QVariant data( const QModelIndex &index, int role) const;
Qt::ItemFlags flags( const QModelIndex &index) const; Qt::ItemFlags flags( const QModelIndex &index) const;
QVariant headerData( int section, Qt::Orientation orientation, QVariant headerData( int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const; int role = Qt::DisplayRole) const;
QModelIndex index( int r, int c, const QModelIndex &parent ) const; QModelIndex index( int r, int c, const QModelIndex &parent ) const;
QModelIndex index( PLItem *, int c ) const; QModelIndex index( PLItem *, int c ) const;
int itemId( const QModelIndex &index ) const; int itemId( const QModelIndex &index ) const;
bool isCurrent( const QModelIndex &index ); bool isCurrent( const QModelIndex &index );
QModelIndex parent( const QModelIndex &index) const; QModelIndex parent( const QModelIndex &index) const;
int childrenCount( const QModelIndex &parent = QModelIndex() ) const; int childrenCount( const QModelIndex &parent = QModelIndex() ) const;
int rowCount( const QModelIndex &parent = QModelIndex() ) const; int rowCount( const QModelIndex &parent = QModelIndex() ) const;
...@@ -116,14 +112,17 @@ public: ...@@ -116,14 +112,17 @@ public:
bool b_need_update; bool b_need_update;
int i_items_to_append; int i_items_to_append;
void Rebuild(); void rebuild(); void rebuild( playlist_item_t *);
void rebuildRoot( playlist_item_t * );
bool hasRandom(); bool hasLoop(); bool hasRepeat(); bool hasRandom(); bool hasLoop(); bool hasRepeat();
/* Actions made by the views */
void popup( QModelIndex & index, QPoint &point, QModelIndexList list );
void doDelete( QModelIndexList selected ); void doDelete( QModelIndexList selected );
private: private:
void addCallbacks(); void addCallbacks();
void delCallbacks(); void delCallbacks();
void customEvent( QEvent * );
PLItem *rootItem; PLItem *rootItem;
playlist_t *p_playlist; playlist_t *p_playlist;
...@@ -145,6 +144,10 @@ private: ...@@ -145,6 +144,10 @@ private:
void recurseDelete( QList<PLItem*> children, QModelIndexList *fullList); void recurseDelete( QList<PLItem*> children, QModelIndexList *fullList);
void doDeleteItem( PLItem *item, QModelIndexList *fullList ); void doDeleteItem( PLItem *item, QModelIndexList *fullList );
/* Popup */
int i_popup_item, i_popup_parent;
QModelIndexList current_selection;
/* Lookups */ /* Lookups */
PLItem *FindById( PLItem *, int ); PLItem *FindById( PLItem *, int );
PLItem *FindByInput( PLItem *, int ); PLItem *FindByInput( PLItem *, int );
...@@ -155,9 +158,13 @@ private: ...@@ -155,9 +158,13 @@ private:
int i_cached_input_id; int i_cached_input_id;
public slots: public slots:
void activateItem( const QModelIndex &index ); void activateItem( const QModelIndex &index );
void activateItem( playlist_item_t *p_item );
void setRandom( bool ); void setRandom( bool );
void setLoop( bool ); void setLoop( bool );
void setRepeat( bool ); void setRepeat( bool );
private slots:
void popupPlay();
void popupDel();
friend class PLItem; friend class PLItem;
}; };
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
class DirectSlider : public QSlider class DirectSlider : public QSlider
{ {
public: public:
DirectSlider( QWidget *_parent ) : QSlider( _parent ) {}; DirectSlider( QWidget *_parent ) : QSlider( _parent ) {};
DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent ) DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent )
{}; {};
virtual ~DirectSlider() {}; virtual ~DirectSlider() {};
......
/*****************************************************************************
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment