1 /********************************************************************\
2 * dialog-options.c -- GNOME option handling *
3 * Copyright (C) 1998-2000 Linas Vepstas *
4 * Copyright (c) 2006 David Hampton <hampton@employees.org> *
5 * Copyright (c) 2011 Robert Fewell *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License as *
9 * published by the Free Software Foundation; either version 2 of *
10 * the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License*
18 * along with this program; if not, contact: *
19 * *
20 * Free Software Foundation Voice: +1-617-542-5942 *
21 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22 * Boston, MA 02110-1301, USA gnu@gnu.org *
23 \********************************************************************/
24
25 #include <config.h>
26
27 #include <gtk/gtk.h>
28 #include <gdk/gdk.h>
29 #include <glib/gi18n.h>
30 #include "swig-runtime.h"
31
32 #include "gnc-tree-model-budget.h" //FIXME?
33 #include "gnc-budget.h"
34
35 #include "dialog-options.h"
36 #include "dialog-utils.h"
37 #include "gnc-engine-guile.h"
38 #include "glib-guile.h"
39 #include "gnc-account-sel.h"
40 #include "gnc-tree-view-account.h"
41 #include "gnc-tree-model-account.h"
42 #include "gnc-commodity-edit.h"
43 #include "gnc-component-manager.h"
44 #include "gnc-general-select.h"
45 #include "gnc-currency-edit.h"
46 #include "gnc-date-edit.h"
47 #include "gnc-engine.h"
48 #include "gnc-prefs.h"
49 #include "gnc-gui-query.h"
50 #include "gnc-session.h"
51 #include "gnc-ui.h"
52 #include "gnc-guile-utils.h"
53 #include "option-util.h"
54 #include "guile-mappings.h"
55 #include "gnc-date-format.h"
56 #include "misc-gnome-utils.h"
57
58 #define GNC_PREF_CLOCK_24H "clock-24h"
59
60 #define FUNC_NAME G_STRFUNC
61 /* TODO: clean up "register-stocks" junk
62 */
63
64
65 /* This static indicates the debugging module that this .o belongs to. */
66 static QofLogModule log_module = GNC_MOD_GUI;
67
68 #define DIALOG_OPTIONS_CM_CLASS "dialog-options"
69 #define DIALOG_BOOK_OPTIONS_CM_CLASS "dialog-book-options"
70
71 #define GNC_PREFS_GROUP "dialogs.options"
72
73 /*
74 * Point where preferences switch control method from a set of
75 * notebook tabs to a list.
76 */
77 #define MAX_TAB_COUNT 6
78
79 /* A pointer to the last selected filename */
80 #define LAST_SELECTION "last-selection"
81
82 /* A Hash-table of GNCOptionDef_t keyed with option names. */
83 static GHashTable *optionTable = NULL;
84
85 static int gain_loss_accounts_in_filter = 0;
86
87 struct gnc_option_win
88 {
89 GtkWidget * window;
90 GtkWidget * notebook;
91 GtkWidget * page_list_view;
92 GtkWidget * page_list;
93
94 gboolean toplevel;
95
96 GNCOptionWinCallback apply_cb;
97 gpointer apply_cb_data;
98
99 GNCOptionWinCallback help_cb;
100 gpointer help_cb_data;
101
102 GNCOptionWinCallback close_cb;
103 gpointer close_cb_data;
104
105 /* Hold onto this for a complete reset */
106 GNCOptionDB *option_db;
107
108 /* Hold on to this to unregister the right class */
109 const char *component_class;
110
111 /* widget being destroyed */
112 gboolean destroyed;
113 };
114
115 typedef enum
116 {
117 GNC_RD_WID_AB_BUTTON_POS = 0,
118 GNC_RD_WID_AB_WIDGET_POS,
119 GNC_RD_WID_REL_BUTTON_POS,
120 GNC_RD_WID_REL_WIDGET_POS
121 } GNCRdPositions;
122
123 enum page_tree
124 {
125 PAGE_INDEX = 0,
126 PAGE_NAME,
127 NUM_COLUMNS
128 };
129
130 typedef struct
131 {
132 GtkWidget *gnc_currency_radiobutton_0;
133 GtkWidget *gnc_currency_radiobutton_1;
134 GtkWidget *gnc_currency_radiobutton_2;
135 GtkWidget *book_currency_widget;
136 GtkWidget *default_cost_policy_widget;
137 GtkWidget *default_gain_loss_account_widget;
138 GtkWidget *book_currency_table;
139 GtkWidget *book_currency_vbox;
140 GtkWidget *gain_loss_account_del_button;
141 GtkWidget *gain_loss_account_table;
142 GtkWidget *default_gain_loss_account_text;
143 GNCOption *option;
144 Account *prior_gain_loss_account;
145 gnc_commodity *retrieved_book_currency;
146
147 SCM retrieved_policy_scm;
148 SCM retrieved_gain_loss_acct_guid_scm;
149
150 } currency_accounting_data;
151
152 static currency_accounting_data *book_currency_data = NULL;
153
154 static GNCOptionWinCallback global_help_cb = NULL;
155 gpointer global_help_cb_data = NULL;
156
157 static void gnc_options_dialog_reset_cb (GtkWidget * w, gpointer data);
158 void gnc_options_dialog_list_select_cb (GtkTreeSelection *selection,
159 gpointer data);
160 void gnc_set_default_cost_policy_widget (SCM list_symbol);
161 void gnc_set_default_gain_loss_account_widget (gnc_commodity *commodity);
162 void gnc_option_changed_book_currency_widget_cb (GtkWidget *widget);
163 void gnc_option_changed_gain_loss_account_widget_cb (GtkTreeSelection *selection,
164 gpointer data);
165 void gnc_option_changed_gain_loss_account_del_button_widget_cb (GtkButton *button,
166 gpointer data);
167 static void component_close_handler (gpointer data);
168
169 GtkWidget *
gnc_option_get_gtk_widget(GNCOption * option)170 gnc_option_get_gtk_widget (GNCOption *option)
171 {
172 return (GtkWidget *)gnc_option_get_widget (option);
173 }
174
175 static void
gnc_options_dialog_changed_internal(GtkWidget * widget,gboolean sensitive)176 gnc_options_dialog_changed_internal (GtkWidget *widget, gboolean sensitive)
177 {
178 GtkButton *button = NULL;
179
180 while (widget && !GTK_IS_WINDOW(widget))
181 widget = gtk_widget_get_parent (widget);
182 if (widget == NULL)
183 return;
184
185 /* find the ok and cancel buttons, we know where they will be so do it
186 this way as opposed to using gtk_container_foreach, much less iteration */
187 if (GTK_IS_CONTAINER(widget))
188 {
189 GList *children = gtk_container_get_children (GTK_CONTAINER(widget));
190 for (GList *it = children; it; it = it->next)
191 {
192 if (GTK_IS_BOX(GTK_WIDGET(it->data)))
193 {
194 GList *children = gtk_container_get_children (GTK_CONTAINER(it->data));
195 for (GList *it = children; it; it = it->next)
196 {
197 if (GTK_IS_BUTTON_BOX(GTK_WIDGET(it->data)))
198 {
199 GList *children = gtk_container_get_children (GTK_CONTAINER(it->data));
200 for (GList *it = children; it; it = it->next)
201 {
202 if (g_strcmp0 (gtk_widget_get_name (GTK_WIDGET(it->data)), "ok_button") == 0)
203 gtk_widget_set_sensitive (GTK_WIDGET(it->data), sensitive);
204
205 if (g_strcmp0 (gtk_widget_get_name (GTK_WIDGET(it->data)), "apply_button") == 0)
206 gtk_widget_set_sensitive (GTK_WIDGET(it->data), sensitive);
207
208 if (g_strcmp0 (gtk_widget_get_name (GTK_WIDGET(it->data)), "cancel_button") == 0)
209 button = GTK_BUTTON(it->data);
210 }
211 g_list_free (children);
212 }
213 }
214 g_list_free (children);
215 }
216 }
217 g_list_free (children);
218 }
219
220 if (button)
221 {
222 if (sensitive)
223 gtk_button_set_label (button, _("_Cancel"));
224 else
225 gtk_button_set_label (button, _("_Close"));
226 }
227 }
228
229 void
gnc_options_dialog_changed(GNCOptionWin * win)230 gnc_options_dialog_changed (GNCOptionWin *win)
231 {
232 if (!win) return;
233
234 gnc_options_dialog_changed_internal (win->window, TRUE);
235 }
236
237 void
gnc_option_changed_widget_cb(GtkWidget * widget,GNCOption * option)238 gnc_option_changed_widget_cb (GtkWidget *widget, GNCOption *option)
239 {
240 gnc_option_set_changed (option, TRUE);
241 gnc_option_call_option_widget_changed_proc (option, FALSE);
242 gnc_options_dialog_changed_internal (widget, TRUE);
243 }
244
245 void
gnc_option_changed_option_cb(GtkWidget * dummy,GNCOption * option)246 gnc_option_changed_option_cb (GtkWidget *dummy, GNCOption *option)
247 {
248 GtkWidget *widget = gnc_option_get_gtk_widget (option);
249 gnc_option_changed_widget_cb (widget, option);
250 }
251
252 static void
gnc_date_option_set_select_method(GNCOption * option,gboolean use_absolute,gboolean set_buttons)253 gnc_date_option_set_select_method (GNCOption *option,
254 gboolean use_absolute,
255 gboolean set_buttons)
256 {
257 GList* widget_list;
258 GtkWidget *ab_button, *rel_button, *rel_widget, *ab_widget;
259 GtkWidget *widget;
260
261 widget = gnc_option_get_gtk_widget (option);
262
263 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
264 ab_button = g_list_nth_data (widget_list, GNC_RD_WID_AB_BUTTON_POS);
265 ab_widget = g_list_nth_data (widget_list, GNC_RD_WID_AB_WIDGET_POS);
266 rel_button = g_list_nth_data (widget_list, GNC_RD_WID_REL_BUTTON_POS);
267 rel_widget = g_list_nth_data (widget_list, GNC_RD_WID_REL_WIDGET_POS);
268 g_list_free (widget_list);
269
270 if (use_absolute)
271 {
272 gtk_widget_set_sensitive (ab_widget, TRUE);
273 gtk_widget_set_sensitive (rel_widget, FALSE);
274 if (set_buttons)
275 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(ab_button), TRUE);
276 }
277 else
278 {
279 gtk_widget_set_sensitive (rel_widget, TRUE);
280 gtk_widget_set_sensitive (ab_widget, FALSE);
281 if (set_buttons)
282 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rel_button), TRUE);
283 }
284 }
285
286 static void
gnc_rd_option_ab_set_cb(GtkWidget * widget,gpointer * raw_option)287 gnc_rd_option_ab_set_cb (GtkWidget *widget, gpointer *raw_option)
288 {
289 GNCOption *option = (GNCOption *) raw_option;
290 gnc_date_option_set_select_method (option, TRUE, FALSE);
291 gnc_option_changed_option_cb (widget, option);
292 }
293
294 static void
gnc_rd_option_rel_set_cb(GtkWidget * widget,gpointer * raw_option)295 gnc_rd_option_rel_set_cb (GtkWidget *widget, gpointer *raw_option)
296 {
297 GNCOption *option = (GNCOption *) raw_option;
298 gnc_date_option_set_select_method (option, FALSE, FALSE);
299 gnc_option_changed_option_cb (widget, option);
300 return;
301 }
302
303 static void
gnc_image_option_update_preview_cb(GtkFileChooser * chooser,GNCOption * option)304 gnc_image_option_update_preview_cb (GtkFileChooser *chooser,
305 GNCOption *option)
306 {
307 gchar *filename;
308 GtkImage *image;
309 GdkPixbuf *pixbuf;
310 gboolean have_preview;
311
312 g_return_if_fail (chooser != NULL);
313
314 ENTER("chooser %p, option %p", chooser, option);
315 filename = gtk_file_chooser_get_preview_filename (chooser);
316 DEBUG("chooser preview name is %s.", filename ? filename : "(null)");
317 if (filename == NULL)
318 {
319 filename = g_strdup (g_object_get_data (G_OBJECT(chooser), LAST_SELECTION));
320 DEBUG("using last selection of %s", filename ? filename : "(null)");
321 if (filename == NULL)
322 {
323 LEAVE("no usable name");
324 return;
325 }
326 }
327
328 image = GTK_IMAGE(gtk_file_chooser_get_preview_widget (chooser));
329 pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL);
330 g_free (filename);
331 have_preview = (pixbuf != NULL);
332
333 gtk_image_set_from_pixbuf (image, pixbuf);
334 if (pixbuf)
335 g_object_unref (pixbuf);
336
337 gtk_file_chooser_set_preview_widget_active (chooser, have_preview);
338 LEAVE("preview visible is %d", have_preview);
339 }
340
341 static void
gnc_image_option_selection_changed_cb(GtkFileChooser * chooser,GNCOption * option)342 gnc_image_option_selection_changed_cb (GtkFileChooser *chooser,
343 GNCOption *option)
344 {
345 gchar *filename = gtk_file_chooser_get_preview_filename (chooser);
346 if (!filename)
347 return;
348 g_object_set_data_full (G_OBJECT(chooser), LAST_SELECTION, filename, g_free);
349 }
350
351 /********************************************************************\
352 * gnc_option_set_ui_value_internal *
353 * sets the GUI representation of an option with either its *
354 * current guile value, or its default value *
355 * *
356 * Args: option - option structure containing option *
357 * use_default - if true, use the default value, otherwise *
358 * use the current value *
359 * Return: nothing *
360 \********************************************************************/
361 static void
gnc_option_set_ui_value_internal(GNCOption * option,gboolean use_default)362 gnc_option_set_ui_value_internal (GNCOption *option, gboolean use_default)
363 {
364 gboolean bad_value = FALSE;
365 GtkWidget *widget;
366 char *type;
367 SCM getter;
368 SCM value;
369 GNCOptionDef_t *option_def;
370
371 widget = gnc_option_get_gtk_widget (option);
372 if (!widget)
373 return;
374
375 type = gnc_option_type (option);
376
377 if (use_default)
378 {
379 SCM opt_getter = gnc_option_getter (option);
380 SCM opt_value = scm_call_0 (opt_getter);
381 SCM def_value;
382
383 getter = gnc_option_default_getter (option);
384 def_value = scm_call_0 (getter);
385
386 // only set changed if the values have changed
387 if (!scm_is_true (scm_equal_p (opt_value, def_value)))
388 gnc_option_set_changed (option, TRUE);
389 }
390 else
391 getter = gnc_option_getter (option);
392
393 value = scm_call_0 (getter);
394
395 option_def = gnc_options_ui_get_option (type);
396 if (option_def && option_def->set_value)
397 {
398 bad_value = option_def->set_value (option, use_default, widget, value);
399 if (bad_value)
400 {
401 gchar *name = gnc_option_name (option);
402 gchar *val = scm_to_locale_string (scm_object_to_string
403 (value, scm_c_eval_string ("write")));
404 PERR ("option '%s' bad value '%s'\n", name, val);
405 g_free (name);
406 g_free (val);
407 }
408 }
409 else
410 PERR("Unknown type. Ignoring.\n");
411
412 free (type);
413 }
414
415 /********************************************************************\
416 * gnc_option_get_ui_value_internal *
417 * returns the SCM representation of the GUI option value *
418 * *
419 * Args: option - option structure containing option *
420 * Return: SCM handle to GUI option value *
421 \********************************************************************/
422 static SCM
gnc_option_get_ui_value_internal(GNCOption * option)423 gnc_option_get_ui_value_internal (GNCOption *option)
424 {
425 SCM result = SCM_UNDEFINED;
426 GtkWidget *widget;
427 char *type;
428 GNCOptionDef_t *option_def;
429
430 widget = gnc_option_get_gtk_widget (option);
431 if (!widget)
432 return result;
433
434 type = gnc_option_type (option);
435
436 option_def = gnc_options_ui_get_option (type);
437
438 if (option_def && option_def->get_value)
439 result = option_def->get_value (option, widget);
440 else
441 PERR("Unknown type for refresh. Ignoring.\n");
442
443 free (type);
444
445 return result;
446 }
447
448 /********************************************************************\
449 * gnc_option_set_selectable_internal *
450 * Change the selectable state of the widget that represents a *
451 * GUI option. *
452 * *
453 * Args: option - option to change widget state for *
454 * selectable - if false, update the widget so that it *
455 * cannot be selected by the user. If true, *
456 * update the widget so that it can be selected.*
457 * Return: nothing *
458 \********************************************************************/
459 static void
gnc_option_set_selectable_internal(GNCOption * option,gboolean selectable)460 gnc_option_set_selectable_internal (GNCOption *option, gboolean selectable)
461 {
462 GtkWidget *widget;
463
464 widget = gnc_option_get_gtk_widget (option);
465 if (!widget)
466 return;
467
468 gtk_widget_set_sensitive (widget, selectable);
469 }
470
471 static void
gnc_option_default_cb(GtkWidget * widget,GNCOption * option)472 gnc_option_default_cb (GtkWidget *widget, GNCOption *option)
473 {
474 gnc_option_set_ui_value (option, TRUE);
475 gnc_option_set_changed (option, TRUE);
476 gnc_options_dialog_changed_internal (widget, TRUE);
477 }
478
479 static void
gnc_option_show_hidden_toggled_cb(GtkWidget * widget,GNCOption * option)480 gnc_option_show_hidden_toggled_cb (GtkWidget *widget, GNCOption* option)
481 {
482 AccountViewInfo avi;
483 GncTreeViewAccount *tree_view;
484
485 tree_view = GNC_TREE_VIEW_ACCOUNT(gnc_option_get_gtk_widget (option));
486 gnc_tree_view_account_get_view_info (tree_view, &avi);
487 avi.show_hidden = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget));
488 gnc_tree_view_account_set_view_info (tree_view, &avi);
489 gnc_option_changed_widget_cb (widget, option);
490 }
491
492 static void
gnc_option_multichoice_cb(GtkWidget * widget,gpointer data)493 gnc_option_multichoice_cb (GtkWidget *widget, gpointer data)
494 {
495 GNCOption *option = data;
496 gnc_option_changed_widget_cb (widget, option);
497 }
498
499 static void
gnc_option_radiobutton_cb(GtkWidget * w,gpointer data)500 gnc_option_radiobutton_cb (GtkWidget *w, gpointer data)
501 {
502 GNCOption *option = data;
503 GtkWidget *widget;
504 gpointer _current, _new_value;
505 gint current, new_value;
506
507 widget = gnc_option_get_gtk_widget (option);
508
509 _current = g_object_get_data (G_OBJECT(widget), "gnc_radiobutton_index");
510 current = GPOINTER_TO_INT(_current);
511
512 _new_value = g_object_get_data (G_OBJECT(w), "gnc_radiobutton_index");
513 new_value = GPOINTER_TO_INT(_new_value);
514
515 if (current == new_value)
516 return;
517
518 g_object_set_data (G_OBJECT(widget), "gnc_radiobutton_index",
519 GINT_TO_POINTER(new_value));
520 gnc_option_changed_widget_cb (widget, option);
521 }
522
523 static gboolean
gnc_gain_loss_account_view_filter(Account * account,gpointer data)524 gnc_gain_loss_account_view_filter (Account *account, gpointer data)
525 {
526 GNCAccountType type = xaccAccountGetType (account);
527
528 /* gain/loss accts must be an Income or Expense accts and not hidden;
529 placeholder accounts must be included, irrespective of their currency,
530 so their children are available to be considered */
531 if (((type == ACCT_TYPE_INCOME) || (type == ACCT_TYPE_EXPENSE)) &&
532 (!xaccAccountIsHidden(account)))
533 {
534 if (xaccAccountGetPlaceholder (account))
535 {
536 GList *placeholder_children = gnc_account_get_children (account);
537
538 if (placeholder_children)
539 { /* determine if any children qualify; just need one but don't
540 double count in gain_loss_accounts_in_filter */
541 int saved_gain_loss_accounts_in_filter =
542 gain_loss_accounts_in_filter;
543 gboolean child_pass_filter = FALSE;
544 GList *l = NULL;
545 for (l = placeholder_children; l != NULL; l = l->next)
546 {
547 Account *child_account = l->data;
548 child_pass_filter =
549 gnc_gain_loss_account_view_filter (child_account, NULL);
550 if (child_pass_filter)
551 break;
552 }
553 g_list_free (placeholder_children);
554 gain_loss_accounts_in_filter =
555 saved_gain_loss_accounts_in_filter;
556 return child_pass_filter;
557 }
558 else return FALSE; // no children, not interested
559 }
560 else
561 {
562 gnc_commodity *commodity = NULL;
563
564 /* gain/loss accts must be in book-currency; if a book currency has been
565 specified in the widget, use it to filter */
566 if (gtk_combo_box_get_active (GTK_COMBO_BOX(
567 book_currency_data->book_currency_widget)) != -1)
568 commodity = gnc_currency_edit_get_currency (
569 GNC_CURRENCY_EDIT(
570 book_currency_data->book_currency_widget));
571 if (commodity)
572 {
573 if (gnc_commodity_equal (xaccAccountGetCommodity (account),
574 commodity))
575 {
576 gain_loss_accounts_in_filter++;
577 return TRUE;
578 }
579 else return FALSE;
580 }
581 /* else use the default currency */
582 else if (gnc_commodity_equal (xaccAccountGetCommodity (account),
583 gnc_default_currency ()))
584 {
585 gain_loss_accounts_in_filter++;
586 return TRUE;
587 }
588 else return FALSE;
589 }
590 }
591 else return FALSE;
592 }
593
594 static gboolean
gnc_gain_loss_account_all_fail_filter(Account * account,gpointer data)595 gnc_gain_loss_account_all_fail_filter (Account *account, gpointer data)
596 {
597 return FALSE;
598 }
599
600 void
gnc_set_default_cost_policy_widget(SCM list_symbol)601 gnc_set_default_cost_policy_widget (SCM list_symbol)
602 {
603 GList *list_of_policies = gnc_get_valid_policy_list ();
604
605 if (list_of_policies)
606 {
607 GList *l = NULL;
608 gint i = 0;
609 for (l = list_of_policies; l != NULL; l = l->next)
610 {
611 GNCPolicy *pcy = l->data;
612 if (g_strcmp0 (PolicyGetName (pcy),
613 gnc_scm_symbol_to_locale_string (list_symbol))
614 == 0)
615 {
616 gtk_combo_box_set_active (
617 GTK_COMBO_BOX(
618 book_currency_data->default_cost_policy_widget), i);
619 }
620 i++;
621 }
622 g_list_free (list_of_policies);
623 }
624 else
625 {
626 gtk_combo_box_set_active (
627 GTK_COMBO_BOX(book_currency_data->default_cost_policy_widget), -1);
628 }
629 }
630
631 void
gnc_set_default_gain_loss_account_widget(gnc_commodity * commodity)632 gnc_set_default_gain_loss_account_widget (gnc_commodity *commodity)
633 {
634 if (book_currency_data->default_gain_loss_account_widget)
635 {
636 gtk_widget_destroy (
637 book_currency_data->default_gain_loss_account_widget);
638 book_currency_data->default_gain_loss_account_widget = NULL;
639 book_currency_data->prior_gain_loss_account = NULL;
640 gain_loss_accounts_in_filter = 0;
641 }
642 if (book_currency_data->gain_loss_account_del_button)
643 {
644 gtk_widget_destroy (
645 book_currency_data->gain_loss_account_del_button);
646 book_currency_data->gain_loss_account_del_button = NULL;
647 }
648 if (book_currency_data->default_gain_loss_account_text)
649 {
650 gtk_widget_destroy (
651 book_currency_data->default_gain_loss_account_text);
652 book_currency_data->default_gain_loss_account_text = NULL;
653 }
654 if (gnc_is_new_book ())
655 {
656 book_currency_data->default_gain_loss_account_text =
657 gtk_label_new ( _("Because no accounts have " \
658 "been set up yet, you will need to return to this " \
659 "dialog (via File->Properties), after account setup, " \
660 "if you want to set a default gain/loss account.") );
661
662 gtk_label_set_line_wrap (GTK_LABEL(book_currency_data->default_gain_loss_account_text), TRUE);
663
664 gtk_grid_attach (GTK_GRID(book_currency_data->gain_loss_account_table),
665 book_currency_data->default_gain_loss_account_text, 0, 1, 2, 1);
666 }
667 else
668 {
669 GtkTreeSelection *selection = NULL;
670 book_currency_data->default_gain_loss_account_widget =
671 GTK_WIDGET(gnc_tree_view_account_new (FALSE));
672 gain_loss_accounts_in_filter = 0;
673 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(
674 book_currency_data->default_gain_loss_account_widget));
675 if (!commodity) // that means not book currency
676 {
677 /* set the default_gain_loss_account_widget to be blank with a
678 no-acct filter */
679 gnc_tree_view_account_set_filter (GNC_TREE_VIEW_ACCOUNT(
680 book_currency_data->default_gain_loss_account_widget),
681 gnc_gain_loss_account_all_fail_filter,
682 NULL, /* user data */
683 NULL /* destroy callback */ );
684 gtk_tree_selection_unselect_all (selection);
685 }
686 else // that means book currency
687 {
688 /* see if there are any accounts after filter */
689 gnc_tree_view_account_set_filter (GNC_TREE_VIEW_ACCOUNT(
690 book_currency_data->default_gain_loss_account_widget),
691 gnc_gain_loss_account_view_filter,
692 NULL, /* user data */
693 NULL /* destroy callback */);
694 if (gain_loss_accounts_in_filter > 0)
695 { /* there are accounts; find out if one is selected */
696 Account *gain_loss_account = NULL;
697 Account *selected_account = NULL;
698 GtkTreeViewColumn *col;
699
700 book_currency_data->gain_loss_account_del_button =
701 gtk_button_new_with_label ( _("Select no account") );
702
703 g_signal_connect (GTK_BUTTON(
704 book_currency_data->gain_loss_account_del_button),
705 "clicked",
706 G_CALLBACK(
707 gnc_option_changed_gain_loss_account_del_button_widget_cb),
708 NULL);
709 gtk_grid_attach (GTK_GRID(book_currency_data->gain_loss_account_table),
710 book_currency_data->gain_loss_account_del_button, 1, 0, 1, 1);
711
712 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(
713 book_currency_data->default_gain_loss_account_widget),
714 TRUE);
715 col = gnc_tree_view_add_text_column (GNC_TREE_VIEW(
716 book_currency_data->default_gain_loss_account_widget),
717 _("Currency"), /* title */
718 "commodity", /* pref name */
719 NULL,
720 "Currency--", /* sizing text */
721 GNC_TREE_MODEL_ACCOUNT_COL_COMMODITY,
722 GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
723 NULL);
724 g_object_set_data (G_OBJECT(col), DEFAULT_VISIBLE,
725 GINT_TO_POINTER(1));
726
727 // add the color background data function to the column
728 gnc_tree_view_account_column_add_color (GNC_TREE_VIEW_ACCOUNT(
729 book_currency_data->default_gain_loss_account_widget), col);
730
731 col = gnc_tree_view_add_toggle_column (GNC_TREE_VIEW(
732 book_currency_data->default_gain_loss_account_widget),
733 _("Placeholder"),
734 C_("Column header for 'Placeholder'", "P"),
735 "placeholder",
736 GNC_TREE_MODEL_ACCOUNT_COL_PLACEHOLDER,
737 GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
738 NULL,
739 NULL);
740 g_object_set_data (G_OBJECT(col), DEFAULT_VISIBLE,
741 GINT_TO_POINTER(1));
742
743 // add the color background data function to the column
744 gnc_tree_view_account_column_add_color (GNC_TREE_VIEW_ACCOUNT(
745 book_currency_data->default_gain_loss_account_widget), col);
746
747 gnc_tree_view_configure_columns (GNC_TREE_VIEW(
748 book_currency_data->default_gain_loss_account_widget));
749 gnc_tree_view_set_show_column_menu (GNC_TREE_VIEW(
750 book_currency_data->default_gain_loss_account_widget),
751 FALSE);
752 if (book_currency_data->retrieved_gain_loss_acct_guid_scm &&
753 (scm_is_string (
754 book_currency_data->retrieved_gain_loss_acct_guid_scm)))
755 {
756 GncGUID *guid= g_new (GncGUID, 1);
757
758 if (string_to_guid (
759 gnc_scm_to_utf8_string (
760 book_currency_data->retrieved_gain_loss_acct_guid_scm),
761 guid))
762 gain_loss_account =
763 xaccAccountLookup (guid, gnc_get_current_book ());
764 g_free (guid);
765 }
766 if (gain_loss_account)
767 {
768 (gnc_tree_view_account_set_selected_account
769 (GNC_TREE_VIEW_ACCOUNT(
770 book_currency_data->default_gain_loss_account_widget),
771 gain_loss_account));
772 selected_account =
773 gnc_tree_view_account_get_selected_account (
774 GNC_TREE_VIEW_ACCOUNT(
775 book_currency_data->default_gain_loss_account_widget));
776 }
777 if (selected_account)
778 {
779 book_currency_data->prior_gain_loss_account =
780 selected_account;
781 gtk_widget_set_sensitive (
782 book_currency_data->gain_loss_account_del_button,
783 TRUE);
784 }
785 else /* none selected */
786 {
787 gtk_tree_selection_unselect_all (selection);
788 gtk_widget_set_sensitive (
789 book_currency_data->gain_loss_account_del_button,
790 FALSE);
791 }
792 }
793 else /* no accts in widget?; replace widget with text */
794 {
795 gtk_widget_destroy (
796 book_currency_data->default_gain_loss_account_widget);
797 book_currency_data->default_gain_loss_account_widget = NULL;
798 book_currency_data->prior_gain_loss_account = NULL;
799 gain_loss_accounts_in_filter = 0;
800 book_currency_data->default_gain_loss_account_text =
801 gtk_label_new ( _("There are no income " \
802 "or expense accounts of the specified\n" \
803 "book currency; you will have to return to this " \
804 "dialog\n(via File->Properties), after account setup, " \
805 "to select a\ndefault gain/loss account.") );
806 gtk_grid_attach (GTK_GRID(book_currency_data->gain_loss_account_table),
807 book_currency_data->default_gain_loss_account_text, 0, 1, 2, 1);
808 }
809 }
810 if (book_currency_data->default_gain_loss_account_widget)
811 {
812 gtk_widget_set_hexpand (GTK_WIDGET(book_currency_data->default_gain_loss_account_widget), TRUE);
813 g_signal_connect (G_OBJECT(selection),
814 "changed",
815 G_CALLBACK(gnc_option_changed_gain_loss_account_widget_cb),
816 NULL);
817 gtk_grid_attach (GTK_GRID(book_currency_data->gain_loss_account_table),
818 book_currency_data->default_gain_loss_account_widget, 0, 1, 2, 1);
819 }
820 }
821 }
822
823 void
gnc_option_changed_book_currency_widget_cb(GtkWidget * widget)824 gnc_option_changed_book_currency_widget_cb (GtkWidget *widget)
825 {
826 /* Once the book currency widget is set, need to set the
827 default_gain_loss_account_widget and/or del-button or text*/
828 if (gtk_combo_box_get_active (GTK_COMBO_BOX(book_currency_data->book_currency_widget)) != -1)
829 {
830 gnc_commodity *commodity = gnc_currency_edit_get_currency (
831 GNC_CURRENCY_EDIT(
832 book_currency_data->book_currency_widget));
833
834 gnc_set_default_gain_loss_account_widget (commodity);
835 }
836 gtk_widget_show_all (book_currency_data->book_currency_vbox);
837 gnc_option_changed_widget_cb (widget, book_currency_data->option);
838 }
839
840 void
gnc_option_changed_gain_loss_account_widget_cb(GtkTreeSelection * selection,gpointer data)841 gnc_option_changed_gain_loss_account_widget_cb (GtkTreeSelection *selection,
842 gpointer data)
843 {
844 Account *account = NULL;
845 gboolean new_eq_prior_acct = FALSE;
846
847 g_return_if_fail (book_currency_data->default_gain_loss_account_widget);
848 account = gnc_tree_view_account_get_selected_account (
849 GNC_TREE_VIEW_ACCOUNT(
850 book_currency_data->default_gain_loss_account_widget));
851 if (account && book_currency_data->prior_gain_loss_account)
852 new_eq_prior_acct = xaccAccountEqual (account,
853 book_currency_data->prior_gain_loss_account,
854 TRUE);
855 if (account && (!new_eq_prior_acct))
856 { /* a new account has been selected */
857 if (!xaccAccountGetPlaceholder (account))
858 {
859 GtkWidget *option_widget =
860 gnc_option_get_gtk_widget (book_currency_data->option);
861 book_currency_data->prior_gain_loss_account = account;
862 gtk_widget_set_sensitive (
863 book_currency_data->gain_loss_account_del_button, TRUE);
864 gtk_widget_show_all (book_currency_data->book_currency_vbox);
865 gnc_option_changed_option_cb (option_widget, book_currency_data->option);
866 }
867 else /* new account, but placeholder */
868 {
869 const char *message = _("The account %s is a placeholder account " \
870 "and does not allow transactions. " \
871 "Please choose a different account.");
872
873 gnc_error_dialog (gnc_ui_get_gtk_window (book_currency_data->default_gain_loss_account_widget),
874 message, xaccAccountGetName (account));
875 if (book_currency_data->prior_gain_loss_account)
876 {
877 (gnc_tree_view_account_set_selected_account
878 (GNC_TREE_VIEW_ACCOUNT(
879 book_currency_data->default_gain_loss_account_widget),
880 book_currency_data->prior_gain_loss_account));
881 }
882 else
883 {
884 gtk_tree_selection_unselect_all (selection);
885 }
886 }
887 }
888 else /* a new account has not been selected */
889 {
890 if (book_currency_data->prior_gain_loss_account == NULL)
891 {
892 gtk_tree_selection_unselect_all (selection);
893 if (book_currency_data->gain_loss_account_del_button)
894 {
895 gtk_widget_set_sensitive (
896 book_currency_data->gain_loss_account_del_button, FALSE);
897 }
898 }
899 }
900 }
901
902 void
gnc_option_changed_gain_loss_account_del_button_widget_cb(GtkButton * button,gpointer data)903 gnc_option_changed_gain_loss_account_del_button_widget_cb (GtkButton *button,
904 gpointer data)
905 {
906 GtkTreeSelection *selection = NULL;
907 GtkWidget *option_widget =
908 gnc_option_get_gtk_widget (book_currency_data->option);
909
910 g_return_if_fail (book_currency_data->default_gain_loss_account_widget);
911 g_return_if_fail (book_currency_data->gain_loss_account_del_button);
912
913 selection = gtk_tree_view_get_selection (
914 GTK_TREE_VIEW(
915 book_currency_data->default_gain_loss_account_widget));
916 gtk_tree_selection_unselect_all (selection);
917 book_currency_data->prior_gain_loss_account = NULL;
918 gtk_widget_set_sensitive (
919 book_currency_data->gain_loss_account_del_button, FALSE);
920 gnc_option_changed_option_cb (option_widget, book_currency_data->option);
921 }
922
923 static void
gnc_option_currency_accounting_non_book_cb(GtkWidget * widget,gpointer data)924 gnc_option_currency_accounting_non_book_cb (GtkWidget *widget, gpointer data)
925 {
926 gnc_currency_edit_clear_display (GNC_CURRENCY_EDIT(
927 book_currency_data->book_currency_widget));
928 gtk_combo_box_set_active (GTK_COMBO_BOX(
929 book_currency_data->default_cost_policy_widget),
930 -1);
931 gnc_set_default_gain_loss_account_widget (NULL);
932 gtk_widget_show_all (book_currency_data->book_currency_vbox);
933 gtk_widget_set_sensitive (book_currency_data->book_currency_vbox, FALSE);
934 gnc_option_radiobutton_cb (widget, (gpointer) book_currency_data->option);
935 }
936
937 static void
gnc_option_currency_accounting_book_cb(GtkWidget * widget,gpointer data)938 gnc_option_currency_accounting_book_cb (GtkWidget *widget, gpointer data)
939 {
940 SCM list_symbol =
941 gnc_currency_accounting_option_get_default_policy (
942 book_currency_data->option);
943 SCM curr_scm = gnc_currency_accounting_option_get_default_currency (
944 book_currency_data->option);
945 gnc_commodity *commodity = gnc_scm_to_commodity (curr_scm);
946
947 if (book_currency_data->retrieved_book_currency)
948 {
949 gnc_currency_edit_set_currency
950 (GNC_CURRENCY_EDIT(book_currency_data->book_currency_widget),
951 book_currency_data->retrieved_book_currency);
952 }
953 else if (commodity)
954 {
955 gnc_currency_edit_set_currency
956 (GNC_CURRENCY_EDIT(book_currency_data->book_currency_widget),
957 commodity);
958 }
959 else
960 {
961 gnc_currency_edit_set_currency
962 (GNC_CURRENCY_EDIT(book_currency_data->book_currency_widget),
963 gnc_default_currency());
964 }
965 if (book_currency_data->retrieved_policy_scm)
966 {
967 gnc_set_default_cost_policy_widget (
968 book_currency_data->retrieved_policy_scm);
969 }
970 else
971 {
972 gnc_set_default_cost_policy_widget (list_symbol);
973 }
974 gtk_widget_show_all (book_currency_data->book_currency_vbox);
975 gtk_widget_set_sensitive (book_currency_data->book_currency_vbox, TRUE);
976 gnc_option_radiobutton_cb (widget, (gpointer) book_currency_data->option);
977 }
978
979 static GtkWidget *
gnc_option_create_date_widget(GNCOption * option)980 gnc_option_create_date_widget (GNCOption *option)
981 {
982 GtkWidget * box = NULL;
983 GtkWidget *rel_button = NULL, *ab_button = NULL;
984 GtkWidget *rel_widget = NULL, *ab_widget = NULL;
985 GtkWidget *entry;
986 gboolean show_time, use24;
987 char *type;
988 int num_values;
989
990 type = gnc_option_date_option_get_subtype (option);
991 show_time = gnc_option_show_time (option);
992 use24 = gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_CLOCK_24H);
993
994 if (g_strcmp0 (type, "relative") != 0)
995 {
996 ab_widget = gnc_date_edit_new (time (NULL), show_time, use24);
997 entry = GNC_DATE_EDIT(ab_widget)->date_entry;
998 g_signal_connect (G_OBJECT(entry), "changed",
999 G_CALLBACK(gnc_option_changed_option_cb), option);
1000 if (show_time)
1001 {
1002 entry = GNC_DATE_EDIT(ab_widget)->time_entry;
1003 g_signal_connect (G_OBJECT(entry), "changed",
1004 G_CALLBACK(gnc_option_changed_option_cb), option);
1005 }
1006 }
1007
1008 if (g_strcmp0 (type, "absolute") != 0)
1009 {
1010 int i;
1011 num_values = gnc_option_num_permissible_values (option);
1012
1013 g_return_val_if_fail (num_values >= 0, NULL);
1014
1015 {
1016 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1017 GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
1018 GtkTreeIter iter;
1019 char *itemstring;
1020
1021 /* Add values to the list store */
1022 for (i = 0; i < num_values; i++)
1023 {
1024 itemstring = gnc_option_permissible_value_name (option, i);
1025 gtk_list_store_append (store, &iter);
1026 gtk_list_store_set (store, &iter, 0, itemstring, -1);
1027 if (itemstring)
1028 g_free (itemstring);
1029 }
1030 /* Create the new Combo and add the store */
1031 rel_widget = GTK_WIDGET(gtk_combo_box_new_with_model (GTK_TREE_MODEL(store)));
1032
1033 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(rel_widget), renderer, TRUE);
1034 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(rel_widget),
1035 renderer, "text", 0);
1036 g_object_unref (store);
1037
1038 g_signal_connect (G_OBJECT(rel_widget), "changed",
1039 G_CALLBACK(gnc_option_multichoice_cb), option);
1040 }
1041 }
1042
1043 if (g_strcmp0 (type, "absolute") == 0)
1044 {
1045 free (type);
1046 gnc_option_set_widget (option, ab_widget);
1047 return ab_widget;
1048 }
1049 else if (g_strcmp0 (type, "relative") == 0)
1050 {
1051 gnc_option_set_widget (option, rel_widget);
1052 free (type);
1053
1054 return rel_widget;
1055 }
1056 else if (g_strcmp0 (type, "both") == 0)
1057 {
1058 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
1059 gtk_box_set_homogeneous (GTK_BOX(box), FALSE);
1060
1061 ab_button = gtk_radio_button_new (NULL);
1062 g_signal_connect (G_OBJECT(ab_button), "toggled",
1063 G_CALLBACK(gnc_rd_option_ab_set_cb), option);
1064
1065 rel_button = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON(ab_button));
1066 g_signal_connect (G_OBJECT(rel_button), "toggled",
1067 G_CALLBACK(gnc_rd_option_rel_set_cb), option);
1068
1069 gtk_box_pack_start (GTK_BOX(box), ab_button, FALSE, FALSE, 0);
1070 gtk_box_pack_start (GTK_BOX(box), ab_widget, FALSE, FALSE, 0);
1071 gtk_box_pack_start (GTK_BOX(box), rel_button, FALSE, FALSE, 0);
1072 gtk_box_pack_start (GTK_BOX(box), rel_widget, FALSE, FALSE, 0);
1073
1074 free (type);
1075
1076 gnc_option_set_widget (option, box);
1077
1078 return box;
1079 }
1080 else /* can't happen */
1081 return NULL;
1082 }
1083
1084 static GtkWidget *
gnc_option_create_budget_widget(GNCOption * option)1085 gnc_option_create_budget_widget (GNCOption *option)
1086 {
1087 GtkTreeModel *tm;
1088 GtkComboBox *cb;
1089 GtkCellRenderer *cr;
1090
1091 tm = gnc_tree_model_budget_new (gnc_get_current_book());
1092 cb = GTK_COMBO_BOX(gtk_combo_box_new_with_model (tm));
1093 g_object_unref (tm);
1094 cr = gtk_cell_renderer_text_new ();
1095 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(cb), cr, TRUE);
1096
1097 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(cb), cr, "text",
1098 BUDGET_NAME_COLUMN, NULL);
1099 return GTK_WIDGET(cb);
1100 }
1101
1102 static GtkWidget *
gnc_option_create_multichoice_widget(GNCOption * option)1103 gnc_option_create_multichoice_widget (GNCOption *option)
1104 {
1105 GtkWidget *widget;
1106 int num_values;
1107 int i;
1108
1109 num_values = gnc_option_num_permissible_values (option);
1110
1111 g_return_val_if_fail (num_values >= 0, NULL);
1112
1113 {
1114 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1115 GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
1116 GtkTreeIter iter;
1117 char *itemstring;
1118
1119 /* Add values to the list store */
1120 for (i = 0; i < num_values; i++)
1121 {
1122 itemstring = gnc_option_permissible_value_name (option, i);
1123
1124 gtk_list_store_append (store, &iter);
1125 gtk_list_store_set (store, &iter, 0,
1126 (itemstring && *itemstring) ? _(itemstring) : "", -1);
1127
1128 if (itemstring)
1129 g_free (itemstring);
1130 }
1131 /* Create the new Combo and add the store */
1132 widget = GTK_WIDGET(gtk_combo_box_new_with_model (GTK_TREE_MODEL(store)));
1133
1134 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(widget), renderer, TRUE);
1135 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(widget),
1136 renderer, "text", 0);
1137 g_object_unref (store);
1138
1139 g_signal_connect (G_OBJECT(widget), "changed",
1140 G_CALLBACK(gnc_option_multichoice_cb), option);
1141 }
1142 return widget;
1143 }
1144
1145 static GtkWidget *
gnc_option_create_radiobutton_widget(char * name,GNCOption * option)1146 gnc_option_create_radiobutton_widget (char *name, GNCOption *option)
1147 {
1148 GtkWidget *frame, *box;
1149 GtkWidget *widget = NULL;
1150 int num_values;
1151 char *label;
1152 int i;
1153
1154 num_values = gnc_option_num_permissible_values (option);
1155
1156 g_return_val_if_fail (num_values >= 0, NULL);
1157
1158 /* Create our button frame */
1159 frame = gtk_frame_new (name);
1160
1161 /* Create the button box */
1162 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1163 gtk_box_set_homogeneous (GTK_BOX(box), FALSE);
1164 gtk_container_add (GTK_CONTAINER(frame), box);
1165
1166 /* Iterate over the options and create a radio button for each one */
1167 for (i = 0; i < num_values; i++)
1168 {
1169 label = gnc_option_permissible_value_name (option, i);
1170
1171 widget =
1172 gtk_radio_button_new_with_label_from_widget (widget ?
1173 GTK_RADIO_BUTTON(widget) :
1174 NULL,
1175 label && *label ? _(label) : "");
1176 g_object_set_data (G_OBJECT(widget), "gnc_radiobutton_index",
1177 GINT_TO_POINTER (i));
1178
1179 g_signal_connect (G_OBJECT(widget), "toggled",
1180 G_CALLBACK(gnc_option_radiobutton_cb), option);
1181 gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
1182
1183 if (label)
1184 free (label);
1185 }
1186 return frame;
1187 }
1188
1189 static GtkWidget *
gnc_option_create_currency_accounting_widget(char * name,GNCOption * option)1190 gnc_option_create_currency_accounting_widget (char *name, GNCOption *option)
1191 {
1192 GtkWidget *frame = NULL,
1193 *widget = NULL,
1194 *vbox = NULL;
1195 int i;
1196 int num_values = gnc_option_num_permissible_values (option);
1197
1198 g_return_val_if_fail (num_values == 3, NULL);
1199 book_currency_data = g_new0 (currency_accounting_data, 1);
1200 book_currency_data->option = option;
1201
1202 /* Create the button frame */
1203 frame = gtk_frame_new (name);
1204 gtk_widget_set_halign (GTK_WIDGET(frame), GTK_ALIGN_FILL);
1205 gtk_widget_set_hexpand (GTK_WIDGET(frame), TRUE);
1206
1207 /* Create the vertical button box */
1208 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1209 gtk_box_set_homogeneous (GTK_BOX(vbox), FALSE);
1210 gtk_container_add (GTK_CONTAINER(frame), vbox);
1211 gtk_widget_set_halign (GTK_WIDGET(vbox), GTK_ALIGN_FILL);
1212 gtk_widget_set_hexpand (GTK_WIDGET(vbox), TRUE);
1213
1214 gtk_widget_set_margin_end (GTK_WIDGET(vbox), 12);
1215 gtk_widget_set_margin_bottom (GTK_WIDGET(vbox), 12);
1216
1217 /* Iterate over the three options and create a radio button for each one */
1218 for (i = 0; i < num_values; i++)
1219 {
1220 char *label;
1221 char *tip = NULL;
1222 GtkWidget *table = NULL;
1223
1224 label = gnc_option_permissible_value_name (option, i);
1225
1226 widget =
1227 gtk_radio_button_new_with_label_from_widget (widget ?
1228 GTK_RADIO_BUTTON(widget) :
1229 NULL,
1230 label && *label ? _(label) : "");
1231 g_object_set_data (G_OBJECT(widget), "gnc_radiobutton_index",
1232 GINT_TO_POINTER(i));
1233 switch (i)
1234 {
1235 case 0:
1236 book_currency_data->gnc_currency_radiobutton_0 = widget;
1237 break;
1238
1239 case 1:
1240 book_currency_data->gnc_currency_radiobutton_1 = widget;
1241 break;
1242
1243 case 2:
1244 book_currency_data->gnc_currency_radiobutton_2 = widget;
1245 break;
1246
1247 default:
1248 break;
1249 }
1250 if (g_strcmp0 (gnc_option_permissible_value_name (option, i),
1251 "Use a Book Currency") == 0)
1252 {
1253 GtkWidget *widget_label,
1254 *policy_table = gtk_grid_new ();
1255
1256 book_currency_data->book_currency_widget = gnc_currency_edit_new ();
1257 book_currency_data->default_cost_policy_widget =
1258 gnc_cost_policy_select_new ();
1259 book_currency_data->default_gain_loss_account_widget = NULL;
1260 book_currency_data->gain_loss_account_del_button = NULL;
1261 book_currency_data->default_gain_loss_account_text = NULL;
1262 book_currency_data->prior_gain_loss_account = NULL;
1263
1264 book_currency_data->book_currency_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1265 gtk_box_set_homogeneous (GTK_BOX(book_currency_data->book_currency_vbox), FALSE);
1266
1267 table = gtk_grid_new ();
1268 gtk_grid_attach (GTK_GRID(table), widget, 0, 0, 2, 1);
1269 g_signal_connect (G_OBJECT(widget), "toggled",
1270 G_CALLBACK(gnc_option_currency_accounting_book_cb),
1271 book_currency_data);
1272
1273 book_currency_data->book_currency_table = gtk_grid_new ();
1274 gtk_grid_set_row_spacing (GTK_GRID(book_currency_data->book_currency_table), 6);
1275 gtk_grid_set_column_spacing (GTK_GRID(book_currency_data->book_currency_table), 6);
1276
1277 tip = gnc_currency_accounting_option_currency_documentation (option);
1278 widget_label = gtk_label_new ( _("Book currency") );
1279 gtk_widget_set_tooltip_text (book_currency_data->book_currency_table,
1280 tip && *tip ? _(tip) : "");
1281
1282 gtk_widget_set_halign (GTK_WIDGET(widget_label), GTK_ALIGN_START);
1283 gtk_widget_set_hexpand (GTK_WIDGET(widget_label), TRUE);
1284
1285 gtk_grid_attach (GTK_GRID(book_currency_data->book_currency_table), widget_label, 0, 0, 1, 1);
1286
1287 g_signal_connect (G_OBJECT(book_currency_data->book_currency_widget),
1288 "changed",
1289 G_CALLBACK(gnc_option_changed_book_currency_widget_cb),
1290 NULL);
1291
1292 gtk_grid_attach (GTK_GRID(book_currency_data->book_currency_table),
1293 book_currency_data->book_currency_widget, 1, 0, 1, 1);
1294
1295 gtk_box_pack_start (GTK_BOX(book_currency_data->book_currency_vbox),
1296 book_currency_data->book_currency_table,
1297 TRUE, TRUE, 0);
1298 gtk_widget_set_margin_start (GTK_WIDGET(book_currency_data->book_currency_table), 12);
1299 gtk_grid_set_row_spacing (GTK_GRID(policy_table), 6);
1300 gtk_grid_set_column_spacing (GTK_GRID(policy_table), 6);
1301
1302 tip = gnc_currency_accounting_option_policy_documentation (option);
1303 widget_label = gtk_label_new ( _("Default lot tracking policy") );
1304 gtk_widget_set_tooltip_text (policy_table, tip && *tip ? _(tip) : "");
1305
1306 gtk_widget_set_halign (GTK_WIDGET(widget_label), GTK_ALIGN_START);
1307 gtk_widget_set_hexpand (GTK_WIDGET(widget_label), TRUE);
1308
1309 gtk_grid_attach (GTK_GRID(policy_table), widget_label, 0, 1, 1, 1);
1310
1311 g_signal_connect (G_OBJECT(book_currency_data->default_cost_policy_widget),
1312 "changed",
1313 G_CALLBACK(gnc_option_multichoice_cb), option);
1314
1315 gtk_grid_attach (GTK_GRID(policy_table),
1316 book_currency_data->default_cost_policy_widget, 1, 1, 1, 1);
1317
1318 gtk_box_pack_start (GTK_BOX(book_currency_data->book_currency_vbox),
1319 policy_table, TRUE, TRUE, 0);
1320 gtk_widget_set_margin_start (GTK_WIDGET(policy_table), 12);
1321 book_currency_data->gain_loss_account_table = gtk_grid_new ();
1322 gtk_grid_set_row_spacing (GTK_GRID(book_currency_data->gain_loss_account_table), 6);
1323 gtk_grid_set_column_spacing (GTK_GRID(book_currency_data->gain_loss_account_table), 6);
1324
1325 tip = gnc_currency_accounting_option_gain_loss_account_documentation (option);
1326 widget_label = gtk_label_new ( _("Default gain/loss account") );
1327 gnc_label_set_alignment (GTK_WIDGET(widget_label), 0.0, 0.5);
1328
1329 gtk_widget_set_tooltip_text (book_currency_data->gain_loss_account_table,
1330 tip && *tip ? _(tip) : "");
1331
1332 gtk_grid_attach (GTK_GRID(book_currency_data->gain_loss_account_table),
1333 widget_label, 0, 0, 1, 1);
1334
1335 widget_label = NULL;
1336 gtk_box_pack_start (GTK_BOX (book_currency_data->book_currency_vbox),
1337 book_currency_data->gain_loss_account_table,
1338 TRUE, TRUE, 0);
1339 gtk_widget_set_margin_start (GTK_WIDGET(book_currency_data->gain_loss_account_table), 12);
1340 gtk_grid_attach (GTK_GRID(table), book_currency_data->book_currency_vbox, 1, 2, 1, 1);
1341 }
1342 else /* trading or neither */
1343 {
1344 table = gtk_grid_new ();
1345 gtk_grid_attach (GTK_GRID(table), widget, 0, 1, 1, 1);
1346
1347 g_signal_connect (G_OBJECT(widget), "toggled",
1348 G_CALLBACK(gnc_option_currency_accounting_non_book_cb),
1349 book_currency_data);
1350 }
1351 gtk_box_pack_start (GTK_BOX(vbox), table, TRUE, TRUE, 0);
1352
1353 if (label)
1354 free (label);
1355 if (tip)
1356 free (tip);
1357 }
1358 return frame;
1359 }
1360
1361 static void
gnc_option_account_cb(GtkTreeSelection * selection,gpointer data)1362 gnc_option_account_cb (GtkTreeSelection *selection, gpointer data)
1363 {
1364 GNCOption *option = data;
1365 GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
1366 gnc_option_changed_widget_cb (GTK_WIDGET(tree_view), option);
1367 }
1368
1369 static void
gnc_option_account_select_all_cb(GtkWidget * widget,gpointer data)1370 gnc_option_account_select_all_cb (GtkWidget *widget, gpointer data)
1371 {
1372 GNCOption *option = data;
1373 GncTreeViewAccount *tree_view;
1374 GtkTreeSelection *selection;
1375
1376 tree_view = GNC_TREE_VIEW_ACCOUNT(gnc_option_get_gtk_widget (option));
1377 gtk_tree_view_expand_all (GTK_TREE_VIEW(tree_view));
1378 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree_view));
1379 gtk_tree_selection_select_all (selection);
1380 gnc_option_changed_widget_cb (widget, option);
1381 }
1382
1383 static void
gnc_option_account_clear_all_cb(GtkWidget * widget,gpointer data)1384 gnc_option_account_clear_all_cb (GtkWidget *widget, gpointer data)
1385 {
1386 GNCOption *option = data;
1387 GncTreeViewAccount *tree_view;
1388 GtkTreeSelection *selection;
1389
1390 tree_view = GNC_TREE_VIEW_ACCOUNT(gnc_option_get_gtk_widget (option));
1391 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree_view));
1392 gtk_tree_selection_unselect_all (selection);
1393 gnc_option_changed_widget_cb (widget, option);
1394 }
1395
1396 static void
gnc_option_account_select_children_cb(GtkWidget * widget,gpointer data)1397 gnc_option_account_select_children_cb (GtkWidget *widget, gpointer data)
1398 {
1399 GNCOption *option = data;
1400 GncTreeViewAccount *tree_view;
1401 GList *acct_list = NULL, *acct_iter = NULL;
1402
1403 tree_view = GNC_TREE_VIEW_ACCOUNT(gnc_option_get_gtk_widget (option));
1404 acct_list = gnc_tree_view_account_get_selected_accounts (tree_view);
1405
1406 for (acct_iter = acct_list; acct_iter; acct_iter = acct_iter->next)
1407 gnc_tree_view_account_select_subaccounts (tree_view, acct_iter->data);
1408
1409 g_list_free (acct_list);
1410 }
1411
1412 static GtkWidget *
gnc_option_create_account_widget(GNCOption * option,char * name)1413 gnc_option_create_account_widget (GNCOption *option, char *name)
1414 {
1415 gboolean multiple_selection;
1416 GtkWidget *scroll_win;
1417 GtkWidget *button;
1418 GtkWidget *frame;
1419 GtkWidget *tree;
1420 GtkWidget *vbox;
1421 GtkWidget *bbox;
1422 GList *acct_type_list;
1423 GtkTreeSelection *selection;
1424
1425 multiple_selection = gnc_option_multiple_selection (option);
1426 acct_type_list = gnc_option_get_account_type_list (option);
1427
1428 frame = gtk_frame_new (name);
1429
1430 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1431 gtk_box_set_homogeneous (GTK_BOX(vbox), FALSE);
1432
1433 gtk_container_add (GTK_CONTAINER(frame), vbox);
1434
1435 tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
1436 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(tree), FALSE);
1437 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
1438 if (multiple_selection)
1439 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1440 else
1441 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1442
1443 if (acct_type_list)
1444 {
1445 GList *node;
1446 AccountViewInfo avi;
1447 int i;
1448
1449 gnc_tree_view_account_get_view_info (GNC_TREE_VIEW_ACCOUNT(tree), &avi);
1450
1451 for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
1452 avi.include_type[i] = FALSE;
1453 avi.show_hidden = FALSE;
1454
1455 for (node = acct_type_list; node; node = node->next)
1456 {
1457 GNCAccountType type = GPOINTER_TO_INT(node->data);
1458 avi.include_type[type] = TRUE;
1459 }
1460
1461 gnc_tree_view_account_set_view_info (GNC_TREE_VIEW_ACCOUNT(tree), &avi);
1462 g_list_free (acct_type_list);
1463 }
1464 else
1465 {
1466 AccountViewInfo avi;
1467 int i;
1468
1469 gnc_tree_view_account_get_view_info (GNC_TREE_VIEW_ACCOUNT(tree), &avi);
1470
1471 for (i = 0; i < NUM_ACCOUNT_TYPES; i++)
1472 avi.include_type[i] = TRUE;
1473 avi.show_hidden = FALSE;
1474 gnc_tree_view_account_set_view_info (GNC_TREE_VIEW_ACCOUNT(tree), &avi);
1475 }
1476
1477 scroll_win = gtk_scrolled_window_new (NULL, NULL);
1478 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scroll_win),
1479 GTK_POLICY_AUTOMATIC,
1480 GTK_POLICY_AUTOMATIC);
1481
1482 gtk_box_pack_start (GTK_BOX(vbox), scroll_win, TRUE, TRUE, 0);
1483 gtk_container_set_border_width (GTK_CONTAINER(scroll_win), 5);
1484 gtk_container_add (GTK_CONTAINER(scroll_win), tree);
1485
1486 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1487 gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD);
1488 gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, FALSE, 10);
1489
1490 if (multiple_selection)
1491 {
1492 button = gtk_button_new_with_label (_("Select All"));
1493 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1494 gtk_widget_set_tooltip_text (button, _("Select all accounts."));
1495
1496 g_signal_connect (G_OBJECT(button), "clicked",
1497 G_CALLBACK(gnc_option_account_select_all_cb), option);
1498
1499 button = gtk_button_new_with_label (_("Clear All"));
1500 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1501 gtk_widget_set_tooltip_text (button, _("Clear the selection and unselect all accounts."));
1502
1503 g_signal_connect (G_OBJECT(button), "clicked",
1504 G_CALLBACK(gnc_option_account_clear_all_cb), option);
1505
1506 button = gtk_button_new_with_label (_("Select Children"));
1507 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1508 gtk_widget_set_tooltip_text (button, _("Select all descendents of selected account."));
1509
1510 g_signal_connect (G_OBJECT(button), "clicked",
1511 G_CALLBACK(gnc_option_account_select_children_cb), option);
1512 }
1513
1514 button = gtk_button_new_with_label (_("Select Default"));
1515 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1516 gtk_widget_set_tooltip_text (button, _("Select the default account selection."));
1517
1518 g_signal_connect (G_OBJECT(button), "clicked",
1519 G_CALLBACK(gnc_option_default_cb), option);
1520
1521 gtk_widget_set_margin_start (GTK_WIDGET(bbox), 6);
1522 gtk_widget_set_margin_end (GTK_WIDGET(bbox), 6);
1523
1524 if (multiple_selection)
1525 {
1526 /* Put the "Show hidden" checkbox on a separate line since the 4 buttons make
1527 the dialog too wide. */
1528 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1529 gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
1530 gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1531 }
1532
1533 button = gtk_check_button_new_with_label (_("Show Hidden Accounts"));
1534 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1535 gtk_widget_set_tooltip_text (button, _("Show accounts that have been marked hidden."));
1536 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), FALSE);
1537 g_signal_connect (G_OBJECT(button), "toggled",
1538 G_CALLBACK(gnc_option_show_hidden_toggled_cb), option);
1539
1540 gnc_option_set_widget (option, tree);
1541
1542 return frame;
1543 }
1544
1545 static void
gnc_option_list_changed_cb(GtkTreeSelection * selection,GNCOption * option)1546 gnc_option_list_changed_cb (GtkTreeSelection *selection,
1547 GNCOption *option)
1548 {
1549 GtkTreeView *view = gtk_tree_selection_get_tree_view (selection);
1550 gnc_option_changed_widget_cb (GTK_WIDGET(view), option);
1551 }
1552
1553 static void
gnc_option_list_select_all_cb(GtkWidget * widget,gpointer data)1554 gnc_option_list_select_all_cb (GtkWidget *widget, gpointer data)
1555 {
1556 GNCOption *option = data;
1557 GtkTreeView *view;
1558 GtkTreeSelection *selection;
1559
1560 view = GTK_TREE_VIEW(gnc_option_get_gtk_widget (option));
1561 selection = gtk_tree_view_get_selection (view);
1562 gtk_tree_selection_select_all (selection);
1563 gnc_option_changed_widget_cb (GTK_WIDGET(view), option);
1564 }
1565
1566 static void
gnc_option_list_clear_all_cb(GtkWidget * widget,gpointer data)1567 gnc_option_list_clear_all_cb (GtkWidget *widget, gpointer data)
1568 {
1569 GNCOption *option = data;
1570 GtkTreeView *view;
1571 GtkTreeSelection *selection;
1572
1573 view = GTK_TREE_VIEW(gnc_option_get_gtk_widget (option));
1574 selection = gtk_tree_view_get_selection (view);
1575 gtk_tree_selection_unselect_all (selection);
1576 gnc_option_changed_widget_cb (GTK_WIDGET(view), option);
1577 }
1578
1579 static GtkWidget *
gnc_option_create_list_widget(GNCOption * option,char * name)1580 gnc_option_create_list_widget (GNCOption *option, char *name)
1581 {
1582 GtkListStore *store;
1583 GtkTreeView *view;
1584 GtkTreeIter iter;
1585 GtkTreeViewColumn *column;
1586 GtkCellRenderer *renderer;
1587 GtkTreeSelection *selection;
1588
1589 GtkWidget *button;
1590 GtkWidget *frame;
1591 GtkWidget *hbox;
1592 GtkWidget *bbox;
1593 gint num_values;
1594 gint i;
1595
1596 frame = gtk_frame_new (name);
1597 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1598 gtk_box_set_homogeneous (GTK_BOX(hbox), FALSE);
1599 gtk_container_add (GTK_CONTAINER(frame), hbox);
1600
1601 store = gtk_list_store_new (1, G_TYPE_STRING);
1602 view = GTK_TREE_VIEW(gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)));
1603 g_object_unref (store);
1604 renderer = gtk_cell_renderer_text_new ();
1605 column = gtk_tree_view_column_new_with_attributes ("", renderer,
1606 "text", 0,
1607 NULL);
1608 gtk_tree_view_append_column (view, column);
1609 gtk_tree_view_set_headers_visible (view, FALSE);
1610
1611 num_values = gnc_option_num_permissible_values (option);
1612 for (i = 0; i < num_values; i++)
1613 {
1614 gchar *raw_string, *string;
1615
1616 raw_string = gnc_option_permissible_value_name (option, i);
1617 string = (raw_string && *raw_string) ? _(raw_string) : "";
1618 gtk_list_store_append (store, &iter);
1619 gtk_list_store_set (store, &iter,
1620 0, string ? string : "",
1621 -1);
1622 g_free (raw_string);
1623 }
1624
1625 gtk_box_pack_start (GTK_BOX(hbox), GTK_WIDGET(view), FALSE, FALSE, 0);
1626
1627 selection = gtk_tree_view_get_selection (view);
1628 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1629 g_signal_connect (selection, "changed",
1630 G_CALLBACK(gnc_option_list_changed_cb), option);
1631
1632 bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
1633 gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD);
1634 gtk_box_pack_end (GTK_BOX(hbox), bbox, FALSE, FALSE, 0);
1635
1636 button = gtk_button_new_with_label (_("Select All"));
1637 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1638 gtk_widget_set_tooltip_text (button, _("Select all entries."));
1639
1640 g_signal_connect (G_OBJECT(button), "clicked",
1641 G_CALLBACK(gnc_option_list_select_all_cb), option);
1642
1643 button = gtk_button_new_with_label (_("Clear All"));
1644 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1645 gtk_widget_set_tooltip_text (button, _("Clear the selection and unselect all entries."));
1646
1647 g_signal_connect (G_OBJECT(button), "clicked",
1648 G_CALLBACK(gnc_option_list_clear_all_cb), option);
1649
1650 button = gtk_button_new_with_label (_("Select Default"));
1651 gtk_box_pack_start (GTK_BOX(bbox), button, FALSE, FALSE, 0);
1652 gtk_widget_set_tooltip_text (button, _("Select the default selection."));
1653
1654 g_signal_connect (G_OBJECT(button), "clicked",
1655 G_CALLBACK(gnc_option_default_cb), option);
1656
1657 g_object_set (G_OBJECT(hbox), "margin", 3, NULL);
1658
1659 gnc_option_set_widget (option, GTK_WIDGET(view));
1660
1661 return frame;
1662 }
1663
1664 static void
gnc_option_color_changed_cb(GtkColorButton * color_button,GNCOption * option)1665 gnc_option_color_changed_cb (GtkColorButton *color_button, GNCOption *option)
1666 {
1667 gnc_option_changed_widget_cb (GTK_WIDGET(color_button), option);
1668 }
1669
1670 static void
gnc_option_font_changed_cb(GtkFontButton * font_button,GNCOption * option)1671 gnc_option_font_changed_cb (GtkFontButton *font_button, GNCOption *option)
1672 {
1673 gnc_option_changed_widget_cb (GTK_WIDGET(font_button), option);
1674 }
1675
1676 static void
gnc_option_set_ui_widget(GNCOption * option,GtkGrid * page_box,gint grid_row)1677 gnc_option_set_ui_widget (GNCOption *option, GtkGrid *page_box, gint grid_row)
1678 {
1679 GtkWidget *enclosing = NULL;
1680 GtkWidget *value = NULL;
1681 gboolean packed = FALSE;
1682 char *raw_name, *raw_documentation;
1683 char *name, *documentation;
1684 char *type;
1685 GNCOptionDef_t *option_def;
1686 GtkLabel *name_label;
1687
1688 ENTER("option %p(%s), box %p",
1689 option, gnc_option_name (option), page_box);
1690 type = gnc_option_type (option);
1691 if (type == NULL)
1692 {
1693 LEAVE("bad type");
1694 return;
1695 }
1696 else if (g_strcmp0 (type, "internal") == 0)
1697 {
1698 LEAVE("internal type");
1699 return;
1700 }
1701
1702 raw_name = gnc_option_name (option);
1703 if (raw_name && *raw_name)
1704 name = _(raw_name);
1705 else
1706 name = NULL;
1707
1708 raw_documentation = gnc_option_documentation (option);
1709 if (raw_documentation && *raw_documentation)
1710 documentation = _(raw_documentation);
1711 else
1712 documentation = NULL;
1713
1714 name_label = GTK_LABEL(gtk_label_new (name));
1715
1716 option_def = gnc_options_ui_get_option (type);
1717 if (option_def && option_def->set_widget)
1718 {
1719 value = option_def->set_widget (option, page_box,
1720 name_label, documentation,
1721 /* Return values */
1722 &enclosing, &packed);
1723 }
1724 else
1725 {
1726 PERR("Unknown option type. Ignoring option \"%s\".\n", name);
1727 }
1728
1729 /* attach the name label to the first column of the grid and align to the end
1730 * if option is a check button, do not add a label as we are using the built
1731 * in one */
1732 if (!GTK_IS_CHECK_BUTTON(value))
1733 gtk_grid_attach (GTK_GRID(page_box), GTK_WIDGET(name_label),
1734 0, grid_row, // left, top
1735 1, 1); // width, height
1736
1737 gtk_widget_set_halign (GTK_WIDGET(name_label), GTK_ALIGN_END);
1738
1739 if (!packed && (enclosing != NULL))
1740 {
1741 /* Pack option widget into an extra eventbox because otherwise the
1742 "documentation" tooltip is not displayed. */
1743 GtkWidget *eventbox = gtk_event_box_new ();
1744
1745 gtk_container_add (GTK_CONTAINER(eventbox), enclosing);
1746
1747 /* attach the option widget to the second column of the grid */
1748 gtk_grid_attach (GTK_GRID(page_box), eventbox,
1749 1, grid_row, // left, top
1750 1, 1); // width, height
1751
1752 gtk_widget_set_tooltip_text (eventbox, documentation);
1753 }
1754
1755 if (value != NULL)
1756 gtk_widget_set_tooltip_text (value, documentation);
1757
1758 if (raw_name != NULL)
1759 free (raw_name);
1760 if (raw_documentation != NULL)
1761 free (raw_documentation);
1762 free (type);
1763 LEAVE(" ");
1764 }
1765
1766 static void
gnc_options_dialog_add_option(GtkWidget * page,GNCOption * option,gint row)1767 gnc_options_dialog_add_option (GtkWidget *page,
1768 GNCOption *option, gint row)
1769 {
1770 g_object_set_data (G_OBJECT(page), "options-grid-row", GINT_TO_POINTER(row));
1771 gnc_option_set_ui_widget (option, GTK_GRID(page), row);
1772 }
1773
1774 static gint
gnc_options_dialog_append_page(GNCOptionWin * propertybox,GNCOptionSection * section)1775 gnc_options_dialog_append_page (GNCOptionWin * propertybox,
1776 GNCOptionSection *section)
1777 {
1778 GNCOption *option;
1779 GtkWidget *page_label;
1780 GtkWidget *options_box;
1781 GtkWidget *page_content_box;
1782 GtkWidget* notebook_page;
1783 GtkWidget *reset_button;
1784 GtkWidget *listitem = NULL;
1785 GtkWidget *buttonbox;
1786 GtkWidget *options_scrolled_win;
1787 GtkTreeView *view;
1788 GtkListStore *list;
1789 GtkTreeIter iter;
1790 gint num_options;
1791 const char *name;
1792 gint i, page_count, name_offset;
1793 gboolean advanced;
1794
1795 name = gnc_option_section_name (section);
1796 if (!name)
1797 return -1;
1798
1799 if (strncmp (name, "__", 2) == 0)
1800 return -1;
1801 advanced = (strncmp (name, "_+", 2) == 0);
1802 name_offset = (advanced) ? 2 : 0;
1803 page_label = gtk_label_new (_(name + name_offset));
1804 PINFO("Page_label is %s", _(name + name_offset));
1805 gtk_widget_show (page_label);
1806
1807 /* Build this options page */
1808 page_content_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
1809 gtk_widget_set_name (page_content_box, "page-content-box");
1810 gtk_box_set_homogeneous (GTK_BOX (page_content_box), FALSE);
1811
1812 gtk_container_set_border_width (GTK_CONTAINER(page_content_box), 12);
1813
1814 options_scrolled_win = gtk_scrolled_window_new (NULL, NULL);
1815 gtk_box_pack_start (GTK_BOX(page_content_box), options_scrolled_win, TRUE, TRUE, 0);
1816
1817 /* Build space for the content - the options box */
1818 options_box = gtk_grid_new (); // this will have two columns
1819 gtk_widget_set_name (options_box, "options-box");
1820 gtk_grid_set_row_homogeneous (GTK_GRID(options_box), FALSE);
1821 gtk_grid_set_column_homogeneous (GTK_GRID(options_box), FALSE);
1822 gtk_grid_set_row_spacing (GTK_GRID(options_box), 6);
1823 gtk_grid_set_column_spacing (GTK_GRID(options_box), 6);
1824
1825 gtk_container_set_border_width (GTK_CONTAINER(options_box), 0);
1826 gtk_container_add (GTK_CONTAINER(options_scrolled_win), GTK_WIDGET(options_box));
1827 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(options_scrolled_win),
1828 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1829
1830 /* Create all the options */
1831 num_options = gnc_option_section_num_options (section);
1832 for (i = 0; i < num_options; i++)
1833 {
1834 option = gnc_get_option_section_option (section, i);
1835 gnc_options_dialog_add_option (options_box, option, i);
1836 }
1837
1838 /* Add a button box at the bottom of the page */
1839 buttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1840 gtk_button_box_set_layout (GTK_BUTTON_BOX (buttonbox),
1841 GTK_BUTTONBOX_EDGE);
1842 gtk_container_set_border_width (GTK_CONTAINER(buttonbox), 5);
1843 gtk_box_pack_end (GTK_BOX(page_content_box), buttonbox, FALSE, FALSE, 0);
1844
1845 /* The reset button on each option page */
1846 reset_button = gtk_button_new_with_label (_("Reset defaults"));
1847 gtk_widget_set_tooltip_text (reset_button,
1848 _("Reset all values to their defaults."));
1849
1850 g_signal_connect (G_OBJECT(reset_button), "clicked",
1851 G_CALLBACK(gnc_options_dialog_reset_cb), propertybox);
1852 g_object_set_data (G_OBJECT(reset_button), "section", section);
1853 gtk_box_pack_end (GTK_BOX(buttonbox), reset_button, FALSE, FALSE, 0);
1854 gtk_widget_show_all (page_content_box);
1855 gtk_notebook_append_page (GTK_NOTEBOOK(propertybox->notebook),
1856 page_content_box, page_label);
1857
1858 /* Switch to selection from a list if the page count threshold is reached */
1859 page_count = gtk_notebook_page_num (GTK_NOTEBOOK(propertybox->notebook),
1860 page_content_box);
1861
1862 if (propertybox->page_list_view)
1863 {
1864 /* Build the matching list item for selecting from large page sets */
1865 view = GTK_TREE_VIEW(propertybox->page_list_view);
1866 list = GTK_LIST_STORE(gtk_tree_view_get_model (view));
1867
1868 PINFO("Page name is %s and page_count is %d", name, page_count);
1869 gtk_list_store_append (list, &iter);
1870 gtk_list_store_set (list, &iter,
1871 PAGE_NAME, _(name),
1872 PAGE_INDEX, page_count,
1873 -1);
1874
1875 if (page_count > MAX_TAB_COUNT - 1) /* Convert 1-based -> 0-based */
1876 {
1877 gtk_widget_show (propertybox->page_list);
1878 gtk_notebook_set_show_tabs (GTK_NOTEBOOK(propertybox->notebook), FALSE);
1879 gtk_notebook_set_show_border (GTK_NOTEBOOK(propertybox->notebook), FALSE);
1880 }
1881 else
1882 gtk_widget_hide (propertybox->page_list);
1883
1884 /* Tweak "advanced" pages for later handling. */
1885 if (advanced)
1886 {
1887 notebook_page = gtk_notebook_get_nth_page (GTK_NOTEBOOK(propertybox->notebook),
1888 page_count);
1889
1890 g_object_set_data (G_OBJECT(notebook_page), "listitem", listitem);
1891 g_object_set_data (G_OBJECT(notebook_page), "advanced",
1892 GINT_TO_POINTER(advanced));
1893 }
1894 }
1895 return (page_count);
1896 }
1897
1898 /********************************************************************\
1899 * gnc_options_dialog_build_contents *
1900 * builds an options dialog given a property box and an options *
1901 * database and make the dialog visible *
1902 * *
1903 * Args: propertybox - gnome property box to use *
1904 * odb - option database to use *
1905 * Return: nothing *
1906 \********************************************************************/
1907 void
gnc_options_dialog_build_contents(GNCOptionWin * propertybox,GNCOptionDB * odb)1908 gnc_options_dialog_build_contents (GNCOptionWin *propertybox,
1909 GNCOptionDB *odb)
1910 {
1911 gnc_options_dialog_build_contents_full (propertybox, odb, TRUE);
1912 }
1913
1914 /********************************************************************\
1915 * gnc_options_dialog_build_contents_full *
1916 * builds an options dialog given a property box and an options *
1917 * database and make the dialog visible depending on the *
1918 * show_dialog flag *
1919 * *
1920 * Args: propertybox - gnome property box to use *
1921 * odb - option database to use *
1922 * show_dialog - should dialog be made visible or not *
1923 * Return: nothing *
1924 \********************************************************************/
1925 void
gnc_options_dialog_build_contents_full(GNCOptionWin * propertybox,GNCOptionDB * odb,gboolean show_dialog)1926 gnc_options_dialog_build_contents_full (GNCOptionWin *propertybox,
1927 GNCOptionDB *odb, gboolean show_dialog)
1928 {
1929 GNCOptionSection *section;
1930 gchar *default_section_name;
1931 gint default_page = -1;
1932 gint num_sections;
1933 gint page;
1934 gint i;
1935 guint j;
1936
1937 g_return_if_fail (propertybox != NULL);
1938 g_return_if_fail (odb != NULL);
1939
1940 gnc_option_db_set_ui_callbacks (odb,
1941 gnc_option_get_ui_value_internal,
1942 gnc_option_set_ui_value_internal,
1943 gnc_option_set_selectable_internal);
1944
1945 propertybox->option_db = odb;
1946
1947 num_sections = gnc_option_db_num_sections (odb);
1948 default_section_name = gnc_option_db_get_default_section (odb);
1949
1950 PINFO("Default Section name is %s", default_section_name);
1951
1952 for (i = 0; i < num_sections; i++)
1953 {
1954 const char *section_name;
1955
1956 section = gnc_option_db_get_section (odb, i);
1957 page = gnc_options_dialog_append_page (propertybox, section);
1958
1959 section_name = gnc_option_section_name (section);
1960 if (g_strcmp0 (section_name, default_section_name) == 0)
1961 default_page = page;
1962 }
1963
1964 if (default_section_name != NULL)
1965 free (default_section_name);
1966
1967 /* call each option widget changed callbacks once at this point,
1968 * now that all options widgets exist.
1969 */
1970 for (i = 0; i < num_sections; i++)
1971 {
1972 section = gnc_option_db_get_section (odb, i);
1973
1974 for (j = 0; j < gnc_option_section_num_options (section); j++)
1975 {
1976 // setting TRUE will clear the changed flag after proc
1977 gnc_option_call_option_widget_changed_proc (
1978 gnc_get_option_section_option(section, j), TRUE);
1979 }
1980 }
1981
1982 gtk_notebook_popup_enable (GTK_NOTEBOOK(propertybox->notebook));
1983 if (default_page >= 0)
1984 {
1985 /* Find the page list and set the selection to the default page */
1986 GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(propertybox->page_list_view));
1987 GtkTreeIter iter;
1988 GtkTreeModel *model;
1989
1990 model = gtk_tree_view_get_model (GTK_TREE_VIEW(propertybox->page_list_view));
1991 gtk_tree_model_iter_nth_child (model, &iter, NULL, default_page);
1992 gtk_tree_selection_select_iter (selection, &iter);
1993 gtk_notebook_set_current_page (GTK_NOTEBOOK(propertybox->notebook), default_page);
1994 }
1995 gnc_options_dialog_changed_internal (propertybox->window, FALSE);
1996 if (show_dialog)
1997 gtk_widget_show (propertybox->window);
1998 }
1999
2000 GtkWidget *
gnc_options_dialog_widget(GNCOptionWin * win)2001 gnc_options_dialog_widget (GNCOptionWin * win)
2002 {
2003 return win->window;
2004 }
2005
2006 GtkWidget *
gnc_options_page_list(GNCOptionWin * win)2007 gnc_options_page_list (GNCOptionWin * win)
2008 {
2009 return win->page_list;
2010 }
2011
2012 GtkWidget *
gnc_options_dialog_notebook(GNCOptionWin * win)2013 gnc_options_dialog_notebook (GNCOptionWin * win)
2014 {
2015 return win->notebook;
2016 }
2017
2018 static void
gnc_options_dialog_help_button_cb(GtkWidget * widget,GNCOptionWin * win)2019 gnc_options_dialog_help_button_cb (GtkWidget * widget, GNCOptionWin *win)
2020 {
2021 if (win->help_cb)
2022 (win->help_cb)(win, win->help_cb_data);
2023 }
2024
2025 static void
gnc_options_dialog_cancel_button_cb(GtkWidget * widget,GNCOptionWin * win)2026 gnc_options_dialog_cancel_button_cb (GtkWidget * widget, GNCOptionWin *win)
2027 {
2028 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(win->window));
2029
2030 if (win->close_cb)
2031 (win->close_cb)(win, win->close_cb_data);
2032 else
2033 gtk_widget_hide (win->window);
2034 }
2035
2036 static void
gnc_options_dialog_apply_button_cb(GtkWidget * widget,GNCOptionWin * win)2037 gnc_options_dialog_apply_button_cb (GtkWidget * widget, GNCOptionWin *win)
2038 {
2039 GNCOptionWinCallback close_cb = win->close_cb;
2040
2041 win->close_cb = NULL;
2042 if (win->apply_cb)
2043 win->apply_cb (win, win->apply_cb_data);
2044 win->close_cb = close_cb;
2045 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(win->window));
2046 gnc_options_dialog_changed_internal (win->window, FALSE);
2047 }
2048
2049 static void
gnc_options_dialog_ok_button_cb(GtkWidget * widget,GNCOptionWin * win)2050 gnc_options_dialog_ok_button_cb (GtkWidget * widget, GNCOptionWin *win)
2051 {
2052 GNCOptionWinCallback close_cb = win->close_cb;
2053
2054 win->close_cb = NULL;
2055 if (win->apply_cb)
2056 win->apply_cb (win, win->apply_cb_data);
2057 win->close_cb = close_cb;
2058
2059 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(win->window));
2060
2061 if (win->close_cb)
2062 (win->close_cb)(win, win->close_cb_data);
2063 else
2064 gtk_widget_hide (win->window);
2065 }
2066
2067 static void
gnc_options_dialog_destroy_cb(GtkWidget * object,GNCOptionWin * win)2068 gnc_options_dialog_destroy_cb (GtkWidget *object, GNCOptionWin *win)
2069 {
2070 if (!win) return;
2071
2072 if (win->destroyed == FALSE)
2073 {
2074 if (win->close_cb)
2075 (win->close_cb)(win, win->close_cb_data);
2076 }
2077 }
2078
2079 static gboolean
gnc_options_dialog_window_key_press_cb(GtkWidget * widget,GdkEventKey * event,gpointer data)2080 gnc_options_dialog_window_key_press_cb (GtkWidget *widget,
2081 GdkEventKey *event,
2082 gpointer data)
2083 {
2084 GNCOptionWin *win = data;
2085
2086 if (event->keyval == GDK_KEY_Escape)
2087 {
2088 component_close_handler (win);
2089 return TRUE;
2090 }
2091 else
2092 return FALSE;
2093 }
2094
2095 static void
gnc_options_dialog_reset_cb(GtkWidget * w,gpointer data)2096 gnc_options_dialog_reset_cb (GtkWidget * w, gpointer data)
2097 {
2098 GNCOptionWin *win = data;
2099 GNCOptionSection *section;
2100 gpointer val;
2101
2102 val = g_object_get_data (G_OBJECT(w), "section");
2103 g_return_if_fail (val);
2104 g_return_if_fail (win);
2105
2106 section = (GNCOptionSection*)val;
2107
2108 gnc_option_db_section_reset_widgets (section);
2109
2110 if (gnc_option_db_get_changed (win->option_db))
2111 gnc_options_dialog_changed_internal (win->window, TRUE);
2112 }
2113
2114 void
gnc_options_dialog_list_select_cb(GtkTreeSelection * selection,gpointer data)2115 gnc_options_dialog_list_select_cb (GtkTreeSelection *selection,
2116 gpointer data)
2117 {
2118 GNCOptionWin * win = data;
2119 GtkTreeModel *list;
2120 GtkTreeIter iter;
2121 gint index = 0;
2122
2123 if (!gtk_tree_selection_get_selected (selection, &list, &iter))
2124 return;
2125 gtk_tree_model_get (list, &iter,
2126 PAGE_INDEX, &index,
2127 -1);
2128 PINFO("Index is %d", index);
2129 gtk_notebook_set_current_page (GTK_NOTEBOOK(win->notebook), index);
2130 }
2131
2132 void
gnc_options_register_stocks(void)2133 gnc_options_register_stocks (void)
2134 {
2135 #if 0
2136 static gboolean done = FALSE;
2137
2138 GtkStockItem items[] =
2139 {
2140 { GTK_STOCK_APPLY , "gnc_option_apply_button", 0, 0, NULL },
2141 { GTK_STOCK_HELP , "gnc_options_dialog_help", 0, 0, NULL },
2142 { GTK_STOCK_OK , "gnc_options_dialog_ok", 0, 0, NULL },
2143 { GTK_STOCK_CANCEL , "gnc_options_dialog_cancel", 0, 0, NULL },
2144 };
2145
2146 if (done)
2147 {
2148 return;
2149 }
2150 done = TRUE;
2151
2152 gtk_stock_add (items, G_N_ELEMENTS (items));
2153 #endif
2154 }
2155
2156 static void
component_close_handler(gpointer data)2157 component_close_handler (gpointer data)
2158 {
2159 GNCOptionWin *win = data;
2160 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(win->window));
2161 gnc_options_dialog_cancel_button_cb (NULL, win);
2162 }
2163
2164 static void
refresh_handler(GHashTable * changes,gpointer user_data)2165 refresh_handler (GHashTable *changes, gpointer user_data)
2166 {
2167 gnc_commodity *commodity = NULL;
2168 GtkTreeIter iter;
2169
2170 /* The default_gain_loss_account_widget needs to be refreshed if any
2171 changes have been made via account maintenance, if it exists and
2172 if the book currency widget has a selection */
2173 /* if (book_currency_data->default_gain_loss_account_widget &&
2174 gtk_combo_box_get_active_iter(
2175 GTK_COMBO_BOX(book_currency_data->book_currency_widget), &iter))
2176 {
2177 commodity = gnc_currency_edit_get_currency(
2178 GNC_CURRENCY_EDIT(
2179 book_currency_data->book_currency_widget));
2180 gnc_set_default_gain_loss_account_widget(commodity);
2181 gtk_widget_show_all(book_currency_data->book_currency_vbox);
2182 } */
2183 }
2184
2185 /* gnc_options_dialog_new:
2186 *
2187 * - Opens the dialog-options glade file
2188 * - Connects signals specified in the builder file
2189 * - Sets the window's title
2190 * - Initializes a new GtkNotebook, and adds it to the window
2191 *
2192 */
2193 GNCOptionWin *
gnc_options_dialog_new(gchar * title,GtkWindow * parent)2194 gnc_options_dialog_new (gchar *title, GtkWindow *parent)
2195 {
2196 return gnc_options_dialog_new_modal (FALSE, title, NULL, parent);
2197 }
2198
2199 /* gnc_options_dialog_new_modal:
2200 *
2201 * - Opens the dialog-options glade file
2202 * - Connects signals specified in the builder file
2203 * - Sets the window's title
2204 * - Initializes a new GtkNotebook, and adds it to the window
2205 * - If modal TRUE, hides 'apply' button
2206 * - If component_class is provided, it is used, otherwise,
2207 * DIALOG_OPTIONS_CM_CLASS is used; this is used to distinguish the
2208 * book-option dialog from report dialogs. The book-option dialog is a
2209 * singleton, so if a dialog already exists it will be raised to the top of
2210 * the window stack instead of creating a new dialog.
2211 */
2212 GNCOptionWin *
gnc_options_dialog_new_modal(gboolean modal,gchar * title,const char * component_class,GtkWindow * parent)2213 gnc_options_dialog_new_modal (gboolean modal, gchar *title,
2214 const char *component_class,
2215 GtkWindow *parent)
2216 {
2217 GNCOptionWin *retval;
2218 GtkBuilder *builder;
2219 GtkWidget *hbox;
2220 gint component_id;
2221 GtkWidget *button;
2222
2223 retval = g_new0 (GNCOptionWin, 1);
2224 builder = gtk_builder_new ();
2225 gnc_builder_add_from_file (builder, "dialog-options.glade", "gnucash_options_window");
2226 retval->window = GTK_WIDGET(gtk_builder_get_object (builder, "gnucash_options_window"));
2227 retval->page_list = GTK_WIDGET(gtk_builder_get_object (builder, "page_list_scroll"));
2228
2229 // Set the name for this dialog so it can be easily manipulated with css
2230 gtk_widget_set_name (GTK_WIDGET(retval->window), "gnc-id-options");
2231
2232 /* Page List */
2233 {
2234 GtkTreeView *view;
2235 GtkListStore *store;
2236 GtkTreeSelection *selection;
2237 GtkCellRenderer *renderer;
2238 GtkTreeViewColumn *column;
2239
2240 retval->page_list_view = GTK_WIDGET(gtk_builder_get_object (builder, "page_list_treeview"));
2241
2242 view = GTK_TREE_VIEW(retval->page_list_view);
2243
2244 store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_INT, G_TYPE_STRING);
2245 gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
2246 g_object_unref (store);
2247
2248 renderer = gtk_cell_renderer_text_new ();
2249 column = gtk_tree_view_column_new_with_attributes (_("Page"), renderer,
2250 "text", PAGE_NAME,
2251 NULL);
2252 gtk_tree_view_append_column (view, column);
2253
2254 gtk_tree_view_column_set_alignment (column, 0.5);
2255
2256 selection = gtk_tree_view_get_selection (view);
2257 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
2258 g_signal_connect (selection, "changed",
2259 G_CALLBACK (gnc_options_dialog_list_select_cb), retval);
2260 }
2261
2262 button = GTK_WIDGET(gtk_builder_get_object (builder, "helpbutton"));
2263 g_signal_connect (button, "clicked", G_CALLBACK(gnc_options_dialog_help_button_cb), retval);
2264 button = GTK_WIDGET(gtk_builder_get_object (builder, "cancelbutton"));
2265 g_signal_connect (button, "clicked", G_CALLBACK(gnc_options_dialog_cancel_button_cb), retval);
2266 button = GTK_WIDGET(gtk_builder_get_object (builder, "applybutton"));
2267 g_signal_connect (button, "clicked", G_CALLBACK(gnc_options_dialog_apply_button_cb), retval);
2268 button = GTK_WIDGET(gtk_builder_get_object (builder, "okbutton"));
2269 g_signal_connect (button, "clicked", G_CALLBACK(gnc_options_dialog_ok_button_cb), retval);
2270
2271 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, retval);
2272
2273 if (parent) // when added to a page of the hierarchy assistant there will be no parent
2274 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(retval->window), parent);
2275
2276 if (title)
2277 gtk_window_set_title (GTK_WINDOW(retval->window), title);
2278
2279 /* modal */
2280 if (modal == TRUE)
2281 {
2282 GtkWidget *apply_button;
2283
2284 apply_button = GTK_WIDGET(gtk_builder_get_object (builder, "applybutton"));
2285 gtk_widget_hide (apply_button);
2286 }
2287
2288 /* glade doesn't support a notebook with zero pages */
2289 hbox = GTK_WIDGET(gtk_builder_get_object (builder, "notebook_placeholder"));
2290 retval->notebook = gtk_notebook_new ();
2291
2292 gtk_widget_set_vexpand (retval->notebook, TRUE);
2293
2294 gtk_widget_show (retval->notebook);
2295 gtk_box_pack_start (GTK_BOX(hbox), retval->notebook, TRUE, TRUE, 5);
2296
2297 retval->component_class =
2298 (component_class ? component_class : DIALOG_OPTIONS_CM_CLASS);
2299 component_id = gnc_register_gui_component (retval->component_class,
2300 refresh_handler, component_close_handler,
2301 retval);
2302 gnc_gui_component_set_session (component_id, gnc_get_current_session());
2303
2304 /* Watch account maintenance events only if book option dialog */
2305 if (g_strcmp0 (retval->component_class, DIALOG_BOOK_OPTIONS_CM_CLASS) == 0)
2306 {
2307 gnc_gui_component_watch_entity_type (component_id,
2308 GNC_ID_ACCOUNT,
2309 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
2310 }
2311
2312 g_signal_connect (retval->window, "destroy",
2313 G_CALLBACK(gnc_options_dialog_destroy_cb), retval);
2314
2315 g_signal_connect (retval->window, "key_press_event",
2316 G_CALLBACK(gnc_options_dialog_window_key_press_cb), retval);
2317
2318 g_object_unref (G_OBJECT(builder));
2319
2320 retval->destroyed = FALSE;
2321 return retval;
2322 }
2323
2324 /* Creates a new GNCOptionWin structure, but assumes you have your own
2325 dialog widget you want to plugin */
2326 GNCOptionWin *
gnc_options_dialog_new_w_dialog(gchar * title,GtkWidget * window)2327 gnc_options_dialog_new_w_dialog (gchar *title, GtkWidget *window)
2328 {
2329 GNCOptionWin * retval;
2330
2331 retval = g_new0 (GNCOptionWin, 1);
2332 retval->window = window;
2333 return retval;
2334 }
2335
2336 void
gnc_options_dialog_set_apply_cb(GNCOptionWin * win,GNCOptionWinCallback cb,gpointer data)2337 gnc_options_dialog_set_apply_cb (GNCOptionWin * win, GNCOptionWinCallback cb,
2338 gpointer data)
2339 {
2340 win->apply_cb = cb;
2341 win->apply_cb_data = data;
2342 }
2343
2344 void
gnc_options_dialog_set_help_cb(GNCOptionWin * win,GNCOptionWinCallback cb,gpointer data)2345 gnc_options_dialog_set_help_cb (GNCOptionWin * win, GNCOptionWinCallback cb,
2346 gpointer data)
2347 {
2348 win->help_cb = cb;
2349 win->help_cb_data = data;
2350 }
2351
2352 void
gnc_options_dialog_set_close_cb(GNCOptionWin * win,GNCOptionWinCallback cb,gpointer data)2353 gnc_options_dialog_set_close_cb (GNCOptionWin * win, GNCOptionWinCallback cb,
2354 gpointer data)
2355 {
2356 win->close_cb = cb;
2357 win->close_cb_data = data;
2358 }
2359
2360 void
gnc_options_dialog_set_global_help_cb(GNCOptionWinCallback thunk,gpointer cb_data)2361 gnc_options_dialog_set_global_help_cb (GNCOptionWinCallback thunk,
2362 gpointer cb_data)
2363 {
2364 global_help_cb = thunk;
2365 global_help_cb_data = cb_data;
2366 }
2367
2368 /* This is for global program preferences. */
2369 void
gnc_options_dialog_destroy(GNCOptionWin * win)2370 gnc_options_dialog_destroy (GNCOptionWin * win)
2371 {
2372 if (!win) return;
2373
2374 gnc_unregister_gui_component_by_data (win->component_class, win);
2375
2376 win->destroyed = TRUE;
2377 gtk_widget_destroy (win->window);
2378
2379 win->window = NULL;
2380 win->notebook = NULL;
2381 win->apply_cb = NULL;
2382 win->help_cb = NULL;
2383 win->component_class = NULL;
2384
2385 g_free (win);
2386 }
2387
2388 /*****************************************************************/
2389 /* Option Registration */
2390
2391 /*************************
2392 * SET WIDGET *
2393 *************************
2394 *
2395 * gnc_option_set_ui_widget_<type>():
2396 *
2397 * You should create the widget representation for the option type,
2398 * and set the top-level container widget for your control in
2399 * *enclosing. If you want to pack the widget into the page yourself,
2400 * then you may -- just set *packed to TRUE. Otherwise, the widget
2401 * you return in *enclosing will be packed for you. (*packed is
2402 * initialized to FALSE, so if you're not setting it to TRUE, you
2403 * don't have to touch it at all.)
2404 *
2405 * If you need to initialize the state of your control or to connect
2406 * any signals to you widgets, then you should do so in this function.
2407 * If you want to create a label for the widget you should use 'name'
2408 * for the label text.
2409 *
2410 * Somewhere in this function, you should also call
2411 * gnc_option_set_widget(option, value); where 'value' is the
2412 * GtkWidget you will actually store the value in.
2413 *
2414 * Also call gnc_option_set_ui_value(option, FALSE);
2415 *
2416 * You probably want to end with something like:
2417 * gtk_widget_show_all(*enclosing);
2418 *
2419 * If you can detect state changes for your widget's value, you should also
2420 * gnc_option_changed_widget_cb() upon changes.
2421 *
2422 * The widget you return from this function should be the widget in
2423 * which you're storing the option value.
2424 */
2425
2426 static void
gnc_option_set_ui_label_alignment(GtkLabel * name_label)2427 gnc_option_set_ui_label_alignment (GtkLabel *name_label)
2428 {
2429 /* some option widgets have a large vertical foot print so align
2430 the label name to the top and add a small top margin */
2431 gtk_widget_set_valign (GTK_WIDGET(name_label), GTK_ALIGN_START);
2432 gtk_widget_set_margin_top (GTK_WIDGET(name_label), 6);
2433 }
2434
2435 static GtkWidget *
gnc_option_set_ui_widget_boolean(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2436 gnc_option_set_ui_widget_boolean (GNCOption *option, GtkGrid *page_box,
2437 GtkLabel *name_label, char *documentation,
2438 /* Return values */
2439 GtkWidget **enclosing, gboolean *packed)
2440 {
2441 GtkWidget *value;
2442
2443 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2444 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2445 value = gtk_check_button_new_with_label (gtk_label_get_text (name_label));
2446
2447 gnc_option_set_widget (option, value);
2448 gnc_option_set_ui_value (option, FALSE);
2449
2450 g_signal_connect (G_OBJECT(value), "toggled",
2451 G_CALLBACK(gnc_option_changed_widget_cb), option);
2452
2453 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2454 gtk_widget_show_all (*enclosing);
2455
2456 return value;
2457 }
2458
2459 static GtkWidget *
gnc_option_set_ui_widget_string(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2460 gnc_option_set_ui_widget_string (GNCOption *option, GtkGrid *page_box,
2461 GtkLabel *name_label, char *documentation,
2462 /* Return values */
2463 GtkWidget **enclosing, gboolean *packed)
2464 {
2465 GtkWidget *value;
2466
2467 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2468 gtk_widget_set_hexpand (GTK_WIDGET(*enclosing), TRUE);
2469 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2470 value = gtk_entry_new ();
2471
2472 gnc_option_set_widget (option, value);
2473 gnc_option_set_ui_value (option, FALSE);
2474
2475 if (gtk_widget_get_direction (GTK_WIDGET(value)) == GTK_TEXT_DIR_RTL)
2476 gtk_entry_set_alignment (GTK_ENTRY(value), 1.0);
2477
2478 g_signal_connect (G_OBJECT(value), "changed",
2479 G_CALLBACK(gnc_option_changed_widget_cb), option);
2480
2481 gtk_box_pack_start (GTK_BOX(*enclosing), value, TRUE, TRUE, 0);
2482 gtk_widget_show_all (*enclosing);
2483 return value;
2484 }
2485
2486 static GtkWidget *
gnc_option_set_ui_widget_text(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2487 gnc_option_set_ui_widget_text (GNCOption *option, GtkGrid *page_box,
2488 GtkLabel *name_label, char *documentation,
2489 /* Return values */
2490 GtkWidget **enclosing, gboolean *packed)
2491 {
2492 GtkWidget *value;
2493 GtkWidget *frame;
2494 GtkWidget *scroll;
2495 GtkTextBuffer* text_buffer;
2496
2497 frame = gtk_frame_new(NULL);
2498
2499 gnc_option_set_ui_label_alignment (name_label);
2500
2501 scroll = gtk_scrolled_window_new (NULL, NULL);
2502 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scroll),
2503 GTK_POLICY_NEVER,
2504 GTK_POLICY_AUTOMATIC);
2505 gtk_container_set_border_width (GTK_CONTAINER(scroll), 2);
2506
2507 gtk_container_add (GTK_CONTAINER(frame), scroll);
2508
2509 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
2510 gtk_widget_set_vexpand (GTK_WIDGET(*enclosing), TRUE);
2511 gtk_widget_set_hexpand (GTK_WIDGET(*enclosing), TRUE);
2512 gtk_box_set_homogeneous (GTK_BOX (*enclosing), FALSE);
2513 value = gtk_text_view_new ();
2514 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(value), GTK_WRAP_WORD);
2515 gtk_text_view_set_editable (GTK_TEXT_VIEW(value), TRUE);
2516 gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW(value), FALSE);
2517 gtk_container_add (GTK_CONTAINER(scroll), value);
2518
2519 gnc_option_set_widget (option, value);
2520 gnc_option_set_ui_value (option, FALSE);
2521
2522 text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(value));
2523 g_signal_connect (G_OBJECT(text_buffer), "changed",
2524 G_CALLBACK(gnc_option_changed_option_cb), option);
2525
2526 gtk_box_pack_start (GTK_BOX(*enclosing), frame, TRUE, TRUE, 0);
2527 gtk_widget_show_all (*enclosing);
2528 return value;
2529 }
2530
2531 static GtkWidget *
gnc_option_set_ui_widget_currency(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2532 gnc_option_set_ui_widget_currency (GNCOption *option, GtkGrid *page_box,
2533 GtkLabel *name_label, char *documentation,
2534 /* Return values */
2535 GtkWidget **enclosing, gboolean *packed)
2536 {
2537 GtkWidget *value;
2538
2539 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2540 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2541 value = gnc_currency_edit_new ();
2542
2543 gnc_option_set_widget (option, value);
2544 gnc_option_set_ui_value (option, FALSE);
2545
2546 g_signal_connect (G_OBJECT(value), "changed",
2547 G_CALLBACK(gnc_option_changed_widget_cb), option);
2548
2549 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2550 gtk_widget_show_all (*enclosing);
2551 return value;
2552 }
2553
2554 static GtkWidget *
gnc_option_set_ui_widget_commodity(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2555 gnc_option_set_ui_widget_commodity (GNCOption *option, GtkGrid *page_box,
2556 GtkLabel *name_label, char *documentation,
2557 /* Return values */
2558 GtkWidget **enclosing, gboolean *packed)
2559 {
2560 GtkWidget *value;
2561
2562 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2563 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2564 value = gnc_general_select_new (GNC_GENERAL_SELECT_TYPE_SELECT,
2565 gnc_commodity_edit_get_string,
2566 gnc_commodity_edit_new_select,
2567 NULL);
2568
2569 gnc_option_set_widget (option, value);
2570 gnc_option_set_ui_value (option, FALSE);
2571
2572 if (documentation != NULL)
2573 gtk_widget_set_tooltip_text (GNC_GENERAL_SELECT(value)->entry,
2574 documentation);
2575
2576 g_signal_connect (G_OBJECT(GNC_GENERAL_SELECT(value)->entry), "changed",
2577 G_CALLBACK(gnc_option_changed_widget_cb), option);
2578
2579 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2580 gtk_widget_show_all (*enclosing);
2581 return value;
2582 }
2583
2584 static GtkWidget *
gnc_option_set_ui_widget_multichoice(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2585 gnc_option_set_ui_widget_multichoice (GNCOption *option, GtkGrid *page_box,
2586 GtkLabel *name_label, char *documentation,
2587 /* Return values */
2588 GtkWidget **enclosing, gboolean *packed)
2589 {
2590 GtkWidget *value;
2591
2592 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2593 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2594
2595 value = gnc_option_create_multichoice_widget (option);
2596 gnc_option_set_widget (option, value);
2597
2598 gnc_option_set_ui_value (option, FALSE);
2599 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2600 gtk_widget_show_all (*enclosing);
2601 return value;
2602 }
2603
2604 static GtkWidget *
gnc_option_set_ui_widget_date(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2605 gnc_option_set_ui_widget_date (GNCOption *option, GtkGrid *page_box,
2606 GtkLabel *name_label, char *documentation,
2607 /* Return values */
2608 GtkWidget **enclosing, gboolean *packed)
2609 {
2610 GtkWidget *value;
2611 gchar *colon_name;
2612 GtkWidget *eventbox;
2613 gchar *type = gnc_option_date_option_get_subtype (option);
2614
2615
2616 gint grid_row = GPOINTER_TO_INT(g_object_get_data
2617 (G_OBJECT(page_box), "options-grid-row"));
2618
2619 value = gnc_option_create_date_widget (option);
2620
2621 gnc_option_set_widget (option, value);
2622
2623 if (g_strcmp0 (type, "relative") == 0)
2624 {
2625 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2626 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2627
2628 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2629 }
2630 else
2631 {
2632 *enclosing = gtk_frame_new (NULL);
2633 g_object_set (G_OBJECT(value), "margin", 3, NULL);
2634
2635 gtk_container_add (GTK_CONTAINER(*enclosing), value);
2636 }
2637 g_free (type);
2638
2639 gtk_widget_set_halign (GTK_WIDGET(*enclosing), GTK_ALIGN_START);
2640
2641 /* Pack option widget into an extra eventbox because otherwise the
2642 "documentation" tooltip is not displayed. */
2643 eventbox = gtk_event_box_new ();
2644 gtk_container_add (GTK_CONTAINER(eventbox), *enclosing);
2645
2646 gtk_grid_attach (GTK_GRID(page_box), eventbox, 1, grid_row, 1, 1);
2647 *packed = TRUE;
2648
2649 gtk_widget_set_tooltip_text (eventbox, documentation);
2650
2651 gnc_option_set_ui_value (option, FALSE);
2652 gtk_widget_show_all (*enclosing);
2653 return value;
2654 }
2655
2656 static GtkWidget *
gnc_option_set_ui_widget_account_list(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2657 gnc_option_set_ui_widget_account_list (GNCOption *option, GtkGrid *page_box,
2658 GtkLabel *name_label, char *documentation,
2659 /* Return values */
2660 GtkWidget **enclosing, gboolean *packed)
2661 {
2662 GtkWidget *value;
2663 GtkTreeSelection *selection;
2664 gint grid_row = GPOINTER_TO_INT(g_object_get_data
2665 (G_OBJECT(page_box), "options-grid-row"));
2666
2667 gnc_option_set_ui_label_alignment (name_label);
2668
2669 *enclosing = gnc_option_create_account_widget (option, NULL);
2670 gtk_widget_set_vexpand (GTK_WIDGET(*enclosing), TRUE);
2671 gtk_widget_set_hexpand (GTK_WIDGET(*enclosing), TRUE);
2672 value = gnc_option_get_gtk_widget (option);
2673
2674 gtk_widget_set_tooltip_text (*enclosing, documentation);
2675
2676 gtk_grid_attach (GTK_GRID(page_box), *enclosing, 1, grid_row, 1, 1);
2677 *packed = TRUE;
2678
2679 //gtk_widget_realize(value);
2680
2681 gnc_option_set_ui_value (option, FALSE);
2682
2683 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(value));
2684 g_signal_connect (G_OBJECT(selection), "changed",
2685 G_CALLBACK(gnc_option_account_cb), option);
2686
2687 // gtk_clist_set_row_height(GTK_CLIST(value), 0);
2688 // gtk_widget_set_size_request(value, -1, GTK_CLIST(value)->row_height * 10);
2689 gtk_widget_show_all (*enclosing);
2690 return value;
2691 }
2692
2693 static GtkWidget *
gnc_option_set_ui_widget_account_sel(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2694 gnc_option_set_ui_widget_account_sel (GNCOption *option, GtkGrid *page_box,
2695 GtkLabel *name_label, char *documentation,
2696 /* Return values */
2697 GtkWidget **enclosing, gboolean *packed)
2698 {
2699 GtkWidget *value = gnc_account_sel_new ();
2700 GList *acct_type_list = gnc_option_get_account_type_list (option);
2701
2702 gnc_account_sel_set_acct_filters (GNC_ACCOUNT_SEL(value), acct_type_list, NULL);
2703
2704 g_signal_connect (value, "account_sel_changed",
2705 G_CALLBACK(gnc_option_changed_widget_cb), option);
2706
2707 gnc_option_set_widget (option, value);
2708
2709 gnc_option_set_ui_value (option, FALSE);
2710
2711 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2712 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2713 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2714 gtk_widget_show_all (*enclosing);
2715 return value;
2716 }
2717
2718 static GtkWidget *
gnc_option_set_ui_widget_list(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2719 gnc_option_set_ui_widget_list (GNCOption *option, GtkGrid *page_box,
2720 GtkLabel *name_label, char *documentation,
2721 /* Return values */
2722 GtkWidget **enclosing, gboolean *packed)
2723 {
2724 GtkWidget *value;
2725 GtkWidget *eventbox;
2726 gint grid_row = GPOINTER_TO_INT(g_object_get_data
2727 (G_OBJECT(page_box), "options-grid-row"));
2728
2729 *enclosing = gnc_option_create_list_widget (option, NULL);
2730 value = gnc_option_get_gtk_widget (option);
2731
2732 gnc_option_set_ui_label_alignment (name_label);
2733
2734 /* Pack option widget into an extra eventbox because otherwise the
2735 "documentation" tooltip is not displayed. */
2736 eventbox = gtk_event_box_new ();
2737 gtk_container_add (GTK_CONTAINER(eventbox), *enclosing);
2738
2739 gtk_grid_attach (GTK_GRID(page_box), eventbox, 1, grid_row, 1, 1);
2740 *packed = TRUE;
2741
2742 gtk_widget_set_tooltip_text (eventbox, documentation);
2743
2744 gnc_option_set_ui_value (option, FALSE);
2745 gtk_widget_show (*enclosing);
2746 return value;
2747 }
2748
2749 static GtkWidget *
gnc_option_set_ui_widget_number_range(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2750 gnc_option_set_ui_widget_number_range (GNCOption *option, GtkGrid *page_box,
2751 GtkLabel *name_label, char *documentation,
2752 /* Return values */
2753 GtkWidget **enclosing, gboolean *packed)
2754 {
2755 GtkWidget *value;
2756 GtkAdjustment *adj;
2757 gdouble lower_bound = G_MINDOUBLE;
2758 gdouble upper_bound = G_MAXDOUBLE;
2759 gdouble step_size = 1.0;
2760 int num_decimals = 0;
2761
2762 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2763 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2764
2765 gnc_option_get_range_info (option, &lower_bound, &upper_bound,
2766 &num_decimals, &step_size);
2767 adj = GTK_ADJUSTMENT(gtk_adjustment_new (lower_bound, lower_bound,
2768 upper_bound, step_size,
2769 step_size * 5.0,
2770 0));
2771 value = gtk_spin_button_new (adj, step_size, num_decimals);
2772 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON(value), TRUE);
2773
2774 {
2775 gdouble biggest;
2776 gint num_digits;
2777
2778 biggest = ABS(lower_bound);
2779 biggest = MAX(biggest, ABS(upper_bound));
2780
2781 num_digits = 0;
2782 while (biggest >= 1)
2783 {
2784 num_digits++;
2785 biggest = biggest / 10;
2786 }
2787
2788 if (num_digits == 0)
2789 num_digits = 1;
2790
2791 num_digits += num_decimals;
2792
2793 gtk_entry_set_width_chars (GTK_ENTRY(value), num_digits);
2794 }
2795
2796 gnc_option_set_widget (option, value);
2797 gnc_option_set_ui_value (option, FALSE);
2798
2799 g_signal_connect (G_OBJECT(value), "changed",
2800 G_CALLBACK(gnc_option_changed_widget_cb), option);
2801
2802 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2803 gtk_widget_show_all (*enclosing);
2804 return value;
2805 }
2806
2807 static GtkWidget *
gnc_option_set_ui_widget_color(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2808 gnc_option_set_ui_widget_color (GNCOption *option, GtkGrid *page_box,
2809 GtkLabel *name_label, char *documentation,
2810 /* Return values */
2811 GtkWidget **enclosing, gboolean *packed)
2812 {
2813 GtkWidget *value;
2814 gboolean use_alpha;
2815
2816 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2817 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2818
2819 use_alpha = gnc_option_use_alpha (option);
2820
2821 value = gtk_color_button_new ();
2822 gtk_color_chooser_set_use_alpha (GTK_COLOR_CHOOSER(value), use_alpha);
2823
2824 gnc_option_set_widget (option, value);
2825 gnc_option_set_ui_value (option, FALSE);
2826
2827 g_signal_connect (G_OBJECT(value), "color-set",
2828 G_CALLBACK(gnc_option_color_changed_cb), option);
2829
2830 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2831 gtk_widget_show_all (*enclosing);
2832 return value;
2833 }
2834
2835 static GtkWidget *
gnc_option_set_ui_widget_font(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2836 gnc_option_set_ui_widget_font (GNCOption *option, GtkGrid *page_box,
2837 GtkLabel *name_label, char *documentation,
2838 /* Return values */
2839 GtkWidget **enclosing, gboolean *packed)
2840 {
2841 GtkWidget *value;
2842
2843 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2844 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2845 value = gtk_font_button_new ();
2846 g_object_set (G_OBJECT(value),
2847 "use-font", TRUE,
2848 "show-style", TRUE,
2849 "show-size", TRUE,
2850 (char *)NULL);
2851
2852 gnc_option_set_widget (option, value);
2853
2854 gnc_option_set_ui_value (option, FALSE);
2855
2856 g_signal_connect (G_OBJECT(value), "font-set",
2857 G_CALLBACK(gnc_option_font_changed_cb), option);
2858
2859 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2860 gtk_widget_show_all (*enclosing);
2861 return value;
2862 }
2863
2864 static GtkWidget *
gnc_option_set_ui_widget_pixmap(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2865 gnc_option_set_ui_widget_pixmap (GNCOption *option, GtkGrid *page_box,
2866 GtkLabel *name_label, char *documentation,
2867 /* Return values */
2868 GtkWidget **enclosing, gboolean *packed)
2869 {
2870 GtkWidget *value;
2871 GtkWidget *button;
2872
2873 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2874 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2875
2876 button = gtk_button_new_with_label (_("Clear"));
2877 gtk_widget_set_tooltip_text (button, _("Clear any selected image file."));
2878
2879 value = gtk_file_chooser_button_new (_("Select image"),
2880 GTK_FILE_CHOOSER_ACTION_OPEN);
2881 gtk_widget_set_tooltip_text (value, _("Select an image file."));
2882 g_object_set (G_OBJECT(value),
2883 "width-chars", 30,
2884 "preview-widget", gtk_image_new(),
2885 (char *)NULL);
2886 g_signal_connect (G_OBJECT(value), "selection-changed",
2887 G_CALLBACK(gnc_option_changed_widget_cb), option);
2888 g_signal_connect (G_OBJECT(value), "selection-changed",
2889 G_CALLBACK(gnc_image_option_selection_changed_cb), option);
2890 g_signal_connect (G_OBJECT(value), "update-preview",
2891 G_CALLBACK(gnc_image_option_update_preview_cb), option);
2892 g_signal_connect_swapped (G_OBJECT(button), "clicked",
2893 G_CALLBACK(gtk_file_chooser_unselect_all), value);
2894
2895 gnc_option_set_widget (option, value);
2896 gnc_option_set_ui_value (option, FALSE);
2897
2898 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2899 gtk_box_pack_start (GTK_BOX(*enclosing), button, FALSE, FALSE, 0);
2900
2901 gtk_widget_show (value);
2902 gtk_widget_show (*enclosing);
2903
2904 return value;
2905 }
2906
2907 static GtkWidget *
gnc_option_set_ui_widget_radiobutton(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2908 gnc_option_set_ui_widget_radiobutton (GNCOption *option, GtkGrid *page_box,
2909 GtkLabel *name_label, char *documentation,
2910 /* Return values */
2911 GtkWidget **enclosing, gboolean *packed)
2912 {
2913 GtkWidget *value;
2914
2915 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2916 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
2917
2918 gnc_option_set_ui_label_alignment (name_label);
2919
2920 value = gnc_option_create_radiobutton_widget (NULL, option);
2921 gnc_option_set_widget (option, value);
2922
2923 gnc_option_set_ui_value (option, FALSE);
2924 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
2925 gtk_widget_show_all (*enclosing);
2926 return value;
2927 }
2928
2929 static GtkWidget *
gnc_option_set_ui_widget_dateformat(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2930 gnc_option_set_ui_widget_dateformat (GNCOption *option, GtkGrid *page_box,
2931 GtkLabel *name_label, char *documentation,
2932 /* Return values */
2933 GtkWidget **enclosing, gboolean *packed)
2934 {
2935 *enclosing = gnc_date_format_new_without_label ();
2936 gnc_option_set_widget (option, *enclosing);
2937
2938 gnc_option_set_ui_label_alignment (name_label);
2939
2940 gnc_option_set_ui_value (option, FALSE);
2941 g_signal_connect (G_OBJECT(*enclosing), "format_changed",
2942 G_CALLBACK(gnc_option_changed_option_cb), option);
2943 gtk_widget_show_all (*enclosing);
2944 return *enclosing;
2945 }
2946
2947 static void
gnc_plot_size_option_set_select_method(GNCOption * option,gboolean set_buttons)2948 gnc_plot_size_option_set_select_method (GNCOption *option, gboolean set_buttons)
2949 {
2950 GList* widget_list;
2951 GtkWidget *px_widget, *p_widget;
2952 GtkWidget *widget;
2953
2954 widget = gnc_option_get_gtk_widget (option);
2955
2956 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
2957 // px_button item 0
2958 px_widget = g_list_nth_data (widget_list, 1);
2959 // p_button item 2
2960 p_widget = g_list_nth_data (widget_list, 3);
2961 g_list_free (widget_list);
2962
2963 if (set_buttons)
2964 {
2965 gtk_widget_set_sensitive (px_widget, TRUE);
2966 gtk_widget_set_sensitive (p_widget, FALSE);
2967 }
2968 else
2969 {
2970 gtk_widget_set_sensitive (p_widget, TRUE);
2971 gtk_widget_set_sensitive (px_widget, FALSE);
2972 }
2973 }
2974
2975 static void
gnc_rd_option_px_set_cb(GtkWidget * widget,gpointer * raw_option)2976 gnc_rd_option_px_set_cb (GtkWidget *widget, gpointer *raw_option)
2977 {
2978 GNCOption *option = (GNCOption *) raw_option;
2979 gnc_plot_size_option_set_select_method (option, TRUE);
2980 gnc_option_changed_option_cb (widget, option);
2981 }
2982
2983 static void
gnc_rd_option_p_set_cb(GtkWidget * widget,gpointer * raw_option)2984 gnc_rd_option_p_set_cb (GtkWidget *widget, gpointer *raw_option)
2985 {
2986 GNCOption *option = (GNCOption *) raw_option;
2987 gnc_plot_size_option_set_select_method (option, FALSE);
2988 gnc_option_changed_option_cb (widget, option);
2989 return;
2990 }
2991
2992 static GtkWidget *
gnc_option_set_ui_widget_plot_size(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)2993 gnc_option_set_ui_widget_plot_size (GNCOption *option, GtkGrid *page_box,
2994 GtkLabel *name_label, char *documentation,
2995 /* Return values */
2996 GtkWidget **enclosing, gboolean *packed)
2997 {
2998 GtkWidget *value_px, *value_percent;
2999 GtkWidget *px_butt, *p_butt;
3000 GtkWidget *hbox;
3001 GtkAdjustment *adj_px, *adj_percent;
3002 gdouble lower_bound = G_MINDOUBLE;
3003 gdouble upper_bound = G_MAXDOUBLE;
3004 gdouble step_size = 1.0;
3005 int num_decimals = 0;
3006
3007 *enclosing = gtk_frame_new (NULL);
3008 gtk_widget_set_halign (GTK_WIDGET(*enclosing), GTK_ALIGN_START);
3009
3010 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
3011 gtk_box_set_homogeneous (GTK_BOX(hbox), FALSE);
3012 g_object_set (G_OBJECT(hbox), "margin", 3, NULL);
3013
3014 gtk_container_add (GTK_CONTAINER(*enclosing), hbox);
3015
3016 gnc_option_get_range_info (option, &lower_bound, &upper_bound,
3017 &num_decimals, &step_size);
3018 adj_px = GTK_ADJUSTMENT(gtk_adjustment_new (lower_bound, lower_bound,
3019 upper_bound, step_size,
3020 step_size * 5.0,
3021 0));
3022
3023 value_px = gtk_spin_button_new (adj_px, step_size, num_decimals);
3024 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON(value_px), TRUE);
3025
3026 {
3027 gdouble biggest;
3028 gint num_digits;
3029
3030 biggest = ABS(lower_bound);
3031 biggest = MAX(biggest, ABS(upper_bound));
3032
3033 num_digits = 0;
3034 while (biggest >= 1)
3035 {
3036 num_digits++;
3037 biggest = biggest / 10;
3038 }
3039
3040 if (num_digits == 0)
3041 num_digits = 1;
3042
3043 num_digits += num_decimals;
3044
3045 gtk_entry_set_width_chars (GTK_ENTRY(value_px), num_digits);
3046 }
3047 gtk_spin_button_set_value (GTK_SPIN_BUTTON(value_px), (upper_bound / 2)); //default
3048 g_signal_connect (G_OBJECT(value_px), "changed",
3049 G_CALLBACK(gnc_option_changed_widget_cb), option);
3050
3051 adj_percent = GTK_ADJUSTMENT(gtk_adjustment_new (1, 10, 100, 1, 5.0, 0));
3052 value_percent = gtk_spin_button_new (adj_percent, 1, 0);
3053 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON(value_percent), TRUE);
3054 gtk_spin_button_set_value (GTK_SPIN_BUTTON(value_percent), 100); //default
3055 gtk_entry_set_width_chars (GTK_ENTRY(value_percent), 3);
3056 gtk_widget_set_sensitive (value_percent, FALSE);
3057
3058 g_signal_connect (G_OBJECT(value_percent), "changed",
3059 G_CALLBACK(gnc_option_changed_widget_cb), option);
3060
3061 px_butt = gtk_radio_button_new_with_label (NULL, _("Pixels"));
3062 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(px_butt), TRUE);
3063
3064 g_signal_connect (G_OBJECT(px_butt), "toggled",
3065 G_CALLBACK(gnc_rd_option_px_set_cb), option);
3066
3067 p_butt = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(px_butt), _("Percent"));
3068 g_signal_connect (G_OBJECT(p_butt), "toggled",
3069 G_CALLBACK(gnc_rd_option_p_set_cb), option);
3070
3071 gtk_box_pack_start (GTK_BOX(hbox), px_butt, FALSE, FALSE, 0);
3072 gtk_box_pack_start (GTK_BOX(hbox), value_px, FALSE, FALSE, 0);
3073 gtk_box_pack_start (GTK_BOX(hbox), p_butt, FALSE, FALSE, 0);
3074 gtk_box_pack_start (GTK_BOX(hbox), value_percent, FALSE, FALSE, 0);
3075
3076 gnc_option_set_widget (option, hbox);
3077 gnc_option_set_ui_value (option, FALSE);
3078
3079 gtk_widget_show_all (*enclosing);
3080 return hbox;
3081 }
3082
3083 static GtkWidget *
gnc_option_set_ui_widget_budget(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)3084 gnc_option_set_ui_widget_budget (GNCOption *option, GtkGrid *page_box,
3085 GtkLabel *name_label, char *documentation,
3086 /* Return values */
3087 GtkWidget **enclosing, gboolean *packed)
3088 {
3089 GtkWidget *value;
3090
3091
3092 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
3093 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
3094
3095 value = gnc_option_create_budget_widget (option);
3096
3097 gnc_option_set_widget (option, value);
3098 gnc_option_set_ui_value (option, FALSE);
3099
3100 /* Maybe connect destroy handler for tree model here? */
3101 g_signal_connect (G_OBJECT(value), "changed",
3102 G_CALLBACK(gnc_option_changed_widget_cb), option);
3103
3104 gtk_box_pack_start (GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
3105 gtk_widget_show_all (*enclosing);
3106 return value;
3107 }
3108
3109 static GtkWidget *
gnc_option_set_ui_widget_currency_accounting(GNCOption * option,GtkGrid * page_box,GtkLabel * name_label,char * documentation,GtkWidget ** enclosing,gboolean * packed)3110 gnc_option_set_ui_widget_currency_accounting (GNCOption *option,
3111 GtkGrid *page_box,
3112 GtkLabel *name_label, char *documentation,
3113 /* Return values */
3114 GtkWidget **enclosing,
3115 gboolean *packed)
3116 {
3117 GtkWidget *value;
3118
3119 *enclosing = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
3120 gtk_box_set_homogeneous (GTK_BOX(*enclosing), FALSE);
3121
3122 value = gnc_option_create_currency_accounting_widget (NULL, option);
3123 gnc_option_set_widget (option, value);
3124
3125 gnc_option_set_ui_value (option, FALSE);
3126 gtk_box_pack_start (GTK_BOX(*enclosing), value, TRUE, TRUE, 0);
3127 gtk_widget_show_all (*enclosing);
3128 return value;
3129 }
3130
3131 /*************************
3132 * SET VALUE *
3133 *************************
3134 *
3135 * gnc_option_set_ui_value_<type>():
3136 *
3137 * In this function you should set the state of the gui widget to
3138 * correspond to the value provided in 'value'. You should return
3139 * TRUE if there was an error, FALSE otherwise.
3140 *
3141 *
3142 */
3143 static gboolean
gnc_option_set_ui_value_boolean(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3144 gnc_option_set_ui_value_boolean (GNCOption *option, gboolean use_default,
3145 GtkWidget *widget, SCM value)
3146 {
3147 if (scm_is_bool (value))
3148 {
3149 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget),
3150 scm_is_true(value));
3151 return FALSE;
3152 }
3153 else
3154 return TRUE;
3155 }
3156
3157 static gboolean
gnc_option_set_ui_value_string(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3158 gnc_option_set_ui_value_string (GNCOption *option, gboolean use_default,
3159 GtkWidget *widget, SCM value)
3160 {
3161 if (scm_is_string (value))
3162 {
3163 const gchar *string;
3164
3165 string = gnc_scm_to_utf8_string (value);
3166 gtk_entry_set_text (GTK_ENTRY(widget), string);
3167 g_free ((gpointer *) string);
3168 return FALSE;
3169 }
3170 else
3171 return TRUE;
3172 }
3173
3174 static gboolean
gnc_option_set_ui_value_text(GNCOption * option,gboolean use_default,GObject * object,SCM value)3175 gnc_option_set_ui_value_text (GNCOption *option, gboolean use_default,
3176 GObject *object, SCM value)
3177 {
3178 GtkTextBuffer *buffer;
3179
3180 if (GTK_IS_TEXT_BUFFER(object))
3181 buffer = GTK_TEXT_BUFFER(object);
3182 else
3183 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(object));
3184
3185 if (scm_is_string (value))
3186 {
3187 const gchar *string;
3188
3189 string = gnc_scm_to_utf8_string (value);
3190 gtk_text_buffer_set_text (buffer, string, -1);
3191 free ((void*) string);
3192 return FALSE;
3193 }
3194 else
3195 return TRUE;
3196 }
3197
3198 static gboolean
gnc_option_set_ui_value_currency(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3199 gnc_option_set_ui_value_currency (GNCOption *option, gboolean use_default,
3200 GtkWidget *widget, SCM value)
3201 {
3202 gnc_commodity *commodity;
3203
3204 commodity = gnc_scm_to_commodity (value);
3205 if (commodity)
3206 {
3207 gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(widget), commodity);
3208 return FALSE;
3209 }
3210 else
3211 return TRUE;
3212 }
3213
3214 static gboolean
gnc_option_set_ui_value_commodity(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3215 gnc_option_set_ui_value_commodity (GNCOption *option, gboolean use_default,
3216 GtkWidget *widget, SCM value)
3217 {
3218 gnc_commodity *commodity;
3219
3220 commodity = gnc_scm_to_commodity (value);
3221 if (commodity)
3222 {
3223 gnc_general_select_set_selected (GNC_GENERAL_SELECT(widget), commodity);
3224 return FALSE;
3225 }
3226 else
3227 return TRUE;
3228 }
3229
3230 static gboolean
gnc_option_set_ui_value_multichoice(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3231 gnc_option_set_ui_value_multichoice (GNCOption *option, gboolean use_default,
3232 GtkWidget *widget, SCM value)
3233 {
3234 int index;
3235
3236 index = gnc_option_permissible_value_index (option, value);
3237 if (index < 0)
3238 return TRUE;
3239 else
3240 {
3241 gtk_combo_box_set_active (GTK_COMBO_BOX(widget), index);
3242 return FALSE;
3243 }
3244 }
3245
3246 static gboolean
gnc_option_set_ui_value_date(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3247 gnc_option_set_ui_value_date (GNCOption *option, gboolean use_default,
3248 GtkWidget *widget, SCM value)
3249 {
3250 int index;
3251 char *date_option_type;
3252 char *symbol_str;
3253 gboolean bad_value = FALSE;
3254
3255 date_option_type = gnc_option_date_option_get_subtype (option);
3256
3257 if (scm_is_pair (value))
3258 {
3259 symbol_str = gnc_date_option_value_get_type (value);
3260 if (symbol_str)
3261 {
3262 if (g_strcmp0 (symbol_str, "relative") == 0)
3263 {
3264 SCM relative = gnc_date_option_value_get_relative (value);
3265
3266 index = gnc_option_permissible_value_index (option, relative);
3267 if (g_strcmp0 (date_option_type, "relative") == 0)
3268 {
3269 gtk_combo_box_set_active (GTK_COMBO_BOX(widget), index);
3270 }
3271 else if (g_strcmp0 (date_option_type, "both") == 0)
3272 {
3273 GList *widget_list;
3274 GtkWidget *rel_date_widget;
3275
3276 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
3277 rel_date_widget = g_list_nth_data (widget_list,
3278 GNC_RD_WID_REL_WIDGET_POS);
3279 g_list_free (widget_list);
3280 gnc_date_option_set_select_method (option, FALSE, TRUE);
3281 gtk_combo_box_set_active (GTK_COMBO_BOX(rel_date_widget), index);
3282 }
3283 else
3284 bad_value = TRUE;
3285 }
3286 else if (g_strcmp0 (symbol_str, "absolute") == 0)
3287 {
3288 time64 time;
3289
3290 time = gnc_date_option_value_get_absolute (value);
3291
3292 if (g_strcmp0 (date_option_type, "absolute") == 0)
3293 {
3294 gnc_date_edit_set_time (GNC_DATE_EDIT(widget), time);
3295 }
3296 else if (g_strcmp0 (date_option_type, "both") == 0)
3297 {
3298 GList *widget_list;
3299 GtkWidget *ab_widget;
3300
3301 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
3302 ab_widget = g_list_nth_data (widget_list,
3303 GNC_RD_WID_AB_WIDGET_POS);
3304 g_list_free (widget_list);
3305 gnc_date_option_set_select_method (option, TRUE, TRUE);
3306 gnc_date_edit_set_time (GNC_DATE_EDIT(ab_widget), time);
3307 }
3308 else
3309 bad_value = TRUE;
3310 }
3311 else
3312 bad_value = TRUE;
3313
3314 if (symbol_str)
3315 free (symbol_str);
3316 }
3317 }
3318 else
3319 bad_value = TRUE;
3320
3321 if (date_option_type)
3322 free (date_option_type);
3323
3324 return bad_value;
3325 }
3326
3327 static gboolean
gnc_option_set_ui_value_account_list(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3328 gnc_option_set_ui_value_account_list (GNCOption *option, gboolean use_default,
3329 GtkWidget *widget, SCM value)
3330 {
3331 GList *list;
3332
3333 list = gnc_scm_list_to_glist (value);
3334
3335 gnc_tree_view_account_set_selected_accounts (GNC_TREE_VIEW_ACCOUNT(widget),
3336 list, TRUE);
3337 g_list_free (list);
3338 return FALSE;
3339 }
3340
3341 static gboolean
gnc_option_set_ui_value_account_sel(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3342 gnc_option_set_ui_value_account_sel (GNCOption *option, gboolean use_default,
3343 GtkWidget *widget, SCM value)
3344 {
3345 Account *acc = NULL;
3346
3347 if (value != SCM_BOOL_F)
3348 {
3349 if (!SWIG_IsPointer (value))
3350 scm_misc_error ("gnc_option_set_ui_value_account_sel",
3351 "Option Value not a wcp.", value);
3352
3353 acc = SWIG_MustGetPtr (value, SWIG_TypeQuery ("_p_Account"), 4, 0);
3354 }
3355
3356 //doesn't default because this function is called to set a specific account
3357 gnc_account_sel_set_account (GNC_ACCOUNT_SEL(widget), acc, FALSE);
3358
3359 return FALSE;
3360 }
3361
3362 static gboolean
gnc_option_set_ui_value_list(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3363 gnc_option_set_ui_value_list (GNCOption *option, gboolean use_default,
3364 GtkWidget *widget, SCM value)
3365 {
3366 GtkTreeSelection *selection;
3367 GtkTreePath *path;
3368 gint row;
3369
3370 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(widget));
3371 gtk_tree_selection_unselect_all (selection);
3372
3373 while (scm_is_list (value) && !scm_is_null (value))
3374 {
3375 SCM item;
3376
3377 item = SCM_CAR(value);
3378 value = SCM_CDR(value);
3379
3380 row = gnc_option_permissible_value_index (option, item);
3381 if (row < 0)
3382 {
3383 return TRUE;
3384 }
3385
3386 path = gtk_tree_path_new_from_indices (row, -1);
3387 gtk_tree_selection_select_path (selection, path);
3388 gtk_tree_path_free (path);
3389 }
3390
3391 if (!scm_is_list (value) || !scm_is_null (value))
3392 return TRUE;
3393
3394 return FALSE;
3395 }
3396
3397 static gboolean
gnc_option_set_ui_value_number_range(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3398 gnc_option_set_ui_value_number_range (GNCOption *option, gboolean use_default,
3399 GtkWidget *widget, SCM value)
3400 {
3401 GtkSpinButton *spinner;
3402 gdouble d_value;
3403
3404 spinner = GTK_SPIN_BUTTON(widget);
3405
3406 if (scm_is_number (value))
3407 {
3408 d_value = scm_to_double (value);
3409 gtk_spin_button_set_value (spinner, d_value);
3410 return FALSE;
3411 }
3412 else
3413 return TRUE;
3414 }
3415
3416 static gboolean
gnc_option_set_ui_value_color(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3417 gnc_option_set_ui_value_color (GNCOption *option, gboolean use_default,
3418 GtkWidget *widget, SCM value)
3419 {
3420
3421 GdkRGBA color;
3422 if (gnc_option_get_color_info (option, use_default,
3423 &color.red, &color.green,
3424 &color.blue, &color.alpha))
3425 {
3426 GtkColorChooser *color_button;
3427
3428 DEBUG("red %f, green %f, blue %f, alpha %f",
3429 color.red, color.green, color.blue, color.alpha);
3430 color_button = GTK_COLOR_CHOOSER(widget);
3431
3432 gtk_color_chooser_set_rgba (color_button, &color);
3433 return FALSE;
3434 }
3435
3436 LEAVE("TRUE");
3437 return TRUE;
3438 }
3439
3440 static gboolean
gnc_option_set_ui_value_font(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3441 gnc_option_set_ui_value_font (GNCOption *option, gboolean use_default,
3442 GtkWidget *widget, SCM value)
3443 {
3444 if (scm_is_string (value))
3445 {
3446 const gchar *string;
3447
3448 string = gnc_scm_to_utf8_string (value);
3449 if ((string != NULL) && (*string != '\0'))
3450 {
3451 GtkFontButton *font_button = GTK_FONT_BUTTON(widget);
3452 gtk_font_button_set_font_name (font_button, string);
3453 }
3454 g_free ((gpointer *) string);
3455 return FALSE;
3456 }
3457 else
3458 return TRUE;
3459 }
3460
3461 static gboolean
gnc_option_set_ui_value_pixmap(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3462 gnc_option_set_ui_value_pixmap (GNCOption *option, gboolean use_default,
3463 GtkWidget *widget, SCM value)
3464 {
3465 ENTER("option %p(%s)", option, gnc_option_name (option));
3466 if (scm_is_string (value))
3467 {
3468 const gchar *string;
3469
3470 string = gnc_scm_to_locale_string (value);
3471 if (string && *string)
3472 {
3473 gchar *test;
3474 DEBUG("string = %s", string);
3475 gtk_file_chooser_select_filename (GTK_FILE_CHOOSER(widget), string);
3476 test = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(widget));
3477 g_object_set_data_full (G_OBJECT(widget), LAST_SELECTION,
3478 g_strdup (string), g_free);
3479 DEBUG("Set %s, retrieved %s", string, test ? test : "(null)");
3480 gnc_image_option_update_preview_cb (GTK_FILE_CHOOSER(widget), option);
3481 }
3482 LEAVE("FALSE");
3483 g_free ((gpointer *) string);
3484 return FALSE;
3485 }
3486
3487 LEAVE("TRUE");
3488 return TRUE;
3489 }
3490
gnc_option_set_ui_value_budget(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3491 static gboolean gnc_option_set_ui_value_budget (GNCOption *option,
3492 gboolean use_default,
3493 GtkWidget *widget,
3494 SCM value)
3495 {
3496 GncBudget *bgt;
3497
3498 // if (!scm_is_null(value)) {
3499 if (value != SCM_BOOL_F)
3500 {
3501 if (!SWIG_IsPointer (value))
3502 scm_misc_error ("gnc_option_set_ui_value_budget",
3503 "Option Value not a wcp.", value);
3504
3505 bgt = SWIG_MustGetPtr (value, SWIG_TypeQuery ("GncBudget *"), 4, 0);
3506 if (bgt)
3507 {
3508 GtkComboBox *cb = GTK_COMBO_BOX(widget);
3509 GtkTreeModel *tm = gtk_combo_box_get_model (cb);
3510 GtkTreeIter iter;
3511 if (gnc_tree_model_budget_get_iter_for_budget (tm, &iter, bgt))
3512 gtk_combo_box_set_active_iter (cb, &iter);
3513 }
3514 }
3515 //FIXME: Unimplemented.
3516 return FALSE;
3517 }
3518
3519 static gboolean
gnc_option_set_ui_value_radiobutton(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3520 gnc_option_set_ui_value_radiobutton (GNCOption *option, gboolean use_default,
3521 GtkWidget *widget, SCM value)
3522 {
3523 int index;
3524
3525 index = gnc_option_permissible_value_index (option, value);
3526 if (index < 0)
3527 return TRUE;
3528 else
3529 {
3530 GtkWidget *box, *button;
3531 GList *list;
3532 int i;
3533 gpointer val;
3534
3535 list = gtk_container_get_children (GTK_CONTAINER(widget));
3536 box = list->data;
3537 g_list_free(list);
3538
3539 list = gtk_container_get_children (GTK_CONTAINER(box));
3540 button = g_list_nth_data (list, index);
3541 g_list_free (list);
3542 g_return_val_if_fail (button, TRUE);
3543 val = g_object_get_data (G_OBJECT(button), "gnc_radiobutton_index");
3544 g_return_val_if_fail (GPOINTER_TO_INT(val) == index, TRUE);
3545
3546 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE);
3547 // g_object_set_data(G_OBJECT(widget), "gnc_radiobutton_index",
3548 // GINT_TO_POINTER(index));
3549 return FALSE;
3550 }
3551 }
3552
3553 static gboolean
gnc_option_set_ui_value_dateformat(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3554 gnc_option_set_ui_value_dateformat (GNCOption *option, gboolean use_default,
3555 GtkWidget *widget, SCM value)
3556 {
3557 GNCDateFormat * gdf = GNC_DATE_FORMAT(widget);
3558 QofDateFormat format;
3559 GNCDateMonthFormat months;
3560 gboolean years;
3561 char *custom;
3562
3563 if (gnc_dateformat_option_value_parse (value, &format, &months, &years, &custom))
3564 return TRUE;
3565
3566 gnc_date_format_set_format (gdf, format);
3567 gnc_date_format_set_months (gdf, months);
3568 gnc_date_format_set_years (gdf, years);
3569 gnc_date_format_set_custom (gdf, custom);
3570 gnc_date_format_refresh (gdf);
3571
3572 if (custom)
3573 free (custom);
3574
3575 return FALSE;
3576 }
3577
3578 static gboolean
gnc_option_set_ui_value_plot_size(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3579 gnc_option_set_ui_value_plot_size (GNCOption *option, gboolean use_default,
3580 GtkWidget *widget, SCM value)
3581 {
3582 GList* widget_list;
3583 GtkWidget *px_button, *p_button, *px_widget, *p_widget;
3584 char *symbol_str;
3585 gdouble d_value;
3586
3587 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
3588 px_button = g_list_nth_data (widget_list, 0);
3589 px_widget = g_list_nth_data (widget_list, 1);
3590 p_button = g_list_nth_data (widget_list, 2);
3591 p_widget = g_list_nth_data (widget_list, 3);
3592 g_list_free (widget_list);
3593
3594 if (scm_is_pair (value))
3595 {
3596 symbol_str = gnc_plot_size_option_value_get_type (value);
3597 d_value = gnc_plot_size_option_value_get_value (value);
3598
3599 if (symbol_str)
3600 {
3601 if (g_strcmp0 (symbol_str, "pixels") == 0) // pixel values
3602 {
3603 gtk_spin_button_set_value (GTK_SPIN_BUTTON(px_widget), d_value);
3604 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(px_button), TRUE);
3605 }
3606 else // percent values
3607 {
3608 gtk_spin_button_set_value (GTK_SPIN_BUTTON(p_widget), (d_value));
3609 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(p_button), TRUE);
3610 }
3611 return FALSE;
3612 }
3613 }
3614 return TRUE;
3615 }
3616
3617 static gboolean
gnc_option_set_ui_value_currency_accounting(GNCOption * option,gboolean use_default,GtkWidget * widget,SCM value)3618 gnc_option_set_ui_value_currency_accounting (GNCOption *option,
3619 gboolean use_default,
3620 GtkWidget *widget, SCM value)
3621 {
3622 if (scm_is_pair (value))
3623 {
3624 SCM rb_symbol;
3625
3626 rb_symbol = gnc_currency_accounting_option_value_get_method (value);
3627
3628 if (rb_symbol)
3629 {
3630 int index;
3631
3632 index = gnc_option_permissible_value_index (option, rb_symbol);
3633 if (index < 0)
3634 return TRUE;
3635 else
3636 {
3637 GtkWidget *button = NULL;
3638 gpointer val;
3639
3640 switch (index)
3641 {
3642 case 0:
3643 button = book_currency_data->gnc_currency_radiobutton_0;
3644 break;
3645 case 1:
3646 button = book_currency_data->gnc_currency_radiobutton_1;
3647 break;
3648 case 2:
3649 button = book_currency_data->gnc_currency_radiobutton_2;
3650 break;
3651 default:
3652 return TRUE;
3653 }
3654
3655 val = g_object_get_data (G_OBJECT(button),
3656 "gnc_radiobutton_index");
3657 g_return_val_if_fail (GPOINTER_TO_INT(val) == index, TRUE);
3658
3659 if (g_strcmp0 (gnc_option_permissible_value_name (option,
3660 index),
3661 "Use a Book Currency") == 0)
3662 {
3663 gnc_commodity *commodity = NULL;
3664 SCM curr_scm =
3665 gnc_currency_accounting_option_value_get_book_currency
3666 (value);
3667 SCM list_symbol =
3668 gnc_currency_accounting_option_value_get_default_policy
3669 (value);
3670 SCM acct_guid_scm =
3671 gnc_currency_accounting_option_value_get_default_account
3672 (value);
3673
3674 commodity = gnc_scm_to_commodity (curr_scm);
3675 if (commodity)
3676 {
3677 book_currency_data->retrieved_book_currency = commodity;
3678 }
3679 else
3680 {
3681 book_currency_data->retrieved_book_currency = NULL;
3682 }
3683 if (list_symbol)
3684 {
3685 book_currency_data->retrieved_policy_scm = list_symbol;
3686 }
3687 else
3688 {
3689 book_currency_data->retrieved_policy_scm = NULL;
3690 }
3691 if (acct_guid_scm)
3692 {
3693 book_currency_data->retrieved_gain_loss_acct_guid_scm =
3694 acct_guid_scm;
3695 }
3696 else
3697 {
3698 book_currency_data->retrieved_gain_loss_acct_guid_scm =
3699 NULL;
3700 }
3701 }
3702 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE);
3703 /* when an unselected button in a group is clicked the clicked
3704 button receives the “toggled” signal, as does the
3705 previously selected button; however, if the first button
3706 is active when the currency-accounting dialog is created,
3707 that is, it's read from the option, the "toggled" handler
3708 is not called while it is if any other button is active.
3709 To get desired result, that is, to set sensitivity to
3710 FALSE, explicitly call the handler here if first button */
3711 if (index == 0)
3712 {
3713 gnc_option_currency_accounting_non_book_cb (button,
3714 (gpointer) book_currency_data);
3715 }
3716 return FALSE;
3717 }
3718 }
3719 return TRUE;
3720 }
3721 return TRUE;
3722 }
3723
3724 /*************************
3725 * GET VALUE *
3726 *************************
3727 *
3728 * gnc_option_get_ui_value_<type>():
3729 *
3730 * 'widget' will be the widget returned from the
3731 * gnc_option_set_ui_widget_<type>() function.
3732 *
3733 * You should return a SCM value corresponding to the current state of the
3734 * gui widget.
3735 *
3736 */
3737 static SCM
gnc_option_get_ui_value_boolean(GNCOption * option,GtkWidget * widget)3738 gnc_option_get_ui_value_boolean (GNCOption *option, GtkWidget *widget)
3739 {
3740 gboolean active;
3741
3742 active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget));
3743 return SCM_BOOL(active);
3744 }
3745
3746 static SCM
gnc_option_get_ui_value_string(GNCOption * option,GtkWidget * widget)3747 gnc_option_get_ui_value_string (GNCOption *option, GtkWidget *widget)
3748 {
3749 char * string;
3750 SCM result;
3751
3752 string = gtk_editable_get_chars (GTK_EDITABLE(widget), 0, -1);
3753 result = scm_from_utf8_string (string ? string : "");
3754 g_free (string);
3755 return result;
3756 }
3757
3758 static SCM
gnc_option_get_ui_value_text(GNCOption * option,GtkWidget * widget)3759 gnc_option_get_ui_value_text (GNCOption *option, GtkWidget *widget)
3760 {
3761 char * string;
3762 SCM result;
3763
3764 string = xxxgtk_textview_get_text (GTK_TEXT_VIEW(widget));
3765 result = scm_from_utf8_string (string ? string : "");
3766 g_free (string);
3767 return result;
3768 }
3769
3770 static SCM
gnc_option_get_ui_value_currency(GNCOption * option,GtkWidget * widget)3771 gnc_option_get_ui_value_currency (GNCOption *option, GtkWidget *widget)
3772 {
3773 gnc_commodity *commodity;
3774
3775 commodity =
3776 gnc_currency_edit_get_currency (GNC_CURRENCY_EDIT(widget));
3777
3778 return (gnc_commodity_to_scm (commodity));
3779 }
3780
3781 static SCM
gnc_option_get_ui_value_commodity(GNCOption * option,GtkWidget * widget)3782 gnc_option_get_ui_value_commodity (GNCOption *option, GtkWidget *widget)
3783 {
3784 gnc_commodity *commodity;
3785
3786 commodity =
3787 gnc_general_select_get_selected (GNC_GENERAL_SELECT(widget));
3788
3789 return (gnc_commodity_to_scm (commodity));
3790 }
3791
3792 static SCM
gnc_option_get_ui_value_multichoice(GNCOption * option,GtkWidget * widget)3793 gnc_option_get_ui_value_multichoice (GNCOption *option, GtkWidget *widget)
3794 {
3795 int index = gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
3796 return (gnc_option_permissible_value (option, index));
3797 }
3798
3799 static SCM
gnc_option_get_ui_value_date(GNCOption * option,GtkWidget * widget)3800 gnc_option_get_ui_value_date (GNCOption *option, GtkWidget *widget)
3801 {
3802 int index;
3803 SCM type, val, result = SCM_UNDEFINED;
3804 char *subtype = gnc_option_date_option_get_subtype (option);
3805
3806 if (g_strcmp0 (subtype, "relative") == 0)
3807 {
3808 index = gtk_combo_box_get_active (GTK_COMBO_BOX(widget));
3809
3810 type = scm_from_locale_symbol ("relative");
3811 val = gnc_option_permissible_value (option, index);
3812 result = scm_cons (type, val);
3813 }
3814 else if (g_strcmp0 (subtype, "absolute") == 0)
3815 {
3816 time64 time;
3817 time = gnc_date_edit_get_date (GNC_DATE_EDIT(widget));
3818 result = scm_cons (scm_from_locale_symbol ("absolute"), scm_from_int64 (time));
3819 }
3820 else if (g_strcmp0 (subtype, "both") == 0)
3821 {
3822 time64 time;
3823 int index;
3824 SCM val;
3825 GList *widget_list;
3826 GtkWidget *ab_button, *rel_widget, *ab_widget;
3827
3828 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
3829 ab_button = g_list_nth_data (widget_list, GNC_RD_WID_AB_BUTTON_POS);
3830 ab_widget = g_list_nth_data (widget_list, GNC_RD_WID_AB_WIDGET_POS);
3831 rel_widget = g_list_nth_data (widget_list, GNC_RD_WID_REL_WIDGET_POS);
3832 g_list_free (widget_list);
3833
3834 /* if it's an absolute date */
3835 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(ab_button)))
3836 {
3837 time = gnc_date_edit_get_date (GNC_DATE_EDIT(ab_widget));
3838 result = scm_cons (scm_from_locale_symbol ("absolute"), scm_from_int64 (time));
3839 }
3840 else
3841 {
3842 index = gtk_combo_box_get_active (GTK_COMBO_BOX(rel_widget));
3843
3844 val = gnc_option_permissible_value (option, index);
3845 result = scm_cons (scm_from_locale_symbol ("relative"), val);
3846 }
3847 }
3848 g_free (subtype);
3849 return result;
3850 }
3851
3852 static SCM
gnc_option_get_ui_value_account_list(GNCOption * option,GtkWidget * widget)3853 gnc_option_get_ui_value_account_list (GNCOption *option, GtkWidget *widget)
3854 {
3855 GncTreeViewAccount *tree;
3856 GList *list;
3857 SCM result;
3858
3859 tree = GNC_TREE_VIEW_ACCOUNT(widget);
3860 list = gnc_tree_view_account_get_selected_accounts (tree);
3861
3862 /* handover list */
3863 result = gnc_glist_to_scm_list (list, "_p_Account");
3864 g_list_free (list);
3865 return result;
3866 }
3867
3868 static SCM
gnc_option_get_ui_value_account_sel(GNCOption * option,GtkWidget * widget)3869 gnc_option_get_ui_value_account_sel (GNCOption *option, GtkWidget *widget)
3870 {
3871 GNCAccountSel *gas;
3872 Account* acc;
3873
3874 gas = GNC_ACCOUNT_SEL(widget);
3875 acc = gnc_account_sel_get_account (gas);
3876
3877 if (!acc)
3878 return SCM_BOOL_F;
3879
3880 return SWIG_NewPointerObj (acc, SWIG_TypeQuery ("_p_Account"), 0);
3881 }
3882
3883 static SCM
gnc_option_get_ui_value_budget(GNCOption * option,GtkWidget * widget)3884 gnc_option_get_ui_value_budget (GNCOption *option, GtkWidget *widget)
3885 {
3886 GncBudget *bgt;
3887 GtkComboBox *cb;
3888 GtkTreeModel *tm;
3889 GtkTreeIter iter;
3890
3891 cb = GTK_COMBO_BOX(widget);
3892 gtk_combo_box_get_active_iter (cb, &iter);
3893 tm = gtk_combo_box_get_model (cb);
3894 bgt = gnc_tree_model_budget_get_budget (tm, &iter);
3895
3896 if (!bgt)
3897 return SCM_BOOL_F;
3898
3899 return SWIG_NewPointerObj (bgt, SWIG_TypeQuery ("_p_budget_s"), 0);
3900 }
3901
3902 static SCM
gnc_option_get_ui_value_list(GNCOption * option,GtkWidget * widget)3903 gnc_option_get_ui_value_list (GNCOption *option, GtkWidget *widget)
3904 {
3905 GtkTreeSelection *selection;
3906 GtkTreePath *path;
3907 SCM result;
3908 gboolean selected;
3909 gint num_rows;
3910 gint row;
3911
3912 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(widget));
3913 num_rows = gnc_option_num_permissible_values (option);
3914 result = scm_c_eval_string ("'()");
3915
3916 for (row = 0; row < num_rows; row++)
3917 {
3918 path = gtk_tree_path_new_from_indices (row, -1);
3919 selected = gtk_tree_selection_path_is_selected (selection, path);
3920 gtk_tree_path_free (path);
3921 if (selected)
3922 result = scm_cons (gnc_option_permissible_value (option, row), result);
3923 }
3924 return (scm_reverse (result));
3925 }
3926
3927 static SCM
gnc_option_get_ui_value_number_range(GNCOption * option,GtkWidget * widget)3928 gnc_option_get_ui_value_number_range (GNCOption *option, GtkWidget *widget)
3929 {
3930 GtkSpinButton *spinner;
3931 gdouble value;
3932
3933 spinner = GTK_SPIN_BUTTON(widget);
3934
3935 value = gtk_spin_button_get_value (spinner);
3936
3937 return (scm_from_double (value));
3938 }
3939
3940 static SCM
gnc_option_get_ui_value_color(GNCOption * option,GtkWidget * widget)3941 gnc_option_get_ui_value_color (GNCOption *option, GtkWidget *widget)
3942 {
3943 SCM result;
3944 GtkColorChooser *color_button;
3945 GdkRGBA color;
3946 gdouble scale;
3947
3948 ENTER("option %p(%s), widget %p",
3949 option, gnc_option_name (option), widget);
3950
3951 color_button = GTK_COLOR_CHOOSER(widget);
3952 gtk_color_chooser_get_rgba (color_button, &color);
3953
3954 scale = gnc_option_color_range (option);
3955
3956 result = SCM_EOL;
3957 result = scm_cons (scm_from_double (color.alpha * scale), result);
3958 result = scm_cons (scm_from_double (color.blue * scale), result);
3959 result = scm_cons (scm_from_double (color.green * scale), result);
3960 result = scm_cons (scm_from_double (color.red * scale), result);
3961 return result;
3962 }
3963
3964 static SCM
gnc_option_get_ui_value_font(GNCOption * option,GtkWidget * widget)3965 gnc_option_get_ui_value_font (GNCOption *option, GtkWidget *widget)
3966 {
3967 GtkFontButton *font_button = GTK_FONT_BUTTON(widget);
3968 const gchar * string;
3969
3970 string = gtk_font_button_get_font_name (font_button);
3971 return (string ? scm_from_utf8_string (string) : SCM_BOOL_F);
3972 }
3973
3974 static SCM
gnc_option_get_ui_value_pixmap(GNCOption * option,GtkWidget * widget)3975 gnc_option_get_ui_value_pixmap (GNCOption *option, GtkWidget *widget)
3976 {
3977 gchar *string;
3978 SCM result;
3979
3980 string = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(widget));
3981 DEBUG("filename %s", string ? string : "(null)");
3982 result = scm_from_utf8_string (string ? string : "");
3983 g_free (string);
3984 return result;
3985 }
3986
3987 static SCM
gnc_option_get_ui_value_radiobutton(GNCOption * option,GtkWidget * widget)3988 gnc_option_get_ui_value_radiobutton (GNCOption *option, GtkWidget *widget)
3989 {
3990 gpointer _index;
3991 int index;
3992
3993 _index = g_object_get_data (G_OBJECT(widget), "gnc_radiobutton_index");
3994 index = GPOINTER_TO_INT(_index);
3995
3996 return (gnc_option_permissible_value (option, index));
3997 }
3998
3999 static SCM
gnc_option_get_ui_value_dateformat(GNCOption * option,GtkWidget * widget)4000 gnc_option_get_ui_value_dateformat (GNCOption *option, GtkWidget *widget)
4001 {
4002 GNCDateFormat *gdf = GNC_DATE_FORMAT(widget);
4003 QofDateFormat format;
4004 GNCDateMonthFormat months;
4005 gboolean years;
4006 const char* custom;
4007
4008 format = gnc_date_format_get_format (gdf);
4009 months = gnc_date_format_get_months (gdf);
4010 years = gnc_date_format_get_years (gdf);
4011 custom = gnc_date_format_get_custom (gdf);
4012
4013 return (gnc_dateformat_option_set_value (format, months, years, custom));
4014 }
4015
4016 static SCM
gnc_option_get_ui_value_plot_size(GNCOption * option,GtkWidget * widget)4017 gnc_option_get_ui_value_plot_size (GNCOption *option, GtkWidget *widget)
4018 {
4019 GList* widget_list;
4020 GtkWidget *px_button, *px_widget, *p_widget;
4021 gdouble d_value;
4022 SCM type, val;
4023
4024 widget_list = gtk_container_get_children (GTK_CONTAINER(widget));
4025 px_button = g_list_nth_data (widget_list, 0);
4026 px_widget = g_list_nth_data (widget_list, 1);
4027 // p_button item 2
4028 p_widget = g_list_nth_data (widget_list, 3);
4029 g_list_free (widget_list);
4030
4031 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(px_button)))
4032 {
4033 type = scm_from_locale_symbol ("pixels");
4034 d_value = gtk_spin_button_get_value (GTK_SPIN_BUTTON(px_widget));
4035 }
4036 else
4037 {
4038 type = scm_from_locale_symbol ("percent");
4039 d_value = gtk_spin_button_get_value (GTK_SPIN_BUTTON(p_widget));
4040 }
4041 val = scm_from_double (d_value);
4042 return scm_cons (type, val);
4043 }
4044
4045 static SCM
gnc_option_get_ui_value_currency_accounting(GNCOption * option,GtkWidget * widget)4046 gnc_option_get_ui_value_currency_accounting (GNCOption *option,
4047 GtkWidget *widget)
4048 {
4049 gpointer _index;
4050 int index;
4051 SCM value = SCM_EOL;
4052
4053 _index = g_object_get_data (G_OBJECT(widget), "gnc_radiobutton_index");
4054 index = GPOINTER_TO_INT(_index);
4055
4056 /* build the return list in reverse order */
4057 if (g_strcmp0 (gnc_option_permissible_value_name (option, index),
4058 "Use a Book Currency") == 0)
4059 {
4060 gnc_commodity *commodity = NULL;
4061 int policy_index;
4062 SCM val;
4063 GList *list_of_policies = NULL;
4064 const char *str = NULL;
4065
4066 if (book_currency_data->default_gain_loss_account_widget)
4067 {
4068 /* get account from widget, if one selected */
4069 Account *gain_loss_account = NULL;
4070
4071 gain_loss_account =
4072 gnc_tree_view_account_get_selected_account
4073 (GNC_TREE_VIEW_ACCOUNT(
4074 book_currency_data->default_gain_loss_account_widget));
4075
4076 if (gain_loss_account == NULL)
4077 {
4078 val = SCM_BOOL_F;
4079 }
4080 else
4081 {
4082 gchar *gain_loss_account_guid = guid_to_string (
4083 xaccAccountGetGUID (gain_loss_account));
4084
4085 val = scm_from_utf8_string (gain_loss_account_guid);
4086 g_free (gain_loss_account_guid);
4087 }
4088 }
4089 else
4090 {
4091 val = SCM_BOOL_F;
4092 }
4093 value = scm_cons (val, value);
4094
4095 list_of_policies = gnc_get_valid_policy_list ();
4096 if (list_of_policies && book_currency_data->default_cost_policy_widget)
4097 {
4098 GList *l = NULL;
4099 gint i = 0;
4100
4101 policy_index =
4102 gtk_combo_box_get_active (GTK_COMBO_BOX(
4103 book_currency_data->default_cost_policy_widget));
4104 for (l = list_of_policies; l != NULL; l = l->next)
4105 {
4106 GNCPolicy *pcy = l->data;
4107 if(i == policy_index)
4108 str = PolicyGetName (pcy);
4109 i++;
4110 }
4111 g_list_free (list_of_policies);
4112 }
4113 if (str)
4114 {
4115 val = scm_from_locale_symbol (str);
4116 }
4117 else
4118 {
4119 val = SCM_BOOL_F;
4120 }
4121 value = scm_cons (val, value);
4122
4123 if (gtk_combo_box_get_active (GTK_COMBO_BOX(book_currency_data->book_currency_widget)) != -1)
4124 {
4125 commodity =
4126 gnc_currency_edit_get_currency (
4127 GNC_CURRENCY_EDIT(
4128 book_currency_data->book_currency_widget));
4129 if (commodity)
4130 {
4131 val = gnc_commodity_to_scm (commodity);
4132 }
4133 else
4134 {
4135 val = SCM_BOOL_F;
4136 }
4137 }
4138 else
4139 {
4140 val = SCM_BOOL_F;
4141 }
4142 value = scm_cons (val, value);
4143 }
4144
4145 return (scm_cons (gnc_option_permissible_value (option, index), value));
4146 }
4147
4148 /************************************/
4149 /* INITIALIZATION */
4150 /************************************/
gnc_options_initialize_options(void)4151 static void gnc_options_initialize_options (void)
4152 {
4153 static GNCOptionDef_t options[] =
4154 {
4155 {
4156 "boolean", gnc_option_set_ui_widget_boolean,
4157 gnc_option_set_ui_value_boolean, gnc_option_get_ui_value_boolean
4158 },
4159 {
4160 "string", gnc_option_set_ui_widget_string,
4161 gnc_option_set_ui_value_string, gnc_option_get_ui_value_string
4162 },
4163 {
4164 "text", gnc_option_set_ui_widget_text,
4165 (GNCOptionUISetValue)gnc_option_set_ui_value_text,
4166 gnc_option_get_ui_value_text
4167 },
4168 {
4169 "currency", gnc_option_set_ui_widget_currency,
4170 gnc_option_set_ui_value_currency, gnc_option_get_ui_value_currency
4171 },
4172 {
4173 "commodity", gnc_option_set_ui_widget_commodity,
4174 gnc_option_set_ui_value_commodity, gnc_option_get_ui_value_commodity
4175 },
4176 {
4177 "multichoice", gnc_option_set_ui_widget_multichoice,
4178 gnc_option_set_ui_value_multichoice, gnc_option_get_ui_value_multichoice
4179 },
4180 {
4181 "date", gnc_option_set_ui_widget_date,
4182 gnc_option_set_ui_value_date, gnc_option_get_ui_value_date
4183 },
4184 {
4185 "account-list", gnc_option_set_ui_widget_account_list,
4186 gnc_option_set_ui_value_account_list, gnc_option_get_ui_value_account_list
4187 },
4188 {
4189 "account-sel", gnc_option_set_ui_widget_account_sel,
4190 gnc_option_set_ui_value_account_sel, gnc_option_get_ui_value_account_sel
4191 },
4192 {
4193 "list", gnc_option_set_ui_widget_list,
4194 gnc_option_set_ui_value_list, gnc_option_get_ui_value_list
4195 },
4196 {
4197 "number-range", gnc_option_set_ui_widget_number_range,
4198 gnc_option_set_ui_value_number_range, gnc_option_get_ui_value_number_range
4199 },
4200 {
4201 "color", gnc_option_set_ui_widget_color,
4202 gnc_option_set_ui_value_color, gnc_option_get_ui_value_color
4203 },
4204 {
4205 "font", gnc_option_set_ui_widget_font,
4206 gnc_option_set_ui_value_font, gnc_option_get_ui_value_font
4207 },
4208 {
4209 "pixmap", gnc_option_set_ui_widget_pixmap,
4210 gnc_option_set_ui_value_pixmap, gnc_option_get_ui_value_pixmap
4211 },
4212 {
4213 "radiobutton", gnc_option_set_ui_widget_radiobutton,
4214 gnc_option_set_ui_value_radiobutton, gnc_option_get_ui_value_radiobutton
4215 },
4216 {
4217 "dateformat", gnc_option_set_ui_widget_dateformat,
4218 gnc_option_set_ui_value_dateformat, gnc_option_get_ui_value_dateformat
4219 },
4220 {
4221 "plot-size", gnc_option_set_ui_widget_plot_size,
4222 gnc_option_set_ui_value_plot_size, gnc_option_get_ui_value_plot_size
4223 },
4224 {
4225 "budget", gnc_option_set_ui_widget_budget,
4226 gnc_option_set_ui_value_budget, gnc_option_get_ui_value_budget
4227 },
4228 {
4229 "currency-accounting",
4230 gnc_option_set_ui_widget_currency_accounting,
4231 gnc_option_set_ui_value_currency_accounting,
4232 gnc_option_get_ui_value_currency_accounting
4233 },
4234 { NULL, NULL, NULL, NULL }
4235 };
4236 int i;
4237
4238 for (i = 0; options[i].option_name; i++)
4239 gnc_options_ui_register_option (&(options[i]));
4240 }
4241
4242 /* Register a new option type in the UI */
gnc_options_ui_register_option(GNCOptionDef_t * option)4243 void gnc_options_ui_register_option (GNCOptionDef_t *option)
4244 {
4245 g_return_if_fail (optionTable);
4246 g_return_if_fail (option);
4247
4248 /* FIXME: should protect against repeat insertion. */
4249 g_hash_table_insert (optionTable, (gpointer)(option->option_name), option);
4250 }
4251
gnc_options_ui_get_option(const char * option_name)4252 GNCOptionDef_t * gnc_options_ui_get_option (const char *option_name)
4253 {
4254 GNCOptionDef_t *retval;
4255 g_return_val_if_fail (optionTable, NULL);
4256 g_return_val_if_fail (option_name, NULL);
4257
4258 retval = g_hash_table_lookup (optionTable, option_name);
4259 if (!retval)
4260 {
4261 PERR("Option lookup for type '%s' failed!", option_name);
4262 }
4263 return retval;
4264 }
4265
gnc_options_ui_initialize(void)4266 void gnc_options_ui_initialize (void)
4267 {
4268 SWIG_GetModule (NULL); /* Work-around for SWIG bug. */
4269 // gnc_options_register_stocks ();
4270 g_return_if_fail (optionTable == NULL);
4271 optionTable = g_hash_table_new (g_str_hash, g_str_equal);
4272
4273 /* add known types */
4274 gnc_options_initialize_options ();
4275 }
4276
4277 struct scm_cb
4278 {
4279 SCM apply_cb;
4280 SCM close_cb;
4281 };
4282
4283 static void
scm_apply_cb(GNCOptionWin * win,gpointer data)4284 scm_apply_cb (GNCOptionWin *win, gpointer data)
4285 {
4286 struct scm_cb *cbdata = data;
4287
4288 if (gnc_option_db_get_changed (win->option_db))
4289 {
4290 GList *results = NULL, *iter;
4291 results = gnc_option_db_commit (win->option_db);
4292 for (iter = results; iter; iter = iter->next)
4293 {
4294 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(gnc_options_dialog_widget (win)),
4295 0,
4296 GTK_MESSAGE_ERROR,
4297 GTK_BUTTONS_OK,
4298 "%s",
4299 (char*)iter->data);
4300 gtk_dialog_run (GTK_DIALOG(dialog));
4301 gtk_widget_destroy (dialog);
4302 g_free (iter->data);
4303 }
4304 g_list_free (results);
4305
4306 if (cbdata->apply_cb != SCM_BOOL_F)
4307 {
4308 scm_call_0 (cbdata->apply_cb);
4309 }
4310 }
4311 }
4312
4313 static void
scm_close_cb(GNCOptionWin * win,gpointer data)4314 scm_close_cb (GNCOptionWin *win, gpointer data)
4315 {
4316 struct scm_cb *cbdata = data;
4317
4318 if (cbdata->close_cb != SCM_BOOL_F)
4319 {
4320 scm_call_0 (cbdata->close_cb);
4321 scm_gc_unprotect_object (cbdata->close_cb);
4322 }
4323
4324 if (cbdata->apply_cb != SCM_BOOL_F)
4325 scm_gc_unprotect_object (cbdata->apply_cb);
4326
4327 g_free (cbdata);
4328 }
4329
4330 /* Both apply_cb and close_cb should be scheme functions with 0 arguments.
4331 * References to these functions will be held until the close_cb is called
4332 */
4333 void
gnc_options_dialog_set_scm_callbacks(GNCOptionWin * win,SCM apply_cb,SCM close_cb)4334 gnc_options_dialog_set_scm_callbacks (GNCOptionWin *win, SCM apply_cb,
4335 SCM close_cb)
4336 {
4337 struct scm_cb *cbdata;
4338
4339 cbdata = g_new0 (struct scm_cb, 1);
4340 cbdata->apply_cb = apply_cb;
4341 cbdata->close_cb = close_cb;
4342
4343 if (apply_cb != SCM_BOOL_F)
4344 scm_gc_protect_object (cbdata->apply_cb);
4345
4346 if (close_cb != SCM_BOOL_F)
4347 scm_gc_protect_object (cbdata->close_cb);
4348
4349 gnc_options_dialog_set_apply_cb (win, scm_apply_cb, cbdata);
4350 gnc_options_dialog_set_close_cb (win, scm_close_cb, cbdata);
4351 }
4352