Implemented GladeSignalEditor::callback-suggestions signal

(based on patch by Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com >)
Closes bug #667570 "Implement callback name suggestion on glade-signal-editor"

Added GladeSignalEditor:widget missing property
Added new accumulator _glade_strv_handled_accumulator()
Added new marshall BOXED:OBJECT
This commit is contained in:
Juan Pablo Ugarte 2012-03-19 19:25:34 -03:00
parent 51d10c3202
commit 0e0bf998f2
5 changed files with 265 additions and 104 deletions

View File

@ -30,9 +30,9 @@
gboolean gboolean
_glade_single_object_accumulator (GSignalInvocationHint * ihint, _glade_single_object_accumulator (GSignalInvocationHint *ihint,
GValue * return_accu, GValue *return_accu,
const GValue * handler_return, gpointer dummy) const GValue *handler_return, gpointer dummy)
{ {
GObject *object = g_value_get_object (handler_return); GObject *object = g_value_get_object (handler_return);
g_value_set_object (return_accu, object); g_value_set_object (return_accu, object);
@ -41,9 +41,9 @@ _glade_single_object_accumulator (GSignalInvocationHint * ihint,
} }
gboolean gboolean
_glade_integer_handled_accumulator (GSignalInvocationHint * ihint, _glade_integer_handled_accumulator (GSignalInvocationHint *ihint,
GValue * return_accu, GValue *return_accu,
const GValue * handler_return, const GValue *handler_return,
gpointer dummy) gpointer dummy)
{ {
gboolean continue_emission; gboolean continue_emission;
@ -58,9 +58,9 @@ _glade_integer_handled_accumulator (GSignalInvocationHint * ihint,
/* From gtkmain.c */ /* From gtkmain.c */
gboolean gboolean
_glade_boolean_handled_accumulator (GSignalInvocationHint * ihint, _glade_boolean_handled_accumulator (GSignalInvocationHint *ihint,
GValue * return_accu, GValue *return_accu,
const GValue * handler_return, const GValue *handler_return,
gpointer dummy) gpointer dummy)
{ {
gboolean continue_emission; gboolean continue_emission;
@ -74,9 +74,9 @@ _glade_boolean_handled_accumulator (GSignalInvocationHint * ihint,
} }
gboolean gboolean
_glade_string_accumulator (GSignalInvocationHint * ihint, _glade_string_accumulator (GSignalInvocationHint *ihint,
GValue * return_accu, GValue *return_accu,
const GValue * handler_return, gpointer dummy) const GValue *handler_return, gpointer dummy)
{ {
const gchar *handler_str; const gchar *handler_str;
@ -89,9 +89,22 @@ _glade_string_accumulator (GSignalInvocationHint * ihint,
} }
gboolean gboolean
_glade_stop_emission_accumulator (GSignalInvocationHint * ihint, _glade_strv_handled_accumulator (GSignalInvocationHint *ihint,
GValue * return_accu, GValue *return_accu,
const GValue * handler_return, gpointer dummy) const GValue *handler_return, gpointer dummy)
{
const gchar **handler_strv;
handler_strv = g_value_get_boxed (handler_return);
g_value_set_boxed (return_accu, handler_strv);
return (handler_strv == NULL);
}
gboolean
_glade_stop_emission_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return, gpointer dummy)
{ {
g_value_copy (handler_return, return_accu); g_value_copy (handler_return, return_accu);

View File

@ -25,6 +25,11 @@ gboolean _glade_string_accumulator (GSignalInvocationHint *ihint,
const GValue *handler_return, const GValue *handler_return,
gpointer dummy); gpointer dummy);
gboolean _glade_strv_handled_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer dummy);
gboolean _glade_stop_emission_accumulator (GSignalInvocationHint *ihint, gboolean _glade_stop_emission_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu, GValue *return_accu,
const GValue *handler_return, const GValue *handler_return,

View File

@ -22,3 +22,4 @@ BOOLEAN:STRING,STRING,STRING,BOXED
BOOLEAN:STRING,BOXED,OBJECT BOOLEAN:STRING,BOXED,OBJECT
STRING:OBJECT STRING:OBJECT
INT:OBJECT,BOXED INT:OBJECT,BOXED
BOXED:OBJECT

View File

@ -56,24 +56,33 @@ struct _GladeSignalEditorPrivate
GtkTreeModel *model; GtkTreeModel *model;
GladeWidget *widget; GladeWidget *widget;
GladeWidgetAdaptor* adaptor; GladeWidgetAdaptor *adaptor;
GtkWidget* signal_tree; GtkWidget *signal_tree;
GtkTreeViewColumn* column_name; GtkTreeViewColumn *column_name;
GtkTreeViewColumn* column_handler; GtkTreeViewColumn *column_handler;
GtkTreeViewColumn* column_userdata; GtkTreeViewColumn *column_userdata;
GtkTreeViewColumn* column_swap; GtkTreeViewColumn *column_swap;
GtkTreeViewColumn* column_after; GtkTreeViewColumn *column_after;
GtkCellRenderer* renderer_userdata; GtkCellRenderer *renderer_userdata;
GtkListStore *handler_completion_store;
}; };
enum enum
{ {
SIGNAL_ACTIVATED, SIGNAL_ACTIVATED,
CALLBACK_SUGGESTIONS,
LAST_SIGNAL LAST_SIGNAL
}; };
enum
{
PROP_0,
PROP_GLADE_WIDGET
};
static guint glade_signal_editor_signals[LAST_SIGNAL] = { 0 }; static guint glade_signal_editor_signals[LAST_SIGNAL] = { 0 };
/* Utils */ /* Utils */
@ -88,16 +97,16 @@ glade_signal_is_dummy (GladeSignal *signal)
/* Signal handlers */ /* Signal handlers */
static void static void
on_handler_edited (GtkCellRendererText* renderer, on_handler_edited (GtkCellRendererText *renderer,
gchar* path, gchar *path,
gchar* handler, gchar *handler,
gpointer user_data) gpointer user_data)
{ {
GladeSignalEditor* self = GLADE_SIGNAL_EDITOR(user_data); GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (user_data);
GtkTreePath* tree_path = gtk_tree_path_new_from_string (path); GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
GtkTreeIter iter; GtkTreeIter iter;
gchar* old_handler; gchar *old_handler;
GladeSignal* signal; GladeSignal *signal;
gboolean dummy; gboolean dummy;
g_return_if_fail (self->priv->widget != NULL); g_return_if_fail (self->priv->widget != NULL);
@ -178,42 +187,98 @@ on_handler_edited (GtkCellRendererText* renderer,
gtk_tree_path_free (tree_path); gtk_tree_path_free (tree_path);
} }
static void static gchar **
on_handler_editing_started (GtkCellRenderer* renderer, glade_signal_editor_callback_suggestions (GladeSignalEditor *editor,
GtkCellEditable* editable, GladeSignal *signal)
gchar* path,
gpointer user_data)
{ {
GladeSignalEditor* self = GLADE_SIGNAL_EDITOR(user_data); GladeWidget *widget = glade_signal_editor_get_widget (editor);
GtkTreePath* tree_path = gtk_tree_path_new_from_string (path); gchar *signal_name, *name, **suggestions;
/* Remove the <Type here> */ suggestions = g_new (gchar *, 10);
if (GTK_IS_ENTRY (editable))
{ name = (gchar *) glade_widget_get_name (widget);
GtkTreeIter iter;
GladeSignal* signal; signal_name = g_strdup (glade_signal_get_name (signal));
gboolean dummy; glade_util_replace (signal_name, '-', '_');
gtk_tree_model_get_iter (self->priv->model,
&iter, suggestions[0] = g_strdup_printf ("on_%s_%s", name, signal_name);
tree_path); suggestions[1] = g_strdup_printf ("%s_%s_cb", name, signal_name);
gtk_tree_model_get (self->priv->model, suggestions[2] = g_strdup ("gtk_widget_show");
&iter, suggestions[3] = g_strdup ("gtk_widget_hide");
GLADE_SIGNAL_COLUMN_SIGNAL, &signal, suggestions[4] = g_strdup ("gtk_widget_grab_focus");
-1); suggestions[5] = g_strdup ("gtk_widget_destroy");
dummy = glade_signal_is_dummy (signal); suggestions[6] = g_strdup ("gtk_true");
if (dummy) suggestions[7] = g_strdup ("gtk_false");
{ suggestions[8] = g_strdup ("gtk_main_quit");
gtk_entry_set_text (GTK_ENTRY (editable), ""); suggestions[9] = NULL;
}
g_object_unref (signal); return suggestions;
}
gtk_tree_path_free (tree_path);
} }
static void static void
glade_signal_editor_user_data_activate (GtkCellRenderer * icon_renderer, on_handler_editing_started (GtkCellRenderer *renderer,
const gchar * path_str, GtkCellEditable *editable,
GladeSignalEditor * editor) gchar *path,
gpointer user_data)
{
/* Check if editable is still an entry */
if (GTK_IS_ENTRY (editable))
{
GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (user_data);
GladeSignalEditorPrivate *priv = self->priv;
GtkEntry *entry = GTK_ENTRY (editable);
GtkEntryCompletion *completion;
const gchar *signal_name = NULL;
GtkTreePath *tree_path;
GtkTreeIter iter;
GladeSignal *signal;
gchar **suggestions;
gint i;
tree_path = gtk_tree_path_new_from_string (path);
gtk_tree_model_get_iter (priv->model, &iter, tree_path);
gtk_tree_path_free (tree_path);
gtk_tree_model_get (priv->model, &iter,
GLADE_SIGNAL_COLUMN_SIGNAL, &signal,
-1);
signal_name = glade_signal_get_name (signal);
if (glade_signal_is_dummy (signal))
gtk_entry_set_text (entry, "");
g_signal_emit (self, glade_signal_editor_signals [CALLBACK_SUGGESTIONS], 0, signal, &suggestions);
g_object_unref (signal);
if (!signal_name)
return;
completion = gtk_entry_completion_new ();
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_completion_set_minimum_key_length (completion, 0);
gtk_entry_completion_set_inline_completion (completion, FALSE);
gtk_entry_completion_set_inline_selection (completion, TRUE);
gtk_entry_completion_set_popup_completion (completion, TRUE);
gtk_entry_set_completion (entry, NULL);
gtk_list_store_clear (priv->handler_completion_store);
for (i = 0; suggestions[i]; i++)
{
gtk_list_store_append (priv->handler_completion_store, &iter);
gtk_list_store_set (priv->handler_completion_store, &iter, 0, suggestions[i], -1);
}
gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (priv->handler_completion_store));
gtk_entry_set_completion (entry, completion);
}
}
static void
glade_signal_editor_user_data_activate (GtkCellRenderer *icon_renderer,
const gchar *path_str,
GladeSignalEditor *editor)
{ {
GladeSignalEditorPrivate *priv = editor->priv; GladeSignalEditorPrivate *priv = editor->priv;
GtkTreePath *path = gtk_tree_path_new_from_string (path_str); GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
@ -268,15 +333,15 @@ glade_signal_editor_user_data_activate (GtkCellRenderer * icon_renderer,
} }
static void static void
on_swap_toggled (GtkCellRendererToggle* renderer, on_swap_toggled (GtkCellRendererToggle *renderer,
gchar* path, gchar *path,
gpointer user_data) gpointer user_data)
{ {
GladeSignalEditor* self = GLADE_SIGNAL_EDITOR(user_data); GladeSignalEditor *self = GLADE_SIGNAL_EDITOR(user_data);
GtkTreePath* tree_path = gtk_tree_path_new_from_string (path); GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
GtkTreeIter iter; GtkTreeIter iter;
GladeSignal* old_signal; GladeSignal *old_signal;
GladeSignal* new_signal; GladeSignal *new_signal;
g_return_if_fail (self->priv->widget != NULL); g_return_if_fail (self->priv->widget != NULL);
@ -304,15 +369,15 @@ on_swap_toggled (GtkCellRendererToggle* renderer,
} }
static void static void
on_after_toggled (GtkCellRendererToggle* renderer, on_after_toggled (GtkCellRendererToggle *renderer,
gchar* path, gchar *path,
gpointer user_data) gpointer user_data)
{ {
GladeSignalEditor* self = GLADE_SIGNAL_EDITOR(user_data); GladeSignalEditor *self = GLADE_SIGNAL_EDITOR(user_data);
GtkTreePath* tree_path = gtk_tree_path_new_from_string (path); GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
GtkTreeIter iter; GtkTreeIter iter;
GladeSignal* old_signal; GladeSignal *old_signal;
GladeSignal* new_signal; GladeSignal *new_signal;
g_return_if_fail (self->priv->widget != NULL); g_return_if_fail (self->priv->widget != NULL);
@ -340,9 +405,9 @@ on_after_toggled (GtkCellRendererToggle* renderer,
} }
static void static void
glade_signal_editor_devhelp (GtkCellRenderer * cell, glade_signal_editor_devhelp (GtkCellRenderer *cell,
const gchar * path_str, const gchar *path_str,
GladeSignalEditor * editor) GladeSignalEditor *editor)
{ {
GladeSignalEditorPrivate *priv = editor->priv; GladeSignalEditorPrivate *priv = editor->priv;
GtkTreePath *path = gtk_tree_path_new_from_string (path_str); GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
@ -373,6 +438,45 @@ glade_signal_editor_devhelp (GtkCellRenderer * cell,
g_object_unref (signal); g_object_unref (signal);
} }
static void
glade_signal_editor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (object);
GladeSignalEditorPrivate *priv = self->priv;
switch (prop_id)
{
case PROP_GLADE_WIDGET:
g_value_set_object (value, priv->widget);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
glade_signal_editor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (object);
switch (prop_id)
{
case PROP_GLADE_WIDGET:
glade_signal_editor_load_widget (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/** /**
* glade_signal_editor_new: * glade_signal_editor_new:
* *
@ -477,13 +581,13 @@ glade_signal_editor_dispose (GObject *object)
#define BORDER 10 #define BORDER 10
static cairo_surface_t* static cairo_surface_t*
create_rich_drag_surface (GtkWidget* widget, const gchar* text) create_rich_drag_surface (GtkWidget *widget, const gchar *text)
{ {
GtkStyleContext* context = gtk_widget_get_style_context (widget); GtkStyleContext *context = gtk_widget_get_style_context (widget);
GtkStateFlags state = gtk_widget_get_state_flags (widget); GtkStateFlags state = gtk_widget_get_state_flags (widget);
PangoLayout* layout = pango_layout_new (gtk_widget_get_pango_context (widget)); PangoLayout *layout = pango_layout_new (gtk_widget_get_pango_context (widget));
cairo_t* cr; cairo_t *cr;
cairo_surface_t* s; cairo_surface_t *s;
gint width, height; gint width, height;
GdkRGBA rgba; GdkRGBA rgba;
@ -517,14 +621,14 @@ create_rich_drag_surface (GtkWidget* widget, const gchar* text)
} }
static void static void
glade_signal_editor_drag_begin (GtkWidget* widget, glade_signal_editor_drag_begin (GtkWidget *widget,
GdkDragContext* context, GdkDragContext *context,
gpointer user_data) gpointer user_data)
{ {
cairo_surface_t *s = NULL; cairo_surface_t *s = NULL;
GtkTreeModel *model; GtkTreeModel *model;
GtkTreeIter iter; GtkTreeIter iter;
GtkTreeSelection* selection; GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
@ -561,7 +665,7 @@ glade_signal_editor_name_cell_data_func (GtkTreeViewColumn *column,
GtkTreeIter *iter, GtkTreeIter *iter,
gpointer data) gpointer data)
{ {
GladeSignal* signal; GladeSignal *signal;
gboolean show_name; gboolean show_name;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
@ -660,8 +764,8 @@ glade_signal_editor_data_cell_data_func (GtkTreeViewColumn *column,
GtkTreeIter *iter, GtkTreeIter *iter,
gpointer data) gpointer data)
{ {
GladeSignalEditor* editor = GLADE_SIGNAL_EDITOR (data); GladeSignalEditor *editor = GLADE_SIGNAL_EDITOR (data);
GladeSignal* signal; GladeSignal *signal;
GdkRGBA color; GdkRGBA color;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
@ -719,7 +823,7 @@ glade_signal_editor_warning_cell_data_func (GtkTreeViewColumn *column,
GtkTreeIter *iter, GtkTreeIter *iter,
gpointer data) gpointer data)
{ {
GladeSignal* signal; GladeSignal *signal;
gboolean visible = FALSE; gboolean visible = FALSE;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
@ -744,16 +848,16 @@ glade_signal_editor_devhelp_cell_data_func (GtkTreeViewColumn *column,
GtkTreeIter *iter, GtkTreeIter *iter,
gpointer data) gpointer data)
{ {
GladeSignal* signal; GladeSignal *signal;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
GLADE_SIGNAL_COLUMN_SIGNAL, &signal, GLADE_SIGNAL_COLUMN_SIGNAL, &signal,
-1); -1);
if (signal) if (signal)
{ {
const GladeSignalClass* class = glade_signal_get_class (signal); const GladeSignalClass *class = glade_signal_get_class (signal);
GladeWidgetAdaptor* adaptor = glade_signal_class_get_adaptor (class); GladeWidgetAdaptor *adaptor = glade_signal_class_get_adaptor (class);
gchar* book; gchar *book;
g_object_get (adaptor, "book", &book, NULL); g_object_get (adaptor, "book", &book, NULL);
g_object_set (renderer, g_object_set (renderer,
@ -784,7 +888,7 @@ glade_signal_editor_signal_activate (GtkTreeView *tree_view,
GladeSignalEditor *editor) GladeSignalEditor *editor)
{ {
GladeSignalEditor* self = GLADE_SIGNAL_EDITOR(editor); GladeSignalEditor *self = GLADE_SIGNAL_EDITOR (editor);
if (self->priv->widget == NULL || column != self->priv->column_name) if (self->priv->widget == NULL || column != self->priv->column_name)
return; return;
@ -811,9 +915,9 @@ static void
glade_signal_editor_init (GladeSignalEditor *self) glade_signal_editor_init (GladeSignalEditor *self)
{ {
GtkWidget *scroll; GtkWidget *scroll;
GtkCellRenderer* renderer; GtkCellRenderer *renderer;
GtkCellArea* cell_area; GtkCellArea *cell_area;
GladeSignalEditorPrivate* priv; GladeSignalEditorPrivate *priv;
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GLADE_TYPE_SIGNAL_EDITOR, GladeSignalEditorPrivate); self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GLADE_TYPE_SIGNAL_EDITOR, GladeSignalEditorPrivate);
priv = self->priv; priv = self->priv;
@ -995,6 +1099,9 @@ glade_signal_editor_init (GladeSignalEditor *self)
G_CALLBACK(glade_signal_editor_drag_begin), G_CALLBACK(glade_signal_editor_drag_begin),
self); self);
/* Handler completion */
priv->handler_completion_store = gtk_list_store_new (1, G_TYPE_STRING);
/* Emit created signal */ /* Emit created signal */
g_signal_emit_by_name (glade_app_get(), "signal-editor-created", self); g_signal_emit_by_name (glade_app_get(), "signal-editor-created", self);
@ -1009,8 +1116,12 @@ glade_signal_editor_class_init (GladeSignalEditorClass *klass)
glade_signal_editor_parent_class = g_type_class_peek_parent (klass); glade_signal_editor_parent_class = g_type_class_peek_parent (klass);
object_class = G_OBJECT_CLASS (klass); object_class = G_OBJECT_CLASS (klass);
object_class->get_property = glade_signal_editor_get_property;
object_class->set_property = glade_signal_editor_set_property;
object_class->dispose = glade_signal_editor_dispose; object_class->dispose = glade_signal_editor_dispose;
klass->callback_suggestions = glade_signal_editor_callback_suggestions;
g_type_class_add_private (klass, sizeof (GladeSignalEditorPrivate)); g_type_class_add_private (klass, sizeof (GladeSignalEditorPrivate));
/** /**
@ -1020,12 +1131,42 @@ glade_signal_editor_class_init (GladeSignalEditorClass *klass)
* Emitted when a item is activated in the GladeInspector. * Emitted when a item is activated in the GladeInspector.
*/ */
glade_signal_editor_signals[SIGNAL_ACTIVATED] = glade_signal_editor_signals[SIGNAL_ACTIVATED] =
g_signal_new ("signal-activated", g_signal_new ("signal-activated",
G_TYPE_FROM_CLASS (object_class), G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, g_cclosure_marshal_VOID__OBJECT, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_NONE, 1,
GLADE_TYPE_SIGNAL /* Signal data formatted string */ GLADE_TYPE_SIGNAL /* Signal data formatted string */
); );
/**
* GladeSignalEditor::callback-suggestions:
* @editor: the object which received the signal
* @signal: the #GladeSignal that needs callbacks suggestions
* @suggestions: Return
*
* Emitted when the editor needs to show a list of callbacks suggestions to the user.
*
* Returns wheter or not the event was handled.
*/
glade_signal_editor_signals[CALLBACK_SUGGESTIONS] =
g_signal_new ("callback-suggestions",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GladeSignalEditorClass, callback_suggestions),
_glade_strv_handled_accumulator,
NULL, _glade_marshal_BOXED__OBJECT,
G_TYPE_STRV, 1,
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",
GTK_TYPE_TREE_MODEL,
G_PARAM_READWRITE));
} }

View File

@ -31,6 +31,7 @@ struct _GladeSignalEditorClass
{ {
GtkVBoxClass parent_class; GtkVBoxClass parent_class;
gchar ** (* callback_suggestions) (GladeSignalEditor *editor, GladeSignal *signal);
void (* glade_reserved1) (void); void (* glade_reserved1) (void);
void (* glade_reserved2) (void); void (* glade_reserved2) (void);
void (* glade_reserved3) (void); void (* glade_reserved3) (void);