[gedit] Revert the three previous commits.
- From: Steve Frécinaux <sfre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit] Revert the three previous commits.
- Date: Sun, 13 Jun 2010 20:10:27 +0000 (UTC)
commit e9d4234f729147c1ecf69a6595ac91d67f52d15c
Author: Steve Frécinaux <code istique net>
Date: Sun Jun 13 22:08:29 2010 +0200
Revert the three previous commits.
Those were pushed by mistake.
This reverts commit 2786eba0d2a333b9e4d5675be410b4c42d48addd.
This reverts commit cae391accd5f15a34902a60b0f3eb5e130b0031a.
This reverts commit c7f9f4aa8a0ee1f81ec33c9c3488a838c529a101.
Makefile.am | 2 +-
configure.ac | 7 +-
gedit/Makefile.am | 10 +
gedit/dialogs/gedit-preferences-dialog.c | 8 +-
gedit/gedit-dirs.c | 30 +-
gedit/gedit-dirs.h | 5 +-
gedit/gedit-metadata-manager.h | 1 -
gedit/gedit-plugin-info-priv.h | 69 +++
gedit/gedit-plugin-info.c | 402 +++++++++++++
gedit/gedit-plugin-info.h | 64 ++
gedit/gedit-plugin-loader.c | 132 +++++
gedit/gedit-plugin-loader.h | 108 ++++
gedit/gedit-plugin-manager.c | 895 +++++++++++++++++++++++++++++
gedit/gedit-plugin-manager.h | 85 +++
gedit/gedit-plugin.c | 339 +++++++++++
gedit/gedit-plugin.h | 242 ++++++++
gedit/gedit-plugins-engine.c | 862 +++++++++++++++++++++++++---
gedit/gedit-plugins-engine.h | 43 ++-
gedit/gedit-window-private.h | 3 -
gedit/gedit-window.c | 82 +--
plugin-loaders/Makefile.am | 3 +
plugin-loaders/c/Makefile.am | 24 +
plugin-loaders/c/gedit-plugin-loader-c.c | 183 ++++++
plugin-loaders/c/gedit-plugin-loader-c.h | 61 ++
plugins/Makefile.am | 53 +-
plugins/modelines/gedit-modeline-plugin.c | 89 ++--
plugins/modelines/gedit-modeline-plugin.h | 22 +-
plugins/pysample/Makefile.am | 15 -
plugins/pysample/pysample.gedit-plugin.in | 9 -
plugins/pysample/pysample.py | 15 -
30 files changed, 3552 insertions(+), 311 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 122a88b..e57b203 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
## Process this file with automake to produce Makefile.in
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = gedit pixmaps po plugins data docs tests win32 osx
+SUBDIRS = gedit pixmaps po data plugin-loaders plugins docs tests win32 osx
if !OS_OSX
SUBDIRS += help
diff --git a/configure.ac b/configure.ac
index 8fe0f25..e07fa4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -274,8 +274,6 @@ PKG_CHECK_MODULES(GEDIT, [
gtk+-3.0 >= 2.90.0
gtksourceview-3.0 >= 2.11.2
gconf-2.0 >= 2.31.1
- libpeas-1.0
- libpeasui-1.0
])
if test "$os_osx" = "no" &&
@@ -372,8 +370,6 @@ AC_SUBST(GEDIT_IMPLIB)
AC_SUBST(PLUGIN_LIBTOOL_FLAGS)
AC_SUBST(LOADER_LIBTOOL_FLAGS)
-AM_PATH_PYTHON(2.6)
-
GEDIT_PLUGINS_DATA_DIR="$datadir/gedit-2/plugins"
AC_SUBST(GEDIT_PLUGINS_DATA_DIR)
@@ -397,6 +393,8 @@ gedit/smclient/Makefile
gedit/Makefile
help/Makefile
pixmaps/Makefile
+plugin-loaders/Makefile
+plugin-loaders/c/Makefile
plugins/Makefile
plugins/changecase/Makefile
plugins/checkupdate/org.gnome.gedit.checkupdate.gschema.xml.in
@@ -405,7 +403,6 @@ plugins/docinfo/Makefile
plugins/filebrowser/org.gnome.gedit.file-browser.gschema.xml.in
plugins/filebrowser/Makefile
plugins/modelines/Makefile
-plugins/pysample/Makefile
plugins/sort/Makefile
plugins/spell/Makefile
plugins/taglist/Makefile
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index 72c8074..6bf6894 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -105,6 +105,11 @@ NOINST_H_FILES = \
gedit-language-manager.h \
gedit-multi-notebook.h \
gedit-notebook.h \
+ gedit-object-module.h \
+ gedit-plugin-info.h \
+ gedit-plugin-info-priv.h \
+ gedit-plugin-loader.h \
+ gedit-plugin-manager.h \
gedit-plugins-engine.h \
gedit-print-job.h \
gedit-print-preview.h \
@@ -129,6 +134,7 @@ INST_H_FILES = \
gedit-message-type.h \
gedit-message.h \
gedit-panel.h \
+ gedit-plugin.h \
gedit-progress-info-bar.h \
gedit-statusbar.h \
gedit-status-combo-box.h \
@@ -180,6 +186,10 @@ libgedit_la_SOURCES = \
gedit-object-module.c \
gedit-notebook.c \
gedit-panel.c \
+ gedit-plugin-info.c \
+ gedit-plugin.c \
+ gedit-plugin-loader.c \
+ gedit-plugin-manager.c \
gedit-plugins-engine.c \
gedit-print-job.c \
gedit-print-preview.c \
diff --git a/gedit/dialogs/gedit-preferences-dialog.c b/gedit/dialogs/gedit-preferences-dialog.c
index 593a53d..2cbbce4 100644
--- a/gedit/dialogs/gedit-preferences-dialog.c
+++ b/gedit/dialogs/gedit-preferences-dialog.c
@@ -39,15 +39,14 @@
#include <string.h>
#include <glib/gi18n.h>
-#include <libpeasui/peas-ui-plugin-manager.h>
#include "gedit-preferences-dialog.h"
#include "gedit-utils.h"
#include "gedit-debug.h"
#include "gedit-document.h"
#include "gedit-style-scheme-manager.h"
+#include "gedit-plugin-manager.h"
#include "gedit-dirs.h"
-#include "gedit-plugins-engine.h"
#include "gedit-settings.h"
#include "gedit-utils.h"
@@ -906,14 +905,11 @@ setup_font_colors_page (GeditPreferencesDialog *dlg)
static void
setup_plugins_page (GeditPreferencesDialog *dlg)
{
- GeditPluginsEngine *engine;
GtkWidget *page_content;
gedit_debug (DEBUG_PREFS);
- engine = gedit_plugins_engine_get_default ();
-
- page_content = peas_ui_plugin_manager_new (PEAS_ENGINE (engine));
+ page_content = gedit_plugin_manager_new ();
g_return_if_fail (page_content != NULL);
gtk_box_pack_start (GTK_BOX (dlg->priv->plugin_manager_place_holder),
diff --git a/gedit/gedit-dirs.c b/gedit/gedit-dirs.c
index 5dac9b7..c3aae39 100644
--- a/gedit/gedit-dirs.c
+++ b/gedit/gedit-dirs.c
@@ -286,25 +286,19 @@ gedit_dirs_get_gedit_plugins_dir (void)
}
gchar *
-gedit_dirs_get_gedit_plugins_data_dir (void)
+gedit_dirs_get_gedit_plugin_loaders_dir (void)
{
- gchar *data_dir;
- gchar *plugin_data_dir;
-
- data_dir = gedit_dirs_get_gedit_data_dir ();
-
- plugin_data_dir = g_build_filename (data_dir,
- "plugins",
- NULL);
- g_free (data_dir);
-
- return plugin_data_dir;
-}
-
-gchar *
-gedit_dirs_get_binding_modules_dir (void)
-{
- return gedit_dirs_get_gedit_lib_dir ();
+ gchar *lib_dir;
+ gchar *loader_dir;
+
+ lib_dir = gedit_dirs_get_gedit_lib_dir ();
+
+ loader_dir = g_build_filename (lib_dir,
+ "plugin-loaders",
+ NULL);
+ g_free (lib_dir);
+
+ return loader_dir;
}
gchar *
diff --git a/gedit/gedit-dirs.h b/gedit/gedit-dirs.h
index e0be2f9..ba79cee 100644
--- a/gedit/gedit-dirs.h
+++ b/gedit/gedit-dirs.h
@@ -44,9 +44,8 @@ gchar *gedit_dirs_get_gedit_lib_dir (void);
gchar *gedit_dirs_get_gedit_plugins_dir (void);
-gchar *gedit_dirs_get_gedit_plugins_data_dir (void);
-
-gchar *gedit_dirs_get_binding_modules_dir (void);
+gchar *gedit_dirs_get_gedit_plugin_loaders_dir
+ (void);
gchar *gedit_dirs_get_ui_file (const gchar *file);
diff --git a/gedit/gedit-metadata-manager.h b/gedit/gedit-metadata-manager.h
index cdb28b4..b055c55 100644
--- a/gedit/gedit-metadata-manager.h
+++ b/gedit/gedit-metadata-manager.h
@@ -31,7 +31,6 @@
#define __GEDIT_METADATA_MANAGER_H__
#include <glib.h>
-#include <gio/gio.h>
G_BEGIN_DECLS
diff --git a/gedit/gedit-plugin-info-priv.h b/gedit/gedit-plugin-info-priv.h
new file mode 100644
index 0000000..14c6100
--- /dev/null
+++ b/gedit/gedit-plugin-info-priv.h
@@ -0,0 +1,69 @@
+/*
+ * gedit-plugin-info-priv.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002-2005 - Paolo Maggi
+ * Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 2002-2007. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifndef __GEDIT_PLUGIN_INFO_PRIV_H__
+#define __GEDIT_PLUGIN_INFO_PRIV_H__
+
+#include "gedit-plugin-info.h"
+#include "gedit-plugin.h"
+
+struct _GeditPluginInfo
+{
+ gint refcount;
+
+ GeditPlugin *plugin;
+ gchar *file;
+
+ gchar *module_name;
+ gchar *loader;
+ gchar **dependencies;
+
+ gchar *name;
+ gchar *desc;
+ gchar *icon_name;
+ gchar **authors;
+ gchar *copyright;
+ gchar *website;
+ gchar *version;
+
+ /* A plugin is unavailable if it is not possible to activate it
+ due to an error loading the plugin module (e.g. for Python plugins
+ when the interpreter has not been correctly initializated) */
+ gint available : 1;
+};
+
+GeditPluginInfo *_gedit_plugin_info_new (const gchar *file);
+void _gedit_plugin_info_ref (GeditPluginInfo *info);
+void _gedit_plugin_info_unref (GeditPluginInfo *info);
+
+
+#endif /* __GEDIT_PLUGIN_INFO_PRIV_H__ */
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin-info.c b/gedit/gedit-plugin-info.c
new file mode 100644
index 0000000..b7f0ac4
--- /dev/null
+++ b/gedit/gedit-plugin-info.c
@@ -0,0 +1,402 @@
+/*
+ * gedit-plugin-info.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002-2005 - Paolo Maggi
+ * Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 2002-2007. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+
+#include "gedit-plugin-info.h"
+#include "gedit-plugin-info-priv.h"
+#include "gedit-debug.h"
+#include "gedit-plugin.h"
+
+#define GEDIT_PLUGIN_IAGE 3
+
+void
+_gedit_plugin_info_ref (GeditPluginInfo *info)
+{
+ g_atomic_int_inc (&info->refcount);
+}
+
+static GeditPluginInfo *
+gedit_plugin_info_copy (GeditPluginInfo *info)
+{
+ _gedit_plugin_info_ref (info);
+ return info;
+}
+
+void
+_gedit_plugin_info_unref (GeditPluginInfo *info)
+{
+ if (!g_atomic_int_dec_and_test (&info->refcount))
+ return;
+
+ if (info->plugin != NULL)
+ {
+ gedit_debug_message (DEBUG_PLUGINS, "Unref plugin %s", info->name);
+
+ g_object_unref (info->plugin);
+ }
+
+ g_free (info->file);
+ g_free (info->module_name);
+ g_strfreev (info->dependencies);
+ g_free (info->name);
+ g_free (info->desc);
+ g_free (info->icon_name);
+ g_free (info->website);
+ g_free (info->copyright);
+ g_free (info->loader);
+ g_free (info->version);
+ g_strfreev (info->authors);
+
+ g_free (info);
+}
+
+/**
+ * gedit_plugin_info_get_type:
+ *
+ * Retrieves the #GType object which is associated with the #GeditPluginInfo
+ * class.
+ *
+ * Return value: the GType associated with #GeditPluginInfo.
+ **/
+GType
+gedit_plugin_info_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (G_UNLIKELY (!the_type))
+ the_type = g_boxed_type_register_static (
+ "GeditPluginInfo",
+ (GBoxedCopyFunc) gedit_plugin_info_copy,
+ (GBoxedFreeFunc) _gedit_plugin_info_unref);
+
+ return the_type;
+}
+
+/**
+ * gedit_plugin_info_new:
+ * @filename: the filename where to read the plugin information
+ *
+ * Creates a new #GeditPluginInfo from a file on the disk.
+ *
+ * Return value: a newly created #GeditPluginInfo.
+ */
+GeditPluginInfo *
+_gedit_plugin_info_new (const gchar *file)
+{
+ GeditPluginInfo *info;
+ GKeyFile *plugin_file = NULL;
+ gchar *str;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ gedit_debug_message (DEBUG_PLUGINS, "Loading plugin: %s", file);
+
+ info = g_new0 (GeditPluginInfo, 1);
+ info->refcount = 1;
+ info->file = g_strdup (file);
+
+ plugin_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL))
+ {
+ g_warning ("Bad plugin file: %s", file);
+ goto error;
+ }
+
+ if (!g_key_file_has_key (plugin_file,
+ "Gedit Plugin",
+ "IAge",
+ NULL))
+ {
+ gedit_debug_message (DEBUG_PLUGINS,
+ "IAge key does not exist in file: %s", file);
+ goto error;
+ }
+
+ /* Check IAge=GEDIT_PLUGIN_IAGE */
+ if (g_key_file_get_integer (plugin_file,
+ "Gedit Plugin",
+ "IAge",
+ NULL) != GEDIT_PLUGIN_IAGE)
+ {
+ gedit_debug_message (DEBUG_PLUGINS,
+ "Wrong IAge in file: %s", file);
+ goto error;
+ }
+
+ /* Get module name */
+ str = g_key_file_get_string (plugin_file,
+ "Gedit Plugin",
+ "Module",
+ NULL);
+
+ if ((str != NULL) && (*str != '\0'))
+ {
+ info->module_name = str;
+ }
+ else
+ {
+ g_warning ("Could not find 'Module' in %s", file);
+ goto error;
+ }
+
+ /* Get the dependency list */
+ info->dependencies = g_key_file_get_string_list (plugin_file,
+ "Gedit Plugin",
+ "Depends",
+ NULL,
+ NULL);
+ if (info->dependencies == NULL)
+ {
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Depends' in %s", file);
+ info->dependencies = g_new0 (gchar *, 1);
+ }
+
+ /* Get the loader for this plugin */
+ str = g_key_file_get_string (plugin_file,
+ "Gedit Plugin",
+ "Loader",
+ NULL);
+
+ if ((str != NULL) && (*str != '\0'))
+ {
+ info->loader = str;
+ }
+ else
+ {
+ /* default to the C loader */
+ info->loader = g_strdup("c");
+ }
+
+ /* Get Name */
+ str = g_key_file_get_locale_string (plugin_file,
+ "Gedit Plugin",
+ "Name",
+ NULL, NULL);
+ if (str)
+ info->name = str;
+ else
+ {
+ g_warning ("Could not find 'Name' in %s", file);
+ goto error;
+ }
+
+ /* Get Description */
+ str = g_key_file_get_locale_string (plugin_file,
+ "Gedit Plugin",
+ "Description",
+ NULL, NULL);
+ if (str)
+ info->desc = str;
+ else
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Description' in %s", file);
+
+ /* Get Icon */
+ str = g_key_file_get_locale_string (plugin_file,
+ "Gedit Plugin",
+ "Icon",
+ NULL, NULL);
+ if (str)
+ info->icon_name = str;
+ else
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Icon' in %s, using 'gedit-plugin'", file);
+
+
+ /* Get Authors */
+ info->authors = g_key_file_get_string_list (plugin_file,
+ "Gedit Plugin",
+ "Authors",
+ NULL,
+ NULL);
+ if (info->authors == NULL)
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Authors' in %s", file);
+
+
+ /* Get Copyright */
+ str = g_key_file_get_string (plugin_file,
+ "Gedit Plugin",
+ "Copyright",
+ NULL);
+ if (str)
+ info->copyright = str;
+ else
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Copyright' in %s", file);
+
+ /* Get Website */
+ str = g_key_file_get_string (plugin_file,
+ "Gedit Plugin",
+ "Website",
+ NULL);
+ if (str)
+ info->website = str;
+ else
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Website' in %s", file);
+
+ /* Get Version */
+ str = g_key_file_get_string (plugin_file,
+ "Gedit Plugin",
+ "Version",
+ NULL);
+ if (str)
+ info->version = str;
+ else
+ gedit_debug_message (DEBUG_PLUGINS, "Could not find 'Version' in %s", file);
+
+ g_key_file_free (plugin_file);
+
+ /* If we know nothing about the availability of the plugin,
+ set it as available */
+ info->available = TRUE;
+
+ return info;
+
+error:
+ g_free (info->file);
+ g_free (info->module_name);
+ g_free (info->name);
+ g_free (info->loader);
+ g_free (info);
+ g_key_file_free (plugin_file);
+
+ return NULL;
+}
+
+gboolean
+gedit_plugin_info_is_active (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ return info->available && info->plugin != NULL;
+}
+
+gboolean
+gedit_plugin_info_is_available (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ return info->available != FALSE;
+}
+
+gboolean
+gedit_plugin_info_is_configurable (GeditPluginInfo *info)
+{
+ gedit_debug_message (DEBUG_PLUGINS, "Is '%s' configurable?", info->name);
+
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ if (info->plugin == NULL || !info->available)
+ return FALSE;
+
+ return gedit_plugin_is_configurable (info->plugin);
+}
+
+const gchar *
+gedit_plugin_info_get_module_name (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info->module_name;
+}
+
+const gchar *
+gedit_plugin_info_get_name (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info->name;
+}
+
+const gchar *
+gedit_plugin_info_get_description (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info->desc;
+}
+
+const gchar *
+gedit_plugin_info_get_icon_name (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ /* use the gedit-plugin icon as a default if the plugin does not
+ have its own */
+ if (info->icon_name != NULL &&
+ gtk_icon_theme_has_icon (gtk_icon_theme_get_default (),
+ info->icon_name))
+ {
+ return info->icon_name;
+ }
+ else
+ {
+ return "gedit-plugin";
+ }
+}
+
+const gchar **
+gedit_plugin_info_get_authors (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, (const gchar **)NULL);
+
+ return (const gchar **) info->authors;
+}
+
+const gchar *
+gedit_plugin_info_get_website (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info->website;
+}
+
+const gchar *
+gedit_plugin_info_get_copyright (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info->copyright;
+}
+
+const gchar *
+gedit_plugin_info_get_version (GeditPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return info->version;
+}
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin-info.h b/gedit/gedit-plugin-info.h
new file mode 100644
index 0000000..cc39a55
--- /dev/null
+++ b/gedit/gedit-plugin-info.h
@@ -0,0 +1,64 @@
+/*
+ * gedit-plugin-info.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002-2005 - Paolo Maggi
+ * Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 2002-2007. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifndef __GEDIT_PLUGIN_INFO_H__
+#define __GEDIT_PLUGIN_INFO_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_PLUGIN_INFO (gedit_plugin_info_get_type ())
+#define GEDIT_PLUGIN_INFO(obj) ((GeditPluginInfo *) (obj))
+
+typedef struct _GeditPluginInfo GeditPluginInfo;
+
+GType gedit_plugin_info_get_type (void) G_GNUC_CONST;
+
+gboolean gedit_plugin_info_is_active (GeditPluginInfo *info);
+gboolean gedit_plugin_info_is_available (GeditPluginInfo *info);
+gboolean gedit_plugin_info_is_configurable (GeditPluginInfo *info);
+
+const gchar *gedit_plugin_info_get_module_name (GeditPluginInfo *info);
+
+const gchar *gedit_plugin_info_get_name (GeditPluginInfo *info);
+const gchar *gedit_plugin_info_get_description (GeditPluginInfo *info);
+const gchar *gedit_plugin_info_get_icon_name (GeditPluginInfo *info);
+const gchar **gedit_plugin_info_get_authors (GeditPluginInfo *info);
+const gchar *gedit_plugin_info_get_website (GeditPluginInfo *info);
+const gchar *gedit_plugin_info_get_copyright (GeditPluginInfo *info);
+const gchar *gedit_plugin_info_get_version (GeditPluginInfo *info);
+
+G_END_DECLS
+
+#endif /* __GEDIT_PLUGIN_INFO_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin-loader.c b/gedit/gedit-plugin-loader.c
new file mode 100644
index 0000000..9f23521
--- /dev/null
+++ b/gedit/gedit-plugin-loader.c
@@ -0,0 +1,132 @@
+/*
+ * gedit-plugin-loader.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gedit-plugin-loader.h"
+
+static void
+gedit_plugin_loader_base_init (gpointer g_class)
+{
+ static gboolean initialized = FALSE;
+
+ if (G_UNLIKELY (!initialized))
+ {
+ /* create interface signals here. */
+ initialized = TRUE;
+ }
+}
+
+GType
+gedit_plugin_loader_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ {
+ static const GTypeInfo info =
+ {
+ sizeof (GeditPluginLoaderInterface),
+ gedit_plugin_loader_base_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "GeditPluginLoader", &info, 0);
+ }
+
+ return type;
+}
+
+const gchar *
+gedit_plugin_loader_type_get_id (GType type)
+{
+ GTypeClass *klass;
+ GeditPluginLoaderInterface *iface;
+
+ klass = g_type_class_ref (type);
+
+ if (klass == NULL)
+ {
+ g_warning ("Could not get class info for plugin loader");
+ return NULL;
+ }
+
+ iface = g_type_interface_peek (klass, GEDIT_TYPE_PLUGIN_LOADER);
+
+ if (iface == NULL)
+ {
+ g_warning ("Could not get plugin loader interface");
+ g_type_class_unref (klass);
+
+ return NULL;
+ }
+
+ g_return_val_if_fail (iface->get_id != NULL, NULL);
+ return iface->get_id ();
+}
+
+GeditPlugin *
+gedit_plugin_loader_load (GeditPluginLoader *loader,
+ GeditPluginInfo *info,
+ const gchar *path)
+{
+ GeditPluginLoaderInterface *iface;
+
+ g_return_val_if_fail (GEDIT_IS_PLUGIN_LOADER (loader), NULL);
+
+ iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
+ g_return_val_if_fail (iface->load != NULL, NULL);
+
+ return iface->load (loader, info, path);
+}
+
+void
+gedit_plugin_loader_unload (GeditPluginLoader *loader,
+ GeditPluginInfo *info)
+{
+ GeditPluginLoaderInterface *iface;
+
+ g_return_if_fail (GEDIT_IS_PLUGIN_LOADER (loader));
+
+ iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
+ g_return_if_fail (iface->unload != NULL);
+
+ iface->unload (loader, info);
+}
+
+void
+gedit_plugin_loader_garbage_collect (GeditPluginLoader *loader)
+{
+ GeditPluginLoaderInterface *iface;
+
+ g_return_if_fail (GEDIT_IS_PLUGIN_LOADER (loader));
+
+ iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
+
+ if (iface->garbage_collect != NULL)
+ iface->garbage_collect (loader);
+}
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin-loader.h b/gedit/gedit-plugin-loader.h
new file mode 100644
index 0000000..4e0c4b2
--- /dev/null
+++ b/gedit/gedit-plugin-loader.h
@@ -0,0 +1,108 @@
+/*
+ * gedit-plugin-loader.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GEDIT_PLUGIN_LOADER_H__
+#define __GEDIT_PLUGIN_LOADER_H__
+
+#include <glib-object.h>
+#include <gedit/gedit-plugin.h>
+#include <gedit/gedit-plugin-info.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_PLUGIN_LOADER (gedit_plugin_loader_get_type ())
+#define GEDIT_PLUGIN_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER, GeditPluginLoader))
+#define GEDIT_IS_PLUGIN_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_PLUGIN_LOADER))
+#define GEDIT_PLUGIN_LOADER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GEDIT_TYPE_PLUGIN_LOADER, GeditPluginLoaderInterface))
+
+typedef struct _GeditPluginLoader GeditPluginLoader; /* dummy object */
+typedef struct _GeditPluginLoaderInterface GeditPluginLoaderInterface;
+
+struct _GeditPluginLoaderInterface {
+ GTypeInterface parent;
+
+ const gchar *(*get_id) (void);
+
+ GeditPlugin *(*load) (GeditPluginLoader *loader,
+ GeditPluginInfo *info,
+ const gchar *path);
+
+ void (*unload) (GeditPluginLoader *loader,
+ GeditPluginInfo *info);
+
+ void (*garbage_collect) (GeditPluginLoader *loader);
+};
+
+GType gedit_plugin_loader_get_type (void);
+
+const gchar *gedit_plugin_loader_type_get_id (GType type);
+GeditPlugin *gedit_plugin_loader_load (GeditPluginLoader *loader,
+ GeditPluginInfo *info,
+ const gchar *path);
+void gedit_plugin_loader_unload (GeditPluginLoader *loader,
+ GeditPluginInfo *info);
+void gedit_plugin_loader_garbage_collect (GeditPluginLoader *loader);
+
+/**
+ * GEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
+ *
+ * Utility macro used to register interfaces for gobject types in plugin loaders.
+ */
+#define GEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) \
+ const GInterfaceInfo g_implement_interface_info = \
+ { \
+ (GInterfaceInitFunc) iface_init, \
+ NULL, \
+ NULL \
+ }; \
+ \
+ g_type_module_add_interface (type_module, \
+ g_define_type_id, \
+ TYPE_IFACE, \
+ &g_implement_interface_info);
+
+/**
+ * GEDIT_PLUGIN_LOADER_REGISTER_TYPE(PluginLoaderName, plugin_loader_name, PARENT_TYPE, loader_interface_init):
+ *
+ * Utility macro used to register plugin loaders.
+ */
+#define GEDIT_PLUGIN_LOADER_REGISTER_TYPE(PluginLoaderName, plugin_loader_name, PARENT_TYPE, loader_iface_init) \
+ G_DEFINE_DYNAMIC_TYPE_EXTENDED (PluginLoaderName, \
+ plugin_loader_name, \
+ PARENT_TYPE, \
+ 0, \
+ GEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(GEDIT_TYPE_PLUGIN_LOADER, loader_iface_init)); \
+ \
+ \
+G_MODULE_EXPORT GType \
+register_gedit_plugin_loader (GTypeModule *type_module) \
+{ \
+ plugin_loader_name##_register_type (type_module); \
+ \
+ return plugin_loader_name##_get_type(); \
+}
+
+G_END_DECLS
+
+#endif /* __GEDIT_PLUGIN_LOADER_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin-manager.c b/gedit/gedit-plugin-manager.c
new file mode 100644
index 0000000..2071332
--- /dev/null
+++ b/gedit/gedit-plugin-manager.c
@@ -0,0 +1,895 @@
+/*
+ * gedit-plugin-manager.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002 Paolo Maggi and James Willcox
+ * Copyright (C) 2003-2006 Paolo Maggi
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 1998-2006. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include "gedit-plugin-manager.h"
+#include "gedit-utils.h"
+#include "gedit-plugins-engine.h"
+#include "gedit-plugin.h"
+#include "gedit-debug.h"
+
+enum
+{
+ ACTIVE_COLUMN,
+ AVAILABLE_COLUMN,
+ INFO_COLUMN,
+ N_COLUMNS
+};
+
+#define PLUGIN_MANAGER_NAME_TITLE _("Plugin")
+#define PLUGIN_MANAGER_ACTIVE_TITLE _("Enabled")
+
+#define GEDIT_PLUGIN_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerPrivate))
+
+struct _GeditPluginManagerPrivate
+{
+ GeditPluginsEngine *engine;
+
+ GtkWidget *tree;
+
+ GtkWidget *about_button;
+ GtkWidget *configure_button;
+
+ GtkWidget *about;
+
+ GtkWidget *popup_menu;
+};
+
+G_DEFINE_TYPE(GeditPluginManager, gedit_plugin_manager, GTK_TYPE_VBOX)
+
+static GeditPluginInfo *plugin_manager_get_selected_plugin (GeditPluginManager *pm);
+static void plugin_manager_toggle_active (GeditPluginManager *pm,
+ GtkTreeIter *iter,
+ GtkTreeModel *model);
+static void gedit_plugin_manager_finalize (GObject *object);
+
+static void
+gedit_plugin_manager_class_init (GeditPluginManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gedit_plugin_manager_finalize;
+
+ g_type_class_add_private (object_class, sizeof (GeditPluginManagerPrivate));
+}
+
+static void
+about_button_cb (GtkWidget *button,
+ GeditPluginManager *pm)
+{
+ GeditPluginInfo *info;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ info = plugin_manager_get_selected_plugin (pm);
+
+ g_return_if_fail (info != NULL);
+
+ /* if there is another about dialog already open destroy it */
+ if (pm->priv->about)
+ gtk_widget_destroy (pm->priv->about);
+
+ pm->priv->about = g_object_new (GTK_TYPE_ABOUT_DIALOG,
+ "program-name", gedit_plugin_info_get_name (info),
+ "copyright", gedit_plugin_info_get_copyright (info),
+ "authors", gedit_plugin_info_get_authors (info),
+ "comments", gedit_plugin_info_get_description (info),
+ "website", gedit_plugin_info_get_website (info),
+ "logo-icon-name", gedit_plugin_info_get_icon_name (info),
+ "version", gedit_plugin_info_get_version (info),
+ NULL);
+
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (pm->priv->about),
+ TRUE);
+
+ g_signal_connect (pm->priv->about,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ g_signal_connect (pm->priv->about,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &pm->priv->about);
+
+ gtk_window_set_transient_for (GTK_WINDOW (pm->priv->about),
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (pm))));
+ gtk_widget_show (pm->priv->about);
+}
+
+static void
+configure_button_cb (GtkWidget *button,
+ GeditPluginManager *pm)
+{
+ GeditPluginInfo *info;
+ GtkWindow *toplevel;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ info = plugin_manager_get_selected_plugin (pm);
+
+ g_return_if_fail (info != NULL);
+
+ gedit_debug_message (DEBUG_PLUGINS, "Configuring: %s\n",
+ gedit_plugin_info_get_name (info));
+
+ toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm)));
+
+ gedit_plugins_engine_configure_plugin (pm->priv->engine,
+ info, toplevel);
+
+ gedit_debug_message (DEBUG_PLUGINS, "Done");
+}
+
+static void
+plugin_manager_view_info_cell_cb (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GeditPluginInfo *info;
+ gchar *text;
+
+ g_return_if_fail (tree_model != NULL);
+ g_return_if_fail (tree_column != NULL);
+
+ gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1);
+
+ if (info == NULL)
+ return;
+
+ text = g_markup_printf_escaped ("<b>%s</b>\n%s",
+ gedit_plugin_info_get_name (info),
+ gedit_plugin_info_get_description (info));
+ g_object_set (G_OBJECT (cell),
+ "markup", text,
+ "sensitive", gedit_plugin_info_is_available (info),
+ NULL);
+
+ g_free (text);
+}
+
+static void
+plugin_manager_view_icon_cell_cb (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GeditPluginInfo *info;
+
+ g_return_if_fail (tree_model != NULL);
+ g_return_if_fail (tree_column != NULL);
+
+ gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1);
+
+ if (info == NULL)
+ return;
+
+ g_object_set (G_OBJECT (cell),
+ "icon-name", gedit_plugin_info_get_icon_name (info),
+ "sensitive", gedit_plugin_info_is_available (info),
+ NULL);
+}
+
+
+static void
+active_toggled_cb (GtkCellRendererToggle *cell,
+ gchar *path_str,
+ GeditPluginManager *pm)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ path = gtk_tree_path_new_from_string (path_str);
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
+ g_return_if_fail (model != NULL);
+
+ gtk_tree_model_get_iter (model, &iter, path);
+
+ if (&iter != NULL)
+ plugin_manager_toggle_active (pm, &iter, model);
+
+ gtk_tree_path_free (path);
+}
+
+static void
+cursor_changed_cb (GtkTreeView *view,
+ GeditPluginManager *pm)
+{
+ GeditPluginInfo *info;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ info = plugin_manager_get_selected_plugin (pm);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->about_button),
+ info != NULL);
+ gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button),
+ (info != NULL) &&
+ gedit_plugin_info_is_configurable (info));
+}
+
+static void
+row_activated_cb (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ GeditPluginManager *pm)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
+
+ g_return_if_fail (model != NULL);
+
+ gtk_tree_model_get_iter (model, &iter, path);
+
+ g_return_if_fail (&iter != NULL);
+
+ plugin_manager_toggle_active (pm, &iter, model);
+}
+
+static void
+plugin_manager_populate_lists (GeditPluginManager *pm)
+{
+ const GList *plugins;
+ GtkListStore *model;
+ GtkTreeIter iter;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ plugins = gedit_plugins_engine_get_plugin_list (pm->priv->engine);
+
+ model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)));
+
+ while (plugins)
+ {
+ GeditPluginInfo *info;
+ info = (GeditPluginInfo *)plugins->data;
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ ACTIVE_COLUMN, gedit_plugin_info_is_active (info),
+ AVAILABLE_COLUMN, gedit_plugin_info_is_available (info),
+ INFO_COLUMN, info,
+ -1);
+
+ plugins = plugins->next;
+ }
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
+ {
+ GtkTreeSelection *selection;
+ GeditPluginInfo* info;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
+ g_return_if_fail (selection != NULL);
+
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
+ INFO_COLUMN, &info, -1);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button),
+ gedit_plugin_info_is_configurable (info));
+ }
+}
+
+static gboolean
+plugin_manager_set_active (GeditPluginManager *pm,
+ GtkTreeIter *iter,
+ GtkTreeModel *model,
+ gboolean active)
+{
+ GeditPluginInfo *info;
+ gboolean res = TRUE;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1);
+
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ if (active)
+ {
+ /* activate the plugin */
+ if (!gedit_plugins_engine_activate_plugin (pm->priv->engine, info))
+ {
+ gedit_debug_message (DEBUG_PLUGINS, "Could not activate %s.\n",
+ gedit_plugin_info_get_name (info));
+
+ res = FALSE;
+ }
+ }
+ else
+ {
+ /* deactivate the plugin */
+ if (!gedit_plugins_engine_deactivate_plugin (pm->priv->engine, info))
+ {
+ gedit_debug_message (DEBUG_PLUGINS, "Could not deactivate %s.\n",
+ gedit_plugin_info_get_name (info));
+
+ res = FALSE;
+ }
+ }
+
+ /* cause the configure button sensitivity to be updated */
+ cursor_changed_cb (GTK_TREE_VIEW (pm->priv->tree), pm);
+
+ return res;
+}
+
+static void
+plugin_manager_toggle_active (GeditPluginManager *pm,
+ GtkTreeIter *iter,
+ GtkTreeModel *model)
+{
+ gboolean active;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ gtk_tree_model_get (model, iter, ACTIVE_COLUMN, &active, -1);
+
+ active ^= 1;
+
+ plugin_manager_set_active (pm, iter, model, active);
+}
+
+static GeditPluginInfo *
+plugin_manager_get_selected_plugin (GeditPluginManager *pm)
+{
+ GeditPluginInfo *info = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
+ g_return_val_if_fail (model != NULL, NULL);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
+ g_return_val_if_fail (selection != NULL, NULL);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+ {
+ gtk_tree_model_get (model, &iter, INFO_COLUMN, &info, -1);
+ }
+
+ return info;
+}
+
+static void
+plugin_manager_set_active_all (GeditPluginManager *pm,
+ gboolean active)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
+
+ g_return_if_fail (model != NULL);
+
+ gtk_tree_model_get_iter_first (model, &iter);
+
+ do
+ {
+ plugin_manager_set_active (pm, &iter, model, active);
+ } while (gtk_tree_model_iter_next (model, &iter));
+}
+
+/* Callback used as the interactive search comparison function */
+static gboolean
+name_search_cb (GtkTreeModel *model,
+ gint column,
+ const gchar *key,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GeditPluginInfo *info;
+ gchar *normalized_string;
+ gchar *normalized_key;
+ gchar *case_normalized_string;
+ gchar *case_normalized_key;
+ gint key_len;
+ gboolean retval;
+
+ gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1);
+ if (!info)
+ return FALSE;
+
+ normalized_string = g_utf8_normalize (gedit_plugin_info_get_name (info), -1, G_NORMALIZE_ALL);
+ normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
+ case_normalized_string = g_utf8_casefold (normalized_string, -1);
+ case_normalized_key = g_utf8_casefold (normalized_key, -1);
+
+ key_len = strlen (case_normalized_key);
+
+ /* Oddly enough, this callback must return whether to stop the search
+ * because we found a match, not whether we actually matched.
+ */
+ retval = (strncmp (case_normalized_key, case_normalized_string, key_len) != 0);
+
+ g_free (normalized_key);
+ g_free (normalized_string);
+ g_free (case_normalized_key);
+ g_free (case_normalized_string);
+
+ return retval;
+}
+
+static void
+enable_plugin_menu_cb (GtkMenu *menu,
+ GeditPluginManager *pm)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
+ g_return_if_fail (model != NULL);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
+ g_return_if_fail (selection != NULL);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+ plugin_manager_toggle_active (pm, &iter, model);
+}
+
+static void
+enable_all_menu_cb (GtkMenu *menu,
+ GeditPluginManager *pm)
+{
+ plugin_manager_set_active_all (pm, TRUE);
+}
+
+static void
+disable_all_menu_cb (GtkMenu *menu,
+ GeditPluginManager *pm)
+{
+ plugin_manager_set_active_all (pm, FALSE);
+}
+
+static GtkWidget *
+create_tree_popup_menu (GeditPluginManager *pm)
+{
+ GtkWidget *menu;
+ GtkWidget *item;
+ GtkWidget *image;
+ GeditPluginInfo *info;
+
+ info = plugin_manager_get_selected_plugin (pm);
+
+ menu = gtk_menu_new ();
+
+ item = gtk_image_menu_item_new_with_mnemonic (_("_About"));
+ image = gtk_image_new_from_stock (GTK_STOCK_ABOUT,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+ g_signal_connect (item, "activate",
+ G_CALLBACK (about_button_cb), pm);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ item = gtk_image_menu_item_new_with_mnemonic (_("C_onfigure"));
+ image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+ g_signal_connect (item, "activate",
+ G_CALLBACK (configure_button_cb), pm);
+ gtk_widget_set_sensitive (item, gedit_plugin_info_is_configurable (info));
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ item = gtk_check_menu_item_new_with_mnemonic (_("A_ctivate"));
+ gtk_widget_set_sensitive (item, gedit_plugin_info_is_available (info));
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
+ gedit_plugin_info_is_active (info));
+ g_signal_connect (item, "toggled",
+ G_CALLBACK (enable_plugin_menu_cb), pm);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("Ac_tivate All"));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (enable_all_menu_cb), pm);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Deactivate All"));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (disable_all_menu_cb), pm);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ gtk_widget_show_all (menu);
+
+ return menu;
+}
+
+static void
+tree_popup_menu_detach (GeditPluginManager *pm,
+ GtkMenu *menu)
+{
+ pm->priv->popup_menu = NULL;
+}
+
+static void
+show_tree_popup_menu (GtkTreeView *tree,
+ GeditPluginManager *pm,
+ GdkEventButton *event)
+{
+ if (pm->priv->popup_menu)
+ gtk_widget_destroy (pm->priv->popup_menu);
+
+ pm->priv->popup_menu = create_tree_popup_menu (pm);
+
+ gtk_menu_attach_to_widget (GTK_MENU (pm->priv->popup_menu),
+ GTK_WIDGET (pm),
+ (GtkMenuDetachFunc) tree_popup_menu_detach);
+
+ if (event != NULL)
+ {
+ gtk_menu_popup (GTK_MENU (pm->priv->popup_menu), NULL, NULL,
+ NULL, NULL,
+ event->button, event->time);
+ }
+ else
+ {
+ gtk_menu_popup (GTK_MENU (pm->priv->popup_menu), NULL, NULL,
+ gedit_utils_menu_position_under_tree_view, tree,
+ 0, gtk_get_current_event_time ());
+
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (pm->priv->popup_menu),
+ FALSE);
+ }
+}
+
+static gboolean
+button_press_event_cb (GtkWidget *tree,
+ GdkEventButton *event,
+ GeditPluginManager *pm)
+{
+ /* We want the treeview selection to be updated before showing the menu.
+ * This code is evil, thanks to Federico Mena Quintero's black magic.
+ * See: http://mail.gnome.org/archives/gtk-devel-list/2006-February/msg00168.html
+ * FIXME: Let's remove it asap.
+ */
+
+ static gboolean in_press = FALSE;
+ gboolean handled;
+
+ if (in_press)
+ return FALSE; /* we re-entered */
+
+ if (GDK_BUTTON_PRESS != event->type || 3 != event->button)
+ return FALSE; /* let the normal handler run */
+
+ in_press = TRUE;
+ handled = gtk_widget_event (tree, (GdkEvent *) event);
+ in_press = FALSE;
+
+ if (!handled)
+ return FALSE;
+
+ /* The selection is fully updated by now */
+ show_tree_popup_menu (GTK_TREE_VIEW (tree), pm, event);
+ return TRUE;
+}
+
+static gboolean
+popup_menu_cb (GtkTreeView *tree,
+ GeditPluginManager *pm)
+{
+ show_tree_popup_menu (tree, pm, NULL);
+ return TRUE;
+}
+
+static gint
+model_name_sort_func (GtkTreeModel *model,
+ GtkTreeIter *iter1,
+ GtkTreeIter *iter2,
+ gpointer user_data)
+{
+ GeditPluginInfo *info1, *info2;
+
+ gtk_tree_model_get (model, iter1, INFO_COLUMN, &info1, -1);
+ gtk_tree_model_get (model, iter2, INFO_COLUMN, &info2, -1);
+
+ return g_utf8_collate (gedit_plugin_info_get_name (info1),
+ gedit_plugin_info_get_name (info2));
+}
+
+static void
+plugin_manager_construct_tree (GeditPluginManager *pm)
+{
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell;
+ GtkListStore *model;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ model = gtk_list_store_new (N_COLUMNS,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_POINTER);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (pm->priv->tree),
+ GTK_TREE_MODEL (model));
+ g_object_unref (model);
+
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm->priv->tree), TRUE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pm->priv->tree), FALSE);
+
+ /* first column */
+ cell = gtk_cell_renderer_toggle_new ();
+ g_object_set (cell, "xpad", 6, NULL);
+ g_signal_connect (cell,
+ "toggled",
+ G_CALLBACK (active_toggled_cb),
+ pm);
+ column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE,
+ cell,
+ "active",
+ ACTIVE_COLUMN,
+ "activatable",
+ AVAILABLE_COLUMN,
+ "sensitive",
+ AVAILABLE_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column);
+
+ /* second column */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, PLUGIN_MANAGER_NAME_TITLE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, cell, FALSE);
+ g_object_set (cell, "stock-size", GTK_ICON_SIZE_SMALL_TOOLBAR, NULL);
+ gtk_tree_view_column_set_cell_data_func (column, cell,
+ plugin_manager_view_icon_cell_cb,
+ pm, NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_set_cell_data_func (column, cell,
+ plugin_manager_view_info_cell_cb,
+ pm, NULL);
+
+
+ gtk_tree_view_column_set_spacing (column, 6);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column);
+
+ /* Sort on the plugin names */
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
+ model_name_sort_func,
+ NULL,
+ NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+ GTK_SORT_ASCENDING);
+
+ /* Enable search for our non-string column */
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm->priv->tree),
+ INFO_COLUMN);
+ gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm->priv->tree),
+ name_search_cb,
+ NULL,
+ NULL);
+
+ g_signal_connect (pm->priv->tree,
+ "cursor-changed",
+ G_CALLBACK (cursor_changed_cb),
+ pm);
+ g_signal_connect (pm->priv->tree,
+ "row-activated",
+ G_CALLBACK (row_activated_cb),
+ pm);
+
+ g_signal_connect (pm->priv->tree,
+ "button-press-event",
+ G_CALLBACK (button_press_event_cb),
+ pm);
+ g_signal_connect (pm->priv->tree,
+ "popup-menu",
+ G_CALLBACK (popup_menu_cb),
+ pm);
+ gtk_widget_show (pm->priv->tree);
+}
+
+static void
+plugin_toggled_cb (GeditPluginsEngine *engine,
+ GeditPluginInfo *info,
+ GeditPluginManager *pm)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean info_found = FALSE;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ {
+ /* There is an item selected: it's probably the one we want! */
+ GeditPluginInfo *tinfo;
+ gtk_tree_model_get (model, &iter, INFO_COLUMN, &tinfo, -1);
+ info_found = info == tinfo;
+ }
+
+ if (!info_found)
+ {
+ gtk_tree_model_get_iter_first (model, &iter);
+
+ do
+ {
+ GeditPluginInfo *tinfo;
+ gtk_tree_model_get (model, &iter, INFO_COLUMN, &tinfo, -1);
+ info_found = info == tinfo;
+ } while (!info_found && gtk_tree_model_iter_next (model, &iter));
+ }
+
+ if (!info_found)
+ {
+ g_warning ("GeditPluginManager: plugin '%s' not found in the tree model",
+ gedit_plugin_info_get_name (info));
+ return;
+ }
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ ACTIVE_COLUMN, gedit_plugin_info_is_active (info),
+ -1);
+}
+
+static void
+gedit_plugin_manager_init (GeditPluginManager *pm)
+{
+ GtkWidget *label;
+ GtkWidget *viewport;
+ GtkWidget *hbuttonbox;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ pm->priv = GEDIT_PLUGIN_MANAGER_GET_PRIVATE (pm);
+
+ /* Before we create the manager, we rescan the plugins directory */
+ gedit_plugins_engine_rescan_plugins (gedit_plugins_engine_get_default ());
+
+ gtk_box_set_spacing (GTK_BOX (pm), 6);
+
+ label = gtk_label_new_with_mnemonic (_("Active _Plugins:"));
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+ gtk_box_pack_start (GTK_BOX (pm), label, FALSE, TRUE, 0);
+
+ viewport = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (viewport),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (viewport),
+ GTK_SHADOW_IN);
+
+ gtk_box_pack_start (GTK_BOX (pm), viewport, TRUE, TRUE, 0);
+
+ pm->priv->tree = gtk_tree_view_new ();
+ gtk_container_add (GTK_CONTAINER (viewport), pm->priv->tree);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), pm->priv->tree);
+
+ hbuttonbox = gtk_hbutton_box_new ();
+ gtk_box_pack_start (GTK_BOX (pm), hbuttonbox, FALSE, FALSE, 0);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing (GTK_BOX (hbuttonbox), 8);
+
+ pm->priv->about_button = gedit_gtk_button_new_with_stock_icon (_("_About Plugin"),
+ GTK_STOCK_ABOUT);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->about_button);
+
+ pm->priv->configure_button = gedit_gtk_button_new_with_stock_icon (_("C_onfigure Plugin"),
+ GTK_STOCK_PREFERENCES);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->configure_button);
+
+ /* Set a sane size for the window */
+ gtk_widget_set_size_request (GTK_WIDGET (viewport), 270, 100);
+
+ g_signal_connect (pm->priv->about_button,
+ "clicked",
+ G_CALLBACK (about_button_cb),
+ pm);
+ g_signal_connect (pm->priv->configure_button,
+ "clicked",
+ G_CALLBACK (configure_button_cb),
+ pm);
+
+ plugin_manager_construct_tree (pm);
+
+ /* get the plugin engine and populate the treeview */
+ pm->priv->engine = gedit_plugins_engine_get_default ();
+
+ g_signal_connect_after (pm->priv->engine,
+ "activate-plugin",
+ G_CALLBACK (plugin_toggled_cb),
+ pm);
+ g_signal_connect_after (pm->priv->engine,
+ "deactivate-plugin",
+ G_CALLBACK (plugin_toggled_cb),
+ pm);
+
+ if (gedit_plugins_engine_get_plugin_list (pm->priv->engine) != NULL)
+ {
+ plugin_manager_populate_lists (pm);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (pm->priv->about_button, FALSE);
+ gtk_widget_set_sensitive (pm->priv->configure_button, FALSE);
+ }
+}
+
+static void
+gedit_plugin_manager_finalize (GObject *object)
+{
+ GeditPluginManager *pm = GEDIT_PLUGIN_MANAGER (object);
+
+ g_signal_handlers_disconnect_by_func (pm->priv->engine,
+ plugin_toggled_cb,
+ pm);
+
+ if (pm->priv->popup_menu)
+ gtk_widget_destroy (pm->priv->popup_menu);
+
+ G_OBJECT_CLASS (gedit_plugin_manager_parent_class)->finalize (object);
+
+}
+
+GtkWidget *gedit_plugin_manager_new (void)
+{
+ return g_object_new (GEDIT_TYPE_PLUGIN_MANAGER,0);
+}
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin-manager.h b/gedit/gedit-plugin-manager.h
new file mode 100644
index 0000000..00963b2
--- /dev/null
+++ b/gedit/gedit-plugin-manager.h
@@ -0,0 +1,85 @@
+/*
+ * gedit-plugin-manager.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002-2005 Paolo Maggi
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifndef __GEDIT_PLUGIN_MANAGER_H__
+#define __GEDIT_PLUGIN_MANAGER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GEDIT_TYPE_PLUGIN_MANAGER (gedit_plugin_manager_get_type())
+#define GEDIT_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManager))
+#define GEDIT_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerClass))
+#define GEDIT_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGIN_MANAGER))
+#define GEDIT_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN_MANAGER))
+#define GEDIT_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGIN_MANAGER, GeditPluginManagerClass))
+
+/* Private structure type */
+typedef struct _GeditPluginManagerPrivate GeditPluginManagerPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GeditPluginManager GeditPluginManager;
+
+struct _GeditPluginManager
+{
+ GtkVBox vbox;
+
+ /*< private > */
+ GeditPluginManagerPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GeditPluginManagerClass GeditPluginManagerClass;
+
+struct _GeditPluginManagerClass
+{
+ GtkVBoxClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType gedit_plugin_manager_get_type (void) G_GNUC_CONST;
+
+GtkWidget *gedit_plugin_manager_new (void);
+
+G_END_DECLS
+
+#endif /* __GEDIT_PLUGIN_MANAGER_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin.c b/gedit/gedit-plugin.c
new file mode 100644
index 0000000..d27896c
--- /dev/null
+++ b/gedit/gedit-plugin.c
@@ -0,0 +1,339 @@
+/*
+ * gedit-plugin.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002-2005 Paolo Maggi
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gedit-plugin.h"
+#include "gedit-dirs.h"
+
+/* properties */
+enum {
+ PROP_0,
+ PROP_INSTALL_DIR,
+ PROP_DATA_DIR_NAME,
+ PROP_DATA_DIR
+};
+
+typedef struct _GeditPluginPrivate GeditPluginPrivate;
+
+struct _GeditPluginPrivate
+{
+ gchar *install_dir;
+ gchar *data_dir_name;
+};
+
+#define GEDIT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_PLUGIN, GeditPluginPrivate))
+
+G_DEFINE_TYPE(GeditPlugin, gedit_plugin, G_TYPE_OBJECT)
+
+static void
+dummy (GeditPlugin *plugin,
+ GeditWindow *window)
+{
+ /* Empty */
+}
+
+static GtkWidget *
+create_configure_dialog (GeditPlugin *plugin)
+{
+ return NULL;
+}
+
+static gboolean
+is_configurable (GeditPlugin *plugin)
+{
+ return (GEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog !=
+ create_configure_dialog);
+}
+
+static void
+gedit_plugin_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_INSTALL_DIR:
+ g_value_take_string (value, gedit_plugin_get_install_dir (GEDIT_PLUGIN (object)));
+ break;
+ case PROP_DATA_DIR:
+ g_value_take_string (value, gedit_plugin_get_data_dir (GEDIT_PLUGIN (object)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_plugin_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditPluginPrivate *priv = GEDIT_PLUGIN_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_INSTALL_DIR:
+ priv->install_dir = g_value_dup_string (value);
+ break;
+ case PROP_DATA_DIR_NAME:
+ priv->data_dir_name = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_plugin_finalize (GObject *object)
+{
+ GeditPluginPrivate *priv = GEDIT_PLUGIN_GET_PRIVATE (object);
+
+ g_free (priv->install_dir);
+ g_free (priv->data_dir_name);
+
+ G_OBJECT_CLASS (gedit_plugin_parent_class)->finalize (object);
+}
+
+static void
+gedit_plugin_class_init (GeditPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ klass->activate = dummy;
+ klass->deactivate = dummy;
+ klass->update_ui = dummy;
+
+ klass->create_configure_dialog = create_configure_dialog;
+ klass->is_configurable = is_configurable;
+
+ object_class->get_property = gedit_plugin_get_property;
+ object_class->set_property = gedit_plugin_set_property;
+ object_class->finalize = gedit_plugin_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_INSTALL_DIR,
+ g_param_spec_string ("install-dir",
+ "Install Directory",
+ "The directory where the plugin is installed",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /* the basename of the data dir is set at construction time by the plugin loader
+ * while the full path is constructed on the fly to take into account relocability
+ * that's why we have a writeonly prop and a readonly prop */
+ g_object_class_install_property (object_class,
+ PROP_DATA_DIR_NAME,
+ g_param_spec_string ("data-dir-name",
+ "Basename of the data directory",
+ "The basename of the directory where the plugin should look for its data files",
+ NULL,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_DATA_DIR,
+ g_param_spec_string ("data-dir",
+ "Data Directory",
+ "The full path of the directory where the plugin should look for its data files",
+ NULL,
+ G_PARAM_READABLE));
+
+ g_type_class_add_private (klass, sizeof (GeditPluginPrivate));
+}
+
+static void
+gedit_plugin_init (GeditPlugin *plugin)
+{
+ /* Empty */
+}
+
+/**
+ * gedit_plugin_get_install_dir:
+ * @plugin: a #GeditPlugin
+ *
+ * Get the path of the directory where the plugin is installed.
+ *
+ * Return value: a newly allocated string with the path of the
+ * directory where the plugin is installed
+ */
+gchar *
+gedit_plugin_get_install_dir (GeditPlugin *plugin)
+{
+ g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL);
+
+ return g_strdup (GEDIT_PLUGIN_GET_PRIVATE (plugin)->install_dir);
+}
+
+/**
+ * gedit_plugin_get_data_dir:
+ * @plugin: a #GeditPlugin
+ *
+ * Get the path of the directory where the plugin should look for
+ * its data files.
+ *
+ * Return value: a newly allocated string with the path of the
+ * directory where the plugin should look for its data files
+ */
+gchar *
+gedit_plugin_get_data_dir (GeditPlugin *plugin)
+{
+ GeditPluginPrivate *priv;
+ gchar *gedit_lib_dir;
+ gchar *data_dir;
+
+ g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL);
+
+ priv = GEDIT_PLUGIN_GET_PRIVATE (plugin);
+
+ /* If it's a "user" plugin the data dir is
+ * install_dir/data_dir_name if instead it's a
+ * "system" plugin the data dir is under gedit_data_dir,
+ * so it's under $prefix/share/gedit-2/plugins/data_dir_name
+ * where data_dir_name usually it's the name of the plugin
+ */
+ gedit_lib_dir = gedit_dirs_get_gedit_lib_dir ();
+
+ /* CHECK: is checking the prefix enough or should we be more
+ * careful about normalizing paths etc? */
+ if (g_str_has_prefix (priv->install_dir, gedit_lib_dir))
+ {
+ gchar *gedit_data_dir;
+
+ gedit_data_dir = gedit_dirs_get_gedit_data_dir ();
+
+ data_dir = g_build_filename (gedit_data_dir,
+ "plugins",
+ priv->data_dir_name,
+ NULL);
+
+ g_free (gedit_data_dir);
+ }
+ else
+ {
+ data_dir = g_build_filename (priv->install_dir,
+ priv->data_dir_name,
+ NULL);
+ }
+
+ g_free (gedit_lib_dir);
+
+ return data_dir;
+}
+
+/**
+ * gedit_plugin_activate:
+ * @plugin: a #GeditPlugin
+ * @window: a #GeditWindow
+ *
+ * Activates the plugin.
+ */
+void
+gedit_plugin_activate (GeditPlugin *plugin,
+ GeditWindow *window)
+{
+ g_return_if_fail (GEDIT_IS_PLUGIN (plugin));
+ g_return_if_fail (GEDIT_IS_WINDOW (window));
+
+ GEDIT_PLUGIN_GET_CLASS (plugin)->activate (plugin, window);
+}
+
+/**
+ * gedit_plugin_deactivate:
+ * @plugin: a #GeditPlugin
+ * @window: a #GeditWindow
+ *
+ * Deactivates the plugin.
+ */
+void
+gedit_plugin_deactivate (GeditPlugin *plugin,
+ GeditWindow *window)
+{
+ g_return_if_fail (GEDIT_IS_PLUGIN (plugin));
+ g_return_if_fail (GEDIT_IS_WINDOW (window));
+
+ GEDIT_PLUGIN_GET_CLASS (plugin)->deactivate (plugin, window);
+}
+
+/**
+ * gedit_plugin_update_ui:
+ * @plugin: a #GeditPlugin
+ * @window: a #GeditWindow
+ *
+ * Triggers an update of the user interface to take into account state changes
+ * caused by the plugin.
+ */
+void
+gedit_plugin_update_ui (GeditPlugin *plugin,
+ GeditWindow *window)
+{
+ g_return_if_fail (GEDIT_IS_PLUGIN (plugin));
+ g_return_if_fail (GEDIT_IS_WINDOW (window));
+
+ GEDIT_PLUGIN_GET_CLASS (plugin)->update_ui (plugin, window);
+}
+
+/**
+ * gedit_plugin_is_configurable:
+ * @plugin: a #GeditPlugin
+ *
+ * Whether the plugin is configurable.
+ *
+ * Returns: TRUE if the plugin is configurable:
+ */
+gboolean
+gedit_plugin_is_configurable (GeditPlugin *plugin)
+{
+ g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), FALSE);
+
+ return GEDIT_PLUGIN_GET_CLASS (plugin)->is_configurable (plugin);
+}
+
+/**
+ * gedit_plugin_create_configure_dialog:
+ * @plugin: a #GeditPlugin
+ *
+ * Creates the configure dialog widget for the plugin.
+ *
+ * Returns: the configure dialog widget for the plugin.
+ */
+GtkWidget *
+gedit_plugin_create_configure_dialog (GeditPlugin *plugin)
+{
+ g_return_val_if_fail (GEDIT_IS_PLUGIN (plugin), NULL);
+
+ return GEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog (plugin);
+}
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugin.h b/gedit/gedit-plugin.h
new file mode 100644
index 0000000..87f06d3
--- /dev/null
+++ b/gedit/gedit-plugin.h
@@ -0,0 +1,242 @@
+/*
+ * gedit-plugin.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2002-2005 - Paolo Maggi
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the gedit Team, 2002-2005. See the AUTHORS file for a
+ * list of people on the gedit Team.
+ * See the ChangeLog files for a list of changes.
+ *
+ * $Id$
+ */
+
+#ifndef __GEDIT_PLUGIN_H__
+#define __GEDIT_PLUGIN_H__
+
+#include <glib-object.h>
+
+#include <gedit/gedit-window.h>
+#include <gedit/gedit-debug.h>
+
+/* TODO: add a .h file that includes all the .h files normally needed to
+ * develop a plugin */
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GEDIT_TYPE_PLUGIN (gedit_plugin_get_type())
+#define GEDIT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GEDIT_TYPE_PLUGIN, GeditPlugin))
+#define GEDIT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GEDIT_TYPE_PLUGIN, GeditPluginClass))
+#define GEDIT_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GEDIT_TYPE_PLUGIN))
+#define GEDIT_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN))
+#define GEDIT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_PLUGIN, GeditPluginClass))
+
+/*
+ * Main object structure
+ */
+typedef struct _GeditPlugin GeditPlugin;
+
+struct _GeditPlugin
+{
+ GObject parent;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GeditPluginClass GeditPluginClass;
+
+struct _GeditPluginClass
+{
+ GObjectClass parent_class;
+
+ /* Virtual public methods */
+
+ void (*activate) (GeditPlugin *plugin,
+ GeditWindow *window);
+ void (*deactivate) (GeditPlugin *plugin,
+ GeditWindow *window);
+
+ void (*update_ui) (GeditPlugin *plugin,
+ GeditWindow *window);
+
+ GtkWidget *(*create_configure_dialog)
+ (GeditPlugin *plugin);
+
+ /* Plugins should not override this, it's handled automatically by
+ the GeditPluginClass */
+ gboolean (*is_configurable)
+ (GeditPlugin *plugin);
+
+ /* Padding for future expansion */
+ void (*_gedit_reserved1) (void);
+ void (*_gedit_reserved2) (void);
+ void (*_gedit_reserved3) (void);
+ void (*_gedit_reserved4) (void);
+};
+
+/*
+ * Public methods
+ */
+GType gedit_plugin_get_type (void) G_GNUC_CONST;
+
+gchar *gedit_plugin_get_install_dir (GeditPlugin *plugin);
+gchar *gedit_plugin_get_data_dir (GeditPlugin *plugin);
+
+void gedit_plugin_activate (GeditPlugin *plugin,
+ GeditWindow *window);
+void gedit_plugin_deactivate (GeditPlugin *plugin,
+ GeditWindow *window);
+
+void gedit_plugin_update_ui (GeditPlugin *plugin,
+ GeditWindow *window);
+
+gboolean gedit_plugin_is_configurable (GeditPlugin *plugin);
+GtkWidget *gedit_plugin_create_configure_dialog
+ (GeditPlugin *plugin);
+
+/**
+ * GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE):
+ *
+ * Utility macro used to register plugins with additional code.
+ */
+#define GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE) \
+ G_DEFINE_DYNAMIC_TYPE_EXTENDED (PluginName, \
+ plugin_name, \
+ GEDIT_TYPE_PLUGIN, \
+ 0, \
+ GTypeModule *module G_GNUC_UNUSED = type_module; /* back compat */ \
+ CODE) \
+ \
+/* This is not very nice, but G_DEFINE_DYNAMIC wants it and our old macro \
+ * did not support it */ \
+static void \
+plugin_name##_class_finalize (PluginName##Class *klass) \
+{ \
+} \
+ \
+ \
+G_MODULE_EXPORT GType \
+register_gedit_plugin (GTypeModule *type_module) \
+{ \
+ plugin_name##_register_type (type_module); \
+ \
+ return plugin_name##_get_type(); \
+}
+
+/**
+ * GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name):
+ *
+ * Utility macro used to register plugins.
+ */
+#define GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name) \
+ GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, ;)
+
+/**
+ * GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE):
+ *
+ * Utility macro used to register gobject types in plugins with additional code.
+ *
+ * Deprecated: use G_DEFINE_DYNAMIC_TYPE_EXTENDED instead
+ */
+#define GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE) \
+ \
+static GType g_define_type_id = 0; \
+ \
+GType \
+object_name##_get_type (void) \
+{ \
+ return g_define_type_id; \
+} \
+ \
+static void object_name##_init (ObjectName *self); \
+static void object_name##_class_init (ObjectName##Class *klass); \
+static gpointer object_name##_parent_class = NULL; \
+static void object_name##_class_intern_init (gpointer klass) \
+{ \
+ object_name##_parent_class = g_type_class_peek_parent (klass); \
+ object_name##_class_init ((ObjectName##Class *) klass); \
+} \
+ \
+GType \
+object_name##_register_type (GTypeModule *type_module) \
+{ \
+ GTypeModule *module G_GNUC_UNUSED = type_module; /* back compat */ \
+ static const GTypeInfo our_info = \
+ { \
+ sizeof (ObjectName##Class), \
+ NULL, /* base_init */ \
+ NULL, /* base_finalize */ \
+ (GClassInitFunc) object_name##_class_intern_init, \
+ NULL, \
+ NULL, /* class_data */ \
+ sizeof (ObjectName), \
+ 0, /* n_preallocs */ \
+ (GInstanceInitFunc) object_name##_init \
+ }; \
+ \
+ g_define_type_id = g_type_module_register_type (type_module, \
+ PARENT_TYPE, \
+ #ObjectName, \
+ &our_info, \
+ 0); \
+ \
+ CODE \
+ \
+ return g_define_type_id; \
+}
+
+
+/**
+ * GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE):
+ *
+ * Utility macro used to register gobject types in plugins.
+ *
+ * Deprecated: use G_DEFINE_DYNAMIC instead
+ */
+#define GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE) \
+ GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, ;)
+
+/**
+ * GEDIT_PLUGIN_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
+ *
+ * Utility macro used to register interfaces for gobject types in plugins.
+ */
+#define GEDIT_PLUGIN_IMPLEMENT_INTERFACE(object_name, TYPE_IFACE, iface_init) \
+ const GInterfaceInfo object_name##_interface_info = \
+ { \
+ (GInterfaceInitFunc) iface_init, \
+ NULL, \
+ NULL \
+ }; \
+ \
+ g_type_module_add_interface (type_module, \
+ g_define_type_id, \
+ TYPE_IFACE, \
+ &object_name##_interface_info);
+
+G_END_DECLS
+
+#endif /* __GEDIT_PLUGIN_H__ */
+
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugins-engine.c b/gedit/gedit-plugins-engine.c
index 3d9a6e2..8902662 100644
--- a/gedit/gedit-plugins-engine.c
+++ b/gedit/gedit-plugins-engine.c
@@ -3,7 +3,6 @@
* This file is part of gedit
*
* Copyright (C) 2002-2005 Paolo Maggi
- * Copyright (C) 2010 Steve Frécinaux
*
* 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
@@ -36,11 +35,14 @@
#include <string.h>
#include <glib/gi18n.h>
-#include <girepository.h>
#include "gedit-plugins-engine.h"
+#include "gedit-plugin-info-priv.h"
+#include "gedit-plugin.h"
#include "gedit-debug.h"
#include "gedit-app.h"
+#include "gedit-plugin-loader.h"
+#include "gedit-object-module.h"
#include "gedit-dirs.h"
#include "gedit-settings.h"
#include "gedit-utils.h"
@@ -48,152 +50,852 @@
#define GEDIT_PLUGINS_ENGINE_BASE_KEY "/apps/gedit-2/plugins"
#define GEDIT_PLUGINS_ENGINE_KEY GEDIT_PLUGINS_ENGINE_BASE_KEY "/active-plugins"
-G_DEFINE_TYPE(GeditPluginsEngine, gedit_plugins_engine, PEAS_TYPE_ENGINE)
+#define PLUGIN_EXT ".gedit-plugin"
+#define LOADER_EXT G_MODULE_SUFFIX
+
+typedef struct
+{
+ GeditPluginLoader *loader;
+ GeditObjectModule *module;
+} LoaderInfo;
+
+/* Signals */
+enum
+{
+ ACTIVATE_PLUGIN,
+ DEACTIVATE_PLUGIN,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE(GeditPluginsEngine, gedit_plugins_engine, G_TYPE_OBJECT)
struct _GeditPluginsEnginePrivate
{
GSettings *plugin_settings;
- gboolean setting_active_plugins;
+
+ GList *plugin_list;
+ GHashTable *loaders;
+
+ gboolean activate_from_prefs;
+
+ guint scanned : 1;
};
GeditPluginsEngine *default_engine = NULL;
-static void
-gedit_plugins_engine_init (GeditPluginsEngine *engine)
+static void gedit_plugins_engine_activate_plugin_real (GeditPluginsEngine *engine,
+ GeditPluginInfo *info);
+static void gedit_plugins_engine_deactivate_plugin_real (GeditPluginsEngine *engine,
+ GeditPluginInfo *info);
+
+typedef gboolean (*LoadDirCallback)(GeditPluginsEngine *engine, const gchar *filename, gpointer userdata);
+
+static gboolean
+load_dir_real (GeditPluginsEngine *engine,
+ const gchar *dir,
+ const gchar *suffix,
+ LoadDirCallback callback,
+ gpointer userdata)
{
- gedit_debug (DEBUG_PLUGINS);
+ GError *error = NULL;
+ GDir *d;
+ const gchar *dirent;
+ gboolean ret = TRUE;
- engine->priv = G_TYPE_INSTANCE_GET_PRIVATE (engine,
- GEDIT_TYPE_PLUGINS_ENGINE,
- GeditPluginsEnginePrivate);
+ g_return_val_if_fail (dir != NULL, TRUE);
- engine->priv->plugin_settings = g_settings_new ("org.gnome.gedit.plugins");
+ gedit_debug_message (DEBUG_PLUGINS, "DIR: %s", dir);
+
+ d = g_dir_open (dir, 0, &error);
+ if (!d)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return TRUE;
+ }
+
+ while ((dirent = g_dir_read_name (d)))
+ {
+ gchar *filename;
+
+ if (!g_str_has_suffix (dirent, suffix))
+ continue;
+
+ filename = g_build_filename (dir, dirent, NULL);
+
+ ret = callback (engine, filename, userdata);
+
+ g_free (filename);
- engine->priv->setting_active_plugins = FALSE;
+ if (!ret)
+ break;
+ }
+
+ g_dir_close (d);
+ return ret;
}
-static void
-save_active_plugin_list (PeasEngine *engine)
+static gboolean
+load_plugin_info (GeditPluginsEngine *engine,
+ const gchar *filename,
+ gpointer userdata)
{
- GeditPluginsEngine *gengine = GEDIT_PLUGINS_ENGINE (engine);
- gchar **active_plugins;
+ GeditPluginInfo *info;
+
+ info = _gedit_plugin_info_new (filename);
+
+ if (info == NULL)
+ return TRUE;
- active_plugins = peas_engine_get_active_plugins (engine);
+ /* If a plugin with this name has already been loaded
+ * drop this one (user plugins override system plugins) */
+ if (gedit_plugins_engine_get_plugin_info (engine, gedit_plugin_info_get_module_name (info)) != NULL)
+ {
+ gedit_debug_message (DEBUG_PLUGINS, "Two or more plugins named '%s'. "
+ "Only the first will be considered.\n",
+ gedit_plugin_info_get_module_name (info));
- g_settings_set_strv (gengine->priv->plugin_settings,
- GEDIT_SETTINGS_ACTIVE_PLUGINS,
- (const gchar * const *) active_plugins);
+ _gedit_plugin_info_unref (info);
- g_strfreev (active_plugins);
+ return TRUE;
+ }
+
+ engine->priv->plugin_list = g_list_prepend (engine->priv->plugin_list, info);
+
+ gedit_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name);
+ return TRUE;
}
static void
-gedit_plugins_engine_activate_plugin (PeasEngine *engine,
- PeasPluginInfo *info)
+load_all_plugins (GeditPluginsEngine *engine)
+{
+ gchar *plugin_dir;
+ const gchar *pdirs_env = NULL;
+
+ /* load user plugins */
+ plugin_dir = gedit_dirs_get_user_plugins_dir ();
+ if (g_file_test (plugin_dir, G_FILE_TEST_IS_DIR))
+ {
+ load_dir_real (engine,
+ plugin_dir,
+ PLUGIN_EXT,
+ load_plugin_info,
+ NULL);
+
+ }
+ g_free (plugin_dir);
+
+ /* load system plugins */
+ pdirs_env = g_getenv ("GEDIT_PLUGINS_PATH");
+
+ gedit_debug_message (DEBUG_PLUGINS, "GEDIT_PLUGINS_PATH=%s", pdirs_env);
+
+ if (pdirs_env != NULL)
+ {
+ gchar **pdirs;
+ gint i;
+
+ pdirs = g_strsplit (pdirs_env, G_SEARCHPATH_SEPARATOR_S, 0);
+
+ for (i = 0; pdirs[i] != NULL; i++)
+ {
+ if (!load_dir_real (engine,
+ pdirs[i],
+ PLUGIN_EXT,
+ load_plugin_info,
+ NULL))
+ {
+ break;
+ }
+ }
+
+ g_strfreev (pdirs);
+ }
+ else
+ {
+ plugin_dir = gedit_dirs_get_gedit_plugins_dir ();
+
+ load_dir_real (engine,
+ plugin_dir,
+ PLUGIN_EXT,
+ load_plugin_info,
+ NULL);
+
+ g_free (plugin_dir);
+ }
+}
+
+static guint
+hash_lowercase (gconstpointer data)
+{
+ gchar *lowercase;
+ guint ret;
+
+ lowercase = g_ascii_strdown ((const gchar *)data, -1);
+ ret = g_str_hash (lowercase);
+ g_free (lowercase);
+
+ return ret;
+}
+
+static gboolean
+equal_lowercase (gconstpointer a, gconstpointer b)
{
- PEAS_ENGINE_CLASS (gedit_plugins_engine_parent_class)->activate_plugin (engine, info);
+ return g_ascii_strcasecmp ((const gchar *)a, (const gchar *)b) == 0;
+}
- /* We won't save the plugin list if we are currently activating the
- * plugins from the saved list */
- if (GEDIT_PLUGINS_ENGINE (engine)->priv->setting_active_plugins)
+static void
+loader_destroy (LoaderInfo *info)
+{
+ if (!info)
return;
+
+ if (info->loader)
+ g_object_unref (info->loader);
+
+ g_free (info);
+}
- if (peas_plugin_info_is_active (info))
- save_active_plugin_list (engine);
+static void
+add_loader (GeditPluginsEngine *engine,
+ const gchar *loader_id,
+ GeditObjectModule *module)
+{
+ LoaderInfo *info;
+
+ info = g_new (LoaderInfo, 1);
+ info->loader = NULL;
+ info->module = module;
+
+ g_hash_table_insert (engine->priv->loaders, g_strdup (loader_id), info);
}
static void
-gedit_plugins_engine_deactivate_plugin (PeasEngine *engine,
- PeasPluginInfo *info)
+gedit_plugins_engine_init (GeditPluginsEngine *engine)
{
- PEAS_ENGINE_CLASS (gedit_plugins_engine_parent_class)->deactivate_plugin (engine, info);
+ gedit_debug (DEBUG_PLUGINS);
- /* We won't save the plugin list if we are currently deactivating the
- * plugins from the saved list */
- if (GEDIT_PLUGINS_ENGINE (engine)->priv->setting_active_plugins)
+ if (!g_module_supported ())
+ {
+ g_warning ("gedit is not able to initialize the plugins engine.");
return;
+ }
- if (!peas_plugin_info_is_active (info))
- save_active_plugin_list (engine);
+ engine->priv = G_TYPE_INSTANCE_GET_PRIVATE (engine,
+ GEDIT_TYPE_PLUGINS_ENGINE,
+ GeditPluginsEnginePrivate);
+
+ engine->priv->plugin_settings = g_settings_new ("org.gnome.gedit.plugins");
+
+ load_all_plugins (engine);
+
+ /* make sure that the first reactivation will read active plugins
+ from the prefs */
+ engine->priv->activate_from_prefs = TRUE;
+
+ /* mapping from loadername -> loader object */
+ engine->priv->loaders = g_hash_table_new_full (hash_lowercase,
+ equal_lowercase,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)loader_destroy);
+}
+
+static void
+loader_garbage_collect (const char *id, LoaderInfo *info)
+{
+ if (info->loader)
+ gedit_plugin_loader_garbage_collect (info->loader);
+}
+
+void
+gedit_plugins_engine_garbage_collect (GeditPluginsEngine *engine)
+{
+ g_hash_table_foreach (engine->priv->loaders,
+ (GHFunc) loader_garbage_collect,
+ NULL);
}
static void
gedit_plugins_engine_finalize (GObject *object)
{
+ GeditPluginsEngine *engine = GEDIT_PLUGINS_ENGINE (object);
+ GList *item;
+
gedit_debug (DEBUG_PLUGINS);
+ /* Firs deactivate all plugins */
+ for (item = engine->priv->plugin_list; item; item = item->next)
+ {
+ GeditPluginInfo *info = GEDIT_PLUGIN_INFO (item->data);
+
+ if (gedit_plugin_info_is_active (info))
+ gedit_plugins_engine_deactivate_plugin_real (engine, info);
+ }
+
+ /* unref the loaders */
+ g_hash_table_destroy (engine->priv->loaders);
+
+ /* and finally free the infos */
+ for (item = engine->priv->plugin_list; item; item = item->next)
+ {
+ GeditPluginInfo *info = GEDIT_PLUGIN_INFO (item->data);
+
+ _gedit_plugin_info_unref (info);
+ }
+
+ g_list_free (engine->priv->plugin_list);
+
G_OBJECT_CLASS (gedit_plugins_engine_parent_class)->finalize (object);
}
static void
+gedit_plugins_engine_dispose (GObject *object)
+{
+ GeditPluginsEngine *engine = GEDIT_PLUGINS_ENGINE (object);
+
+ if (engine->priv->plugin_settings != NULL)
+ {
+ g_object_unref (engine->priv->plugin_settings);
+ engine->priv->plugin_settings = NULL;
+ }
+
+ G_OBJECT_CLASS (gedit_plugins_engine_parent_class)->dispose (object);
+}
+
+static void
gedit_plugins_engine_class_init (GeditPluginsEngineClass *klass)
{
+ GType the_type = G_TYPE_FROM_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- PeasEngineClass *engine_class = PEAS_ENGINE_CLASS (klass);
object_class->finalize = gedit_plugins_engine_finalize;
- engine_class->activate_plugin = gedit_plugins_engine_activate_plugin;
- engine_class->deactivate_plugin = gedit_plugins_engine_deactivate_plugin;
+ object_class->dispose = gedit_plugins_engine_dispose;
+ klass->activate_plugin = gedit_plugins_engine_activate_plugin_real;
+ klass->deactivate_plugin = gedit_plugins_engine_deactivate_plugin_real;
+
+ signals[ACTIVATE_PLUGIN] =
+ g_signal_new ("activate-plugin",
+ the_type,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GeditPluginsEngineClass, activate_plugin),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ 1,
+ GEDIT_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ signals[DEACTIVATE_PLUGIN] =
+ g_signal_new ("deactivate-plugin",
+ the_type,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GeditPluginsEngineClass, deactivate_plugin),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ 1,
+ GEDIT_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE);
g_type_class_add_private (klass, sizeof (GeditPluginsEnginePrivate));
}
+static gboolean
+load_loader (GeditPluginsEngine *engine,
+ const gchar *filename,
+ gpointer data)
+{
+ GeditObjectModule *module;
+ gchar *base;
+ gchar *path;
+ const gchar *id;
+ GType type;
+
+ /* try to load in the module */
+ path = g_path_get_dirname (filename);
+ base = g_path_get_basename (filename);
+
+ /* for now they are all resident */
+ module = gedit_object_module_new (base,
+ path,
+ "register_gedit_plugin_loader",
+ TRUE);
+
+ g_free (base);
+ g_free (path);
+
+ /* make sure to load the type definition */
+ if (!g_type_module_use (G_TYPE_MODULE (module)))
+ {
+ g_object_unref (module);
+ g_warning ("Plugin loader module `%s' could not be loaded", filename);
+
+ return TRUE;
+ }
+
+ /* get the exported type and check the name as exported by the
+ * loader interface */
+ type = gedit_object_module_get_object_type (module);
+ id = gedit_plugin_loader_type_get_id (type);
+
+ add_loader (engine, id, module);
+ g_type_module_unuse (G_TYPE_MODULE (module));
+
+ return TRUE;
+}
+
+static void
+ensure_loader (LoaderInfo *info)
+{
+ if (info->loader == NULL && info->module != NULL)
+ {
+ /* create a new loader object */
+ GeditPluginLoader *loader;
+ loader = (GeditPluginLoader *)gedit_object_module_new_object (info->module, NULL);
+
+ if (loader == NULL || !GEDIT_IS_PLUGIN_LOADER (loader))
+ {
+ g_warning ("Loader object is not a valid GeditPluginLoader instance");
+
+ if (loader != NULL && G_IS_OBJECT (loader))
+ g_object_unref (loader);
+ }
+ else
+ {
+ info->loader = loader;
+ }
+ }
+}
+
+static GeditPluginLoader *
+get_plugin_loader (GeditPluginsEngine *engine,
+ GeditPluginInfo *info)
+{
+ const gchar *loader_id;
+ LoaderInfo *loader_info;
+
+ loader_id = info->loader;
+
+ loader_info = (LoaderInfo *)g_hash_table_lookup (
+ engine->priv->loaders,
+ loader_id);
+
+ if (loader_info == NULL && !engine->priv->scanned)
+ {
+ gchar *loader_dir;
+
+ loader_dir = gedit_dirs_get_gedit_plugin_loaders_dir ();
+
+ /* loader could not be found in the hash, try to find it by
+ scanning */
+ load_dir_real (engine,
+ loader_dir,
+ LOADER_EXT,
+ (LoadDirCallback)load_loader,
+ NULL);
+ g_free (loader_dir);
+
+ loader_info = (LoaderInfo *)g_hash_table_lookup (
+ engine->priv->loaders,
+ loader_id);
+
+ engine->priv->scanned = TRUE;
+ }
+
+ if (loader_info == NULL)
+ {
+ /* cache non-existent so we don't scan again */
+ add_loader (engine, loader_id, NULL);
+ return NULL;
+ }
+
+ ensure_loader (loader_info);
+ return loader_info->loader;
+}
+
GeditPluginsEngine *
gedit_plugins_engine_get_default (void)
{
- gchar *modules_dir;
- gchar **search_paths;
-
if (default_engine != NULL)
return default_engine;
- /* This should be moved to libpeas */
- g_irepository_require (g_irepository_get_default (),
- "Peas", "1.0", 0, NULL);
- g_irepository_require (g_irepository_get_default (),
- "PeasUI", "1.0", 0, NULL);
-
- modules_dir = gedit_dirs_get_binding_modules_dir ();
- search_paths = g_new (gchar *, 5);
- /* Add the user plugins dir in ~ */
- search_paths[0] = gedit_dirs_get_user_plugins_dir ();
- search_paths[1] = gedit_dirs_get_user_plugins_dir ();
- /* Add the system plugins dir */
- search_paths[2] = gedit_dirs_get_gedit_plugins_dir ();
- search_paths[3] = gedit_dirs_get_gedit_plugins_data_dir ();
- /* Add the trailing NULL */
- search_paths[4] = NULL;
-
- default_engine = GEDIT_PLUGINS_ENGINE (g_object_new (GEDIT_TYPE_PLUGINS_ENGINE,
- "app-name", "Gedit",
- "base-module-dir", modules_dir,
- "search-paths", search_paths,
- NULL));
-
- g_strfreev (search_paths);
- g_free (modules_dir);
-
+ default_engine = GEDIT_PLUGINS_ENGINE (g_object_new (GEDIT_TYPE_PLUGINS_ENGINE, NULL));
g_object_add_weak_pointer (G_OBJECT (default_engine),
(gpointer) &default_engine);
+ return default_engine;
+}
- gedit_plugins_engine_active_plugins_changed (default_engine);
+const GList *
+gedit_plugins_engine_get_plugin_list (GeditPluginsEngine *engine)
+{
+ gedit_debug (DEBUG_PLUGINS);
- return default_engine;
+ return engine->priv->plugin_list;
+}
+
+static gint
+compare_plugin_info_and_name (GeditPluginInfo *info,
+ const gchar *module_name)
+{
+ return strcmp (gedit_plugin_info_get_module_name (info), module_name);
+}
+
+GeditPluginInfo *
+gedit_plugins_engine_get_plugin_info (GeditPluginsEngine *engine,
+ const gchar *name)
+{
+ GList *l = g_list_find_custom (engine->priv->plugin_list,
+ name,
+ (GCompareFunc) compare_plugin_info_and_name);
+
+ return l == NULL ? NULL : (GeditPluginInfo *) l->data;
+}
+
+static void
+save_active_plugin_list (GeditPluginsEngine *engine)
+{
+ GSList *active_plugins = NULL;
+ GList *l;
+
+ for (l = engine->priv->plugin_list; l != NULL; l = l->next)
+ {
+ GeditPluginInfo *info = (GeditPluginInfo *) l->data;
+
+ if (gedit_plugin_info_is_active (info))
+ {
+ active_plugins = g_slist_prepend (active_plugins,
+ (gpointer)gedit_plugin_info_get_module_name (info));
+ }
+ }
+
+ gedit_settings_set_list (engine->priv->plugin_settings,
+ GEDIT_SETTINGS_ACTIVE_PLUGINS,
+ active_plugins);
+
+ g_slist_free (active_plugins);
+}
+
+static gboolean
+load_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info)
+{
+ GeditPluginLoader *loader;
+ gchar *path;
+
+ if (gedit_plugin_info_is_active (info))
+ return TRUE;
+
+ if (!gedit_plugin_info_is_available (info))
+ return FALSE;
+
+ loader = get_plugin_loader (engine, info);
+
+ if (loader == NULL)
+ {
+ g_warning ("Could not find loader `%s' for plugin `%s'", info->loader, info->name);
+ info->available = FALSE;
+ return FALSE;
+ }
+
+ path = g_path_get_dirname (info->file);
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ info->plugin = gedit_plugin_loader_load (loader, info, path);
+
+ g_free (path);
+
+ if (info->plugin == NULL)
+ {
+ g_warning ("Error loading plugin '%s'", info->name);
+ info->available = FALSE;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+gedit_plugins_engine_activate_plugin_real (GeditPluginsEngine *engine,
+ GeditPluginInfo *info)
+{
+ const GList *wins;
+
+ if (!load_plugin (engine, info))
+ return;
+
+ for (wins = gedit_app_get_windows (gedit_app_get_default ());
+ wins != NULL;
+ wins = wins->next)
+ {
+ gedit_plugin_activate (info->plugin, GEDIT_WINDOW (wins->data));
+ }
+}
+
+gboolean
+gedit_plugins_engine_activate_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info)
+{
+ gedit_debug (DEBUG_PLUGINS);
+
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ if (!gedit_plugin_info_is_available (info))
+ return FALSE;
+
+ if (gedit_plugin_info_is_active (info))
+ return TRUE;
+
+ g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
+
+ if (gedit_plugin_info_is_active (info))
+ save_active_plugin_list (engine);
+
+ return gedit_plugin_info_is_active (info);
+}
+
+static void
+call_plugin_deactivate (GeditPlugin *plugin,
+ GeditWindow *window)
+{
+ gedit_plugin_deactivate (plugin, window);
+
+ /* ensure update of ui manager, because we suspect it does something
+ with expected static strings in the type module (when unloaded the
+ strings don't exist anymore, and ui manager updates in an idle
+ func) */
+ gtk_ui_manager_ensure_update (gedit_window_get_ui_manager (window));
+}
+
+static void
+gedit_plugins_engine_deactivate_plugin_real (GeditPluginsEngine *engine,
+ GeditPluginInfo *info)
+{
+ const GList *wins;
+ GeditPluginLoader *loader;
+
+ if (!gedit_plugin_info_is_active (info) ||
+ !gedit_plugin_info_is_available (info))
+ return;
+
+ for (wins = gedit_app_get_windows (gedit_app_get_default ());
+ wins != NULL;
+ wins = wins->next)
+ {
+ call_plugin_deactivate (info->plugin, GEDIT_WINDOW (wins->data));
+ }
+
+ /* first unref the plugin (the loader still has one) */
+ g_object_unref (info->plugin);
+
+ /* find the loader and tell it to gc and unload the plugin */
+ loader = get_plugin_loader (engine, info);
+
+ gedit_plugin_loader_garbage_collect (loader);
+ gedit_plugin_loader_unload (loader, info);
+
+ info->plugin = NULL;
+}
+
+gboolean
+gedit_plugins_engine_deactivate_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info)
+{
+ gedit_debug (DEBUG_PLUGINS);
+
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ if (!gedit_plugin_info_is_active (info))
+ return TRUE;
+
+ g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
+ if (!gedit_plugin_info_is_active (info))
+ save_active_plugin_list (engine);
+
+ return !gedit_plugin_info_is_active (info);
}
void
+gedit_plugins_engine_activate_plugins (GeditPluginsEngine *engine,
+ GeditWindow *window)
+{
+ GSList *active_plugins = NULL;
+ GList *pl;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ g_return_if_fail (GEDIT_IS_PLUGINS_ENGINE (engine));
+ g_return_if_fail (GEDIT_IS_WINDOW (window));
+
+ /* the first time, we get the 'active' plugins from gconf */
+ if (engine->priv->activate_from_prefs)
+ {
+ active_plugins = gedit_settings_get_list (engine->priv->plugin_settings,
+ GEDIT_SETTINGS_ACTIVE_PLUGINS);
+ }
+
+ for (pl = engine->priv->plugin_list; pl; pl = pl->next)
+ {
+ GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
+
+ if (engine->priv->activate_from_prefs &&
+ g_slist_find_custom (active_plugins,
+ gedit_plugin_info_get_module_name (info),
+ (GCompareFunc)strcmp) == NULL)
+ {
+ continue;
+ }
+
+ /* If plugin is not active, don't try to activate/load it */
+ if (!engine->priv->activate_from_prefs &&
+ !gedit_plugin_info_is_active (info))
+ {
+ continue;
+ }
+
+ if (load_plugin (engine, info))
+ {
+ gedit_plugin_activate (info->plugin,
+ window);
+ }
+ }
+
+ if (engine->priv->activate_from_prefs)
+ {
+ g_slist_foreach (active_plugins, (GFunc) g_free, NULL);
+ g_slist_free (active_plugins);
+ engine->priv->activate_from_prefs = FALSE;
+ }
+
+ gedit_debug_message (DEBUG_PLUGINS, "End");
+
+ /* also call update_ui after activation */
+ gedit_plugins_engine_update_plugins_ui (engine, window);
+}
+
+void
+gedit_plugins_engine_deactivate_plugins (GeditPluginsEngine *engine,
+ GeditWindow *window)
+{
+ GList *pl;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ g_return_if_fail (GEDIT_IS_PLUGINS_ENGINE (engine));
+ g_return_if_fail (GEDIT_IS_WINDOW (window));
+
+ for (pl = engine->priv->plugin_list; pl; pl = pl->next)
+ {
+ GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
+
+ /* check if the plugin is actually active */
+ if (!gedit_plugin_info_is_active (info))
+ continue;
+
+ /* call deactivate for the plugin for this window */
+ gedit_plugin_deactivate (info->plugin, window);
+ }
+
+ gedit_debug_message (DEBUG_PLUGINS, "End");
+}
+
+void
+gedit_plugins_engine_update_plugins_ui (GeditPluginsEngine *engine,
+ GeditWindow *window)
+{
+ GList *pl;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ g_return_if_fail (GEDIT_IS_PLUGINS_ENGINE (engine));
+ g_return_if_fail (GEDIT_IS_WINDOW (window));
+
+ /* call update_ui for all active plugins */
+ for (pl = engine->priv->plugin_list; pl; pl = pl->next)
+ {
+ GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
+
+ if (!gedit_plugin_info_is_active (info))
+ continue;
+
+ gedit_debug_message (DEBUG_PLUGINS, "Updating UI of %s", info->name);
+ gedit_plugin_update_ui (info->plugin, window);
+ }
+}
+
+void
+gedit_plugins_engine_configure_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info,
+ GtkWindow *parent)
+{
+ GtkWidget *conf_dlg;
+
+ GtkWindowGroup *wg;
+
+ gedit_debug (DEBUG_PLUGINS);
+
+ g_return_if_fail (info != NULL);
+
+ conf_dlg = gedit_plugin_create_configure_dialog (info->plugin);
+ g_return_if_fail (conf_dlg != NULL);
+ gtk_window_set_transient_for (GTK_WINDOW (conf_dlg),
+ parent);
+
+ if (gtk_window_has_group (parent))
+ {
+ wg = gtk_window_get_group (parent);
+ }
+ else
+ {
+ wg = gtk_window_group_new ();
+ gtk_window_group_add_window (wg, parent);
+ }
+
+ gtk_window_group_add_window (wg,
+ GTK_WINDOW (conf_dlg));
+
+ gtk_window_set_modal (GTK_WINDOW (conf_dlg), TRUE);
+ gtk_widget_show (conf_dlg);
+}
+
+void
gedit_plugins_engine_active_plugins_changed (GeditPluginsEngine *engine)
{
- gchar **active_plugins;
+ gboolean to_activate;
+ GSList *active_plugins;
+ GList *pl;
- active_plugins = g_settings_get_strv (engine->priv->plugin_settings,
- GEDIT_SETTINGS_ACTIVE_PLUGINS);
+ gedit_debug (DEBUG_PLUGINS);
+
+ active_plugins = gedit_settings_get_list (engine->priv->plugin_settings,
+ GEDIT_SETTINGS_ACTIVE_PLUGINS);
+
+ for (pl = engine->priv->plugin_list; pl; pl = pl->next)
+ {
+ GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
+
+ if (!gedit_plugin_info_is_available (info))
+ continue;
+
+ to_activate = (g_slist_find_custom (active_plugins,
+ gedit_plugin_info_get_module_name (info),
+ (GCompareFunc)strcmp) != NULL);
+
+ if (!gedit_plugin_info_is_active (info) && to_activate)
+ g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
+ else if (gedit_plugin_info_is_active (info) && !to_activate)
+ g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
+ }
- engine->priv->setting_active_plugins = TRUE;
- peas_engine_set_active_plugins (PEAS_ENGINE (engine),
- (const gchar **) active_plugins);
- engine->priv->setting_active_plugins = FALSE;
- g_strfreev (active_plugins);
+ g_slist_foreach (active_plugins, (GFunc) g_free, NULL);
+ g_slist_free (active_plugins);
+}
+
+void
+gedit_plugins_engine_rescan_plugins (GeditPluginsEngine *engine)
+{
+ gedit_debug (DEBUG_PLUGINS);
+
+ load_all_plugins (engine);
}
-/* ex:set ts=8 noet: */
+/* ex:ts=8:noet: */
diff --git a/gedit/gedit-plugins-engine.h b/gedit/gedit-plugins-engine.h
index dba35f4..0ebb7f2 100644
--- a/gedit/gedit-plugins-engine.h
+++ b/gedit/gedit-plugins-engine.h
@@ -3,7 +3,6 @@
* This file is part of gedit
*
* Copyright (C) 2002-2005 - Paolo Maggi
- * Copyright (C) 2010 - Steve Frécinaux
*
* 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
@@ -33,7 +32,9 @@
#define __GEDIT_PLUGINS_ENGINE_H__
#include <glib.h>
-#include <libpeas/peas-engine.h>
+#include "gedit-window.h"
+#include "gedit-plugin-info.h"
+#include "gedit-plugin.h"
G_BEGIN_DECLS
@@ -49,7 +50,7 @@ typedef struct _GeditPluginsEnginePrivate GeditPluginsEnginePrivate;
struct _GeditPluginsEngine
{
- PeasEngine parent;
+ GObject parent;
GeditPluginsEnginePrivate *priv;
};
@@ -57,16 +58,50 @@ typedef struct _GeditPluginsEngineClass GeditPluginsEngineClass;
struct _GeditPluginsEngineClass
{
- PeasEngineClass parent_class;
+ GObjectClass parent_class;
+
+ void (* activate_plugin) (GeditPluginsEngine *engine,
+ GeditPluginInfo *info);
+
+ void (* deactivate_plugin) (GeditPluginsEngine *engine,
+ GeditPluginInfo *info);
};
GType gedit_plugins_engine_get_type (void) G_GNUC_CONST;
GeditPluginsEngine *gedit_plugins_engine_get_default (void);
+void gedit_plugins_engine_garbage_collect (GeditPluginsEngine *engine);
+
+const GList *gedit_plugins_engine_get_plugin_list (GeditPluginsEngine *engine);
+
+GeditPluginInfo *gedit_plugins_engine_get_plugin_info (GeditPluginsEngine *engine,
+ const gchar *name);
+
+/* plugin load and unloading (overall, for all windows) */
+gboolean gedit_plugins_engine_activate_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info);
+gboolean gedit_plugins_engine_deactivate_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info);
+
+void gedit_plugins_engine_configure_plugin (GeditPluginsEngine *engine,
+ GeditPluginInfo *info,
+ GtkWindow *parent);
+
+/* plugin activation/deactivation per window, private to GeditWindow */
+void gedit_plugins_engine_activate_plugins (GeditPluginsEngine *engine,
+ GeditWindow *window);
+void gedit_plugins_engine_deactivate_plugins
+ (GeditPluginsEngine *engine,
+ GeditWindow *window);
+void gedit_plugins_engine_update_plugins_ui (GeditPluginsEngine *engine,
+ GeditWindow *window);
+
/* private for gconf notification */
void gedit_plugins_engine_active_plugins_changed (GeditPluginsEngine *engine);
+void gedit_plugins_engine_rescan_plugins (GeditPluginsEngine *engine);
+
G_END_DECLS
#endif /* __GEDIT_PLUGINS_ENGINE_H__ */
diff --git a/gedit/gedit-window-private.h b/gedit/gedit-window-private.h
index b3dac50..9f02055 100644
--- a/gedit/gedit-window-private.h
+++ b/gedit/gedit-window-private.h
@@ -31,8 +31,6 @@
#ifndef __GEDIT_WINDOW_PRIVATE_H__
#define __GEDIT_WINDOW_PRIVATE_H__
-#include <libpeas/peas-extension-set.h>
-
#include "gedit/gedit-window.h"
#include "gedit-message-bus.h"
#include "gedit-settings.h"
@@ -64,7 +62,6 @@ struct _GeditWindowPrivate
GtkWidget *language_combo;
GeditMessageBus *message_bus;
- PeasExtensionSet *extensions;
/* Widgets for fullscreen mode */
GtkWidget *fullscreen_controls;
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index 3fea97e..0d43819 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -38,8 +38,6 @@
#include <glib/gi18n.h>
#include <gio/gio.h>
-#include <libpeas/peas-activatable.h>
-#include <libpeas/peas-extension-set.h>
#include "gedit-ui.h"
#include "gedit-window.h"
@@ -244,15 +242,6 @@ gedit_window_dispose (GObject *object)
window = GEDIT_WINDOW (object);
- if (!window->priv->dispose_has_run)
- {
- peas_extension_set_call (window->priv->extensions,
- "deactivate",
- window);
-
- peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
- }
-
/* Stop tracking removal of panes otherwise we always
* end up with thinking we had no pane active, since they
* should all be removed below */
@@ -263,6 +252,11 @@ gedit_window_dispose (GObject *object)
window->priv->bottom_panel_item_removed_handler_id = 0;
}
+ /* First of all, force collection so that plugins
+ * really drop some of the references.
+ */
+ gedit_plugins_engine_garbage_collect (gedit_plugins_engine_get_default ());
+
/* save the panes position and make sure to deactivate plugins
* for this window, but only once */
if (!window->priv->dispose_has_run)
@@ -270,6 +264,8 @@ gedit_window_dispose (GObject *object)
save_window_state (GTK_WIDGET (window));
save_panes_state (window);
+ gedit_plugins_engine_deactivate_plugins (gedit_plugins_engine_get_default (),
+ window);
window->priv->dispose_has_run = TRUE;
}
@@ -336,7 +332,7 @@ gedit_window_dispose (GObject *object)
/* Now that there have broken some reference loops,
* force collection again.
*/
- peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
+ gedit_plugins_engine_garbage_collect (gedit_plugins_engine_get_default ());
#ifdef OS_OSX
remove_mac_root_menu (window);
@@ -354,8 +350,6 @@ gedit_window_finalize (GObject *object)
window = GEDIT_WINDOW (object);
- g_object_unref (window->priv->extensions);
-
if (window->priv->default_location != NULL)
g_object_unref (window->priv->default_location);
@@ -445,7 +439,7 @@ static void
gedit_window_tab_removed (GeditWindow *window,
GeditTab *tab)
{
- peas_engine_garbage_collect (PEAS_ENGINE (gedit_plugins_engine_get_default ()));
+ gedit_plugins_engine_garbage_collect (gedit_plugins_engine_get_default ());
}
static void
@@ -970,7 +964,8 @@ set_sensitivity_according_to_tab (GeditWindow *window,
update_next_prev_doc_sensitivity (window, tab);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
static void
@@ -2973,7 +2968,8 @@ sync_name (GeditTab *tab,
g_free (escaped_name);
g_free (tip);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
static GeditWindow *
@@ -3375,7 +3371,8 @@ selection_changed (GeditDocument *doc,
editable &&
gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)));
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
static void
@@ -3384,7 +3381,8 @@ sync_languages_menu (GeditDocument *doc,
GeditWindow *window)
{
update_languages_menu (window);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
static void
@@ -3397,7 +3395,8 @@ readonly_changed (GeditDocument *doc,
sync_name (gedit_window_get_active_tab (window), NULL, window);
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
static void
@@ -3405,7 +3404,8 @@ editable_changed (GeditView *view,
GParamSpec *arg1,
GeditWindow *window)
{
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
static void
@@ -3634,7 +3634,8 @@ on_tab_removed (GeditMultiNotebook *multi,
if (num_tabs == 0)
{
- peas_extension_set_call (window->priv->extensions, "update_state", window);
+ gedit_plugins_engine_update_plugins_ui (gedit_plugins_engine_get_default (),
+ window);
}
}
@@ -4056,29 +4057,6 @@ setup_mac_menu (GeditWindow *window)
#endif
static void
-extension_added (PeasExtensionSet *extensions,
- PeasPluginInfo *info,
- PeasExtension *exten,
- GeditWindow *window)
-{
- peas_extension_call (exten, "activate", window);
-}
-
-static void
-extension_removed (PeasExtensionSet *extensions,
- PeasPluginInfo *info,
- PeasExtension *exten,
- GeditWindow *window)
-{
- peas_extension_call (exten, "deactivate", window);
- /* Ensure update of ui manager, because we suspect it does something
- * with expected static strings in the type module (when unloaded the
- * strings don't exist anymore, and ui manager updates in an idle
- * func) */
- gtk_ui_manager_ensure_update (window->priv->manager);
-}
-
-static void
gedit_window_init (GeditWindow *window)
{
GtkWidget *main_box;
@@ -4245,18 +4223,8 @@ gedit_window_init (GeditWindow *window)
gedit_debug_message (DEBUG_WINDOW, "Update plugins ui");
- window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (gedit_plugins_engine_get_default ()),
- PEAS_TYPE_ACTIVATABLE);
- g_signal_connect (window->priv->extensions,
- "extension-added",
- G_CALLBACK (extension_added),
- window);
- g_signal_connect (window->priv->extensions,
- "extension-removed",
- G_CALLBACK (extension_removed),
- window);
- peas_extension_set_call (window->priv->extensions, "activate", window);
-
+ gedit_plugins_engine_activate_plugins (gedit_plugins_engine_get_default (),
+ window);
/* set visibility of panes.
* This needs to be done after plugins activatation */
diff --git a/plugin-loaders/Makefile.am b/plugin-loaders/Makefile.am
new file mode 100644
index 0000000..2573ec3
--- /dev/null
+++ b/plugin-loaders/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = c
+
+-include $(top_srcdir)/git.mk
diff --git a/plugin-loaders/c/Makefile.am b/plugin-loaders/c/Makefile.am
new file mode 100644
index 0000000..7760aef
--- /dev/null
+++ b/plugin-loaders/c/Makefile.am
@@ -0,0 +1,24 @@
+# C plugin loader
+
+loaderdir = $(libdir)/gedit-2/plugin-loaders
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(GEDIT_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(DISABLE_DEPRECATED_CFLAGS) \
+ -DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\"
+
+loader_LTLIBRARIES = libcloader.la
+
+NOINST_H_FILES = \
+ gedit-plugin-loader-c.h
+
+libcloader_la_SOURCES = \
+ gedit-plugin-loader-c.c \
+ $(NOINST_H_FILES)
+
+libcloader_la_LDFLAGS = $(LOADER_LIBTOOL_FLAGS)
+libcloader_la_LIBADD = $(GEDIT_LIBS)
+
+-include $(top_srcdir)/git.mk
diff --git a/plugin-loaders/c/gedit-plugin-loader-c.c b/plugin-loaders/c/gedit-plugin-loader-c.c
new file mode 100644
index 0000000..add817e
--- /dev/null
+++ b/plugin-loaders/c/gedit-plugin-loader-c.c
@@ -0,0 +1,183 @@
+/*
+ * gedit-plugin-loader-c.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gedit-plugin-loader-c.h"
+#include <gedit/gedit-object-module.h>
+
+#define GEDIT_PLUGIN_LOADER_C_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderCPrivate))
+
+struct _GeditPluginLoaderCPrivate
+{
+ GHashTable *loaded_plugins;
+};
+
+static void gedit_plugin_loader_iface_init (gpointer g_iface, gpointer iface_data);
+
+GEDIT_PLUGIN_LOADER_REGISTER_TYPE (GeditPluginLoaderC, gedit_plugin_loader_c, G_TYPE_OBJECT, gedit_plugin_loader_iface_init);
+
+
+static const gchar *
+gedit_plugin_loader_iface_get_id (void)
+{
+ return "C";
+}
+
+static GeditPlugin *
+gedit_plugin_loader_iface_load (GeditPluginLoader *loader,
+ GeditPluginInfo *info,
+ const gchar *path)
+{
+ GeditPluginLoaderC *cloader = GEDIT_PLUGIN_LOADER_C (loader);
+ GeditObjectModule *module;
+ const gchar *module_name;
+ GeditPlugin *result;
+
+ module = (GeditObjectModule *)g_hash_table_lookup (cloader->priv->loaded_plugins, info);
+ module_name = gedit_plugin_info_get_module_name (info);
+
+ if (module == NULL)
+ {
+ /* For now we force all modules to be resident */
+ module = gedit_object_module_new (module_name,
+ path,
+ "register_gedit_plugin",
+ TRUE);
+
+ /* Infos are available for all the lifetime of the loader.
+ * If this changes, we should use weak refs or something */
+
+ g_hash_table_insert (cloader->priv->loaded_plugins, info, module);
+ }
+
+ if (!g_type_module_use (G_TYPE_MODULE (module)))
+ {
+ g_warning ("Could not load plugin module: %s", gedit_plugin_info_get_name (info));
+
+ return NULL;
+ }
+
+ /* TODO: for now we force data-dir-name = module-name... if needed we can
+ * add a datadir field to the plugin descriptor file.
+ */
+ result = (GeditPlugin *)gedit_object_module_new_object (module,
+ "install-dir", path,
+ "data-dir-name", module_name,
+ NULL);
+
+ if (!result)
+ {
+ g_warning ("Could not create plugin object: %s", gedit_plugin_info_get_name (info));
+ g_type_module_unuse (G_TYPE_MODULE (module));
+
+ return NULL;
+ }
+
+ g_type_module_unuse (G_TYPE_MODULE (module));
+
+ return result;
+}
+
+static void
+gedit_plugin_loader_iface_unload (GeditPluginLoader *loader,
+ GeditPluginInfo *info)
+{
+ //GeditPluginLoaderC *cloader = GEDIT_PLUGIN_LOADER_C (loader);
+
+ /* this is a no-op, since the type module will be properly unused as
+ the last reference to the plugin dies. When the plugin is activated
+ again, the library will be reloaded */
+}
+
+static void
+gedit_plugin_loader_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GeditPluginLoaderInterface *iface = (GeditPluginLoaderInterface *)g_iface;
+
+ iface->get_id = gedit_plugin_loader_iface_get_id;
+ iface->load = gedit_plugin_loader_iface_load;
+ iface->unload = gedit_plugin_loader_iface_unload;
+}
+
+static void
+gedit_plugin_loader_c_finalize (GObject *object)
+{
+ GeditPluginLoaderC *cloader = GEDIT_PLUGIN_LOADER_C (object);
+ GList *infos;
+ GList *item;
+
+ /* FIXME: this sanity check it's not efficient. Let's remove it
+ * once we are confident with the code */
+
+ infos = g_hash_table_get_keys (cloader->priv->loaded_plugins);
+
+ for (item = infos; item; item = item->next)
+ {
+ GeditPluginInfo *info = (GeditPluginInfo *)item->data;
+
+ if (gedit_plugin_info_is_active (info))
+ {
+ g_warning ("There are still C plugins loaded during destruction");
+ break;
+ }
+ }
+
+ g_list_free (infos);
+
+ g_hash_table_destroy (cloader->priv->loaded_plugins);
+
+ G_OBJECT_CLASS (gedit_plugin_loader_c_parent_class)->finalize (object);
+}
+
+static void
+gedit_plugin_loader_c_class_init (GeditPluginLoaderCClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gedit_plugin_loader_c_finalize;
+
+ g_type_class_add_private (object_class, sizeof (GeditPluginLoaderCPrivate));
+}
+
+static void
+gedit_plugin_loader_c_class_finalize (GeditPluginLoaderCClass *klass)
+{
+}
+
+static void
+gedit_plugin_loader_c_init (GeditPluginLoaderC *self)
+{
+ self->priv = GEDIT_PLUGIN_LOADER_C_GET_PRIVATE (self);
+
+ /* loaded_plugins maps GeditPluginInfo to a GeditObjectModule */
+ self->priv->loaded_plugins = g_hash_table_new (g_direct_hash,
+ g_direct_equal);
+}
+
+GeditPluginLoaderC *
+gedit_plugin_loader_c_new ()
+{
+ GObject *loader = g_object_new (GEDIT_TYPE_PLUGIN_LOADER_C, NULL);
+
+ return GEDIT_PLUGIN_LOADER_C (loader);
+}
+/* ex:ts=8:noet: */
diff --git a/plugin-loaders/c/gedit-plugin-loader-c.h b/plugin-loaders/c/gedit-plugin-loader-c.h
new file mode 100644
index 0000000..dcf4f2d
--- /dev/null
+++ b/plugin-loaders/c/gedit-plugin-loader-c.h
@@ -0,0 +1,61 @@
+/*
+ * gedit-plugin-loader-c.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GEDIT_PLUGIN_LOADER_C_H__
+#define __GEDIT_PLUGIN_LOADER_C_H__
+
+#include <gedit/gedit-plugin-loader.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_PLUGIN_LOADER_C (gedit_plugin_loader_c_get_type ())
+#define GEDIT_PLUGIN_LOADER_C(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderC))
+#define GEDIT_PLUGIN_LOADER_C_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderC const))
+#define GEDIT_PLUGIN_LOADER_C_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderCClass))
+#define GEDIT_IS_PLUGIN_LOADER_C(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_PLUGIN_LOADER_C))
+#define GEDIT_IS_PLUGIN_LOADER_C_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN_LOADER_C))
+#define GEDIT_PLUGIN_LOADER_C_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderCClass))
+
+typedef struct _GeditPluginLoaderC GeditPluginLoaderC;
+typedef struct _GeditPluginLoaderCClass GeditPluginLoaderCClass;
+typedef struct _GeditPluginLoaderCPrivate GeditPluginLoaderCPrivate;
+
+struct _GeditPluginLoaderC {
+ GObject parent;
+
+ GeditPluginLoaderCPrivate *priv;
+};
+
+struct _GeditPluginLoaderCClass {
+ GObjectClass parent_class;
+};
+
+GType gedit_plugin_loader_c_get_type (void) G_GNUC_CONST;
+GeditPluginLoaderC *gedit_plugin_loader_c_new(void);
+
+/* All the loaders must implement this function */
+G_MODULE_EXPORT GType register_gedit_plugin_loader (GTypeModule * module);
+
+G_END_DECLS
+
+#endif /* __GEDIT_PLUGIN_LOADER_C_H__ */
+/* ex:ts=8:noet: */
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6fbac4b..ec1df43 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,30 +1,28 @@
-DIST_SUBDIRS = \
- modelines
+DIST_SUBDIRS = \
+ changecase \
+ checkupdate \
+ docinfo \
+ filebrowser \
+ modelines \
+ sort \
+ spell \
+ taglist \
+ time
-# changecase \
-# checkupdate \
-# docinfo \
-# filebrowser \
-# modelines \
-# sort \
-# spell \
-# taglist \
-# time
# externaltools
# pythonconsole
# quickopen
# snippets
-SUBDIRS = \
- modelines
+SUBDIRS = \
+ changecase \
+ docinfo \
+ filebrowser \
+ modelines \
+ sort \
+ taglist \
+ time
-# changecase
-# docinfo
-# filebrowser
-# modelines
-# sort
-# taglist
-# time
# pythonconsole
# quickopen
# snippets
@@ -33,15 +31,12 @@ SUBDIRS = \
#SUBDIRS += externaltools
#endif
-#if ENABLE_ENCHANT
-#SUBDIRS += spell
-#endif
-
-#if ENABLE_UPDATER
-#SUBDIRS += checkupdate
-#endif
+if ENABLE_ENCHANT
+SUBDIRS += spell
+endif
-DIST_SUBDIRS += pysample
-SUBDIRS += pysample
+if ENABLE_UPDATER
+SUBDIRS += checkupdate
+endif
-include $(top_srcdir)/git.mk
diff --git a/plugins/modelines/gedit-modeline-plugin.c b/plugins/modelines/gedit-modeline-plugin.c
index 93ae710..b6bd4e3 100644
--- a/plugins/modelines/gedit-modeline-plugin.c
+++ b/plugins/modelines/gedit-modeline-plugin.c
@@ -2,7 +2,7 @@
* gedit-modeline-plugin.c
* Emacs, Kate and Vim-style modelines support for gedit.
*
- * Copyright (C) 2005-2010 - Steve Frécinaux <code istique net>
+ * Copyright (C) 2005-2007 - Steve Frécinaux <code istique net>
*
* 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
@@ -25,34 +25,39 @@
#include <glib/gi18n-lib.h>
#include <gmodule.h>
-#include <libpeas/peas-activatable.h>
#include "gedit-modeline-plugin.h"
#include "modeline-parser.h"
#include <gedit/gedit-debug.h>
-#include <gedit/gedit-window.h>
#include <gedit/gedit-utils.h>
+#define WINDOW_DATA_KEY "GeditModelinePluginWindowData"
#define DOCUMENT_DATA_KEY "GeditModelinePluginDocumentData"
typedef struct
{
+ gulong tab_added_handler_id;
+ gulong tab_removed_handler_id;
+} WindowData;
+
+typedef struct
+{
gulong document_loaded_handler_id;
gulong document_saved_handler_id;
} DocumentData;
-static void peas_activatable_iface_init (PeasActivatableInterface *iface);
-static void gedit_modeline_plugin_activate (PeasActivatable *activatable, GObject *object);
-static void gedit_modeline_plugin_deactivate (PeasActivatable *activatable, GObject *object);
+static void gedit_modeline_plugin_activate (GeditPlugin *plugin, GeditWindow *window);
+static void gedit_modeline_plugin_deactivate (GeditPlugin *plugin, GeditWindow *window);
static GObject *gedit_modeline_plugin_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_param);
static void gedit_modeline_plugin_finalize (GObject *object);
-G_DEFINE_DYNAMIC_TYPE_EXTENDED (GeditModelinePlugin,
- gedit_modeline_plugin,
- PEAS_TYPE_EXTENSION_BASE,
- 0,
- G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
- peas_activatable_iface_init))
+GEDIT_PLUGIN_REGISTER_TYPE(GeditModelinePlugin, gedit_modeline_plugin)
+
+static void
+window_data_free (WindowData *wdata)
+{
+ g_slice_free (WindowData, wdata);
+}
static void
document_data_free (DocumentData *ddata)
@@ -64,21 +69,13 @@ static void
gedit_modeline_plugin_class_init (GeditModelinePluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GeditPluginClass *plugin_class = GEDIT_PLUGIN_CLASS (klass);
object_class->constructor = gedit_modeline_plugin_constructor;
object_class->finalize = gedit_modeline_plugin_finalize;
-}
-static void
-peas_activatable_iface_init (PeasActivatableInterface *iface)
-{
- iface->activate = gedit_modeline_plugin_activate;
- iface->deactivate = gedit_modeline_plugin_deactivate;
-}
-
-static void
-gedit_modeline_plugin_class_finalize (GeditModelinePluginClass *klass)
-{
+ plugin_class->activate = gedit_modeline_plugin_activate;
+ plugin_class->deactivate = gedit_modeline_plugin_deactivate;
}
static GObject *
@@ -93,7 +90,7 @@ gedit_modeline_plugin_constructor (GType type,
n_construct_properties,
construct_param);
- data_dir = peas_extension_base_get_data_dir (PEAS_EXTENSION_BASE (object));
+ data_dir = gedit_plugin_get_data_dir (GEDIT_PLUGIN (object));
modeline_parser_init (data_dir);
@@ -189,12 +186,10 @@ on_window_tab_removed (GeditWindow *window,
}
static void
-gedit_modeline_plugin_activate (PeasActivatable *activatable,
- GObject *object)
+gedit_modeline_plugin_activate (GeditPlugin *plugin,
+ GeditWindow *window)
{
- GeditModelinePlugin *plugin = GEDIT_MODELINE_PLUGIN (activatable);
- GeditWindow *window = GEDIT_WINDOW (object);
-
+ WindowData *wdata;
GList *views;
GList *l;
@@ -208,28 +203,36 @@ gedit_modeline_plugin_activate (PeasActivatable *activatable,
}
g_list_free (views);
- plugin->tab_added_handler_id =
+ wdata = g_slice_new (WindowData);
+
+ wdata->tab_added_handler_id =
g_signal_connect (window, "tab-added",
G_CALLBACK (on_window_tab_added), NULL);
- plugin->tab_removed_handler_id =
+ wdata->tab_removed_handler_id =
g_signal_connect (window, "tab-removed",
G_CALLBACK (on_window_tab_removed), NULL);
+
+ g_object_set_data_full (G_OBJECT (window), WINDOW_DATA_KEY,
+ wdata, (GDestroyNotify) window_data_free);
}
static void
-gedit_modeline_plugin_deactivate (PeasActivatable *activatable,
- GObject *object)
+gedit_modeline_plugin_deactivate (GeditPlugin *plugin,
+ GeditWindow *window)
{
- GeditModelinePlugin *plugin = GEDIT_MODELINE_PLUGIN (activatable);
- GeditWindow *window = GEDIT_WINDOW (object);
+ WindowData *wdata;
GList *views;
GList *l;
gedit_debug (DEBUG_PLUGINS);
- g_signal_handler_disconnect (window, plugin->tab_added_handler_id);
- g_signal_handler_disconnect (window, plugin->tab_removed_handler_id);
+ wdata = g_object_steal_data (G_OBJECT (window), WINDOW_DATA_KEY);
+
+ g_signal_handler_disconnect (window, wdata->tab_added_handler_id);
+ g_signal_handler_disconnect (window, wdata->tab_removed_handler_id);
+
+ window_data_free (wdata);
views = gedit_window_get_views (window);
@@ -243,14 +246,4 @@ gedit_modeline_plugin_deactivate (PeasActivatable *activatable,
g_list_free (views);
}
-G_MODULE_EXPORT void
-peas_register_types (PeasObjectModule *module)
-{
- gedit_modeline_plugin_register_type (G_TYPE_MODULE (module));
-
- peas_object_module_register_extension_type (module,
- PEAS_TYPE_ACTIVATABLE,
- GEDIT_TYPE_MODELINE_PLUGIN);
-}
-
-/* ex:set ts=8 noet: */
+/* ex:ts=8:noet: */
diff --git a/plugins/modelines/gedit-modeline-plugin.h b/plugins/modelines/gedit-modeline-plugin.h
index 3f7a764..a5ff1da 100644
--- a/plugins/modelines/gedit-modeline-plugin.h
+++ b/plugins/modelines/gedit-modeline-plugin.h
@@ -24,8 +24,7 @@
#include <glib.h>
#include <glib-object.h>
-#include <libpeas/peas-extension-base.h>
-#include <libpeas/peas-object-module.h>
+#include <gedit/gedit-plugin.h>
G_BEGIN_DECLS
@@ -36,24 +35,13 @@ G_BEGIN_DECLS
#define GEDIT_IS_MODELINE_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GEDIT_TYPE_MODELINE_PLUGIN))
#define GEDIT_MODELINE_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GEDIT_TYPE_MODELINE_PLUGIN, GeditModelinePluginClass))
-typedef struct _GeditModelinePlugin GeditModelinePlugin;
-typedef struct _GeditModelinePluginClass GeditModelinePluginClass;
-
-struct _GeditModelinePlugin {
- PeasExtensionBase parent;
-
- /*< private >*/
- gulong tab_added_handler_id;
- gulong tab_removed_handler_id;
-};
-
-struct _GeditModelinePluginClass {
- PeasExtensionBaseClass parent_class;
-};
+/* Private structure type */
+typedef GeditPluginClass GeditModelinePluginClass;
+typedef GeditPlugin GeditModelinePlugin;
GType gedit_modeline_plugin_get_type (void) G_GNUC_CONST;
-G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
+G_MODULE_EXPORT GType register_gedit_plugin (GTypeModule *module);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]