Blame editor/registry-view.vala

Packit 2c4300
/*
Packit 2c4300
  This file is part of Dconf Editor
Packit 2c4300
Packit 2c4300
  Dconf Editor is free software: you can redistribute it and/or modify
Packit 2c4300
  it under the terms of the GNU General Public License as published by
Packit 2c4300
  the Free Software Foundation, either version 3 of the License, or
Packit 2c4300
  (at your option) any later version.
Packit 2c4300
Packit 2c4300
  Dconf Editor is distributed in the hope that it will be useful,
Packit 2c4300
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 2c4300
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 2c4300
  GNU General Public License for more details.
Packit 2c4300
Packit 2c4300
  You should have received a copy of the GNU General Public License
Packit 2c4300
  along with Dconf Editor.  If not, see <https://www.gnu.org/licenses/>.
Packit 2c4300
*/
Packit 2c4300
Packit 2c4300
using Gtk;
Packit 2c4300
Packit 2c4300
[GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/registry-view.ui")]
Packit 2c4300
private abstract class RegistryList : Grid, BrowsableView
Packit 2c4300
{
Packit 2c4300
    [GtkChild] protected ListBox key_list_box;
Packit 2c4300
    [GtkChild] protected RegistryPlaceholder placeholder;
Packit 2c4300
    [GtkChild] private ScrolledWindow scrolled;
Packit 2c4300
Packit 2c4300
    protected GLib.ListStore list_model = new GLib.ListStore (typeof (SettingObject));
Packit 2c4300
Packit 2c4300
    protected GLib.ListStore rows_possibly_with_popover = new GLib.ListStore (typeof (ClickableListBoxRow));
Packit 2c4300
Packit 2c4300
    protected bool _small_keys_list_rows;
Packit 2c4300
    public bool small_keys_list_rows
Packit 2c4300
    {
Packit 2c4300
        set
Packit 2c4300
        {
Packit 2c4300
            _small_keys_list_rows = value;
Packit 2c4300
            key_list_box.foreach ((row) => {
Packit 2c4300
                    Widget? row_child = ((ListBoxRow) row).get_child ();
Packit 2c4300
                    if (row_child != null && (!) row_child is KeyListBoxRow)
Packit 2c4300
                        ((KeyListBoxRow) (!) row_child).small_keys_list_rows = value;
Packit 2c4300
                });
Packit 2c4300
        }
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    protected void scroll_to_row (ListBoxRow row, bool grab_focus)
Packit 2c4300
    {
Packit 2c4300
        key_list_box.select_row (row);
Packit 2c4300
        if (grab_focus)
Packit 2c4300
            row.grab_focus ();
Packit 2c4300
Packit 2c4300
        Allocation list_allocation, row_allocation;
Packit 2c4300
        scrolled.get_allocation (out list_allocation);
Packit 2c4300
        row.get_allocation (out row_allocation);
Packit 2c4300
        key_list_box.get_adjustment ().set_value (row_allocation.y + (int) ((row_allocation.height - list_allocation.height) / 2.0));
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public void invalidate_popovers ()
Packit 2c4300
    {
Packit 2c4300
        uint position = 0;
Packit 2c4300
        ClickableListBoxRow? row = (ClickableListBoxRow?) rows_possibly_with_popover.get_item (0);
Packit 2c4300
        while (row != null)
Packit 2c4300
        {
Packit 2c4300
            ((!) row).destroy_popover ();
Packit 2c4300
            position++;
Packit 2c4300
            row = (ClickableListBoxRow?) rows_possibly_with_popover.get_item (position);
Packit 2c4300
        }
Packit 2c4300
        rows_possibly_with_popover.remove_all ();
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public string get_selected_row_name ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = key_list_box.get_selected_row ();
Packit 2c4300
        if (selected_row != null)
Packit 2c4300
        {
Packit 2c4300
            int position = ((!) selected_row).get_index ();
Packit 2c4300
            return ((SettingObject) list_model.get_object (position)).full_name;
Packit 2c4300
        }
Packit 2c4300
        else
Packit 2c4300
            return "";
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public abstract void select_first_row ();
Packit 2c4300
Packit 2c4300
    public void select_row_named (string selected, string context, bool grab_focus)
Packit 2c4300
    {
Packit 2c4300
        check_resize ();
Packit 2c4300
        ListBoxRow? row = key_list_box.get_row_at_index (get_row_position (selected, context));
Packit 2c4300
        if (row != null)
Packit 2c4300
            scroll_to_row ((!) row, grab_focus);
Packit 2c4300
    }
Packit 2c4300
    private int get_row_position (string selected, string context)
Packit 2c4300
    {
Packit 2c4300
        uint position = 0;
Packit 2c4300
        uint fallback = 0;
Packit 2c4300
        while (position < list_model.get_n_items ())
Packit 2c4300
        {
Packit 2c4300
            SettingObject object = (SettingObject) list_model.get_object (position);
Packit 2c4300
            if (object.full_name == selected)
Packit 2c4300
            {
Packit 2c4300
                if (object is Directory
Packit 2c4300
                 || context == ".dconf" && object is DConfKey // theorical?
Packit 2c4300
                 || object is GSettingsKey && ((GSettingsKey) object).schema_id == context)
Packit 2c4300
                    return (int) position;
Packit 2c4300
                fallback = position;
Packit 2c4300
            }
Packit 2c4300
            position++;
Packit 2c4300
        }
Packit 2c4300
        return (int) fallback; // selected row may have been removed or context could be ""
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public abstract bool up_or_down_pressed (bool is_down);
Packit 2c4300
Packit 2c4300
    /*\
Packit 2c4300
    * * Keyboard calls
Packit 2c4300
    \*/
Packit 2c4300
Packit 2c4300
    public bool show_row_popover ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = (ListBoxRow?) key_list_box.get_selected_row ();
Packit 2c4300
        if (selected_row == null)
Packit 2c4300
            return false;
Packit 2c4300
Packit 2c4300
        ClickableListBoxRow row = (ClickableListBoxRow) ((!) selected_row).get_child ();
Packit 2c4300
Packit 2c4300
        if (row.right_click_popover_visible ())
Packit 2c4300
            row.hide_right_click_popover ();
Packit 2c4300
        else
Packit 2c4300
        {
Packit 2c4300
            row.show_right_click_popover ();
Packit 2c4300
            rows_possibly_with_popover.append (row);
Packit 2c4300
        }
Packit 2c4300
        return true;
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public string? get_copy_text ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = key_list_box.get_selected_row ();
Packit 2c4300
        if (selected_row == null)
Packit 2c4300
            return null;
Packit 2c4300
Packit 2c4300
        return ((ClickableListBoxRow) ((!) selected_row).get_child ()).get_text ();
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public void toggle_boolean_key ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = (ListBoxRow?) key_list_box.get_selected_row ();
Packit 2c4300
        if (selected_row == null)
Packit 2c4300
            return;
Packit 2c4300
Packit 2c4300
        if (!(((!) selected_row).get_child () is KeyListBoxRow))
Packit 2c4300
            return;
Packit 2c4300
Packit 2c4300
        ((KeyListBoxRow) ((!) selected_row).get_child ()).toggle_boolean_key ();
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public void set_selected_to_default ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = (ListBoxRow?) key_list_box.get_selected_row ();
Packit 2c4300
        if (selected_row == null)
Packit 2c4300
            return;
Packit 2c4300
Packit 2c4300
        if (!(((!) selected_row).get_child () is KeyListBoxRow))
Packit 2c4300
            assert_not_reached ();
Packit 2c4300
Packit 2c4300
        ((KeyListBoxRow) ((!) selected_row).get_child ()).on_delete_call ();
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public void discard_row_popover ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = (ListBoxRow?) key_list_box.get_selected_row ();
Packit 2c4300
        if (selected_row == null)
Packit 2c4300
            return;
Packit 2c4300
Packit 2c4300
        ((ClickableListBoxRow) ((!) selected_row).get_child ()).destroy_popover ();
Packit 2c4300
    }
Packit 2c4300
}
Packit 2c4300
Packit 2c4300
class RegistryView : RegistryList
Packit 2c4300
{
Packit 2c4300
    public ModificationsHandler modifications_handler { private get; set; }
Packit 2c4300
Packit 2c4300
    construct
Packit 2c4300
    {
Packit 2c4300
        placeholder.label = _("No keys in this path");
Packit 2c4300
        key_list_box.set_header_func (update_row_header);
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    /*\
Packit 2c4300
    * * Updating
Packit 2c4300
    \*/
Packit 2c4300
Packit 2c4300
    public void set_key_model (GLib.ListStore key_model)
Packit 2c4300
    {
Packit 2c4300
        list_model = key_model;
Packit 2c4300
        key_list_box.bind_model (list_model, new_list_box_row);
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public bool check_reload (GLib.ListStore fresh_key_model)
Packit 2c4300
    {
Packit 2c4300
        if (list_model.get_n_items () != fresh_key_model.get_n_items ())
Packit 2c4300
            return true;
Packit 2c4300
        for (uint i = 0; i < list_model.get_n_items (); i++)
Packit 2c4300
        {
Packit 2c4300
            SettingObject setting_object = (SettingObject) list_model.get_item (i);
Packit 2c4300
            bool found = false;
Packit 2c4300
            for (uint j = 0; j < fresh_key_model.get_n_items (); j++)
Packit 2c4300
            {
Packit 2c4300
                SettingObject fresh_setting_object = (SettingObject) fresh_key_model.get_item (j);
Packit 2c4300
                if (setting_object.get_type () != fresh_setting_object.get_type ())
Packit 2c4300
                    continue;
Packit 2c4300
                if (setting_object.name != fresh_setting_object.name)
Packit 2c4300
                    continue;
Packit 2c4300
                // TODO compare other visible info (i.e. key summary and value)
Packit 2c4300
                found = true;
Packit 2c4300
                fresh_key_model.remove (j);
Packit 2c4300
                break;
Packit 2c4300
            }
Packit 2c4300
            if (!found)
Packit 2c4300
                return true;
Packit 2c4300
        }
Packit 2c4300
        if (fresh_key_model.get_n_items () > 0)
Packit 2c4300
            return true;
Packit 2c4300
        return false;
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public override void select_first_row ()
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? row = key_list_box.get_row_at_index (0);
Packit 2c4300
        if (row != null)
Packit 2c4300
            scroll_to_row ((!) row, true);
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    /*\
Packit 2c4300
    * * Key ListBox
Packit 2c4300
    \*/
Packit 2c4300
Packit 2c4300
    private void update_row_header (ListBoxRow row, ListBoxRow? before)
Packit 2c4300
    {
Packit 2c4300
        string? label_text = null;
Packit 2c4300
        if (row.get_child () is KeyListBoxRowEditable)
Packit 2c4300
        {
Packit 2c4300
            string schema_id = ((KeyListBoxRowEditable) row.get_child ()).key.schema_id;
Packit 2c4300
            if (before == null
Packit 2c4300
             || !(((!) before).get_child () is KeyListBoxRowEditable
Packit 2c4300
               && ((KeyListBoxRowEditable) ((!) before).get_child ()).key.schema_id == schema_id))
Packit 2c4300
                label_text = schema_id;
Packit 2c4300
        }
Packit 2c4300
        else if (row.get_child () is KeyListBoxRowEditableNoSchema)
Packit 2c4300
        {
Packit 2c4300
            if (before == null || !(((!) before).get_child () is KeyListBoxRowEditableNoSchema))
Packit 2c4300
                label_text = _("Keys not defined by a schema");
Packit 2c4300
        }
Packit 2c4300
Packit 2c4300
        ListBoxRowHeader header = new ListBoxRowHeader (before == null, label_text);
Packit 2c4300
        row.set_header (header);
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    private Widget new_list_box_row (Object item)
Packit 2c4300
    {
Packit 2c4300
        ClickableListBoxRow row;
Packit 2c4300
        SettingObject setting_object = (SettingObject) item;
Packit 2c4300
Packit 2c4300
        if (setting_object is Directory)
Packit 2c4300
        {
Packit 2c4300
            row = new FolderListBoxRow (setting_object.name, setting_object.full_name, setting_object.parent_path);
Packit 2c4300
        }
Packit 2c4300
        else
Packit 2c4300
        {
Packit 2c4300
            if (setting_object is GSettingsKey)
Packit 2c4300
                row = new KeyListBoxRowEditable ((GSettingsKey) setting_object, modifications_handler);
Packit 2c4300
            else
Packit 2c4300
                row = new KeyListBoxRowEditableNoSchema ((DConfKey) setting_object, modifications_handler);
Packit 2c4300
Packit 2c4300
            KeyListBoxRow key_row = (KeyListBoxRow) row;
Packit 2c4300
            key_row.small_keys_list_rows = _small_keys_list_rows;
Packit 2c4300
Packit 2c4300
            ulong delayed_modifications_changed_handler = modifications_handler.delayed_changes_changed.connect (() => key_row.set_delayed_icon ());
Packit 2c4300
            key_row.set_delayed_icon ();
Packit 2c4300
            row.destroy.connect (() => modifications_handler.disconnect (delayed_modifications_changed_handler));
Packit 2c4300
        }
Packit 2c4300
Packit 2c4300
        ulong button_press_event_handler = row.button_press_event.connect (on_button_pressed);
Packit 2c4300
        row.destroy.connect (() => row.disconnect (button_press_event_handler));
Packit 2c4300
Packit 2c4300
        /* Wrapper ensures max width for rows */
Packit 2c4300
        ListBoxRowWrapper wrapper = new ListBoxRowWrapper ();
Packit 2c4300
Packit 2c4300
        wrapper.set_halign (Align.CENTER);
Packit 2c4300
        wrapper.add (row);
Packit 2c4300
        if (row is FolderListBoxRow)
Packit 2c4300
        {
Packit 2c4300
            wrapper.get_style_context ().add_class ("folder-row");
Packit 2c4300
            wrapper.action_name = "ui.open-folder";
Packit 2c4300
            wrapper.set_action_target ("s", setting_object.full_name);
Packit 2c4300
        }
Packit 2c4300
        else
Packit 2c4300
        {
Packit 2c4300
            wrapper.get_style_context ().add_class ("key-row");
Packit 2c4300
            wrapper.action_name = "ui.open-object";
Packit 2c4300
            string context = (setting_object is GSettingsKey) ? ((GSettingsKey) setting_object).schema_id : ".dconf";
Packit 2c4300
            wrapper.set_action_target ("(ss)", setting_object.full_name, context);
Packit 2c4300
        }
Packit 2c4300
Packit 2c4300
        return wrapper;
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    private bool on_button_pressed (Widget widget, Gdk.EventButton event)
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow list_box_row = (ListBoxRow) widget.get_parent ();
Packit 2c4300
        key_list_box.select_row (list_box_row);
Packit 2c4300
        list_box_row.grab_focus ();
Packit 2c4300
Packit 2c4300
        if (event.button == Gdk.BUTTON_SECONDARY)
Packit 2c4300
        {
Packit 2c4300
            ClickableListBoxRow row = (ClickableListBoxRow) widget;
Packit 2c4300
Packit 2c4300
            int event_x = (int) event.x;
Packit 2c4300
            if (event.window != widget.get_window ())   // boolean value switch
Packit 2c4300
            {
Packit 2c4300
                int widget_x, unused;
Packit 2c4300
                event.window.get_position (out widget_x, out unused);
Packit 2c4300
                event_x += widget_x;
Packit 2c4300
            }
Packit 2c4300
Packit 2c4300
            row.show_right_click_popover (event_x);
Packit 2c4300
            rows_possibly_with_popover.append (row);
Packit 2c4300
        }
Packit 2c4300
Packit 2c4300
        return false;
Packit 2c4300
    }
Packit 2c4300
Packit 2c4300
    public override bool up_or_down_pressed (bool is_down)
Packit 2c4300
    {
Packit 2c4300
        ListBoxRow? selected_row = key_list_box.get_selected_row ();
Packit 2c4300
        uint n_items = list_model.get_n_items ();
Packit 2c4300
Packit 2c4300
        if (selected_row != null)
Packit 2c4300
        {
Packit 2c4300
            Widget? row_content = ((!) selected_row).get_child ();
Packit 2c4300
            if (row_content != null && ((ClickableListBoxRow) (!) row_content).right_click_popover_visible ())
Packit 2c4300
                return false;
Packit 2c4300
Packit 2c4300
            int position = ((!) selected_row).get_index ();
Packit 2c4300
            ListBoxRow? row = null;
Packit 2c4300
            if (!is_down && (position >= 1))
Packit 2c4300
                row = key_list_box.get_row_at_index (position - 1);
Packit 2c4300
            if (is_down && (position < n_items - 1))
Packit 2c4300
                row = key_list_box.get_row_at_index (position + 1);
Packit 2c4300
Packit 2c4300
            if (row != null)
Packit 2c4300
                scroll_to_row ((!) row, true);
Packit 2c4300
Packit 2c4300
            return true;
Packit 2c4300
        }
Packit 2c4300
        else if (n_items >= 1)
Packit 2c4300
        {
Packit 2c4300
            key_list_box.select_row (key_list_box.get_row_at_index (is_down ? 0 : (int) n_items - 1));
Packit 2c4300
            return true;
Packit 2c4300
        }
Packit 2c4300
        return false;
Packit 2c4300
    }
Packit 2c4300
}