Commit 7b44a636 authored by Juan Pablo Ugarte's avatar Juan Pablo Ugarte
Browse files

Added support for signal detail. Fixes bug #670792 "Unable to connect to specific notify signals."

parent ab03f8cc
......@@ -59,7 +59,8 @@ struct _GladeSignalEditorPrivate
GladeWidgetAdaptor *adaptor;
GtkWidget *signal_tree;
GtkTreeViewColumn *column_name;
GtkTreeViewColumn *column_name;
GtkTreeViewColumn *column_detail;
GtkTreeViewColumn *column_handler;
GtkTreeViewColumn *column_userdata;
GtkTreeViewColumn *column_swap;
......@@ -86,13 +87,10 @@ enum
static guint glade_signal_editor_signals[LAST_SIGNAL] = { 0 };
/* Utils */
static gboolean
static inline gboolean
glade_signal_is_dummy (GladeSignal *signal)
{
gboolean dummy;
dummy = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (signal),
DUMMY_DATA));
return dummy;
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (signal), DUMMY_DATA));
}
/* Signal handlers */
......@@ -130,8 +128,8 @@ on_handler_edited (GtkCellRendererText *renderer,
if (strlen (handler))
{
/* change an existing signal handler */
GladeSignal* old_signal;
GladeSignal* new_signal;
GladeSignal *old_signal;
GladeSignal *new_signal;
gtk_tree_model_get (self->priv->model,
&iter,
......@@ -149,7 +147,7 @@ on_handler_edited (GtkCellRendererText *renderer,
}
else
{
GladeSignal* deleted_signal;
GladeSignal *deleted_signal;
gtk_tree_model_get (self->priv->model,
&iter,
GLADE_SIGNAL_COLUMN_SIGNAL,
......@@ -157,15 +155,14 @@ on_handler_edited (GtkCellRendererText *renderer,
/* Delete signal */
glade_command_remove_signal (self->priv->widget,
deleted_signal);
glade_command_remove_signal (self->priv->widget, deleted_signal);
}
}
else if (strlen (handler))
{
GladeSignal* signal;
GladeSignal* dummy;
gchar* name;
GladeSignal *signal;
GladeSignal *dummy;
gchar *name;
/* Get the signal name */
gtk_tree_model_get (self->priv->model, &iter,
......@@ -192,15 +189,18 @@ glade_signal_editor_callback_suggestions (GladeSignalEditor *editor,
GladeSignal *signal)
{
GladeWidget *widget = glade_signal_editor_get_widget (editor);
gchar *signal_name, *name, **suggestions;
gchar *signal_name, **suggestions = g_new (gchar *, 10);
const gchar *name, *detail;
suggestions = g_new (gchar *, 10);
name = (gchar *) glade_widget_get_name (widget);
if ((detail = glade_signal_get_detail (signal)))
signal_name = g_strdup_printf ("%s_%s", detail, glade_signal_get_name (signal));
else
signal_name = g_strdup (glade_signal_get_name (signal));
signal_name = g_strdup (glade_signal_get_name (signal));
glade_util_replace (signal_name, '-', '_');
name = glade_widget_get_name (widget);
suggestions[0] = g_strdup_printf ("on_%s_%s", name, signal_name);
suggestions[1] = g_strdup_printf ("%s_%s_cb", name, signal_name);
suggestions[2] = g_strdup ("gtk_widget_show");
......@@ -215,6 +215,48 @@ glade_signal_editor_callback_suggestions (GladeSignalEditor *editor,
return suggestions;
}
static void
on_detail_edited (GtkCellRendererText *renderer,
gchar *path,
gchar *detail,
gpointer user_data)
{
GladeSignalEditor *self = GLADE_SIGNAL_EDITOR(user_data);
GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
GtkTreeIter iter;
gchar *old_detail;
g_return_if_fail (self->priv->widget != NULL);
gtk_tree_model_get_iter (self->priv->model, &iter, tree_path);
gtk_tree_model_get (self->priv->model, &iter,
GLADE_SIGNAL_COLUMN_DETAIL, &old_detail, -1);
if (detail && g_strcmp0 (old_detail, detail))
{
/* change an existing signal detail */
GladeSignal *old_signal;
GladeSignal *new_signal;
gtk_tree_model_get (self->priv->model,
&iter,
GLADE_SIGNAL_COLUMN_SIGNAL,
&old_signal, -1);
new_signal = glade_signal_clone (old_signal);
/* Change the new signal detail */
glade_signal_set_detail (new_signal, detail);
glade_command_change_signal (self->priv->widget, old_signal, new_signal);
g_object_unref (new_signal);
}
g_free (old_detail);
gtk_tree_path_free (tree_path);
}
static void
on_handler_editing_started (GtkCellRenderer *renderer,
GtkCellEditable *editable,
......@@ -757,6 +799,65 @@ glade_signal_editor_handler_cell_data_func (GtkTreeViewColumn *column,
}
}
static void
glade_signal_editor_detail_cell_data_func (GtkTreeViewColumn *column,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data)
{
GladeSignalEditor *editor = GLADE_SIGNAL_EDITOR (data);
GladeSignal *signal;
gtk_tree_model_get (model, iter,
GLADE_SIGNAL_COLUMN_SIGNAL, &signal,
-1);
if (signal &&
(glade_signal_class_get_flags (glade_signal_get_class (signal)) & G_SIGNAL_DETAILED))
{
GdkRGBA color;
gboolean dummy;
GtkStyleContext* context = gtk_widget_get_style_context (editor->priv->signal_tree);
dummy = glade_signal_is_dummy (signal);
if (dummy || !glade_signal_get_detail (signal))
{
gtk_style_context_get_color (context,
GTK_STATE_FLAG_INSENSITIVE, &color);
g_object_set (renderer,
"style", PANGO_STYLE_ITALIC,
"foreground-rgba", &color,
NULL);
}
else
{
gtk_style_context_get_color (context,
GTK_STATE_FLAG_NORMAL,
&color);
g_object_set (renderer,
"style", PANGO_STYLE_NORMAL,
"foreground-rgba", &color,
NULL);
}
g_object_set (renderer,
"sensitive", !dummy,
"visible", TRUE,
"editable", TRUE,
NULL);
g_object_unref (signal);
}
else
{
g_object_set (renderer,
"editable", FALSE,
"sensitive", FALSE,
"visible", FALSE,
NULL);
}
}
static void
glade_signal_editor_data_cell_data_func (GtkTreeViewColumn *column,
GtkCellRenderer *renderer,
......@@ -966,8 +1067,22 @@ glade_signal_editor_init (GladeSignalEditor *self)
gtk_tree_view_column_set_title (priv->column_name, _("Signal"));
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->signal_tree), priv->column_name);
/* Signal detail */
renderer = gtk_cell_renderer_text_new ();
g_signal_connect (renderer, "edited", G_CALLBACK(on_detail_edited), self);
priv->column_detail = gtk_tree_view_column_new_with_attributes (_("Detail"),
renderer,
"text", GLADE_SIGNAL_COLUMN_DETAIL,
NULL);
gtk_tree_view_column_set_cell_data_func (priv->column_detail, renderer,
glade_signal_editor_detail_cell_data_func,
self,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->signal_tree), priv->column_detail);
/* Signal handler */
renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer, "editable", FALSE, NULL);
g_signal_connect (renderer, "edited", G_CALLBACK(on_handler_edited), self);
g_signal_connect (renderer, "editing-started", G_CALLBACK (on_handler_editing_started), self);
priv->column_handler = gtk_tree_view_column_new_with_attributes (_("Handler"),
......@@ -979,7 +1094,7 @@ glade_signal_editor_init (GladeSignalEditor *self)
self,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->signal_tree), priv->column_handler);
/* Signal user_data */
priv->renderer_userdata = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (priv->renderer_userdata),
......@@ -1158,15 +1273,14 @@ glade_signal_editor_class_init (GladeSignalEditorClass *klass)
_glade_strv_handled_accumulator,
NULL, _glade_marshal_BOXED__OBJECT,
G_TYPE_STRV, 1,
GLADE_TYPE_SIGNAL
);
GLADE_TYPE_SIGNAL);
g_object_class_install_property (object_class,
PROP_GLADE_WIDGET,
g_param_spec_object ("glade-widget",
"Glade Widget",
"The glade widget to edit signals",
_("Glade Widget"),
_("The glade widget to edit signals"),
GTK_TYPE_TREE_MODEL,
G_PARAM_READWRITE));
}
......@@ -24,7 +24,7 @@ struct _GladeSignalEditor
{
GtkVBox parent;
GladeSignalEditorPrivate* priv;
GladeSignalEditorPrivate *priv;
};
struct _GladeSignalEditorClass
......
......@@ -26,6 +26,7 @@
#include <glib/gi18n-lib.h>
#include <string.h>
#define DETAIL_DEFAULT _("<Type here>")
#define HANDLER_DEFAULT _("<Type here>")
#define USERDATA_DEFAULT _("<Click here>")
......@@ -110,7 +111,7 @@ glade_signal_model_create_widget_list (GladeSignalModel *sig_model)
static void
glade_signal_model_finalize (GObject *object)
{
GladeSignalModel* sig_model = GLADE_SIGNAL_MODEL (object);
GladeSignalModel *sig_model = GLADE_SIGNAL_MODEL (object);
g_list_free (sig_model->priv->widgets);
g_hash_table_destroy (sig_model->priv->dummy_signals);
......@@ -118,7 +119,10 @@ glade_signal_model_finalize (GObject *object)
}
static void
glade_signal_model_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
glade_signal_model_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GladeSignalModel *sig_model;
......@@ -128,30 +132,32 @@ glade_signal_model_set_property (GObject *object, guint prop_id, const GValue *v
switch (prop_id)
{
case PROP_WIDGET:
sig_model->priv->widget = g_value_get_object (value);
glade_signal_model_create_widget_list (sig_model);
g_signal_connect (sig_model->priv->widget,
"add-signal-handler",
G_CALLBACK (on_glade_signal_model_added), sig_model);
g_signal_connect (sig_model->priv->widget, "remove-signal-handler",
G_CALLBACK (on_glade_signal_model_removed), sig_model);
g_signal_connect (sig_model->priv->widget, "change-signal-handler",
G_CALLBACK (on_glade_signal_model_changed), sig_model);
g_signal_connect (sig_model->priv->widget, "support-changed",
G_CALLBACK (on_glade_widget_support_changed), sig_model);
case PROP_WIDGET:
sig_model->priv->widget = g_value_get_object (value);
glade_signal_model_create_widget_list (sig_model);
g_signal_connect (sig_model->priv->widget, "add-signal-handler",
G_CALLBACK (on_glade_signal_model_added), sig_model);
g_signal_connect (sig_model->priv->widget, "remove-signal-handler",
G_CALLBACK (on_glade_signal_model_removed), sig_model);
g_signal_connect (sig_model->priv->widget, "change-signal-handler",
G_CALLBACK (on_glade_signal_model_changed), sig_model);
g_signal_connect (sig_model->priv->widget, "support-changed",
G_CALLBACK (on_glade_widget_support_changed), sig_model);
break;
case PROP_SIGNALS:
sig_model->priv->signals = g_value_get_pointer (value);
case PROP_SIGNALS:
sig_model->priv->signals = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
glade_signal_model_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
glade_signal_model_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GladeSignalModel *sig_model;
......@@ -161,14 +167,14 @@ glade_signal_model_get_property (GObject *object, guint prop_id, GValue *value,
switch (prop_id)
{
case PROP_WIDGET:
g_value_set_object (value, sig_model->priv->widget);
case PROP_WIDGET:
g_value_set_object (value, sig_model->priv->widget);
break;
case PROP_SIGNALS:
g_value_set_pointer (value, sig_model->priv->signals);
case PROP_SIGNALS:
g_value_set_pointer (value, sig_model->priv->signals);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
......@@ -209,8 +215,7 @@ glade_signal_model_class_init (GladeSignalModelClass *klass)
*/
GtkTreeModel *
glade_signal_model_new (GladeWidget *widget,
GHashTable *signals)
glade_signal_model_new (GladeWidget *widget, GHashTable *signals)
{
GObject *object = g_object_new (GLADE_TYPE_SIGNAL_MODEL,
"widget", widget,
......@@ -231,30 +236,31 @@ glade_signal_model_get_n_columns (GtkTreeModel *model)
}
static GType
glade_signal_model_get_column_type (GtkTreeModel *model,
gint column)
glade_signal_model_get_column_type (GtkTreeModel *model, gint column)
{
switch (column)
{
case GLADE_SIGNAL_COLUMN_NAME:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_SHOW_NAME:
return G_TYPE_BOOLEAN;
case GLADE_SIGNAL_COLUMN_HANDLER:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_OBJECT:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_SWAP:
return G_TYPE_BOOLEAN;
case GLADE_SIGNAL_COLUMN_AFTER:
return G_TYPE_BOOLEAN;
case GLADE_SIGNAL_COLUMN_TOOLTIP:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_SIGNAL:
return G_TYPE_OBJECT;
default:
g_assert_not_reached();
return G_TYPE_NONE;
case GLADE_SIGNAL_COLUMN_NAME:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_SHOW_NAME:
return G_TYPE_BOOLEAN;
case GLADE_SIGNAL_COLUMN_HANDLER:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_OBJECT:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_SWAP:
return G_TYPE_BOOLEAN;
case GLADE_SIGNAL_COLUMN_AFTER:
return G_TYPE_BOOLEAN;
case GLADE_SIGNAL_COLUMN_TOOLTIP:
return G_TYPE_STRING;
case GLADE_SIGNAL_COLUMN_SIGNAL:
return G_TYPE_OBJECT;
case GLADE_SIGNAL_COLUMN_DETAIL:
return G_TYPE_STRING;
default:
g_assert_not_reached();
return G_TYPE_NONE;
}
}
......@@ -264,15 +270,11 @@ enum
ITER_SIGNAL = 1,
};
static gboolean
static inline gboolean
glade_signal_model_is_dummy_handler (GladeSignalModel *model,
GladeSignal *signal)
{
gboolean dummy;
dummy = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (signal),
DUMMY_DATA));
return dummy;
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (signal), DUMMY_DATA));
}
static GladeSignal *
......@@ -291,6 +293,7 @@ glade_signal_model_get_dummy_handler (GladeSignalModel *model,
USERDATA_DEFAULT,
FALSE,
FALSE);
glade_signal_set_detail (signal, DETAIL_DEFAULT);
g_object_set_data (G_OBJECT (signal), DUMMY_DATA, GINT_TO_POINTER (TRUE));
g_hash_table_insert (model->priv->dummy_signals,
(gpointer) glade_signal_class_get_name (sig_class),
......@@ -319,7 +322,7 @@ glade_signal_model_create_signal_iter (GladeSignalModel *sig_model,
GtkTreeIter *iter)
{
glade_signal_model_create_widget_iter (sig_model, widget, iter);
iter->user_data2 = (GladeSignal *) signal;
iter->user_data2 = GLADE_SIGNAL (signal);
}
static GList *
......@@ -345,7 +348,8 @@ glade_signal_model_create_signal_list (GladeSignalModel *sig_model,
}
static void
on_glade_signal_model_added (GladeWidget *widget, const GladeSignal *signal,
on_glade_signal_model_added (GladeWidget *widget,
const GladeSignal *signal,
GladeSignalModel* model)
{
GtkTreeIter iter;
......@@ -356,18 +360,16 @@ on_glade_signal_model_added (GladeWidget *widget, const GladeSignal *signal,
glade_signal_class_get_type (sig_class),
signal,
&iter);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model),
&iter);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model),
path,
&iter);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
gtk_tree_path_free (path);
model->priv->stamp++;
}
static void
on_glade_signal_model_removed (GladeWidget *widget, const GladeSignal *signal,
on_glade_signal_model_removed (GladeWidget *widget,
const GladeSignal *signal,
GladeSignalModel *model)
{
GtkTreeIter iter;
......@@ -378,16 +380,15 @@ on_glade_signal_model_removed (GladeWidget *widget, const GladeSignal *signal,
glade_signal_class_get_type (sig_class),
signal,
&iter);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model),
&iter);
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model),
path);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
gtk_tree_path_free (path);
model->priv->stamp++;
}
static void
on_glade_signal_model_changed (GladeWidget *widget, const GladeSignal *signal,
on_glade_signal_model_changed (GladeWidget *widget,
const GladeSignal *signal,
GladeSignalModel *model)
{
GtkTreeIter iter;
......@@ -399,17 +400,15 @@ on_glade_signal_model_changed (GladeWidget *widget, const GladeSignal *signal,
signal,
&iter);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
gtk_tree_model_row_changed (GTK_TREE_MODEL (model),
path,
&iter);
gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
gtk_tree_path_free (path);
model->priv->stamp++;
}
static void
verify_dummies (const gchar *signal_name,
GladeSignal *signal,
GladeSignalModel *model)
verify_dummies (const gchar *signal_name,
GladeSignal *signal,
GladeSignalModel *model)
{
glade_project_verify_signal (model->priv->widget, signal);
......@@ -417,8 +416,8 @@ verify_dummies (const gchar *signal_name,
}
static void
emit_changed (const gchar *signal_name,
GPtrArray *signals,
emit_changed (const gchar *signal_name,
GPtrArray *signals,
GladeSignalModel *model)
{
gint i;
......@@ -432,8 +431,7 @@ emit_changed (const gchar *signal_name,
}
static void
on_glade_widget_support_changed (GladeWidget *widget,
GladeSignalModel *model)
on_glade_widget_support_changed (GladeWidget *widget, GladeSignalModel *model)
{
/* Update support warning on dummy signals */
g_hash_table_foreach (model->priv->dummy_signals, (GHFunc)verify_dummies, model);
......@@ -461,38 +459,37 @@ glade_signal_model_get_iter (GtkTreeModel *model,
switch (depth)
{
case 1:
/* Widget */
{
glade_signal_model_create_widget_iter (sig_model,
g_list_nth_data (sig_model->priv->widgets,
indices[ITER_WIDGET]),
iter);
return TRUE;
}
case 2:
/* Signal */
{
gboolean retval;
GtkTreePath *path =
gtk_tree_path_new_from_indices (indices[ITER_WIDGET], -1);
GtkTreeIter widget_iter;
gtk_tree_model_get_iter (model, &widget_iter, path);
retval = gtk_tree_model_iter_nth_child (model,
iter,
&widget_iter,
indices[ITER_SIGNAL]);
gtk_tree_path_free (path);
return retval;
}
case 1:
/* Widget */
{
glade_signal_model_create_widget_iter (sig_model,
g_list_nth_data (sig_model->priv->widgets,
indices[ITER_WIDGET]),
iter);
return TRUE;
}
case 2:
/* Signal */
{
gboolean retval;
GtkTreePath *path =
gtk_tree_path_new_from_indices (indices[ITER_WIDGET], -1);
GtkTreeIter widget_iter;
gtk_tree_model_get_iter (model, &widget_iter, path);
retval = gtk_tree_model_iter_nth_child (model,
iter,
&widget_iter,
indices[ITER_SIGNAL]);
gtk_tree_path_free (path);
return retval;
}
}
return FALSE;
}
static GtkTreePath*
glade_signal_model_get_path (GtkTreeModel *model,
GtkTreeIter *iter)
glade_signal_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
{
const gchar *widget;
GladeSignal *handler;
......@@ -524,8 +521,8 @@ glade_signal_model_get_path (GtkTreeModel *model,
if (signal->data != sig_class)
{
if (handlers)
index1 += handlers->len;
if (handlers)
index1 += handlers->len;
index1++; /* dummy_handler */
}