[vlc-commits] [Git][videolan/vlc][master] 3 commits: qt: Create control_list_filter

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Fri Mar 11 10:33:46 UTC 2022



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
026b9db3 by Benjamin Arnaud at 2022-03-11T09:41:32+00:00
qt: Create control_list_filter

- - - - -
50df9c28 by Benjamin Arnaud at 2022-03-11T09:41:32+00:00
qml/PlayerControlLayout: Add ControlListFilter(s) to hide unnecessary buttons

fix #26607

- - - - -
dcc4520c by Benjamin Arnaud at 2022-03-11T09:41:32+00:00
qml/ControlLayout: Update keyboard navigation implementation

Our prior implementation couldn't handle a model invalidate() properly and ended up corrupting
the keyboard navigation.

- - - - -


7 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/mainui.cpp
- + modules/gui/qt/player/control_list_filter.cpp
- + modules/gui/qt/player/control_list_filter.hpp
- modules/gui/qt/player/qml/ControlLayout.qml
- modules/gui/qt/player/qml/PlayerControlLayout.qml
- po/POTFILES.in


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -228,6 +228,8 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/player/player_controller.cpp gui/qt/player/player_controller.hpp gui/qt/player/player_controller_p.hpp \
 	gui/qt/player/player_controlbar_model.cpp gui/qt/player/player_controlbar_model.hpp \
 	gui/qt/player/control_list_model.cpp gui/qt/player/control_list_model.hpp \
+	gui/qt/player/control_list_filter.cpp \
+	gui/qt/player/control_list_filter.hpp \
 	gui/qt/playlist/media.hpp \
 	gui/qt/playlist/playlist_common.cpp \
 	gui/qt/playlist/playlist_common.hpp \
@@ -424,6 +426,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/player/player_controller.moc.cpp \
 	gui/qt/player/player_controlbar_model.moc.cpp \
 	gui/qt/player/control_list_model.moc.cpp \
+	gui/qt/player/control_list_filter.moc.cpp \
 	gui/qt/playlist/playlist_common.moc.cpp \
 	gui/qt/playlist/playlist_controller.moc.cpp \
 	gui/qt/playlist/playlist_item.moc.cpp \


=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -22,6 +22,7 @@
 #include "player/player_controller.hpp"
 #include "player/player_controlbar_model.hpp"
 #include "player/control_list_model.hpp"
+#include "player/control_list_filter.hpp"
 
 #include "dialogs/toolbar/controlbar_profile_model.hpp"
 #include "dialogs/toolbar/controlbar_profile.hpp"
@@ -255,6 +256,7 @@ void MainUI::registerQMLTypes()
         qmlRegisterUncreatableType<ControlbarProfile>(uri, versionMajor, versionMinor, "ControlbarProfile", "");
         qmlRegisterUncreatableType<PlayerControlbarModel>(uri, versionMajor, versionMinor, "PlayerControlbarModel", "");
         qmlRegisterUncreatableType<ControlListModel>( uri, versionMajor, versionMinor, "ControlListModel", "" );
+        qmlRegisterType<ControlListFilter>(uri, versionMajor, versionMinor, "ControlListFilter");
         qmlRegisterSingletonType(uri, versionMajor, versionMinor, "PlayerListModel", PlayerControlbarModel::getPlaylistIdentifierListModel);
 
         qmlRegisterType<StringListMenu>( uri, versionMajor, versionMinor, "StringListMenu" );


=====================================
modules/gui/qt/player/control_list_filter.cpp
=====================================
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Benjamin Arnaud <bunjee at omega.gg>
+ *
+ * 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 "control_list_filter.hpp"
+
+// Player includes
+#include "player_controller.hpp"
+#include "control_list_model.hpp"
+
+// Ctor / dtor
+
+/* explicit */ ControlListFilter::ControlListFilter(QObject * parent)
+    : QSortFilterProxyModel(parent) {}
+
+// QAbstractProxyModel reimplementation
+
+void ControlListFilter::setSourceModel(QAbstractItemModel * sourceModel) /* override */
+{
+    assert(sourceModel->inherits("ControlListModel"));
+
+    QSortFilterProxyModel::setSourceModel(sourceModel);
+}
+
+// Protected QSortFilterProxyModel reimplementation
+
+bool ControlListFilter::filterAcceptsRow(int source_row, const QModelIndex &) const /* override */
+{
+    QAbstractItemModel * model = sourceModel();
+
+    if (model == nullptr || m_player == nullptr)
+        return true;
+
+    QVariant variant = model->data(model->index(source_row, 0), ControlListModel::ID_ROLE);
+
+    if (variant.isValid() == false)
+        return true;
+
+    ControlListModel::ControlType type
+        = static_cast<ControlListModel::ControlType> (variant.toInt());
+
+    // NOTE: These controls are completely hidden when the current media does not support them.
+    if (type == ControlListModel::TELETEXT_BUTTONS)
+    {
+        return m_player->isTeletextAvailable();
+    }
+    else if (type == ControlListModel::DVD_MENUS_BUTTON)
+    {
+        return m_player->hasMenu();
+    }
+
+    return true;
+}
+
+// Properties
+
+PlayerController * ControlListFilter::player()
+{
+    return m_player;
+}
+
+void ControlListFilter::setPlayer(PlayerController * player)
+{
+    if (m_player == player) return;
+
+    if (m_player)
+        disconnect(m_player, nullptr, this, nullptr);
+
+    m_player = player;
+
+    connect(player, &PlayerController::teletextAvailableChanged, this, &ControlListFilter::invalidate);
+    connect(player, &PlayerController::hasMenuChanged,           this, &ControlListFilter::invalidate);
+
+    invalidate();
+
+    emit playerChanged();
+}


=====================================
modules/gui/qt/player/control_list_filter.hpp
=====================================
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Benjamin Arnaud <bunjee at omega.gg>
+ *
+ * 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 CONTROLLISTFILTER_HPP
+#define CONTROLLISTFILTER_HPP
+
+// Qt includes
+#include <QSortFilterProxyModel>
+
+// Forward declarations
+class PlayerController;
+
+class ControlListFilter : public QSortFilterProxyModel
+{
+    Q_OBJECT
+
+    Q_PROPERTY(PlayerController * player READ player WRITE setPlayer NOTIFY playerChanged)
+
+public:
+    explicit ControlListFilter(QObject * parent = nullptr);
+
+public: // QAbstractProxyModel reimplementation
+    void setSourceModel(QAbstractItemModel * sourceModel) override;
+
+protected: // QSortFilterProxyModel reimplementation
+    bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override;
+
+signals:
+    void playerChanged();
+
+public: // Properties
+    PlayerController * player();
+    void setPlayer(PlayerController * player);
+
+private: // Variables
+    PlayerController * m_player = nullptr;
+};
+
+#endif // CONTROLLISTFILTER_HPP


=====================================
modules/gui/qt/player/qml/ControlLayout.qml
=====================================
@@ -92,7 +92,13 @@ FocusScope {
         Repeater {
             id: repeater
 
+            // NOTE: We apply the 'navigation chain' after adding the item.
+            onItemAdded: item.applyNavigation()
+
             onItemRemoved: {
+                // NOTE: We update the 'navigation chain' after removing the item.
+                item.removeNavigation()
+
                 item.recoverFocus(index)
             }
 
@@ -129,23 +135,7 @@ FocusScope {
                     value: (loader.x + minimumWidth <= rowLayout.width)
                 }
 
-                function buildFocusChain() {
-                    // rebuild the focus chain:
-                    if (typeof repeater === "undefined")
-                        return
-
-                    var rightItem = repeater.itemAt(index + 1)
-                    var leftItem = repeater.itemAt(index - 1)
-
-                    item.Navigation.rightItem = !!rightItem ? rightItem.item : null
-                    item.Navigation.leftItem = !!leftItem ? leftItem.item : null
-                }
-
-                Component.onCompleted: {
-                    repeater.countChanged.connect(loader.buildFocusChain)
-                    repeater.modelChanged.connect(loader.buildFocusChain)
-                    repeater.countChanged.connect(controlLayout._handleFocus)
-                }
+                Component.onCompleted: repeater.countChanged.connect(controlLayout._handleFocus)
 
                 onActiveFocusChanged: {
                     if (activeFocus && (!!item && !item.focus)) {
@@ -190,6 +180,47 @@ FocusScope {
                     item.visible = Qt.binding(function() { return loader.visible })
                 }
 
+                function applyNavigation() {
+                    var itemLeft  = repeater.itemAt(index - 1)
+                    var itemRight = repeater.itemAt(index + 1)
+
+                    if (itemLeft) {
+                        var componentLeft = itemLeft.item;
+
+                        item.Navigation.leftItem = componentLeft
+
+                        componentLeft.Navigation.rightItem = item
+                    }
+
+                    if (itemRight) {
+                        var componentRight = itemRight.item;
+
+                        item.Navigation.rightItem = componentRight
+
+                        componentRight.Navigation.leftItem = item
+                    }
+                }
+
+                function removeNavigation() {
+                    var itemLeft = repeater.itemAt(index - 1)
+
+                    // NOTE: The current item was removed from the repeater so we test against the
+                    //       same index.
+                    var itemRight = repeater.itemAt(index)
+
+                    if (itemLeft) {
+                        if (itemRight) {
+                            itemLeft.item.Navigation.rightItem = itemRight.item
+                            itemRight.item.Navigation.leftItem = itemLeft.item
+                        }
+                        else
+                            itemLeft.item.Navigation.rightItem = null
+                    }
+                    else if (itemRight) {
+                        itemRight.item.Navigation.leftItem = null
+                    }
+                }
+
                 function _focusIfFocusable(_loader) {
                     if (!!_loader && !!_loader.item && _loader.item.focus) {
                         if (item.focusReason !== undefined)


=====================================
modules/gui/qt/player/qml/PlayerControlLayout.qml
=====================================
@@ -68,7 +68,11 @@ FocusScope {
         focus: true
 
         sourceComponent: ControlLayout {
-            model: playerControlLayout.model.left
+            model: ControlListFilter {
+                sourceModel: playerControlLayout.model.left
+
+                player: Player
+            }
 
             Navigation.parentItem: playerControlLayout
             Navigation.rightItem: layoutLoader_center.item
@@ -95,7 +99,11 @@ FocusScope {
                                               : implicitWidth
 
         sourceComponent: ControlLayout {
-            model: playerControlLayout.model.center
+            model: ControlListFilter {
+                sourceModel: playerControlLayout.model.center
+
+                player: Player
+            }
 
             Navigation.parentItem: playerControlLayout
             Navigation.leftItem: layoutLoader_left.item
@@ -123,7 +131,11 @@ FocusScope {
                 && !!playerControlLayout.model.right
 
         sourceComponent: ControlLayout {
-            model: playerControlLayout.model.right
+            model: ControlListFilter {
+                sourceModel: playerControlLayout.model.right
+
+                player: Player
+            }
 
             rightAligned: true
 


=====================================
po/POTFILES.in
=====================================
@@ -817,6 +817,8 @@ modules/gui/qt/util/validators.cpp
 modules/gui/qt/util/validators.hpp
 modules/gui/qt/player/player_controlbar_model.cpp
 modules/gui/qt/player/player_controlbar_model.hpp
+modules/gui/qt/player/control_list_filter.cpp
+modules/gui/qt/player/control_list_filter.hpp
 modules/gui/qt/dialogs/dialogs/qml/CustomDialog.qml
 modules/gui/qt/dialogs/dialogs/qml/Dialogs.qml
 modules/gui/qt/dialogs/dialogs/qml/WindowDialog.qml



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b5923a21d65d4e33dcc498a204a0ecc82437153e...dcc4520cd9257fdcc77582e18853e6f46ddb4a07

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b5923a21d65d4e33dcc498a204a0ecc82437153e...dcc4520cd9257fdcc77582e18853e6f46ddb4a07
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