1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2018 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "ui-category.h"
34 /* our global datas */
35 extern struct HomeBank
*GLOBALS
;
36 extern struct Preferences
*PREFS
;
39 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
42 * ui_pay_comboboxentry_get_name:
44 * get the name of the active payee or -1
46 * Return value: a new allocated name tobe freed with g_free
50 ui_pay_comboboxentry_get_name(GtkComboBox
*entry_box
)
55 DB( g_print ("ui_pay_comboboxentry_get_name()\n") );
57 cbname
= (gchar
*)gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box
))));
60 name
= g_strdup(cbname
);
69 * ui_pay_comboboxentry_get_key_add_new:
71 * get the key of the active payee
72 * and create the payee if it do not exists
74 * Return value: the key or 0
78 ui_pay_comboboxentry_get_key_add_new(GtkComboBox
*entry_box
)
83 name
= ui_pay_comboboxentry_get_name(entry_box
);
85 item
= da_pay_get_by_name(name
);
89 //todo: check prefs + ask the user here 1st time
90 item
= da_pay_malloc();
91 item
->name
= g_strdup(name
);
93 ui_pay_comboboxentry_add(entry_box
, item
);
102 * ui_pay_comboboxentry_get_key:
104 * get the key of the active payee
106 * Return value: the key or 0
110 ui_pay_comboboxentry_get_key(GtkComboBox
*entry_box
)
115 name
= ui_pay_comboboxentry_get_name(entry_box
);
116 item
= da_pay_get_by_name(name
);
127 *ui_pay_comboboxentry_get(GtkComboBox
*entry_box
)
132 DB( g_print ("ui_pay_comboboxentry_get()\n") );
134 name
= (gchar
*)gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box
))));
135 item
= da_pay_get_by_name(name
);
142 ui_pay_comboboxentry_set_active(GtkComboBox
*entry_box
, guint32 key
)
148 item
= da_pay_get(key
);
151 gtk_entry_set_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box
))), item
->name
);
155 gtk_entry_set_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box
))), "");
160 * ui_pay_comboboxentry_add:
162 * Add a single element (useful for dynamics add)
168 ui_pay_comboboxentry_add(GtkComboBox
*entry_box
, Payee
*pay
)
170 if( pay
->name
!= NULL
)
175 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(entry_box
));
177 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
178 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
, 0, pay
->name
, -1);
183 ui_pay_comboboxentry_populate_ghfunc(gpointer key
, gpointer value
, struct payPopContext
*ctx
)
188 if( ( pay
->key
!= ctx
->except_key
) )
190 //gtk_list_store_append (GTK_LIST_STORE(ctx->model), &iter);
191 //gtk_list_store_set (GTK_LIST_STORE(ctx->model), &iter, 0, pay->name, -1);
192 gtk_list_store_insert_with_values(GTK_LIST_STORE(ctx
->model
), &iter
, -1,
198 * ui_pay_comboboxentry_populate:
200 * Populate the list and completion
206 ui_pay_comboboxentry_populate(GtkComboBox
*entry_box
, GHashTable
*hash
)
208 ui_pay_comboboxentry_populate_except(entry_box
, hash
, -1);
212 ui_pay_comboboxentry_populate_except(GtkComboBox
*entry_box
, GHashTable
*hash
, guint except_key
)
215 //GtkEntryCompletion *completion;
216 struct payPopContext ctx
;
218 DB( g_print ("ui_pay_comboboxentry_populate\n") );
220 model
= gtk_combo_box_get_model(GTK_COMBO_BOX(entry_box
));
221 //completion = gtk_entry_get_completion(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box))));
223 /* keep our model alive and detach from comboboxentry and completion */
224 //g_object_ref(model);
225 //gtk_combo_box_set_model(GTK_COMBO_BOX(entry_box), NULL);
226 //gtk_entry_completion_set_model (completion, NULL);
228 /* clear and populate */
230 ctx
.except_key
= except_key
;
231 gtk_list_store_clear (GTK_LIST_STORE(model
));
233 //gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(GTK_LIST_STORE(model)), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
235 g_hash_table_foreach(hash
, (GHFunc
)ui_pay_comboboxentry_populate_ghfunc
, &ctx
);
237 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model
), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
, GTK_SORT_ASCENDING
);
239 /* reatach our model */
240 //g_print("reattach\n");
241 //gtk_combo_box_set_model(GTK_COMBO_BOX(entry_box), model);
242 //gtk_entry_completion_set_model (completion, model);
243 //g_object_unref(model);
249 ui_pay_comboboxentry_compare_func (GtkTreeModel
*model
, GtkTreeIter
*a
, GtkTreeIter
*b
, gpointer userdata
)
252 gchar
*name1
, *name2
;
254 gtk_tree_model_get(model
, a
, 0, &name1
, -1);
255 gtk_tree_model_get(model
, b
, 0, &name2
, -1);
257 retval
= hb_string_utf8_compare(name1
, name2
);
267 ui_pay_comboboxentry_test (GtkCellLayout
*cell_layout
,
268 GtkCellRenderer
*cell
,
269 GtkTreeModel
*tree_model
,
275 gtk_tree_model_get(tree_model
, iter
,
280 g_object_set(cell
, "text", _("(no payee)"), NULL
);
282 g_object_set(cell
, "text", name
, NULL
);
290 * ui_pay_comboboxentry_new:
292 * Create a new payee comboboxentry
294 * Return value: the new widget
298 ui_pay_comboboxentry_new(GtkWidget
*label
)
301 GtkWidget
*comboboxentry
;
302 GtkEntryCompletion
*completion
;
303 GtkCellRenderer
*renderer
;
305 DB( g_print ("ui_pay_comboboxentry_new()\n") );
307 store
= gtk_list_store_new (1,
310 gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store
), ui_pay_comboboxentry_compare_func
, NULL
, NULL
);
312 completion
= gtk_entry_completion_new ();
313 gtk_entry_completion_set_model (completion
, GTK_TREE_MODEL(store
));
314 g_object_set(completion
, "text-column", 0, NULL
);
316 renderer
= gtk_cell_renderer_text_new ();
317 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion
), renderer
, TRUE
);
318 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion
), renderer
, "text", 0, NULL
);
320 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion
),
322 ui_pay_comboboxentry_test
,
325 // dothe same for combobox
327 comboboxentry
= gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(store
));
328 gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboboxentry
), 0);
330 gtk_cell_layout_clear(GTK_CELL_LAYOUT (comboboxentry
));
332 renderer
= gtk_cell_renderer_text_new ();
333 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comboboxentry
), renderer
, TRUE
);
334 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (comboboxentry
), renderer
, "text", 0, NULL
);
336 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (comboboxentry
),
338 ui_pay_comboboxentry_test
,
343 gtk_entry_set_completion (GTK_ENTRY (gtk_bin_get_child(GTK_BIN (comboboxentry
))), completion
);
345 g_object_unref(store
);
348 gtk_label_set_mnemonic_widget (GTK_LABEL(label
), comboboxentry
);
350 gtk_widget_set_size_request(comboboxentry
, HB_MINWIDTH_LIST
, -1);
352 return comboboxentry
;
356 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
359 ui_pay_listview_toggled_cb (GtkCellRendererToggle
*cell
,
363 GtkTreeModel
*model
= (GtkTreeModel
*)data
;
365 GtkTreePath
*path
= gtk_tree_path_new_from_string (path_str
);
368 /* get toggled iter */
369 gtk_tree_model_get_iter (model
, &iter
, path
);
370 gtk_tree_model_get (model
, &iter
, LST_DEFPAY_TOGGLE
, &fixed
, -1);
372 /* do something with the value */
376 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
, LST_DEFPAY_TOGGLE
, fixed
, -1);
379 gtk_tree_path_free (path
);
384 ui_pay_listview_compare_func (GtkTreeModel
*model
, GtkTreeIter
*a
, GtkTreeIter
*b
, gpointer userdata
)
386 gint sortcol
= GPOINTER_TO_INT(userdata
);
387 Payee
*entry1
, *entry2
;
390 gtk_tree_model_get(model
, a
, LST_DEFPAY_DATAS
, &entry1
, -1);
391 gtk_tree_model_get(model
, b
, LST_DEFPAY_DATAS
, &entry2
, -1);
395 case LST_DEFPAY_SORT_NAME
:
396 retval
= hb_string_utf8_compare(entry1
->name
, entry2
->name
);
398 case LST_DEFPAY_SORT_USED
:
399 retval
= entry1
->usage_count
- entry2
->usage_count
;
401 case LST_DEFPAY_SORT_DEFCAT
:
404 gchar
*name1
, *name2
;
406 c1
= da_cat_get(entry1
->kcat
);
407 c2
= da_cat_get(entry2
->kcat
);
408 if( c1
!= NULL
&& c2
!= NULL
)
410 name1
= da_cat_get_fullname(c1
);
411 name2
= da_cat_get_fullname(c2
);
412 retval
= hb_string_utf8_compare(name1
, name2
);
419 g_return_val_if_reached(0);
427 ui_pay_listview_count_cell_data_function (GtkTreeViewColumn
*col
,
428 GtkCellRenderer
*renderer
,
436 gtk_tree_model_get(model
, iter
, LST_DEFPAY_DATAS
, &entry
, -1);
437 if(entry
->usage_count
> 0)
439 g_snprintf(buffer
, 256-1, "%d", entry
->usage_count
);
440 g_object_set(renderer
, "text", buffer
, NULL
);
443 g_object_set(renderer
, "text", "", NULL
);
448 ui_pay_listview_defcat_cell_data_function (GtkTreeViewColumn
*col
,
449 GtkCellRenderer
*renderer
,
458 gtk_tree_model_get(model
, iter
, LST_DEFPAY_DATAS
, &entry
, -1);
460 cat
= da_cat_get(entry
->kcat
);
463 fullname
= da_cat_get_fullname(cat
);
464 g_object_set(renderer
, "text", fullname
, NULL
);
468 g_object_set(renderer
, "text", "", NULL
);
473 ui_pay_listview_name_cell_data_function (GtkTreeViewColumn
*col
,
474 GtkCellRenderer
*renderer
,
485 gtk_tree_model_get(model
, iter
, LST_DEFPAY_DATAS
, &entry
, -1);
488 name
= _("(no payee)");
493 string
= g_strdup_printf ("%d > %s [ft=%d]", entry
->key
, name
, entry
->filter
);
494 g_object_set(renderer
, "text", string
, NULL
);
497 g_object_set(renderer
, "text", name
, NULL
);
503 /* = = = = = = = = = = = = = = = = */
507 ui_pay_listview_add(GtkTreeView
*treeview
, Payee
*item
)
512 if( item
->name
!= NULL
)
514 model
= gtk_tree_view_get_model(treeview
);
516 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
517 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
518 LST_DEFPAY_TOGGLE
, FALSE
,
519 LST_DEFPAY_DATAS
, item
,
525 ui_pay_listview_get_selected_key(GtkTreeView
*treeview
)
527 GtkTreeSelection
*selection
;
531 selection
= gtk_tree_view_get_selection(treeview
);
532 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
))
536 gtk_tree_model_get(model
, &iter
, LST_DEFPAY_DATAS
, &item
, -1);
545 ui_pay_listview_remove_selected(GtkTreeView
*treeview
)
547 GtkTreeSelection
*selection
;
551 DB( g_print("ui_pay_listview_remove_selected() \n") );
553 selection
= gtk_tree_view_get_selection(treeview
);
554 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
))
556 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
561 static void ui_pay_listview_populate_ghfunc(gpointer key
, gpointer value
, GtkTreeModel
*model
)
566 //DB( g_print(" populate: %p\n", key) );
568 //gtk_list_store_append (GTK_LIST_STORE(model), &iter);
569 //gtk_list_store_set (GTK_LIST_STORE(model), &iter,
570 gtk_list_store_insert_with_values(GTK_LIST_STORE(model
), &iter
, -1,
571 LST_DEFPAY_TOGGLE
, FALSE
,
572 LST_DEFPAY_DATAS
, item
,
576 void ui_pay_listview_populate(GtkWidget
*view
)
580 DB( g_print("ui_pay_listview_populate \n") );
582 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(view
));
583 gtk_list_store_clear (GTK_LIST_STORE(model
));
585 //g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
586 //gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL); /* Detach model from view */
589 g_hash_table_foreach(GLOBALS
->h_pay
, (GHFunc
)ui_pay_listview_populate_ghfunc
, model
);
591 //gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); /* Re-attach model to view */
592 //g_object_unref(model);
596 static gboolean
ui_pay_listview_search_equal_func (GtkTreeModel
*model
,
600 gpointer search_data
)
602 gboolean retval
= TRUE
;
603 gchar
*normalized_string
;
604 gchar
*normalized_key
;
605 gchar
*case_normalized_string
= NULL
;
606 gchar
*case_normalized_key
= NULL
;
609 //gtk_tree_model_get_value (model, iter, column, &value);
610 gtk_tree_model_get(model
, iter
, LST_DEFPAY_DATAS
, &item
, -1);
614 normalized_string
= g_utf8_normalize (item
->name
, -1, G_NORMALIZE_ALL
);
615 normalized_key
= g_utf8_normalize (key
, -1, G_NORMALIZE_ALL
);
617 if (normalized_string
&& normalized_key
)
619 case_normalized_string
= g_utf8_casefold (normalized_string
, -1);
620 case_normalized_key
= g_utf8_casefold (normalized_key
, -1);
622 if (strncmp (case_normalized_key
, case_normalized_string
, strlen (case_normalized_key
)) == 0)
626 g_free (normalized_key
);
627 g_free (normalized_string
);
628 g_free (case_normalized_key
);
629 g_free (case_normalized_string
);
636 ui_pay_listview_new(gboolean withtoggle
, gboolean withcount
)
640 GtkCellRenderer
*renderer
;
641 GtkTreeViewColumn
*column
;
643 DB( g_print("ui_pay_listview_new() \n") );
645 store
= gtk_list_store_new(
651 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
));
652 g_object_unref(store
);
654 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview
), PREFS
->grid_lines
);
657 if( withtoggle
== TRUE
)
659 renderer
= gtk_cell_renderer_toggle_new ();
660 column
= gtk_tree_view_column_new_with_attributes (_("Visible"),
661 renderer
, "active", LST_DEFPAY_TOGGLE
, NULL
);
662 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
664 g_signal_connect (G_OBJECT(renderer
), "toggled",
665 G_CALLBACK (ui_pay_listview_toggled_cb
), store
);
670 renderer
= gtk_cell_renderer_text_new ();
671 g_object_set(renderer
,
672 "ellipsize", PANGO_ELLIPSIZE_END
,
673 "ellipsize-set", TRUE
,
676 column
= gtk_tree_view_column_new();
677 gtk_tree_view_column_set_title(column
, _("Name"));
678 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
679 gtk_tree_view_column_set_cell_data_func(column
, renderer
, ui_pay_listview_name_cell_data_function
, GINT_TO_POINTER(LST_DEFPAY_DATAS
), NULL
);
680 gtk_tree_view_column_set_alignment (column
, 0.5);
681 gtk_tree_view_column_set_min_width(column
, HB_MINWIDTH_LIST
);
682 gtk_tree_view_column_set_sort_column_id (column
, LST_DEFPAY_SORT_NAME
);
683 gtk_tree_view_column_set_resizable(column
, TRUE
);
684 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
687 if( withcount
== TRUE
)
689 renderer
= gtk_cell_renderer_text_new ();
690 g_object_set(renderer
, "xalign", 0.5, NULL
);
692 column
= gtk_tree_view_column_new();
693 gtk_tree_view_column_set_title(column
, _("Usage"));
694 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
695 gtk_tree_view_column_set_cell_data_func(column
, renderer
, ui_pay_listview_count_cell_data_function
, GINT_TO_POINTER(LST_DEFPAY_DATAS
), NULL
);
696 gtk_tree_view_column_set_alignment (column
, 0.5);
697 gtk_tree_view_column_set_sort_column_id (column
, LST_DEFPAY_SORT_USED
);
698 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
702 if( withtoggle
== FALSE
)
704 renderer
= gtk_cell_renderer_text_new ();
705 g_object_set(renderer
,
706 "ellipsize", PANGO_ELLIPSIZE_END
,
707 "ellipsize-set", TRUE
,
710 column
= gtk_tree_view_column_new();
711 gtk_tree_view_column_set_title(column
, _("Default category"));
712 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
713 gtk_tree_view_column_set_cell_data_func(column
, renderer
, ui_pay_listview_defcat_cell_data_function
, GINT_TO_POINTER(LST_DEFPAY_DATAS
), NULL
);
714 gtk_tree_view_column_set_alignment (column
, 0.5);
715 gtk_tree_view_column_set_sort_column_id (column
, LST_DEFPAY_SORT_DEFCAT
);
716 gtk_tree_view_column_set_resizable(column
, TRUE
);
717 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
720 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview
), ui_pay_listview_search_equal_func
, NULL
, NULL
);
722 // treeview attribute
723 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview
), withcount
);
725 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DEFPAY_SORT_NAME
, ui_pay_listview_compare_func
, GINT_TO_POINTER(LST_DEFPAY_SORT_NAME
), NULL
);
726 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DEFPAY_SORT_USED
, ui_pay_listview_compare_func
, GINT_TO_POINTER(LST_DEFPAY_SORT_USED
), NULL
);
727 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DEFPAY_SORT_DEFCAT
, ui_pay_listview_compare_func
, GINT_TO_POINTER(LST_DEFPAY_SORT_DEFCAT
), NULL
);
729 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store
), LST_DEFPAY_SORT_NAME
, GTK_SORT_ASCENDING
);
735 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
738 ui_pay_manage_dialog_delete_unused( GtkWidget
*widget
, gpointer user_data
)
740 struct ui_pay_manage_dialog_data
*data
= user_data
;
743 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
745 DB( g_print("(ui_pay_manage_dialog) delete unused - data %p\n", data
) );
747 result
= ui_dialog_msg_confirm_alert(
748 GTK_WINDOW(data
->window
),
749 _("Delete unused payee"),
750 _("Are you sure you want to\npermanently delete unused payee?"),
754 if( result
== GTK_RESPONSE_OK
)
758 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_pay
));
759 gtk_list_store_clear (GTK_LIST_STORE(model
));
761 payee_delete_unused();
763 ui_pay_listview_populate (data
->LV_pay
);
769 * ui_pay_manage_dialog_load_csv:
773 ui_pay_manage_dialog_load_csv( GtkWidget
*widget
, gpointer user_data
)
775 struct ui_pay_manage_dialog_data
*data
= user_data
;
776 gchar
*filename
= NULL
;
779 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
781 DB( g_print("(ui_pay_manage_dialog) load csv - data %p\n", data
) );
783 if( ui_file_chooser_csv(GTK_WINDOW(data
->window
), GTK_FILE_CHOOSER_ACTION_OPEN
, &filename
, NULL
) == TRUE
)
785 DB( g_print(" + filename is %s\n", filename
) );
787 if( !payee_load_csv(filename
, &error
) )
789 ui_dialog_msg_infoerror(GTK_WINDOW(data
->window
), GTK_MESSAGE_ERROR
,
790 _("File format error"),
791 _("The CSV file must contains the exact numbers of column,\nseparated by a semi-colon, please see the help for more details.")
796 ui_pay_listview_populate(data
->LV_pay
);
801 * ui_pay_manage_dialog_save_csv:
805 ui_pay_manage_dialog_save_csv( GtkWidget
*widget
, gpointer user_data
)
807 struct ui_pay_manage_dialog_data
*data
= user_data
;
808 gchar
*filename
= NULL
;
810 DB( g_print("(ui_pay_manage_dialog) save csv\n") );
812 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
814 if( ui_file_chooser_csv(GTK_WINDOW(data
->window
), GTK_FILE_CHOOSER_ACTION_SAVE
, &filename
, NULL
) == TRUE
)
816 DB( g_print(" + filename is %s\n", filename
) );
818 payee_save_csv(filename
);
825 * ui_pay_manage_dialog_add:
829 ui_pay_manage_dialog_add(GtkWidget
*widget
, gpointer user_data
)
831 struct ui_pay_manage_dialog_data
*data
;
835 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
836 DB( g_print("(defayee) add (data=%p)\n", data
) );
838 name
= (gchar
*)gtk_entry_get_text(GTK_ENTRY(data
->ST_name
));
840 if( payee_append_if_new(name
, &item
) )
843 ui_pay_listview_add(GTK_TREE_VIEW(data
->LV_pay
), item
);
848 gtk_entry_set_text(GTK_ENTRY(data
->ST_name
), "");
852 static void ui_pay_manage_dialog_edit_entry_cb(GtkEditable
*editable
, gpointer user_data
)
854 GtkDialog
*window
= user_data
;
857 buffer
= gtk_entry_get_text(GTK_ENTRY(editable
));
858 gtk_dialog_set_response_sensitive(GTK_DIALOG(window
), GTK_RESPONSE_ACCEPT
, strlen(buffer
) > 0 ? TRUE
: FALSE
);
862 static void ui_pay_manage_dialog_edit(GtkWidget
*dowidget
, gpointer user_data
)
864 struct ui_pay_manage_dialog_data
*data
;
865 GtkWidget
*dialog
, *content_area
, *content_grid
, *group_grid
;
866 GtkWidget
*label
, *widget
;
867 GtkWidget
*ST_name
, *PO_cat
, *NU_mode
;
871 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(dowidget
, GTK_TYPE_WINDOW
)), "inst_data");
872 DB( g_print("(defayee) modify %p\n", data
) );
874 key
= ui_pay_listview_get_selected_key(GTK_TREE_VIEW(data
->LV_pay
));
879 item
= da_pay_get( key
);
881 dialog
= gtk_dialog_new_with_buttons (_("Edit..."),
882 GTK_WINDOW (data
->window
),
890 content_area
= gtk_dialog_get_content_area(GTK_DIALOG (dialog
));
892 content_grid
= gtk_grid_new();
893 gtk_grid_set_row_spacing (GTK_GRID (content_grid
), SPACING_LARGE
);
894 gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid
), GTK_ORIENTATION_VERTICAL
);
895 gtk_container_set_border_width (GTK_CONTAINER(content_grid
), SPACING_MEDIUM
);
896 gtk_box_pack_start (GTK_BOX (content_area
), content_grid
, TRUE
, TRUE
, 0);
900 group_grid
= gtk_grid_new ();
901 gtk_grid_set_row_spacing (GTK_GRID (group_grid
), SPACING_SMALL
);
902 gtk_grid_set_column_spacing (GTK_GRID (group_grid
), SPACING_MEDIUM
);
903 gtk_grid_attach (GTK_GRID (content_grid
), group_grid
, 0, crow
++, 1, 1);
905 //label = make_label_group(_("General"));
906 //gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
909 label
= make_label_widget(_("_Name:"));
910 gtk_grid_attach (GTK_GRID (group_grid
), label
, 1, row
, 1, 1);
911 widget
= gtk_entry_new();
913 gtk_widget_set_hexpand(widget
, TRUE
);
914 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
917 group_grid
= gtk_grid_new ();
918 gtk_grid_set_row_spacing (GTK_GRID (group_grid
), SPACING_SMALL
);
919 gtk_grid_set_column_spacing (GTK_GRID (group_grid
), SPACING_MEDIUM
);
920 gtk_grid_attach (GTK_GRID (content_grid
), group_grid
, 0, crow
++, 1, 1);
922 label
= make_label_group(_("Default"));
923 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, 0, 4, 1);
926 label
= make_label_widget(_("_Category:"));
927 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
928 widget
= ui_cat_comboboxentry_new(label
);
930 gtk_widget_set_hexpand (widget
, TRUE
);
931 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
934 label
= make_label_widget(_("Pa_yment:"));
935 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
936 widget
= make_paymode(label
);
938 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
941 gtk_entry_set_text(GTK_ENTRY(ST_name
), item
->name
);
942 gtk_widget_grab_focus (ST_name
);
943 gtk_entry_set_activates_default (GTK_ENTRY(ST_name
), TRUE
);
945 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(PO_cat
), GLOBALS
->h_cat
);
946 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(PO_cat
), item
->kcat
);
948 gtk_combo_box_set_active(GTK_COMBO_BOX(NU_mode
), item
->paymode
);
950 g_signal_connect (G_OBJECT (ST_name
), "changed", G_CALLBACK (ui_pay_manage_dialog_edit_entry_cb
), dialog
);
952 gtk_widget_show_all(content_grid
);
955 gtk_dialog_set_default_response(GTK_DIALOG( dialog
), GTK_RESPONSE_ACCEPT
);
958 gint result
= gtk_dialog_run (GTK_DIALOG (dialog
));
960 if(result
== GTK_RESPONSE_ACCEPT
)
964 // 1: manage renaming
965 name
= gtk_entry_get_text(GTK_ENTRY(ST_name
));
966 // ignore if item is empty
969 if( payee_rename(item
, name
) )
971 //to redraw the active entry
972 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data
->LV_pay
));
977 ui_dialog_msg_infoerror(GTK_WINDOW(dialog
), GTK_MESSAGE_ERROR
,
979 _("Cannot rename this Payee,\n"
980 "from '%s' to '%s',\n"
981 "this name already exists."),
989 item
->kcat
= ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(PO_cat
));
990 item
->paymode
= gtk_combo_box_get_active(GTK_COMBO_BOX(NU_mode
));
994 // cleanup and destroy
995 gtk_widget_destroy (dialog
);
1001 static void ui_pay_manage_dialog_merge_entry_cb(GtkComboBox
*widget
, gpointer user_data
)
1003 GtkDialog
*window
= user_data
;
1006 buffer
= (gchar
*)gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (widget
))));
1007 gtk_dialog_set_response_sensitive(GTK_DIALOG(window
), GTK_RESPONSE_OK
, strlen(buffer
) > 0 ? TRUE
: FALSE
);
1011 static void ui_pay_manage_dialog_merge(GtkWidget
*widget
, gpointer user_data
)
1013 struct ui_pay_manage_dialog_data
*data
;
1014 GtkWidget
*dialog
, *content
, *mainvbox
;
1015 GtkWidget
*getwidget
, *togglebutton
;
1016 GtkTreeSelection
*selection
;
1017 GtkTreeModel
*model
;
1020 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
1021 DB( g_print("(defayee) merge %p\n", data
) );
1023 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->LV_pay
));
1024 //if true there is a selected node
1025 if (gtk_tree_selection_get_selected(selection
, &model
, &iter
))
1031 gtk_tree_model_get(model
, &iter
, LST_DEFPAY_DATAS
, &srcpay
, -1);
1033 title
= g_strdup_printf (
1034 _("Merge payee '%s'"), srcpay
->name
);
1036 dialog
= gtk_message_dialog_new (GTK_WINDOW (data
->window
),
1037 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1038 GTK_MESSAGE_WARNING
,
1044 gtk_dialog_add_buttons (GTK_DIALOG(dialog
),
1045 _("_Cancel"), GTK_RESPONSE_CANCEL
,
1046 _("Merge"), GTK_RESPONSE_OK
,
1049 gtk_dialog_set_default_response(GTK_DIALOG (dialog
), GTK_RESPONSE_CANCEL
);
1051 content
= gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG (dialog
));
1052 mainvbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, SPACING_SMALL
);
1053 gtk_box_pack_start (GTK_BOX (content
), mainvbox
, TRUE
, TRUE
, 0);
1055 secondtext
= _("Transactions assigned to this payee,\n"
1056 "will be moved to the payee selected below.");
1058 g_object_set(GTK_MESSAGE_DIALOG (dialog
), "secondary-text", secondtext
, NULL
);
1061 getwidget
= ui_pay_comboboxentry_new(NULL
);
1062 gtk_box_pack_start (GTK_BOX (mainvbox
), getwidget
, FALSE
, FALSE
, 0);
1064 secondtext
= g_strdup_printf (
1065 _("_Delete the payee '%s'"), srcpay
->name
);
1066 togglebutton
= gtk_check_button_new_with_mnemonic(secondtext
);
1067 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togglebutton
), TRUE
);
1069 gtk_box_pack_start (GTK_BOX (mainvbox
), togglebutton
, FALSE
, FALSE
, 0);
1072 //gtk_combo_box_set_active(GTK_COMBO_BOX(getwidget), oldpos);
1073 g_signal_connect (G_OBJECT (getwidget
), "changed", G_CALLBACK (ui_pay_manage_dialog_merge_entry_cb
), dialog
);
1074 gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog
), GTK_RESPONSE_OK
, FALSE
);
1076 ui_pay_comboboxentry_populate_except(GTK_COMBO_BOX(getwidget
), GLOBALS
->h_pay
, srcpay
->key
);
1077 gtk_widget_grab_focus (getwidget
);
1079 gtk_widget_show_all(mainvbox
);
1082 gint result
= gtk_dialog_run (GTK_DIALOG (dialog
));
1084 if(result
== GTK_RESPONSE_OK
)
1086 GtkTreeModel
*model
;
1090 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_pay
));
1091 gtk_list_store_clear (GTK_LIST_STORE(model
));
1093 dstpaykey
= ui_pay_comboboxentry_get_key_add_new(GTK_COMBO_BOX(getwidget
));
1095 payee_move(srcpay
->key
, dstpaykey
);
1098 // add the new payee to listview
1099 payee
= da_pay_get(dstpaykey
);
1101 ui_pay_listview_add(GTK_TREE_VIEW(data
->LV_pay
), payee
);
1103 // delete the old payee
1104 if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(togglebutton
)) )
1106 DB( g_print(" -> delete %d '%s'\n", srcpay
->key
, srcpay
->name
) );
1108 da_pay_remove(srcpay
->key
);
1109 ui_pay_listview_remove_selected(GTK_TREE_VIEW(data
->LV_pay
));
1115 ui_pay_listview_populate(data
->LV_pay
);
1118 // cleanup and destroy
1119 gtk_widget_destroy (dialog
);
1126 ** delete the selected payee to our treeview and temp GList
1128 static void ui_pay_manage_dialog_delete(GtkWidget
*widget
, gpointer user_data
)
1130 struct ui_pay_manage_dialog_data
*data
;
1136 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
1137 DB( g_print("(ui_pay_manage_dialog) delete (data=%p)\n", data
) );
1139 key
= ui_pay_listview_get_selected_key(GTK_TREE_VIEW(data
->LV_pay
));
1143 gchar
*secondtext
= NULL
;
1145 item
= da_pay_get(key
);
1147 title
= g_strdup_printf (
1148 _("Are you sure you want to permanently delete '%s'?"), item
->name
);
1150 if( item
->usage_count
> 0 )
1152 secondtext
= _("This payee is used.\n"
1153 "Any transaction using that payee will be set to (no payee)");
1156 result
= ui_dialog_msg_confirm_alert(
1157 GTK_WINDOW(data
->window
),
1165 if( result
== GTK_RESPONSE_OK
)
1168 ui_pay_listview_remove_selected(GTK_TREE_VIEW(data
->LV_pay
));
1177 static void ui_pay_manage_dialog_update(GtkWidget
*treeview
, gpointer user_data
)
1179 struct ui_pay_manage_dialog_data
*data
;
1183 DB( g_print("\n(ui_pay_manage_dialog) cursor changed\n") );
1185 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview
), GTK_TYPE_WINDOW
)), "inst_data");
1187 key
= ui_pay_listview_get_selected_key(GTK_TREE_VIEW(data
->LV_pay
));
1189 sensitive
= (key
> 0) ? TRUE
: FALSE
;
1190 gtk_widget_set_sensitive(data
->BT_edit
, sensitive
);
1191 gtk_widget_set_sensitive(data
->BT_merge
, sensitive
);
1192 gtk_widget_set_sensitive(data
->BT_delete
, sensitive
);
1200 static void ui_pay_manage_dialog_selection(GtkTreeSelection
*treeselection
, gpointer user_data
)
1202 ui_pay_manage_dialog_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), NULL
);
1205 static void ui_pay_manage_dialog_onRowActivated (GtkTreeView
*treeview
,
1207 GtkTreeViewColumn
*col
,
1210 GtkTreeModel
*model
;
1213 DB( g_print("ui_pay_manage_dialog_onRowActivated()\n") );
1216 model
= gtk_tree_view_get_model(treeview
);
1217 gtk_tree_model_get_iter_first(model
, &iter
);
1218 if(gtk_tree_selection_iter_is_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
)), &iter
) == FALSE
)
1220 ui_pay_manage_dialog_edit(GTK_WIDGET(treeview
), NULL
);
1225 GtkWidget
*ui_pay_manage_dialog (void)
1227 struct ui_pay_manage_dialog_data data
;
1228 GtkWidget
*window
, *content
, *mainvbox
, *bbox
, *treeview
, *scrollwin
, *table
;
1229 GtkWidget
*menu
, *menuitem
, *widget
, *image
;
1232 window
= gtk_dialog_new_with_buttons (_("Manage Payees"),
1233 GTK_WINDOW(GLOBALS
->mainwindow
),
1236 GTK_RESPONSE_ACCEPT
,
1239 data
.window
= window
;
1242 gtk_window_set_icon_name(GTK_WINDOW (window
), ICONNAME_HB_PAYEE
);
1244 //set a nice dialog size
1245 gtk_window_get_size(GTK_WINDOW(GLOBALS
->mainwindow
), &w
, &h
);
1246 gtk_window_set_default_size (GTK_WINDOW(window
), -1, h
/PHI
);
1249 //store our window private data
1250 g_object_set_data(G_OBJECT(window
), "inst_data", (gpointer
)&data
);
1251 DB( g_print("(ui_pay_manage_dialog) window=%p, inst_data=%p\n", window
, &data
) );
1253 g_signal_connect (window
, "destroy",
1254 G_CALLBACK (gtk_widget_destroyed
), &window
);
1257 content
= gtk_dialog_get_content_area(GTK_DIALOG (window
));
1258 mainvbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, SPACING_SMALL
);
1259 gtk_box_pack_start (GTK_BOX (content
), mainvbox
, TRUE
, TRUE
, 0);
1260 gtk_container_set_border_width (GTK_CONTAINER(mainvbox
), SPACING_MEDIUM
);
1263 table
= gtk_grid_new ();
1264 gtk_grid_set_row_spacing (GTK_GRID (table
), SPACING_SMALL
);
1265 gtk_grid_set_column_spacing (GTK_GRID (table
), SPACING_MEDIUM
);
1266 gtk_box_pack_start (GTK_BOX (mainvbox
), table
, TRUE
, TRUE
, 0);
1269 menu
= gtk_menu_new ();
1270 gtk_widget_set_halign (menu
, GTK_ALIGN_END
);
1272 menuitem
= gtk_menu_item_new_with_mnemonic (_("_Import CSV"));
1273 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), menuitem
);
1274 g_signal_connect (G_OBJECT (menuitem
), "activate", G_CALLBACK (ui_pay_manage_dialog_load_csv
), &data
);
1276 menuitem
= gtk_menu_item_new_with_mnemonic (_("E_xport CSV"));
1277 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), menuitem
);
1278 g_signal_connect (G_OBJECT (menuitem
), "activate", G_CALLBACK (ui_pay_manage_dialog_save_csv
), &data
);
1280 menuitem
= gtk_separator_menu_item_new();
1281 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), menuitem
);
1283 menuitem
= gtk_menu_item_new_with_mnemonic (_("_Delete unused"));
1284 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), menuitem
);
1285 g_signal_connect (G_OBJECT (menuitem
), "activate", G_CALLBACK (ui_pay_manage_dialog_delete_unused
), &data
);
1287 gtk_widget_show_all (menu
);
1289 widget
= gtk_menu_button_new();
1290 image
= gtk_image_new_from_icon_name (ICONNAME_HB_BUTTON_MENU
, GTK_ICON_SIZE_MENU
);
1293 //gtk_image_get_icon_name(image, &thename, NULL);
1294 //g_print("the name is %s\n", thename);
1296 g_object_set (widget
, "image", image
, "popup", GTK_MENU(menu
), NULL
);
1297 gtk_widget_set_halign (widget
, GTK_ALIGN_END
);
1298 gtk_grid_attach (GTK_GRID (table
), widget
, 1, row
, 1, 1);
1301 data
.ST_name
= gtk_entry_new ();
1302 gtk_entry_set_placeholder_text(GTK_ENTRY(data
.ST_name
), _("new payee") );
1303 gtk_widget_set_hexpand (data
.ST_name
, TRUE
);
1304 gtk_grid_attach (GTK_GRID (table
), data
.ST_name
, 0, row
, 2, 1);
1309 scrollwin
= gtk_scrolled_window_new(NULL
,NULL
);
1310 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin
), GTK_SHADOW_ETCHED_IN
);
1311 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin
), GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
1312 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scrollwin
), HB_MINHEIGHT_LIST
);
1313 treeview
= ui_pay_listview_new(FALSE
, TRUE
);
1314 data
.LV_pay
= treeview
;
1315 gtk_container_add(GTK_CONTAINER(scrollwin
), treeview
);
1316 gtk_widget_set_hexpand (scrollwin
, TRUE
);
1317 gtk_widget_set_vexpand (scrollwin
, TRUE
);
1318 gtk_grid_attach (GTK_GRID (table
), scrollwin
, 0, row
, 2, 1);
1321 bbox
= gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL
);
1322 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox
), GTK_BUTTONBOX_START
);
1323 gtk_box_set_spacing (GTK_BOX (bbox
), SPACING_SMALL
);
1324 gtk_grid_attach (GTK_GRID (table
), bbox
, 0, row
, 2, 1);
1326 data
.BT_edit
= gtk_button_new_with_mnemonic(_("_Edit"));
1327 gtk_container_add (GTK_CONTAINER (bbox
), data
.BT_edit
);
1329 data
.BT_merge
= gtk_button_new_with_mnemonic(_("_Merge"));
1330 gtk_container_add (GTK_CONTAINER (bbox
), data
.BT_merge
);
1332 data
.BT_delete
= gtk_button_new_with_mnemonic(_("_Delete"));
1333 gtk_container_add (GTK_CONTAINER (bbox
), data
.BT_delete
);
1336 //connect all our signals
1337 g_signal_connect (G_OBJECT (data
.ST_name
), "activate", G_CALLBACK (ui_pay_manage_dialog_add
), NULL
);
1339 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data
.LV_pay
)), "changed", G_CALLBACK (ui_pay_manage_dialog_selection
), NULL
);
1340 g_signal_connect (GTK_TREE_VIEW(data
.LV_pay
), "row-activated", G_CALLBACK (ui_pay_manage_dialog_onRowActivated
), NULL
);
1342 g_signal_connect (G_OBJECT (data
.BT_edit
), "clicked", G_CALLBACK (ui_pay_manage_dialog_edit
), NULL
);
1343 g_signal_connect (G_OBJECT (data
.BT_merge
), "clicked", G_CALLBACK (ui_pay_manage_dialog_merge
), NULL
);
1344 g_signal_connect (G_OBJECT (data
.BT_delete
), "clicked", G_CALLBACK (ui_pay_manage_dialog_delete
), NULL
);
1346 //setup, init and show window
1348 ui_pay_listview_populate(data
.LV_pay
);
1349 ui_pay_manage_dialog_update(data
.LV_pay
, NULL
);
1351 gtk_widget_show_all (window
);
1354 gint result
= gtk_dialog_run (GTK_DIALOG (window
));
1358 case GTK_RESPONSE_ACCEPT
:
1359 //do_application_specific_something ();
1362 //do_nothing_since_dialog_was_cancelled ();
1366 // cleanup and destroy
1368 gtk_widget_destroy (window
);
1370 GLOBALS
->changes_count
+= data
.change
;