[vlc-commits] [Git][videolan/vlc][master] 4 commits: qt: introduce `RadioButtonExt.qml`

Steve Lhomme (@robUx4) gitlab at videolan.org
Mon Apr 7 14:48:45 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
4d4a4e8b by Fatih Uzunoglu at 2025-04-07T14:34:32+00:00
qt: introduce `RadioButtonExt.qml`

Based on Qt Quick Basic Style, the difference being mainly
custom colorization and sizing.

- - - - -
5f38a4c9 by Fatih Uzunoglu at 2025-04-07T14:34:32+00:00
qml: use radio buttons instead of combo box in `PlaybackSpeed.qml`

Having radio buttons requires one click less to adjust the speed
from the presets.

- - - - -
d00c68a3 by Fatih Uzunoglu at 2025-04-07T14:34:32+00:00
qml: do not use `Layout.topMargin` when the layout already provides `spacing`

- - - - -
09d3f991 by Fatih Uzunoglu at 2025-04-07T14:34:32+00:00
qml: close the playback speed popup when a radio button is clicked

- - - - -


5 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/meson.build
- modules/gui/qt/player/qml/PlaybackSpeed.qml
- modules/gui/qt/player/qml/controlbarcontrols/PlaybackSpeedButton.qml
- + modules/gui/qt/widgets/qml/RadioButtonExt.qml


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -1302,7 +1302,8 @@ libqml_module_widgets_a_QML = \
 	widgets/qml/RectangularGlow.qml \
 	widgets/qml/ImageExt.qml \
 	widgets/qml/ScrollBarExt.qml \
-	widgets/qml/FastBlend.qml
+	widgets/qml/FastBlend.qml \
+	widgets/qml/RadioButtonExt.qml
 if HAVE_QT65
 libqml_module_widgets_a_QML += \
 	widgets/qml/DynamicShadow.qml \


=====================================
modules/gui/qt/meson.build
=====================================
@@ -902,6 +902,7 @@ qml_modules += {
         'widgets/qml/ImageExt.qml',
         'widgets/qml/ScrollBarExt.qml',
         'widgets/qml/FastBlend.qml',
+        'widgets/qml/RadioButtonExt.qml',
     ),
 }
 


=====================================
modules/gui/qt/player/qml/PlaybackSpeed.qml
=====================================
@@ -18,6 +18,7 @@
 
 import QtQuick
 import QtQuick.Controls
+import QtQuick.Templates as T
 import QtQuick.Layouts
 
 
@@ -32,16 +33,9 @@ ColumnLayout {
 
     property alias slider: slider
 
-    // Private
+    signal radioButtonClicked(T.AbstractButton button)
 
-    property var _model: [{ "value": 0.25 },
-                          { "value": 0.5 },
-                          { "value": 0.75 },
-                          { "value": 1, "title": qsTr("Normal") },
-                          { "value": 1.25 },
-                          { "value": 1.5 },
-                          { "value": 1.75 },
-                          { "value": 2 }]
+    // Private
 
     // NOTE: 0.96 and 1.04 are useful for video enthusiasts.
     property var _values: [ 0.25, 0.5, 0.75, 0.96, 1.0, 1.04, 1.25, 1.5, 1.75, 2 ]
@@ -67,39 +61,19 @@ ColumnLayout {
     Layout.fillWidth: true
     Layout.fillHeight: true
 
+    spacing: VLCStyle.margin_normal
+
     // Events
 
     Component.onCompleted: _updateValue(Player.rate)
 
     // Function
 
-    function _updateComboBox(value) {
-        // NOTE: We want a rounded 1.xx value.
-        value = Math.round(value * 100) / 100
-
-        for (let i = 0; i < _model.length; i++) {
-            if (Helpers.compareFloat(_model[i].value, value) === false)
-                continue
-
-            comboBox.currentIndex = i
-
-            _value = value
-
-            return;
-        }
-
-        comboBox.currentIndex = -1
-
-        _value = value
-    }
-
     function _updateValue(value) {
         _update = false
 
         _applySlider(value)
 
-        _updateComboBox(value)
-
         _update = true
     }
 
@@ -138,8 +112,6 @@ ColumnLayout {
 
         Player.rate = value
 
-        _updateComboBox(value)
-
         _update = true
     }
 
@@ -180,7 +152,6 @@ ColumnLayout {
         id: rowA
 
         Layout.fillWidth: true
-        Layout.topMargin: VLCStyle.margin_xsmall
 
         Layout.alignment: Qt.AlignTop
 
@@ -214,7 +185,7 @@ ColumnLayout {
         id: slider
 
         Layout.fillWidth: true
-        Layout.topMargin: VLCStyle.margin_xsmall
+
         topPadding: 0
 
         // NOTE: These values come from the VLC 3.x implementation.
@@ -232,7 +203,6 @@ ColumnLayout {
         toolTipFollowsMouse: true
 
         Navigation.parentItem: root
-        Navigation.downItem: comboBox
 
         Keys.priority: Keys.AfterItem
         Keys.onPressed: (event) => Navigation.defaultKeyAction(event)
@@ -266,56 +236,48 @@ ColumnLayout {
         }
     }
 
-    RowLayout {
-        id: rowB
-
+    Widgets.ListLabel {
+        text: qsTr("Presets:")
+        color: colorContext.fg.primary
         Layout.fillWidth: true
-        Layout.topMargin: VLCStyle.margin_xsmall
+    }
 
-        Navigation.parentItem: root
-        Navigation.upItem: slider
+    GridLayout {
+        Layout.fillWidth: true
+        Layout.fillHeight: true
 
-        Widgets.ListLabel {
-            text: qsTr("Presets")
-            color: colorContext.fg.primary
-            Layout.fillWidth: true
-        }
+        rows: radioButtonRepeater.count / 2 // two columns
+        flow: GridLayout.TopToBottom
 
-        Widgets.ComboBoxExt {
-            id: comboBox
+        rowSpacing: VLCStyle.margin_small
+        columnSpacing: VLCStyle.margin_small
 
-            Layout.preferredWidth: VLCStyle.combobox_width_normal
-            Layout.preferredHeight: VLCStyle.combobox_height_normal
+        ButtonGroup {
+            id: buttonGroup
 
-            model: ListModel {}
+            onClicked: function(button /* : AbstractButton */) {
+                Player.rate = button.modelData
+                root.radioButtonClicked(button)
+            }
+        }
 
-            // NOTE: We display the 'Normal' string when the Slider is centered.
-            displayText: (currentIndex === 3) ? currentText
-                                              : root._value
+        Repeater {
+            id: radioButtonRepeater
 
-            Navigation.parentItem: rowB
+            model: root._values
 
-            // NOTE: This makes the navigation possible since 'up' is changing the comboBox value.
-            Navigation.leftItem: slider
+            delegate: Widgets.RadioButtonExt {
+                required property double modelData
 
-            Component.onCompleted: {
-                for (let i = 0; i < _model.length; i++) {
-                    const item = _model[i]
+                Layout.fillWidth: true
 
-                    const title = item.title
+                text: modelData
 
-                    if (title)
-                        model.append({ "title": title })
-                    else
-                        model.append({ "title": String(item.value) })
-                }
-            }
+                checked: Math.abs(Player.rate - modelData) < 0.01 // need some generous epsilon here
 
-            onCurrentIndexChanged: {
-                if (root._update === false || currentIndex === -1)
-                    return
+                padding: 0 // we use spacing instead of paddings here
 
-                root._applySlider(_model[currentIndex].value)
+                ButtonGroup.group: buttonGroup
             }
         }
     }


=====================================
modules/gui/qt/player/qml/controlbarcontrols/PlaybackSpeedButton.qml
=====================================
@@ -42,6 +42,10 @@ PopupIconToolButton {
 
         // NOTE: Mapping the right direction because the down action triggers the ComboBox.
         Navigation.rightItem: root
+
+        onRadioButtonClicked: {
+            root.popup.close()
+        }
     }
 
     contentItem: Item {


=====================================
modules/gui/qt/widgets/qml/RadioButtonExt.qml
=====================================
@@ -0,0 +1,79 @@
+/*****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ * Copyright (C) 2017 The Qt Company Ltd.
+ *
+ * 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
+import QtQuick.Templates as T
+
+import VLC.Style
+
+// Based on Qt Quick Basic Style:
+T.RadioButton {
+    id: control
+
+    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+                            implicitContentWidth + leftPadding + rightPadding)
+    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+                             implicitContentHeight + topPadding + bottomPadding,
+                             implicitIndicatorHeight + topPadding + bottomPadding)
+
+    padding: VLCStyle.margin_xxsmall
+    spacing: VLCStyle.margin_xxsmall
+
+    readonly property ColorContext colorContext: ColorContext {
+        id: theme
+        colorSet: ColorContext.ButtonStandard
+
+        focused: control.visualFocus
+        hovered: control.hovered
+        enabled: control.enabled
+        pressed: control.down
+    }
+
+    // keep in sync with RadioDelegate.qml (shared RadioIndicator.qml was removed for performance reasons)
+    indicator: Rectangle {
+        implicitWidth: control.contentItem ? implicitHeight : VLCStyle.dp(28, VLCStyle.scale)
+        implicitHeight: control.contentItem ? control.contentItem.implicitHeight : VLCStyle.dp(28, VLCStyle.scale)
+
+        x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
+        y: control.topPadding + (control.availableHeight - height) / 2
+
+        radius: width / 2
+        color: control.down ? Qt.lighter(theme.accent) : theme.bg.primary
+        border.width: control.visualFocus ? VLCStyle.dp(2, VLCStyle.scale) : VLCStyle.dp(1, VLCStyle.scale)
+        border.color: control.visualFocus ? theme.accent : (theme.palette.isDark ? Qt.lighter(theme.separator) : Qt.darker(theme.separator))
+
+        Rectangle {
+            x: (parent.width - width) / 2
+            y: (parent.height - height) / 2
+            width: parent.width * 3 / 4
+            height: parent.height * 3 / 4
+            radius: width / 2
+            color: theme.accent
+            visible: control.checked
+        }
+    }
+
+    contentItem: ListLabel {
+        leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0
+        rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0
+
+        text: control.text
+        color: theme.fg.primary
+    }
+}



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9ec4c3dfeb154827eca1fbd18788293fb6236131...09d3f9914cd3ab27cbbb0a14a65c21c8d431be76

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9ec4c3dfeb154827eca1fbd18788293fb6236131...09d3f9914cd3ab27cbbb0a14a65c21c8d431be76
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