[libgda/LIBGDA_4.2] Support out of tree UI plugins creation



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]