2 * This file is part of hildon-libs
4 * Copyright (C) 2005, 2006 Nokia Corporation.
6 * Author: Kuisma Salonen <kuisma.salonen@nokia.com>
7 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; version 2.1 of
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 * SECTION:hildon-plugin-widget
28 * @short_description: A simple interface to load plugin based widgets. Not
29 * compatible with GObject.
31 * #HildonPluginWidgetInfo is a struct containing information about loaded
32 * module which contains code for a widget.
43 #include "hildon-plugin-widget.h"
47 #define PLUGIN_DIR "/usr/lib/hildon-widgets"
51 struct HildonPluginWidgetInfo_ {
63 static gchar *hildon_plugin_filename(GType base_type, const gchar *name);
65 /* WARNING: works properly only with ASCII */
66 static gchar *ascii_decapitalize_without_dashes(gchar *source);
68 static gchar *hildon_plugin_default_name(gchar *typename);
71 * hildon_plugin_info_initialize:
72 * @base_type: a #GType representing parent type of object that will be
74 * @name: Name of child. To load default (or #GtkSettings defined), NULL
75 * should be passed as name. To load specific child type, decapitalized name
76 * should be passed here.
78 * Creates a new #HildonPluginWidgetInfo structure and opens a module.
80 * The naming of child widgets (or objects) doesn't matter, but for plugins
81 * the file names should be type
82 * <decapitalized-parent-type-name-with-dashes>-<pluginname>.so where the
83 * decapitalized type name would be for example for #GtkWidget gtk-widget.
85 * The name comes from name argument or from #GtkSettings where the variable
86 * storing it is with name <ParentTypeName>-plugin, for #GtkWidget this would
87 * be "GtkWidget-plugin". If nothing is defined in #GtkSettings, name
88 * "default" is assumed. For this case there should be symlink to some child
89 * type plugin named <parent-type-name>-default.so
91 * Returns: a #HildonPluginWidgetInfo struct pointer upon success, NULL if
94 HildonPluginWidgetInfo *hildon_plugin_info_initialize(GType base_type, const gchar *name)
96 HildonPluginWidgetInfo *ret;
106 filename = hildon_plugin_filename(base_type, name);
107 g_return_val_if_fail (filename != NULL, NULL);
110 module = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
112 g_warning ("Failed to load plugin for '%s' (filename: '%s')", name, filename);
118 ret = (HildonPluginWidgetInfo *)g_malloc0(sizeof(HildonPluginWidgetInfo) + strlen(filename) + 1);
119 ret->filename = (gchar *)ret + sizeof(HildonPluginWidgetInfo);
121 ret->base_type = base_type;
123 ret->module = module;
125 g_module_symbol(module, "export_type", (void **)&ret->get_type);
127 memcpy(ret->filename, filename, strlen(filename));
137 * hildon_plugin_info_construct_widget:
138 * @info: pointer to a #HildonPluginWidgetInfo struct.
140 * Creates instance of loaded type from module stored in
141 * #HildonPluginWidgetInfo struct. Designed for loading types inherited from
142 * GtkWidget, but could be basically any GTK+ type.
144 * Returns: a GtkWidget pointer to instance of loaded type.
146 GtkWidget *hildon_plugin_info_construct_widget(HildonPluginWidgetInfo *info)
148 g_return_val_if_fail (info != NULL, NULL);
152 return GTK_WIDGET(g_type_create_instance(info->get_type()));
156 * hildon_plugin_info_kill:
157 * @info: a pointer to a #HildonPluginWidgetInfo struct that should be
160 * Frees the plugin information structure and unloads the module.
162 void hildon_plugin_info_kill(HildonPluginWidgetInfo *info)
169 g_module_close(info->module);
176 static gchar *hildon_plugin_filename(GType base_type, const gchar *name)
178 gchar *ret, *name2, *plgbuf;
179 gchar *typename = (gchar *)g_type_name(base_type);
183 plgbuf = ascii_decapitalize_without_dashes(typename);
187 name2 = g_strdup(name);
189 name2 = hildon_plugin_default_name(typename);
193 retsize = strlen(PLUGIN_DIR) + strlen(plgbuf) + strlen(name2) + 6;
194 ret = (gchar *)g_malloc0(retsize);
195 g_snprintf(ret, retsize, "%s/%s_%s.so", PLUGIN_DIR, plgbuf, name2);
205 /* possible speedup: pre-allocate more memory and ditch the first loop */
206 static gchar *ascii_decapitalize_without_dashes(gchar *source)
208 gchar *ptr, *ret = g_strdup (source);
211 for(ptr = ret; *ptr; ptr++) {
212 if(*ptr >= 'A' && *ptr <= 'Z') {
222 static gchar *hildon_plugin_default_name(gchar *typename)
224 GtkSettings *settings;
225 gchar *ret, *val, *tmp;
229 tmplen = strlen(typename) + strlen("-plugin") + 1;
230 tmp = (gchar *)g_malloc0(tmplen);
231 g_snprintf(tmp, tmplen, "%s-plugin", typename);
234 gtk_settings_install_property(g_param_spec_string(tmp,
236 "Plugin for this pecific widget",
240 settings = gtk_settings_get_default();
242 g_object_get(G_OBJECT(settings), tmp, &val, NULL);
248 ret = (gchar *)g_malloc0(strlen(val)+1);
249 memcpy(ret, val, strlen(val));
252 ret = (gchar *)g_malloc0(strlen("default")+1);
255 g_snprintf(ret, strlen("default")+1, "default");