[vlc-commits] [Git][videolan/vlc][master] 18 commits: config: add general subcat data to cat data table

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Fri Jan 7 09:34:57 UTC 2022



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


Commits:
d3b61926 by Lyndon Brown at 2022-01-07T08:44:46+00:00
config: add general subcat data to cat data table

every category must have one general subcat, which is now made
more clear / enforced, by being captured in the category data
table.

the new helper that looks up the general subcat for a given
cat will be put to use by some later commits. for now it is
used only to reimplement the is-general helper to rely upon
the data table.

- - - - -
eeeff5ff by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: fix confusing cat/subcat ID storage

instead of the pointlessly confusing design of sometimes storing subcat IDs
in the 'subcat_id' attribute and sometimes the 'object_id' attribute, where
cat IDs are always otherwise stored, let's simplify things by renaming the
'object_id' property to 'cat_id', and consistently use 'cat_id' for
category IDs and 'subcat_id' for subcat IDs.

- - - - -
0387d06f by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: tweak sub-optimal plugin option-set loop

- - - - -
5a4af7f6 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: remove duplicate write

`data` is the pointer to an object belonging to the current category node..

when handling a 'general' subcat, which gets "merged" into the category
node, all we need to do is modify the `data` object's attributes. we do not
need to save the pointer to this object in the tree node object, which was
already done earlier.

- - - - -
cb00f275 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: refactor adv prefs tree construction

non-functional change, just reorganising the code, splitting out the node
creation and locating routines into helper methods.

this forms the basis for cleanly implementing further improvements.

- - - - -
84a95852 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: create tree nodes where missing for plugin nodes

the advanced preferences tree construction code is designed to build up
the base cat/subcat tree from the core option set only, then attach
nodes for plugin sets to that tree.

the author(s) of that code made the mistake of assuming that the core
would always make use of all subcats, and thus that there would never be
a problem when it came to attaching plugin nodes. this assumption has
proved wrong, requiring redundant subcategory entries to be added to the
core option set as a temporary fix for placement issues
(1ca5bfaa1901551618ccac5fa97ac40babde7ab3).

5c18cff8d8cdba5784ca4bdb641fb483499117ed is a good example of the
fragility of this design. it removed the video-splitter entry from the
core set, which thus had the unintended and unnoticed consequence of
plugins targetting this category suddenly being incorrectly attached
to the parent cat node rather than appearing under the video-splitter
subcat child node as before.

having to keep 'unused' subcategories within the core option set just
to support proper plugin node placement, besides being fragile, also
has the disadvantage that if no plugins attach to it, we just end up
with useless empty nodes in the tree. it is certainly not a good long
term solution.

this patch addresses the problems just described by implementing the
ability for the plugin node handling portion of the tree contruction
code to add missing tree nodes if and when it needs to.

(this now makes 1ca5bfaa1901551618ccac5fa97ac40babde7ab3 redundant).

- - - - -
0921395a by Lyndon Brown at 2022-01-07T08:44:46+00:00
core: remove/disable unused config subcats

this reverts 1ca5bfaa1901551618ccac5fa97ac40babde7ab3 with that now being
redundant after the previous commit, which implemented a proper solution
for the problem of placement issues for plugin nodes within the Qt advanced
preferences tree, where a plugin targets a subcategory not used within the
core option set.

(the macos interface did not suffer from this flaw).

with respect to 1ca5bfaa1901551618ccac5fa97ac40babde7ab3 this removes the
temporarily added `SUBCAT_VIDEO_SPLITTER` and `SUBCAT_ADVANCED_NETWORK`
entries, while bc9567ccf13d107508cf2f5b67e44e3d70cfdd7f already removed
`SUBCAT_AUDIO_MISC`.

additionally this removed the now unused `SUBCAT_SOUT_VOD` entry, since we
now have no plugins using it, nor options for it, which meant that it has
been resulting in a pointless empty node.

furthermore the unused  `SUBCAT_INPUT_ACODEC` and `SUBCAT_INPUT_SCODEC`
entries have been disabled such that we do not get pointless empty nodes
should it ever be the case that no plugins are loaded that need them.

- - - - -
509d1dc5 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: improve efficiency of finding adv prefs tree nodes

fixed arrays of pointers for tracking the handful of cat and subcat node
items (but not plugin nodes), gives a much more efficient alternative to
the current solution of searching the tree, each time we need to attach
a new plugin node to the tree when building it.

this also proves to have a secondary benefit per the next commit.

- - - - -
75bc26fb by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: robustify adv prefs base tree construction

using the new mapping arrays, we can more robustly create the base tree
cat/subcat nodes used in the core option set, now working correctly should,
deliberately or otherwise, the order of subcat use ever become mixed rather
than all for each cat being used in a continuous block.

- - - - -
23627043 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: simplify handling of general subcats

every cat has a general subcat, as defined in `vlc_config_cat.h`; let's
simplify things by merging the code that applies the general subcat
properties on top of the already established cat properties, rather
than doing this in a seperate step after creation of the category node.

note that the initial category item was given a `PrefsItemData` type of
`TYPE_CATEGORY`. once the general subcat properties were merged, it was
given the type `TYPE_CATSUBCAT`. this change now effectively wipes out
the need for this distinction. this will be tackled in a follow up
commit.

you may also notice that this makes more clear the fact that category
help text, as captured in the `vlc_config_cat.h` data table
`categories_array` goes entirely unused, being overridden by that of
the general subcat help text. removing this unused help text was a
point of contention when i previously tried to bring it up, so for now
it remains. (it is also unused in the macos gui).

- - - - -
57d349ee by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: merge `TYPE_CATEGORY` with `TYPE_CATSUBCAT`

per the previous commit, we have no need for the distinction now.

- - - - -
4abe052b by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: rename `prefsType::TYPE_MODULE` to `TYPE_PLUGIN`

plugins own option sets, not individual modules, and nodes in the prefs
tree represent plugins.

yes, we still loop over modules to get the sets and get properties from the
first module in a plugin for labels, but that confusing disparity can be
tackled later.

- - - - -
81a9d2c0 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: purge obsolete cleanup code

redundant since a622a74a1fe9cd481474960ff8435335d56a4067.

- - - - -
27a46c37 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: rework adv prefs tree to use derived `QTreeWidgetItem`

rather than allocating a custom object to hold data for each tree node,
linked to the tree via `QObject` for ownership and destruction purposes,
and the pointer held in a 'data' property of the node, let's simplify this
significantly with a custom `QTreeWidgetItem`.

`PrefsTreeData` has been renamed `PrefsTreeItem` and converted as such.

- - - - -
ed67f132 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: avoid pointless module-loaded assessments

for cat & subcat nodes. this should only be assessed for plugin nodes..

- - - - -
dcebb25b by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: cache and reuse pointer to main module in prefs tree creation

each creation of a panel for a non-plugin (cat or subcat) node resulted in
a call to `module_get_main()` to obtain the pointer to the main module to
thus be in a position to get to the main config set.

by doing this once when creating the `PrefsTree` instance and caching it,
we can copy it into the existing module pointer property of cat and subcat
nodes (which was only used previously for plugin type nodes) when they are
created, and thus we will already have the necessary pointer available when
creating the panels, saving dozens of calls.

- - - - -
f1131bdc by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: reorganise adv prefs panel creation

(non-functional)

 - removed pointless init of `p_config` (changed two lines later).
 - merged two condition blocks working on the same condition (core
   cat/subcat node panel vs. plugin node panel logic).
 - renamed `head` to `heading` for clarity in doing so.
 - explained the commented-on `p_item++` in doing so.
 - dropped unnecessary `help` intermediary.

- - - - -
56c4b6f1 by Lyndon Brown at 2022-01-07T08:44:46+00:00
qt: fix confusing mess of loop logic

- - - - -


5 changed files:

- include/vlc_config_cat.h
- modules/gui/qt/dialogs/preferences/complete_preferences.cpp
- modules/gui/qt/dialogs/preferences/complete_preferences.hpp
- modules/gui/qt/dialogs/preferences/preferences.cpp
- src/libvlc-module.c


Changes:

=====================================
include/vlc_config_cat.h
=====================================
@@ -195,6 +195,7 @@
 struct config_category_t
 {
     int         id;
+    int         general_subcat;
     const char *name;
     const char *help;
 };
@@ -209,13 +210,13 @@ struct config_subcategory_t
 
 static const struct config_category_t categories_array[] =
 {
-    { CAT_INTERFACE,  INTF_TITLE,       INTF_HELP      },
-    { CAT_AUDIO,      AUDIO_TITLE,      AUDIO_HELP     },
-    { CAT_VIDEO,      VIDEO_TITLE,      VIDEO_HELP     },
-    { CAT_INPUT,      INPUT_TITLE,      INPUT_HELP     },
-    { CAT_SOUT,       SOUT_TITLE,       SOUT_HELP      },
-    { CAT_PLAYLIST,   PLAYLIST_TITLE,   PLAYLIST_HELP  },
-    { CAT_ADVANCED,   AADVANCED_TITLE,  AADVANCED_HELP },
+    { CAT_INTERFACE,  SUBCAT_INTERFACE_GENERAL,  INTF_TITLE,       INTF_HELP      },
+    { CAT_AUDIO,      SUBCAT_AUDIO_GENERAL,      AUDIO_TITLE,      AUDIO_HELP     },
+    { CAT_VIDEO,      SUBCAT_VIDEO_GENERAL,      VIDEO_TITLE,      VIDEO_HELP     },
+    { CAT_INPUT,      SUBCAT_INPUT_GENERAL,      INPUT_TITLE,      INPUT_HELP     },
+    { CAT_SOUT,       SUBCAT_SOUT_GENERAL,       SOUT_TITLE,       SOUT_HELP      },
+    { CAT_PLAYLIST,   SUBCAT_PLAYLIST_GENERAL,   PLAYLIST_TITLE,   PLAYLIST_HELP  },
+    { CAT_ADVANCED,   SUBCAT_ADVANCED_MISC,      AADVANCED_TITLE,  AADVANCED_HELP },
 };
 
 static const struct config_subcategory_t subcategories_array[] =
@@ -295,6 +296,28 @@ static inline int vlc_config_subcat_IndexOf( int subcat )
     return index;
 }
 
+/** Get the "general" subcategory for a given category.
+ *
+ * In a cat/subcat preference tree, subcategories typically appear as child
+ * nodes under their respective parent category node. Core config items, which
+ * are always associated with a particular subcategory, are shown when that
+ * subcategory node is selected. Each category however has a "general"
+ * subcategory which is not shown as a child node, instead the options for
+ * this are shown when the category node itself is selected in the tree.
+ *
+ * One or more nodes are also created in the tree per plugin, with the
+ * location relating to the subcategory association of its config items. Plugin
+ * nodes associated with general subcategories naturally appear as child nodes
+ * of the category node (as a sibling to its subcategory nodes), rather than as
+ * a child node of a subcategory node.
+ */
+VLC_USED
+static inline int vlc_config_cat_GetGeneralSubcat( int cat )
+{
+    int i = vlc_config_cat_IndexOf( cat );
+    return (i != -1) ? categories_array[i].general_subcat : SUBCAT_UNKNOWN;
+}
+
 /** Get the name for a category. */
 VLC_USED
 static inline const char *vlc_config_cat_GetName( int cat )
@@ -335,37 +358,14 @@ static inline int vlc_config_cat_FromSubcat( int subcat )
     return (i != -1) ? subcategories_array[i].cat : CAT_UNKNOWN;
 }
 
-/** Check if the given subcategory is a "general" one.
- *
- * In a cat/subcat preference tree, subcategories typically appear as child
- * nodes under their respective parent category node. Core config items, which
- * are always associated with a particular subcategory, are shown when that
- * subcategory node is selected. Each category however has a "general"
- * subcategory which is not shown as a child node, instead the options for
- * this are shown when the category node itself is selected in the tree.
- *
- * One or more nodes are also created in the tree per plugin, with the
- * location relating to the subcategory association of its config items. Plugin
- * nodes associated with general subcategories naturally appear as child nodes
- * of the category node (as a sibling to its subcategory nodes), rather than as
- * a child node of a subcategory node.
- */
+/** Check if the given subcategory is a "general" one. */
 VLC_USED
 static inline bool vlc_config_subcat_IsGeneral( int subcat )
 {
-    switch (subcat)
-    {
-        case SUBCAT_INTERFACE_GENERAL:
-        case SUBCAT_AUDIO_GENERAL:
-        case SUBCAT_VIDEO_GENERAL:
-        case SUBCAT_INPUT_GENERAL:
-        case SUBCAT_SOUT_GENERAL:
-        case SUBCAT_ADVANCED_MISC:
-        case SUBCAT_PLAYLIST_GENERAL:
-            return true;
-        default:
-            return false;
-    }
+    if( subcat == SUBCAT_UNKNOWN )
+        return false;
+    int cat = vlc_config_cat_FromSubcat( subcat );
+    return (subcat == vlc_config_cat_GetGeneralSubcat( cat ));
 }
 
 #endif /* VLC_CONFIG_CAT_H */


=====================================
modules/gui/qt/dialogs/preferences/complete_preferences.cpp
=====================================
@@ -26,7 +26,6 @@
 #include <QApplication>
 #include <QLabel>
 #include <QTreeWidget>
-#include <QTreeWidgetItem>
 #include <QVariant>
 #include <QString>
 #include <QFont>
@@ -38,7 +37,6 @@
 #include "dialogs/preferences/complete_preferences.hpp"
 #include "dialogs/preferences/preferences_widgets.hpp"
 
-#include <vlc_config_cat.h>
 #include <vlc_intf_strings.h>
 #include <vlc_modules.h>
 #include <vlc_plugin.h>
@@ -64,205 +62,100 @@ PrefsTree::PrefsTree( qt_intf_t *_p_intf, QWidget *_parent,
     setUniformRowHeights( true );
     CONNECT( this, itemExpanded(QTreeWidgetItem*), this, resizeColumns() );
 
-    /* Nice icons */
-#define BI( a,b) QIcon a##_icon = QIcon( b )
-    BI( audio, ":/prefsmenu/advanced/audio.svg" );
-    BI( video, ":/prefsmenu/advanced/video.svg" );
-    BI( input, ":/prefsmenu/advanced/codec.svg" );
-    BI( sout, ":/prefsmenu/advanced/sout.svg" );
-    BI( advanced, ":/prefsmenu/advanced/extended.svg" );
-    BI( playlist, ":/prefsmenu/advanced/playlist.svg" );
-    BI( interface, ":/prefsmenu/advanced/intf.svg" );
-#undef BI
-
-    /* Build the tree for the main module */
-    module_t *p_module = module_get_main();
+    main_module = module_get_main();
+    assert( main_module );
+
+    int cat = CAT_UNKNOWN;
+    int subcat = SUBCAT_UNKNOWN;
+    QTreeWidgetItem *cat_item = nullptr;
 
-    /* Initialisation and get the confsize */
-    int last_cat = CAT_UNKNOWN;
-    PrefsItemData *data = NULL;
-    PrefsItemData *data_sub = NULL;
-    QTreeWidgetItem *current_item = NULL;
+    /* Create base cat/subcat tree from core config set */
     unsigned confsize;
+    module_t *p_module = module_get_main();
     module_config_t *const p_config = module_config_get (p_module, &confsize);
-
-    /* Go through the list of core conf to build the base tree */
     for( size_t i = 0; i < confsize; i++ )
     {
-        QIcon icon;
-
         module_config_t *p_item = p_config + i;
 
         if( p_item->i_type != CONFIG_SUBCATEGORY )
             continue;
 
-        int subcat = p_item->value.i;
-        int cat = vlc_config_cat_FromSubcat(subcat);
+        subcat = p_item->value.i;
+        cat = vlc_config_cat_FromSubcat(subcat);
 
         if( cat == CAT_UNKNOWN || cat == CAT_HIDDEN )
             continue;
 
         /* Create parent cat node? */
-        if( cat != last_cat )
-        {
-            last_cat = cat;
-
-            /* PrefsItemData Init */
-            data = new PrefsItemData( this );
-            data->name = qfu( vlc_config_cat_GetName( cat ) );
-            data->help = qfu( vlc_config_cat_GetHelp( cat ) );
-            data->i_type = PrefsItemData::TYPE_CATEGORY;
-            data->i_object_id = cat;
-
-            /* This is a category, put a nice icon */
-            switch( cat )
-            {
-#define CI(a,b) case a: icon = b##_icon;break
-            CI( CAT_AUDIO, audio );
-            CI( CAT_VIDEO, video );
-            CI( CAT_INPUT, input );
-            CI( CAT_SOUT, sout );
-            CI( CAT_ADVANCED, advanced );
-            CI( CAT_PLAYLIST, playlist );
-            CI( CAT_INTERFACE, interface );
-            }
-#undef CI
-
-            /* Create a new QTreeItem to display it in the tree at top level */
-            current_item = new QTreeWidgetItem();
-            current_item->setText( 0, data->name );
-            current_item->setIcon( 0 , icon );
-            //current_item->setSizeHint( 0, QSize( -1, ITEM_HEIGHT ) );
-            current_item->setData( 0, Qt::UserRole,
-                                   QVariant::fromValue( data ) );
-            addTopLevelItem( current_item );
-            expandItem( current_item );
-        }
-
-        /* Special cases: move the general subcat to the parent cat */
-        if( data && vlc_config_subcat_IsGeneral(subcat) )
-        {
-            /* Data still contains the correct thing */
-            data->i_type = PrefsItemData::TYPE_CATSUBCAT;
-            data->i_subcat_id = subcat;
-            data->name = qfu( vlc_config_subcat_GetName( subcat ) );
-            data->help = qfu( vlc_config_subcat_GetHelp( subcat ) );
-            current_item->setData( 0, Qt::UserRole,
-                                   QVariant::fromValue( data ) );
-            continue;
-        }
-
-        /* Normal Subcategories */
-
-        /* Process the Data */
-        data_sub = new PrefsItemData( this );
-        data_sub->name = qfu( vlc_config_subcat_GetName( subcat ) );
-        data_sub->help = qfu( vlc_config_subcat_GetHelp( subcat ) );
-        data_sub->i_type = PrefsItemData::TYPE_SUBCATEGORY;
-        data_sub->i_object_id = subcat;
-
-        /* Create a new TreeWidget */
-        QTreeWidgetItem *subcat_item = new QTreeWidgetItem();
-        subcat_item->setText( 0, data_sub->name );
-        subcat_item->setData( 0, Qt::UserRole,
-                              QVariant::fromValue( data_sub ) );
-        //subcat_item->setSizeHint( 0, QSize( -1, ITEM_HEIGHT ) );
-
-        /* Add it to the parent */
-        assert( current_item );
-        current_item->addChild( subcat_item );
+        if( findCatItem(cat) == nullptr )
+            cat_item = createCatNode( cat );
+
+        // Create subcat node
+        // Note that this is done conditionally, primarily because we must take
+        // no action here for 'general' subcats (which are merged into the
+        // parent category node), but also just out of caution should a mistake
+        // result in more than one instance of a subcat to be present within the
+        // core option set.
+        if( findSubcatItem( subcat ) == nullptr )
+            createSubcatNode( cat_item, subcat );
     }
     module_config_free( p_config );
 
-    /* Build the tree of plugins */
+    /* Add nodes for plugins */
+    /* A plugin gets one node for its entire set, located based on the first used subcat */
     for( size_t i = 0; i < count; i++ )
     {
         p_module = p_list[i];
-        // Main module excluded
-        if( module_is_main( p_module) ) continue;
 
-        unsigned  confsize;
-        int i_subcategory = SUBCAT_UNKNOWN, i_category = CAT_UNKNOWN;
+        /* Main module is already covered above */
+        if( module_is_main( p_module) )
+            continue;
 
-        bool b_options = false;
+        unsigned confsize;
         module_config_t *const p_config = module_config_get (p_module, &confsize);
 
-        /* Loop through the configurations items */
+        /* Get the first (used) subcat */
+        cat = CAT_UNKNOWN;
+        subcat = SUBCAT_UNKNOWN;
+        bool has_options = false;
         for (size_t i = 0; i < confsize; i++)
         {
             const module_config_t *p_item = p_config + i;
 
             if( p_item->i_type == CONFIG_SUBCATEGORY )
             {
-                i_subcategory = p_item->value.i;
-                i_category = vlc_config_cat_FromSubcat( i_subcategory );
+                subcat = p_item->value.i;
+                cat = vlc_config_cat_FromSubcat( subcat );
+                continue;
             }
 
             if( CONFIG_ITEM(p_item->i_type) )
-                b_options = true;
-
-            if( b_options && i_category != CAT_UNKNOWN )
-                break;
+            {
+                has_options = true;
+                /* If cat lookup worked, we can stop now, else keep looking */
+                if( cat != CAT_UNKNOWN )
+                    break;
+            }
         }
         module_config_free (p_config);
 
-        /* Dummy item, please proceed */
-        if( !b_options || i_category == CAT_UNKNOWN )
+        /* No options, or definitely no place to place it in the tree - ignore */
+        if( !has_options || cat == CAT_UNKNOWN || cat == CAT_HIDDEN )
             continue;
 
-        // Locate the category item;
-        QTreeWidgetItem *subcat_item = NULL;
-        bool b_found = false;
+        /* Locate the category item */
+        /* If not found (very unlikely), we will create it */
+        cat_item = findCatItem( cat );
+        if ( !cat_item )
+            cat_item = createCatNode( cat );
 
-        for( int i_cat_index = 0 ; i_cat_index < topLevelItemCount();
-                                   i_cat_index++ )
-        {
-            /* Get the treeWidgetItem that correspond to the category */
-            QTreeWidgetItem *cat_item = topLevelItem( i_cat_index );
-            PrefsItemData *data = cat_item->data( 0, Qt::UserRole ).
-                                             value<PrefsItemData *>();
+        /* Locate the subcategory item */
+        /* If not found (was not used in the core option set - quite possible), we will create it */
+        QTreeWidgetItem *subcat_item = findSubcatItem( subcat );
+        if( !subcat_item )
+            subcat_item = createSubcatNode( cat_item, subcat );
 
-            /* If we match the good category */
-            if( data->i_object_id == i_category )
-            {
-                for( int i_sc_index = 0; i_sc_index < cat_item->childCount();
-                         i_sc_index++ )
-                {
-                    subcat_item = cat_item->child( i_sc_index );
-                    PrefsItemData *sc_data = subcat_item->data(0, Qt::UserRole).
-                                                value<PrefsItemData *>();
-                    if( sc_data && sc_data->i_object_id == i_subcategory )
-                    {
-                        b_found = true;
-                        break;
-                    }
-                }
-                if( !b_found )
-                {
-                    subcat_item = cat_item;
-                    b_found = true;
-                }
-                break;
-            }
-        }
-        if( !b_found ) continue;
-
-        PrefsItemData *module_data = new PrefsItemData( this );
-        module_data->i_type = PrefsItemData::TYPE_MODULE;
-        module_data->psz_shortcut = strdup( module_get_object( p_module ) );
-        module_data->name = qfut( module_GetShortName( p_module ) );
-        module_data->help.clear();
-        module_data->p_module = p_module;
-        const char *psz_help = module_get_help( p_module );
-        if ( psz_help )
-            module_data->help = qfut( psz_help );
-
-        QTreeWidgetItem *module_item = new QTreeWidgetItem();
-        module_item->setText( 0, module_data->name );
-        module_item->setData( 0, Qt::UserRole,
-                              QVariant::fromValue( module_data) );
-        //module_item->setSizeHint( 0, QSize( -1, ITEM_HEIGHT ) );
-        subcat_item->addChild( module_item );
+        createPluginNode( subcat_item, p_module );
     }
 
     /* We got everything, just sort a bit */
@@ -271,71 +164,139 @@ PrefsTree::PrefsTree( qt_intf_t *_p_intf, QWidget *_parent,
     resizeColumnToContents( 0 );
 }
 
-void PrefsTree::applyAll()
+QTreeWidgetItem *PrefsTree::createCatNode( int cat )
 {
-    doAll( false );
+    int general_subcat = vlc_config_cat_GetGeneralSubcat( cat );
+    assert(general_subcat != SUBCAT_UNKNOWN && general_subcat != SUBCAT_HIDDEN);
+
+    PrefsTreeItem *item = new PrefsTreeItem( PrefsTreeItem::CATEGORY_NODE );
+
+    item->cat_id = cat;
+    item->subcat_id = general_subcat;
+    item->p_module = this->main_module;
+    item->name = qfu( vlc_config_subcat_GetName( general_subcat ) );
+    item->help = qfu( vlc_config_subcat_GetHelp( general_subcat ) );
+
+    QIcon icon;
+    switch( cat )
+    {
+#define CI(a,b) case a: icon = QIcon( b );break
+        CI( CAT_AUDIO,     ":/prefsmenu/advanced/audio.svg"    );
+        CI( CAT_VIDEO,     ":/prefsmenu/advanced/video.svg"    );
+        CI( CAT_INPUT,     ":/prefsmenu/advanced/codec.svg"    );
+        CI( CAT_SOUT,      ":/prefsmenu/advanced/sout.svg"     );
+        CI( CAT_ADVANCED,  ":/prefsmenu/advanced/extended.svg" );
+        CI( CAT_PLAYLIST,  ":/prefsmenu/advanced/playlist.svg" );
+        CI( CAT_INTERFACE, ":/prefsmenu/advanced/intf.svg"     );
+#undef CI
+        default: break;
+    }
+
+    item->setText( 0, qfu( vlc_config_cat_GetName( cat ) ) );
+    item->setIcon( 0, icon );
+    //current_item->setSizeHint( 0, QSize( -1, ITEM_HEIGHT ) );
+
+    int cat_index = vlc_config_cat_IndexOf( cat );
+    int general_subcat_index = vlc_config_subcat_IndexOf( general_subcat );
+    this->catMap[cat_index] = item;
+    this->subcatMap[general_subcat_index] = item;
+
+    addTopLevelItem( item );
+    expandItem( item );
+
+    return item;
 }
 
-void PrefsTree::cleanAll()
+QTreeWidgetItem *PrefsTree::createSubcatNode( QTreeWidgetItem * cat, int subcat )
 {
-    doAll( true );
+    assert( cat );
+
+    PrefsTreeItem *item = new PrefsTreeItem( PrefsTreeItem::SUBCATEGORY_NODE );
+
+    item->cat_id = CAT_UNKNOWN;
+    item->subcat_id = subcat;
+    item->p_module = this->main_module;
+    item->name = qfu( vlc_config_subcat_GetName( subcat ) );
+    item->help = qfu( vlc_config_subcat_GetHelp( subcat ) );
+
+    item->setText( 0, item->name );
+    //item->setSizeHint( 0, QSize( -1, ITEM_HEIGHT ) );
+
+    int subcat_index = vlc_config_subcat_IndexOf( subcat );
+    this->subcatMap[subcat_index] = item;
+
+    cat->addChild( item );
+
+    return item;
 }
 
-void PrefsTree::doAll( bool doclean )
+void PrefsTree::createPluginNode( QTreeWidgetItem * parent, module_t *mod )
+{
+    assert( parent );
+
+    PrefsTreeItem *item = new PrefsTreeItem( PrefsTreeItem::PLUGIN_NODE );
+
+    item->cat_id = CAT_UNKNOWN;
+    item->subcat_id = SUBCAT_UNKNOWN;
+    item->p_module = mod;
+    item->module_name = strdup( module_get_object( mod ) );
+    item->name = qfut( module_get_name( mod, false ) );
+    const char *help = module_get_help( mod );
+    if( help )
+        item->help = qfut( help );
+    else
+        item->help.clear();
+
+    item->setText( 0, item->name );
+    //item->setSizeHint( 0, QSize( -1, ITEM_HEIGHT ) );
+
+    parent->addChild( item );
+}
+
+QTreeWidgetItem *PrefsTree::findCatItem( int cat )
+{
+    int cat_index = vlc_config_cat_IndexOf( cat );
+    return this->catMap[cat_index];
+}
+
+QTreeWidgetItem *PrefsTree::findSubcatItem( int subcat )
+{
+    int subcat_index = vlc_config_subcat_IndexOf( subcat );
+    return this->subcatMap[subcat_index];
+}
+
+void PrefsTree::applyAll()
 {
     for( int i_cat_index = 0 ; i_cat_index < topLevelItemCount();
              i_cat_index++ )
     {
-        QTreeWidgetItem *cat_item = topLevelItem( i_cat_index );
+        PrefsTreeItem *cat_item = topLevelItem( i_cat_index );
         for( int i_sc_index = 0; i_sc_index < cat_item->childCount();
                  i_sc_index++ )
         {
-            QTreeWidgetItem *sc_item = cat_item->child( i_sc_index );
-            for( int i_module = 0 ; i_module < sc_item->childCount();
+            PrefsTreeItem *subcat_item = cat_item->child( i_sc_index );
+            for( int i_module = 0 ; i_module < subcat_item->childCount();
                      i_module++ )
             {
-                PrefsItemData *data = sc_item->child( i_module )->
-                               data( 0, Qt::UserRole).value<PrefsItemData *>();
-                if( data->panel && doclean )
-                {
-                    delete data->panel;
-                    data->panel = NULL;
-                }
-                else if( data->panel )
-                    data->panel->apply();
-            }
-            PrefsItemData *data = sc_item->data( 0, Qt::UserRole).
-                                            value<PrefsItemData *>();
-            if( data->panel && doclean )
-            {
-                delete data->panel;
-                data->panel = NULL;
+                PrefsTreeItem *mod_item = subcat_item->child( i_module );
+                mod_item->panel->apply();
             }
-            else if( data->panel )
-                data->panel->apply();
+            subcat_item->panel->apply();
         }
-        PrefsItemData *data = cat_item->data( 0, Qt::UserRole).
-                                            value<PrefsItemData *>();
-        if( data->panel && doclean )
-        {
-            delete data->panel;
-            data->panel = NULL;
-        }
-        else if( data->panel )
-            data->panel->apply();
+        cat_item->panel->apply();
     }
 }
 
 /* apply filter on tree item and recursively on its sub items
  * returns whether the item was filtered */
-bool PrefsTree::filterItems( QTreeWidgetItem *item, const QString &text,
+bool PrefsTree::filterItems( PrefsTreeItem *item, const QString &text,
                            Qt::CaseSensitivity cs )
 {
     bool sub_filtered = true;
 
     for( int i = 0; i < item->childCount(); i++ )
     {
-        QTreeWidgetItem *sub_item = item->child( i );
+        PrefsTreeItem *sub_item = item->child( i );
         if ( !filterItems( sub_item, text, cs ) )
         {
             /* not all the sub items were filtered */
@@ -343,10 +304,8 @@ bool PrefsTree::filterItems( QTreeWidgetItem *item, const QString &text,
         }
     }
 
-    PrefsItemData *data = item->data( 0, Qt::UserRole ).value<PrefsItemData *>();
-
-    bool filtered = sub_filtered && !data->contains( text, cs );
-    if ( b_show_only_loaded && sub_filtered && !data->b_loaded )
+    bool filtered = sub_filtered && !item->contains( text, cs );
+    if ( b_show_only_loaded && sub_filtered && !item->module_is_loaded )
         filtered = true;
     item->setExpanded( !sub_filtered );
     item->setHidden( filtered );
@@ -354,16 +313,15 @@ bool PrefsTree::filterItems( QTreeWidgetItem *item, const QString &text,
     return filtered;
 }
 
-
 /* collapse item if it's not selected or one of its sub items
  * returns whether the item was collapsed */
-bool PrefsTree::collapseUnselectedItems( QTreeWidgetItem *item )
+bool PrefsTree::collapseUnselectedItems( PrefsTreeItem *item )
 {
     bool sub_collapsed = true;
 
     for( int i = 0; i < item->childCount(); i++ )
     {
-        QTreeWidgetItem *sub_item = item->child( i );
+        PrefsTreeItem *sub_item = item->child( i );
         if ( !collapseUnselectedItems( sub_item ) )
         {
             /* not all the sub items were collapsed */
@@ -406,9 +364,9 @@ static void populateLoadedSet( QSet<QString> *loaded, vlc_object_t *p_node )
     delete[] tab;
 }
 
-/* Updates the PrefsItemData loaded status to reflect currently
+/* Updates the plugin node 'loaded' status to reflect currently
  * running modules */
-void PrefsTree::updateLoadedStatus( QTreeWidgetItem *item = NULL,
+void PrefsTree::updateLoadedStatus( PrefsTreeItem *item = NULL,
                                     QSet<QString> *loaded = NULL )
 {
     bool b_release = false;
@@ -428,9 +386,8 @@ void PrefsTree::updateLoadedStatus( QTreeWidgetItem *item = NULL,
     }
     else
     {
-        PrefsItemData *data = item->data( 0, Qt::UserRole )
-                .value<PrefsItemData *>();
-        data->b_loaded = loaded->contains( QString( data->psz_shortcut ) );
+        if( item->node_type == PrefsTreeItem::PLUGIN_NODE )
+            item->module_is_loaded = loaded->contains( QString( item->module_name ) );
 
         for( int i = 0; i < item->childCount(); i++ )
             updateLoadedStatus( item->child( i ), loaded );
@@ -449,7 +406,7 @@ void PrefsTree::filter( const QString &text )
 
     for( int i = 0 ; i < topLevelItemCount(); i++ )
     {
-        QTreeWidgetItem *cat_item = topLevelItem( i );
+        PrefsTreeItem *cat_item = topLevelItem( i );
         if ( clear_filter )
         {
             collapseUnselectedItems( cat_item );
@@ -472,24 +429,23 @@ void PrefsTree::resizeColumns()
     resizeColumnToContents( 0 );
 }
 
-PrefsItemData::PrefsItemData( QObject *_parent ) : QObject( _parent )
+PrefsTreeItem::PrefsTreeItem( PrefsTreeItemType ty ) : QTreeWidgetItem(ty)
 {
-    panel = NULL;
-    i_object_id = 0;
-    i_subcat_id = SUBCAT_UNKNOWN;
-    psz_shortcut = NULL;
-    b_loaded = false;
+    node_type = ty;
+    panel = nullptr;
+    cat_id = CAT_UNKNOWN;
+    subcat_id = SUBCAT_UNKNOWN;
+    p_module = nullptr;
+    module_name = nullptr;
+    module_is_loaded = false;
 }
 
 /* go over the config items and search text in psz_text
  * also search the node name and head */
-bool PrefsItemData::contains( const QString &text, Qt::CaseSensitivity cs )
+bool PrefsTreeItem::contains( const QString &text, Qt::CaseSensitivity cs )
 {
-    if( this->i_type == TYPE_CATEGORY )
-        return false;
-
-    bool is_core = this->i_type != TYPE_MODULE;
-    int id = SUBCAT_UNKNOWN;
+    bool is_core = this->node_type != PrefsTreeItem::PLUGIN_NODE;
+    int id = this->subcat_id;
 
     /* find our module */
     module_t *p_module;
@@ -499,11 +455,6 @@ bool PrefsItemData::contains( const QString &text, Qt::CaseSensitivity cs )
     {
         p_module = module_get_main();
         assert( p_module );
-
-        if( this->i_type == TYPE_SUBCATEGORY )
-            id = this->i_object_id;
-        else // TYPE_CATSUBCAT
-            id = this->i_subcat_id;
     }
 
     /* check the node itself (its name/longname/helptext) */
@@ -585,62 +536,41 @@ end:
  *********************************************************************/
 
 AdvPrefsPanel::AdvPrefsPanel( qt_intf_t *_p_intf, QWidget *_parent,
-                        PrefsItemData * data ) :
+                        PrefsTreeItem * node ) :
                         QWidget( _parent ), p_intf( _p_intf )
 {
-    /* Find our module */
-    module_t *p_module = NULL;
-    p_config = NULL;
-    if( data->i_type == PrefsItemData::TYPE_CATEGORY )
-        return;
-    else if( data->i_type == PrefsItemData::TYPE_MODULE )
-        p_module = data->p_module;
-    else
-    {
-        p_module = module_get_main();
-        assert( p_module );
-    }
+    module_t *p_module = node->p_module;
 
     unsigned confsize;
     p_config = module_config_get( p_module, &confsize );
     module_config_t *p_item = p_config,
                     *p_end = p_config + confsize;
 
-    if( data->i_type == PrefsItemData::TYPE_SUBCATEGORY ||
-        data->i_type == PrefsItemData::TYPE_CATSUBCAT )
+    QString heading;
+
+    if( node->node_type != PrefsTreeItem::PLUGIN_NODE  )
     {
+        heading = QString( node->name );
+        /* Skip to the relevant part of the core config */
         while (p_item < p_end)
         {
             if(  p_item->i_type == CONFIG_SUBCATEGORY &&
-                 ( ( data->i_type == PrefsItemData::TYPE_SUBCATEGORY &&
-                     p_item->value.i == data->i_object_id ) ||
-                   ( data->i_type == PrefsItemData::TYPE_CATSUBCAT &&
-                     p_item->value.i == data->i_subcat_id ) ) )
+                 p_item->value.i == node->subcat_id )
                 break;
             p_item++;
         }
+        p_item++; // Skip past the subcat entry itself
+    }
+    else
+    {
+        heading = QString( qfut( module_GetLongName( p_module ) ) );
     }
 
     /* Widgets now */
     global_layout = new QVBoxLayout();
     global_layout->setMargin( 2 );
-    QString head;
-    QString help;
-
-    help = QString( data->help );
-
-    if( data->i_type == PrefsItemData::TYPE_SUBCATEGORY ||
-        data->i_type == PrefsItemData::TYPE_CATSUBCAT )
-    {
-        head = QString( data->name );
-        p_item++; // Why that ?
-    }
-    else
-    {
-        head = QString( qfut( module_GetLongName( p_module ) ) );
-    }
 
-    QLabel *titleLabel = new QLabel( head );
+    QLabel *titleLabel = new QLabel( heading );
     QFont titleFont = QApplication::font();
     titleFont.setPointSize( titleFont.pointSize() + 6 );
     titleLabel->setFont( titleFont );
@@ -650,7 +580,7 @@ AdvPrefsPanel::AdvPrefsPanel( qt_intf_t *_p_intf, QWidget *_parent,
     title_line->setFrameShape(QFrame::HLine);
     title_line->setFrameShadow(QFrame::Sunken);
 
-    QLabel *helpLabel = new QLabel( help, this );
+    QLabel *helpLabel = new QLabel( node->help, this );
     helpLabel->setWordWrap( true );
 
     global_layout->addWidget( titleLabel );
@@ -668,14 +598,15 @@ AdvPrefsPanel::AdvPrefsPanel( qt_intf_t *_p_intf, QWidget *_parent,
     int i_line = 0, i_boxline = 0;
     bool has_hotkey = false;
 
-    if( p_item ) do
+    if( p_item ) for ( ; p_item < p_end; ++p_item)
     {
-        if( ( ( data->i_type == PrefsItemData::TYPE_SUBCATEGORY &&
-                p_item->value.i != data->i_object_id ) ||
-              ( data->i_type == PrefsItemData::TYPE_CATSUBCAT  &&
-                p_item->value.i != data->i_subcat_id ) ) &&
-            p_item->i_type == CONFIG_SUBCATEGORY )
-            break;
+        if( p_item->i_type == CONFIG_SUBCATEGORY )
+        {
+            if( node->node_type == PrefsTreeItem::PLUGIN_NODE )
+                continue;
+            else
+                break;
+        }
 
         if( p_item->i_type == CONFIG_SECTION )
         {
@@ -691,6 +622,7 @@ AdvPrefsPanel::AdvPrefsPanel( qt_intf_t *_p_intf, QWidget *_parent,
             box->hide();
             boxlayout = new QGridLayout();
         }
+
         /* Only one hotkey control */
         if( p_item->i_type == CONFIG_ITEM_KEY )
         {
@@ -713,10 +645,6 @@ AdvPrefsPanel::AdvPrefsPanel( qt_intf_t *_p_intf, QWidget *_parent,
         else i_line++;
         controls.append( control );
     }
-    while( !( ( data->i_type == PrefsItemData::TYPE_SUBCATEGORY ||
-               data->i_type == PrefsItemData::TYPE_CATSUBCAT ) &&
-             p_item->i_type == CONFIG_SUBCATEGORY )
-        && ( ++p_item < p_end ) );
 
     if( box && i_boxline > 0 )
     {


=====================================
modules/gui/qt/dialogs/preferences/complete_preferences.hpp
=====================================
@@ -29,8 +29,10 @@
 
 #include <vlc_common.h>
 #include <vlc_interface.h>
+#include <vlc_config_cat.h>
 
 #include <QTreeWidget>
+#include <QTreeWidgetItem>
 #include <QSet>
 
 #include "qt.hpp"
@@ -55,33 +57,34 @@
 class AdvPrefsPanel;
 class QVBoxLayout;
 
-class PrefsItemData : public QObject
+class PrefsTreeItem : public QTreeWidgetItem
 {
-    Q_OBJECT
 public:
-    PrefsItemData( QObject * );
-    virtual ~PrefsItemData() { free( psz_shortcut ); }
-    bool contains( const QString &text, Qt::CaseSensitivity cs );
-    AdvPrefsPanel *panel;
-    int i_object_id;
-    int i_subcat_id;
-    enum prefsType
+    enum PrefsTreeItemType
     {
-        TYPE_CATEGORY,
-        TYPE_CATSUBCAT,
-        TYPE_SUBCATEGORY,
-        TYPE_MODULE
+        CATEGORY_NODE = QTreeWidgetItem::UserType,
+        SUBCATEGORY_NODE,
+        PLUGIN_NODE
     };
-    prefsType i_type;
-    char *psz_shortcut;
-    bool b_loaded;
+    PrefsTreeItem( PrefsTreeItemType );
+    virtual ~PrefsTreeItem() { free( module_name ); }
+    PrefsTreeItem *child(int index) const
+    {
+        return static_cast<PrefsTreeItem *>( QTreeWidgetItem::child( index ) );
+    }
+    /* Search filter helper */
+    bool contains( const QString &text, Qt::CaseSensitivity cs );
+    PrefsTreeItemType node_type;
+    AdvPrefsPanel *panel;
     QString name;
     QString help;
+    int cat_id;
+    int subcat_id;
     module_t *p_module;
+    char *module_name;
+    bool module_is_loaded;
 };
 
-Q_DECLARE_METATYPE( PrefsItemData* );
-
 class PrefsTree : public QTreeWidget
 {
     Q_OBJECT
@@ -90,17 +93,27 @@ public:
     PrefsTree( qt_intf_t *, QWidget *, module_t **, size_t );
 
     void applyAll();
-    void cleanAll();
     void filter( const QString &text );
     void setLoadedOnly( bool );
+    PrefsTreeItem *topLevelItem(int index) const
+    {
+        return static_cast<PrefsTreeItem *>( QTreeWidget::topLevelItem( index ) );
+    }
 
 private:
-    void doAll( bool );
-    bool filterItems( QTreeWidgetItem *item, const QString &text, Qt::CaseSensitivity cs );
-    bool collapseUnselectedItems( QTreeWidgetItem *item );
-    void updateLoadedStatus( QTreeWidgetItem *item , QSet<QString> *loaded );
+    QTreeWidgetItem *createCatNode( int cat );
+    QTreeWidgetItem *createSubcatNode( QTreeWidgetItem * cat, int subcat );
+    void createPluginNode( QTreeWidgetItem * parent, module_t *mod );
+    QTreeWidgetItem *findCatItem( int cat );
+    QTreeWidgetItem *findSubcatItem( int subcat );
+    bool filterItems( PrefsTreeItem *item, const QString &text, Qt::CaseSensitivity cs );
+    bool collapseUnselectedItems( PrefsTreeItem *item );
+    void updateLoadedStatus( PrefsTreeItem *item , QSet<QString> *loaded );
     qt_intf_t *p_intf;
+    module_t *main_module;
     bool b_show_only_loaded;
+    QTreeWidgetItem *catMap[ARRAY_SIZE(categories_array)] = { nullptr };
+    QTreeWidgetItem *subcatMap[ARRAY_SIZE(subcategories_array)] = { nullptr };
 
 private slots:
     void resizeColumns();
@@ -112,7 +125,7 @@ class AdvPrefsPanel : public QWidget
 {
     Q_OBJECT
 public:
-    AdvPrefsPanel( qt_intf_t *, QWidget *, PrefsItemData * );
+    AdvPrefsPanel( qt_intf_t *, QWidget *, PrefsTreeItem * );
     virtual ~AdvPrefsPanel();
     void apply();
     void clean();


=====================================
modules/gui/qt/dialogs/preferences/preferences.cpp
=====================================
@@ -239,15 +239,15 @@ void PrefsDialog::changeSimplePanel( int number )
 void PrefsDialog::changeAdvPanel( QTreeWidgetItem *item )
 {
     if( item == NULL ) return;
-    PrefsItemData *data = item->data( 0, Qt::UserRole ).value<PrefsItemData*>();
+    PrefsTreeItem *node = static_cast<PrefsTreeItem *>( item );
 
-    if( !data->panel )
+    if( !node->panel )
     {
-        data->panel = new AdvPrefsPanel( p_intf, advanced_panels_stack, data );
+        node->panel = new AdvPrefsPanel( p_intf, advanced_panels_stack, node );
         advanced_panels_stack->insertWidget( advanced_panels_stack->count(),
-                                             data->panel );
+                                             node->panel );
     }
-    advanced_panels_stack->setCurrentWidget( data->panel );
+    advanced_panels_stack->setCurrentWidget( node->panel );
 }
 
 /* Actual apply and save for the preferences */


=====================================
src/libvlc-module.c
=====================================
@@ -1734,8 +1734,6 @@ vlc_module_begin ()
     add_module_list("video-filter", "video filter", NULL,
                     VIDEO_FILTER_TEXT, VIDEO_FILTER_LONGTEXT)
 
-    set_subcategory( SUBCAT_VIDEO_SPLITTER )
-
 #if 0
     add_string( "pixel-ratio", "1", PIXEL_RATIO_TEXT, PIXEL_RATIO_TEXT )
 #endif
@@ -1998,7 +1996,7 @@ vlc_module_begin ()
     add_module("demux", "demux", "any", DEMUX_TEXT, DEMUX_LONGTEXT)
     add_string( "demux-filter", NULL, DEMUX_FILTER_TEXT, DEMUX_FILTER_LONGTEXT )
 
-    set_subcategory( SUBCAT_INPUT_ACODEC )
+    //set_subcategory( SUBCAT_INPUT_ACODEC )
     set_subcategory( SUBCAT_INPUT_VCODEC )
 
     add_string( "codec", NULL, CODEC_TEXT, CODEC_LONGTEXT )
@@ -2006,7 +2004,7 @@ vlc_module_begin ()
     add_obsolete_string( "encoder" ) /* since 4.0.0 */
     add_module("dec-dev", "decoder device", "any", DEC_DEV_TEXT, DEC_DEV_LONGTEXT)
 
-    set_subcategory( SUBCAT_INPUT_SCODEC )
+    //set_subcategory( SUBCAT_INPUT_SCODEC )
     set_subcategory( SUBCAT_INPUT_STREAM_FILTER )
 
     add_module_list("stream-filter", "stream_filter", NULL,
@@ -2053,8 +2051,6 @@ vlc_module_begin ()
     add_module("packetizer", "packetizer", NULL,
                PACKETIZER_TEXT, PACKETIZER_LONGTEXT)
 
-    set_subcategory( SUBCAT_SOUT_VOD )
-
 /* Advanced options */
     set_subcategory( SUBCAT_ADVANCED_MISC )
     add_category_hint(N_("Advanced"), NULL)
@@ -2097,8 +2093,6 @@ vlc_module_begin ()
         change_string_list( clock_sources, clock_sources_text )
 #endif
 
-    set_subcategory( SUBCAT_ADVANCED_NETWORK )
-
 /* Playlist options */
     set_subcategory( SUBCAT_PLAYLIST_GENERAL )
     add_category_hint(N_("Playlist"), PLAYLIST_CAT_LONGTEXT)



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2437956b1335be4d2efa4cafb34ba55b856e79b3...56c4b6f13def4499826d74a0687477c46d614c86

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/2437956b1335be4d2efa4cafb34ba55b856e79b3...56c4b6f13def4499826d74a0687477c46d614c86
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list