[fusion-commits] Compizconfig Settings Manager in Python: Changes to 'master' (273e1c437a78a9bdee97308c06c6e3a26fc89921)

crdlb at server.opencompositing.org crdlb at server.opencompositing.org
Sat Mar 29 04:35:27 CET 2008


New commits:
commit 273e1c437a78a9bdee97308c06c6e3a26fc89921
Author: Christopher Williams <christopherw at verizon.net>
Date:   Fri Mar 28 23:26:35 2008 -0400

    Reorganise and optimise setting filter code


 ccm/Constants.py.in |    6 ++
 ccm/Pages.py        |  138 ++++++++++++++++++++++++++----------------
 ccm/Settings.py     |  169 ++++++++++++++++++++++++++++++++++-----------------
 ccm/Utils.py        |   12 +---
 4 files changed, 210 insertions(+), 115 deletions(-)


Modified: fusion/compizconfig/ccsm/ccm/Constants.py.in
===================================================================
--- fusion/compizconfig/ccsm/ccm/Constants.py.in
+++ fusion/compizconfig/ccsm/ccm/Constants.py.in
@@ -61,6 +61,12 @@ ImageCategory = 2
 ImageThemed   = 3
 ImageStock    = 4
 
+# Filter Levels
+#
+FilterName = 1 << 0
+FilterLongDesc = 1 << 1
+FilterValue = 1 << 2
+FilterAll = FilterName | FilterLongDesc | FilterValue
 # Paths
 #
 DataDir = "@prefix@/share"

Modified: fusion/compizconfig/ccsm/ccm/Pages.py
===================================================================
--- fusion/compizconfig/ccsm/ccm/Pages.py
+++ fusion/compizconfig/ccsm/ccm/Pages.py
@@ -106,7 +106,7 @@ class PluginPage:
             groupPage = GroupPage(name, group)
             if not groupPage.Empty:
                 self.RightWidget.append_page(groupPage.Widget, gtk.Label(name))
-                self.Pages = self.Pages + [groupPage]
+                self.Pages.append(groupPage)
         
         self.RightWidget.connect('size-allocate', self.ResetFocus)
 
@@ -117,43 +117,62 @@ class PluginPage:
         self.FilterEntry.grab_focus()
         self.FilterEntry.set_position(pos)
 
-    def FilterChanged(self, widget):
-        filter = widget.get_text().lower()
-        if filter == "":
-            filter = None
+    def GetPageSpot(self, new):
+        vpos = 0 #visible position
+        for page in self.Pages:
+            if page is new:
+                break
+            if page.Visible:
+                vpos += 1
+        return vpos
 
-        groups = []
+    def ShowFilterError(self, text):
 
-        for name, group in self.Plugin.Groups.items():
-            name = name or _("General")
-            groupPage = GroupPage(name, group, filter)
-            if not groupPage.Empty:
-                groups.append((name, groupPage))
+        if self.NotFoundBox is None:
+            self.NotFoundBox = NotFoundBox(text)
+            self.RightWidget.append_page(self.NotFoundBox, gtk.Label(_("Error")))
+        else:
+            self.NotFoundBox.update(text)
 
-        for page in self.RightWidget.get_children():
-            label = self.RightWidget.get_tab_label(page).get_label()
-            if label != _("Error"):
-                self.RightWidget.remove_page(self.RightWidget.page_num(page))
-                page.destroy()
+    def HideFilterError(self):
+        if self.NotFoundBox is None:
+            return
+        num = self.RightWidget.page_num(self.NotFoundBox)
+        if num >= 0:
+            self.RightWidget.remove_page(num)
+        self.NotFoundBox.destroy()
+        self.NotFoundBox = None
 
-        for name, groupPage in groups:
-            self.RightWidget.append_page(groupPage.Widget, gtk.Label(name))
+        self.RightWidget.set_current_page(0)
 
-        # Add
-        if len(self.RightWidget.get_children()) == 0 and not self.NotFoundBox:
-            self.NotFoundBox = NotFoundBox(filter)
-            self.RightWidget.append_page(self.NotFoundBox, gtk.Label(_("Error")))
-        # Update
-        elif len(self.RightWidget.get_children()) == 1 and self.NotFoundBox:
-            self.NotFoundBox.update(filter)
-        # Cleanup
-        elif len(self.RightWidget.get_children()) > 1 and self.NotFoundBox:
-            self.RightWidget.remove_page(self.RightWidget.page_num(self.NotFoundBox))
-            self.NotFoundBox.destroy()
-            self.NotFoundBox = None
+    def FilterChanged(self, widget):
+        text = widget.get_text().lower()
+        if text == "":
+            text = None
+
+        empty = True
+        for page in self.Pages:
+            num = self.RightWidget.page_num(page.Widget)
+            if page.Filter(text):
+                empty = False
+                if num < 0:
+                    self.RightWidget.insert_page(page.Widget, gtk.Label(page.Name), self.GetPageSpot(page))
+            else:
+                if num >= 0:
+                    self.RightWidget.remove_page(num)
+
+        if empty:
+            self.ShowFilterError(text)
+        else:
+            self.HideFilterError()
 
         self.RightWidget.show_all()
 
+        # This seems to be necessary to ensure all gaps from hidden settings are removed on all tabs
+        for page in self.Pages:
+            page.Widget.queue_resize_no_redraw()
+
+
     def EnablePlugin(self, widget):
         if self.Block > 0:
             return
@@ -170,7 +189,7 @@ class PluginPage:
 
 # Filter Page
 #
-class FilterPage:
+class FilterPage(object):
     def __init__(self, main, context):
         self.Context = context
         self.Main = main
@@ -258,15 +277,15 @@ class FilterPage:
         self.RightChild.pack_start(self.SelectorButtons, False, False)
         self.RightChild.pack_start(self.SelectorBoxes, False, False)
         self.SettingsArea = gtk.ScrolledWindow()
-        viewport = gtk.Viewport()
+        ebox = gtk.EventBox()
         self.SettingsBox = gtk.VBox()
         self.SettingsBox.set_border_width(5)
         self.SettingsBox.set_spacing(5)
-        viewport.add(self.SettingsBox)
+        ebox.add(self.SettingsBox)
         self.SettingsArea.props.hscrollbar_policy = gtk.POLICY_NEVER
         self.SettingsArea.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
         self.SettingsArea.set_border_width(5)
-        self.SettingsArea.add(viewport)
+        self.SettingsArea.add_with_viewport(ebox)
         self.SettingsArea.set_no_show_all(True)
         self.RightChild.pack_start(self.SettingsArea, True, True)
 
@@ -394,11 +413,14 @@ class FilterPage:
             self.SubGroupBox.add_item(name, self.SubGroupChanged)
 
             # Settings
+            # FIXME: optimise this later
             if self.CurrentSubGroup in (_("All"), name):
-                sga = SubGroupArea('', subGroup, self.Filter)
+                sga = SubGroupArea('', subGroup)
+                sga.Filter(self.Filter)
                 self.SettingsBox.pack_start(sga.Widget, False, False)
             elif self.CurrentSubGroup == None:
-                sga = SubGroupArea(name, subGroup, self.Filter)
+                sga = SubGroupArea(name, subGroup)
+                sga.Filter(self.Filter)
                 self.SettingsBox.pack_start(sga.Widget, False, False)
 
         self.SettingsArea.set_no_show_all(len(self.SettingsBox.get_children()) == 0)
@@ -439,13 +461,13 @@ class FilterPage:
     def FilterChanged(self, widget=None):
         self.Filter = self.FilterEntry.get_text()
 
-        runLevels = []
+        level = 0
         if self.FilterName.get_active():
-            runLevels.append(0)
+            level |= FilterName
         if self.FilterLongDesc.get_active():
-            runLevels.append(1)
+            level |= FilterLongDesc
         if self.FilterValue.get_active():
-            runLevels.append(2)
+            level |= FilterValue
 
         plugins = {}
         foundCurrentPlugin = False
@@ -457,7 +479,7 @@ class FilterPage:
                 subGroups = {}
                 for name, subGroup in plugin.Groups[group].items():
                     settings = sum((v.values() for v in [subGroup.Display]+[subGroup.Screens[CurrentScreenNum]]), [])
-                    settings = FilterSettings(settings, self.Filter, run=runLevels, singleRun=True)
+                    settings = FilterSettings(settings, self.Filter, level=level)
                     if len(settings) > 0:
                         subGroups[name] = subGroup
                         isCurrentPlugin = plugin.ShortDesc == self.CurrentPlugin
@@ -509,7 +531,7 @@ class FilterPage:
 
 # Profile and Backend Page
 #
-class ProfileBackendPage:
+class ProfileBackendPage(object):
     def __init__(self, main, context):
         self.Context = context
         self.Main = main
@@ -766,7 +788,7 @@ class ProfileBackendPage:
 
 # Plugin List Page
 #
-class PluginListPage:
+class PluginListPage(object):
     def __init__(self, main, context):
         self.Context = context
         self.Main = main
@@ -938,7 +960,7 @@ class PluginListPage:
 
 # Preferences Page
 #
-class PreferencesPage:
+class PreferencesPage(object):
     def __init__(self, main, context):
         self.Context = context
         self.Main = main
@@ -999,12 +1021,10 @@ class PreferencesPage:
 
 # Page
 #
-class Page:
+class Page(object):
     def __init__(self):
-        self.Widget = gtk.VBox()
         self.SetContainer = gtk.VBox()
-        
-        scroll = gtk.ScrolledWindow()
+        self.Widget = scroll = gtk.ScrolledWindow()
         scroll.props.hscrollbar_policy = gtk.POLICY_NEVER
         scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
         
@@ -1016,20 +1036,20 @@ class Page:
         ebox = gtk.EventBox()
         view.add(ebox)
         ebox.add(self.SetContainer)
-        self.Widget.pack_start(scroll, True, True)
         
         self.Empty = True
 
 # Group Page
 #
 class GroupPage(Page):
-    def __init__(self, name, group, filter=None):
+    def __init__(self, name, group):
         Page.__init__(self)
 
+        self.Name = name
         self.subGroupAreas = []
 
         if '' in group:
-            sga = SubGroupArea('', group[''], filter)
+            sga = SubGroupArea('', group[''])
             if not sga.Empty:
                 self.SetContainer.pack_start(sga.Widget, False, False)
                 self.Empty = False
@@ -1037,8 +1057,22 @@ class GroupPage(Page):
 
         for subGroup in sorted(group):
             if not subGroup == '':
-                sga = SubGroupArea(subGroup, group[subGroup], filter)
+                sga = SubGroupArea(subGroup, group[subGroup])
                 if not sga.Empty:
                     self.SetContainer.pack_start(sga.Widget, False, False)
                     self.Empty = False
                     self.subGroupAreas.append(sga)
+
+        self.Visible = not self.Empty
+
+    def Filter(self, text):
+        empty = True
+        for area in self.subGroupAreas:
+            if area.Filter(text):
+                empty = False
+
+        self.Visible = not empty
+
+        return not empty
+
+

Modified: fusion/compizconfig/ccsm/ccm/Settings.py
===================================================================
--- fusion/compizconfig/ccsm/ccm/Settings.py
+++ fusion/compizconfig/ccsm/ccm/Settings.py
@@ -42,7 +42,6 @@ class Setting(object):
     NoneValue = ''
 
     def __init__(self, Setting=None, Settings=None, List=False):
-        self.Custom = False
         self.Setting = Setting
         self.Settings = Settings # for multi-list settings
         self.List = List
@@ -52,6 +51,7 @@ class Setting(object):
         self.Blocked = 0
         self.EBox = gtk.EventBox()
         self.Box = gtk.HBox()
+        self.EBox.set_visible_window(False)
         self.Box.set_spacing(5)
         self.EBox.add(self.Box)
         self.Reset = gtk.Button()
@@ -69,16 +69,6 @@ class Setting(object):
     def GetColumn(self, num):
         return (str, gtk.TreeViewColumn(self.Setting.ShortDesc, gtk.CellRendererText(), text=num))
 
-    def Attach(self, table, row):
-        if self.Custom:
-            self.EBox.set_sensitive(not self.Setting.ReadOnly)
-            table.attach(self.EBox, 0, 2, row, row+1, TableDef, TableDef, TableX, TableX)
-        else:
-            self.EBox.set_sensitive(not self.Setting.ReadOnly)
-            table.attach(self.EBox, 0, 1, row, row+1, TableDef, TableDef, TableX, TableX)
-            self.Reset.set_sensitive(not self.Setting.ReadOnly)
-            table.attach(self.Reset, 1, 2, row, row+1, 0, 0, TableX, TableX)
-
     def PureVirtual (self, func):
         message = "Missing %(function)s function for %(name)s setting (%(class)s)"
 
@@ -161,13 +151,47 @@ class Setting(object):
         vlist.insert(b, vlist.pop(a))
         self.Setting.Value = vlist
 
-class StringSetting(Setting):
+    def _SetHidden(self, visible):
+
+        self.EBox.props.no_show_all = not visible
+
+        if visible:
+            self.EBox.show()
+        else:
+            self.EBox.hide()
+
+    def _Filter(self, text, level):
+        visible = False
+        if text is not None:
+            if level & FilterName:
+                visible = (text in self.Setting.Name.lower()
+                    or text in self.Setting.ShortDesc.lower())
+            if not visible and level & FilterLongDesc:
+                visible = text in self.Setting.LongDesc.lower()
+            if not visible and level & FilterValue:
+                visible = text in str(self.Setting.Value).lower()
+        else:
+            visible = True
+        return visible
+
+    def Filter(self, text, level=FilterAll):
+        visible = self._Filter(text, level=level)
+        self._SetHidden(visible)
+        return visible
+
+class StockSetting(Setting):
+
     def _Init(self):
+        self.Box.pack_start(self.Label, False, False)
+        self.Box.pack_end(self.Reset, False, False)
+
+class StringSetting(StockSetting):
+    def _Init(self):
+        StockSetting._Init(self)
         self.Entry = gtk.Entry()
         self.Entry.connect('activate', self.Changed)
         self.Entry.connect('focus-out-event', self.Changed)
         self.Widget = self.Entry
-        self.Box.pack_start(self.Label, False, False)
         self.Box.pack_start(self.Widget, True, True)
 
     def _Read(self):
@@ -195,11 +219,12 @@ class FileStringSetting(StringSetting):
             self.isDirectory, self.isImage)
         self.Box.pack_start(self.FileButton, False, False)
 
-class EnumSetting(Setting):
+class EnumSetting(StockSetting):
 
     NoneValue = 0
 
     def _Init(self):
+        StockSetting._Init(self)
         self.Combo = gtk.combo_box_new_text()
         if self.List:
             self.Info = self.Setting.Info[1][2]
@@ -211,7 +236,6 @@ class EnumSetting(Setting):
         self.Combo.connect('changed', self.Changed)
 
         self.Widget = self.Combo
-        self.Box.pack_start(self.Label, False, False)
         self.Box.pack_start(self.Combo, True, True)
 
     def _CellEdited(self, cell, path, new_text):
@@ -246,14 +270,20 @@ class EnumSetting(Setting):
         
         self.Set(self.Info[active])
 
-class BoolSetting (Setting):
+    def _Filter(self, text, level):
+        visible = Setting._Filter(self, text, level=level)
+        if text is not None and not visible and level & FilterValue:
+            visible = any(text in s.lower() for s in self.Info)
+        return visible
+
+class BoolSetting (StockSetting):
 
     NoneValue = False
 
     def _Init (self):
+        StockSetting._Init(self)
         self.Label.set_size_request(-1, -1)
         self.CheckButton = gtk.CheckButton ()
-        self.Box.pack_start(self.Label, False, False)
         align = gtk.Alignment(yalign=0.5)
         align.add(self.CheckButton)
         self.Box.pack_end(align, False, False)
@@ -278,12 +308,12 @@ class BoolSetting (Setting):
         cell.connect('toggled', self.CellToggled)
         return (bool, gtk.TreeViewColumn(self.Setting.ShortDesc, cell, active=num))
 
-class NumberSetting(Setting):
+class NumberSetting(StockSetting):
 
     NoneValue = 0
 
     def _Init(self):
-
+        StockSetting._Init(self)
         if self.List:
             self.Info = info = self.Setting.Info[1]
         else:
@@ -302,7 +332,6 @@ class NumberSetting(Setting):
         self.Spin.connect("value-changed", self.Changed)
         self.Widget = self.Scale
 
-        self.Box.pack_start(self.Label, False, False)
         self.Box.pack_start(self.Scale, True, True)
         self.Box.pack_start(self.Spin, False, False)
 
@@ -331,11 +360,12 @@ class FloatSetting(NumberSetting):
         self.Scale.set_digits(4)
 
 
-class ColorSetting(Setting):
+class ColorSetting(StockSetting):
 
     NoneValue = (0, 0, 0, 65535) # opaque black
 
     def _Init(self):
+        StockSetting._Init(self)
         self.Button = gtk.ColorButton()
         self.Button.set_size_request (100, -1)
         self.Button.set_use_alpha(True)
@@ -343,7 +373,6 @@ class ColorSetting(Setting):
 
         self.Widget = gtk.Alignment (1, 0.5)
         self.Widget.add (self.Button)
-        self.Box.pack_start(self.Label, False, False)
         self.Box.pack_start(self.Widget, True, True)
 
     def GetForRenderer(self):
@@ -367,8 +396,6 @@ class ColorSetting(Setting):
 class BaseListSetting(Setting):
     def _Init(self):
         self.Widget = gtk.VBox()
-        self.Custom = True
-        self.Setting = None
         self.EditDialog = None        
 
         self.Widgets = []
@@ -383,6 +410,7 @@ class BaseListSetting(Setting):
 
         for widget in self.Widgets:
             widget.Store = self.Store
+            widget.Box.remove(widget.Reset)
 
         for col in cols:
             self.View.append_column(col)
@@ -580,9 +608,6 @@ class BaseListSetting(Setting):
         for values in zip(*[w.GetForRenderer() for w in self.Widgets]):
             self.Store.append(values)
 
-    def Attach(self, table, row):
-        table.attach(self.EBox, 0, 2, row, row+1, xpadding=5)
-
 class ListSetting(BaseListSetting):
 
     def _Init(self):
@@ -595,11 +620,17 @@ class MultiListSetting(BaseListSetting):
         Tooltips.set_tip(self.EBox, _("Multi-list settings. You can double-click a row to edit the values."))
         BaseListSetting._Init(self)
 
+    def Filter(self, text, level=FilterAll):
+        visible = False
+        for setting in self.Widgets:
+            if setting._Filter(text, level=level):
+                visible = True
+        self._SetHidden(visible)
+        return visible
+
 class EnumFlagsSetting(Setting):
 
     def _Init(self):
-        self.Custom = True
-
         frame = gtk.Frame(self.Setting.ShortDesc)
         table = gtk.Table()
         
@@ -640,10 +671,16 @@ class EnumFlagsSetting(Setting):
                 values.append(self.Setting.Info[1][2][key])
         self.Setting.Value = values
 
-class EditableActionSetting (Setting):
+    def _Filter(self, text, level=FilterAll):
+        visible = Setting._Filter(self, text, level=level)
+        if text is not None and not visible and level & FilterValue:
+            visible = any(text in s.lower() for s in self.Setting.Info[1][2])
+        return visible
 
-    def _Init (self, widget, action):
+class EditableActionSetting (StockSetting):
 
+    def _Init (self, widget, action):
+        StockSetting._Init(self)
         alignment = gtk.Alignment (0, 0.5)
         alignment.add (widget)
 
@@ -657,11 +694,9 @@ class EditableActionSetting (Setting):
 
         action = ActionImage (action)
         self.Box.pack_start (action, False, False)
-        self.Box.pack_start(self.Label, True, True)
+        self.Box.reorder_child (action, 0)
         self.Box.pack_end (editButton, False, False)
         self.Box.pack_end(alignment, False, False)
-
-
         self.Widget = widget
 
 
@@ -1220,42 +1255,66 @@ def MakeSetting(setting, List=False):
 
     return stype(setting, List=List)
 
-class SubGroupArea:
-    def __init__(self, name, subGroup, filter=None):
+class SubGroupArea(object):
+    def __init__(self, name, subGroup):
         self.MySettings = []
-        settings = FilterSettings(sorted(sum((v.values() for v in [subGroup.Display]+[subGroup.Screens[CurrentScreenNum]]), []), key=SettingKeyFunc), filter)
+        self.Name = name
+        settings = sorted(sum((v.values() for v in [subGroup.Display]+[subGroup.Screens[CurrentScreenNum]]), []), key=SettingKeyFunc)
         if not name:
-            self.Widget = gtk.Table()
-            self.Child = self.Widget
+            self.Child = self.Widget = gtk.VBox()
         else:
             self.Widget = gtk.Frame()
             self.Expander = gtk.Expander(name)
             self.Widget.add(self.Expander)
             self.Expander.set_expanded(False)
-            self.Child = gtk.Table()
+            self.Child = gtk.VBox()
             self.Expander.add(self.Child)
 
-            # create a special widget for list subGroups
-            if len(settings) > 1 and HasOnlyType(settings, 'List'):
-                multiList = MultiListSetting(Settings=settings)
-                multiList.Read()
-                multiList.Attach(self.Child, 0)
-                self.Empty = False
+        self.Child.set_spacing(TableX)
+        self.Child.set_border_width(TableX)
+
+        # create a special widget for list subGroups
+        if len(settings) > 1 and HasOnlyType(settings, 'List'):
+            multiList = MultiListSetting(Settings=settings)
+            multiList.Read()
+            self.Child.pack_start(multiList.EBox, True, True)
+            self.MySettings.append(multiList)
+            self.Empty = False
+            if name:
                 self.Expander.set_expanded(True)
 
-                return # exit earlier to avoid unneeded logic's
+            return # exit earlier to avoid unneeded logic's
         
         self.Empty = True
-        row = 0
         for setting in settings:
             if not (setting.Plugin.Name == 'core' and setting.Name == 'active_plugins'):
-                set = MakeSetting(setting)
-                if set is not None:
-                    set.Read()
-                    set.Attach(self.Child, row)
-                    self.MySettings.append(set)
-                    row = row+1
+                setting = MakeSetting(setting)
+                if setting is not None:
+                    setting.Read()
+                    self.Child.pack_start(setting.EBox, True, True)
+                    self.MySettings.append(setting)
                     self.Empty = False
 
-        if name and row < 4: # ahi hay magic numbers!
+        if name and len(settings) < 4: # ahi hay magic numbers!
             self.Expander.set_expanded(True)
+
+    def Filter(self, text, level=FilterAll):
+        empty = True
+        count = 0
+        for setting in self.MySettings:
+            if setting.Filter(text, level=level):
+                empty = False
+                count += 1
+
+        if self.Name:
+            self.Expander.set_expanded(count < 4)
+
+        self.Widget.props.no_show_all = empty
+
+        if empty:
+            self.Widget.hide()
+        else:
+            self.Widget.show()
+
+        return not empty
+

Modified: fusion/compizconfig/ccsm/ccm/Utils.py
===================================================================
--- fusion/compizconfig/ccsm/ccm/Utils.py
+++ fusion/compizconfig/ccsm/ccm/Utils.py
@@ -321,7 +321,7 @@ PluginKeyFunc = operator.attrgetter('ShortDesc')
 
 # singleRun is used to combine the run stages, in this case run is a list
 # containing the run levels which should be used to filter the settings
-def FilterSettings(settings, filter, run=0, singleRun=False):
+def FilterSettings(settings, filter, level=FilterAll):
     if filter == None:
         return settings
 
@@ -331,7 +331,7 @@ def FilterSettings(settings, filter, run=0, singleRun=False):
 
     for setting in settings:
         # First run, only search in shortDesc and name
-        if run == 0 or (singleRun and 0 in run):
+        if level & FilterName:
             shortDesc = setting.ShortDesc.lower()
             name = setting.Name.lower()
             if filter in shortDesc:
@@ -341,13 +341,13 @@ def FilterSettings(settings, filter, run=0, singleRun=False):
                 filteredSettings.append(setting)
                 continue
         # Then in longDesc
-        if run == 1 or (singleRun and 1 in run):
+        if level & FilterLongDesc:
             longDesc = setting.LongDesc.lower()
             if filter in longDesc:
                 filteredSettings.append(setting)
                 continue
         # Finally search in the option value
-        if run == 2 or (singleRun and 2 in run):
+        if level & FilterValue:
             value = ""
             # make sure enum settings work too
             if setting.Type == 'Int' and setting.Info[2]:
@@ -365,10 +365,6 @@ def FilterSettings(settings, filter, run=0, singleRun=False):
             if filter in value:
                 filteredSettings.append(setting)
 
-    # Nothing was found, search also in the longDesc/value
-    if not filteredSettings and run < 2 and not singleRun:
-        return FilterSettings(settings, filter, run+1, False)
-
     return filteredSettings
 
 def HasOnlyType (settings, stype):


More information about the commits mailing list