|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * dialog-preferences.c -- preferences dialog * 00003 * * 00004 * Copyright (C) 2005 David Hampton * 00005 * Copyright (C) 2011 Robert Fewell * 00006 * * 00007 * This program is free software; you can redistribute it and/or * 00008 * modify it under the terms of the GNU General Public License as * 00009 * published by the Free Software Foundation; either version 2 of * 00010 * the License, or (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License* 00018 * along with this program; if not, contact: * 00019 * * 00020 * Free Software Foundation Voice: +1-617-542-5942 * 00021 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00022 * Boston, MA 02110-1301, USA gnu@gnu.org * 00023 \********************************************************************/ 00024 00060 #include "config.h" 00061 00062 #include <gtk/gtk.h> 00063 #include <glib/gi18n.h> 00064 00065 #include "dialog-utils.h" 00066 #include "gnc-currency-edit.h" 00067 #include "gnc-date-edit.h" 00068 #include "gnc-gconf-utils.h" 00069 #include "gnc-gobject-utils.h" 00070 #include "gnc-period-select.h" 00071 #include "gnc-engine.h" 00072 #include "Account.h" 00073 #include "gnc-ui.h" 00074 #include "gnc-ui-util.h" 00075 #include "gnc-component-manager.h" 00076 #include "dialog-preferences.h" 00077 00078 #define DIALOG_PREFERENCES_CM_CLASS "dialog-newpreferences" 00079 #define GCONF_SECTION "dialogs/preferences" 00080 #define PREFIX_LEN sizeof("gconf/") - 1 00081 #define WIDGET_HASH "widget_hash" 00082 #define NOTEBOOK "notebook" 00083 00085 static QofLogModule log_module = GNC_MOD_PREFS; 00086 00087 void gnc_preferences_response_cb(GtkDialog *dialog, gint response, GtkDialog *unused); 00088 00089 00092 typedef struct addition_t 00093 { 00096 gchar *filename; 00100 gchar *widgetname; 00103 gchar *tabname; 00106 gboolean full_page; 00107 } addition; 00108 00112 GSList *add_ins = NULL; 00113 00114 00125 static void 00126 gnc_account_separator_prefs_cb (GConfEntry *unused, GtkWidget *dialog) 00127 { 00128 GtkWidget *label, *image; 00129 gchar *sample; 00130 GList *invalid_account_names; 00131 QofBook *book; 00132 00133 label = g_object_get_data(G_OBJECT(dialog), "sample_account"); 00134 DEBUG("Sample Account pointer is %p", label ); 00135 /* Translators: Both %s will be the account separator character; the 00136 resulting string is a demonstration how the account separator 00137 character will look like. You can replace these three account 00138 names with other account names that are more suitable for your 00139 language - just keep in mind to have exactly two %s in your 00140 translation. */ 00141 sample = g_strdup_printf(_("Income%sSalary%sTaxable"), 00142 gnc_get_account_separator_string(), 00143 gnc_get_account_separator_string()); 00144 PINFO(" Label set to '%s'", sample); 00145 gtk_label_set_text(GTK_LABEL(label), sample); 00146 g_free(sample); 00147 00148 /* Check if the new separator clashes with existing account names */ 00149 image = g_object_get_data(G_OBJECT(dialog), "separator_error"); 00150 DEBUG("Separator Error Image pointer is %p", image ); 00151 book = gnc_get_current_book(); 00152 invalid_account_names = gnc_account_list_name_violations ( book, 00153 gnc_get_account_separator_string() ); 00154 if ( invalid_account_names ) 00155 { 00156 gchar *message = gnc_account_name_violations_errmsg ( gnc_get_account_separator_string(), 00157 invalid_account_names ); 00158 gnc_warning_dialog(dialog, "%s", message); 00159 gtk_widget_set_tooltip_text(GTK_WIDGET(image), message); 00160 gtk_widget_show (GTK_WIDGET(image)); 00161 g_free ( message ); 00162 } 00163 else 00164 gtk_widget_hide (GTK_WIDGET(image)); 00165 00166 g_list_free ( invalid_account_names ); 00167 } 00168 00169 00181 static gint 00182 gnc_prefs_compare_addins (addition *a, 00183 addition *b) 00184 { 00185 return g_utf8_collate(a->tabname, b->tabname); 00186 } 00187 00188 00208 static void 00209 gnc_preferences_add_page_internal (const gchar *filename, 00210 const gchar *widgetname, 00211 const gchar *tabname, 00212 gboolean full_page) 00213 { 00214 addition *add_in, *preexisting; 00215 gboolean error = FALSE; 00216 GSList *ptr; 00217 00218 ENTER("file %s, widget %s, tab %s full page %d", 00219 filename, widgetname, tabname, full_page); 00220 00221 add_in = g_malloc(sizeof(addition)); 00222 if (add_in == NULL) 00223 { 00224 g_critical("Unable to allocate memory.\n"); 00225 LEAVE("no memory"); 00226 return; 00227 } 00228 00229 add_in->filename = g_strdup(filename); 00230 add_in->widgetname = g_strdup(widgetname); 00231 add_in->tabname = g_strdup(tabname); 00232 add_in->full_page = full_page; 00233 if (!add_in->filename || !add_in->widgetname || !add_in->tabname) 00234 { 00235 g_critical("Unable to allocate memory.\n"); 00236 g_free(add_in->filename); 00237 g_free(add_in->widgetname); 00238 g_free(add_in->tabname); 00239 g_free(add_in); 00240 LEAVE("no memory"); 00241 return; 00242 } 00243 00244 ptr = g_slist_find_custom(add_ins, add_in, (GCompareFunc)gnc_prefs_compare_addins); 00245 if (ptr) 00246 { 00247 /* problem? */ 00248 preexisting = ptr->data; 00249 00250 if (preexisting->full_page) 00251 { 00252 g_warning("New tab %s(%s/%s/%s) conflicts with existing tab %s(%s/%s/full)", 00253 add_in->tabname, add_in->filename, add_in->widgetname, 00254 add_in->full_page ? "full" : "partial", 00255 preexisting->tabname, preexisting->filename, preexisting->widgetname); 00256 error = TRUE; 00257 } 00258 else if (add_in->full_page) 00259 { 00260 g_warning("New tab %s(%s/%s/%s) conflicts with existing tab %s(%s/%s/partial)", 00261 add_in->tabname, add_in->filename, add_in->widgetname, 00262 add_in->full_page ? "full" : "partial", 00263 preexisting->tabname, preexisting->filename, preexisting->widgetname); 00264 error = TRUE; 00265 } 00266 } 00267 00268 if (error) 00269 { 00270 g_free(add_in->filename); 00271 g_free(add_in->widgetname); 00272 g_free(add_in->tabname); 00273 g_free(add_in); 00274 LEAVE("err"); 00275 return; 00276 } 00277 else 00278 { 00279 add_ins = g_slist_append(add_ins, add_in); 00280 } 00281 LEAVE(""); 00282 } 00283 00284 00285 /* This function adds a full page of preferences to the preferences 00286 * dialog. When the dialog is created, the specified content will be 00287 * pulled from the specified glade file and added to the preferences 00288 * dialog with the specified tab name. The tab name may not be 00289 * duplicated. For example, the Business code might have a full page 00290 * of its own preferences. */ 00291 void 00292 gnc_preferences_add_page (const gchar *filename, 00293 const gchar *widgetname, 00294 const gchar *tabname) 00295 { 00296 gnc_preferences_add_page_internal(filename, widgetname, tabname, TRUE); 00297 } 00298 00299 00300 /* This function adds a partial page of preferences to the 00301 * preferences dialog. When the dialog is created, the specified 00302 * content will be pulled from the glade file and added to the 00303 * preferences dialog with the specified tab name. The tab name 00304 * may be duplicated. For example, the HBCI preferences may share a 00305 * "Data Import" page with QIF and other methods. */ 00306 void 00307 gnc_preferences_add_to_page (const gchar *filename, 00308 const gchar *widgetname, 00309 const gchar *tabname) 00310 { 00311 gnc_preferences_add_page_internal(filename, widgetname, tabname, FALSE); 00312 } 00313 00314 00315 /*******************************************************************/ 00316 00330 static void 00331 gnc_prefs_build_widget_table (GtkBuilder *builder, 00332 GtkWidget *dialog) 00333 { 00334 GHashTable *table; 00335 GSList *interesting, *runner; 00336 const gchar *name; 00337 const gchar *wname; 00338 GtkWidget *widget; 00339 00340 table = g_object_get_data(G_OBJECT(dialog), WIDGET_HASH); 00341 00342 interesting = gtk_builder_get_objects(builder); 00343 00344 for (runner = interesting; runner; runner = g_slist_next(runner)) 00345 { 00346 widget = runner->data; 00347 if (GTK_IS_WIDGET(widget)) 00348 { 00349 wname = gtk_widget_get_name(widget); 00350 name = gtk_buildable_get_name(GTK_BUILDABLE(widget)); 00351 DEBUG("Widget type is %s and buildable get name is %s", wname, name); 00352 if (g_str_has_prefix (name, "gconf")) 00353 g_hash_table_insert(table, (gchar *)name, widget); 00354 } 00355 } 00356 g_slist_free(interesting); 00357 } 00358 00359 00365 struct copy_data 00366 { 00368 GtkTable *table_from; 00370 GtkTable *table_to; 00373 gint row_offset; 00374 }; 00375 00376 00377 static GtkWidget * 00378 gnc_prefs_find_page (GtkNotebook *notebook, const gchar *name) 00379 { 00380 int n_pages, i; 00381 GtkWidget *child; 00382 const gchar *child_name; 00383 00384 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL); 00385 g_return_val_if_fail (name, NULL); 00386 00387 ENTER(""); 00388 00389 n_pages = gtk_notebook_get_n_pages (notebook); 00390 00391 for (i = 0; i < n_pages; i++) 00392 { 00393 child = gtk_notebook_get_nth_page (notebook, i); 00394 g_return_val_if_fail (child, NULL); 00395 00396 child_name = gtk_notebook_get_tab_label_text (notebook, child); 00397 g_return_val_if_fail (child_name, NULL); 00398 00399 if (g_utf8_collate (name, child_name) == 0) 00400 { 00401 LEAVE("found at index: %d", i); 00402 return child; 00403 } 00404 } 00405 00406 LEAVE("not found"); 00407 return NULL; 00408 } 00409 00410 00423 static void 00424 gnc_prefs_move_table_entry (GtkWidget *child, 00425 gpointer data) 00426 { 00427 struct copy_data *copydata = data; 00428 GtkAttachOptions x_opts, y_opts; 00429 gint bottom, top, left, right, x_pad, y_pad; 00430 00431 ENTER("child %p, copy data %p", child, data); 00432 gtk_container_child_get(GTK_CONTAINER(copydata->table_from), child, 00433 "bottom-attach", &bottom, 00434 "left-attach", &left, 00435 "right-attach", &right, 00436 "top-attach", &top, 00437 "x-options", &x_opts, 00438 "x-padding", &x_pad, 00439 "y-options", &y_opts, 00440 "y-padding", &y_pad, 00441 NULL); 00442 00443 gtk_widget_ref(child); 00444 gtk_container_remove(GTK_CONTAINER(copydata->table_from), child); 00445 gtk_table_attach(copydata->table_to, child, left, right, 00446 top + copydata->row_offset, bottom + copydata->row_offset, 00447 x_opts, y_opts, x_pad, y_pad); 00448 gtk_widget_unref(child); 00449 LEAVE(" "); 00450 } 00451 00452 00464 static void 00465 gnc_preferences_build_page (gpointer data, 00466 gpointer user_data) 00467 { 00468 GtkBuilder *builder; 00469 GtkWidget *dialog, *existing_content, *new_content, *label; 00470 GtkNotebook *notebook; 00471 addition *add_in; 00472 struct copy_data copydata; 00473 gint rows, cols; 00474 gchar **widgetname; 00475 gint i; 00476 00477 ENTER("add_in %p, dialog %p", data, user_data); 00478 add_in = (addition *)data; 00479 dialog = user_data; 00480 00481 DEBUG("Opening %s to get %s", add_in->filename, add_in->widgetname); 00482 builder = gtk_builder_new(); 00483 00484 /* Adjustments etc... must come before dialog information */ 00485 widgetname = g_strsplit(add_in->widgetname, ",", -1); 00486 00487 for (i = 0; widgetname[i]; i++) 00488 { 00489 DEBUG("Opening %s to get content %s", add_in->filename, widgetname[i]); 00490 gnc_builder_add_from_file (builder, add_in->filename, widgetname[i]); 00491 } 00492 00493 DEBUG("Widget Content is %s", widgetname[i - 1]); 00494 new_content = GTK_WIDGET(gtk_builder_get_object (builder, widgetname[i - 1])); 00495 00496 g_strfreev(widgetname); 00497 DEBUG("done"); 00498 00499 /* Add to the list of interesting widgets */ 00500 gnc_prefs_build_widget_table(builder, dialog); 00501 00502 /* Connect the signals in this glade file. The dialog is passed in 00503 * so the the callback can find "interesting" widgets from other 00504 * glade files if necessary (via the WIDGET_HASH hash table). */ 00505 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, dialog); 00506 00507 /* Prepare for recursion */ 00508 notebook = g_object_get_data(G_OBJECT(dialog), NOTEBOOK); 00509 00510 if (add_in->full_page) 00511 { 00512 label = gtk_label_new(add_in->tabname); 00513 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); 00514 gtk_notebook_append_page(notebook, new_content, label); 00515 g_object_unref(G_OBJECT(builder)); 00516 LEAVE("appended page"); 00517 return; 00518 } 00519 00520 /* Copied tables must match the size of the main table */ 00521 if (!GTK_IS_TABLE(new_content)) 00522 { 00523 g_critical("The object name %s in file %s is not a GtkTable. It cannot " 00524 "be added to the preferences dialog.", 00525 add_in->widgetname, add_in->filename); 00526 g_object_unref(G_OBJECT(builder)); 00527 LEAVE(""); 00528 return; 00529 } 00530 g_object_get(G_OBJECT(new_content), "n-columns", &cols, NULL); 00531 if (cols != 4) 00532 { 00533 g_critical("The table %s in file %s does not have four columns. It cannot " 00534 "be added to the preferences dialog.", 00535 add_in->widgetname, add_in->filename); 00536 g_object_unref(G_OBJECT(builder)); 00537 LEAVE(""); 00538 return; 00539 } 00540 00541 /* Does the page exist or must we create it */ 00542 existing_content = gnc_prefs_find_page(notebook, add_in->tabname); 00543 00544 if (!existing_content) 00545 { 00546 /* No existing content with this name. Create a blank page */ 00547 rows = 0; 00548 existing_content = gtk_table_new(0, 4, FALSE); 00549 gtk_container_set_border_width(GTK_CONTAINER(existing_content), 6); 00550 label = gtk_label_new(add_in->tabname); 00551 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); 00552 gtk_notebook_append_page(notebook, existing_content, label); 00553 gtk_widget_show_all(existing_content); 00554 DEBUG("created new page %s, appended it", add_in->tabname); 00555 } 00556 else 00557 { 00558 g_object_get(G_OBJECT(existing_content), "n-rows", &rows, NULL); 00559 DEBUG("found existing page %s", add_in->tabname); 00560 } 00561 00562 /* Maybe add a spacer row */ 00563 DEBUG("rows is %d", rows); 00564 if (rows > 0) 00565 { 00566 label = gtk_label_new(""); 00567 gtk_widget_show(label); 00568 gtk_table_attach(GTK_TABLE(existing_content), label, 0, 1, rows, rows + 1, 00569 GTK_FILL, GTK_FILL, 0, 0); 00570 rows++; 00571 } 00572 00573 /* Now copy all the entries in the table */ 00574 copydata.table_from = GTK_TABLE(new_content); 00575 copydata.table_to = GTK_TABLE(existing_content); 00576 copydata.row_offset = rows; 00577 gtk_container_foreach(GTK_CONTAINER(new_content), gnc_prefs_move_table_entry, 00578 ©data); 00579 00580 g_object_ref_sink(new_content); 00581 g_object_unref(G_OBJECT(builder)); 00582 00583 LEAVE("added content to page"); 00584 } 00585 00586 00587 static gint 00588 tab_cmp (GtkWidget *page_a, GtkWidget *page_b, GtkNotebook *notebook) 00589 { 00590 return g_utf8_collate (gtk_notebook_get_tab_label_text (notebook, page_a), 00591 gtk_notebook_get_tab_label_text (notebook, page_b)); 00592 } 00593 00594 00595 static void 00596 gnc_prefs_sort_pages (GtkNotebook *notebook) 00597 { 00598 gint n_pages, i; 00599 GList *tabs = NULL, *iter = NULL; 00600 00601 g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); 00602 00603 /* gather tabs */ 00604 n_pages = gtk_notebook_get_n_pages (notebook); 00605 for (i = n_pages - 1; i >= 0; i--) 00606 tabs = g_list_prepend (tabs, gtk_notebook_get_nth_page (notebook, i)); 00607 00608 /* sort in local copy */ 00609 tabs = g_list_sort_with_data (tabs, (GCompareDataFunc) tab_cmp, notebook); 00610 00611 /* reorder tabs */ 00612 for (i = 0, iter = tabs; iter; i++, iter = iter->next) 00613 gtk_notebook_reorder_child (notebook, GTK_WIDGET (iter->data), i); 00614 00615 g_list_free (tabs); 00616 } 00617 00618 00619 /*******************************/ 00620 /* Dynamically added Callbacks */ 00621 /*******************************/ 00622 00632 static void 00633 gnc_prefs_font_button_user_cb (GtkFontButton *fb, 00634 gpointer user_data) 00635 { 00636 const gchar *key, *font; 00637 00638 g_return_if_fail(GTK_IS_FONT_BUTTON(fb)); 00639 key = gtk_buildable_get_name(GTK_BUILDABLE(fb)) + PREFIX_LEN; 00640 font = gtk_font_button_get_font_name(fb); 00641 00642 DEBUG("font_button %s set", key); 00643 gnc_gconf_set_string(key, NULL, font, NULL); 00644 } 00645 00646 00656 static void 00657 gnc_prefs_font_button_gconf_cb (GtkFontButton *fb, 00658 GConfEntry *entry) 00659 { 00660 const gchar *font; 00661 00662 g_return_if_fail(GTK_IS_FONT_BUTTON(fb)); 00663 ENTER("fb %p, entry %p", fb, entry); 00664 00665 font = gconf_value_get_string(entry->value); 00666 00667 g_signal_handlers_block_by_func(G_OBJECT(fb), 00668 G_CALLBACK(gnc_prefs_font_button_user_cb), NULL); 00669 gtk_font_button_set_font_name(fb, font); 00670 g_signal_handlers_unblock_by_func(G_OBJECT(fb), 00671 G_CALLBACK(gnc_prefs_font_button_user_cb), NULL); 00672 LEAVE(" "); 00673 } 00674 00675 00683 static void 00684 gnc_prefs_connect_font_button (GtkFontButton *fb) 00685 { 00686 const gchar *name; 00687 gchar *font; 00688 00689 g_return_if_fail(GTK_IS_FONT_BUTTON(fb)); 00690 00691 /* Lookup font name based upon gconf setting */ 00692 name = gtk_buildable_get_name(GTK_BUILDABLE(fb)) + PREFIX_LEN; 00693 font = gnc_gconf_get_string(name, NULL, NULL); 00694 00695 gtk_font_button_set_font_name(fb, font); 00696 DEBUG(" font_button %s set", name); 00697 g_free(font); 00698 00699 g_signal_connect(G_OBJECT(fb), "font_set", 00700 G_CALLBACK(gnc_prefs_font_button_user_cb), NULL); 00701 00702 gtk_widget_show_all(GTK_WIDGET(fb)); 00703 } 00704 00705 /****************************************************************************/ 00706 00718 static void 00719 gnc_prefs_radio_button_user_cb (GtkRadioButton *button, 00720 gpointer user_data) 00721 { 00722 gchar *key, *button_name; 00723 gboolean active; 00724 00725 g_return_if_fail(GTK_IS_RADIO_BUTTON(button)); 00726 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); 00727 if (!active) 00728 return; 00729 00730 /* Copy the widget name and split into gconf key and button value parts */ 00731 key = g_strdup(gtk_buildable_get_name(GTK_BUILDABLE(button)) + PREFIX_LEN); 00732 button_name = strrchr(key, '/'); 00733 *button_name++ = '\0'; 00734 00735 DEBUG("Radio button group %s now set to %s", key, button_name); 00736 gnc_gconf_set_string(key, NULL, button_name, NULL); 00737 g_free(key); 00738 } 00739 00740 00749 static void 00750 gnc_prefs_radio_button_gconf_cb (GtkRadioButton *button) 00751 { 00752 g_return_if_fail(GTK_IS_RADIO_BUTTON(button)); 00753 ENTER("button %p", button); 00754 g_signal_handlers_block_by_func(G_OBJECT(button), 00755 G_CALLBACK(gnc_prefs_radio_button_user_cb), NULL); 00756 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE); 00757 g_signal_handlers_unblock_by_func(G_OBJECT(button), 00758 G_CALLBACK(gnc_prefs_radio_button_user_cb), NULL); 00759 LEAVE(" "); 00760 } 00761 00762 00772 static void 00773 gnc_prefs_connect_radio_button (GtkRadioButton *button) 00774 { 00775 gchar *key, *button_name, *value; 00776 gboolean active; 00777 GSList *group; 00778 00779 g_return_if_fail(GTK_IS_RADIO_BUTTON(button)); 00780 00781 /* Copy the widget name and split into gconf key and button name parts */ 00782 key = g_strdup(gtk_buildable_get_name(GTK_BUILDABLE(button)) + PREFIX_LEN); 00783 button_name = strrchr(key, '/'); 00784 *button_name++ = '\0'; 00785 00786 /* Get the current value. */ 00787 value = gnc_gconf_get_string(key, NULL, NULL); 00788 if (value) 00789 { 00790 active = (g_utf8_collate(value, button_name) == 0); 00791 } 00792 else 00793 { 00794 /* Sigh. There's no gconf default for this key. Use the first 00795 * button in the dialog, which is the last button in the list. */ 00796 group = gtk_radio_button_get_group(button); 00797 active = (button != g_slist_nth_data(group, g_slist_length(group))); 00798 } 00799 DEBUG(" Radio set %s, button %s initially set to %d", key, button_name, active); 00800 00801 /* Wire up the button */ 00802 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active); 00803 g_signal_connect(G_OBJECT(button), "toggled", 00804 G_CALLBACK(gnc_prefs_radio_button_user_cb), NULL); 00805 g_free(value); 00806 g_free(key); 00807 } 00808 00809 /****************************************************************************/ 00810 00820 static void 00821 gnc_prefs_check_button_user_cb (GtkCheckButton *button, 00822 gpointer user_data) 00823 { 00824 const gchar *name; 00825 gboolean active; 00826 00827 g_return_if_fail(GTK_IS_CHECK_BUTTON(button)); 00828 name = gtk_buildable_get_name(GTK_BUILDABLE(button)) + PREFIX_LEN; 00829 active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); 00830 DEBUG("Checkbox %s now %sactive", name, active ? "" : "in"); 00831 gnc_gconf_set_bool(name, NULL, active, NULL); 00832 } 00833 00834 00844 static void 00845 gnc_prefs_check_button_gconf_cb (GtkCheckButton *button, 00846 gboolean active) 00847 { 00848 g_return_if_fail(GTK_IS_CHECK_BUTTON(button)); 00849 ENTER("button %p, active %d", button, active); 00850 g_signal_handlers_block_by_func(G_OBJECT(button), 00851 G_CALLBACK(gnc_prefs_check_button_user_cb), NULL); 00852 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active); 00853 g_signal_handlers_unblock_by_func(G_OBJECT(button), 00854 G_CALLBACK(gnc_prefs_check_button_user_cb), NULL); 00855 LEAVE(" "); 00856 } 00857 00858 00867 static void 00868 gnc_prefs_connect_check_button (GtkCheckButton *button) 00869 { 00870 const gchar *name; 00871 gboolean active; 00872 00873 name = gtk_buildable_get_name(GTK_BUILDABLE(button)) + PREFIX_LEN; 00874 active = gnc_gconf_get_bool(name, NULL, NULL); 00875 DEBUG(" Checkbox %s initially %sactive", name, active ? "" : "in"); 00876 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active); 00877 g_signal_connect(G_OBJECT(button), "toggled", 00878 G_CALLBACK(gnc_prefs_check_button_user_cb), NULL); 00879 } 00880 00881 /****************************************************************************/ 00882 00892 static void 00893 gnc_prefs_spin_button_user_cb (GtkSpinButton *spin, 00894 gpointer user_data) 00895 { 00896 const gchar *name; 00897 gdouble value; 00898 00899 g_return_if_fail(GTK_IS_SPIN_BUTTON(spin)); 00900 name = gtk_buildable_get_name(GTK_BUILDABLE(spin)) + PREFIX_LEN; 00901 value = gtk_spin_button_get_value(spin); 00902 DEBUG("Spin button %s has value %f", name, value); 00903 gnc_gconf_set_float(name, NULL, value, NULL); 00904 } 00905 00906 00916 static void 00917 gnc_prefs_spin_button_gconf_cb (GtkSpinButton *spin, 00918 gdouble value) 00919 { 00920 g_return_if_fail(GTK_IS_SPIN_BUTTON(spin)); 00921 ENTER("button %p, value %f", spin, value); 00922 g_signal_handlers_block_by_func(G_OBJECT(spin), 00923 G_CALLBACK(gnc_prefs_spin_button_user_cb), NULL); 00924 gtk_spin_button_set_value(spin, value); 00925 g_signal_handlers_unblock_by_func(G_OBJECT(spin), 00926 G_CALLBACK(gnc_prefs_spin_button_user_cb), NULL); 00927 LEAVE(" "); 00928 } 00929 00930 00939 static void 00940 gnc_prefs_connect_spin_button (GtkSpinButton *spin) 00941 { 00942 const gchar *name; 00943 gdouble value; 00944 00945 g_return_if_fail(GTK_IS_SPIN_BUTTON(spin)); 00946 name = gtk_buildable_get_name(GTK_BUILDABLE(spin)) + PREFIX_LEN; 00947 value = gnc_gconf_get_float(name, NULL, NULL); 00948 gtk_spin_button_set_value(spin, value); 00949 DEBUG(" Spin button %s has initial value %f", name, value); 00950 g_signal_connect(G_OBJECT(spin), "value-changed", 00951 G_CALLBACK(gnc_prefs_spin_button_user_cb), NULL); 00952 } 00953 00954 /****************************************************************************/ 00955 00965 static void 00966 gnc_prefs_combo_box_user_cb (GtkComboBox *box, 00967 gpointer user_data) 00968 { 00969 const gchar *name; 00970 gint active; 00971 00972 g_return_if_fail(GTK_IS_COMBO_BOX(box)); 00973 name = gtk_buildable_get_name(GTK_BUILDABLE(box)) + PREFIX_LEN; 00974 active = gtk_combo_box_get_active(box); 00975 DEBUG("Combo box %s set to item %d", name, active); 00976 gnc_gconf_set_int(name, NULL, active, NULL); 00977 } 00978 00979 00989 static void 00990 gnc_prefs_combo_box_gconf_cb (GtkComboBox *box, 00991 gint value) 00992 { 00993 g_return_if_fail(GTK_IS_COMBO_BOX(box)); 00994 ENTER("box %p, value %d", box, value); 00995 g_signal_handlers_block_by_func(G_OBJECT(box), 00996 G_CALLBACK(gnc_prefs_combo_box_user_cb), NULL); 00997 gtk_combo_box_set_active(box, value); 00998 g_signal_handlers_unblock_by_func(G_OBJECT(box), 00999 G_CALLBACK(gnc_prefs_combo_box_user_cb), NULL); 01000 LEAVE(" "); 01001 } 01002 01003 01011 static void 01012 gnc_prefs_connect_combo_box (GtkComboBox *box) 01013 { 01014 const gchar *name; 01015 gint active; 01016 01017 g_return_if_fail(GTK_IS_COMBO_BOX(box)); 01018 name = gtk_buildable_get_name(GTK_BUILDABLE(box)) + PREFIX_LEN; 01019 active = gnc_gconf_get_int(name, NULL, NULL); 01020 gtk_combo_box_set_active(GTK_COMBO_BOX(box), active); 01021 DEBUG(" Combo box %s set to item %d", name, active); 01022 g_signal_connect(G_OBJECT(box), "changed", 01023 G_CALLBACK(gnc_prefs_combo_box_user_cb), NULL); 01024 } 01025 01026 /****************************************************************************/ 01027 01037 static void 01038 gnc_prefs_currency_edit_user_cb (GNCCurrencyEdit *gce, 01039 gpointer user_data) 01040 { 01041 const gchar *name, *mnemonic; 01042 gnc_commodity *currency; 01043 01044 g_return_if_fail(GNC_IS_CURRENCY_EDIT(gce)); 01045 name = g_object_get_data(G_OBJECT(gce), "name"); 01046 currency = gnc_currency_edit_get_currency(gce); 01047 mnemonic = gnc_commodity_get_mnemonic(currency); 01048 01049 DEBUG("Currency edit %s set to %s", name, mnemonic); 01050 gnc_gconf_set_string(name, NULL, mnemonic, NULL); 01051 } 01052 01053 01063 static void 01064 gnc_prefs_currency_edit_gconf_cb (GNCCurrencyEdit *gce, 01065 GConfEntry *entry) 01066 { 01067 const gchar *mnemonic; 01068 gnc_commodity *currency; 01069 01070 g_return_if_fail(GNC_IS_CURRENCY_EDIT(gce)); 01071 ENTER("gce %p, entry %p", gce, entry); 01072 01073 mnemonic = gconf_value_get_string(entry->value); 01074 DEBUG("gce %p, mnemonic %s", gce, mnemonic); 01075 currency = gnc_commodity_table_lookup(gnc_get_current_commodities(), 01076 GNC_COMMODITY_NS_CURRENCY, mnemonic); 01077 01078 /* If there isn't any such commodity, get the default */ 01079 if (!currency) 01080 { 01081 currency = gnc_locale_default_currency(); 01082 DEBUG("gce %p, default currency mnemonic %s", 01083 gce, gnc_commodity_get_mnemonic(currency)); 01084 } 01085 01086 g_signal_handlers_block_by_func(G_OBJECT(gce), 01087 G_CALLBACK(gnc_prefs_currency_edit_user_cb), NULL); 01088 gnc_currency_edit_set_currency(GNC_CURRENCY_EDIT(gce), currency); 01089 g_signal_handlers_unblock_by_func(G_OBJECT(gce), 01090 G_CALLBACK(gnc_prefs_currency_edit_user_cb), NULL); 01091 LEAVE(" "); 01092 } 01093 01094 01102 static void 01103 gnc_prefs_connect_currency_edit (GNCCurrencyEdit *gce, const gchar *boxname ) 01104 { 01105 gnc_commodity *currency; 01106 const gchar *name; 01107 gchar *mnemonic; 01108 01109 g_return_if_fail(GNC_IS_CURRENCY_EDIT(gce)); 01110 01111 /* Lookup commodity based upon gconf setting */ 01112 name = boxname + PREFIX_LEN; 01113 01114 g_object_set_data(G_OBJECT(gce), "name", g_strdup(name) ); 01115 01116 mnemonic = gnc_gconf_get_string(name, NULL, NULL); 01117 currency = gnc_commodity_table_lookup(gnc_get_current_commodities(), 01118 GNC_COMMODITY_NS_CURRENCY, mnemonic); 01119 if (mnemonic) 01120 g_free(mnemonic); 01121 01122 /* If there isn't any such commodity, get the default */ 01123 if (!currency) 01124 currency = gnc_locale_default_currency(); 01125 01126 gnc_currency_edit_set_currency(GNC_CURRENCY_EDIT(gce), currency); 01127 DEBUG(" Currency edit %s set to %s", name, 01128 gnc_commodity_get_mnemonic(currency)); 01129 01130 g_signal_connect(G_OBJECT(gce), "changed", 01131 G_CALLBACK(gnc_prefs_currency_edit_user_cb), NULL); 01132 01133 gtk_widget_show_all(GTK_WIDGET(gce)); 01134 } 01135 01136 /****************************************************************************/ 01137 01146 static void 01147 gnc_prefs_entry_user_cb (GtkEntry *entry, 01148 gpointer user_data) 01149 { 01150 const gchar *name, *text; 01151 01152 g_return_if_fail(GTK_IS_ENTRY(entry)); 01153 name = gtk_buildable_get_name(GTK_BUILDABLE(entry)) + PREFIX_LEN; 01154 text = gtk_entry_get_text(entry); 01155 DEBUG("entry %s set to '%s'", name, text); 01156 gnc_gconf_set_string(name, NULL, text, NULL); 01157 } 01158 01159 01168 static void 01169 gnc_prefs_entry_gconf_cb (GtkEntry *entry, 01170 const gchar *value) 01171 { 01172 g_return_if_fail(GTK_IS_ENTRY(entry)); 01173 ENTER("entry %p, value '%s'", entry, value); 01174 g_signal_handlers_block_by_func(G_OBJECT(entry), 01175 G_CALLBACK(gnc_prefs_entry_user_cb), NULL); 01176 gtk_entry_set_text(entry, value); 01177 g_signal_handlers_unblock_by_func(G_OBJECT(entry), 01178 G_CALLBACK(gnc_prefs_entry_user_cb), NULL); 01179 LEAVE(" "); 01180 } 01181 01182 01190 static void 01191 gnc_prefs_connect_entry (GtkEntry *entry) 01192 { 01193 const gchar *name; 01194 gchar *text; 01195 01196 g_return_if_fail(GTK_IS_ENTRY(entry)); 01197 name = gtk_buildable_get_name(GTK_BUILDABLE(entry)) + PREFIX_LEN; 01198 text = gnc_gconf_get_string(name, NULL, NULL); 01199 gtk_entry_set_text(GTK_ENTRY(entry), text ? text : ""); 01200 DEBUG(" Entry %s set to '%s'", name ? name : "(null)", text ? text : "(null)"); 01201 g_free(text); 01202 g_signal_connect(G_OBJECT(entry), "changed", 01203 G_CALLBACK(gnc_prefs_entry_user_cb), NULL); 01204 } 01205 01206 /****************************************************************************/ 01207 01217 static void 01218 gnc_prefs_period_select_user_cb (GncPeriodSelect *period, 01219 gpointer user_data) 01220 { 01221 const gchar *name; 01222 gint active; 01223 01224 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 01225 name = g_object_get_data(G_OBJECT(period), "name"); 01226 active = gnc_period_select_get_active(period); 01227 DEBUG("period select %s set to item %d", name, active); 01228 gnc_gconf_set_int(name, NULL, active, NULL); 01229 } 01230 01231 01241 static void 01242 gnc_prefs_period_select_gconf_cb (GncPeriodSelect *period, 01243 gint value) 01244 { 01245 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 01246 ENTER("period %p, value %d", period, value); 01247 g_signal_handlers_block_by_func(G_OBJECT(period), 01248 G_CALLBACK(gnc_prefs_period_select_user_cb), NULL); 01249 gnc_period_select_set_active(period, value); 01250 g_signal_handlers_unblock_by_func(G_OBJECT(period), 01251 G_CALLBACK(gnc_prefs_period_select_user_cb), NULL); 01252 LEAVE(" "); 01253 } 01254 01255 01263 static void 01264 gnc_prefs_connect_period_select (GncPeriodSelect *period, const gchar *boxname ) 01265 { 01266 const gchar *name; 01267 gint active; 01268 QofBook *book; 01269 KvpFrame *book_frame; 01270 gint64 month, day; 01271 GDate fy_end; 01272 01273 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 01274 book = gnc_get_current_book(); 01275 book_frame = qof_book_get_slots(book); 01276 month = kvp_frame_get_gint64(book_frame, "/book/fyear_end/month"); 01277 day = kvp_frame_get_gint64(book_frame, "/book/fyear_end/day"); 01278 if (g_date_valid_dmy(day, month, 2005 /* not leap year */)) 01279 { 01280 g_date_clear(&fy_end, 1); 01281 g_date_set_dmy(&fy_end, day, month, G_DATE_BAD_YEAR); 01282 gnc_period_select_set_fy_end(period, &fy_end); 01283 } 01284 01285 name = boxname + PREFIX_LEN; 01286 01287 g_object_set_data(G_OBJECT(period), "name", g_strdup(name) ); 01288 01289 active = gnc_gconf_get_int(name, NULL, NULL); 01290 gnc_period_select_set_active(period, active); 01291 DEBUG(" Period select %s set to item %d", name, active); 01292 g_signal_connect(G_OBJECT(period), "changed", 01293 G_CALLBACK(gnc_prefs_period_select_user_cb), NULL); 01294 } 01295 01296 /****************************************************************************/ 01297 01307 static void 01308 gnc_prefs_date_edit_user_cb (GNCDateEdit *gde, 01309 gpointer user_data) 01310 { 01311 const gchar *name; 01312 time_t time; 01313 01314 g_return_if_fail(GNC_IS_DATE_EDIT(gde)); 01315 name = g_object_get_data(G_OBJECT(gde), "name"); 01316 time = gnc_date_edit_get_date(gde); 01317 01318 DEBUG("date_edit %s set", name); 01319 gnc_gconf_set_int(name, NULL, time, NULL); 01320 } 01321 01322 01332 static void 01333 gnc_prefs_date_edit_gconf_cb (GNCDateEdit *gde, 01334 GConfEntry *entry) 01335 { 01336 time_t time; 01337 01338 g_return_if_fail(GNC_IS_DATE_EDIT(gde)); 01339 ENTER("date_edit %p, entry %p", gde, entry); 01340 01341 time = gconf_value_get_int(entry->value); 01342 01343 g_signal_handlers_block_by_func(G_OBJECT(gde), 01344 G_CALLBACK(gnc_prefs_date_edit_user_cb), NULL); 01345 gnc_date_edit_set_time(GNC_DATE_EDIT(gde), time); 01346 g_signal_handlers_unblock_by_func(G_OBJECT(gde), 01347 G_CALLBACK(gnc_prefs_date_edit_user_cb), NULL); 01348 LEAVE(" "); 01349 } 01350 01351 01359 static void 01360 gnc_prefs_connect_date_edit (GNCDateEdit *gde , const gchar *boxname ) 01361 { 01362 const gchar *name; 01363 time_t time; 01364 01365 g_return_if_fail(GNC_IS_DATE_EDIT(gde)); 01366 01367 /* Lookup the date based upon gconf setting */ 01368 name = boxname + PREFIX_LEN; 01369 01370 g_object_set_data(G_OBJECT(gde), "name", g_strdup(name) ); 01371 01372 time = gnc_gconf_get_int(name, NULL, NULL); 01373 01374 gnc_date_edit_set_time(GNC_DATE_EDIT(gde), time); 01375 DEBUG(" date_edit %s set", name); 01376 01377 g_signal_connect(G_OBJECT(gde), "date_changed", 01378 G_CALLBACK(gnc_prefs_date_edit_user_cb), NULL); 01379 01380 gtk_widget_show_all(GTK_WIDGET(gde)); 01381 } 01382 01383 01384 /****************************************************************************/ 01385 01386 /********************/ 01387 /* Callbacks */ 01388 /********************/ 01389 01403 void 01404 gnc_preferences_response_cb(GtkDialog *dialog, gint response, GtkDialog *unused) 01405 { 01406 switch (response) 01407 { 01408 case GTK_RESPONSE_HELP: 01409 gnc_gnome_help(HF_HELP, HL_GLOBPREFS); 01410 break; 01411 01412 default: 01413 gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(dialog)); 01414 gnc_unregister_gui_component_by_data(DIALOG_PREFERENCES_CM_CLASS, 01415 dialog); 01416 gnc_gconf_general_remove_cb( 01417 KEY_ACCOUNT_SEPARATOR, 01418 (GncGconfGeneralCb)gnc_account_separator_prefs_cb, 01419 dialog); 01420 gnc_gconf_remove_notification(G_OBJECT(dialog), NULL, 01421 DIALOG_PREFERENCES_CM_CLASS); 01422 gtk_widget_destroy(GTK_WIDGET(dialog)); 01423 break; 01424 } 01425 } 01426 01427 01428 /********************/ 01429 /* Creation */ 01430 /********************/ 01431 01443 static void 01444 gnc_prefs_connect_one (const gchar *name, 01445 GtkWidget *widget, 01446 gpointer user_data) 01447 { 01448 /* These tests must be ordered from more specific widget to less 01449 * specific widget. */ 01450 01451 if (GTK_IS_FONT_BUTTON(widget)) 01452 { 01453 DEBUG(" %s - entry", name); 01454 gnc_prefs_connect_font_button(GTK_FONT_BUTTON(widget)); 01455 } 01456 else if (GTK_IS_RADIO_BUTTON(widget)) 01457 { 01458 DEBUG(" %s - radio button", name); 01459 gnc_prefs_connect_radio_button(GTK_RADIO_BUTTON(widget)); 01460 } 01461 else if (GTK_IS_CHECK_BUTTON(widget)) 01462 { 01463 DEBUG(" %s - check button", name); 01464 gnc_prefs_connect_check_button(GTK_CHECK_BUTTON(widget)); 01465 } 01466 else if (GTK_IS_SPIN_BUTTON(widget)) 01467 { 01468 DEBUG(" %s - spin button", name); 01469 gnc_prefs_connect_spin_button(GTK_SPIN_BUTTON(widget)); 01470 } 01471 else if (GTK_IS_COMBO_BOX(widget)) 01472 { 01473 DEBUG(" %s - combo box", name); 01474 gnc_prefs_connect_combo_box(GTK_COMBO_BOX(widget)); 01475 } 01476 else if (GTK_IS_ENTRY(widget)) 01477 { 01478 DEBUG(" %s - entry", name); 01479 gnc_prefs_connect_entry(GTK_ENTRY(widget)); 01480 } 01481 else if (GTK_IS_HBOX(widget)) 01482 { 01483 /* Test custom widgets are all children of a hbox */ 01484 GtkWidget *widget_child; 01485 GList* child = gtk_container_get_children(GTK_CONTAINER(widget)); 01486 widget_child = child->data; 01487 g_list_free(child); 01488 DEBUG(" %s - hbox", name); 01489 DEBUG("Hbox widget type is %s and name is %s", gtk_widget_get_name(GTK_WIDGET(widget_child)), name); 01490 01491 if (GNC_IS_CURRENCY_EDIT(widget_child)) 01492 { 01493 DEBUG(" %s - currency_edit", name); 01494 gnc_prefs_connect_currency_edit(GNC_CURRENCY_EDIT(widget_child), name ); 01495 } 01496 else if (GNC_IS_PERIOD_SELECT(widget_child)) 01497 { 01498 DEBUG(" %s - period_Select", name); 01499 gnc_prefs_connect_period_select(GNC_PERIOD_SELECT(widget_child), name ); 01500 } 01501 else if (GNC_IS_DATE_EDIT(widget_child)) 01502 { 01503 DEBUG(" %s - date_edit", name); 01504 gnc_prefs_connect_date_edit(GNC_DATE_EDIT(widget_child), name ); 01505 } 01506 } 01507 else 01508 { 01509 DEBUG(" %s - unsupported %s", name, 01510 G_OBJECT_TYPE_NAME(G_OBJECT(widget))); 01511 } 01512 } 01513 01514 01526 static GtkWidget * 01527 gnc_preferences_dialog_create(void) 01528 { 01529 GtkBuilder *builder; 01530 GtkWidget *dialog, *notebook, *label, *image; 01531 GtkWidget *box, *date, *period, *currency; 01532 GHashTable *table; 01533 GDate* gdate; 01534 gchar buf[128]; 01535 gnc_commodity *locale_currency; 01536 const gchar *currency_name; 01537 01538 ENTER(""); 01539 DEBUG("Opening dialog-preferences.glade:"); 01540 builder = gtk_builder_new(); 01541 01542 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "auto_decimal_places_adj"); 01543 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "autosave_interval_minutes_adj"); 01544 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "date_backmonth_adj"); 01545 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "max_transactions_adj"); 01546 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "new_search_limit_adj"); 01547 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "retain_days_adj"); 01548 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "tab_width_adj"); 01549 gnc_builder_add_from_file (builder, "dialog-preferences.glade", "GnuCash Preferences"); 01550 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "GnuCash Preferences")); 01551 01552 DEBUG("autoconnect"); 01553 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, dialog); 01554 01555 DEBUG("done"); 01556 01557 notebook = GTK_WIDGET(gtk_builder_get_object (builder, "notebook1")); 01558 table = g_hash_table_new(g_str_hash, g_str_equal); 01559 g_object_set_data(G_OBJECT(dialog), NOTEBOOK, notebook); 01560 g_object_set_data_full(G_OBJECT(dialog), WIDGET_HASH, 01561 table, (GDestroyNotify)g_hash_table_destroy); 01562 01563 box = GTK_WIDGET(gtk_builder_get_object (builder, "gconf/window/pages/account_tree/summary/start_period")); 01564 period = gnc_period_select_new(TRUE); 01565 gtk_widget_show (period); 01566 gtk_box_pack_start (GTK_BOX (box), period, TRUE, TRUE, 0); 01567 01568 box = GTK_WIDGET(gtk_builder_get_object (builder, "gconf/window/pages/account_tree/summary/start_date")); 01569 date = gnc_date_edit_new(time(NULL), FALSE, FALSE); 01570 gtk_widget_show (date); 01571 gtk_box_pack_start (GTK_BOX (box), date, TRUE, TRUE, 0); 01572 01573 box = GTK_WIDGET(gtk_builder_get_object (builder, "gconf/window/pages/account_tree/summary/end_period")); 01574 period = gnc_period_select_new(FALSE); 01575 gtk_widget_show (period); 01576 gtk_box_pack_start (GTK_BOX (box), period, TRUE, TRUE, 0); 01577 01578 box = GTK_WIDGET(gtk_builder_get_object (builder, "gconf/window/pages/account_tree/summary/end_date")); 01579 date = gnc_date_edit_new(time(NULL), FALSE, FALSE); 01580 gtk_widget_show (date); 01581 gtk_box_pack_start (GTK_BOX (box), date, TRUE, TRUE, 0); 01582 01583 box = GTK_WIDGET(gtk_builder_get_object (builder, "gconf/general/currency_other")); 01584 currency = gnc_currency_edit_new(); 01585 gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(currency), gnc_default_currency()); 01586 gtk_widget_show (currency); 01587 gtk_box_pack_start(GTK_BOX (box), currency, TRUE, TRUE, 0); 01588 01589 box = GTK_WIDGET(gtk_builder_get_object (builder, "gconf/general/report/currency_other")); 01590 currency = gnc_currency_edit_new(); 01591 gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(currency), gnc_default_currency()); 01592 gtk_widget_show (currency); 01593 gtk_box_pack_start(GTK_BOX (box), currency, TRUE, TRUE, 0); 01594 01595 01596 /* Add to the list of interesting widgets */ 01597 gnc_prefs_build_widget_table(builder, dialog); 01598 01599 g_slist_foreach(add_ins, gnc_preferences_build_page, dialog); 01600 01601 /* Sort tabs alphabetically */ 01602 gnc_prefs_sort_pages(GTK_NOTEBOOK(notebook)); 01603 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0); 01604 01605 DEBUG("We have the following interesting widgets:"); 01606 g_hash_table_foreach(table, (GHFunc)gnc_prefs_connect_one, dialog); 01607 DEBUG("Done with interesting widgets."); 01608 01609 /* Other stuff */ 01610 gdate = g_date_new_dmy(31, G_DATE_JULY, 2005); 01611 g_date_strftime(buf, sizeof(buf), "%x", gdate); 01612 label = GTK_WIDGET(gtk_builder_get_object (builder, "locale_date_sample")); 01613 gtk_label_set_text(GTK_LABEL(label), buf); 01614 g_date_free(gdate); 01615 01616 locale_currency = gnc_locale_default_currency (); 01617 currency_name = gnc_commodity_get_printname(locale_currency); 01618 label = GTK_WIDGET(gtk_builder_get_object (builder, "locale_currency")); 01619 gtk_label_set_label(GTK_LABEL(label), currency_name); 01620 label = GTK_WIDGET(gtk_builder_get_object (builder, "locale_currency2")); 01621 gtk_label_set_label(GTK_LABEL(label), currency_name); 01622 01623 label = GTK_WIDGET(gtk_builder_get_object (builder, "sample_account")); 01624 g_object_set_data(G_OBJECT(dialog), "sample_account", label); 01625 01626 image = GTK_WIDGET(gtk_builder_get_object (builder, "separator_error")); 01627 g_object_set_data(G_OBJECT(dialog), "separator_error", image); 01628 01629 gnc_account_separator_prefs_cb(NULL, dialog); 01630 01631 g_object_unref(G_OBJECT(builder)); 01632 01633 LEAVE("dialog %p", dialog); 01634 return dialog; 01635 } 01636 01637 01638 /*************************************/ 01639 /* GConf common callback code */ 01640 /*************************************/ 01641 01662 static gboolean 01663 gnc_prefs_nearest_match (gpointer key, 01664 gpointer value, 01665 gpointer user_data) 01666 { 01667 const gchar *widget_name = key; 01668 const gchar *gconf_name = user_data; 01669 01670 return (strncmp(widget_name, gconf_name, strlen(gconf_name)) == 0); 01671 } 01672 01673 01685 static void 01686 gnc_preferences_gconf_changed (GConfClient *client, 01687 guint cnxn_id, 01688 GConfEntry *entry, 01689 gpointer dialog) 01690 { 01691 GConfValue *value; 01692 const gchar *key, *string_value; 01693 gchar **parts, *name, *group_name = NULL; 01694 GtkWidget *widget; 01695 GHashTable *table; 01696 01697 ENTER("key %s, value %p", entry->key, entry->value); 01698 key = gconf_entry_get_key(entry); 01699 value = gconf_entry_get_value(entry); 01700 if (!value) 01701 { 01702 /* Values can be unset */ 01703 LEAVE("Unset valued for %s", key); 01704 return; 01705 } 01706 01707 parts = g_strsplit(entry->key, "/", 4); 01708 name = g_strconcat("gconf/", parts[3], NULL); 01709 g_strfreev(parts); 01710 DEBUG("proposed widget name %s", name); 01711 01712 /* Can't just do a glade lookup here because not all of the widgets 01713 * came from the same xml file. That's why the extra hash table. */ 01714 table = g_object_get_data(G_OBJECT(dialog), WIDGET_HASH); 01715 widget = g_hash_table_lookup(table, name); 01716 if ((widget == NULL) && (entry->value->type == GCONF_VALUE_STRING)) 01717 { 01718 string_value = gconf_value_get_string(entry->value); 01719 group_name = name; 01720 name = g_strjoin("/", group_name, string_value, NULL); 01721 DEBUG("proposed widget name %s", name); 01722 widget = g_hash_table_lookup(table, name); 01723 if (widget == NULL) 01724 { 01725 /* Mutter, mutter. Someone must have typed a bad string into 01726 * gconf. Force the value to a legal string. Do this by 01727 * directly setting the first widget in the group. This will 01728 * ensure synchronization of Gnucash, Gconf, and the Prefs 01729 * Dialog. */ 01730 DEBUG("bad value"); 01731 widget = g_hash_table_find(table, gnc_prefs_nearest_match, group_name); 01732 if (widget) 01733 { 01734 DEBUG("forcing %s", gtk_widget_get_name(widget)); 01735 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); 01736 } 01737 g_free(group_name); 01738 g_free(name); 01739 LEAVE("no exact match"); 01740 return; 01741 } 01742 g_free(group_name); 01743 } 01744 if (widget != NULL) 01745 { 01746 /* These tests must be ordered from more specific widget to less 01747 * specific widget. */ 01748 01749 if (GTK_IS_FONT_BUTTON(widget)) 01750 { 01751 DEBUG("widget %p - font button", widget); 01752 gnc_prefs_font_button_gconf_cb(GTK_FONT_BUTTON(widget), entry); 01753 } 01754 else if (GTK_IS_RADIO_BUTTON(widget)) 01755 { 01756 DEBUG("widget %p - radio button", widget); 01757 gnc_prefs_radio_button_gconf_cb(GTK_RADIO_BUTTON(widget)); 01758 } 01759 else if (GTK_IS_CHECK_BUTTON(widget)) 01760 { 01761 DEBUG("widget %p - check button", widget); 01762 gnc_prefs_check_button_gconf_cb(GTK_CHECK_BUTTON(widget), 01763 gconf_value_get_bool(entry->value)); 01764 } 01765 else if (GTK_IS_SPIN_BUTTON(widget)) 01766 { 01767 DEBUG("widget %p - spin button", widget); 01768 gnc_prefs_spin_button_gconf_cb(GTK_SPIN_BUTTON(widget), 01769 gconf_value_get_float(entry->value)); 01770 } 01771 else if (GTK_IS_COMBO_BOX(widget)) 01772 { 01773 DEBUG("widget %p - combo_box", widget); 01774 gnc_prefs_combo_box_gconf_cb(GTK_COMBO_BOX(widget), 01775 gconf_value_get_int(entry->value)); 01776 } 01777 else if (GTK_IS_ENTRY(widget)) 01778 { 01779 DEBUG("widget %p - entry", widget); 01780 gnc_prefs_entry_gconf_cb(GTK_ENTRY(widget), 01781 gconf_value_get_string(entry->value)); 01782 } 01783 else if (GTK_IS_HBOX(widget)) 01784 { 01785 /* Test custom widgets are all children of a hbox */ 01786 GtkWidget *widget_child; 01787 GList* child = gtk_container_get_children(GTK_CONTAINER(widget)); 01788 widget_child = child->data; 01789 g_list_free(child); 01790 01791 DEBUG(" %s - hbox", name); 01792 DEBUG("Hbox gconf name is %s and widget get name is %s", name, gtk_widget_get_name(GTK_WIDGET(widget_child))); 01793 01794 if (GNC_IS_CURRENCY_EDIT(widget_child)) 01795 { 01796 DEBUG("widget %p - currency_edit", widget_child); 01797 gnc_prefs_currency_edit_gconf_cb(GNC_CURRENCY_EDIT(widget_child), entry); 01798 } 01799 else if (GNC_IS_PERIOD_SELECT(widget_child)) 01800 { 01801 DEBUG("widget %p - period_select", widget_child); 01802 gnc_prefs_period_select_gconf_cb(GNC_PERIOD_SELECT(widget_child), 01803 gconf_value_get_int(entry->value)); 01804 } 01805 else if (GNC_IS_DATE_EDIT(widget_child)) 01806 { 01807 DEBUG("widget %p - date_edit", widget_child); 01808 gnc_prefs_date_edit_gconf_cb(GNC_DATE_EDIT(widget_child), entry); 01809 } 01810 } 01811 else 01812 { 01813 DEBUG("widget %p - unsupported %s", widget, 01814 G_OBJECT_TYPE_NAME(G_OBJECT(widget))); 01815 } 01816 } 01817 g_free(name); 01818 LEAVE(" "); 01819 } 01820 01821 01836 static gboolean 01837 show_handler (const char *class, gint component_id, 01838 gpointer user_data, gpointer iter_data) 01839 { 01840 GtkWidget *dialog; 01841 01842 ENTER(" "); 01843 dialog = GTK_WIDGET(user_data); 01844 gtk_window_present(GTK_WINDOW(dialog)); 01845 LEAVE(" "); 01846 return(TRUE); 01847 } 01848 01849 01856 static void 01857 close_handler (gpointer user_data) 01858 { 01859 GtkWidget *dialog; 01860 01861 ENTER(" "); 01862 dialog = GTK_WIDGET(user_data); 01863 gnc_unregister_gui_component_by_data(DIALOG_PREFERENCES_CM_CLASS, dialog); 01864 gtk_widget_destroy(dialog); 01865 LEAVE(" "); 01866 } 01867 01868 01869 /* This function creates the preferences dialog and presents it to 01870 * the user. The preferences dialog is a singleton, so if a 01871 * preferences dialog already exists it will be raised to the top of 01872 * the window stack instead of creating a new dialog. */ 01873 void 01874 gnc_preferences_dialog (void) 01875 { 01876 GtkWidget *dialog; 01877 01878 ENTER(""); 01879 if (gnc_forall_gui_components(DIALOG_PREFERENCES_CM_CLASS, 01880 show_handler, NULL)) 01881 { 01882 LEAVE("existing window"); 01883 return; 01884 } 01885 01886 dialog = gnc_preferences_dialog_create(); 01887 01888 gnc_restore_window_size(GCONF_SECTION, GTK_WINDOW(dialog)); 01889 gtk_widget_show(dialog); 01890 01891 gnc_gconf_add_notification(G_OBJECT(dialog), NULL, 01892 gnc_preferences_gconf_changed, 01893 DIALOG_PREFERENCES_CM_CLASS); 01894 gnc_gconf_general_register_cb(KEY_ACCOUNT_SEPARATOR, 01895 (GncGconfGeneralCb)gnc_account_separator_prefs_cb, 01896 dialog); 01897 gnc_register_gui_component(DIALOG_PREFERENCES_CM_CLASS, 01898 NULL, close_handler, dialog); 01899 01900 LEAVE(" "); 01901 } 01902
1.7.4