[dconf-editor] Make popovers work correctly in delayed mode.
- From: Arnaud Bonatti <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf-editor] Make popovers work correctly in delayed mode.
- Date: Sat, 18 Jun 2016 00:56:06 +0000 (UTC)
commit 0b8e19b4645aba279d31b1c3cdf64ea4d6b92ac5
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Sat Jun 18 02:55:46 2016 +0200
Make popovers work correctly in delayed mode.
editor/dconf-model.vala | 2 +
editor/dconf-view.vala | 4 +-
editor/dconf-window.vala | 50 ++++++++++++++--
editor/key-list-box-row.vala | 108 +++++++++++++++++++++++++----------
editor/modifications-revealer.vala | 51 ++++++++++++++++-
5 files changed, 171 insertions(+), 44 deletions(-)
---
diff --git a/editor/dconf-model.vala b/editor/dconf-model.vala
index fe11d56..53fceba 100644
--- a/editor/dconf-model.vala
+++ b/editor/dconf-model.vala
@@ -179,7 +179,9 @@ public abstract class Key : SettingObject
public string type_string { get; protected set; default = "*"; }
public Variant properties { owned get; protected set; }
+ public bool planned_change = false;
public Variant? planned_value { get; set; default = null; }
+
public abstract Variant value { owned get; set; }
public signal void value_changed ();
diff --git a/editor/dconf-view.vala b/editor/dconf-view.vala
index 157770f..17e0d6a 100644
--- a/editor/dconf-view.vala
+++ b/editor/dconf-view.vala
@@ -149,7 +149,7 @@ private class KeyEditorChildEnum : MenuButton, KeyEditorChild
this.label = variant.get_type () == VariantType.STRING ? variant.get_string () : variant.print
(false);
ContextPopover popover = new ContextPopover ();
- popover.create_buttons_list (key, false);
+ popover.create_buttons_list (key, false, false);
popover.set_relative_to (this);
popover.value_changed.connect ((gvariant) => {
variant = gvariant;
@@ -231,7 +231,7 @@ private class KeyEditorChildNullableBool : MenuButton, KeyEditorChild
this.label = Key.cool_boolean_text_value (((!) maybe_variant).get_boolean ());
ContextPopover popover = new ContextPopover ();
- popover.create_buttons_list (key, false);
+ popover.create_buttons_list (key, false, false);
popover.set_relative_to (this);
popover.value_changed.connect ((gvariant) => {
variant = gvariant;
diff --git a/editor/dconf-window.vala b/editor/dconf-window.vala
index f2f91f4..190d501 100644
--- a/editor/dconf-window.vala
+++ b/editor/dconf-window.vala
@@ -42,6 +42,8 @@ class DConfWindow : ApplicationWindow
private GLib.Settings settings = new GLib.Settings ("ca.desrt.dconf-editor.Settings");
[GtkChild] private Bookmarks bookmarks_button;
+ private GLib.ListStore rows_possibly_with_popover = new GLib.ListStore (typeof (ClickableListBoxRow));
+
[GtkChild] private ModificationsRevealer revealer;
[GtkChild] private SearchBar search_bar;
@@ -57,6 +59,9 @@ class DConfWindow : ApplicationWindow
add_action_entries (action_entries, this);
add_action (settings.create_action ("delayed-apply-menu"));
+ settings.changed["delayed-apply-menu"].connect (invalidate_popovers);
+ revealer.invalidate_popovers.connect (invalidate_popovers);
+
set_default_size (settings.get_int ("window-width"), settings.get_int ("window-height"));
if (settings.get_boolean ("window-is-fullscreen"))
fullscreen ();
@@ -193,6 +198,8 @@ class DConfWindow : ApplicationWindow
[GtkCallback]
private bool scroll_to_path (string full_name)
{
+ invalidate_popovers ();
+
if (full_name == "/")
{
dir_tree_selection.unselect_all ();
@@ -240,13 +247,17 @@ class DConfWindow : ApplicationWindow
Key key = (Key) item;
if (key.has_schema)
{
- row = new KeyListBoxRowEditable ((GSettingsKey) key);
- ((KeyListBoxRow) row).set_key_value.connect ((variant) => { set_glib_key_value
((GSettingsKey) key, variant); });
+ GSettingsKey gkey = (GSettingsKey) key;
+ row = new KeyListBoxRowEditable (gkey);
+ ((KeyListBoxRow) row).set_key_value.connect ((variant) => { set_glib_key_value (gkey,
variant); });
+ ((KeyListBoxRow) row).change_dismissed.connect (() => { revealer.dismiss_glib_change (gkey);
});
}
else
{
- row = new KeyListBoxRowEditableNoSchema ((DConfKey) key);
- ((KeyListBoxRow) row).set_key_value.connect ((variant) => { set_dconf_key_value ((DConfKey)
key, variant); });
+ DConfKey dkey = (DConfKey) key;
+ row = new KeyListBoxRowEditableNoSchema (dkey);
+ ((KeyListBoxRow) row).set_key_value.connect ((variant) => { set_dconf_key_value (dkey,
variant); });
+ ((KeyListBoxRow) row).change_dismissed.connect (() => { revealer.dismiss_dconf_change
(dkey); });
}
row.on_row_clicked.connect (() => { new_key_editor (key); });
// TODO bug: row is always visually activated after the dialog destruction if mouse is over at
this time
@@ -373,6 +384,14 @@ class DConfWindow : ApplicationWindow
ListBoxRow list_box_row = (ListBoxRow) widget.get_parent ();
key_list_box.select_row (list_box_row);
list_box_row.grab_focus ();
+
+ ClickableListBoxRow row = (ClickableListBoxRow) widget;
+ if (event.button == Gdk.BUTTON_SECONDARY)
+ {
+ row.show_right_click_popover (settings.get_boolean ("delayed-apply-menu"), (int) (event.x -
row.get_allocated_width () / 2.0));
+ rows_possibly_with_popover.append (row);
+ }
+
return false;
}
@@ -384,13 +403,26 @@ class DConfWindow : ApplicationWindow
((ClickableListBoxRow) list_box_row.get_child ()).on_row_clicked ();
}
+ private void invalidate_popovers ()
+ {
+ uint position = 0;
+ ClickableListBoxRow? row = (ClickableListBoxRow?) rows_possibly_with_popover.get_item (0);
+ while (row != null)
+ {
+ row.destroy_popover ();
+ position++;
+ row = (ClickableListBoxRow?) rows_possibly_with_popover.get_item (position);
+ }
+ rows_possibly_with_popover.remove_all ();
+ }
+
/*\
* * Revealer stuff
\*/
private void set_dconf_key_value (DConfKey key, Variant? new_value)
{
- if (settings.get_boolean ("delayed-apply-menu"))
+ if (settings.get_boolean ("delayed-apply-menu") || key.planned_change)
revealer.add_delayed_dconf_settings (key, new_value);
else if (new_value != null)
key.value = new_value;
@@ -400,7 +432,7 @@ class DConfWindow : ApplicationWindow
private void set_glib_key_value (GSettingsKey key, Variant? new_value)
{
- if (settings.get_boolean ("delayed-apply-menu"))
+ if (settings.get_boolean ("delayed-apply-menu") || key.planned_change)
revealer.add_delayed_glib_settings (key, new_value);
else if (new_value != null)
key.value = new_value;
@@ -415,11 +447,13 @@ class DConfWindow : ApplicationWindow
private void reset ()
{
reset_generic (key_model, false);
+ invalidate_popovers ();
}
private void reset_recursively ()
{
reset_generic (key_model, true);
+ invalidate_popovers ();
}
private void reset_generic (GLib.ListStore? objects, bool recursively) // TODO notification if nothing
to reset
@@ -535,7 +569,9 @@ class DConfWindow : ApplicationWindow
bookmarks_button.active = false;
if (info_button.active)
info_button.active = false;
- ((ClickableListBoxRow) ((!) selected_row).get_child ()).show_right_click_popover ();
+ ClickableListBoxRow row = (ClickableListBoxRow) ((!) selected_row).get_child ();
+ row.show_right_click_popover (settings.get_boolean ("delayed-apply-menu"));
+ rows_possibly_with_popover.append (row);
}
else if (info_button.active == false)
{
diff --git a/editor/key-list-box-row.vala b/editor/key-list-box-row.vala
index 9931349..72050a9 100644
--- a/editor/key-list-box-row.vala
+++ b/editor/key-list-box-row.vala
@@ -28,34 +28,26 @@ private abstract class ClickableListBoxRow : EventBox
\*/
private ContextPopover? nullable_popover = null;
- protected virtual bool generate_popover (ContextPopover popover) { return false; } // no popover
should be created
+ protected virtual bool generate_popover (ContextPopover popover, bool delayed_apply_menu) { return
false; } // no popover should be created
- protected void destroy_popover ()
+ public void destroy_popover ()
{
if (nullable_popover != null) // check sometimes not useful
((!) nullable_popover).destroy ();
}
- public override bool button_press_event (Gdk.EventButton event) // list_box_row selection is done
elsewhere
- {
- if (event.button == Gdk.BUTTON_SECONDARY)
- show_right_click_popover ((int) (event.x - this.get_allocated_width () / 2.0));
-
- return false;
- }
-
public void hide_right_click_popover ()
{
if (nullable_popover != null)
((!) nullable_popover).hide ();
}
- public void show_right_click_popover (int event_x = 0)
+ public void show_right_click_popover (bool delayed_apply_menu, int event_x = 0)
{
if (nullable_popover == null)
{
nullable_popover = new ContextPopover ();
- if (!generate_popover ((!) nullable_popover))
+ if (!generate_popover ((!) nullable_popover, delayed_apply_menu))
{
((!) nullable_popover).destroy (); // TODO better, again
nullable_popover = null;
@@ -95,7 +87,7 @@ private class FolderListBoxRow : ClickableListBoxRow
return full_name;
}
- protected override bool generate_popover (ContextPopover popover)
+ protected override bool generate_popover (ContextPopover popover, bool unused) // TODO better
{
popover.new_action ("open", () => { on_row_clicked (); });
popover.new_copy_action (get_text ());
@@ -112,6 +104,7 @@ private abstract class KeyListBoxRow : ClickableListBoxRow
[GtkChild] protected Label key_info_label;
public signal void set_key_value (Variant? new_value);
+ public signal void change_dismissed ();
protected static string cool_text_value (Key key) // TODO better
{
@@ -155,7 +148,7 @@ private class KeyListBoxRowEditableNoSchema : KeyListBoxRow
return key.is_ghost ? _("%s (key erased)").printf (key.full_name) : key.full_name + " " +
key.value.print (false);
}
- protected override bool generate_popover (ContextPopover popover)
+ protected override bool generate_popover (ContextPopover popover, bool delayed_apply_menu)
{
if (key.is_ghost)
{
@@ -169,13 +162,25 @@ private class KeyListBoxRowEditableNoSchema : KeyListBoxRow
if (key.type_string == "b" || key.type_string == "mb")
{
popover.new_section ();
- popover.create_buttons_list (key, false);
+ popover.create_buttons_list (key, true, delayed_apply_menu);
+ popover.change_dismissed.connect (() => {
+ destroy_popover ();
+ change_dismissed ();
+ });
popover.value_changed.connect ((gvariant) => {
destroy_popover ();
set_key_value (gvariant);
});
}
+ else if (delayed_apply_menu && key.planned_change)
+ {
+ popover.new_section ();
+ popover.new_action ("dismiss", () => {
+ destroy_popover ();
+ change_dismissed ();
+ });
+ }
return true;
}
}
@@ -206,7 +211,7 @@ private class KeyListBoxRowEditable : KeyListBoxRow
return key.descriptor + " " + key.value.print (false);
}
- protected override bool generate_popover (ContextPopover popover)
+ protected override bool generate_popover (ContextPopover popover, bool delayed_apply_menu)
{
popover.new_action ("customize", () => { on_row_clicked (); });
popover.new_copy_action (get_text ());
@@ -214,14 +219,18 @@ private class KeyListBoxRowEditable : KeyListBoxRow
if (key.type_string == "b" || key.type_string == "<enum>" || key.type_string == "mb")
{
popover.new_section ();
- popover.create_buttons_list (key, true);
+ popover.create_buttons_list (key, true, delayed_apply_menu);
+ popover.change_dismissed.connect (() => {
+ destroy_popover ();
+ change_dismissed ();
+ });
popover.value_changed.connect ((gvariant) => {
destroy_popover ();
set_key_value (gvariant);
});
}
- else if (key.type_string == "<flags>")
+ else if (!delayed_apply_menu && !key.planned_change && key.type_string == "<flags>")
{
popover.new_section ();
@@ -238,10 +247,24 @@ private class KeyListBoxRowEditable : KeyListBoxRow
set_key_value (gvariant);
});
}
+ else if (key.planned_change)
+ {
+ popover.new_section ();
+ popover.new_action ("dismiss", () => {
+ destroy_popover ();
+ change_dismissed ();
+ });
+ if (key.planned_value != null)
+ popover.new_action ("default1", () => {
+ destroy_popover ();
+ set_key_value (null);
+ });
+ }
else if (!key.is_default)
{
popover.new_section ();
popover.new_action ("default1", () => {
+ destroy_popover ();
set_key_value (null);
});
}
@@ -266,6 +289,7 @@ private class ContextPopover : Popover
// public signals
public signal void value_changed (Variant? gvariant);
+ public signal void change_dismissed ();
public ContextPopover ()
{
@@ -306,6 +330,9 @@ private class ContextPopover : Popover
current_section.append (_("Set to default"), group_dot_action);
else if (action_action == "default2")
new_multi_default_action (group_dot_action);
+ else if (action_action == "dismiss")
+ /* Translators: "dismiss change" action in the right-click menu on a key with pending changes */
+ current_section.append (_("Dismiss change"), group_dot_action);
else if (action_action == "open")
/* Translators: "open folder" action in the right-click menu on a folder */
current_section.append (_("Open"), group_dot_action);
@@ -382,7 +409,7 @@ private class ContextPopover : Popover
* * Choices
\*/
- public void create_buttons_list (Key key, bool nullable)
+ public void create_buttons_list (Key key, bool has_default_value, bool delayed_apply_menu)
{
set_group ("enum");
const string ACTION_NAME = "choice";
@@ -390,19 +417,34 @@ private class ContextPopover : Popover
VariantType original_type = key.value.get_type ();
VariantType nullable_type = new VariantType.maybe (original_type);
- string nullable_type_string = nullable_type.dup_string ();
- Variant variant = new Variant.maybe (original_type, key.has_schema && ((GSettingsKey)
key).is_default ? null : key.value);
+ VariantType nullable_nullable_type = new VariantType.maybe (nullable_type);
+ string nullable_nullable_type_string = nullable_nullable_type.dup_string ();
- current_group.add_action (new SimpleAction.stateful (ACTION_NAME, nullable_type, variant));
+ Variant value_variant = key.planned_change ? key.planned_value : key.value;
+ Variant variant = new Variant.maybe (original_type, key.has_schema && ((GSettingsKey)
key).is_default ? null : value_variant);
+ Variant nullable_variant = new Variant.maybe (nullable_type, delayed_apply_menu &&
!key.planned_change ? null : variant);
+ current_group.add_action (new SimpleAction.stateful (ACTION_NAME, nullable_nullable_type,
nullable_variant));
- if (nullable)
- new_multi_default_action (group_dot_action + "(@" + nullable_type_string + " nothing)");
+ if (has_default_value)
+ {
+ bool complete_menu = delayed_apply_menu || key.planned_change;
+
+ if (complete_menu)
+ /* Translators: "no change" option in the right-click menu on a key when on delayed mode */
+ current_section.append (_("No change"), group_dot_action + "(@" +
nullable_nullable_type_string + " nothing)");
+
+ if (key.has_schema)
+ new_multi_default_action (group_dot_action + "(@" + nullable_nullable_type_string + " just
nothing)");
+ else if (complete_menu)
+ /* Translators: "erase key" option in the right-click menu on a key without schema when on
delayed mode */
+ current_section.append (_("Erase key"), group_dot_action + "(@" +
nullable_nullable_type_string + " just nothing)");
+ }
switch (key.type_string)
{
case "b":
- current_section.append (Key.cool_boolean_text_value (true), group_dot_action + "(@mb true)");
- current_section.append (Key.cool_boolean_text_value (false), group_dot_action + "(@mb
false)");
+ current_section.append (Key.cool_boolean_text_value (true), group_dot_action + "(@mmb
true)");
+ current_section.append (Key.cool_boolean_text_value (false), group_dot_action + "(@mmb
false)");
break;
case "<enum>": // defined by the schema
Variant range = ((GSettingsKey) key).range_content;
@@ -410,17 +452,21 @@ private class ContextPopover : Popover
if (size == 0) // TODO special case also 1?
assert_not_reached ();
for (uint index = 0; index < size; index++)
- current_section.append (range.get_child_value (index).print (false), group_dot_action +
"(@ms '" + range.get_child_value (index).get_string () + "')"); // TODO use int settings.get_enum ()
+ current_section.append (range.get_child_value (index).print (false), group_dot_action +
"(@mms '" + range.get_child_value (index).get_string () + "')"); // TODO use int settings.get_enum ()
break;
case "mb":
- current_section.append (Key.cool_boolean_text_value (null), group_dot_action + "(@mmb just
nothing)");
- current_section.append (Key.cool_boolean_text_value (true), group_dot_action + "(@mmb
true)");
- current_section.append (Key.cool_boolean_text_value (false), group_dot_action + "(@mmb
false)");
+ current_section.append (Key.cool_boolean_text_value (null), group_dot_action + "(@mmmb just
just nothing)");
+ current_section.append (Key.cool_boolean_text_value (true), group_dot_action + "(@mmmb
true)");
+ current_section.append (Key.cool_boolean_text_value (false), group_dot_action + "(@mmmb
false)");
break;
}
((GLib.ActionGroup) current_group).action_state_changed [ACTION_NAME].connect ((unknown_string,
tmp_variant) => {
- value_changed (tmp_variant.get_maybe ());
+ Variant? change_variant = tmp_variant.get_maybe ();
+ if (change_variant != null)
+ value_changed (change_variant.get_maybe ());
+ else
+ change_dismissed ();
});
finalize_menu ();
diff --git a/editor/modifications-revealer.vala b/editor/modifications-revealer.vala
index 192ec1a..9a187a2 100644
--- a/editor/modifications-revealer.vala
+++ b/editor/modifications-revealer.vala
@@ -27,12 +27,15 @@ 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 calls
\*/
public void add_delayed_dconf_settings (DConfKey key, Variant? new_value)
{
+ key.planned_change = true;
key.planned_value = new_value;
dconf_keys_awaiting_hashtable.insert (key.full_name, key);
@@ -41,12 +44,31 @@ class ModificationsRevealer : Revealer
public void add_delayed_glib_settings (GSettingsKey key, Variant? new_value)
{
+ key.planned_change = true;
key.planned_value = new_value;
gsettings_keys_awaiting_hashtable.insert (key.descriptor, key);
update ();
}
+ public void dismiss_dconf_change (DConfKey key)
+ {
+ key.planned_change = false;
+ key.planned_value = null;
+ dconf_keys_awaiting_hashtable.remove (key.full_name);
+
+ update ();
+ }
+
+ public void dismiss_glib_change (GSettingsKey key)
+ {
+ key.planned_change = false;
+ key.planned_value = null;
+ gsettings_keys_awaiting_hashtable.remove (key.descriptor);
+
+ update ();
+ }
+
/*\
* * Buttons callbacks
\*/
@@ -55,11 +77,12 @@ class ModificationsRevealer : Revealer
private void apply_delayed_settings ()
{
set_reveal_child (false);
+ invalidate_popovers ();
/* GSettings stuff */
HashTable<string, GLib.Settings> delayed_settings_hashtable = new HashTable<string, GLib.Settings>
(str_hash, str_equal);
- gsettings_keys_awaiting_hashtable.foreach_remove ((full_name, key) => {
+ gsettings_keys_awaiting_hashtable.foreach_remove ((descriptor, key) => {
GLib.Settings? settings = delayed_settings_hashtable.lookup (key.schema_id);
if (settings == null)
{
@@ -72,6 +95,7 @@ class ModificationsRevealer : Revealer
((!) settings).reset (key.name);
else
((!) settings).set_value (key.name, (!) key.planned_value);
+ key.planned_change = false;
return true;
});
@@ -86,6 +110,7 @@ class ModificationsRevealer : Revealer
if (key.planned_value == null)
key.is_ghost = true;
+ key.planned_change = false;
return true;
});
@@ -101,9 +126,21 @@ class ModificationsRevealer : Revealer
private void dismiss_delayed_settings ()
{
set_reveal_child (false);
+ invalidate_popovers ();
- gsettings_keys_awaiting_hashtable.remove_all ();
- dconf_keys_awaiting_hashtable.remove_all ();
+ /* GSettings stuff */
+
+ gsettings_keys_awaiting_hashtable.foreach_remove ((descriptor, key) => {
+ key.planned_change = false;
+ return true;
+ });
+
+ /* DConf stuff */
+
+ dconf_keys_awaiting_hashtable.foreach_remove ((full_name, key) => {
+ key.planned_change = false;
+ return true;
+ });
}
/*\
@@ -111,8 +148,14 @@ class ModificationsRevealer : Revealer
\*/
private void update ()
- requires (dconf_keys_awaiting_hashtable.length != 0 || gsettings_keys_awaiting_hashtable.length != 0)
{
+ if (dconf_keys_awaiting_hashtable.length == 0 && gsettings_keys_awaiting_hashtable.length == 0)
+ {
+ set_reveal_child (false);
+ label.set_text ("");
+ return;
+ }
+
if (dconf_keys_awaiting_hashtable.length == 0)
label.set_text (_("%u gsettings operations awaiting.").printf
(gsettings_keys_awaiting_hashtable.length));
else if (gsettings_keys_awaiting_hashtable.length == 0)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]