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.
This commit is contained in:
Matthias Clasen 2014-05-08 01:04:16 -04:00
parent 5fa71c69d8
commit c9dba4b8e0
9 changed files with 298 additions and 3 deletions

View File

@ -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) \
@ -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)

View File

@ -9,5 +9,6 @@
<file>prop-list.ui</file>
<file>themes.ui</file>
<file>window.ui</file>
<file>signals-list.ui</file>
</gresource>
</gresources>

View File

@ -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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#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:

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef _GTK_INSPECTOR_SIGNALS_LIST_H_
#define _GTK_INSPECTOR_SIGNALS_LIST_H_
#include <gtk/gtk.h>
#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:

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk30">
<object class="GtkListStore" id="model">
<columns>
<column type="gboolean"/>
<column type="gchararray"/>
<column type="gchararray"/>
<column type="gchararray"/>
</columns>
</object>
<template class="GtkInspectorSignalsList" parent="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="expand">True</property>
<child>
<object class="GtkTreeView" id="view">
<property name="visible">True</property>
<property name="model">model</property>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Name</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Defined At</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Connected</property>
<child>
<object class="GtkCellRendererText">
<property name="scale">0.8</property>
</object>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@ -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);

View File

@ -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;

View File

@ -159,6 +159,26 @@
<property name="label" translatable="yes">Child Properties</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="hscrollbar-policy">automatic</property>
<property name="vscrollbar-policy">always</property>
<property name="shadow-type">in</property>
<property name="width-request">250</property>
<child>
<object class="GtkInspectorSignalsList" id="signals_list">
<property name="visible">True</property>
</object>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Signals</property>
</object>
</child>
<child>
<object class="GtkInspectorObjectHierarchy" id="object_hierarchy">
<property name="visible">True</property>