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 \
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 \
......
......@@ -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
......@@ -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();
......
......@@ -33,13 +33,15 @@
#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 )
......
......@@ -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
**********************************************************************/
......
......@@ -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;
};
......
......@@ -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);
......
/*****************************************************************************
* 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