[ghex/gtk4-port: 46/91] Implement syncing of prefs
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex/gtk4-port: 46/91] Implement syncing of prefs
- Date: Thu, 12 Aug 2021 23:35:10 +0000 (UTC)
commit 773286b6b1b95e3ce0fc4db012c7d20925c1cd0f
Author: Logan Rathbone <poprocks gmail com>
Date: Wed Jan 20 20:13:02 2021 -0500
Implement syncing of prefs
src/ghex-application-window.c | 326 +++++++++++++++++++++++++++++++++++++----
src/ghex-application-window.ui | 10 +-
src/gtkhex.c | 2 +-
src/meson.build | 4 +-
4 files changed, 310 insertions(+), 32 deletions(-)
---
diff --git a/src/ghex-application-window.c b/src/ghex-application-window.c
index 502b3e9b..59fd98f8 100644
--- a/src/ghex-application-window.c
+++ b/src/ghex-application-window.c
@@ -66,6 +66,7 @@ struct _GHexApplicationWindow
GtkApplicationWindow parent_instance;
GtkHex *gh;
+ GtkCssProvider *provider;
HexDialog *dialog;
GtkWidget *dialog_widget;
guint statusbar_id;
@@ -154,38 +155,255 @@ static void update_gui_data (GHexApplicationWindow *self);
/* GHexApplicationWindow -- PRIVATE FUNCTIONS */
-// FIXME - This could be the wrong approach. I don't know if we can
-// guarantee the tab will be un-switchable while the dialog is up.
-
+/* This function was written by Matthias Clasen and is included somewhere in
+ * the GTK source tree.. I believe it is also included in libdazzle, but I
+ * didn't want to include a whole dependency just for one function. LGPL, but
+ * credit where credit is due!
+ */
+static char *
+pango_font_description_to_css (PangoFontDescription *desc)
+{
+ GString *s;
+ PangoFontMask set;
+
+ s = g_string_new ("* { ");
+
+ set = pango_font_description_get_set_fields (desc);
+ if (set & PANGO_FONT_MASK_FAMILY)
+ {
+ g_string_append (s, "font-family: ");
+ g_string_append (s, pango_font_description_get_family (desc));
+ g_string_append (s, "; ");
+ }
+ if (set & PANGO_FONT_MASK_STYLE)
+ {
+ switch (pango_font_description_get_style (desc))
+ {
+ case PANGO_STYLE_NORMAL:
+ g_string_append (s, "font-style: normal; ");
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ g_string_append (s, "font-style: oblique; ");
+ break;
+ case PANGO_STYLE_ITALIC:
+ g_string_append (s, "font-style: italic; ");
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_VARIANT)
+ {
+ switch (pango_font_description_get_variant (desc))
+ {
+ case PANGO_VARIANT_NORMAL:
+ g_string_append (s, "font-variant: normal; ");
+ break;
+ case PANGO_VARIANT_SMALL_CAPS:
+ g_string_append (s, "font-variant: small-caps; ");
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_WEIGHT)
+ {
+ switch (pango_font_description_get_weight (desc))
+ {
+ case PANGO_WEIGHT_THIN:
+ g_string_append (s, "font-weight: 100; ");
+ break;
+ case PANGO_WEIGHT_ULTRALIGHT:
+ g_string_append (s, "font-weight: 200; ");
+ break;
+ case PANGO_WEIGHT_LIGHT:
+ case PANGO_WEIGHT_SEMILIGHT:
+ g_string_append (s, "font-weight: 300; ");
+ break;
+ case PANGO_WEIGHT_BOOK:
+ case PANGO_WEIGHT_NORMAL:
+ g_string_append (s, "font-weight: 400; ");
+ break;
+ case PANGO_WEIGHT_MEDIUM:
+ g_string_append (s, "font-weight: 500; ");
+ break;
+ case PANGO_WEIGHT_SEMIBOLD:
+ g_string_append (s, "font-weight: 600; ");
+ break;
+ case PANGO_WEIGHT_BOLD:
+ g_string_append (s, "font-weight: 700; ");
+ break;
+ case PANGO_WEIGHT_ULTRABOLD:
+ g_string_append (s, "font-weight: 800; ");
+ break;
+ case PANGO_WEIGHT_HEAVY:
+ case PANGO_WEIGHT_ULTRAHEAVY:
+ g_string_append (s, "font-weight: 900; ");
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_STRETCH)
+ {
+ switch (pango_font_description_get_stretch (desc))
+ {
+ case PANGO_STRETCH_ULTRA_CONDENSED:
+ g_string_append (s, "font-stretch: ultra-condensed; ");
+ break;
+ case PANGO_STRETCH_EXTRA_CONDENSED:
+ g_string_append (s, "font-stretch: extra-condensed; ");
+ break;
+ case PANGO_STRETCH_CONDENSED:
+ g_string_append (s, "font-stretch: condensed; ");
+ break;
+ case PANGO_STRETCH_SEMI_CONDENSED:
+ g_string_append (s, "font-stretch: semi-condensed; ");
+ break;
+ case PANGO_STRETCH_NORMAL:
+ g_string_append (s, "font-stretch: normal; ");
+ break;
+ case PANGO_STRETCH_SEMI_EXPANDED:
+ g_string_append (s, "font-stretch: semi-expanded; ");
+ break;
+ case PANGO_STRETCH_EXPANDED:
+ g_string_append (s, "font-stretch: expanded; ");
+ break;
+ case PANGO_STRETCH_EXTRA_EXPANDED:
+ g_string_append (s, "font-stretch: extra-expanded; ");
+ break;
+ case PANGO_STRETCH_ULTRA_EXPANDED:
+ g_string_append (s, "font-stretch: ultra-expanded; ");
+ break;
+ }
+ }
+ if (set & PANGO_FONT_MASK_SIZE)
+ {
+ g_string_append_printf (s, "font-size: %dpt",
+ pango_font_description_get_size (desc) / PANGO_SCALE);
+ }
+
+ g_string_append (s, "}");
+
+ return g_string_free (s, FALSE);
+}
+
+/* set_*_from_settings
+ * These functions all basically set properties from the GSettings global
+ * variables. They should be used when a new gh is created, and when we're
+ * `foreaching` through all of our tabs via a settings-change cb. See also
+ * the `SETTINGS_CHANGED_GH_FOREACH_{START,END}` macros below.
+ */
+static void
+set_css_provider_font_from_settings (GHexApplicationWindow *self)
+{
+ PangoFontDescription *desc;
+ char *css_str;
+
+ desc = pango_font_description_from_string (def_font_name);
+ css_str = pango_font_description_to_css (desc);
+
+ g_debug("%s: css_str: %s", __func__, css_str);
+
+ gtk_css_provider_load_from_data (GTK_STYLE_PROVIDER(self->provider),
+ css_str, -1);
+}
+
+static void
+set_gtkhex_font_from_settings (GHexApplicationWindow *self, GtkHex *gh)
+{
+ GtkStyleContext *context;
+
+ g_return_if_fail (GTK_IS_HEX(gh));
+ g_return_if_fail (GTK_IS_STYLE_PROVIDER(self->provider));
+
+ context = gtk_widget_get_style_context (GTK_WIDGET(gh));
+
+ gtk_style_context_add_provider (context,
+ GTK_STYLE_PROVIDER (self->provider),
+ GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
+}
+
+static void
+set_gtkhex_offsets_column_from_settings (GtkHex *gh)
+{
+ gtk_hex_show_offsets (gh, show_offsets_column);
+}
+
+static void
+set_gtkhex_group_type_from_settings (GtkHex *gh)
+{
+ gtk_hex_set_group_type (gh, def_group_type);
+}
+
+
+/* Common macro for the `settings*changed_cb` stuff.
+ * Between _START and _END, put in function calls that use `gh` to be applied
+ * to each gh in a tab. Technically you'll also have access to `notebook`
+ * and `tab`, but there is generally no reason to directly access these.
+ */
+#define SETTINGS_CHANGED_GH_FOREACH_START
\
+{
\
+ GtkNotebook *notebook = GTK_NOTEBOOK(self->hex_notebook); \
+ int i;
\
+ g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); \
+ for (i = gtk_notebook_get_n_pages(notebook) - 1; i >= 0; --i) { \
+ GHexNotebookTab *tab;
\
+ GtkHex *gh;
\
+ g_debug ("%s: Working on %d'th page", __func__, i); \
+ gh = GTK_HEX(gtk_notebook_get_nth_page (notebook, i)); \
+ g_return_if_fail (GTK_IS_HEX (gh));
\
+ tab = GHEX_NOTEBOOK_TAB(gtk_notebook_get_tab_label (notebook, \
+ GTK_WIDGET(gh)));
\
+ g_return_if_fail (GHEX_IS_NOTEBOOK_TAB (tab)); \
+/* !SETTINGS_CHANGED_GH_FOREACH_START */
+
+#define SETTINGS_CHANGED_GH_FOREACH_END
\
+ }
\
+}
\
+/* !SETTINGS_CHANGED_GH_FOREACH_END */
+
+
+static void
+settings_font_changed_cb (GSettings *settings,
+ const gchar *key,
+ gpointer user_data)
+{
+ GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
+
+ SETTINGS_CHANGED_GH_FOREACH_START
+
+ set_css_provider_font_from_settings (self);
+ set_gtkhex_font_from_settings (self, gh);
+
+ SETTINGS_CHANGED_GH_FOREACH_END
+}
+
static void
settings_offsets_column_changed_cb (GSettings *settings,
const gchar *key,
gpointer user_data)
{
GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
- GtkNotebook *notebook = GTK_NOTEBOOK(self->hex_notebook);
- int i;
- g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+ SETTINGS_CHANGED_GH_FOREACH_START
- for (i = gtk_notebook_get_n_pages(notebook) - 1; i >= 0; --i)
- {
- GHexNotebookTab *tab;
- GtkHex *gh;
+ set_gtkhex_offsets_column_from_settings (gh);
- g_debug ("%s: Working on %d'th page", __func__, i);
+ SETTINGS_CHANGED_GH_FOREACH_END
+}
- gh = GTK_HEX(gtk_notebook_get_nth_page (notebook, i));
- g_return_if_fail (GTK_IS_HEX (gh));
+static void
+settings_group_type_changed_cb (GSettings *settings,
+ const gchar *key,
+ gpointer user_data)
+{
+ GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
- tab = GHEX_NOTEBOOK_TAB(gtk_notebook_get_tab_label (notebook,
- GTK_WIDGET(gh)));
- g_return_if_fail (GHEX_IS_NOTEBOOK_TAB (tab));
+ SETTINGS_CHANGED_GH_FOREACH_START
- gtk_hex_show_offsets (gh, show_offsets_column);
- }
+ set_gtkhex_group_type_from_settings (gh);
+
+ SETTINGS_CHANGED_GH_FOREACH_END
}
+/* ! settings*changed_cb 's */
+
+
GHexNotebookTab *
ghex_application_window_get_current_tab (GHexApplicationWindow *self)
{
@@ -906,9 +1124,6 @@ new_gh_from_gfile (GFile *file)
doc = hex_document_new_from_file (path);
gh = GTK_HEX(gtk_hex_new (doc));
- /* Initialize whether offsets should be shown based on setting. */
- gtk_hex_show_offsets (gh, show_offsets_column);
-
if (error) g_error_free (error);
g_clear_object (&info);
g_clear_object (&file);
@@ -1417,7 +1632,8 @@ ghex_application_window_init (GHexApplicationWindow *self)
{
GtkWidget *widget = GTK_WIDGET(self);
GtkStyleContext *context;
- GtkCssProvider *provider;
+ GtkCssProvider *conversions_box_provider;
+ GAction *action;
gtk_widget_init_template (widget);
@@ -1428,19 +1644,24 @@ ghex_application_window_init (GHexApplicationWindow *self)
gtk_box_append (GTK_BOX(self->conversions_box), self->dialog_widget);
gtk_widget_hide (self->conversions_box);
+ /* CSS - provider for GtkHex widget */
+
+ self->provider = gtk_css_provider_new ();
+
/* CSS - conversions_box */
+
context = gtk_widget_get_style_context (self->conversions_box);
- provider = gtk_css_provider_new ();
+ conversions_box_provider = gtk_css_provider_new ();
- gtk_css_provider_load_from_data (provider,
+ gtk_css_provider_load_from_data (conversions_box_provider,
"box {\n"
" padding: 20px;\n"
"}\n", -1);
/* add the provider to our widget's style context. */
gtk_style_context_add_provider (context,
- GTK_STYLE_PROVIDER (provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ GTK_STYLE_PROVIDER (conversions_box_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
/* Setup signals */
@@ -1452,6 +1673,23 @@ ghex_application_window_init (GHexApplicationWindow *self)
g_signal_connect (settings, "changed::" GHEX_PREF_OFFSETS_COLUMN,
G_CALLBACK (settings_offsets_column_changed_cb), self);
+ g_signal_connect (settings, "changed::" GHEX_PREF_FONT,
+ G_CALLBACK (settings_font_changed_cb), self);
+
+ g_signal_connect (settings, "changed::" GHEX_PREF_GROUP,
+ G_CALLBACK (settings_group_type_changed_cb), self);
+
+
+ /* Actions - SETTINGS */
+
+ /* for the 'group data by' stuff. There isn't a function to do this from
+ * class-init, so we end up with the 'win' namespace when we do it from
+ * here. Be aware of that.
+ */
+ action = g_settings_create_action (settings,
+ GHEX_PREF_GROUP);
+ g_action_map_add_action (G_ACTION_MAP(self), action);
+
/* Setup notebook signals */
g_signal_connect (self->hex_notebook, "switch-page",
@@ -1518,17 +1756,39 @@ ghex_application_window_finalize(GObject *gobject)
G_OBJECT_CLASS(ghex_application_window_parent_class)->finalize(gobject);
}
+#if 0
+static void
+ghex_application_window_startup (GApplication *app)
+{
+ GtkBuilder *builder;
+
+ /* chain up */
+ G_APPLICATION_CLASS(ghex_application_window_parent_class)->startup (app);
+
+ builder = gtk_builder_new_from_resource (builder,
+ "/org/gnome/ghex/ghex-application-window.ui", NULL);
+
+ gtk_application_set_menubar (GTK_APPLICATION (app),
+ G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
+
+ g_object_unref (builder);
+}
+#endif
+
static void
ghex_application_window_class_init(GHexApplicationWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+// GApplicationClass *app_class = G_APPLICATION_CLASS (class);
object_class->dispose = ghex_application_window_dispose;
object_class->finalize = ghex_application_window_finalize;
object_class->get_property = ghex_application_window_get_property;
object_class->set_property = ghex_application_window_set_property;
+// app_class->startup = ghex_application_window_startup;
+
/* PROPERTIES */
properties[PROP_CHARTABLE_OPEN] =
@@ -1606,6 +1866,7 @@ ghex_application_window_class_init(GHexApplicationWindowClass *klass)
NULL, // GVariant string param_type
open_about);
+
gtk_widget_class_install_property_action (widget_class,
"ghex.find", "find-open");
@@ -1621,6 +1882,13 @@ ghex_application_window_class_init(GHexApplicationWindowClass *klass)
gtk_widget_class_install_property_action (widget_class,
"ghex.converter", "converter-open");
+
+
+// gtk_widget_class_install_action (widget_class, "win.group-data-by",
+// "i", // GVariant string param_type
+// NULL);
+
+
/* WIDGET TEMPLATE .UI */
gtk_widget_class_set_template_from_resource (widget_class,
@@ -1695,6 +1963,12 @@ ghex_application_window_add_hex (GHexApplicationWindow *self,
g_return_if_fail (GTK_IS_HEX(gh));
g_return_if_fail (HEX_IS_DOCUMENT(doc));
+ /* Setup GtkHex based on settings. */
+ set_css_provider_font_from_settings (self);
+ set_gtkhex_font_from_settings (self, gh);
+ set_gtkhex_offsets_column_from_settings (gh);
+ set_gtkhex_group_type_from_settings (gh);
+
/* Add this GtkHex to our internal list */
// FIXME / TODO - used for nothing rn.
self->gh_list = g_list_append (self->gh_list, gh);
diff --git a/src/ghex-application-window.ui b/src/ghex-application-window.ui
index 5ba8f4b9..0bd3a1ca 100644
--- a/src/ghex-application-window.ui
+++ b/src/ghex-application-window.ui
@@ -61,15 +61,19 @@
<attribute name="label" translatable="yes">G_roup Data As</attribute>
<item>
<attribute name="label" translatable="yes">_Bytes</attribute>
- <attribute name="action">ghex.group-bytes</attribute>
+ <!-- use 'win' prefix for these because that's what gets set
automatically by g_settings_create_action in _init -->
+ <attribute name="action">win.group-data-by</attribute>
+ <attribute name="target">bytes</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Words</attribute>
- <attribute name="action">ghex.group-words</attribute>
+ <attribute name="action">win.group-data-by</attribute>
+ <attribute name="target">words</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Longwords</attribute>
- <attribute name="action">ghex.group-long</attribute>
+ <attribute name="action">win.group-data-by</attribute>
+ <attribute name="target">longwords</attribute>
</item>
</submenu>
</section>
diff --git a/src/gtkhex.c b/src/gtkhex.c
index b4ac5785..ad42bc4e 100644
--- a/src/gtkhex.c
+++ b/src/gtkhex.c
@@ -3005,7 +3005,7 @@ gtk_hex_init(GtkHex *gh)
/* add the provider to our widget's style context. */
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
/* Setup offsets widget. */
diff --git a/src/meson.build b/src/meson.build
index 77f5927f..c61260a0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -65,8 +65,8 @@ ghex_sources = [
'preferences.h',
'print.c',
'print.h',
- 'ui.c',
- 'ui.h'
+ 'common-ui.c',
+ 'common-ui.h'
]
ghex_deps = [
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]