[dconf-editor] Case-insensitive keys list.



commit b12c053bc63c70df8aa9ce3a67fd6a5ab9c59fd8
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Tue Feb 7 01:38:00 2017 +0100

    Case-insensitive keys list.

 editor/ca.desrt.dconf-editor.gschema.xml |    6 ++++
 editor/dconf-model.vala                  |   44 ++++++++++++++++++++++++-----
 editor/registry-view.ui                  |   35 +++++++++++++++++++++++
 editor/registry-view.vala                |   31 ++++++++++++++++++++-
 4 files changed, 107 insertions(+), 9 deletions(-)
---
diff --git a/editor/ca.desrt.dconf-editor.gschema.xml b/editor/ca.desrt.dconf-editor.gschema.xml
index f5feeb5..d4c5fb4 100644
--- a/editor/ca.desrt.dconf-editor.gschema.xml
+++ b/editor/ca.desrt.dconf-editor.gschema.xml
@@ -68,6 +68,12 @@
       <summary>Change the behaviour of a key value change request</summary>
       <description>The “unsafe” value is discouraged: for keys that have a non-special-cased type, it 
updates the key value each time something changes in the entry, so including intermediate states. The “safe” 
value asks for confirmation in these cases, but allows instant changes for booleans and nullable booleans, 
enums and flags. The “always-confirm-implicit” and “always-confirm-explicit” values always asks for 
confirmation, but the first applies the change if you change path whereas the second dismiss it. The 
“always-delay” value adds each change in delay mode, allowing to apply multiple keys at once.</description>
     </key>
+    <key name="sort-case-sensitive" type="b">
+      <default>false</default>
+      <summary>A flag to sort keys list case-sensitively</summary>
+      <description>GSettings doesn’t allow keys to use upper-case in their names, but installation paths of 
schemas can. If “true”, the keys list is sorted case-sensitively, with in usual order upper-case folders 
first.</description>
+    </key>
+    <!-- TODO sort-folder-first/last/mixed ; maybe also sort-reversed, but should that one be saved between 
sessions if the last path is not? -->
   </schema>
   <enum id="ca.desrt.dconf-editor.DemoEnum">
     <value value="0" nick="Red"/>
diff --git a/editor/dconf-model.vala b/editor/dconf-model.vala
index 1284109..f0a1a8f 100644
--- a/editor/dconf-model.vala
+++ b/editor/dconf-model.vala
@@ -21,10 +21,12 @@ public abstract class SettingObject : Object
     public Directory parent { get { return nullable_parent == null ? (Directory) this : (!) nullable_parent; 
}}   // TODO make protected or even remove
     public string name { get; construct; }
 
+    public string casefolded_name { get; construct; }
     public string full_name { get; private set; }
     construct
     {
         full_name = nullable_parent == null ? "/" : ((!) nullable_parent).full_name + name + ((this is 
Directory) ? "/" : "");
+        casefolded_name = name.casefold ();
     }
 }
 
@@ -53,6 +55,9 @@ public class Directory : SettingObject
 
     private DConf.Client client;
 
+    private bool? last_sort = null;
+    private bool? require_sorting = null;
+
     private GLib.ListStore? _key_model = null;
     public GLib.ListStore key_model
     {
@@ -64,24 +69,47 @@ public class Directory : SettingObject
                 create_folders ();
                 create_gsettings_keys ();
                 create_dconf_keys ();
-                sort_key_model ();
             }
             return (!) _key_model;
         }
     }
 
-    private void sort_key_model ()
-    {
-        ((!) _key_model).sort ((a, b) => { return strcmp (((SettingObject) a).name, ((SettingObject) 
b).name); });
-    }
-
     /*\
     * * Folders creation
     \*/
 
-    public void create_folders ()
+    private void create_folders ()
+    {
+        require_sorting = false;
+        children.foreach ((dir) => {
+                SettingObject _dir = (SettingObject) dir;
+                ((!) _key_model).append (_dir);
+                if (_dir.name != _dir.casefolded_name)
+                    require_sorting = true;
+            });
+    }
+
+    public bool need_sorting (bool case_sensitive)
+        requires (require_sorting != null)
+        requires (last_sort != null)
     {
-        children.foreach ((dir) => ((!) _key_model).append ((SettingObject) dir));
+        return ((!) require_sorting) && (case_sensitive != (!) last_sort);
+    }
+
+    public void sort_key_model (bool case_sensitive)
+    {
+        if (require_sorting != null && !need_sorting (case_sensitive))
+            return;
+
+        _sort_key_model (key_model, case_sensitive);
+        last_sort = case_sensitive;
+    }
+    private static void _sort_key_model (GLib.ListStore model, bool case_sensitive)
+    {
+        if (case_sensitive)
+            model.sort ((a, b) => { return strcmp (((SettingObject) a).name, ((SettingObject) b).name); });
+        else
+            model.sort ((a, b) => { return ((SettingObject) a).casefolded_name.collate (((SettingObject) 
b).casefolded_name); });
     }
 
     /*\
diff --git a/editor/registry-view.ui b/editor/registry-view.ui
index dcfaef1..df6569e 100644
--- a/editor/registry-view.ui
+++ b/editor/registry-view.ui
@@ -14,6 +14,41 @@
       </object>
     </child>
     <child>
+      <object class="GtkRevealer" id="need_reload_warning_revealer">
+        <property name="visible">True</property>
+        <property name="reveal-child">False</property>
+        <child>
+          <object class="GtkInfoBar">
+            <property name="visible">True</property>
+            <property name="message-type">warning</property>
+            <child internal-child="content_area">
+              <object class="GtkBox">
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="max-width-chars">40</property>
+                    <property name="wrap">True</property>
+                    <property name="label" translatable="yes">Sort preferences have changed. Do you want to 
reload the view?</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkButton">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Reload</property>
+                    <signal name="clicked" handler="reload"/>
+                  </object>
+                  <packing>
+                    <property name="pack-type">end</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
       <object class="GtkRevealer"> <!-- Workaround for the gtk+ bug: 
https://bugzilla.gnome.org/show_bug.cgi?id=724096 -->
         <property name="visible">True</property>
         <property name="reveal-child" bind-source="search_bar" bind-property="search-mode-enabled" 
bind-flags="bidirectional">False</property>
diff --git a/editor/registry-view.vala b/editor/registry-view.vala
index 5876b7f..5f82a36 100644
--- a/editor/registry-view.vala
+++ b/editor/registry-view.vala
@@ -24,6 +24,9 @@ class RegistryView : Grid, PathElement
     public bool show_search_bar { get; set; }
     public Behaviour behaviour { get; set; }
 
+    private GLib.Settings application_settings = new GLib.Settings ("ca.desrt.dconf-editor.Settings");
+    [GtkChild] private Revealer need_reload_warning_revealer;
+
     private SettingsModel model = new SettingsModel ();
     [GtkChild] private TreeView dir_tree_view;
     [GtkChild] private TreeSelection dir_tree_selection;
@@ -67,6 +70,11 @@ class RegistryView : Grid, PathElement
 
         current_path = (restore_view && path != "" && path [0] == '/') ? path : "/";
         path_requested (current_path, null);
+
+        application_settings.changed ["sort-case-sensitive"].connect (() => {
+                if (get_selected_directory ().need_sorting (application_settings.get_boolean 
("sort-case-sensitive")))
+                    need_reload_warning_revealer.set_reveal_child (true);
+            });
     }
 
     /*\
@@ -76,6 +84,7 @@ class RegistryView : Grid, PathElement
     private void show_browse_view (string path, string? selected, bool grab = true)
     {
         stack.set_transition_type (current_path.has_prefix (path) ? StackTransitionType.CROSSFADE : 
StackTransitionType.NONE);
+        need_reload_warning_revealer.set_reveal_child (false);
         update_current_path (path);
         stack.set_visible_child_name ("browse-view");
         if (selected != null)
@@ -143,7 +152,10 @@ class RegistryView : Grid, PathElement
     private void dir_selected_cb ()
     {
         search_next_button.set_sensitive (true);        // TODO better, or maybe just hide search_bar 1/2
-        key_model = get_selected_directory ().key_model;
+        Directory dir = get_selected_directory ();
+        dir.sort_key_model (application_settings.get_boolean ("sort-case-sensitive"));
+        key_model = dir.key_model;
+
         key_list_box.bind_model (key_model, new_list_box_row);
     }
 
@@ -370,6 +382,22 @@ class RegistryView : Grid, PathElement
         get_dconf_window ().update_hamburger_menu ();
     }
 
+    [GtkCallback]
+    private void reload ()
+        requires (!is_not_browsing_view ())
+    {
+        ListBoxRow? selected_row = key_list_box.get_selected_row ();
+        string? saved_selection = null;
+        if (selected_row != null)
+        {
+            int position = ((!) selected_row).get_index ();
+            saved_selection = ((SettingObject) ((!) key_model).get_object (position)).full_name;
+        }
+
+        get_selected_directory ().sort_key_model (application_settings.get_boolean ("sort-case-sensitive"));
+        show_browse_view (current_path, saved_selection);
+    }
+
     /*\
     * * Revealer stuff
     \*/
@@ -576,6 +604,7 @@ class RegistryView : Grid, PathElement
                 on_first_directory = false;
 
             /* Select next key that matches */
+            dir.sort_key_model (application_settings.get_boolean ("sort-case-sensitive"));
             GLib.ListStore key_model = dir.key_model;
             while (position < key_model.get_n_items ())
             {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]