From c9dba4b8e0e7dc9b1030065e6b7f5e7177976288 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 8 May 2014 01:04:16 -0400 Subject: [PATCH] inspector: Show signals Add a tab that shows available signals for each object. For now, we only show if each signal has handlers connected or now. More functionality will be added later. --- modules/inspector/Makefile.am | 9 +- modules/inspector/inspector.gresource.xml | 1 + modules/inspector/module.c | 2 + modules/inspector/signals-list.c | 145 ++++++++++++++++++++++ modules/inspector/signals-list.h | 55 ++++++++ modules/inspector/signals-list.ui | 65 ++++++++++ modules/inspector/window.c | 3 + modules/inspector/window.h | 1 + modules/inspector/window.ui | 20 +++ 9 files changed, 298 insertions(+), 3 deletions(-) create mode 100644 modules/inspector/signals-list.c create mode 100644 modules/inspector/signals-list.h create mode 100644 modules/inspector/signals-list.ui diff --git a/modules/inspector/Makefile.am b/modules/inspector/Makefile.am index 6cc8f60a28..2ab2bb5f2c 100644 --- a/modules/inspector/Makefile.am +++ b/modules/inspector/Makefile.am @@ -40,7 +40,9 @@ libgtkinspector_la_SOURCES = \ object-hierarchy.h \ object-hierarchy.c \ themes.h \ - themes.c + themes.c \ + signals-list.h \ + signals-list.c libgtkinspector_la_CPPFLAGS = \ -I$(top_srcdir) \ @@ -63,7 +65,7 @@ libgtkinspector_la_LIBADD = \ $(top_builddir)/gtk/libgtk-3.la \ $(GTK_DEP_LIBS) -templates = \ +templates = \ button-path.ui \ classes-list.ui \ css-editor.ui \ @@ -71,7 +73,8 @@ templates = \ prop-list.ui \ themes.ui \ widget-tree.ui \ - window.ui + window.ui \ + signals-list.ui template_headers = $(templates:.ui=.ui.h) diff --git a/modules/inspector/inspector.gresource.xml b/modules/inspector/inspector.gresource.xml index 145c88363c..0feec7c97d 100644 --- a/modules/inspector/inspector.gresource.xml +++ b/modules/inspector/inspector.gresource.xml @@ -9,5 +9,6 @@ prop-list.ui themes.ui window.ui + signals-list.ui diff --git a/modules/inspector/module.c b/modules/inspector/module.c index 2195d03016..31b4a1cb02 100644 --- a/modules/inspector/module.c +++ b/modules/inspector/module.c @@ -31,6 +31,7 @@ #include "python-hooks.h" #include "python-shell.h" #include "resources.h" +#include "signals-list.h" #include "themes.h" #include "widget-tree.h" #include "window.h" @@ -54,6 +55,7 @@ gtk_module_init (gint *argc, gchar ***argv) g_type_ensure (GTK_TYPE_INSPECTOR_PYTHON_SHELL); g_type_ensure (GTK_TYPE_INSPECTOR_PROPERTY_CELL_RENDERER); g_type_ensure (GTK_TYPE_INSPECTOR_WINDOW); + g_type_ensure (GTK_TYPE_INSPECTOR_SIGNALS_LIST); } diff --git a/modules/inspector/signals-list.c b/modules/inspector/signals-list.c new file mode 100644 index 0000000000..f511e2addb --- /dev/null +++ b/modules/inspector/signals-list.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" +#include +#include "signals-list.h" + +enum +{ + COLUMN_ENABLED, + COLUMN_NAME, + COLUMN_CLASS, + COLUMN_CONNECTED +}; + +struct _GtkInspectorSignalsListPrivate +{ + GtkWidget *view; + GtkListStore *model; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorSignalsList, gtk_inspector_signals_list, GTK_TYPE_BOX) + +static void +gtk_inspector_signals_list_init (GtkInspectorSignalsList *sl) +{ + sl->priv = gtk_inspector_signals_list_get_instance_private (sl); + gtk_widget_init_template (GTK_WIDGET (sl)); +} + +static GType * +get_types (GObject *object, guint *length) +{ + GHashTable *seen; + GType *ret; + GType type; + GType *iface; + gint i; + + seen = g_hash_table_new (g_direct_hash, g_direct_equal); + + type = ((GTypeInstance*)object)->g_class->g_type; + while (type) + { + g_hash_table_add (seen, GSIZE_TO_POINTER (type)); + iface = g_type_interfaces (type, NULL); + for (i = 0; iface[i]; i++) + g_hash_table_add (seen, GSIZE_TO_POINTER (iface[i])); + g_free (iface); + type = g_type_parent (type); + } + + ret = (GType *)g_hash_table_get_keys_as_array (seen, length); + g_hash_table_unref (seen); + + return ret; +} + +static void +add_signals (GtkInspectorSignalsList *sl, + GType type, + GObject *object) +{ + guint *ids; + guint n_ids; + gint i; + GSignalQuery query; + GtkTreeIter iter; + gboolean has_handler; + + if (!G_TYPE_IS_INSTANTIATABLE (type) && !G_TYPE_IS_INTERFACE (type)) + return; + + ids = g_signal_list_ids (type, &n_ids); + for (i = 0; i < n_ids; i++) + { + g_signal_query (ids[i], &query); + has_handler = g_signal_has_handler_pending (object, ids[i], 0, TRUE); + gtk_list_store_append (sl->priv->model, &iter); + gtk_list_store_set (sl->priv->model, &iter, + COLUMN_ENABLED, FALSE, + COLUMN_NAME, query.signal_name, + COLUMN_CLASS, g_type_name (type), + COLUMN_CONNECTED, has_handler ? _("Yes") : "", + -1); + } + g_free (ids); +} + +static void +read_signals_from_object (GtkInspectorSignalsList *sl, + GObject *object) +{ + GType *types; + guint length; + gint i; + + types = get_types (object, &length); + for (i = 0; i < length; i++) + add_signals (sl, types[i], object); + g_free (types); +} + +void +gtk_inspector_signals_list_set_object (GtkInspectorSignalsList *sl, + GObject *object) +{ + gtk_list_store_clear (sl->priv->model); + + gtk_widget_set_sensitive (GTK_WIDGET (sl), TRUE); + + read_signals_from_object (sl, object); +} + +static void +gtk_inspector_signals_list_class_init (GtkInspectorSignalsListClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/signals-list.ui"); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, view); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorSignalsList, model); +} + +GtkWidget * +gtk_inspector_signals_list_new (void) +{ + return GTK_WIDGET (g_object_new (GTK_TYPE_INSPECTOR_SIGNALS_LIST, NULL)); +} + +// vim: set et sw=2 ts=2: diff --git a/modules/inspector/signals-list.h b/modules/inspector/signals-list.h new file mode 100644 index 0000000000..4332bd220c --- /dev/null +++ b/modules/inspector/signals-list.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef _GTK_INSPECTOR_SIGNALS_LIST_H_ +#define _GTK_INSPECTOR_SIGNALS_LIST_H_ + +#include + +#define GTK_TYPE_INSPECTOR_SIGNALS_LIST (gtk_inspector_signals_list_get_type()) +#define GTK_INSPECTOR_SIGNALS_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_SIGNALS_LIST, GtkInspectorSignalsList)) +#define GTK_INSPECTOR_SIGNALS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_SIGNALS_LIST, GtkInspectorSignalsListClass)) +#define GTK_INSPECTOR_IS_SIGNALS_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INSPECTOR_SIGNALS_LIST)) +#define GTK_INSPECTOR_IS_SIGNALS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_INSPECTOR_SIGNALS_LIST)) +#define GTK_INSPECTOR_SIGNALS_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INSPECTOR_SIGNALS_LIST, GtkInspectorSignalsListClass)) + + +typedef struct _GtkInspectorSignalsListPrivate GtkInspectorSignalsListPrivate; + +typedef struct _GtkInspectorSignalsList +{ + GtkBox parent; + GtkInspectorSignalsListPrivate *priv; +} GtkInspectorSignalsList; + +typedef struct _GtkInspectorSignalsListClass +{ + GtkBoxClass parent; +} GtkInspectorSignalsListClass; + +G_BEGIN_DECLS + +GType gtk_inspector_signals_list_get_type (void); +GtkWidget *gtk_inspector_signals_list_new (void); +void gtk_inspector_signals_list_set_object (GtkInspectorSignalsList *sl, + GObject *object); + +G_END_DECLS + +#endif // _GTK_INSPECTOR_SIGNALS_LIST_H_ + +// vim: set et sw=2 ts=2: diff --git a/modules/inspector/signals-list.ui b/modules/inspector/signals-list.ui new file mode 100644 index 0000000000..d9243a519c --- /dev/null +++ b/modules/inspector/signals-list.ui @@ -0,0 +1,65 @@ + + + + + + + + + + + + diff --git a/modules/inspector/window.c b/modules/inspector/window.c index fb9fa9e216..898afdaca3 100644 --- a/modules/inspector/window.c +++ b/modules/inspector/window.c @@ -36,6 +36,7 @@ #include "python-shell.h" #include "button-path.h" #include "themes.h" +#include "signals-list.h" G_DEFINE_TYPE (GtkInspectorWindow, gtk_inspector_window, GTK_TYPE_WINDOW) @@ -72,6 +73,7 @@ on_widget_tree_selection_changed (GtkInspectorWidgetTree *wt, return; gtk_inspector_prop_list_set_object (GTK_INSPECTOR_PROP_LIST (iw->child_prop_list), selected); + gtk_inspector_signals_list_set_object (GTK_INSPECTOR_SIGNALS_LIST (iw->signals_list), selected); gtk_inspector_object_hierarchy_set_object (GTK_INSPECTOR_OBJECT_HIERARCHY (iw->object_hierarchy), selected); if (GTK_IS_WIDGET (selected)) @@ -179,6 +181,7 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass) gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, widget_tree); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, prop_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, child_prop_list); + gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, signals_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, button_path); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, classes_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, widget_css_editor); diff --git a/modules/inspector/window.h b/modules/inspector/window.h index b070b0fbca..1e9bd69996 100644 --- a/modules/inspector/window.h +++ b/modules/inspector/window.h @@ -44,6 +44,7 @@ typedef struct GtkWidget *widget_tree; GtkWidget *prop_list; GtkWidget *child_prop_list; + GtkWidget *signals_list; GtkWidget *python_shell; GtkWidget *button_path; GtkWidget *classes_list; diff --git a/modules/inspector/window.ui b/modules/inspector/window.ui index 287628f053..6c364ab910 100644 --- a/modules/inspector/window.ui +++ b/modules/inspector/window.ui @@ -159,6 +159,26 @@ Child Properties + + + True + automatic + always + in + 250 + + + True + + + + + + + True + Signals + + True