GNOME Clipboard Manager - Documentation

Creating plugins for GNOME Clipboard Manager


Index


Step1: Setting all includes and preprocessor stuff right


Make a yourplugin.c file that looks like this :
#include "yourplugin.h"
/* 
 * Add all the .h files of the windows of gcm you want to use 
 */
#include "../src/textitemwin.h"
#include "../src/mainwin.h"
#include 
#include <string.h>
#include <gnome.h>


#ifdef __cplusplus
extern "C" {
#endif

/* Add code here */

#ifdef __cplusplus
}
#endif


And a yourplugin.h file that looks like this :
/* The plugin.h file of the gcm distrubution*/
#include "../src/plugin.h"

#ifdef __cplusplus
extern "C" {
#endif

	void plugin_init (GtkWidget *mainwin);
	void plugin_about (GtkWidget *mainwin);
	void plugin_configure (GtkWidget *mainwin);
	void plugin_cleanup ();
	void plugin_on_mainwin_show (GtkWidget *mainwin, gpointer *user_data);
	void plugin_on_mainwin_hide (GtkWidget *mainwin, gpointer *user_data);
	void plugin_on_plugin_added (GtkWidget *mainwin, GcmPlugin *p);
	void plugin_on_firsttime(gpointer *client, gpointer *prefs);
	void plugin_on_reload_prefs (GtkWidget *mainwin);
	void plugin_on_update_item (GtkWidget *mainwin, gint row, gpointer *user_data);
	void plugin_on_add_item (GtkWidget *mainwin, gpointer *item, gint row);
	void plugin_on_remove_item (GtkWidget *mainwin, gpointer *item, gint row);
	void plugin_on_selection_claimed (GtkWidget *mainwin, GtkClipboard *clipboard,GtkTargetEntry *ttargets, gpointer *item);
	void plugin_on_selectiondata_received (GtkWidget *mainwin, gpointer *item, GtkSelectionData *data);
	GcmPlugin *plugin_i_will_handle_that_target (GdkAtom target);
	gboolean plugin_handle_target_tab (gpointer *mytab, GtkSelectionData *data);
	GtkSelectionData *plugin_handle_target_merge (GtkSelectionData *old, GtkSelectionData *in);

#ifdef __cplusplus
}
#endif

Step2: Creating a GcmPlugin struct

Add a GcmPlugin struct in the yourplugin.c file
/* Change the name in two places; the variable-name and in the GcmPlugin struct !*/
GcmPlugin yourplugin =
{
	NULL,	/* Leave empty */
	NULL,	/* Leave empty */
	"Your plugin",	/* Description (change this!) */
	"yourplugin", /* The name of your plugin (change this!) */
	FALSE, /* Always put false here (this is yourplugin.enabled) */
	plugin_init, /* The name of your init function */
	plugin_about /* The name of your about function */,
	plugin_configure /* The name of your configure function */,
	plugin_cleanup /* The name of your cleanup function */,
	plugin_on_mainwin_show /* the name of your ... */,
	plugin_on_mainwin_hide /* ... */,
	plugin_on_plugin_added,
	plugin_on_firsttime,
	plugin_on_reload_prefs,
	plugin_on_update_item,
	plugin_on_add_item,
	plugin_on_remove_item,
	plugin_on_selection_claimed,
	plugin_on_selectiondata_received,
	plugin_i_will_handle_that_target,
	plugin_handle_target_tab,
	plugin_handle_target_merge

};

/* Function to return a handle to the plugin */
GcmPlugin *get_gcmplugin_info(void) { return &yourplugin; }
MainWin *themainwin;
void enabled_changed_callback (GConfClient *client,guint cnxn_id,GConfEntry *entry,gpointer user_data);

Step3: Create the functions

Add these functions to the yourplugin.c file

	void enabled_changed_callback (GConfClient *client,guint cnxn_id,GConfEntry *entry,gpointer user_data)
	{
		/* Yes, this is required ! */
		gboolean enabled = gconf_value_get_bool (gconf_entry_get_value (entry));
		/* You must change this ! */
		GcmPlugin *pe = &yourplugin;
		if (enabled) {
			themainwin->plugin_enable_plugin (themainwin, pe);
		} else {
			themainwin->plugin_disable_plugin (themainwin, pe);
		}
	}

	void plugin_init (GtkWidget *mainwin)
	{
		MainWin *mwin = (MainWin*)mainwin;
		/* PLUGIN_ENABLED_CONFIG_KEY is a macro defined in plugin.h */
		gchar *key = PLUGIN_ENABLED_CONFIG_KEY(sampleplugin);
		GError *err=NULL;
		GConfClient *client;
		themainwin = mwin;
		client = gconf_client_get_default();

		/* Yes, this is required ! */
		gconf_client_notify_add(client, key,
			(GConfClientNotifyFunc) enabled_changed_callback,
			themainwin->prefswin, /* Give a pointer to the prefswin*/
			NULL, NULL);

		yourplugin.enabled = gconf_client_get_bool (client, key, &err);
		/* You are free to add more code here */

		g_free(key);
	}

	void plugin_about (GtkWidget *mainwin)
	{
		GtkWidget *thewin;
		gchar *comment;	void plugin_on_mainwin_show (GtkWidget *mainwin, gpointer *user_data);

		const gchar *documenters[] = {
		  "Documenter",
		  NULL
		};
		const gchar *translator_credits = _("translator_credits");
		const gchar *authors[] = {
		  "author",
		  NULL
		};
		comment = g_strdup (_("This plugin is a .... plugin for GNOME Clipboard Manager"));

		thewin = gnome_about_new ( _("GNOME Clipboard Manager pluginname plugin"), "0.0.1",
			"(C) 2000",
			_("Released under the GNU General Public License.\n"),
			authors,
			documenters,
			strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
			NULL);
		gtk_widget_show(thewin);
	}

	void plugin_configure (GtkWidget *mainwin){
		GtkWidget *win, *vbox, *bbox, *closeb;
		win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
		gtk_widget_set_size_request(GTK_WIDGET(win), 150, 80);
		gtk_window_set_title (GTK_WINDOW (win), _("SamplePlugin configuration"));
		vbox = gtk_vbox_new (FALSE, 0);
		gtk_container_add (GTK_CONTAINER(win), vbox);
		gtk_widget_show (vbox);

		bbox = gtk_hbutton_box_new ();
		gtk_widget_show (bbox);

		gtk_box_pack_end (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
		gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
		gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 6);
		gtk_container_set_border_width (GTK_CONTAINER (bbox), 6);

		closeb = gtk_button_new_from_stock  (GNOME_STOCK_BUTTON_CLOSE);
		gtk_widget_show (closeb);
		gtk_container_add (GTK_CONTAINER (bbox), closeb);
		GTK_WIDGET_SET_FLAGS (closeb, GTK_CAN_DEFAULT);
		gtk_widget_grab_default (closeb);

		g_signal_connect (G_OBJECT (closeb), "clicked",
						  G_CALLBACK (on_preferencesclose_clicked),
						  win);

		gtk_widget_show(win);
	}

	void plugin_cleanup	()
	{
		/*
		 * Free all memory here !!
		 */
	}


	void plugin_on_mainwin_show (GtkWidget *mainwin, gpointer *user_data);
	void plugin_on_mainwin_hide (GtkWidget *mainwin, gpointer *user_data);
	void plugin_on_plugin_added (GtkWidget *mainwin, GcmPlugin *p);
	void plugin_on_firsttime(gpointer *client, gpointer *prefs);
	void plugin_on_reload_prefs (GtkWidget *mainwin);
	void plugin_on_update_item (GtkWidget *mainwin, gint row, gpointer *user_data);
	void plugin_on_add_item (GtkWidget *mainwin, gpointer *item, gint row);
	void plugin_on_remove_item (GtkWidget *mainwin, gpointer *item, gint row);
	void plugin_on_selection_claimed (GtkWidget *mainwin, GtkClipboard *clipboard,GtkTargetEntry *ttargets, gpointer *item);
	void plugin_on_selectiondata_received (GtkWidget *mainwin, gpointer *item, GtkSelectionData *data);


	GcmPlugin *plugin_i_will_handle_that_target	(GdkAtom target) {
		/* If your plugin is not respos*/
		if (yourplugin.enabled) return NULL;
			else if (gdk_atom_intern("THE TARGET THAT YOU WANT TO SUPPORT", FALSE) == target) {
				return &yourplugin;
			} else {
				return NULL;
			}
	}

	gboolean plugin_handle_target_tab				(gpointer *mytab, GtkSelectionData *data) {
		if (yourplugin.enabled) {
				TextItemTab *tab = (TextItemTab*) mytab;
				GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
				GtkWidget *label = gtk_label_new("Hi, I am yourplugin and I am\nresponsible for this target\n");
				tab->tabwidget = vbox;
				gtk_box_pack_start (GTK_BOX (tab->tabwidget), label, TRUE, FALSE, 0);
				gtk_widget_show(label);
				gtk_widget_show(tab->tabwidget);
			return TRUE;
		} else return FALSE;
	}

	GtkSelectionData
		*plugin_handle_target_merge				(GtkSelectionData *old, GtkSelectionData *in) {
		if (yourplugin.enabled) {
			g_print("yourplugin: merging old with new\n");
			return old;
		}
	}




You can use the following casts (if possible: include the correct .h files!)

MainWin *mwin = (MainWin*)mainwin;
TextItemTab *tab = (TextItemTab*) mytab;
Selection *myitem = (Selection*) item;
GConfClient *myclient = (GConfClient*)client;
Prefs *myprefs = (Prefs*) prefs;
...
You can perform the following functions on gcm in your plugins
	MainWin *mwin = (MainWin*)mainwin;

	void mwin->plugin_update_item (MainWin *mwin, gpointer *user_data);
	void mwin->plugin_update_row (MainWin *mwin, gint row);
	void mwin->plugin_get_new_item (MainWin *mwin, gpointer *user_data) ;
	void mwin->plugin_delete_selected_items (MainWin *mwin, GtkCList *cliplist, gpointer *usr_data);
	void mwin->plugin_add_selection (MainWin *mwin, Selection *item);
	void mwin->plugin_add_text_selection (MainWin *mwin, gchar *type, gchar *from, gchar *data);
	void mwin->plugin_update_menus (MainWin *mwin);
	void mwin->plugin_reload_prefs (MainWin *mwin);
	void mwin->plugin_claim_selection (MainWin *mwin, Selection *item);


	void mwin->plugin_update_text_selection (MainWin *mwin, gint row, gchar *type, gchar *from, gchar *data);
	void mwin->plugin_move_selected_up (MainWin *mwin, GList *remaining, gint startrow);
	void mwin->plugin_move_selected_down (MainWin *mwin, GList *remaining, gint startrow);

	void mwin->plugin_selection_free (Selection *item);
	void mwin->plugin_prefs_free (Prefs *p);
	void mwin->plugin_targetmanip_free (TargetManip *tz);
	void mwin->plugin_try_to_get_text_target (MainWin *mwin, gpointer *user_data);
	void mwin->plugin_saveasdata_free (SaveAsData *sa);
	void mwin->plugin_show_prefswin (MainWin *mwin, gpointer *user_data);



You can also use libgcm. Just include libgcm.h in your yourplugin.c file. Note that you must add something special to your Makefile.am file which will be explained later...

Step3: Add your plugin to the Makefile.am file


If you look at the Makefile.am file you will find the gcmlib_LTLIBRARIES variable. You will have to add your plugin to it :
gcmlib_LTLIBRARIES = \
		librtftohtmlplugin.la \
		libsampleplugin.la \
		libyourplugin.la \
		libtoolsplugin.la


You will also have to add the LIBADD, LDFLAGS and SOURCES variables of your plugin :
libyourplugin_la_LDFLAGS = -avoid-version -module
libyourplugin_la_LIBADD =  $(GCM_LIBS)
libyourplugin_la_SOURCES = yourplugin.c


If you want to use libgcm in your plugin then pay special attention to the LDFLAGS variable ! You will have to add the variable like this :
libyourplugin_la_LIBADD =  $(GCM_LIBS) $(top_builddir)/libgcm/libgcm.la


If you want to use librtotohtml in your plugin then pay special attention to the LDFLAGS variable ! You will have to add the variable like this :
librtftohtmlplugin_la_LIBADD =  $(GCM_LIBS) $(top_builddir)/librtftohtml/librtftohtml.la -lstdc++


As you can see I also added -lstdc++. This is because the library uses objects and is written in C++. If your "special library" is also written in C++ then you too must add it to the line.

Step4: Create a patch and send it to the mailinglist

Creating a patch
cvs diff -u > myplugin_by_my_real_name.unified.diff
And send it to the mailinglist of GNOME Clipboard Manager so that I can include your plugin with the main Gcm distrubution.