gedit r6625 - in branches/message_system: gedit plugin-loaders/python/bindings
- From: jessevdk svn gnome org
- To: svn-commits-list gnome org
- Subject: gedit r6625 - in branches/message_system: gedit plugin-loaders/python/bindings
- Date: Wed, 26 Nov 2008 16:45:01 +0000 (UTC)
Author: jessevdk
Date: Wed Nov 26 16:45:01 2008
New Revision: 6625
URL: http://svn.gnome.org/viewvc/gedit?rev=6625&view=rev
Log:
Basic, unfinished message bus implementation
Added:
branches/message_system/gedit/gedit-commands-messages.c
branches/message_system/gedit/gedit-message-bus.c
branches/message_system/gedit/gedit-message-bus.h
branches/message_system/gedit/gedit-message.c
branches/message_system/gedit/gedit-message.h
branches/message_system/plugin-loaders/python/bindings/geditmessage.override
Modified:
branches/message_system/gedit/Makefile.am
branches/message_system/gedit/gedit-commands.h
branches/message_system/gedit/gedit.c
branches/message_system/plugin-loaders/python/bindings/Makefile.am
branches/message_system/plugin-loaders/python/bindings/gedit.defs
branches/message_system/plugin-loaders/python/bindings/gedit.override
Modified: branches/message_system/gedit/Makefile.am
==============================================================================
--- branches/message_system/gedit/Makefile.am (original)
+++ branches/message_system/gedit/Makefile.am Wed Nov 26 16:45:01 2008
@@ -21,7 +21,9 @@
-DGEDIT_ICONDIR=\""$(datadir)/gedit-2/icons"\"
gedit_SOURCES = \
- gedit.c
+ gedit.c \
+ gedit-message.c \
+ gedit-message-bus.c
gedit_LDADD = libgedit.la $(GEDIT_LIBS)
@@ -84,7 +86,9 @@
gedit-encodings-option-menu.h \
gedit-file-chooser-dialog.h \
gedit-help.h \
+ gedit-message.h \
gedit-message-area.h \
+ gedit-message-bus.h \
gedit-metadata-manager.h \
gedit-notebook.h \
gedit-panel.h \
Added: branches/message_system/gedit/gedit-commands-messages.c
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-commands-messages.c Wed Nov 26 16:45:01 2008
@@ -0,0 +1,321 @@
+/*
+ * gedit-commands-messages.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 Jesse van den Kieboom <jesse icecrew nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gedit-commands.h"
+
+#include "gedit-app.h"
+#include "gedit-window.h"
+#include "gedit-encodings.h"
+#include "gedit-message-bus.h"
+
+#include <gdk/gdkx.h>
+#include <string.h>
+
+#define BUS_CONNECT(domain, name, callback) gedit_message_bus_connect (bus, domain, name, callback, NULL, NULL)
+
+static GdkDisplay *
+display_open_if_needed (const gchar *name)
+{
+ GSList *displays;
+ GSList *l;
+ GdkDisplay *display = NULL;
+
+ displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+
+ for (l = displays; l != NULL; l = l->next)
+ {
+ if (strcmp (gdk_display_get_name ((GdkDisplay *) l->data), name) == 0)
+ {
+ display = l->data;
+ break;
+ }
+ }
+
+ g_slist_free (displays);
+
+ return display != NULL ? display : gdk_display_open (name);
+}
+
+static GeditWindow *
+get_window_from_message (GeditMessage *message)
+{
+ gboolean new_window = FALSE;
+ GeditApp *app;
+ const gchar *invalid_key;
+
+ /* optional parameters, used to specify correct workspace/viewport */
+ GdkScreen *screen = NULL;
+ gint screen_number = -1;
+ gint workspace = -1;
+ gint viewport_x = -1;
+ gint viewport_y = -1;
+ gchar *display_name = NULL;
+
+ if (!gedit_message_get_type_safe (message,
+ &invalid_key,
+ "new_window", G_TYPE_BOOLEAN, &new_window,
+ "screen_number", G_TYPE_INT, &screen_number,
+ "workspace", G_TYPE_INT, &workspace,
+ "viewport_x", G_TYPE_INT, &viewport_x,
+ "viewport_y", G_TYPE_INT, &viewport_y,
+ "display_name", G_TYPE_STRING, &display_name,
+ NULL))
+ {
+ g_warning ("Message contains invalid value for key `%s'", invalid_key);
+ g_free (display_name);
+ return NULL;
+ }
+
+ app = gedit_app_get_default ();
+
+ /* get correct screen using the display_name and screen_number */
+ if (display_name != NULL)
+ {
+ GdkDisplay *display;
+
+ display = display_open_if_needed (display_name);
+ screen = gdk_display_get_screen (display, screen_number == -1 ? 0 : screen_number);
+ }
+
+ if (new_window)
+ return gedit_app_create_window (app, screen);
+ else if (screen != NULL)
+ return _gedit_app_get_window_in_viewport (app,
+ screen,
+ workspace == -1 ? 0 : workspace,
+ viewport_x == -1 ? 0 : viewport_x,
+ viewport_y == -1 ? 0 : viewport_y);
+ else
+ return gedit_app_get_active_window (app);
+}
+
+static void
+set_interaction_time_and_present (GeditWindow *window,
+ guint32 startup_timestamp)
+{
+ /* set the proper interaction time on the window.
+ * Fall back to roundtripping to the X server when we
+ * don't have the timestamp, e.g. when launched from
+ * terminal. We also need to make sure that the window
+ * has been realized otherwise it will not work. lame.
+ */
+ if (!GTK_WIDGET_REALIZED (window))
+ gtk_widget_realize (GTK_WIDGET (window));
+
+ if (startup_timestamp <= 0)
+ startup_timestamp = gdk_x11_get_server_time (GTK_WIDGET (window)->window);
+
+ gdk_x11_window_set_user_time (GTK_WIDGET (window)->window,
+ startup_timestamp);
+
+ gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+on_message_commands_open (GeditMessageBus *bus,
+ GeditMessage *message,
+ gpointer userdata)
+{
+ GStrv uris = NULL;
+ gchar *encoding_charset = NULL;
+ gint line_position = 0;
+ const GeditEncoding *encoding = NULL;
+ GSList *uri_list = NULL;
+ const gchar *invalid_key;
+ GStrv ptr;
+ guint32 startup_timestamp = 0;
+ GeditWindow *window;
+
+ if (gedit_message_has_key (message, "uris") &&
+ gedit_message_type_check (message, NULL, G_TYPE_STRV, "uris", NULL))
+ {
+ /* good, this is what we want, list of uris */
+ gedit_message_get (message, "uris", &uris, NULL);
+
+ }
+ else if (gedit_message_has_key (message, "uri") &&
+ gedit_message_type_check (message, NULL, G_TYPE_STRING, "uri", NULL))
+ {
+ /* single uri is also supported, we put it in uris */
+ uris = g_new0 (gchar *, 2);
+ gedit_message_get (message, "uri", uris, NULL);
+ }
+
+ /* check if we got at least one uri */
+ if (uris == NULL || *uris == NULL)
+ {
+ g_strfreev (uris);
+ return;
+ }
+
+ window = get_window_from_message (message);
+
+ if (window == NULL)
+ {
+ g_strfreev (uris);
+ return;
+ }
+
+ /* get all the other parameters */
+ if (!gedit_message_get_type_safe (message,
+ &invalid_key,
+ "encoding", G_TYPE_STRING, &encoding_charset,
+ "line_position", G_TYPE_INT, &line_position,
+ "startup_timestamp", G_TYPE_UINT, &startup_timestamp,
+ NULL))
+ {
+ g_warning ("Message commands.open contains invalid value for key `%s'", invalid_key);
+
+ g_strfreev (uris);
+ g_free (encoding_charset);
+ return;
+ }
+
+ if (encoding_charset != NULL)
+ encoding = gedit_encoding_get_from_charset (encoding_charset);
+
+ ptr = uris;
+
+ while (*ptr)
+ {
+ uri_list = g_slist_prepend (uri_list, *ptr);
+ ptr++;
+ }
+
+ uri_list = g_slist_reverse (uri_list);
+
+ _gedit_cmd_load_files_from_prompt (window, uri_list, encoding, line_position);
+
+ /* set the proper interaction time on the window.
+ * Fall back to roundtripping to the X server when we
+ * don't have the timestamp, e.g. when launched from
+ * terminal. We also need to make sure that the window
+ * has been realized otherwise it will not work. lame.
+ */
+ set_interaction_time_and_present (window, startup_timestamp);
+
+ g_strfreev (uris);
+ g_free (encoding_charset);
+
+ g_slist_free (uri_list);
+}
+
+static void
+on_message_commands_new_document (GeditMessageBus *bus,
+ GeditMessage *message,
+ gpointer userdata)
+{
+ GeditWindow *window;
+ const gchar *invalid_key;
+ guint32 startup_timestamp = 0;
+
+ window = get_window_from_message (message);
+
+ if (window == NULL)
+ return;
+
+ if (!gedit_message_get_type_safe (message,
+ &invalid_key,
+ "startup_timestamp", G_TYPE_UINT, &startup_timestamp,
+ NULL))
+ {
+ g_warning ("Message contains invalid value for key `%s'", invalid_key);
+ return;
+ }
+
+ gedit_window_create_tab (window, TRUE);
+
+ /* set the proper interaction time on the window.
+ * Fall back to roundtripping to the X server when we
+ * don't have the timestamp, e.g. when launched from
+ * terminal. We also need to make sure that the window
+ * has been realized otherwise it will not work. lame.
+ */
+ set_interaction_time_and_present (window, startup_timestamp);
+}
+
+static void
+on_message_commands_present (GeditMessageBus *bus,
+ GeditMessage *message,
+ gpointer userdata)
+{
+ GeditWindow *window;
+ const gchar *invalid_key;
+ guint32 startup_timestamp = 0;
+ gboolean new_document = FALSE;
+ GeditDocument *doc;
+
+ window = get_window_from_message (message);
+
+ if (window == NULL)
+ return;
+
+ if (!gedit_message_get_type_safe (message,
+ &invalid_key,
+ "new_document", G_TYPE_BOOLEAN, &new_document,
+ "startup_timestamp", G_TYPE_UINT, &startup_timestamp,
+ NULL))
+ {
+ g_warning ("Message contains invalid value for key `%s'", invalid_key);
+ return;
+ }
+
+
+ doc = gedit_window_get_active_document (window);
+
+ if (doc == NULL ||
+ !gedit_document_is_untouched (doc) ||
+ new_document)
+ gedit_window_create_tab (window, TRUE);
+
+ /* set the proper interaction time on the window.
+ * Fall back to roundtripping to the X server when we
+ * don't have the timestamp, e.g. when launched from
+ * terminal. We also need to make sure that the window
+ * has been realized otherwise it will not work. lame.
+ */
+ set_interaction_time_and_present (window, startup_timestamp);
+}
+
+void
+_gedit_commands_messages_register ()
+{
+ GeditMessageBus *bus;
+
+ /* register message handlers on the message bus */
+ bus = gedit_message_bus_get_default ();
+
+ /* open list of uris, or single uri */
+ BUS_CONNECT ("core", "open", on_message_commands_open);
+
+ /* alias "open_uris", "open_uri", "load", "load_uris", "load_uri" */
+ BUS_CONNECT ("core", "open_uris", on_message_commands_open);
+ BUS_CONNECT ("core", "open_uri", on_message_commands_open);
+ BUS_CONNECT ("core", "load", on_message_commands_open);
+ BUS_CONNECT ("core", "load_uris", on_message_commands_open);
+ BUS_CONNECT ("core", "load_uri", on_message_commands_open);
+
+ /* new document message, used by gedit startup */
+ BUS_CONNECT ("core", "new_document", on_message_commands_new_document);
+
+ BUS_CONNECT ("core", "present", on_message_commands_present);
+}
Modified: branches/message_system/gedit/gedit-commands.h
==============================================================================
--- branches/message_system/gedit/gedit-commands.h (original)
+++ branches/message_system/gedit/gedit-commands.h Wed Nov 26 16:45:01 2008
@@ -151,6 +151,8 @@
void _gedit_cmd_file_save_documents_list (GeditWindow *window,
GList *docs);
+//void _gedit_commands_messages_register (void);
+
G_END_DECLS
#endif /* __GEDIT_COMMANDS_H__ */
Added: branches/message_system/gedit/gedit-message-bus.c
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-message-bus.c Wed Nov 26 16:45:01 2008
@@ -0,0 +1,941 @@
+#include "gedit-message-bus.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <gobject/gvaluecollector.h>
+
+#define GEDIT_MESSAGE_BUS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusPrivate))
+
+typedef struct
+{
+ gchar *domain;
+ gchar *name;
+
+ GList *listeners;
+} Message;
+
+typedef struct
+{
+ gchar *key;
+ GType type;
+ gboolean required;
+} PolicyItem;
+
+typedef struct
+{
+ gchar *domain;
+ gchar *name;
+
+ GList *policies; /* list of PolicyItem */
+} Policy;
+
+typedef struct
+{
+ guint id;
+ gboolean blocked;
+
+ GDestroyNotify destroy_data;
+ GeditMessageCallback callback;
+ gpointer userdata;
+} Listener;
+
+typedef struct
+{
+ Message *message;
+ GList *listener;
+} IdMap;
+
+struct _GeditMessageBusPrivate
+{
+ GHashTable *messages;
+ GHashTable *idmap;
+
+ GList *message_queue;
+ guint idle_id;
+
+ guint next_id;
+
+ GHashTable *policies;
+};
+
+/* signals */
+enum
+{
+ DISPATCH,
+ LAST_SIGNAL
+};
+
+static guint message_bus_signals[LAST_SIGNAL];
+
+static void gedit_message_bus_dispatch_real (GeditMessageBus *bus,
+ GeditMessage *message);
+
+G_DEFINE_TYPE(GeditMessageBus, gedit_message_bus, G_TYPE_OBJECT)
+
+static void
+policy_item_free (PolicyItem *pitem)
+{
+ g_free (pitem->key);
+ g_free (pitem);
+}
+
+static void
+policy_free (Policy *policy)
+{
+ GList *item;
+
+ g_free (policy->domain);
+ g_free (policy->name);
+
+ for (item = policy->policies; item; item = item->next)
+ policy_item_free ((PolicyItem *)item->data);
+
+ g_list_free (policy->policies);
+ g_free (policy);
+}
+
+static void
+listener_free (Listener *listener)
+{
+ if (listener->destroy_data)
+ listener->destroy_data (listener->userdata);
+
+ g_free (listener);
+}
+
+static void
+message_free (Message *message)
+{
+ g_free (message->name);
+ g_free (message->domain);
+
+ g_list_foreach (message->listeners, (GFunc)listener_free, NULL);
+ g_list_free (message->listeners);
+
+ g_free (message);
+}
+
+static void
+message_queue_free (GList *queue)
+{
+ g_list_foreach (queue, (GFunc)g_object_unref, NULL);
+ g_list_free (queue);
+}
+
+static void
+gedit_message_bus_finalize (GObject *object)
+{
+ GeditMessageBus *bus = GEDIT_MESSAGE_BUS (object);
+
+ if (bus->priv->idle_id != 0)
+ g_source_remove (bus->priv->idle_id);
+
+ message_queue_free (bus->priv->message_queue);
+ g_hash_table_destroy (bus->priv->messages);
+ g_hash_table_destroy (bus->priv->idmap);
+
+ G_OBJECT_CLASS (gedit_message_bus_parent_class)->finalize (object);
+}
+
+static void
+gedit_message_bus_class_init (GeditMessageBusClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gedit_message_bus_finalize;
+
+ klass->dispatch = gedit_message_bus_dispatch_real;
+
+ message_bus_signals[DISPATCH] =
+ g_signal_new ("dispatch",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GeditMessageBusClass, dispatch),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GEDIT_TYPE_MESSAGE);
+
+ g_type_class_add_private (object_class, sizeof(GeditMessageBusPrivate));
+}
+
+inline static gchar *
+msg_identifier (const gchar *domain,
+ const gchar *name)
+{
+ return g_strconcat (domain, "::", name, NULL);
+}
+
+static Message *
+message_new (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name)
+{
+ Message *message = g_new (Message, 1);
+
+ message->domain = g_strdup (domain);
+ message->name = g_strdup (name);
+ message->listeners = NULL;
+
+ g_hash_table_insert (bus->priv->messages,
+ msg_identifier (domain, name),
+ message);
+ return message;
+}
+
+static Message *
+lookup_message (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ gboolean create)
+{
+ gchar *identifier;
+ Message *message;
+
+ identifier = msg_identifier (domain, name);
+ message = (Message *)g_hash_table_lookup (bus->priv->messages, identifier);
+ g_free (identifier);
+
+ if (!message && !create)
+ return NULL;
+
+ if (!message)
+ message = message_new (bus, domain, name);
+
+ return message;
+}
+
+static guint
+add_listener (GeditMessageBus *bus,
+ Message *message,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ GDestroyNotify destroy_data)
+{
+ Listener *listener;
+ IdMap *idmap;
+
+ listener = g_new (Listener, 1);
+ listener->id = ++bus->priv->next_id;
+ listener->callback = callback;
+ listener->userdata = userdata;
+ listener->blocked = FALSE;
+ listener->destroy_data = destroy_data;
+
+ message->listeners = g_list_append (message->listeners, listener);
+
+ idmap = g_new (IdMap, 1);
+ idmap->message = message;
+ idmap->listener = g_list_last (message->listeners);
+
+ g_hash_table_insert (bus->priv->idmap, GINT_TO_POINTER (listener->id), idmap);
+ return listener->id;
+}
+
+static void
+remove_listener (GeditMessageBus *bus,
+ Message *message,
+ GList *listener)
+{
+ Listener *lst;
+
+ lst = (Listener *)listener->data;
+
+ /* remove from idmap */
+ g_hash_table_remove (bus->priv->idmap, GINT_TO_POINTER (lst->id));
+ listener_free (lst);
+
+ /* remove from list of listeners */
+ message->listeners = g_list_delete_link (message->listeners, listener);
+
+ if (!message->listeners)
+ {
+ /* remove message because it does not have any listeners */
+ g_hash_table_remove (bus->priv->messages, message);
+ }
+}
+
+static void
+block_listener (GeditMessageBus *bus,
+ Message *message,
+ GList *listener)
+{
+ Listener *lst;
+
+ lst = (Listener *)listener->data;
+ lst->blocked = TRUE;
+}
+
+static void
+unblock_listener (GeditMessageBus *bus,
+ Message *message,
+ GList *listener)
+{
+ Listener *lst;
+
+ lst = (Listener *)listener->data;
+ lst->blocked = FALSE;
+}
+
+static void
+dispatch_message_real (GeditMessageBus *bus,
+ Message *msg,
+ GeditMessage *message)
+{
+ GList *item;
+
+ for (item = msg->listeners; item; item = item->next)
+ {
+ Listener *listener = (Listener *)item->data;
+
+ if (!listener->blocked)
+ listener->callback (bus, message, listener->userdata);
+ }
+}
+
+static void
+gedit_message_bus_dispatch_real (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ const gchar *domain;
+ const gchar *name;
+ Message *msg;
+
+ domain = gedit_message_get_domain (message);
+ name = gedit_message_get_name (message);
+
+ msg = lookup_message (bus, domain, name, FALSE);
+
+ if (msg)
+ dispatch_message_real (bus, msg, message);
+}
+
+static void
+dispatch_message (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ g_signal_emit (bus, message_bus_signals[DISPATCH], 0, message);
+}
+
+static gboolean
+idle_dispatch (GeditMessageBus *bus)
+{
+ GList *list;
+ GList *item;
+
+ /* make sure to set idle_id to 0 first so that any new async messages
+ will be queued properly */
+ bus->priv->idle_id = 0;
+
+ /* reverse queue to get correct delivery order */
+ list = g_list_reverse (bus->priv->message_queue);
+ bus->priv->message_queue = NULL;
+
+ for (item = list; item; item = item->next)
+ {
+ GeditMessage *msg = GEDIT_MESSAGE (item->data);
+
+ dispatch_message (bus, msg);
+ }
+
+ message_queue_free (list);
+ return FALSE;
+}
+
+typedef void (*MatchCallback) (GeditMessageBus *, Message *, GList *);
+
+static void
+process_by_id (GeditMessageBus *bus,
+ guint id,
+ MatchCallback processor)
+{
+ IdMap *idmap;
+
+ idmap = (IdMap *)g_hash_table_lookup (bus->priv->idmap, GINT_TO_POINTER (id));
+
+ if (idmap == NULL)
+ {
+ g_warning ("No handler registered with id `%d'", id);
+ return;
+ }
+
+ processor (bus, idmap->message, idmap->listener);
+}
+
+static void
+process_by_match (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ MatchCallback processor)
+{
+ Message *message;
+ GList *item;
+
+ message = lookup_message (bus, domain, name, FALSE);
+
+ if (!message)
+ {
+ g_warning ("No such handler registered for %s::%s", domain, name);
+ return;
+ }
+
+ for (item = message->listeners; item; item = item->next)
+ {
+ Listener *listener = (Listener *)item->data;
+
+ if (listener->callback == callback &&
+ listener->userdata == userdata)
+ {
+ processor (bus, message, item);
+ return;
+ }
+ }
+
+ g_warning ("No such handler registered for %s::%s", domain, name);
+}
+
+static void
+gedit_message_bus_init (GeditMessageBus *self)
+{
+ self->priv = GEDIT_MESSAGE_BUS_GET_PRIVATE (self);
+
+ self->priv->messages = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)message_free);
+
+ self->priv->idmap = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify)g_free);
+
+ self->priv->policies = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)policy_free);
+}
+
+GeditMessageBus *
+gedit_message_bus_get_default (void)
+{
+ static GeditMessageBus *default_bus = NULL;
+
+ if (G_UNLIKELY (default_bus == NULL))
+ {
+ default_bus = g_object_new (GEDIT_TYPE_MESSAGE_BUS, NULL);
+ g_object_add_weak_pointer (G_OBJECT (default_bus),
+ (gpointer) &default_bus);
+ }
+
+ return default_bus;
+}
+
+void
+gedit_message_bus_register (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ guint num_optional,
+ ...)
+{
+ gchar *identifier;
+ gpointer data;
+ Policy *policy;
+ va_list var_args;
+ const gchar *key;
+ GList *item;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ identifier = msg_identifier (domain, name);
+ data = g_hash_table_lookup (bus->priv->policies, identifier);
+
+ if (data != NULL)
+ {
+ /* policy is already registered */
+ g_free (identifier);
+ return;
+ }
+
+ policy = g_new(Policy, 1);
+ policy->domain = g_strdup (domain);
+ policy->name = g_strdup (name);
+ policy->policies = NULL;
+
+ /* construct policy items */
+ va_start (var_args, num_optional);
+
+ /* read in required items */
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ GType gtype;
+ PolicyItem *pitem;
+
+ gtype = va_arg (var_args, GType);
+
+ if (!_gedit_message_gtype_supported (gtype))
+ {
+ g_warning ("Type `%s' is not supported on the message bus",
+ g_type_name (gtype));
+ continue;
+ }
+
+ pitem = g_new(PolicyItem, 1);
+ pitem->key = g_strdup (key);
+ pitem->type = gtype;
+
+ policy->policies = g_list_prepend (policy->policies, pitem);
+ }
+
+ for (item = policy->policies; num_optional-- > 0 && item; item = item->next)
+ ((PolicyItem *)item->data)->required = FALSE;
+
+ policy->policies = g_list_reverse (policy->policies);
+ g_hash_table_insert (bus->priv->policies, identifier, policy);
+}
+
+void
+gedit_message_bus_unregister (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name)
+{
+ gchar *identifier;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ identifier = msg_identifier (domain, name);
+ g_hash_table_remove (bus->priv->policies, name);
+ g_free (identifier);
+}
+
+void
+gedit_message_bus_unregister_all (GeditMessageBus *bus,
+ const gchar *domain)
+{
+ GList *pols;
+ GList *item;
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ pols = g_hash_table_get_values (bus->priv->policies);
+
+ for (item = pols; item; item = item->next)
+ {
+ Policy *policy = (Policy *)item->data;
+
+ if (strcmp (policy->domain, domain) == 0)
+ {
+ gchar *identifier = msg_identifier (policy->domain, policy->name);
+ g_hash_table_remove (bus->priv->policies, identifier);
+ g_free (identifier);
+ }
+ }
+
+ g_list_free (pols);
+}
+
+guint
+gedit_message_bus_connect (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ GDestroyNotify destroy_data)
+{
+ Message *message;
+
+ g_return_val_if_fail (GEDIT_IS_MESSAGE_BUS (bus), 0);
+ g_return_val_if_fail (domain != NULL, 0);
+ g_return_val_if_fail (name != NULL, 0);
+ g_return_val_if_fail (callback != NULL, 0);
+
+ /* lookup the message and create if it does not exist yet */
+ message = lookup_message (bus, domain, name, TRUE);
+
+ return add_listener (bus, message, callback, userdata, destroy_data);
+}
+
+void
+gedit_message_bus_disconnect (GeditMessageBus *bus,
+ guint id)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_id (bus, id, remove_listener);
+}
+
+void
+gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_match (bus, domain, name, callback, userdata, remove_listener);
+}
+
+void
+gedit_message_bus_block (GeditMessageBus *bus,
+ guint id)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_id (bus, id, block_listener);
+}
+
+void
+gedit_message_bus_block_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_match (bus, domain, name, callback, userdata, block_listener);
+}
+
+void
+gedit_message_bus_unblock (GeditMessageBus *bus,
+ guint id)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_id (bus, id, unblock_listener);
+}
+
+void
+gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+
+ process_by_match (bus, domain, name, callback, userdata, unblock_listener);
+}
+
+static gboolean
+check_message_policy (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ const gchar *domain = gedit_message_get_domain (message);
+ const gchar *name = gedit_message_get_name (message);
+
+ gchar *identifier = msg_identifier (domain, name);
+ Policy *policy = (Policy *)g_hash_table_lookup (bus->priv->policies, identifier);
+ PolicyItem *pitem;
+ GList *item;
+
+ g_free (identifier);
+
+ if (policy == NULL)
+ {
+ g_warning ("Policy for '%s::%s' could not be found", domain, name);
+ return FALSE;
+ }
+
+ /* check all required and optional arguments */
+ for (item = policy->policies; item; item = item->next)
+ {
+ GType gtype;
+ gboolean haskey;
+
+ pitem = (PolicyItem *)item->data;
+
+ /* check if key exists */
+ haskey = gedit_message_has_key (message, pitem->key);
+
+ if (pitem->required && !haskey)
+ {
+ g_warning ("Required key %s not found for %s::%s", pitem->key, domain, name);
+ return FALSE;
+ }
+ else if (!haskey && !pitem->required)
+ {
+ continue;
+ }
+
+ gtype = gedit_message_get_key_type (message, pitem->key);
+
+ if (!g_type_is_a (pitem->type, gtype) &&
+ !g_value_type_transformable (pitem->type, gtype))
+ {
+ g_warning ("Invalid key type for %s::%s, expected %s, got %s", domain, name, g_type_name (pitem->type), g_type_name (gtype));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void
+gedit_message_bus_send_message (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ if (!check_message_policy (bus, message))
+ return;
+
+ bus->priv->message_queue = g_list_prepend (bus->priv->message_queue,
+ g_object_ref (message));
+
+ if (bus->priv->idle_id == 0)
+ bus->priv->idle_id = g_idle_add_full (G_PRIORITY_HIGH,
+ (GSourceFunc)idle_dispatch,
+ bus,
+ NULL);
+}
+
+void
+gedit_message_bus_send_message_sync (GeditMessageBus *bus,
+ GeditMessage *message)
+{
+ g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ if (!check_message_policy (bus, message))
+ return;
+
+ dispatch_message (bus, message);
+}
+
+static GType
+policy_find_type (Policy *policy,
+ const gchar *key)
+{
+ GList *item;
+
+ for (item = policy->policies; item; item = item->next)
+ {
+ PolicyItem *pitem = (PolicyItem *)item->data;
+
+ if (strcmp (pitem->key, key) == 0)
+ return pitem->type;
+ }
+
+ return 0;
+}
+
+static GeditMessage *
+create_message (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ va_list var_args)
+{
+ const gchar **keys = NULL;
+ GType *types = NULL;
+ GValue *values = NULL;
+ gint num = 0;
+ const gchar *key;
+ gchar *identifier;
+ GeditMessage *message;
+ Policy *policy;
+ gint i;
+
+ identifier = msg_identifier (domain, name);
+ policy = g_hash_table_lookup (bus->priv->policies, identifier);
+ g_free (identifier);
+
+ if (policy == NULL)
+ {
+ g_warning ("Policy for %s::%s not found", domain, name);
+ return NULL;
+ }
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ gchar *error = NULL;
+ GType gtype;
+ GValue value = {0,};
+
+ gtype = policy_find_type (policy, key);
+
+ if (!gtype)
+ {
+ g_warning ("Key %s not registered in policy for %s::%s", key, domain, name);
+ return NULL;
+ }
+
+ g_value_init (&value, gtype);
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* leak value, might have gone bad */
+ continue;
+ }
+
+ num++;
+
+ keys = g_realloc (keys, sizeof(gchar *) * num);
+ types = g_realloc (types, sizeof(GType) * num);
+ values = g_realloc (values, sizeof(GValue) * num);
+
+ keys[num - 1] = key;
+ types[num - 1] = gtype;
+
+ memset (&values[num - 1], 0, sizeof(GValue));
+ g_value_init (&values[num - 1], types[num - 1]);
+ g_value_copy (&value, &values[num - 1]);
+
+ g_value_unset (&value);
+ }
+
+ message = gedit_message_new (domain, name, NULL);
+ gedit_message_set_types (message, keys, types, num);
+ gedit_message_set_valuesv (message, keys, values, num);
+
+ g_free (keys);
+ g_free (types);
+
+ for (i = 0; i < num; i++)
+ g_value_unset (&values[i]);
+
+ g_free (values);
+
+ return message;
+}
+
+void
+gedit_message_bus_send (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...)
+{
+ va_list var_args;
+ GeditMessage *message;
+
+ va_start (var_args, name);
+
+ message = create_message (bus, domain, name, var_args);
+
+ if (message)
+ {
+ gedit_message_bus_send_message (bus, message);
+ g_object_unref (message);
+ }
+
+ va_end (var_args);
+}
+
+GeditMessage *
+gedit_message_bus_send_sync (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...)
+{
+ va_list var_args;
+ GeditMessage *message;
+
+ va_start (var_args, name);
+ message = create_message (bus, domain, name, var_args);
+
+ if (message)
+ gedit_message_bus_send_message_sync (bus, message);
+
+ va_end (var_args);
+
+ return message;
+}
+
+typedef struct
+{
+ gchar *domain;
+ gchar *name;
+ GeditMessageBus *bus;
+} PropertyProxy;
+
+static void
+property_proxy_message (GObject *object,
+ GParamSpec *spec,
+ PropertyProxy *proxy)
+{
+ GeditMessage *message;
+ GValue value = {0,};
+
+ message = gedit_message_new (proxy->domain,
+ proxy->name,
+ spec->name, spec->value_type,
+ NULL);
+
+ g_value_init (&value, spec->value_type);
+ g_object_get_property (object, spec->name, &value);
+ gedit_message_set_value (message, spec->name, &value);
+
+ gedit_message_bus_send_message (proxy->bus, message);
+
+ g_object_unref (message);
+ g_value_unset (&value);
+}
+
+static PropertyProxy *
+property_proxy_new (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name)
+{
+ PropertyProxy *proxy;
+
+ proxy = g_new (PropertyProxy, 1);
+ proxy->domain = g_strdup (domain);
+ proxy->name = g_strdup (name);
+ proxy->bus = bus;
+
+ return proxy;
+}
+
+static void
+property_proxy_free (PropertyProxy *proxy,
+ GClosure *closure)
+{
+ g_free (proxy->domain);
+ g_free (proxy->name);
+ g_free (proxy);
+}
+
+void
+gedit_message_bus_proxy_property (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GObject *object,
+ const gchar *property)
+{
+ GParamSpec *spec;
+ gchar *detailed;
+
+ spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
+ property);
+
+ if (!spec)
+ {
+ g_warning ("Could not connect proxy because property `%s' does not exist for %s",
+ property,
+ g_type_name (G_OBJECT_TYPE (object)));
+ return;
+ }
+
+ if (!_gedit_message_gtype_supported (spec->value_type))
+ {
+ g_warning ("Type of property `%s' is not supported on the message bus",
+ g_type_name (spec->value_type));
+ return;
+ }
+
+ detailed = g_strconcat ("notify::", property, NULL);
+ g_signal_connect_data (object,
+ detailed,
+ G_CALLBACK (property_proxy_message),
+ property_proxy_new (bus, domain, name),
+ (GClosureNotify)property_proxy_free,
+ 0);
+ g_free (detailed);
+}
Added: branches/message_system/gedit/gedit-message-bus.h
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-message-bus.h Wed Nov 26 16:45:01 2008
@@ -0,0 +1,115 @@
+#ifndef __GEDIT_MESSAGE_BUS_H__
+#define __GEDIT_MESSAGE_BUS_H__
+
+#include <glib-object.h>
+#include <gedit/gedit-message.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_MESSAGE_BUS (gedit_message_bus_get_type ())
+#define GEDIT_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBus))
+#define GEDIT_MESSAGE_BUS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBus const))
+#define GEDIT_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusClass))
+#define GEDIT_IS_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MESSAGE_BUS))
+#define GEDIT_IS_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE_BUS))
+#define GEDIT_MESSAGE_BUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE_BUS, GeditMessageBusClass))
+
+typedef struct _GeditMessageBus GeditMessageBus;
+typedef struct _GeditMessageBusClass GeditMessageBusClass;
+typedef struct _GeditMessageBusPrivate GeditMessageBusPrivate;
+
+struct _GeditMessageBus {
+ GObject parent;
+
+ GeditMessageBusPrivate *priv;
+};
+
+struct _GeditMessageBusClass {
+ GObjectClass parent_class;
+
+ void (*dispatch) (GeditMessageBus *bus,
+ GeditMessage *message);
+};
+
+typedef void (* GeditMessageCallback) (GeditMessageBus *bus,
+ GeditMessage *message,
+ gpointer userdata);
+
+GType gedit_message_bus_get_type (void) G_GNUC_CONST;
+
+GeditMessageBus *gedit_message_bus_get_default (void);
+
+/* registering messages */
+void gedit_message_bus_register (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ guint num_optional,
+ ...) G_GNUC_NULL_TERMINATED;
+
+void gedit_message_bus_unregister (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name);
+
+void gedit_message_bus_unregister_all (GeditMessageBus *bus,
+ const gchar *domain);
+
+/* connecting to message events */
+guint gedit_message_bus_connect (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata,
+ GDestroyNotify destroy_data);
+
+void gedit_message_bus_disconnect (GeditMessageBus *bus,
+ guint id);
+
+void gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata);
+
+/* blocking message event callbacks */
+void gedit_message_bus_block (GeditMessageBus *bus,
+ guint id);
+void gedit_message_bus_block_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata);
+
+void gedit_message_bus_unblock (GeditMessageBus *bus,
+ guint id);
+void gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GeditMessageCallback callback,
+ gpointer userdata);
+
+/* sending messages */
+void gedit_message_bus_send_message (GeditMessageBus *bus,
+ GeditMessage *message);
+
+void gedit_message_bus_send_message_sync (GeditMessageBus *bus,
+ GeditMessage *message);
+
+void gedit_message_bus_send (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...) G_GNUC_NULL_TERMINATED;
+GeditMessage *gedit_message_bus_send_sync (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ ...) G_GNUC_NULL_TERMINATED;
+
+/* automatic property proxy over the bus */
+void gedit_message_bus_proxy_property (GeditMessageBus *bus,
+ const gchar *domain,
+ const gchar *name,
+ GObject *object,
+ const gchar *property);
+
+G_END_DECLS
+
+#endif /* __GEDIT_MESSAGE_BUS_H__ */
Added: branches/message_system/gedit/gedit-message.c
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-message.c Wed Nov 26 16:45:01 2008
@@ -0,0 +1,578 @@
+#include "gedit-message.h"
+
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+
+#define GEDIT_MESSAGE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_MESSAGE, GeditMessagePrivate))
+
+enum {
+ PROP_0,
+
+ PROP_DOMAIN,
+ PROP_NAME
+};
+
+struct _GeditMessagePrivate
+{
+ gchar *domain;
+ gchar *name;
+
+ GHashTable *values;
+};
+
+G_DEFINE_TYPE (GeditMessage, gedit_message, G_TYPE_OBJECT)
+
+static void
+gedit_message_finalize (GObject *object)
+{
+ GeditMessage *message = GEDIT_MESSAGE (object);
+
+ g_free (message->priv->domain);
+ g_free (message->priv->name);
+
+ g_hash_table_destroy (message->priv->values);
+
+ G_OBJECT_CLASS (gedit_message_parent_class)->finalize (object);
+}
+
+static void
+gedit_message_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMessage *msg = GEDIT_MESSAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DOMAIN:
+ g_value_set_string (value, msg->priv->domain);
+ break;
+ case PROP_NAME:
+ g_value_set_string (value, msg->priv->name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_message_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditMessage *msg = GEDIT_MESSAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DOMAIN:
+ msg->priv->domain = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_NAME:
+ msg->priv->name = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_message_class_init (GeditMessageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->finalize = gedit_message_finalize;
+ object_class->get_property = gedit_message_get_property;
+ object_class->set_property = gedit_message_set_property;
+
+ g_object_class_install_property (object_class, PROP_DOMAIN,
+ g_param_spec_string ("domain",
+ "DOMAIN",
+ "The message domain",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_NAME,
+ g_param_spec_string ("name",
+ "NAME",
+ "The message name",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof(GeditMessagePrivate));
+}
+
+static void
+destroy_value (GValue *value)
+{
+ g_value_unset (value);
+ g_free (value);
+}
+
+static void
+gedit_message_init (GeditMessage *self)
+{
+ self->priv = GEDIT_MESSAGE_GET_PRIVATE (self);
+
+ self->priv->values = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)destroy_value);
+}
+
+gboolean
+_gedit_message_gtype_supported (GType type)
+{
+ gint i = 0;
+
+ static const GType type_list[] =
+ {
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_INT,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ G_TYPE_INT64,
+ G_TYPE_UINT64,
+ G_TYPE_ENUM,
+ G_TYPE_FLAGS,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_POINTER,
+ G_TYPE_BOXED,
+ G_TYPE_OBJECT,
+ G_TYPE_INVALID
+ };
+
+ if (!G_TYPE_IS_VALUE_TYPE (type))
+ return FALSE;
+
+ while (type_list[i] != G_TYPE_INVALID)
+ {
+ if (g_type_is_a (type, type_list[i]))
+ return TRUE;
+ i++;
+ }
+
+ return FALSE;
+}
+
+static void
+add_value (GeditMessage *message,
+ const gchar *key,
+ GType gtype)
+{
+ GValue *value;
+
+ value = g_new0 (GValue, 1);
+ g_value_init (value, gtype);
+ g_value_reset (value);
+
+ g_hash_table_insert (message->priv->values, g_strdup (key), value);
+}
+
+static gboolean
+set_value_real (GValue *to,
+ const GValue *from)
+{
+ GType from_type;
+ GType to_type;
+
+ from_type = G_VALUE_TYPE (from);
+ to_type = G_VALUE_TYPE (to);
+
+ if (!g_type_is_a (from_type, to_type))
+ {
+ if (!g_value_transform (from, to))
+ {
+ g_warning ("%s: Unable to make conversion from %s to %s",
+ G_STRLOC,
+ g_type_name (from_type),
+ g_type_name (to_type));
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ g_value_copy (from, to);
+ return TRUE;
+}
+
+inline static GValue *
+value_lookup (GeditMessage *message,
+ const gchar *key)
+{
+ return (GValue *)g_hash_table_lookup (message->priv->values, key);
+}
+
+GeditMessage*
+gedit_message_new (const gchar *domain,
+ const gchar *name,
+ ...)
+{
+ va_list var_args;
+ GeditMessage *message;
+
+ va_start (var_args, name);
+ message = gedit_message_new_valist (domain, name, var_args);
+ va_end (var_args);
+
+ return message;
+}
+
+GeditMessage *
+gedit_message_new_valist (const gchar *domain,
+ const gchar *name,
+ va_list var_args)
+{
+ GeditMessage *message;
+ const gchar *key;
+ GArray *keys;
+ GArray *types;
+
+ message = g_object_new (GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
+
+ keys = g_array_new (FALSE, FALSE, sizeof (const gchar *));
+ types = g_array_new (FALSE, FALSE, sizeof (GType));
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ /* get corresponding GType */
+ GType gtype = va_arg (var_args, GType);
+
+ g_array_append_val (keys, key);
+ g_array_append_val (types, gtype);
+ }
+
+ gedit_message_set_types (message,
+ (const gchar **)keys->data,
+ (GType *)types->data,
+ keys->len);
+
+ g_array_free (keys, TRUE);
+ g_array_free (types, TRUE);
+
+ return message;
+}
+
+GeditMessage *
+gedit_message_new_hash (const gchar *domain,
+ const gchar *name,
+ GHashTable *values)
+{
+ GeditMessage *message;
+ const gchar *key;
+ GList *keys;
+ GList *item;
+ GValue *value;
+
+ message = g_object_new (GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
+ keys = g_hash_table_get_keys (values);
+
+ for (item = keys; item; item = item->next)
+ {
+ key = (const gchar *)(item->data);
+ value = g_hash_table_lookup (values, key);
+
+ if (value == NULL)
+ continue;
+
+ if (!_gedit_message_gtype_supported (G_VALUE_TYPE (value)))
+ {
+ g_warning ("GType %s is not supported, ignoring key %s",
+ g_type_name (G_VALUE_TYPE (value)),
+ key);
+ continue;
+ }
+
+ add_value (message, key, G_VALUE_TYPE (value));
+ gedit_message_set_value (message, key, value);
+ }
+
+ g_list_free (keys);
+
+ return message;
+}
+
+void
+gedit_message_set_types (GeditMessage *message,
+ const gchar **keys,
+ GType *types,
+ gint n_types)
+{
+ gint i;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ g_hash_table_ref (message->priv->values);
+ g_hash_table_destroy (message->priv->values);
+
+ for (i = 0; i < n_types; i++)
+ {
+ if (!_gedit_message_gtype_supported (types[i]))
+ {
+ g_warning ("GType %s is not supported, ignoring key %s", g_type_name (types[i]), keys[i]);
+ continue;
+ }
+
+ add_value (message, keys[i], types[i]);
+ }
+}
+
+const gchar *
+gedit_message_get_name (GeditMessage *message)
+{
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
+
+ return message->priv->name;
+}
+
+const gchar *
+gedit_message_get_domain (GeditMessage *message)
+{
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
+
+ return message->priv->domain;
+}
+
+void
+gedit_message_set (GeditMessage *message,
+ ...)
+{
+ va_list ap;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ va_start (ap, message);
+ gedit_message_set_valist (message, ap);
+ va_end (ap);
+}
+
+void
+gedit_message_set_valist (GeditMessage *message,
+ va_list var_args)
+{
+ const gchar *key;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ /* lookup the key */
+ GValue *container = value_lookup (message, key);
+ GValue value = {0,};
+ gchar *error = NULL;
+
+ if (!container)
+ {
+ g_warning ("%s: Cannot set value for %s, does not exist",
+ G_STRLOC,
+ key);
+
+ /* skip value */
+ va_arg (var_args, gpointer);
+ continue;
+ }
+
+ g_value_init (&value, G_VALUE_TYPE (container));
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ continue;
+ }
+
+ set_value_real (container, &value);
+ g_value_unset (&value);
+ }
+}
+
+void
+gedit_message_set_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value)
+{
+ GValue *container;
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Cannot set value for %s, does not exist",
+ G_STRLOC,
+ key);
+ return;
+ }
+
+ set_value_real (container, value);
+}
+
+void
+gedit_message_set_valuesv (GeditMessage *message,
+ const gchar **keys,
+ GValue *values,
+ gint n_values)
+{
+ gint i;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ for (i = 0; i < n_values; i++)
+ {
+ gedit_message_set_value (message, keys[i], &values[i]);
+ }
+}
+
+void
+gedit_message_get (GeditMessage *message,
+ ...)
+{
+ va_list ap;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ va_start (ap, message);
+ gedit_message_get_valist (message, ap);
+ va_end (ap);
+}
+
+void
+gedit_message_get_valist (GeditMessage *message,
+ va_list var_args)
+{
+ const gchar *key;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ while ((key = va_arg (var_args, const gchar *)) != NULL)
+ {
+ GValue *container;
+ GValue copy = {0,};
+ gchar *error = NULL;
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ /* skip value */
+ va_arg (var_args, gpointer);
+ continue;
+ }
+
+ /* copy the value here, to be sure it isn't tainted */
+ g_value_init (©, G_VALUE_TYPE (container));
+ g_value_copy (container, ©);
+
+ G_VALUE_LCOPY (©, var_args, 0, &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* purposely leak the value here, because it might
+ be in a bad state */
+ continue;
+ }
+
+ g_value_unset (©);
+ }
+}
+
+void
+gedit_message_get_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value)
+{
+ GValue *container;
+
+ g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Invalid key `%s'",
+ G_STRLOC,
+ key);
+ return;
+ }
+
+ g_value_init (value, G_VALUE_TYPE (container));
+ set_value_real (value, container);
+}
+
+GType
+gedit_message_get_key_type (GeditMessage *message,
+ const gchar *key)
+{
+ GValue *container;
+
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), 0);
+
+ container = value_lookup (message, key);
+
+ if (!container)
+ {
+ g_warning ("%s: Invalid key `%s'",
+ G_STRLOC,
+ key);
+ return 0;
+ }
+
+ return G_VALUE_TYPE (container);
+}
+
+GStrv
+gedit_message_get_keys (GeditMessage *message)
+{
+ GList *keys;
+ GList *item;
+ GStrv result;
+ gint i = 0;
+
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
+
+ result = g_new0 (gchar *, g_hash_table_size (message->priv->values) + 1);
+
+ keys = g_hash_table_get_keys (message->priv->values);
+
+ for (item = keys; item; item = item->next)
+ result[i++] = g_strdup ((gchar *)(item->data));
+
+ g_list_free (keys);
+ return result;
+}
+
+GHashTable *
+gedit_message_get_hash (GeditMessage *message)
+{
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
+ return message->priv->values;
+}
+
+gboolean
+gedit_message_has_key (GeditMessage *message,
+ const gchar *key)
+{
+ GValue *container;
+
+ g_return_val_if_fail (GEDIT_IS_MESSAGE (message), FALSE);
+
+ container = value_lookup (message, key);
+
+ return container != NULL;
+}
Added: branches/message_system/gedit/gedit-message.h
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-message.h Wed Nov 26 16:45:01 2008
@@ -0,0 +1,83 @@
+#ifndef __GEDIT_MESSAGE_H__
+#define __GEDIT_MESSAGE_H__
+
+#include <glib-object.h>
+#include <stdarg.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_MESSAGE (gedit_message_get_type ())
+#define GEDIT_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE, GeditMessage))
+#define GEDIT_MESSAGE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_MESSAGE, GeditMessage const))
+#define GEDIT_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_MESSAGE, GeditMessageClass))
+#define GEDIT_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_MESSAGE))
+#define GEDIT_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE))
+#define GEDIT_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE, GeditMessageClass))
+
+typedef struct _GeditMessage GeditMessage;
+typedef struct _GeditMessageClass GeditMessageClass;
+typedef struct _GeditMessagePrivate GeditMessagePrivate;
+
+struct _GeditMessage {
+ GObject parent;
+
+ GeditMessagePrivate *priv;
+};
+
+struct _GeditMessageClass {
+ GObjectClass parent_class;
+};
+
+GType gedit_message_get_type (void) G_GNUC_CONST;
+
+GeditMessage *gedit_message_new (const gchar *domain,
+ const gchar *name,
+ ...) G_GNUC_NULL_TERMINATED;
+GeditMessage *gedit_message_new_valist (const gchar *domain,
+ const gchar *name,
+ va_list var_args);
+GeditMessage *gedit_message_new_hash (const gchar *domain,
+ const gchar *name,
+ GHashTable *values);
+
+void gedit_message_set_types (GeditMessage *message,
+ const gchar **keys,
+ GType *types,
+ gint n_types);
+
+const gchar *gedit_message_get_domain (GeditMessage *message);
+const gchar *gedit_message_get_name (GeditMessage *message);
+
+void gedit_message_get (GeditMessage *message,
+ ...) G_GNUC_NULL_TERMINATED;
+void gedit_message_get_valist (GeditMessage *message,
+ va_list var_args);
+void gedit_message_get_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value);
+
+void gedit_message_set (GeditMessage *message,
+ ...) G_GNUC_NULL_TERMINATED;
+void gedit_message_set_valist (GeditMessage *message,
+ va_list var_args);
+void gedit_message_set_value (GeditMessage *message,
+ const gchar *key,
+ GValue *value);
+void gedit_message_set_valuesv (GeditMessage *message,
+ const gchar **keys,
+ GValue *values,
+ gint n_values);
+
+gboolean gedit_message_has_key (GeditMessage *message,
+ const gchar *key);
+
+GStrv gedit_message_get_keys (GeditMessage *message);
+GType gedit_message_get_key_type (GeditMessage *message,
+ const gchar *key);
+
+GHashTable *gedit_message_get_hash (GeditMessage *message);
+gboolean _gedit_message_gtype_supported (GType type);
+
+G_END_DECLS
+
+#endif /* __GEDIT_MESSAGE_H__ */
Modified: branches/message_system/gedit/gedit.c
==============================================================================
--- branches/message_system/gedit/gedit.c (original)
+++ branches/message_system/gedit/gedit.c Wed Nov 26 16:45:01 2008
@@ -520,6 +520,9 @@
g_warning ("Cannot create the 'gedit' connection.");
}
+ /* register message bus commands */
+ //_gedit_commands_messages_register ();
+
gedit_debug_message (DEBUG_APP, "Set icon");
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
Modified: branches/message_system/plugin-loaders/python/bindings/Makefile.am
==============================================================================
--- branches/message_system/plugin-loaders/python/bindings/Makefile.am (original)
+++ branches/message_system/plugin-loaders/python/bindings/Makefile.am Wed Nov 26 16:45:01 2008
@@ -33,7 +33,7 @@
$(top_builddir)/gedit/gedit-enum-types.h:
cd $(top_builddir)/gedit && $(MAKE) gedit-enum-types.h
-gedit.c: gedit.defs gedit.override geditplugin.override $(top_builddir)/gedit/gedit-enum-types.h
+gedit.c: gedit.defs gedit.override geditplugin.override geditmessage.override $(top_builddir)/gedit/gedit-enum-types.h
( cd $(srcdir) && $(PYGTK_CODEGEN) \
--register $(PYGTK_DEFSDIR)/pango-types.defs \
--register $(PYGTK_DEFSDIR)/gdk-types.defs \
Modified: branches/message_system/plugin-loaders/python/bindings/gedit.defs
==============================================================================
--- branches/message_system/plugin-loaders/python/bindings/gedit.defs (original)
+++ branches/message_system/plugin-loaders/python/bindings/gedit.defs Wed Nov 26 16:45:01 2008
@@ -14,6 +14,20 @@
(gtype-id "GEDIT_TYPE_DOCUMENT")
)
+(define-object Message
+ (in-module "Gedit")
+ (parent "GObject")
+ (c-name "GeditMessage")
+ (gtype-id "GEDIT_TYPE_MESSAGE")
+)
+
+(define-object MessageBus
+ (in-module "Gedit")
+ (parent "GObject")
+ (c-name "GeditMessageBus")
+ (gtype-id "GEDIT_TYPE_MESSAGE_BUS")
+)
+
(define-object Panel
(in-module "Gedit")
(parent "GtkVBox")
@@ -991,6 +1005,271 @@
)
)
+
+;; From gedit-message-bus.h
+
+(define-function gedit_message_bus_get_type
+ (c-name "gedit_message_bus_get_type")
+ (return-type "GType")
+)
+
+(define-function message_bus_get_default
+ (c-name "gedit_message_bus_get_default")
+ (return-type "GeditMessageBus*")
+)
+
+(define-method connect
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_connect")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method disconnect
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_disconnect")
+ (return-type "none")
+ (parameters
+ '("guint" "id")
+ )
+)
+
+(define-method disconnect_by_func
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_disconnect_by_func")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method block
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_block")
+ (return-type "none")
+ (parameters
+ '("guint" "id")
+ )
+)
+
+(define-method block_by_func
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_block_by_func")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method unblock
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_unblock")
+ (return-type "none")
+ (parameters
+ '("guint" "id")
+ )
+)
+
+(define-method unblock_by_func
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_unblock_by_func")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("GeditMessageCallback" "callback")
+ '("gpointer" "userdata")
+ )
+)
+
+(define-method send_message
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send_message")
+ (return-type "none")
+ (parameters
+ '("GeditMessage*" "message")
+ )
+)
+
+(define-method send_message_sync
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send_message_sync")
+ (return-type "none")
+ (parameters
+ '("GeditMessage*" "message")
+ )
+)
+
+(define-method send
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ )
+ (varargs #t)
+)
+
+(define-method send_sync
+ (of-object "GeditMessageBus")
+ (c-name "gedit_message_bus_send_sync")
+ (return-type "GeditMessage*")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ )
+ (varargs #t)
+)
+
+
+
+;; From gedit-message.h
+
+(define-function gedit_message_get_type
+ (c-name "gedit_message_get_type")
+ (return-type "GType")
+)
+
+(define-function gedit_message_new
+ (c-name "gedit_message_new")
+ (is-constructor-of "GeditMessage")
+ (return-type "GeditMessage*")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ )
+ (varargs #t)
+)
+
+(define-function gedit_message_new_valist
+ (c-name "gedit_message_new_valist")
+ (return-type "GeditMessage*")
+ (parameters
+ '("const-gchar*" "domain")
+ '("const-gchar*" "name")
+ '("va_list" "var_args")
+ )
+)
+
+(define-method set_types
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_types")
+ (return-type "none")
+ (parameters
+ '("const-gchar**" "keys")
+ '("GType*" "types")
+ '("gint" "n_types")
+ )
+)
+
+(define-method get_domain
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_domain")
+ (return-type "const-gchar*")
+)
+
+(define-method get_name
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_name")
+ (return-type "const-gchar*")
+)
+
+(define-method get
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get")
+ (return-type "none")
+ (parameters
+ )
+ (varargs #t)
+)
+
+(define-method get_valist
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_valist")
+ (return-type "none")
+ (parameters
+ '("va_list" "var_args")
+ )
+)
+
+(define-method get_value
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_value")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "key")
+ '("GValue*" "value")
+ )
+)
+
+(define-method set
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set")
+ (return-type "none")
+ (parameters
+ )
+ (varargs #t)
+)
+
+(define-method set_valist
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_valist")
+ (return-type "none")
+ (parameters
+ '("va_list" "var_args")
+ )
+)
+
+(define-method set_value
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_value")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "key")
+ '("GValue*" "value")
+ )
+)
+
+(define-method set_valuesv
+ (of-object "GeditMessage")
+ (c-name "gedit_message_set_valuesv")
+ (return-type "none")
+ (parameters
+ '("const-gchar**" "keys")
+ '("GValue*" "values")
+ '("gint" "n_values")
+ )
+)
+
+(define-method has_key
+ (of-object "GeditMessage")
+ (c-name "gedit_message_has_key")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "key")
+ )
+)
+
+(define-method get_keys
+ (of-object "GeditMessage")
+ (c-name "gedit_message_get_keys")
+ (return-type "gchar**")
+ (parameters
+ )
+)
+
;; From ../../gedit/gedit-debug.h
(define-function debug
Modified: branches/message_system/plugin-loaders/python/bindings/gedit.override
==============================================================================
--- branches/message_system/plugin-loaders/python/bindings/gedit.override (original)
+++ branches/message_system/plugin-loaders/python/bindings/gedit.override Wed Nov 26 16:45:01 2008
@@ -61,6 +61,7 @@
}
%%
include
+ geditmessage.override
geditplugin.override
%%
modulename gedit
Added: branches/message_system/plugin-loaders/python/bindings/geditmessage.override
==============================================================================
--- (empty file)
+++ branches/message_system/plugin-loaders/python/bindings/geditmessage.override Wed Nov 26 16:45:01 2008
@@ -0,0 +1,544 @@
+%%
+headers
+
+#include <gedit/gedit-message-bus.h>
+#include <gedit/gedit-message.h>
+
+static GType
+_helper_wrap_get_gtype_from_pytype (PyObject *pytype)
+{
+ PyTypeObject *type = (PyTypeObject *)pytype;
+
+ if (type == &PyList_Type || type == &PyTuple_Type)
+ return G_TYPE_STRV;
+
+ return pyg_type_from_object (pytype);
+}
+
+static gchar *
+_helper_wrap_get_string (PyObject *obj)
+{
+ PyObject *str;
+ gchar *result;
+
+ str = PyObject_Str (obj);
+
+ if (!str)
+ return NULL;
+
+ result = g_strdup (PyString_AsString (str));
+ Py_DECREF (str);
+
+ return result;
+}
+
+static int
+_helper_wrap_message_types(PyObject *args, gchar ***keys, GType **types, gint *num, gboolean direct)
+{
+ guint len, i;
+ Py_ssize_t pos;
+
+ len = PyTuple_Size(args);
+
+ if (len == 1 && PyDict_Check(PyTuple_GetItem(args, 0)))
+ {
+ /* get key -> gtype from mapping */
+ PyObject *dict = PyTuple_GetItem(args, 0);
+ PyObject *key;
+ PyObject *value;
+
+ *num = PyDict_Size(dict);
+ *types = g_new0(GType, *num);
+ *keys = g_new0(gchar *, *num + 1);
+ pos = 0;
+ i = 0;
+
+ while (PyDict_Next(dict, &pos, &key, &value)) {
+ (*keys)[i] = _helper_wrap_get_string (key);
+
+ if (direct) {
+ (*types)[i] = _helper_wrap_get_gtype_from_pytype(value);
+ } else {
+ (*types)[i] = _helper_wrap_get_gtype_from_pytype((PyObject *)value->ob_type);
+ }
+
+ if ((*types)[i] == 0 || (*keys)[i] == NULL) {
+ g_free(*types);
+ g_strfreev(*keys);
+ return 0;
+ }
+
+ i++;
+ }
+ }
+ else
+ {
+ if (len % 2 != 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "Even number of arguments expected (name/type pairs)");
+ return 0;
+ }
+
+ *num = len / 2;
+ *types = g_new(GType, *num);
+ *keys = g_new0(gchar *, *num + 1);
+
+ for (i = 0; i < *num; i++) {
+ PyObject *key = PyTuple_GetItem(args, i * 2);
+ PyObject *value = PyTuple_GetItem(args, i * 2 + 1);
+
+ (*keys)[i] = _helper_wrap_get_string (key);
+
+ if (direct) {
+ (*types)[i] = _helper_wrap_get_gtype_from_pytype(value);
+ } else {
+ (*types)[i] = _helper_wrap_get_gtype_from_pytype((PyObject *)value->ob_type);
+ }
+
+ if ((*types)[i] == 0 || (*keys)[i] == NULL) {
+ g_free(*types);
+ g_strfreev(*keys);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+_helper_wrap_list_to_gvalue (GValue *gvalue, PyObject *pyvalue)
+{
+ int num;
+ gchar **lst;
+ gint i;
+
+ num = PySequence_Size (pyvalue);
+ lst = g_new0 (gchar *, num + 1);
+
+ for (i = 0; i < num; i++)
+ {
+ lst[i] = _helper_wrap_get_string (PySequence_GetItem (pyvalue, i));
+
+ if (lst[i] == NULL)
+ {
+ g_strfreev (lst);
+ return 1;
+ }
+ }
+
+ g_value_set_boxed (gvalue, lst);
+ g_strfreev (lst);
+
+ return 0;
+}
+
+static int
+_helper_wrap_get_gvalue_from_pyobject (GValue *gvalue, PyObject *pyvalue)
+{
+ if (pyvalue->ob_type == &PyList_Type || pyvalue->ob_type == &PyTuple_Type)
+ return _helper_wrap_list_to_gvalue (gvalue, pyvalue);
+
+ return pyg_value_from_pyobject(gvalue, pyvalue);
+}
+
+static int
+_helper_wrap_message_set_value(GeditMessage *message, PyObject *pykey, PyObject *pyvalue)
+{
+ gchar *key;
+ GType gtype;
+ GValue value = {0,};
+
+ key = _helper_wrap_get_string(pykey);
+
+ if (key == NULL)
+ return 0;
+
+ gtype = gedit_message_get_key_type(message, key);
+
+ if (gtype == 0) {
+ PyErr_SetString(PyExc_TypeError, "invalid key");
+ g_free (key);
+ return 0;
+ }
+
+ g_value_init(&value, gtype);
+
+ if (_helper_wrap_get_gvalue_from_pyobject (&value, pyvalue)) {
+ PyErr_SetString(PyExc_TypeError,
+ "value is of the wrong type for this key");
+ g_free (key);
+ return 0;
+ }
+
+ gedit_message_set_value(message, key, &value);
+ g_value_unset(&value);
+ g_free (key);
+
+ return 1;
+}
+
+static int
+_helper_wrap_message_set_values(GeditMessage *message, PyObject *args)
+{
+ guint len;
+ Py_ssize_t i;
+
+ len = PyTuple_Size(args);
+
+ if (len == 1 && PyDict_Check(PyTuple_GetItem(args, 0)))
+ {
+ /* do key -> value from mapping */
+ PyObject *dict = PyTuple_GetItem(args, 0);
+ PyObject *pykey, *pyvalue;
+
+ i = 0;
+
+ while (PyDict_Next(dict, &i, &pykey, &pyvalue)) {
+ if (!_helper_wrap_message_set_value(message, pykey, pyvalue))
+ return 0;
+ }
+ } else {
+ if (len % 2 != 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "Even number of arguments expected (name/type pairs)");
+ return 0;
+ }
+
+ for (i = 0; i < len / 2; i++) {
+ PyObject *pykey = PyTuple_GetItem(args, i * 2);
+ PyObject *pyvalue = PyTuple_GetItem(args, i * 2 + 1);
+
+ if (!_helper_wrap_message_set_value(message, pykey, pyvalue))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static GeditMessage *
+_helper_wrap_create_message(PyObject *args)
+{
+ guint len;
+ gint num;
+ gchar *domain;
+ gchar *name;
+ GType *types;
+ gchar **keys;
+ PyObject *slice;
+ GeditMessage *message;
+
+ len = PyTuple_Size(args);
+
+ if (len < 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "GeditMessage requires at least two arguments");
+ return NULL;
+ }
+
+ domain = _helper_wrap_get_string(PyTuple_GetItem(args, 0));
+ name = _helper_wrap_get_string(PyTuple_GetItem(args, 1));
+
+ if (!domain || !name) {
+ PyErr_SetString(PyExc_TypeError,
+ "First two arguments need to be strings");
+ g_free (domain);
+ g_free (name);
+ return NULL;
+ }
+
+ slice = PyTuple_GetSlice (args, 2, len);
+
+ if (!_helper_wrap_message_types (slice, &keys, &types, &num, FALSE)) {
+ Py_DECREF(slice);
+ return NULL;
+ }
+
+ message = g_object_new(GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
+ gedit_message_set_types (message, (const gchar **)keys, types, num);
+
+ g_free(types);
+ g_strfreev(keys);
+ g_free (name);
+ g_free (domain);
+
+ _helper_wrap_message_set_values(message, slice);
+ Py_DECREF(slice);
+
+ return message;
+}
+
+typedef struct {
+ PyObject *func;
+ PyObject *data;
+} PyGeditCustomNotify;
+
+static void
+pygedit_custom_destroy_notify(gpointer user_data)
+{
+ PyGeditCustomNotify *cunote = user_data;
+ PyGILState_STATE state;
+
+ g_return_if_fail(user_data);
+ state = pyg_gil_state_ensure();
+ Py_XDECREF(cunote->func);
+ Py_XDECREF(cunote->data);
+ pyg_gil_state_release(state);
+
+ g_free(cunote);
+}
+%%
+ignore-glob
+ *_get_type
+ gedit_message_new_valist
+ gedit_message_get_valist
+ gedit_message_set_valist
+ gedit_message_set_valuesv
+ gedit_message_bus_disconnect_by_func
+ gedit_message_bus_block_by_func
+ gedit_message_bus_unblock_by_func
+%%
+override gedit_message_new
+static int
+_wrap_gedit_message_new(PyGObject *self, PyObject *args)
+{
+ self->obj = (GObject *)_helper_wrap_create_message(args);
+
+ if (!self->obj) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "could not create GeditMessage object");
+ return -1;
+ }
+ pygobject_register_wrapper((PyObject *)self);
+
+ return 0;
+}
+%%
+override gedit_message_set_types args
+static PyObject *
+_wrap_gedit_message_set_types(PyGObject *self, PyObject *args)
+{
+ gint num;
+ GType *types;
+ gchar **keys;
+
+ if (!_helper_wrap_message_types (args, &keys, &types, &num, TRUE)) {
+ return NULL;
+ }
+
+ gedit_message_set_types (GEDIT_MESSAGE(self->obj), (const gchar **)keys, types, num);
+
+ g_free(types);
+ g_strfreev(keys);
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_get args
+static PyObject *
+_wrap_gedit_message_get(PyGObject *self, PyObject *args)
+{
+ guint len, i;
+ PyObject *ret;
+
+ len = PyTuple_Size(args);
+
+ ret = PyTuple_New(len);
+
+ for (i = 0; i < len; i++) {
+ GValue value = { 0, };
+ PyObject *py_key = PyTuple_GetItem(args, i);
+ const gchar *key;
+
+ if (!PyString_Check(py_key)) {
+ PyErr_SetString(PyExc_TypeError, "keys must be strings");
+ Py_DECREF(ret);
+ return NULL;
+ }
+
+ key = PyString_AsString(py_key);
+ gedit_message_get_value (GEDIT_MESSAGE (self->obj), key, &value);
+
+ PyTuple_SetItem(ret, i, pyg_value_as_pyobject(&value, TRUE));
+ g_value_unset(&value);
+ }
+
+ return ret;
+}
+%%
+override gedit_message_get_value kwargs
+static PyObject *
+_wrap_gedit_message_get_value(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "key", NULL };
+ const gchar *key;
+ PyObject *ret;
+ GValue value = { 0, };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:GeditMessage.get_value", kwlist, &key))
+ return NULL;
+
+ gedit_message_get_value(GEDIT_MESSAGE(self->obj), key, &value);
+ ret = pyg_value_as_pyobject(&value, TRUE);
+ g_value_unset(&value);
+
+ return ret;
+}
+%%
+override gedit_message_set_value kwargs
+static PyObject *
+_wrap_gedit_message_set_value(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "key", "value", NULL };
+ PyObject *ret, *pykey, *pyvalue;
+ GValue value = { 0, };
+ GType gtype;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO:GeditMessage.set_value", kwlist, &pykey, &pyvalue))
+ return NULL;
+
+ if (!_helper_wrap_message_set_value(GEDIT_MESSAGE(self->obj), pykey, pyvalue))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_set args
+static PyObject *
+_wrap_gedit_message_set (PyGObject *self, PyObject *args) {
+ if (!_helper_wrap_message_set_values(GEDIT_MESSAGE(self->obj), args))
+ return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_get_keys args
+static PyObject *
+_wrap_gedit_message_get_keys (PyGObject *self, PyObject *args) {
+ PyObject *py_list;
+ gchar **keys;
+ gchar **ptr;
+
+ if ((py_list = PyList_New(0)) == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ keys = gedit_message_get_keys (GEDIT_MESSAGE (self->obj));
+ ptr = keys;
+
+ if (!keys)
+ return py_list;
+
+ while (*ptr)
+ PyList_Append(py_list, PyString_FromString (*ptr));
+
+ g_strfreev (keys);
+ return py_list;
+}
+
+%%
+override gedit_message_bus_connect kwargs
+static void
+pygedit_message_bus_connect_cb(GeditMessageBus *bus, GeditMessage *message, gpointer data)
+{
+ PyGILState_STATE state;
+ PyGeditCustomNotify *cunote = data;
+ PyObject *pybus, *pymessage, *retobj;
+ gboolean ret = FALSE;
+
+ g_assert(cunote->func);
+
+ state = pyg_gil_state_ensure();
+
+ pybus = pygobject_new((GObject *)bus);
+ pymessage = pygobject_new((GObject *)message);
+
+ if (cunote->data) {
+ retobj = PyEval_CallFunction(cunote->func, "(NNO)", pybus, pymessage, cunote->data);
+ } else {
+ retobj = PyEval_CallFunction(cunote->func, "(NN)", pybus, pymessage);
+ }
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ }
+
+ Py_XDECREF(retobj);
+
+ pyg_gil_state_release(state);
+}
+
+static PyObject *
+_wrap_gedit_message_bus_connect(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "domain", "name", "func", "data", NULL };
+ PyObject *pyfunc, *pyarg = NULL;
+ const gchar *domain;
+ const gchar *name;
+ PyGeditCustomNotify *cunote;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "ssO|O:GeditMessageBus.connect",
+ kwlist, &domain, &name, &pyfunc, &pyarg))
+ return NULL;
+
+ if (!PyCallable_Check(pyfunc)) {
+ PyErr_SetString(PyExc_TypeError, "func must be a callable object");
+ return NULL;
+ }
+ cunote = g_new(PyGeditCustomNotify, 1);
+ Py_INCREF(pyfunc);
+ cunote->func = pyfunc;
+ Py_XINCREF(pyarg);
+ cunote->data = pyarg;
+
+ gedit_message_bus_connect(GEDIT_MESSAGE_BUS(self->obj),
+ domain,
+ name,
+ pygedit_message_bus_connect_cb,
+ (gpointer)cunote,
+ pygedit_custom_destroy_notify);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_bus_send args
+static PyObject *
+_wrap_gedit_message_bus_send (PyGObject *self, PyObject *args)
+{
+ /* create a new message object */
+ GeditMessage *message;
+
+ message = _helper_wrap_create_message(args);
+
+ if (!message)
+ return NULL;
+
+ gedit_message_bus_send_message(GEDIT_MESSAGE_BUS(self->obj), message);
+ g_object_unref (message);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
+override gedit_message_bus_send_sync args
+static PyObject *
+_wrap_gedit_message_bus_send_sync (PyGObject *self, PyObject *args)
+{
+ /* create a new message object */
+ GeditMessage *message;
+
+ message = _helper_wrap_create_message(args);
+
+ if (!message)
+ return NULL;
+
+ gedit_message_bus_send_message_sync(GEDIT_MESSAGE_BUS(self->obj), message);
+ return pygobject_new((GObject *)message);
+}
+%%
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]