[vlc-commits] [Git][videolan/vlc][master] 2 commits: qt/qml: chapters UI redesign

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Fri Jul 22 09:47:31 UTC 2022



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


Commits:
8ed9912b by Leon Vitanos at 2022-07-22T09:19:45+00:00
qt/qml: chapters UI redesign

- - - - -
ce53cd1e by Leon Vitanos at 2022-07-22T09:19:45+00:00
qml: fix activeFocus issue by using invalidateFilter instead of invalidate

- - - - -


4 changed files:

- modules/gui/qt/player/control_list_filter.cpp
- modules/gui/qt/player/input_models.cpp
- modules/gui/qt/player/input_models.hpp
- modules/gui/qt/player/qml/SliderBar.qml


Changes:

=====================================
modules/gui/qt/player/control_list_filter.cpp
=====================================
@@ -45,7 +45,7 @@ bool ControlListFilter::filterAcceptsRow(int source_row, const QModelIndex &) co
 {
     QAbstractItemModel * model = sourceModel();
 
-    if (model == nullptr || m_player == nullptr)
+    if (model == nullptr || m_player == nullptr || m_ctx == nullptr)
         return true;
 
     QVariant variant = model->data(model->index(source_row, 0), ControlListModel::ID_ROLE);
@@ -63,11 +63,9 @@ bool ControlListFilter::filterAcceptsRow(int source_row, const QModelIndex &) co
     }
     else if (type == ControlListModel::BOOKMARK_BUTTON)
     {
-        assert(m_ctx);
         return (m_ctx->hasMediaLibrary() || m_player->hasChapters() || m_player->hasTitles());
     }
 
-
     return true;
 }
 
@@ -87,10 +85,10 @@ void ControlListFilter::setPlayer(PlayerController * player)
 
     m_player = player;
 
-    connect(player, &PlayerController::teletextAvailableChanged, this, &ControlListFilter::invalidate);
-    connect(player, &PlayerController::hasMenuChanged,           this, &ControlListFilter::invalidate);
-    connect(player, &PlayerController::hasChaptersChanged,       this, &ControlListFilter::invalidate);
-    connect(player, &PlayerController::hasTitlesChanged,         this, &ControlListFilter::invalidate);
+    connect(player, &PlayerController::teletextAvailableChanged, this, &ControlListFilter::invalidateFilter);
+    connect(player, &PlayerController::hasMenuChanged,           this, &ControlListFilter::invalidateFilter);
+    connect(player, &PlayerController::hasChaptersChanged,       this, &ControlListFilter::invalidateFilter);
+    connect(player, &PlayerController::hasTitlesChanged,         this, &ControlListFilter::invalidateFilter);
 
     invalidate();
 


=====================================
modules/gui/qt/player/input_models.cpp
=====================================
@@ -325,8 +325,13 @@ QVariant ChapterListModel::data(const QModelIndex &index, int role) const
         return QVariant::fromValue<bool>(row == m_current);
     else if (role == ChapterListRoles::TimeRole )
         return QVariant::fromValue<vlc_tick_t>(chapter.time);
-    else if (role == ChapterListRoles::PositionRole && (m_title->length != 0) )
-        return QVariant::fromValue<float>(chapter.time /(float) m_title->length);
+    else if (role == ChapterListRoles::StartPositionRole && (m_title->length != 0))
+        return QVariant::fromValue<float>(chapter.time / (float) m_title->length);
+    else if (role == ChapterListRoles::EndPositionRole && (m_title->length != 0))
+        return (size_t)row + 1 == m_title->chapter_count
+                ? QVariant::fromValue<float> (1)
+                : QVariant::fromValue<float> (m_title->chapters[row+1].time / (float) m_title->length);
+
     return QVariant{};
 }
 
@@ -354,7 +359,8 @@ QHash<int, QByteArray> ChapterListModel::roleNames() const
         {Qt::DisplayRole, "display"},
         {Qt::CheckStateRole, "checked"},
         {ChapterListRoles::TimeRole, "time"},
-        {ChapterListRoles::PositionRole, "position"}
+        {ChapterListRoles::StartPositionRole, "startPosition"},
+        {ChapterListRoles::EndPositionRole, "endPosition"}
     };
 }
 
@@ -436,6 +442,8 @@ int ChapterListModel::getClosestChapterFromPos(float pos, float threshold) const
             closestTime = currentChapterTime;
             chapterIndex = i;
         }
+        else
+            break;
     }
 
     if (closestTime == VLC_TICK_INVALID)


=====================================
modules/gui/qt/player/input_models.hpp
=====================================
@@ -165,7 +165,8 @@ public:
     //user role
     enum ChapterListRoles {
         TimeRole = Qt::UserRole + 1 ,
-        PositionRole
+        StartPositionRole,
+        EndPositionRole
     };
 public:
     ChapterListModel(vlc_player_t* player, QObject* parent = nullptr);


=====================================
modules/gui/qt/player/qml/SliderBar.qml
=====================================
@@ -29,13 +29,20 @@ import "qrc:///util/Helpers.js" as Helpers
 Slider {
     id: control
 
+    readonly property real _hoveredScalingFactor: 2
     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)
+
     property bool _isSeekPointsShown: true
+    readonly property int _seekPointsDistance: VLCStyle.dp(2, VLCStyle.scale)
+    readonly property int _seekPointsRadius: VLCStyle.dp(0.5, VLCStyle.scale)
+    readonly property real _scaledSeekPointsRadius: _seekPointsRadius * _hoveredScalingFactor
+
+    property bool _currentChapterHovered: false
     property real _tooltipPosition: timeTooltip.pos.x / sliderRectMouseArea.width
 
     property alias backgroundColor: sliderRect.color
-    property alias progressBarColor: progressRect.color
-
     property VLCColors colors: VLCStyle.colors
 
     Keys.onRightPressed: Player.jumpFwd()
@@ -134,28 +141,37 @@ Slider {
         onPositionChanged: fsm.playerUpdatePosition(Player.position)
     }
 
+    Component.onCompleted:  {
+        fsm.playerUpdatePosition(Player.position)
+    }
+
     height: control.barHeight
     implicitHeight: control.barHeight
 
-    topPadding: 0
-    leftPadding: 0
-    bottomPadding: 0
-    rightPadding: 0
+    padding: 0
 
     stepSize: 0.01
 
-    background: Rectangle {
-        id: sliderRect
+    background: Item {
+        id: slider
         width: control.availableWidth
         implicitHeight: control.implicitHeight
         height: implicitHeight
-        color: control.colors.setColorAlpha( control.colors.playerFg, 0.2 )
-        radius: implicitHeight
+
+        Rectangle {
+            id: sliderRect
+            visible: !Player.hasChapters
+            color: backgroundColor
+            anchors.fill: parent
+            radius: implicitHeight
+        }
 
         MouseArea {
             id: sliderRectMouseArea
 
-            anchors.fill: parent
+            width: control.availableWidth
+            height: control._scaledBarHeight
+            y: control._scaledY
 
             hoverEnabled: true
 
@@ -175,12 +191,101 @@ Slider {
             }
         }
 
+        Repeater {
+            id: seekpointsRptr
+
+            anchors.left: parent.left
+            anchors.right: parent.right
+            height: control.barHeight
+            visible: Player.hasChapters
+
+            model: Player.chapters
+            Item {
+                Rectangle {
+                    id: seekpointsRect
+                    readonly property real startPosition: model.startPosition === undefined ? 0.0 : model.startPosition
+                    readonly property real endPosition: model.endPosition === undefined ? 1.0 : model.endPosition
+
+                    readonly property int _currentChapter: {
+                        if (control.visualPosition < seekpointsRect.startPosition)
+                            return 1
+                        else if (control.visualPosition > seekpointsRect.endPosition)
+                            return -1
+                        return 0
+                    }
+                    on_CurrentChapterChanged: {
+                        if(_hovered)
+                            control._currentChapterHovered = _currentChapter === 0
+                    }
+
+                    readonly property bool _hovered: control.hovered &&
+                                            (sliderRectMouseArea.mouseX > x && sliderRectMouseArea.mouseX < x+width)
+
+                    color: _currentChapter < 0 ? control.colors.accent : control.backgroundColor
+                    width: sliderRect.width * seekpointsRect.endPosition - x - control._seekPointsDistance
+                    x: sliderRect.width * seekpointsRect.startPosition
+
+                    Rectangle {
+                        id: progressRepRect
+                        anchors.left: parent.left
+                        anchors.top: parent.top
+                        anchors.bottom: parent.bottom
+
+                        width: sliderRect.width * control.visualPosition - parent.x - control._seekPointsDistance
+                        visible: parent._currentChapter === 0
+                        color: control.colors.accent
+                    }
+                }
+
+                transitions: [
+                    Transition {
+                        to: "*"
+                        SequentialAnimation{
+                            PropertyAction { targets: control; property: "_currentChapterHovered" }
+                            NumberAnimation {
+                                targets: [seekpointsRect, progressRepRect]; properties: "height, y, radius"
+                                duration: VLCStyle.duration_short; easing.type: Easing.InSine
+                            }
+                        }
+                    }
+                ]
+
+                states:[
+                    State {
+                        name: "visible"
+                        PropertyChanges {
+                            target: control;
+                            _currentChapterHovered: seekpointsRect._currentChapter === 0 ? false : control._currentChapterHovered
+                        }
+                        PropertyChanges { target: seekpointsRect; height: control.barHeight }
+                        PropertyChanges { target: seekpointsRect; y: 0 }
+                        PropertyChanges { target: seekpointsRect; radius: control._seekPointsRadius }
+                    },
+                    State {
+                        name: "visibleLarge"
+                        PropertyChanges {
+                            target: control;
+                            _currentChapterHovered: seekpointsRect._currentChapter === 0 ? true : control._currentChapterHovered
+                        }
+                        PropertyChanges { target: seekpointsRect; height: control._scaledBarHeight }
+                        PropertyChanges { target: seekpointsRect; y: control._scaledY }
+                        PropertyChanges { target: seekpointsRect; radius: control._scaledSeekPointsRadius }
+                    }
+                ]
+
+                state: (seekpointsRect._hovered || (seekpointsRect._currentChapter === 0 && fsm._state == fsmHeld))
+                       ? "visibleLarge"
+                       : "visible"
+            }
+        }
+
         Rectangle {
             id: progressRect
             width: control.visualPosition * parent.width
-            height: control.barHeight
+            visible: !Player.hasChapters
             color: control.colors.accent
-            radius: control.barHeight
+            height: control.barHeight
+            radius: control._seekPointsRadius
         }
 
         Rectangle {
@@ -266,47 +371,14 @@ Slider {
                 }
             }
         }
-
-        Item {
-            id: seekpointsRow
-
-            width: parent.width
-            height: control.barHeight
-            visible: Player.hasChapters
-
-            Repeater {
-                id: seekpointsRptr
-                model: Player.chapters
-                Rectangle {
-                    id: seekpointsRect
-                    property real position: model.position === undefined ? 0.0 : model.position
-
-                    color: control.colors.seekpoint
-                    width: VLCStyle.dp(1, VLCStyle.scale)
-                    height: control.barHeight
-                    x: sliderRect.width * seekpointsRect.position
-                }
-            }
-
-            OpacityAnimator on opacity {
-                from: 1
-                to: 0
-                running: !control._isSeekPointsShown
-            }
-            OpacityAnimator on opacity{
-                from: 0
-                to: 1
-                running: control._isSeekPointsShown
-            }
-        }
     }
 
     handle: Rectangle {
         id: sliderHandle
 
-        visible: control.activeFocus
         x: (control.visualPosition * control.availableWidth) - width / 2
-        y: (control.barHeight - width) / 2
+        y: (control.barHeight - height) / 2
+
         implicitWidth: VLCStyle.margin_small
         implicitHeight: VLCStyle.margin_small
         radius: VLCStyle.margin_small
@@ -318,12 +390,9 @@ Slider {
                 SequentialAnimation {
                     NumberAnimation {
                         target: sliderHandle; properties: "implicitWidth,implicitHeight"
-
                         to: 0
-
                         duration: VLCStyle.duration_short; easing.type: Easing.OutSine
                     }
-
                     PropertyAction { target: sliderHandle; property: "visible"; value: false; }
                 }
             },
@@ -331,18 +400,28 @@ Slider {
                 to: "visible"
                 SequentialAnimation {
                     PropertyAction { target: sliderHandle; property: "visible"; value: true; }
-
                     NumberAnimation {
                         target: sliderHandle; properties: "implicitWidth,implicitHeight"
-
                         to: VLCStyle.margin_small
-
+                        duration: VLCStyle.duration_short; easing.type: Easing.InSine
+                    }
+                }
+            },
+            Transition {
+                to: "visibleLarge"
+                SequentialAnimation {
+                    PropertyAction { target: sliderHandle; property: "visible"; value: true; }
+                    NumberAnimation {
+                        target: sliderHandle; properties: "implicitWidth,implicitHeight"
+                        to: VLCStyle.margin_small * (0.75 * control._hoveredScalingFactor)
                         duration: VLCStyle.duration_short; easing.type: Easing.InSine
                     }
                 }
             }
         ]
 
-        state: (control.hovered || control.activeFocus) ? "visible" : "hidden"
+        state: (control.hovered || control.activeFocus)
+               ? ((control._currentChapterHovered || (Player.hasChapters && fsm._state == fsmHeld)) ? "visibleLarge" : "visible")
+               : "hidden"
     }
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2395eb294e21703cb82a3a926b00cca6367de97c...ce53cd1eb7b78d0189abce3a98565697a93e6069

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