[dconf-editor] New UI.



commit d8a17ddaddd533866122f91b3ee3661a57351dab
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Mon Jun 27 00:22:22 2016 +0200

    New UI.

 editor/Makefile.am                 |    1 -
 editor/dconf-editor.gresource.xml  |    1 -
 editor/dconf-editor.ui             |    4 +-
 editor/dconf-view.vala             |  180 +++++++++++++++-----------------
 editor/dconf-window.vala           |    2 +-
 editor/key-editor.ui               |   64 -----------
 editor/key-list-box-row.vala       |   13 ++-
 editor/modifications-revealer.vala |   10 +-
 editor/property-row.ui             |    2 +
 editor/registry-view.ui            |   58 ++++++++++-
 editor/registry-view.vala          |  202 ++++++++++++++++++++++++-----------
 po/POTFILES.in                     |    1 -
 12 files changed, 296 insertions(+), 242 deletions(-)
---
diff --git a/editor/Makefile.am b/editor/Makefile.am
index f59d2d7..30c5c6e 100644
--- a/editor/Makefile.am
+++ b/editor/Makefile.am
@@ -26,7 +26,6 @@ resource_data = \
        dconf-editor.ui \
        folder-list-box-row.ui \
        key-list-box-row.ui \
-       key-editor.ui \
        bookmarks.ui \
        bookmark.ui \
        help-overlay.ui \
diff --git a/editor/dconf-editor.gresource.xml b/editor/dconf-editor.gresource.xml
index 3ffabbb..d90b66d 100644
--- a/editor/dconf-editor.gresource.xml
+++ b/editor/dconf-editor.gresource.xml
@@ -7,7 +7,6 @@
     <file preprocess="xml-stripblanks">dconf-editor.ui</file>
     <file preprocess="xml-stripblanks">folder-list-box-row.ui</file>
     <file preprocess="xml-stripblanks">key-list-box-row.ui</file>
-    <file preprocess="xml-stripblanks">key-editor.ui</file>
     <file preprocess="xml-stripblanks">modifications-revealer.ui</file>
     <file preprocess="xml-stripblanks">pathbar.ui</file>
     <file preprocess="xml-stripblanks">pathbar-item.ui</file>
diff --git a/editor/dconf-editor.ui b/editor/dconf-editor.ui
index 4a3b4ac..8371456 100644
--- a/editor/dconf-editor.ui
+++ b/editor/dconf-editor.ui
@@ -4,8 +4,8 @@
   <template class="DConfWindow" parent="GtkApplicationWindow">
     <property name="visible">False</property>
     <property name="title" translatable="yes">dconf Editor</property>
-    <property name="height-request">525</property>
-    <property name="width-request">700</property>
+    <property name="height-request">550</property>
+    <property name="width-request">770</property>
     <signal name="show" handler="on_show"/>
     <signal name="key-press-event" handler="on_key_press_event"/>
     <signal name="window-state-event" handler="on_window_state_event"/>
diff --git a/editor/dconf-view.vala b/editor/dconf-view.vala
index 08c1522..62226c4 100644
--- a/editor/dconf-view.vala
+++ b/editor/dconf-view.vala
@@ -56,80 +56,14 @@ private class PropertyRow : ListBoxRow
     }
 }
 
-[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/key-editor.ui")]
-private class KeyEditor : Dialog
-{
-    [GtkChild] private Button button_apply;
-    [GtkChild] private InfoBar no_schema_warning;
-    [GtkChild] private ListBox listbox;
-
-    public bool custom_value_is_valid { get; set; default = true; }
-
-    public KeyEditor (bool has_schema, string name, string parent_path)
-    {
-        Object (use_header_bar: Gtk.Settings.get_default ().gtk_dialogs_use_header ? 1 : 0);
-
-        if (has_schema)
-            no_schema_warning.destroy ();
-        else
-            no_schema_warning.show ();
-
-        this.title = name;
-
-        if (this.use_header_bar == 1)        // TODO else..?
-            ((HeaderBar) this.get_header_bar ()).subtitle = parent_path;   // TODO get_header_bar() is 
[transfer none]
-
-        notify ["custom-value-is-valid"].connect (() => { button_apply.set_sensitive 
(custom_value_is_valid); });
-    }
-
-    public void switch_is_active (bool active)
-    {
-        button_apply.set_sensitive (active ? true : custom_value_is_valid);
-    }
-
-    public void add_row_from_label (string property_name, string property_value)
-    {
-        listbox.add (new PropertyRow.from_label (property_name, property_value));
-    }
-
-    public void add_row_from_widget (string property_name, Widget widget, string? type)
-    {
-        listbox.add (new PropertyRow.from_widgets (property_name, widget, type != null ? add_warning ((!) 
type) : null));
-    }
-
-    private static Widget? add_warning (string type)
-    {
-        if (type != "<flags>" && ((type != "s" && "s" in type) || (type != "g" && "g" in type)) || (type != 
"o" && "o" in type))
-        {
-            if ("m" in type)
-                /* Translators: neither the "nothing" keyword nor the "m" type should be translated; a 
"maybe type" is a type of variant that is nullable. */
-                return warning_label (_("Use the keyword “nothing” to set a maybe type (beginning with “m”) 
to its empty value. Strings, signatures and object paths should be surrounded by quotation marks."));
-            else
-                return warning_label (_("Strings, signatures and object paths should be surrounded by 
quotation marks."));
-        }
-        else if (type != "m" && type != "mb" && type != "<enum>" && "m" in type)
-            /* Translators: neither the "nothing" keyword nor the "m" type should be translated; a "maybe 
type" is a type of variant that is nullable. */
-            return warning_label (_("Use the keyword “nothing” to set a maybe type (beginning with “m”) to 
its empty value."));
-        return null;
-    }
-    private static Widget warning_label (string text)
-    {
-        Label label = new Label ("<i>" + text + "</i>");
-        label.visible = true;
-        label.use_markup = true;
-        label.max_width_chars = 59;
-        label.wrap = true;
-        label.halign = Align.START;
-        return (Widget) label;
-    }
-}
-
 public interface KeyEditorChild : Widget
 {
-    public signal void value_has_changed (bool is_valid);
+    public signal void value_has_changed (bool enable_revealer, bool is_valid = false);
 
     public abstract Variant get_variant ();
     public signal void child_activated ();
+
+    public abstract void reload (Variant gvariant);
 }
 
 private class KeyEditorChildEnum : MenuButton, KeyEditorChild
@@ -154,9 +88,9 @@ private class KeyEditorChildEnum : MenuButton, KeyEditorChild
                 reload (gvariant);
                 popover.closed ();
 
-                value_has_changed (true);
+                value_has_changed (true, true);
             });
-        reload (key.value);
+        reload (key.planned_change && (key.planned_value != null) ? key.planned_value : key.value);
         this.set_popover ((Popover) popover);
     }
 
@@ -165,7 +99,7 @@ private class KeyEditorChildEnum : MenuButton, KeyEditorChild
         return variant;
     }
 
-    private void reload (Variant gvariant)
+    public void reload (Variant gvariant)
     {
         variant = gvariant;
         VariantType type = gvariant.get_type ();
@@ -177,16 +111,14 @@ private class KeyEditorChildEnum : MenuButton, KeyEditorChild
 private class KeyEditorChildFlags : Grid, KeyEditorChild
 {
     private Variant variant;
+    private Label label = new Label ("");
 
     public KeyEditorChildFlags (GSettingsKey key)
         requires (key.type_string == "<flags>")
     {
-        this.variant = key.value;
-
         this.visible = true;
         this.hexpand = true;
 
-        Label label = new Label (variant.print (false));
         label.visible = true;
         label.halign = Align.START;
         label.hexpand = true;
@@ -203,11 +135,10 @@ private class KeyEditorChildFlags : Grid, KeyEditorChild
         popover.create_flags_list (key);
         popover.set_relative_to (button);
         popover.value_changed.connect ((gvariant) => {
-                variant = gvariant;
-                label.label = gvariant.print (false);
-
-                value_has_changed (true);
+                reload (gvariant);
+                value_has_changed (true, true);
             });
+        reload (key.planned_change && (key.planned_value != null) ? key.planned_value : key.value);
         button.set_popover ((Popover) popover);
     }
 
@@ -215,6 +146,13 @@ private class KeyEditorChildFlags : Grid, KeyEditorChild
     {
         return variant;
     }
+
+    public void reload (Variant gvariant)
+    {
+        this.variant = gvariant;
+        label.label = gvariant.print (false);
+        value_has_changed (false);
+    }
 }
 
 private class KeyEditorChildNullableBool : MenuButton, KeyEditorChild
@@ -240,9 +178,9 @@ private class KeyEditorChildNullableBool : MenuButton, KeyEditorChild
                 reload (gvariant);
                 popover.closed ();
 
-                value_has_changed (true);
+                value_has_changed (true, true);
             });
-        reload (key.value);
+        reload (key.planned_change && (key.planned_value != null) ? key.planned_value : key.value);
         this.set_popover ((Popover) popover);
     }
 
@@ -251,7 +189,7 @@ private class KeyEditorChildNullableBool : MenuButton, KeyEditorChild
         return variant;
     }
 
-    private void reload (Variant gvariant)
+    public void reload (Variant gvariant)
     {
         variant = gvariant;
         maybe_variant = variant.get_maybe ();
@@ -291,17 +229,25 @@ private class KeyEditorChildBool : Grid, KeyEditorChild // might be managed by a
         button_true.active = initial_value;
         button_true.bind_property ("active", button_false, "active", 
BindingFlags.INVERT_BOOLEAN|BindingFlags.SYNC_CREATE|BindingFlags.BIDIRECTIONAL);
 
-        button_true.toggled.connect (() => { value_has_changed (true); });
+        button_true.toggled.connect (() => { value_has_changed (true, true); });
     }
 
     public Variant get_variant ()
     {
         return new Variant.boolean (button_true.active);
     }
+
+    public void reload (Variant gvariant)
+    {
+        button_true.active = gvariant.get_boolean ();
+        value_has_changed (false);
+    }
 }
 
 private class KeyEditorChildNumberDouble : SpinButton, KeyEditorChild
 {
+    private uint locked = 0;
+
     public KeyEditorChildNumberDouble (Key key)
         requires (key.type_string == "d")
     {
@@ -321,7 +267,7 @@ private class KeyEditorChildNumberDouble : SpinButton, KeyEditorChild
             max = double.MAX;
         }
 
-        Adjustment adjustment = new Adjustment (key.value.get_double (), min, max, 0.01, 0.1, 0.0);
+        Adjustment adjustment = new Adjustment (key.planned_change && (key.planned_value != null) ? 
key.planned_value.get_double () : key.value.get_double (), min, max, 0.01, 0.1, 0.0);
         this.configure (adjustment, 0.01, 2);
 
         this.update_policy = SpinButtonUpdatePolicy.IF_VALID;
@@ -329,8 +275,8 @@ private class KeyEditorChildNumberDouble : SpinButton, KeyEditorChild
         this.input_purpose = InputPurpose.NUMBER;
         this.width_chars = 30;
 
-        this.buffer.deleted_text.connect (() => { value_has_changed (true); });     // TODO test value for
-        this.buffer.inserted_text.connect (() => { value_has_changed (true); });    //   non-numeric chars
+        this.buffer.deleted_text.connect (() => { if (locked > 0) locked -= 1; else value_has_changed (true, 
true); });     // TODO test value for
+        this.buffer.inserted_text.connect (() => { if (locked > 0) locked -= 1; else value_has_changed 
(true, true); });    //   non-numeric chars
         this.activate.connect (() => { update (); child_activated (); });
     }
 
@@ -338,11 +284,19 @@ private class KeyEditorChildNumberDouble : SpinButton, KeyEditorChild
     {
         return new Variant.double (this.get_value ());
     }
+
+    public void reload (Variant gvariant)
+    {
+        locked = 2;
+        this.set_value (gvariant.get_double ());
+        value_has_changed (false);  // set disable_revealer_for_value to false, might be useful for corner 
cases
+    }
 }
 
 private class KeyEditorChildNumberInt : SpinButton, KeyEditorChild
 {
     private string key_type;
+    private uint locked = 0;
 
     public KeyEditorChildNumberInt (Key key)
         requires (key.type_string == "y" || key.type_string == "n" || key.type_string == "q" || 
key.type_string == "i" || key.type_string == "u" || key.type_string == "h")     // TODO key.type_string == 
"x" || key.type_string == "t" ||
@@ -362,7 +316,7 @@ private class KeyEditorChildNumberInt : SpinButton, KeyEditorChild
         else
             get_min_and_max_double (out min, out max, key.type_string);
 
-        Adjustment adjustment = new Adjustment (get_variant_as_double (key.value), min, max, 1.0, 5.0, 0.0);
+        Adjustment adjustment = new Adjustment (get_variant_as_double (key.planned_change && 
(key.planned_value != null) ? key.planned_value : key.value), min, max, 1.0, 5.0, 0.0);
         this.configure (adjustment, 1.0, 0);
 
         this.update_policy = SpinButtonUpdatePolicy.IF_VALID;
@@ -371,8 +325,8 @@ private class KeyEditorChildNumberInt : SpinButton, KeyEditorChild
         this.input_purpose = InputPurpose.NUMBER;   // TODO could be DIGITS for UnsignedInt
         this.width_chars = 30;
 
-        this.buffer.deleted_text.connect (() => { value_has_changed (true); });     // TODO test value for
-        this.buffer.inserted_text.connect (() => { value_has_changed (true); });    //   non-numeric chars
+        this.buffer.deleted_text.connect (() => { if (locked > 0) locked -= 1; else value_has_changed (true, 
true); });     // TODO test value for
+        this.buffer.inserted_text.connect (() => { if (locked > 0) locked -= 1; else value_has_changed 
(true, true); });    //   non-numeric chars
         this.activate.connect (() => { update (); child_activated (); });
     }
 
@@ -408,15 +362,22 @@ private class KeyEditorChildNumberInt : SpinButton, KeyEditorChild
     {
         switch (key_type)
         {
-            case "y": return new Variant.byte   ((uchar) this.get_value ());        // TODO uchar or uint8?
-            case "n": return new Variant.int16  ((int16) this.get_value ());
-            case "q": return new Variant.uint16 ((uint16) this.get_value ());
-            case "i": return new Variant.int32  ((int32) this.get_value ());
-            case "u": return new Variant.uint32 ((uint32) this.get_value ());
-            case "h": return new Variant.handle ((int32) this.get_value ());
+            case "y": return new Variant.byte   ((uchar) this.get_value_as_int ());     // TODO uchar or 
uint8?
+            case "n": return new Variant.int16  ((int16) this.get_value_as_int ());
+            case "q": return new Variant.uint16 ((uint16) this.get_value_as_int ());
+            case "i": return new Variant.int32  (this.get_value_as_int ());
+            case "u": return new Variant.uint32 ((uint32) this.get_value ());           // TODO also use 
get_value_as_int?
+            case "h": return new Variant.handle (this.get_value_as_int ());
             default: assert_not_reached ();
         }
     }
+
+    public void reload (Variant gvariant)
+    {
+        locked = 2;
+        this.set_value (get_variant_as_double (gvariant));
+        value_has_changed (false);  // set disable_revealer_for_value to false, might be useful for corner 
cases
+    }
 }
 
 private class KeyEditorChildDefault : Entry, KeyEditorChild
@@ -424,6 +385,7 @@ private class KeyEditorChildDefault : Entry, KeyEditorChild
     private string variant_type;
     private Variant variant;
     private bool is_string;
+    private bool locked = false;
 
     public KeyEditorChildDefault (string type, Variant initial_value)
     {
@@ -432,14 +394,16 @@ private class KeyEditorChildDefault : Entry, KeyEditorChild
 
         this.visible = true;
         this.hexpand = true;
+        this.secondary_icon_activatable = false;
+        this.set_icon_tooltip_text (EntryIconPosition.SECONDARY, _("This value is invalid for the key 
type."));    // TODO report bug, not displayed, neither like that nor by setting secondary_icon_tooltip_text
 
         this.is_string = type == "s" || type == "o" || type == "g";
         this.text = is_string ? initial_value.get_string () : initial_value.print (false);
 
-        this.buffer.deleted_text.connect (() => { value_has_changed (test_value ()); });
-        this.buffer.inserted_text.connect (() => { value_has_changed (test_value ()); });
+        this.buffer.deleted_text.connect (() => { if (!locked) value_has_changed (true, test_value ()); });
+        this.buffer.inserted_text.connect (() => { if (!locked) value_has_changed (true, test_value ()); });
         this.activate.connect (() => { if (test_value ()) child_activated (); });
-        value_has_changed (test_value ());
+        value_has_changed (true, test_value ());
     }
 
     private bool test_value ()
@@ -454,10 +418,21 @@ private class KeyEditorChildDefault : Entry, KeyEditorChild
             string tmp_text = is_string ? @"'$text'" : this.text;
             Variant? tmp_variant = Variant.parse (new VariantType (variant_type), tmp_text);
             variant = (!) tmp_variant;
+
+            StyleContext context = get_style_context ();
+            if (context.has_class ("error"))
+                context.remove_class ("error");
+            secondary_icon_name = null;
+
             return true;
         }
         catch (VariantParseError e)
         {
+            StyleContext context = get_style_context ();
+            if (!context.has_class ("error"))
+                context.add_class ("error");
+            secondary_icon_name = "dialog-error-symbolic";
+
             return false;
         }
     }
@@ -466,4 +441,13 @@ private class KeyEditorChildDefault : Entry, KeyEditorChild
     {
         return variant;
     }
+
+    public void reload (Variant gvariant)
+    {
+        locked = true;
+        this.text = is_string ? gvariant.get_string () : gvariant.print (false);
+        if (!test_value ())
+            assert_not_reached ();
+        locked = false;
+    }
 }
diff --git a/editor/dconf-window.vala b/editor/dconf-window.vala
index 79ec304..86c6e50 100644
--- a/editor/dconf-window.vala
+++ b/editor/dconf-window.vala
@@ -67,7 +67,7 @@ class DConfWindow : ApplicationWindow
         registry_view.init (settings.get_string ("saved-view"), settings.get_boolean ("restore-view"));  // 
TODO better?
     }
 
-    private static string stripped_path (string path)
+    public static string stripped_path (string path)
     {
         if (path.length <= 1)
             return "/";
diff --git a/editor/key-list-box-row.vala b/editor/key-list-box-row.vala
index 820da23..29524c7 100644
--- a/editor/key-list-box-row.vala
+++ b/editor/key-list-box-row.vala
@@ -176,8 +176,7 @@ private class KeyListBoxRowEditableNoSchema : KeyListBoxRow
             GLib.Action action = popover.create_buttons_list (key, true, delayed_apply_menu);
 
             popover.change_dismissed.connect (() => {
-                    hide_right_click_popover ();
-                    action.change_state (new Variant.maybe (new VariantType ("m" + key.type_string), null));
+                    destroy_popover ();
                     change_dismissed ();
                 });
             popover.value_changed.connect ((gvariant) => {
@@ -237,8 +236,7 @@ private class KeyListBoxRowEditable : KeyListBoxRow
             GLib.Action action = popover.create_buttons_list (key, true, delayed_apply_menu);
 
             popover.change_dismissed.connect (() => {
-                    hide_right_click_popover ();
-                    action.change_state (new Variant.maybe (new VariantType ("m" + real_type_string), null));
+                    destroy_popover ();
                     change_dismissed ();
                 });
             popover.value_changed.connect ((gvariant) => {
@@ -417,6 +415,13 @@ private class ContextPopover : Popover
                     Variant variant = new Variant.strv (new_flags);
                     value_changed (variant);
                 });
+
+            key.notify ["planned-value"].connect (() => {
+                    active_flags = key.planned_value != null ? key.planned_value.get_strv () : 
key.value.get_strv ();
+                    bool active = flag in active_flags;
+                    if (active != simple_action.get_state ())
+                        simple_action.set_state (new Variant.boolean (active));
+                });
         }
 
         finalize_menu ();
diff --git a/editor/modifications-revealer.vala b/editor/modifications-revealer.vala
index 7280d32..1c0d93f 100644
--- a/editor/modifications-revealer.vala
+++ b/editor/modifications-revealer.vala
@@ -27,7 +27,7 @@ class ModificationsRevealer : Revealer
     private HashTable<string, DConfKey>         dconf_keys_awaiting_hashtable = new HashTable<string, 
DConfKey>     (str_hash, str_equal);
     private HashTable<string, GSettingsKey> gsettings_keys_awaiting_hashtable = new HashTable<string, 
GSettingsKey> (str_hash, str_equal);
 
-    public signal void invalidate_popovers ();
+    public signal void reload ();
 
     /*\
     * * Public calls
@@ -64,10 +64,9 @@ class ModificationsRevealer : Revealer
     \*/
 
     [GtkCallback]
-    private void apply_delayed_settings ()
+    public void apply_delayed_settings ()
     {
         set_reveal_child (false);
-        invalidate_popovers ();
 
         /* GSettings stuff */
 
@@ -116,7 +115,6 @@ class ModificationsRevealer : Revealer
     private void dismiss_delayed_settings ()
     {
         set_reveal_child (false);
-        invalidate_popovers ();
 
         /* GSettings stuff */
 
@@ -131,6 +129,10 @@ class ModificationsRevealer : Revealer
                 key.planned_change = false;
                 return true;
             });
+
+        /* reload notably key_editor_child */
+
+        reload ();
     }
 
     /*\
diff --git a/editor/property-row.ui b/editor/property-row.ui
index 69a84e0..72b8d4c 100644
--- a/editor/property-row.ui
+++ b/editor/property-row.ui
@@ -7,6 +7,8 @@
     <child>
       <object class="GtkGrid" id="grid">
         <property name="visible">True</property>
+        <property name="halign">center</property>
+        <property name="width-request">700</property>
         <property name="orientation">horizontal</property>
         <child>
           <object class="GtkLabel" id="name_label">
diff --git a/editor/registry-view.ui b/editor/registry-view.ui
index 97927d1..df17f5d 100644
--- a/editor/registry-view.ui
+++ b/editor/registry-view.ui
@@ -18,6 +18,7 @@
         <property name="visible">True</property>
         <property name="search-mode-enabled">False</property>
         <property name="show-close-button">False</property>
+        <signal name="notify::search-mode-enabled" handler="show_browse_view"/>
         <child>
           <object class="GtkGrid">
             <property name="visible">True</property>
@@ -51,9 +52,10 @@
       </object>
     </child>
     <child>
-      <object class="GtkStack">
+      <object class="GtkStack" id="stack">
         <property name="visible">True</property>
-        <property name="visible-child">browse-view</property>
+        <property name="visible-child">browse-view</property> <!-- uses the "id" attribute -->
+        <property name="transition-type">crossfade</property>
         <property name="expand">True</property>
         <child>
           <object class="GtkScrolledWindow" id="browse-view">
@@ -103,6 +105,58 @@
               </object>
             </child>
           </object>
+          <packing>
+            <property name="name">browse-view</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkRevealer" id="no_schema_warning"> <!-- TODO report bug: hiding and showing 
infobar fails to draw it the 2nd time -->
+                <property name="visible">True</property>
+                <property name="reveal-child">False</property>
+                <child>
+                  <object class="GtkInfoBar">
+                    <property name="visible">True</property>
+                    <property name="message-type">info</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="use-markup">True</property>
+                            <property name="wrap">True</property>
+                            <property name="label" translatable="yes">&#60;b&#62;No schema 
available.&#60;/b&#62; Dconf Editor can’t find a schema associated with this key. The application that 
installed this key may have been removed, may have stop the use of this key, or may use a relocatable schema 
for defining its keys.</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkListBox" id="properties_list_box">
+                    <property name="visible">True</property>
+                    <property name="selection-mode">none</property>
+                    <style>
+                      <class name="properties-list"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="name">properties-view</property>
+          </packing>
         </child>
       </object>
     </child>
diff --git a/editor/registry-view.vala b/editor/registry-view.vala
index 4b540e5..c22b6fd 100644
--- a/editor/registry-view.vala
+++ b/editor/registry-view.vala
@@ -23,11 +23,16 @@ class RegistryView : Grid
     public string current_path { get; private set; }
     public bool show_search_bar { get; set; }
     public bool delayed_apply_menu { get; set; }
+    public bool planned_change { get { return revealer.get_reveal_child (); }}
 
     private SettingsModel model = new SettingsModel ();
     [GtkChild] private TreeView dir_tree_view;
     [GtkChild] private TreeSelection dir_tree_selection;
 
+    [GtkChild] private Revealer no_schema_warning;
+    [GtkChild] private Stack stack;
+    [GtkChild] private ListBox properties_list_box;
+
     [GtkChild] private ListBox key_list_box;
     private GLib.ListStore? key_model = null;
 
@@ -41,7 +46,7 @@ class RegistryView : Grid
 
     construct
     {
-        revealer.invalidate_popovers.connect (invalidate_popovers);
+        revealer.reload.connect (invalidate_popovers);
 
         search_entry.get_buffer ().deleted_text.connect (() => { search_next_button.set_sensitive (true); });
         search_bar.connect_entry (search_entry);
@@ -61,6 +66,12 @@ class RegistryView : Grid
         }
     }
 
+    private void update_current_path (string path)
+    {
+        current_path = path;
+        ((DConfWindow) this.get_parent ()).update_current_path ();
+    }
+
     /*\
     * * Dir TreeView
     \*/
@@ -80,14 +91,23 @@ class RegistryView : Grid
             dir = model.get_root_directory ();
 
         key_model = dir.key_model;
-        current_path = dir.full_name;
-        ((DConfWindow) this.get_parent ()).update_current_path ();
+        update_current_path (dir.full_name);
 
         key_list_box.bind_model (key_model, new_list_box_row);
     }
 
-    public bool scroll_to_path (string full_name)
+    public bool scroll_to_path (string _full_name)      // TODO for now we assume full_name is a folder; 
also, don't do all the selection work if the folder didn't change
     {
+        string full_name = _full_name.dup ();
+
+        if (!full_name.has_suffix ("/"))
+            full_name = DConfWindow.stripped_path (full_name);
+
+        update_current_path (full_name);
+
+        no_schema_warning.set_reveal_child (false);
+        stack.set_visible_child_name ("browse-view");
+
         invalidate_popovers ();
 
         if (full_name == "/")
@@ -143,18 +163,27 @@ class RegistryView : Grid
             ((KeyListBoxRow) row).set_key_value.connect ((variant) => { set_key_value (key, variant); });
             ((KeyListBoxRow) row).change_dismissed.connect (() => { revealer.dismiss_change (key); });
 
-            row.on_row_clicked.connect (() => { new_key_editor (key); });
+            row.on_row_clicked.connect (() => {
+                    if (!key.has_schema && ((DConfKey) key).is_ghost)
+                        return;
+
+                    properties_list_box  foreach ((widget) => { widget.destroy (); });
+                    populate_properties_list_box (key);
+
+                    stack.set_visible_child_name ("properties-view");
+
+                    update_current_path (key.full_name);
+
+                    no_schema_warning.set_reveal_child (!key.has_schema);
+                });
             // TODO bug: row is always visually activated after the dialog destruction if mouse is over at 
this time
         }
         row.button_press_event.connect (on_button_pressed);
         return row;
     }
 
-    private void new_key_editor (Key key)
+    private void populate_properties_list_box (Key key)
     {
-        if (!key.has_schema && ((DConfKey) key).is_ghost)
-            return;
-
         bool has_schema;
         unowned Variant [] dict_container;
         key.properties.get ("(ba{ss})", out has_schema, out dict_container);
@@ -166,78 +195,70 @@ class RegistryView : Grid
         if (!dict.lookup ("key-name",     "s", out key_name))   assert_not_reached ();
         if (!dict.lookup ("parent-path",  "s", out tmp_string)) assert_not_reached ();
 
-        KeyEditor key_editor = new KeyEditor (has_schema, key_name, tmp_string);
-
-        if (dict.lookup ("schema-id",     "s", out tmp_string)) key_editor.add_row_from_label (_("Schema"),  
    tmp_string);
-        if (dict.lookup ("summary",       "s", out tmp_string)) key_editor.add_row_from_label (_("Summary"), 
    tmp_string);
-        if (dict.lookup ("description",   "s", out tmp_string)) key_editor.add_row_from_label 
(_("Description"), tmp_string);
+        if (dict.lookup ("schema-id",     "s", out tmp_string)) add_row_from_label (_("Schema"),      
tmp_string);
+        if (dict.lookup ("summary",       "s", out tmp_string)) add_row_from_label (_("Summary"),     
tmp_string);
+        if (dict.lookup ("description",   "s", out tmp_string)) add_row_from_label (_("Description"), 
tmp_string);
         /* Translators: as in datatype (integer, boolean, string, etc.) */
-        if (dict.lookup ("type-name",     "s", out tmp_string)) key_editor.add_row_from_label (_("Type"),    
    tmp_string);
+        if (dict.lookup ("type-name",     "s", out tmp_string)) add_row_from_label (_("Type"),        
tmp_string);
         else assert_not_reached ();
-        if (dict.lookup ("minimum",       "s", out tmp_string)) key_editor.add_row_from_label (_("Minimum"), 
    tmp_string);
-        if (dict.lookup ("maximum",       "s", out tmp_string)) key_editor.add_row_from_label (_("Maximum"), 
    tmp_string);
-        if (dict.lookup ("default-value", "s", out tmp_string)) key_editor.add_row_from_label (_("Default"), 
    tmp_string);
+        if (dict.lookup ("minimum",       "s", out tmp_string)) add_row_from_label (_("Minimum"),     
tmp_string);
+        if (dict.lookup ("maximum",       "s", out tmp_string)) add_row_from_label (_("Maximum"),     
tmp_string);
+        if (dict.lookup ("default-value", "s", out tmp_string)) add_row_from_label (_("Default"),     
tmp_string);
 
         if (!dict.lookup ("type-code",    "s", out tmp_string)) assert_not_reached ();
 
-        KeyEditorChild key_editor_child = create_child (key_editor, key);
+        bool disable_revealer_for_value = false;
+        KeyEditorChild key_editor_child = create_child (key);
         if (has_schema)
         {
             Switch custom_value_switch = new Switch ();
-            custom_value_switch.width_request = 100; /* same request than for button_cancel/button_apply on 
scale 1; TODO better */
             custom_value_switch.halign = Align.END;
             custom_value_switch.hexpand = true;
             custom_value_switch.show ();
-            key_editor.add_row_from_widget (_("Use default value"), custom_value_switch, null);
+            add_row_from_widget (_("Use default value"), custom_value_switch, null);
 
             custom_value_switch.bind_property ("active", key_editor_child, "sensitive", 
BindingFlags.SYNC_CREATE | BindingFlags.INVERT_BOOLEAN);
 
+            bool disable_revealer_for_switch = false;
             GSettingsKey gkey = (GSettingsKey) key;
-            custom_value_switch.set_active (gkey.is_default);
-            custom_value_switch.notify ["active"].connect (() => {
-                    bool is_active = custom_value_switch.get_active ();
-                    key_editor.switch_is_active (is_active);
+            revealer.reload.connect (() => {
+                    disable_revealer_for_switch = true;
+                    custom_value_switch.set_active (gkey.is_default);
+                    disable_revealer_for_switch = false;    // TODO bad but needed
                 });
-
-            key_editor.response.connect ((dialog, response_id) => {
-                    if (response_id == ResponseType.APPLY)
-                    {
-                        if (!custom_value_switch.active)
-                        {
-                            Variant variant = key_editor_child.get_variant ();
-                            if (key.value != variant)
-                                key.value = variant;
-                        }
-                        else if (!gkey.is_default)
-                            gkey.set_to_default ();
-                    }
-                    dialog.destroy ();
-                });
-        }
-        else
-        {
-            key_editor.response.connect ((dialog, response_id) => {
-                    if (response_id == ResponseType.APPLY)
+            custom_value_switch.set_active (key.planned_change ? key.planned_value == null : 
gkey.is_default);
+            custom_value_switch.notify ["active"].connect (() => {
+                    if (disable_revealer_for_switch)
+                        disable_revealer_for_switch = false;
+                    else if (custom_value_switch.get_active ())
+                        revealer.add_delayed_setting (key, null);
+                    else
                     {
-                        Variant variant = key_editor_child.get_variant ();
-                        if (key.value != variant)
-                            key.value = variant;
+                        Variant tmp_variant = key.planned_change && (key.planned_value != null) ? 
key.planned_value : key.value;
+                        revealer.add_delayed_setting (key, tmp_variant);
+                        key_editor_child.reload (tmp_variant);
                     }
-                    dialog.destroy ();
                 });
         }
-        key_editor_child.value_has_changed.connect ((is_valid) => { key_editor.custom_value_is_valid = 
is_valid; });    // TODO not always useful
-        key_editor_child.child_activated.connect (() => {       // TODO "only" used for string-based and 
spin widgets
-                if (key_editor.custom_value_is_valid)
-                    key_editor.response (ResponseType.APPLY);
+        key_editor_child.value_has_changed.connect ((enable_revealer, is_valid) => {
+                if (disable_revealer_for_value)
+                    disable_revealer_for_value = false;
+                else if (enable_revealer && is_valid)
+                    revealer.add_delayed_setting (key, key_editor_child.get_variant ());
+                else if (enable_revealer && !is_valid)
+                    revealer.dismiss_change (key);
             });
-        key_editor.add_row_from_widget (_("Custom value"), key_editor_child, tmp_string);
-
-        key_editor.set_transient_for ((Window) this.get_parent ());
-        key_editor.run ();
+        key_editor_child.child_activated.connect (() => { revealer.apply_delayed_settings (); });  // TODO 
"only" used for string-based and spin widgets
+        revealer.reload.connect (() => {
+                disable_revealer_for_value = true;
+                key_editor_child.reload (key.value);
+                if (tmp_string == "<flags>")
+                    key.planned_value = key.value;
+            });
+        add_row_from_widget (_("Custom value"), key_editor_child, tmp_string);
     }
 
-    private static KeyEditorChild create_child (KeyEditor dialog, Key key)
+    private static KeyEditorChild create_child (Key key)
     {
         switch (key.type_string)
         {
@@ -246,7 +267,7 @@ class RegistryView : Grid
             case "<flags>":
                 return (KeyEditorChild) new KeyEditorChildFlags ((GSettingsKey) key);
             case "b":
-                return (KeyEditorChild) new KeyEditorChildBool (key.value.get_boolean ());
+                return (KeyEditorChild) new KeyEditorChildBool (key.planned_change && (key.planned_value != 
null) ? ((!) key.planned_value).get_boolean () : key.value.get_boolean ());
             case "y":
             case "n":
             case "q":
@@ -259,7 +280,7 @@ class RegistryView : Grid
             case "mb":
                 return (KeyEditorChild) new KeyEditorChildNullableBool (key);
             default:
-                return (KeyEditorChild) new KeyEditorChildDefault (key.type_string, key.value);
+                return (KeyEditorChild) new KeyEditorChildDefault (key.type_string, key.planned_change && 
(key.planned_value != null) ? key.planned_value : key.value);
         }
     }
 
@@ -272,7 +293,7 @@ class RegistryView : Grid
         if (event.button == Gdk.BUTTON_SECONDARY)
         {
             ClickableListBoxRow row = (ClickableListBoxRow) widget;
-            row.show_right_click_popover (delayed_apply_menu, (int) (event.x - row.get_allocated_width () / 
2.0));
+            row.show_right_click_popover (delayed_apply_menu || planned_change, (int) (event.x - 
row.get_allocated_width () / 2.0));
             rows_possibly_with_popover.append (row);
         }
 
@@ -301,12 +322,52 @@ class RegistryView : Grid
     }
 
     /*\
+    * * Properties listbox
+    \*/
+
+    private void add_row_from_label (string property_name, string property_value)
+    {
+        properties_list_box.add (new PropertyRow.from_label (property_name, property_value));
+    }
+
+    private void add_row_from_widget (string property_name, Widget widget, string? type)
+    {
+        properties_list_box.add (new PropertyRow.from_widgets (property_name, widget, type != null ? 
add_warning ((!) type) : null));
+    }
+
+    private static Widget? add_warning (string type)
+    {
+        if (type != "<flags>" && ((type != "s" && "s" in type) || (type != "g" && "g" in type)) || (type != 
"o" && "o" in type))
+        {
+            if ("m" in type)
+                /* Translators: neither the "nothing" keyword nor the "m" type should be translated; a 
"maybe type" is a type of variant that is nullable. */
+                return warning_label (_("Use the keyword “nothing” to set a maybe type (beginning with “m”) 
to its empty value. Strings, signatures and object paths should be surrounded by quotation marks."));
+            else
+                return warning_label (_("Strings, signatures and object paths should be surrounded by 
quotation marks."));
+        }
+        else if (type != "m" && type != "mb" && type != "<enum>" && "m" in type)
+            /* Translators: neither the "nothing" keyword nor the "m" type should be translated; a "maybe 
type" is a type of variant that is nullable. */
+            return warning_label (_("Use the keyword “nothing” to set a maybe type (beginning with “m”) to 
its empty value."));
+        return null;
+    }
+    private static Widget warning_label (string text)
+    {
+        Label label = new Label ("<i>" + text + "</i>");
+        label.visible = true;
+        label.use_markup = true;
+        label.max_width_chars = 59;
+        label.wrap = true;
+        label.halign = Align.START;
+        return (Widget) label;
+    }
+
+    /*\
     * * Revealer stuff
     \*/
 
     private void set_key_value (Key key, Variant? new_value)
     {
-        if (delayed_apply_menu || key.planned_change)
+        if (delayed_apply_menu || planned_change)
             revealer.add_delayed_setting (key, new_value);
         else if (new_value != null)
             key.value = (!) new_value;
@@ -358,7 +419,14 @@ class RegistryView : Grid
     * * Search box
     \*/
 
-    public void set_search_mode (bool? mode)
+    [GtkCallback]
+    private void show_browse_view ()
+    {
+        if (stack.get_visible_child_name () != "browse-view")
+            stack.set_visible_child_name ("browse-view");
+    }
+
+    public void set_search_mode (bool? mode)    // mode is never 'true'...
     {
         if (mode == null)
             search_bar.set_search_mode (!search_bar.get_search_mode ());
@@ -368,17 +436,23 @@ class RegistryView : Grid
 
     public bool handle_search_event (Gdk.EventKey event)
     {
+        if (stack.get_visible_child_name () != "browse-view")
+            return false;
+
         return search_bar.handle_event (event);
     }
 
     public bool show_row_popover ()
     {
+        if (stack.get_visible_child_name () != "browse-view")
+            return false;
+
         ListBoxRow? selected_row = (ListBoxRow) key_list_box.get_selected_row ();
         if (selected_row == null)
             return false;
 
         ClickableListBoxRow row = (ClickableListBoxRow) ((!) selected_row).get_child ();
-        row.show_right_click_popover (delayed_apply_menu);
+        row.show_right_click_popover (delayed_apply_menu || planned_change);
         rows_possibly_with_popover.append (row);
         return true;
     }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 087382e..5d986d9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,7 +10,6 @@ editor/dconf-model.vala
 editor/dconf-view.vala
 editor/dconf-window.vala
 [type: gettext/glade]editor/help-overlay.ui
-[type: gettext/glade]editor/key-editor.ui
 editor/key-list-box-row.vala
 [type: gettext/glade]editor/modifications-revealer.ui
 editor/modifications-revealer.vala



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