├── .gitignore ├── po ├── meson.build ├── LINGUAS ├── POTFILES.skip └── POTFILES.in ├── editor ├── screenshot1.png ├── screenshot2.png ├── ca.desrt.dconf-editor.service.in ├── config.vapi ├── ca.desrt.dconf-editor.desktop.in ├── icons │ └── hicolor │ │ ├── symbolic │ │ └── apps │ │ │ └── ca.desrt.dconf-editor-symbolic.svg │ │ └── scalable │ │ ├── actions │ │ ├── ca.desrt.dconf-editor.big-rows-symbolic.svg │ │ └── ca.desrt.dconf-editor.small-rows-symbolic.svg │ │ └── apps │ │ └── ca.desrt.dconf-editor.svg ├── base-window.ui ├── large-pathbar-item.ui ├── adaptative-window.ui ├── base-view.ui ├── large-pathbar.ui ├── search-list-box-row.ui ├── folder-list-box-row.ui ├── bookmark.ui ├── property-row.ui ├── schemas-utility.vala ├── filter-list-box-row.ui ├── return-list-box-row.ui ├── browser-stack.ui ├── browser-infobar.ui ├── dconf-editor.1 ├── registry-placeholder.ui ├── registry-list.ui ├── registry-placeholder.vala ├── dconf-editor.gresource.xml ├── notifications-revealer.vala ├── browser-content.vala ├── browser-infobar.vala ├── short-pathbar.ui ├── notifications-revealer.ui ├── bookmarks-controller.vala ├── overlayed-list.ui ├── ca.desrt.dconf-editor.metainfo.xml.in ├── base-window.css ├── registry-view.vala ├── pathentry.ui ├── modifications-revealer.ui ├── key-list-box-row.ui ├── completion │ └── dconf-editor ├── base-headerbar.ui ├── bookmarks-controller.ui ├── base-view.vala ├── meson.build ├── pathwidget.ui ├── large-pathbar.css ├── bookmarks-view.vala ├── modifications-list.vala ├── short-pathbar.vala ├── delayed-setting-view.ui ├── browser-headerbar.vala ├── bookmarks.ui ├── pathwidget.vala ├── delayed-setting-view.vala ├── pathentry.vala ├── adaptative-pathbar.vala └── modifications-handler.vala ├── README.md ├── code-of-conduct.md ├── .gitlab-ci.yml ├── dconf-editor.doap └── meson.build /.gitignore: -------------------------------------------------------------------------------- 1 | # for all subdirectories 2 | *~ 3 | .flatpak-builder 4 | -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext(dconf_editor_gettext, preset: 'glib') 2 | -------------------------------------------------------------------------------- /editor/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/dconf-editor/HEAD/editor/screenshot1.png -------------------------------------------------------------------------------- /editor/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GNOME/dconf-editor/HEAD/editor/screenshot2.png -------------------------------------------------------------------------------- /editor/ca.desrt.dconf-editor.service.in: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=ca.desrt.dconf-editor 3 | Exec=@bindir@/dconf-editor --gapplication-service 4 | -------------------------------------------------------------------------------- /editor/config.vapi: -------------------------------------------------------------------------------- 1 | [CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] 2 | namespace Config 3 | { 4 | public const string PKGDATADIR; 5 | public const string GETTEXT_PACKAGE; 6 | public const string LOCALEDIR; 7 | public const string VERSION; 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dconf-Editor 2 | 3 | A GSettings editor for GNOME. 4 | 5 | ## Useful links 6 | 7 | - Homepage: 8 | - Report issues: 9 | - Translate: 10 | - Code of Conduct: 11 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | The web-places where this application is developed –mainly on the GNOME Gitlab instance– try to be welcoming spaces. If you feel something is missing for reaching that goal, please open an issue about it or notify it to the maintainer. Also, note that the [GNOME Foundation code of conduct](https://wiki.gnome.org/Foundation/CodeOfConduct) applies there. Thanks. 4 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - project: 'gnome/citemplates' 3 | file: 'flatpak/flatpak_ci_initiative.yml' 4 | - component: "gitlab.gnome.org/GNOME/citemplates/release-service@master" 5 | inputs: 6 | dist-job-name: "flatpak" 7 | 8 | flatpak: 9 | variables: 10 | BUNDLE: "dconf-editor-dev.flatpak" 11 | MANIFEST_PATH: "build-aux/ca.desrt.dconf-editor.json" 12 | FLATPAK_MODULE: "dconf-editor" 13 | RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo" 14 | APP_ID: "ca.desrt.dconf-editor" 15 | extends: ".flatpak" 16 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | # please keep this list sorted alphabetically 2 | ab 3 | af 4 | an 5 | ar 6 | as 7 | be 8 | bg 9 | bn_IN 10 | bs 11 | ca 12 | ca@valencia 13 | cs 14 | da 15 | de 16 | el 17 | en_GB 18 | eo 19 | es 20 | et 21 | eu 22 | fa 23 | fi 24 | fr 25 | fur 26 | gl 27 | he 28 | hi 29 | hr 30 | hu 31 | id 32 | is 33 | it 34 | ja 35 | ka 36 | kab 37 | kk 38 | ko 39 | lt 40 | lv 41 | ml 42 | mr 43 | ms 44 | nb 45 | ne 46 | nl 47 | oc 48 | pa 49 | pl 50 | pt 51 | pt_BR 52 | ro 53 | ru 54 | sk 55 | sl 56 | sr 57 | sr@latin 58 | sv 59 | ta 60 | te 61 | tg 62 | th 63 | tr 64 | uk 65 | uz 66 | vi 67 | zh_CN 68 | zh_HK 69 | zh_TW 70 | ug 71 | -------------------------------------------------------------------------------- /po/POTFILES.skip: -------------------------------------------------------------------------------- 1 | # List of source files that should *not* be translated. 2 | # Please keep this file sorted alphabetically. 3 | editor/about-list.c 4 | editor/adaptative-pathbar.c 5 | editor/adaptative-window.c 6 | editor/base-headerbar.c 7 | editor/bookmarks.c 8 | editor/bookmarks-headerbar.c 9 | editor/bookmarks-list.c 10 | editor/browser-headerbar.c 11 | editor/browser-view.c 12 | editor/browser-window.c 13 | editor/dconf-editor.c 14 | editor/dconf-headerbar.c 15 | editor/dconf-model.c 16 | editor/dconf-view.c 17 | editor/dconf-window.c 18 | editor/delayed-setting-view.c 19 | editor/key-editor-child.c 20 | editor/key-list-box-row.c 21 | editor/model-utils.c 22 | editor/modifications-list.c 23 | editor/modifications-revealer.c 24 | editor/registry-info.c 25 | editor/registry-list.c 26 | editor/registry-search.c 27 | editor/registry-view.c 28 | editor/setting-object.c 29 | -------------------------------------------------------------------------------- /editor/ca.desrt.dconf-editor.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=dconf Editor 3 | # Translators: a GenericName that gives the application goal, as defined in the desktop file spec 4 | GenericName=Configuration editor for dconf 5 | # Translators: a Comment that gives the application function, as defined in the desktop file spec 6 | Comment=Directly edit your entire configuration database 7 | # Translators: some search Keywords to find this application, as defined in the desktop file spec. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! 8 | Keywords=settings;configuration; 9 | Exec=dconf-editor 10 | Terminal=false 11 | Type=Application 12 | StartupNotify=true 13 | Categories=GNOME;GTK;System; 14 | DBusActivatable=true 15 | # Translators: Do NOT translate or transliterate this text (this is an icon file name)! 16 | Icon=ca.desrt.dconf-editor 17 | -------------------------------------------------------------------------------- /editor/icons/hicolor/symbolic/apps/ca.desrt.dconf-editor-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /editor/base-window.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 30 | 31 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files containing translatable strings. 2 | # Please keep this file sorted alphabetically. 3 | editor/about-list.vala 4 | editor/adaptative-pathbar.vala 5 | editor/adaptative-window.vala 6 | editor/base-headerbar.ui 7 | editor/base-headerbar.vala 8 | editor/bookmarks-headerbar.vala 9 | editor/bookmarks-list.vala 10 | editor/bookmarks.ui 11 | editor/bookmarks.vala 12 | editor/bookmark.ui 13 | editor/browser-headerbar.vala 14 | editor/browser-view.vala 15 | editor/browser-window.vala 16 | editor/ca.desrt.dconf-editor.desktop.in 17 | editor/ca.desrt.dconf-editor.metainfo.xml.in 18 | editor/ca.desrt.dconf-editor.gschema.xml 19 | editor/dconf-editor.vala 20 | editor/dconf-headerbar.vala 21 | editor/dconf-model.vala 22 | editor/dconf-view.vala 23 | editor/dconf-window.vala 24 | editor/delayed-setting-view.ui 25 | editor/delayed-setting-view.vala 26 | editor/help-overlay.ui 27 | editor/key-editor-child.vala 28 | editor/key-list-box-row.vala 29 | editor/model-utils.vala 30 | editor/modifications-list.vala 31 | editor/modifications-revealer.ui 32 | editor/modifications-revealer.vala 33 | editor/pathentry.ui 34 | editor/pathwidget.ui 35 | editor/registry-info.ui 36 | editor/registry-info.vala 37 | editor/registry-list.vala 38 | editor/registry-search.vala 39 | editor/registry-view.vala 40 | editor/setting-object.vala 41 | editor/short-pathbar.ui 42 | -------------------------------------------------------------------------------- /editor/large-pathbar-item.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 33 | 34 | -------------------------------------------------------------------------------- /dconf-editor.doap: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | dconf-editor 9 | dconf Editor 10 | A graphical viewer and editor of applications internal settings 11 | 12 | 13 | 14 | 15 | 16 | 17 | Vala 18 | 19 | 20 | 21 | Dylan McCall 22 | 23 | dylanmccall 24 | 25 | 26 | 27 | 28 | 29 | Davi da Silva Böger 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /editor/adaptative-window.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 27 | 28 | -------------------------------------------------------------------------------- /editor/base-view.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 38 | 39 | -------------------------------------------------------------------------------- /editor/large-pathbar.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 38 | 39 | -------------------------------------------------------------------------------- /editor/search-list-box-row.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 44 | 45 | -------------------------------------------------------------------------------- /editor/folder-list-box-row.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 44 | 45 | -------------------------------------------------------------------------------- /editor/bookmark.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 42 | 43 | -------------------------------------------------------------------------------- /editor/property-row.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 43 | 44 | -------------------------------------------------------------------------------- /editor/schemas-utility.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | private class SchemasUtility : Object 19 | { 20 | private SettingsSchemaSource? settings_schema_source = SettingsSchemaSource.get_default (); 21 | private string [] non_relocatable_schemas = {}; 22 | private string [] relocatable_schemas = {}; 23 | 24 | construct 25 | { 26 | if (settings_schema_source != null) 27 | ((!) settings_schema_source).list_schemas (true, out non_relocatable_schemas, out relocatable_schemas); 28 | } 29 | 30 | internal bool is_relocatable_schema (string id) 31 | { 32 | return (id in relocatable_schemas); 33 | } 34 | 35 | internal bool is_non_relocatable_schema (string id) 36 | { 37 | return (id in non_relocatable_schemas); 38 | } 39 | 40 | internal string? get_schema_path (string id) 41 | { 42 | if (settings_schema_source == null) 43 | return null; // TODO better? 44 | 45 | SettingsSchema? schema = ((!) settings_schema_source).lookup (id, true); 46 | if (schema == null) 47 | return null; 48 | 49 | return ((!) schema).get_path (); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /editor/filter-list-box-row.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 46 | 47 | -------------------------------------------------------------------------------- /editor/return-list-box-row.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 46 | 47 | -------------------------------------------------------------------------------- /editor/browser-stack.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 46 | 47 | -------------------------------------------------------------------------------- /editor/browser-infobar.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 46 | 47 | -------------------------------------------------------------------------------- /editor/dconf-editor.1: -------------------------------------------------------------------------------- 1 | .\" This file is part of Dconf Editor 2 | .\" 3 | .\" Dconf Editor is free software: you can redistribute it and/or modify 4 | .\" it under the terms of the GNU General Public License as published by 5 | .\" the Free Software Foundation, either version 3 of the License, or 6 | .\" (at your option) any later version. 7 | .\" 8 | .\" Dconf Editor is distributed in the hope that it will be useful, 9 | .\" but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | .\" GNU General Public License for more details. 12 | .\" 13 | .\" You should have received a copy of the GNU General Public License 14 | .\" along with Dconf Editor. If not, see . 15 | .TH "DCONF\-EDITOR" "1" 16 | .SH "NAME" 17 | dconf-editor \- Graphical editor for gsettings and dconf 18 | .SH "SYNOPSIS" 19 | .B dconf\-editor [OPTIONS...] 20 | .RE 21 | .B dconf\-editor [OPTIONS...] [PATH] 22 | .RE 23 | .B dconf\-editor [OPTIONS...] [FIXED_SCHEMA | RELOCATABLE_SCHEMA:PATH] [KEY] 24 | .SH "DESCRIPTION" 25 | The 26 | .B dconf\-editor 27 | program provides a graphical interface for editing settings that are stored by other applications using the 28 | .I gsettings 29 | functions of the 30 | .I glib 31 | library, or in the 32 | .I dconf 33 | database. The 34 | .BR gsettings (1) 35 | and 36 | .BR dconf (1) 37 | utilities provides similar functionality on the commandline. 38 | .SH "OPTIONS" 39 | .TP 40 | .BR \-h , \ \-\-help 41 | Prints the command-line options and exits. 42 | .TP 43 | .BR \-v , \ \-\-version 44 | Prints the release version and exits. 45 | .TP 46 | .BR \-\-list\-relocatable\-schemas 47 | Prints the list of relocatable schemas and exits. 48 | .TP 49 | .BR \--I-understand-that-changing-options-can-break-applications 50 | Launches application without showing initial warning. 51 | .SH "SEE ALSO" 52 | .BR dconf (7) 53 | .BR dconf (1) 54 | .BR gsettings (1) 55 | -------------------------------------------------------------------------------- /editor/registry-placeholder.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 48 | 49 | -------------------------------------------------------------------------------- /editor/registry-list.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 45 | 46 | -------------------------------------------------------------------------------- /editor/registry-placeholder.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/registry-placeholder.ui")] 21 | private class RegistryPlaceholder : Grid 22 | { 23 | [GtkChild] private unowned Label placeholder_label; 24 | [GtkChild] private unowned Image placeholder_image; 25 | 26 | [CCode (notify = false)] public string label { internal construct set { placeholder_label.label = value; }} 27 | [CCode (notify = false)] public string icon_name { private get; internal construct; } 28 | [CCode (notify = false)] public bool big 29 | { 30 | internal construct set 31 | { 32 | if (value) 33 | { 34 | placeholder_image.pixel_size = 72; 35 | get_style_context ().add_class ("big-popover"); 36 | } 37 | else 38 | { 39 | placeholder_image.pixel_size = 36; 40 | get_style_context ().remove_class ("big-popover"); 41 | } 42 | } 43 | } 44 | 45 | construct 46 | { 47 | placeholder_image.icon_name = icon_name; 48 | } 49 | 50 | internal RegistryPlaceholder (string _icon_name, string _label, bool _big) 51 | { 52 | Object (icon_name:_icon_name, label: _label, big: _big); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /editor/dconf-editor.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | adaptative-window.ui 5 | base-headerbar.ui 6 | base-view.ui 7 | base-window.css 8 | base-window.ui 9 | bookmark.ui 10 | bookmarks.ui 11 | bookmarks-controller.ui 12 | browser-infobar.ui 13 | browser-stack.ui 14 | dconf-editor.css 15 | delayed-setting-view.ui 16 | filter-list-box-row.ui 17 | folder-list-box-row.ui 18 | key-list-box-row.ui 19 | large-pathbar.css 20 | large-pathbar.ui 21 | large-pathbar-item.ui 22 | modifications-revealer.ui 23 | notifications-revealer.ui 24 | overlayed-list.ui 25 | pathentry.ui 26 | pathwidget.ui 27 | property-row.ui 28 | registry-info.ui 29 | registry-list.ui 30 | registry-placeholder.ui 31 | return-list-box-row.ui 32 | search-list-box-row.ui 33 | short-pathbar.ui 34 | 35 | 36 | help-overlay.ui 37 | 38 | 39 | -------------------------------------------------------------------------------- /editor/icons/hicolor/scalable/actions/ca.desrt.dconf-editor.big-rows-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 37 | 42 | 47 | 48 | 56 | 57 | -------------------------------------------------------------------------------- /editor/notifications-revealer.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/notifications-revealer.ui")] 21 | private class NotificationsRevealer : Revealer, AdaptativeWidget 22 | { 23 | [GtkChild] private unowned Label notification_label; 24 | 25 | construct 26 | { 27 | install_action_entries (); 28 | } 29 | 30 | /*\ 31 | * * internal calls 32 | \*/ 33 | 34 | internal void show_notification (string notification) 35 | { 36 | notification_label.set_text (notification); 37 | set_reveal_child (true); 38 | } 39 | 40 | private bool is_thin = false; 41 | private void set_window_size (AdaptativeWidget.WindowSize new_size) 42 | { 43 | bool _is_thin = AdaptativeWidget.WindowSize.is_quite_thin (new_size); 44 | if (is_thin == _is_thin) 45 | return; 46 | is_thin = _is_thin; 47 | 48 | if (_is_thin) 49 | { 50 | hexpand = true; 51 | halign = Align.FILL; 52 | } 53 | else 54 | { 55 | hexpand = false; 56 | halign = Align.CENTER; 57 | } 58 | } 59 | 60 | /*\ 61 | * * action entries 62 | \*/ 63 | 64 | private void install_action_entries () 65 | { 66 | SimpleActionGroup action_group = new SimpleActionGroup (); 67 | action_group.add_action_entries (action_entries, this); 68 | insert_action_group ("notification", action_group); 69 | } 70 | 71 | private const GLib.ActionEntry [] action_entries = 72 | { 73 | { "hide", hide_notification } 74 | }; 75 | 76 | internal void hide_notification (/* SimpleAction action, Variant? variant */) 77 | { 78 | set_reveal_child (false); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /editor/browser-content.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private interface BrowserContent : Widget, AdaptativeWidget 21 | { 22 | [CCode (notify = false)] internal abstract ViewType current_view { internal get; protected set; } 23 | 24 | internal abstract void prepare_folder_view (GLib.ListStore key_model, bool is_ancestor); 25 | internal abstract void prepare_object_view (string full_name, uint16 context_id, Variant properties, bool is_parent); 26 | internal abstract void set_path (ViewType type, string path); 27 | 28 | /*\ 29 | * * current row stuff 30 | \*/ 31 | 32 | internal abstract string get_selected_row_name (); 33 | internal abstract void select_row_named (string selected, uint16 last_context_id, bool grab_focus_if_needed); 34 | internal abstract void select_first_row (); 35 | internal abstract void row_grab_focus (); 36 | /*\ 37 | * * popovers 38 | \*/ 39 | 40 | internal abstract bool toggle_row_popover (); 41 | internal abstract void discard_row_popover (); 42 | internal abstract void invalidate_popovers (); 43 | 44 | /*\ 45 | * * reload 46 | \*/ 47 | 48 | internal abstract bool check_reload_folder (Variant? fresh_key_model); 49 | internal abstract bool check_reload_object (uint properties_hash); 50 | 51 | /*\ 52 | * * keyboard calls 53 | \*/ 54 | 55 | internal abstract bool handle_copy_text (out string copy_text); // c 56 | internal abstract bool handle_alt_copy_text (out string copy_text); // C 57 | 58 | internal abstract bool next_match (); // g 59 | internal abstract bool previous_match (); // G 60 | 61 | internal abstract bool return_pressed (); // Return or KP_Enter 62 | } 63 | -------------------------------------------------------------------------------- /editor/browser-infobar.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/browser-infobar.ui")] 21 | private class BrowserInfoBar : Revealer 22 | { 23 | [GtkChild] private unowned Stack content; 24 | 25 | internal void add_label (string name, string text_label, string? button_label = null, string button_action = "") 26 | { 27 | RegistryWarning grid = new RegistryWarning (); 28 | 29 | Label label = new Label (text_label); 30 | label.hexpand = true; 31 | label.max_width_chars = 40; 32 | label.wrap = true; 33 | 34 | if (button_label != null) 35 | { 36 | if (button_action == "") 37 | assert_not_reached (); 38 | 39 | Button button = new Button (); 40 | button.label = (!) button_label; 41 | button.set_detailed_action_name (button_action); 42 | 43 | label.set_xalign ((float) 0.0); 44 | grid.add (label); 45 | grid.add (button); 46 | } 47 | else 48 | { 49 | label.set_xalign ((float) 0.5); 50 | grid.add (label); 51 | } 52 | 53 | grid.show_all (); 54 | content.add_named (grid, name); 55 | } 56 | 57 | internal void hide_warning () 58 | { 59 | set_reveal_child (false); 60 | } 61 | 62 | internal bool is_shown (string name) 63 | { 64 | return get_child_revealed () && (content.get_visible_child_name () == name); 65 | } 66 | 67 | internal void show_warning (string name) 68 | { 69 | if (!get_child_revealed ()) 70 | { 71 | content.set_transition_type (StackTransitionType.NONE); 72 | content.set_visible_child_name (name); 73 | set_reveal_child (true); 74 | } 75 | else if (content.get_visible_child_name () != name) 76 | { 77 | content.set_transition_type (StackTransitionType.SLIDE_DOWN); 78 | content.set_visible_child_name (name); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /editor/short-pathbar.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 67 | 68 | -------------------------------------------------------------------------------- /editor/notifications-revealer.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 70 | 71 | -------------------------------------------------------------------------------- /editor/bookmarks-controller.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/bookmarks-controller.ui")] 21 | private class BookmarksController : Grid 22 | { 23 | [GtkChild] private unowned Image big_rows_icon; 24 | [GtkChild] private unowned Image small_rows_icon; 25 | 26 | [GtkChild] private unowned Button rows_size_button; 27 | [CCode (notify = false)] public bool show_rows_size_button { private get; construct; default = false; } 28 | 29 | [GtkChild] private unowned Button trash_bookmark_button; 30 | [GtkChild] private unowned Button move_top_button; 31 | [GtkChild] private unowned Button move_up_button; 32 | [GtkChild] private unowned Button move_down_button; 33 | [GtkChild] private unowned Button move_bottom_button; 34 | [CCode (notify = false)] public string controller_action_prefix 35 | { 36 | construct 37 | { 38 | // TODO sanitize "value" 39 | trash_bookmark_button.set_detailed_action_name (value + ".trash-bookmark"); 40 | move_top_button.set_detailed_action_name (value + ".move-top"); 41 | move_up_button.set_detailed_action_name (value + ".move-up"); 42 | move_down_button.set_detailed_action_name (value + ".move-down"); 43 | move_bottom_button.set_detailed_action_name (value + ".move-bottom"); 44 | } 45 | } 46 | 47 | construct 48 | { 49 | if (show_rows_size_button) // TODO construct instead of hiding 50 | rows_size_button.show (); 51 | else 52 | rows_size_button.hide (); 53 | } 54 | 55 | internal BookmarksController (string _controller_action_prefix, bool _show_rows_size_button) 56 | { 57 | Object (controller_action_prefix: _controller_action_prefix, show_rows_size_button: _show_rows_size_button); 58 | } 59 | 60 | internal void update_rows_size_button_icon (bool small_bookmarks_rows) 61 | { 62 | if (small_bookmarks_rows) 63 | rows_size_button.set_image (big_rows_icon); 64 | else 65 | rows_size_button.set_image (small_rows_icon); 66 | } 67 | 68 | internal bool get_small_rows_state () 69 | { 70 | return rows_size_button.get_image () == small_rows_icon; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /editor/overlayed-list.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 80 | 81 | -------------------------------------------------------------------------------- /editor/icons/hicolor/scalable/actions/ca.desrt.dconf-editor.small-rows-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 55 | 63 | 69 | 75 | 76 | 84 | 85 | -------------------------------------------------------------------------------- /editor/ca.desrt.dconf-editor.metainfo.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ca.desrt.dconf-editor 5 | 6 | CC0-1.0 7 | GPL-3.0+ 8 | 9 | Dconf Editor 10 | A graphical tool for editing the dconf database 11 | 12 | 13 |

14 | Dconf Editor is a tool to allow direct editing of the dconf configuration database. 15 | This is useful when developing applications that use these settings. 16 |

17 |

18 | Editing your configuration directly is an advanced feature and may cause applications to not work correctly. 19 |

20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | ​ 32 | 33 | 34 | 35 | 36 | https://gitlab.gnome.org/GNOME/dconf-editor/raw/master/editor/screenshot1.png 37 | Browse the keys used by installed applications 38 | 39 | 40 | https://gitlab.gnome.org/GNOME/dconf-editor/raw/master/editor/screenshot2.png 41 | Read keys descriptions and edit their values 42 | 43 | 44 | 45 | 46 | #68a5ff 47 | #0062d2 48 | 49 | 50 | https://apps.gnome.org/DconfEditor/ 51 | https://gitlab.gnome.org/GNOME/dconf-editor/issues 52 | https://l10n.gnome.org/module/dconf-editor/ 53 | https://gitlab.gnome.org/GNOME/dconf-editor 54 | 55 | https://www.gnome.org/donate/ 56 | https://welcome.gnome.org/app/DconfEditor/ 57 | arnaud.bonatti_at_gmail.com 58 | 59 | The GNOME Project 60 | 61 | 62 | 63 | 64 | 360 65 | offline-only 66 | 67 | 68 | keyboard 69 | pointing 70 | touch 71 | 72 | 73 | 74 | dconf-editor 75 | 76 | dconf-editor 77 | ca.desrt.dconf-editor.desktop 78 |
79 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project( 2 | 'dconf-editor', ['c', 'vala'], 3 | version: '49.0', 4 | license: 'GPL3+', 5 | default_options: [ 6 | 'buildtype=debugoptimized', 7 | 'warning_level=1' 8 | ], 9 | meson_version: '>= 0.59.0', 10 | ) 11 | 12 | dconf_editor_name = meson.project_name() 13 | dconf_editor_version = meson.project_version() 14 | 15 | dconf_editor_prefix = get_option('prefix') 16 | dconf_editor_bindir = join_paths(dconf_editor_prefix, get_option('bindir')) 17 | dconf_editor_datadir = join_paths(dconf_editor_prefix, get_option('datadir')) 18 | dconf_editor_localedir = join_paths(dconf_editor_prefix, get_option('localedir')) 19 | dconf_editor_mandir = join_paths(dconf_editor_prefix, get_option('mandir')) 20 | 21 | dconf_editor_pkgdatadir = join_paths(dconf_editor_datadir, dconf_editor_name) 22 | 23 | dconf_editor_gettext = 'dconf-editor' 24 | dconf_editor_namespace = 'ca.desrt.dconf-editor' 25 | 26 | cc = meson.get_compiler('c') 27 | valac = meson.get_compiler('vala') 28 | 29 | vala_req_version = '>= 0.40.0' 30 | 31 | assert(valac.version().version_compare(vala_req_version), 32 | 'vala ' + vala_req_version + ' is required') 33 | 34 | config_h = configuration_data() 35 | 36 | # package 37 | set_defines = [ 38 | ['PACKAGE', dconf_editor_name], 39 | ['PACKAGE_BUGREPORT', 'https://bugzilla.gnome.org/enter_bug.cgi?product=' + dconf_editor_name], 40 | ['PACKAGE_NAME', dconf_editor_name], 41 | ['PACKAGE_STRING', '@0@ @1@'.format(dconf_editor_name, dconf_editor_version)], 42 | ['PACKAGE_TARNAME', dconf_editor_name], 43 | ['PACKAGE_URL', 'https://wiki.gnome.org/Apps/DconfEditor'], 44 | ['PACKAGE_VERSION', dconf_editor_version], 45 | ['VERSION', dconf_editor_version], 46 | # i18n 47 | ['GETTEXT_PACKAGE', dconf_editor_gettext] 48 | ] 49 | 50 | foreach define: set_defines 51 | config_h.set_quoted(define[0], define[1]) 52 | endforeach 53 | 54 | # headers 55 | check_headers = [ 56 | ['HAVE_DLFCN_H', 'dlfcn.h'], 57 | ['HAVE_FLOAT_H', 'float.h'], 58 | ['HAVE_INTTYPES_H', 'inttypes.h'], 59 | ['HAVE_MEMORY_H', 'memory.h'], 60 | ['HAVE_STDINT_H', 'stdint.h'], 61 | ['HAVE_STDLIB_H', 'stdlib.h'], 62 | ['HAVE_STRINGS_H', 'strings.h'], 63 | ['HAVE_STRING_H', 'string.h'], 64 | ['HAVE_SYS_STAT_H', 'sys/stat.h'], 65 | ['HAVE_UNISTD_H', 'unistd.h'], 66 | # i18n 67 | ['HAVE_LOCALE_H', 'locale.h'] 68 | ] 69 | 70 | foreach header: check_headers 71 | if cc.has_header(header[1]) 72 | config_h.set(header[0], true) 73 | endif 74 | endforeach 75 | 76 | sys_types_h = cc.has_header('sys/types.h') 77 | config_h.set('HAVE_SYS_TYPES_H', sys_types_h) 78 | if not sys_types_h 79 | config_h.set('size_t', 'unsigned int') 80 | endif 81 | 82 | # functions 83 | check_functions = [ 84 | ['HAVE_MEMSET', 'memset'], 85 | ['HAVE_STRSTR', 'strstr'], 86 | # i18n 87 | ['HAVE_DCGETTEXT', 'dcgettext'], 88 | ['HAVE_GETTEXT', 'gettext'], 89 | ['HAVE_ICONV', 'iconv'], 90 | ['HAVE_SETLOCALE', 'setlocale'] 91 | ] 92 | 93 | if host_machine.system().contains('darwin') 94 | check_functions += [ 95 | ['HAVE_CFLOCALECOPYCURRENT', 'CFLocaleCopyCurrent'], 96 | ['HAVE_CFPREFERENCESCOPYAPPVALUE', 'CFPreferencesCopyAppValue'] 97 | ] 98 | endif 99 | 100 | foreach func: check_functions 101 | if cc.has_function(func[1]) 102 | config_h.set(func[0], true) 103 | endif 104 | endforeach 105 | 106 | # compiler flags 107 | add_project_arguments('-DHAVE_CONFIG_H', language: 'c') 108 | 109 | gnome = import('gnome') 110 | i18n = import('i18n') 111 | 112 | po_dir = join_paths(meson.source_root(), 'po') 113 | 114 | top_inc = include_directories('.') 115 | 116 | subdir('editor') 117 | subdir('po') 118 | 119 | configure_file( 120 | output: 'config.h', 121 | configuration: config_h 122 | ) 123 | 124 | gnome.post_install( 125 | glib_compile_schemas: true, 126 | gtk_update_icon_cache: true, 127 | update_desktop_database: true, 128 | ) 129 | -------------------------------------------------------------------------------- /editor/base-window.css: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | /*\ 19 | * * center widget revealers 20 | \*/ 21 | 22 | /* hack: fix the double space when the child of the revealer is hidden; 6px is the spacing of the centerwidget box */ 23 | .centerwidget:dir(ltr) .headerbar-revealer { padding-right:6px; } 24 | .centerwidget:dir(rtl) .headerbar-revealer { padding-left :6px; } 25 | 26 | .centerwidget:dir(ltr) { margin-right:-6px; } 27 | .centerwidget:dir(rtl) { margin-left :-6px; } 28 | 29 | /*\ 30 | * * app notification 31 | \*/ 32 | 33 | .extra-thin-window .app-notification, 34 | .thin-window .app-notification { 35 | border-radius:0; 36 | } 37 | 38 | /*\ 39 | * * overlaid list 40 | \*/ 41 | 42 | .vertical.overlayed-list.needs-padding > scrolledwindow > viewport > list { 43 | padding-bottom:0; 44 | transition:padding-bottom 0.3s, 45 | font-size 0.3s; 46 | } 47 | .vertical.overlayed-list.needs-padding > scrolledwindow > viewport > list:not(.empty-list) { 48 | padding-bottom:3rem; 49 | } 50 | .vertical.overlayed-list.needs-padding > .linked-circular { 51 | margin-bottom:0.3rem; 52 | } 53 | 54 | .horizontal.overlayed-list:dir(ltr).needs-padding > scrolledwindow > viewport > list > row { 55 | padding-right:calc(160px+1rem); /* width-request of edit_mode_box + a bit */ 56 | } 57 | .horizontal.overlayed-list:dir(rtl).needs-padding > scrolledwindow > viewport > list > row { 58 | padding-left :calc(160px+1rem); /* width-request of edit_mode_box + a bit */ 59 | } 60 | .horizontal.overlayed-list:dir(ltr).needs-padding > .linked-circular { 61 | margin-right:1.5rem; 62 | } 63 | .horizontal.overlayed-list:dir(rtl).needs-padding > .linked-circular { 64 | margin-left :1.5rem; 65 | } 66 | 67 | .vertical.overlayed-list:dir(rtl) > .linked-circular > .right-on-ltr, 68 | .vertical.overlayed-list:dir(ltr) > .linked-circular > .left-on-ltr { 69 | border-radius:2rem 0 0 2rem; 70 | -gtk-outline-top-left-radius :2rem; 71 | -gtk-outline-bottom-left-radius:2rem; 72 | } 73 | 74 | .vertical.overlayed-list:dir(ltr) > .linked-circular > .right-on-ltr, 75 | .vertical.overlayed-list:dir(rtl) > .linked-circular > .left-on-ltr { 76 | border-radius:0 2rem 2rem 0; 77 | -gtk-outline-top-right-radius :2rem; 78 | -gtk-outline-bottom-right-radius:2rem; 79 | } 80 | 81 | .horizontal.overlayed-list:dir(rtl) > .linked-circular > .right-on-ltr, 82 | .horizontal.overlayed-list:dir(ltr) > .linked-circular > .left-on-ltr { 83 | border-radius:1.5rem 1.5rem 0 0; 84 | -gtk-outline-top-right-radius:1.4rem; 85 | -gtk-outline-top-left-radius :1.4rem; 86 | } 87 | .horizontal.overlayed-list:dir(ltr) > .linked-circular > .right-on-ltr, 88 | .horizontal.overlayed-list:dir(rtl) > .linked-circular > .left-on-ltr { 89 | border-radius:0 0 1.5rem 1.5rem; 90 | -gtk-outline-bottom-right-radius:1.4rem; 91 | -gtk-outline-bottom-left-radius :1.4rem; 92 | } 93 | 94 | /*\ 95 | * * in-window about 96 | \*/ 97 | 98 | .about-list > scrolledwindow > viewport > list > row { 99 | min-height:1.3rem; 100 | } 101 | 102 | .about-list > scrolledwindow > viewport > list > row > label { 103 | margin:4px; 104 | } 105 | 106 | .about-list > scrolledwindow > viewport > list > row > button { 107 | margin-top:2px; 108 | margin-bottom:2px; 109 | } 110 | 111 | /*\ 112 | * * text formatting 113 | \*/ 114 | 115 | .small-label { 116 | font-size:small; 117 | } 118 | .bold-label { 119 | font-weight:bold; 120 | } 121 | .italic-label { 122 | font-style:italic; 123 | } 124 | 125 | .big-popover { 126 | font-size:144%; 127 | } 128 | 129 | /*\ 130 | * * the end 131 | \*/ 132 | -------------------------------------------------------------------------------- /editor/registry-view.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private class RegistryView : RegistryList 21 | { 22 | /* Translators: placeholder text of the keys list when there's nothing to display in a path (not used in current design) */ 23 | [CCode (notify = false)] public override string placeholder_label { protected get { return _("No keys in this path"); }} 24 | 25 | construct 26 | { 27 | search_mode = false; 28 | key_list_box.set_header_func (update_row_header); 29 | } 30 | 31 | /*\ 32 | * * Updating 33 | \*/ 34 | 35 | internal void set_key_model (GLib.ListStore key_model) 36 | { 37 | list_model = key_model; 38 | key_list_box.bind_model (list_model, new_list_box_row); 39 | modifications_handler.model.keys_value_push (); 40 | } 41 | 42 | internal bool check_reload (Variant? fresh_key_model) 43 | { 44 | if (fresh_key_model == null) 45 | return true; 46 | VariantIter iter = new VariantIter ((!) fresh_key_model); 47 | 48 | uint n_items = (uint) iter.n_children (); 49 | if (list_model.get_n_items () != n_items) 50 | return true; 51 | 52 | bool [] skip = new bool [n_items]; 53 | for (uint i = 0; i < n_items; i++) 54 | skip [i] = false; 55 | uint16 context_id; 56 | string name; 57 | while (iter.next ("(qs)", out context_id, out name)) 58 | { 59 | bool found = false; 60 | for (uint i = 0; i < list_model.get_n_items (); i++) 61 | { 62 | if (skip [i] == true) 63 | continue; 64 | 65 | SimpleSettingObject? setting_object = (SimpleSettingObject) list_model.get_item (i); 66 | if (setting_object == null) 67 | assert_not_reached (); 68 | 69 | if (((!) setting_object).context_id != context_id) 70 | continue; 71 | if (((!) setting_object).name != name) 72 | continue; 73 | 74 | /* FIXME // TODO compare other visible info (i.e. key type_string or summary [if not directories]) 75 | if (SettingsModel.is_key_path (fresh_key_model [j,2])) 76 | { 77 | if (((Key) (!) setting_object).type_string != ((Key) fresh_key_model [j]).type_string) 78 | continue; 79 | } */ 80 | found = true; 81 | skip [i] = true; 82 | break; 83 | } 84 | if (!found) 85 | return true; 86 | } 87 | for (uint i = 0; i < n_items; i++) 88 | if (skip [i] == false) 89 | return true; 90 | return false; 91 | } 92 | 93 | internal override void select_first_row () 94 | { 95 | uint n_items = list_model.get_n_items (); 96 | if (n_items == 0) 97 | assert_not_reached (); 98 | 99 | ListBoxRow? row; 100 | if (n_items == 2) 101 | row = key_list_box.get_row_at_index (1); 102 | else 103 | row = key_list_box.get_row_at_index (0); 104 | 105 | if (row == null) 106 | assert_not_reached (); 107 | key_list_box.select_row ((!) row); 108 | ((!) row).grab_focus (); 109 | } 110 | 111 | /*\ 112 | * * Key ListBox 113 | \*/ 114 | 115 | private void update_row_header (ListBoxRow row, ListBoxRow? before) 116 | { 117 | if (is_first_row (row.get_index (), before)) 118 | return; 119 | update_row_header_with_context (row, (!) before, modifications_handler.model, /* local search header */ false); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /editor/icons/hicolor/scalable/apps/ca.desrt.dconf-editor.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /editor/pathentry.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 104 | 105 | -------------------------------------------------------------------------------- /editor/modifications-revealer.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 102 | 103 | 104 | 300 105 | 550 106 | 109 | 110 | 111 | True 112 | True 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /editor/key-list-box-row.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 111 | 112 | -------------------------------------------------------------------------------- /editor/completion/dconf-editor: -------------------------------------------------------------------------------- 1 | 2 | # Check for bash 3 | [ -z "$BASH_VERSION" ] && return 4 | 5 | #################################################################################################### 6 | 7 | __dconf-editor() { 8 | function gen_paths() { 9 | local _cur=$1 10 | local _prefix=$2 11 | 12 | local dconf_choices="$(dconf _complete '' "${_cur}")" 13 | local gsettings_current_path="" 14 | local gsettings_choices="$(gsettings list-schemas --print-paths | 15 | cut -f2 -d" " | 16 | grep ^${_cur} | 17 | sed -e 's,^'"${_cur}"',,' | 18 | awk '{if($0 != "") {print $1} else if ("'"${_cur:0-1}"'" == "/") {print ""}}' | 19 | awk -F'/' '{if ($0 == "") {print ""} else if(($1 != "") AND ("'"${_cur:0-1}"'" != "/")) {print $1 "/"}}' | 20 | sed -e 's,.*,'"${_prefix} ${_cur}"'&,' )" 21 | local keys_choices="$(gsettings list-schemas --print-paths | 22 | awk -F' ' '{if ("'"${_cur%/*}/"'" == $2) {system("gsettings list-keys "$1)}}' | 23 | sed -e 's,.*,'"${_prefix} ${_cur%/*}/"'&,' )" 24 | 25 | echo "$(echo "$dconf_choices" " 26 | " "$gsettings_current_path" " 27 | " "$gsettings_choices" " 28 | " "$keys_choices" | 29 | sort | uniq)" 30 | } 31 | function gen_fixed() { 32 | local _cur=$1 33 | local _prefix=$2 34 | 35 | echo "$(gsettings list-schemas | 36 | grep ^${_cur} | 37 | sed -e 's,^'"${_cur}"',,' | 38 | awk -F'.' '{if ($2 != "") {print $1 "."} else {print $1}}' | 39 | sed -e 's,.*,'"${_prefix} ${_cur}"'&,' | 40 | sort | uniq)" 41 | } 42 | function gen_reloc() { 43 | local _cur=$1 44 | local _prefix=$2 45 | 46 | echo "$(gsettings list-relocatable-schemas | 47 | grep ^${_cur} | 48 | sed -e 's,^'"${_cur}"',,' | 49 | awk -F'.' '{if ($2 != "") {print $1 "."} else {print $1 "\\\\:/"}}' | 50 | sed -e 's,.*,'"${_prefix} ${_cur}"'&,' | 51 | sort | uniq)" 52 | } 53 | function gen_schemas() { 54 | local _cur=$1 55 | local _prefix=$2 56 | 57 | echo "$(echo "$(gen_fixed $1 $2)" " 58 | " "$(gen_reloc $1 $2)" | sort | uniq)" 59 | } 60 | function gen_keys() { 61 | local _schema=$1 62 | 63 | echo "$(gsettings list-keys "${_schema}" | 64 | sort)" 65 | } 66 | 67 | local cur="${COMP_WORDS[COMP_CWORD]}" 68 | local complist="" 69 | local nosoloopt="--I-understand-that-changing-options-can-break-applications" 70 | 71 | if [[ "${COMP_CWORD}" == "1" ]]; then 72 | if [[ "${cur}" == "${nosoloopt}" ]]; then 73 | local IFS=$'\n' 74 | complist="$(gen_paths "/" "${nosoloopt}") $(gen_schemas "" "${nosoloopt}")" 75 | 76 | else 77 | local soloopts="--help 78 | --list-relocatable-schemas 79 | --version" 80 | 81 | if [[ "${cur}" == -* ]]; then complist="${soloopts} ${nosoloopt}" 82 | elif [[ "${cur}" == "" ]]; then complist="${soloopts} ${nosoloopt} $(gen_paths "/" ) $(gen_schemas "" )" 83 | elif [[ "${cur}" == /* ]]; then complist=" $(gen_paths "${cur}") " 84 | else complist=" $(gen_schemas "${cur}")" 85 | fi 86 | fi 87 | 88 | elif [[ "${COMP_CWORD}" == "2" ]]; then 89 | local prim="${COMP_WORDS[1]}" 90 | 91 | if [[ "${prim:0:1}" == "/" ]]; then 92 | complist="${nosoloopt}" 93 | elif [[ ("$(gsettings list-schemas | grep ^"${prim}" )" != "") || 94 | ("$(gsettings list-relocatable-schemas | grep ^"$(echo "${prim}" | awk -F':' '{print substr($1, 1, length($1)-1)}')")" != "") ]]; then 95 | complist="${nosoloopt} $(gen_keys "$(echo "${prim}" | awk -F':' '{if (substr($1, length($1)) == "\\") {print substr($1, 1, length($1)-1)} else {print $1}}')")" 96 | 97 | elif [[ "${prim}" == "${nosoloopt}" ]]; then 98 | if [[ "${cur}" == "" ]]; then complist=" $(gen_paths "/" ) $(gen_schemas "" )" 99 | elif [[ "${cur}" == /* ]]; then complist=" $(gen_paths "${cur}") " 100 | else complist=" $(gen_schemas "${cur}")" 101 | fi 102 | fi 103 | 104 | elif [[ "${COMP_CWORD}" == "3" ]]; then 105 | local prim="${COMP_WORDS[1]}" 106 | 107 | if [[ "${prim}" == "${nosoloopt}" ]]; then 108 | complist="$(gen_keys "${COMP_WORDS[2]}")" 109 | elif [[ ("$(gsettings list-schemas | grep ^"${prim}")" != "") && ("${COMP_WORDS[2]}" != "${nosoloopt}") ]]; then 110 | complist="${nosoloopt}" 111 | fi 112 | 113 | # problem with paths containing a ':', considered having four words or more 114 | fi 115 | COMPREPLY=($(compgen -o nosort -W "${complist}" -- "${cur}")) 116 | return 0 117 | } 118 | 119 | #################################################################################################### 120 | 121 | complete -o nospace -o nosort -F __dconf-editor dconf-editor 122 | -------------------------------------------------------------------------------- /editor/base-headerbar.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 131 | 132 | -------------------------------------------------------------------------------- /editor/bookmarks-controller.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | True 22 | ca.desrt.dconf-editor.big-rows-symbolic 23 | 1 24 | 25 | 26 | True 27 | ca.desrt.dconf-editor.small-rows-symbolic 28 | 1 29 | 30 | 131 | 132 | -------------------------------------------------------------------------------- /editor/base-view.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/base-view.ui")] 21 | private class BaseView : Stack, AdaptativeWidget 22 | { 23 | [GtkChild] protected unowned Grid main_grid; 24 | 25 | internal virtual bool handle_copy_text (out string copy_text) 26 | { 27 | if (in_window_about) 28 | return about_list.handle_copy_text (out copy_text); // TODO copying logo... 29 | else 30 | return BaseWindow.no_copy_text (out copy_text); 31 | } 32 | 33 | internal virtual void close_popovers () {} 34 | 35 | /*\ 36 | * * adaptative stuff 37 | \*/ 38 | 39 | protected AdaptativeWidget.WindowSize saved_window_size { protected get; private set; default = AdaptativeWidget.WindowSize.START_SIZE; } 40 | protected virtual void set_window_size (AdaptativeWidget.WindowSize new_size) 41 | { 42 | saved_window_size = new_size; 43 | if (about_list_created) 44 | about_list.set_window_size (new_size); 45 | if (notifications_revealer_created) 46 | notifications_revealer.set_window_size (new_size); 47 | } 48 | 49 | /*\ 50 | * * in-window modes 51 | \*/ 52 | 53 | internal virtual void show_default_view () 54 | { 55 | if (in_window_about) 56 | { 57 | in_window_about = false; 58 | set_visible_child (notifications_overlay); // or set_visible_child_name ("main-view"); 59 | } 60 | else 61 | assert_not_reached (); 62 | } 63 | 64 | internal virtual bool is_in_in_window_mode () 65 | { 66 | return in_window_about; 67 | } 68 | 69 | /*\ 70 | * * in-window about 71 | \*/ 72 | 73 | protected bool in_window_about { protected get; private set; default = false; } 74 | 75 | private bool about_list_created = false; 76 | private AboutList about_list; 77 | 78 | internal void create_about_list (ref string [] artists, 79 | ref string [] authors, 80 | ref string comments, 81 | ref string copyright, 82 | ref string [] documenters, 83 | ref string logo_icon_name, 84 | ref string program_name, 85 | ref string translator_credits, 86 | ref string version, 87 | ref string website, 88 | ref string website_label) 89 | { 90 | about_list = new AboutList (/* needs shadows */ false, 91 | /* big placeholder */ true, 92 | ref artists, ref authors, ref comments, ref copyright, ref documenters, ref logo_icon_name, ref program_name, ref translator_credits, ref version, ref website, ref website_label); 93 | about_list.set_window_size (saved_window_size); 94 | about_list.show (); 95 | add (about_list); 96 | about_list_created = true; 97 | } 98 | 99 | internal void show_about_view () 100 | requires (about_list_created == true) 101 | requires (in_window_about == false) 102 | { 103 | about_list.reset (); 104 | set_visible_child (about_list); 105 | in_window_about = true; 106 | } 107 | 108 | /*\ 109 | * * notifications 110 | \*/ 111 | 112 | [GtkChild] private unowned Overlay notifications_overlay; 113 | 114 | private bool notifications_revealer_created = false; 115 | private NotificationsRevealer notifications_revealer; 116 | 117 | private void create_notifications_revealer () 118 | { 119 | notifications_revealer = new NotificationsRevealer (); 120 | notifications_revealer.set_window_size (saved_window_size); 121 | notifications_revealer.show (); 122 | notifications_overlay.add_overlay (notifications_revealer); 123 | notifications_overlay.set_overlay_pass_through (notifications_revealer, true); 124 | notifications_revealer_created = true; 125 | } 126 | 127 | internal void show_notification (string notification) 128 | { 129 | if (!notifications_revealer_created) 130 | create_notifications_revealer (); 131 | 132 | notifications_revealer.show_notification (notification); 133 | } 134 | 135 | internal void hide_notification () 136 | { 137 | if (!notifications_revealer_created) 138 | return; 139 | 140 | notifications_revealer.hide_notification (); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /editor/meson.build: -------------------------------------------------------------------------------- 1 | desktop = dconf_editor_namespace + '.desktop' 2 | 3 | i18n.merge_file ( 4 | type: 'desktop', 5 | input: desktop + '.in', 6 | output: desktop, 7 | po_dir: po_dir, 8 | install: true, 9 | install_dir: join_paths(dconf_editor_datadir, 'applications') 10 | ) 11 | 12 | service_conf = configuration_data() 13 | service_conf.set('bindir', dconf_editor_bindir) 14 | 15 | service = dconf_editor_namespace + '.service' 16 | 17 | configure_file( 18 | input: service + '.in', 19 | output: service, 20 | install: true, 21 | install_dir: join_paths(dconf_editor_datadir, 'dbus-1', 'services'), 22 | configuration: service_conf 23 | ) 24 | 25 | appdata = dconf_editor_namespace + '.metainfo.xml' 26 | 27 | appdata_file = i18n.merge_file( 28 | input: appdata + '.in', 29 | output: appdata, 30 | po_dir: po_dir, 31 | install: true, 32 | install_dir: join_paths(dconf_editor_datadir, 'metainfo') 33 | ) 34 | 35 | appstreamcli = find_program('appstreamcli', required: false) 36 | if appstreamcli.found() 37 | test( 38 | 'validate-appdata', appstreamcli, 39 | args: ['validate', '--no-net', '--explain', appdata_file.full_path()], 40 | ) 41 | endif 42 | 43 | gschema = dconf_editor_namespace + '.gschema.xml' 44 | dconf_editor_schemadir = join_paths(dconf_editor_datadir, 'glib-2.0', 'schemas') 45 | install_data( 46 | gschema, 47 | install_dir: dconf_editor_schemadir 48 | ) 49 | 50 | xmllint = find_program('xmllint', required : false) 51 | if xmllint.found() 52 | test('test_dtd', xmllint, args: ['--valid', 53 | '--noout', '--nowarning', 54 | join_paths(meson.current_source_dir(), gschema)]) 55 | else 56 | message('xmllint not found, no gschema DTD verification') 57 | endif 58 | 59 | install_subdir( 60 | 'icons', 61 | install_dir: dconf_editor_datadir 62 | ) 63 | 64 | install_data( 65 | dconf_editor_name + '.1', 66 | install_dir: join_paths(dconf_editor_mandir, 'man1') 67 | ) 68 | 69 | install_data( 70 | 'completion/dconf-editor', 71 | install_dir: join_paths(dconf_editor_datadir, 'bash-completion', 'completions') 72 | ) 73 | 74 | sources = files( 75 | 'about-list.vala', 76 | 'adaptative-pathbar.vala', 77 | 'adaptative-window.vala', 78 | 'base-headerbar.vala', 79 | 'base-view.vala', 80 | 'base-window.vala', 81 | 'bookmarks.vala', 82 | 'bookmarks-controller.vala', 83 | 'bookmarks-headerbar.vala', 84 | 'bookmarks-list.vala', 85 | 'bookmarks-view.vala', 86 | 'bookmarks-window.vala', 87 | 'browser-content.vala', 88 | 'browser-headerbar.vala', 89 | 'browser-infobar.vala', 90 | 'browser-stack.vala', 91 | 'browser-view.vala', 92 | 'browser-window.vala', 93 | 'dconf-editor.vala', 94 | 'dconf-headerbar.vala', 95 | 'dconf-model.vala', 96 | 'dconf-view.vala', 97 | 'dconf-window.vala', 98 | 'delayed-setting-view.vala', 99 | 'key-editor-child.vala', 100 | 'key-list-box-row.vala', 101 | 'large-pathbar.vala', 102 | 'model-utils.vala', 103 | 'modifications-handler.vala', 104 | 'modifications-list.vala', 105 | 'modifications-revealer.vala', 106 | 'notifications-revealer.vala', 107 | 'overlayed-list.vala', 108 | 'pathentry.vala', 109 | 'pathwidget.vala', 110 | 'registry-info.vala', 111 | 'registry-list.vala', 112 | 'registry-placeholder.vala', 113 | 'registry-search.vala', 114 | 'registry-view.vala', 115 | 'schemas-utility.vala', 116 | 'setting-object.vala', 117 | 'short-pathbar.vala', 118 | 'source-manager.vala' 119 | ) 120 | 121 | css_data = files( 122 | 'base-window.css', 123 | 'dconf-editor.css', 124 | 'large-pathbar.css' 125 | ) 126 | 127 | ui_data = files( 128 | 'adaptative-window.ui', 129 | 'base-headerbar.ui', 130 | 'base-view.ui', 131 | 'base-window.ui', 132 | 'bookmarks.ui', 133 | 'bookmarks-controller.ui', 134 | 'bookmark.ui', 135 | 'browser-infobar.ui', 136 | 'browser-stack.ui', 137 | 'delayed-setting-view.ui', 138 | 'filter-list-box-row.ui', 139 | 'folder-list-box-row.ui', 140 | 'help-overlay.ui', 141 | 'key-list-box-row.ui', 142 | 'large-pathbar-item.ui', 143 | 'large-pathbar.ui', 144 | 'modifications-revealer.ui', 145 | 'notifications-revealer.ui', 146 | 'overlayed-list.ui', 147 | 'pathentry.ui', 148 | 'pathwidget.ui', 149 | 'property-row.ui', 150 | 'registry-info.ui', 151 | 'registry-list.ui', 152 | 'registry-placeholder.ui', 153 | 'return-list-box-row.ui', 154 | 'search-list-box-row.ui', 155 | 'short-pathbar.ui' 156 | ) 157 | 158 | resource_data = css_data + ui_data 159 | 160 | sources += gnome.compile_resources( 161 | 'resources', 162 | dconf_editor_name + '.gresource.xml', 163 | dependencies: resource_data, 164 | export: true 165 | ) 166 | 167 | deps = [ 168 | dependency('dconf', version: '>= 0.26.1'), 169 | dependency('glib-2.0', version: '>= 2.56.0'), 170 | dependency('gmodule-2.0'), 171 | dependency('gtk+-3.0', version: '>= 3.22.27'), 172 | dependency('libhandy-1', version: '>= 1.6'), 173 | valac.find_library('config', dirs: meson.current_source_dir()), 174 | valac.find_library('posix') 175 | ] 176 | 177 | cflags = [ 178 | '-DPKGDATADIR="@0@"'.format(dconf_editor_pkgdatadir), 179 | '-DVERSION="@0@"'.format(dconf_editor_version), 180 | '-DLOCALEDIR="@0@"'.format(dconf_editor_localedir), 181 | '-DGETTEXT_PACKAGE="@0@"'.format(dconf_editor_gettext), 182 | '-w' 183 | ] 184 | 185 | executable( 186 | dconf_editor_name, 187 | sources, 188 | include_directories: top_inc, 189 | dependencies: deps, 190 | c_args: cflags, 191 | vala_args: '--enable-experimental-non-null', 192 | install: true, 193 | install_dir: dconf_editor_bindir 194 | ) 195 | -------------------------------------------------------------------------------- /editor/pathwidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 117 | 118 | -------------------------------------------------------------------------------- /editor/large-pathbar.css: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | /*\ 19 | * * main large-window stuff 20 | \*/ 21 | 22 | .pathbar { 23 | border-width:1px; 24 | border-style:solid; 25 | border-radius:3px; 26 | 27 | padding:0; 28 | margin:6px 0; 29 | 30 | /* nautilus/src/resources/css/Adwaita.css:71 .path-bar-box uses 200ms */ 31 | transition: background-color 0.3s, 32 | color 0.3s, 33 | border-color 0.3s; 34 | border-color:transparent; 35 | } 36 | 37 | .large-window .pathbar { 38 | background-color:@theme_bg_color; 39 | color :@theme_fg_color; 40 | border-color :@borders; 41 | } 42 | 43 | .large-window:backdrop .pathbar { 44 | background-color:@theme_unfocused_bg_color; 45 | color :@theme_unfocused_fg_color; 46 | border-color :@unfocused_borders; 47 | } 48 | 49 | /*\ 50 | * * items generic init and hacks 51 | \*/ 52 | 53 | /* transition hacks */ 54 | box.pathbar > button, 55 | box.pathbar > label { 56 | transition:all 0 ease; 57 | } 58 | 59 | /* button config */ 60 | .pathbar > button { 61 | padding:0 0.1em; 62 | margin :0 0.1em; 63 | 64 | outline-offset:-4px; 65 | 66 | border-radius:0; 67 | 68 | border:none; 69 | border-color:transparent; 70 | box-shadow:none; 71 | background:none; 72 | background-color:transparent; 73 | color:currentColor; 74 | } 75 | 76 | button.invisible { 77 | padding:0; 78 | min-width:0; 79 | 80 | border:none; 81 | border-color:transparent; 82 | box-shadow:none; 83 | background:none; 84 | background-color:transparent; 85 | color:currentColor; 86 | } 87 | 88 | button.invisible.invisible-menu-button { 89 | background-repeat:no-repeat; 90 | background-size:1.1rem; 91 | background-image:-gtk-icontheme("pan-down-symbolic"); 92 | } 93 | button.invisible.invisible-menu-button:dir(ltr) { padding-left :1.4rem; background-position:0 center; } 94 | button.invisible.invisible-menu-button:dir(rtl) { padding-right:1.4rem; background-position:100% center; } 95 | 96 | /* items hacks */ 97 | .thin-window.startup .pathbar > button > label.item { /* class remove after 0.3s */ 98 | transition:padding 0s; 99 | } 100 | 101 | .thin-window .pathbar > button > label.item { 102 | padding:2px 1px; 103 | } 104 | 105 | /*\ 106 | * * border bottom 107 | \*/ 108 | 109 | .pathbar > button > label.item { 110 | border-width:3px 2px; 111 | border-radius:0; 112 | padding:2px 4px; 113 | border-style:solid; 114 | border-color:transparent; 115 | transition:border-bottom-color 0.3s, 116 | padding 0.2s; /* needs to be a bit faster */ 117 | } 118 | 119 | .pathbar > button:hover > label.item { 120 | border-bottom-color:alpha(currentColor, 0.15); 121 | } 122 | 123 | .pathbar > button.active > label.item, 124 | .pathbar > button.active:hover > label.item, 125 | .pathbar > button.active.inexistent > label.item, 126 | .pathbar > button.active.inexistent:hover > label.item { 127 | border-bottom-color:@theme_selected_bg_color; 128 | } 129 | 130 | .pathbar:backdrop > button.active > label.item, 131 | .pathbar:backdrop > button.active:hover > label.item, 132 | .pathbar:backdrop > button.active.inexistent > label.item, 133 | .pathbar:backdrop > button.active.inexistent:hover > label.item { 134 | border-bottom-color:alpha(currentColor, 0.15); 135 | } 136 | 137 | .pathbar > button.inexistent:not(.active):hover > label.item { 138 | border-bottom-color:transparent; 139 | } 140 | 141 | .pathbar.config > button.active > label.item { 142 | border-bottom-style:dashed; 143 | } 144 | 145 | /*\ 146 | * * root button 147 | \*/ 148 | 149 | /* general stuff */ 150 | .pathbar > button.root-button > label.item { 151 | padding-left:3px; 152 | transition:border-width 0 ease, padding 0 ease; 153 | background-position:50% center; 154 | margin-left:0; 155 | margin-right:0; 156 | background-image:-gtk-icontheme("ca.desrt.dconf-editor-symbolic"); 157 | background-size:1.1rem; 158 | background-repeat:no-repeat; 159 | min-width:1.1rem; 160 | } 161 | 162 | .large-window .pathbar > button.root-button > label.item { 163 | padding-left:5px; 164 | border-left-width:0; 165 | background-position:60% center; 166 | } 167 | 168 | /* rtl/ltr specificities */ 169 | .pathbar:dir(ltr) > button.root-button { padding-left :0; margin-left :0; } 170 | .pathbar:dir(rtl) > button.root-button { padding-right:0; margin-right:0; } 171 | 172 | /*\ 173 | * * special texts "colors" 174 | \*/ 175 | 176 | /* slash */ 177 | .pathbar > label { 178 | opacity:0.55; 179 | } 180 | .pathbar:backdrop > label { 181 | opacity:0.8; 182 | } 183 | 184 | /* removed paths */ 185 | .pathbar > button.inexistent:not(.active) > label.item { 186 | opacity:0.7; 187 | } 188 | .pathbar:backdrop > button.inexistent:not(.active) > label.item { 189 | opacity:1.0; 190 | } 191 | 192 | /*\ 193 | * * the end 194 | \*/ 195 | -------------------------------------------------------------------------------- /editor/bookmarks-view.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private class BookmarksView : BrowserView, AdaptativeWidget 21 | { 22 | construct 23 | { 24 | create_bookmarks_list (); 25 | } 26 | 27 | protected override void set_window_size (AdaptativeWidget.WindowSize new_size) 28 | { 29 | base.set_window_size (new_size); 30 | 31 | bookmarks_list.set_window_size (new_size); 32 | } 33 | 34 | internal override bool is_in_in_window_mode () 35 | { 36 | return (in_window_bookmarks || base.is_in_in_window_mode ()); 37 | } 38 | 39 | internal override void show_default_view () 40 | { 41 | if (in_window_bookmarks) 42 | { 43 | if (in_window_bookmarks_edit_mode) 44 | leave_bookmarks_edit_mode (); 45 | in_window_bookmarks = false; 46 | set_visible_child_name ("main-view"); 47 | } 48 | else 49 | base.show_default_view (); 50 | } 51 | 52 | /*\ 53 | * * bookmarks view 54 | \*/ 55 | 56 | [CCode (notify = false)] internal bool in_window_bookmarks { internal get; private set; default = false; } 57 | [CCode (notify = false)] internal bool in_window_bookmarks_edit_mode { internal get; private set; default = false; } 58 | 59 | private BookmarksList bookmarks_list; 60 | 61 | private void create_bookmarks_list () 62 | { 63 | bookmarks_list = new BookmarksList (/* needs shadows */ false, 64 | /* big placeholder */ true, 65 | /* edit-mode action prefix */ "bmk", 66 | /* schema path */ "/ca/desrt/dconf-editor/"); 67 | bookmarks_list.selection_changed.connect (on_bookmarks_selection_changed); 68 | bookmarks_list.update_bookmarks_icons.connect (on_update_bookmarks_icons); 69 | bookmarks_list.show (); 70 | add (bookmarks_list); 71 | } 72 | 73 | private string [] old_bookmarks = new string [0]; 74 | 75 | internal void show_bookmarks_view (string [] bookmarks) 76 | { 77 | if (is_in_in_window_mode ()) 78 | show_default_view (); 79 | 80 | bookmarks_list.reset (); 81 | 82 | if (bookmarks != old_bookmarks) 83 | { 84 | Variant variant = new Variant.strv (bookmarks); 85 | bookmarks_list.create_bookmark_rows (variant); 86 | 87 | old_bookmarks = bookmarks; 88 | } 89 | set_visible_child (bookmarks_list); 90 | in_window_bookmarks = true; 91 | } 92 | 93 | internal void update_bookmark_icon (string bookmark, BookmarkIcon icon) 94 | { 95 | bookmarks_list.update_bookmark_icon (bookmark, icon); 96 | } 97 | 98 | /*\ 99 | * * edit mode 100 | \*/ 101 | 102 | internal void enter_bookmarks_edit_mode () 103 | requires (in_window_bookmarks == true) 104 | { 105 | bookmarks_list.enter_edit_mode (); 106 | in_window_bookmarks_edit_mode = true; 107 | } 108 | 109 | internal bool leave_bookmarks_edit_mode () 110 | requires (in_window_bookmarks == true) 111 | { 112 | in_window_bookmarks_edit_mode = false; 113 | return bookmarks_list.leave_edit_mode (); 114 | } 115 | 116 | internal OverlayedList.SelectionState get_bookmarks_selection_state () 117 | { 118 | return bookmarks_list.get_selection_state (); 119 | } 120 | 121 | internal void trash_bookmark () 122 | { 123 | bookmarks_list.trash_bookmark (); 124 | } 125 | 126 | internal void move_top () 127 | { 128 | bookmarks_list.move_top (); 129 | } 130 | 131 | internal void move_up () 132 | { 133 | bookmarks_list.move_up (); 134 | } 135 | 136 | internal void move_down () 137 | { 138 | bookmarks_list.move_down (); 139 | } 140 | 141 | internal void move_bottom () 142 | { 143 | bookmarks_list.move_bottom (); 144 | } 145 | 146 | /*\ 147 | * * callbacks 148 | \*/ 149 | 150 | private void on_bookmarks_selection_changed () 151 | { 152 | if (!in_window_bookmarks) 153 | return; 154 | bookmarks_selection_changed (); 155 | } 156 | 157 | internal signal void bookmarks_selection_changed (); 158 | 159 | internal signal void update_bookmarks_icons (Variant bookmarks_variant); 160 | private void on_update_bookmarks_icons (Variant bookmarks_variant) 161 | { 162 | update_bookmarks_icons (bookmarks_variant); 163 | } 164 | 165 | /*\ 166 | * * keyboard calls 167 | \*/ 168 | 169 | internal override bool next_match () 170 | { 171 | if (in_window_bookmarks) 172 | return bookmarks_list.next_match (); 173 | return base.next_match (); 174 | } 175 | 176 | internal override bool previous_match () 177 | { 178 | if (in_window_bookmarks) 179 | return bookmarks_list.previous_match (); 180 | return base.previous_match (); 181 | } 182 | 183 | internal override bool handle_copy_text (out string copy_text) 184 | { 185 | if (in_window_bookmarks) 186 | return bookmarks_list.handle_copy_text (out copy_text); 187 | return base.handle_copy_text (out copy_text); 188 | } 189 | 190 | internal override bool toggle_row_popover () // Menu 191 | { 192 | if (in_window_bookmarks) 193 | return false; 194 | return base.toggle_row_popover (); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /editor/modifications-list.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private class ModificationsList : OverlayedList 21 | { 22 | construct 23 | { 24 | get_style_context ().add_class ("delayed-list"); 25 | 26 | placeholder_icon = "document-open-recent-symbolic"; 27 | /* Translators: placeholder text of the list of pending modifications, displayed when the user is in delayed mode but has no pending modifications */ 28 | placeholder_text = _("Delayed mode is on\nbut\nno pending changes"); 29 | add_placeholder (); 30 | 31 | /* Translators: label of one of the two buttons of the list of pending modifications, to switch between applying changes to the whole list and selecting some items for more advanced things (not displayed currently, but this change is wanted); the second is "Select" */ 32 | first_mode_name = _("Rule all"); 33 | /* Translators: label of one of the two buttons of the list of pending modifications, to switch between applying changes to the whole list and selecting some items for more advanced things (not displayed currently, but this change is wanted); the first is "Rule all" */ 34 | second_mode_name = _("Select"); 35 | 36 | main_list_box.set_header_func (delayed_setting_row_update_header); 37 | } 38 | 39 | internal ModificationsList (bool needs_shadows, bool big_placeholder) 40 | { 41 | Object (needs_shadows : needs_shadows, 42 | big_placeholder : big_placeholder); 43 | } 44 | 45 | internal override void reset () 46 | { 47 | scroll_top (); // FIXME doesn't work if selected row is not the first 48 | select_first_row (main_list_box); 49 | } 50 | 51 | private static void delayed_setting_row_update_header (ListBoxRow _row, ListBoxRow? before) 52 | { 53 | if (!(_row is DelayedSettingView)) 54 | assert_not_reached (); 55 | 56 | DelayedSettingView row = (DelayedSettingView) (!) _row; 57 | string row_key_name = ((DelayedSettingView) row).full_name; 58 | bool add_location_header = false; 59 | if (before == null) 60 | add_location_header = true; 61 | else 62 | { 63 | string before_key_name = ((DelayedSettingView) (!) before).full_name; 64 | 65 | if (ModelUtils.get_parent_path (row_key_name) != ModelUtils.get_parent_path (before_key_name)) 66 | add_location_header = true; 67 | } 68 | 69 | if (add_location_header) 70 | { 71 | Grid location_header = new Grid (); 72 | location_header.show (); 73 | location_header.orientation = Orientation.VERTICAL; 74 | 75 | Label location_header_label = new Label (ModelUtils.get_parent_path (row_key_name)); 76 | location_header_label.show (); 77 | location_header_label.hexpand = true; 78 | location_header_label.halign = Align.START; 79 | 80 | StyleContext context = location_header_label.get_style_context (); 81 | context.add_class ("dim-label"); 82 | context.add_class ("bold-label"); 83 | context.add_class ("list-row-header"); 84 | 85 | location_header.add (location_header_label); 86 | 87 | Separator separator_header = new Separator (Orientation.HORIZONTAL); 88 | separator_header.show (); 89 | location_header.add (separator_header); 90 | 91 | row.set_header (location_header); 92 | } 93 | else 94 | { 95 | Separator separator_header = new Separator (Orientation.HORIZONTAL); 96 | separator_header.show (); 97 | row.set_header (separator_header); 98 | } 99 | } 100 | 101 | /*\ 102 | * * Modifications list public functions 103 | \*/ 104 | 105 | internal string? get_selected_row_name () 106 | { 107 | ListBoxRow? selected_row = main_list_box.get_selected_row (); 108 | if (selected_row == null) 109 | return null; 110 | return ((DelayedSettingView) (!) selected_row).full_name; 111 | } 112 | 113 | internal void bind_model (GLib.ListStore modifications, ListBoxCreateWidgetFunc delayed_setting_row_create) 114 | { 115 | main_list_box.bind_model (modifications, delayed_setting_row_create); 116 | select_first_row (main_list_box); 117 | } 118 | private static inline void select_first_row (ListBox main_list_box) 119 | { 120 | ListBoxRow? first_row = main_list_box.get_row_at_index (0); 121 | if (first_row != null) 122 | main_list_box.select_row ((!) first_row); 123 | } 124 | 125 | /*\ 126 | * * Updating values; TODO only works for watched keys... 127 | \*/ 128 | 129 | internal void gkey_value_push (string full_name, uint16 context_id, Variant key_value, bool is_key_default) 130 | { 131 | main_list_box.@foreach ((widget) => { 132 | DelayedSettingView row = (DelayedSettingView) widget; 133 | if (row.full_name == full_name && row.context_id == context_id) 134 | row.update_gsettings_key_current_value (key_value, is_key_default); 135 | }); 136 | } 137 | 138 | internal void dkey_value_push (string full_name, Variant? key_value_or_null) 139 | { 140 | main_list_box.@foreach ((widget) => { 141 | DelayedSettingView row = (DelayedSettingView) widget; 142 | if (row.full_name == full_name) 143 | row.update_dconf_key_current_value (key_value_or_null); 144 | }); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /editor/short-pathbar.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/short-pathbar.ui")] 21 | private class ShortPathbar : Grid, Pathbar // TODO make MenuButton? 22 | { 23 | private string non_ghost_path = ""; 24 | 25 | private string complete_path = ""; 26 | internal void get_complete_path (out string _complete_path) 27 | { 28 | _complete_path = complete_path; 29 | } 30 | internal void get_fallback_path_and_complete_path (out string _fallback_path, out string _complete_path) 31 | { 32 | if (non_ghost_path != "" && ModelUtils.is_folder_path (non_ghost_path) && complete_path.has_prefix (non_ghost_path)) 33 | _fallback_path = non_ghost_path; 34 | else 35 | _fallback_path = complete_path; 36 | 37 | _complete_path = complete_path; 38 | } 39 | 40 | [GtkChild] private unowned MenuButton menu_button; 41 | [GtkChild] private unowned Label view_label; 42 | 43 | internal ShortPathbar (string complete_path_or_empty, ViewType type, string path) 44 | { 45 | complete_path = complete_path_or_empty; 46 | non_ghost_path = complete_path_or_empty; 47 | set_path (type, path); 48 | } 49 | 50 | /*\ 51 | * * callbacks 52 | \*/ 53 | 54 | private int event_x = 0; 55 | 56 | [GtkCallback] 57 | private bool on_button_press_event (Widget widget, Gdk.EventButton event) 58 | { 59 | event_x = (int) event.x; 60 | return false; 61 | } 62 | 63 | [GtkCallback] 64 | private void on_button_clicked (Button button) 65 | { 66 | MenuButton menu_button = (MenuButton) button; 67 | Popover? popover = menu_button.get_popover (); 68 | if (popover == null) 69 | assert_not_reached (); 70 | 71 | Allocation allocation; 72 | menu_button.get_allocated_size (out allocation, null); 73 | Gdk.Rectangle rect = { x:event_x, y:allocation.height, width:0, height:0 }; 74 | ((!) popover).set_pointing_to (rect); 75 | } 76 | 77 | /*\ 78 | * * keyboard 79 | \*/ 80 | 81 | internal bool has_popover () 82 | { 83 | return menu_button.active; 84 | } 85 | 86 | internal void close_menu () 87 | { 88 | menu_button.active = false; 89 | } 90 | 91 | internal void toggle_menu () 92 | { 93 | menu_button.active = !menu_button.active; 94 | } 95 | 96 | /*\ 97 | * * main public calls 98 | \*/ 99 | 100 | internal void set_path (ViewType type, string path) 101 | { 102 | if (type == ViewType.SEARCH) 103 | return; 104 | 105 | if (complete_path == "" 106 | || !path.has_suffix ("/") 107 | || !complete_path.has_prefix (path)) 108 | { 109 | complete_path = path; 110 | non_ghost_path = path; 111 | } 112 | 113 | view_label.set_text (ModelUtils.get_name (path)); 114 | update_menu (); 115 | } 116 | 117 | internal void update_ghosts (string _non_ghost_path, bool is_search) 118 | { 119 | non_ghost_path = _non_ghost_path; 120 | update_menu (); 121 | } 122 | 123 | /*\ 124 | * * menu creation 125 | \*/ 126 | 127 | private void update_menu () 128 | { 129 | GLib.Menu menu; 130 | _update_menu (complete_path, non_ghost_path, out menu); 131 | menu_button.set_menu_model (menu); 132 | } 133 | private static void _update_menu (string complete_path, string non_ghost_path, out GLib.Menu menu) 134 | { 135 | menu = new GLib.Menu (); 136 | GLib.Menu section = new GLib.Menu (); 137 | 138 | string [] split = complete_path.split ("/", /* max tokens disabled */ 0); 139 | if (split.length < 2) 140 | assert_not_reached (); 141 | string last = split [split.length - 1]; 142 | split = split [1:split.length - 1]; // excludes initial "" and either last "" or key name 143 | 144 | // slash folder 145 | string tmp_path = "/"; 146 | 147 | if (complete_path != "/") 148 | menu.append ("/", "browser.open-path(('/',uint16 " + ModelUtils.folder_context_id_string + "))"); 149 | 150 | // other folders 151 | foreach (string item in split) 152 | { 153 | tmp_path += item + "/"; 154 | Variant variant = new Variant ("(sq)", tmp_path, ModelUtils.folder_context_id); 155 | if (non_ghost_path.has_prefix (tmp_path)) 156 | menu.append (item, "browser.open-path(" + variant.print (true) + ")"); // TODO append or prepend? 157 | else 158 | menu.append (item, "browser.disabled-state-sq(" + variant.print (true) + ")"); // TODO append or prepend? 159 | } 160 | 161 | // key or nothing 162 | if (last != "") 163 | { 164 | bool is_folder = ModelUtils.is_folder_path (complete_path); 165 | tmp_path += last; 166 | if (is_folder) 167 | tmp_path += "/"; 168 | 169 | uint16 context_id = is_folder ? ModelUtils.folder_context_id : ModelUtils.undefined_context_id; 170 | Variant variant = new Variant ("(sq)", tmp_path, context_id); 171 | if (non_ghost_path.has_prefix (tmp_path)) // FIXME problem if key and folder named similarly 172 | menu.append (last, "browser.open-path(" + variant.print (true) + ")"); 173 | else 174 | menu.append (last, "browser.disabled-state-sq(" + variant.print (true) + ")"); // TODO append or prepend? 175 | } 176 | 177 | section.freeze (); 178 | menu.append_section (null, section); 179 | 180 | Pathbar.populate_pathbar_menu (/* is folder */ last == "", ref menu); 181 | 182 | menu.freeze (); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /editor/delayed-setting-view.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 158 | 159 | -------------------------------------------------------------------------------- /editor/browser-headerbar.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private abstract class BrowserHeaderBar : BaseHeaderBar, AdaptativeWidget 21 | { 22 | private PathWidget path_widget; 23 | 24 | construct 25 | { 26 | init_path_widget (); 27 | 28 | register_properties_mode (); 29 | } 30 | 31 | private bool current_type_is_config = false; 32 | internal virtual void set_path (ViewType type, string path) 33 | { 34 | path_widget.set_path (type, path); 35 | 36 | if (current_type_is_config != (type == ViewType.CONFIG)) 37 | { 38 | current_type_is_config = !current_type_is_config; 39 | update_properties_view (); 40 | } 41 | 42 | update_hamburger_menu (); 43 | } 44 | 45 | private bool is_extra_thin = false; 46 | protected override void set_window_size (AdaptativeWidget.WindowSize new_size) 47 | { 48 | if (is_extra_thin != AdaptativeWidget.WindowSize.is_extra_thin (new_size)) 49 | { 50 | is_extra_thin = !is_extra_thin; 51 | update_properties_view (); 52 | } 53 | 54 | base.set_window_size (new_size); 55 | 56 | path_widget.set_window_size (new_size); 57 | } 58 | 59 | /*\ 60 | * * path_widget creation 61 | \*/ 62 | 63 | private void init_path_widget () 64 | { 65 | add_path_widget (); 66 | 67 | this.change_mode.connect (mode_changed_browser); 68 | } 69 | 70 | private void add_path_widget () 71 | { 72 | path_widget = new PathWidget (); 73 | path_widget.hexpand = false; 74 | 75 | path_widget.visible = true; 76 | center_box.add (path_widget); 77 | } 78 | 79 | private static void mode_changed_browser (BaseHeaderBar _this, uint8 mode_id) 80 | { 81 | if (mode_id == default_mode_id) 82 | { 83 | PathWidget path_widget = ((BrowserHeaderBar) _this).path_widget; 84 | path_widget.show (); 85 | if (path_widget.search_mode_enabled) 86 | path_widget.entry_grab_focus_without_selecting (); 87 | } 88 | else 89 | ((BrowserHeaderBar) _this).path_widget.hide (); 90 | } 91 | 92 | /*\ 93 | * * path_widget proxy calls 94 | \*/ 95 | 96 | [CCode (notify = false)] internal bool search_mode_enabled { get { return path_widget.search_mode_enabled; }} 97 | 98 | internal void get_complete_path (out string complete_path) { path_widget.get_complete_path (out complete_path); } 99 | internal void get_fallback_path_and_complete_path (out string fallback_path, out string complete_path) 100 | { 101 | path_widget.get_fallback_path_and_complete_path (out fallback_path, out complete_path); 102 | } 103 | internal void toggle_pathbar_menu () { path_widget.toggle_pathbar_menu (); } 104 | 105 | internal void update_ghosts (string fallback_path) { path_widget.update_ghosts (fallback_path); } 106 | internal void prepare_search (PathEntry.SearchMode mode, string? search){ path_widget.prepare_search (mode, search); } 107 | internal string get_selected_child (string fallback_path) { return path_widget.get_selected_child (fallback_path); } 108 | 109 | internal void entry_grab_focus (bool select) 110 | { 111 | if (select) 112 | path_widget.entry_grab_focus (); 113 | else 114 | path_widget.entry_grab_focus_without_selecting (); 115 | } 116 | 117 | internal bool handle_event (Gdk.EventKey event) 118 | { 119 | return path_widget.handle_event (event); 120 | } 121 | 122 | /*\ 123 | * * properties mode 124 | \*/ 125 | 126 | private uint8 properties_mode_id = 0; 127 | private bool properties_mode_on = false; 128 | internal bool in_window_properties { get { return properties_mode_on; }} 129 | 130 | private void update_properties_view () 131 | { 132 | if (is_extra_thin && current_type_is_config) 133 | show_properties_view (); 134 | else 135 | hide_properties_view (); 136 | } 137 | 138 | private void show_properties_view () 139 | requires (properties_mode_id > 0) 140 | { 141 | if (!properties_mode_on) 142 | change_mode (properties_mode_id); 143 | } 144 | 145 | private void hide_properties_view () 146 | { 147 | if (properties_mode_on) 148 | change_mode (default_mode_id); 149 | } 150 | 151 | private void register_properties_mode () 152 | { 153 | properties_mode_id = register_new_mode (); 154 | 155 | this.change_mode.connect (mode_changed_properties); 156 | } 157 | 158 | private static void mode_changed_properties (BaseHeaderBar _this, uint8 requested_mode_id) 159 | { 160 | BrowserHeaderBar real_this = (BrowserHeaderBar) _this; 161 | if (is_not_requested_mode (real_this.properties_mode_id, requested_mode_id, ref real_this.properties_mode_on)) 162 | return; 163 | 164 | /* Translators: on really small windows, name of the view when showing a folder properties, displayed in the headerbar */ 165 | real_this.set_default_widgets_states (_("Properties"), /* title_label text or null */ 166 | true, /* show go_back_button */ 167 | false, /* show ltr_left_separator */ 168 | false, /* show info_button */ 169 | false, /* show ltr_right_separator */ 170 | true); /* show quit_button_stack */ 171 | } 172 | 173 | /*\ 174 | * * popovers methods 175 | \*/ 176 | 177 | internal override void close_popovers () 178 | { 179 | base.close_popovers (); 180 | path_widget.close_popovers (); 181 | } 182 | 183 | internal override bool has_popover () 184 | { 185 | return base.has_popover () || path_widget.has_popover (); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /editor/bookmarks.ui: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | True 22 | ca.desrt.dconf-editor.big-rows-symbolic 23 | 1 24 | 25 | 26 | True 27 | ca.desrt.dconf-editor.small-rows-symbolic 28 | 1 29 | 30 | 31 | 350 32 | 300 33 | 34 | 37 | 38 | 39 | True 40 | 6 41 | 4 42 | vertical 43 | 44 | 45 | True 46 | 47 | 48 | True 49 | center 50 | horizontal 51 | 12 52 | 53 | 54 | True 55 | 6 56 | True 57 | start 58 | 59 | 60 | 61 | 62 | True 63 | end 64 | browser.empty 65 | (byte 255,'') 66 | 67 | 68 | 69 | Location bookmarked 70 | 71 | Toggle to bookmark this location 72 | 73 | 74 | 75 | 76 | 77 | 78 | edit-mode-off 79 | 80 | 81 | 82 | 83 | True 84 | True 85 | bookmarks 86 | 87 | 88 | edit-mode-on 89 | 90 | 91 | 92 | 93 | True 94 | center 95 | 96 | The bookmarks list is not editable. 97 | 100 | 101 | 102 | edit-mode-disabled 103 | 104 | 105 | 106 | 107 | 108 | 109 | True 110 | True 111 | False 112 | bookmarks 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 144 | 145 | -------------------------------------------------------------------------------- /editor/pathwidget.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/pathwidget.ui")] 21 | private class PathWidget : Box, AdaptativeWidget 22 | { 23 | [GtkChild] private unowned ModelButton search_toggle; // most window size button 24 | [GtkChild] private unowned ModelButton search_button; // extra-small-window only 25 | [GtkChild] private unowned Stack pathwidget_stack; 26 | [GtkChild] private unowned Grid pathbar_grid; 27 | [GtkChild] private unowned AdaptativePathbar pathbar; 28 | [GtkChild] private unowned PathEntry searchentry; 29 | 30 | [GtkChild] private unowned Revealer parent_revealer; 31 | [GtkChild] private unowned ModelButton parent_button; 32 | 33 | private ThemedIcon search_icon = new ThemedIcon.from_names ({"edit-find-symbolic"}); 34 | private ThemedIcon parent_icon = new ThemedIcon.from_names ({"go-up-symbolic"}); 35 | construct 36 | { 37 | search_toggle.icon = search_icon; 38 | search_button.icon = search_icon; 39 | parent_button.icon = parent_icon; 40 | } 41 | 42 | private bool quite_thin_window = false; 43 | private bool extra_thin_window = false; 44 | private void set_window_size (AdaptativeWidget.WindowSize new_size) 45 | { 46 | pathbar.set_window_size (new_size); 47 | 48 | bool _quite_thin_window = AdaptativeWidget.WindowSize.is_quite_thin (new_size); 49 | bool _extra_thin_window = AdaptativeWidget.WindowSize.is_extra_thin (new_size); 50 | if (quite_thin_window != _quite_thin_window 51 | || extra_thin_window != _extra_thin_window) 52 | { 53 | quite_thin_window = _quite_thin_window; 54 | extra_thin_window = _extra_thin_window; 55 | if (_extra_thin_window) 56 | { 57 | search_toggle.hide (); 58 | search_button.show (); 59 | parent_revealer.set_reveal_child (true); 60 | } 61 | else if (_quite_thin_window) 62 | { 63 | search_toggle.hide (); 64 | search_button.show (); 65 | parent_revealer.set_reveal_child (false); 66 | } 67 | else 68 | { 69 | search_button.hide (); 70 | search_toggle.show (); 71 | parent_revealer.set_reveal_child (false); 72 | } 73 | } 74 | 75 | searchentry.set_window_size (new_size); 76 | } 77 | 78 | /*\ 79 | * * search mode 80 | \*/ 81 | 82 | [CCode (notify = false)] internal bool search_mode_enabled { internal get; private set; default = false; } 83 | 84 | private void enter_search_mode () 85 | { 86 | search_mode_enabled = true; 87 | search_toggle.set_action_target_value (false); 88 | pathwidget_stack.set_visible_child (searchentry); 89 | } 90 | 91 | private void leave_search_mode () 92 | { 93 | search_mode_enabled = false; 94 | search_toggle.set_action_target_value (true); 95 | pathwidget_stack.set_visible_child (pathbar_grid); 96 | } 97 | 98 | /*\ 99 | * * proxy calls 100 | \*/ 101 | 102 | internal void set_path (ViewType type, string path) 103 | { 104 | pathbar.set_path (type, path); 105 | searchentry.set_path (type, path); 106 | 107 | bool is_search = type == ViewType.SEARCH; 108 | 109 | if (!is_search) 110 | { 111 | if (path != "/") 112 | { 113 | Variant path_variant = new Variant.string (path); 114 | parent_button.set_detailed_action_name ("browser.open-parent(" + path_variant.print (false) + ")"); 115 | } 116 | else 117 | parent_button.set_detailed_action_name ("browser.disabled-state-s('/')"); 118 | } 119 | 120 | if (is_search && !search_mode_enabled) 121 | enter_search_mode (); 122 | else if (!is_search && search_mode_enabled) 123 | leave_search_mode (); 124 | } 125 | 126 | internal void close_popovers () 127 | { 128 | pathbar.close_menu (); 129 | } 130 | 131 | internal bool has_popover () 132 | { 133 | if (pathbar.has_popover ()) 134 | return true; 135 | return false; 136 | } 137 | 138 | /* path bar */ 139 | internal void get_complete_path (out string complete_path) 140 | { 141 | pathbar.get_complete_path (out complete_path); 142 | } 143 | internal void get_fallback_path_and_complete_path (out string fallback_path, out string complete_path) 144 | { 145 | pathbar.get_fallback_path_and_complete_path (out fallback_path, out complete_path); 146 | } 147 | 148 | internal void update_ghosts (string fallback_path) 149 | { 150 | pathbar.update_ghosts (fallback_path, search_mode_enabled); 151 | } 152 | 153 | internal string get_selected_child (string fallback_path) 154 | { 155 | return pathbar.get_selected_child (fallback_path); 156 | } 157 | 158 | internal void toggle_pathbar_menu () 159 | { 160 | pathbar.toggle_menu (); 161 | } 162 | 163 | /* path entry */ 164 | internal void entry_grab_focus () { searchentry.entry_grab_focus (); } 165 | internal void entry_grab_focus_without_selecting () { searchentry.entry_grab_focus_without_selecting (); } 166 | 167 | internal bool handle_event (Gdk.EventKey event) 168 | { 169 | searchentry.prepare (PathEntry.SearchMode.SEARCH); 170 | if (!searchentry.handle_event (event)) 171 | return false; 172 | enter_search_mode (); 173 | return true; 174 | } 175 | 176 | internal void prepare_search (PathEntry.SearchMode mode, string? search) 177 | { 178 | searchentry.prepare (mode, search); 179 | } 180 | 181 | /* string [] tokens = full_name.split (" "); 182 | uint index = 0; 183 | string token; 184 | while (index < tokens.length) 185 | { 186 | token = tokens [index]; 187 | if (token.has_prefix ("/")) 188 | { 189 | path_requested (token, pathbar.get_selected_child (token)); 190 | break; 191 | } 192 | index++; 193 | } */ 194 | 195 | /*\ 196 | * * sizing; TODO should be set by the center box of the headerbar, not by one of its children... 197 | \*/ 198 | 199 | internal override void get_preferred_width (out int minimum_width, out int natural_width) 200 | { 201 | base.get_preferred_width (out minimum_width, out natural_width); 202 | natural_width = MAX_ROW_WIDTH - 46; // see key-list-box-row.vala 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /editor/delayed-setting-view.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/delayed-setting-view.ui")] 21 | private class DelayedSettingView : OverlayedListRow 22 | { 23 | [GtkChild] private unowned Label key_name_label; 24 | [GtkChild] private unowned Label key_value_label; 25 | [GtkChild] private unowned Label key_value_default; 26 | [GtkChild] private unowned Label planned_value_label; 27 | [GtkChild] private unowned Label planned_value_default; 28 | [GtkChild] private unowned Button cancel_change_button; 29 | 30 | [CCode (notify = false)] public string full_name { internal get; internal construct; } 31 | [CCode (notify = false)] public uint16 context_id { internal get; internal construct; } 32 | 33 | internal DelayedSettingView (string name, string _full_name, uint16 _context_id, bool has_schema_and_is_default, Variant key_value, string? cool_planned_value, string? cool_default_value) 34 | { 35 | Object (full_name: _full_name, context_id: _context_id); 36 | Variant variant = new Variant.string (full_name); 37 | key_name_label.label = name; 38 | cancel_change_button.set_detailed_action_name ("ui.dismiss-change(" + variant.print (false) + ")"); 39 | 40 | if (cool_default_value == null) 41 | { 42 | // at row creation, key is never ghost 43 | _update_dconf_key_current_value (key_value, 44 | key_value_label, 45 | key_value_default); 46 | 47 | _update_dconf_key_planned_value (cool_planned_value, 48 | planned_value_label, 49 | planned_value_default); 50 | } 51 | else 52 | { 53 | _update_gsettings_key_current_value (key_value, 54 | has_schema_and_is_default, 55 | key_value_label, 56 | key_value_default); 57 | 58 | _update_gsettings_key_planned_value (cool_planned_value, 59 | (!) cool_default_value, 60 | planned_value_label, 61 | planned_value_default); 62 | } 63 | } 64 | 65 | internal override bool handle_copy_text (out string copy_text) 66 | { 67 | copy_text = full_name; 68 | return true; 69 | } 70 | 71 | /*\ 72 | * * "updating" planned value 73 | \*/ 74 | 75 | private static inline void _update_gsettings_key_planned_value (string? cool_planned_value, 76 | string cool_default_value, 77 | Label planned_value_label, 78 | Label planned_value_default) 79 | { 80 | bool is_default = cool_planned_value == null; 81 | planned_value_label.label = is_default ? cool_default_value : (!) cool_planned_value; 82 | update_value_default_label (is_default, planned_value_default); 83 | } 84 | 85 | private static inline void _update_dconf_key_planned_value (string? cool_planned_value, 86 | Label planned_value_label, 87 | Label planned_value_default) 88 | { 89 | if (cool_planned_value == null) 90 | update_labels_dconf_key_erased (planned_value_label, planned_value_default); 91 | else 92 | update_labels_dconf_key_values ((!) cool_planned_value, 93 | planned_value_label, planned_value_default); 94 | } 95 | 96 | /*\ 97 | * * updating current value 98 | \*/ 99 | 100 | internal void update_gsettings_key_current_value (Variant key_value, bool is_default) 101 | { 102 | _update_gsettings_key_current_value (key_value, is_default, key_value_label, key_value_default); 103 | } 104 | private static void _update_gsettings_key_current_value (Variant key_value, 105 | bool is_default, 106 | Label key_value_label, 107 | Label key_value_default) 108 | { 109 | key_value_label.label = Key.cool_text_value_from_variant (key_value); 110 | update_value_default_label (is_default, key_value_default); 111 | } 112 | 113 | internal void update_dconf_key_current_value (Variant? key_value_or_null) 114 | { 115 | _update_dconf_key_current_value (key_value_or_null, key_value_label, key_value_default); 116 | } 117 | private static void _update_dconf_key_current_value (Variant? key_value_or_null, 118 | Label key_value_label, 119 | Label key_value_default) 120 | { 121 | if (key_value_or_null == null) 122 | update_labels_dconf_key_erased (key_value_label, key_value_default); 123 | else 124 | update_labels_dconf_key_values (Key.cool_text_value_from_variant ((!) key_value_or_null), 125 | key_value_label, key_value_default); 126 | } 127 | 128 | /*\ 129 | * * common utilities 130 | \*/ 131 | 132 | private static void update_labels_dconf_key_erased (Label value_label, Label value_default) 133 | { 134 | value_label.visible = false; 135 | /* Translators: displayed in the list of pending changes (could be an in-window panel, or in the popover of the bottom bar); for dconf keys */ 136 | value_default.label = _("Key erased"); 137 | value_default.visible = true; 138 | } 139 | 140 | private static void update_labels_dconf_key_values (string key_value, Label value_label, Label value_default) 141 | { 142 | value_default.visible = false; 143 | value_label.label = key_value; // TODO move Key.cool_text_value_from_variant here? 144 | value_label.visible = true; 145 | } 146 | 147 | private static void update_value_default_label (bool is_default, Label value_default) 148 | { 149 | if (is_default) 150 | /* Translators: displayed in the list of pending changes (could be an in-window panel, or in the popover of the bottom bar); for gsettings keys */ 151 | value_default.label = _("Default value"); 152 | value_default.visible = is_default; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /editor/pathentry.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private class BrowserEntry : SearchEntry 21 | { 22 | private StyleContext context; 23 | 24 | construct 25 | { 26 | context = get_style_context (); 27 | } 28 | 29 | private bool has_error_class = false; 30 | internal void check_error (ref string path) 31 | { 32 | bool is_invalid = BrowserWindow.is_path_invalid (path); 33 | if (!has_error_class && is_invalid) 34 | { 35 | has_error_class = true; 36 | context.add_class ("error"); 37 | } 38 | else if (has_error_class && !is_invalid) 39 | { 40 | has_error_class = false; 41 | context.remove_class ("error"); 42 | } 43 | } 44 | 45 | internal void set_is_thin_window (bool thin_window) 46 | { 47 | if (thin_window) 48 | set_icon_from_pixbuf (EntryIconPosition.PRIMARY, null); 49 | else 50 | set_icon_from_icon_name (EntryIconPosition.PRIMARY, "edit-find-symbolic"); 51 | } 52 | } 53 | 54 | [GtkTemplate (ui = "/ca/desrt/dconf-editor/ui/pathentry.ui")] 55 | private class PathEntry : Box, AdaptativeWidget 56 | { 57 | [GtkChild] private unowned Button hide_search_button; 58 | [GtkChild] private unowned Button reload_search_button; 59 | 60 | [GtkChild] private unowned BrowserEntry search_entry; 61 | [GtkChild] private unowned Button search_action_button; 62 | 63 | private string current_path = ""; 64 | 65 | internal override void get_preferred_width (out int minimum_width, out int natural_width) 66 | { 67 | base.get_preferred_width (out minimum_width, out natural_width); 68 | minimum_width = 72; // the search entry does something wrong that makes the first size_allocate ask for 478px width instead of 349 69 | } 70 | 71 | private ulong can_reload_handler = 0; 72 | private bool thin_window = false; 73 | private void set_window_size (AdaptativeWidget.WindowSize new_size) 74 | { 75 | bool _thin_window = AdaptativeWidget.WindowSize.is_quite_thin (new_size); 76 | if (thin_window == _thin_window) 77 | return; 78 | thin_window = _thin_window; 79 | 80 | search_entry.set_is_thin_window (_thin_window); 81 | 82 | if (_thin_window) 83 | { 84 | can_reload_handler = reload_search_button.notify ["sensitive"].connect (() => { 85 | if (reload_search_button.sensitive) 86 | { 87 | hide_search_button.hide (); 88 | reload_search_button.show (); 89 | } 90 | else 91 | { 92 | reload_search_button.hide (); 93 | hide_search_button.show (); 94 | } 95 | }); 96 | 97 | if (!reload_search_button.sensitive) 98 | { 99 | reload_search_button.hide (); 100 | hide_search_button.show (); 101 | } 102 | } 103 | else 104 | { 105 | reload_search_button.disconnect (can_reload_handler); 106 | 107 | hide_search_button.hide (); 108 | reload_search_button.show (); 109 | } 110 | } 111 | 112 | internal enum SearchMode { 113 | UNCLEAR, 114 | EDIT_PATH_MOVE_END, 115 | EDIT_PATH_SELECT_ALL, 116 | EDIT_PATH_SELECT_LAST_WORD, 117 | SEARCH 118 | } 119 | 120 | private ulong search_changed_handler = 0; 121 | 122 | construct 123 | { 124 | search_changed_handler = search_entry.search_changed.connect (() => { 125 | search_action_button.set_action_target ("ms", search_entry.text); 126 | search_action_button.clicked (); 127 | }); 128 | search_entry.stop_search.connect (() => { 129 | search_action_button.set_action_target ("ms", null); 130 | search_action_button.clicked (); 131 | }); 132 | } 133 | 134 | internal void entry_grab_focus_without_selecting () 135 | { 136 | _entry_grab_focus_without_selecting (search_entry); 137 | } 138 | private static void _entry_grab_focus_without_selecting (BrowserEntry search_entry) 139 | { 140 | if (search_entry.text_length != 0) 141 | { 142 | if (search_entry.cursor_position == search_entry.text_length) 143 | search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, -1, false); 144 | search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, 1, false); 145 | } 146 | search_entry.grab_focus_without_selecting (); 147 | } 148 | internal void entry_grab_focus () 149 | { 150 | search_entry.grab_focus (); 151 | } 152 | internal bool handle_event (Gdk.EventKey event) 153 | { 154 | return search_entry.handle_event (event); 155 | } 156 | 157 | internal void set_path (ViewType type, string _path) 158 | { 159 | string path = _path.strip (); 160 | 161 | search_entry.check_error (ref path); 162 | 163 | current_path = path; 164 | // if (type == ViewType.SEARCH) 165 | } 166 | 167 | /*\ 168 | * * prepare call 169 | \*/ 170 | 171 | internal void prepare (SearchMode mode, string? nullable_search = null) 172 | requires (search_changed_handler != 0) 173 | { 174 | SignalHandler.block (search_entry, search_changed_handler); 175 | _prepare (mode, nullable_search, ref current_path, search_entry); 176 | SignalHandler.unblock (search_entry, search_changed_handler); 177 | } 178 | 179 | private static inline void _prepare (SearchMode mode, 180 | string? nullable_search, 181 | ref string current_path, 182 | BrowserEntry search_entry) 183 | { 184 | string search; 185 | switch (mode) 186 | { 187 | case SearchMode.EDIT_PATH_MOVE_END: 188 | search = nullable_search == null ? current_path : (!) nullable_search; 189 | _prepare_move_end (ref search, search_entry); 190 | return; 191 | 192 | case SearchMode.EDIT_PATH_SELECT_ALL: 193 | search = nullable_search == null ? current_path : (!) nullable_search; 194 | _prepare_search (ref search, search_entry); 195 | return; 196 | 197 | case SearchMode.EDIT_PATH_SELECT_LAST_WORD: 198 | search = current_path; 199 | _prepare_select_last_word (ref search, search_entry); 200 | return; 201 | 202 | case SearchMode.SEARCH: 203 | search = ""; 204 | _prepare_search (ref search, search_entry); 205 | return; 206 | 207 | case SearchMode.UNCLEAR: 208 | default: 209 | assert_not_reached (); 210 | } 211 | } 212 | 213 | private static inline void _prepare_move_end (ref string text, BrowserEntry search_entry) 214 | { 215 | search_entry.text = text; 216 | _entry_grab_focus_without_selecting (search_entry); 217 | } 218 | 219 | private static inline void _prepare_search (ref string text, BrowserEntry search_entry) 220 | { 221 | search_entry.text = text; 222 | search_entry.grab_focus (); 223 | } 224 | 225 | private static inline void _prepare_select_last_word (ref string current_path, BrowserEntry search_entry) 226 | { 227 | search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, -1, false); 228 | search_entry.text = current_path; 229 | if (search_entry.text_length == 1) // root 230 | { 231 | search_entry.grab_focus (); 232 | return; 233 | } 234 | if (search_entry.text_length != 0) 235 | { 236 | if (search_entry.cursor_position == search_entry.text_length) 237 | search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, -1, false); 238 | search_entry.move_cursor (MovementStep.VISUAL_POSITIONS, ModelUtils.get_parent_path (current_path).length, false); 239 | search_entry.move_cursor (MovementStep.DISPLAY_LINE_ENDS, 1, true); 240 | } 241 | search_entry.grab_focus_without_selecting (); 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /editor/adaptative-pathbar.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | using Gtk; 19 | 20 | private class AdaptativePathbar : Stack, Pathbar, AdaptativeWidget 21 | { 22 | construct 23 | { 24 | hexpand = true; 25 | hhomogeneous = false; 26 | } 27 | 28 | /*\ 29 | * * pathbars creation 30 | \*/ 31 | 32 | private bool start_infos_not_given = true; 33 | private bool window_size_not_given = true; 34 | 35 | private bool large_pathbar_created = false; 36 | private bool short_pathbar_created = false; 37 | 38 | private LargePathbar large_pathbar; 39 | private ShortPathbar short_pathbar; 40 | 41 | private void create_large_pathbar () 42 | { 43 | large_pathbar = new LargePathbar (complete_path, current_type, current_path); 44 | large_pathbar.valign = Align.FILL; 45 | large_pathbar.vexpand = true; 46 | large_pathbar.show (); 47 | add (large_pathbar); 48 | large_pathbar_created = true; 49 | } 50 | 51 | private void create_short_pathbar () 52 | { 53 | short_pathbar = new ShortPathbar (complete_path, current_type, current_path); 54 | short_pathbar.valign = Align.CENTER; 55 | short_pathbar.show (); 56 | add (short_pathbar); 57 | short_pathbar_created = true; 58 | } 59 | 60 | private void create_initial_pathbar () 61 | { 62 | if (thin_window) 63 | { 64 | create_short_pathbar (); 65 | set_visible_child (short_pathbar); 66 | } 67 | else 68 | { 69 | create_large_pathbar (); 70 | set_visible_child (large_pathbar); 71 | } 72 | } 73 | 74 | /*\ 75 | * * window size state 76 | \*/ 77 | 78 | private bool thin_window = false; 79 | private void set_window_size (AdaptativeWidget.WindowSize new_size) 80 | { 81 | if (window_size_not_given) 82 | { 83 | thin_window = AdaptativeWidget.WindowSize.is_extra_thin (new_size); 84 | window_size_not_given = false; 85 | if (start_infos_not_given) 86 | return; 87 | create_initial_pathbar (); 88 | return; 89 | } 90 | 91 | bool _thin_window = AdaptativeWidget.WindowSize.is_extra_thin (new_size); 92 | if (thin_window == _thin_window) 93 | return; 94 | thin_window = _thin_window; 95 | 96 | if (start_infos_not_given) 97 | return; 98 | 99 | if (_thin_window) 100 | { 101 | if (!short_pathbar_created) 102 | create_short_pathbar (); 103 | set_visible_child (short_pathbar); 104 | } 105 | else 106 | { 107 | if (!large_pathbar_created) 108 | create_large_pathbar (); 109 | set_visible_child (large_pathbar); 110 | } 111 | } 112 | 113 | /*\ 114 | * * current path state 115 | \*/ 116 | 117 | private ViewType current_type; 118 | private string current_path; 119 | private string complete_path = ""; 120 | 121 | internal void set_path (ViewType type, string path) 122 | { 123 | current_type = type; 124 | current_path = path; 125 | 126 | if (complete_path == "" 127 | || !path.has_suffix ("/") 128 | || !complete_path.has_prefix (path)) 129 | complete_path = path; 130 | 131 | if (start_infos_not_given) 132 | { 133 | start_infos_not_given = false; 134 | if (window_size_not_given) 135 | return; 136 | create_initial_pathbar (); 137 | return; 138 | } 139 | 140 | if (window_size_not_given) 141 | return; 142 | 143 | if (large_pathbar_created) 144 | large_pathbar.set_path (type, path); 145 | if (short_pathbar_created) 146 | short_pathbar.set_path (type, path); 147 | } 148 | 149 | /*\ 150 | * * keyboard 151 | \*/ 152 | 153 | internal bool has_popover () 154 | { 155 | return (large_pathbar_created && large_pathbar.has_popover ()) 156 | || (short_pathbar_created && short_pathbar.has_popover ()); 157 | } 158 | 159 | internal void close_menu () 160 | { 161 | if (large_pathbar_created) 162 | large_pathbar.close_menu (); 163 | if (short_pathbar_created) 164 | short_pathbar.close_menu (); 165 | } 166 | 167 | internal void toggle_menu () 168 | { 169 | if (thin_window) 170 | { 171 | if (!short_pathbar_created) 172 | assert_not_reached (); 173 | short_pathbar.toggle_menu (); 174 | } 175 | else 176 | { 177 | if (!large_pathbar_created) 178 | assert_not_reached (); 179 | large_pathbar.toggle_menu (); 180 | } 181 | } 182 | 183 | /*\ 184 | * * public calls 185 | \*/ 186 | 187 | internal void get_complete_path (out string _complete_path) 188 | { 189 | _complete_path = complete_path; 190 | } 191 | 192 | internal void get_fallback_path_and_complete_path (out string _fallback_path, out string _complete_path) 193 | { 194 | if (large_pathbar_created) 195 | large_pathbar.get_fallback_path_and_complete_path (out _fallback_path, out _complete_path); 196 | else if (short_pathbar_created) 197 | short_pathbar.get_fallback_path_and_complete_path (out _fallback_path, out _complete_path); 198 | else 199 | assert_not_reached (); 200 | } 201 | 202 | internal void update_ghosts (string non_ghost_path, bool is_search) 203 | { 204 | if (large_pathbar_created) 205 | large_pathbar.update_ghosts (non_ghost_path, is_search); 206 | if (short_pathbar_created) 207 | short_pathbar.update_ghosts (non_ghost_path, is_search); 208 | } 209 | } 210 | 211 | private interface Pathbar 212 | { 213 | /* simple proxy calls */ 214 | internal abstract bool has_popover (); 215 | internal abstract void close_menu (); 216 | internal abstract void toggle_menu (); 217 | 218 | internal abstract void set_path (ViewType type, string path); 219 | internal abstract void update_ghosts (string non_ghost_path, bool is_search); 220 | 221 | /* complex proxy calls */ 222 | internal abstract void get_complete_path (out string _complete_path); 223 | internal abstract void get_fallback_path_and_complete_path (out string _fallback_path, out string _complete_path); 224 | 225 | internal virtual string get_selected_child (string current_path) 226 | { 227 | string complete_path; 228 | get_complete_path (out complete_path); 229 | return _get_selected_child (current_path, complete_path); 230 | } 231 | private static string _get_selected_child (string current_path, string complete_path) 232 | { 233 | if (!complete_path.has_prefix (current_path) || complete_path == current_path) 234 | return ""; 235 | int index_of_last_slash = complete_path.index_of ("/", current_path.length); 236 | return index_of_last_slash == -1 ? complete_path : complete_path.slice (0, index_of_last_slash + 1); 237 | } 238 | 239 | /* called from inside the pathbar, by ShortPathbar and LargePathbar*Item* (so cannot make "protected") */ 240 | internal static void populate_pathbar_menu (bool is_folder, ref GLib.Menu menu) 241 | { 242 | add_copy_path_section (ref menu); 243 | if (is_folder) 244 | add_open_config_section (ref menu); 245 | } 246 | 247 | private static void add_copy_path_section (ref GLib.Menu menu) 248 | { 249 | GLib.Menu section = new GLib.Menu (); 250 | /* Translators: menu entry of the pathbar menu */ 251 | section.append (_("Copy current path"), "base.copy-alt"); 252 | // or "app.copy(\"" + get_action_target_value ().get_string () + "\")" 253 | section.freeze (); 254 | menu.append_section (null, section); 255 | } 256 | 257 | private static void add_open_config_section (ref GLib.Menu menu) 258 | { 259 | // method "disabled" for now 260 | return; 261 | 262 | GLib.Menu section = new GLib.Menu (); 263 | /* Translators: menu entry of the pathbar menu (not displayed for now) */ 264 | section.append (_("Show properties"), "browser.open-config-local"); 265 | section.freeze (); 266 | menu.append_section (null, section); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /editor/modifications-handler.vala: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Dconf Editor 3 | 4 | Dconf Editor is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Dconf Editor is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Dconf Editor. If not, see . 16 | */ 17 | 18 | internal enum Behaviour { 19 | UNSAFE, 20 | SAFE, 21 | ALWAYS_CONFIRM_IMPLICIT, 22 | ALWAYS_CONFIRM_EXPLICIT, 23 | ALWAYS_DELAY 24 | } 25 | internal enum ModificationsMode { 26 | NONE, 27 | TEMPORARY, 28 | DELAYED 29 | } 30 | 31 | private class ModificationsHandler : Object 32 | { 33 | [CCode (notify = false)] internal ModificationsMode mode { internal get; private set; default = ModificationsMode.NONE; } 34 | 35 | private HashTable keys_awaiting_hashtable = new HashTable (str_hash, str_equal); 36 | 37 | private GenericSet dconf_changes_set = new GenericSet (str_hash, str_equal); 38 | private HashTable gsettings_changes_set = new HashTable (str_hash, str_equal); 39 | [CCode (notify = false)] internal uint dconf_changes_count { internal get { return dconf_changes_set.length; }} 40 | [CCode (notify = false)] internal uint gsettings_changes_count { internal get { return gsettings_changes_set.length; }} 41 | 42 | public SettingsModel model { internal get; internal construct; } 43 | 44 | internal signal void leave_delay_mode (); 45 | internal signal void delayed_changes_changed (); 46 | 47 | [CCode (notify = false)] internal Behaviour behaviour { internal get; internal set; } 48 | 49 | internal ModificationsHandler (SettingsModel model) 50 | { 51 | Object (model: model); 52 | } 53 | 54 | /*\ 55 | * * Public calls 56 | \*/ 57 | 58 | internal bool has_pending_changes () 59 | { 60 | return dconf_changes_count + gsettings_changes_count != 0; 61 | } 62 | 63 | internal bool get_current_delay_mode () 64 | { 65 | return mode == ModificationsMode.DELAYED || behaviour == Behaviour.ALWAYS_DELAY; 66 | } 67 | 68 | internal bool should_delay_apply (string type_string) 69 | { 70 | if (get_current_delay_mode () || behaviour == Behaviour.ALWAYS_CONFIRM_IMPLICIT || behaviour == Behaviour.ALWAYS_CONFIRM_EXPLICIT) 71 | return true; 72 | if (behaviour == Behaviour.UNSAFE) 73 | return false; 74 | if (behaviour == Behaviour.SAFE) 75 | return type_string != "b" && type_string != "mb" && type_string != "" && type_string != ""; 76 | assert_not_reached (); 77 | } 78 | 79 | internal void enter_delay_mode () 80 | { 81 | mode = ModificationsMode.DELAYED; 82 | 83 | delayed_changes_changed (); 84 | } 85 | 86 | internal void add_delayed_setting (string key_path, Variant? new_value, uint16 context_id) 87 | requires (!ModelUtils.is_folder_context_id (context_id)) 88 | { 89 | if (!keys_awaiting_hashtable.contains (key_path)) 90 | { 91 | if (ModelUtils.is_dconf_context_id (context_id)) 92 | dconf_changes_set.add (key_path); 93 | else 94 | gsettings_changes_set.insert (key_path, context_id); 95 | keys_awaiting_hashtable.insert (key_path, new_value); 96 | } 97 | else 98 | keys_awaiting_hashtable.replace (key_path, new_value); 99 | 100 | mode = get_current_delay_mode () ? ModificationsMode.DELAYED : ModificationsMode.TEMPORARY; 101 | 102 | delayed_changes_changed (); 103 | } 104 | 105 | internal void dismiss_change (string key_path) 106 | { 107 | if (mode == ModificationsMode.NONE) 108 | mode = behaviour == Behaviour.ALWAYS_DELAY ? ModificationsMode.DELAYED : ModificationsMode.TEMPORARY; 109 | 110 | if (keys_awaiting_hashtable.remove (key_path)) 111 | { 112 | if (!gsettings_changes_set.remove (key_path) 113 | && !dconf_changes_set.remove (key_path)) 114 | assert_not_reached (); 115 | } 116 | // else... // happens on the second edit with unparsable value in a KeyEditorChildDefault 117 | 118 | delayed_changes_changed (); 119 | } 120 | 121 | internal void path_changed () 122 | { 123 | if (mode != ModificationsMode.TEMPORARY) 124 | return; 125 | if (behaviour == Behaviour.ALWAYS_CONFIRM_IMPLICIT || behaviour == Behaviour.SAFE) 126 | apply_delayed_settings (); 127 | else if (behaviour == Behaviour.ALWAYS_CONFIRM_EXPLICIT) 128 | dismiss_delayed_settings (); 129 | else 130 | assert_not_reached (); 131 | } 132 | 133 | internal void apply_delayed_settings () 134 | { 135 | mode = ModificationsMode.NONE; 136 | 137 | model.apply_key_value_changes (keys_awaiting_hashtable); 138 | gsettings_changes_set.remove_all (); 139 | dconf_changes_set.remove_all (); 140 | keys_awaiting_hashtable.remove_all (); 141 | 142 | delayed_changes_changed (); 143 | leave_delay_mode (); 144 | } 145 | 146 | internal void dismiss_delayed_settings () 147 | { 148 | mode = ModificationsMode.NONE; 149 | 150 | gsettings_changes_set.remove_all (); 151 | dconf_changes_set.remove_all (); 152 | keys_awaiting_hashtable.remove_all (); 153 | 154 | delayed_changes_changed (); 155 | leave_delay_mode (); 156 | } 157 | 158 | internal Variant get_key_custom_value (string full_name, uint16 context_id) 159 | { 160 | bool planned_change = key_has_planned_change (full_name); 161 | Variant? planned_value = get_key_planned_value (full_name); 162 | if (planned_change && (planned_value != null)) 163 | return (!) planned_value; 164 | 165 | RegistryVariantDict properties = new RegistryVariantDict.from_aqv (model.get_key_properties (full_name, context_id, (uint16) PropertyQuery.KEY_VALUE)); 166 | Variant key_value; 167 | if (!properties.lookup (PropertyQuery.KEY_VALUE, "v", out key_value)) 168 | assert_not_reached (); 169 | properties.clear (); 170 | return key_value; 171 | } 172 | 173 | internal void set_dconf_key_value (string full_name, Variant key_value) 174 | { 175 | model.set_dconf_key_value (full_name, key_value); 176 | } 177 | 178 | internal void set_gsettings_key_value (string full_name, uint16 context_id, Variant key_value) 179 | { 180 | model.set_gsettings_key_value (full_name, context_id, key_value); 181 | } 182 | 183 | internal void erase_dconf_key (string full_name) 184 | { 185 | if (get_current_delay_mode ()) 186 | add_delayed_setting (full_name, null, ModelUtils.dconf_context_id); 187 | else if (behaviour != Behaviour.UNSAFE) 188 | { 189 | mode = ModificationsMode.DELAYED; // call only once delayed_changes_changed() 190 | add_delayed_setting (full_name, null, ModelUtils.dconf_context_id); 191 | } 192 | else 193 | model.erase_key (full_name); 194 | } 195 | 196 | internal void set_to_default (string full_name, uint16 context_id) 197 | requires (!ModelUtils.is_folder_context_id (context_id)) 198 | requires (!ModelUtils.is_dconf_context_id (context_id)) 199 | { 200 | if (get_current_delay_mode ()) 201 | add_delayed_setting (full_name, null, context_id); 202 | else 203 | model.set_key_to_default (full_name, context_id); 204 | } 205 | 206 | internal bool key_has_planned_change (string key_path) 207 | { 208 | if (keys_awaiting_hashtable.contains (key_path)) 209 | return true; 210 | 211 | bool has_planned_changed = false; 212 | keys_awaiting_hashtable.@foreach ((key_awaiting, planned_value) => { 213 | if (key_path == key_awaiting) 214 | has_planned_changed = true; 215 | }); 216 | return has_planned_changed; 217 | } 218 | 219 | internal Variant? get_key_planned_value (string key_path) 220 | { 221 | if (keys_awaiting_hashtable.contains (key_path)) 222 | return keys_awaiting_hashtable.lookup (key_path); 223 | 224 | Variant? planned_changed = null; 225 | keys_awaiting_hashtable.@foreach ((key_awaiting, planned_value) => { 226 | if (key_path == key_awaiting) 227 | planned_changed = planned_value; 228 | }); 229 | return planned_changed; 230 | } 231 | 232 | internal ListStore get_delayed_settings () 233 | { 234 | ListStore delayed_settings_list = new ListStore (typeof (SimpleSettingObject)); 235 | keys_awaiting_hashtable.@foreach ((key_path, planned_value) => { 236 | if (dconf_changes_set.contains (key_path)) 237 | delayed_settings_list.append ( 238 | new SimpleSettingObject.from_full_name (ModelUtils.dconf_context_id, 239 | key_path.slice (key_path.last_index_of_char ('/') + 1, key_path.length), 240 | key_path)); 241 | else if (gsettings_changes_set.contains (key_path)) 242 | delayed_settings_list.append ( 243 | new SimpleSettingObject.from_full_name (gsettings_changes_set.lookup (key_path), 244 | key_path.slice (key_path.last_index_of_char ('/') + 1, key_path.length), 245 | key_path)); 246 | else 247 | assert_not_reached (); 248 | }); 249 | return delayed_settings_list; 250 | } 251 | } 252 | --------------------------------------------------------------------------------