X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Fplaylist_model.cpp;h=4abe981d7f09424520775a0ebd29269ed5a0290b;hb=96a9eea8c77b0325391d50b002b0e068ac115a0c;hp=e87772d4ebeb8204a836bb2357bf22978769b172;hpb=f2627995b642c9130901a87d8b98e1141b2aefce;p=vlc diff --git a/modules/gui/qt4/playlist_model.cpp b/modules/gui/qt4/playlist_model.cpp index e87772d4eb..4abe981d7f 100644 --- a/modules/gui/qt4/playlist_model.cpp +++ b/modules/gui/qt4/playlist_model.cpp @@ -1,8 +1,8 @@ /***************************************************************************** - * input_manager.cpp : Manage an input and interact with its GUI elements + * playlist_model.cpp : Manage playlist model **************************************************************************** - * Copyright (C) 2000-2005 the VideoLAN team - * $Id: wxwidgets.cpp 15731 2006-05-25 14:43:53Z zorglub $ + * Copyright (C) 2006 the VideoLAN team + * $Id$ * * Authors: Clément Stenac * @@ -21,10 +21,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#include "pixmaps/codec.xpm" +#include +#include "qt4.hpp" #include #include "playlist_model.hpp" #include +#include "pixmaps/type_unknown.xpm" +#include "pixmaps/type_afile.xpm" +#include "pixmaps/type_vfile.xpm" +#include "pixmaps/type_net.xpm" +#include "pixmaps/type_card.xpm" +#include "pixmaps/type_disc.xpm" +#include "pixmaps/type_cdda.xpm" +#include "pixmaps/type_directory.xpm" +#include "pixmaps/type_playlist.xpm" +#include "pixmaps/type_node.xpm" + +QIcon PLModel::icons[ITEM_TYPE_NUMBER]; static int PlaylistChanged( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); @@ -36,25 +51,36 @@ static int ItemAppended( vlc_object_t *p_this, const char *psz_variable, vlc_value_t oval, vlc_value_t nval, void *param ); static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable, vlc_value_t oval, vlc_value_t nval, void *param ); - /************************************************************************* * Playlist item implementation *************************************************************************/ -PLItem::PLItem( int _i_id, int _i_input_id, PLItem *parent, PLModel *m) +/** + * Column strings + * Title + * Artist + * Duration + */ + +void PLItem::init( int _i_id, int _i_input_id, PLItem *parent, PLModel *m) { parentItem = parent; i_id = _i_id; i_input_id = _i_input_id; model = m; + strings.append( "" ); + strings.append( "" ); + strings.append( "" ); +} + +PLItem::PLItem( int _i_id, int _i_input_id, PLItem *parent, PLModel *m) +{ + init( _i_id, _i_input_id, parent, m ); } PLItem::PLItem( playlist_item_t * p_item, PLItem *parent, PLModel *m ) { - i_id = p_item->i_id; - i_input_id = p_item->p_input->i_id; - parentItem = parent; - model = m; + init( p_item->i_id, p_item->p_input->i_id, parent, m ); } PLItem::~PLItem() @@ -79,22 +105,57 @@ int PLItem::row() const return 0; } +void PLItem::update( playlist_item_t *p_item ) +{ + assert( p_item->p_input->i_id == i_input_id ); + strings[0] = QString::fromUtf8( p_item->p_input->psz_name ); + if( p_item->p_input->p_meta ) + { + strings[1] = QString::fromUtf8( p_item->p_input->p_meta->psz_artist ); + } + type = p_item->p_input->i_type; +} /************************************************************************* * Playlist model implementation *************************************************************************/ -PLModel::PLModel( playlist_item_t * p_root, int i_depth, QObject *parent) +PLModel::PLModel( playlist_t *_p_playlist, + playlist_item_t * p_root, int _i_depth, QObject *parent) : QAbstractItemModel(parent) { - rootItem = new PLItem( p_root, NULL, this ); - + i_depth = _i_depth; + assert( i_depth == 1 || i_depth == -1 ); + p_playlist= _p_playlist; i_items_to_append = 0; b_need_update = false; i_cached_id = -1; i_cached_input_id = -1; +#define ADD_ICON(type, x) icons[ITEM_TYPE_##type] = QIcon( QPixmap( type_##x##_xpm ) ); + ADD_ICON( UNKNOWN , unknown ); + ADD_ICON( AFILE,afile ); + ADD_ICON( VFILE, vfile ); + ADD_ICON( DIRECTORY, directory ); + ADD_ICON( DISC, disc ); + ADD_ICON( CDDA, cdda ); + ADD_ICON( CARD, card ); + ADD_ICON( NET, net ); + ADD_ICON( PLAYLIST, playlist ); + ADD_ICON( NODE, node ); + + rootItem = NULL; + rebuildRoot( 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() @@ -124,24 +185,52 @@ void PLModel::delCallbacks() var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this ); } -/****************** Base model mandatory implementations *****************/ +void PLModel::activateItem( const QModelIndex &index ) +{ + assert( index.isValid() ); + PLItem *item = static_cast(index.internalPointer()); + assert( item ); + PL_LOCK; + playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id ); + playlist_item_t *p_parent = p_item; + while( p_parent ) + { + if( p_parent->i_id == rootItem->i_id ) break; + 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 *****************/ QVariant PLModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) - return QVariant(); - if (role != Qt::DisplayRole) - return QVariant(); - + assert( index.isValid() ); PLItem *item = static_cast(index.internalPointer()); - return QVariant( item->columnString( index.column() ) ); + if( role == Qt::DisplayRole ) + { + return QVariant( item->columnString( index.column() ) ); + } + else if( role == Qt::DecorationRole && index.column() == 0 ) + { + if( item->type >= 0 ) + return QVariant( PLModel::icons[item->type] ); + } + return QVariant(); } -Qt::ItemFlags PLModel::flags(const QModelIndex &index) const +int PLModel::itemId( const QModelIndex &index ) const { - if (!index.isValid()) - return Qt::ItemIsEnabled; + assert( index.isValid() ); + return static_cast(index.internalPointer())->i_id; +} +Qt::ItemFlags PLModel::flags(const QModelIndex &index) const +{ + if( !index.isValid() ) return Qt::ItemIsEnabled; return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } @@ -170,7 +259,7 @@ QModelIndex PLModel::index(int row, int column, const QModelIndex &parent) } /* Return the index of a given item */ -QModelIndex PLModel::index( PLItem *item, int column ) const +QModelIndex PLModel::index( PLItem *item, int column ) const { if( !item ) return QModelIndex(); const PLItem *parent = item->parent(); @@ -181,21 +270,20 @@ QModelIndex PLModel::index( PLItem *item, int column ) const QModelIndex PLModel::parent(const QModelIndex &index) const { - if (!index.isValid()) - return QModelIndex(); + if (!index.isValid()) return QModelIndex(); PLItem *childItem = static_cast(index.internalPointer()); PLItem *parentItem = childItem->parent(); - if (parentItem == rootItem) - return QModelIndex(); + if (parentItem == rootItem) return QModelIndex(); return createIndex(parentItem->row(), 0, parentItem); } -int PLModel::columnCount( const QModelIndex &i) const +int PLModel::columnCount( const QModelIndex &i) const { - return 1; + if( i_depth == 1 ) return 1; + return 2; } int PLModel::childrenCount(const QModelIndex &parent) const @@ -232,9 +320,11 @@ PLItem *PLModel::FindByInput( PLItem *root, int i_id ) PLItem * PLModel::FindInner( PLItem *root, int i_id, bool b_input ) { - if( ( !b_input && i_cached_id == i_id) || + if( ( !b_input && i_cached_id == i_id) || ( b_input && i_cached_input_id ==i_id ) ) + { return b_input ? p_cached_item_bi : p_cached_item; + } if( !b_input && root->i_id == i_id ) { @@ -258,11 +348,12 @@ PLItem * PLModel::FindInner( PLItem *root, int i_id, bool b_input ) else if( b_input && (*it)->i_input_id == i_id ) { ICACHE( i_id, (*it) ); + return p_cached_item_bi; } if( (*it)->children.size() ) { PLItem *childFound = FindInner( (*it), i_id, b_input ); - if( childFound ) + if( childFound ) { if( b_input ) { @@ -273,8 +364,9 @@ PLItem * PLModel::FindInner( PLItem *root, int i_id, bool b_input ) CACHE( i_id, childFound ); } return childFound; - } + } } + it++; } return NULL; } @@ -285,11 +377,16 @@ PLItem * PLModel::FindInner( PLItem *root, int i_id, bool b_input ) /************************* Updates handling *****************************/ void PLModel::customEvent( QEvent *event ) { - PLEvent *ple = dynamic_cast(event); + int type = event->type(); + if( type != ItemUpdate_Type && type != ItemAppend_Type && + type != ItemDelete_Type ) + return; + + PLEvent *ple = static_cast(event); - if( event->type() == ItemUpdate_Type ) + if( type == ItemUpdate_Type ) ProcessInputItemUpdate( ple->i_id ); - else if( event->type() == ItemAppend_Type ) + else if( type == ItemAppend_Type ) ProcessItemAppend( ple->p_add ); else ProcessItemRemoval( ple->i_id ); @@ -298,13 +395,15 @@ void PLModel::customEvent( QEvent *event ) /**** Events processing ****/ void PLModel::ProcessInputItemUpdate( int i_input_id ) { - assert( i_input_id >= 0 ); - UpdateTreeItem( FindByInput( rootItem, i_input_id ), true ); + if( i_input_id <= 0 ) return; + PLItem *item = FindByInput( rootItem, i_input_id ); + if( item ) + UpdateTreeItem( item, true ); } void PLModel::ProcessItemRemoval( int i_id ) { - assert( i_id >= 0 ); + if( i_id <= 0 ) return; if( i_id == i_cached_id ) i_cached_id = -1; i_cached_input_id = -1; @@ -314,6 +413,7 @@ void PLModel::ProcessItemRemoval( int i_id ) void PLModel::ProcessItemAppend( playlist_add_t *p_add ) { playlist_item_t *p_item = NULL; + PLItem *newItem = NULL; i_items_to_append--; if( b_need_update ) return; @@ -322,9 +422,13 @@ void PLModel::ProcessItemAppend( playlist_add_t *p_add ) p_item = playlist_ItemGetById( p_playlist, p_add->i_item ); if( !p_item || p_item->i_flags & PLAYLIST_DBL_FLAG ) goto end; + if( i_depth == 1 && p_item->p_parent && + p_item->p_parent->i_id != rootItem->i_id ) + goto end; - nodeItem->appendChild( new PLItem( p_item, nodeItem, this ) ); - + newItem = new PLItem( p_item, nodeItem, this ); + nodeItem->appendChild( newItem ); + UpdateTreeItem( p_item, newItem, true ); end: return; } @@ -363,28 +467,32 @@ void PLModel::UpdateNodeChildren( playlist_item_t *p_node, PLItem *root ) { PLItem *newItem = new PLItem( p_node->pp_children[i], root, this ); root->appendChild( newItem, false ); - UpdateTreeItem( newItem, false ); - if( p_node->pp_children[i]->i_children != -1 ) + UpdateTreeItem( newItem, false, true ); + if( i_depth != 1 && p_node->pp_children[i]->i_children != -1 ) UpdateNodeChildren( p_node->pp_children[i], newItem ); } } -void PLModel::UpdateTreeItem( PLItem *item, bool signal ) +void PLModel::UpdateTreeItem( PLItem *item, bool signal, bool force ) { - playlist_item_t *p_item = playlist_ItemGetById( p_playlist, rootItem->i_id ); - UpdateTreeItem( p_item, item, signal ); + playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id ); + UpdateTreeItem( p_item, item, signal, force ); } -void PLModel::UpdateTreeItem( playlist_item_t *p_item, PLItem *item, bool signal ) +void PLModel::UpdateTreeItem( playlist_item_t *p_item, PLItem *item, + bool signal, bool force ) { - /// \todo + if( !force && i_depth == 1 && p_item->p_parent && + p_item->p_parent->i_id != rootItem->i_id ) + return; + item->update( p_item ); if( signal ) - { // emit + { /// \todo emit } } - + /********************************************************************** - * Playlist callbacks + * Playlist callbacks **********************************************************************/ static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, vlc_value_t oval, vlc_value_t nval, void *param ) @@ -409,7 +517,7 @@ static int ItemChanged( vlc_object_t *p_this, const char *psz_variable, vlc_value_t oval, vlc_value_t nval, void *param ) { PLModel *p_model = (PLModel *) param; - PLEvent *event = new PLEvent( ItemUpdate_Type, nval.i_int ); + PLEvent *event = new PLEvent( ItemUpdate_Type, nval.i_int ); QApplication::postEvent( p_model, static_cast(event) ); return VLC_SUCCESS; }