[dconf-editor] Introduce BookmarksList.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf-editor] Introduce BookmarksList.
- Date: Wed, 14 Nov 2018 13:48:38 +0000 (UTC)
commit 08d39d249a1302b39b8845223e347f818844f287
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Thu Oct 25 17:29:10 2018 +0200
Introduce BookmarksList.
editor/bookmarks-list.ui | 80 ++++++
editor/bookmarks-list.vala | 527 ++++++++++++++++++++++++++++++++++++++
editor/bookmarks.ui | 75 +-----
editor/bookmarks.vala | 423 +++---------------------------
editor/dconf-editor.gresource.xml | 1 +
editor/meson.build | 2 +
6 files changed, 643 insertions(+), 465 deletions(-)
---
diff --git a/editor/bookmarks-list.ui b/editor/bookmarks-list.ui
new file mode 100644
index 0000000..575e977
--- /dev/null
+++ b/editor/bookmarks-list.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="dconf-editor">
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="BookmarksList" parent="GtkOverlay">
+ <property name="expand">True</property>
+ <property name="valign">fill</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled">
+ <property name="visible">True</property>
+ <property name="expand">True</property>
+ <!-- property name="window-placement">top-right</property -->
+ <property name="hscrollbar-policy">never</property>
+ <property name="shadow-type">etched-in</property>
+ <property name="max-content-height">300</property>
+ <property name="propagate-natural-width">True</property>
+ <property name="propagate-natural-height">True</property>
+ <child>
+ <object class="GtkListBox" id="bookmarks_list_box">
+ <property name="visible">True</property>
+ <signal name="selected-rows-changed" handler="on_selection_changed"/>
+ <signal name="add" handler="on_content_changed"/>
+ <signal name="remove" handler="on_content_changed"/>
+ <style>
+ <class name="padding-bottom"/>
+ </style>
+ <child type="placeholder">
+ <object class="RegistryPlaceholder">
+ <property name="label" translatable="yes">Bookmarks will
be added here</property>
+ <property name="icon-name">starred-symbolic</property> <!-- or starred-symbolic? or
dconf-editor-symbolic? -->
+ <property name="big">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkBox" id="edit_mode_box">
+ <property name="visible">False</property>
+ <property name="halign">center</property>
+ <property name="valign">end</property>
+ <property name="width-request">200</property>
+ <style>
+ <class name="linked"/>
+ <class name="linked-circular"/>
+ </style>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="centered">True</property>
+ <property name="iconic">True</property>
+ <property name="focus-on-click">False</property>
+ <property name="action-name">bookmarks.set-edit-mode</property>
+ <property name="action-target">false</property>
+ <property name="text" translatable="yes">Use</property>
+ <style>
+ <class name="left-on-ltr"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkModelButton">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="centered">True</property>
+ <property name="iconic">True</property>
+ <property name="focus-on-click">False</property>
+ <property name="action-name">bookmarks.set-edit-mode</property>
+ <property name="action-target">true</property>
+ <property name="text" translatable="yes">Edit</property>
+ <style>
+ <class name="right-on-ltr"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/editor/bookmarks-list.vala b/editor/bookmarks-list.vala
new file mode 100644
index 0000000..c7d3d89
--- /dev/null
+++ b/editor/bookmarks-list.vala
@@ -0,0 +1,527 @@
+/*
+ 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/bookmarks-list.ui")]
+private class BookmarksList : Overlay
+{
+ [GtkChild] private ScrolledWindow scrolled;
+ [GtkChild] private ListBox bookmarks_list_box;
+ [GtkChild] private Box edit_mode_box;
+
+ private HashTable<string, Bookmark> bookmarks_hashtable = new HashTable<string, Bookmark> (str_hash,
str_equal);
+ private Bookmark? last_row = null;
+ private uint n_bookmarks = 0;
+
+ internal signal void selection_changed ();
+
+ internal enum SelectionState {
+ EMPTY,
+ UNIQUE,
+ FIRST,
+ LAST,
+ MIDDLE,
+ MULTIPLE
+ }
+
+ internal SelectionState get_selection_state ()
+ {
+ List<weak ListBoxRow> selected_rows = bookmarks_list_box.get_selected_rows ();
+ uint n_selected_rows = selected_rows.length ();
+
+ if (n_selected_rows == 0)
+ return SelectionState.EMPTY;
+ if (n_selected_rows >= 2)
+ return SelectionState.MULTIPLE;
+
+ int index = selected_rows.nth_data (0).get_index ();
+ bool is_first = index == 0;
+ bool is_last = bookmarks_list_box.get_row_at_index (index + 1) == null;
+ if (is_first && is_last)
+ return SelectionState.UNIQUE;
+ if (is_first)
+ return SelectionState.FIRST;
+ if (is_last)
+ return SelectionState.LAST;
+ return SelectionState.MIDDLE;
+ }
+
+ internal void enter_edit_mode ()
+ {
+ bookmarks_list_box.grab_focus ();
+
+ bookmarks_list_box.@foreach ((widget) => { ((Bookmark) widget).set_actionable (false); });
+ bookmarks_list_box.set_activate_on_single_click (false);
+ bookmarks_list_box.set_selection_mode (SelectionMode.MULTIPLE);
+ }
+
+ internal bool leave_edit_mode ()
+ {
+
+ ListBoxRow? row = (ListBoxRow?) bookmarks_list_box.get_focus_child (); // broken, the child needs
to have the global focus...
+ bool give_focus_to_switch = row == null;
+ if (give_focus_to_switch)
+ {
+ List<weak ListBoxRow> selected_rows = bookmarks_list_box.get_selected_rows ();
+ row = selected_rows.nth_data (0);
+ }
+
+ bookmarks_list_box.@foreach ((widget) => { ((Bookmark) widget).set_actionable (true); });
+ bookmarks_list_box.set_activate_on_single_click (true);
+ bookmarks_list_box.set_selection_mode (SelectionMode.SINGLE);
+
+ if (row != null)
+ select_row_for_real ((!) row);
+
+ return give_focus_to_switch;
+ }
+
+ internal string [] get_bookmarks ()
+ {
+ string [] bookmarks = new string [0];
+ bookmarks_list_box.@foreach ((widget) => { bookmarks += ((Bookmark) widget).bookmark_name; });
+ return bookmarks;
+ }
+
+ private bool has_empty_list_class = false;
+ internal bool create_bookmark_rows (Variant bookmarks_variant)
+ {
+ _create_bookmark_rows (bookmarks_variant, ref bookmarks_list_box, ref bookmarks_hashtable, ref
last_row, ref n_bookmarks);
+ bool no_bookmarks = n_bookmarks == 0;
+
+ if (no_bookmarks && !has_empty_list_class)
+ {
+ bookmarks_list_box.get_style_context ().add_class ("empty-list");
+ has_empty_list_class = true;
+ edit_mode_box.hide ();
+ }
+ else if (!no_bookmarks && has_empty_list_class)
+ {
+ bookmarks_list_box.get_style_context ().remove_class ("empty-list");
+ has_empty_list_class = false;
+ edit_mode_box.show ();
+ }
+
+ return no_bookmarks;
+ }
+ private static void _create_bookmark_rows (Variant bookmarks_variant, ref ListBox bookmarks_list_box,
ref HashTable<string, Bookmark> bookmarks_hashtable, ref Bookmark? last_row, ref uint n_bookmarks)
+ {
+ string saved_bookmark_name = "";
+ ListBoxRow? selected_row = bookmarks_list_box.get_selected_row ();
+ if (selected_row != null && ((!) selected_row) is Bookmark)
+ saved_bookmark_name = ((Bookmark) (!) selected_row).bookmark_name;
+ selected_row = null;
+
+ bookmarks_list_box.@foreach ((widget) => widget.destroy ());
+ bookmarks_hashtable.remove_all ();
+ last_row = null;
+ n_bookmarks = 0;
+
+ string [] bookmarks = bookmarks_variant.get_strv ();
+ string [] unduplicated_bookmarks = new string [0];
+ foreach (string bookmark in bookmarks)
+ {
+ if (DConfWindow.is_path_invalid (bookmark))
+ continue;
+ if (bookmark in unduplicated_bookmarks)
+ continue;
+ unduplicated_bookmarks += bookmark;
+
+ Bookmark bookmark_row = new Bookmark (bookmark);
+ bookmarks_list_box.add (bookmark_row);
+ bookmark_row.show ();
+ bookmarks_hashtable.insert (bookmark, bookmark_row);
+ last_row = bookmark_row;
+
+ if (saved_bookmark_name == bookmark)
+ selected_row = bookmark_row;
+ n_bookmarks ++;
+ }
+
+ if (selected_row == null)
+ selected_row = bookmarks_list_box.get_row_at_index (0);
+ if (selected_row != null)
+ bookmarks_list_box.select_row ((!) selected_row);
+ }
+
+ internal void update_bookmark_icon (string bookmark, BookmarkIcon icon)
+ {
+ Bookmark? bookmark_row = bookmarks_hashtable.lookup (bookmark);
+ if (bookmark_row == null)
+ return;
+ Widget? bookmark_grid = ((!) bookmark_row).get_child ();
+ if (bookmark_grid == null)
+ assert_not_reached ();
+ _update_bookmark_icon (((!) bookmark_grid).get_style_context (), icon);
+ }
+ private static inline void _update_bookmark_icon (StyleContext context, BookmarkIcon icon)
+ {
+ switch (icon)
+ {
+ case BookmarkIcon.VALID_FOLDER: context.add_class ("folder");
+ return;
+ case BookmarkIcon.EMPTY_FOLDER: context.add_class ("folder");
+ context.add_class ("erase");
+ return;
+ case BookmarkIcon.SEARCH: context.add_class ("search");
+ return;
+ case BookmarkIcon.EMPTY_OBJECT: context.add_class ("key");
+ context.add_class ("dconf-key");
+ context.add_class ("erase");
+ return;
+ case BookmarkIcon.DCONF_OBJECT: context.add_class ("key");
+ context.add_class ("dconf-key");
+ return;
+ case BookmarkIcon.KEY_DEFAULTS: context.add_class ("key");
+ context.add_class ("gsettings-key");
+ return;
+ case BookmarkIcon.EDITED_VALUE: context.add_class ("key");
+ context.add_class ("gsettings-key");
+ context.add_class ("edited");
+ return;
+ default: assert_not_reached ();
+ }
+ }
+
+ /*\
+ * * keyboard
+ \*/
+
+ internal void down_pressed ()
+ {
+ ListBoxRow? row = bookmarks_list_box.get_selected_row ();
+ if (row == null)
+ row = bookmarks_list_box.get_row_at_index (0);
+ else
+ row = bookmarks_list_box.get_row_at_index (((!) row).get_index () + 1);
+
+ if (row == null)
+ return;
+ bookmarks_list_box.select_row ((!) row);
+ ((!) row).grab_focus ();
+ }
+
+ internal void up_pressed ()
+ {
+ ListBoxRow? row = bookmarks_list_box.get_selected_row ();
+ if (row == null)
+ row = last_row;
+ else
+ {
+ int index = ((!) row).get_index ();
+ if (index <= 0)
+ return;
+ row = bookmarks_list_box.get_row_at_index (index - 1);
+ }
+
+ if (row == null)
+ return;
+ bookmarks_list_box.select_row ((!) row);
+ ((!) row).grab_focus ();
+ }
+
+ internal void select_all ()
+ {
+ bookmarks_list_box.select_all ();
+ }
+
+ internal void unselect_all ()
+ {
+ bookmarks_list_box.unselect_all ();
+ }
+
+ /*\
+ * * remote action entries
+ \*/
+
+ internal void trash_bookmark (out string [] bookmarks_to_remove)
+ {
+ ListBoxRow? row = (ListBoxRow?) bookmarks_list_box.get_focus_child ();
+ bool focused_row_will_survive = row != null && !((!) row).is_selected ();
+
+ string [] _bookmarks_to_remove = new string [0];
+ int upper_index = int.MAX;
+ bookmarks_list_box.selected_foreach ((_list_box, selected_row) => {
+ if (!(selected_row is Bookmark))
+ assert_not_reached ();
+ _bookmarks_to_remove += ((Bookmark) selected_row).bookmark_name;
+
+ if (focused_row_will_survive)
+ return;
+
+ int index = selected_row.get_index ();
+ if (upper_index > index)
+ upper_index = index;
+ });
+ if (upper_index == int.MAX)
+ assert_not_reached ();
+
+ if (!focused_row_will_survive)
+ {
+ row = bookmarks_list_box.get_row_at_index (upper_index + 1);
+ if (row == null)
+ {
+ if (upper_index > 0)
+ row = bookmarks_list_box.get_row_at_index (upper_index - 1);
+ // TODO else quit mode
+ }
+ }
+ if (row != null)
+ bookmarks_list_box.select_row ((!) row);
+
+ bookmarks_to_remove = _bookmarks_to_remove;
+ }
+
+ internal bool move_top ()
+ {
+// bookmarks_list_box.selected_foreach ((_list_box, selected_row) => {
+
+ ListBoxRow? row = bookmarks_list_box.get_selected_row ();
+ if (row == null)
+ return true; // TODO assert_not_reached?
+
+ int index = ((!) row).get_index ();
+ if (index < 0)
+ assert_not_reached ();
+
+ if (index == 0)
+ return true;
+ bookmarks_list_box.remove ((!) row);
+ bookmarks_list_box.prepend ((!) row);
+ select_row_for_real ((!) row);
+
+ Adjustment adjustment = bookmarks_list_box.get_adjustment ();
+ adjustment.set_value (adjustment.get_lower ());
+
+ return false;
+ }
+
+ internal bool move_up ()
+ {
+ ListBoxRow? row = bookmarks_list_box.get_selected_row ();
+ if (row == null)
+ return true; // TODO assert_not_reached?
+
+ int index = ((!) row).get_index ();
+ if (index < 0)
+ assert_not_reached ();
+
+ if (index == 0)
+ return true;
+
+ ListBoxRow? prev_row = bookmarks_list_box.get_row_at_index (index - 1);
+ if (prev_row == null)
+ assert_not_reached ();
+
+ Allocation list_allocation, row_allocation;
+ scrolled.get_allocation (out list_allocation);
+ Widget? row_child = ((!) prev_row).get_child (); // using prev_row as the allocation is not
updated anyway
+ if (row_child == null)
+ assert_not_reached ();
+ ((!) row_child).get_allocation (out row_allocation);
+ Adjustment adjustment = bookmarks_list_box.get_adjustment ();
+ int proposed_adjustemnt_value = row_allocation.y + (int) ((row_allocation.height -
list_allocation.height) / 3.0);
+ bool should_adjust = adjustment.get_value () > proposed_adjustemnt_value;
+
+ bookmarks_list_box.unselect_row ((!) row);
+ bookmarks_list_box.remove ((!) prev_row);
+
+ if (should_adjust)
+ adjustment.set_value (proposed_adjustemnt_value);
+
+ bookmarks_list_box.insert ((!) prev_row, index);
+ bookmarks_list_box.select_row ((!) row);
+
+ return false;
+ }
+
+ internal bool move_down ()
+ {
+ ListBoxRow? row = bookmarks_list_box.get_selected_row ();
+ if (row == null)
+ return true; // TODO assert_not_reached?
+
+ int index = ((!) row).get_index ();
+ if (index < 0)
+ assert_not_reached ();
+
+ ListBoxRow? next_row = bookmarks_list_box.get_row_at_index (index + 1);
+ if (next_row == null)
+ return true;
+
+ Allocation list_allocation, row_allocation;
+ scrolled.get_allocation (out list_allocation);
+ Widget? row_child = ((!) next_row).get_child (); // using next_row as the allocation is not
updated
+ if (row_child == null)
+ assert_not_reached ();
+ ((!) row_child).get_allocation (out row_allocation);
+ Adjustment adjustment = bookmarks_list_box.get_adjustment ();
+ int proposed_adjustemnt_value = row_allocation.y + (int) (2 * (row_allocation.height -
list_allocation.height) / 3.0);
+ bool should_adjust = adjustment.get_value () < proposed_adjustemnt_value;
+
+ bookmarks_list_box.unselect_row ((!) row);
+ bookmarks_list_box.remove ((!) next_row);
+
+ if (should_adjust)
+ adjustment.set_value (proposed_adjustemnt_value);
+
+ bookmarks_list_box.insert ((!) next_row, index);
+ bookmarks_list_box.select_row ((!) row);
+
+ return false;
+ }
+
+ internal bool move_bottom ()
+ {
+// bookmarks_list_box.selected_foreach ((_list_box, selected_row) => {
+
+ ListBoxRow? row = bookmarks_list_box.get_selected_row ();
+ if (row == null)
+ return true; // TODO assert_not_reached?
+
+ int index = ((!) row).get_index ();
+ if (index < 0)
+ assert_not_reached ();
+
+ bookmarks_list_box.remove ((!) row);
+ bookmarks_list_box.insert ((!) row, -1);
+ select_row_for_real ((!) row);
+
+ Adjustment adjustment = bookmarks_list_box.get_adjustment ();
+ adjustment.set_value (adjustment.get_upper ());
+
+ return false;
+ }
+
+ private void select_row_for_real (ListBoxRow row) // ahem...
+ {
+ bookmarks_list_box.unselect_row (row);
+ bookmarks_list_box.select_row (row);
+ }
+
+ /*\
+ * * callbacks
+ \*/
+
+ [GtkCallback]
+ private void on_selection_changed ()
+ {
+ selection_changed ();
+ }
+
+ [GtkCallback]
+ private void on_content_changed ()
+ {
+ List<weak Widget> widgets = bookmarks_list_box.get_children ();
+ if (widgets.length () == 0)
+ edit_mode_box.hide ();
+ else
+ edit_mode_box.show ();
+ }
+}
+
+[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/bookmark.ui")]
+private class Bookmark : ListBoxRow
+{
+ [GtkChild] private Label bookmark_label;
+
+ public string bookmark_name { internal get; internal construct; }
+
+ construct
+ {
+ string bookmark_text;
+ ViewType bookmark_type;
+ parse_bookmark_name (bookmark_name, out bookmark_text, out bookmark_type);
+
+ construct_actions_names (bookmark_text, bookmark_type, out detailed_action_name, out
inactive_action_name);
+ set_actionable (true);
+
+ bookmark_label.set_label (bookmark_text);
+ }
+
+ internal Bookmark (string bookmark_name)
+ {
+ Object (bookmark_name: bookmark_name);
+ }
+
+ internal void set_actionable (bool actionable)
+ {
+ if (actionable)
+ set_detailed_action_name (detailed_action_name);
+ else
+ set_detailed_action_name (inactive_action_name);
+ }
+
+ /*\
+ * * Actions names
+ \*/
+
+ private string detailed_action_name;
+ private string inactive_action_name;
+
+ private static void construct_actions_names (string bookmark_text,
+ ViewType bookmark_type,
+ out string detailed_action_name,
+ out string inactive_action_name)
+ {
+ switch (bookmark_type)
+ {
+ case ViewType.SEARCH:
+ Variant variant = new Variant.string (bookmark_text);
+ detailed_action_name = "ui.open-search(" + variant.print (false) + ")";
+ inactive_action_name = "ui.empty('')";
+ return;
+
+ case ViewType.FOLDER:
+ Variant variant = new Variant.string (bookmark_text);
+ detailed_action_name = "ui.open-folder(" + variant.print (false) + ")";
+ inactive_action_name = "ui.empty('')";
+ return;
+
+ case ViewType.OBJECT:
+ Variant variant = new Variant ("(sq)", bookmark_text, ModelUtils.undefined_context_id); //
TODO save context
+ detailed_action_name = "ui.open-object(" + variant.print (true) + ")";
+ inactive_action_name = "ui.empty(('',uint16 65535))";
+ return;
+
+ case ViewType.CONFIG:
+ default: assert_not_reached ();
+ }
+ }
+
+ private static void parse_bookmark_name (string bookmark_name,
+ out string bookmark_text,
+ out ViewType bookmark_type)
+ {
+ if (bookmark_name.has_prefix ("?"))
+ {
+ bookmark_text = bookmark_name.slice (1, bookmark_name.length);
+ bookmark_type = ViewType.SEARCH;
+ }
+ else if (ModelUtils.is_folder_path (bookmark_name))
+ {
+ bookmark_text = bookmark_name;
+ bookmark_type = ViewType.FOLDER;
+ }
+ else
+ {
+ bookmark_text = bookmark_name;
+ bookmark_type = ViewType.OBJECT;
+ }
+ }
+}
diff --git a/editor/bookmarks.ui b/editor/bookmarks.ui
index 48dd100..04381a0 100644
--- a/editor/bookmarks.ui
+++ b/editor/bookmarks.ui
@@ -85,80 +85,9 @@
</object>
</child>
<child>
- <object class="GtkOverlay">
+ <object class="BookmarksList" id="bookmarks_list">
<property name="visible">True</property>
- <property name="expand">True</property>
- <property name="valign">fill</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolled">
- <property name="visible">True</property>
- <property name="expand">True</property>
- <!-- property name="window-placement">top-right</property -->
- <property name="hscrollbar-policy">never</property>
- <property name="shadow-type">etched-in</property>
- <property name="max-content-height">300</property>
- <property name="propagate-natural-width">True</property>
- <property name="propagate-natural-height">True</property>
- <child>
- <object class="GtkListBox" id="bookmarks_list_box">
- <property name="visible">True</property>
- <signal name="selected-rows-changed" handler="on_selection_changed"/>
- <style>
- <class name="padding-bottom"/>
- </style>
- <child type="placeholder">
- <object class="RegistryPlaceholder">
- <property name="label" translatable="yes">Bookmarks will
be added here</property>
- <property name="icon-name">starred-symbolic</property> <!-- or starred-symbolic? or
dconf-editor-symbolic? -->
- <property name="big">False</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="overlay">
- <object class="GtkBox" id="edit_mode_box">
- <property name="visible">True</property>
- <property name="halign">center</property>
- <property name="valign">end</property>
- <property name="width-request">200</property>
- <style>
- <class name="linked"/>
- <class name="linked-circular"/>
- </style>
- <child>
- <object class="GtkModelButton">
- <property name="visible">True</property>
- <property name="hexpand">True</property>
- <property name="centered">True</property>
- <property name="iconic">True</property>
- <property name="focus-on-click">False</property>
- <property name="action-name">bookmarks.set-edit-mode</property>
- <property name="action-target">false</property>
- <property name="text" translatable="yes">Use</property>
- <style>
- <class name="left-on-ltr"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkModelButton">
- <property name="visible">True</property>
- <property name="hexpand">True</property>
- <property name="centered">True</property>
- <property name="iconic">True</property>
- <property name="focus-on-click">False</property>
- <property name="action-name">bookmarks.set-edit-mode</property>
- <property name="action-target">true</property>
- <property name="text" translatable="yes">Edit</property>
- <style>
- <class name="right-on-ltr"/>
- </style>
- </object>
- </child>
- </object>
- </child>
+ <signal name="selection-changed" handler="on_selection_changed"/>
</object>
</child>
</object>
diff --git a/editor/bookmarks.vala b/editor/bookmarks.vala
index 31d7a0d..64a1acd 100644
--- a/editor/bookmarks.vala
+++ b/editor/bookmarks.vala
@@ -32,17 +32,13 @@ internal enum BookmarkIcon {
[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/bookmarks.ui")]
private class Bookmarks : MenuButton
{
- [GtkChild] private ListBox bookmarks_list_box;
- [GtkChild] private ScrolledWindow scrolled;
- [GtkChild] private Popover bookmarks_popover;
-
- [GtkChild] private Image bookmarks_icon;
- [GtkChild] private Switch bookmarked_switch;
- [GtkChild] private Label switch_label;
-
- [GtkChild] private Stack edit_mode_stack;
- [GtkChild] private Box edit_mode_box;
- [GtkChild] private BookmarksController bookmarks_controller;
+ [GtkChild] private Image bookmarks_icon;
+ [GtkChild] private Popover bookmarks_popover;
+ [GtkChild] private Stack edit_mode_stack;
+ [GtkChild] private BookmarksList bookmarks_list;
+ [GtkChild] private Switch bookmarked_switch;
+ [GtkChild] private Label switch_label;
+ [GtkChild] private BookmarksController bookmarks_controller;
private string current_path = "/";
private ViewType current_type = ViewType.FOLDER;
@@ -52,10 +48,6 @@ private class Bookmarks : MenuButton
private GLib.Settings settings;
ulong bookmarks_changed_handler = 0;
- private HashTable<string, Bookmark> bookmarks_hashtable = new HashTable<string, Bookmark> (str_hash,
str_equal);
- private Bookmark? last_row = null;
- private uint n_bookmarks = 0;
-
internal signal void update_bookmarks_icons (Variant bookmarks_variant);
construct
@@ -123,7 +115,7 @@ private class Bookmarks : MenuButton
else
{
edit_mode_stack.set_visible_child_name ("edit-mode-disabled");
- bookmarks_list_box.grab_focus ();
+ bookmarks_list.grab_focus ();
}
}
@@ -146,12 +138,12 @@ private class Bookmarks : MenuButton
{
if (name == "a")
{
- bookmarks_list_box.select_all ();
+ bookmarks_list.select_all ();
return true;
}
if (name == "A")
{
- bookmarks_list_box.unselect_all ();
+ bookmarks_list.unselect_all ();
return true;
}
}
@@ -209,35 +201,13 @@ private class Bookmarks : MenuButton
internal void down_pressed ()
requires (active)
{
- ListBoxRow? row = bookmarks_list_box.get_selected_row ();
- if (row == null)
- row = bookmarks_list_box.get_row_at_index (0);
- else
- row = bookmarks_list_box.get_row_at_index (((!) row).get_index () + 1);
-
- if (row == null)
- return;
- bookmarks_list_box.select_row ((!) row);
- ((!) row).grab_focus ();
+ bookmarks_list.down_pressed ();
}
+
internal void up_pressed ()
requires (active)
{
- ListBoxRow? row = bookmarks_list_box.get_selected_row ();
- if (row == null)
- row = last_row;
- else
- {
- int index = ((!) row).get_index ();
- if (index <= 0)
- return;
- row = bookmarks_list_box.get_row_at_index (index - 1);
- }
-
- if (row == null)
- return;
- bookmarks_list_box.select_row ((!) row);
- ((!) row).grab_focus ();
+ bookmarks_list.up_pressed ();
}
internal void bookmark_current_path ()
@@ -256,41 +226,7 @@ private class Bookmarks : MenuButton
internal void update_bookmark_icon (string bookmark, BookmarkIcon icon)
{
- Bookmark? bookmark_row = bookmarks_hashtable.lookup (bookmark);
- if (bookmark_row == null)
- return;
- Widget? bookmark_grid = ((!) bookmark_row).get_child ();
- if (bookmark_grid == null)
- assert_not_reached ();
- _update_bookmark_icon (((!) bookmark_grid).get_style_context (), icon);
- }
- private static inline void _update_bookmark_icon (StyleContext context, BookmarkIcon icon)
- {
- switch (icon)
- {
- case BookmarkIcon.VALID_FOLDER: context.add_class ("folder");
- return;
- case BookmarkIcon.EMPTY_FOLDER: context.add_class ("folder");
- context.add_class ("erase");
- return;
- case BookmarkIcon.SEARCH: context.add_class ("search");
- return;
- case BookmarkIcon.EMPTY_OBJECT: context.add_class ("key");
- context.add_class ("dconf-key");
- context.add_class ("erase");
- return;
- case BookmarkIcon.DCONF_OBJECT: context.add_class ("key");
- context.add_class ("dconf-key");
- return;
- case BookmarkIcon.KEY_DEFAULTS: context.add_class ("key");
- context.add_class ("gsettings-key");
- return;
- case BookmarkIcon.EDITED_VALUE: context.add_class ("key");
- context.add_class ("gsettings-key");
- context.add_class ("edited");
- return;
- default: assert_not_reached ();
- }
+ bookmarks_list.update_bookmark_icon (bookmark, icon);
}
/*\
@@ -308,11 +244,10 @@ private class Bookmarks : MenuButton
private void update_actions ()
requires (actions_init_done)
{
- List<weak ListBoxRow> selected_rows = bookmarks_list_box.get_selected_rows ();
- uint n_selected_rows = selected_rows.length ();
+ BookmarksList.SelectionState selection_state = bookmarks_list.get_selection_state ();
- bool has_selected_items = n_selected_rows > 0;
- bool has_one_selected_item = n_selected_rows == 1;
+ bool has_selected_items = selection_state != BookmarksList.SelectionState.EMPTY;
+ bool has_one_selected_item = has_selected_items && (selection_state !=
BookmarksList.SelectionState.MULTIPLE);
bool enable_move_top_action = has_one_selected_item; // TODO has_selected_items;
bool enable_move_up_action = has_one_selected_item;
@@ -321,13 +256,12 @@ private class Bookmarks : MenuButton
if (has_one_selected_item)
{
- int index = selected_rows.nth_data (0).get_index ();
- if (index == 0)
+ if (selection_state == BookmarksList.SelectionState.UNIQUE || selection_state ==
BookmarksList.SelectionState.FIRST)
{
enable_move_top_action = false;
enable_move_up_action = false;
}
- if (bookmarks_list_box.get_row_at_index (index + 1) == null)
+ if (selection_state == BookmarksList.SelectionState.UNIQUE || selection_state ==
BookmarksList.SelectionState.LAST)
{
enable_move_down_action = false;
enable_move_bottom_action = false;
@@ -391,11 +325,7 @@ private class Bookmarks : MenuButton
update_actions ();
edit_mode_stack.set_visible_child_name ("edit-mode-on");
- bookmarks_list_box.grab_focus ();
-
- bookmarks_list_box.@foreach ((widget) => { ((Bookmark) widget).set_actionable (false); });
- bookmarks_list_box.set_activate_on_single_click (false);
- bookmarks_list_box.set_selection_mode (SelectionMode.MULTIPLE);
+ bookmarks_list.enter_edit_mode ();
}
[GtkCallback]
@@ -403,60 +333,17 @@ private class Bookmarks : MenuButton
{
edit_mode_state_action.set_state (false);
- ListBoxRow? row = (ListBoxRow?) bookmarks_list_box.get_focus_child (); // broken, the child needs
to have the global focus...
- bool give_focus_to_switch = row == null;
- if (give_focus_to_switch)
- {
- List<weak ListBoxRow> selected_rows = bookmarks_list_box.get_selected_rows ();
- row = selected_rows.nth_data (0);
- }
-
- bookmarks_list_box.@foreach ((widget) => { ((Bookmark) widget).set_actionable (true); });
- bookmarks_list_box.set_activate_on_single_click (true);
- bookmarks_list_box.set_selection_mode (SelectionMode.SINGLE);
-
+ bool give_focus_to_switch = bookmarks_list.leave_edit_mode ();
edit_mode_stack.set_visible_child_name ("edit-mode-off");
- if (row != null)
- select_row_for_real ((!) row);
if (give_focus_to_switch)
bookmarked_switch.grab_focus ();
}
private void trash_bookmark (/* SimpleAction action, Variant? variant */)
{
- ListBoxRow? row = (ListBoxRow?) bookmarks_list_box.get_focus_child ();
- bool focused_row_will_survive = row != null && !((!) row).is_selected ();
-
- string [] bookmarks_to_remove = new string [0];
- int upper_index = int.MAX;
- bookmarks_list_box.selected_foreach ((_list_box, selected_row) => {
- if (!(selected_row is Bookmark))
- assert_not_reached ();
- bookmarks_to_remove += ((Bookmark) selected_row).bookmark_name;
-
- if (focused_row_will_survive)
- return;
-
- int index = selected_row.get_index ();
- if (upper_index > index)
- upper_index = index;
- });
- if (upper_index == int.MAX)
- assert_not_reached ();
-
- if (!focused_row_will_survive)
- {
- row = bookmarks_list_box.get_row_at_index (upper_index + 1);
- if (row == null)
- {
- if (upper_index > 0)
- row = bookmarks_list_box.get_row_at_index (upper_index - 1);
- // TODO else quit mode
- }
- }
- if (row != null)
- bookmarks_list_box.select_row ((!) row);
+ string [] bookmarks_to_remove;
+ bookmarks_list.trash_bookmark (out bookmarks_to_remove);
remove_bookmarks (settings, bookmarks_to_remove);
update_bookmarks_icons (settings.get_value ("bookmarks"));
@@ -469,129 +356,31 @@ private class Bookmarks : MenuButton
private void move_top (/* SimpleAction action, Variant? variant */)
{
-// bookmarks_list_box.selected_foreach ((_list_box, selected_row) => {
-
- ListBoxRow? row = bookmarks_list_box.get_selected_row ();
- if (row == null)
- return; // TODO assert_not_reached?
-
- int index = ((!) row).get_index ();
- if (index < 0)
- assert_not_reached ();
-
- if (index == 0)
+ if (bookmarks_list.move_top ())
return;
- bookmarks_list_box.remove ((!) row);
- bookmarks_list_box.prepend ((!) row);
- select_row_for_real ((!) row);
-
- Adjustment adjustment = bookmarks_list_box.get_adjustment ();
- adjustment.set_value (adjustment.get_lower ());
-
update_bookmarks_after_move ();
}
private void move_up (/* SimpleAction action, Variant? variant */)
{
- ListBoxRow? row = bookmarks_list_box.get_selected_row ();
- if (row == null)
- return; // TODO assert_not_reached?
-
- int index = ((!) row).get_index ();
- if (index < 0)
- assert_not_reached ();
-
- if (index == 0)
+ if (bookmarks_list.move_up ())
return;
-
- ListBoxRow? prev_row = bookmarks_list_box.get_row_at_index (index - 1);
- if (prev_row == null)
- assert_not_reached ();
-
- Allocation list_allocation, row_allocation;
- scrolled.get_allocation (out list_allocation);
- Widget? row_child = ((!) prev_row).get_child (); // using prev_row as the allocation is not
updated anyway
- if (row_child == null)
- assert_not_reached ();
- ((!) row_child).get_allocation (out row_allocation);
- Adjustment adjustment = bookmarks_list_box.get_adjustment ();
- int proposed_adjustemnt_value = row_allocation.y + (int) ((row_allocation.height -
list_allocation.height) / 3.0);
- bool should_adjust = adjustment.get_value () > proposed_adjustemnt_value;
-
- bookmarks_list_box.unselect_row ((!) row);
- bookmarks_list_box.remove ((!) prev_row);
-
- if (should_adjust)
- adjustment.set_value (proposed_adjustemnt_value);
-
- bookmarks_list_box.insert ((!) prev_row, index);
- bookmarks_list_box.select_row ((!) row);
-
update_bookmarks_after_move ();
}
private void move_down (/* SimpleAction action, Variant? variant */)
{
- ListBoxRow? row = bookmarks_list_box.get_selected_row ();
- if (row == null)
- return; // TODO assert_not_reached?
-
- int index = ((!) row).get_index ();
- if (index < 0)
- assert_not_reached ();
-
- ListBoxRow? next_row = bookmarks_list_box.get_row_at_index (index + 1);
- if (next_row == null)
+ if (bookmarks_list.move_down ())
return;
-
- Allocation list_allocation, row_allocation;
- scrolled.get_allocation (out list_allocation);
- Widget? row_child = ((!) next_row).get_child (); // using next_row as the allocation is not
updated
- if (row_child == null)
- assert_not_reached ();
- ((!) row_child).get_allocation (out row_allocation);
- Adjustment adjustment = bookmarks_list_box.get_adjustment ();
- int proposed_adjustemnt_value = row_allocation.y + (int) (2 * (row_allocation.height -
list_allocation.height) / 3.0);
- bool should_adjust = adjustment.get_value () < proposed_adjustemnt_value;
-
- bookmarks_list_box.unselect_row ((!) row);
- bookmarks_list_box.remove ((!) next_row);
-
- if (should_adjust)
- adjustment.set_value (proposed_adjustemnt_value);
-
- bookmarks_list_box.insert ((!) next_row, index);
- bookmarks_list_box.select_row ((!) row);
-
update_bookmarks_after_move ();
}
private void move_bottom (/* SimpleAction action, Variant? variant */)
{
-// bookmarks_list_box.selected_foreach ((_list_box, selected_row) => {
-
- ListBoxRow? row = bookmarks_list_box.get_selected_row ();
- if (row == null)
- return; // TODO assert_not_reached?
-
- int index = ((!) row).get_index ();
- if (index < 0)
- assert_not_reached ();
-
- bookmarks_list_box.remove ((!) row);
- bookmarks_list_box.insert ((!) row, -1);
- select_row_for_real ((!) row);
-
- Adjustment adjustment = bookmarks_list_box.get_adjustment ();
- adjustment.set_value (adjustment.get_upper ());
-
+ if (bookmarks_list.move_bottom ())
+ return;
update_bookmarks_after_move ();
}
- private void select_row_for_real (ListBoxRow row) // ahem...
- {
- bookmarks_list_box.unselect_row (row);
- bookmarks_list_box.select_row (row);
- }
private void bookmark (SimpleAction action, Variant? path_variant)
requires (path_variant != null)
@@ -621,8 +410,7 @@ private class Bookmarks : MenuButton
private void update_bookmarks_after_move ()
{
- string [] new_bookmarks = new string [0];
- bookmarks_list_box.@foreach ((widget) => { new_bookmarks += ((Bookmark) widget).bookmark_name; });
+ string [] new_bookmarks = bookmarks_list.get_bookmarks ();
string [] old_bookmarks = settings.get_strv ("bookmarks"); // be cool :-)
foreach (string bookmark in old_bookmarks)
@@ -672,74 +460,16 @@ private class Bookmarks : MenuButton
bookmarked_switch.active = bookmarked;
}
- private bool has_empty_list_class = false;
private void update_bookmarks (Variant bookmarks_variant)
{
set_detailed_action_name ("ui.update-bookmarks-icons(" + bookmarks_variant.print (true) + ")"); //
TODO disable action on popover closed
- create_bookmark_rows (bookmarks_variant, ref bookmarks_list_box, ref bookmarks_hashtable, ref
last_row, ref n_bookmarks);
- if (n_bookmarks == 0)
+ bool no_bookmarks = bookmarks_list.create_bookmark_rows (bookmarks_variant);
+ if (no_bookmarks)
{
string? visible_child_name = edit_mode_stack.get_visible_child_name (); // do it like that
if (visible_child_name != null && (!) visible_child_name == "edit-mode-on")
leave_edit_mode ();
-
- if (!has_empty_list_class)
- {
- bookmarks_list_box.get_style_context ().add_class ("empty-list");
- has_empty_list_class = true;
- }
-
- edit_mode_box.hide ();
- }
- else
- {
- if (has_empty_list_class)
- {
- bookmarks_list_box.get_style_context ().remove_class ("empty-list");
- has_empty_list_class = false;
- }
-
- edit_mode_box.show ();
- }
- }
- private static void create_bookmark_rows (Variant bookmarks_variant, ref ListBox bookmarks_list_box, ref
HashTable<string, Bookmark> bookmarks_hashtable, ref Bookmark? last_row, ref uint n_bookmarks)
- {
- string saved_bookmark_name = "";
- ListBoxRow? selected_row = bookmarks_list_box.get_selected_row ();
- if (selected_row != null && ((!) selected_row) is Bookmark)
- saved_bookmark_name = ((Bookmark) (!) selected_row).bookmark_name;
- selected_row = null;
-
- bookmarks_list_box.@foreach ((widget) => widget.destroy ());
- bookmarks_hashtable.remove_all ();
- last_row = null;
- n_bookmarks = 0;
-
- string [] bookmarks = bookmarks_variant.get_strv ();
- string [] unduplicated_bookmarks = new string [0];
- foreach (string bookmark in bookmarks)
- {
- if (DConfWindow.is_path_invalid (bookmark))
- continue;
- if (bookmark in unduplicated_bookmarks)
- continue;
- unduplicated_bookmarks += bookmark;
-
- Bookmark bookmark_row = new Bookmark (bookmark);
- bookmarks_list_box.add (bookmark_row);
- bookmark_row.show ();
- bookmarks_hashtable.insert (bookmark, bookmark_row);
- last_row = bookmark_row;
-
- if (saved_bookmark_name == bookmark)
- selected_row = bookmark_row;
- n_bookmarks ++;
}
-
- if (selected_row == null)
- selected_row = bookmarks_list_box.get_row_at_index (0);
- if (selected_row != null)
- bookmarks_list_box.select_row ((!) selected_row);
}
private static void append_bookmark (GLib.Settings settings, string bookmark_name)
@@ -784,94 +514,3 @@ private class Bookmarks : MenuButton
return path;
}
}
-
-[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/bookmark.ui")]
-private class Bookmark : ListBoxRow
-{
- [GtkChild] private Label bookmark_label;
-
- public string bookmark_name { internal get; internal construct; }
-
- construct
- {
- string bookmark_text;
- ViewType bookmark_type;
- parse_bookmark_name (bookmark_name, out bookmark_text, out bookmark_type);
-
- construct_actions_names (bookmark_text, bookmark_type, out detailed_action_name, out
inactive_action_name);
- set_actionable (true);
-
- bookmark_label.set_label (bookmark_text);
- }
-
- internal Bookmark (string bookmark_name)
- {
- Object (bookmark_name: bookmark_name);
- }
-
- internal void set_actionable (bool actionable)
- {
- if (actionable)
- set_detailed_action_name (detailed_action_name);
- else
- set_detailed_action_name (inactive_action_name);
- }
-
- /*\
- * * Actions names
- \*/
-
- private string detailed_action_name;
- private string inactive_action_name;
-
- private static void construct_actions_names (string bookmark_text,
- ViewType bookmark_type,
- out string detailed_action_name,
- out string inactive_action_name)
- {
- switch (bookmark_type)
- {
- case ViewType.SEARCH:
- Variant variant = new Variant.string (bookmark_text);
- detailed_action_name = "ui.open-search(" + variant.print (false) + ")";
- inactive_action_name = "ui.empty('')";
- return;
-
- case ViewType.FOLDER:
- Variant variant = new Variant.string (bookmark_text);
- detailed_action_name = "ui.open-folder(" + variant.print (false) + ")";
- inactive_action_name = "ui.empty('')";
- return;
-
- case ViewType.OBJECT:
- Variant variant = new Variant ("(sq)", bookmark_text, ModelUtils.undefined_context_id); //
TODO save context
- detailed_action_name = "ui.open-object(" + variant.print (true) + ")";
- inactive_action_name = "ui.empty(('',uint16 65535))";
- return;
-
- case ViewType.CONFIG:
- default: assert_not_reached ();
- }
- }
-
- private static void parse_bookmark_name (string bookmark_name,
- out string bookmark_text,
- out ViewType bookmark_type)
- {
- if (bookmark_name.has_prefix ("?"))
- {
- bookmark_text = bookmark_name.slice (1, bookmark_name.length);
- bookmark_type = ViewType.SEARCH;
- }
- else if (ModelUtils.is_folder_path (bookmark_name))
- {
- bookmark_text = bookmark_name;
- bookmark_type = ViewType.FOLDER;
- }
- else
- {
- bookmark_text = bookmark_name;
- bookmark_type = ViewType.OBJECT;
- }
- }
-}
diff --git a/editor/dconf-editor.gresource.xml b/editor/dconf-editor.gresource.xml
index 8696a68..ed364f0 100644
--- a/editor/dconf-editor.gresource.xml
+++ b/editor/dconf-editor.gresource.xml
@@ -5,6 +5,7 @@
<file preprocess="xml-stripblanks">bookmark.ui</file>
<file preprocess="xml-stripblanks">bookmarks.ui</file>
<file preprocess="xml-stripblanks">bookmarks-controller.ui</file>
+ <file preprocess="xml-stripblanks">bookmarks-list.ui</file>
<file preprocess="xml-stripblanks">browser-headerbar.ui</file>
<file preprocess="xml-stripblanks">browser-infobar.ui</file>
<file preprocess="xml-stripblanks">browser-stack.ui</file>
diff --git a/editor/meson.build b/editor/meson.build
index feadf38..e158ce4 100644
--- a/editor/meson.build
+++ b/editor/meson.build
@@ -69,6 +69,7 @@ sources = files(
'adaptative-pathbar.vala',
'bookmarks.vala',
'bookmarks-controller.vala',
+ 'bookmarks-list.vala',
'browser-headerbar.vala',
'browser-infobar.vala',
'browser-stack.vala',
@@ -101,6 +102,7 @@ resource_data = files(
'adaptative-pathbar.ui',
'bookmarks.ui',
'bookmarks-controller.ui',
+ 'bookmarks-list.ui',
'bookmark.ui',
'browser-headerbar.ui',
'browser-infobar.ui',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]