[gnome-builder/wip/gtk4-port: 373/736] libide/gui: bind some settings to properties




commit b9c7ac64919b6239d27d445554942a71dda86ad6
Author: Christian Hergert <chergert redhat com>
Date:   Mon Apr 4 13:25:27 2022 -0700

    libide/gui: bind some settings to properties
    
    This makes it easier to bind from various places if we can just have the
    name of the scheme or default-font as properties. They can be updated when
    we get signal changes from the settings portal and/or gsettings.

 src/libide/gui/ide-application-private.h  |   5 +
 src/libide/gui/ide-application-settings.c | 206 ++++++++++++++++++++++++++++++
 src/libide/gui/ide-application.c          |  86 ++++++++++++-
 src/libide/gui/ide-application.h          |   7 +
 src/libide/gui/meson.build                |   1 +
 5 files changed, 303 insertions(+), 2 deletions(-)
---
diff --git a/src/libide/gui/ide-application-private.h b/src/libide/gui/ide-application-private.h
index eca37f886..cc02d7547 100644
--- a/src/libide/gui/ide-application-private.h
+++ b/src/libide/gui/ide-application-private.h
@@ -75,6 +75,10 @@ struct _IdeApplication
   /* The CSS provider to recolor all of the widgetry based on style schemes */
   GtkCssProvider *recoloring;
 
+  /* A D-Bus proxy to settings portal */
+  GDBusProxy *settings_portal;
+  char *system_font_name;
+
   /* We need to stash the unmodified argv for the application somewhere
    * so that we can pass it to a remote instance. Otherwise we lose
    * the ability by cmdline-addins to determine if any options were
@@ -98,6 +102,7 @@ struct _IdeApplication
 IdeApplication *_ide_application_new                      (gboolean                 standalone);
 void            _ide_application_init_color               (IdeApplication          *self);
 void            _ide_application_init_actions             (IdeApplication          *self);
+void            _ide_application_init_settings            (IdeApplication          *self);
 void            _ide_application_load_addins              (IdeApplication          *self);
 void            _ide_application_unload_addins            (IdeApplication          *self);
 void            _ide_application_load_plugin              (IdeApplication          *self,
diff --git a/src/libide/gui/ide-application-settings.c b/src/libide/gui/ide-application-settings.c
new file mode 100644
index 000000000..0ba7a54f6
--- /dev/null
+++ b/src/libide/gui/ide-application-settings.c
@@ -0,0 +1,206 @@
+/* ide-application-settings.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-application-settings"
+
+#include "config.h"
+
+#include "ide-application-private.h"
+#include "ide-recoloring-private.h"
+
+#define PORTAL_BUS_NAME "org.freedesktop.portal.Desktop"
+#define PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
+#define PORTAL_SETTINGS_INTERFACE "org.freedesktop.portal.Settings"
+
+static void
+on_portal_settings_changed_cb (IdeApplication *self,
+                               const char     *sender_name,
+                               const char     *signal_name,
+                               GVariant       *parameters,
+                               gpointer        user_data)
+{
+  g_autoptr(GVariant) value = NULL;
+  const char *schema_id;
+  const char *key;
+
+  g_assert (IDE_IS_APPLICATION (self));
+  g_assert (sender_name != NULL);
+  g_assert (signal_name != NULL);
+
+  if (g_strcmp0 (signal_name, "SettingChanged") != 0)
+    return;
+
+  g_variant_get (parameters, "(&s&sv)", &schema_id, &key, &value);
+
+  if (g_strcmp0 (schema_id, "org.gnome.desktop.interface") == 0 &&
+      g_strcmp0 (key, "monospace-font-name") == 0 &&
+      g_strcmp0 (g_variant_get_string (value, NULL), "") != 0)
+    {
+      g_free (self->system_font_name);
+      self->system_font_name = g_strdup (g_variant_get_string (value, NULL));
+      g_object_notify (G_OBJECT (self), "system-font-name");
+    }
+}
+
+static void
+parse_portal_settings (IdeApplication *self,
+                       GVariant       *parameters)
+{
+  GVariantIter *iter = NULL;
+  const char *schema_str;
+  GVariant *val;
+
+  g_assert (IDE_IS_APPLICATION (self));
+
+  if (parameters == NULL)
+    return;
+
+  g_variant_get (parameters, "(a{sa{sv}})", &iter);
+
+  while (g_variant_iter_loop (iter, "{s@a{sv}}", &schema_str, &val))
+    {
+      GVariantIter *iter2 = g_variant_iter_new (val);
+      const char *key;
+      GVariant *v;
+
+      while (g_variant_iter_loop (iter2, "{sv}", &key, &v))
+        {
+          if (g_strcmp0 (schema_str, "org.gnome.desktop.interface") == 0 &&
+              g_strcmp0 (key, "monospace-font-name") == 0 &&
+              g_strcmp0 (g_variant_get_string (v, NULL), "") != 0)
+            {
+              g_free (self->system_font_name);
+              self->system_font_name = g_strdup (g_variant_get_string (v, NULL));
+            }
+        }
+
+      g_variant_iter_free (iter2);
+    }
+
+  g_variant_iter_free (iter);
+}
+
+static void
+ide_application_settings_style_scheme_changed_cb (IdeApplication *self,
+                                                  const char     *key,
+                                                  GSettings      *settings)
+{
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_APPLICATION (self));
+  g_assert (G_IS_SETTINGS (settings));
+
+  g_object_notify (G_OBJECT (self), "style-scheme");
+
+  IDE_EXIT;
+}
+
+void
+_ide_application_init_settings (IdeApplication *self)
+{
+  static const char *patterns[] = { "org.gnome.*", NULL };
+  g_autoptr(GVariant) all = NULL;
+  g_autofree char *style_scheme_name = NULL;
+
+  g_return_if_fail (IDE_IS_APPLICATION (self));
+  g_return_if_fail (self->settings_portal == NULL);
+
+  /* We must query the key to get changed notifications */
+  style_scheme_name = g_settings_get_string (self->editor_settings, "style-scheme-name");
+  g_debug ("Initial style scheme set to %s", style_scheme_name);
+  g_signal_connect_object (self->editor_settings,
+                           "changed::style-scheme-name",
+                           G_CALLBACK (ide_application_settings_style_scheme_changed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  self->settings_portal = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                         G_DBUS_PROXY_FLAGS_NONE,
+                                                         NULL,
+                                                         PORTAL_BUS_NAME,
+                                                         PORTAL_OBJECT_PATH,
+                                                         PORTAL_SETTINGS_INTERFACE,
+                                                         NULL,
+                                                         NULL);
+
+  if (self->settings_portal != NULL)
+    {
+      g_signal_connect_object (self->settings_portal,
+                               "g-signal",
+                               G_CALLBACK (on_portal_settings_changed_cb),
+                               self,
+                               G_CONNECT_SWAPPED);
+      all = g_dbus_proxy_call_sync (self->settings_portal,
+                                    "ReadAll",
+                                    g_variant_new ("(^as)", patterns),
+                                    G_DBUS_CALL_FLAGS_NONE,
+                                    G_MAXINT,
+                                    NULL,
+                                    NULL);
+      parse_portal_settings (self, all);
+    }
+}
+
+void
+ide_application_set_style_scheme (IdeApplication *self,
+                                  const char     *style_scheme)
+{
+  g_return_if_fail (IDE_IS_APPLICATION (self));
+
+  if (style_scheme == NULL)
+    style_scheme = "Adwaita";
+
+  g_object_freeze_notify (G_OBJECT (self));
+  g_settings_set_string (self->editor_settings, "style-scheme-name", style_scheme);
+  g_object_thaw_notify (G_OBJECT (self));
+}
+
+const char *
+ide_application_get_style_scheme (IdeApplication *self)
+{
+  GtkSourceStyleSchemeManager *style_scheme_manager;
+  GtkSourceStyleScheme *style_scheme;
+  AdwStyleManager *style_manager;
+  g_autofree char *style_scheme_id = NULL;
+  const char *variant;
+
+  g_return_val_if_fail (IDE_IS_APPLICATION (self), NULL);
+
+  style_manager = adw_style_manager_get_default ();
+  style_scheme_manager = gtk_source_style_scheme_manager_get_default ();
+  style_scheme_id = g_settings_get_string (self->editor_settings, "style-scheme-name");
+
+  /* Fallback to Adwaita if we don't find a match */
+  if (gtk_source_style_scheme_manager_get_scheme (style_scheme_manager, style_scheme_id) == NULL)
+    {
+      g_free (style_scheme_id);
+      style_scheme_id = g_strdup ("Adwaita");
+    }
+
+  if (adw_style_manager_get_dark (style_manager))
+    variant = "dark";
+  else
+    variant = "light";
+
+  style_scheme = gtk_source_style_scheme_manager_get_scheme (style_scheme_manager, style_scheme_id);
+  style_scheme = _ide_source_style_scheme_get_variant (style_scheme, variant);
+
+  return gtk_source_style_scheme_get_id (style_scheme);
+}
diff --git a/src/libide/gui/ide-application.c b/src/libide/gui/ide-application.c
index 936404a72..1e4bbacc4 100644
--- a/src/libide/gui/ide-application.c
+++ b/src/libide/gui/ide-application.c
@@ -37,8 +37,6 @@
 #include "ide-gui-global.h"
 #include "ide-primary-workspace.h"
 
-G_DEFINE_FINAL_TYPE (IdeApplication, ide_application, ADW_TYPE_APPLICATION)
-
 typedef struct
 {
   IdeApplication  *self;
@@ -47,6 +45,17 @@ typedef struct
   const gchar     *hint;
 } OpenData;
 
+G_DEFINE_FINAL_TYPE (IdeApplication, ide_application, ADW_TYPE_APPLICATION)
+
+enum {
+  PROP_0,
+  PROP_STYLE_SCHEME,
+  PROP_SYSTEM_FONT_NAME,
+  N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
 static void
 ide_application_add_platform_data (GApplication    *app,
                                    GVariantBuilder *builder)
@@ -132,6 +141,9 @@ ide_application_startup (GApplication *app)
   gtk_source_style_scheme_manager_append_search_path (styles, style_path);
   gtk_source_style_scheme_manager_append_search_path (styles, PACKAGE_DATADIR"/gtksourceview-5/styles/");
 
+  /* Setup access to portal settings */
+  _ide_application_init_settings (self);
+
   /* Load color settings (Night Light, Dark Mode, etc) */
   _ide_application_init_color (self);
 
@@ -323,6 +335,48 @@ _ide_application_add_resources (IdeApplication *self,
     }
 }
 
+static void
+ide_application_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  IdeApplication *self = IDE_APPLICATION (object);
+
+  switch (prop_id)
+    {
+    case PROP_STYLE_SCHEME:
+      g_value_set_string (value, ide_application_get_style_scheme (self));
+      break;
+
+    case PROP_SYSTEM_FONT_NAME:
+      g_value_set_string (value, ide_application_get_system_font_name (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_application_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  IdeApplication *self = IDE_APPLICATION (object);
+
+  switch (prop_id)
+    {
+    case PROP_STYLE_SCHEME:
+      ide_application_set_style_scheme (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
 static void
 ide_application_dispose (GObject *object)
 {
@@ -339,6 +393,7 @@ ide_application_dispose (GObject *object)
   g_clear_pointer (&self->css_providers, g_hash_table_unref);
   g_clear_pointer (&self->argv, g_strfreev);
   g_clear_pointer (&self->menu_merge_ids, g_hash_table_unref);
+  g_clear_pointer (&self->system_font_name, g_free);
   g_clear_object (&self->recoloring);
   g_clear_object (&self->addins);
   g_clear_object (&self->editor_settings);
@@ -356,6 +411,8 @@ ide_application_class_init (IdeApplicationClass *klass)
   GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
 
   object_class->dispose = ide_application_dispose;
+  object_class->get_property = ide_application_get_property;
+  object_class->set_property = ide_application_set_property;
 
   app_class->activate = ide_application_activate;
   app_class->open = ide_application_open;
@@ -364,11 +421,28 @@ ide_application_class_init (IdeApplicationClass *klass)
   app_class->local_command_line = ide_application_local_command_line;
   app_class->startup = ide_application_startup;
   app_class->shutdown = ide_application_shutdown;
+
+  properties[PROP_STYLE_SCHEME] =
+    g_param_spec_string ("style-scheme",
+                         "Style Scheme",
+                         "The style scheme for the editor",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  properties[PROP_SYSTEM_FONT_NAME] =
+    g_param_spec_string ("system-font-name",
+                         "System Font Name",
+                         "System Font Name",
+                         "Monospace 11",
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
 }
 
 static void
 ide_application_init (IdeApplication *self)
 {
+  self->system_font_name = g_strdup ("Monospace 11");
   self->menu_merge_ids = g_hash_table_new (g_str_hash, g_str_equal);
   self->menu_manager = ide_menu_manager_new ();
   self->started_at = g_date_time_new_now_local ();
@@ -739,3 +813,11 @@ ide_application_get_menu_by_id (IdeApplication *self,
 
   return ide_menu_manager_get_menu_by_id (self->menu_manager, menu_id);
 }
+
+const char *
+ide_application_get_system_font_name (IdeApplication *self)
+{
+  g_return_val_if_fail (IDE_IS_APPLICATION (self), NULL);
+
+  return self->system_font_name;
+}
diff --git a/src/libide/gui/ide-application.h b/src/libide/gui/ide-application.h
index 3f4ac373a..1f8c1126d 100644
--- a/src/libide/gui/ide-application.h
+++ b/src/libide/gui/ide-application.h
@@ -89,5 +89,12 @@ char          *ide_application_create_cancel_action      (IdeApplication
 IDE_AVAILABLE_IN_ALL
 GMenu         *ide_application_get_menu_by_id            (IdeApplication           *self,
                                                           const char               *menu_id);
+IDE_AVAILABLE_IN_ALL
+const char    *ide_application_get_system_font_name      (IdeApplication           *self);
+IDE_AVAILABLE_IN_ALL
+const char    *ide_application_get_style_scheme          (IdeApplication           *self);
+IDE_AVAILABLE_IN_ALL
+void           ide_application_set_style_scheme          (IdeApplication           *self,
+                                                          const char               *style_scheme);
 
 G_END_DECLS
diff --git a/src/libide/gui/meson.build b/src/libide/gui/meson.build
index 1a908602a..38e95e9e8 100644
--- a/src/libide/gui/meson.build
+++ b/src/libide/gui/meson.build
@@ -60,6 +60,7 @@ libide_gui_private_sources = [
   'ide-application-actions.c',
   'ide-application-color.c',
   'ide-application-plugins.c',
+  'ide-application-settings.c',
   'ide-environment-editor-row.c',
   'ide-notification-list-box-row.c',
   'ide-notification-stack.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]