Revision: 1785 http://geany.svn.sourceforge.net/geany/?rev=1785&view=rev Author: ntrel Date: 2007-08-10 09:11:17 -0700 (Fri, 10 Aug 2007)
Log Message: ----------- Add plugin symbol geany_callbacks (see plugindata.h for details). Add GeanyObject type with "document-new", "document-open", "document-save" signals.
Modified Paths: -------------- trunk/ChangeLog trunk/src/Makefile.am trunk/src/document.c trunk/src/main.c trunk/src/plugindata.h trunk/src/plugins.c
Added Paths: ----------- trunk/src/geanyobject.c trunk/src/geanyobject.h
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-10 11:45:20 UTC (rev 1784) +++ trunk/ChangeLog 2007-08-10 16:11:17 UTC (rev 1785) @@ -8,6 +8,11 @@ Update selected line(s) keybindings. * src/plugindata.h: Tidy up struct typedefs. + * src/geanyobject.c, src/plugindata.h, src/geanyobject.h, + src/document.c, src/plugins.c, src/main.c, src/Makefile.am: + Add plugin symbol geany_callbacks (see plugindata.h for details). + Add GeanyObject type with "document-new", "document-open", + "document-save" signals.
2007-08-10 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-10 11:45:20 UTC (rev 1784) +++ trunk/src/Makefile.am 2007-08-10 16:11:17 UTC (rev 1785) @@ -15,6 +15,7 @@ editor.c editor.h \ encodings.c encodings.h \ filetypes.c filetypes.h \ + geanyobject.c geanyobject.h \ highlighting.c highlighting.h \ interface.c interface.h \ keybindings.c keybindings.h \
Modified: trunk/src/document.c =================================================================== --- trunk/src/document.c 2007-08-10 11:45:20 UTC (rev 1784) +++ trunk/src/document.c 2007-08-10 16:11:17 UTC (rev 1785) @@ -67,6 +67,7 @@ #include "build.h" #include "symbols.h" #include "callbacks.h" +#include "geanyobject.h"
/* dynamic array of document elements to hold all information of the notebook tabs */ @@ -459,7 +460,8 @@ ft = filetypes_detect_from_file(idx);
document_set_filetype(idx, ft); // also clears taglist - if (ft == NULL) filetypes[GEANY_FILETYPES_ALL]->style_func_ptr(doc_list[idx].sci); + if (ft == NULL) + filetypes[GEANY_FILETYPES_ALL]->style_func_ptr(doc_list[idx].sci); ui_set_window_title(idx); build_menu_update(idx);
@@ -477,6 +479,11 @@ g_signal_connect((GtkWidget*) doc_list[idx].sci, "sci-notify", G_CALLBACK(on_editor_notification), GINT_TO_POINTER(idx));
+ if (geany_object) + { + g_signal_emit_by_name(geany_object, "document-new", idx); + } + msgwin_status_add(_("New file "%s" opened."), (doc_list[idx].file_name != NULL) ? doc_list[idx].file_name : GEANY_STRING_UNTITLED);
@@ -854,10 +861,13 @@ document_set_text_changed(idx); // also updates tab state ui_document_show_hide(idx); // update the document menu
- // finally add current file to recent files menu, but not the files from the last session - if (! app->opening_session_files) ui_add_recent_file(utf8_filename); + if (! app->opening_session_files) + ui_add_recent_file(utf8_filename);
+ if (! reload && geany_object) + g_signal_emit_by_name(geany_object, "document-open", idx); + if (reload) msgwin_status_add(_("File %s reloaded."), utf8_filename); else @@ -1096,7 +1106,7 @@ * timestamp can be ahead of time(NULL) */ document_update_timestamp(idx);
- if (doc_list[idx].file_type == NULL || doc_list[idx].file_type->id == GEANY_FILETYPES_ALL) + if (FILETYPE_ID(doc_list[idx].file_type) == GEANY_FILETYPES_ALL) { doc_list[idx].file_type = filetypes_detect_from_file(idx); filetypes_select_radio_item(doc_list[idx].file_type); @@ -1111,8 +1121,11 @@ #ifdef HAVE_VTE vte_cwd(doc_list[idx].file_name, FALSE); #endif - } + if (geany_object) + { + g_signal_emit_by_name(geany_object, "document-save", idx); + } return TRUE; }
Added: trunk/src/geanyobject.c =================================================================== --- trunk/src/geanyobject.c (rev 0) +++ trunk/src/geanyobject.c 2007-08-10 16:11:17 UTC (rev 1785) @@ -0,0 +1,152 @@ +/* + * geanyobject.c - this file is part of Geany, a fast and lightweight IDE + * + * Copyright 2007 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + * Copyright 2007 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id$ + */ + +/* GObject used for connecting and emitting signals when certain events happen, + * e.g. opening a document. + * Mainly used for plugins - geany_object is created in plugins_init(). */ + +#include "geany.h" +#include "geanyobject.h" +#include "plugindata.h" + +GObject *geany_object; + +static guint geany_object_signals[GCB_MAX] = { 0 }; + + +typedef struct _GeanyObjectPrivate GeanyObjectPrivate; + +#define GEANY_OBJECT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ + GEANY_OBJECT_TYPE, GeanyObjectPrivate)) + +struct _GeanyObjectPrivate +{ + /* add your private declarations here */ +}; + +static void geany_object_class_init (GeanyObjectClass *klass); +static void geany_object_init (GeanyObject *self); +static void geany_object_finalize (GObject *object); + +/* Local data */ +static GObjectClass *parent_class = NULL; + + +GType geany_object_get_type(void) +{ + static GType self_type = 0; + if (! self_type) + { + static const GTypeInfo self_info = + { + sizeof(GeanyObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)geany_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GeanyObject), + 0, + (GInstanceInitFunc)geany_object_init, + NULL + }; + + self_type = g_type_register_static(G_TYPE_OBJECT, "GeanyObject", &self_info, 0); } + + return self_type; +} + + +static void create_signals(GObjectClass *g_object_class) +{ + geany_object_signals[GCB_DOCUMENT_NEW] = g_signal_new ( + "document-new", + G_OBJECT_CLASS_TYPE (g_object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeanyObjectClass, document_new), + NULL, NULL, + gtk_marshal_NONE__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + geany_object_signals[GCB_DOCUMENT_OPEN] = g_signal_new ( + "document-open", + G_OBJECT_CLASS_TYPE (g_object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeanyObjectClass, document_open), + NULL, NULL, + gtk_marshal_NONE__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + geany_object_signals[GCB_DOCUMENT_SAVE] = g_signal_new ( + "document-save", + G_OBJECT_CLASS_TYPE (g_object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GeanyObjectClass, document_save), + NULL, NULL, + gtk_marshal_NONE__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); +} + + +static void geany_object_class_init(GeanyObjectClass *klass) +{ + GObjectClass *g_object_class; + + g_object_class = G_OBJECT_CLASS(klass); + + g_object_class->finalize = geany_object_finalize; + + parent_class = (GObjectClass*)g_type_class_peek(G_TYPE_OBJECT); + g_type_class_add_private((gpointer)klass, sizeof(GeanyObjectPrivate)); + + create_signals(g_object_class); +} + + +static void geany_object_init(GeanyObject *self) +{ + +} + + +GObject* geany_object_new(void) +{ + return (GObject*)g_object_new(GEANY_OBJECT_TYPE, NULL); +} + + +void geany_object_finalize(GObject *object) +{ + GeanyObject *self; + + g_return_if_fail(object != NULL); + g_return_if_fail(IS_GEANY_OBJECT(object)); + + self = GEANY_OBJECT(object); + + if (G_OBJECT_CLASS(parent_class)->finalize) + (* G_OBJECT_CLASS(parent_class)->finalize)(object); +} +
Property changes on: trunk/src/geanyobject.c ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native
Added: trunk/src/geanyobject.h =================================================================== --- trunk/src/geanyobject.h (rev 0) +++ trunk/src/geanyobject.h 2007-08-10 16:11:17 UTC (rev 1785) @@ -0,0 +1,79 @@ +/* + * geanyobject.h - this file is part of Geany, a fast and lightweight IDE + * + * Copyright 2007 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + * Copyright 2007 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id$ + */ + + +#ifndef __GEANYOBJECT_H__ +#define __GEANYOBJECT_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +extern GObject *geany_object; + +typedef enum +{ + GCB_DOCUMENT_NEW, + GCB_DOCUMENT_OPEN, + GCB_DOCUMENT_SAVE, + GCB_MAX +} GeanyCallbackId; + + +#define GEANY_OBJECT_TYPE (geany_object_get_type()) +#define GEANY_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GEANY_OBJECT_TYPE, GeanyObject)) +#define GEANY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + GEANY_OBJECT_TYPE, GeanyObjectClass)) +#define IS_GEANY_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ + GEANY_OBJECT_TYPE)) +#define IS_GEANY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + GEANY_OBJECT_TYPE)) + +typedef struct _GeanyObject GeanyObject; +typedef struct _GeanyObjectClass GeanyObjectClass; + +struct _GeanyObject +{ + GObject parent; + /* add your public declarations here */ +}; + +struct SCNotification; + +struct _GeanyObjectClass +{ + GObjectClass parent_class; + + void (*document_new)(gint idx); + void (*document_open)(gint idx); + void (*document_save)(gint idx); +}; + +GType geany_object_get_type (void); +GObject* geany_object_new (void); + +G_END_DECLS + +#endif /* __GEANYOBJECT_H__ */
Property changes on: trunk/src/geanyobject.h ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native
Modified: trunk/src/main.c =================================================================== --- trunk/src/main.c 2007-08-10 11:45:20 UTC (rev 1784) +++ trunk/src/main.c 2007-08-10 16:11:17 UTC (rev 1785) @@ -701,6 +701,12 @@ // apply all configuration options apply_settings();
+#ifdef HAVE_PLUGINS + // load any enabled plugins before we open any documents + if (! no_plugins) + plugins_init(); +#endif + // load any command line files or session files app->opening_session_files = TRUE; if (! open_cl_files(argc, argv)) @@ -720,7 +726,8 @@ app->opening_session_files = FALSE;
// open a new file if no other file was opened - if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(app->notebook)) == 0) document_new_file(NULL, NULL); + if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(app->notebook)) == 0) + document_new_file(NULL, NULL);
ui_document_buttons_update(); ui_save_buttons_toggle(FALSE); @@ -743,12 +750,6 @@ } #endif
-#ifdef HAVE_PLUGINS - // load any enabled plugins just before we draw the main window - if (! no_plugins) - plugins_init(); -#endif - // finally realize the window to show the user what we have done gtk_widget_show(app->window); app->main_window_realized = TRUE;
Modified: trunk/src/plugindata.h =================================================================== --- trunk/src/plugindata.h 2007-08-10 11:45:20 UTC (rev 1784) +++ trunk/src/plugindata.h 2007-08-10 16:11:17 UTC (rev 1785) @@ -40,6 +40,10 @@ * PluginFields* plugin_fields * Plugin owned fields, including flags. * + * GeanyCallback geany_callbacks[] + * An array for connecting GeanyObject events, which should be terminated with + * {NULL, NULL, FALSE, NULL}. See signals below. + * * void init(GeanyData *data) * Called after loading the plugin. data is the same as geany_data. * @@ -48,10 +52,23 @@ * everything done in init() - e.g. destroy menu items, free memory. */
+/** + * Signals: + * + * "document-new" + * Sent when a new document is created. + * + * "document-open" + * Sent when a file is opened. + * + * "document-save" + * Sent when a file is saved. + */
+ /* The API version should be incremented whenever any plugin data types below are * modified. */ -static const gint api_version = 8; +static const gint api_version = 9;
/* The ABI version should be incremented whenever existing fields in the plugin * data types below have to be changed or reordered. It should stay the same if fields @@ -212,4 +229,14 @@ } SupportFuncs;
+ +typedef struct GeanyCallback +{ + gchar *signal_name; + GCallback callback; + gboolean after; + gpointer user_data; +} +GeanyCallback; + #endif
Modified: trunk/src/plugins.c =================================================================== --- trunk/src/plugins.c 2007-08-10 11:45:20 UTC (rev 1784) +++ trunk/src/plugins.c 2007-08-10 16:11:17 UTC (rev 1785) @@ -46,6 +46,7 @@ #include "sciwrappers.h" #include "ui_utils.h" #include "editor.h" +#include "geanyobject.h"
#ifdef G_OS_WIN32 # define PLUGIN_EXT "dll" @@ -211,6 +212,27 @@ }
+// TODO: disconnect the callbacks when the plugin is unloaded. +static void add_callbacks(GeanyCallback *callbacks) +{ + GeanyCallback *cb; + guint i = 0; + + do + { + cb = &callbacks[i]; + if (!cb->signal_name || !cb->callback) + break; + + if (cb->after) + g_signal_connect_after(geany_object, cb->signal_name, cb->callback, cb->user_data); + else + g_signal_connect(geany_object, cb->signal_name, cb->callback, cb->user_data); + i++; + } while (TRUE); +} + + static Plugin* plugin_new(const gchar *fname) { @@ -219,6 +241,7 @@ PluginInfo* (*info)(); PluginFields **plugin_fields; GeanyData **p_geany_data; + GeanyCallback *callbacks;
g_return_val_if_fail(fname, NULL); g_return_val_if_fail(g_module_supported(), NULL); @@ -293,6 +316,10 @@ gtk_widget_set_sensitive(plugin->fields.menu_item, enable); }
+ g_module_symbol(module, "geany_callbacks", (void *) &callbacks); + if (callbacks) + add_callbacks(callbacks); + geany_debug("Loaded: %s (%s)", fname, NVL(plugin->info()->name, "<Unknown>")); return plugin; @@ -360,16 +387,10 @@ #endif
-void plugins_init() +static void load_plugin_paths() { - GtkWidget *widget; gchar *path;
- geany_data_init(); - - widget = gtk_separator_menu_item_new(); - gtk_container_add(GTK_CONTAINER(geany_data.tools_menu), widget); - path = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "plugins", NULL); // first load plugins in ~/.geany/plugins/, then in $prefix/lib/geany load_plugins(path); @@ -380,15 +401,32 @@ #else load_plugins(PACKAGE_LIB_DIR G_DIR_SEPARATOR_S "geany"); #endif - if (g_list_length(plugin_list) > 0) - gtk_widget_show(widget);
g_free(path); }
+void plugins_init() +{ + GtkWidget *widget; + + geany_data_init(); + geany_object = geany_object_new(); + + widget = gtk_separator_menu_item_new(); + gtk_container_add(GTK_CONTAINER(geany_data.tools_menu), widget); + + load_plugin_paths(); + + if (g_list_length(plugin_list) > 0) + gtk_widget_show(widget); +} + + void plugins_free() { + g_object_unref(geany_object); + if (plugin_list != NULL) { g_list_foreach(plugin_list, (GFunc) plugin_free, NULL);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.