Commit ca08ed0e authored by Francois Cartegnie's avatar Francois Cartegnie

Qt: Set popup entries logic into models, and keep interaction outside.

- popup now created according to the selected items and models.
- fixes view/popup model abstraction.
- allows introducing new methods/models.
parent 3de79f56
......@@ -41,6 +41,7 @@
#include "components/playlist/sorting.h"
#include "dialogs_provider.hpp"
#include "input_manager.hpp" /* THEMIM */
#include "util/qt_dirs.hpp"
#include <assert.h>
#include <vlc_intf_strings.h>
......@@ -99,7 +100,7 @@ MLModel::~MLModel()
var_DelCallback( p_ml, "media-added", mediaAdded, this );
}
void MLModel::clearPlaylist()
void MLModel::removeAll()
{
vlc_array_t* p_where = vlc_array_new();
if ( !p_where ) return;
......@@ -499,32 +500,116 @@ void MLModel::activateItem( const QModelIndex &idx )
AddItemToPlaylist( itemId( idx, MLMEDIA_ID ), true, p_ml, true );
}
void MLModel::action( QAction *action, const QModelIndexList &indexes )
bool MLModel::action( QAction *action, const QModelIndexList &indexes )
{
actionsContainerType a = action->data().value<actionsContainerType>();
input_item_t *p_input;
switch ( a.action )
{
case actionsContainerType::ACTION_PLAY:
case ACTION_PLAY:
if ( ! indexes.empty() && indexes.first().isValid() )
{
activateItem( indexes.first() );
return true;
}
break;
case actionsContainerType::ACTION_ADDTOPLAYLIST:
case ACTION_ADDTOPLAYLIST:
foreach( const QModelIndex &index, indexes )
{
if( !index.isValid() ) break;
if( !index.isValid() ) return false;
AddItemToPlaylist( itemId( index, MLMEDIA_ID ), false, p_ml, true );
}
break;
return true;
case actionsContainerType::ACTION_REMOVE:
case ACTION_REMOVE:
doDelete( indexes );
return true;
case ACTION_SORT:
break;
case actionsContainerType::ACTION_SORT:
case ACTION_CLEAR:
removeAll();
return true;
case ACTION_ENQUEUEFILE:
foreach( const QString &uri, a.uris )
playlist_Add( THEPL, uri.toAscii().constData(),
NULL, PLAYLIST_APPEND | PLAYLIST_PREPARSE,
PLAYLIST_END, false, pl_Unlocked );
return true;
case ACTION_ENQUEUEDIR:
if( a.uris.isEmpty() ) return false;
p_input = input_item_New( a.uris.first().toAscii().constData(), NULL );
if( unlikely( p_input == NULL ) ) return false;
/* FIXME: playlist_AddInput() can fail */
playlist_AddInput( THEPL, p_input,
PLAYLIST_APPEND,
PLAYLIST_END, true, pl_Unlocked );
vlc_gc_decref( p_input );
return true;
case ACTION_ENQUEUEGENERIC:
foreach( const QString &uri, a.uris )
{
p_input = input_item_New( qtu( uri ), NULL );
/* Insert options */
foreach( const QString &option, a.options.split( " :" ) )
{
QString temp = colon_unescape( option );
if( !temp.isEmpty() )
input_item_AddOption( p_input, qtu( temp ),
VLC_INPUT_OPTION_TRUSTED );
}
/* FIXME: playlist_AddInput() can fail */
playlist_AddInput( THEPL, p_input,
PLAYLIST_APPEND | PLAYLIST_PREPARSE,
PLAYLIST_END, false, pl_Unlocked );
vlc_gc_decref( p_input );
}
return true;
default:
break;
}
return false;
}
bool MLModel::isSupportedAction( actions action, const QModelIndex &index ) const
{
switch ( action )
{
case ACTION_ADDTOPLAYLIST:
return index.isValid();
case ACTION_SORT:
return false;
case ACTION_PLAY:
case ACTION_STREAM:
case ACTION_SAVE:
case ACTION_INFO:
case ACTION_REMOVE:
return index.isValid();
case ACTION_EXPLORE:
if( index.isValid() )
return getURI( index ).startsWith( "file://" );
case ACTION_CREATENODE:
return false;
case ACTION_CLEAR:
return rowCount() && canEdit();
case ACTION_ENQUEUEFILE:
case ACTION_ENQUEUEDIR:
case ACTION_ENQUEUEGENERIC:
return canEdit();
default:
return false;
}
return false;
}
QModelIndex MLModel::rootIndex() const
......@@ -545,13 +630,6 @@ bool MLModel::canEdit() const
return true;
}
bool MLModel::isCurrentItem( const QModelIndex &index, playLocation where ) const
{
if ( where == IN_SQLMEDIALIB )
return index.isValid();
return false;
}
QModelIndex MLModel::getIndexByMLID( int id ) const
{
for( int i = 0; i < rowCount( ); i++ )
......
......@@ -82,6 +82,7 @@ public:
Qt::ItemFlags flags( const QModelIndex& ) const;
QMimeData* mimeData( const QModelIndexList & indexes ) const;
virtual bool removeRows( int row, int count, const QModelIndex & parent = QModelIndex() );
virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder );
// Custom functions
bool isEditable( const QModelIndex& ) const;
......@@ -94,22 +95,21 @@ public:
virtual void rebuild( playlist_item_t * p = NULL );
virtual void doDelete( QModelIndexList selected );
virtual void createNode( QModelIndex, QString ) {};
virtual void removeAll();
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 canEdit() const;
virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const;
virtual void action( QAction *action, const QModelIndexList &indexes );
virtual bool action( QAction *action, const QModelIndexList &indexes );
virtual bool isSupportedAction( actions action, const QModelIndex & ) const;
/* VLCModelSubInterface virtual slots */
virtual void activateItem( const QModelIndex &index );
virtual void clearPlaylist();
protected:
......
......@@ -30,6 +30,7 @@
#include "qt4.hpp"
#include "components/playlist/playlist_model.hpp"
#include "input_manager.hpp" /* THEMIM */
#include "util/qt_dirs.hpp"
#include <vlc_intf_strings.h> /* I_DIR */
......@@ -90,6 +91,16 @@ QModelIndexList VLCProxyModel::mapListToSource( const QModelIndexList& list )
return newlist;
}
void VLCProxyModel::sort( const int column, Qt::SortOrder order )
{
/* sorting on PLModel affects playlist order. */
if ( model() == sourcemodels[ PL_MODEL ] )
model()->sort( column, order );
else
/* otherwise we just use native proxy sorting */
QSortFilterProxyModel::sort( column, order );
}
/*************************************************************************
* Playlist model implementation
*************************************************************************/
......@@ -479,20 +490,6 @@ PLItem* PLModel::getItem( const QModelIndex & index ) const
return item;
}
bool PLModel::isCurrentItem( const QModelIndex &index, playLocation where ) const
{
if ( where == IN_PLAYLIST )
{
return itemId( index, PLAYLIST_ID ) == THEPL->p_playing->i_id;
}
else if ( where == IN_MEDIALIBRARY )
{
return ( p_playlist->p_media_library &&
rootItem->inputItem() == p_playlist->p_media_library->p_input );
}
return false;
}
QModelIndex PLModel::index( const int row, const int column, const QModelIndex &parent )
const
{
......@@ -615,6 +612,15 @@ PLItem * PLModel::findInner( PLItem *root, int i_id, bool b_isinputid ) const
return NULL;
}
PLModel::pl_nodetype PLModel::getPLRootType() const
{
if ( rootItem->id( PLAYLIST_ID ) == 3 )
return ROOTTYPE_MEDIA_LIBRARY;
else
return ROOTTYPE_CURRENT_PLAYING; // id == 2
/* FIXME: handle all cases */
}
bool PLModel::canEdit() const
{
return (
......@@ -1006,7 +1012,7 @@ void PLModel::filter( const QString& search_text, const QModelIndex & idx, bool
rebuild();
}
void PLModel::clearPlaylist()
void PLModel::removeAll()
{
if( rowCount() < 1 ) return;
......@@ -1032,19 +1038,24 @@ void PLModel::createNode( QModelIndex index, QString name )
PL_UNLOCK;
}
void PLModel::action( QAction *action, const QModelIndexList &indexes )
bool PLModel::action( QAction *action, const QModelIndexList &indexes )
{
QModelIndex index;
actionsContainerType a = action->data().value<actionsContainerType>();
input_item_t *p_input;
switch ( a.action )
{
case actionsContainerType::ACTION_PLAY:
case ACTION_PLAY:
if ( !indexes.empty() && indexes.first().isValid() )
{
activateItem( indexes.first() );
return true;
}
break;
case actionsContainerType::ACTION_ADDTOPLAYLIST:
case ACTION_ADDTOPLAYLIST:
PL_LOCK;
foreach( const QModelIndex &currentIndex, indexes )
{
......@@ -1056,22 +1067,107 @@ void PLModel::action( QAction *action, const QModelIndexList &indexes )
PLAYLIST_END );
}
PL_UNLOCK;
break;
return true;
case actionsContainerType::ACTION_REMOVE:
case ACTION_REMOVE:
doDelete( indexes );
break;
return true;
case actionsContainerType::ACTION_SORT:
case ACTION_SORT:
if ( indexes.empty() ) break;
index = indexes.first().parent();
if( !index.isValid() ) index = rootIndex();
sort( indexes.first(), index,
a.column > 0 ? a.column - 1 : -a.column - 1,
a.column > 0 ? Qt::AscendingOrder : Qt::DescendingOrder );
return true;
case ACTION_CLEAR:
removeAll();
return true;
case ACTION_ENQUEUEFILE:
foreach( const QString &uri, a.uris )
playlist_Add( THEPL, uri.toAscii().constData(),
NULL, PLAYLIST_APPEND | PLAYLIST_PREPARSE,
PLAYLIST_END,
getPLRootType() == ROOTTYPE_CURRENT_PLAYING,
pl_Unlocked );
return true;
case ACTION_ENQUEUEDIR:
if( a.uris.isEmpty() ) break;
p_input = input_item_New( a.uris.first().toAscii().constData(), NULL );
if( unlikely( p_input == NULL ) ) break;
/* FIXME: playlist_AddInput() can fail */
playlist_AddInput( THEPL, p_input,
PLAYLIST_APPEND,
PLAYLIST_END,
getPLRootType() == ROOTTYPE_CURRENT_PLAYING,
pl_Unlocked );
vlc_gc_decref( p_input );
return true;
case ACTION_ENQUEUEGENERIC:
foreach( const QString &uri, a.uris )
{
p_input = input_item_New( qtu( uri ), NULL );
/* Insert options */
foreach( const QString &option, a.options.split( " :" ) )
{
QString temp = colon_unescape( option );
if( !temp.isEmpty() )
input_item_AddOption( p_input, qtu( temp ),
VLC_INPUT_OPTION_TRUSTED );
}
/* FIXME: playlist_AddInput() can fail */
playlist_AddInput( THEPL, p_input,
PLAYLIST_APPEND | PLAYLIST_PREPARSE,
PLAYLIST_END, true, pl_Unlocked );
vlc_gc_decref( p_input );
}
return true;
default:
break;
}
return false;
}
bool PLModel::isSupportedAction( actions action, const QModelIndex &index ) const
{
switch ( action )
{
case ACTION_ADDTOPLAYLIST:
/* Only if we are not already in Current Playing */
if ( getPLRootType() == ROOTTYPE_CURRENT_PLAYING ) return false;
if( index.isValid() && index != rootIndex() )
return ( itemId( index, PLAYLIST_ID ) != THEPL->p_playing->i_id );
case ACTION_SORT:
return rowCount();
case ACTION_PLAY:
case ACTION_STREAM:
case ACTION_SAVE:
case ACTION_INFO:
case ACTION_REMOVE:
return index.isValid() && index != rootIndex();
case ACTION_EXPLORE:
if( index.isValid() )
return getURI( index ).startsWith( "file://" );
case ACTION_CREATENODE:
return ( canEdit() && isTree() );
case ACTION_CLEAR:
return rowCount() && canEdit();
case ACTION_ENQUEUEFILE:
case ACTION_ENQUEUEDIR:
case ACTION_ENQUEUEGENERIC:
return canEdit();
default:
return false;
}
return false;
}
/******************* Drag and Drop helper class ******************/
......
......@@ -60,12 +60,13 @@ public:
return qobject_cast<VLCModel *>( sourceModel() );
}
/* Different Models Handling */
enum models
{
PL_MODEL = 0,
SQLML_MODEL /* note: keep it last */
};
bool switchToModel( models type );
void setModel( models type, VLCModel *model )
{
......@@ -73,24 +74,17 @@ public:
}
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 void removeAll() { model()->removeAll(); }
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 ) ); }
......@@ -99,19 +93,20 @@ public:
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 )
virtual bool action( QAction *action, const QModelIndexList &indexes )
{
model()->action( action, mapListToSource( indexes ) );
return model()->action( action, mapListToSource( indexes ) );
}
virtual bool isSupportedAction( actions action, const QModelIndex &index ) const { return model()->isSupportedAction( action, mapToSource( index ) ); }
/* 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(); }
/* AbstractItemModel subclassing */
virtual void sort( const int column, Qt::SortOrder order = Qt::AscendingOrder );
/* Local signals for index conversion */
public slots:
......@@ -172,6 +167,7 @@ public:
virtual void rebuild( playlist_item_t * p = NULL );
virtual void doDelete( QModelIndexList selected );
virtual void createNode( QModelIndex index, QString name );
virtual void removeAll();
/* Lookups */
virtual QModelIndex rootIndex() const;
......@@ -181,12 +177,11 @@ public:
virtual QModelIndex indexByInputItemID( const int i_inputitem_id, const int c ) const;
virtual bool isTree() const;
virtual bool canEdit() const;
virtual bool isCurrentItem( const QModelIndex &index, playLocation where ) const;
virtual void action( QAction *action, const QModelIndexList &indexes );
virtual bool action( QAction *action, const QModelIndexList &indexes );
virtual bool isSupportedAction( actions action, const QModelIndex & ) const;
/* VLCModelSubInterface indirect slots */
virtual void activateItem( const QModelIndex &index );
virtual void clearPlaylist();
protected:
/* VLCModel subclassing */
......@@ -235,6 +230,12 @@ private:
PLItem *findByPLId( PLItem *, int i_plitemid ) const;
PLItem *findByInputId( PLItem *, int i_input_itemid ) const;
PLItem *findInner(PLItem *, int i_id, bool b_isinputid ) const;
enum pl_nodetype
{
ROOTTYPE_CURRENT_PLAYING,
ROOTTYPE_MEDIA_LIBRARY
};
pl_nodetype getPLRootType() const;
/* */
QString latestSearch;
......
......@@ -129,11 +129,6 @@ private slots:
void popupPlView( const QPoint & );
void popupSelectColumn( QPoint );
void popupPromptAndCreateNode();
void popupInfoDialog();
void popupExplore();
void popupStream();
void popupSave();
void popupAction( QAction * );
void increaseZoom() { updateZoom( i_zoom + 1 ); };
void decreaseZoom() { updateZoom( i_zoom - 1 ); };
......
......@@ -56,54 +56,59 @@ class VLCModelSubInterface
public:
VLCModelSubInterface();
virtual ~VLCModelSubInterface();
enum nodeRole
{
IsCurrentRole = Qt::UserRole,
IsLeafNodeRole,
IsCurrentsParentNodeRole
};
virtual void rebuild( playlist_item_t * p = NULL ) = 0;
virtual void doDelete( QModelIndexList ) = 0;
virtual void createNode( QModelIndex, QString ) = 0;
virtual void removeAll() = 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 canEdit() const = 0;
enum playLocation
{
IN_PLAYLIST,
IN_MEDIALIBRARY,
IN_SQLMEDIALIB
};
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
enum actions
{
ACTION_PLAY = 1,
ACTION_STREAM,
ACTION_SAVE,
ACTION_INFO,
ACTION_ADDTOPLAYLIST,
ACTION_REMOVE,
ACTION_SORT,
ACTION_EXPLORE,
ACTION_CREATENODE,
ACTION_CLEAR,
ACTION_ENQUEUEFILE,
ACTION_ENQUEUEDIR,
ACTION_ENQUEUEGENERIC
};
struct actionsContainerType
{
enum
{
ACTION_PLAY = 1,
ACTION_ADDTOPLAYLIST,
ACTION_REMOVE,
ACTION_SORT
} action;
actions action;
int column; /* for sorting */
QStringList uris; /* for enqueuing */
QString options;
};
virtual bool action( QAction *, const QModelIndexList & ) = 0;
virtual bool isSupportedAction( actions action, const QModelIndex & ) const = 0;
static int columnFromMeta( int meta_col );
VLCModelSignalsHandler *sigs;
/* Indirect slots handlers */
VLCModelSignalsHandler *sigs;
virtual void activateItem( const QModelIndex &index ) = 0;
virtual void ensureArtRequested( const QModelIndex &index ) = 0;
virtual void clearPlaylist() = 0;
};
class VLCModelSignalsHandler : public QObject
......@@ -119,7 +124,6 @@ public:
public slots:
void activateItemSlot( const QModelIndex &index ) { parent->activateItem( index ); }
void ensureArtRequestedSlot( const QModelIndex &index ) { parent->ensureArtRequested( index ); }
void clearPlaylistSlot() { parent->clearPlaylist(); }
signals:
void currentIndexChanged( const QModelIndex& );
......
......@@ -232,6 +232,15 @@ QString OpenDialog::getMRL( bool b_all )
: itemsMRL[0];
}
QStringList OpenDialog::getMRLs( bool b_with_options )
{
if ( !b_with_options ) return itemsMRL;
QStringList postfixedMRLs;
foreach( const QString &mrl, itemsMRL )
postfixedMRLs << QString( mrl ).append( getOptions() );
return postfixedMRLs;
}
QString OpenDialog::getOptions()
{
return ui.advancedLineInput->text();
......
......@@ -71,6 +71,8 @@ public:
void showTab( int = OPEN_FILE_TAB );
QString getMRL( bool b = true );
QStringList getMRLs( bool b = true );
QString getOptions();
public slots:
......
......@@ -458,16 +458,6 @@ void DialogsProvider::simpleOpenDialog()
addFromSimple( true, true ); /* Playlist and Go */
}
void DialogsProvider::simplePLAppendDialog()
{
addFromSimple( true, false );
}
void DialogsProvider::simpleMLAppendDialog()
{
addFromSimple( false, false );
}
/* Url & Clipboard */
/**
* Open a MRL.
......@@ -540,6 +530,33 @@ static void openDirectory( intf_thread_t *p_intf, bool pl, bool go )
vlc_gc_decref( p_input );
}
QString DialogsProvider::getDirectoryDialog()
{
QString dir = QFileDialog::getExistingDirectory( NULL, qtr( I_OP_DIR_WINTITLE ), p_intf->p_sys->filepath );
if( dir.isEmpty() ) return QString();
p_intf->p_sys->filepath = dir;
const char *scheme = "directory";
if( dir.endsWith( "/VIDEO_TS", Qt::CaseInsensitive ) )
scheme = "dvd";
else if( dir.endsWith( "/BDMV", Qt::CaseInsensitive ) )
{
scheme = "bluray";
dir.remove( "BDMV" );
}
char *uri = vlc_path2uri( qtu( toNativeSeparators( dir ) ), scheme );
if( unlikely(uri == NULL) ) return QString();
dir = qfu( uri );
free( uri );
RecentsMRL::getInstance( p_intf )->addRecent( dir );
return dir;
}
void DialogsProvider::PLOpenDir()
{
openDirectory( p_intf, true, true );
......@@ -550,11 +567,6 @@ void DialogsProvider::PLAppendDir()
openDirectory( p_intf, true, false );
}
void DialogsProvider::MLAppendDir()
{
openDirectory( p_intf, false , false );
}
/****************
* Playlist *
****************/
......
......@@ -140,8 +140,6 @@ public slots:
void openFileGenericDialog( intf_dialog_args_t * );
void simpleOpenDialog();
void simplePLAppendDialog();
void simpleMLAppendDialog();
void openDialog();
void openDiscDialog();
......@@ -150,12 +148,12 @@ public slots:
void openNetDialog();
void openCaptureDialog();
QString getDirectoryDialog();
void PLAppendDialog( int tab = OPEN_FILE_TAB );
void MLAppendDialog( int tab = OPEN_FILE_TAB );
void PLOpenDir();
void PLAppendDir();
void MLAppendDir();
void streamingDialog( QWidget *parent, const QString& mrl, bool b_stream = true,
QStringList options = QStringList("") );
......
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