[dconf-editor] Fusion pathbar and searchentry.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf-editor] Fusion pathbar and searchentry.
- Date: Thu, 13 Sep 2018 15:10:51 +0000 (UTC)
commit 6ae65cf86d4ca650f08612c8e0a71dda8af5a818
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Mon Sep 10 19:08:26 2018 +0200
Fusion pathbar and searchentry.
editor/browser-stack.vala | 6 ++
editor/browser-view.vala | 5 +
editor/dconf-editor.css | 80 ++++++++++++----
editor/dconf-editor.gresource.xml | 2 +
editor/dconf-editor.ui | 103 ++-------------------
editor/dconf-model.vala | 11 ++-
editor/dconf-window.vala | 189 ++++++++++++++++++++++++++------------
editor/help-overlay.ui | 41 +++++++--
editor/meson.build | 4 +
editor/pathentry.ui | 55 +++++++++++
editor/pathentry.vala | 119 ++++++++++++++++++++++++
editor/pathwidget.ui | 69 ++++++++++++++
editor/pathwidget.vala | 141 ++++++++++++++++++++++++++++
editor/registry-list.vala | 16 +++-
editor/registry-search.vala | 156 ++++++++++++++++++++++++-------
editor/setting-object.vala | 10 +-
16 files changed, 789 insertions(+), 218 deletions(-)
---
diff --git a/editor/browser-stack.vala b/editor/browser-stack.vala
index c6a2a1d..f353ef0 100644
--- a/editor/browser-stack.vala
+++ b/editor/browser-stack.vala
@@ -196,6 +196,12 @@ private class BrowserStack : Grid
* * Keyboard calls
\*/
+ internal void row_grab_focus ()
+ {
+ if (current_view != ViewType.OBJECT)
+ ((RegistryList) stack.get_visible_child ()).row_grab_focus ();
+ }
+
internal bool return_pressed ()
requires (current_view == ViewType.SEARCH)
{
diff --git a/editor/browser-view.vala b/editor/browser-view.vala
index f2671ac..5ee7b44 100644
--- a/editor/browser-view.vala
+++ b/editor/browser-view.vala
@@ -278,6 +278,11 @@ private class BrowserView : Grid
* * Proxy calls
\*/
+ internal void row_grab_focus ()
+ {
+ current_child.row_grab_focus ();
+ }
+
internal ViewType current_view { get { return current_child.current_view; }}
// popovers invalidation and toggles hiding/revealing
diff --git a/editor/dconf-editor.css b/editor/dconf-editor.css
index bff7b9e..d673cf2 100644
--- a/editor/dconf-editor.css
+++ b/editor/dconf-editor.css
@@ -56,6 +56,12 @@
* * lists rows height and icon
\*/
+/* hack: fix next lines misplacement when the first line is a header */
+
+list.keys-list > grid.big-popover.dim-label.vertical + grid.vertical {
+ margin-top:-1px;
+}
+
/* row height */
.keys-list > row { transition:min-height 0.3s,
margin-left 0.3s,
margin-right 0.3s,
@@ -165,21 +171,56 @@
* * pathbar
\*/
-.root-button > label {
+/* evolutions on large window */
+ .pathbar {
+ /* nautilus/src/resources/css/Adwaita.css:71 .path-bar-box uses 200ms */
+ transition: border-color 0.3s,
+ background-color 0.3s;
+ border-color:transparent;
+
+ border-width:1px;
+ border-style:solid;
+ border-radius:3px;
+
+ padding:0;
+ margin:6px 0;
+}
+
+.large-window .pathbar {
+ /* like in nautilus/src/resources/css/Adwaita.css:75
+ .path-bar-box.width-maximized */
+ border-color:@borders;
+}
+
+.large-window .pathbar:not(:backdrop) {
+ /* like in nautilus/src/resources/css/Adwaita.css:79
+ .path-bar-box.width-maximized:not(:backdrop) */
+ background-color:@theme_bg_color;
+}
+
+/* root button */
+ .pathbar:dir(ltr) > button.root-button { padding-left :0; margin-left :0; }
+ .pathbar:dir(rtl) > button.root-button { padding-right:0; margin-right:0; }
+
+ .pathbar > button.root-button > label {
+ padding-left:3px;
+ transition:border-width 0 ease, padding 0 ease;
+ background-position:50% center;
+ margin-left:0;
+ margin-right:0;
background-image:-gtk-icontheme("ca.desrt.dconf-editor-symbolic");
- background-position:center;
background-size:1.1rem;
background-repeat:no-repeat;
min-width:1.1rem;
}
-
-.pathbar {
- margin:0 4px;
+.large-window .pathbar > button.root-button > label {
+ padding-left:5px;
+ border-left-width:0;
+ background-position:60% center;
}
+/* pathbar internals */
.pathbar > label {
- padding-left:0.1em;
- padding-right:0.1em;
color:alpha(currentColor,0.8);
}
.pathbar > label:backdrop {
@@ -187,12 +228,12 @@
}
.pathbar > button {
- padding-left:0.1em;
- padding-right:0.1em;
- margin-left:0.1em;
- margin-right:0.1em;
+ padding:0 0.1em;
+ margin:0 0.1em;
+
+ outline-offset:-4px;
- outline-offset:0;
+ border-radius:0;
border:none;
border-color:transparent;
@@ -204,14 +245,21 @@
/* underline selected label */
.pathbar > button > .item {
- border-width:2px 0px;
+ border-width:3px 2px;
+ border-radius:0;
+ padding:2px 4px;
border-style:solid;
border-color:transparent;
transition:border-bottom-color 0.3s;
}
+.small-window .pathbar > button > .item {
+ transition:padding 0.3s; /* here because the class is applied on startup */
+ padding:2px 1px;
+}
+
.pathbar > button:hover > .item {
- border-bottom-color:alpha(currentColor,0.5);
+ border-bottom-color:@borders;
}
.pathbar > button.active > .item,
@@ -259,8 +307,8 @@
.delayed-settings-popover list > row > grid > label,
.delayed-settings-popover list > row > grid > grid > label,
.modifications-revealer button,
-.titlebar > box.pathbar > button,
-.titlebar > box.pathbar > label {
+.titlebar > box > stack > box.pathbar > button,
+.titlebar > box > stack > box.pathbar > label {
transition:all 0 ease;
}
diff --git a/editor/dconf-editor.gresource.xml b/editor/dconf-editor.gresource.xml
index d6db7d0..6ea530c 100644
--- a/editor/dconf-editor.gresource.xml
+++ b/editor/dconf-editor.gresource.xml
@@ -14,6 +14,8 @@
<file preprocess="xml-stripblanks">modifications-revealer.ui</file>
<file preprocess="xml-stripblanks">pathbar.ui</file>
<file preprocess="xml-stripblanks">pathbar-item.ui</file>
+ <file preprocess="xml-stripblanks">pathentry.ui</file>
+ <file preprocess="xml-stripblanks">pathwidget.ui</file>
<file preprocess="xml-stripblanks">property-row.ui</file>
<file preprocess="xml-stripblanks">registry-info.ui</file>
<file preprocess="xml-stripblanks">registry-placeholder.ui</file>
diff --git a/editor/dconf-editor.ui b/editor/dconf-editor.ui
index b128e20..ffa31ff 100644
--- a/editor/dconf-editor.ui
+++ b/editor/dconf-editor.ui
@@ -24,7 +24,7 @@
<property name="visible">True</property>
<property name="valign">center</property>
<property name="focus-on-click">False</property>
- <property name="sensitive" bind-source="search-toggle" bind-property="active"
bind-flags="sync-create|invert-boolean"/>
+ <property name="sensitive" bind-source="path_widget" bind-property="search-mode-enabled"
bind-flags="sync-create|invert-boolean"/>
<accelerator key="F10" signal="clicked"/> <!-- TODO report bug: property binding has to be
defined before accelerator -->
<style>
<class name="image-button"/>
@@ -47,41 +47,13 @@
<property name="pack-type">end</property>
</packing>
</child>
- <child>
- <object class="GtkToggleButton" id="search-toggle">
- <property name="visible">True</property>
- <property name="valign">center</property>
- <property name="active" bind-source="search_bar" bind-property="search-mode-enabled"
bind-flags="bidirectional">False</property>
- <property name="focus-on-click">False</property>
- <!-- <accelerator key="F" signal="toggled" modifiers="GDK_CONTROL_MASK"/> TODO -->
- <style>
- <class name="image-button"/>
- </style>
- <child internal-child="accessible">
- <object class="AtkObject">
- <property name="AtkObject::accessible-name" translatable="yes">Search</property>
- <property name="AtkObject::accessible-description" translatable="yes">Search keys</property>
- </object>
- </child>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">edit-find-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
- </child>
<child>
<object class="Bookmarks" id="bookmarks_button">
<property name="visible">True</property>
<property name="valign">center</property>
<property name="focus-on-click">False</property>
<property name="schema-path">/ca/desrt/dconf-editor/</property>
- <property name="sensitive" bind-source="search-toggle" bind-property="active"
bind-flags="sync-create|invert-boolean"/>
+ <property name="sensitive" bind-source="path_widget" bind-property="search-mode-enabled"
bind-flags="sync-create|invert-boolean"/>
<!-- <accelerator key="B" signal="activate" modifiers="GDK_CONTROL_MASK"/> TODO -->
<style>
<class name="image-button"/> <!-- TODO https://bugzilla.gnome.org/show_bug.cgi?id=756731 -->
@@ -92,10 +64,11 @@
</packing>
</child>
<child type="title">
- <object class="PathBar" id="pathbar">
+ <object class="PathWidget" id="path_widget">
<property name="visible">True</property>
- <property name="hexpand">True</property>
- <property name="valign">center</property>
+ <property name="hexpand">False</property>
+ <signal name="search-changed" handler="search_changed_cb"/>
+ <signal name="search-stopped" handler="search_stopped_cb"/>
</object>
<packing>
<property name="pack-type">start</property>
@@ -110,70 +83,6 @@
<object class="GtkGrid">
<property name="visible">True</property>
<property name="orientation">vertical</property>
- <child>
- <object class="GtkRevealer">
- <property name="visible">True</property>
- <property name="reveal-child" bind-source="search_bar" bind-property="search-mode-enabled"
bind-flags="bidirectional">False</property>
- <child>
- <object class="GtkSearchBar" id="search_bar">
- <property name="visible">True</property>
- <property name="search-mode-enabled">False</property>
- <property name="show-close-button">False</property>
- <child>
- <object class="GtkBox"> <!-- https://bugzilla.gnome.org/show_bug.cgi?id=769876 -->
- <property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <style>
- <class name="linked"/>
- </style>
- <child>
- <object class="GtkSearchEntry" id="search_entry">
- <property name="visible">True</property>
- <property name="width-request">350</property>
- <signal name="search-changed" handler="search_changed"/>
- <signal name="stop-search" handler="search_cancelled"/>
- </object>
- </child>
- <!-- child>
- <object class="GtkButton" id="search_options_button">
- <property name="visible">False</property>
- <property name="sensitive" bind-source="search_bar"
bind-property="search-mode-enabled"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">pan-down-symbolic</property>
- </object>
- </child>
- </object>
- </child -->
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <property name="action-name">ui.reload-search</property>
- <style>
- <class name="image-button"/>
- <class name="suggested-action"/>
- </style>
- <child internal-child="accessible">
- <object class="AtkObject">
- <property name="AtkObject::accessible-name"
translatable="yes">Refresh</property>
- <property name="AtkObject::accessible-description"
translatable="yes">Refresh search results</property>
- </object>
- </child>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">view-refresh-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
<child>
<object class="BrowserView" id="browser_view">
<property name="visible">True</property>
diff --git a/editor/dconf-model.vala b/editor/dconf-model.vala
index 3a805a5..34dd423 100644
--- a/editor/dconf-model.vala
+++ b/editor/dconf-model.vala
@@ -195,7 +195,7 @@ private abstract class SettingsModelCore : Object
return builder.end ();
}
- protected bool _get_object (string path, out uint16 context_id, out string name)
+ protected bool _get_object (string path, out uint16 context_id, out string name, bool watch)
{
SettingObject? object;
if (ModelUtils.is_key_path (path))
@@ -210,7 +210,7 @@ private abstract class SettingsModelCore : Object
return false;
}
- if ((!) object is Key)
+ if (watch && (!) object is Key)
add_watched_key ((Key) (!) object);
context_id = get_context_id_from_object ((!) object);
@@ -631,7 +631,8 @@ private abstract class SettingsModelCore : Object
((DConfKey) key).disconnect_client (client);
else assert_not_reached ();
- key.disconnect (key.key_value_changed_handler);
+ if (key.key_value_changed_handler != 0) // FIXME happens since editable paths 3/3
+ key.disconnect (key.key_value_changed_handler);
key.key_value_changed_handler = 0;
position++;
@@ -1015,9 +1016,9 @@ private class SettingsModel : SettingsModelCore
copy_action = true;
}
- internal bool get_object (string path, out uint16 context_id, out string name)
+ internal bool get_object (string path, out uint16 context_id, out string name, bool watch = true)
{
- return _get_object (path, out context_id, out name);
+ return _get_object (path, out context_id, out name, watch);
}
internal string get_fallback_path (string path)
diff --git a/editor/dconf-window.vala b/editor/dconf-window.vala
index ea0e764..7e3fe9d 100644
--- a/editor/dconf-window.vala
+++ b/editor/dconf-window.vala
@@ -57,9 +57,7 @@ private class DConfWindow : ApplicationWindow
[GtkChild] private Bookmarks bookmarks_button;
[GtkChild] private MenuButton info_button;
- [GtkChild] private PathBar pathbar;
- [GtkChild] private SearchBar search_bar;
- [GtkChild] private SearchEntry search_entry;
+ [GtkChild] private PathWidget path_widget;
[GtkChild] private BrowserView browser_view;
[GtkChild] private ModificationsRevealer revealer;
@@ -87,16 +85,12 @@ private class DConfWindow : ApplicationWindow
if (!disable_warning && settings.get_boolean ("show-warning"))
show.connect (show_initial_warning);
- // maximize before setting default size: only one call to on_size_allocate() so no change of the
large-window CSS class at start
if (settings.get_boolean ("window-is-maximized"))
maximize ();
set_default_size (settings.get_int ("window-width"), settings.get_int ("window-height"));
set_css_styles ();
- search_bar.connect_entry (search_entry);
- search_bar.notify ["search-mode-enabled"].connect (search_changed);
-
settings.bind ("mouse-use-extra-buttons", this, "mouse-extra-buttons",
SettingsBindFlags.GET|SettingsBindFlags.NO_SENSITIVITY);
settings.bind ("mouse-back-button", this, "mouse-back-button",
SettingsBindFlags.GET|SettingsBindFlags.NO_SENSITIVITY);
settings.bind ("mouse-forward-button", this, "mouse-forward-button",
SettingsBindFlags.GET|SettingsBindFlags.NO_SENSITIVITY);
@@ -223,7 +217,7 @@ private class DConfWindow : ApplicationWindow
else if (browser_view.check_reload (current_type, current_path, !internal_changes)) // handle
infobars in needed
reload_view ();
- pathbar.update_ghosts (((SettingsModel) _model).get_fallback_path (pathbar.complete_path),
search_bar.search_mode_enabled);
+ path_widget.update_ghosts (((SettingsModel) _model).get_fallback_path (path_widget.complete_path));
}
private void propagate_gkey_value_push (string full_name, uint16 context, Variant key_value, bool
is_key_default)
{
@@ -336,9 +330,20 @@ private class DConfWindow : ApplicationWindow
StyleContext context = get_style_context ();
if (allocation.width > MAX_ROW_WIDTH + 42)
+ {
+ context.remove_class ("small-window");
context.add_class ("large-window");
+ }
+ else if (allocation.width < 787)
+ {
+ context.remove_class ("large-window");
+ context.add_class ("small-window");
+ }
else
+ {
context.remove_class ("large-window");
+ context.remove_class ("small-window");
+ }
/* save size */
@@ -424,6 +429,8 @@ private class DConfWindow : ApplicationWindow
{ "reload-object", reload_object },
{ "reload-search", reload_search },
+ { "toggle-search", toggle_search, "b" },
+
{ "reset-recursive", reset_recursively, "s" },
{ "reset-visible", reset_visible, "s" },
@@ -505,6 +512,16 @@ private class DConfWindow : ApplicationWindow
request_search (true);
}
+ private void toggle_search (SimpleAction action, Variant? path_variant)
+ requires (path_variant != null)
+ {
+ bool search_request = ((!) path_variant).get_boolean ();
+ if (search_request && !path_widget.search_mode_enabled)
+ request_search (true, PathEntry.SearchMode.EDIT_PATH_SELECT_ALL);
+ else if (!search_request && path_widget.search_mode_enabled)
+ stop_search ();
+ }
+
private void reset_recursively (SimpleAction action, Variant? path_variant)
requires (path_variant != null)
{
@@ -560,7 +577,7 @@ private class DConfWindow : ApplicationWindow
{
browser_view.discard_row_popover ();
- if (search_bar.search_mode_enabled)
+ if (path_widget.search_mode_enabled)
{
model.copy_action_called ();
string selected_row_text = browser_view.get_copy_path_text () ?? saved_view;
@@ -594,11 +611,12 @@ private class DConfWindow : ApplicationWindow
update_current_path (ViewType.FOLDER, fallback_path);
if (selected_or_empty == "")
- browser_view.select_row (pathbar.get_selected_child (fallback_path));
+ browser_view.select_row (path_widget.get_selected_child (fallback_path));
else
browser_view.select_row (selected_or_empty);
- search_bar.search_mode_enabled = false; // do last to avoid flickering RegistryView before
PropertiesView when selecting a search result
+ stop_search ();
+ // path_widget.search_mode_enabled = false; // do last to avoid flickering RegistryView before
PropertiesView when selecting a search result
}
private static GLib.ListStore create_key_model (string base_path, Variant? children)
{
@@ -633,7 +651,7 @@ private class DConfWindow : ApplicationWindow
cannot_find_folder (full_name);
}
request_folder (ModelUtils.get_parent_path (full_name), full_name, false);
- pathbar.update_ghosts (model.get_fallback_path (pathbar.complete_path), false);
+ path_widget.update_ghosts (model.get_fallback_path (path_widget.complete_path));
}
else
{
@@ -643,10 +661,11 @@ private class DConfWindow : ApplicationWindow
update_current_path (ViewType.OBJECT, strdup (full_name));
}
- search_bar.search_mode_enabled = false; // do last to avoid flickering RegistryView before
PropertiesView when selecting a search result
+ stop_search ();
+ // path_widget.search_mode_enabled = false; // do last to avoid flickering RegistryView before
PropertiesView when selecting a search result
}
- private void request_search (bool reload)
+ private void request_search (bool reload, PathEntry.SearchMode mode = PathEntry.SearchMode.UNCLEAR)
{
string selected_row = browser_view.get_selected_row_name ();
if (reload)
@@ -655,10 +674,12 @@ private class DConfWindow : ApplicationWindow
browser_view.set_search_parameters (saved_view, bookmarks_button.get_bookmarks ());
reload_search_next = false;
}
- update_current_path (ViewType.SEARCH, search_entry.text);
+ if (mode != PathEntry.SearchMode.UNCLEAR)
+ path_widget.prepare_search (mode);
+ update_current_path (ViewType.SEARCH, path_widget.text);
browser_view.select_row (selected_row);
- if (!search_entry.has_focus)
- search_entry.grab_focus_without_selecting ();
+ if (!path_widget.entry_has_focus)
+ path_widget.entry_grab_focus_without_selecting ();
}
private void reload_view ()
@@ -692,13 +713,13 @@ private class DConfWindow : ApplicationWindow
browser_view.set_path (type, path);
bookmarks_button.set_path (type, path);
- pathbar.set_path (type, path);
+ path_widget.set_path (type, path);
invalidate_popovers_without_reload ();
}
private void update_hamburger_menu ()
{
- if (search_bar.search_mode_enabled)
+ if (path_widget.search_mode_enabled)
return;
GLib.Menu section;
@@ -754,24 +775,16 @@ private class DConfWindow : ApplicationWindow
\*/
[GtkCallback]
- private void search_changed ()
+ private void search_changed_cb ()
{
- if (search_bar.search_mode_enabled)
- request_search (reload_search_next);
- else
- hide_search_view ();
+ request_search (reload_search_next);
}
[GtkCallback]
- private void search_cancelled ()
+ private void search_stopped_cb ()
{
- if (!search_bar.search_mode_enabled)
- return;
- hide_search_view ();
- }
+ browser_view.row_grab_focus ();
- private void hide_search_view ()
- {
reload_search_action.set_enabled (false);
if (saved_type == ViewType.FOLDER)
request_folder (saved_view, saved_selection);
@@ -780,6 +793,12 @@ private class DConfWindow : ApplicationWindow
reload_search_next = true;
}
+ private void stop_search ()
+ {
+ if (path_widget.search_mode_enabled)
+ search_stopped_cb ();
+ }
+
/*\
* * Global callbacks
\*/
@@ -812,14 +831,11 @@ private class DConfWindow : ApplicationWindow
[GtkCallback]
private bool on_key_press_event (Widget widget, Gdk.EventKey event) // TODO better?
{
- string name = (!) (Gdk.keyval_name (event.keyval) ?? "");
+ uint keyval = event.keyval;
+ string name = (!) (Gdk.keyval_name (keyval) ?? "");
Widget? focus = get_focus ();
bool focus_is_text_widget = focus != null && (((!) focus is Entry) || ((!) focus is TextView));
- if (!focus_is_text_widget)
- if (name != "F10") // else <Shift>F10 toggles the search_entry popup; see if a976aa9740 fixes
that in Gtk+ 4
- if (search_bar.handle_event (event))
- return true;
if ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0)
{
@@ -866,19 +882,32 @@ private class DConfWindow : ApplicationWindow
return true;
case "f":
- if (bookmarks_button.active)
+ if (bookmarks_button.active) // should never happen if path_widget.search_mode_enabled
bookmarks_button.active = false;
- if (info_button.active)
+ if (info_button.active) // should never happen if path_widget.search_mode_enabled
info_button.active = false;
- browser_view.discard_row_popover ();
- if (!search_bar.search_mode_enabled)
- search_bar.search_mode_enabled = true;
- else if (!search_entry.has_focus)
- search_entry.grab_focus ();
+ browser_view.discard_row_popover (); // could happen if path_widget.search_mode_enabled
+ if (!path_widget.search_mode_enabled)
+ request_search (true, PathEntry.SearchMode.SEARCH);
+ else if (!path_widget.entry_has_focus)
+ path_widget.entry_grab_focus ();
else
- search_bar.search_mode_enabled = false;
+ stop_search ();
return true;
+ case "g": // usual shortcut for "next-match" in a SearchEntry; see also "Down"
+ if (bookmarks_button.active == false
+ && info_button.active == false
+ && !revealer.get_modifications_list_state ())
+ return browser_view.down_pressed ();
+ return false;
+ case "G": // usual shortcut for "previous-match" in a SearchEntry; see also "Up"
+ if (bookmarks_button.active == false
+ && info_button.active == false
+ && !revealer.get_modifications_list_state ())
+ return browser_view.up_pressed ();
+ return false;
+
case "i":
if (revealer.reveal_child)
{
@@ -887,6 +916,17 @@ private class DConfWindow : ApplicationWindow
}
return false;
+ case "l":
+ if (path_widget.search_mode_enabled)
+ return false;
+ request_search (true, PathEntry.SearchMode.EDIT_PATH_MOVE_END);
+ return true;
+ case "L":
+ if (path_widget.search_mode_enabled)
+ return false;
+ request_search (true, PathEntry.SearchMode.EDIT_PATH_SELECT_LAST_WORD);
+ return true;
+
case "F1":
browser_view.discard_row_popover ();
if ((event.state & Gdk.ModifierType.SHIFT_MASK) == 0)
@@ -928,7 +968,7 @@ private class DConfWindow : ApplicationWindow
}
}
- if (((event.state & Gdk.ModifierType.MOD1_MASK) != 0))
+ if ((event.state & Gdk.ModifierType.MOD1_MASK) != 0)
{
if (name == "Up")
{
@@ -951,24 +991,37 @@ private class DConfWindow : ApplicationWindow
return false;
}
- if (name == "Up"
+ if (name == "Up" // see also <ctrl>G
&& bookmarks_button.active == false
&& info_button.active == false
&& !revealer.get_modifications_list_state ())
return browser_view.up_pressed ();
- if (name == "Down"
+ if (name == "Down" // see also <ctrl>g
&& bookmarks_button.active == false
&& info_button.active == false
&& !revealer.get_modifications_list_state ())
return browser_view.down_pressed ();
- if ((name == "Return" || name == "KP_Enter")
- && browser_view.current_view == ViewType.SEARCH
- && search_entry.has_focus
- && browser_view.return_pressed ())
+ if (name == "Return" || name == "KP_Enter")
{
- search_bar.set_search_mode (false);
- return true;
+ if (browser_view.current_view == ViewType.SEARCH
+ && path_widget.entry_has_focus
+ && browser_view.return_pressed ())
+ {
+ stop_search ();
+ return true;
+ }
+ return false;
+ }
+
+ if (name == "Escape")
+ {
+ if (path_widget.search_mode_enabled)
+ {
+ stop_search ();
+ return true;
+ }
+ return false;
}
if (name == "Menu")
@@ -997,12 +1050,34 @@ private class DConfWindow : ApplicationWindow
if (bookmarks_button.active || info_button.active)
return false;
- return false; // browser_view.handle_search_event (event);
+ if (!path_widget.search_mode_enabled &&
+ // see gtk_search_entry_is_keynav() in gtk+/gtk/gtksearchentry.c:388
+ (keyval == Gdk.Key.Tab || keyval == Gdk.Key.KP_Tab ||
+ keyval == Gdk.Key.Up || keyval == Gdk.Key.KP_Up ||
+ keyval == Gdk.Key.Down || keyval == Gdk.Key.KP_Down ||
+ keyval == Gdk.Key.Left || keyval == Gdk.Key.KP_Left ||
+ keyval == Gdk.Key.Right || keyval == Gdk.Key.KP_Right ||
+ keyval == Gdk.Key.Home || keyval == Gdk.Key.KP_Home ||
+ keyval == Gdk.Key.End || keyval == Gdk.Key.KP_End ||
+ keyval == Gdk.Key.Page_Up || keyval == Gdk.Key.KP_Page_Up ||
+ keyval == Gdk.Key.Page_Down || keyval == Gdk.Key.KP_Page_Down ||
+ ((event.state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)) != 0) ||
+ name == "space" || name == "KP_Space"))
+ return false;
+
+ if ((!focus_is_text_widget)
+ && (event.is_modifier == 0)
+ && (event.length != 0)
+// && (name != "F10") // else <Shift>F10 toggles the search_entry popup; see if a976aa9740 fixes
that in Gtk+ 4
+ && (path_widget.handle_event (event)))
+ return true;
+
+ return false;
}
private void go_backward (bool shift)
{
- if (search_bar.search_mode_enabled)
+ if (path_widget.search_mode_enabled)
return;
browser_view.discard_row_popover ();
@@ -1015,10 +1090,10 @@ private class DConfWindow : ApplicationWindow
}
private void go_forward (bool shift)
{
- if (search_bar.search_mode_enabled)
+ if (path_widget.search_mode_enabled)
return;
- string complete_path = pathbar.complete_path;
+ string complete_path = path_widget.complete_path;
browser_view.discard_row_popover ();
if (current_path == complete_path) // TODO something?
diff --git a/editor/help-overlay.ui b/editor/help-overlay.ui
index 3f81f0b..f0e8476 100644
--- a/editor/help-overlay.ui
+++ b/editor/help-overlay.ui
@@ -30,13 +30,6 @@
<property name="accelerator"><Primary><Shift>d</property>
</object>
</child>
- <child>
- <object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
- <property name="title" translatable="yes" context="shortcut window">Search bar</property>
- <property name="accelerator"><Primary>f</property>
- </object>
- </child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
@@ -174,6 +167,40 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkShortcutsGroup">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes" context="shortcut window">Search options</property>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes" context="shortcut window">Toggle search</property>
+ <property name="accelerator"><Primary>f</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes" context="shortcut window">Edit path</property>
+ <property name="accelerator"><Primary>l</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes" context="shortcut window">Edit parent
path</property>
+ <property name="accelerator"><Primary><Shift>l</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes" context="shortcut window">Browse keys
tree</property>
+ <property name="accelerator">Escape</property>
+ </object>
+ </child>
+ </object>
+ </child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">True</property>
diff --git a/editor/meson.build b/editor/meson.build
index 616853e..aef074f 100644
--- a/editor/meson.build
+++ b/editor/meson.build
@@ -80,6 +80,8 @@ sources = files(
'modifications-handler.vala',
'modifications-revealer.vala',
'pathbar.vala',
+ 'pathentry.vala',
+ 'pathwidget.vala',
'registry-info.vala',
'registry-list.vala',
'registry-placeholder.vala',
@@ -105,6 +107,8 @@ resource_data = files(
'modifications-revealer.ui',
'pathbar-item.ui',
'pathbar.ui',
+ 'pathentry.ui',
+ 'pathwidget.ui',
'property-row.ui',
'registry-info.ui',
'registry-placeholder.ui',
diff --git a/editor/pathentry.ui b/editor/pathentry.ui
new file mode 100644
index 0000000..2992702
--- /dev/null
+++ b/editor/pathentry.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="PathEntry" parent="GtkBox"> <!-- https://bugzilla.gnome.org/show_bug.cgi?id=769876 -->
+ <property name="orientation">horizontal</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <signal name="search-changed" handler="search_changed_cb"/>
+ <signal name="stop-search" handler="search_stopped_cb"/>
+ <!-- "next-match" (<ctrl>g) and "previous-match" (<ctrl>G) are handled in dconf-window.vala -->
+ </object>
+ </child>
+ <!-- child>
+ <object class="GtkButton" id="search_options_button">
+ <property name="visible">False</property>
+ <property name="sensitive" bind-source="search_bar" bind-property="search-mode-enabled"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">pan-down-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child -->
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="action-name">ui.reload-search</property>
+ <style>
+ <class name="image-button"/>
+ <class name="suggested-action"/>
+ </style>
+ <child internal-child="accessible">
+ <object class="AtkObject">
+ <property name="AtkObject::accessible-name" translatable="yes">Refresh</property>
+ <property name="AtkObject::accessible-description" translatable="yes">Refresh search
results</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">view-refresh-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/editor/pathentry.vala b/editor/pathentry.vala
new file mode 100644
index 0000000..9b19366
--- /dev/null
+++ b/editor/pathentry.vala
@@ -0,0 +1,119 @@
+/*
+ This file is part of Dconf Editor
+
+ Dconf Editor is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Dconf Editor is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Dconf Editor. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using Gtk;
+
+[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/pathentry.ui")]
+private class PathEntry : Box
+{
+ [GtkChild] SearchEntry search_entry;
+
+ private string current_path = "";
+
+ internal string text { get { return search_entry.text; }}
+ internal bool entry_has_focus { get { return search_entry.has_focus; }}
+
+ internal enum SearchMode {
+ UNCLEAR,
+ EDIT_PATH_MOVE_END,
+ EDIT_PATH_SELECT_ALL,
+ EDIT_PATH_SELECT_LAST_WORD,
+ SEARCH
+ }
+
+ internal signal void search_changed ();
+ internal signal void search_stopped ();
+
+ internal void entry_grab_focus_without_selecting ()
+ {
+ if (search_entry.text_length != 0)
+ {
+ if (search_entry.cursor_position == search_entry.text_length)
+ search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, -1, false);
+ search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, 1, false);
+ }
+ search_entry.grab_focus_without_selecting ();
+ }
+ internal void entry_grab_focus ()
+ {
+ search_entry.grab_focus ();
+ }
+ internal bool handle_event (Gdk.EventKey event)
+ {
+ return search_entry.handle_event (event);
+ }
+
+ internal void set_path (ViewType type, string path)
+ {
+ current_path = path;
+// if (type == ViewType.SEARCH)
+ }
+
+ internal void prepare (SearchMode mode)
+ {
+ switch (mode)
+ {
+ case SearchMode.EDIT_PATH_MOVE_END:
+ search_entry.text = current_path;
+ entry_grab_focus_without_selecting ();
+ return;
+
+ case SearchMode.EDIT_PATH_SELECT_ALL:
+ search_entry.text = current_path;
+ search_entry.grab_focus ();
+ return;
+
+ case SearchMode.EDIT_PATH_SELECT_LAST_WORD:
+ search_entry.text = current_path;
+ if (search_entry.text_length == 1) // root
+ {
+ search_entry.grab_focus ();
+ return;
+ }
+ if (search_entry.text_length != 0)
+ {
+ if (search_entry.cursor_position == search_entry.text_length)
+ search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, -1, false);
+ search_entry.move_cursor (MovementStep.VISUAL_POSITIONS, ModelUtils.get_parent_path
(current_path).length, false);
+ search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, 1, true);
+ }
+ search_entry.grab_focus_without_selecting ();
+ return;
+
+ case SearchMode.SEARCH:
+ search_entry.text = "";
+ search_entry.grab_focus ();
+ return;
+
+ case SearchMode.UNCLEAR:
+ default:
+ assert_not_reached ();
+ }
+ }
+
+ [GtkCallback]
+ private void search_changed_cb ()
+ {
+ search_changed ();
+ }
+
+ [GtkCallback]
+ private void search_stopped_cb ()
+ {
+ search_stopped ();
+ }
+}
diff --git a/editor/pathwidget.ui b/editor/pathwidget.ui
new file mode 100644
index 0000000..65d1400
--- /dev/null
+++ b/editor/pathwidget.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="PathWidget" parent="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkStack" id="pathbar_stack">
+ <property name="visible">True</property>
+ <property name="valign">center</property>
+ <property name="visible-child">pathbar</property> <!-- uses the "id" attribute -->
+ <child>
+ <object class="PathEntry" id="searchentry">
+ <property name="visible">True</property>
+ <signal name="search-changed" handler="search_changed_cb"/>
+ <signal name="search-stopped" handler="search_stopped_cb"/>
+ </object>
+ <packing>
+ <property name="icon-name">document-edit-symbolic</property> <!-- TODO document-edit-symbolic ?
-->
+ <property name="title" translatable="yes">Edit path</property>
+ <property name="name">entry</property>
+ </packing>
+ </child>
+ <child>
+ <object class="PathBar" id="pathbar">
+ <property name="visible">True</property>
+ <property name="valign">center</property>
+ </object>
+ <packing>
+ <property name="icon-name">folder-visiting-symbolic</property>
+ <property name="title" translatable="yes">Browse keys</property>
+ <property name="name">pathbar</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="search_toggle">
+ <property name="visible">True</property>
+ <property name="valign">center</property>
+ <property name="focus-on-click">False</property>
+ <property name="action-name">ui.toggle-search</property>
+ <property name="action-target">true</property>
+ <!-- <accelerator key="F" signal="toggled" modifiers="GDK_CONTROL_MASK"/> TODO -->
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child internal-child="accessible">
+ <object class="AtkObject">
+ <property name="AtkObject::accessible-name" translatable="yes">Search</property>
+ <property name="AtkObject::accessible-description" translatable="yes">Search keys</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">edit-find-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/editor/pathwidget.vala b/editor/pathwidget.vala
new file mode 100644
index 0000000..01e38dd
--- /dev/null
+++ b/editor/pathwidget.vala
@@ -0,0 +1,141 @@
+/*
+ This file is part of Dconf Editor
+
+ Dconf Editor is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Dconf Editor is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Dconf Editor. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+using Gtk;
+
+[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/pathwidget.ui")]
+private class PathWidget : Box
+{
+ [GtkChild] private ToggleButton search_toggle;
+ [GtkChild] private Stack pathbar_stack;
+ [GtkChild] private PathBar pathbar;
+ [GtkChild] private PathEntry searchentry;
+
+ internal signal void search_changed ();
+ internal signal void search_stopped ();
+
+ /*\
+ * * search mode
+ \*/
+
+ internal bool search_mode_enabled { get; private set; default = false; }
+
+ private void enter_search_mode ()
+ {
+ search_mode_enabled = true;
+ search_toggle.active = true;
+ search_toggle.set_action_target_value (false);
+ pathbar_stack.set_visible_child (searchentry);
+ }
+
+ private void leave_search_mode ()
+ {
+ search_mode_enabled = false;
+ search_toggle.active = false;
+ search_toggle.set_action_target_value (true);
+ pathbar_stack.set_visible_child (pathbar);
+ }
+
+ /*\
+ * * callbacks
+ \*/
+
+ [GtkCallback]
+ private void search_changed_cb ()
+ {
+ if (search_mode_enabled)
+ search_changed ();
+ }
+
+ [GtkCallback]
+ private void search_stopped_cb ()
+ {
+ search_stopped ();
+ }
+
+ /*\
+ * * proxy calls
+ \*/
+
+ internal void set_path (ViewType type, string path)
+ {
+ pathbar.set_path (type, path);
+ searchentry.set_path (type, path);
+
+ if (type == ViewType.SEARCH && !search_mode_enabled)
+ enter_search_mode ();
+ else if (type != ViewType.SEARCH && search_mode_enabled)
+ leave_search_mode ();
+ }
+
+ /* path bar */
+ internal string complete_path { get { return pathbar.complete_path; }}
+
+ internal void update_ghosts (string fallback_path)
+ {
+ pathbar.update_ghosts (fallback_path, search_mode_enabled);
+ }
+
+ internal string get_selected_child (string fallback_path)
+ {
+ return pathbar.get_selected_child (fallback_path);
+ }
+
+ /* path entry */
+ internal string text { get { return searchentry.text; }}
+ internal bool entry_has_focus { get { return searchentry.entry_has_focus; }}
+ internal void entry_grab_focus () { searchentry.entry_grab_focus (); }
+ internal void entry_grab_focus_without_selecting () { searchentry.entry_grab_focus_without_selecting ();
}
+
+ internal bool handle_event (Gdk.EventKey event)
+ {
+ searchentry.prepare (PathEntry.SearchMode.SEARCH);
+ if (!searchentry.handle_event (event))
+ return false;
+ enter_search_mode ();
+ return true;
+ }
+
+ internal void prepare_search (PathEntry.SearchMode mode)
+ {
+ searchentry.prepare (mode);
+ }
+
+/* string [] tokens = full_name.split (" ");
+ uint index = 0;
+ string token;
+ while (index < tokens.length)
+ {
+ token = tokens [index];
+ if (token.has_prefix ("/"))
+ {
+ path_requested (token, pathbar.get_selected_child (token));
+ break;
+ }
+ index++;
+ } */
+
+ /*\
+ * * sizing
+ \*/
+
+ internal override void get_preferred_width (out int minimum_width, out int natural_width)
+ {
+ base.get_preferred_width (out minimum_width, out natural_width);
+ natural_width = MAX_ROW_WIDTH; // see key-list-box-row.vala
+ }
+}
diff --git a/editor/registry-list.vala b/editor/registry-list.vala
index 13158a6..16551c1 100644
--- a/editor/registry-list.vala
+++ b/editor/registry-list.vala
@@ -25,7 +25,8 @@ private abstract class RegistryList : Grid, BrowsableView
[GtkChild] private ScrolledWindow scrolled;
protected bool search_mode { private get; set; }
- protected string? current_path_if_search_mode = null; // TODO only used in search mode
+ protected string? current_path_if_search_mode = null; // TODO only used in search mode
+ protected bool search_is_path_search = false; // TODO only used in search mode
protected GLib.ListStore list_model = new GLib.ListStore (typeof (SimpleSettingObject));
@@ -233,6 +234,15 @@ private abstract class RegistryList : Grid, BrowsableView
((ClickableListBoxRow) ((!) selected_row).get_child ()).destroy_popover ();
}
+ internal void row_grab_focus ()
+ {
+ ListBoxRow? selected_row = (ListBoxRow?) key_list_box.get_selected_row ();
+ if (selected_row == null)
+ return;
+
+ ((!) selected_row).grab_focus ();
+ }
+
internal bool up_or_down_pressed (bool is_down)
{
ListBoxRow? selected_row = (ListBoxRow?) key_list_box.get_selected_row ();
@@ -284,7 +294,9 @@ private abstract class RegistryList : Grid, BrowsableView
if (search_mode && current_path_if_search_mode == null)
assert_not_reached ();
- bool search_mode_non_local_result = search_mode && ModelUtils.get_parent_path (full_name) != (!)
current_path_if_search_mode;
+ bool search_mode_non_local_result = search_mode
+ && (search_is_path_search
+ || ModelUtils.get_parent_path (full_name) != (!)
current_path_if_search_mode);
if (ModelUtils.is_folder_context_id (context_id))
{
diff --git a/editor/registry-search.vala b/editor/registry-search.vala
index a3f9b1e..a61213a 100644
--- a/editor/registry-search.vala
+++ b/editor/registry-search.vala
@@ -55,6 +55,7 @@ private class RegistrySearch : RegistryList
stop_global_search ();
post_local = -1;
+ post_paths = -1;
post_bookmarks = -1;
post_folders = -1;
@@ -139,6 +140,7 @@ private class RegistrySearch : RegistryList
// indices for the start of each section. used to know where to insert search hits and to update the
headers
// must be updated before changing the list model, so that the header function works correctly
private int post_local;
+ private int post_paths;
private int post_bookmarks;
private int post_folders;
private uint? search_source = null;
@@ -153,17 +155,19 @@ private class RegistrySearch : RegistryList
return;
}
+ bool old_term_is_term_prefix = old_term != null && term.has_prefix ((!) old_term);
SettingsModel model = modifications_handler.model;
- if (old_term != null && term.has_prefix ((!) old_term))
+ if (old_term_is_term_prefix && !(term.has_prefix ("/") && term.slice (((!) old_term).length,
term.length).contains ("/")))
{
pause_global_search (ref search_source);
- refine_local_results (term, ref list_model, ref post_local, ref post_bookmarks, ref
post_folders);
- refine_bookmarks_results (term, post_local, ref list_model, ref post_bookmarks, ref
post_folders);
+ refine_local_results (term, ref list_model, ref post_local, ref post_paths, ref post_bookmarks,
ref post_folders);
+ refine_paths_results (term, post_local, ref list_model, ref post_paths, ref post_bookmarks, ref
post_folders);
+ refine_bookmarks_results (term, post_paths, ref list_model, ref post_bookmarks, ref
post_folders);
if ((!) old_term == "")
start_global_search ((!) current_path_if_search_mode, term);
else
{
- refine_global_results (term, post_local, ref list_model, ref post_folders);
+ refine_global_results (term, post_bookmarks, ref list_model, ref post_folders);
resume_global_search ((!) current_path_if_search_mode, term); // update search term
}
@@ -178,11 +182,18 @@ private class RegistrySearch : RegistryList
stop_global_search ();
local_search (model, sorting_options, ModelUtils.get_base_path ((!)
current_path_if_search_mode), term, ref list_model);
+
post_local = (int) list_model.get_n_items ();
- post_bookmarks = post_local;
- post_folders = post_local;
+ post_paths = post_local;
+
+ search_is_path_search = term.has_prefix ("/");
+ if (search_is_path_search)
+ paths_search (model, term, ref list_model, ref post_paths);
+ post_bookmarks = post_paths;
+
+ bookmark_search (model, (!) current_path_if_search_mode, term, bookmarks, ref list_model, ref
post_bookmarks);
+ post_folders = post_bookmarks;
- bookmark_search (model, (!) current_path_if_search_mode, term, bookmarks, ref list_model, ref
post_bookmarks, ref post_folders);
key_list_box.bind_model (list_model, new_list_box_row);
_select_first_row (key_list_box);
@@ -195,14 +206,22 @@ private class RegistrySearch : RegistryList
old_term = term;
}
- private static void refine_local_results (string term, ref GLib.ListStore list_model, ref int
post_local, ref int post_bookmarks, ref int post_folders)
+ private static void refine_local_results (string term, ref GLib.ListStore list_model, ref int
post_local, ref int post_paths, ref int post_bookmarks, ref int post_folders)
{
+ if (post_local < 0)
+ assert_not_reached ();
+ if (post_local == 0)
+ return;
+
for (int i = post_local - 1; i >= 0; i--)
{
- SimpleSettingObject item = (SimpleSettingObject) list_model.get_item (i);
- if (!(term in item.name))
+ SimpleSettingObject? item = (SimpleSettingObject?) list_model.get_item (i);
+ if (item == null)
+ assert_not_reached ();
+ if (!(term in ((!) item).name))
{
post_local--;
+ post_paths--;
post_bookmarks--;
post_folders--;
list_model.remove (i);
@@ -210,12 +229,41 @@ private class RegistrySearch : RegistryList
}
}
- private static void refine_bookmarks_results (string term, int post_local, ref GLib.ListStore
list_model, ref int post_bookmarks, ref int post_folders)
+ private static void refine_paths_results (string term, int post_local, ref GLib.ListStore list_model,
ref int post_paths, ref int post_bookmarks, ref int post_folders)
{
- for (int i = post_bookmarks - 1; i >= post_local; i--)
+ if (post_paths < post_local)
+ assert_not_reached ();
+ if (post_paths == post_local)
+ return;
+
+ for (int i = post_paths - 1; i >= post_local; i--)
{
- SimpleSettingObject item = (SimpleSettingObject) list_model.get_item (i);
- if (!(term in item.name))
+ SimpleSettingObject? item = (SimpleSettingObject?) list_model.get_item (i);
+ if (item == null)
+ assert_not_reached ();
+ if (!(term in ((!) item).full_name))
+ {
+ post_paths--;
+ post_bookmarks--;
+ post_folders--;
+ list_model.remove (i);
+ }
+ }
+ }
+
+ private static void refine_bookmarks_results (string term, int post_paths, ref GLib.ListStore
list_model, ref int post_bookmarks, ref int post_folders)
+ {
+ if (post_bookmarks < post_paths)
+ assert_not_reached ();
+ if (post_bookmarks == post_paths)
+ return;
+
+ for (int i = post_bookmarks - 1; i >= post_paths; i--)
+ {
+ SimpleSettingObject? item = (SimpleSettingObject?) list_model.get_item (i);
+ if (item == null)
+ assert_not_reached ();
+ if (!(term in ((!) item).name))
{
post_bookmarks--;
post_folders--;
@@ -224,7 +272,7 @@ private class RegistrySearch : RegistryList
}
}
- private static void refine_global_results (string term, int post_local, ref GLib.ListStore list_model,
ref int post_folders)
+ private static void refine_global_results (string term, int post_bookmarks, ref GLib.ListStore
list_model, ref int post_folders)
{
for (int i = (int) list_model.get_n_items () - 1; i >= post_folders; i--)
{
@@ -232,7 +280,7 @@ private class RegistrySearch : RegistryList
if (!(term in item.name))
list_model.remove (i);
}
- for (int i = post_folders - 1; i >= post_local; i--)
+ for (int i = post_folders - 1; i >= post_bookmarks; i--)
{
SimpleSettingObject item = (SimpleSettingObject) list_model.get_item (i);
if (!(term in item.name))
@@ -250,23 +298,66 @@ private class RegistrySearch : RegistryList
GLib.CompareDataFunc compare = (a, b) => comparator.compare ((SimpleSettingObject) a,
(SimpleSettingObject) b);
Variant? key_model = model.get_children (current_path, true, false); // here to update watched keys
even coming from RegistryInfo
- if (key_model != null)
+ if (key_model == null)
+ return;
+
+ VariantIter iter = new VariantIter ((!) key_model);
+ uint16 context_id;
+ string name;
+ while (iter.next ("(qs)", out context_id, out name))
{
- VariantIter iter = new VariantIter ((!) key_model);
- uint16 context_id;
- string name;
- while (iter.next ("(qs)", out context_id, out name))
+ if (term in name)
+ {
+ SimpleSettingObject sso = new SimpleSettingObject.from_base_path (context_id, name,
current_path);
+ list_model.insert_sorted (sso, compare);
+ }
+ }
+ }
+
+ private static void paths_search (SettingsModel model, string term, ref GLib.ListStore list_model, ref
int post_paths)
+ {
+ uint16 context_id;
+ string name;
+
+ string base_path;
+ if (ModelUtils.is_key_path (term))
+ base_path = ModelUtils.get_parent_path (term);
+ else if (model.get_object (term, out context_id, out name, false)) // TODO model.get_folder
+ {
+ SimpleSettingObject sso = new SimpleSettingObject.from_full_name (context_id, name, term);
+ list_model.insert (post_paths, sso);
+ post_paths++;
+ base_path = term;
+ }
+ else // strange construction because else something wrong happens
+ base_path = ModelUtils.get_parent_path (term);
+
+ Variant? key_model = model.get_children (base_path, true, false);
+ if (key_model == null)
+ return;
+
+ int post_subfolders = post_paths;
+ VariantIter iter = new VariantIter ((!) key_model);
+ while (iter.next ("(qs)", out context_id, out name))
+ {
+ bool is_folder = context_id == ModelUtils.folder_context_id;
+ string full_name = ModelUtils.recreate_full_name (base_path, name, is_folder);
+ if (term in full_name)
{
- if (term in name)
+ SimpleSettingObject sso = new SimpleSettingObject.from_full_name (context_id, name,
full_name);
+ if (is_folder)
{
- SimpleSettingObject sso = new SimpleSettingObject.from_base_path (context_id, name,
current_path);
- list_model.insert_sorted (sso, compare);
+ list_model.insert (post_subfolders, sso);
+ post_subfolders++;
}
+ else
+ list_model.insert (post_paths, sso);
+ post_paths++;
}
}
}
- private static void bookmark_search (SettingsModel model, string current_path, string term, string []
bookmarks, ref GLib.ListStore list_model, ref int post_bookmarks, ref int post_folders)
+ private static void bookmark_search (SettingsModel model, string current_path, string term, string []
bookmarks, ref GLib.ListStore list_model, ref int post_bookmarks)
{
foreach (string bookmark in bookmarks)
{
@@ -282,10 +373,9 @@ private class RegistrySearch : RegistryList
if (term in name)
{
- post_bookmarks++;
- post_folders++;
SimpleSettingObject sso = new SimpleSettingObject.from_full_name (context_id, name,
bookmark);
- list_model.insert (post_bookmarks - 1, sso);
+ list_model.insert (post_bookmarks, sso);
+ post_bookmarks++;
}
}
}
@@ -346,7 +436,7 @@ private class RegistrySearch : RegistryList
if (!local_again && !(full_name in bookmarks) && term in name)
{
SimpleSettingObject sso = new SimpleSettingObject.from_full_name (context_id, name,
full_name);
- list_model.insert (post_folders++, sso);
+ list_model.insert (post_folders++, sso); // do not move the ++ outside
}
search_nodes.push_tail (full_name); // we still search local children
}
@@ -367,15 +457,17 @@ private class RegistrySearch : RegistryList
private void update_row_header (ListBoxRow row, ListBoxRow? before)
{
- string? label_text = get_header_text (row.get_index (), post_local, post_bookmarks, post_folders);
+ string? label_text = get_header_text (row.get_index (), post_local, post_paths, post_bookmarks,
post_folders);
ListBoxRowHeader header = new ListBoxRowHeader (before == null, label_text);
row.set_header (header);
}
- private static string? get_header_text (int row_index, int post_local, int post_bookmarks, int
post_folders)
+ private static string? get_header_text (int row_index, int post_local, int post_paths, int
post_bookmarks, int post_folders)
{
if (row_index == 0 && post_local > 0)
return _("Current folder");
- if (row_index == post_local && post_local != post_bookmarks)
+ if (row_index == post_local && post_local != post_paths)
+ return _("Paths");
+ if (row_index == post_paths && post_paths != post_bookmarks)
return _("Bookmarks");
if (row_index == post_bookmarks && post_bookmarks != post_folders)
return _("Folders");
diff --git a/editor/setting-object.vala b/editor/setting-object.vala
index 4ab926e..8a915a3 100644
--- a/editor/setting-object.vala
+++ b/editor/setting-object.vala
@@ -269,8 +269,11 @@ private class DConfKey : Key
private ulong client_changed_handler = 0;
internal void connect_client (DConf.Client client)
- requires (client_changed_handler == 0)
+// requires (client_changed_handler == 0)
{
+ if (client_changed_handler != 0) // FIXME happens since editable paths 1/3
+ return;
+
client_changed_handler = client.changed.connect ((client, prefix, changes, tag) => {
foreach (string item in changes)
if (prefix + item == full_name)
@@ -281,8 +284,11 @@ private class DConfKey : Key
});
}
internal void disconnect_client (DConf.Client client)
- requires (client_changed_handler != 0)
+// requires (client_changed_handler != 0)
{
+ if (client_changed_handler == 0) // FIXME happens since editable paths 2/3
+ return;
+
client.disconnect (client_changed_handler);
client_changed_handler = 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]