[vlc-commits] [Git][videolan/vlc][master] 9 commits: qt: Added in colour scheme SVGs

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Thu Sep 2 14:39:36 UTC 2021



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
3bcaa23f by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Added in colour scheme SVGs

- - - - -
a7bc09ef by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Added getter method for colour schemes and moved Item struct

- - - - -
2237d8ce by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Added firstrun property to MainInterface with qml medialibrary reload check

- - - - -
815ea41c by Adam Leung at 2021-09-02T13:07:25+00:00
medialibrary: Remove default folder insertion and ml-folders option

- - - - -
016945b8 by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Added new classic style toolbar layout option

- - - - -
09ca278c by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Added distinct profile id parameter to controlbar profiles

- - - - -
d33d01fb by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Complete firstrun wizard

- - - - -
e3581269 by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Removed legacy firstrun dialog

- - - - -
3895e912 by Adam Leung at 2021-09-02T13:07:25+00:00
qt: Added firstrun wizard into MainInterface

- - - - -


23 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/dialogs/dialogs_provider.cpp
- modules/gui/qt/dialogs/dialogs_provider.hpp
- − modules/gui/qt/dialogs/firstrun/firstrun.cpp
- + modules/gui/qt/dialogs/firstrun/firstrunwizard.cpp
- modules/gui/qt/dialogs/firstrun/firstrun.hpp → modules/gui/qt/dialogs/firstrun/firstrunwizard.hpp
- + modules/gui/qt/dialogs/firstrun/firstrunwizard.ui
- modules/gui/qt/dialogs/toolbar/controlbar_profile.cpp
- modules/gui/qt/dialogs/toolbar/controlbar_profile.hpp
- modules/gui/qt/dialogs/toolbar/controlbar_profile_model.cpp
- modules/gui/qt/dialogs/toolbar/controlbar_profile_model.hpp
- modules/gui/qt/maininterface/main_interface.cpp
- modules/gui/qt/maininterface/main_interface.hpp
- modules/gui/qt/maininterface/qml/MainDisplay.qml
- + modules/gui/qt/pixmaps/theme_dark.svg
- + modules/gui/qt/pixmaps/theme_daynight.svg
- + modules/gui/qt/pixmaps/theme_light.svg
- modules/gui/qt/util/color_scheme_model.cpp
- modules/gui/qt/util/color_scheme_model.hpp
- modules/gui/qt/vlc.qrc
- modules/misc/medialibrary/medialibrary.cpp
- modules/misc/medialibrary/medialibrary.h
- po/POTFILES.in


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -17,6 +17,7 @@ libqt_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
 	-I$(srcdir)/gui/qt -I$(builddir)/gui/qt/ \
 	-I$(builddir)/gui/qt/dialogs/extended \
 	-I$(builddir)/gui/qt/dialogs/fingerprint \
+	-I$(builddir)/gui/qt/dialogs/firstrun \
 	-I$(builddir)/gui/qt/dialogs/help \
 	-I$(builddir)/gui/qt/dialogs/messages \
 	-I$(builddir)/gui/qt/dialogs/open \
@@ -81,7 +82,7 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/dialogs/fingerprint/chromaprint.hpp \
 	gui/qt/dialogs/fingerprint/fingerprintdialog.cpp \
 	gui/qt/dialogs/fingerprint/fingerprintdialog.hpp \
-	gui/qt/dialogs/firstrun/firstrun.cpp gui/qt/dialogs/firstrun/firstrun.hpp \
+	gui/qt/dialogs/firstrun/firstrunwizard.cpp gui/qt/dialogs/firstrun/firstrunwizard.hpp \
 	gui/qt/dialogs/gototime/gototime.cpp gui/qt/dialogs/gototime/gototime.hpp \
 	gui/qt/dialogs/help/aboutmodel.cpp \
 	gui/qt/dialogs/help/aboutmodel.hpp \
@@ -312,7 +313,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/dialogs/extensions/extensions_manager.moc.cpp \
 	gui/qt/dialogs/fingerprint/chromaprint.moc.cpp \
 	gui/qt/dialogs/fingerprint/fingerprintdialog.moc.cpp \
-	gui/qt/dialogs/firstrun/firstrun.moc.cpp \
+	gui/qt/dialogs/firstrun/firstrunwizard.moc.cpp \
 	gui/qt/dialogs/gototime/gototime.moc.cpp \
 	gui/qt/dialogs/help/aboutmodel.moc.cpp \
 	gui/qt/dialogs/help/help.moc.cpp \
@@ -422,6 +423,7 @@ nodist_libqt_plugin_la_SOURCES += \
 	gui/qt/dialogs/extended/ui_equalizer.h \
 	gui/qt/dialogs/extended/ui_video_effects.h \
 	gui/qt/dialogs/fingerprint/ui_fingerprintdialog.h \
+	gui/qt/dialogs/firstrun/ui_firstrunwizard.h \
 	gui/qt/dialogs/help/ui_about.h \
 	gui/qt/dialogs/help/ui_update.h \
 	gui/qt/dialogs/messages/ui_messages_panel.h \
@@ -462,6 +464,7 @@ libqt_plugin_la_UI = \
 	gui/qt/dialogs/extended/equalizer.ui \
 	gui/qt/dialogs/extended/video_effects.ui \
 	gui/qt/dialogs/fingerprint/fingerprintdialog.ui \
+	gui/qt/dialogs/firstrun/firstrunwizard.ui \
 	gui/qt/dialogs/help/about.ui \
 	gui/qt/dialogs/help/update.ui \
 	gui/qt/dialogs/messages/messages_panel.ui \
@@ -653,7 +656,10 @@ libqt_plugin_la_RES = \
 	gui/qt/pixmaps/cone.svg \
 	gui/qt/pixmaps/album_cover.svg \
 	gui/qt/pixmaps/back.svg \
-	gui/qt/pixmaps/time.svg
+	gui/qt/pixmaps/time.svg \
+	gui/qt/pixmaps/theme_dark.svg \
+	gui/qt/pixmaps/theme_daynight.svg \
+	gui/qt/pixmaps/theme_light.svg
 
 if HAVE_WIN32
 libqt_plugin_la_RES += gui/qt/pixmaps/windows-theme.conf


=====================================
modules/gui/qt/dialogs/dialogs_provider.cpp
=====================================
@@ -54,6 +54,7 @@
 #include "dialogs/epg/epg.hpp"
 #include "dialogs/errors/errors.hpp"
 #include "dialogs/playlists/playlists.hpp"
+#include "dialogs/firstrun/firstrunwizard.hpp"
 
 #include <QEvent>
 #include <QApplication>
@@ -262,6 +263,13 @@ void DialogsProvider::prefsDialog()
     p->toggleVisible();
 }
 
+void DialogsProvider::firstRunDialog()
+{
+    FirstRunWizard *p = new FirstRunWizard( p_intf );
+    QVLCDialog::setWindowTransientParent(p, nullptr, p_intf);
+    p->show();
+}
+
 void DialogsProvider::extendedDialog()
 {
     ExtendedDialog *extDialog = ExtendedDialog::getInstance(p_intf );


=====================================
modules/gui/qt/dialogs/dialogs_provider.hpp
=====================================
@@ -136,6 +136,7 @@ public slots:
     void mediaInfoDialog( const PlaylistItem& pItem );
     void mediaCodecDialog();
     void prefsDialog();
+    void firstRunDialog();
     void extendedDialog();
     void synchroDialog();
     void messagesDialog();


=====================================
modules/gui/qt/dialogs/firstrun/firstrun.cpp deleted
=====================================
@@ -1,108 +0,0 @@
-/*****************************************************************************
- * firstrun.cpp : First Run dialogs
- ****************************************************************************
- * Copyright © 2009 VideoLAN
- *
- * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
- *
- * 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 "firstrun.hpp"
-
-#include <QGridLayout>
-#include <QGroupBox>
-#include <QCheckBox>
-#include <QLabel>
-#include <QDialogButtonBox>
-
-FirstRun::FirstRun( QWidget *_p, qt_intf_t *_p_intf  )
-         : QWidget( _p ), p_intf( _p_intf )
-{
-    msg_Dbg( p_intf, "Boring first Run Wizard" );
-    buildPrivDialog();
-    setVisible( true );
-}
-
-void FirstRun::save()
-{
-    config_PutInt( "metadata-network-access", checkbox->isChecked() );
-#ifdef UPDATE_CHECK
-    config_PutInt( "qt-updates-notif", checkbox2->isChecked() );
-#endif
-    config_PutInt( "qt-privacy-ask", 0 );
-
-    /* We have to save here because the user may not launch Prefs */
-    config_SaveConfigFile( p_intf );
-    close();
-}
-
-void FirstRun::buildPrivDialog()
-{
-    setWindowTitle( qtr( "Privacy and Network Access Policy" ) );
-    setWindowRole( "vlc-privacy" );
-    setWindowModality( Qt::ApplicationModal );
-    setWindowFlags( Qt::Dialog );
-    setAttribute( Qt::WA_DeleteOnClose );
-
-    QGridLayout *gLayout = new QGridLayout( this );
-
-    QGroupBox *blabla = new QGroupBox( qtr( "Privacy and Network Access Policy" ) );
-    QGridLayout *blablaLayout = new QGridLayout( blabla );
-    QLabel *text = new QLabel( qtr(
-        "<p>In order to protect your privacy, <i>VLC media player</i> "
-        "does <b>not</b> collect personal data or transmit them, "
-        "not even in anonymized form, to anyone."
-        "</p>\n"
-        "<p>Nevertheless, <i>VLC</i> is able to automatically retrieve "
-        "information about the media in your playlist from third party "
-        "Internet-based services. This includes cover art, track names, "
-        "artist names and other meta-data."
-        "</p>\n"
-        "<p>Consequently, this may entail identifying some of your media files to third party "
-        "entities. Therefore the <i>VLC</i> developers require your express "
-        "consent for the media player to access the Internet automatically."
-        "</p>\n"
-        ) );
-    text->setWordWrap( true );
-    text->setTextFormat( Qt::RichText );
-
-    blablaLayout->addWidget( text, 0, 0 ) ;
-
-    QGroupBox *options = new QGroupBox( qtr( "Network Access Policy" ) );
-    QGridLayout *optionsLayout = new QGridLayout( options );
-
-    gLayout->addWidget( blabla, 0, 0, 1, 3 );
-    gLayout->addWidget( options, 1, 0, 1, 3 );
-    int line = 0;
-
-    checkbox = new QCheckBox( qtr( "Allow metadata network access" ) );
-    checkbox->setChecked( true );
-    optionsLayout->addWidget( checkbox, line++, 0 );
-
-#ifdef UPDATE_CHECK
-    checkbox2 = new QCheckBox( qtr( "Regularly check for VLC updates" ) );
-    checkbox2->setChecked( true );
-    optionsLayout->addWidget( checkbox2, line++, 0 );
-#endif
-
-    QDialogButtonBox *buttonsBox = new QDialogButtonBox( this );
-    buttonsBox->addButton( qtr( "Continue" ), QDialogButtonBox::AcceptRole );
-
-    gLayout->addWidget( buttonsBox, 2, 0, 2, 3 );
-
-    CONNECT( buttonsBox, accepted(), this, save() );
-    buttonsBox->setFocus();
-}


=====================================
modules/gui/qt/dialogs/firstrun/firstrunwizard.cpp
=====================================
@@ -0,0 +1,360 @@
+/*****************************************************************************
+ * Copyright (C) 2021 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.
+ *****************************************************************************/
+
+#include "firstrunwizard.hpp"
+#include "util/color_scheme_model.hpp"
+#include "maininterface/main_interface.hpp"
+#include "dialogs/toolbar/controlbar_profile_model.hpp"
+
+#include <QPushButton>
+#include <QButtonGroup>
+#include <QFileDialog>
+#include <QtCore>
+
+#include <vlc_common.h>
+#include <vlc_input_item.h>
+#include <vlc_url.h>
+
+FirstRunWizard::FirstRunWizard( qt_intf_t *_p_intf, QWidget *parent)
+               : QWizard( parent )
+{
+    p_intf = _p_intf;
+
+    /* Set windown properties */
+    setWindowTitle( qtr( "Welcome" ) );
+    setWindowModality( Qt::WindowModal );
+    setAttribute( Qt::WA_DeleteOnClose );
+
+    /* Build the Ui */
+    ui.setupUi( this );
+
+    /* Set the privacy and network policy */
+    ui.policy->setHtml( qtr( "<p>In order to protect your privacy, <i>VLC media player</i> "
+        "does <b>not</b> collect personal data or transmit them, "
+        "not even in anonymized form, to anyone."
+        "</p>\n"
+        "<p>Nevertheless, <i>VLC</i> is able to automatically retrieve "
+        "information about the media in your playlist from third party "
+        "Internet-based services. This includes cover art, track names, "
+        "artist names and other meta-data."
+        "</p>\n"
+        "<p>Consequently, this may entail identifying some of your media files to third party "
+        "entities. Therefore the <i>VLC</i> developers require your express "
+        "consent for the media player to access the Internet automatically."
+        "</p>\n" ) );
+    ui.policy->setReadOnly( true );
+
+    /* Set up the button group for colour schemes. */
+    /* Creating in Qt Designer has unstable ordering when calling buttons() */
+    colorSchemeGroup = new QButtonGroup( this );
+    colorSchemeGroup->addButton( ui.systemButton );
+    colorSchemeGroup->addButton( ui.lightButton );
+    colorSchemeGroup->addButton( ui.darkButton );
+    colorSchemeGroup->setExclusive( true );
+
+    colorSchemeImages = new QButtonGroup( this );
+    colorSchemeImages->addButton( ui.daynightImage );
+    colorSchemeImages->addButton( ui.lightImage );
+    colorSchemeImages->addButton( ui.darkImage );
+
+    /* Setup the layout page */
+    ui.layoutGroup->setId( ui.modernButton, 0 );
+    ui.layoutGroup->setId( ui.classicButton, 1 );
+
+    layoutImages = new QButtonGroup( this );
+    layoutImages->addButton( ui.modernImage );
+    layoutImages->addButton( ui.classicImage );
+    layoutImages->setId( ui.modernImage, MODERN );
+    layoutImages->setId( ui.classicImage, CLASSIC );
+
+    /* Set the tooltips for each of the layout choices */
+    ui.classicButton->setToolTip( qtr("<ul>"
+                                      "<li>No client-side decoration</li>"
+                                      "<li>Toolbar menu</li>"
+                                      "<li>Pinned video controls</li>"
+                                      "</ul>") );
+
+    ui.modernButton->setToolTip( qtr("<ul>"
+                                     "<li>Client-side decoration</li>"
+                                     "<li>No toolbar menu</li>"
+                                     "<li>Video controls unpinned</li>"
+                                     "</ul>") );
+
+    /* Remove the cancel button */
+    setOption( QWizard::NoCancelButton );
+
+    /* Create new instance of MLFoldersModel */
+    if ( vlc_ml_instance_get( p_intf ) )
+    {
+        const auto foldersModel = new MLFoldersModel( this );
+        foldersModel->setMl( vlc_ml_instance_get( p_intf ) );
+        ui.entryPoints->setMLFoldersModel( foldersModel );
+        mlFoldersEditor = ui.entryPoints;
+        mlFoldersModel = foldersModel;
+    }
+    else
+    {
+        ui.enableMl->setChecked( false );
+    }
+
+    /* Disable the ML button as toggling doesn't actually do anything */
+    ui.enableMl->setEnabled(false);
+
+    /* Slots and Signals */
+    connect( ui.addButton, &QPushButton::clicked, this, &FirstRunWizard::MLaddNewFolder );
+    connect( colorSchemeGroup, qOverload<QAbstractButton*>( &QButtonGroup::buttonClicked ), this, &FirstRunWizard::updateColorLabel );
+    connect( colorSchemeImages, qOverload<QAbstractButton*>( &QButtonGroup::buttonClicked ), this, &FirstRunWizard::imageColorSchemeClick );
+    connect( ui.layoutGroup, qOverload<QAbstractButton*>( &QButtonGroup::buttonClicked ), this, &FirstRunWizard::updateLayoutLabel );
+    connect( layoutImages, qOverload<QAbstractButton*>( &QButtonGroup::buttonClicked ), this, &FirstRunWizard::imageLayoutClick );
+    connect( this->button(QWizard::FinishButton), &QPushButton::clicked, this, &FirstRunWizard::finish );
+}
+
+/**
+ * Function called when the finish button is pressed.
+ * Processes all inputted settings according to chosen options
+ */
+void FirstRunWizard::finish()
+{
+    /* Welcome Page settings  */
+    config_PutInt( "metadata-network-access", ui.privacyCheckbox->isChecked() );
+    config_PutInt( "qt-privacy-ask", 0 );
+
+    /* Colour Page settings */
+    p_intf->p_mi->getColorScheme()->setCurrentIndex( colorSchemeGroup->checkedId() );
+
+    /* Layout Page settings */
+    config_PutInt( "qt-menubar", ui.layoutGroup->checkedId() );
+#if QT_CLIENT_SIDE_DECORATION_AVAILABLE
+    config_PutInt( "qt-titlebar", ui.layoutGroup->checkedId() );
+#endif
+    p_intf->p_mi->setPinVideoControls( ui.layoutGroup->checkedId() );
+
+    ControlbarProfileModel* controlbarModel = p_intf->p_mi->controlbarProfileModel();
+    assert(controlbarModel);
+    if( ui.layoutGroup->checkedId() )
+        controlbarModel->setSelectedProfileFromId(ControlbarProfileModel::CLASSIC_STYLE);
+    else
+        controlbarModel->setSelectedProfileFromId(ControlbarProfileModel::DEFAULT_STYLE);
+
+    /* Commit changes to the scanned folders for the Media Library */
+    if( vlc_ml_instance_get( p_intf ) && mlFoldersEditor )
+        mlFoldersEditor->commit();
+
+    /* Reload the indexing service for the media library */
+    if( p_intf->p_mi->getMediaLibrary() )
+        p_intf->p_mi->getMediaLibrary()->reload();
+
+    p_intf->p_mi->reloadPrefs();
+    p_intf->p_mi->controlbarProfileModel()->save();
+    config_SaveConfigFile( p_intf );
+}
+
+/**
+ * Opens a QFileDialog for the user to select a folder to add to the Media Library
+ * If a folder is selected, add it to the list of folders under MLFoldersEditor
+ */
+void FirstRunWizard::MLaddNewFolder()
+{
+    QUrl newEntryPoint = QFileDialog::getExistingDirectoryUrl( this, qtr("Choose a folder to add to the Media Library"),
+                                                               QUrl( QDir::homePath() ));
+
+    if( !newEntryPoint.isEmpty() )
+        mlFoldersEditor->add( newEntryPoint );
+}
+
+/**
+ * Automatically updates the label on the color scheme page depending
+ * on the currently selected radio button choice
+ * @param id The id of the button we are updating the label of
+ */
+void FirstRunWizard::updateColorLabel( QAbstractButton* btn )
+{
+    switch ( colorSchemeGroup->id(btn) )
+    {
+        case ColorSchemeModel::System:
+            ui.explainerLabel->setText( qtr( "<i>VLC will automatically switch to dark mode accordingly with system settings</i>" ) );
+            break;
+        case ColorSchemeModel::Day:
+            ui.explainerLabel->setText( qtr( "<i>VLC will automatically use light mode</i>" ) );
+            break;
+        case ColorSchemeModel::Night:
+            ui.explainerLabel->setText( qtr( "<i>VLC will automatically use dark mode</i>" ) );
+            break;
+        case ColorSchemeModel::Auto:
+            ui.explainerLabel->setText( qtr( "<i>VLC will automatically switch to dark mode accordingly with system settings</i>") );
+            break;
+    }
+}
+
+/**
+ * Automatically updates the label depending on the currently selected layout
+ * @param id The id of the button we are updating the label of
+ */
+void FirstRunWizard::updateLayoutLabel( QAbstractButton* btn )
+{
+    switch ( ui.layoutGroup->id( btn ) )
+    {
+        case MODERN:
+            ui.layoutExplainer->setText( qtr( "<i>VLC will use a modern layout with no menubar or pinned controls but with client-side decoration</i>" ) );
+            break;
+        case CLASSIC:
+            ui.layoutExplainer->setText( qtr( "<i>VLC will use a classic layout with a menubar and pinned controls but with no client-side decoration</i>" ) );
+            break;
+    }
+}
+
+/**
+ * Checks the correct button when the corresponding image is clicked
+ * for the color scheme page.
+ * @param id The id of the image that was clicked
+ */
+void FirstRunWizard::imageColorSchemeClick( QAbstractButton* btn )
+{
+    QAbstractButton* groupBtn = colorSchemeGroup->buttons().at( colorSchemeImages->id( btn ) );
+    assert( groupBtn );
+    groupBtn->setChecked( true );
+    updateColorLabel( groupBtn );
+}
+
+/**
+ * Checks the correct button when the corresponding image is clicked
+ * for the layouts page.
+ * @param id The id of the image that was clicked
+ */
+void FirstRunWizard::imageLayoutClick( QAbstractButton* btn )
+{
+    QAbstractButton* layoutBtn = ui.layoutGroup->buttons().at( layoutImages->id( btn ) );
+    assert( layoutBtn );
+    layoutBtn->setChecked( true );
+    updateLayoutLabel( layoutBtn );
+}
+
+/**
+ * Defines the navigation of pages for the wizard
+ * @return int - the page id to go to or -1 if we are done
+ */
+int FirstRunWizard::nextId() const
+{
+    switch ( currentId() )
+    {
+        case WELCOME_PAGE:
+            if( ui.enableMl->isChecked() )
+                return FOLDER_PAGE;
+            else
+                return COLOR_SCHEME_PAGE;
+        case FOLDER_PAGE:
+            return COLOR_SCHEME_PAGE;
+        case COLOR_SCHEME_PAGE:
+            return LAYOUT_PAGE;
+        default:
+            return -1;
+    }
+}
+
+/**
+ * Sets up the buttons and options for the color scheme page
+ * Needs to be set up later or else the main interface hasn't been created yet
+ * Color schemes are always in the order system/auto, day then night
+ */
+void FirstRunWizard::initializePage( int id )
+{
+    if(id == COLOR_SCHEME_PAGE)
+    {
+        QVector<ColorSchemeModel::Item> schemes = p_intf->p_mi->getColorScheme()->getSchemes();
+        auto schemeButtons = colorSchemeGroup->buttons();
+        auto schemeImages = colorSchemeImages->buttons();
+
+        /* Number of buttons should be equal to the schemes we can choose from */
+        assert( schemes.size() == schemeButtons.size() );
+        assert( schemes.size() == schemeImages.size() );
+
+        for( int i = 0; i < schemes.size(); i++ )
+        {
+            colorSchemeGroup->setId( schemeButtons.at(i), schemes.at(i).scheme );
+            colorSchemeImages->setId( schemeImages.at(i), schemes.at(i).scheme );
+            schemeButtons.at(i)->setText( schemes.at(i).text );
+            if( !i ) updateColorLabel( schemeButtons.at(i) );
+        }
+    }
+    else if ( id == FOLDER_PAGE )
+        addDefaults();
+}
+
+/**
+ * Processes the default options on rejection of the FirstRun Wizard.
+ * The default options are:
+ * - Yes to metadata
+ * - Default folders in the Media Library
+ * - System/Auto colour scheme
+ * - Modern VLC layout
+ */
+void FirstRunWizard::reject()
+{
+    assert(p_intf->p_mi);
+    /* Welcome Page settings  */
+    config_PutInt( "metadata-network-access", 1 );
+    config_PutInt( "qt-privacy-ask", 0 );
+
+    /* Colour Page settings */
+    p_intf->p_mi->getColorScheme()->setCurrentIndex( p_intf->p_mi->getColorScheme()->getSchemes().at(0).scheme );
+
+    /* Layout Page settings */
+    config_PutInt( "qt-menubar", 0 );
+#if QT_CLIENT_SIDE_DECORATION_AVAILABLE
+    config_PutInt( "qt-titlebar", 0 );
+#endif
+    p_intf->p_mi->setPinVideoControls( 0 );
+    p_intf->p_mi->controlbarProfileModel()->setSelectedProfileFromId(ControlbarProfileModel::DEFAULT_STYLE);
+
+    /* Folders Page settings */
+    if ( mlFoldersEditor )
+    {
+        addDefaults();
+        mlFoldersEditor->commit();
+    }
+
+    if( p_intf->p_mi->getMediaLibrary() )
+        p_intf->p_mi->getMediaLibrary()->reload();
+
+    config_SaveConfigFile( p_intf );
+    p_intf->p_mi->reloadPrefs();
+    p_intf->p_mi->controlbarProfileModel()->save();
+
+    done( QDialog::Rejected );
+}
+
+/**
+ * Adds the default folders to the media library
+ */
+void FirstRunWizard::addDefaults()
+{
+    // Return if we already set the defaults or something is null
+    if( mlDefaults || !mlFoldersEditor || mlFoldersEditor->rowCount() )
+        return;
+
+    for( auto&& target : { VLC_VIDEOS_DIR, VLC_MUSIC_DIR } )
+    {
+        auto folder = vlc::wrap_cptr( config_GetUserDir( target ) );
+        if( folder == nullptr )
+            continue;
+        auto folderMrl = vlc::wrap_cptr( vlc_path2uri( folder.get(), nullptr ) );
+        mlFoldersEditor->add( QUrl( folderMrl.get() ) );
+    }
+
+    mlDefaults = true;
+}


=====================================
modules/gui/qt/dialogs/firstrun/firstrun.hpp → modules/gui/qt/dialogs/firstrun/firstrunwizard.hpp
=====================================
@@ -1,46 +1,68 @@
 /*****************************************************************************
- * firstrun.hpp : First Run dialogs
- ****************************************************************************
- * Copyright © 2009 VideoLAN
- *
- * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
+ * Copyright (C) 2021 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.
+ * ( 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
+ * 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.
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-#include "qt.hpp"
+#ifndef VLC_FIRSTRUNWIZARD_H
+#define VLC_FIRSTRUNWIZARD_H
+
+#include "ui_firstrunwizard.h"
+
+#include <QObject>
+#include <QWizard>
 
-#include <QWidget>
-#include <QSettings>
+class MLFoldersEditor;
+class MLFoldersModel;
 
-class QCheckBox;
-class FirstRun : public QWidget
+class FirstRunWizard : public QWizard
 {
     Q_OBJECT
-    public:
-        static void CheckAndRun( QWidget *_p, qt_intf_t *p_intf )
-        {
-            if( var_InheritBool( p_intf, "qt-privacy-ask") )
-                new FirstRun( _p, p_intf );
-        }
-        FirstRun( QWidget *, qt_intf_t * );
-    private:
-        QCheckBox *checkbox, *checkbox2;
-        qt_intf_t *p_intf;
-        void buildPrivDialog();
-    private slots:
-        void save();
+public:
+    FirstRunWizard ( qt_intf_t*, QWidget* parent = nullptr );
+
+private:
+    enum { WELCOME_PAGE, FOLDER_PAGE, COLOR_SCHEME_PAGE, LAYOUT_PAGE };
+    enum { MODERN, CLASSIC };
+
+    void addDefaults();
+
+    int nextId() const;
+    void initializePage( int id );
+    void reject();
+
+private:
+    Ui::firstrun ui;
+
+    MLFoldersEditor *mlFoldersEditor = nullptr;
+    MLFoldersModel *mlFoldersModel = nullptr;
+
+    qt_intf_t* p_intf;
+    bool mlDefaults = false;
+
+    QButtonGroup* colorSchemeGroup = nullptr;
+    QButtonGroup* colorSchemeImages = nullptr;
+    QButtonGroup* layoutImages = nullptr;
+
+private slots:
+    void finish();
+    void MLaddNewFolder();
+    void updateColorLabel( QAbstractButton* );
+    void updateLayoutLabel (QAbstractButton* );
+    void imageColorSchemeClick ( QAbstractButton* );
+    void imageLayoutClick( QAbstractButton* );
 };
 
+#endif // VLC_FIRSTRUNWIZARD_H


=====================================
modules/gui/qt/dialogs/firstrun/firstrunwizard.ui
=====================================
@@ -0,0 +1,560 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>firstrun</class>
+ <widget class="QWizard" name="firstrun">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>650</width>
+    <height>400</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Welcome</string>
+  </property>
+  <widget class="QWizardPage" name="welcomePage">
+   <property name="minimumSize">
+    <size>
+     <width>320</width>
+     <height>0</height>
+    </size>
+   </property>
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QFrame" name="horizontalFrame_policy">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QLabel" name="privacy">
+         <property name="text">
+          <string>Privacy and Network Access Policy</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QTextEdit" name="policy">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="privacyCheckbox">
+         <property name="text">
+          <string>Allow metadata network access</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QFrame" name="horizontalFrame_prefs">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <widget class="QLabel" name="pref">
+         <property name="text">
+          <string>Preferences</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string><small>For a full list of settings, see the <b>preferences</b> tab</small></string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="enableMl">
+         <property name="text">
+          <string>Enable the Media Library</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWizardPage" name="folderPage">
+   <layout class="QGridLayout" name="gridLayout_2">
+    <item row="0" column="0">
+     <widget class="QLabel" name="folderLabel">
+      <property name="text">
+       <string>Folders scanned by the Media Library</string>
+      </property>
+     </widget>
+    </item>
+    <item row="0" column="1">
+     <widget class="QPushButton" name="addButton">
+      <property name="maximumSize">
+       <size>
+        <width>16</width>
+        <height>16</height>
+       </size>
+      </property>
+      <property name="text">
+       <string>+</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="0" colspan="2">
+     <widget class="MLFoldersEditor" name="entryPoints">
+      <property name="editTriggers">
+       <set>QAbstractItemView::AllEditTriggers</set>
+      </property>
+      <property name="alternatingRowColors">
+       <bool>true</bool>
+      </property>
+      <property name="showGrid">
+       <bool>false</bool>
+      </property>
+      <property name="rowCount">
+       <number>1</number>
+      </property>
+      <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+       <bool>false</bool>
+      </attribute>
+      <row/>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWizardPage" name="colorSchemePage">
+   <layout class="QGridLayout" name="gridLayout_3">
+    <item row="1" column="0">
+     <spacer name="verticalSpacer">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::MinimumExpanding</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="2" column="1">
+     <layout class="QVBoxLayout" name="verticalLayout_4">
+      <item alignment="Qt::AlignHCenter">
+       <widget class="QRadioButton" name="lightButton">
+        <property name="text">
+         <string>Light</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_3">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="lightImage">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="../../vlc.qrc">
+          <normaloff>:/theme_light.svg</normaloff>:/theme_light.svg</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>87</width>
+          <height>154</height>
+         </size>
+        </property>
+        <property name="flat">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item row="2" column="2">
+     <layout class="QVBoxLayout" name="verticalLayout_5">
+      <item alignment="Qt::AlignHCenter">
+       <widget class="QRadioButton" name="darkButton">
+        <property name="text">
+         <string>Dark</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_4">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="darkImage">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="../../vlc.qrc">
+          <normaloff>:/theme_dark.svg</normaloff>:/theme_dark.svg</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>87</width>
+          <height>154</height>
+         </size>
+        </property>
+        <property name="flat">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item row="0" column="0">
+     <widget class="QLabel" name="colorLabel">
+      <property name="text">
+       <string>Select a color scheme</string>
+      </property>
+     </widget>
+    </item>
+    <item row="2" column="0">
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item alignment="Qt::AlignHCenter">
+       <widget class="QRadioButton" name="systemButton">
+        <property name="text">
+         <string>System </string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="daynightImage">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="../../vlc.qrc">
+          <normaloff>:/theme_daynight.svg</normaloff>:/theme_daynight.svg</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>87</width>
+          <height>154</height>
+         </size>
+        </property>
+        <property name="flat">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item row="3" column="1">
+     <spacer name="verticalSpacer_5">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::Maximum</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>10</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="4" column="0" colspan="3">
+     <widget class="QLabel" name="explainerLabel">
+      <property name="text">
+       <string><i>VLC will automatically switch to dark mode accordingly with system settings</i></string>
+      </property>
+      <property name="scaledContents">
+       <bool>false</bool>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignCenter</set>
+      </property>
+      <property name="wordWrap">
+       <bool>true</bool>
+      </property>
+     </widget>
+    </item>
+    <item row="5" column="0">
+     <spacer name="verticalSpacer_10">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::MinimumExpanding</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>40</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QWizardPage" name="layoutPage">
+   <layout class="QGridLayout" name="gridLayout_4">
+    <item row="4" column="0" colspan="2">
+     <spacer name="verticalSpacer_7">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::Minimum</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="1" column="0" colspan="2">
+     <spacer name="verticalSpacer_6">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::MinimumExpanding</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item row="0" column="0">
+     <widget class="QLabel" name="layoutLabel">
+      <property name="text">
+       <string>Select a layout</string>
+      </property>
+     </widget>
+    </item>
+    <item row="2" column="0">
+     <layout class="QVBoxLayout" name="verticalLayout_6">
+      <item alignment="Qt::AlignHCenter">
+       <widget class="QRadioButton" name="modernButton">
+        <property name="text">
+         <string>Modern</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+        <attribute name="buttonGroup">
+         <string notr="true">layoutGroup</string>
+        </attribute>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_8">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>0</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="modernImage">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="../../vlc.qrc">
+          <normaloff>:/prefsmenu/sample_minimal.png</normaloff>:/prefsmenu/sample_minimal.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>244</width>
+          <height>145</height>
+         </size>
+        </property>
+        <property name="flat">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item row="2" column="1">
+     <layout class="QVBoxLayout" name="verticalLayout_7">
+      <item alignment="Qt::AlignHCenter">
+       <widget class="QRadioButton" name="classicButton">
+        <property name="text">
+         <string>Classic</string>
+        </property>
+        <attribute name="buttonGroup">
+         <string notr="true">layoutGroup</string>
+        </attribute>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer_9">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>0</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QPushButton" name="classicImage">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="../../vlc.qrc">
+          <normaloff>:/prefsmenu/sample_complete.png</normaloff>:/prefsmenu/sample_complete.png</iconset>
+        </property>
+        <property name="iconSize">
+         <size>
+          <width>244</width>
+          <height>145</height>
+         </size>
+        </property>
+        <property name="flat">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+    <item row="5" column="0" colspan="2">
+     <widget class="QLabel" name="layoutExplainer">
+      <property name="text">
+       <string><i>VLC will use a modern layout with no menubar or pinned controls but with client-side decoration</i></string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignCenter</set>
+      </property>
+     </widget>
+    </item>
+    <item row="6" column="0">
+     <spacer name="verticalSpacer_11">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::MinimumExpanding</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>40</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>MLFoldersEditor</class>
+   <extends>QTableWidget</extends>
+   <header>widgets/native/mlfolderseditor.hpp</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="../../vlc.qrc"/>
+ </resources>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="layoutGroup"/>
+ </buttongroups>
+</ui>


=====================================
modules/gui/qt/dialogs/toolbar/controlbar_profile.cpp
=====================================
@@ -162,6 +162,16 @@ void ControlbarProfile::setName(const QString &name)
     emit nameChanged(m_name);
 }
 
+void ControlbarProfile::setId( const int id )
+{
+    if(id == m_id)
+        return;
+
+    m_id = id;
+
+    emit idChanged(m_id);
+}
+
 bool ControlbarProfile::dirty() const
 {
     return (m_dirty > 0);
@@ -172,6 +182,11 @@ QString ControlbarProfile::name() const
     return m_name;
 }
 
+int ControlbarProfile::id() const
+{
+    return m_id;
+}
+
 void ControlbarProfile::injectDefaults(bool resetDirty)
 {
     injectModel(m_defaults);


=====================================
modules/gui/qt/dialogs/toolbar/controlbar_profile.hpp
=====================================
@@ -31,6 +31,7 @@ class ControlbarProfile : public QObject
 
     Q_PROPERTY(bool dirty READ dirty RESET resetDirty NOTIFY dirtyChanged FINAL)
     Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged FINAL)
+    Q_PROPERTY(int profileId READ id WRITE setId NOTIFY idChanged FINAL)
 
     friend class ControlbarProfileModel;
 
@@ -50,9 +51,16 @@ public:
     bool dirty() const;
     QString name() const;
 
+    // The id is a unique number supplied to each profile
+    // which differentiates it independently from its index
+    // in the profiles array. Provides a more stable way to
+    // identify a profile than using its name.
+    int id() const;
+
 public slots:
     void resetDirty();
     void setName(const QString& name);
+    void setId( const int id );
 
 private:
     // m_dirty indicates the count of PlayerControlbarModel
@@ -60,6 +68,7 @@ private:
     // set true.
     int m_dirty = 0;
 
+    int m_id = -1;
     QString m_name {"N/A"};
     bool m_pauseControlListGeneration = false;
 
@@ -84,6 +93,7 @@ private slots:
 signals:
     void dirtyChanged(bool dirty);
     void nameChanged(QString name);
+    void idChanged(int id);
 
     void controlListChanged(const QVector<int>& linearControlList);
 };


=====================================
modules/gui/qt/dialogs/toolbar/controlbar_profile_model.cpp
=====================================
@@ -28,6 +28,7 @@
 #define SETTINGS_ARRAYNAME_PROFILES "Profiles"
 #define SETTINGS_KEY_NAME "Name"
 #define SETTINGS_KEY_MODEL "Model"
+#define SETTINGS_KEY_ID "Id"
 
 #define SETTINGS_CONTROL_SEPARATOR ","
 #define SETTINGS_CONFIGURATION_SEPARATOR "|"
@@ -37,6 +38,7 @@ decltype (ControlbarProfileModel::m_defaults)
     ControlbarProfileModel::m_defaults =
         {
             {
+                MINIMALIST_STYLE,
                 N_("Minimalist Style"),
                 {
                     {
@@ -89,6 +91,7 @@ decltype (ControlbarProfileModel::m_defaults)
                 }
             },
             {
+                ONE_LINER_STYLE,
                 N_("One-liner Style"),
                 {
                     {
@@ -145,6 +148,7 @@ decltype (ControlbarProfileModel::m_defaults)
                 }
             },
             {
+                SIMPLEST_STYLE,
                 N_("Simplest Style"),
                 {
                     {
@@ -184,6 +188,66 @@ decltype (ControlbarProfileModel::m_defaults)
                         }
                     }
                 }
+            },
+            {
+                CLASSIC_STYLE,
+                N_("Classic Style"),
+                {
+                    {
+                        PlayerControlbarModel::Mainplayer,
+                        {
+                            {
+                                {
+                                    ControlListModel::PLAY_BUTTON,
+                                    ControlListModel::WIDGET_SPACER,
+                                    ControlListModel::PREVIOUS_BUTTON,
+                                    ControlListModel::STOP_BUTTON,
+                                    ControlListModel::NEXT_BUTTON,
+                                    ControlListModel::WIDGET_SPACER,
+                                    ControlListModel::FULLSCREEN_BUTTON,
+                                    ControlListModel::EXTENDED_BUTTON,
+                                    ControlListModel::WIDGET_SPACER,
+                                    ControlListModel::PLAYLIST_BUTTON,
+                                    ControlListModel::LOOP_BUTTON,
+                                    ControlListModel::RANDOM_BUTTON
+                                },
+                                {
+
+                                },
+                                {
+                                    ControlListModel::VOLUME
+                                }
+                            }
+                        }
+                    },
+                    {
+                        PlayerControlbarModel::Miniplayer,
+                        {
+                            {
+                                {
+                                    ControlListModel::PLAY_BUTTON,
+                                    ControlListModel::WIDGET_SPACER,
+                                    ControlListModel::PREVIOUS_BUTTON,
+                                    ControlListModel::STOP_BUTTON,
+                                    ControlListModel::NEXT_BUTTON,
+                                    ControlListModel::WIDGET_SPACER,
+                                    ControlListModel::FULLSCREEN_BUTTON,
+                                    ControlListModel::EXTENDED_BUTTON,
+                                    ControlListModel::WIDGET_SPACER,
+                                    ControlListModel::PLAYLIST_BUTTON,
+                                    ControlListModel::LOOP_BUTTON,
+                                    ControlListModel::RANDOM_BUTTON
+                                },
+                                {
+
+                                },
+                                {
+                                    ControlListModel::VOLUME
+                                }
+                            }
+                        }
+                    }
+                }
             }
         };
 
@@ -222,12 +286,13 @@ void ControlbarProfileModel::insertDefaults()
 {
     // First, add a blank new profile:
     // ControlbarProfile will inject the default configurations during its construction.
-    newProfile(tr("Default Profile"));
+    m_maxId = 0;
+    newProfile(tr("Default Profile"), DEFAULT_STYLE);
 
     // Add default profiles:
     for (const auto& i : m_defaults)
     {
-        const auto ptrNewProfile = newProfile(qfut(i.name));
+        const auto ptrNewProfile = newProfile(qfut(i.name), i.id);
         if (!ptrNewProfile)
             continue;
 
@@ -422,6 +487,18 @@ ControlbarProfile* ControlbarProfileModel::currentModel() const
     return getProfile(selectedProfile());
 }
 
+/* Set the selected profile to the profile with the matching id */
+bool ControlbarProfileModel::setSelectedProfileFromId(int id)
+{
+    for(int i = 0; i < rowCount(); i++)
+    {
+        if(id == m_profiles.at(i)->id())
+            return setSelectedProfile(i);
+    }
+
+    return false;
+}
+
 void ControlbarProfileModel::save(bool clearDirty) const
 {
     assert(m_intf);
@@ -482,6 +559,7 @@ void ControlbarProfileModel::save(bool clearDirty) const
 
         settings->setValue(SETTINGS_KEY_NAME, m_profiles.at(i)->name());
         settings->setValue(SETTINGS_KEY_MODEL, val);
+        settings->setValue(SETTINGS_KEY_ID, m_profiles.at(i)->id());
     }
 
     settings->endArray();
@@ -528,6 +606,7 @@ bool ControlbarProfileModel::reload()
 
         const auto ptrNewProfile = new ControlbarProfile(this);
         ptrNewProfile->setName(settings->value(SETTINGS_KEY_NAME).toString());
+        ptrNewProfile->setId(settings->value(SETTINGS_KEY_ID).toInt());
 
         for (auto j : val)
         {
@@ -583,6 +662,7 @@ bool ControlbarProfileModel::reload()
 
     bool ok = false;
     int index = settings->value(SETTINGS_KEY_SELECTEDPROFILE).toInt(&ok);
+    m_maxId = m_profiles.isEmpty() ? 0 : m_profiles.back()->id() + 1;
 
     if (ok)
         setSelectedProfile(index);
@@ -633,7 +713,7 @@ ControlbarProfile *ControlbarProfileModel::getProfile(int index) const
     return m_profiles.at(index);
 }
 
-ControlbarProfile *ControlbarProfileModel::newProfile(const QString &name)
+ControlbarProfile *ControlbarProfileModel::newProfile(const QString &name, const int id)
 {
     if (name.isEmpty())
         return nullptr;
@@ -641,6 +721,8 @@ ControlbarProfile *ControlbarProfileModel::newProfile(const QString &name)
     const auto ptrProfile = newProfile();
 
     ptrProfile->setName(generateUniqueName(name));
+    ptrProfile->setId(id);
+    m_maxId++;
 
     return ptrProfile;
 }
@@ -660,7 +742,8 @@ ControlbarProfile *ControlbarProfileModel::newProfile()
 
 ControlbarProfile *ControlbarProfileModel::cloneProfile(const ControlbarProfile *profile)
 {
-    const auto ptrNewProfile = newProfile(profile->name());
+    // Any new profiles will just have the next incremental id
+    const auto ptrNewProfile = newProfile(profile->name(), m_maxId);
 
     if (!ptrNewProfile)
         return nullptr;
@@ -704,7 +787,6 @@ void ControlbarProfileModel::deleteSelectedProfile()
         return;
 
     const auto _selectedProfile = m_selectedProfile;
-
     beginRemoveRows(QModelIndex(), _selectedProfile, _selectedProfile);
 
     m_selectedProfile = -1;


=====================================
modules/gui/qt/dialogs/toolbar/controlbar_profile_model.hpp
=====================================
@@ -42,6 +42,7 @@ public:
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
     QHash<int, QByteArray> roleNames() const override;
+    enum {DEFAULT_STYLE, MINIMALIST_STYLE, ONE_LINER_STYLE, SIMPLEST_STYLE, CLASSIC_STYLE};
 
     // Editable:
     Q_INVOKABLE bool setData(const QModelIndex &index, const QVariant &value,
@@ -62,13 +63,14 @@ public:
 
     int selectedProfile() const;
     ControlbarProfile* currentModel() const;
+    bool setSelectedProfileFromId(int id);
 
     ControlbarProfile* cloneProfile(const ControlbarProfile* profile);
     Q_INVOKABLE void cloneSelectedProfile(const QString& newProfileName);
 
     Q_INVOKABLE ControlbarProfile* getProfile(int index) const;
 
-    Q_INVOKABLE ControlbarProfile* newProfile(const QString& name);
+    Q_INVOKABLE ControlbarProfile* newProfile(const QString& name, const int id);
     ControlbarProfile* newProfile();
 
     Q_INVOKABLE void deleteSelectedProfile();
@@ -89,8 +91,10 @@ private:
     QVector<ControlbarProfile *> m_profiles;
 
     int m_selectedProfile = -1;
+    int m_maxId = 0;
 
     struct Profile {
+        const int id;
         const char* name;
         QVector<ControlbarProfile::Configuration> modelData;
     };


=====================================
modules/gui/qt/maininterface/main_interface.cpp
=====================================
@@ -39,7 +39,6 @@
 #include "util/color_scheme_model.hpp"
 
 #include "widgets/native/interface_widgets.hpp"     // bgWidget, videoWidget
-#include "dialogs/firstrun/firstrun.hpp"                 // First Run
 
 #include "playlist/playlist_model.hpp"
 #include "playlist/playlist_controller.hpp"
@@ -207,6 +206,14 @@ MainInterface::MainInterface(qt_intf_t *_p_intf)
 
     /* Register callback for the intf-popupmenu variable */
     var_AddCallback( libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
+
+    if( config_GetInt("qt-privacy-ask") )
+    {
+        //postpone dialog call, as composition might not be ready yet
+        QMetaObject::invokeMethod(this, [this](){
+            THEDP->firstRunDialog();
+        }, Qt::QueuedConnection);
+    }
 }
 
 MainInterface::~MainInterface()
@@ -259,6 +266,10 @@ bool MainInterface::useClientSideDecoration() const
     return m_clientSideDecoration && m_windowVisibility != QWindow::FullScreen;
 }
 
+bool MainInterface::hasFirstrun() const {
+    return config_GetInt( "qt-privacy-ask" );
+}
+
 /*****************************
  *   Main UI handling        *
  *****************************/


=====================================
modules/gui/qt/maininterface/main_interface.hpp
=====================================
@@ -157,6 +157,7 @@ class MainInterface : public QObject
     Q_PROPERTY(ColorSchemeModel* colorScheme READ getColorScheme CONSTANT FINAL)
     Q_PROPERTY(bool hasVLM READ hasVLM CONSTANT FINAL)
     Q_PROPERTY(bool clientSideDecoration READ useClientSideDecoration NOTIFY useClientSideDecorationChanged FINAL)
+    Q_PROPERTY(bool hasFirstrun READ hasFirstrun CONSTANT FINAL)
     Q_PROPERTY(int  csdBorderSize READ CSDBorderSize NOTIFY useClientSideDecorationChanged FINAL)
     Q_PROPERTY(bool hasToolbarMenu READ hasToolbarMenu NOTIFY hasToolbarMenuChanged FINAL)
     Q_PROPERTY(bool canShowVideoPIP READ canShowVideoPIP CONSTANT FINAL)
@@ -208,6 +209,7 @@ public:
     inline ColorSchemeModel* getColorScheme() const { return m_colorScheme; }
     bool hasVLM() const;
     bool useClientSideDecoration() const;
+    bool hasFirstrun() const;
     inline bool hasToolbarMenu() const { return m_hasToolbarMenu; }
     inline bool canShowVideoPIP() const { return m_canShowVideoPIP; }
     inline void setCanShowVideoPIP(bool canShowVideoPIP) { m_canShowVideoPIP = canShowVideoPIP; }


=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -48,7 +48,7 @@ FocusScope {
     onViewPropertiesChanged: loadView()
     Component.onCompleted: {
         loadView()
-        if (medialib)
+        if (medialib && !mainInterface.hasFirstrun)
             // asynchronous call
             medialib.reload()
     }


=====================================
modules/gui/qt/pixmaps/theme_dark.svg
=====================================
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="87px" height="154px" viewBox="0 0 87 154" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>Theme - dark at 3x</title>
+    <defs>
+        <rect id="path-1" x="0" y="0" width="87" height="154" rx="2"></rect>
+    </defs>
+    <g id="Theme---dark" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="phone-dark-theme">
+            <g id="Combined-Shape-+-Combined-Shape-Copy-+-Combined-Shape-Copy-2-+-Combined-Shape-Copy-3-+-Combined-Shape-Copy-4-+-Combined-Shape-Copy-5-Mask">
+                <mask id="mask-2" fill="white">
+                    <use xlink:href="#path-1"></use>
+                </mask>
+                <use id="Mask" fill="#222222" xlink:href="#path-1"></use>
+                <path d="M21.75,63.765625 L21.75,66.171875 L4.83333333,66.171875 L4.83333333,63.765625 L21.75,63.765625 Z M36.25,58.953125 L36.25,61.359375 L4.83333333,61.359375 L4.83333333,58.953125 L36.25,58.953125 Z M40.0833333,20.453125 C40.6356181,20.453125 41.0833333,20.9008403 41.0833333,21.453125 L41.0833333,55.546875 C41.0833333,56.0991597 40.6356181,56.546875 40.0833333,56.546875 L5.83333333,56.546875 C5.28104858,56.546875 4.83333333,56.0991597 4.83333333,55.546875 L4.83333333,21.453125 C4.83333333,20.9008403 5.28104858,20.453125 5.83333333,20.453125 L40.0833333,20.453125 Z" id="Combined-Shape" fill-opacity="0.08" fill="#FFFFFF" mask="url(#mask-2)"></path>
+                <path d="M62.8333333,63.765625 L62.8333333,66.171875 L45.9166667,66.171875 L45.9166667,63.765625 L62.8333333,63.765625 Z M77.3333333,58.953125 L77.3333333,61.359375 L45.9166667,61.359375 L45.9166667,58.953125 L77.3333333,58.953125 Z M81.1666667,20.453125 C81.7189514,20.453125 82.1666667,20.9008403 82.1666667,21.453125 L82.1666667,55.546875 C82.1666667,56.0991597 81.7189514,56.546875 81.1666667,56.546875 L46.9166667,56.546875 C46.3643819,56.546875 45.9166667,56.0991597 45.9166667,55.546875 L45.9166667,21.453125 C45.9166667,20.9008403 46.3643819,20.453125 46.9166667,20.453125 L81.1666667,20.453125 Z" id="Combined-Shape-Copy" fill-opacity="0.08" fill="#FFFFFF" mask="url(#mask-2)"></path>
+                <path d="M21.75,114.296875 L21.75,116.703125 L4.83333333,116.703125 L4.83333333,114.296875 L21.75,114.296875 Z M36.25,109.484375 L36.25,111.890625 L4.83333333,111.890625 L4.83333333,109.484375 L36.25,109.484375 Z M40.0833333,70.984375 C40.6356181,70.984375 41.0833333,71.4320903 41.0833333,71.984375 L41.0833333,106.078125 C41.0833333,106.63041 40.6356181,107.078125 40.0833333,107.078125 L5.83333333,107.078125 C5.28104858,107.078125 4.83333333,106.63041 4.83333333,106.078125 L4.83333333,71.984375 C4.83333333,71.4320903 5.28104858,70.984375 5.83333333,70.984375 L40.0833333,70.984375 Z" id="Combined-Shape-Copy-2" fill-opacity="0.08" fill="#FFFFFF" mask="url(#mask-2)"></path>
+                <path d="M62.8333333,114.296875 L62.8333333,116.703125 L45.9166667,116.703125 L45.9166667,114.296875 L62.8333333,114.296875 Z M77.3333333,109.484375 L77.3333333,111.890625 L45.9166667,111.890625 L45.9166667,109.484375 L77.3333333,109.484375 Z M81.1666667,70.984375 C81.7189514,70.984375 82.1666667,71.4320903 82.1666667,71.984375 L82.1666667,106.078125 C82.1666667,106.63041 81.7189514,107.078125 81.1666667,107.078125 L46.9166667,107.078125 C46.3643819,107.078125 45.9166667,106.63041 45.9166667,106.078125 L45.9166667,71.984375 C45.9166667,71.4320903 46.3643819,70.984375 46.9166667,70.984375 L81.1666667,70.984375 Z" id="Combined-Shape-Copy-3" fill-opacity="0.08" fill="#FFFFFF" mask="url(#mask-2)"></path>
+                <path d="M21.75,164.828125 L21.75,167.234375 L4.83333333,167.234375 L4.83333333,164.828125 L21.75,164.828125 Z M36.25,160.015625 L36.25,162.421875 L4.83333333,162.421875 L4.83333333,160.015625 L36.25,160.015625 Z M40.0833333,121.515625 C40.6356181,121.515625 41.0833333,121.96334 41.0833333,122.515625 L41.0833333,156.609375 C41.0833333,157.16166 40.6356181,157.609375 40.0833333,157.609375 L5.83333333,157.609375 C5.28104858,157.609375 4.83333333,157.16166 4.83333333,156.609375 L4.83333333,122.515625 C4.83333333,121.96334 5.28104858,121.515625 5.83333333,121.515625 L40.0833333,121.515625 Z" id="Combined-Shape-Copy-4" fill-opacity="0.08" fill="#FFFFFF" mask="url(#mask-2)"></path>
+                <path d="M62.8333333,164.828125 L62.8333333,167.234375 L45.9166667,167.234375 L45.9166667,164.828125 L62.8333333,164.828125 Z M77.3333333,160.015625 L77.3333333,162.421875 L45.9166667,162.421875 L45.9166667,160.015625 L77.3333333,160.015625 Z M81.1666667,121.515625 C81.7189514,121.515625 82.1666667,121.96334 82.1666667,122.515625 L82.1666667,156.609375 C82.1666667,157.16166 81.7189514,157.609375 81.1666667,157.609375 L46.9166667,157.609375 C46.3643819,157.609375 45.9166667,157.16166 45.9166667,156.609375 L45.9166667,122.515625 C45.9166667,121.96334 46.3643819,121.515625 46.9166667,121.515625 L81.1666667,121.515625 Z" id="Combined-Shape-Copy-5" fill-opacity="0.08" fill="#FFFFFF" mask="url(#mask-2)"></path>
+            </g>
+            <path d="M2,0 L85,0 C86.1045695,-4.2495073e-16 87,0.8954305 87,2 L87,14.4375 L87,14.4375 L0,14.4375 L0,2 C-1.3527075e-16,0.8954305 0.8954305,2.02906125e-16 2,0 Z" id="Rectangle" fill="#FF8800"></path>
+            <ellipse id="Oval" fill="#FF8800" cx="72.5" cy="139.5625" rx="7.25" ry="7.21875"></ellipse>
+        </g>
+    </g>
+</svg>
\ No newline at end of file


=====================================
modules/gui/qt/pixmaps/theme_daynight.svg
=====================================
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="87px" height="154px" viewBox="0 0 87 154" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>Theme - mix</title>
+    <defs>
+        <rect id="path-1" x="0" y="0" width="87" height="154" rx="2.40625"></rect>
+        <rect id="path-3" x="0" y="0" width="87" height="154" rx="2"></rect>
+        <path d="M87,0.764935658 L87,152.59 C87,153.921006 85.9210062,155 84.59,155 L0,155 L0,155 L86.6255948,0.667043717 C86.679659,0.570722394 86.8015706,0.536466249 86.8978919,0.590530475 C86.9609573,0.625928426 87,0.692615198 87,0.764935658 Z" id="path-5"></path>
+    </defs>
+    <g id="Theme---mix" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="phone-both-theme">
+            <g id="Combined-Shape-+-Combined-Shape-Copy-+-Combined-Shape-Copy-2-+-Combined-Shape-Copy-3-+-Combined-Shape-Copy-4-+-Combined-Shape-Copy-5-Mask">
+                <mask id="mask-2" fill="white">
+                    <use xlink:href="#path-1"></use>
+                </mask>
+                <use id="Mask" fill="#FFFFFF" xlink:href="#path-1"></use>
+                <path d="M21.65625,63.765625 L21.65625,66.171875 L4.8125,66.171875 L4.8125,63.765625 L21.65625,63.765625 Z M36.09375,58.953125 L36.09375,61.359375 L4.8125,61.359375 L4.8125,58.953125 L36.09375,58.953125 Z M39.703125,20.453125 C40.3675926,20.453125 40.90625,20.9917824 40.90625,21.65625 L40.90625,55.34375 C40.90625,56.0082176 40.3675926,56.546875 39.703125,56.546875 L6.015625,56.546875 C5.35115741,56.546875 4.8125,56.0082176 4.8125,55.34375 L4.8125,21.65625 C4.8125,20.9917824 5.35115741,20.453125 6.015625,20.453125 L39.703125,20.453125 Z" id="Combined-Shape" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M62.5625,63.765625 L62.5625,66.171875 L45.71875,66.171875 L45.71875,63.765625 L62.5625,63.765625 Z M77,58.953125 L77,61.359375 L45.71875,61.359375 L45.71875,58.953125 L77,58.953125 Z M80.609375,20.453125 C81.2738426,20.453125 81.8125,20.9917824 81.8125,21.65625 L81.8125,55.34375 C81.8125,56.0082176 81.2738426,56.546875 80.609375,56.546875 L46.921875,56.546875 C46.2574074,56.546875 45.71875,56.0082176 45.71875,55.34375 L45.71875,21.65625 C45.71875,20.9917824 46.2574074,20.453125 46.921875,20.453125 L80.609375,20.453125 Z" id="Combined-Shape-Copy" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M21.65625,114.296875 L21.65625,116.703125 L4.8125,116.703125 L4.8125,114.296875 L21.65625,114.296875 Z M36.09375,109.484375 L36.09375,111.890625 L4.8125,111.890625 L4.8125,109.484375 L36.09375,109.484375 Z M39.703125,70.984375 C40.3675926,70.984375 40.90625,71.5230324 40.90625,72.1875 L40.90625,105.875 C40.90625,106.539468 40.3675926,107.078125 39.703125,107.078125 L6.015625,107.078125 C5.35115741,107.078125 4.8125,106.539468 4.8125,105.875 L4.8125,72.1875 C4.8125,71.5230324 5.35115741,70.984375 6.015625,70.984375 L39.703125,70.984375 Z" id="Combined-Shape-Copy-2" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M62.5625,114.296875 L62.5625,116.703125 L45.71875,116.703125 L45.71875,114.296875 L62.5625,114.296875 Z M77,109.484375 L77,111.890625 L45.71875,111.890625 L45.71875,109.484375 L77,109.484375 Z M80.609375,70.984375 C81.2738426,70.984375 81.8125,71.5230324 81.8125,72.1875 L81.8125,105.875 C81.8125,106.539468 81.2738426,107.078125 80.609375,107.078125 L46.921875,107.078125 C46.2574074,107.078125 45.71875,106.539468 45.71875,105.875 L45.71875,72.1875 C45.71875,71.5230324 46.2574074,70.984375 46.921875,70.984375 L80.609375,70.984375 Z" id="Combined-Shape-Copy-3" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M21.65625,164.828125 L21.65625,167.234375 L4.8125,167.234375 L4.8125,164.828125 L21.65625,164.828125 Z M36.09375,160.015625 L36.09375,162.421875 L4.8125,162.421875 L4.8125,160.015625 L36.09375,160.015625 Z M39.703125,121.515625 C40.3675926,121.515625 40.90625,122.054282 40.90625,122.71875 L40.90625,156.40625 C40.90625,157.070718 40.3675926,157.609375 39.703125,157.609375 L6.015625,157.609375 C5.35115741,157.609375 4.8125,157.070718 4.8125,156.40625 L4.8125,122.71875 C4.8125,122.054282 5.35115741,121.515625 6.015625,121.515625 L39.703125,121.515625 Z" id="Combined-Shape-Copy-4" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M62.5625,164.828125 L62.5625,167.234375 L45.71875,167.234375 L45.71875,164.828125 L62.5625,164.828125 Z M77,160.015625 L77,162.421875 L45.71875,162.421875 L45.71875,160.015625 L77,160.015625 Z M80.609375,121.515625 C81.2738426,121.515625 81.8125,122.054282 81.8125,122.71875 L81.8125,156.40625 C81.8125,157.070718 81.2738426,157.609375 80.609375,157.609375 L46.921875,157.609375 C46.2574074,157.609375 45.71875,157.070718 45.71875,156.40625 L45.71875,122.71875 C45.71875,122.054282 46.2574074,121.515625 46.921875,121.515625 L80.609375,121.515625 Z" id="Combined-Shape-Copy-5" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M2.40625,0 L84.59375,0 C85.9226852,-2.44121432e-16 87,1.07731482 87,2.40625 L87,14.4375 L87,14.4375 L0,14.4375 L0,2.40625 C-1.62747621e-16,1.07731482 1.07731482,2.44121432e-16 2.40625,0 Z" id="Rectangle" fill="#FF610A" mask="url(#mask-2)"></path>
+            </g>
+            <mask id="mask-4" fill="white">
+                <use xlink:href="#path-3"></use>
+            </mask>
+            <g id="Mask"></g>
+            <g id="file" mask="url(#mask-4)">
+                <g transform="translate(0.000000, -1.000000)">
+                    <mask id="mask-6" fill="white">
+                        <use xlink:href="#path-5"></use>
+                    </mask>
+                    <use id="Mask" stroke="none" fill="#222222" fill-rule="evenodd" xlink:href="#path-5"></use>
+                    <path d="M21.65625,64.765625 L21.65625,67.171875 L4.8125,67.171875 L4.8125,64.765625 L21.65625,64.765625 Z M36.09375,59.953125 L36.09375,62.359375 L4.8125,62.359375 L4.8125,59.953125 L36.09375,59.953125 Z M39.703125,21.453125 C40.3675926,21.453125 40.90625,21.9917824 40.90625,22.65625 L40.90625,56.34375 C40.90625,57.0082176 40.3675926,57.546875 39.703125,57.546875 L6.015625,57.546875 C5.35115741,57.546875 4.8125,57.0082176 4.8125,56.34375 L4.8125,22.65625 C4.8125,21.9917824 5.35115741,21.453125 6.015625,21.453125 L39.703125,21.453125 Z" id="Combined-Shape" stroke="none" fill-opacity="0.08" fill="#FFFFFF" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                    <path d="M62.5625,64.765625 L62.5625,67.171875 L45.71875,67.171875 L45.71875,64.765625 L62.5625,64.765625 Z M77,59.953125 L77,62.359375 L45.71875,62.359375 L45.71875,59.953125 L77,59.953125 Z M80.609375,21.453125 C81.2738426,21.453125 81.8125,21.9917824 81.8125,22.65625 L81.8125,56.34375 C81.8125,57.0082176 81.2738426,57.546875 80.609375,57.546875 L46.921875,57.546875 C46.2574074,57.546875 45.71875,57.0082176 45.71875,56.34375 L45.71875,22.65625 C45.71875,21.9917824 46.2574074,21.453125 46.921875,21.453125 L80.609375,21.453125 Z" id="Combined-Shape-Copy" stroke="none" fill-opacity="0.08" fill="#FFFFFF" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                    <path d="M21.65625,115.296875 L21.65625,117.703125 L4.8125,117.703125 L4.8125,115.296875 L21.65625,115.296875 Z M36.09375,110.484375 L36.09375,112.890625 L4.8125,112.890625 L4.8125,110.484375 L36.09375,110.484375 Z M39.703125,71.984375 C40.3675926,71.984375 40.90625,72.5230324 40.90625,73.1875 L40.90625,106.875 C40.90625,107.539468 40.3675926,108.078125 39.703125,108.078125 L6.015625,108.078125 C5.35115741,108.078125 4.8125,107.539468 4.8125,106.875 L4.8125,73.1875 C4.8125,72.5230324 5.35115741,71.984375 6.015625,71.984375 L39.703125,71.984375 Z" id="Combined-Shape-Copy-2" stroke="none" fill-opacity="0.08" fill="#FFFFFF" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                    <path d="M62.5625,115.296875 L62.5625,117.703125 L45.71875,117.703125 L45.71875,115.296875 L62.5625,115.296875 Z M77,110.484375 L77,112.890625 L45.71875,112.890625 L45.71875,110.484375 L77,110.484375 Z M80.609375,71.984375 C81.2738426,71.984375 81.8125,72.5230324 81.8125,73.1875 L81.8125,106.875 C81.8125,107.539468 81.2738426,108.078125 80.609375,108.078125 L46.921875,108.078125 C46.2574074,108.078125 45.71875,107.539468 45.71875,106.875 L45.71875,73.1875 C45.71875,72.5230324 46.2574074,71.984375 46.921875,71.984375 L80.609375,71.984375 Z" id="Combined-Shape-Copy-3" stroke="none" fill-opacity="0.08" fill="#FFFFFF" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                    <path d="M21.65625,165.828125 L21.65625,168.234375 L4.8125,168.234375 L4.8125,165.828125 L21.65625,165.828125 Z M36.09375,161.015625 L36.09375,163.421875 L4.8125,163.421875 L4.8125,161.015625 L36.09375,161.015625 Z M39.703125,122.515625 C40.3675926,122.515625 40.90625,123.054282 40.90625,123.71875 L40.90625,157.40625 C40.90625,158.070718 40.3675926,158.609375 39.703125,158.609375 L6.015625,158.609375 C5.35115741,158.609375 4.8125,158.070718 4.8125,157.40625 L4.8125,123.71875 C4.8125,123.054282 5.35115741,122.515625 6.015625,122.515625 L39.703125,122.515625 Z" id="Combined-Shape-Copy-4" stroke="none" fill-opacity="0.08" fill="#FFFFFF" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                    <path d="M62.5625,165.828125 L62.5625,168.234375 L45.71875,168.234375 L45.71875,165.828125 L62.5625,165.828125 Z M77,161.015625 L77,163.421875 L45.71875,163.421875 L45.71875,161.015625 L77,161.015625 Z M80.609375,122.515625 C81.2738426,122.515625 81.8125,123.054282 81.8125,123.71875 L81.8125,157.40625 C81.8125,158.070718 81.2738426,158.609375 80.609375,158.609375 L46.921875,158.609375 C46.2574074,158.609375 45.71875,158.070718 45.71875,157.40625 L45.71875,123.71875 C45.71875,123.054282 46.2574074,122.515625 46.921875,122.515625 L80.609375,122.515625 Z" id="Combined-Shape-Copy-5" stroke="none" fill-opacity="0.08" fill="#FFFFFF" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                    <path d="M2.40625,1 L84.59375,1 C85.9226852,1 87,2.07731482 87,3.40625 L87,15.4375 L87,15.4375 L0,15.4375 L0,3.40625 C-1.62747621e-16,2.07731482 1.07731482,1 2.40625,1 Z" id="Rectangle" stroke="none" fill="#FF8800" fill-rule="evenodd" mask="url(#mask-6)"></path>
+                </g>
+            </g>
+            <circle id="Oval" fill="#FF8800" mask="url(#mask-4)" cx="72.1875" cy="139.5625" r="7.21875"></circle>
+        </g>
+    </g>
+</svg>
\ No newline at end of file


=====================================
modules/gui/qt/pixmaps/theme_light.svg
=====================================
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="87px" height="154px" viewBox="0 0 87 154" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>Theme - light at 3x</title>
+    <defs>
+        <rect id="path-1" x="0" y="0" width="87" height="154" rx="2.40625"></rect>
+    </defs>
+    <g id="Theme---light" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="phone-light-theme">
+            <g id="Combined-Shape-+-Combined-Shape-Copy-+-Combined-Shape-Copy-2-+-Combined-Shape-Copy-3-+-Combined-Shape-Copy-4-+-Combined-Shape-Copy-5-Mask">
+                <mask id="mask-2" fill="white">
+                    <use xlink:href="#path-1"></use>
+                </mask>
+                <use id="Mask" fill="#FFFFFF" xlink:href="#path-1"></use>
+                <path d="M21.65625,63.765625 L21.65625,66.171875 L4.8125,66.171875 L4.8125,63.765625 L21.65625,63.765625 Z M36.09375,58.953125 L36.09375,61.359375 L4.8125,61.359375 L4.8125,58.953125 L36.09375,58.953125 Z M39.703125,20.453125 C40.3675926,20.453125 40.90625,20.9917824 40.90625,21.65625 L40.90625,55.34375 C40.90625,56.0082176 40.3675926,56.546875 39.703125,56.546875 L6.015625,56.546875 C5.35115741,56.546875 4.8125,56.0082176 4.8125,55.34375 L4.8125,21.65625 C4.8125,20.9917824 5.35115741,20.453125 6.015625,20.453125 L39.703125,20.453125 Z" id="Combined-Shape" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M62.5625,63.765625 L62.5625,66.171875 L45.71875,66.171875 L45.71875,63.765625 L62.5625,63.765625 Z M77,58.953125 L77,61.359375 L45.71875,61.359375 L45.71875,58.953125 L77,58.953125 Z M80.609375,20.453125 C81.2738426,20.453125 81.8125,20.9917824 81.8125,21.65625 L81.8125,55.34375 C81.8125,56.0082176 81.2738426,56.546875 80.609375,56.546875 L46.921875,56.546875 C46.2574074,56.546875 45.71875,56.0082176 45.71875,55.34375 L45.71875,21.65625 C45.71875,20.9917824 46.2574074,20.453125 46.921875,20.453125 L80.609375,20.453125 Z" id="Combined-Shape-Copy" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M21.65625,114.296875 L21.65625,116.703125 L4.8125,116.703125 L4.8125,114.296875 L21.65625,114.296875 Z M36.09375,109.484375 L36.09375,111.890625 L4.8125,111.890625 L4.8125,109.484375 L36.09375,109.484375 Z M39.703125,70.984375 C40.3675926,70.984375 40.90625,71.5230324 40.90625,72.1875 L40.90625,105.875 C40.90625,106.539468 40.3675926,107.078125 39.703125,107.078125 L6.015625,107.078125 C5.35115741,107.078125 4.8125,106.539468 4.8125,105.875 L4.8125,72.1875 C4.8125,71.5230324 5.35115741,70.984375 6.015625,70.984375 L39.703125,70.984375 Z" id="Combined-Shape-Copy-2" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M62.5625,114.296875 L62.5625,116.703125 L45.71875,116.703125 L45.71875,114.296875 L62.5625,114.296875 Z M77,109.484375 L77,111.890625 L45.71875,111.890625 L45.71875,109.484375 L77,109.484375 Z M80.609375,70.984375 C81.2738426,70.984375 81.8125,71.5230324 81.8125,72.1875 L81.8125,105.875 C81.8125,106.539468 81.2738426,107.078125 80.609375,107.078125 L46.921875,107.078125 C46.2574074,107.078125 45.71875,106.539468 45.71875,105.875 L45.71875,72.1875 C45.71875,71.5230324 46.2574074,70.984375 46.921875,70.984375 L80.609375,70.984375 Z" id="Combined-Shape-Copy-3" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M21.65625,164.828125 L21.65625,167.234375 L4.8125,167.234375 L4.8125,164.828125 L21.65625,164.828125 Z M36.09375,160.015625 L36.09375,162.421875 L4.8125,162.421875 L4.8125,160.015625 L36.09375,160.015625 Z M39.703125,121.515625 C40.3675926,121.515625 40.90625,122.054282 40.90625,122.71875 L40.90625,156.40625 C40.90625,157.070718 40.3675926,157.609375 39.703125,157.609375 L6.015625,157.609375 C5.35115741,157.609375 4.8125,157.070718 4.8125,156.40625 L4.8125,122.71875 C4.8125,122.054282 5.35115741,121.515625 6.015625,121.515625 L39.703125,121.515625 Z" id="Combined-Shape-Copy-4" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+                <path d="M62.5625,164.828125 L62.5625,167.234375 L45.71875,167.234375 L45.71875,164.828125 L62.5625,164.828125 Z M77,160.015625 L77,162.421875 L45.71875,162.421875 L45.71875,160.015625 L77,160.015625 Z M80.609375,121.515625 C81.2738426,121.515625 81.8125,122.054282 81.8125,122.71875 L81.8125,156.40625 C81.8125,157.070718 81.2738426,157.609375 80.609375,157.609375 L46.921875,157.609375 C46.2574074,157.609375 45.71875,157.070718 45.71875,156.40625 L45.71875,122.71875 C45.71875,122.054282 46.2574074,121.515625 46.921875,121.515625 L80.609375,121.515625 Z" id="Combined-Shape-Copy-5" fill-opacity="0.12" fill="#000000" mask="url(#mask-2)"></path>
+            </g>
+            <path d="M2.40625,0 L84.59375,0 C85.9226852,-2.44121432e-16 87,1.07731482 87,2.40625 L87,14.4375 L87,14.4375 L0,14.4375 L0,2.40625 C-1.62747621e-16,1.07731482 1.07731482,2.44121432e-16 2.40625,0 Z" id="Rectangle" fill="#FF610A"></path>
+            <circle id="Oval" fill="#FF610A" cx="72.1875" cy="139.5625" r="7.21875"></circle>
+        </g>
+    </g>
+</svg>
\ No newline at end of file


=====================================
modules/gui/qt/util/color_scheme_model.cpp
=====================================
@@ -90,15 +90,9 @@ public:
     }
 
 private:
-    struct Item
-    {
-        QString text;
-        ColorScheme scheme;
-    };
-
     ColorSchemeModel *m_colorSchemeModel;
     QSettings m_settings;
-    const QVector<Item> m_items;
+    const QVector<ColorSchemeModel::Item> m_items;
 };
 
 #endif
@@ -127,13 +121,7 @@ public:
     }
 
 private:
-    struct Item
-    {
-        QString text;
-        ColorScheme scheme;
-    };
-
-    const QVector<Item> m_items;
+    const QVector<ColorSchemeModel::Item> m_items;
 };
 
 std::unique_ptr<ColorSchemeModel::SchemeList> ColorSchemeModel::createList(ColorSchemeModel *parent)
@@ -219,6 +207,18 @@ QString ColorSchemeModel::currentText() const
     return m_list->text(m_currentIndex);
 }
 
+QVector<ColorSchemeModel::Item> ColorSchemeModel::getSchemes() const
+{
+    QVector<ColorSchemeModel::Item> vec;
+    vec.reserve( m_list->size() );
+
+    for(int i = 0; i < m_list->size(); ++i)
+    {
+        vec.push_back( { m_list->text(i), m_list->scheme(i) } );
+    }
+    return vec;
+}
+
 void ColorSchemeModel::setCurrentScheme(const ColorScheme scheme)
 {
     for (int i = 0; i < m_list->size(); ++i)


=====================================
modules/gui/qt/util/color_scheme_model.hpp
=====================================
@@ -39,6 +39,12 @@ public:
         Auto
     };
 
+    struct Item
+    {
+        QString text;
+        ColorScheme scheme;
+    };
+
     Q_ENUM(ColorScheme);
 
     explicit ColorSchemeModel(QObject* parent = nullptr);
@@ -52,6 +58,7 @@ public:
     void setCurrentIndex(int newIndex);
 
     QString currentText() const;
+    QVector<Item> getSchemes() const;
 
     void setCurrentScheme(ColorScheme scheme);
     ColorScheme currentScheme() const;


=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -117,6 +117,9 @@
         <file alias="noart_videoCover.svg">pixmaps/noart_videoCover.svg</file>
         <file alias="play_button.svg">pixmaps/play_button.svg</file>
         <file alias="back.svg">pixmaps/back.svg</file>
+        <file alias="theme_dark.svg">pixmaps/theme_dark.svg</file>
+        <file alias="theme_daynight.svg">pixmaps/theme_daynight.svg</file>
+        <file alias="theme_light.svg">pixmaps/theme_light.svg</file>
     </qresource>
     <qresource prefix="/prefsmenu">
         <file alias="cone_audio_64.png">pixmaps/prefs/spref_cone_Audio_64.png</file>


=====================================
modules/misc/medialibrary/medialibrary.cpp
=====================================
@@ -461,49 +461,6 @@ bool MediaLibrary::Init()
     return true;
 }
 
-bool MediaLibrary::Start()
-{
-    if ( Init() == false )
-        return false;
-
-    if ( m_started.test_and_set() )
-        /* The code below should be executed at most once */
-        return true;
-
-    /*
-     * If we already provided the medialib with some entry points, then we have
-     * nothing left to do
-     */
-    auto entryPoints = m_ml->entryPoints()->all();
-    if ( entryPoints.empty() == false )
-        return true;
-
-    auto folders = vlc::wrap_cptr( var_InheritString( m_vlc_ml, "ml-folders" ) );
-    if ( folders != nullptr && strlen( folders.get() ) > 0 )
-    {
-        std::istringstream ss( folders.get() );
-        std::string folder;
-        while ( std::getline( ss, folder, ';' ) )
-            m_ml->discover( folder );
-    }
-    else
-    {
-        std::string varValue;
-        for( auto&& target : { VLC_VIDEOS_DIR, VLC_MUSIC_DIR } )
-        {
-            auto folder = vlc::wrap_cptr( config_GetUserDir( target ) );
-            if( folder == nullptr )
-                continue;
-            auto folderMrl = vlc::wrap_cptr( vlc_path2uri( folder.get(), nullptr ) );
-            m_ml->discover( folderMrl.get() );
-            varValue += std::string{ ";" } + folderMrl.get();
-        }
-        if ( varValue.empty() == false )
-            config_PutPsz( "ml-folders", varValue.c_str()+1 ); /* skip initial ';' */
-    }
-    return true;
-}
-
 int MediaLibrary::Control( int query, va_list args )
 {
     /*
@@ -531,7 +488,7 @@ int MediaLibrary::Control( int query, va_list args )
         {
             /* These operations require the media library to be started
              * ie. that the background threads are started */
-            if ( Start() == false )
+            if ( !Init() )
                 return VLC_EGENERIC;
             break;
         }
@@ -2035,6 +1992,5 @@ vlc_module_begin()
     set_subcategory(SUBCAT_ADVANCED_MISC)
     set_capability("medialibrary", 100)
     set_callbacks(Open, Close)
-    add_string( "ml-folders", nullptr, ML_FOLDER_TEXT, ML_FOLDER_LONGTEXT )
     add_bool( "ml-verbose", false, ML_VERBOSE, nullptr )
 vlc_module_end()


=====================================
modules/misc/medialibrary/medialibrary.h
=====================================
@@ -152,7 +152,6 @@ public:
     static MediaLibrary* create( vlc_medialibrary_module_t* ml );
 
     bool Init();
-    bool Start();
     int Control( int query, va_list args );
     int List( int query, const vlc_ml_query_params_t* params, va_list args );
     void* Get( int query, va_list args );


=====================================
po/POTFILES.in
=====================================
@@ -731,8 +731,8 @@ modules/gui/qt/dialogs/extensions/extensions.cpp
 modules/gui/qt/dialogs/extensions/extensions.hpp
 modules/gui/qt/dialogs/fingerprint/fingerprintdialog.cpp
 modules/gui/qt/dialogs/fingerprint/fingerprintdialog.hpp
-modules/gui/qt/dialogs/firstrun/firstrun.cpp
-modules/gui/qt/dialogs/firstrun/firstrun.hpp
+modules/gui/qt/dialogs/firstrun/firstrunwizard.cpp
+modules/gui/qt/dialogs/firstrun/firstrunwizard.hpp
 modules/gui/qt/dialogs/gototime/gototime.cpp
 modules/gui/qt/dialogs/gototime/gototime.hpp
 modules/gui/qt/dialogs/help/help.cpp



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3d1d2a5d550d8d0c6fd111e5e7ba0dddb4682d64...3895e912bffaed9f99a5f657272f307f2251791d

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3d1d2a5d550d8d0c6fd111e5e7ba0dddb4682d64...3895e912bffaed9f99a5f657272f307f2251791d
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list