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