Commit 04698e71 authored by Jesse van den Kieboom's avatar Jesse van den Kieboom

Implemented new bindable message bus

parent 71feff66
......@@ -294,6 +294,27 @@ fi
AM_CONDITIONAL(ENABLE_ZEITGEIST, test x"$enable_zeitgeist" = "xyes")
PYGOBJECT_REQUIRED=2.28
AC_ARG_ENABLE([python],
AS_HELP_STRING([--enable-python[=@<:@no/auto/yes@:>@]],[Build with python support]),
[enable_python=$enableval],
[enable_python="auto"])
if test "x$enable_python" = "xauto"; then
PKG_CHECK_EXISTS([pygobject-2.0 >= $PYGOBJECT_REQUIRED],
[enable_python=yes],[enable_python=no])
fi
if test "x$enable_python" = "xyes"; then
PKG_CHECK_MODULES(PYTHON, [pygobject-2.0 >= $PYGOBJECT_REQUIRED])
pyoverridesdir=`$PKG_CONFIG --variable=overridesdir pygobject-2.0`
AC_SUBST(pyoverridesdir)
fi
AM_CONDITIONAL(ENABLE_PYTHON, test x"$enable_python" = "xyes")
dnl ================================================================
dnl Start of pkg-config checks
dnl ================================================================
......@@ -488,6 +509,7 @@ Configuration:
GObject Introspection: $enable_introspection
GDK Backend: $gdk_windowing
Zeitgeist support: $enable_zeitgeist
Python support: $enable_python
"
if expr ${GEDIT_MINOR_VERSION} % 2 > /dev/null; then
......
from gi.repository import GObject
from ..overrides import override
from ..importer import modules
Gedit = modules['Gedit']._introspection_module
__all__ = []
class MessageBus(Gedit.MessageBus):
def create(self, object_path, method, **kwargs):
tp = self.lookup(object_path, method)
if not tp.is_a(Gedit.Message.__gtype__):
return None
kwargs['object-path'] = object_path
kwargs['method'] = method
return GObject.new(tp, **kwargs)
def send_sync(self, object_path, method, **kwargs):
msg = self.create(object_path, method, **kwargs)
self.send_message_sync(msg)
return msg
def send(self, object_path, method, **kwargs):
msg = self.create(object_path, method, **kwargs)
self.send_message(msg)
return msg
MessageBus = override(MessageBus)
__all__.append('MessageBus')
class Message(Gedit.Message):
def __getattribute__(self, name):
try:
return Gedit.Message.__getattribute__(self, name)
except:
return getattr(self.props, name)
Message = override(Message)
__all__.append('Message')
# vi:ex:ts=4:et
......@@ -145,7 +145,6 @@ INST_H_FILES = \
gedit-encodings.h \
gedit-encodings-combo-box.h \
gedit-message-bus.h \
gedit-message-type.h \
gedit-message.h \
gedit-panel.h \
gedit-progress-info-bar.h \
......@@ -202,7 +201,6 @@ libgedit_c_files = \
gedit-io-error-info-bar.c \
gedit-language-manager.c \
gedit-message-bus.c \
gedit-message-type.c \
gedit-message.c \
gedit-multi-notebook.c \
gedit-notebook.c \
......@@ -264,6 +262,12 @@ ui_DATA = \
gedit-ui.xml \
gedit-print-preferences.ui
if ENABLE_PYTHON
overridesdir = $(pyoverridesdir)
overrides_DATA = \
Gedit.py
endif
EXTRA_DIST = \
$(ui_DATA) \
gedit-enum-types.h.template \
......
......@@ -15,3 +15,4 @@ VOID:VOID
VOID:INT,INT
VOID:OBJECT,OBJECT,INT
OBJECT:OBJECT,OBJECT,INT,INT
VOID:STRING,STRING
This diff is collapsed.
......@@ -25,7 +25,6 @@
#include <glib-object.h>
#include <gedit/gedit-message.h>
#include <gedit/gedit-message-type.h>
G_BEGIN_DECLS
......@@ -44,107 +43,109 @@ typedef struct _GeditMessageBusPrivate GeditMessageBusPrivate;
struct _GeditMessageBus
{
GObject parent;
GeditMessageBusPrivate *priv;
};
struct _GeditMessageBusClass
{
GObjectClass parent_class;
void (*dispatch) (GeditMessageBus *bus,
GeditMessage *message);
void (*registered) (GeditMessageBus *bus,
GeditMessageType *message_type);
void (*unregistered) (GeditMessageBus *bus,
GeditMessageType *message_type);
void (*dispatch) (GeditMessageBus *bus,
GeditMessage *message);
void (*registered) (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
void (*unregistered) (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
};
typedef void (* GeditMessageCallback) (GeditMessageBus *bus,
GeditMessage *message,
gpointer user_data);
typedef void (* GeditMessageBusForeach) (GeditMessageType *message_type,
gpointer user_data);
GType gedit_message_bus_get_type (void) G_GNUC_CONST;
GeditMessageBus *gedit_message_bus_get_default (void);
GeditMessageBus *gedit_message_bus_new (void);
/* registering messages */
GeditMessageType *gedit_message_bus_lookup (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
GeditMessageType *gedit_message_bus_register (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
guint num_optional,
...) G_GNUC_NULL_TERMINATED;
void gedit_message_bus_unregister (GeditMessageBus *bus,
GeditMessageType *message_type);
void gedit_message_bus_unregister_all (GeditMessageBus *bus,
const gchar *object_path);
gboolean gedit_message_bus_is_registered (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
void gedit_message_bus_foreach (GeditMessageBus *bus,
GeditMessageBusForeach func,
gpointer user_data);
/* connecting to message events */
guint gedit_message_bus_connect (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data,
GDestroyNotify destroy_data);
void gedit_message_bus_disconnect (GeditMessageBus *bus,
guint id);
void gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data);
/* blocking message event callbacks */
void gedit_message_bus_block (GeditMessageBus *bus,
guint id);
void gedit_message_bus_block_by_func (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data);
void gedit_message_bus_unblock (GeditMessageBus *bus,
guint id);
void gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data);
/* 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 *object_path,
const gchar *method,
...) G_GNUC_NULL_TERMINATED;
GeditMessage *gedit_message_bus_send_sync (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
...) G_GNUC_NULL_TERMINATED;
typedef void (* GeditMessageCallback) (GeditMessageBus *bus,
GeditMessage *message,
gpointer user_data);
typedef void (* GeditMessageBusForeach) (gchar const *object_path,
gchar const *method,
gpointer user_data);
GType gedit_message_bus_get_type (void) G_GNUC_CONST;
GeditMessageBus *gedit_message_bus_get_default (void);
GeditMessageBus *gedit_message_bus_new (void);
GType gedit_message_bus_lookup (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
void gedit_message_bus_register (GeditMessageBus *bus,
GType message_type,
const gchar *object_path,
const gchar *method);
void gedit_message_bus_unregister (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
void gedit_message_bus_unregister_all (GeditMessageBus *bus,
const gchar *object_path);
gboolean gedit_message_bus_is_registered (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
void gedit_message_bus_foreach (GeditMessageBus *bus,
GeditMessageBusForeach func,
gpointer user_data);
guint gedit_message_bus_connect (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data,
GDestroyNotify destroy_data);
void gedit_message_bus_disconnect (GeditMessageBus *bus,
guint id);
void gedit_message_bus_disconnect_by_func (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data);
void gedit_message_bus_block (GeditMessageBus *bus,
guint id);
void gedit_message_bus_block_by_func (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data);
void gedit_message_bus_unblock (GeditMessageBus *bus,
guint id);
void gedit_message_bus_unblock_by_func (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
GeditMessageCallback callback,
gpointer user_data);
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 *object_path,
const gchar *method,
const gchar *first_property,
...) G_GNUC_NULL_TERMINATED;
GeditMessage *gedit_message_bus_send_sync (GeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
const gchar *first_property,
...) G_GNUC_NULL_TERMINATED;
G_END_DECLS
......
/*
* gedit-message-type.c
* This file is part of gedit
*
* Copyright (C) 2008-2010 - Jesse van den Kieboom
*
* gedit 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.
*
* gedit 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 gedit; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include "gedit-message-type.h"
/**
* SECTION:gedit-message-type
* @short_description: message type description
* @include: gedit/gedit-message-type.h
*
* A message type is a prototype description for a #GeditMessage used to
* transmit messages on a #GeditMessageBus. The message type describes
* the Object Path, Method and Arguments of the message.
*
* A message type can contain any number of required and optional arguments.
* To instantiate a #GeditMessage from a #GeditMessageType, use
* gedit_message_type_instantiate().
*
* Registering a new message type on a #GeditMessageBus with
* gedit_message_bus_register() internally creates a new #GeditMessageType. When
* then using gedit_message_bus_send(), an actual instantiation of the
* registered type is internally created and send over the bus.
*
* <example>
* <programlisting>
* // Defining a new message type
* GeditMessageType *message_type = gedit_message_type_new ("/plugins/example",
* "method",
* 0,
* "arg1", G_TYPE_STRING,
* NULL);
*
* // Instantiating an actual message from the type
* GeditMessage *message = gedit_message_type_instantiate (message_type,
* "arg1", "Hello World",
* NULL);
* </programlisting>
* </example>
*
* Since: 2.25.3
*
*/
typedef struct
{
GType type;
gboolean required;
} ArgumentInfo;
struct _GeditMessageType
{
/* FIXME this is an issue for introspection */
gint ref_count;
gchar *object_path;
gchar *method;
guint num_arguments;
guint num_required;
GHashTable *arguments; /* mapping of key -> ArgumentInfo */
};
G_DEFINE_BOXED_TYPE (GeditMessageType, gedit_message_type,
gedit_message_type_ref,
gedit_message_type_unref)
/**
* gedit_message_type_ref:
* @message_type: the #GeditMessageType
*
* Increases the reference count on @message_type.
*
* Return value: @message_type
*
*/
GeditMessageType *
gedit_message_type_ref (GeditMessageType *message_type)
{
g_return_val_if_fail (message_type != NULL, NULL);
g_atomic_int_inc (&message_type->ref_count);
return message_type;
}
/**
* gedit_message_type_unref:
* @message_type: the #GeditMessageType
*
* Decreases the reference count on @message_type. When the reference count
* drops to 0, @message_type is destroyed.
*
*/
void
gedit_message_type_unref (GeditMessageType *message_type)
{
g_return_if_fail (message_type != NULL);
if (!g_atomic_int_dec_and_test (&message_type->ref_count))
return;
g_free (message_type->object_path);
g_free (message_type->method);
g_hash_table_destroy (message_type->arguments);
g_free (message_type);
}
/**
* gedit_message_type_identifier:
* @object_path: (allow-none): the object path
* @method: (allow-none): the method
*
* Get the string identifier for @method at @object_path.
*
* Return value: the identifier for @method at @object_path
*
*/
gchar *
gedit_message_type_identifier (const gchar *object_path,
const gchar *method)
{
return g_strconcat (object_path, ".", method, NULL);
}
/**
* gedit_message_type_is_valid_object_path:
* @object_path: (allow-none): the object path
*
* Returns whether @object_path is a valid object path
*
* Return value: %TRUE if @object_path is a valid object path
*
*/
gboolean
gedit_message_type_is_valid_object_path (const gchar *object_path)
{
if (!object_path)
return FALSE;
/* needs to start with / */
if (*object_path != '/')
return FALSE;
while (*object_path)
{
if (*object_path == '/')
{
++object_path;
if (!*object_path || !(g_ascii_isalpha (*object_path) || *object_path == '_'))
return FALSE;
}
else if (!(g_ascii_isalnum (*object_path) || *object_path == '_'))
{
return FALSE;
}
++object_path;
}
return TRUE;
}
/**
* gedit_message_type_is_supported:
* @type: the #GType
*
* Returns if @type is #GType supported by the message system.
*
* Return value: %TRUE if @type is a supported #GType
*
*/
gboolean
gedit_message_type_is_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;
}
/**
* gedit_message_type_new_valist:
* @object_path: (allow-none): the object path
* @method: (allow-none): the method
* @num_optional: number of optional arguments
* @var_args: key/gtype pair variable argument list
*
* Create a new #GeditMessageType for @method at @object_path. Argument names
* and values are supplied by the %NULL terminated variable argument list.
* The last @num_optional provided arguments are considered optional.
*
* Return value: the newly constructed #GeditMessageType
*
*/
GeditMessageType *
gedit_message_type_new_valist (const gchar *object_path,
const gchar *method,
guint num_optional,
va_list var_args)
{
GeditMessageType *message_type;
g_return_val_if_fail (object_path != NULL, NULL);
g_return_val_if_fail (method != NULL, NULL);
g_return_val_if_fail (gedit_message_type_is_valid_object_path (object_path), NULL);
message_type = g_new0 (GeditMessageType, 1);
message_type->ref_count = 1;
message_type->object_path = g_strdup (object_path);
message_type->method = g_strdup (method);
message_type->num_arguments = 0;
message_type->arguments = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_free);
gedit_message_type_set_valist (message_type, num_optional, var_args);
return message_type;
}
/**
* gedit_message_type_new:
* @object_path: (allow-none): the object path
* @method: (allow-none): the method
* @num_optional: number of optional arguments
* @...: key/gtype pair variable argument list
*
* Create a new #GeditMessageType for @method at @object_path. Argument names
* and values are supplied by the %NULL terminated variable argument list.
* The last @num_optional provided arguments are considered optional.
*
* Return value: the newly constructed #GeditMessageType
*
*/
GeditMessageType *
gedit_message_type_new (const gchar *object_path,
const gchar *method,
guint num_optional,
...)
{
GeditMessageType *message_type;
va_list var_args;
va_start (var_args, num_optional);
message_type = gedit_message_type_new_valist (object_path, method, num_optional, var_args);
va_end (var_args);
return message_type;
}
/**
* gedit_message_type_set:
* @message_type: the #GeditMessageType
* @num_optional: number of optional arguments
* @...: key/gtype pair variable argument list
*
* Sets argument names/types supplied by the %NULL terminated variable
* argument list. The last @num_optional provided arguments are considered
* optional.
*
*/
void
gedit_message_type_set (GeditMessageType *message_type,
guint num_optional,
...)
{
va_list va_args;
va_start (va_args, num_optional);
gedit_message_type_set_valist (message_type, num_optional, va_args);
va_end (va_args);
}
/**
* gedit_message_type_set_valist:
* @message_type: the #GeditMessageType
* @num_optional: number of optional arguments
* @var_args: key/gtype pair variable argument list
*
* Sets argument names/types supplied by the %NULL terminated variable
* argument list @var_args. The last @num_optional provided arguments are
* considered optional.
*
*/
void
gedit_message_type_set_valist (GeditMessageType *message_type,
guint num_optional,
va_list var_args)
{
const gchar *key;
ArgumentInfo **optional = g_new0( ArgumentInfo *, num_optional);
guint i;
guint added = 0;
g_return_if_fail (message_type != NULL);
/* parse key -> gtype pair arguments */
while ((key = va_arg (var_args, const gchar *)) != NULL)
{
/* get corresponding GType */
GType gtype = va_arg (var_args, GType);
ArgumentInfo *info;
if (!gedit_message_type_is_supported (gtype))
{
g_error ("Message type '%s' is not supported", g_type_name (gtype));
gedit_message_type_unref (message_type);
g_free (optional);
return;
}
info = g_new(ArgumentInfo, 1);
info->type = gtype;
info->required = TRUE;
g_hash_table_insert (message_type->arguments, g_strdup (key), info);
++message_type->num_arguments;
++added;
if (num_optional > 0)
{
for (i = num_optional - 1; i > 0; --i)
optional[i] = optional[i - 1];
*optional = info;
}
}
message_type->num_required += added;
/* set required for last num_optional arguments */
for (i = 0; i < num_optional; ++i)
{
if (optional[i])
{
optional[i]->required = FALSE;
--message_type->num_required;
}
}