[libdazzle] prefs: add default DzlPreferences implementation
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdazzle] prefs: add default DzlPreferences implementation
- Date: Tue, 6 Jun 2017 09:26:17 +0000 (UTC)
commit 498a9c1fda0206bbb88277edaea22dea9b856ead
Author: Christian Hergert <chergert redhat com>
Date: Tue Jun 6 02:26:07 2017 -0700
prefs: add default DzlPreferences implementation
This is based on IdePreferencesPerspective from Builder and extracted into
a standalone widget. It still needs iteration, in particular for CSS
styling. I also think we have some priority/positioning bugs to work
out.
src/dazzle.gresources.xml | 1 +
src/dazzle.h | 1 +
src/meson.build | 2 +
src/prefs/dzl-preferences-view.c | 870 +++++++++++++++++++++++++++++++++++++
src/prefs/dzl-preferences-view.h | 36 ++
src/prefs/dzl-preferences-view.ui | 75 ++++
tests/meson.build | 6 +
tests/test-preferences.c | 77 ++++
8 files changed, 1068 insertions(+), 0 deletions(-)
---
diff --git a/src/dazzle.gresources.xml b/src/dazzle.gresources.xml
index 3b5077b..97b74c3 100644
--- a/src/dazzle.gresources.xml
+++ b/src/dazzle.gresources.xml
@@ -11,6 +11,7 @@
<file compressed="true" preprocess="xml-stripblanks"
alias="dzl-preferences-page.ui">prefs/dzl-preferences-page.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="dzl-preferences-spin-button.ui">prefs/dzl-preferences-spin-button.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="dzl-preferences-switch.ui">prefs/dzl-preferences-switch.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks"
alias="dzl-preferences-view.ui">prefs/dzl-preferences-view.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="dzl-suggestion-popover.ui">suggestions/dzl-suggestion-popover.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="dzl-suggestion-row.ui">suggestions/dzl-suggestion-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="dzl-shortcut-accel-dialog.ui">shortcuts/dzl-shortcut-accel-dialog.ui</file>
diff --git a/src/dazzle.h b/src/dazzle.h
index 7659d2a..5117fb2 100644
--- a/src/dazzle.h
+++ b/src/dazzle.h
@@ -77,6 +77,7 @@ G_BEGIN_DECLS
#include "prefs/dzl-preferences-page.h"
#include "prefs/dzl-preferences-spin-button.h"
#include "prefs/dzl-preferences-switch.h"
+#include "prefs/dzl-preferences-view.h"
#include "prefs/dzl-preferences.h"
#include "search/dzl-fuzzy-index.h"
#include "search/dzl-fuzzy-index-builder.h"
diff --git a/src/meson.build b/src/meson.build
index 3e13244..f0264d2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -82,6 +82,7 @@ libdazzle_public_headers = [
'prefs/dzl-preferences-page.h',
'prefs/dzl-preferences-spin-button.h',
'prefs/dzl-preferences-switch.h',
+ 'prefs/dzl-preferences-view.h',
'prefs/dzl-preferences.h',
'search/dzl-fuzzy-index-builder.h',
@@ -217,6 +218,7 @@ libdazzle_public_sources = [
'prefs/dzl-preferences-page.c',
'prefs/dzl-preferences-spin-button.c',
'prefs/dzl-preferences-switch.c',
+ 'prefs/dzl-preferences-view.c',
'prefs/dzl-preferences.c',
'search/dzl-fuzzy-index-builder.c',
diff --git a/src/prefs/dzl-preferences-view.c b/src/prefs/dzl-preferences-view.c
new file mode 100644
index 0000000..ec31d36
--- /dev/null
+++ b/src/prefs/dzl-preferences-view.c
@@ -0,0 +1,870 @@
+/* dzl-preferences-view.c
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "dzl-preferences-view"
+
+#include <glib/gi18n.h>
+
+#include "prefs/dzl-preferences-file-chooser-button.h"
+#include "prefs/dzl-preferences-font-button.h"
+#include "prefs/dzl-preferences-group-private.h"
+#include "prefs/dzl-preferences-page-private.h"
+#include "prefs/dzl-preferences-spin-button.h"
+#include "prefs/dzl-preferences-switch.h"
+#include "prefs/dzl-preferences-view.h"
+#include "util/dzl-util-private.h"
+
+struct _DzlPreferencesView
+{
+ GtkBin parent_instance;
+
+ guint last_widget_id;
+
+ GActionGroup *actions;
+ GSequence *pages;
+ GHashTable *widgets;
+
+ GtkScrolledWindow *scroller;
+ GtkStack *page_stack;
+ GtkStackSwitcher *page_stack_sidebar;
+ GtkSearchEntry *search_entry;
+ GtkStack *subpage_stack;
+};
+
+static void dzl_preferences_iface_init (DzlPreferencesInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (DzlPreferencesView, dzl_preferences_view, GTK_TYPE_BIN,
+ G_IMPLEMENT_INTERFACE (DZL_TYPE_PREFERENCES, dzl_preferences_iface_init))
+
+static void
+dzl_preferences_view_refilter_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ DzlPreferencesPage *page = (DzlPreferencesPage *)widget;
+ DzlPatternSpec *spec = user_data;
+
+ g_assert (DZL_IS_PREFERENCES_PAGE (page));
+
+ dzl_preferences_page_refilter (page, spec);
+}
+
+static void
+dzl_preferences_view_refilter (DzlPreferencesView *self,
+ const gchar *search_text)
+{
+ DzlPatternSpec *spec = NULL;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+
+ if (!dzl_str_empty0 (search_text))
+ spec = dzl_pattern_spec_new (search_text);
+
+ gtk_container_foreach (GTK_CONTAINER (self->page_stack),
+ dzl_preferences_view_refilter_cb,
+ spec);
+ gtk_container_foreach (GTK_CONTAINER (self->subpage_stack),
+ dzl_preferences_view_refilter_cb,
+ spec);
+
+ g_clear_pointer (&spec, dzl_pattern_spec_unref);
+}
+
+static gint
+sort_by_priority (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ gint prioritya = 0;
+ gint priorityb = 0;
+
+ g_object_get ((gpointer)a, "priority", &prioritya, NULL);
+ g_object_get ((gpointer)b, "priority", &priorityb, NULL);
+
+ return prioritya - priorityb;
+}
+
+static void
+dzl_preferences_view_notify_visible_child (DzlPreferencesView *self,
+ GParamSpec *pspec,
+ GtkStack *stack)
+{
+ DzlPreferencesPage *page;
+ GHashTableIter iter;
+ gpointer value;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+
+ /* Short circuit if we are destroying everything */
+ if (gtk_widget_in_destruction (GTK_WIDGET (self)))
+ return;
+
+ gtk_widget_hide (GTK_WIDGET (self->subpage_stack));
+
+ /*
+ * If there are any selections in list groups, re-select it to cause
+ * the subpage to potentially reappear.
+ */
+
+ if (NULL == (page = DZL_PREFERENCES_PAGE (gtk_stack_get_visible_child (stack))))
+ return;
+
+ g_hash_table_iter_init (&iter, page->groups_by_name);
+
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ DzlPreferencesGroup *group = value;
+ GtkSelectionMode mode = GTK_SELECTION_NONE;
+
+ g_assert (DZL_IS_PREFERENCES_GROUP (group));
+
+ if (!group->is_list)
+ continue;
+
+ g_object_get (group, "mode", &mode, NULL);
+
+ if (mode == GTK_SELECTION_SINGLE)
+ {
+ GtkListBoxRow *selected;
+
+ selected = gtk_list_box_get_selected_row (group->list_box);
+
+ g_assert (!selected || GTK_IS_LIST_BOX_ROW (selected));
+
+ if (selected != NULL && gtk_widget_activate (GTK_WIDGET (selected)))
+ break;
+ }
+ }
+}
+
+static void
+dzl_preferences_view_finalize (GObject *object)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)object;
+
+ g_clear_pointer (&self->pages, g_sequence_free);
+ g_clear_pointer (&self->widgets, g_hash_table_unref);
+ g_clear_object (&self->actions);
+
+ G_OBJECT_CLASS (dzl_preferences_view_parent_class)->finalize (object);
+}
+
+static void
+dzl_preferences_view_class_init (DzlPreferencesViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = dzl_preferences_view_finalize;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/dazzle/ui/dzl-preferences-view.ui");
+ gtk_widget_class_set_css_name (widget_class, "dzlpreferencesview");
+ gtk_widget_class_bind_template_child (widget_class, DzlPreferencesView, page_stack);
+ gtk_widget_class_bind_template_child (widget_class, DzlPreferencesView, page_stack_sidebar);
+ gtk_widget_class_bind_template_child (widget_class, DzlPreferencesView, scroller);
+ gtk_widget_class_bind_template_child (widget_class, DzlPreferencesView, search_entry);
+ gtk_widget_class_bind_template_child (widget_class, DzlPreferencesView, subpage_stack);
+}
+
+static void
+go_back_activate (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ DzlPreferencesView *self = user_data;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+
+ gtk_widget_hide (GTK_WIDGET (self->subpage_stack));
+}
+
+static void
+dzl_preferences_view_search_entry_changed (DzlPreferencesView *self,
+ GtkSearchEntry *search_entry)
+{
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (GTK_IS_SEARCH_ENTRY (search_entry));
+
+ dzl_preferences_view_refilter (self, gtk_entry_get_text (GTK_ENTRY (search_entry)));
+}
+
+static void
+dzl_preferences_view_notify_subpage_stack_visible (DzlPreferencesView *self,
+ GParamSpec *pspec,
+ GtkStack *subpage_stack)
+{
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (GTK_IS_STACK (subpage_stack));
+
+ /*
+ * Because the subpage stack can cause us to have a wider display than
+ * the screen has, we need to allow scrolling. This can happen because
+ * side-by-side we could be just a bit bigger than 1280px which is a
+ * fairly common laptop screen size (especially under HiDPI).
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=772700
+ */
+
+ if (gtk_widget_get_visible (GTK_WIDGET (subpage_stack)))
+ g_object_set (self->scroller, "hscrollbar-policy", GTK_POLICY_AUTOMATIC, NULL);
+ else
+ g_object_set (self->scroller, "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
+}
+
+static void
+dzl_preferences_view_init (DzlPreferencesView *self)
+{
+ static const GActionEntry entries[] = {
+ { "go-back", go_back_activate },
+ };
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect_object (self->search_entry,
+ "changed",
+ G_CALLBACK (dzl_preferences_view_search_entry_changed),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->page_stack,
+ "notify::visible-child",
+ G_CALLBACK (dzl_preferences_view_notify_visible_child),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->subpage_stack,
+ "notify::visible",
+ G_CALLBACK (dzl_preferences_view_notify_subpage_stack_visible),
+ self,
+ G_CONNECT_SWAPPED);
+
+ self->pages = g_sequence_new (NULL);
+ self->widgets = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ self->actions = G_ACTION_GROUP (g_simple_action_group_new ());
+ g_action_map_add_action_entries (G_ACTION_MAP (self->actions),
+ entries, G_N_ELEMENTS (entries),
+ self);
+}
+
+static GtkWidget *
+dzl_preferences_view_get_page (DzlPreferencesView *self,
+ const gchar *page_name)
+{
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+
+ if (strchr (page_name, '.') != NULL)
+ return gtk_stack_get_child_by_name (self->subpage_stack, page_name);
+ else
+ return gtk_stack_get_child_by_name (self->page_stack, page_name);
+}
+
+static void
+dzl_preferences_view_add_page (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *title,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesPage *page;
+ GSequenceIter *iter;
+ GtkStack *stack;
+ gint position = -1;
+
+ g_assert (DZL_IS_PREFERENCES (preferences));
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (title != NULL || strchr (page_name, '.'));
+
+ if (strchr (page_name, '.') != NULL)
+ stack = self->subpage_stack;
+ else
+ stack = self->page_stack;
+
+ if (gtk_stack_get_child_by_name (stack, page_name))
+ return;
+
+ page = g_object_new (DZL_TYPE_PREFERENCES_PAGE,
+ "priority", priority,
+ "visible", TRUE,
+ NULL);
+
+ if (stack == self->page_stack)
+ {
+ iter = g_sequence_insert_sorted (self->pages, page, sort_by_priority, NULL);
+ position = g_sequence_iter_get_position (iter);
+ }
+
+ gtk_container_add_with_properties (GTK_CONTAINER (stack), GTK_WIDGET (page),
+ "position", position,
+ "name", page_name,
+ "title", title,
+ NULL);
+}
+
+static void
+dzl_preferences_view_add_group (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *title,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesGroup *group;
+ GtkWidget *page;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return;
+ }
+
+ group = g_object_new (DZL_TYPE_PREFERENCES_GROUP,
+ "name", group_name,
+ "priority", priority,
+ "title", title,
+ "visible", TRUE,
+ NULL);
+ dzl_preferences_page_add_group (DZL_PREFERENCES_PAGE (page), group);
+}
+
+static void
+dzl_preferences_view_add_list_group (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *title,
+ GtkSelectionMode mode,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesGroup *group;
+ GtkWidget *page;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return;
+ }
+
+ group = g_object_new (DZL_TYPE_PREFERENCES_GROUP,
+ "is-list", TRUE,
+ "mode", mode,
+ "name", group_name,
+ "priority", priority,
+ "title", title,
+ "visible", TRUE,
+ NULL);
+ dzl_preferences_page_add_group (DZL_PREFERENCES_PAGE (page), group);
+}
+
+static guint
+dzl_preferences_view_add_radio (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *path,
+ const gchar *variant_string,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesSwitch *widget;
+ DzlPreferencesGroup *group;
+ g_autoptr(GVariant) variant = NULL;
+ GtkWidget *page;
+ guint widget_id;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+ g_assert (schema_id != NULL);
+ g_assert (key != NULL);
+ g_assert (title != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return 0;
+ }
+
+ group = dzl_preferences_page_get_group (DZL_PREFERENCES_PAGE (page), group_name);
+
+ if (group == NULL)
+ {
+ g_warning ("No such preferences group \"%s\" in page \"%s\"",
+ group_name, page_name);
+ return 0;
+ }
+
+ if (variant_string != NULL)
+ {
+ g_autoptr(GError) error = NULL;
+
+ variant = g_variant_parse (NULL, variant_string, NULL, NULL, &error);
+
+ if (variant == NULL)
+ g_warning ("%s", error->message);
+ else
+ g_variant_ref_sink (variant);
+ }
+
+ widget = g_object_new (DZL_TYPE_PREFERENCES_SWITCH,
+ "is-radio", TRUE,
+ "key", key,
+ "keywords", keywords,
+ "path", path,
+ "priority", priority,
+ "schema-id", schema_id,
+ "subtitle", subtitle,
+ "target", variant,
+ "title", title,
+ "visible", TRUE,
+ NULL);
+
+ dzl_preferences_group_add (group, GTK_WIDGET (widget));
+
+ widget_id = ++self->last_widget_id;
+ g_hash_table_insert (self->widgets, GINT_TO_POINTER (widget_id), widget);
+
+ return widget_id;
+}
+
+static guint
+dzl_preferences_view_add_switch (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *path,
+ const gchar *variant_string,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesSwitch *widget;
+ DzlPreferencesGroup *group;
+ g_autoptr(GVariant) variant = NULL;
+ GtkWidget *page;
+ guint widget_id;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+ g_assert (schema_id != NULL);
+ g_assert (key != NULL);
+ g_assert (title != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return 0;
+ }
+
+ group = dzl_preferences_page_get_group (DZL_PREFERENCES_PAGE (page), group_name);
+
+ if (group == NULL)
+ {
+ g_warning ("No such preferences group \"%s\" in page \"%s\"",
+ group_name, page_name);
+ return 0;
+ }
+
+ if (variant_string != NULL)
+ {
+ g_autoptr(GError) error = NULL;
+
+ variant = g_variant_parse (NULL, variant_string, NULL, NULL, &error);
+
+ if (variant == NULL)
+ g_warning ("%s", error->message);
+ else
+ g_variant_ref_sink (variant);
+ }
+
+ widget = g_object_new (DZL_TYPE_PREFERENCES_SWITCH,
+ "key", key,
+ "keywords", keywords,
+ "path", path,
+ "priority", priority,
+ "schema-id", schema_id,
+ "subtitle", subtitle,
+ "target", variant,
+ "title", title,
+ "visible", TRUE,
+ NULL);
+
+ dzl_preferences_group_add (group, GTK_WIDGET (widget));
+
+ widget_id = ++self->last_widget_id;
+ g_hash_table_insert (self->widgets, GINT_TO_POINTER (widget_id), widget);
+
+ return widget_id;
+}
+
+static guint
+dzl_preferences_view_add_spin_button (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *path,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesSpinButton *widget;
+ DzlPreferencesGroup *group;
+ GtkWidget *page;
+ guint widget_id;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+ g_assert (schema_id != NULL);
+ g_assert (key != NULL);
+ g_assert (title != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return 0;
+ }
+
+ group = dzl_preferences_page_get_group (DZL_PREFERENCES_PAGE (page), group_name);
+
+
+ if (group == NULL)
+ {
+ g_warning ("No such preferences group \"%s\" in page \"%s\"",
+ group_name, page_name);
+ return 0;
+ }
+
+ widget = g_object_new (DZL_TYPE_PREFERENCES_SPIN_BUTTON,
+ "key", key,
+ "keywords", keywords,
+ "path", path,
+ "priority", priority,
+ "schema-id", schema_id,
+ "subtitle", subtitle,
+ "title", title,
+ "visible", TRUE,
+ NULL);
+
+ dzl_preferences_group_add (group, GTK_WIDGET (widget));
+
+ widget_id = ++self->last_widget_id;
+ g_hash_table_insert (self->widgets, GINT_TO_POINTER (widget_id), widget);
+
+ return widget_id;
+}
+
+static guint
+dzl_preferences_view_add_font_button (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *keywords,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesSwitch *widget;
+ DzlPreferencesGroup *group;
+ GtkWidget *page;
+ guint widget_id;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+ g_assert (schema_id != NULL);
+ g_assert (key != NULL);
+ g_assert (title != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return 0;
+ }
+
+ group = dzl_preferences_page_get_group (DZL_PREFERENCES_PAGE (page), group_name);
+
+ if (group == NULL)
+ {
+ g_warning ("No such preferences group \"%s\" in page \"%s\"",
+ group_name, page_name);
+ return 0;
+ }
+
+ widget = g_object_new (DZL_TYPE_PREFERENCES_FONT_BUTTON,
+ "key", key,
+ "keywords", keywords,
+ "priority", priority,
+ "schema-id", schema_id,
+ "title", title,
+ "visible", TRUE,
+ NULL);
+
+ dzl_preferences_group_add (group, GTK_WIDGET (widget));
+
+ widget_id = ++self->last_widget_id;
+ g_hash_table_insert (self->widgets, GINT_TO_POINTER (widget_id), widget);
+
+ return widget_id;
+}
+
+static guint
+dzl_preferences_view_add_file_chooser (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *path,
+ const gchar *title,
+ const gchar *subtitle,
+ GtkFileChooserAction action,
+ const gchar *keywords,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesFileChooserButton *widget;
+ DzlPreferencesGroup *group;
+ GtkWidget *page;
+ guint widget_id;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+ g_assert (schema_id != NULL);
+ g_assert (key != NULL);
+ g_assert (title != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return 0;
+ }
+
+ group = dzl_preferences_page_get_group (DZL_PREFERENCES_PAGE (page), group_name);
+
+ if (group == NULL)
+ {
+ g_warning ("No such preferences group \"%s\" in page \"%s\"",
+ group_name, page_name);
+ return 0;
+ }
+
+ widget = g_object_new (DZL_TYPE_PREFERENCES_FILE_CHOOSER_BUTTON,
+ "action", action,
+ "key", key,
+ "priority", priority,
+ "schema-id", schema_id,
+ "path", path,
+ "subtitle", subtitle,
+ "title", title,
+ "keywords", keywords,
+ "visible", TRUE,
+ NULL);
+
+ dzl_preferences_group_add (group, GTK_WIDGET (widget));
+
+ widget_id = ++self->last_widget_id;
+ g_hash_table_insert (self->widgets, GINT_TO_POINTER (widget_id), widget);
+
+ return widget_id;
+}
+
+static guint
+dzl_preferences_view_add_custom (DzlPreferences *preferences,
+ const gchar *page_name,
+ const gchar *group_name,
+ GtkWidget *widget,
+ const gchar *keywords,
+ gint priority)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ DzlPreferencesBin *container;
+ DzlPreferencesGroup *group;
+ GtkWidget *page;
+ guint widget_id;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+ g_assert (group_name != NULL);
+ g_assert (GTK_IS_WIDGET (widget));
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No page named \"%s\" could be found.", page_name);
+ return 0;
+ }
+
+ group = dzl_preferences_page_get_group (DZL_PREFERENCES_PAGE (page), group_name);
+
+ if (group == NULL)
+ {
+ g_warning ("No such preferences group \"%s\" in page \"%s\"",
+ group_name, page_name);
+ return 0;
+ }
+
+ widget_id = ++self->last_widget_id;
+
+ gtk_widget_show (widget);
+ gtk_widget_show (GTK_WIDGET (group));
+
+ if (DZL_IS_PREFERENCES_BIN (widget))
+ container = DZL_PREFERENCES_BIN (widget);
+ else
+ container = g_object_new (DZL_TYPE_PREFERENCES_BIN,
+ "child", widget,
+ "keywords", keywords,
+ "priority", priority,
+ "visible", TRUE,
+ NULL);
+
+ dzl_preferences_group_add (group, GTK_WIDGET (container));
+
+ g_hash_table_insert (self->widgets, GINT_TO_POINTER (widget_id), widget);
+
+ return widget_id;
+}
+
+static gboolean
+dzl_preferences_view_remove_id (DzlPreferences *preferences,
+ guint widget_id)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ GtkWidget *widget;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (widget_id);
+
+ widget = g_hash_table_lookup (self->widgets, GINT_TO_POINTER (widget_id));
+ if (widget != NULL)
+ {
+ if (g_hash_table_remove (self->widgets, GINT_TO_POINTER (widget_id)))
+ {
+ GtkWidget *parent = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
+
+ /* in case we added our own row ancestor, destroy it */
+ if (parent != NULL)
+ gtk_widget_destroy (parent);
+ else
+ gtk_widget_destroy (widget);
+
+ return TRUE;
+ }
+ }
+
+ g_warning ("No Preferences widget with number %i could be found and thus removed.", widget_id);
+
+ return FALSE;
+}
+
+static void
+dzl_preferences_view_set_page (DzlPreferences *preferences,
+ const gchar *page_name,
+ GHashTable *map)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+ GtkWidget *page;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (page_name != NULL);
+
+ page = dzl_preferences_view_get_page (self, page_name);
+
+ if (page == NULL)
+ {
+ g_warning ("No such page \"%s\"", page_name);
+ return;
+ }
+
+ if (strchr (page_name, '.') != NULL)
+ {
+ dzl_preferences_page_set_map (DZL_PREFERENCES_PAGE (page), map);
+ gtk_stack_set_visible_child (self->subpage_stack, page);
+ gtk_widget_show (GTK_WIDGET (self->subpage_stack));
+ }
+ else
+ {
+ gtk_stack_set_visible_child (self->page_stack, page);
+ gtk_widget_hide (GTK_WIDGET (self->subpage_stack));
+ }
+}
+
+static GtkWidget *
+dzl_preferences_view_get_widget (DzlPreferences *preferences,
+ guint widget_id)
+{
+ DzlPreferencesView *self = (DzlPreferencesView *)preferences;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+
+ return g_hash_table_lookup (self->widgets, GINT_TO_POINTER (widget_id));
+}
+
+static void
+dzl_preferences_iface_init (DzlPreferencesInterface *iface)
+{
+ iface->add_page = dzl_preferences_view_add_page;
+ iface->add_group = dzl_preferences_view_add_group;
+ iface->add_list_group = dzl_preferences_view_add_list_group;
+ iface->add_radio = dzl_preferences_view_add_radio;
+ iface->add_font_button = dzl_preferences_view_add_font_button;
+ iface->add_switch = dzl_preferences_view_add_switch;
+ iface->add_spin_button = dzl_preferences_view_add_spin_button;
+ iface->add_file_chooser = dzl_preferences_view_add_file_chooser;
+ iface->add_custom = dzl_preferences_view_add_custom;
+ iface->set_page = dzl_preferences_view_set_page;
+ iface->remove_id = dzl_preferences_view_remove_id;
+ iface->get_widget = dzl_preferences_view_get_widget;
+}
diff --git a/src/prefs/dzl-preferences-view.h b/src/prefs/dzl-preferences-view.h
new file mode 100644
index 0000000..91ca058
--- /dev/null
+++ b/src/prefs/dzl-preferences-view.h
@@ -0,0 +1,36 @@
+/* dzl-preferences-view.h
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DZL_PREFERENCES_VIEW_H
+#define DZL_PREFERENCES_VIEW_H
+
+#include <gtk/gtk.h>
+
+#include "prefs/dzl-preferences.h"
+
+G_BEGIN_DECLS
+
+#define DZL_TYPE_PREFERENCES_VIEW (dzl_preferences_view_get_type())
+
+G_DECLARE_FINAL_TYPE (DzlPreferencesView, dzl_preferences_view, DZL, PREFERENCES_VIEW, GtkBin)
+
+GtkWidget *dzl_preferences_view_new (void);
+
+G_END_DECLS
+
+#endif /* DZL_PREFERENCES_VIEW_H */
diff --git a/src/prefs/dzl-preferences-view.ui b/src/prefs/dzl-preferences-view.ui
new file mode 100644
index 0000000..25bb738
--- /dev/null
+++ b/src/prefs/dzl-preferences-view.ui
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.18 -->
+ <template class="DzlPreferencesView" parent="GtkBin">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="placeholder-text" translatable="yes">Search Preferences</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="preferences-search"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackSidebar" id="page_stack_sidebar">
+ <property name="stack">page_stack</property>
+ <property name="visible">true</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">200</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scroller">
+ <property name="hscrollbar-policy">never</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkStack" id="page_stack">
+ <property name="margin">24</property>
+ <property name="homogeneous">false</property>
+ <property name="transition-duration">333</property>
+ <property name="transition-type">crossfade</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkStack" id="subpage_stack">
+ <property name="margin-start">0</property>
+ <property name="margin-end">24</property>
+ <property name="margin-top">24</property>
+ <property name="margin-bottom">24</property>
+ <property name="halign">start</property>
+ <property name="hexpand">false</property>
+ <property name="homogeneous">false</property>
+ <property name="transition-duration">333</property>
+ <property name="transition-type">crossfade</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/tests/meson.build b/tests/meson.build
index 7fc8eed..923e554 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -232,3 +232,9 @@ test_pill_box = executable('test-pill-box', 'test-pill-box.c',
link_args: test_link_args,
dependencies: libdazzle_deps + [libdazzle_dep],
)
+
+test_preferences = executable('test-preferences', 'test-preferences.c',
+ c_args: test_cflags,
+ link_args: test_link_args,
+ dependencies: libdazzle_deps + [libdazzle_dep],
+)
diff --git a/tests/test-preferences.c b/tests/test-preferences.c
new file mode 100644
index 0000000..e3b4291
--- /dev/null
+++ b/tests/test-preferences.c
@@ -0,0 +1,77 @@
+#include <dazzle.h>
+
+static const gchar *themes[] = {
+ "Applications",
+ "Cursor",
+ "Icons",
+ "System",
+ NULL
+};
+
+static void
+add_preferences (DzlPreferences *prefs)
+{
+ dzl_preferences_add_page (prefs, "appearance", "Appearance", 0);
+ dzl_preferences_add_page (prefs, "desktop", "Desktop", 1);
+ dzl_preferences_add_page (prefs, "extensions", "Extensions", 2);
+ dzl_preferences_add_page (prefs, "fonts", "Fonts", 3);
+ dzl_preferences_add_page (prefs, "keyboard", "Keyboard & Mouse", 4);
+ dzl_preferences_add_page (prefs, "power", "Power", 5);
+ dzl_preferences_add_page (prefs, "startup", "Startup Applications", 6);
+ dzl_preferences_add_page (prefs, "topbar", "Top Bar", 7);
+ dzl_preferences_add_page (prefs, "windows", "Windows", 7);
+ dzl_preferences_add_page (prefs, "workspaces", "Workspaces", 8);
+
+ dzl_preferences_add_group (prefs, "appearance", "basic", NULL, 0);
+ dzl_preferences_add_switch (prefs, "appearance", "basic", "com.example", "foo", NULL, NULL, "Global Dark
Theme", "Applications need to be restarted for this change to take place", "dark theme", 0);
+ dzl_preferences_add_switch (prefs, "appearance", "basic", "com.example", "foo", NULL, NULL, "Animations",
NULL, "animations", 1);
+
+ dzl_preferences_add_list_group (prefs, "appearance", "themes", "Themes", GTK_SELECTION_NONE, 10);
+
+ for (guint i = 0; themes[i]; i++)
+ dzl_preferences_add_custom (prefs, "appearance", "themes",
+ g_object_new (GTK_TYPE_LABEL,
+ "label", themes[i],
+ "visible", TRUE,
+ "xalign", 0.0f,
+ NULL),
+ themes[i], i);
+
+ dzl_preferences_add_group (prefs, "appearance", "install", NULL, 20);
+ dzl_preferences_add_custom (prefs, "appearance", "install",
+ g_object_new (GTK_TYPE_BUTTON,
+ "label", "Install from Fileā¦",
+ "halign", GTK_ALIGN_END,
+ "visible", TRUE,
+ NULL),
+ NULL, 0);
+
+ dzl_preferences_set_page (prefs, "appearance", NULL);
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *view;
+
+ gtk_init (&argc, &argv);
+
+ window = g_object_new (GTK_TYPE_WINDOW,
+ "title", "Preferences Test",
+ "default-width", 800,
+ "default-height", 600,
+ NULL);
+
+ view = g_object_new (DZL_TYPE_PREFERENCES_VIEW,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (window), view);
+
+ add_preferences (DZL_PREFERENCES (view));
+
+ g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
+ gtk_window_present (GTK_WINDOW (window));
+ return gtk_main (), 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]