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


Commits:
1d5f27ac by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: make `UpdateModelPrivate::m_release` pointer to constant

- - - - -
a6cc6470 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: introduce `UPDATE_MOCK` in `help.cpp`

This is only used for debugging purposes.

- - - - -
90ac31d3 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: add `UpdateModel::download(void)`

It does not make sense to have this in the
dialog code, so it is moved now.

- - - - -
6c507a24 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: add `UpdateModel::resetStatus()`

- - - - -
e60160ee by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: add `UpdateModel::Status::Downloading`

This is currently not plugged to anything, introduced
because QML side is ready to respect it.

- - - - -
1bc35b6c by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: add `progress` property to `UpdateModel`

This is currently not plugged to anything, introduced
because QML side is ready to respect it.

- - - - -
2a5df657 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: call check update directly with check for updates action

... in the help menu.

- - - - -
a102f54d by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: introduce `ProgressBarExt.qml`

Directly copied from `ScanProgressBar.qml`,
which is not a generic type.

- - - - -
4023c51e by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qml: derive `ScanProgressBar` from `ProgressBarExt`

- - - - -
44704b9c by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: move `ScanProgressBar.qml` from `widgets` to `medialibrary`

As a de facto rule, qml files that import the media library
module `VLC.MediaLibrary` are placed under the `medialibrary`
directory.

- - - - -
dc35967e by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: register qml singleton instance `UpdateModel`

- - - - -
3648d9c0 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: introduce icon `ic_fluent_arrow_download_24_regular`

Taken from Microsoft Fluent System Icons, subject to
MIT license (see pixmaps/LICENCE)

- - - - -
b91c1bf8 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: introduce icon `ic_fluent_arrow_sync_24_regular`

Taken from Microsoft Fluent System Icons, subject to
MIT license (see pixmaps/LICENCE)

- - - - -
675e0a2f by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: regenerate `VLCIcons.ttf`

- - - - -
de36970a by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qml: introduce `UpdatePane`

A modern alternative to the archaic update dialog.

We do not intend to remove the old update dialog,
at least for now, since it is triggered with
`INTF_DIALOG_UPDATEVLC`.

- - - - -
3e39718f by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qml: use `UpdatePane` in `MainDisplay`

Placed above the mini player (and media
library scan pane, if visible).

- - - - -
68548e5b by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: do not trigger old update dialog if modern update pane is available at start

There is a fallback mechanism to the old dialog if -for any reason- the
new update pane is not available.

- - - - -
1ee9c413 by Fatih Uzunoglu at 2026-05-30T16:32:39+02:00
qt: make the connection for update status changed at appropriate time in 
`MainCtx`

Not only this gets rid of the custom single shot connection, but also makes it
possible to fallback to the old dialog at all times (such as update check
triggered through the menus) in case the modern update pane is not available.

- - - - -


20 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/assets.qrc
- modules/gui/qt/dialogs/help/help.cpp
- modules/gui/qt/dialogs/help/help.hpp
- modules/gui/qt/maininterface/mainctx.cpp
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/maininterface/qml/MainDisplay.qml
- + modules/gui/qt/maininterface/qml/UpdatePane.qml
- + modules/gui/qt/medialibrary/qml/ScanProgressBar.qml
- modules/gui/qt/menus/menus.cpp
- modules/gui/qt/menus/menus.hpp
- modules/gui/qt/menus/qml_menu_wrapper.cpp
- modules/gui/qt/meson.build
- modules/gui/qt/pixmaps/VLCIcons.json
- modules/gui/qt/pixmaps/VLCIcons.ttf
- + modules/gui/qt/pixmaps/icons/ic_fluent_arrow_download_24_regular.svg
- + modules/gui/qt/pixmaps/icons/ic_fluent_arrow_sync_24_regular.svg
- modules/gui/qt/style/VLCIcons.qml
- modules/gui/qt/widgets/qml/ScanProgressBar.qml → 
modules/gui/qt/widgets/qml/ProgressBarExt.qml
- po/POTFILES.in


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -879,6 +879,8 @@ libqt_plugin_la_RES = \
        pixmaps/icons/window_maximize.svg \
        pixmaps/icons/window_minimize.svg \
        pixmaps/icons/window_restore.svg \
+       pixmaps/icons/ic_fluent_arrow_download_24_regular.svg \
+       pixmaps/icons/ic_fluent_arrow_sync_24_regular.svg \
        pixmaps/menu/add.svg \
        pixmaps/menu/capture-card.svg \
        pixmaps/menu/clear.svg \
@@ -1020,6 +1022,11 @@ libqml_module_maininterface_a_QML = \
        maininterface/qml/MainViewLoader.qml \
        maininterface/qml/MainDisplay.qml \
        maininterface/qml/NoMedialibHome.qml
+
+if UPDATE_CHECK
+libqml_module_maininterface_a_QML += maininterface/qml/UpdatePane.qml
+endif
+
 nodist_libqml_module_maininterface_a_SOURCES = maininterface_qmlassets.cpp
 $(libqml_module_maininterface_a_QML:.qml=.cpp) : 
$(builddir)/maininterface/res.qrc
 $(libqml_module_maininterface_a_QML:.qml=.cpp) : 
QML_CACHEGEN_ARGS=--resource=$(builddir)/maininterface/res.qrc
@@ -1067,7 +1074,8 @@ libqml_module_medialibrary_a_QML = \
        medialibrary/qml/Bookmarks.qml \
        medialibrary/qml/MLContextMenu.qml \
        medialibrary/qml/MLDragItem.qml \
-       medialibrary/qml/MLTableColumns.qml
+       medialibrary/qml/MLTableColumns.qml \
+       medialibrary/qml/ScanProgressBar.qml
 nodist_libqml_module_medialibrary_a_SOURCES = medialibrary_qmlassets.cpp
 $(libqml_module_medialibrary_a_QML:.qml=.cpp) : 
$(builddir)/medialibrary/res.qrc
 $(libqml_module_medialibrary_a_QML:.qml=.cpp) : 
QML_CACHEGEN_ARGS=--resource=$(builddir)/medialibrary/res.qrc
@@ -1296,7 +1304,6 @@ libqml_module_widgets_a_QML = \
        widgets/qml/PlayCover.qml \
        widgets/qml/RoundButtonExt.qml \
        widgets/qml/ScaledImage.qml \
-       widgets/qml/ScanProgressBar.qml \
        widgets/qml/TextAutoScroller.qml \
        widgets/qml/SearchBox.qml \
        widgets/qml/SliderExt.qml \
@@ -1331,7 +1338,8 @@ libqml_module_widgets_a_QML = \
        widgets/qml/RoundedRectangleShadow.qml \
        widgets/qml/VoronoiSnow.qml \
        widgets/qml/DualKawaseBlur.qml \
-       widgets/qml/CheckBoxExt.qml
+       widgets/qml/CheckBoxExt.qml \
+       widgets/qml/ProgressBarExt.qml
 nodist_libqml_module_widgets_a_SOURCES = widgets_qmlassets.cpp
 $(libqml_module_widgets_a_QML:.qml=.cpp) : $(builddir)/widgets/res.qrc
 $(libqml_module_widgets_a_QML:.qml=.cpp) : 
QML_CACHEGEN_ARGS=--resource=$(builddir)/widgets/res.qrc


=====================================
modules/gui/qt/assets.qrc
=====================================
@@ -10,6 +10,8 @@
     </qresource>
     <qresource prefix="/icons">
         <file alias="atob.svg">pixmaps/icons/atob.svg</file>
+        <file 
alias="ic_fluent_arrow_download_24_regular.svg">pixmaps/icons/ic_fluent_arrow_download_24_regular.svg</file>
+        <file 
alias="ic_fluent_arrow_sync_24_regular.svg">pixmaps/icons/ic_fluent_arrow_sync_24_regular.svg</file>
     </qresource>
     <qresource prefix="/menu">
         <file alias="add.svg">pixmaps/menu/add.svg</file>


=====================================
modules/gui/qt/dialogs/help/help.cpp
=====================================
@@ -46,6 +46,12 @@
 
 #include <cassert>
 
+#ifndef NDEBUG
+// Uncomment the following line to make use a mock update for debugging 
purposes,
+// it is only applicable when there is no new release found:
+// #define UPDATE_MOCK
+#endif
+
 HelpDialog::HelpDialog( qt_intf_t *_p_intf ) : QVLCFrame( _p_intf )
 
 {
@@ -192,7 +198,7 @@ public:
 
     update_t* m_update = nullptr;
 
-    update_release_t* m_release = nullptr;
+    const update_release_t* m_release = nullptr;
     UpdateModel::Status m_status = UpdateModel::Unchecked;
 
     UpdateModel* q_ptr = nullptr;
@@ -212,8 +218,42 @@ static void UpdateCallback(void *data, bool b_ret)
             bool needUpdate = update_NeedUpgrade( that->m_update );
             if (!needUpdate)
             {
-                that->m_status = UpdateModel::UpToDate;
-                that->m_release = nullptr;
+#if defined(UPDATE_MOCK) && !defined(NDEBUG)
+               static const update_release_t updateReleaseMock = {
+                   9,
+                   0,
+                   99,
+                   999,
+                   "",
+                   // Lorem ipsum with some "Security" to see if red coloring 
works:
+                   "Lorem ipsum dolor sit amet, security consectetur 
adipiscing elit. Sed vitae ante lobortis," \
+                   "condimentum sem et, auctor libero. Aliquam eget mi justo. 
<br /> <br /> Class aptent taciti sociosqu" \
+                   "ad litora Security torquent per conubia nostra, per 
inceptos himenaeos. Nulla id pretium ante. Nam" \
+                   "eu blandit lacus. Proin faucibus in risus quis 
condimentum. <br /> <br /> Pellentesque a tellus vitae" \
+                   "massa tristique cursus. Phasellus fermentum euismod 
mauris, at ultricies ipsum volutpat eu." \
+                   "Praesent arcu lacus, laoreet at lacinia quis, rhoncus at 
lectus. " \
+                   // Repeat:
+                   "Lorem ipsum dolor sit amet, security consectetur 
adipiscing elit. Sed vitae ante lobortis," \
+                   "condimentum sem et, auctor libero. Aliquam eget mi justo. 
<br /> <br /> Class aptent taciti sociosqu" \
+                   "ad litora Security torquent per conubia nostra, per 
inceptos himenaeos. Nulla id pretium ante. Nam" \
+                   "eu blandit lacus. Proin faucibus in risus quis 
condimentum. <br /> <br /> Pellentesque a tellus vitae" \
+                   "massa tristique cursus. Phasellus fermentum euismod 
mauris, at ultricies ipsum volutpat eu." \
+                   "Praesent arcu lacus, laoreet at lacinia quis, rhoncus at 
lectus. " \
+                   // Repeat:
+                   "Lorem ipsum dolor sit amet, security consectetur 
adipiscing elit. Sed vitae ante lobortis," \
+                   "condimentum sem et, auctor libero. Aliquam eget mi justo. 
<br /> <br /> Class aptent taciti sociosqu" \
+                   "ad litora Security torquent per conubia nostra, per 
inceptos himenaeos. Nulla id pretium ante. Nam" \
+                   "eu blandit lacus. Proin faucibus in risus quis 
condimentum. <br /> <br /> Pellentesque a tellus vitae" \
+                   "massa tristique cursus. Phasellus fermentum euismod 
mauris, at ultricies ipsum volutpat eu." \
+                   "Praesent arcu lacus, laoreet at lacinia quis, rhoncus at 
lectus. " \
+               };
+
+               that->m_release = &updateReleaseMock;
+               that->m_status = UpdateModel::NeedUpdate;
+#else
+               that->m_status = UpdateModel::UpToDate;
+               that->m_release = nullptr;
+#endif
             }
             else
             {
@@ -258,6 +298,27 @@ bool UpdateModel::download(QString destDir)
     return true;
 }
 
+bool UpdateModel::download()
+{
+    QString dest_dir = QDir::tempPath();
+    if (Q_UNLIKELY(dest_dir.isEmpty()))
+        return false;
+
+    dest_dir = toNativeSepNoSlash( std::move(dest_dir) ) + DIR_SEP;
+    qDebug() << "Downloading to folder:" << qtu( dest_dir );
+
+    return download(dest_dir);
+}
+
+void UpdateModel::resetStatus()
+{
+    Q_D(UpdateModel);
+    if (d->m_status == Unchecked)
+        return;
+    d->m_status = Unchecked;
+    emit updateStatusChanged();
+}
+
 UpdateModel::Status UpdateModel::updateStatus() const
 {
     Q_D(const UpdateModel);
@@ -301,6 +362,12 @@ QString UpdateModel::getUrl() const
     return qfu( d->m_release->psz_desc );
 }
 
+double UpdateModel::getProgress() const
+{
+    // TODO: Stub
+    return 0.0;
+}
+
 
 
 /*****************************************************************************
@@ -360,15 +427,8 @@ void UpdateDialog::checkOrDownload()
     }
     case UpdateModel::NeedUpdate:
     {
-        QString dest_dir = QDir::tempPath();
-        if( !dest_dir.isEmpty() )
-        {
-            dest_dir = toNativeSepNoSlash( std::move(dest_dir) ) + DIR_SEP;
-            msg_Dbg( p_intf, "Downloading to folder: %s", qtu( dest_dir ) );
+        if (m_model->download())
             toggleVisible();
-            m_model->download(dest_dir);
-            /* FIXME: We should trigger a change to another dialog here ! */
-        }
         break;
     }
     default: // Checking


=====================================
modules/gui/qt/dialogs/help/help.hpp
=====================================
@@ -82,17 +82,19 @@ public:
         Checking,
         UpToDate,
         NeedUpdate,
-        CheckFailed
+        CheckFailed,
+        Downloading // TODO
     };
     Q_ENUM(Status)
 
-    Q_PROPERTY(Status updateStatus READ updateStatus NOTIFY 
updateStatusChanged FINAL)
+    Q_PROPERTY(Status updateStatus READ updateStatus RESET resetStatus NOTIFY 
updateStatusChanged FINAL)
     Q_PROPERTY(int major READ getMajor NOTIFY updateStatusChanged FINAL)
     Q_PROPERTY(int minor READ getMinor NOTIFY updateStatusChanged FINAL)
     Q_PROPERTY(int revision READ getRevision NOTIFY updateStatusChanged FINAL)
     Q_PROPERTY(int extra READ getExtra NOTIFY updateStatusChanged FINAL)
     Q_PROPERTY(QString description READ getDescription NOTIFY 
updateStatusChanged FINAL)
     Q_PROPERTY(QString url READ getUrl NOTIFY updateStatusChanged FINAL)
+    Q_PROPERTY(double progress READ getProgress NOTIFY progressChanged FINAL) 
// TODO
 
 public:
     explicit UpdateModel(qt_intf_t * p_intf);
@@ -101,6 +103,9 @@ public:
     Q_INVOKABLE void checkUpdate();
 
     Q_INVOKABLE bool download(QString destDir);
+    Q_INVOKABLE bool download();
+
+    Q_INVOKABLE void resetStatus();
 
     Status updateStatus() const;
     int getMajor() const;
@@ -109,9 +114,11 @@ public:
     int getExtra() const;
     QString getDescription() const;
     QString getUrl() const;
+    double getProgress() const;
 
 signals:
     void updateStatusChanged();
+    void progressChanged();
 
 private:
     Q_DECLARE_PRIVATE(UpdateModel)


=====================================
modules/gui/qt/maininterface/mainctx.cpp
=====================================
@@ -275,24 +275,7 @@ MainCtx::MainCtx(qt_intf_t *_p_intf)
             getSettings()->value( "updatedate" ).toDate().addDays( interval ) )
         {
             /* check for update at startup */
-            m_updateModel = std::make_unique<UpdateModel>(p_intf);
-            connect(m_updateModel.get(), &UpdateModel::updateStatusChanged, 
this, [this](){
-                switch (m_updateModel->updateStatus())
-                {
-                case UpdateModel::Checking:
-                case UpdateModel::Unchecked:
-                    break;
-                case UpdateModel::NeedUpdate:
-                    qWarning() << "Need Udpate";
-                    THEDP->updateDialog();
-                    [[fallthrough]];
-                case UpdateModel::UpToDate:
-                case UpdateModel::CheckFailed:
-                    disconnect(m_updateModel.get(), nullptr, this, nullptr);
-                    break;
-                }
-            });
-            m_updateModel->checkUpdate();
+            getUpdateModel()->checkUpdate();
             getSettings()->setValue( "updatedate", QDate::currentDate() );
         }
     }
@@ -1211,7 +1194,51 @@ void MainCtx::setArtistAlbumsWidthFactor(double 
newArtistAlbumsWidthFactor)
 UpdateModel* MainCtx::getUpdateModel() const
 {
     if (!m_updateModel)
+    {
         m_updateModel = std::make_unique<UpdateModel>(p_intf);
+
+        connect(m_updateModel.get(), &UpdateModel::updateStatusChanged, this, 
[this](){
+            switch (m_updateModel->updateStatus())
+            {
+            case UpdateModel::NeedUpdate:
+                qWarning() << "Need update";
+
+                // No-op, modern update pane opens itself automatically when 
status changes.
+                // However, the old update dialog is used as fallback in case 
for any reason
+                // the modern pane is not available.
+
+                {
+                    // Fallback:
+
+                    if (Q_LIKELY(p_intf &&
+                                 p_intf->p_compositor &&
+                                 p_intf->p_compositor->quickWindow() &&
+                                 
p_intf->p_compositor->quickWindow()->contentItem()))
+                    {
+                        const auto target = 
p_intf->p_compositor->quickWindow()->contentItem();
+                        QMetaObject::invokeMethod(target, [target]() {
+                            const auto updatePaneLoader = 
target->findChild<QQuickItem*>(QStringLiteral("updatePaneLoader"));
+                            if (!updatePaneLoader || 
(updatePaneLoader->property("status").toInt() != 1 /* Loader.Ready */))
+                            {
+                                qDebug("No acknowledgement from the modern 
update loader, falling back to the old update dialog.");
+                                THEDP->updateDialog();
+                            }
+                        }, Qt::QueuedConnection);
+                    }
+                    else
+                    {
+                        qDebug("Compositor is not available, falling back to 
the old update dialog.");
+                        THEDP->updateDialog();
+                    }
+                }
+
+                break;
+            default:
+                break;
+            }
+        });
+    }
+
     return m_updateModel.get();
 }
 #endif


=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -56,6 +56,9 @@
 #include "dialogs/help/aboutmodel.hpp"
 #include "dialogs/dialogs_provider.hpp"
 #include "dialogs/dialogs/dialogmodel.hpp"
+#ifdef UPDATE_CHECK
+#include "dialogs/help/help.hpp" // UpdateModel
+#endif
 #include "util/vlchotkeyconverter.hpp"
 
 #include "network/networkmediamodel.hpp"
@@ -237,6 +240,10 @@ void MainUI::registerQMLTypes()
         qmlRegisterUncreatableType<CSDButtonModel>(uri, versionMajor, 
versionMinor, "CSDButtonModel", "has CSD buttons and provides for communicating 
CSD events between UI and backend");
         qmlRegisterTypesAndRevisions<CSDMenu>( uri, versionMajor);
         qmlRegisterUncreatableType<NavigationAttached>( uri, versionMajor, 
versionMinor, "Navigation", "Navigation is only available via attached 
properties");
+#ifdef UPDATE_CHECK
+        qmlRegisterSingletonInstance<UpdateModel>( uri, versionMajor, 
versionMinor, "UpdateModel", m_mainCtx->getUpdateModel() );
+#endif
+
         qmlRegisterModule(uri, versionMajor, versionMinor);
         qmlProtectModule(uri, versionMajor);
     }


=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -36,7 +36,9 @@ FocusScope {
     property bool hasMiniPlayer: miniPlayer.visible
 
     // NOTE: The main view must be above the indexing bar and the mini player.
-    property real displayMargin: (height - miniPlayer.y) + 
(loaderProgress.active ? loaderProgress.height : 0)
+    property real displayMargin: (height - miniPlayer.y) +
+                                 (loaderProgress.active ? 
loaderProgress.height : 0) +
+                                 (loaderUpdatePane.active ? 
loaderUpdatePane.height : 0)
 
     //MainDisplay behave as a PageLoader
     property alias pagePrefix: stackView.pagePrefix
@@ -286,7 +288,7 @@ FocusScope {
 
                 layer.enabled: MainCtx.backdropBlurRequested() &&
                                (GraphicsInfo.shaderType === 
GraphicsInfo.RhiShader) &&
-                               (miniPlayer.visible || 
!!loaderProgress.item?.visible)
+                               (miniPlayer.visible || 
!!loaderProgress.item?.visible || !!loaderUpdatePane.item?.visible)
 
                 // Blurring requires to access neighbour pixels, thus the 
source texture should be bigger than
                 // the effect so that the effect have access to the neighbor 
pixels for the pixels near the
@@ -351,7 +353,7 @@ FocusScope {
                     effectRect: Qt.rect(0,
                                         stackView.height - 
stackViewParent.edgeExtension,
                                         stackViewParent.width,
-                                        loaderProgress.height + 
miniPlayer.height + 2 * stackViewParent.edgeExtension)
+                                        loaderProgress.height + 
loaderUpdatePane.height + miniPlayer.height + 2 * stackViewParent.edgeExtension)
 
                     // WARNING: We are not using `sourceVisualRect` because it 
is not trivial to guarantee that
                     //          the visual (`ShaderEffect`) scene graph sizing 
and sub-texturing are synchronized.
@@ -423,7 +425,7 @@ FocusScope {
                     Navigation.parentItem: mainColumn
                     Navigation.upItem: sourcesBanner
                     Navigation.rightItem: playlistLoader
-                    Navigation.downItem:  miniPlayer.visible ? miniPlayer : 
null
+                    Navigation.downItem: loaderUpdatePane
                 }
 
                 Rectangle {
@@ -525,7 +527,7 @@ FocusScope {
 
                     Navigation.parentItem: mainColumn
                     Navigation.upItem: sourcesBanner
-                    Navigation.downItem: miniPlayer.visible ? miniPlayer : null
+                    Navigation.downItem: loaderUpdatePane
 
                     Navigation.leftAction: function() {
                         
stackView.currentItem.setCurrentItemFocus(Qt.TabFocusReason);
@@ -601,6 +603,78 @@ FocusScope {
         }
     }
 
+    Loader {
+        id: loaderUpdatePane
+
+        // WARNING: Object name is used from C++ side to acknowledge the 
modern update pane is loaded,
+        //          if C++ side does not get this acknowledgement, the old 
update dialog is shown as
+        //          fallback.
+        objectName: "updatePaneLoader"
+
+        anchors.left: parent.left
+        anchors.right: parent.right
+        anchors.bottom: loaderProgress.top
+
+        active: !!UpdateModel && (shouldShow || height > 0.0)
+
+        focus: !!item
+
+        readonly property bool shouldShow: !!UpdateModel && 
(UpdateModel.updateStatus !== UpdateModel.Unchecked)
+
+        // This property can be used to enable/disable the animation:
+        property alias toggleAnimation: heightBehavior.enabled
+
+        function dismiss() {
+            height = 0.0
+        }
+
+        onShouldShowChanged: {
+            if (shouldShow)
+                height = Qt.binding(() => { return implicitHeight })
+        }
+
+        onActiveChanged: {
+            console.assert(!!UpdateModel)
+            if (!active)
+                UpdateModel.resetStatus()
+        }
+
+        clip: (height < implicitHeight)
+
+        Behavior on height {
+            id: heightBehavior
+
+            NumberAnimation {
+                easing.type: Easing.InOutSine
+                duration: VLCStyle.duration_long
+            }
+        }
+
+        source: "qrc:///qt/qml/VLC/MainInterface/UpdatePane.qml"
+
+        Navigation.parentItem: mainColumn
+        Navigation.upItem: mainRow
+        Navigation.downItem: miniPlayer
+
+        onLoaded: {            
+            item.background.visible = Qt.binding(function() { return 
!stackViewParent.layer.enabled })
+
+            item.leftPadding = Qt.binding(function() { return 
VLCStyle.margin_large + VLCStyle.applicationHorizontalMargin })
+            item.rightPadding = Qt.binding(function() { return 
VLCStyle.margin_large + VLCStyle.applicationHorizontalMargin })
+            item.bottomPadding = Qt.binding(function() { return 
VLCStyle.margin_small + ((miniPlayer.visible || loaderProgress.visible) ? 0
+                                                                               
                                                         : 
VLCStyle.applicationVerticalMargin) })
+
+            item.dismissRequested.connect(loaderUpdatePane, 
loaderUpdatePane.dismiss)
+
+            // We have height animation here, we don't want animation inside 
the item in addition to that:
+            item.animations = Qt.binding(function() { return 
!loaderUpdatePane.toggleAnimation })
+
+            item.Navigation.parentItem = loaderUpdatePane
+
+            item.focus = true // Loader itself is a focus scope, so we need 
this
+        }
+    }
+
 
     Loader {
         id: loaderProgress
@@ -613,7 +687,7 @@ FocusScope {
 
         height: active ? implicitHeight : 0
 
-        source: "qrc:///qt/qml/VLC/Widgets/ScanProgressBar.qml"
+        source: "qrc:///qt/qml/VLC/MediaLibrary/ScanProgressBar.qml"
 
         onLoaded: {
             item.background.visible = Qt.binding(function() { return 
!stackViewParent.layer.enabled })
@@ -699,7 +773,7 @@ FocusScope {
         background.visible: !stackViewParent.layer.enabled
 
         Navigation.parentItem: mainColumn
-        Navigation.upItem: mainRow
+        Navigation.upItem: loaderUpdatePane
         Navigation.cancelItem:sourcesBanner
         onVisibleChanged: {
             if (!visible && miniPlayer.activeFocus)


=====================================
modules/gui/qt/maininterface/qml/UpdatePane.qml
=====================================
@@ -0,0 +1,352 @@
+/*****************************************************************************
+ * Copyright (C) 2026 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
+import QtQuick.Layouts
+import QtQuick.Templates as T
+
+import VLC.MainInterface
+import VLC.Widgets as Widgets
+import VLC.Style
+import VLC.Util
+
+T.Pane {
+    id: root
+
+    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+                            implicitContentWidth + leftPadding + rightPadding)
+    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+                             implicitContentHeight + topPadding + 
bottomPadding)
+
+    horizontalPadding: VLCStyle.margin_large
+    verticalPadding: VLCStyle.margin_small
+
+    property bool animations: true
+
+    signal dismissRequested()
+
+    readonly property ColorContext colorContext: ColorContext {
+        id: theme
+        colorSet: ColorContext.Window // ###
+
+        focused: root.activeFocus
+        hovered: root.hovered
+        enabled: root.enabled
+    }
+
+    background: Rectangle {
+        color: theme.bg.primary
+    }
+
+    contentItem: Column {
+        spacing: VLCStyle.margin_xsmall
+
+        RowLayout {
+            id: rowLayout
+
+            anchors.left: parent.left
+            anchors.right: parent.right
+
+            spacing: VLCStyle.margin_small
+
+            readonly property bool collapseText: (width < VLCStyle.colWidth(5))
+
+            Image {
+                id: cone
+
+                sourceSize: Qt.size(VLCStyle.icon_normal, VLCStyle.icon_normal)
+                source: 
SVGColorImage.colorize("qrc:///misc/cone.svg").accent(theme.accent).uri()
+            }
+
+            Widgets.LabelExt {
+                id: titleLabel
+
+                Layout.fillWidth: true
+
+                text: {
+                    switch (UpdateModel.updateStatus) {
+                        case UpdateModel.NeedUpdate:
+                            const extra = UpdateModel.extra
+                            return qsTr("A new version of VLC (%1.%2.%3%4) is 
available.").arg(UpdateModel.major)
+                                                                               
           .arg(UpdateModel.minor)
+                                                                               
           .arg(UpdateModel.revision)
+                                                                               
           .arg(extra === 0 ? "" : "." + extra)
+                        case UpdateModel.UpToDate:
+                            return qsTr("You have the latest version of VLC 
media player.")
+                        case UpdateModel.CheckFailed:
+                            return qsTr("An error occurred while checking for 
updates...")
+                        case UpdateModel.Checking:
+                            return qsTr("Checking for updates...")
+                        default:
+                            return qsTr("N/A")
+                    }
+                }
+
+                elide: Text.ElideRight
+
+                font.pixelSize: VLCStyle.fontSize_large
+
+                color: theme.fg.primary
+            }
+
+            Widgets.ActionButtonOverlay {
+                id: revealDetailsButton
+
+                iconTxt: VLCIcons.chevron_up
+                iconRotation: descriptionFlickable.revealed ? 180 : 0
+
+                Behavior on iconRotation {
+                    // WARNING: Can't use `RotationAnimator` because it 
expects property to be "rotation".
+                    RotationAnimation {
+                        easing.type: Easing.InOutSine
+                        duration: heightAnimation.duration
+                    }
+                }
+
+                text: qsTr("Details")
+                showText: !rowLayout.collapseText
+
+                // Do not assume that description would be available depending 
on specific update status.
+                // This button must be available at any time if the model 
provides description.
+                visible: (descriptionLabel.text.length > 0)
+
+                onClicked: {
+                    descriptionFlickable.revealed = 
!descriptionFlickable.revealed
+                }
+
+                Navigation.parentItem: root
+                Navigation.rightItem: recheckButton
+            }
+
+            component Separator : Rectangle {
+                id: separator
+
+                implicitWidth: 1
+                implicitHeight: titleLabel.height
+
+                color: theme.border
+            }
+
+            Separator {
+                visible: revealDetailsButton.visible
+            }
+
+            Widgets.ActionButtonOverlay {
+                id: recheckButton
+
+                iconTxt: VLCIcons.ic_fluent_arrow_sync_24_regular
+                text: qsTr("Re-check")
+                showText: !rowLayout.collapseText
+
+                visible: (UpdateModel.updateStatus !== UpdateModel.Checking)
+
+                onClicked: {
+                    descriptionFlickable.revealed = false
+                    UpdateModel.checkUpdate()
+                }
+
+                Navigation.parentItem: root
+                Navigation.leftItem: revealDetailsButton
+                Navigation.rightItem: downloadButton
+            }
+
+            Widgets.ActionButtonPrimary {
+                id: downloadButton
+
+                visible: (UpdateModel.updateStatus === UpdateModel.NeedUpdate)
+
+                iconTxt: VLCIcons.ic_fluent_arrow_download_24_regular
+                text: qsTr("Download")
+                showText: !rowLayout.collapseText
+
+                onVisibleChanged: {
+                    if (visible)
+                        focus = true // Request focus here by default
+                }
+
+                onClicked: {
+                    if (!UpdateModel.download())
+                        console.error("UpdateModel::download() failed!")
+
+                    // Since downloading dialog is still a separate one, we
+                    // should request dismissing this pane. In the future
+                    // we can get rid of the separate dialog and represent
+                    // the download status here.
+                    if (UpdateModel.updateStatus !== UpdateModel.Downloading)
+                        root.dismissRequested()
+                }
+
+                Navigation.parentItem: root
+                Navigation.leftItem: recheckButton
+                Navigation.rightItem: dismissButton
+            }
+
+            Separator {
+                visible: recheckButton.visible || downloadButton.visible
+            }
+
+            Widgets.ActionButtonOverlay {
+                id: dismissButton
+
+                iconTxt: VLCIcons.close
+                text: qsTr("Dismiss")
+                showText: false // Always collapsed
+
+                onVisibleChanged: {
+                    if (visible) {
+                        if (!downloadButton.visible || !downloadButton.focus)
+                            focus = true // Second chance for focus
+                    }
+                }
+
+                Component.onCompleted: {
+                    clicked.connect(root, dismissRequested)
+                }
+
+                Navigation.parentItem: root
+                Navigation.leftItem: downloadButton
+            }
+        }
+
+        Widgets.ProgressBarExt {
+            anchors.left: parent.left
+            anchors.right: parent.right
+
+            horizontalPadding: 0
+
+            from: 0
+            to: 1
+
+            indeterminate: (UpdateModel.updateStatus === UpdateModel.Checking)
+
+            value: {
+                switch (UpdateModel.updateStatus) {
+                case UpdateModel.Checking:
+                case UpdateModel.Downloading:
+                    return UpdateModel.progress
+                case UpdateModel.UpToDate:
+                    return 1.0
+                case UpdateModel.NeedUpdate:
+                default:
+                    return 0.0
+                }
+            }
+
+            visible: {
+                switch (UpdateModel.updateStatus) {
+                case UpdateModel.Checking:
+                case UpdateModel.Downloading:
+                    return true
+                case UpdateModel.UpToDate:
+                case UpdateModel.NeedUpdate:
+                default:
+                    return false
+                }
+            }
+
+            background: null
+        }
+
+        Flickable {
+            id: descriptionFlickable
+
+            anchors.left: parent.left
+            anchors.right: parent.right
+
+            implicitWidth: contentWidth
+            implicitHeight: contentHeight
+
+            contentWidth: width
+            contentHeight: descriptionLabel.height
+
+            interactive: height < descriptionLabel.height
+
+            clip: !fadingEdge.effectCompatible && (height < implicitHeight)
+            visible: height > 0.1
+
+            property bool revealed: false
+
+            height: revealed ? Math.min(implicitHeight, VLCStyle.dp(256, 
VLCStyle.scale)) : 0.1 // We want 0.0, but Qt 6.2.4 is bugged
+
+            boundsBehavior: Flickable.StopAtBounds
+
+            Behavior on height {
+                enabled: root.animations
+
+                NumberAnimation {
+                    id: heightAnimation
+
+                    easing.type: Easing.InOutSine
+                    duration: VLCStyle.duration_long
+                }
+            }
+
+            T.ScrollBar.vertical: Widgets.ScrollBarExt {}
+
+            Widgets.LabelExt {
+                id: descriptionLabel
+
+                width: parent.width
+
+                font.pixelSize: VLCStyle.fontSize_normal
+
+                color: theme.fg.primary
+
+                // Highlight "security", like the old check for updates dialog.
+                // ES6 does not have replaceAll(), but this works too with 
regex, which we need to use
+                // anyway to match case insensitive:
+                text: UpdateModel.description.replace(/security/gi,
+                                                      (match) => { return 
"<font color=\"red\">" + match + "</font>" })
+
+                wrapMode: Text.WordWrap
+
+                padding: VLCStyle.margin_xxsmall
+
+                style: Text.Raised
+                styleColor: Qt.rgba(0.0, 0.0, 0.0, 0.2)
+            }
+
+            Widgets.FadingEdge {
+                id: fadingEdge
+
+                parent: descriptionFlickable
+
+                anchors.fill: parent
+
+                backgroundColor: (root.background?.visible && 
root.background.color.a >= 1.0) ? root.background.color
+                                                                               
               : "transparent"
+
+                sourceItem: descriptionFlickable.contentItem
+
+                sourceX: descriptionFlickable.contentX
+                sourceY: descriptionFlickable.contentY
+
+                orientation: Qt.Vertical
+
+                Binding on enableBeginningFade {
+                    when: descriptionFlickable.atYBeginning
+                    value: false
+                }
+
+                Binding on enableEndFade {
+                    when: descriptionFlickable.atYEnd
+                    value: false
+                }
+            }
+        }
+    }
+}


=====================================
modules/gui/qt/medialibrary/qml/ScanProgressBar.qml
=====================================
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * Copyright (C) 2019 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
+import QtQuick.Controls
+import QtQuick.Templates as T
+
+import VLC.Widgets
+import VLC.MediaLibrary
+import VLC.Style
+
+ProgressBarExt {
+    id: control
+
+    value: MediaLib.parsingProgress
+
+    indeterminate: MediaLib.discoveryPending
+
+    SubtitleLabel {
+        parent: control.contentItem
+
+        anchors.left: parent.left
+        anchors.right: parent.right
+
+        text: (MediaLib.discoveryPending) ? qsTr("Scanning %1")
+                                            .arg(MediaLib.discoveryEntryPoint)
+                                          : qsTr("Indexing Medias (%1%)")
+                                            .arg(MediaLib.parsingProgress)
+
+        elide: Text.ElideMiddle
+
+        font.pixelSize: VLCStyle.fontSize_large
+        font.weight: Font.Normal
+        color: theme.fg.primary
+    }
+}


=====================================
modules/gui/qt/menus/menus.cpp
=====================================
@@ -39,6 +39,7 @@
 
 #include "maininterface/mainctx.hpp"                     /* View modifications 
*/
 #include "dialogs/dialogs_provider.hpp"                   /* Dialogs display */
+#include "dialogs/help/help.hpp"
 #include "player/player_controller.hpp"                      /* Input 
Management */
 #include "playlist/playlist_controller.hpp"
 #include "dialogs/extensions/extensions_manager.hpp"                 /* 
Extensions menu */
@@ -548,13 +549,20 @@ void VLCMenuBar::RebuildNavigMenu( qt_intf_t *p_intf, 
QMenu *menu )
 /**
  * Help/About Menu
 **/
-void VLCMenuBar::HelpMenu( QMenu *menu )
+void VLCMenuBar::HelpMenu(qt_intf_t *p_intf, QMenu *menu )
 {
     addDPStaticEntry( menu, qtr( "&Help" ) ,
         ":/menu/help.svg", &DialogsProvider::helpDialog, "F1" );
 #ifdef UPDATE_CHECK
     addDPStaticEntry( menu, qtr( "Check for &Updates..." ) , "",
-                      &DialogsProvider::updateDialog);
+                     [ctx = QPointer(p_intf->p_mi)]() {
+        if (Q_LIKELY(ctx))
+        {
+            const auto updateModel = ctx->getUpdateModel();
+            assert(updateModel);
+            updateModel->checkUpdate();
+        }
+    });
 #endif
     menu->addSeparator();
     addDPStaticEntry( menu, qfut( I_MENU_ABOUT ), ":/menu/info.svg",
@@ -849,7 +857,7 @@ QMenu* VLCMenuBar::PopupMenu( qt_intf_t *p_intf, bool show )
         menu->addSeparator();
 
         QMenu* helpmenu = new QMenu( qtr( "Help" ), menu );
-        HelpMenu( helpmenu );
+        HelpMenu( p_intf, helpmenu );
         menu->addMenu( helpmenu );
 
         addDPStaticEntry( menu, qtr( "Quit" ), ":/menu/exit.svg",


=====================================
modules/gui/qt/menus/menus.hpp
=====================================
@@ -94,7 +94,7 @@ public:
 
     static void AudioMenu( qt_intf_t *, QMenu * );
 
-    static void HelpMenu( QMenu *menu );
+    static void HelpMenu( qt_intf_t *, QMenu *menu );
 
     /* Popups Menus */
     static void PopupMenuStaticEntries( QMenu *menu );


=====================================
modules/gui/qt/menus/qml_menu_wrapper.cpp
=====================================
@@ -286,7 +286,7 @@ void QmlGlobalMenu::popup(QPoint pos)
     ViewMenu( p_intf, submenu );
 
     submenu = m_menu->addMenu(qtr( "&Help" ));
-    HelpMenu(submenu);
+    HelpMenu( p_intf, submenu );
 
     m_menu->popup(pos);
 }
@@ -410,7 +410,7 @@ void QmlMenuBar::setupMenuEntry(QMenu* menu, MenuEntry 
entry)
         ViewMenu( p_intf, menu );
         break;
     case HELP:
-        HelpMenu( menu );
+        HelpMenu( p_intf, menu );
         break;
     default:
         vlc_assert_unreachable();
@@ -478,8 +478,9 @@ void QmlMenuBar::popupViewMenu(QQuickItem* button )
 
 void QmlMenuBar::popupHelpMenu( QQuickItem* button )
 {
-    popupMenuCommon(button, [](QMenu* menu) {
-        HelpMenu(menu);
+    popupMenuCommon(button, [this](QMenu* menu) {
+        qt_intf_t* p_intf = m_ctx->getIntf();
+        HelpMenu( p_intf, menu );
     });
 }
 


=====================================
modules/gui/qt/meson.build
=====================================
@@ -612,6 +612,13 @@ qml_modules += {
     ),
 }
 
+qml_maininterface_extra_files = []
+
+if get_option('update-check').allowed() and gcrypt_dep.found()
+    qt_extra_flags += '-DUPDATE_CHECK'
+    qml_maininterface_extra_files += 'maininterface/qml/UpdatePane.qml'
+endif
+
 qml_modules += {
     'name' : 'VLC.MainInterface',
     'target' : 'maininterface',
@@ -621,7 +628,8 @@ qml_modules += {
         'maininterface/qml/MainInterface.qml',
         'maininterface/qml/MainViewLoader.qml',
         'maininterface/qml/MainDisplay.qml',
-        'maininterface/qml/NoMedialibHome.qml'
+        'maininterface/qml/NoMedialibHome.qml',
+        qml_maininterface_extra_files,
     ),
 }
 qml_modules += {
@@ -668,6 +676,7 @@ qml_modules += {
         'medialibrary/qml/MLContextMenu.qml',
         'medialibrary/qml/MLDragItem.qml',
         'medialibrary/qml/MLTableColumns.qml',
+        'medialibrary/qml/ScanProgressBar.qml',
     ),
 }
 
@@ -887,7 +896,6 @@ qml_modules += {
         'widgets/qml/PlayCover.qml',
         'widgets/qml/RoundButtonExt.qml',
         'widgets/qml/ScaledImage.qml',
-        'widgets/qml/ScanProgressBar.qml',
         'widgets/qml/TextAutoScroller.qml',
         'widgets/qml/SearchBox.qml',
         'widgets/qml/SliderExt.qml',
@@ -923,6 +931,7 @@ qml_modules += {
         'widgets/qml/VoronoiSnow.qml',
         'widgets/qml/DualKawaseBlur.qml',
         'widgets/qml/CheckBoxExt.qml',
+        'widgets/qml/ProgressBarExt.qml',
     ),
 }
 
@@ -1218,11 +1227,6 @@ if qt6_dep.found()
         endif
     endif
 
-    if get_option('update-check').allowed() and gcrypt_dep.found()
-        qt_extra_flags += '-DUPDATE_CHECK'
-    endif
-
-
     vlc_modules += {
         'name' : 'qt_x11',
         'include_directories' : qt_include_dir,


=====================================
modules/gui/qt/pixmaps/VLCIcons.json
=====================================
@@ -90,6 +90,8 @@
         {"key":"window_minimize", "path": "./icons/window_minimize.svg" },
         {"key":"window_restore", "path": "./icons/window_restore.svg" },
         {"key":"ic_fluent_document_add_24_regular", "path": 
"./icons/ic_fluent_document_add_24_regular.svg"},
-        {"key":"ic_fluent_document_copy_24_regular", "path": 
"./icons/ic_fluent_document_copy_24_regular.svg"}
+        {"key":"ic_fluent_document_copy_24_regular", "path": 
"./icons/ic_fluent_document_copy_24_regular.svg"},
+        {"key":"ic_fluent_arrow_download_24_regular", "path": 
"./icons/ic_fluent_arrow_download_24_regular.svg"},
+        {"key":"ic_fluent_arrow_sync_24_regular", "path": 
"./icons/ic_fluent_arrow_sync_24_regular.svg"}
     ]
 }


=====================================
modules/gui/qt/pixmaps/VLCIcons.ttf
=====================================
Binary files a/modules/gui/qt/pixmaps/VLCIcons.ttf and 
b/modules/gui/qt/pixmaps/VLCIcons.ttf differ


=====================================
modules/gui/qt/pixmaps/icons/ic_fluent_arrow_download_24_regular.svg
=====================================
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" 
xmlns="http://www.w3.org/2000/svg";>
+<path d="M18.2498 20.5009C18.664 20.5008 19 20.8365 19 21.2507C19 21.6649 
18.6644 22.0008 18.2502 22.0009L5.25022 22.0047C4.836 22.0048 4.5 21.6691 4.5 
21.2549C4.5 20.8407 4.83557 20.5048 5.24978 20.5047L18.2498 20.5009ZM11.6482 
2.01271L11.75 2.00586C12.1297 2.00586 12.4435 2.28801 12.4932 2.65409L12.5 
2.75586L12.499 16.4409L16.2208 12.7205C16.4871 12.4543 16.9038 12.4301 17.1974 
12.648L17.2815 12.7206C17.5477 12.9869 17.5719 13.4036 17.354 13.6972L17.2814 
13.7813L12.2837 18.7779C12.0176 19.044 11.6012 19.0683 11.3076 18.8507L11.2235 
18.7782L6.22003 13.7816C5.92694 13.4889 5.92661 13.014 6.21931 12.7209C6.48539 
12.4545 6.90204 12.43 7.1958 12.6477L7.27997 12.7202L10.999 16.4339L11 
2.75586C11 2.37616 11.2822 2.06237 11.6482 2.01271L11.75 2.00586L11.6482 
2.01271Z" fill="#212121"/>
+</svg>


=====================================
modules/gui/qt/pixmaps/icons/ic_fluent_arrow_sync_24_regular.svg
=====================================
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" 
xmlns="http://www.w3.org/2000/svg";>
+<path d="M16.2506 5.18011C15.9994 5.50947 16.0627 5.9801 16.3921 
6.23128C18.1804 7.59515 19.25 9.70821 19.25 12C19.25 15.736 16.4242 18.812 
12.7933 19.2071L13.4697 18.5303C13.7626 18.2374 13.7626 17.7626 13.4697 
17.4697C13.2034 17.2034 12.7867 17.1792 12.4931 17.3971L12.409 17.4697L10.409 
19.4697C10.1427 19.7359 10.1185 20.1526 10.3364 20.4462L10.409 20.5303L12.409 
22.5303C12.7019 22.8232 13.1768 22.8232 13.4697 22.5303C13.7359 22.2641 13.7601 
21.8474 13.5423 21.5538L13.4697 21.4697L12.7194 20.7208C17.2154 20.355 20.75 
16.5903 20.75 12C20.75 9.23526 19.4582 6.68321 17.3017 5.03856C16.9724 4.78738 
16.5017 4.85075 16.2506 5.18011ZM10.5303 1.46967C10.2374 1.76256 10.2374 
2.23744 10.5303 2.53033L11.2796 3.27923C6.78409 3.6456 3.25 7.41008 3.25 
12C3.25 14.6445 4.43126 17.0974 6.43081 18.7491C6.75016 19.0129 7.22289 18.9679 
7.48669 18.6485C7.75048 18.3292 7.70545 17.8564 7.3861 17.5926C5.72793 16.2229 
4.75 14.1922 4.75 12C4.75 8.26436 7.57532 5.18861 11.2057 4.79301L10.5303 
5.46967C10.2374 5.76256 10.2374 6.23744 10.5303 6.53033C10.8232 6.82322 11.2981 
6.82322 11.591 6.53033L13.591 4.53033C13.8839 4.23744 13.8839 3.76256 13.591 
3.46967L11.591 1.46967C11.2981 1.17678 10.8232 1.17678 10.5303 1.46967Z" 
fill="#212121"/>
+</svg>


=====================================
modules/gui/qt/style/VLCIcons.qml
=====================================
@@ -98,7 +98,9 @@ QtObject {
     readonly property string window_maximize : "\ue052"
     readonly property string window_minimize : "\ue053"
     readonly property string window_restore : "\ue054"
-    readonly property string ic_fluent_document_add_24_regular: "\ue055"
-    readonly property string ic_fluent_document_copy_24_regular: "\ue056"
+    readonly property string ic_fluent_document_add_24_regular : "\ue055"
+    readonly property string ic_fluent_document_copy_24_regular : "\ue056"
+    readonly property string ic_fluent_arrow_download_24_regular : "\ue057"
+    readonly property string ic_fluent_arrow_sync_24_regular : "\ue058"
 
 }


=====================================
modules/gui/qt/widgets/qml/ScanProgressBar.qml → 
modules/gui/qt/widgets/qml/ProgressBarExt.qml
=====================================
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (C) 2019 VLC authors and VideoLAN
+ * Copyright (C) 2026 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
@@ -15,13 +15,10 @@
  * 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.Controls
 import QtQuick.Templates as T
 
-import VLC.MediaLibrary
-
 import VLC.Style
 
 T.ProgressBar {
@@ -38,15 +35,11 @@ T.ProgressBar {
     from: 0
     to: 100
 
-    value: MediaLib.parsingProgress
-
     readonly property ColorContext colorContext: ColorContext {
         id: theme
         colorSet: ColorContext.Window
     }
 
-    indeterminate: MediaLib.discoveryPending
-
     background: Rectangle {
         color: theme.bg.primary
     }
@@ -132,21 +125,5 @@ T.ProgressBar {
                 }
             }
         }
-
-        SubtitleLabel {
-            anchors.left: parent.left
-            anchors.right: parent.right
-
-            text: (MediaLib.discoveryPending) ? qsTr("Scanning %1")
-                                                
.arg(MediaLib.discoveryEntryPoint)
-                                              : qsTr("Indexing Medias (%1%)")
-                                                .arg(MediaLib.parsingProgress)
-
-            elide: Text.ElideMiddle
-
-            font.pixelSize: VLCStyle.fontSize_large
-            font.weight: Font.Normal
-            color: theme.fg.primary
-        }
     }
-}
+}
\ No newline at end of file


=====================================
po/POTFILES.in
=====================================
@@ -751,6 +751,7 @@ modules/gui/qt/maininterface/qml/BannerSources.qml
 modules/gui/qt/maininterface/qml/MainDisplay.qml
 modules/gui/qt/maininterface/qml/MainInterface.qml
 modules/gui/qt/maininterface/qml/NoMedialibHome.qml
+modules/gui/qt/maininterface/qml/UpdatePane.qml
 modules/gui/qt/widgets/qml/EmptyLabelButton.qml
 modules/gui/qt/widgets/qml/EmptyLabel.qml
 modules/gui/qt/medialibrary/mlbookmarkmodel.cpp
@@ -806,6 +807,7 @@ modules/gui/qt/medialibrary/qml/VideoPlaylistsDisplay.qml
 modules/gui/qt/medialibrary/qml/VideoGridDisplay.qml
 modules/gui/qt/medialibrary/qml/MusicAlbumSectionDelegate.qml
 modules/gui/qt/medialibrary/qml/MLContextMenu.qml
+modules/gui/qt/medialibrary/qml/ScanProgressBar.qml
 modules/gui/qt/menus/custom_menus.cpp
 modules/gui/qt/menus/custom_menus.hpp
 modules/gui/qt/menus/menus.cpp
@@ -913,7 +915,6 @@ modules/gui/qt/widgets/native/qvlcframe.hpp
 modules/gui/qt/widgets/native/searchlineedit.cpp
 modules/gui/qt/widgets/native/searchlineedit.hpp
 modules/gui/qt/widgets/qml/DragItem.qml
-modules/gui/qt/widgets/qml/ScanProgressBar.qml
 modules/gui/qt/widgets/qml/SearchBox.qml
 modules/gui/qt/widgets/qml/SortControl.qml
 modules/gui/qt/widgets/qml/TableColumns.qml



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/ecadeffefefd5f9a33bfa06c1d49dca48adf6dc4...1ee9c4139eacf5ac562795f089ffc5aec1c500ad

-- 
View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/ecadeffefefd5f9a33bfa06c1d49dca48adf6dc4...1ee9c4139eacf5ac562795f089ffc5aec1c500ad
You're receiving this email because of your account on code.videolan.org. 
Manage all notifications: https://code.videolan.org/-/profile/notifications | 
Help: https://code.videolan.org/help


_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to