|
GnuCash 2.4.99
|
00001 /* 00002 * gnc-plugin-file-history.c -- 00003 * Copyright (C) 2003,2005 David Hampton <hampton@employees.org> 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License as 00007 * published by the Free Software Foundation; either version 2 of 00008 * the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, contact: 00017 * 00018 * Free Software Foundation Voice: +1-617-542-5942 00019 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00020 * Boston, MA 02110-1301, USA gnu@gnu.org 00021 */ 00022 00032 #include "config.h" 00033 00034 #include <gtk/gtk.h> 00035 #include <glib/gi18n.h> 00036 #include <glib/gprintf.h> 00037 #include <string.h> 00038 00039 #include "gnc-gkeyfile-utils.h" 00040 #include "gnc-file.h" 00041 #include "gnc-main-window.h" 00042 #include "gnc-plugin-file-history.h" 00043 #include "gnc-window.h" 00044 #include "gnc-engine.h" 00045 #include "gnc-gconf-utils.h" 00046 #include "gnc-uri-utils.h" 00047 00048 static GObjectClass *parent_class = NULL; 00049 00050 #define FILENAME_STRING "filename" 00051 00052 static void gnc_plugin_file_history_class_init (GncPluginFileHistoryClass *klass); 00053 static void gnc_plugin_file_history_init (GncPluginFileHistory *plugin); 00054 static void gnc_plugin_file_history_finalize (GObject *object); 00055 00056 static void gnc_plugin_file_history_add_to_window (GncPlugin *plugin, GncMainWindow *window, GQuark type); 00057 static void gnc_plugin_file_history_remove_from_window (GncPlugin *plugin, GncMainWindow *window, GQuark type); 00058 00059 00061 static QofLogModule log_module = GNC_MOD_GUI; 00062 00063 /* Command callbacks */ 00064 static void gnc_plugin_file_history_cmd_open_file (GtkAction *action, GncMainWindowActionData *data); 00065 00066 00068 #define PLUGIN_ACTIONS_NAME "gnc-plugin-file-history-actions" 00069 00070 #define PLUGIN_UI_FILENAME "gnc-plugin-file-history-ui.xml" 00071 00072 #define GNOME1_HISTORY "History" 00073 #define GNOME1_MAXFILES "MaxFiles" 00074 00080 static GtkActionEntry gnc_plugin_actions [] = 00081 { 00082 { "RecentFile0Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00083 { "RecentFile1Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00084 { "RecentFile2Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00085 { "RecentFile3Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00086 { "RecentFile4Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00087 { "RecentFile5Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00088 { "RecentFile6Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00089 { "RecentFile7Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00090 { "RecentFile8Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00091 { "RecentFile9Action", NULL, "", NULL, NULL, G_CALLBACK (gnc_plugin_file_history_cmd_open_file) }, 00092 }; 00094 static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions); 00095 00096 00099 typedef struct GncPluginFileHistoryPrivate 00100 { 00101 gpointer dummy; 00102 } GncPluginFileHistoryPrivate; 00103 00104 00105 #define GNC_PLUGIN_FILE_HISTORY_GET_PRIVATE(o) \ 00106 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_FILE_HISTORY, GncPluginFileHistoryPrivate)) 00107 00108 /************************************************************ 00109 * Other Functions * 00110 ************************************************************/ 00111 00120 static gchar * 00121 gnc_history_gconf_index_to_key (guint index) 00122 { 00123 return g_strdup_printf(HISTORY_STRING_FILE_N, index); 00124 } 00125 00126 00135 static gint 00136 gnc_history_gconf_key_to_index (const gchar *key) 00137 { 00138 gint index, result; 00139 00140 result = sscanf(key, HISTORY_STRING_FILE_N, &index); 00141 if (result != 1) 00142 return -1; 00143 if ((index < 0) || (index >= gnc_plugin_n_actions)) 00144 return -1; 00145 return index; 00146 } 00147 00148 00149 /* Add a file name to the front of the file "history list". If the 00150 * name already exist on the list, then it is moved from its current 00151 * location to the front of the list. The "list" is actually a 00152 * sequence of up to ten gconf keys. 00153 */ 00154 void 00155 gnc_history_add_file (const char *newfile) 00156 { 00157 gchar *filename, *from, *to; 00158 gint i, last; 00159 00160 if (newfile == NULL) 00161 return; 00162 if (!g_utf8_validate(newfile, -1, NULL)) 00163 return; 00164 00165 /* 00166 * Look for the filename in gconf. 00167 */ 00168 last = MAX_HISTORY_FILES - 1; 00169 for (i = 0; i < MAX_HISTORY_FILES; i++) 00170 { 00171 from = gnc_history_gconf_index_to_key(i); 00172 filename = gnc_gconf_get_string(HISTORY_STRING_SECTION, from, NULL); 00173 g_free(from); 00174 00175 if (!filename) 00176 { 00177 last = i; 00178 break; 00179 } 00180 if (g_utf8_collate(newfile, filename) == 0) 00181 { 00182 g_free(filename); 00183 last = i; 00184 break; 00185 } 00186 g_free(filename); 00187 } 00188 00189 /* 00190 * Shuffle filenames upward through gconf. 00191 */ 00192 to = gnc_history_gconf_index_to_key(last); 00193 for (i = last - 1; i >= 0; i--) 00194 { 00195 from = gnc_history_gconf_index_to_key(i); 00196 filename = gnc_gconf_get_string(HISTORY_STRING_SECTION, from, NULL); 00197 if (filename) 00198 { 00199 gnc_gconf_set_string(HISTORY_STRING_SECTION, to, filename, NULL); 00200 g_free(filename); 00201 } 00202 else 00203 { 00204 gnc_gconf_unset(HISTORY_STRING_SECTION, to, NULL); 00205 } 00206 g_free(to); 00207 to = from; 00208 } 00209 00210 /* 00211 * Store the new zero entry. 00212 */ 00213 gnc_gconf_set_string(HISTORY_STRING_SECTION, to, newfile, NULL); 00214 g_free(to); 00215 } 00216 00217 00223 void 00224 gnc_history_remove_file (const char *oldfile) 00225 { 00226 gchar *filename, *from, *to; 00227 gint i, j; 00228 00229 if (!oldfile) 00230 return; 00231 if (!g_utf8_validate(oldfile, -1, NULL)) 00232 return; 00233 00234 for (i = 0, j = 0; i < MAX_HISTORY_FILES; i++) 00235 { 00236 from = gnc_history_gconf_index_to_key(i); 00237 filename = gnc_gconf_get_string(HISTORY_STRING_SECTION, from, NULL); 00238 00239 if (filename) 00240 { 00241 if (g_utf8_collate(oldfile, filename) == 0) 00242 { 00243 gnc_gconf_unset(HISTORY_STRING_SECTION, from, NULL); 00244 } 00245 else 00246 { 00247 if (i != j) 00248 { 00249 to = gnc_history_gconf_index_to_key(j); 00250 gnc_gconf_set_string(HISTORY_STRING_SECTION, to, filename, NULL); 00251 gnc_gconf_unset(HISTORY_STRING_SECTION, from, NULL); 00252 g_free(to); 00253 } 00254 j++; 00255 } 00256 } 00257 g_free(from); 00258 } 00259 } 00260 00261 /* Retrieve the name of the file most recently accessed. This is the 00262 * name at the front of the list. Since the "list" is actually a 00263 * sequence of up to ten gconf keys, this is the value of key zero. 00264 */ 00265 char * 00266 gnc_history_get_last (void) 00267 { 00268 char *filename, *key; 00269 00270 key = gnc_history_gconf_index_to_key(0); 00271 filename = gnc_gconf_get_string(HISTORY_STRING_SECTION, key, NULL); 00272 g_free(key); 00273 00274 return filename; 00275 } 00276 00277 00278 /************************************************************ 00279 * Other Functions * 00280 ************************************************************/ 00281 00291 static gchar * 00292 gnc_history_generate_label (int index, const gchar *filename) 00293 { 00294 gchar *label, *result; 00295 gchar **splitlabel; 00296 00297 if ( gnc_uri_is_file_uri ( filename ) ) 00298 { 00299 /* for file paths, only display the file name */ 00300 gchar *filepath = gnc_uri_get_path ( filename ); 00301 label = g_path_get_basename ( filepath ); 00302 g_free ( filepath ); 00303 } 00304 else 00305 { 00306 /* for databases, display the full uri, except for the password */ 00307 label = gnc_uri_normalize_uri ( filename, FALSE ); 00308 } 00309 00310 /* Escape '_' characters */ 00311 splitlabel = g_strsplit ( label, "_", 0); 00312 g_free (label); 00313 label = g_strjoinv ( "__", splitlabel); 00314 g_strfreev (splitlabel); 00315 00316 result = g_strdup_printf ( "_%d %s", (index + 1) % 10, label); 00317 g_free ( label ); 00318 return result; 00319 00320 } 00321 00322 00340 static void 00341 gnc_history_update_action (GncMainWindow *window, 00342 gint index, 00343 const gchar *filename) 00344 { 00345 GtkActionGroup *action_group; 00346 GtkAction *action; 00347 gchar *action_name, *label_name, *old_filename; 00348 gint limit; 00349 00350 ENTER("window %p, index %d, filename %s", window, index, 00351 filename ? filename : "(null)"); 00352 /* Get the action group */ 00353 action_group = 00354 gnc_main_window_get_action_group(window, PLUGIN_ACTIONS_NAME); 00355 00356 action_name = g_strdup_printf("RecentFile%dAction", index); 00357 action = gtk_action_group_get_action (action_group, action_name); 00358 00359 limit = gnc_gconf_get_int (HISTORY_STRING_SECTION, 00360 HISTORY_STRING_MAXFILES, 00361 NULL); 00362 00363 if (filename && (strlen(filename) > 0) && (index < limit)) 00364 { 00365 /* set the menu label (w/accelerator) */ 00366 label_name = gnc_history_generate_label(index, filename); 00367 g_object_set(G_OBJECT(action), "label", label_name, "visible", TRUE, NULL); 00368 g_free(label_name); 00369 00370 /* set the filename for the callback function */ 00371 old_filename = g_object_get_data(G_OBJECT(action), FILENAME_STRING); 00372 if (old_filename) 00373 g_free(old_filename); 00374 g_object_set_data(G_OBJECT(action), FILENAME_STRING, g_strdup(filename)); 00375 } 00376 else 00377 { 00378 gtk_action_set_visible(action, FALSE); 00379 } 00380 g_free(action_name); 00381 LEAVE(""); 00382 } 00383 00384 00393 static void 00394 gnc_history_update_menus (GncMainWindow *window) 00395 { 00396 gchar *filename, *key; 00397 guint i; 00398 00399 ENTER(""); 00400 for (i = 0; i < MAX_HISTORY_FILES; i++) 00401 { 00402 key = gnc_history_gconf_index_to_key(i); 00403 filename = gnc_gconf_get_string(HISTORY_STRING_SECTION, key, NULL); 00404 gnc_history_update_action(window, i, filename); 00405 g_free(filename); 00406 g_free(key); 00407 } 00408 LEAVE(""); 00409 } 00410 00411 00427 static void 00428 gnc_plugin_history_list_changed (GConfClient *client, 00429 guint cnxn_id, 00430 GConfEntry *entry, 00431 gpointer user_data) 00432 { 00433 GncMainWindow *window; 00434 GConfValue *value; 00435 const gchar *fullkey, *key, *filename; 00436 gint index; 00437 00438 ENTER(""); 00439 window = GNC_MAIN_WINDOW(user_data); 00440 00441 fullkey = gconf_entry_get_key(entry); 00442 key = strrchr(fullkey, '/') + 1; 00443 if (strcmp(key, HISTORY_STRING_MAXFILES) == 0) 00444 { 00445 gnc_history_update_menus (window); 00446 LEAVE("updated maxfiles"); 00447 return; 00448 } 00449 index = gnc_history_gconf_key_to_index(key); 00450 if (index < 0) 00451 { 00452 LEAVE("bad index"); 00453 return; 00454 } 00455 00456 value = gconf_entry_get_value(entry); 00457 if (!value) 00458 { 00459 LEAVE("No gconf value"); 00460 return; 00461 } 00462 filename = gconf_value_get_string(value); 00463 gnc_history_update_action (window, index, filename); 00464 00465 gnc_main_window_actions_updated (window); 00466 LEAVE(""); 00467 } 00468 00469 00470 /* This routine copies the gnucash 1.x file history list over to 00471 * gnucash 2.0. */ 00472 static void 00473 gnc_plugin_history_list_from_gnucash1 (void) 00474 { 00475 GKeyFile *keyfile; 00476 const gchar *home; 00477 gchar *mdi_file, *value; 00478 gchar **keys, **key, *new_key; 00479 gint file_id, max; 00480 00481 /* First test if there are already files in the gconf file history. 00482 * If so, then bail out now. */ 00483 value = gnc_gconf_get_string(HISTORY_STRING_SECTION, "file0", NULL); 00484 if (value) 00485 { 00486 g_free(value); 00487 return; 00488 } 00489 00490 home = g_get_home_dir(); 00491 if (!home) 00492 return; 00493 00494 /* Copy the old values from the gnucash 1.x/gnome1 settings file to 00495 * the gnucash 2.x/gconf settings area. */ 00496 mdi_file = g_build_filename(home, ".gnome", "GnuCash", (gchar *)NULL); 00497 keyfile = gnc_key_file_load_from_file (mdi_file, FALSE, FALSE, NULL); 00498 if (keyfile) 00499 { 00500 keys = g_key_file_get_keys(keyfile, GNOME1_HISTORY, NULL, NULL); 00501 if (keys) 00502 { 00503 for (key = keys; *key; key++) 00504 { 00505 if (!strcmp(*key, GNOME1_MAXFILES)) 00506 { 00507 max = g_key_file_get_integer(keyfile, GNOME1_HISTORY, 00508 GNOME1_MAXFILES, NULL); 00509 printf("Found old maxfiles: %d\n", max); 00510 if ((max > 0) && (max < MAX_HISTORY_FILES)) 00511 printf("Setting maxfiles: %d\n\n", max); 00512 gnc_gconf_set_int(HISTORY_STRING_SECTION, HISTORY_STRING_MAXFILES, 00513 max, NULL); 00514 continue; 00515 } 00516 00517 if (sscanf(*key, "File%d", &file_id) == 1) 00518 { 00519 value = g_key_file_get_string(keyfile, GNOME1_HISTORY, *key, NULL); 00520 if (!value) 00521 continue; 00522 printf("Found old file %d: %s\n", file_id, value); 00523 new_key = g_strdup_printf(HISTORY_STRING_FILE_N, file_id); 00524 gnc_gconf_set_string (HISTORY_STRING_SECTION, new_key, value, NULL); 00525 printf("Setting %s: %s\n\n", new_key, value); 00526 g_free(new_key); 00527 g_free(value); 00528 } 00529 } 00530 g_strfreev(keys); 00531 } 00532 g_key_file_free(keyfile); 00533 } 00534 00535 g_free(mdi_file); 00536 } 00537 00538 /************************************************************ 00539 * Object Implementation * 00540 ************************************************************/ 00541 00542 /* Get the type of a file history plugin. */ 00543 GType 00544 gnc_plugin_file_history_get_type (void) 00545 { 00546 static GType gnc_plugin_file_history_type = 0; 00547 00548 if (gnc_plugin_file_history_type == 0) 00549 { 00550 static const GTypeInfo our_info = 00551 { 00552 sizeof (GncPluginFileHistoryClass), 00553 NULL, /* base_init */ 00554 NULL, /* base_finalize */ 00555 (GClassInitFunc) gnc_plugin_file_history_class_init, 00556 NULL, /* class_finalize */ 00557 NULL, /* class_data */ 00558 sizeof (GncPluginFileHistory), 00559 0, 00560 (GInstanceInitFunc) gnc_plugin_file_history_init 00561 }; 00562 00563 gnc_plugin_file_history_type = 00564 g_type_register_static (GNC_TYPE_PLUGIN, 00565 "GncPluginFileHistory", 00566 &our_info, 0); 00567 } 00568 00569 return gnc_plugin_file_history_type; 00570 } 00571 00572 00574 static void 00575 gnc_plugin_file_history_class_init (GncPluginFileHistoryClass *klass) 00576 { 00577 GObjectClass *object_class = G_OBJECT_CLASS (klass); 00578 GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass); 00579 00580 parent_class = g_type_class_peek_parent (klass); 00581 00582 object_class->finalize = gnc_plugin_file_history_finalize; 00583 00584 /* plugin info */ 00585 plugin_class->plugin_name = GNC_PLUGIN_FILE_HISTORY_NAME; 00586 00587 /* function overrides */ 00588 plugin_class->add_to_window = gnc_plugin_file_history_add_to_window; 00589 plugin_class->remove_from_window = 00590 gnc_plugin_file_history_remove_from_window; 00591 00592 /* widget addition/removal */ 00593 plugin_class->actions_name = PLUGIN_ACTIONS_NAME; 00594 plugin_class->actions = gnc_plugin_actions; 00595 plugin_class->n_actions = gnc_plugin_n_actions; 00596 plugin_class->ui_filename = PLUGIN_UI_FILENAME; 00597 00598 plugin_class->gconf_section = HISTORY_STRING_SECTION; 00599 plugin_class->gconf_notifications = gnc_plugin_history_list_changed; 00600 00601 g_type_class_add_private(klass, sizeof(GncPluginFileHistoryPrivate)); 00602 00603 gnc_plugin_history_list_from_gnucash1(); 00604 } 00605 00606 00608 static void 00609 gnc_plugin_file_history_init (GncPluginFileHistory *plugin) 00610 { 00611 ENTER("plugin %p", plugin); 00612 LEAVE(""); 00613 } 00614 00615 00617 static void 00618 gnc_plugin_file_history_finalize (GObject *object) 00619 { 00620 GncPluginFileHistory *plugin; 00621 GncPluginFileHistoryPrivate *priv; 00622 00623 g_return_if_fail (GNC_IS_PLUGIN_FILE_HISTORY (object)); 00624 00625 ENTER("plugin %p", object); 00626 plugin = GNC_PLUGIN_FILE_HISTORY (object); 00627 priv = GNC_PLUGIN_FILE_HISTORY_GET_PRIVATE (plugin); 00628 00629 G_OBJECT_CLASS (parent_class)->finalize (object); 00630 LEAVE(""); 00631 } 00632 00633 00634 /* Create a new file history plugin. This plugin attaches the file 00635 * history menu to any window that is opened. 00636 */ 00637 GncPlugin * 00638 gnc_plugin_file_history_new (void) 00639 { 00640 GncPlugin *plugin_page = NULL; 00641 00642 ENTER(""); 00643 plugin_page = GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_FILE_HISTORY, NULL)); 00644 LEAVE("plugin %p", plugin_page); 00645 return plugin_page; 00646 } 00647 00648 /************************************************************ 00649 * Plugin Function Implementation * 00650 ************************************************************/ 00651 00668 static void 00669 gnc_plugin_file_history_add_to_window (GncPlugin *plugin, 00670 GncMainWindow *window, 00671 GQuark type) 00672 { 00673 gnc_history_update_menus(window); 00674 } 00675 00676 00689 static void 00690 gnc_plugin_file_history_remove_from_window (GncPlugin *plugin, 00691 GncMainWindow *window, 00692 GQuark type) 00693 { 00694 } 00695 00696 /************************************************************ 00697 * Command Callbacks * 00698 ************************************************************/ 00699 00712 static void 00713 gnc_plugin_file_history_cmd_open_file (GtkAction *action, 00714 GncMainWindowActionData *data) 00715 { 00716 gchar *filename; 00717 00718 g_return_if_fail(GTK_IS_ACTION(action)); 00719 g_return_if_fail(data != NULL); 00720 00721 /* DRH - Do we need to close all open windows but the first? 00722 * Which progress bar should we be using? One in a window, or 00723 * in a new "file loading" dialog??? 00724 */ 00725 filename = g_object_get_data(G_OBJECT(action), FILENAME_STRING); 00726 gnc_window_set_progressbar_window (GNC_WINDOW(data->window)); 00727 /* also opens new account page */ 00728 gnc_file_open_file (filename, /*open_readonly*/ FALSE); 00729 gnc_window_set_progressbar_window (NULL); 00730 } 00731
1.7.4