[libgda/LIBGDA_4.2] Support out of tree UI plugins creation
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda/LIBGDA_4.2] Support out of tree UI plugins creation
- Date: Fri, 15 Jul 2011 14:37:55 +0000 (UTC)
commit c8573746d755bbef005027390e45ec4a75d0b59a
Author: Vivien Malerba <malerba gnome-db org>
Date: Fri Jul 15 16:17:06 2011 +0200
Support out of tree UI plugins creation
Makefile.am | 8 +-
libgda-ui-4.0.pc.in | 1 +
libgda-ui/data-entries/Makefile.am | 6 +-
samples/CustomUIPlugin/Makefile | 29 +++
samples/CustomUIPlugin/README | 26 +++
samples/CustomUIPlugin/custom-entry-password.c | 230 ++++++++++++++++++++++
samples/CustomUIPlugin/custom-entry-password.h | 38 ++++
samples/CustomUIPlugin/custom-entry-password.xml | 6 +
samples/CustomUIPlugin/libmain.c | 58 ++++++
samples/Makefile | 2 +-
10 files changed, 399 insertions(+), 5 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index cf26163..44ee905 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -99,7 +99,13 @@ example_files = \
samples/Blobs/testblob.db \
samples/LdapBrowser/Makefile \
samples/LdapBrowser/README \
- samples/LdapBrowser/ldap-browser.c
+ samples/LdapBrowser/ldap-browser.c \
+ samples/CustomUIPlugin/Makefile \
+ samples/CustomUIPlugin/README \
+ samples/CustomUIPlugin/custom-entry-password.c \
+ samples/CustomUIPlugin/custom-entry-password.h \
+ samples/CustomUIPlugin/custom-entry-password.xml \
+ samples/CustomUIPlugin/libmain.c
EXTRA_DIST = \
COPYING \
diff --git a/libgda-ui-4.0.pc.in b/libgda-ui-4.0.pc.in
index bfdcf31..2ede6c7 100644
--- a/libgda-ui-4.0.pc.in
+++ b/libgda-ui-4.0.pc.in
@@ -2,6 +2,7 @@ prefix= prefix@
exec_prefix= exec_prefix@
libdir= libdir@
includedir= includedir@
+pluginsdir= libdir@/libgda-4.0/plugins
Name: libgda- GDA_ABI_MAJOR_VERSION@ GDA_ABI_MINOR_VERSION@
Description: GDA (GNOME Data Access) library, UI extension
diff --git a/libgda-ui/data-entries/Makefile.am b/libgda-ui/data-entries/Makefile.am
index 58cbb3a..a82c7d4 100644
--- a/libgda-ui/data-entries/Makefile.am
+++ b/libgda-ui/data-entries/Makefile.am
@@ -17,7 +17,9 @@ AM_CPPFLAGS = \
gdauiincludedir=$(includedir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/libgda-ui
gdauiinclude_HEADERS= $(extra_headers)
extra_headers = \
- gdaui-data-cell-renderer-util.h
+ gdaui-data-cell-renderer-util.h \
+ gdaui-entry-shell.h \
+ gdaui-entry-wrapper.h
libgda_ui_data_entries_headers = \
gdaui-data-cell-renderer-bin.h \
@@ -29,14 +31,12 @@ libgda_ui_data_entries_headers = \
gdaui-entry-boolean.h \
gdaui-entry-combo.h \
gdaui-entry-none.h \
- gdaui-entry-shell.h \
gdaui-entry-string.h \
gdaui-entry-number.h \
gdaui-entry-common-time.h \
gdaui-entry-time.h \
gdaui-entry-timestamp.h \
gdaui-entry-date.h \
- gdaui-entry-wrapper.h \
gdaui-entry.h \
gdaui-formatted-entry.h \
gdaui-numeric-entry.h
diff --git a/samples/CustomUIPlugin/Makefile b/samples/CustomUIPlugin/Makefile
new file mode 100644
index 0000000..d6e0b44
--- /dev/null
+++ b/samples/CustomUIPlugin/Makefile
@@ -0,0 +1,29 @@
+CFLAGS = -Wall -g -DGDA_DISABLE_DEPRECATED `pkg-config --cflags libgda-ui-4.0`
+LDFLAGS = `pkg-config --libs libgda-ui-4.0`
+PLUGINSDIR = `pkg-config --variable=pluginsdir libgda-ui-4.0`
+
+all: custom-plugin.so
+
+custom-plugin.so: libmain.o custom-entry-password.o
+
+libmain.o: libmain.c
+ $(CC) -fPIC -rdynamic $(CFLAGS) -c -o libmain.o libmain.c
+
+custom-entry-password.o: custom-entry-password.c custom-entry-password.h
+ $(CC) -fPIC -rdynamic $(CFLAGS) -c -o custom-entry-password.o custom-entry-password.c
+
+custom-plugin.so: libmain.o custom-entry-password.o
+ $(CC) -shared -Wl,-soname,custom-plugin.so -o custom-plugin.so libmain.o custom-entry-password.o
+
+install: custom-plugin.so custom-entry-password.xml
+ cp custom-plugin.so $(PLUGINSDIR)/
+ cp custom-entry-password.xml $(PLUGINSDIR)/
+
+uninstall:
+ rm $(PLUGINSDIR)/custom-plugin.so
+ rm $(PLUGINSDIR)/custom-entry-password.xml
+
+clean:
+ rm -f *~
+ rm -f *.o
+ rm -f *.so
diff --git a/samples/CustomUIPlugin/README b/samples/CustomUIPlugin/README
new file mode 100644
index 0000000..bb1536f
--- /dev/null
+++ b/samples/CustomUIPlugin/README
@@ -0,0 +1,26 @@
+LibgdaUI simple custom plugin
+=============================
+
+Description:
+------------
+
+The example in this directory illustrate how to create a simple custom data entry plugin.
+
+The custom data entry is a password entry which replaces any entered character with a
+generic '*' character and allows one to set the minimum length.
+
+The compilation creates a "custom-plugin.so" file. This file, along with the XML file containing
+the plugin options need to be copied to LibgdaUI's plugins directory, which can be queried
+using the pkg-config program as:
+> pkg-config --variable=pluginsdir libgda-ui-4.0
+
+Compiling and running:
+----------------------
+
+To compile (make sure Libgdaui is installed prior to this):
+> make
+> make install
+
+The plugin will now automatically be loaded at runtime and useable.
+
+> make uninstall
diff --git a/samples/CustomUIPlugin/custom-entry-password.c b/samples/CustomUIPlugin/custom-entry-password.c
new file mode 100644
index 0000000..7d44ca5
--- /dev/null
+++ b/samples/CustomUIPlugin/custom-entry-password.c
@@ -0,0 +1,230 @@
+#include "custom-entry-password.h"
+#include <libgda/gda-data-handler.h>
+#include <string.h>
+
+/*
+ * Main static functions
+ */
+static void custom_entry_password_class_init (CustomEntryPasswordClass * class);
+static void custom_entry_password_init (CustomEntryPassword * srv);
+static void custom_entry_password_finalize (GObject * object);
+
+/* virtual functions */
+static GtkWidget *create_entry (GdauiEntryWrapper *mgwrap);
+static void real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value);
+static GValue *real_get_value (GdauiEntryWrapper *mgwrap);
+static void connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb);
+static gboolean can_expand (GdauiEntryWrapper *mgwrap, gboolean horiz);
+
+
+/* get a pointer to the parents to be able to call their destructor */
+static GObjectClass *parent_class = NULL;
+
+/* private structure */
+struct _CustomEntryPasswordPrivate
+{
+ GtkWidget *entry;
+ guint minlength; /* 0 for no limit */
+};
+
+GType
+custom_entry_password_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo info = {
+ sizeof (CustomEntryPasswordClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) custom_entry_password_class_init,
+ NULL,
+ NULL,
+ sizeof (CustomEntryPassword),
+ 0,
+ (GInstanceInitFunc) custom_entry_password_init,
+ 0
+ };
+
+ type = g_type_register_static (GDAUI_TYPE_ENTRY_WRAPPER, "CustomEntryPassword", &info, 0);
+ }
+ return type;
+}
+
+static void
+custom_entry_password_class_init (CustomEntryPasswordClass * class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = custom_entry_password_finalize;
+
+ GDAUI_ENTRY_WRAPPER_CLASS (class)->create_entry = create_entry;
+ GDAUI_ENTRY_WRAPPER_CLASS (class)->real_set_value = real_set_value;
+ GDAUI_ENTRY_WRAPPER_CLASS (class)->real_get_value = real_get_value;
+ GDAUI_ENTRY_WRAPPER_CLASS (class)->connect_signals = connect_signals;
+ GDAUI_ENTRY_WRAPPER_CLASS (class)->can_expand = can_expand;
+}
+
+static void
+custom_entry_password_init (CustomEntryPassword * custom_entry_password)
+{
+ custom_entry_password->priv = g_new0 (CustomEntryPasswordPrivate, 1);
+ custom_entry_password->priv->entry = NULL;
+ custom_entry_password->priv->minlength = 0;
+}
+
+/*
+ * custom_entry_password_new:
+ * @dh: the data handler to be used by the new widget
+ * @type: the requested data type (compatible with @dh)
+ *
+ * Creates a new widget which is mainly a GtkEntry
+ *
+ * Returns: the new widget
+ */
+GtkWidget *
+custom_entry_password_new (GdaDataHandler *dh, GType type, const gchar *options)
+{
+ GObject *obj;
+ CustomEntryPassword *mgtxt;
+
+ g_return_val_if_fail (dh && GDA_IS_DATA_HANDLER (dh), NULL);
+ g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
+ g_return_val_if_fail (gda_data_handler_accepts_g_type (dh, type), NULL);
+
+ obj = g_object_new (CUSTOM_ENTRY_PASSWORD_TYPE, "handler", dh, NULL);
+ mgtxt = CUSTOM_ENTRY_PASSWORD (obj);
+ gdaui_data_entry_set_value_type (GDAUI_DATA_ENTRY (mgtxt), type);
+
+ if (options && *options) {
+ GdaQuarkList *params;
+ const gchar *str;
+
+ params = gda_quark_list_new_from_string (options);
+ str = gda_quark_list_find (params, "MINLENGTH");
+ if (str) {
+ mgtxt->priv->minlength = atoi (str);
+ if (mgtxt->priv->minlength < 0)
+ mgtxt->priv->minlength = 0;
+ }
+ gda_quark_list_free (params);
+ }
+
+ return GTK_WIDGET (obj);
+}
+
+static void
+custom_entry_password_finalize (GObject * object)
+{
+ CustomEntryPassword *custom_entry_password;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_CUSTOM_ENTRY_PASSWORD (object));
+
+ custom_entry_password = CUSTOM_ENTRY_PASSWORD (object);
+ if (custom_entry_password->priv) {
+ g_free (custom_entry_password->priv);
+ custom_entry_password->priv = NULL;
+ }
+
+ /* parent class */
+ parent_class->finalize (object);
+}
+
+static GtkWidget *
+create_entry (GdauiEntryWrapper *mgwrap)
+{
+ GtkWidget *entry;
+ CustomEntryPassword *mgstr;
+
+ g_return_val_if_fail (mgwrap && IS_CUSTOM_ENTRY_PASSWORD (mgwrap), NULL);
+ mgstr = CUSTOM_ENTRY_PASSWORD (mgwrap);
+ g_return_val_if_fail (mgstr->priv, NULL);
+
+ entry = gtk_entry_new ();
+ mgstr->priv->entry = entry;
+ gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
+
+ return entry;
+}
+
+static void
+real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
+{
+ CustomEntryPassword *mgstr;
+
+ g_return_if_fail (mgwrap && IS_CUSTOM_ENTRY_PASSWORD (mgwrap));
+ mgstr = CUSTOM_ENTRY_PASSWORD (mgwrap);
+ g_return_if_fail (mgstr->priv);
+
+ if (value) {
+ if (gda_value_is_null ((GValue *) value))
+ gtk_entry_set_text (GTK_ENTRY (mgstr->priv->entry), "");
+ else {
+ GdaDataHandler *dh;
+ gchar *str;
+
+ dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
+ str = gda_data_handler_get_str_from_value (dh, value);
+ gtk_entry_set_text (GTK_ENTRY (mgstr->priv->entry), str);
+ g_free (str);
+ }
+ }
+ else
+ gtk_entry_set_text (GTK_ENTRY (mgstr->priv->entry), "");
+}
+
+static GValue *
+real_get_value (GdauiEntryWrapper *mgwrap)
+{
+ GValue *value = NULL;
+ CustomEntryPassword *mgstr;
+ GdaDataHandler *dh;
+ const gchar *str;
+ GType type;
+
+ g_return_val_if_fail (mgwrap && IS_CUSTOM_ENTRY_PASSWORD (mgwrap), NULL);
+ mgstr = CUSTOM_ENTRY_PASSWORD (mgwrap);
+ g_return_val_if_fail (mgstr->priv, NULL);
+
+ dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
+ str = gtk_entry_get_text (GTK_ENTRY (mgstr->priv->entry));
+ type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgwrap));
+
+ if (*str) {
+ if (((mgstr->priv->minlength > 0) && (strlen (str) >= mgstr->priv->minlength)) ||
+ (mgstr->priv->minlength == 0))
+ value = gda_data_handler_get_value_from_str (dh, str, type);
+ }
+
+ if (!value) {
+ /* in case the gda_data_handler_get_value_from_str() returned an error because
+ the contents of the GtkEntry cannot be interpreted as a GValue */
+ value = gda_value_new_null ();
+ }
+
+ return value;
+}
+
+static void
+connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb)
+{
+ CustomEntryPassword *mgstr;
+
+ g_return_if_fail (mgwrap && IS_CUSTOM_ENTRY_PASSWORD (mgwrap));
+ mgstr = CUSTOM_ENTRY_PASSWORD (mgwrap);
+ g_return_if_fail (mgstr->priv);
+
+ g_signal_connect (G_OBJECT (mgstr->priv->entry), "changed",
+ modify_cb, mgwrap);
+ g_signal_connect (G_OBJECT (mgstr->priv->entry), "activate",
+ activate_cb, mgwrap);
+}
+
+static gboolean
+can_expand (G_GNUC_UNUSED GdauiEntryWrapper *mgwrap, G_GNUC_UNUSED gboolean horiz)
+{
+ return FALSE;
+}
diff --git a/samples/CustomUIPlugin/custom-entry-password.h b/samples/CustomUIPlugin/custom-entry-password.h
new file mode 100644
index 0000000..3d7cfc0
--- /dev/null
+++ b/samples/CustomUIPlugin/custom-entry-password.h
@@ -0,0 +1,38 @@
+#ifndef __CUSTOM_ENTRY_PASSWORD_H_
+#define __CUSTOM_ENTRY_PASSWORD_H_
+
+#include <libgda-ui/gdaui-entry-wrapper.h>
+
+G_BEGIN_DECLS
+
+#define CUSTOM_ENTRY_PASSWORD_TYPE (custom_entry_password_get_type())
+#define CUSTOM_ENTRY_PASSWORD(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, custom_entry_password_get_type(), CustomEntryPassword)
+#define CUSTOM_ENTRY_PASSWORD_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, custom_entry_password_get_type (), CustomEntryPasswordClass)
+#define IS_CUSTOM_ENTRY_PASSWORD(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, custom_entry_password_get_type ())
+
+
+typedef struct _CustomEntryPassword CustomEntryPassword;
+typedef struct _CustomEntryPasswordClass CustomEntryPasswordClass;
+typedef struct _CustomEntryPasswordPrivate CustomEntryPasswordPrivate;
+
+
+/* struct for the object's data */
+struct _CustomEntryPassword
+{
+ GdauiEntryWrapper object;
+ CustomEntryPasswordPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _CustomEntryPasswordClass
+{
+ GdauiEntryWrapperClass parent_class;
+};
+
+GType custom_entry_password_get_type (void) G_GNUC_CONST;
+GtkWidget *custom_entry_password_new (GdaDataHandler *dh, GType type, const gchar *options);
+
+
+G_END_DECLS
+
+#endif
diff --git a/samples/CustomUIPlugin/custom-entry-password.xml b/samples/CustomUIPlugin/custom-entry-password.xml
new file mode 100644
index 0000000..06a2cea
--- /dev/null
+++ b/samples/CustomUIPlugin/custom-entry-password.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<data-set-spec>
+ <parameters>
+ <parameter id="MINLENGTH" name="Min. Length" descr="Minimum Length of the password" gdatype="gchararray" nullok="TRUE"/>
+ </parameters>
+</data-set-spec>
diff --git a/samples/CustomUIPlugin/libmain.c b/samples/CustomUIPlugin/libmain.c
new file mode 100644
index 0000000..1d51575
--- /dev/null
+++ b/samples/CustomUIPlugin/libmain.c
@@ -0,0 +1,58 @@
+#include <libgda/libgda.h>
+#include <libgda-ui/libgda-ui.h>
+#include <libgda-ui/gdaui-plugin.h>
+#include <libgda/gda-binreloc.h>
+
+#include "custom-entry-password.h"
+//#include "custom-data-cell-renderer-password.h"
+
+static GdauiDataEntry *plugin_password_create_func (GdaDataHandler *handler, GType type, const gchar *options);
+static GtkCellRenderer *plugin_cell_renderer_password_create_func (GdaDataHandler *handler, GType type, const gchar *options);
+
+GSList *
+plugin_init (GError **error)
+{
+ GdauiPlugin *plugin;
+ GSList *retlist = NULL;
+ gchar *file;
+
+ /* PASSWORD */
+ plugin = g_new0 (GdauiPlugin, 1);
+ plugin->plugin_name = "custom password";
+ plugin->plugin_descr = "custom password entry";
+ plugin->plugin_file = NULL; /* always leave NULL */
+ plugin->nb_g_types = 1;
+ plugin->valid_g_types = g_new (GType, plugin->nb_g_types);
+ plugin->valid_g_types [0] = G_TYPE_STRING;
+ plugin->options_xml_spec = NULL;
+ plugin->entry_create_func = plugin_password_create_func;
+ plugin->cell_create_func = plugin_cell_renderer_password_create_func;
+ retlist = g_slist_append (retlist, plugin);
+
+ file = gda_gbr_get_file_path (GDA_LIB_DIR, "libgda-4.0", "plugins", "custom-entry-password.xml", NULL);
+ if (! g_file_test (file, G_FILE_TEST_EXISTS)) {
+ if (error && !*error)
+ g_set_error (error, 0, 0, "Missing spec. file '%s'", file);
+ }
+ else {
+ gsize len;
+ g_file_get_contents (file, &(plugin->options_xml_spec), &len, error);
+ }
+ g_free (file);
+
+ return retlist;
+}
+
+static GdauiDataEntry *
+plugin_password_create_func (GdaDataHandler *handler, GType type, const gchar *options)
+{
+ return (GdauiDataEntry *) custom_entry_password_new (handler, type, options);
+}
+
+static GtkCellRenderer *
+plugin_cell_renderer_password_create_func (GdaDataHandler *handler, GType type, const gchar *options)
+{
+ //return gdaui_data_cell_renderer_password_new (handler, type, options);
+ return NULL;
+}
+
diff --git a/samples/Makefile b/samples/Makefile
index dea2227..b1f31ca 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,5 +1,5 @@
SHELL= /bin/sh
-SUBDIRS = BDB DDL DirDataModel F-Spot Report SimpleExample SqlParserConsole TableCopy Virtual XSLT MetaStore Tree SqlBuilder AsyncExec LdapBrowser
+SUBDIRS = BDB DDL DirDataModel F-Spot Report SimpleExample SqlParserConsole TableCopy Virtual XSLT MetaStore Tree SqlBuilder AsyncExec LdapBrowser CustomUIPlugin
all:
for dir in ${SUBDIRS} ; do ( cd $$dir ; ${MAKE} ) ; done
clean:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]