[vlc-devel] [PATCH] qt: implement recent medias menu

Thomas Guillem thomas at gllm.fr
Wed Apr 24 10:03:10 CEST 2019


Hello Abel,

I'm OK with your patches bug I got 2 issues (that could be fixed afterward in seperate commits)
 
- Entries are disapearing when I hover them with my mouse pointer, cf. https://gllm.fr/~tom/vlc/vlc-recents-bug.png It seems that I'm the only one with this issue (Pierre could not reproduce it).

- The name of the media should be displayed instead of the URI.

Regards,

On Tue, Apr 23, 2019, at 12:59, Abel Tesfaye wrote:
> The sub menu located at media -> open recent media used to be empty. 
> This commit fixed that.
> ---
>  modules/gui/qt/Makefile.am                    |  3 +
>  .../gui/qt/components/player_controller.cpp   |  3 +
>  .../gui/qt/components/recent_media_model.cpp  | 97 +++++++++++++++++++
>  .../gui/qt/components/recent_media_model.hpp  | 69 +++++++++++++
>  modules/gui/qt/dialogs_provider.cpp           |  2 -
>  modules/gui/qt/main_interface.cpp             |  3 +-
>  modules/gui/qt/qml/menus/MainDropdownMenu.qml |  3 +-
>  modules/gui/qt/qml/menus/MediaMenu.qml        | 36 ++++++-
>  modules/gui/qt/recents.cpp                    |  1 +
>  modules/gui/qt/recents.hpp                    |  9 +-
>  10 files changed, 218 insertions(+), 8 deletions(-)
>  create mode 100644 modules/gui/qt/components/recent_media_model.cpp
>  create mode 100644 modules/gui/qt/components/recent_media_model.hpp
> 
> diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
> index 5f1498e7ad..203ded3d90 100644
> --- a/modules/gui/qt/Makefile.am
> +++ b/modules/gui/qt/Makefile.am
> @@ -103,6 +103,8 @@ libqt_plugin_la_SOURCES = \
>  	gui/qt/components/controller.cpp gui/qt/components/controller.hpp \
>  	gui/qt/components/controller_widget.cpp \
>  	gui/qt/components/controller_widget.hpp \
> +	gui/qt/components/recent_media_model.cpp  \
> +	gui/qt/components/recent_media_model.hpp \
>  	gui/qt/components/voutwindow/videosurface.cpp \
>  	gui/qt/components/voutwindow/videosurface.hpp \
>  	gui/qt/components/voutwindow/qvoutwindow.cpp \
> @@ -253,6 +255,7 @@ nodist_libqt_plugin_la_SOURCES = \
>  	gui/qt/components/controller.moc.cpp \
>  	gui/qt/components/controller_widget.moc.cpp \
>  	gui/qt/components/custom_menus.moc.cpp \
> +	gui/qt/components/recent_media_model.moc.cpp \
>  	gui/qt/components/voutwindow/videosurface.moc.cpp \
>  	gui/qt/components/voutwindow/qvoutwindow.moc.cpp \
>  	gui/qt/components/voutwindow/qvoutwindowdummy.moc.cpp \
> diff --git a/modules/gui/qt/components/player_controller.cpp 
> b/modules/gui/qt/components/player_controller.cpp
> index 5a445d174c..cd8fc33b45 100644
> --- a/modules/gui/qt/components/player_controller.cpp
> +++ b/modules/gui/qt/components/player_controller.cpp
> @@ -202,6 +202,9 @@ static  void 
> on_player_current_media_changed(vlc_player_t *, input_item_t *new_m
>          that->UpdateName( newMediaPtr.get() );
>          that->UpdateArt( newMediaPtr.get() );
>          that->UpdateMeta( newMediaPtr.get() );
> +
> +        RecentsMRL::getInstance( that->p_intf )->addRecent( 
> newMediaPtr.get()->psz_uri );
> +
>          emit q->inputChanged( newMediaPtr != nullptr );
>      });
>  }
> diff --git a/modules/gui/qt/components/recent_media_model.cpp 
> b/modules/gui/qt/components/recent_media_model.cpp
> new file mode 100644
> index 0000000000..447409ce20
> --- /dev/null
> +++ b/modules/gui/qt/components/recent_media_model.cpp
> @@ -0,0 +1,97 @@
> +/*****************************************************************************
> + * Copyright (C) 2019 VLC authors and VideoLAN
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * ( at your option ) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 
> 02110-1301, USA.
> + 
> *****************************************************************************/
> +
> +#include "recent_media_model.hpp"
> +#include <cassert>
> +
> +namespace {
> +    enum Roles
> +    {
> +        MRLRole = Qt::UserRole
> +    };
> +}
> +
> +VLCRecentMediaModel::VLCRecentMediaModel(intf_thread_t *p_intf,QObject 
> *parent)
> +    : QAbstractListModel(parent)
> +{
> +    assert(p_intf);
> +    rmrl = RecentsMRL::getInstance(p_intf);
> +
> +    connect(rmrl, SIGNAL(saved()), this, SLOT(update()));
> +    connect(this, SIGNAL(limitChanged()), this, SLOT(update()));
> +
> +    update();
> +}
> +
> +int VLCRecentMediaModel::rowCount(QModelIndex const & ) const
> +{
> +    return items.count();
> +}
> +
> +QVariant VLCRecentMediaModel::data(QModelIndex const &index, const int 
> role) const
> +{
> +    if (!index.isValid())
> +        return {};
> +    switch (role)
> +    {
> +        case MRLRole :
> +            return QVariant::fromValue(items[index.row()]);
> +        default :
> +            return {};
> +    }
> +}
> +
> +QHash<int, QByteArray> VLCRecentMediaModel::roleNames() const
> +{
> +    QHash<int, QByteArray> roleNames;
> +    roleNames.insert(MRLRole, "mrl");
> +    return roleNames;
> +}
> +
> +void VLCRecentMediaModel::clear()
> +{
> +    if (!items.isEmpty())
> +    {
> +        rmrl->clear();
> +        update();
> +    }
> +}
> +
> +void VLCRecentMediaModel::update()
> +{
> +    beginResetModel();
> +    items = rmrl->recentList().mid(0,i_limit);
> +    endResetModel();
> +}
> +
> +QStringList VLCRecentMediaModel::getItems()
> +{
> +    return items;
> +}
> +
> +int VLCRecentMediaModel::getLimit() const
> +{
> +    return i_limit; 
> +}
> +
> +void VLCRecentMediaModel::setLimit(int l)
> +{
> +    i_limit = l;
> +    update();
> +    emit limitChanged();
> +}
> diff --git a/modules/gui/qt/components/recent_media_model.hpp 
> b/modules/gui/qt/components/recent_media_model.hpp
> new file mode 100644
> index 0000000000..c37fae9b77
> --- /dev/null
> +++ b/modules/gui/qt/components/recent_media_model.hpp
> @@ -0,0 +1,69 @@
> +/*****************************************************************************
> + * Copyright (C) 2019 VLC authors and VideoLAN
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * ( at your option ) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 
> 02110-1301, USA.
> + 
> *****************************************************************************/
> +
> +#ifndef VLC_RECENT_MEDIA_MODEL_HPP
> +#define VLC_RECENT_MEDIA_MODEL_HPP
> +
> +#ifdef HAVE_CONFIG_H
> +
> +# include "config.h"
> +
> +#endif
> +
> +#include "qt.hpp"
> +#include <QAbstractListModel>
> +
> +#include <QObject>
> +#include <QStringList>
> +#include "recents.hpp"
> +
> +class VLCRecentMediaModel : public QAbstractListModel
> +{
> +    Q_OBJECT
> +    Q_PROPERTY(int limit READ getLimit WRITE setLimit NOTIFY 
> limitChanged)
> +
> +public:
> +    VLCRecentMediaModel(intf_thread_t *p_intf,QObject * parent = 
> nullptr);
> +
> +    Q_INVOKABLE void clear();
> +
> +    Q_INVOKABLE int rowCount(QModelIndex const &parent = {}) const  
> override;
> +
> +    QVariant data(QModelIndex const &index, const int role = 
> Qt::DisplayRole) const  override;
> +
> +    QHash<int, QByteArray> roleNames() const override;
> +
> +    QStringList items;
> +
> +    void setLimit(int l);
> +    int getLimit() const;
> +
> +private:
> +    RecentsMRL *rmrl;
> +    int i_limit = 10;
> +
> +signals:
> +    void limitChanged();
> +
> +public slots:
> +    void update();
> +    QStringList getItems();
> +
> +};
> +
> +#endif // VLC_RECENT_MEDIA_MODEL_HPP
> diff --git a/modules/gui/qt/dialogs_provider.cpp 
> b/modules/gui/qt/dialogs_provider.cpp
> index 17d6b35a44..58c88a7c1f 100644
> --- a/modules/gui/qt/dialogs_provider.cpp
> +++ b/modules/gui/qt/dialogs_provider.cpp
> @@ -566,8 +566,6 @@ QString DialogsProvider::getDirectoryDialog( 
> intf_thread_t *p_intf )
>      dir = qfu( uri );
>      free( uri );
>  
> -    RecentsMRL::getInstance( p_intf )->addRecent( dir );
> -
>      return dir;
>  }
>  
> diff --git a/modules/gui/qt/main_interface.cpp 
> b/modules/gui/qt/main_interface.cpp
> index 7f135f93ba..ac56e3bc2d 100644
> --- a/modules/gui/qt/main_interface.cpp
> +++ b/modules/gui/qt/main_interface.cpp
> @@ -51,6 +51,7 @@
>  #include "components/mediacenter/mlgenremodel.hpp"
>  #include "components/mediacenter/mlvideomodel.hpp"
>  #include "components/mediacenter/mlnetworkmodel.hpp"
> +#include "components/recent_media_model.hpp"
>  
>  #include "components/navigation_history.hpp"
>  #include "components/aboutmodel.hpp"
> @@ -63,7 +64,6 @@
>  #include "util/qmleventfilter.hpp"
>  
>  #include "menus.hpp"                            // Menu creation
> -#include "recents.hpp"                          // RecentItems when DnD
>  
>  #include <QCloseEvent>
>  #include <QKeyEvent>
> @@ -379,6 +379,7 @@ void MainInterface::createMainWidget( QSettings * )
>      rootCtx->setContextProperty( "rootQMLView", mediacenterView);
>      rootCtx->setContextProperty( "rootWindow", this);
>      rootCtx->setContextProperty( "dialogProvider", 
> DialogsProvider::getInstance());
> +    rootCtx->setContextProperty( "recentsMedias",  new 
> VLCRecentMediaModel( p_intf, this ));
>  
>      if (b_hasMedialibrary)
>      {
> diff --git a/modules/gui/qt/qml/menus/MainDropdownMenu.qml 
> b/modules/gui/qt/qml/menus/MainDropdownMenu.qml
> index 4ea0025281..8df4e56c20 100644
> --- a/modules/gui/qt/qml/menus/MainDropdownMenu.qml
> +++ b/modules/gui/qt/qml/menus/MainDropdownMenu.qml
> @@ -21,7 +21,8 @@ import QtQuick.Controls 2.4
>  import "qrc:///utils/" as Utils
>  
>  //main menus, to be used as a dropdown menu
> -Utils.MenuExt {
> +Utils.MenuExt {    
> +    id: mainDropdownMenu
>      //make the menu modal, as we are not attached to a QQuickWindow
>      modal: true
>      closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
> diff --git a/modules/gui/qt/qml/menus/MediaMenu.qml 
> b/modules/gui/qt/qml/menus/MediaMenu.qml
> index 8414b14f8b..8f95dc19ee 100644
> --- a/modules/gui/qt/qml/menus/MediaMenu.qml
> +++ b/modules/gui/qt/qml/menus/MediaMenu.qml
> @@ -30,7 +30,41 @@ Utils.MenuExt {
>      Action { text: qsTr("Open &Capture Device...");       onTriggered: 
> dialogProvider.openCaptureDialog();         
> icon.source:"qrc:/type/capture-card.svg"; shortcut: "Ctrl+C" }
>      Action { text: qsTr("Open &Location from clipboard"); onTriggered: 
> dialogProvider.openUrlDialog();                                         
>               shortcut: "Ctrl+V" }
>  
> -    /* FIXME recent */
> +
> +    Utils.MenuExt {
> +        id: recentsMenu
> +        title: qsTr("Open &Recent Media")
> +        property bool hasData: true
> +        onAboutToShow:{
> +            recentsMenu.hasData = Boolean(recentsMedias.rowCount())
> +        }
> +        Instantiator {
> +            model: recentsMedias
> +            Utils.MenuItemExt {
> +                text: mrl
> +                onTriggered:{
> +                    mainDropdownMenu.close() //needed since menuItem 
> isn't a direct child of a menu
> +                    mainPlaylistController.append([mrl], true)
> +                }
> +
> +                Shortcut {
> +                    sequence: "Ctrl+" + (index + 1)
> +                    onActivated:  mainPlaylistController.append([mrl], 
> true)
> +                    context: Qt.ApplicationShortcut
> +                }
> +            }
> +            onObjectAdded: recentsMenu.insertItem(recentsMenu.count - 
> 2, object)
> +            onObjectRemoved: recentsMenu.removeItem(object)
> +        }
> +
> +        MenuSeparator{}
> +
> +        Utils.MenuItemExt {
> +            text: qsTr("Clear")
> +            enabled: recentsMenu.hasData
> +            onTriggered:recentsMedias.clear()
> +        }
> +    }
>  
>      Action { text: qsTr("Save Playlist to &File...");     onTriggered: 
> dialogProvider.savePlayingToPlaylist();     icon.source: "";            
>           shortcut: "Ctrl+Y" }
>      Action { text: qsTr("Conve&rt / Save..." );           onTriggered: 
> dialogProvider.openAndTranscodingDialogs(); icon.source: "";            
>           shortcut: "Ctrl+R" }
> diff --git a/modules/gui/qt/recents.cpp b/modules/gui/qt/recents.cpp
> index 0857bbba76..4ba7d38fb1 100644
> --- a/modules/gui/qt/recents.cpp
> +++ b/modules/gui/qt/recents.cpp
> @@ -158,6 +158,7 @@ void RecentsMRL::save()
>  {
>      getSettings()->setValue( "RecentsMRL/list", recents );
>      getSettings()->setValue( "RecentsMRL/times", times );
> +    emit saved();
>  }
>  
>  void RecentsMRL::playMRL( const QString &mrl )
> diff --git a/modules/gui/qt/recents.hpp b/modules/gui/qt/recents.hpp
> index 86215f21ff..bb2286ca2c 100644
> --- a/modules/gui/qt/recents.hpp
> +++ b/modules/gui/qt/recents.hpp
> @@ -54,16 +54,16 @@ class RecentsMRL : public QObject, public 
> Singleton<RecentsMRL>
>      friend class Singleton<RecentsMRL>;
>  
>  public:
> +    
>      void addRecent( const QString & );
> -    QStringList recentList();
>      QSignalMapper *signalMapper;
>  
>      vlc_tick_t time( const QString &mrl );
>      void setTime( const QString &mrl, const vlc_tick_t time );
> +    virtual ~RecentsMRL();
>  
>  private:
>      RecentsMRL( intf_thread_t* _p_intf );
> -    virtual ~RecentsMRL();
>  
>      intf_thread_t *p_intf;
>  
> @@ -74,8 +74,11 @@ private:
>  
>      void load();
>      void save();
> -
> +     
> +signals:
> +       void saved();
>  public slots:
> +    QStringList recentList();
>      void clear();
>      void playMRL( const QString & );
>  };
> -- 
> 2.19.1
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list