[sysprof] empty-state: allow action:// in labels



commit 757a62c69243389274f66d652c6da68428421bc0
Author: Christian Hergert <chergert redhat com>
Date:   Mon Oct 17 20:03:46 2016 -0700

    empty-state: allow action:// in labels
    
    This allows us to have an action in the label that can execute a UI
    element.

 lib/sp-empty-state-view.c |  104 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 104 insertions(+), 0 deletions(-)
---
diff --git a/lib/sp-empty-state-view.c b/lib/sp-empty-state-view.c
index 9dc064a..9174b80 100644
--- a/lib/sp-empty-state-view.c
+++ b/lib/sp-empty-state-view.c
@@ -16,6 +16,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define G_LOG_DOMAIN "sp-empty-state-view"
+
+#include <string.h>
+
 #include "sp-empty-state-view.h"
 
 typedef struct
@@ -41,6 +45,98 @@ sp_empty_state_view_new (void)
   return g_object_new (SP_TYPE_EMPTY_STATE_VIEW, NULL);
 }
 
+static gboolean
+sp_empty_state_view_action (GtkWidget   *widget,
+                            const gchar *prefix,
+                            const gchar *action_name,
+                            GVariant    *parameter)
+{
+  GtkWidget *toplevel;
+  GApplication *app;
+  GActionGroup *group = NULL;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (prefix, FALSE);
+  g_return_val_if_fail (action_name, FALSE);
+
+  app = g_application_get_default ();
+  toplevel = gtk_widget_get_toplevel (widget);
+
+  while ((group == NULL) && (widget != NULL))
+    {
+      group = gtk_widget_get_action_group (widget, prefix);
+      widget = gtk_widget_get_parent (widget);
+    }
+
+  if (!group && g_str_equal (prefix, "win") && G_IS_ACTION_GROUP (toplevel))
+    group = G_ACTION_GROUP (toplevel);
+
+  if (!group && g_str_equal (prefix, "app") && G_IS_ACTION_GROUP (app))
+    group = G_ACTION_GROUP (app);
+
+  if (group && g_action_group_has_action (group, action_name))
+    {
+      g_action_group_activate_action (group, action_name, parameter);
+      return TRUE;
+    }
+
+  if (parameter && g_variant_is_floating (parameter))
+    {
+      parameter = g_variant_ref_sink (parameter);
+      g_variant_unref (parameter);
+    }
+
+  g_warning ("Failed to locate action %s.%s", prefix, action_name);
+
+  return FALSE;
+}
+
+static gboolean
+sp_empty_state_view_activate_link (SpEmptyStateView *self,
+                                   const gchar      *uri,
+                                   GtkLabel         *label)
+{
+  g_assert (SP_IS_EMPTY_STATE_VIEW (self));
+  g_assert (uri != NULL);
+  g_assert (GTK_IS_LABEL (label));
+
+  if (g_str_has_prefix (uri, "action://"))
+    {
+      g_autofree gchar *full_name = NULL;
+      g_autofree gchar *action_name = NULL;
+      g_autofree gchar *group_name = NULL;
+      g_autoptr(GVariant) param = NULL;
+      g_autoptr(GError) error = NULL;
+
+      uri += strlen ("action://");
+
+      if (g_action_parse_detailed_name (uri, &full_name, &param, &error))
+        {
+          const gchar *dot = strchr (full_name, '.');
+
+          if (param != NULL && g_variant_is_floating (param))
+            param = g_variant_ref_sink (param);
+
+          if (dot == NULL)
+            return FALSE;
+
+          group_name = g_strndup (full_name, dot - full_name);
+          action_name = g_strdup (++dot);
+
+          sp_empty_state_view_action (GTK_WIDGET (self),
+                                      group_name,
+                                      action_name,
+                                      param);
+
+          return TRUE;
+        }
+      else
+        g_warning ("%s", error->message);
+    }
+
+  return FALSE;
+}
+
 static void
 sp_empty_state_view_set_property (GObject      *object,
                                   guint         prop_id,
@@ -97,5 +193,13 @@ sp_empty_state_view_class_init (SpEmptyStateViewClass *klass)
 static void
 sp_empty_state_view_init (SpEmptyStateView *self)
 {
+  SpEmptyStateViewPrivate *priv = sp_empty_state_view_get_instance_private (self);
+
   gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect_object (priv->subtitle,
+                           "activate-link",
+                           G_CALLBACK (sp_empty_state_view_activate_link),
+                           self,
+                           G_CONNECT_SWAPPED);
 }


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