Commit ce837438 authored by Francois Cartegnie's avatar Francois Cartegnie

Qt: Rework Models.

- Separate common methods into interface, allowing multiple
inheritance architecture (to use any implemented AbstractModel)
- Code factorization between PL/ML models (and PL/ML Items)
- Use proxy model for views and redirection to the PL/ML models.
Fixes filtering and also really make use of the current model (only the
PL Model was really used before, models were half switched).
- stop storing/serializing selection indexes
- ML Missing locks and bug fixes
- Move ML callback into event loop
- ML Items leaks fixes
- Code factorization
- Dead code removal
parent 80e95174
...@@ -91,11 +91,9 @@ static int compareMeta( ml_media_t *a, ml_media_t *b, ml_select_e meta ) ...@@ -91,11 +91,9 @@ static int compareMeta( ml_media_t *a, ml_media_t *b, ml_select_e meta )
} }
MLItem::MLItem( const MLModel *p_model, MLItem::MLItem( intf_thread_t* _p_intf,
intf_thread_t* _p_intf,
ml_media_t *p_media, ml_media_t *p_media,
MLItem *p_parent ) MLItem *p_parent )
: p_intf( _p_intf ), model( p_model )
{ {
parentItem = p_parent; parentItem = p_parent;
if( p_media ) if( p_media )
...@@ -119,18 +117,9 @@ AbstractPLItem* MLItem::child( int row ) const ...@@ -119,18 +117,9 @@ AbstractPLItem* MLItem::child( int row ) const
else return children.at( row ); else return children.at( row );
} }
void MLItem::delChild( int row )
{
if( !childCount() ) return; // assert ?
AbstractPLItem *item =
children.takeAt( ( row!=-1 ) ? row : ( children.count()-1 ) );
assert( item );
delete item;
}
input_item_t* MLItem::inputItem() input_item_t* MLItem::inputItem()
{ {
return ml_CreateInputItem( p_ml, id() ); return ml_CreateInputItem( p_ml, id( MLMEDIA_ID ) );
} }
/** /**
...@@ -139,13 +128,12 @@ input_item_t* MLItem::inputItem() ...@@ -139,13 +128,12 @@ input_item_t* MLItem::inputItem()
* @return The QVariant may be formed of a int, QString * @return The QVariant may be formed of a int, QString
* Use toString() to print it on the screen, except for pixmaps * Use toString() to print it on the screen, except for pixmaps
*/ */
QVariant MLItem::data( int column ) const QVariant MLItem::data( ml_select_e columntype ) const
{ {
ml_select_e type = model->columnType( column );
ml_person_t *p_people = NULL, *p_person = NULL; ml_person_t *p_people = NULL, *p_person = NULL;
QString qsz_return; QString qsz_return;
#define sreturn(a) if(media->a) return qfu(media->a); break #define sreturn(a) if(media->a) return qfu(media->a); break
switch( type ) switch( columntype )
{ {
case ML_ALBUM: sreturn( psz_album ); case ML_ALBUM: sreturn( psz_album );
case ML_ALBUM_ID: return media->i_album_id; case ML_ALBUM_ID: return media->i_album_id;
...@@ -166,7 +154,10 @@ QVariant MLItem::data( int column ) const ...@@ -166,7 +154,10 @@ QVariant MLItem::data( int column ) const
break; break;
case ML_COVER: sreturn( psz_cover ); case ML_COVER: sreturn( psz_cover );
case ML_DURATION: case ML_DURATION:
return QTime().addSecs( media->i_duration/1000000 ).toString( "HH:mm:ss" ); if ( media->i_duration )
return QTime().addSecs( media->i_duration/1000000 ).toString( "HH:mm:ss" );
else
return QString();
case ML_EXTRA: sreturn( psz_extra ); case ML_EXTRA: sreturn( psz_extra );
case ML_GENRE: sreturn( psz_genre ); case ML_GENRE: sreturn( psz_genre );
case ML_ID: return media->i_id; case ML_ID: return media->i_id;
...@@ -194,9 +185,11 @@ QVariant MLItem::data( int column ) const ...@@ -194,9 +185,11 @@ QVariant MLItem::data( int column ) const
return qsz_return; return qsz_return;
else else
{ {
vlc_mutex_lock( &media->lock ); QUrl uri = getURI();
QFileInfo p_file = QFileInfo( qfu( media->psz_uri ) ); if ( uri.scheme() != "file" )
vlc_mutex_unlock( &media->lock ); return QUrl::fromPercentEncoding( getURI().toString().toUtf8() );
QFileInfo p_file( uri.toLocalFile() );
return p_file.fileName().isEmpty() ? p_file.absoluteFilePath() return p_file.fileName().isEmpty() ? p_file.absoluteFilePath()
: p_file.fileName(); : p_file.fileName();
} }
...@@ -249,20 +242,21 @@ bool MLItem::setData( ml_select_e meta, const QVariant &data ) ...@@ -249,20 +242,21 @@ bool MLItem::setData( ml_select_e meta, const QVariant &data )
case ML_ARTIST: ml_DeletePersonTypeFromMedia( media, ML_PERSON_ARTIST ); case ML_ARTIST: ml_DeletePersonTypeFromMedia( media, ML_PERSON_ARTIST );
ml_CreateAppendPersonAdv( &media->p_people, ml_CreateAppendPersonAdv( &media->p_people,
ML_PERSON_ARTIST, (char*)qtu(data.toString()), 0 ); ML_PERSON_ARTIST, (char*)qtu(data.toString()), 0 );
return ml_UpdateSimple( p_ml, ML_MEDIA, NULL, id(), return ml_UpdateSimple( p_ml, ML_MEDIA, NULL, id( MLMEDIA_ID ),
ML_PEOPLE, ML_PERSON_ARTIST, qtu( data.toString() ) ) == VLC_SUCCESS; ML_PEOPLE, ML_PERSON_ARTIST, qtu( data.toString() ) ) == VLC_SUCCESS;
case ML_EXTRA: setmeta( psz_extra ); case ML_EXTRA: setmeta( psz_extra );
case ML_GENRE: setmeta( psz_genre ); case ML_GENRE: setmeta( psz_genre );
case ML_ORIGINAL_TITLE: setmeta( psz_orig_title ); case ML_ORIGINAL_TITLE: setmeta( psz_orig_title );
case ML_TITLE: setmeta( psz_title ); case ML_TITLE: setmeta( psz_title );
update: update:
return ml_UpdateSimple( p_ml, ML_MEDIA, NULL, id(), Q_ASSERT( qtu( data.toString() ) );
return ml_UpdateSimple( p_ml, ML_MEDIA, NULL, id( MLMEDIA_ID ),
meta, qtu( data.toString() ) ) == VLC_SUCCESS; meta, qtu( data.toString() ) ) == VLC_SUCCESS;
/* Modifiable integers */ /* Modifiable integers */
case ML_TRACK_NUMBER: case ML_TRACK_NUMBER:
case ML_YEAR: case ML_YEAR:
return ml_UpdateSimple( p_ml, ML_MEDIA, NULL, id(), return ml_UpdateSimple( p_ml, ML_MEDIA, NULL, id( MLMEDIA_ID ),
meta, data.toInt() ) == VLC_SUCCESS; meta, data.toInt() ) == VLC_SUCCESS;
// TODO case ML_VOTE: // TODO case ML_VOTE:
...@@ -274,9 +268,19 @@ update: ...@@ -274,9 +268,19 @@ update:
# undef setmeta # undef setmeta
} }
int MLItem::id() const int MLItem::id( int type )
{ {
return media->i_id; switch( type )
{
case INPUTITEM_ID:
return inputItem()->i_id;
case MLMEDIA_ID:
return media->i_id;
default:
case PLAYLIST_ID:
assert( NULL );
return -1;
}
} }
ml_media_t* MLItem::getMedia() const ml_media_t* MLItem::getMedia() const
...@@ -284,19 +288,28 @@ ml_media_t* MLItem::getMedia() const ...@@ -284,19 +288,28 @@ ml_media_t* MLItem::getMedia() const
return media; return media;
} }
QUrl MLItem::getUri() const QUrl MLItem::getURI() const
{ {
QString uri; QString uri;
vlc_mutex_lock( &media->lock ); vlc_mutex_lock( &media->lock );
uri = QString( media->psz_uri ); uri = qfu( media->psz_uri );
vlc_mutex_unlock( &media->lock ); vlc_mutex_unlock( &media->lock );
if ( uri.isEmpty() ) return QUrl(); // This should be rootItem if ( uri.isEmpty() ) return QUrl(); // This should be rootItem
QUrl url( uri ); QUrl url = QUrl::fromEncoded( uri.toUtf8(), QUrl::TolerantMode );
if ( url.scheme().isEmpty() ) url.setScheme( "file" ); if ( url.scheme().isEmpty() ) url.setScheme( "file" );
return url; return url;
} }
QString MLItem::getTitle() const
{
QString title;
vlc_mutex_lock( &media->lock );
title = QString( media->psz_title );
vlc_mutex_unlock( &media->lock );
return title;
}
bool MLItem::operator<( MLItem* item ) bool MLItem::operator<( MLItem* item )
{ {
int ret = compareMeta( getMedia(), item->getMedia(), ML_ALBUM ); int ret = compareMeta( getMedia(), item->getMedia(), ML_ALBUM );
......
...@@ -49,28 +49,26 @@ class MLItem : public AbstractPLItem ...@@ -49,28 +49,26 @@ class MLItem : public AbstractPLItem
friend class MLModel; friend class MLModel;
public: public:
MLItem( const MLModel *p_model, intf_thread_t *_p_intf, MLItem( intf_thread_t *_p_intf,
ml_media_t *p_media, MLItem *p_parent ); ml_media_t *p_media, MLItem *p_parent );
virtual ~MLItem(); virtual ~MLItem();
bool operator<( MLItem* item ); bool operator<( MLItem* item );
private: private:
/* AbstractPLItem */ /* AbstractPLItem */
int id() const; int id( int type );
input_item_t *inputItem(); input_item_t *inputItem();
AbstractPLItem* child( int row ) const; AbstractPLItem* child( int row ) const;
virtual QUrl getURI() const;
virtual QString getTitle() const;
/* Local */ /* Local */
void delChild( int row ); QVariant data( ml_select_e meta ) const;
QVariant data( int column ) const;
bool setData( ml_select_e meta, const QVariant &data ); bool setData( ml_select_e meta, const QVariant &data );
// Media structure connections // Media structure connections
ml_media_t* getMedia() const; ml_media_t* getMedia() const;
QUrl getUri() const;
ml_media_t* media; ml_media_t* media;
intf_thread_t* p_intf;
const MLModel *model;
media_library_t* p_ml; media_library_t* p_ml;
}; };
......
...@@ -41,8 +41,25 @@ ...@@ -41,8 +41,25 @@
#include "ml_item.hpp" #include "ml_item.hpp"
#include "qt4.hpp" #include "qt4.hpp"
#include <QMutex>
#include <QEvent>
class MLItem; class MLItem;
/** *************************************************************************
* \brief ML Events class because we don't want direct callbacks
****************************************************************************/
class MLEvent : public QEvent
{
public:
static const QEvent::Type MediaAdded_Type;
static const QEvent::Type MediaRemoved_Type;
static const QEvent::Type MediaUpdated_Type;
MLEvent( QEvent::Type type, media_library_t *_p_ml, int32_t _ml_media_id ) :
QEvent( type ), ml_media_id( _ml_media_id ), p_ml( _p_ml ) {};
int32_t ml_media_id;
media_library_t * p_ml; /* store instance */
};
/** ************************************************************************* /** *************************************************************************
* \brief Tree model for the result list * \brief Tree model for the result list
****************************************************************************/ ****************************************************************************/
...@@ -55,69 +72,57 @@ public: ...@@ -55,69 +72,57 @@ public:
MLModel( intf_thread_t *_p_intf, QObject *parent = NULL ); MLModel( intf_thread_t *_p_intf, QObject *parent = NULL );
virtual ~MLModel(); virtual ~MLModel();
virtual int itemId( const QModelIndex & ) const;
virtual input_item_t *getInputItem( const QModelIndex &index ) const;
QVariant data( const QModelIndex &idx, const int role = Qt::DisplayRole ) const; QVariant data( const QModelIndex &idx, const int role = Qt::DisplayRole ) const;
bool setData( const QModelIndex &idx, const QVariant &value, bool setData( const QModelIndex &idx, const QVariant &value,
int role = Qt::EditRole ); int role = Qt::EditRole );
ml_select_e columnType( int column ) const;
QModelIndex index( int row, int column, QModelIndex index( int row, int column,
const QModelIndex & parent = QModelIndex() ) const; const QModelIndex & parent = QModelIndex() ) const;
virtual QModelIndex currentIndex() const;
int rowCount( const QModelIndex & parent = QModelIndex() ) const; int rowCount( const QModelIndex & parent = QModelIndex() ) const;
QModelIndex parent( const QModelIndex& ) const; QModelIndex parent( const QModelIndex& ) const;
QVariant headerData( int, Qt::Orientation, int ) const;
Qt::ItemFlags flags( const QModelIndex& ) const; Qt::ItemFlags flags( const QModelIndex& ) const;
bool isEditable( const QModelIndex& ) const;
// Drag and drop: MIME data
QMimeData* mimeData( const QModelIndexList & indexes ) const; QMimeData* mimeData( const QModelIndexList & indexes ) const;
virtual bool removeRows( int row, int count, const QModelIndex & parent = QModelIndex() );
// Custom functions // Custom functions
int insertMedia( ml_media_t *p_media, int row = -1, bool isEditable( const QModelIndex& ) const;
bool bSignal = true ); ml_select_e columnType( int column ) const;
int appendMedia( ml_media_t *p_media ); virtual bool event( QEvent * e );
int insertMediaArray( vlc_array_t *p_media_array, int row = -1,
bool bSignal = true ); QModelIndex getIndexByMLID( int id ) const;
int insertResult( const ml_result_t *p_result, int row = -1, /* VLCModelSubInterface */
bool bSignal = true ); virtual void rebuild( playlist_item_t * p = NULL );
inline int appendResult( const ml_result_t *p_result ); virtual void doDelete( QModelIndexList selected );
int insertResultArray( vlc_array_t *p_result_array, int row = -1, virtual void createNode( QModelIndex, QString ) {};
bool bSignal = true );
virtual void doDelete( QModelIndexList list );
void remove( QModelIndex idx );
void clear();
void play( const QModelIndex &idx );
virtual QString getURI( const QModelIndex &index ) const;
virtual QModelIndex rootIndex() const; virtual QModelIndex rootIndex() const;
virtual void filter( const QString& search_text, const QModelIndex & root, bool b_recursive );
virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder );
virtual QModelIndex currentIndex() const;
virtual QModelIndex indexByPLID( const int i_plid, const int c ) const;
virtual QModelIndex indexByInputItemID( const int i_inputitem_id, const int c ) const;
virtual bool isTree() const; virtual bool isTree() const;
virtual bool canEdit() const; virtual bool canEdit() const;
virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const; virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const;
QModelIndex getIndexByMLID( int id ) const; virtual void action( QAction *action, const QModelIndexList &indexes );
public slots: /* VLCModelSubInterface virtual slots */
void activateItem( const QModelIndex &index ); virtual void activateItem( const QModelIndex &index );
virtual void actionSlot( QAction *action ); virtual void clearPlaylist();
protected: protected:
void remove( MLItem *item );
inline MLItem *getItem( QModelIndex index ) const /* VLCModel subclassing */
{ bool isParent( const QModelIndex &index, const QModelIndex &current) const;
if( index.isValid() ) bool isLeaf( const QModelIndex &index ) const;
return static_cast<MLItem*>( index.internalPointer() );
else return NULL;
}
private: private:
/* custom */
int insertMedia( ml_media_t *p_media, int row = -1 );
int insertResultArray( vlc_array_t *p_result_array, int row = -1 );
QList< MLItem* > items; QList< MLItem* > items;
media_library_t* p_ml; media_library_t* p_ml;
}; };
#endif #endif
......
...@@ -94,14 +94,19 @@ PlaylistWidget::PlaylistWidget( intf_thread_t *_p_i, QWidget *_par ) ...@@ -94,14 +94,19 @@ PlaylistWidget::PlaylistWidget( intf_thread_t *_p_i, QWidget *_par )
setMinimumWidth( 400 ); setMinimumWidth( 400 );
PLModel *model = PLModel::getPLModel( p_intf ); VLCProxyModel *model = new VLCProxyModel( this );
PLModel *plmodel = PLModel::getPLModel( p_intf );
model->setModel( VLCProxyModel::PL_MODEL, plmodel );
model->switchToModel( VLCProxyModel::PL_MODEL );
#ifdef MEDIA_LIBRARY #ifdef MEDIA_LIBRARY
MLModel *mlmodel = new MLModel( p_intf, this ); MLModel *mlmodel = new MLModel( p_intf, model );
mainView = new StandardPLPanel( this, p_intf, p_root, selector, model, mlmodel ); model->setModel( VLCProxyModel::SQLML_MODEL, mlmodel );
#else
mainView = new StandardPLPanel( this, p_intf, p_root, selector, model, NULL );
#endif #endif
mainView = new StandardPLPanel( this, p_intf, p_root, selector, model );
/* Location Bar */ /* Location Bar */
locationBar = new LocationBar( model ); locationBar = new LocationBar( model );
locationBar->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred ); locationBar->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
...@@ -228,20 +233,15 @@ void PlaylistWidget::forceShow() ...@@ -228,20 +233,15 @@ void PlaylistWidget::forceShow()
void PlaylistWidget::changeView( const QModelIndex& index ) void PlaylistWidget::changeView( const QModelIndex& index )
{ {
searchEdit->clear();
locationBar->setIndex( index ); locationBar->setIndex( index );
} }
void PlaylistWidget::clearPlaylist()
{
PLModel::getPLModel( p_intf )->clearPlaylist();
}
#include <QSignalMapper> #include <QSignalMapper>
#include <QMenu> #include <QMenu>
#include <QPainter> #include <QPainter>
LocationBar::LocationBar( PLModel *m ) LocationBar::LocationBar( VLCProxyModel *m )
{ {
model = m; setModel( m );
mapper = new QSignalMapper( this ); mapper = new QSignalMapper( this );
CONNECT( mapper, mapped( int ), this, invoke( int ) ); CONNECT( mapper, mapped( int ), this, invoke( int ) );
...@@ -272,7 +272,7 @@ void LocationBar::setIndex( const QModelIndex &index ) ...@@ -272,7 +272,7 @@ void LocationBar::setIndex( const QModelIndex &index )
actions.append( action ); actions.append( action );
CONNECT( btn, clicked(), action, trigger() ); CONNECT( btn, clicked(), action, trigger() );
mapper->setMapping( action, model->itemId( i ) ); mapper->setMapping( action, model->itemId( i, PLAYLIST_ID ) );
CONNECT( action, triggered(), mapper, map() ); CONNECT( action, triggered(), mapper, map() );
first = false; first = false;
...@@ -298,7 +298,7 @@ void LocationBar::setRootIndex() ...@@ -298,7 +298,7 @@ void LocationBar::setRootIndex()
void LocationBar::invoke( int i_id ) void LocationBar::invoke( int i_id )
{ {
QModelIndex index = model->index( i_id, 0 ); QModelIndex index = model->indexByPLID( i_id, 0 );
emit invoked ( index ); emit invoked ( index );
} }
......
...@@ -77,7 +77,6 @@ protected: ...@@ -77,7 +77,6 @@ protected:
virtual void closeEvent( QCloseEvent * ); virtual void closeEvent( QCloseEvent * );
private slots: private slots:
void changeView( const QModelIndex& index ); void changeView( const QModelIndex& index );
void clearPlaylist();
friend class PlaylistDialog; friend class PlaylistDialog;
}; };
...@@ -119,14 +118,16 @@ private: ...@@ -119,14 +118,16 @@ private:
bool b_arrow; bool b_arrow;
}; };
class PLModel; class VLCProxyModel;
class QHBoxLayout; class QHBoxLayout;
class LocationBar : public QWidget class LocationBar : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
LocationBar( PLModel * ); LocationBar( VLCProxyModel * );
void setIndex( const QModelIndex & ); void setIndex( const QModelIndex & );
void setModel( VLCProxyModel * _model ) { model = _model; };
virtual QSize sizeHint() const; virtual QSize sizeHint() const;
protected: protected:
virtual void resizeEvent ( QResizeEvent * event ); virtual void resizeEvent ( QResizeEvent * event );
...@@ -134,7 +135,7 @@ protected: ...@@ -134,7 +135,7 @@ protected:
private: private:
void layOut( const QSize& size ); void layOut( const QSize& size );
PLModel *model; VLCProxyModel *model;
QSignalMapper *mapper; QSignalMapper *mapper;
QWidgetList buttons; QWidgetList buttons;
QList<QAction*> actions; QList<QAction*> actions;
......
...@@ -41,6 +41,12 @@ void AbstractPLItem::clearChildren() ...@@ -41,6 +41,12 @@ void AbstractPLItem::clearChildren()
children.clear(); children.clear();
} }
void AbstractPLItem::removeChild( AbstractPLItem *item )
{
children.removeOne( item );
delete item;
}
/* /*
Playlist item is just a wrapper, an abstraction of the playlist_item Playlist item is just a wrapper, an abstraction of the playlist_item
in order to be managed by PLModel in order to be managed by PLModel
...@@ -51,8 +57,8 @@ void AbstractPLItem::clearChildren() ...@@ -51,8 +57,8 @@ void AbstractPLItem::clearChildren()
void PLItem::init( playlist_item_t *_playlist_item, PLItem *parent ) void PLItem::init( playlist_item_t *_playlist_item, PLItem *parent )
{ {
parentItem = parent; /* Can be NULL, but only for the rootItem */ parentItem = parent; /* Can be NULL, but only for the rootItem */
i_id = _playlist_item->i_id; /* Playlist item specific id */ i_playlist_id = _playlist_item->i_id; /* Playlist item specific id */
p_input = _playlist_item->p_input; p_input = _playlist_item->p_input;
vlc_gc_incref( p_input ); vlc_gc_incref( p_input );
} }
...@@ -77,10 +83,19 @@ PLItem::~PLItem() ...@@ -77,10 +83,19 @@ PLItem::~PLItem()
children.clear(); children.clear();
} }
void PLItem::removeChild( PLItem *item ) int PLItem::id( int type )
{ {
children.removeOne( item ); switch( type )
delete item; {
case INPUTITEM_ID:
return inputItem()->i_id;
case PLAYLIST_ID:
return i_playlist_id;
default:
case MLMEDIA_ID:
assert( NULL );
return -1;
}
} }
void PLItem::takeChildAt( int index ) void PLItem::takeChildAt( int index )
...@@ -98,7 +113,7 @@ int PLItem::row() ...@@ -98,7 +113,7 @@ int PLItem::row()
return 0; return 0;
} }
bool PLItem::operator< ( PLItem& other ) bool PLItem::operator< ( AbstractPLItem& other )
{ {
AbstractPLItem *item1 = this; AbstractPLItem *item1 = this;
while( item1->parentItem ) while( item1->parentItem )
...@@ -117,3 +132,26 @@ bool PLItem::operator< ( PLItem& other ) ...@@ -117,3 +132,26 @@ bool PLItem::operator< ( PLItem& other )
} }
return false; return false;
} }
QUrl PLItem::getURI() const
{
QString uri;
vlc_mutex_lock( &p_input->lock );
uri = QString( p_input->psz_uri );
vlc_mutex_unlock( &p_input->lock );
return QUrl( uri );
}
QString PLItem::getTitle() const
{
QString title;
char *fb_name = input_item_GetTitle( p_input );
if( EMPTY_STR( fb_name ) )
{
free( fb_name );
fb_name = input_item_GetName( p_input );
}
title = qfu(fb_name);
free(fb_name);
return title;
}
...@@ -29,11 +29,21 @@ ...@@ -29,11 +29,21 @@
#endif #endif
#include <QList> #include <QList>
#include <QString>
#include <QUrl>
enum
{
INPUTITEM_ID = 1,
PLAYLIST_ID,
MLMEDIA_ID
};
class AbstractPLItem class AbstractPLItem
{ {
friend class PLItem; /* super ugly glue stuff */ friend class PLItem; /* super ugly glue stuff */
friend class MLItem; friend class MLItem;
friend class VLCModel;
friend class PLModel; friend class PLModel;
friend class MLModel; friend class MLModel;
...@@ -41,7 +51,7 @@ public: ...@@ -41,7 +51,7 @@ public:
virtual ~AbstractPLItem() {} virtual ~AbstractPLItem() {}
protected: protected:
virtual int id() const = 0; virtual int id( int type ) = 0;
int childCount() const { return children.count(); } int childCount() const { return children.count(); }
int indexOf( AbstractPLItem *item ) const { return children.indexOf( item ); }; int indexOf( AbstractPLItem *item ) const { return children.indexOf( item ); };
int lastIndexOf( AbstractPLItem *item ) const { return children.lastIndexOf( item ); }; int lastIndexOf( AbstractPLItem *item ) const { return children.lastIndexOf( item ); };
...@@ -50,7 +60,10 @@ protected: ...@@ -50,7 +60,10 @@ protected:
void insertChild( AbstractPLItem *item, int pos = -1 ) { children.insert( pos, item ); } void insertChild( AbstractPLItem *item, int pos = -1 ) { children.insert( pos, item ); }
void appendChild( AbstractPLItem *item ) { insertChild( item, children.count() ); } ; void appendChild( AbstractPLItem *item ) { insertChild( item, children.count() ); } ;
virtual AbstractPLItem *child( int id ) const = 0; virtual AbstractPLItem *child( int id ) const = 0;
void removeChild( AbstractPLItem *item );
void clearChildren(); void clearChildren();
virtual QUrl getURI() const = 0;
virtual QString getTitle() const = 0;
QList<AbstractPLItem *> children; QList<AbstractPLItem *> children;
AbstractPLItem *parentItem; AbstractPLItem *parentItem;
...@@ -63,23 +76,24 @@ class PLItem : public AbstractPLItem ...@@ -63,23 +76,24 @@ class PLItem : public AbstractPLItem
public: public:
virtual ~PLItem(); virtual ~PLItem();
bool hasSameParent( PLItem *other ) { return parent() == other->parent(); } bool hasSameParent( PLItem *other ) { return parent() == other->parent(); }
bool operator< ( PLItem& ); bool operator< ( AbstractPLItem& );
private: private:
/* AbstractPLItem */ /* AbstractPLItem */
int id() const { return i_id; }; int id( int type );
input_item_t *inputItem() { return p_input; } input_item_t *inputItem() { return p_input; }
AbstractPLItem *child( int id ) const { return children.value( id ); }; AbstractPLItem *child( int id ) const { return children.value( id ); };
virtual QUrl getURI() const;
virtual QString getTitle() const;
/* Local */ /* Local */
PLItem( playlist_item_t *, PLItem *parent ); PLItem( playlist_item_t *, PLItem *parent );
int row(); int row();
void removeChild( PLItem * );
void takeChildAt( int ); void takeChildAt( int );
PLItem( playlist_item_t * ); PLItem( playlist_item_t * );
void init( playlist_item_t *, PLItem * ); void init( playlist_item_t *, PLItem * );
int i_id; int i_playlist_id;
input_item_t *p_input; input_item_t *p_input;
}; };
......
...@@ -39,15 +39,93 @@ ...@@ -39,15 +39,93 @@
#include <QSignalMapper> #include <QSignalMapper>
#include <QMimeData> #include <QMimeData>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QVariant> #include <QVariant>
#include <QModelIndex> #include <QModelIndex>
#include <QTimer> #include <QTimer>
#include <QMutex> #include <QMutex>
#include <QAction>
class PLItem; class PLItem;
class PLSelector; class PLSelector;
class PlMimeData; class PlMimeData;
class VLCProxyModel : public QSortFilterProxyModel, public VLCModelSubInterface
{
Q_OBJECT
public:
VLCProxyModel( QObject *parent = 0 );
inline VLCModel *model() const
{
return qobject_cast<VLCModel *>( sourceModel() );
}
enum models
{
PL_MODEL = 0,
SQLML_MODEL /* note: keep it last */
};
bool switchToModel( models type );
void setModel( models type, VLCModel *model )
{
sourcemodels[ type ] = model;
}
QModelIndexList mapListToSource( const QModelIndexList& list );
/* Different Models Handling */
/* VLCModelSubInterface Methods */
virtual void rebuild( playlist_item_t * p = NULL ) { model()->rebuild( p ); }
virtual void doDelete( QModelIndexList list ) { model()->doDelete( mapListToSource( list ) ); }
virtual void createNode( QModelIndex a, QString b ) { model()->createNode( mapToSource( a ), b ); }
virtual QModelIndex rootIndex() const { return mapFromSource( model()->rootIndex() ); }
virtual void filter( const QString& text, const QModelIndex & root, bool b_recursive )
{
model()->filter( text, mapToSource( root ), b_recursive );
}
virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder )
{
/* use native */
QSortFilterProxyModel::sort( column, order );
}
virtual QModelIndex currentIndex() const { return mapFromSource( model()->currentIndex() ); }
virtual QModelIndex indexByPLID( const int i_plid, const int c ) const { return mapFromSource( model()->indexByPLID( i_plid, c ) ); }
virtual QModelIndex indexByInputItemID( const int i_inputitem_id, const int c ) const { return mapFromSource( model()->indexByInputItemID( i_inputitem_id, c ) ); }
virtual int itemId( const QModelIndex &index, int type ) const { return model()->itemId( mapToSource( index ), type ); }
virtual bool isTree() const { return model()->isTree(); }
virtual bool canEdit() const { return model()->canEdit(); }
virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const { return model()->isCurrentItem( mapToSource( index ), where ); }
virtual QString getURI( const QModelIndex &index ) const { return model()->getURI( mapToSource( index ) ); }
virtual input_item_t *getInputItem( const QModelIndex &index ) const { return model()->getInputItem( mapToSource( index ) ); }
virtual QString getTitle( const QModelIndex &index ) const { return model()->getTitle( mapToSource( index ) ); }
virtual void action( QAction *action, const QModelIndexList &indexes )
{
model()->action( action, mapListToSource( indexes ) );
}
/* Indirect slots handlers */
virtual void activateItem( const QModelIndex &index ) { model()->activateItem( mapToSource( index ) ); }
virtual void ensureArtRequested( const QModelIndex &index ) { model()->ensureArtRequested( mapToSource( index ) ); }
virtual void clearPlaylist() { model()->clearPlaylist(); }
/* Local signals for index conversion */
public slots:
void currentIndexChanged_IndexConversion( const QModelIndex &index )
{
emit currentIndexChanged_Converted( mapFromSource( index ) );
}
signals:
void currentIndexChanged_Converted( const QModelIndex & );
private:
VLCModel * sourcemodels[SQLML_MODEL + 1];
};
class PLModel : public VLCModel class PLModel : public VLCModel
{ {
Q_OBJECT Q_OBJECT
...@@ -75,8 +153,6 @@ public: ...@@ -75,8 +153,6 @@ public:
/* Data structure */ /* Data structure */
virtual QVariant data( const QModelIndex &index, const int role ) const; virtual QVariant data( const QModelIndex &index, const int role ) const;
virtual QVariant headerData( int section, Qt::Orientation orientation,
int role = Qt::DisplayRole ) const;
virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const;
virtual Qt::ItemFlags flags( const QModelIndex &index ) const; virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
virtual QModelIndex index( const int r, const int c, const QModelIndex &parent ) const; virtual QModelIndex index( const int r, const int c, const QModelIndex &parent ) const;
...@@ -92,36 +168,31 @@ public: ...@@ -92,36 +168,31 @@ public:
/* Sort */ /* Sort */
virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder ); virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder );
/**** Custom ****/ /*** VLCModelSubInterface subclassing ***/
virtual void rebuild( playlist_item_t * p = NULL );
virtual void doDelete( QModelIndexList selected );
virtual void createNode( QModelIndex index, QString name );
/* Lookups */ /* Lookups */
QModelIndex index( const int i_id, const int c );
virtual QModelIndex rootIndex() const; virtual QModelIndex rootIndex() const;
virtual void filter( const QString& search_text, const QModelIndex & root, bool b_recursive );
virtual QModelIndex currentIndex() const;
virtual QModelIndex indexByPLID( const int i_plid, const int c ) const;
virtual QModelIndex indexByInputItemID( const int i_inputitem_id, const int c ) const;
virtual bool isTree() const; virtual bool isTree() const;
virtual bool canEdit() const; virtual bool canEdit() const;
virtual QModelIndex currentIndex() const;
int itemId( const QModelIndex &index ) const;
virtual input_item_t *getInputItem( const QModelIndex & ) const;
virtual QString getURI( const QModelIndex &index ) const;
QString getTitle( const QModelIndex &index ) const;
virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const; virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const;
virtual void action( QAction *action, const QModelIndexList &indexes );
/* */ /* VLCModelSubInterface indirect slots */
void search( const QString& search_text, const QModelIndex & root, bool b_recursive );
void rebuild( playlist_item_t * p = NULL );
virtual void doDelete( QModelIndexList selected );
virtual void createNode( QModelIndex index, QString name );
signals:
void currentIndexChanged( const QModelIndex& );
void rootIndexChanged();
public slots:
virtual void activateItem( const QModelIndex &index ); virtual void activateItem( const QModelIndex &index );
void clearPlaylist(); virtual void clearPlaylist();
void ensureArtRequested( const QModelIndex &index );
virtual void actionSlot( QAction *action ); protected:
/* VLCModel subclassing */
bool isParent( const QModelIndex &index, const QModelIndex &current) const;
bool isLeaf( const QModelIndex &index ) const;
PLItem *getItem( const QModelIndex & index ) const;
private: private:
/* General */ /* General */
...@@ -129,8 +200,6 @@ private: ...@@ -129,8 +200,6 @@ private:
playlist_t *p_playlist; playlist_t *p_playlist;
static QIcon icons[ITEM_TYPE_NUMBER];
/* single row linear inserts agregation */ /* single row linear inserts agregation */
void bufferedRowInsert( PLItem *item, PLItem *parent, int pos ); void bufferedRowInsert( PLItem *item, PLItem *parent, int pos );
bool isBufferedForInsert( PLItem *parent, int i_item ); bool isBufferedForInsert( PLItem *parent, int i_item );
...@@ -143,20 +212,11 @@ private: ...@@ -143,20 +212,11 @@ private:
/* Custom model private methods */ /* Custom model private methods */
/* Lookups */ /* Lookups */
PLItem *getItem( const QModelIndex & index ) const
{
if( index.isValid() )
return static_cast<PLItem*>( index.internalPointer() );
else return rootItem;
}
QModelIndex index( PLItem *, const int c ) const; QModelIndex index( PLItem *, const int c ) const;
bool isCurrent( const QModelIndex &index ) const;
bool isParent( const QModelIndex &index, const QModelIndex &current) const;
/* Shallow actions (do not affect core playlist) */ /* Shallow actions (do not affect core playlist) */
void updateTreeItem( PLItem * ); void updateTreeItem( PLItem * );
void removeItem ( PLItem * ); void removeItem ( PLItem * );
void removeItem( int );
void recurseDelete( QList<AbstractPLItem*> children, QModelIndexList *fullList ); void recurseDelete( QList<AbstractPLItem*> children, QModelIndexList *fullList );
void takeItem( PLItem * ); //will not delete item void takeItem( PLItem * ); //will not delete item
void insertChildren( PLItem *node, QList<PLItem*>& items, int i_pos ); void insertChildren( PLItem *node, QList<PLItem*>& items, int i_pos );
...@@ -172,14 +232,9 @@ private: ...@@ -172,14 +232,9 @@ private:
void sort( QModelIndex caller, QModelIndex rootIndex, const int column, Qt::SortOrder order ); void sort( QModelIndex caller, QModelIndex rootIndex, const int column, Qt::SortOrder order );
/* Lookups */ /* Lookups */
PLItem *findById( PLItem *, int ) const; PLItem *findByPLId( PLItem *, int i_plitemid ) const;
PLItem *findByInput( PLItem *, int ) const; PLItem *findByInputId( PLItem *, int i_input_itemid ) const;
PLItem *findInner(PLItem *, int , bool ) const; PLItem *findInner(PLItem *, int i_id, bool b_isinputid ) const;
PLItem *p_cached_item;
PLItem *p_cached_item_bi;
int i_cached_id;
int i_cached_input_id;
/* */ /* */
QString latestSearch; QString latestSearch;
...@@ -187,8 +242,8 @@ private: ...@@ -187,8 +242,8 @@ private:
private slots: private slots:
void processInputItemUpdate( input_item_t *); void processInputItemUpdate( input_item_t *);
void processInputItemUpdate( input_thread_t* p_input ); void processInputItemUpdate( input_thread_t* p_input );
void processItemRemoval( int i_id ); void processItemRemoval( int i_pl_itemid );
void processItemAppend( int item, int parent ); void processItemAppend( int i_pl_itemid, int i_pl_itemidparent );
void commitBufferedRowInserts(); void commitBufferedRowInserts();
void activateItem( playlist_item_t *p_item ); void activateItem( playlist_item_t *p_item );
}; };
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "qt4.hpp" #include "qt4.hpp"
#include "components/playlist/playlist.hpp" #include "components/playlist/playlist.hpp"
#include "components/playlist/vlc_model.hpp"
#include <QWidget> #include <QWidget>
#include <QModelIndexList> #include <QModelIndexList>
...@@ -37,8 +38,7 @@ ...@@ -37,8 +38,7 @@
#include <vlc_playlist.h> /* playlist_item_t */ #include <vlc_playlist.h> /* playlist_item_t */
class QSignalMapper; class QSignalMapper;
class PLModel; class VLCProxyModel;
class MLModel;
class QKeyEvent; class QKeyEvent;
class QWheelEvent; class QWheelEvent;
class QStackedLayout; class QStackedLayout;
...@@ -50,7 +50,6 @@ class PlIconView; ...@@ -50,7 +50,6 @@ class PlIconView;
class PlListView; class PlListView;
class PicFlowView; class PicFlowView;
class LocationBar;
class PLSelector; class PLSelector;
class PlaylistWidget; class PlaylistWidget;
class PixmapAnimator; class PixmapAnimator;
...@@ -61,7 +60,7 @@ class StandardPLPanel: public QWidget ...@@ -61,7 +60,7 @@ class StandardPLPanel: public QWidget
public: public:
StandardPLPanel( PlaylistWidget *, intf_thread_t *, StandardPLPanel( PlaylistWidget *, intf_thread_t *,
playlist_item_t *, PLSelector *, PLModel *, MLModel * ); playlist_item_t *, PLSelector *, VLCProxyModel * );
virtual ~StandardPLPanel(); virtual ~StandardPLPanel();
enum { ICON_VIEW = 0, enum { ICON_VIEW = 0,
...@@ -75,10 +74,9 @@ public: ...@@ -75,10 +74,9 @@ public:
static QMenu *viewSelectionMenu(StandardPLPanel *obj); static QMenu *viewSelectionMenu(StandardPLPanel *obj);
protected: protected:
PLModel *model; VLCProxyModel *model;
MLModel *mlmodel;
virtual void wheelEvent( QWheelEvent *e ); virtual void wheelEvent( QWheelEvent *e );
bool popup( const QModelIndex & index, const QPoint &point, const QModelIndexList &selectionlist ); bool popup( const QPoint &point );
private: private:
intf_thread_t *p_intf; intf_thread_t *p_intf;
...@@ -97,20 +95,16 @@ private: ...@@ -97,20 +95,16 @@ private:
QSignalMapper *selectColumnsSigMapper; QSignalMapper *selectColumnsSigMapper;
int lastActivatedId; int lastActivatedPLItemId;
int currentRootIndexId; int currentRootIndexPLId;
void createTreeView(); void createTreeView();
void createIconView(); void createIconView();
void createListView(); void createListView();
void createCoverView(); void createCoverView();
void updateZoom( int i_zoom ); void updateZoom( int i_zoom );
void changeModel ( bool b_ml );
bool eventFilter ( QObject * watched, QEvent * event ); bool eventFilter ( QObject * watched, QEvent * event );
/* for popup */
QModelIndex popupIndex; /* FIXME: don't store here, pass as Action param */
/* Wait spinner */ /* Wait spinner */
PixmapAnimator *spinnerAnimation; PixmapAnimator *spinnerAnimation;
...@@ -140,6 +134,7 @@ private slots: ...@@ -140,6 +134,7 @@ private slots:
void popupExplore(); void popupExplore();
void popupStream(); void popupStream();
void popupSave(); void popupSave();
void popupAction( QAction * );
void increaseZoom() { updateZoom( i_zoom + 1 ); }; void increaseZoom() { updateZoom( i_zoom + 1 ); };
void decreaseZoom() { updateZoom( i_zoom - 1 ); }; void decreaseZoom() { updateZoom( i_zoom - 1 ); };
void toggleColumnShown( int ); void toggleColumnShown( int );
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*****************************************************************************/ *****************************************************************************/
#include "components/playlist/views.hpp" #include "components/playlist/views.hpp"
#include "components/playlist/playlist_model.hpp" /* PLModel */ #include "components/playlist/vlc_model.hpp" /* VLCModel */
#include "components/playlist/sorting.h" /* Columns List */ #include "components/playlist/sorting.h" /* Columns List */
#include "input_manager.hpp" /* THEMIM */ #include "input_manager.hpp" /* THEMIM */
...@@ -58,7 +58,7 @@ void AbstractPlViewItemDelegate::paintBackground( ...@@ -58,7 +58,7 @@ void AbstractPlViewItemDelegate::paintBackground(
painter->setPen( option.palette.color( QPalette::Highlight ).darker( 150 ) ); painter->setPen( option.palette.color( QPalette::Highlight ).darker( 150 ) );
painter->drawRect( r ); painter->drawRect( r );
} }
else if( index.data( PLModel::IsCurrentRole ).toBool() ) else if( index.data( VLCModel::IsCurrentRole ).toBool() )
{ {
painter->setBrush( QBrush( Qt::lightGray ) ); painter->setBrush( QBrush( Qt::lightGray ) );
painter->setPen( QColor( Qt::darkGray ) ); painter->setPen( QColor( Qt::darkGray ) );
...@@ -81,7 +81,7 @@ void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt ...@@ -81,7 +81,7 @@ void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt
QFont font( index.data( Qt::FontRole ).value<QFont>() ); QFont font( index.data( Qt::FontRole ).value<QFont>() );
font.setPointSize( __MAX( font.pointSize() + i_zoom, 4 ) ); font.setPointSize( __MAX( font.pointSize() + i_zoom, 4 ) );
font.setBold( index.data( PLModel::IsCurrentRole ).toBool() ); font.setBold( index.data( VLCModel::IsCurrentRole ).toBool() );
painter->setFont( font ); painter->setFont( font );
QFontMetrics fm = painter->fontMetrics(); QFontMetrics fm = painter->fontMetrics();
...@@ -120,12 +120,12 @@ void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt ...@@ -120,12 +120,12 @@ void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt
//Draw children indicator //Draw children indicator
if( !index.data( PLModel::IsLeafNodeRole ).toBool() ) if( !index.data( VLCModel::IsLeafNodeRole ).toBool() )
{ {
QRect r( option.rect ); QRect r( option.rect );
r.setSize( QSize( 25, 25 ) ); r.setSize( QSize( 25, 25 ) );
r.translate( 5, 5 ); r.translate( 5, 5 );
if( index.data( PLModel::IsCurrentsParentNodeRole ).toBool() ) if( index.data( VLCModel::IsCurrentsParentNodeRole ).toBool() )
{ {
painter->setOpacity( 0.75 ); painter->setOpacity( 0.75 );
QPainterPath nodeRectPath; QPainterPath nodeRectPath;
...@@ -222,7 +222,7 @@ void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt ...@@ -222,7 +222,7 @@ void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt
//Draw title info //Draw title info
f.setItalic( true ); f.setItalic( true );
f.setPointSize( __MAX( f.pointSize() + i_zoom, 4 ) ); f.setPointSize( __MAX( f.pointSize() + i_zoom, 4 ) );
f.setBold( index.data( PLModel::IsCurrentRole ).toBool() ); f.setBold( index.data( VLCModel::IsCurrentRole ).toBool() );
painter->setFont( f ); painter->setFont( f );
QFontMetrics fm( painter->fontMetrics() ); QFontMetrics fm( painter->fontMetrics() );
...@@ -234,7 +234,7 @@ void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt ...@@ -234,7 +234,7 @@ void PlListViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewIt
} }
//Draw children indicator //Draw children indicator
if( !index.data( PLModel::IsLeafNodeRole ).toBool() ) if( !index.data( VLCModel::IsLeafNodeRole ).toBool() )
{ {
QPixmap dirPix = QPixmap( ":/type/node" ); QPixmap dirPix = QPixmap( ":/type/node" );
painter->drawPixmap( QPoint( textRect.x(), textRect.center().y() - dirPix.height() / 2 ), painter->drawPixmap( QPoint( textRect.x(), textRect.center().y() - dirPix.height() / 2 ),
...@@ -276,7 +276,7 @@ QSize PlListViewItemDelegate::sizeHint ( const QStyleOptionViewItem &, const QMo ...@@ -276,7 +276,7 @@ QSize PlListViewItemDelegate::sizeHint ( const QStyleOptionViewItem &, const QMo
void PlTreeViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const void PlTreeViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{ {
if ( index.data( PLModel::IsCurrentRole ).toBool() ) if ( index.data( VLCModel::IsCurrentRole ).toBool() )
{ {
QStyleOptionViewItem myoptions = option; QStyleOptionViewItem myoptions = option;
myoptions.font.setBold( true ); myoptions.font.setBold( true );
...@@ -305,7 +305,7 @@ static void plViewDragMoveEvent( QAbstractItemView *, QDragMoveEvent * event ) ...@@ -305,7 +305,7 @@ static void plViewDragMoveEvent( QAbstractItemView *, QDragMoveEvent * event )
else event->acceptProposedAction(); else event->acceptProposedAction();
} }
PlIconView::PlIconView( PLModel *, QWidget *parent ) : QListView( parent ) PlIconView::PlIconView( QAbstractItemModel *, QWidget *parent ) : QListView( parent )
{ {
PlIconViewItemDelegate *delegate = new PlIconViewItemDelegate( this ); PlIconViewItemDelegate *delegate = new PlIconViewItemDelegate( this );
...@@ -355,7 +355,7 @@ bool PlIconView::viewportEvent ( QEvent * event ) ...@@ -355,7 +355,7 @@ bool PlIconView::viewportEvent ( QEvent * event )
return QAbstractItemView::viewportEvent( event ); return QAbstractItemView::viewportEvent( event );
} }
PlListView::PlListView( PLModel *, QWidget *parent ) : QListView( parent ) PlListView::PlListView( QAbstractItemModel *, QWidget *parent ) : QListView( parent )
{ {
setViewMode( QListView::ListMode ); setViewMode( QListView::ListMode );
setUniformItemSizes( true ); setUniformItemSizes( true );
...@@ -412,7 +412,7 @@ bool PlListView::viewportEvent ( QEvent * event ) ...@@ -412,7 +412,7 @@ bool PlListView::viewportEvent ( QEvent * event )
return QAbstractItemView::viewportEvent( event ); return QAbstractItemView::viewportEvent( event );
} }
PlTreeView::PlTreeView( PLModel *, QWidget *parent ) : QTreeView( parent ) PlTreeView::PlTreeView( QAbstractItemModel *, QWidget *parent ) : QTreeView( parent )
{ {
setItemDelegate( new PlTreeViewItemDelegate( this ) ); setItemDelegate( new PlTreeViewItemDelegate( this ) );
...@@ -443,8 +443,9 @@ PlTreeView::PlTreeView( PLModel *, QWidget *parent ) : QTreeView( parent ) ...@@ -443,8 +443,9 @@ PlTreeView::PlTreeView( PLModel *, QWidget *parent ) : QTreeView( parent )
void PlTreeView::setModel( QAbstractItemModel * model ) void PlTreeView::setModel( QAbstractItemModel * model )
{ {
QTreeView::setModel( model ); QTreeView::setModel( model );
VLCModel *m = static_cast<VLCModel*>(model);
CONNECT( this, expanded( const QModelIndex & ), CONNECT( this, expanded( const QModelIndex & ),
model, ensureArtRequested( const QModelIndex & ) ); m->sigs, ensureArtRequestedSlot( const QModelIndex & ) );
} }
void PlTreeView::startDrag ( Qt::DropActions supportedActions ) void PlTreeView::startDrag ( Qt::DropActions supportedActions )
...@@ -470,7 +471,7 @@ void PlTreeView::keyPressEvent( QKeyEvent *event ) ...@@ -470,7 +471,7 @@ void PlTreeView::keyPressEvent( QKeyEvent *event )
} }
#include <QHBoxLayout> #include <QHBoxLayout>
PicFlowView::PicFlowView( PLModel *p_model, QWidget *parent ) : QAbstractItemView( parent ) PicFlowView::PicFlowView( QAbstractItemModel *p_model, QWidget *parent ) : QAbstractItemView( parent )
{ {
QHBoxLayout *layout = new QHBoxLayout( this ); QHBoxLayout *layout = new QHBoxLayout( this );
layout->setMargin( 0 ); layout->setMargin( 0 );
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "util/pictureflow.hpp" #include "util/pictureflow.hpp"
class QPainter; class QPainter;
class PLModel;
class QFont; class QFont;
class AbstractPlViewItemDelegate : public QStyledItemDelegate class AbstractPlViewItemDelegate : public QStyledItemDelegate
...@@ -84,7 +83,7 @@ class PlIconView : public QListView ...@@ -84,7 +83,7 @@ class PlIconView : public QListView
Q_OBJECT Q_OBJECT
public: public:
PlIconView( PLModel *model, QWidget *parent = 0 ); PlIconView( QAbstractItemModel *model, QWidget *parent = 0 );
protected: protected:
virtual void startDrag ( Qt::DropActions supportedActions ); virtual void startDrag ( Qt::DropActions supportedActions );
virtual void dragMoveEvent ( QDragMoveEvent * event ); virtual void dragMoveEvent ( QDragMoveEvent * event );
...@@ -96,7 +95,7 @@ class PlListView : public QListView ...@@ -96,7 +95,7 @@ class PlListView : public QListView
Q_OBJECT Q_OBJECT
public: public:
PlListView( PLModel *model, QWidget *parent = 0 ); PlListView( QAbstractItemModel *model, QWidget *parent = 0 );
protected: protected:
virtual void startDrag ( Qt::DropActions supportedActions ); virtual void startDrag ( Qt::DropActions supportedActions );
virtual void dragMoveEvent ( QDragMoveEvent * event ); virtual void dragMoveEvent ( QDragMoveEvent * event );
...@@ -109,7 +108,7 @@ class PlTreeView : public QTreeView ...@@ -109,7 +108,7 @@ class PlTreeView : public QTreeView
Q_OBJECT Q_OBJECT
public: public:
PlTreeView( PLModel *, QWidget *parent = 0 ); PlTreeView( QAbstractItemModel *, QWidget *parent = 0 );
protected: protected:
virtual void startDrag ( Qt::DropActions supportedActions ); virtual void startDrag ( Qt::DropActions supportedActions );
virtual void dragMoveEvent ( QDragMoveEvent * event ); virtual void dragMoveEvent ( QDragMoveEvent * event );
...@@ -121,7 +120,7 @@ class PicFlowView : public QAbstractItemView ...@@ -121,7 +120,7 @@ class PicFlowView : public QAbstractItemView
{ {
Q_OBJECT Q_OBJECT
public: public:
PicFlowView( PLModel *model, QWidget *parent = 0 ); PicFlowView( QAbstractItemModel *model, QWidget *parent = 0 );
virtual QRect visualRect(const QModelIndex&) const; virtual QRect visualRect(const QModelIndex&) const;
virtual void scrollTo(const QModelIndex&, QAbstractItemView::ScrollHint); virtual void scrollTo(const QModelIndex&, QAbstractItemView::ScrollHint);
......
...@@ -22,14 +22,52 @@ ...@@ -22,14 +22,52 @@
*****************************************************************************/ *****************************************************************************/
#include "vlc_model.hpp" #include "vlc_model.hpp"
#include "input_manager.hpp" /* THEMIM */
#include "pixmaps/types/type_unknown.xpm"
VLCModelSubInterface::VLCModelSubInterface()
{
sigs = new VLCModelSignalsHandler( this );
}
VLCModelSubInterface::~VLCModelSubInterface()
{
delete sigs;
}
int VLCModelSubInterface::columnFromMeta( int meta_col )
{
int meta = 1, column = 0;
while( meta != meta_col && meta != COLUMN_END )
{
meta <<= 1;
column++;
}
return column;
}
VLCModel::VLCModel( intf_thread_t *_p_intf, QObject *parent ) VLCModel::VLCModel( intf_thread_t *_p_intf, QObject *parent )
: QAbstractItemModel( parent ), p_intf(_p_intf) : QAbstractItemModel( parent ), VLCModelSubInterface(), p_intf(_p_intf)
{ {
/* Icons initialization */
#define ADD_ICON(type, x) icons[ITEM_TYPE_##type] = QIcon( x )
ADD_ICON( UNKNOWN , type_unknown_xpm );
ADD_ICON( FILE, ":/type/file" );
ADD_ICON( DIRECTORY, ":/type/directory" );
ADD_ICON( DISC, ":/type/disc" );
ADD_ICON( CDDA, ":/type/cdda" );
ADD_ICON( CARD, ":/type/capture-card" );
ADD_ICON( NET, ":/type/net" );
ADD_ICON( PLAYLIST, ":/type/playlist" );
ADD_ICON( NODE, ":/type/node" );
#undef ADD_ICON
} }
VLCModel::~VLCModel() VLCModel::~VLCModel()
{ {
} }
QString VLCModel::getMeta( const QModelIndex & index, int meta ) QString VLCModel::getMeta( const QModelIndex & index, int meta )
...@@ -77,8 +115,93 @@ QPixmap VLCModel::getArtPixmap( const QModelIndex & index, const QSize & size ) ...@@ -77,8 +115,93 @@ QPixmap VLCModel::getArtPixmap( const QModelIndex & index, const QSize & size )
return artPix; return artPix;
} }
QVariant VLCModel::headerData( int section, Qt::Orientation orientation,
int role ) const
{
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
return QVariant();
int meta_col = columnToMeta( section );
if( meta_col == COLUMN_END ) return QVariant();
return QVariant( qfu( psz_column_title( meta_col ) ) );
}
int VLCModel::columnToMeta( int _column )
{
int meta = 1, column = 0;
while( column != _column && meta != COLUMN_END )
{
meta <<= 1;
column++;
}
return meta;
}
int VLCModel::itemId( const QModelIndex &index, int type ) const
{
AbstractPLItem *item = getItem( index );
if ( !item ) return -1;
return item->id( type );
}
AbstractPLItem *VLCModel::getItem( const QModelIndex &index ) const
{
if( index.isValid() )
return static_cast<AbstractPLItem*>( index.internalPointer() );
else return NULL;
}
QString VLCModel::getURI( const QModelIndex &index ) const
{
AbstractPLItem *item = getItem( index );
if ( !item ) return QString();
return item->getURI().toString();
}
input_item_t * VLCModel::getInputItem( const QModelIndex &index ) const
{
AbstractPLItem *item = getItem( index );
if ( !item ) return NULL;
return item->inputItem();
}
QString VLCModel::getTitle( const QModelIndex &index ) const
{
AbstractPLItem *item = getItem( index );
if ( !item ) return QString();
return item->getTitle();
}
bool VLCModel::isCurrent( const QModelIndex &index ) const
{
AbstractPLItem *item = getItem( index );
if ( !item ) return false;
return item->inputItem() == THEMIM->currentInputItem();
}
int VLCModel::columnCount( const QModelIndex & ) const int VLCModel::columnCount( const QModelIndex & ) const
{ {
return columnFromMeta( COLUMN_END ); return columnFromMeta( COLUMN_END );
} }
void VLCModel::ensureArtRequested( const QModelIndex &index )
{
if ( index.isValid() && hasChildren( index ) )
{
int i_art_policy = var_GetInteger( THEPL, "album-art" );
if ( i_art_policy != ALBUM_ART_ALL ) return;
int nbnodes = rowCount( index );
QModelIndex child;
for( int row = 0 ; row < nbnodes ; row++ )
{
child = index.child( row, 0 );
if ( child.isValid() && getArtUrl( child ).isEmpty() )
THEMIM->getIM()->requestArtUpdate( getInputItem( child ) );
}
}
}
...@@ -31,47 +31,61 @@ ...@@ -31,47 +31,61 @@
#include "qt4.hpp" #include "qt4.hpp"
#include "sorting.h" #include "sorting.h"
#include "playlist_item.hpp"
#include <vlc_input.h> #include <vlc_input.h>
#include <QModelIndex> #include <QModelIndex>
#include <QPixmapCache> #include <QPixmapCache>
#include <QSize> #include <QSize>
#include <QObject>
#include <QAbstractItemModel> #include <QAbstractItemModel>
class QAction; #include <QIcon>
class VLCModel : public QAbstractItemModel class QAction;
class VLCModelSignalsHandler;
/* Provides non Q_Object interface for Models.
This allows multiple inheritance on already QAbstractModel based
Qobjects like Q*ProxyModel.
Signals being a Q_Object property, they need to be redirected
using a QObject based class member.
*/
class VLCModelSubInterface
{ {
Q_OBJECT
public: public:
enum { VLCModelSubInterface();
IsCurrentRole = Qt::UserRole, virtual ~VLCModelSubInterface();
IsLeafNodeRole, virtual void rebuild( playlist_item_t * p = NULL ) = 0;
IsCurrentsParentNodeRole
};
VLCModel( intf_thread_t *_p_intf, QObject *parent = 0 );
/*** QAbstractItemModel subclassing ***/
virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const;
virtual int itemId( const QModelIndex & ) const = 0;
virtual input_item_t *getInputItem( const QModelIndex & ) const = 0;
virtual QModelIndex currentIndex() const = 0;
virtual void doDelete( QModelIndexList ) = 0; virtual void doDelete( QModelIndexList ) = 0;
virtual ~VLCModel(); virtual void createNode( QModelIndex, QString ) = 0;
static QString getMeta( const QModelIndex & index, int meta );
static QPixmap getArtPixmap( const QModelIndex & index, const QSize & size );
static QString getArtUrl( const QModelIndex & index );
virtual QString getURI( const QModelIndex &index ) const = 0;
virtual QModelIndex rootIndex() const = 0; virtual QModelIndex rootIndex() const = 0;
virtual void filter( const QString& search_text, const QModelIndex & root, bool b_recursive ) = 0;
virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder ) = 0;
virtual QModelIndex currentIndex() const = 0;
virtual QModelIndex indexByPLID( const int i_plid, const int c ) const = 0;
virtual QModelIndex indexByInputItemID( const int i_inputitem_id, const int c ) const = 0;
virtual int itemId( const QModelIndex &, int type ) const = 0;
virtual bool isTree() const = 0; virtual bool isTree() const = 0;
virtual bool canEdit() const = 0; virtual bool canEdit() const = 0;
enum playLocation enum playLocation
{ {
IN_PLAYLIST, IN_PLAYLIST,
IN_MEDIALIBRARY IN_MEDIALIBRARY,
IN_SQLMEDIALIB
}; };
virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const = 0; virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const = 0;
virtual QString getURI( const QModelIndex &index ) const = 0;
virtual input_item_t *getInputItem( const QModelIndex & ) const = 0;
virtual QString getTitle( const QModelIndex &index ) const = 0;
virtual void action( QAction *, const QModelIndexList & ) = 0;
enum nodeRole {
IsCurrentRole = Qt::UserRole,
IsLeafNodeRole,
IsCurrentsParentNodeRole
};
struct actionsContainerType struct actionsContainerType
{ {
enum enum
...@@ -81,46 +95,83 @@ public: ...@@ -81,46 +95,83 @@ public:
ACTION_REMOVE, ACTION_REMOVE,
ACTION_SORT ACTION_SORT
} action; } action;
QModelIndexList indexes; /* for passing selection or caller index(es) */
int column; /* for sorting */ int column; /* for sorting */
}; };
static int columnFromMeta( int meta_col );
static int columnToMeta( int _column ) VLCModelSignalsHandler *sigs;
{ /* Indirect slots handlers */
int meta = 1, column = 0; virtual void activateItem( const QModelIndex &index ) = 0;
virtual void ensureArtRequested( const QModelIndex &index ) = 0;
virtual void clearPlaylist() = 0;
};
while( column != _column && meta != COLUMN_END ) class VLCModelSignalsHandler : public QObject
{ {
meta <<= 1; Q_OBJECT
column++;
}
return meta; public:
} VLCModelSignalsHandler( VLCModelSubInterface *_parent ) { parent = _parent; }
static int columnFromMeta( int meta_col ) void emit_currentIndexChanged( const QModelIndex &index ) { emit currentIndexChanged( index ); }
{ void emit_rootIndexChanged() { emit rootIndexChanged(); }
int meta = 1, column = 0;
while( meta != meta_col && meta != COLUMN_END ) public slots:
{ void activateItemSlot( const QModelIndex &index ) { parent->activateItem( index ); }
meta <<= 1; void ensureArtRequestedSlot( const QModelIndex &index ) { parent->ensureArtRequested( index ); }
column++; void clearPlaylistSlot() { parent->clearPlaylist(); }
}
return column; signals:
} void currentIndexChanged( const QModelIndex& );
void rootIndexChanged();
virtual void createNode( QModelIndex, QString ) {}; private:
VLCModelSubInterface *parent;
};
public slots: /* Abstract VLC Model ; Base for custom models.
virtual void activateItem( const QModelIndex &index ) = 0; Only implements methods sharing the same code that would be
virtual void actionSlot( QAction *action ) = 0; implemented in subclasses.
Any custom method here must be only used in implemented methods.
*/
class VLCModel : public QAbstractItemModel, public VLCModelSubInterface
{
Q_OBJECT
public:
VLCModel( intf_thread_t *_p_intf, QObject *parent = 0 );
virtual ~VLCModel();
/*** QAbstractItemModel subclassing ***/
virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const;
QVariant headerData( int, Qt::Orientation, int ) const;
/*** VLCModelSubInterface subclassing ***/
virtual int itemId( const QModelIndex &, int type ) const;
virtual QString getURI( const QModelIndex &index ) const;
virtual input_item_t *getInputItem( const QModelIndex & ) const;
virtual QString getTitle( const QModelIndex &index ) const;
/* VLCModelSubInterface Indirect slots handlers */
virtual void ensureArtRequested( const QModelIndex &index );
/* Custom */
static int columnToMeta( int _column );
static QString getMeta( const QModelIndex & index, int meta );
static QPixmap getArtPixmap( const QModelIndex & index, const QSize & size );
static QString getArtUrl( const QModelIndex & index );
protected: protected:
/* Custom methods / helpers */
virtual bool isCurrent( const QModelIndex &index ) const;
virtual bool isParent( const QModelIndex &index, const QModelIndex &current ) const = 0;
virtual bool isLeaf( const QModelIndex &index ) const = 0;
virtual AbstractPLItem *getItem( const QModelIndex & index ) const;
QIcon icons[ITEM_TYPE_NUMBER];
intf_thread_t *p_intf; intf_thread_t *p_intf;
}; };
Q_DECLARE_METATYPE(VLCModel::actionsContainerType) Q_DECLARE_METATYPE(VLCModelSubInterface::actionsContainerType)
#endif #endif
...@@ -494,26 +494,16 @@ QRect PictureFlowSoftwareRenderer::renderSlide(const SlideInfo &slide, int col1, ...@@ -494,26 +494,16 @@ QRect PictureFlowSoftwareRenderer::renderSlide(const SlideInfo &slide, int col1,
QString artURL; QString artURL;
PLModel* plm = qobject_cast<PLModel*>( state->model ); VLCModel *m = static_cast<VLCModel*>( state->model );
#ifdef MEDIA_LIBRARY
MLModel* mlm = qobject_cast<MLModel*>( state->model ); if( m )
#endif
if( plm != 0 )
{
index = ((PLModel*)state->model)->index( slide.slideIndex, 0, state->model->currentIndex().parent() );
if( !index.isValid() )
return QRect();
artURL = plm->data( index, COLUMN_COVER ).toString();
}
#ifdef MEDIA_LIBRARY
else if( mlm != 0 )
{ {
index = ((MLModel*)state->model)->index( slide.slideIndex, 0, QModelIndex() ); index = m->index( slide.slideIndex, 0, m->currentIndex().parent() );
if( !index.isValid() ) if( !index.isValid() )
return QRect(); return QRect();
artURL = mlm->data( index, COLUMN_COVER ).toString(); artURL = m->data( index, COLUMN_COVER ).toString();
} }
#endif
QString key = QString("%1%2%3%4").arg(VLCModel::getMeta( index, COLUMN_TITLE )).arg( VLCModel::getMeta( index, COLUMN_ARTIST ) ).arg(index.data( VLCModel::IsCurrentRole ).toBool() ).arg( artURL ); QString key = QString("%1%2%3%4").arg(VLCModel::getMeta( index, COLUMN_TITLE )).arg( VLCModel::getMeta( index, COLUMN_ARTIST ) ).arg(index.data( VLCModel::IsCurrentRole ).toBool() ).arg( artURL );
QImage* src; QImage* src;
...@@ -643,7 +633,7 @@ void PictureFlowSoftwareRenderer::render() ...@@ -643,7 +633,7 @@ void PictureFlowSoftwareRenderer::render()
// ----------------------------------------- // -----------------------------------------
PictureFlow::PictureFlow(QWidget* parent, VLCModel* _p_model): QWidget(parent) PictureFlow::PictureFlow(QWidget* parent, QAbstractItemModel* _p_model): QWidget(parent)
{ {
d = new PictureFlowPrivate; d = new PictureFlowPrivate;
d->picrole = Qt::DecorationRole; d->picrole = Qt::DecorationRole;
......
...@@ -81,7 +81,7 @@ public: ...@@ -81,7 +81,7 @@ public:
/*! /*!
Creates a new PictureFlow widget. Creates a new PictureFlow widget.
*/ */
PictureFlow(QWidget* parent = 0, VLCModel *model = 0); PictureFlow(QWidget* parent = 0, QAbstractItemModel *model = 0);
/*! /*!
Destroys the widget. Destroys the widget.
......
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