[vlc-commits] [Git][videolan/vlc][master] 7 commits: qt/preferences: fix inital value for color scheme

Jean-Baptiste Kempf gitlab at videolan.org
Fri May 21 23:21:15 UTC 2021



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


Commits:
8e77a60a by Prince Gupta at 2021-05-21T21:50:51+00:00
qt/preferences: fix inital value for color scheme

ref #25584

- - - - -
1db0e725 by Prince Gupta at 2021-05-21T21:50:51+00:00
qt/preferences: fix "Force windows style" option

closes #25720

- - - - -
ef29f1df by Prince Gupta at 2021-05-21T21:50:51+00:00
qt/preferences: reset live properties on cancel

ref #25584

- - - - -
335ca010 by Prince Gupta at 2021-05-21T21:50:51+00:00
qt/mlfoldersmodel: allow directly adding/removing a url

fix MLFoldersModel::remove, ensure MRL are fully encoded
Refs #25555

- - - - -
3a253b50 by Prince Gupta at 2021-05-21T21:50:51+00:00
qt/mlfoldersmodel: notify operation failure

- - - - -
2152fe55 by Prince Gupta at 2021-05-21T21:50:51+00:00
qt: implement MLFoldersEditor widget

can be used to change a MLFoldersModel

- - - - -
995b74f4 by Prince Gupta at 2021-05-21T21:50:51+00:00
qt/preferences: use MLFoldersEditor for ml folders list

doesn't applies changes till save
ref #25584

- - - - -


9 changed files:

- modules/gui/qt/Makefile.am
- modules/gui/qt/dialogs/preferences/simple_preferences.cpp
- modules/gui/qt/dialogs/preferences/simple_preferences.hpp
- modules/gui/qt/dialogs/preferences/sprefs_medialibrary.ui
- modules/gui/qt/medialibrary/mlfoldersmodel.cpp
- modules/gui/qt/medialibrary/mlfoldersmodel.hpp
- modules/gui/qt/util/qvlcapp.hpp
- + modules/gui/qt/widgets/native/mlfolderseditor.cpp
- + modules/gui/qt/widgets/native/mlfolderseditor.hpp


Changes:

=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -256,6 +256,8 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/widgets/native/customwidgets.cpp gui/qt/widgets/native/customwidgets.hpp \
 	gui/qt/widgets/native/interface_widgets.cpp \
 	gui/qt/widgets/native/interface_widgets.hpp \
+	gui/qt/widgets/native/mlfolderseditor.cpp \
+	gui/qt/widgets/native/mlfolderseditor.hpp \
 	gui/qt/widgets/native/qvlcframe.cpp \
 	gui/qt/widgets/native/qvlcframe.hpp \
 	gui/qt/widgets/native/roundimage.cpp gui/qt/widgets/native/roundimage.hpp \
@@ -395,6 +397,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/widgets/native/animators.moc.cpp \
 	gui/qt/widgets/native/customwidgets.moc.cpp \
 	gui/qt/widgets/native/interface_widgets.moc.cpp \
+	gui/qt/widgets/native/mlfolderseditor.moc.cpp \
 	gui/qt/widgets/native/roundimage.moc.cpp \
 	gui/qt/widgets/native/searchlineedit.moc.cpp
 


=====================================
modules/gui/qt/dialogs/preferences/simple_preferences.cpp
=====================================
@@ -30,6 +30,7 @@
 #include "preferences_widgets.hpp"
 #include "maininterface/main_interface.hpp"
 #include "util/color_scheme_model.hpp"
+#include "util/qvlcapp.hpp"
 #include "util/proxycolumnmodel.hpp"
 
 #include <vlc_config_cat.h>
@@ -196,6 +197,50 @@ static int getDefaultAudioVolume(const char *aout)
         return -1;
 }
 
+namespace
+{
+    void fillStylesCombo( QComboBox *stylesCombo, const QString &initialStyle)
+    {
+        stylesCombo->addItem( qtr("System's default") );
+        stylesCombo->addItems( QStyleFactory::keys() );
+        stylesCombo->setCurrentIndex( stylesCombo->findText( initialStyle ) );
+        stylesCombo->insertSeparator( 1 );
+        if ( stylesCombo->currentIndex() < 0 )
+            stylesCombo->setCurrentIndex( 0 ); /* default */
+    }
+
+    QString getQStyleKey(const QComboBox *stylesCombo, const QString &defaultStyleName)
+    {
+        vlc_assert( stylesCombo );
+        const int index = stylesCombo->currentIndex();
+        if (stylesCombo->currentIndex() == 0)
+            return defaultStyleName;
+        return QStyleFactory::keys().at( index - 2 );
+    }
+}
+
+class PropertyResetter
+{
+public:
+    PropertyResetter(QWidget *control, const char * property)
+        : m_control {control}
+        , m_property {property}
+        , m_initialValue {m_control->property(property)}
+    {
+    }
+
+    void reset()
+    {
+        bool success = m_control->setProperty(m_property.data(), m_initialValue);
+        vlc_assert(success);
+    }
+
+private:
+    QWidget *m_control;
+    const QByteArray m_property;
+    const QVariant m_initialValue;
+};
+
 /*********************************************************************
  * The List of categories
  *********************************************************************/
@@ -761,15 +806,10 @@ SPrefsPanel::SPrefsPanel( intf_thread_t *_p_intf, QWidget *_parent,
             optionWidgets["skinRB"] = ui.skins;
             optionWidgets["qtRB"] = ui.qt;
 #if !defined( _WIN32)
-            ui.stylesCombo->addItem( qtr("System's default") );
-            ui.stylesCombo->addItems( QStyleFactory::keys() );
-            ui.stylesCombo->setCurrentIndex( ui.stylesCombo->findText(
-                        getSettings()->value( "MainWindow/QtStyle", "" ).toString() ) );
-            ui.stylesCombo->insertSeparator( 1 );
-            if ( ui.stylesCombo->currentIndex() < 0 )
-                ui.stylesCombo->setCurrentIndex( 0 ); /* default */
-
-            CONNECT( ui.stylesCombo, currentIndexChanged( QString ), this, changeStyle( QString ) );
+            fillStylesCombo( ui.stylesCombo, getSettings()->value( "MainWindow/QtStyle", "" ).toString() );
+            m_resetters.push_back( std::make_unique<PropertyResetter>( ui.stylesCombo, "currentIndex" ) );
+
+            CONNECT( ui.stylesCombo, currentIndexChanged( int ), this, changeStyle( ) );
             optionWidgets["styleCB"] = ui.stylesCombo;
 #else
             ui.stylesCombo->hide();
@@ -811,9 +851,12 @@ SPrefsPanel::SPrefsPanel( intf_thread_t *_p_intf, QWidget *_parent,
             CONFIG_BOOL( "qt-menubar", menuBarCheck );
 
             ui.pinVideoControlsCheckbox->setChecked( p_intf->p_sys->p_mi->pinVideoControls() );
+            m_resetters.push_back(std::make_unique<PropertyResetter>(ui.pinVideoControlsCheckbox, "checked"));
             QObject::connect( ui.pinVideoControlsCheckbox, &QCheckBox::stateChanged, p_intf->p_sys->p_mi, &MainInterface::setPinVideoControls );
 
             ui.colorSchemeComboBox->insertItems(0, p_intf->p_sys->p_mi->getColorScheme()->stringList());
+            ui.colorSchemeComboBox->setCurrentText( p_intf->p_sys->p_mi->getColorScheme()->getCurrent() );
+            m_resetters.push_back(std::make_unique<PropertyResetter>( ui.colorSchemeComboBox, "currentIndex" ));
             QObject::connect( ui.colorSchemeComboBox, &QComboBox::currentTextChanged, p_intf->p_sys->p_mi->getColorScheme(), &ColorSchemeModel::setCurrent );
 
             const float intfScaleFloatFactor = 100.f;
@@ -839,6 +882,8 @@ SPrefsPanel::SPrefsPanel( intf_thread_t *_p_intf, QWidget *_parent,
                                                  , p_intf->p_sys->p_mi->getMaxIntfUserScaleFactor() * intfScaleFloatFactor);
 
             updateIntfUserScaleFactorFromControls( p_intf->p_sys->p_mi->getIntfUserScaleFactor() * intfScaleFloatFactor );
+            m_resetters.push_back( std::make_unique<PropertyResetter>( ui.intfScaleFactorSlider, "value" ) );
+
             QObject::connect( ui.intfScaleFactorSlider, QOverload<int>::of(&QSlider::valueChanged)
                               , p_intf->p_sys->p_mi , updateIntfUserScaleFactorFromControls );
             QObject::connect( ui.intfScaleFactorSpinBox, QOverload<int>::of(&QSpinBox::valueChanged)
@@ -980,21 +1025,18 @@ SPrefsPanel::SPrefsPanel( intf_thread_t *_p_intf, QWidget *_parent,
 
                 if ( vlc_ml_instance_get( p_intf ) != NULL )
                 {
-                    mlFoldersModel = new ProxyColumnModel<MLFoldersModel>(1, {{0, qtr("Path")}, {1, qtr("Remove")}}, this );
-                    mlFoldersModel->setMl( vlc_ml_instance_get( p_intf ) );
-                    ui.entryPoints->setModel( mlFoldersModel );
-                    connect( mlFoldersModel , &QAbstractItemModel::modelReset , this, [this, view = ui.entryPoints]() { MLdrawControls( view ); } );
+                    auto foldersModel = new MLFoldersModel( this );
+                    foldersModel->setMl( vlc_ml_instance_get( p_intf ) );
+                    ui.entryPoints->setMLFoldersModel( foldersModel );
+                    mlFoldersEditor = ui.entryPoints;
 
-                    mlBannedFoldersModel = new ProxyColumnModel<MLBannedFoldersModel>(1, {{0, qtr("Path")}, {1, qtr("Remove")}}, this );
-                    mlBannedFoldersModel->setMl( vlc_ml_instance_get( p_intf ));
-                    ui.bannedEntryPoints->setModel( mlBannedFoldersModel );
-                    connect( mlBannedFoldersModel , &QAbstractItemModel::modelReset , this, [this, view = ui.bannedEntryPoints]() { MLdrawControls( view ); } );
+                    auto bannedFoldersModel = new MLBannedFoldersModel( this );
+                    bannedFoldersModel->setMl( vlc_ml_instance_get( p_intf ));
+                    ui.bannedEntryPoints->setMLFoldersModel( bannedFoldersModel );
+                    mlBannedFoldersEditor = ui.bannedEntryPoints;
 
                     BUTTONACT( ui.addButton , MLaddNewFolder() );
                     BUTTONACT( ui.banButton , MLBanFolder() );
-
-                    MLdrawControls( ui.entryPoints );
-                    MLdrawControls( ui.bannedEntryPoints );
                 }
                 else
                 {
@@ -1082,6 +1124,9 @@ void SPrefsPanel::updateAudioOptions( int number)
 
 SPrefsPanel::~SPrefsPanel()
 {
+    if (!m_isApplied)
+        clean();
+
     qDeleteAll( controls ); controls.clear();
     free( lang );
 }
@@ -1096,6 +1141,8 @@ void SPrefsPanel::updateAudioVolume( int volume )
 /* Function called from the main Preferences dialog on each SPrefs Panel */
 void SPrefsPanel::apply()
 {
+    m_isApplied = true;
+
     /* Generic save for ever panel */
     QList<ConfigControl *>::const_iterator i;
     for( i = controls.begin() ; i != controls.end() ; ++i )
@@ -1141,9 +1188,8 @@ void SPrefsPanel::apply()
         else
         //if( qobject_cast<QRadioButton *>(optionWidgets[qtRB])->isChecked() )
             config_PutPsz( "intf", "" );
-        if( qobject_cast<QComboBox *>(optionWidgets["styleCB"]) )
-            getSettings()->setValue( "MainWindow/QtStyle",
-                qobject_cast<QComboBox *>(optionWidgets["styleCB"])->currentText() );
+        if( auto stylesCombo = qobject_cast<QComboBox *>(optionWidgets["styleCB"]) )
+            getSettings()->setValue( "MainWindow/QtStyle", getQStyleKey(  stylesCombo , "" ) );
 #ifdef _WIN32
     saveLang();
 #endif
@@ -1227,13 +1273,22 @@ void SPrefsPanel::apply()
         else if (!b_checked ) {
             config_PutInt( "freetype-background-opacity", 0 );
         }
+        break;
+    }
 
+    case SPrefsMediaLibrary:
+    {
+        mlFoldersEditor->commit();
+        mlBannedFoldersEditor->commit();
     }
     }
 }
 
 void SPrefsPanel::clean()
-{}
+{
+    for ( auto &resetter : m_resetters )
+        resetter->reset();
+}
 
 void SPrefsPanel::lastfm_Changed( int i_state )
 {
@@ -1243,9 +1298,10 @@ void SPrefsPanel::lastfm_Changed( int i_state )
         config_RemoveIntf( "audioscrobbler" );
 }
 
-void SPrefsPanel::changeStyle( QString s_style )
+void SPrefsPanel::changeStyle()
 {
-    QApplication::setStyle( s_style );
+    QApplication::setStyle( getQStyleKey( qobject_cast<QComboBox *>( optionWidgets["styleCB"] )
+                                          , p_intf->p_sys->p_app->defaultStyle() ) );
 
     /* force refresh on all widgets */
     QWidgetList widgets = QApplication::allWidgets();
@@ -1564,59 +1620,17 @@ void SPrefsPanel::saveAsso()
 #endif /* _WIN32 */
 
 void SPrefsPanel::MLaddNewFolder() {
-    QUrl newEntryPoints = QFileDialog::getExistingDirectoryUrl( this , qtr("Please choose an entry point folder") ,
+    QUrl newEntryPoint = QFileDialog::getExistingDirectoryUrl( this , qtr("Please choose an entry point folder") ,
                                              QUrl( QDir::homePath( ) ) );
 
-    if(! newEntryPoints.isEmpty() )
-        mlFoldersModel->add( newEntryPoints );
+    if(! newEntryPoint.isEmpty() )
+        mlFoldersEditor->add( newEntryPoint );
 }
 
 void SPrefsPanel::MLBanFolder( ) {
-    QUrl newEntryPoints = QFileDialog::getExistingDirectoryUrl( this , qtr("Please choose an entry point folder") ,
+    QUrl newEntryPoint = QFileDialog::getExistingDirectoryUrl( this , qtr("Please choose an entry point folder") ,
                                              QUrl( QDir::homePath( ) ) );
 
-    if(! newEntryPoints.isEmpty() )
-        mlBannedFoldersModel->add( newEntryPoints );
-}
-
-QWidget *SPrefsPanel::MLgenerateWidget( QModelIndex index , MLFoldersBaseModel *mlf , QWidget *parent){
-    if ( index.column( ) == 1 ){
-        QWidget *wid = new QWidget( parent );
-
-        QBoxLayout* layout = new QBoxLayout( QBoxLayout::LeftToRight , wid );
-
-        QPushButton *pb = new QPushButton( "-" , wid );
-        pb->setFixedSize( 16 , 16 );
-
-        layout->addWidget( pb , Qt::AlignCenter );
-        wid->setLayout( layout );
-
-
-        connect( pb , &QPushButton::clicked , [=]() {
-            mlf->removeAt(index.row());
-        } );
-
-        return wid;
-    }
-
-    return nullptr;
-}
-
-void SPrefsPanel::MLdrawControls(QTableView *mlTableView) {
-    const auto model = mlTableView->model();
-    for ( int col = 0 ; col < model->columnCount( model->index(0, 0) ) ; col++ )
-    {
-        for (int row = 0 ; row < model->rowCount() ; row++ )
-        {
-            QModelIndex index = model->index ( row , col );
-            mlTableView->setIndexWidget( index, MLgenerateWidget ( index, qobject_cast<MLFoldersBaseModel *>(model),
-                                       mlTableView ) );
-        }
-    }
-
-  mlTableView->resizeColumnsToContents( );
-  mlTableView->horizontalHeader()->setMinimumSectionSize( 100 );
-  mlTableView->horizontalHeader()->setSectionResizeMode( 0 , QHeaderView::Stretch );
-
-  mlTableView->horizontalHeader()->setFixedHeight( 24 );
+    if(! newEntryPoint.isEmpty() )
+        mlBannedFoldersEditor->add( newEntryPoint );
 }


=====================================
modules/gui/qt/dialogs/preferences/simple_preferences.hpp
=====================================
@@ -42,7 +42,8 @@
 #include <QDialogButtonBox>
 #include <QTableView>
 #include <QFileDialog>
-#include "medialibrary/mlfoldersmodel.hpp"
+
+class MLFoldersEditor;
 
 #ifdef _WIN32
 # include "util/registry.hpp"
@@ -99,7 +100,6 @@ public:
     SPrefsPanel( intf_thread_t *, QWidget *, int );
     virtual ~SPrefsPanel();
     void apply();
-    void clean();
 #ifdef _WIN32
     void cleanLang();
 #endif
@@ -115,8 +115,8 @@ private:
     QButtonGroup *radioGroup;
 
     char *lang;
-    MLFoldersModel *mlFoldersModel;
-    MLBannedFoldersModel *mlBannedFoldersModel;
+    MLFoldersEditor *mlFoldersEditor {};
+    MLFoldersEditor *mlBannedFoldersEditor {};
 
 #ifdef _WIN32
     QList<QTreeWidgetItem *> listAsso;
@@ -124,6 +124,10 @@ private:
     void saveLang();
 #endif
 
+    // used to revert properties on cancel which are immediately set
+    bool m_isApplied = false;
+    std::vector<std::unique_ptr<class PropertyResetter>> m_resetters;
+
 /* Display only the options for the selected audio output */
 private slots:
     void lastfm_Changed( int );
@@ -137,11 +141,11 @@ private slots:
 #endif
     void MLaddNewFolder( );
     void MLBanFolder( );
-    QWidget * MLgenerateWidget(QModelIndex index , MLFoldersBaseModel *mlf , QWidget *parent );
-    void MLdrawControls( QTableView *mlView );
 
     void configML();
-    void changeStyle( QString );
+    void changeStyle( );
+
+    void clean();
 };
 
 #endif


=====================================
modules/gui/qt/dialogs/preferences/sprefs_medialibrary.ui
=====================================
@@ -94,7 +94,7 @@
        </widget>
       </item>
       <item row="4" column="0" colspan="4">
-       <widget class="QTableView" name="bannedEntryPoints">
+       <widget class="MLFoldersEditor" name="bannedEntryPoints">
         <property name="editTriggers">
          <set>QAbstractItemView::AllEditTriggers</set>
         </property>
@@ -104,16 +104,17 @@
         <property name="showGrid">
          <bool>false</bool>
         </property>
-        <attribute name="horizontalHeaderVisible">
-         <bool>true</bool>
-        </attribute>
-        <attribute name="verticalHeaderVisible">
+        <property name="rowCount">
+         <number>1</number>
+        </property>
+        <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
          <bool>false</bool>
         </attribute>
+        <row/>
        </widget>
       </item>
       <item row="1" column="0" colspan="4">
-       <widget class="QTableView" name="entryPoints">
+       <widget class="MLFoldersEditor" name="entryPoints">
         <property name="editTriggers">
          <set>QAbstractItemView::AllEditTriggers</set>
         </property>
@@ -123,12 +124,13 @@
         <property name="showGrid">
          <bool>false</bool>
         </property>
-        <attribute name="horizontalHeaderVisible">
-         <bool>true</bool>
-        </attribute>
-        <attribute name="verticalHeaderVisible">
+        <property name="rowCount">
+         <number>1</number>
+        </property>
+        <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
          <bool>false</bool>
         </attribute>
+        <row/>
        </widget>
       </item>
      </layout>
@@ -149,6 +151,13 @@
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>MLFoldersEditor</class>
+   <extends>QTableWidget</extends>
+   <header>widgets/native/mlfolderseditor.hpp</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>


=====================================
modules/gui/qt/medialibrary/mlfoldersmodel.cpp
=====================================
@@ -97,6 +97,15 @@ QHash<int, QByteArray> MLFoldersBaseModel::roleNames() const
     };
 }
 
+void MLFoldersBaseModel::removeAt(int index)
+{
+    assert(index < rowCount());
+    const QModelIndex idx = this->index( index, 0 );
+    if (idx.isValid())
+        remove( data( idx,  MRL ).toUrl() );
+
+}
+
 void MLFoldersBaseModel::update()
 {
     beginResetModel();
@@ -110,7 +119,8 @@ void MLFoldersBaseModel::onMlEvent( void* data , const vlc_ml_event_t* event )
     if ( event->i_type == VLC_ML_EVENT_ENTRY_POINT_ADDED || event->i_type == VLC_ML_EVENT_ENTRY_POINT_REMOVED ||
          event->i_type == VLC_ML_EVENT_ENTRY_POINT_UNBANNED || event->i_type == VLC_ML_EVENT_ENTRY_POINT_BANNED  )
     {
-        emit self->onMLEntryPointModified( QPrivateSignal() );
+        if (!self->failed( event ))
+            emit self->onMLEntryPointModified( QPrivateSignal() );
     }
 }
 
@@ -129,12 +139,25 @@ std::vector<MLFoldersBaseModel::EntryPoint> MLFoldersModel::entryPoints() const
     return r;
 }
 
-void MLFoldersModel::removeAt( int index )
+bool MLFoldersModel::failed(const vlc_ml_event_t *event) const
 {
-    assert(index < rowCount());
-    const QModelIndex idx = this->index( index, 0 );
-    if (idx.isValid())
-        vlc_ml_remove_folder( ml() , qtu( data( idx, MLFoldersBaseModel::MRL ).value<QString>() ) );
+    if ( event->i_type == VLC_ML_EVENT_ENTRY_POINT_ADDED && !event->entry_point_added.b_success )
+    {
+        emit operationFailed( Add, QUrl::fromEncoded( event->entry_point_added.psz_entry_point ) );
+        return true;
+    }
+    else if ( event->i_type == VLC_ML_EVENT_ENTRY_POINT_REMOVED && !event->entry_point_removed.b_success )
+    {
+        emit operationFailed( Remove, QUrl::fromEncoded( event->entry_point_removed.psz_entry_point ) );
+        return true;
+    }
+
+    return false;
+}
+
+void MLFoldersModel::remove( const QUrl &mrl )
+{
+    vlc_ml_remove_folder( ml() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
 }
 
 void MLFoldersModel::add(const QUrl &mrl )
@@ -142,14 +165,9 @@ void MLFoldersModel::add(const QUrl &mrl )
     vlc_ml_add_folder( ml() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
 }
 
-void MLBannedFoldersModel::removeAt(int index)
+void MLBannedFoldersModel::remove(const QUrl &mrl)
 {
-    assert(index < rowCount());
-    const QModelIndex idx = this->index( index, 0 );
-    if (idx.isValid())
-    {
-        vlc_ml_unban_folder( ml() , qtu( data( idx, MLFoldersBaseModel::MRL ).value<QString>() ) );
-    }
+    vlc_ml_unban_folder( ml() , qtu( mrl.toString( QUrl::FullyEncoded ) ) );
 }
 
 void MLBannedFoldersModel::add(const QUrl &mrl)
@@ -171,3 +189,19 @@ std::vector<MLFoldersBaseModel::EntryPoint> MLBannedFoldersModel::entryPoints()
 
     return r;
 }
+
+bool MLBannedFoldersModel::failed(const vlc_ml_event_t *event) const
+{
+    if ( event->i_type == VLC_ML_EVENT_ENTRY_POINT_BANNED && !event->entry_point_banned.b_success )
+    {
+        emit operationFailed( Ban, QUrl::fromEncoded( event->entry_point_banned.psz_entry_point ) );
+        return true;
+    }
+    else if ( event->i_type == VLC_ML_EVENT_ENTRY_POINT_UNBANNED && !event->entry_point_unbanned.b_success )
+    {
+        emit operationFailed( Unban, QUrl::fromEncoded( event->entry_point_unbanned.psz_entry_point ) );
+        return true;
+    }
+
+    return false;
+}


=====================================
modules/gui/qt/medialibrary/mlfoldersmodel.hpp
=====================================
@@ -47,6 +47,14 @@ public:
         MRL
     };
 
+    enum Operation
+    {
+        Add,
+        Remove,
+        Ban,
+        Unban
+    };
+
     MLFoldersBaseModel( QObject *parent = nullptr );
 
     void setCtx(QmlMainContext* ctx);
@@ -59,11 +67,13 @@ public:
     QHash<int, QByteArray> roleNames() const override;
 
 public slots:
-    virtual void removeAt( int index ) = 0;
+    virtual void remove( const QUrl &mrl ) = 0;
     virtual void add( const QUrl &mrl ) = 0;
+    void removeAt( int index );
 
 signals:
     void ctxChanged();
+    void operationFailed( int op, QUrl url ) const;
     void onMLEntryPointModified(QPrivateSignal);
 
 protected:
@@ -75,6 +85,7 @@ protected:
     };
 
     virtual std::vector<EntryPoint> entryPoints() const = 0;
+    virtual bool failed( const vlc_ml_event_t* event ) const = 0; // will be called outside the main thread
 
 private:
     static void onMlEvent( void* data , const vlc_ml_event_t* event );
@@ -93,11 +104,12 @@ class MLFoldersModel : public MLFoldersBaseModel
 public:
     using MLFoldersBaseModel::MLFoldersBaseModel;
 
-    void removeAt( int index ) override;
+    void remove( const QUrl &mrl ) override;
     void add( const QUrl &mrl ) override;
 
 private:
     std::vector<EntryPoint> entryPoints() const final;
+    bool failed( const vlc_ml_event_t* event ) const override;
 };
 
 class MLBannedFoldersModel : public MLFoldersBaseModel
@@ -105,11 +117,12 @@ class MLBannedFoldersModel : public MLFoldersBaseModel
 public:
     using MLFoldersBaseModel::MLFoldersBaseModel;
 
-    void removeAt( int index ) override;
+    void remove( const QUrl &mrl ) override;
     void add( const QUrl &mrl ) override;
 
 private:
     std::vector<EntryPoint> entryPoints() const final;
+    bool failed( const vlc_ml_event_t* event ) const override;
 };
 
 #endif // ML_FOLDERS_MODEL_HPP


=====================================
modules/gui/qt/util/qvlcapp.hpp
=====================================
@@ -26,6 +26,7 @@
 
 #include <QApplication>
 #include <QEvent>
+#include <QStyle>
 
 #if defined(Q_OS_WIN)
 #   include "qt.hpp"
@@ -45,7 +46,7 @@ private slots:
     }
 
 public:
-    QVLCApp( int & argc, char ** argv ) : QApplication( argc, argv, true )
+    QVLCApp( int & argc, char ** argv ) : QApplication( argc, argv, true ), m_defaultStyle( style()->objectName() )
     {
         connect( this, SIGNAL(quitSignal()), this, SLOT(doQuit()) );
     }
@@ -57,8 +58,16 @@ public:
             emit app->quitSignal();
     }
 
+    QString defaultStyle() const
+    {
+        return m_defaultStyle;
+    }
+
 signals:
     void quitSignal();
 
+private:
+    const QString m_defaultStyle;
 };
+
 #endif


=====================================
modules/gui/qt/widgets/native/mlfolderseditor.cpp
=====================================
@@ -0,0 +1,155 @@
+/*****************************************************************************
+ * roundimage.cpp: Custom widgets
+ ****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * 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.
+ *****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mlfolderseditor.hpp"
+
+#include <QBoxLayout>
+#include <QHeaderView>
+#include <QMessageBox>
+#include <QPushButton>
+
+MLFoldersEditor::MLFoldersEditor(QWidget *parent)
+    : QTableWidget(0, 2, parent)
+{
+    setHorizontalHeaderLabels({ qtr("Path"), qtr("Remove") });
+    horizontalHeader()->setMinimumSectionSize( 100 );
+    horizontalHeader()->setSectionResizeMode( 0 , QHeaderView::Stretch );
+    horizontalHeader()->setFixedHeight( 24 );
+}
+
+void MLFoldersEditor::setMLFoldersModel(MLFoldersBaseModel *foldersModel)
+{
+    if (m_foldersModel)
+        disconnect(m_foldersModel, nullptr, this, nullptr);
+
+    m_foldersModel = foldersModel;
+    m_newEntries.clear();
+    m_removeEntries.clear();
+
+    resetFolders();
+
+    connect(m_foldersModel, &QAbstractItemModel::modelReset, this, &MLFoldersEditor::resetFolders);
+    connect(m_foldersModel, &QAbstractItemModel::rowsInserted, this, &MLFoldersEditor::resetFolders);
+    connect(m_foldersModel, &QAbstractItemModel::rowsRemoved, this, &MLFoldersEditor::resetFolders);
+    connect(m_foldersModel, &QAbstractItemModel::rowsMoved, this, &MLFoldersEditor::resetFolders);
+    connect(m_foldersModel, &MLFoldersBaseModel::operationFailed, this, &MLFoldersEditor::handleOpFailure );
+}
+
+void MLFoldersEditor::add(const QUrl &mrl)
+{
+    m_newEntries.push_back(mrl);
+    newRow(mrl);
+}
+
+void MLFoldersEditor::commit()
+{
+    for ( const auto &removeEntry : m_removeEntries )
+        m_foldersModel->remove( removeEntry );
+
+    for ( const auto &newEntry : m_newEntries )
+        m_foldersModel->add( newEntry );
+
+    m_removeEntries.clear();
+    m_newEntries.clear();
+}
+
+void MLFoldersEditor::handleOpFailure(int operation, const QUrl &url)
+{
+    const QString entryPoint = url.toDisplayString( QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::NormalizePathSegments );
+
+    QString msg;
+    switch (operation)
+    {
+    case MLFoldersBaseModel::Add:
+        msg = qtr("Failed to add \"%1\"").arg( entryPoint );
+        break;
+    case MLFoldersBaseModel::Remove:
+        msg = qtr("Failed to remove \"%1\"").arg( entryPoint );
+        break;
+    case MLFoldersBaseModel::Ban:
+        msg = qtr("Failed to ban \"%1\"").arg( entryPoint );
+        break;
+    case MLFoldersBaseModel::Unban:
+        msg = qtr("Failed to unban \"%1\"").arg( entryPoint );
+        break;
+    }
+
+    QMessageBox::warning( this, qtr( "Medialibrary error" ), msg );
+}
+
+void MLFoldersEditor::resetFolders()
+{
+    setRowCount(0);
+
+    for ( int i = 0; i < m_foldersModel->rowCount(); ++i )
+    {
+        const auto url = m_foldersModel->data(m_foldersModel->index(i), MLFoldersBaseModel::MRL).toUrl();
+        if (!m_removeEntries.contains(url))
+            newRow(url);
+    }
+
+    for ( const auto &newEntry : m_newEntries )
+        newRow(newEntry);
+
+}
+
+void MLFoldersEditor::newRow(const QUrl &mrl)
+{
+    const int row = rowCount();
+    setRowCount(row + 1);
+
+    const QString text = mrl.toDisplayString( QUrl::RemovePassword | QUrl::PreferLocalFile | QUrl::NormalizePathSegments );
+    auto col1 = new QTableWidgetItem( text );
+    col1->setData(Qt::UserRole, mrl);
+    col1->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
+    setItem( row, 0, col1 );
+
+    QWidget *wid = new QWidget( this );
+    QBoxLayout* layout = new QBoxLayout( QBoxLayout::LeftToRight , wid );
+    QPushButton *pb = new QPushButton( "-" , wid );
+    pb->setFixedSize( 16 , 16 );
+
+    layout->addWidget( pb , Qt::AlignCenter );
+    wid->setLayout( layout );
+
+    connect( pb , &QPushButton::clicked , this, [this, col1]()
+    {
+        int row = col1->row();
+        vlc_assert( row >= 0 );
+
+        const QUrl mrl = col1->data( Qt::UserRole ).toUrl();
+        const auto index = m_newEntries.indexOf( mrl );
+        if ( index == -1 )
+            m_removeEntries.push_back( mrl );
+        else
+            m_newEntries.remove( index );
+
+        removeRow( row );
+    });
+
+    setCellWidget( row, 1, wid );
+}


=====================================
modules/gui/qt/widgets/native/mlfolderseditor.hpp
=====================================
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * roundimage.hpp: Custom widgets
+ ****************************************************************************
+ * Copyright (C) 2021 the VideoLAN team
+ *
+ * Authors: Prince Gupta <guptaprince8832 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_QT_MLFOLDERSEDITOR_HPP
+#define VLC_QT_MLFOLDERSEDITOR_HPP
+
+#include "qt.hpp"
+
+#include <QTableWidget>
+
+#include <memory>
+
+#include <medialibrary/mlfoldersmodel.hpp>
+
+class MLFoldersEditor : public QTableWidget
+{
+    Q_OBJECT
+
+public:
+    MLFoldersEditor( QWidget *parent = nullptr );
+
+    void setMLFoldersModel( MLFoldersBaseModel *foldersModel );
+    void add( const QUrl &mrl );
+
+    // call 'commit' to apply changes
+    void commit();
+
+private slots:
+    void handleOpFailure( int operation, const QUrl &url );
+    void resetFolders();
+
+private:
+    void newRow(const QUrl &mrl);
+    void removeMrlEntry(const QUrl &mrl);
+
+    MLFoldersBaseModel *m_foldersModel = nullptr;
+
+    // new entries to add/remove on 'commit' call
+    QVector<QUrl> m_newEntries;
+    QVector<QUrl> m_removeEntries;
+};
+
+#endif
+



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d2e8632531db524a4d0d6ab69cb9ed86a54ded05...995b74f494e2e4a690d927ade2c2ec7aa39837de

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d2e8632531db524a4d0d6ab69cb9ed86a54ded05...995b74f494e2e4a690d927ade2c2ec7aa39837de
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list