1 /* 2 * Copyright (C) 2009 - 2012 Vivien Malerba <malerba@gnome-db.org> 3 * Copyright (C) 2010 David King <davidk@openismus.com> 4 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. D3DCOLOR_ARGB(a: DWORD, r: DWORD, g: DWORD, b: DWORD) -> D3DCOLOR15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the 18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include <string.h> 23 #include <gtk/gtk.h> 24 #include <glib/gi18n-lib.h> 25 #include <libgda/libgda.h> 26 #include <libgda-ui/gdaui-data-entry.h> 27 #include <libgda-ui/gdaui-plugin.h> 28 #include <libgda/binreloc/gda-binreloc.h> 29 #include "data-entries/gdaui-entry-boolean.h" 30 #include "data-entries/gdaui-entry-bin.h" 31 #include "data-entries/gdaui-entry-string.h" 32 #include "data-entries/gdaui-entry-number.h" 33 #include "data-entries/gdaui-entry-time.h" 34 #include "data-entries/gdaui-entry-date.h" 35 #include "data-entries/gdaui-entry-timestamp.h" 36 #include "data-entries/gdaui-entry-none.h" 37 #include "data-entries/gdaui-data-cell-renderer-textual.h" 38 #include "data-entries/gdaui-data-cell-renderer-boolean.h" 39 #include "data-entries/gdaui-data-cell-renderer-bin.h" 40 #include "gdaui-resources.h" 41 42 /* plugins list */ 43 44 typedef GSList *(*GdauiPluginInit) (GError **); 45 static GHashTable *init_plugins_hash (void); 46 GHashTable *gdaui_plugins_hash = NULL; /* key = plugin name, value = GdauiPlugin structure pointer */ 47 48 49 /** 50 * gdaui_init: 51 * 52 * Initialization of the libgda-ui library, must be called before any usage of the library. 53 * 54 * <itemizedlist> 55 * <listitem><para>Note 1: gtk_init() is not called by this function and should also 56 * be called (see Note 2 about the importance of the calling order)</para></listitem> 57 * <listitem><para>Note 2: unless you call setlocale() first in your program, calling gtk_init() 58 * before gdaui_init() will ensure that all information loaded from config files will 59 * be loaded in the correct locale (as gtk_init() calls setlocale()).</para></listitem> 60 * <listitem><para>Note 3: this funtion also calls gda_init() so it should not be called 61 * again</para></listitem> 62 * </itemizedlist> 63 * 64 * Since: 4.2 65 */ 66 void 67 gdaui_init (void) 68 { 69 static gboolean initialized = FALSE; 70 71 if (initialized) { 72 gda_log_error (_("Attempt to initialize an already initialized library")); 73 return; 74 } 75 76 /* 77 gchar *str; 78 gdaui_gbr_init (); 79 str = gdaui_gbr_get_locale_dir_path (); 80 bindtextdomain (GETTEXT_PACKAGE, str); 81 g_free (str); 82 */ 83 84 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 85 86 gda_init (); 87 if (! gdaui_plugins_hash) 88 gdaui_plugins_hash = init_plugins_hash (); 89 90 /* initialize CSS */ 91 GBytes *css_data; 92 GError *error = NULL; 93 _gdaui_register_resource (); 94 css_data = g_resources_lookup_data ("/gdaui/gdaui.css", G_RESOURCE_LOOKUP_FLAGS_NONE, &error); 95 if (css_data) { 96 GtkCssProvider *css_provider; 97 css_provider = gtk_css_provider_new (); 98 if (gtk_css_provider_load_from_data (css_provider, 99 (gchar*) g_bytes_get_data (css_data, NULL), -1, 100 &error)) 101 gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), 102 GTK_STYLE_PROVIDER (css_provider), 103 G_MAXUINT); 104 else { 105 g_warning ("Could not parse resource CSS data: %s", 106 error && error->message ? error->message : _("No detail")); 107 g_clear_error (&error); 108 } 109 g_object_unref (css_provider); 110 g_bytes_unref (css_data); 111 } 112 else { 113 g_warning ("Could not load resource CSS data: %s", 114 error && error->message ? error->message : _("No detail")); 115 g_clear_error (&error); 116 } 117 _gdaui_unregister_resource (); 118 119 initialized = TRUE; 120 } 121 122 /** 123 * gdaui_new_data_entry: 124 * @type: a #GType 125 * @plugin_name: (allow-none): the name of an entry plugin, or %NULL 126 * 127 * Creates a new #GdauiDataEntry widget, taking into account the requested entry name 128 * if @plugin_name is not %NULL (if no entry of that name is found, then the default data 129 * entry widget will be created). 130 * 131 * The @plugin_name format is interpreted as two parts: <plugin name>:<plugin options>, and 132 * if the plugins has no option, then the ":<plugin options>" part may be omitted. 133 * 134 * Returns: (transfer full): a new #GdauiDataEntry widget, _NEVER_ %NULL 135 */ 136 GdauiDataEntry * 137 gdaui_new_data_entry (GType type, const gchar *plugin_name) 138 { 139 GdaDataHandler *dh; 140 GdauiDataEntry *entry = NULL; 141 gchar *spec_options = NULL; 142 143 if (!gdaui_plugins_hash) 144 gdaui_plugins_hash = init_plugins_hash (); 145 146 if (type == GDA_TYPE_NULL) 147 return (GdauiDataEntry *) gdaui_entry_none_new (GDA_TYPE_NULL); 148 149 dh = gda_data_handler_get_default (type); 150 151 if (plugin_name && *plugin_name) { 152 GdauiPlugin *plugin_struct; 153 gchar *plugin = g_strdup (plugin_name); 154 gchar *ptr, *options = NULL; 155 156 for (ptr = plugin; *ptr && (*ptr != ':'); ptr++); 157 *ptr = 0; 158 ptr++; 159 if (ptr < plugin + strlen (plugin_name)) { 160 options = ptr; 161 spec_options = g_strdup (options); 162 } 163 164 plugin_struct = g_hash_table_lookup (gdaui_plugins_hash, plugin); 165 if (plugin_struct && plugin_struct->entry_create_func) { 166 gboolean allok = TRUE; 167 if (plugin_struct->nb_g_types > 0) { 168 guint i; 169 for (i = 0; i < plugin_struct->nb_g_types; i++) { 170 if (plugin_struct->valid_g_types[i] == type) 171 break; 172 } 173 if (i == plugin_struct->nb_g_types) 174 allok = FALSE; 175 } 176 if (allok) 177 entry = (plugin_struct->entry_create_func) (dh, type, options); 178 } 179 g_free (plugin); 180 } 181 182 if (!entry) { 183 if (type == G_TYPE_STRING) 184 entry = (GdauiDataEntry *) gdaui_entry_string_new (dh, type, spec_options); 185 else if ((type == G_TYPE_INT64) || 186 (type == G_TYPE_UINT64) || 187 (type == G_TYPE_DOUBLE) || 188 (type == G_TYPE_INT) || 189 (type == G_TYPE_LONG) || 190 (type == GDA_TYPE_NUMERIC) || 191 (type == G_TYPE_FLOAT) || 192 (type == GDA_TYPE_SHORT) || 193 (type == GDA_TYPE_USHORT) || 194 (type == G_TYPE_CHAR) || 195 (type == G_TYPE_UCHAR) || 196 (type == G_TYPE_ULONG) || 197 (type == G_TYPE_UINT)) 198 entry = (GdauiDataEntry *) gdaui_entry_number_new (dh, type, spec_options); 199 else if (type == G_TYPE_BOOLEAN) 200 entry = (GdauiDataEntry *) gdaui_entry_boolean_new (dh, G_TYPE_BOOLEAN); 201 else if ((type == GDA_TYPE_BLOB) || 202 (type == GDA_TYPE_BINARY)) 203 entry = (GdauiDataEntry *) gdaui_entry_bin_new (dh, type); 204 else if ((type == GDA_TYPE_GEOMETRIC_POINT) || 205 (type == G_TYPE_OBJECT)) 206 entry = (GdauiDataEntry *) gdaui_entry_none_new (type); 207 else if (type == GDA_TYPE_TIME) 208 entry = (GdauiDataEntry *) gdaui_entry_time_new (dh); 209 else if (type == GDA_TYPE_TIMESTAMP) 210 entry = (GdauiDataEntry *) gdaui_entry_timestamp_new (dh); 211 else if (type == G_TYPE_DATE) 212 entry = (GdauiDataEntry *) gdaui_entry_date_new (dh); 213 else 214 entry = (GdauiDataEntry *) gdaui_entry_none_new (type); 215 } 216 217 g_free (spec_options); 218 return entry; 219 } 220 221 /* 222 * _gdaui_new_cell_renderer 223 * @type: a #GType 224 * @plugin_name: (allow-none): the name of an entry plugin, or %NULL 225 * 226 * Creates a new #GtkCellRenderer object which is suitable to use in 227 * a #GtkTreeView widget, taking into account the requested entry name 228 * if @plugin_name is not %NULL (if no entry of that name is found, then the default data 229 * entry widget will be created). 230 * 231 * @plugin_name format is interpreted as two parts: <plugin name>:<plugin options>, and 232 * if the plugins has no option, then the ":<plugin options>" part may be omitted. 233 * 234 * 235 * Returns: a new #GtkCellRenderer object, _NEVER_ %NULL 236 */ 237 GtkCellRenderer * 238 _gdaui_new_cell_renderer (GType type, const gchar *plugin_name) 239 { 240 GdaDataHandler *dh; 241 GtkCellRenderer *cell = NULL; 242 243 if (!gdaui_plugins_hash) 244 gdaui_plugins_hash = init_plugins_hash (); 245 246 dh = gda_data_handler_get_default (type); 247 248 if (plugin_name && *plugin_name) { 249 GdauiPlugin *plugin_struct; 250 gchar *plugin = g_strdup (plugin_name); 251 gchar *ptr, *options = NULL; 252 253 for (ptr = plugin; *ptr && (*ptr != ':'); ptr++); 254 *ptr = 0; 255 ptr++; 256 if (ptr < plugin + strlen (plugin_name)) 257 options = ptr; 258 259 plugin_struct = g_hash_table_lookup (gdaui_plugins_hash, plugin); 260 if (plugin_struct && plugin_struct->cell_create_func) 261 cell = (plugin_struct->cell_create_func) (dh, type, options); 262 g_free (plugin); 263 } 264 265 if (!cell) { 266 if (type == GDA_TYPE_NULL) 267 cell = gdaui_data_cell_renderer_textual_new (NULL, GDA_TYPE_NULL, NULL); 268 else if (type == G_TYPE_BOOLEAN) 269 cell = gdaui_data_cell_renderer_boolean_new (dh, G_TYPE_BOOLEAN); 270 else if ((type == GDA_TYPE_BLOB) || 271 (type == GDA_TYPE_BINARY)) 272 cell = gdaui_data_cell_renderer_bin_new (dh, type); 273 else 274 cell = gdaui_data_cell_renderer_textual_new (dh, type, NULL); 275 } 276 277 return cell; 278 } 279 280 /** 281 * gdaui_plugin_declare: 282 * @plugin: a pointer to a structure filled to describe the new plugin. All the contained information is copied. 283 * 284 * Adds a new plugin which will be used by the forms and grids. The new plugin, as 285 * described by @plugin can declare a custom widget to be used for forms, grids, or both. 286 * 287 * If a plugin is already declared with the same name as the requested name, then 288 * a warning is issued and the operation fails. 289 */ 290 void 291 gdaui_plugin_declare (const GdauiPlugin *plugin) 292 { 293 GdauiPlugin *np; 294 295 g_return_if_fail (plugin); 296 g_return_if_fail (plugin->plugin_name); 297 if (!gdaui_plugins_hash) 298 gdaui_plugins_hash = init_plugins_hash (); 299 if (g_hash_table_lookup (gdaui_plugins_hash, plugin->plugin_name)) { 300 g_warning ("Plugin '%s' already declared", plugin->plugin_name); 301 return; 302 } 303 if (((plugin->nb_g_types < 1) && plugin->valid_g_types) || 304 ((plugin->nb_g_types > 0) && !plugin->valid_g_types)) { 305 g_warning ("Invalid description of plugin accepted types"); 306 return; 307 } 308 g_return_if_fail (plugin->entry_create_func || plugin->cell_create_func); 309 310 np = g_new0 (GdauiPlugin, 1); 311 np->plugin_name = g_strdup (plugin->plugin_name); 312 if (plugin->plugin_descr) 313 np->plugin_descr = g_strdup (plugin->plugin_descr); 314 np->plugin_file = g_strdup (plugin->plugin_file); 315 316 np->nb_g_types = plugin->nb_g_types; 317 if (plugin->valid_g_types) { 318 np->valid_g_types = g_new0 (GType, np->nb_g_types); 319 memcpy (np->valid_g_types, plugin->valid_g_types, sizeof (GType) * np->nb_g_types); 320 } 321 322 if (plugin->options_xml_spec) 323 np->options_xml_spec = g_strdup (plugin->options_xml_spec); 324 np->entry_create_func = plugin->entry_create_func; 325 np->cell_create_func = plugin->cell_create_func; 326 327 g_hash_table_insert (gdaui_plugins_hash, np->plugin_name, np); 328 } 329 330 static GdauiDataEntry *entry_none_create_func (GdaDataHandler *handler, GType type, const gchar *options); 331 static GdauiDataEntry *entry_boolean_create_func (GdaDataHandler *handler, GType type, const gchar *options); 332 static GdauiDataEntry *entry_bin_create_func (GdaDataHandler *handler, GType type, const gchar *options); 333 static GdauiDataEntry *entry_string_create_func (GdaDataHandler *handler, GType type, const gchar *options); 334 static GdauiDataEntry *entry_number_create_func (GdaDataHandler *handler, GType type, const gchar *options); 335 static GdauiDataEntry *entry_time_create_func (GdaDataHandler *handler, GType type, const gchar *options); 336 static GdauiDataEntry *entry_timestamp_create_func (GdaDataHandler *handler, GType type, const gchar *options); 337 static GdauiDataEntry *entry_date_create_func (GdaDataHandler *handler, GType type, const gchar *options); 338 339 static GtkCellRenderer *cell_textual_create_func (GdaDataHandler *handler, GType type, const gchar *options); 340 static GtkCellRenderer *cell_boolean_create_func (GdaDataHandler *handler, GType type, const gchar *options); 341 static GtkCellRenderer *cell_bin_create_func (GdaDataHandler *handler, GType type, const gchar *options); 342 343 static xmlChar *get_spec_with_isocodes (const gchar *file); 344 345 static GHashTable * 346 init_plugins_hash (void) 347 { 348 GHashTable *hash; 349 GdauiPlugin *plugin; 350 gchar *file; 351 352 hash = g_hash_table_new (g_str_hash, g_str_equal); /* key strings are not handled in the hash table */ 353 354 /* default data entry widgets: they are not plugins but will be stored in GdauiPlugin structures */ 355 plugin = g_new0 (GdauiPlugin, 1); 356 plugin->plugin_name = "none"; 357 plugin->plugin_descr = "Nothing displayed"; 358 plugin->plugin_file = NULL; 359 plugin->nb_g_types = 0; 360 plugin->valid_g_types = NULL; 361 plugin->options_xml_spec = NULL; 362 plugin->entry_create_func = entry_none_create_func; 363 plugin->cell_create_func = NULL; 364 g_hash_table_insert (hash, plugin->plugin_name, plugin); 365 366 plugin = g_new0 (GdauiPlugin, 1); 367 plugin->plugin_name = "boolean"; 368 plugin->plugin_descr = "Boolean entry"; 369 plugin->plugin_file = NULL; 370 plugin->nb_g_types = 1; 371 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 372 plugin->valid_g_types [0] = G_TYPE_BOOLEAN; 373 plugin->options_xml_spec = NULL; 374 plugin->entry_create_func = entry_boolean_create_func; 375 plugin->cell_create_func = cell_boolean_create_func; 376 g_hash_table_insert (hash, plugin->plugin_name, plugin); 377 378 plugin = g_new0 (GdauiPlugin, 1); 379 plugin->plugin_name = "binary"; 380 plugin->plugin_descr = "Binary data entry"; 381 plugin->plugin_file = NULL; 382 plugin->nb_g_types = 2; 383 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 384 plugin->valid_g_types [0] = GDA_TYPE_BLOB; 385 plugin->valid_g_types [1] = GDA_TYPE_BINARY; 386 plugin->options_xml_spec = NULL; 387 plugin->entry_create_func = entry_bin_create_func; 388 plugin->cell_create_func = cell_bin_create_func; 389 g_hash_table_insert (hash, plugin->plugin_name, plugin); 390 391 plugin = g_new0 (GdauiPlugin, 1); 392 plugin->plugin_name = "string"; 393 plugin->plugin_descr = "String entry"; 394 plugin->plugin_file = NULL; 395 plugin->nb_g_types = 1; 396 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 397 plugin->valid_g_types [0] = G_TYPE_STRING; 398 plugin->options_xml_spec = NULL; 399 plugin->entry_create_func = entry_string_create_func; 400 plugin->cell_create_func = cell_textual_create_func; 401 g_hash_table_insert (hash, plugin->plugin_name, plugin); 402 file = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "ui", "gdaui-entry-string.xml", NULL); 403 if (! g_file_test (file, G_FILE_TEST_EXISTS)) { 404 g_message ("Could not find file '%s': '%s' data entry will not report any possible option", 405 file, plugin->plugin_name); 406 } 407 else { 408 gsize len; 409 g_file_get_contents (file, &(plugin->options_xml_spec), &len, NULL); 410 } 411 g_free (file); 412 413 plugin = g_new0 (GdauiPlugin, 1); 414 plugin->plugin_name = "number"; 415 plugin->plugin_descr = "Numeric entry"; 416 plugin->plugin_file = NULL; 417 plugin->nb_g_types = 12; 418 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 419 plugin->valid_g_types [0] = G_TYPE_INT64; 420 plugin->valid_g_types [1] = G_TYPE_UINT64; 421 plugin->valid_g_types [2] = G_TYPE_DOUBLE; 422 plugin->valid_g_types [3] = G_TYPE_INT; 423 plugin->valid_g_types [4] = GDA_TYPE_NUMERIC; 424 plugin->valid_g_types [5] = G_TYPE_FLOAT; 425 plugin->valid_g_types [6] = GDA_TYPE_SHORT; 426 plugin->valid_g_types [7] = GDA_TYPE_USHORT; 427 plugin->valid_g_types [8] = G_TYPE_CHAR; 428 plugin->valid_g_types [9] = G_TYPE_UCHAR; 429 plugin->valid_g_types [10] = G_TYPE_ULONG; 430 plugin->valid_g_types [11] = G_TYPE_UINT; 431 plugin->options_xml_spec = NULL; 432 plugin->entry_create_func = entry_number_create_func; 433 plugin->cell_create_func = cell_textual_create_func; 434 g_hash_table_insert (hash, plugin->plugin_name, plugin); 435 file = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, "ui", "gdaui-entry-number.xml", NULL); 436 xmlChar *xml_spec = get_spec_with_isocodes (file); 437 if (xml_spec) { 438 plugin->options_xml_spec = g_strdup ((gchar*) xml_spec); 439 xmlFree (xml_spec); 440 } 441 g_free (file); 442 443 plugin = g_new0 (GdauiPlugin, 1); 444 plugin->plugin_name = "textual"; 445 plugin->plugin_descr = "Textual entry"; 446 plugin->plugin_file = NULL; 447 plugin->nb_g_types = 1; 448 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 449 plugin->valid_g_types [0] = G_TYPE_STRING; 450 plugin->options_xml_spec = NULL; 451 plugin->entry_create_func = entry_string_create_func; 452 plugin->cell_create_func = cell_textual_create_func; 453 g_hash_table_insert (hash, plugin->plugin_name, plugin); 454 455 plugin = g_new0 (GdauiPlugin, 1); 456 plugin->plugin_name = "time"; 457 plugin->plugin_descr = "Time (HH:MM:SS) entry"; 458 plugin->plugin_file = NULL; 459 plugin->nb_g_types = 1; 460 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 461 plugin->valid_g_types [0] = GDA_TYPE_TIME; 462 plugin->options_xml_spec = NULL; 463 plugin->entry_create_func = entry_time_create_func; 464 plugin->cell_create_func = NULL; 465 g_hash_table_insert (hash, plugin->plugin_name, plugin); 466 467 plugin = g_new0 (GdauiPlugin, 1); 468 plugin->plugin_name = "timestamp"; 469 plugin->plugin_descr = "Timestamp (Date + HH:MM:SS) entry"; 470 plugin->plugin_file = NULL; 471 plugin->nb_g_types = 1; 472 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 473 plugin->valid_g_types [0] = GDA_TYPE_TIMESTAMP; 474 plugin->options_xml_spec = NULL; 475 plugin->entry_create_func = entry_timestamp_create_func; 476 plugin->cell_create_func = NULL; 477 g_hash_table_insert (hash, plugin->plugin_name, plugin); 478 479 plugin = g_new0 (GdauiPlugin, 1); 480 plugin->plugin_name = "date"; 481 plugin->plugin_descr = "Date entry"; 482 plugin->plugin_file = NULL; 483 plugin->nb_g_types = 1; 484 plugin->valid_g_types = g_new (GType, plugin->nb_g_types); 485 plugin->valid_g_types [0] = G_TYPE_DATE; 486 plugin->options_xml_spec = NULL; 487 plugin->entry_create_func = entry_date_create_func; 488 plugin->cell_create_func = NULL; 489 g_hash_table_insert (hash, plugin->plugin_name, plugin); 490 491 /* plugins */ 492 GDir *dir; 493 GError *err = NULL; 494 gchar *plugins_dir; 495 gboolean show_status = FALSE; 496 497 /* read the plugin directory */ 498 plugins_dir = gda_gbr_get_file_path (GDA_LIB_DIR, LIBGDA_ABI_NAME, "plugins", NULL); 499 if (g_getenv ("GDAUI_SHOW_PLUGINS_LOADING")) 500 show_status = TRUE; 501 if (show_status) 502 g_print ("Trying to load plugins in %s...\n", plugins_dir); 503 dir = g_dir_open (plugins_dir, 0, NULL); 504 if (!dir) { 505 g_free (plugins_dir); 506 plugins_dir = g_strdup (PLUGINSDIR); 507 if (show_status) 508 g_print ("Trying to load plugins in %s...\n", plugins_dir); 509 dir = g_dir_open (plugins_dir, 0, NULL); 510 } 511 if (!dir && show_status) 512 g_warning (_("Could not open plugins directory, no plugin loaded.")); 513 else { 514 const gchar *name; 515 516 while ((name = g_dir_read_name (dir))) { 517 gchar *ext; 518 GModule *handle; 519 gchar *path; 520 GdauiPluginInit plugin_init; 521 GSList *plugins; 522 523 ext = g_strrstr (name, "."); 524 if (!ext) 525 continue; 526 if (strcmp (ext + 1, G_MODULE_SUFFIX)) 527 continue; 528 529 path = g_build_path (G_DIR_SEPARATOR_S, plugins_dir, name, NULL); 530 handle = g_module_open (path, G_MODULE_BIND_LAZY); 531 if (!handle) { 532 g_warning (_("Error: %s"), g_module_error ()); 533 g_free (path); 534 continue; 535 } 536 537 g_module_symbol (handle, "plugin_init", (gpointer*) &plugin_init); 538 if (plugin_init) { 539 if (show_status) 540 g_print (_("Loading file %s...\n"), path); 541 plugins = plugin_init (&err); 542 if (err) { 543 if (show_status) 544 g_message (_("Plugins load warning: %s"), 545 err->message ? err->message : _("No detail")); 546 if (err) 547 g_error_free (err); 548 err = NULL; 549 } 550 551 GSList *list; 552 for (list = plugins; list; list = list->next) { 553 GdauiPlugin *plugin; 554 555 plugin = (GdauiPlugin *)(list->data); 556 g_hash_table_insert (hash, plugin->plugin_name, plugin); 557 if (show_status) { 558 g_print (" - loaded %s (%s):", plugin->plugin_name, 559 plugin->plugin_descr); 560 if (plugin->entry_create_func) 561 g_print (" Entry"); 562 if (plugin->cell_create_func) 563 g_print (" Cell"); 564 g_print ("\n"); 565 } 566 plugin->plugin_file = g_strdup (path); 567 } 568 g_slist_free (plugins); 569 } 570 g_free (path); 571 } 572 g_dir_close (dir); 573 } 574 g_free (plugins_dir); 575 576 return hash; 577 } 578 579 static GdauiDataEntry * 580 entry_none_create_func (G_GNUC_UNUSED GdaDataHandler *handler, GType type, G_GNUC_UNUSED const gchar *options) 581 { 582 return (GdauiDataEntry *) gdaui_entry_none_new (type); 583 } 584 585 static GdauiDataEntry * 586 entry_boolean_create_func (GdaDataHandler *handler, G_GNUC_UNUSED GType type, 587 G_GNUC_UNUSED const gchar *options) 588 { 589 return (GdauiDataEntry *) gdaui_entry_boolean_new (handler, G_TYPE_BOOLEAN); 590 } 591 592 static GdauiDataEntry * 593 entry_bin_create_func (GdaDataHandler *handler, GType type, G_GNUC_UNUSED const gchar *options) 594 { 595 return (GdauiDataEntry *) gdaui_entry_bin_new (handler, type); 596 } 597 598 static GdauiDataEntry * 599 entry_string_create_func (GdaDataHandler *handler, GType type, const gchar *options) 600 { 601 return (GdauiDataEntry *) gdaui_entry_string_new (handler, type, options); 602 } 603 604 static GdauiDataEntry * 605 entry_number_create_func (GdaDataHandler *handler, GType type, const gchar *options) 606 { 607 return (GdauiDataEntry *) gdaui_entry_number_new (handler, type, options); 608 } 609 610 static GdauiDataEntry * 611 entry_time_create_func (GdaDataHandler *handler, G_GNUC_UNUSED GType type, G_GNUC_UNUSED const gchar *options) 612 { 613 return (GdauiDataEntry *) gdaui_entry_time_new (handler); 614 } 615 616 static GdauiDataEntry * 617 entry_timestamp_create_func (GdaDataHandler *handler, G_GNUC_UNUSED GType type, 618 G_GNUC_UNUSED const gchar *options) 619 { 620 return (GdauiDataEntry *) gdaui_entry_timestamp_new (handler); 621 } 622 623 static GdauiDataEntry * 624 entry_date_create_func (GdaDataHandler *handler, G_GNUC_UNUSED GType type, G_GNUC_UNUSED const gchar *options) 625 { 626 return (GdauiDataEntry *) gdaui_entry_date_new (handler); 627 } 628 629 static GtkCellRenderer * 630 cell_textual_create_func (GdaDataHandler *handler, GType type, const gchar *options) 631 { 632 return gdaui_data_cell_renderer_textual_new (handler, type, options); 633 } 634 635 static GtkCellRenderer * 636 cell_boolean_create_func (GdaDataHandler *handler, G_GNUC_UNUSED GType type, 637 G_GNUC_UNUSED const gchar *options) 638 { 639 return gdaui_data_cell_renderer_boolean_new (handler, G_TYPE_BOOLEAN); 640 } 641 642 static GtkCellRenderer * 643 cell_bin_create_func (GdaDataHandler *handler, GType type, G_GNUC_UNUSED const gchar *options) 644 { 645 return gdaui_data_cell_renderer_bin_new (handler, type); 646 } 647 648 static xmlNodePtr 649 find_child_node_from_name (xmlNodePtr parent, const gchar *name, const gchar *attr_name, const gchar *attr_value) 650 { 651 xmlNodePtr node; 652 653 if (!parent) 654 return NULL; 655 656 for (node = parent->children; node; node = node->next) { 657 if (!strcmp ((gchar*) node->name, name)) { 658 if (attr_name) { 659 xmlChar *prop; 660 prop = xmlGetProp (node, BAD_CAST attr_name); 661 if (prop) { 662 if (attr_value && !strcmp ((gchar*) prop, attr_value)) { 663 xmlFree (prop); 664 break; 665 } 666 xmlFree (prop); 667 } 668 } 669 else 670 break; 671 } 672 } 673 if (!node) 674 g_warning ("Failed to find the <%s> tag", name); 675 676 return node; 677 } 678 679 static xmlChar * 680 get_spec_with_isocodes (const gchar *file) 681 { 682 xmlDocPtr spec, isocodes = NULL; 683 xmlChar *retval = NULL; 684 gchar *isofile = NULL; 685 GError *err = NULL; 686 gchar *buf = NULL; 687 int buf_len; 688 689 /* 690 * Load iso codes 691 */ 692 #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale" 693 694 bindtextdomain ("iso_4217", ISO_CODES_LOCALESDIR); 695 bind_textdomain_codeset ("iso_4217", "UTF-8"); 696 697 isofile = g_build_filename (ISO_CODES_PREFIX, "share", "xml", "iso-codes", "iso_4217.xml", NULL); 698 if (g_file_get_contents (isofile, &buf, NULL, &err)) { 699 isocodes = xmlParseDoc (BAD_CAST buf); 700 g_free (buf); 701 buf = NULL; 702 } 703 704 /* 705 * Load spec string 706 */ 707 spec = xmlParseFile (file); 708 if (!spec) { 709 g_warning ("Can't load '%s' file", file); 710 goto cleanup; 711 } 712 713 if (isocodes) { 714 /* 715 * Merge isocodes into spec 716 */ 717 xmlNodePtr node, spec_node; 718 719 node = find_child_node_from_name (xmlDocGetRootElement (spec), "sources", NULL, NULL); 720 node = find_child_node_from_name (node, "gda_array", "name", "currencies"); 721 spec_node = find_child_node_from_name (node, "gda_array_data", NULL, NULL); 722 xmlUnlinkNode (spec_node); 723 xmlFreeNode (spec_node); 724 spec_node = xmlNewChild (node, NULL, BAD_CAST "gda_array_data", NULL); 725 726 node = xmlDocGetRootElement (isocodes); 727 for (node = node->children; node; node = node->next) { 728 if (!strcmp ((gchar*) node->name, "iso_4217_entry")) { 729 xmlChar *code, *name; 730 code = xmlGetProp (node, BAD_CAST "letter_code"); 731 name = xmlGetProp (node, BAD_CAST "currency_name"); 732 if (code && name) { 733 xmlNodePtr row; 734 row = xmlNewChild (spec_node, NULL, BAD_CAST "gda_array_row", NULL); 735 xmlNewChild (row, NULL, BAD_CAST "gda_value", code); 736 xmlNewChild (row, NULL, BAD_CAST "gda_value", code); 737 xmlNewChild (row, NULL, BAD_CAST "gda_value", 738 BAD_CAST dgettext ("iso_4217", (gchar*) name)); 739 } 740 if (code) 741 xmlFree (code); 742 if (name) 743 xmlFree (name); 744 } 745 } 746 } 747 else { 748 /* 749 * No ISO CODES found => no predefined source 750 */ 751 xmlNodePtr node; 752 node = find_child_node_from_name (xmlDocGetRootElement (spec), "sources", NULL, NULL); 753 node = find_child_node_from_name (node, "gda_array", "name", "currencies"); 754 xmlUnlinkNode (node); 755 xmlFreeNode (node); 756 757 node = find_child_node_from_name (xmlDocGetRootElement (spec), "parameters", NULL, NULL); 758 node = find_child_node_from_name (node, "parameter", "id", "CURRENCY"); 759 xmlSetProp (node, BAD_CAST "source", NULL); 760 } 761 762 xmlDocDumpMemory (spec, (xmlChar **) &retval, &buf_len); 763 764 cleanup: 765 if (spec) 766 xmlFreeDoc (spec); 767 if (isocodes) 768 xmlFreeDoc (isocodes); 769 g_free (isofile); 770 g_free (buf); 771 772 return retval; 773 } 774 775 static gchar *gdaui_path = NULL; 776 777 /** 778 * gdaui_get_default_path: 779 * 780 * Get the default path used when saving a file, or when showing a #GtkFileChooser file chooser. 781 * When the application starts, the default path will be the same as the onde returned by 782 * g_get_current_dir(). 783 * 784 * Returns: (transfer none): the default path, or %NULL 785 * 786 * Since: 4.2.9 787 */ 788 const gchar * 789 gdaui_get_default_path (void) 790 { 791 if (! gdaui_path) 792 gdaui_path = g_get_current_dir (); 793 return gdaui_path; 794 } 795 796 /** 797 * gdaui_set_default_path: 798 * @path: (allow-none): a path, or %NULL to unset 799 * 800 * Define the default path used when saving a file, or when showing a #GtkFileChooser file chooser. 801 * 802 * Since: 4.2.9 803 */ 804 void 805 gdaui_set_default_path (const gchar *path) 806 { 807 g_free (gdaui_path); 808 gdaui_path = NULL; 809 if (path) 810 gdaui_path = g_strdup (path); 811 } 812