1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 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/>.
22 #include "ui-txn-multi.h"
24 #include "ui-account.h"
26 #include "ui-category.h"
27 #include "gtk-dateentry.h"
28 #include "list-operation.h"
31 /****************************************************************************/
33 /****************************************************************************/
42 /* our global datas */
43 extern struct HomeBank
*GLOBALS
;
44 extern struct Preferences
*PREFS
;
47 void ui_multipleedit_dialog_prefill( GtkWidget
*widget
, Transaction
*ope
, gint column_id
)
49 struct ui_multipleedit_dialog_data
*data
;
52 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
54 DB( g_print ("\n[ui-multipleedit] prefill\n") );
57 //if(col_id >= LST_DSPOPE_DATE && col_id != LST_DSPOPE_BALANCE)
62 gtk_date_entry_set_date(GTK_DATE_ENTRY(data
->PO_date
), (guint
)ope
->date
);
63 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_date
), TRUE
);
65 case LST_DSPOPE_AMOUNT
:
66 case LST_DSPOPE_EXPENSE
:
67 case LST_DSPOPE_INCOME
:
68 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data
->ST_amount
), ope
->amount
);
69 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_amount
), TRUE
);
72 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->NU_mode
), ope
->paymode
);
73 gtk_entry_set_text(GTK_ENTRY(data
->ST_info
), (ope
->info
!= NULL
) ? ope
->info
: "");
74 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_mode
), TRUE
);
75 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_info
), TRUE
);
77 case LST_DSPOPE_PAYEE
:
78 ui_pay_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_pay
), ope
->kpay
);
79 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_pay
), TRUE
);
82 gtk_entry_set_text(GTK_ENTRY(data
->ST_memo
), (ope
->memo
!= NULL
) ? ope
->memo
: "");
83 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_memo
), TRUE
);
85 case LST_DSPOPE_CATEGORY
:
86 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_cat
), ope
->kcat
);
87 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_cat
), TRUE
);
90 tagstr
= tags_tostring(ope
->tags
);
91 gtk_entry_set_text(GTK_ENTRY(data
->ST_tags
), (tagstr
!= NULL
) ? tagstr
: "");
93 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->CM_tags
), TRUE
);
100 static void ui_multipleedit_dialog_update( GtkWidget
*widget
, gpointer user_data
)
102 struct ui_multipleedit_dialog_data
*data
;
104 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
106 DB( g_print ("\n[ui-multipleedit] update\n") );
109 gtk_widget_set_sensitive (data
->PO_date
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_date
)) );
112 gtk_widget_set_sensitive (data
->ST_amount
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_amount
)) );
114 if(data
->NU_mode
&& data
->ST_info
)
116 gtk_widget_set_sensitive (data
->NU_mode
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_mode
)) );
117 gtk_widget_set_sensitive (data
->ST_info
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_info
)) );
121 gtk_widget_set_sensitive (data
->PO_acc
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_acc
)) );
124 gtk_widget_set_sensitive (data
->PO_pay
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_pay
)) );
127 gtk_widget_set_sensitive (data
->PO_cat
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_cat
)) );
130 gtk_widget_set_sensitive (data
->ST_tags
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_tags
)) );
133 gtk_widget_set_sensitive (data
->ST_memo
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_memo
)) );
137 static void ui_multipleedit_dialog_init( GtkWidget
*widget
, gpointer user_data
)
139 struct ui_multipleedit_dialog_data
*data
;
141 GList
*selection
, *list
;
143 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
145 DB( g_print ("\n[ui-multipleedit] init\n") );
147 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->treeview
));
148 selection
= gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->treeview
)), &model
);
150 data
->has_xfer
= FALSE
;
152 list
= g_list_last(selection
);
158 gtk_tree_model_get_iter(model
, &iter
, list
->data
);
159 gtk_tree_model_get(model
, &iter
, MODEL_TXN_POINTER
, &entry
, -1);
161 if(entry
->paymode
== PAYMODE_INTXFER
)
162 data
->has_xfer
= TRUE
;
164 list
= g_list_previous(list
);
167 g_list_foreach(selection
, (GFunc
)gtk_tree_path_free
, NULL
);
168 g_list_free(selection
);
173 gint
ui_multipleedit_dialog_apply( GtkWidget
*widget
, gboolean
*do_sort
)
175 struct ui_multipleedit_dialog_data
*data
;
177 GList
*selection
, *list
;
178 gboolean tmp_sort
= FALSE
;
181 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
183 DB( g_print ("\n[ui-multipleedit] apply\n") );
185 changes
= GLOBALS
->changes_count
;
187 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->treeview
));
188 selection
= gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->treeview
)), &model
);
190 list
= g_list_last(selection
);
196 gboolean change
= FALSE
;
198 gtk_tree_model_get_iter(model
, &iter
, list
->data
);
199 gtk_tree_model_get(model
, &iter
, MODEL_TXN_POINTER
, &txn
, -1);
201 DB( g_print(" modifying %s %.2f\n", txn
->memo
, txn
->amount
) );
203 //TODO: this is always true
204 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_DATE
) == TRUE
)
206 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_date
)) )
208 guint32 olddate
= txn
->date
;
210 txn
->date
= gtk_date_entry_get_date(GTK_DATE_ENTRY(data
->PO_date
));
211 DB( g_print(" -> date: '%d'\n", txn
->date
) );
213 //#1270687/1792808: sort if date changed
214 if(olddate
!= txn
->date
)
221 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_AMOUNT
) == TRUE
222 || list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_EXPENSE
) == TRUE
223 || list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_INCOME
) == TRUE
)
225 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_amount
)) )
227 txn
->amount
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
));
232 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_INFO
) == TRUE
)
234 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_mode
)) )
236 txn
->paymode
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->NU_mode
));
240 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_info
)) )
249 txt
= gtk_entry_get_text(GTK_ENTRY(data
->ST_info
));
252 txn
->info
= g_strdup(txt
);
258 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_acc
)) )
260 guint32 nkacc
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_acc
));
262 if( transaction_acc_move(txn
, txn
->kacc
, nkacc
) )
266 DB( g_print(" -> acc: '%d'\n", nkacc
) );
267 gtk_tree_model_get_iter(model
, &iter
, list
->data
);
268 gtk_list_store_remove(GTK_LIST_STORE(model
), &iter
);
273 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_PAYEE
) == TRUE
)
275 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_pay
)) )
277 txn
->kpay
= ui_pay_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data
->PO_pay
));
278 DB( g_print(" -> payee: '%d'\n", txn
->kpay
) );
283 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_CATEGORY
) == TRUE
)
285 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_cat
)) )
287 if(!(txn
->flags
& OF_SPLIT
))
289 txn
->kcat
= ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data
->PO_cat
));
290 DB( g_print(" -> category: '%d'\n", txn
->kcat
) );
296 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_TAGS
) == TRUE
)
298 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_tags
)) )
300 txt
= (gchar
*)gtk_entry_get_text(GTK_ENTRY(data
->ST_tags
));
304 txn
->tags
= tags_parse(txt
);
305 DB( g_print(" -> tags: '%s'\n", txt
) );
311 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_MEMO
) == TRUE
)
313 if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_memo
)) )
322 txt
= gtk_entry_get_text(GTK_ENTRY(data
->ST_memo
));
325 txn
->memo
= g_strdup(txt
);
333 txn
->flags
|= OF_CHANGED
;
334 GLOBALS
->changes_count
++;
337 if( data
->has_xfer
&& txn
->paymode
== PAYMODE_INTXFER
)
340 child
= transaction_xfer_child_strong_get(txn
);
341 transaction_xfer_child_sync(txn
, child
);
344 list
= g_list_previous(list
);
347 g_list_foreach(selection
, (GFunc
)gtk_tree_path_free
, NULL
);
348 g_list_free(selection
);
350 if( do_sort
!= NULL
)
353 return GLOBALS
->changes_count
- changes
;
357 static gboolean
ui_multipleedit_dialog_destroy( GtkWidget
*widget
, gpointer user_data
)
359 struct ui_multipleedit_dialog_data
*data
;
361 data
= g_object_get_data(G_OBJECT(widget
), "inst_data");
363 DB( g_print ("\n[ui-multipleedit] destroy event occurred\n") );
370 GtkWidget
*ui_multipleedit_dialog_new(GtkWindow
*parent
, GtkTreeView
*treeview
)
372 struct ui_multipleedit_dialog_data
*data
;
373 GtkWidget
*dialog
, *content_area
;
374 GtkWidget
*group_grid
, *label
, *widget
, *toggle
;
377 DB( g_print ("\n[ui-multipleedit] new\n") );
379 data
= g_malloc0(sizeof(struct ui_multipleedit_dialog_data
));
381 dialog
= gtk_dialog_new_with_buttons (NULL
,
390 //g_signal_connect (dialog, "delete_event", G_CALLBACK (register_panel_dispose), (gpointer)data);
391 g_signal_connect (dialog
, "destroy", G_CALLBACK (ui_multipleedit_dialog_destroy
), (gpointer
)data
);
393 //store our window private data
394 g_object_set_data(G_OBJECT(dialog
), "inst_data", (gpointer
)data
);
395 DB( g_print(" - new window=%p, inst_data=%p\n", dialog
, data
) );
397 data
->window
= dialog
;
398 data
->treeview
= treeview
;
400 ui_multipleedit_dialog_init(dialog
, NULL
);
403 gtk_window_set_title (GTK_WINDOW (data
->window
), _("Multiple edit transactions"));
405 content_area
= gtk_dialog_get_content_area(GTK_DIALOG (dialog
));
407 group_grid
= gtk_grid_new ();
408 gtk_grid_set_row_spacing (GTK_GRID (group_grid
), SPACING_SMALL
);
409 gtk_grid_set_column_spacing (GTK_GRID (group_grid
), SPACING_MEDIUM
);
410 gtk_container_set_border_width (GTK_CONTAINER(group_grid
), SPACING_MEDIUM
);
411 gtk_container_add (GTK_CONTAINER (content_area
), group_grid
);
415 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_DATE
) == TRUE
)
418 label
= make_label_widget(_("_Date:"));
419 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
420 widget
= gtk_check_button_new();
421 data
->CM_date
= widget
;
422 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
423 widget
= gtk_date_entry_new();
424 data
->PO_date
= widget
;
425 gtk_widget_set_hexpand (widget
, TRUE
);
426 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
428 g_signal_connect (data
->CM_date
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
431 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_AMOUNT
) == TRUE
432 || list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_EXPENSE
) == TRUE
433 || list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_INCOME
) == TRUE
)
436 label
= make_label_widget(_("_Amount:"));
437 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
438 widget
= gtk_check_button_new();
439 data
->CM_amount
= widget
;
440 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
441 widget
= make_amount(label
);
442 data
->ST_amount
= widget
;
443 gtk_widget_set_hexpand (widget
, TRUE
);
444 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
446 g_signal_connect (data
->CM_amount
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
450 label
= make_label_widget(_("A_ccount:"));
451 data
->LB_acc
= label
;
452 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
453 widget
= gtk_check_button_new();
454 data
->CM_acc
= widget
;
455 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
456 widget
= ui_acc_comboboxentry_new(label
);
457 data
->PO_acc
= widget
;
458 gtk_widget_set_hexpand (widget
, TRUE
);
459 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
461 g_signal_connect (data
->CM_acc
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
463 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_INFO
) == TRUE
)
466 label
= make_label_widget(_("Pa_yment:"));
467 data
->LB_mode
= label
;
468 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
469 toggle
= gtk_check_button_new();
470 data
->CM_mode
= toggle
;
471 gtk_grid_attach (GTK_GRID (group_grid
), toggle
, 1, row
, 1, 1);
472 widget
= make_paymode_nointxfer (label
);
473 data
->NU_mode
= widget
;
474 gtk_widget_set_hexpand (widget
, TRUE
);
475 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
477 g_signal_connect (data
->CM_mode
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
480 label
= make_label_widget(_("_Info:"));
481 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
482 widget
= gtk_check_button_new();
483 data
->CM_info
= widget
;
484 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
485 widget
= make_string(label
);
486 data
->ST_info
= widget
;
487 gtk_widget_set_hexpand (widget
, TRUE
);
488 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
490 g_signal_connect (data
->CM_info
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
493 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_PAYEE
) == TRUE
)
496 label
= make_label_widget(_("_Payee:"));
497 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
498 widget
= gtk_check_button_new();
499 data
->CM_pay
= widget
;
500 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
501 widget
= ui_pay_comboboxentry_new(label
);
502 data
->PO_pay
= widget
;
503 gtk_widget_set_hexpand (widget
, TRUE
);
504 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
506 g_signal_connect (data
->CM_pay
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
509 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_CATEGORY
) == TRUE
)
512 label
= make_label_widget(_("_Category:"));
513 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
514 widget
= gtk_check_button_new();
515 data
->CM_cat
= widget
;
516 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
517 widget
= ui_cat_comboboxentry_new(label
);
518 data
->PO_cat
= widget
;
519 gtk_widget_set_hexpand (widget
, TRUE
);
520 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
522 g_signal_connect (data
->CM_cat
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
525 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_MEMO
) == TRUE
)
528 label
= make_label_widget(_("M_emo:"));
529 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
530 widget
= gtk_check_button_new();
531 data
->CM_memo
= widget
;
532 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
533 widget
= make_memo_entry(label
);
534 data
->ST_memo
= widget
;
535 gtk_widget_set_hexpand (widget
, TRUE
);
536 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
538 g_signal_connect (data
->CM_memo
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
541 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_TAGS
) == TRUE
)
544 label
= make_label_widget(_("Ta_gs:"));
545 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
546 widget
= gtk_check_button_new();
547 data
->CM_tags
= widget
;
548 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
549 widget
= make_string(label
);
550 data
->ST_tags
= widget
;
551 gtk_widget_set_hexpand (widget
, TRUE
);
552 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 2, row
, 1, 1);
554 g_signal_connect (data
->CM_tags
, "toggled", G_CALLBACK (ui_multipleedit_dialog_update
), NULL
);
557 ui_multipleedit_dialog_update(dialog
, NULL
);
559 ui_acc_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_acc
), GLOBALS
->h_acc
, ACC_LST_INSERT_NORMAL
);
560 ui_pay_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_pay
), GLOBALS
->h_pay
);
561 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_cat
), GLOBALS
->h_cat
);
563 gtk_widget_show_all (dialog
);
565 if(data
->has_xfer
== TRUE
)
567 hb_widget_visible (data
->LB_acc
, FALSE
);
568 hb_widget_visible (data
->CM_acc
, FALSE
);
569 hb_widget_visible (data
->PO_acc
, FALSE
);
572 if( list_txn_column_id_isvisible(GTK_TREE_VIEW(data
->treeview
), LST_DSPOPE_INFO
) == TRUE
)
574 if(data
->has_xfer
== TRUE
)
576 hb_widget_visible (data
->LB_mode
, FALSE
);
577 hb_widget_visible (data
->CM_mode
, FALSE
);
578 hb_widget_visible (data
->NU_mode
, FALSE
);