[vlc-commits] [Git][videolan/vlc][master] 6 commits: qml: fix progressBar radius and sliderHandle size

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Sep 24 17:10:09 UTC 2022



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
e474d61f by Leon Vitanos at 2022-09-24T16:39:03+00:00
qml: fix progressBar radius and sliderHandle size

- - - - -
ff548f1d by Leon Vitanos at 2022-09-24T16:39:03+00:00
qt/qml: register MLBookmarkModel as QML type

- - - - -
89e0cc2b by Leon Vitanos at 2022-09-24T16:39:03+00:00
qml: improve ControlBar code

- - - - -
03fcc96b by Leon Vitanos at 2022-09-24T16:39:03+00:00
qt/qml: syntax & indentation

- - - - -
e87bb072 by Leon Vitanos at 2022-09-24T16:39:03+00:00
qt: disable add button on bookmarks dialog when media is stopped

- - - - -
5510bdbb by Leon Vitanos at 2022-09-24T16:39:03+00:00
qt/qml: implementation of bookmarks bar under the SliderBar

- - - - -


14 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/dialogs/bookmarks/bookmarks.cpp
- modules/gui/qt/dialogs/bookmarks/bookmarks.hpp
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/medialibrary/mlbookmarkmodel.cpp
- modules/gui/qt/medialibrary/mlbookmarkmodel.hpp
- modules/gui/qt/menus/custom_menus.cpp
- modules/gui/qt/menus/qml_menu_wrapper.cpp
- + modules/gui/qt/player/qml/Bookmarks.qml
- modules/gui/qt/player/qml/ControlBar.qml
- modules/gui/qt/player/qml/MiniPlayer.qml
- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/player/qml/SliderBar.qml
- modules/gui/qt/vlc.qrc


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -422,6 +422,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/medialibrary/mlalbumtrackmodel.moc.cpp \
 	gui/qt/medialibrary/mlartist.moc.cpp \
 	gui/qt/medialibrary/mlartistmodel.moc.cpp \
+        gui/qt/medialibrary/mlbookmarkmodel.moc.cpp \
 	gui/qt/medialibrary/mlbasemodel.moc.cpp \
 	gui/qt/medialibrary/mlfoldersmodel.moc.cpp \
 	gui/qt/medialibrary/mlgenremodel.moc.cpp \
@@ -860,6 +861,7 @@ libqt_plugin_la_QML = \
 	gui/qt/network/qml/NetworkThumbnailItem.qml \
 	gui/qt/network/qml/ServicesHomeDisplay.qml \
 	gui/qt/player/qml/qmldir \
+        gui/qt/player/qml/Bookmarks.qml \
 	gui/qt/player/qml/ControlBar.qml \
 	gui/qt/player/qml/ControlbarControls.qml \
 	gui/qt/player/qml/PlaybackSpeed.qml \


=====================================
modules/gui/qt/dialogs/bookmarks/bookmarks.cpp
=====================================
@@ -44,7 +44,7 @@ BookmarksDialog::BookmarksDialog( qt_intf_t *_p_intf ):QVLCFrame( _p_intf )
     QHBoxLayout *layout = new QHBoxLayout( this );
 
     QDialogButtonBox *buttonsBox = new QDialogButtonBox( Qt::Vertical );
-    QPushButton *addButton = new QPushButton( qtr( "Create" ) );
+    addButton = new QPushButton( qtr( "Create" ) );
     addButton->setToolTip( qtr( "Create a new bookmark" ) );
     buttonsBox->addButton( addButton, QDialogButtonBox::ActionRole );
     delButton = new QPushButton( qtr( "Delete" ) );
@@ -63,9 +63,9 @@ BookmarksDialog::BookmarksDialog( qt_intf_t *_p_intf ):QVLCFrame( _p_intf )
                           QDialogButtonBox::RejectRole);
 
     bookmarksList = new QTreeView( this );
-    m_model = new MLBookmarkModel( _p_intf->p_mi->getMediaLibrary(),
-                                   _p_intf->p_player,
-                                   bookmarksList );
+    m_model = new MLBookmarkModel( bookmarksList );
+    m_model->setPlayer(_p_intf->p_player);
+    m_model->setMl(_p_intf->p_mi->getMediaLibrary());
     bookmarksList->setModel( m_model );
     bookmarksList->setRootIsDecorated( false );
     bookmarksList->setAlternatingRowColors( true );
@@ -106,6 +106,11 @@ BookmarksDialog::~BookmarksDialog()
 
 void BookmarksDialog::updateButtons()
 {
+    vlc_player_locker lock{ m_model->player() };
+    vlc_player_state currentState = vlc_player_GetState( m_model->player() );
+    addButton->setEnabled(currentState != VLC_PLAYER_STATE_STOPPING &&
+                          currentState != VLC_PLAYER_STATE_STOPPED);
+
     clearButton->setEnabled( bookmarksList->model()->rowCount() > 0 );
     delButton->setEnabled( bookmarksList->selectionModel()->hasSelection() );
 }


=====================================
modules/gui/qt/dialogs/bookmarks/bookmarks.hpp
=====================================
@@ -43,6 +43,7 @@ private:
     QTreeView *bookmarksList;
     QPushButton *clearButton;
     QPushButton *delButton;
+    QPushButton *addButton;
     MLBookmarkModel* m_model;
 
 private slots:


=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -19,6 +19,7 @@
 #include "medialibrary/mlplaylistlistmodel.hpp"
 #include "medialibrary/mlplaylistmodel.hpp"
 #include "medialibrary/mlplaylist.hpp"
+#include "medialibrary/mlbookmarkmodel.hpp"
 
 #include "player/player_controller.hpp"
 #include "player/player_controlbar_model.hpp"
@@ -254,7 +255,7 @@ void MainUI::registerQMLTypes()
 
         qmlRegisterUncreatableType<TrackListModel>(uri, versionMajor, versionMinor, "TrackListModel", "available tracks of a media (audio/video/sub)" );
         qmlRegisterUncreatableType<TitleListModel>(uri, versionMajor, versionMinor, "TitleListModel", "available titles of a media" );
-        qmlRegisterUncreatableType<ChapterListModel>(uri, versionMajor, versionMinor, "ChapterListModel", "available titles of a media" );
+        qmlRegisterUncreatableType<ChapterListModel>(uri, versionMajor, versionMinor, "ChapterListModel", "available chapters of a media" );
         qmlRegisterUncreatableType<ProgramListModel>(uri, versionMajor, versionMinor, "ProgramListModel", "available programs of a media" );
         qmlRegisterUncreatableType<VLCVarChoiceModel>(uri, versionMajor, versionMinor, "VLCVarChoiceModel", "generic variable with choice model" );
 
@@ -356,6 +357,7 @@ void MainUI::registerQMLTypes()
         qmlRegisterType<MLVideoFoldersModel>( uri, versionMajor, versionMinor, "MLVideoFoldersModel" );
         qmlRegisterType<MLPlaylistListModel>( uri, versionMajor, versionMinor, "MLPlaylistListModel" );
         qmlRegisterType<MLPlaylistModel>( uri, versionMajor, versionMinor, "MLPlaylistModel" );
+        qmlRegisterType<MLBookmarkModel>( uri, versionMajor, versionMinor, "MLBookmarkModel" );
 
         qRegisterMetaType<NetworkTreeItem>();
         qmlRegisterType<NetworkMediaModel>( uri, versionMajor, versionMinor, "NetworkMediaModel");


=====================================
modules/gui/qt/medialibrary/mlbookmarkmodel.cpp
=====================================
@@ -27,100 +27,55 @@
 
 #include "medialib.hpp"
 #include "mlhelper.hpp"
+
 #include "util/vlctick.hpp"
+#include "player/player_controller.hpp"
 
-MLBookmarkModel::MLBookmarkModel( MediaLib* medialib, vlc_player_t *player,
-                                  QObject *parent )
+MLBookmarkModel::MLBookmarkModel( QObject *parent )
     : QAbstractListModel( parent )
-    , m_mediaLib( medialib )
-    , m_player( player )
     , m_currentItem( nullptr, &input_item_Release )
-{
-    static const vlc_player_cbs cbs {
-        &onCurrentMediaChanged,
-        &onPlaybackStateChanged,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-        nullptr,
-    };
-    QString uri;
-    {
-        vlc_player_locker lock{ m_player };
-        vlc::threads::mutex_locker selflock{ m_mutex };
-        m_listener = vlc_player_AddListener( m_player, &cbs, this );
-        if ( m_listener == nullptr )
-            throw std::bad_alloc{};
-        auto currentItem = vlc_player_GetCurrentMedia( m_player );
-        m_currentItem = vlc::wrap_cptr( currentItem ? input_item_Hold( currentItem ) : nullptr,
-                                        &input_item_Release );
-        if (m_currentItem)
-        {
-            uri = m_currentItem->psz_uri;
-        }
-    }
-    updateMediaId(0, uri);
-}
+    , m_ml_event_handle( nullptr, [this](vlc_ml_event_callback_t* cb ) {
+        if (!cb)
+            return;
+        if ( m_mediaLib )
+            m_mediaLib->unregisterEventListener(cb);
+    })
+{}
 
 MLBookmarkModel::~MLBookmarkModel()
 {
-    vlc_player_locker lock{ m_player };
-    vlc_player_RemoveListener( m_player, m_listener );
+    if(m_player && m_listener){
+        vlc_player_locker lock{ m_player };
+        vlc_player_RemoveListener( m_player, m_listener );
+    }
 }
 
 QVariant MLBookmarkModel::data( const QModelIndex &index, int role ) const
 {
-    if ( !index.isValid() || index.row() < 0 ||
-         !m_bookmarks ||
-         (uint32_t)index.row() >= m_bookmarks->i_nb_items )
-    {
+    if ( !index.isValid() || index.row() < 0 || m_player == nullptr ||
+         !m_bookmarks || (uint32_t)index.row() >= m_bookmarks->i_nb_items )
         return QVariant{};
-    }
 
     const auto& bookmark = m_bookmarks->p_items[index.row()];
 
-    // NOTE: We want to keep the current value when editing.
-    if ( role != Qt::DisplayRole && role != Qt::EditRole )
-        return QVariant{};
+    if (role == Qt::DisplayRole || role == Qt::EditRole)
+        role = columnToRole(index.column());
 
-    switch ( index.column() )
-    {
-    case 0:
-        return QVariant::fromValue( QString::fromUtf8( bookmark.psz_name ) );
-    case 1:
-        return QVariant::fromValue( VLCTick::fromMS( bookmark.i_time ).formatHMS() );
-    case 2:
-        return QVariant::fromValue( QString::fromUtf8( bookmark.psz_description ) );
-    default:
-        return QVariant{};
+    switch(role){
+        case BookmarkRoles::NameRole:
+            return QVariant::fromValue( qfu( bookmark.psz_name ) );
+        case BookmarkRoles::TimeRole:
+            return QVariant::fromValue( VLCTick::fromMS( bookmark.i_time ).formatHMS() );
+        case BookmarkRoles::PositionRole:
+        {
+            vlc_player_locker lock{ m_player };
+            return !vlc_player_GetLength( m_player ) ? QVariant{} :
+                    QVariant::fromValue<float> ((float) VLC_TICK_FROM_MS(bookmark.i_time) / vlc_player_GetLength( m_player ));
+        }
+        case BookmarkRoles::DescriptionRole:
+            return QVariant::fromValue( qfu( bookmark.psz_description ) );
+        default:
+            return QVariant{};
     }
 }
 
@@ -128,17 +83,16 @@ bool MLBookmarkModel::setData(const QModelIndex &index, const QVariant &value, i
 {
     if ( index.isValid() == false )
         return false;
-    if ( role != Qt::EditRole )
-        return false;
-    if ( index.column() == 1 )
-        /* Disable editing the Time value through the listing */
+    if ( role == Qt::EditRole )
+        role = columnToRole(index.column());
+    if ( role != BookmarkRoles::NameRole && role != BookmarkRoles::DescriptionRole )
         return false;
     if ( value.canConvert<QString>() == false )
         return false;
+
     size_t row = index.row();
     bool updateName = (index.column() == 0);
 
-    assert( index.column() == 0 || index.column() == 2 );
     if ( ! m_bookmarks || row >= m_bookmarks->i_nb_items )
         return false;
 
@@ -175,22 +129,44 @@ bool MLBookmarkModel::setData(const QModelIndex &index, const QVariant &value, i
         {
             free( b.psz_name );
             b.psz_name = strdup( qtu( str ) );
+            emit dataChanged(this->index(row, 0), this->index(row, 0),
+                             {Qt::DisplayRole, BookmarkRoles::NameRole});
         }
         else
         {
             free( b.psz_description );
             b.psz_description = strdup( qtu( str ) );
+            emit dataChanged(this->index(row, 2), this->index(row, 2),
+                             {Qt::DisplayRole, BookmarkRoles::DescriptionRole});
         }
-
-        if (updateName)
-            emit dataChanged(this->index(row, 0), this->index(row, 0), {Qt::DisplayRole});
-        else
-            emit dataChanged(this->index(row, 2), this->index(row, 2), {Qt::DisplayRole});
     });
 
     return true;
 }
 
+QHash<int, QByteArray> MLBookmarkModel::roleNames() const{
+    return QHash<int, QByteArray>{
+        {BookmarkRoles::NameRole, "name"},
+        {BookmarkRoles::TimeRole, "time"},
+        {BookmarkRoles::PositionRole, "position"},
+        {BookmarkRoles::DescriptionRole, "description"}
+    };
+}
+
+int MLBookmarkModel::columnToRole(int column) const{
+    switch (column)
+    {
+      case 0:
+         return BookmarkRoles::NameRole;
+      case 1:
+         return BookmarkRoles::TimeRole;
+      case 2:
+        return BookmarkRoles::DescriptionRole;
+      default:
+         return -1;
+    }
+}
+
 Qt::ItemFlags MLBookmarkModel::flags( const QModelIndex& index ) const
 {
     auto f = QAbstractItemModel::flags( index );
@@ -224,10 +200,9 @@ QModelIndex MLBookmarkModel::parent(const QModelIndex &) const
 QVariant MLBookmarkModel::headerData( int section, Qt::Orientation orientation,
                                       int role ) const
 {
-    if ( role != Qt::DisplayRole )
-        return QVariant{};
-    if ( orientation == Qt::Vertical )
+    if (role != Qt::DisplayRole || orientation == Qt::Vertical)
         return QVariant{};
+
     switch ( section )
     {
         case 0:
@@ -266,7 +241,6 @@ void MLBookmarkModel::sort( int column, Qt::SortOrder order )
 
 void MLBookmarkModel::add()
 {
-
     vlc_tick_t currentTime;
     {
         vlc_player_locker lock{ m_player };
@@ -288,7 +262,7 @@ void MLBookmarkModel::add()
 
         if (media)
         {
-            QString name = QString("%1 #%2").arg(media->psz_title).arg(count);
+            QString name = qtr("Bookmark at %1").arg(VLCTick::fromMS( time ).formatHMS());
 
             vlc_ml_media_update_bookmark(ml, mediaId, time, qtu(name), nullptr);
         }
@@ -297,7 +271,6 @@ void MLBookmarkModel::add()
     [this](){
         refresh( MLBOOKMARKMODEL_REFRESH );
     });
-
 }
 
 void MLBookmarkModel::remove( const QModelIndexList &indexes )
@@ -395,6 +368,9 @@ void MLBookmarkModel::onPlaybackStateChanged( vlc_player_t *, vlc_player_state s
 {
     auto self = static_cast<MLBookmarkModel*>( data );
 
+    if(self->m_currentMediaId == 0)
+        return;
+
     QMetaObject::invokeMethod(self, [self, state](){
         if ( state == VLC_PLAYER_STATE_STARTED )
             self->refresh( MLBOOKMARKMODEL_REFRESH );
@@ -445,13 +421,12 @@ void MLBookmarkModel::updateMediaId(uint64_t revision, const QString mediaUri)
             beginResetModel();
             m_bookmarks = std::move(ctx.newBookmarks);
             m_currentMediaId = ctx.newMLid;
+            refresh(MLBOOKMARKMODEL_REFRESH);
             endResetModel();
         }
     });
 }
 
-
-
 void MLBookmarkModel::refresh(MLBookmarkModel::RefreshOperation forceClear )
 {
     if (m_currentMediaId == 0 || forceClear == MLBOOKMARKMODEL_CLEAR)
@@ -488,3 +463,147 @@ void MLBookmarkModel::refresh(MLBookmarkModel::RefreshOperation forceClear )
         });
     }
 }
+
+vlc_player_t * MLBookmarkModel::player() const
+{
+    return m_player;
+}
+
+void MLBookmarkModel::setPlayer(vlc_player_t * player)
+{
+    if (m_player == player) return;
+
+    if(m_player && m_listener){
+        vlc_player_locker lock{ m_player };
+        vlc_player_RemoveListener( m_player, m_listener );
+    }
+
+    m_player = player;
+
+    if (m_player && m_mediaLib)
+        initModel();
+}
+
+
+PlayerController * MLBookmarkModel::playerController() const
+{
+    return m_player_controller;
+}
+
+void MLBookmarkModel::setPlayer(PlayerController * player)
+{
+    if (m_player_controller == player) return;
+
+    if (m_player_controller)
+        disconnect(m_player_controller, nullptr, this, nullptr);
+
+    m_player_controller = player;
+
+    connect(m_player_controller, &PlayerController::lengthChanged, this, &MLBookmarkModel::playerLengthChanged);
+
+    setPlayer(player->getPlayer());
+}
+
+MediaLib* MLBookmarkModel::ml() const
+{
+    return m_mediaLib;
+}
+
+void MLBookmarkModel::playerLengthChanged()
+{
+    refresh(MLBOOKMARKMODEL_REFRESH);
+}
+
+void MLBookmarkModel::setMl(MediaLib* medialib)
+{
+    if(m_mediaLib == medialib) return;
+
+    if(m_mediaLib)
+        m_ml_event_handle.reset(nullptr);
+
+    m_mediaLib = medialib;
+
+    if (m_player && m_mediaLib)
+        initModel();
+}
+
+void MLBookmarkModel::initModel()
+{
+    static const vlc_player_cbs cbs {
+        &onCurrentMediaChanged,
+        &onPlaybackStateChanged,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+        nullptr,
+    };
+    QString uri;
+    {
+        vlc_player_locker lock{ m_player };
+        vlc::threads::mutex_locker selflock{ m_mutex };
+        m_listener = vlc_player_AddListener( m_player, &cbs, this );
+        if ( m_listener == nullptr )
+            throw std::bad_alloc{};
+        auto currentItem = vlc_player_GetCurrentMedia( m_player );
+        m_currentItem = vlc::wrap_cptr( currentItem ? input_item_Hold( currentItem ) : nullptr,
+                                        &input_item_Release );
+        if (m_currentItem)
+        {
+            uri = m_currentItem->psz_uri;
+        }
+    }
+    updateMediaId(0, uri);
+
+    if (m_ml_event_handle == nullptr)
+        m_ml_event_handle.reset(m_mediaLib->registerEventListener(onVlcMlEvent, this));
+}
+
+void MLBookmarkModel::onVlcMlEvent(void* data, const vlc_ml_event_t* event)
+{
+    auto self = static_cast<MLBookmarkModel*>(data);
+    auto  mlEvent = std::make_shared<MLEvent>(event);
+    QMetaObject::invokeMethod(self, [self, mlEvent] () mutable {
+        self->onVlcMlEvent(*mlEvent);
+    });
+}
+
+void MLBookmarkModel::onVlcMlEvent(const MLEvent &event){
+    switch (event.i_type)
+    {
+        case VLC_ML_EVENT_BOOKMARKS_ADDED:
+        case VLC_ML_EVENT_BOOKMARKS_DELETED:
+        case VLC_ML_EVENT_BOOKMARKS_UPDATED:
+            refresh(MLBOOKMARKMODEL_REFRESH);
+        break;
+        default:
+            break;
+    }
+}


=====================================
modules/gui/qt/medialibrary/mlbookmarkmodel.hpp
=====================================
@@ -22,6 +22,10 @@
 #include <QAbstractListModel>
 #include <memory>
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <vlc_common.h>
 #include <vlc_media_library.h>
 #include <vlc_player.h>
@@ -29,15 +33,31 @@
 #include <vlc_cxx_helpers.hpp>
 
 #include "mlhelper.hpp"
+#include "mlevent.hpp"
 
 
+class PlayerController;
 class MediaLib;
 class MLBookmarkModel : public QAbstractListModel
 {
+    Q_OBJECT
+
+    Q_PROPERTY(PlayerController * player READ playerController WRITE setPlayer FINAL)
+
+    Q_PROPERTY(MediaLib * ml READ ml WRITE setMl FINAL)
+
 public:
-    MLBookmarkModel( MediaLib* medialib, vlc_player_t* player, QObject* parent );
+    explicit MLBookmarkModel( QObject* parent = nullptr );
     virtual ~MLBookmarkModel();
 
+    enum BookmarkRoles {
+        NameRole = Qt::UserRole,
+        TimeRole = Qt::UserRole + 1,
+        PositionRole = Qt::UserRole + 2,
+        DescriptionRole = Qt::UserRole + 3
+    };
+    virtual QHash<int, QByteArray> roleNames() const override;
+
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole ) const override;
     bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole ) override;
     Qt::ItemFlags flags( const QModelIndex & ) const override;
@@ -49,18 +69,30 @@ public:
     QVariant headerData( int section, Qt::Orientation orientation, int role ) const override;
     void sort( int column, Qt::SortOrder order ) override;
 
+    vlc_player_t* player() const;
+    void setPlayer(vlc_player_t* player);
+    PlayerController * playerController() const;
+    void setPlayer(PlayerController* playerController);
+    MediaLib* ml() const;
+    void setMl(MediaLib* ml);
+
     void add();
     void remove( const QModelIndexList& indexes );
     void clear();
-    void select( const QModelIndex& index );
+    Q_INVOKABLE void select( const QModelIndex& index );
 
 private:
     static void onCurrentMediaChanged( vlc_player_t* player, input_item_t* media,
                                        void* data );
     static void onPlaybackStateChanged( vlc_player_t* player, vlc_player_state state,
                                         void* data );
+    void playerLengthChanged();
 
     void updateMediaId(uint64_t revision, const QString mediaUri);
+    static void onVlcMlEvent( void* data, const vlc_ml_event_t* event );
+
+    int columnToRole(int column) const;
+    void initModel();
 
     enum RefreshOperation {
         MLBOOKMARKMODEL_REFRESH,
@@ -74,6 +106,7 @@ private:
     MediaLib* m_mediaLib = nullptr;
     vlc_player_t* m_player = nullptr;
     vlc_player_listener_id* m_listener = nullptr;
+    PlayerController* m_player_controller = nullptr;
 
     // Assume to be only used from the GUI thread
     BookmarkListPtr m_bookmarks;
@@ -87,6 +120,11 @@ private:
 
     vlc_ml_sorting_criteria_t m_sort = VLC_ML_SORTING_INSERTIONDATE;
     bool m_desc = false;
+
+protected:
+    std::unique_ptr<vlc_ml_event_callback_t,
+                    std::function<void(vlc_ml_event_callback_t*)>> m_ml_event_handle;
+    virtual void onVlcMlEvent( const MLEvent &event );
 };
 
 #endif // MLBOOKMARKMODEL_HPP


=====================================
modules/gui/qt/menus/custom_menus.cpp
=====================================
@@ -554,7 +554,9 @@ BookmarkMenu::BookmarkMenu(MediaLib * mediaLib, vlc_player_t * player, QWidget *
 
     addSeparator();
 
-    MLBookmarkModel * model = new MLBookmarkModel(mediaLib, player, this);
+    MLBookmarkModel * model = new MLBookmarkModel(this);
+    model->setPlayer(player);
+    model->setMl(mediaLib);
 
     ListMenuHelper * helper = new ListMenuHelper(this, model, nullptr, this);
 


=====================================
modules/gui/qt/menus/qml_menu_wrapper.cpp
=====================================
@@ -479,8 +479,9 @@ bool QmlMenuPositioner::eventFilter(QObject * object, QEvent * event)
 
         m_menu->addSeparator();
 
-        MLBookmarkModel * bookmarks = new MLBookmarkModel(m_ctx->getMediaLibrary(),
-                                                          m_player->getPlayer(), m_menu.get());
+        MLBookmarkModel * bookmarks = new MLBookmarkModel(m_menu.get());
+        bookmarks->setPlayer(m_player->getPlayer());
+        bookmarks->setMl(m_ctx->getMediaLibrary());
 
         helper = new ListMenuHelper(m_menu.get(), bookmarks, nullptr, m_menu.get());
 


=====================================
modules/gui/qt/player/qml/Bookmarks.qml
=====================================
@@ -0,0 +1,119 @@
+/*****************************************************************************
+ * Copyright (C) 2022 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.
+ *****************************************************************************/
+import QtQuick 2.11
+import QtQuick.Controls 2.4
+
+import org.videolan.vlc 0.1
+import org.videolan.medialib 0.1
+
+import "qrc:///widgets/" as Widgets
+import "qrc:///style/"
+
+Item {
+    id: control
+
+    property real barHeight
+    property int yShift
+
+    property VLCColors colors
+
+    property bool controlBarHovered
+
+    property bool bookmarkHovered
+    property string bookmarkText
+    property real bookmarkPosition
+
+    implicitHeight: control.barHeight
+    height: implicitHeight
+
+    visible: false
+    opacity: 0
+
+    Widgets.PointingTooltip {
+        id: timeTooltip
+
+        visible: control.bookmarkHovered
+        text: control.bookmarkText
+        pos: Qt.point(control.bookmarkPosition, - yShift)
+        colors: control.colors
+    }
+
+    transitions: [
+        Transition {
+            to: "hidden"
+            SequentialAnimation {
+                NumberAnimation{
+                    target: control
+                    properties: "opacity"
+                    to: 0
+                    duration: VLCStyle.duration_short; easing.type: Easing.OutSine
+                }
+                PropertyAction { target: control; property: "visible"; value: false; }
+            }
+        },
+        Transition {
+            to: "visible"
+            SequentialAnimation {
+                PropertyAction { target: control; property: "visible"; value: true; }
+                NumberAnimation{
+                    target: control
+                    properties: "opacity"
+                    to: 1
+                    duration: VLCStyle.duration_short; easing.type: Easing.InSine
+                }
+            }
+        }
+    ]
+
+    state: controlBarHovered && bookmarksRptr.count > 0 ? "visible" : "hidden"
+
+    Repeater {
+        id: bookmarksRptr
+        model: MLBookmarkModel {
+            id: modelBookmark
+
+            player: Player
+
+            ml: MediaLib
+        }
+
+        Widgets.IconToolButton {
+            id: bookmarkButton
+
+            size: control.barHeight
+
+            x: control.width * model.position - width/2
+            focusPolicy: Qt.NoFocus
+
+            onClicked: modelBookmark.select(modelBookmark.index(index, 0))
+
+            onHoveredChanged: {
+                if(bookmarkButton.hovered){
+                    control.bookmarkText = model.name
+                    control.bookmarkPosition = x + width/2
+                }
+                control.bookmarkHovered = bookmarkButton.hovered
+            }
+
+            background: Rectangle {
+                radius: parent.width * 0.5
+                color: colors.playerFg
+            }
+        }
+    }
+}


=====================================
modules/gui/qt/player/qml/ControlBar.qml
=====================================
@@ -44,7 +44,7 @@ Control {
     property alias identifier: playerControlLayout.identifier
     property alias sliderHeight: trackPositionSlider.barHeight
     property alias sliderBackgroundColor: trackPositionSlider.backgroundColor
-    property bool showRightTimeText: true
+    property real bookmarksHeight: VLCStyle.icon_xsmall * 0.9
 
     signal requestLockUnlockAutoHide(bool lock)
 
@@ -67,45 +67,48 @@ Control {
     onTextPositionChanged: _layout()
 
     function _layout() {
-        trackPositionSlider.visible = true
-        mediaTime.visible = true
-
-        mediaRemainingTime.visible = Qt.binding(function() { return root.showRightTimeText && textPosition !== ControlBar.TimeTextPosition.Hide; })
-        mediaTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_normal })
-        mediaRemainingTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_normal })
-
-        row2.Layout.leftMargin = 0
-        row2.Layout.rightMargin = 0
-
         switch (textPosition) {
-        case ControlBar.TimeTextPosition.Hide:
-            row1.children = []
-            row2.children = [trackPositionSlider]
-            mediaTime.visible = false
-            break;
-
-        case ControlBar.TimeTextPosition.AboveSlider:
-            var spacer = Qt.createQmlObject("import QtQuick 2.11; Item {}", row1, "ControlBar")
-            row1.children = [mediaTime, spacer, mediaRemainingTime]
-            spacer.Layout.fillWidth = true
-            row2.children = [trackPositionSlider]
-            break;
-
-        case ControlBar.TimeTextPosition.LeftRightSlider:
-            row1.children = []
-            row2.children = [mediaTime, trackPositionSlider, mediaRemainingTime]
-            row2.Layout.leftMargin = Qt.binding(function() { return VLCStyle.margin_xsmall })
-            row2.Layout.rightMargin = Qt.binding(function() { return VLCStyle.margin_xsmall })
-            mediaTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_small })
-            mediaRemainingTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_small })
-            trackPositionSlider.Layout.alignment = Qt.AlignVCenter
-            break;
-
-        default:
-            console.assert(false, "invalid text position")
+            case ControlBar.TimeTextPosition.Hide:
+                row1.children = []
+                row2.children = [trackPositionSlider]
+                mediaTime.visible = false
+                mediaRemainingTime.visible = false
+                spacer.visible = false
+                row2.Layout.leftMargin = 0
+                row2.Layout.rightMargin = 0
+                mediaTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_normal })
+                mediaRemainingTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_normal })
+                break;
+
+            case ControlBar.TimeTextPosition.AboveSlider:
+                row1.children = [mediaTime, spacer, mediaRemainingTime]
+                row2.children = [trackPositionSlider]
+                mediaTime.visible = true
+                mediaRemainingTime.visible = Qt.binding(function() { return !playlistVisibility.isPlaylistVisible })
+                spacer.visible = true
+                row2.Layout.leftMargin = 0
+                row2.Layout.rightMargin = 0
+                mediaTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_normal })
+                mediaRemainingTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_normal })
+                break;
+
+            case ControlBar.TimeTextPosition.LeftRightSlider:
+                row1.children = []
+                row2.children = [mediaTime, trackPositionSlider, mediaRemainingTime]
+                mediaTime.visible = true
+                mediaRemainingTime.visible = true
+                spacer.visible = false
+                row2.Layout.leftMargin = VLCStyle.margin_xsmall
+                row2.Layout.rightMargin = VLCStyle.margin_xsmall
+                mediaTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_small })
+                mediaRemainingTime.font.pixelSize = Qt.binding(function() { return VLCStyle.fontSize_small })
+                trackPositionSlider.Layout.alignment = Qt.AlignVCenter
+                break;
+
+            default:
+                console.assert(false, "invalid text position")
         }
 
-        trackPositionSlider.Layout.fillWidth = true
         row1.visible = row1.children.length > 0
         row2.visible = row2.children.length > 0
     }
@@ -114,6 +117,7 @@ Control {
         id: columnLayout
 
         spacing: VLCStyle.margin_xsmall
+        z: 1
 
         RowLayout {
             id: row1
@@ -147,26 +151,20 @@ Control {
         }
     }
 
-    //FIXME use the right xxxLabel class
     T.Label {
         id: mediaTime
 
-        visible: false
         text: Player.time.formatHMS()
         color: root.colors.playerFg
-        font.pixelSize: VLCStyle.fontSize_normal
     }
 
-    //FIXME use the right xxxLabel class
     T.Label {
         id: mediaRemainingTime
 
-        visible: false
         text: (MainCtx.showRemainingTime && Player.remainingTime.valid())
               ? "-" + Player.remainingTime.formatHMS()
               : Player.length.formatHMS()
         color: root.colors.playerFg
-        font.pixelSize: VLCStyle.fontSize_normal
 
         MouseArea {
             anchors.fill: parent
@@ -174,12 +172,18 @@ Control {
         }
     }
 
+    Item {
+        id: spacer
+
+        Layout.fillWidth: true
+    }
+
     SliderBar {
         id: trackPositionSlider
 
-        visible: false
         backgroundColor: colors.playerSeekBar
         barHeight: VLCStyle.heightBar_xxsmall
+        Layout.fillWidth: true
         enabled: Player.playingState === Player.PLAYING_STATE_PLAYING || Player.playingState === Player.PLAYING_STATE_PAUSED
         colors: root.colors
 
@@ -190,4 +194,22 @@ Control {
             Navigation.defaultKeyAction(event)
         }
     }
+
+    Loader {
+        id: bookmarksLoader
+
+        active: MainCtx.mediaLibraryAvailable
+        source: "qrc:/player/Bookmarks.qml"
+
+        x: root.leftPadding + trackPositionSlider.x + row2.Layout.leftMargin
+        y: row2.y + row2.height + VLCStyle.margin_xxsmall
+        width: trackPositionSlider.width
+
+        onLoaded: {
+           item.colors = Qt.binding(function() { return root.colors })
+           item.barHeight = Qt.binding(function() { return bookmarksHeight })
+           item.controlBarHovered = Qt.binding(function() { return root.hovered })
+           item.yShift = Qt.binding(function() { return row2.height + VLCStyle.margin_xxsmall })
+        }
+    }
 }


=====================================
modules/gui/qt/player/qml/MiniPlayer.qml
=====================================
@@ -89,6 +89,7 @@ FocusScope {
         textPosition: ControlBar.TimeTextPosition.Hide
         sliderHeight: VLCStyle.dp(3, VLCStyle.scale)
         sliderBackgroundColor: colors.sliderBarMiniplayerBgColor
+        bookmarksHeight: VLCStyle.icon_xsmall * 0.7
         identifier: PlayerControlbarModel.Miniplayer
         Navigation.parentItem: root
 


=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -608,7 +608,6 @@ FocusScope {
 
                 colors: rootPlayer.colors
                 textPosition: rootPlayer.pinVideoControls ? ControlBar.TimeTextPosition.LeftRightSlider : ControlBar.TimeTextPosition.AboveSlider
-                showRightTimeText: (textPosition !== ControlBar.TimeTextPosition.AboveSlider) || !playlistVisibility.isPlaylistVisible
 
                 Navigation.parentItem: rootPlayer
                 Navigation.upItem: playlistpopup.showPlaylist ? playlistpopup : (audioControls.visible ? audioControls : topcontrolView)


=====================================
modules/gui/qt/player/qml/SliderBar.qml
=====================================
@@ -29,7 +29,7 @@ import "qrc:///util/Helpers.js" as Helpers
 Slider {
     id: control
 
-    readonly property real _hoveredScalingFactor: 2
+    readonly property real _hoveredScalingFactor: 1.8
     property int barHeight: VLCStyle.dp(5, VLCStyle.scale)
     readonly property real _scaledBarHeight: control.barHeight * _hoveredScalingFactor
     readonly property real _scaledY: (-control.barHeight / 2) * (control._hoveredScalingFactor - 1)
@@ -145,8 +145,8 @@ Slider {
         fsm.playerUpdatePosition(Player.position)
     }
 
-    height: control.barHeight
     implicitHeight: control.barHeight
+    height: implicitHeight
 
     padding: 0
 
@@ -230,6 +230,7 @@ Slider {
                         anchors.left: parent.left
                         anchors.top: parent.top
                         anchors.bottom: parent.bottom
+                        radius: parent.radius
 
                         width: sliderRect.width * control.visualPosition - parent.x - control._seekPointsDistance
                         visible: parent._currentChapter === 0
@@ -376,11 +377,13 @@ Slider {
     handle: Rectangle {
         id: sliderHandle
 
+        property int _size: control.barHeight * 3
+
         x: (control.visualPosition * control.availableWidth) - width / 2
         y: (control.barHeight - height) / 2
 
-        implicitWidth: VLCStyle.margin_small
-        implicitHeight: VLCStyle.margin_small
+        implicitWidth: sliderHandle._size
+        implicitHeight: sliderHandle._size
         radius: VLCStyle.margin_small
         color: control.colors.accent
 
@@ -402,7 +405,7 @@ Slider {
                     PropertyAction { target: sliderHandle; property: "visible"; value: true; }
                     NumberAnimation {
                         target: sliderHandle; properties: "implicitWidth,implicitHeight"
-                        to: VLCStyle.margin_small
+                        to: sliderHandle._size
                         duration: VLCStyle.duration_short; easing.type: Easing.InSine
                     }
                 }
@@ -413,7 +416,7 @@ Slider {
                     PropertyAction { target: sliderHandle; property: "visible"; value: true; }
                     NumberAnimation {
                         target: sliderHandle; properties: "implicitWidth,implicitHeight"
-                        to: VLCStyle.margin_small * (0.75 * control._hoveredScalingFactor)
+                        to: sliderHandle._size * (0.8 * control._hoveredScalingFactor)
                         duration: VLCStyle.duration_short; easing.type: Easing.InSine
                     }
                 }


=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -311,6 +311,7 @@
         <file alias="PlayerPlaylistVisibilityFSM.qml">player/qml/PlayerPlaylistVisibilityFSM.qml</file>
         <file alias="PlayerBlurredBackground.qml">player/qml/PlayerBlurredBackground.qml</file>
         <file alias="PlayerBlurredBackground.frag">player/qml/PlayerBlurredBackground.frag</file>
+        <file alias="Bookmarks.qml">player/qml/Bookmarks.qml</file>
     </qresource>
     <qresource prefix="/player/controlbarcontrols">
         <file alias="HighResolutionTimeWidget.qml">player/qml/controlbarcontrols/HighResolutionTimeWidget.qml</file>



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/570ec04c66efc837d6008f579105f417e3618ab5...5510bdbbd02b5aed61ab115a6e6f6f869624c0c8

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/570ec04c66efc837d6008f579105f417e3618ab5...5510bdbbd02b5aed61ab115a6e6f6f869624c0c8
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list