1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2016 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-transaction.h"
23 #include "hb-transaction.h"
24 #include "gtk-dateentry.h"
26 #include "ui-category.h"
27 #include "ui-account.h"
31 /****************************************************************************/
33 /****************************************************************************/
42 /* our global datas */
43 extern struct HomeBank
*GLOBALS
;
44 extern struct Preferences
*PREFS
;
47 extern gchar
*CYA_TYPE
[];
49 gchar
*CYA_OPERATION
[] = {
50 N_("Add transaction"),
51 N_("Inherit transaction"),
52 N_("Modify transaction")
56 gchar
*CYA_TXN_STATUS
[] = {
65 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
67 static void deftransaction_template_popover_populate(struct deftransaction_data
*data
, GList
*srclist
);
69 static void deftransaction_update(GtkWidget
*widget
, gpointer user_data
)
71 struct deftransaction_data
*data
;
74 DB( g_print("\n[ui-transaction] update\n") );
76 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
78 //# 1419476 empty category when no split either...
79 if( (data
->ope
->flags
& (OF_SPLIT
)) )
81 //# 1416624 empty category when split
82 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_grp
), 0);
85 /* disable amount+category if split is set */
86 sensitive
= (data
->ope
->flags
& (OF_SPLIT
)) ? FALSE
: TRUE
;
87 gtk_widget_set_sensitive(data
->ST_amount
, sensitive
);
88 gtk_widget_set_sensitive(data
->PO_grp
, sensitive
);
91 static void deftransaction_update_warnsign(GtkWidget
*widget
, gpointer user_data
)
93 struct deftransaction_data
*data
;
94 gboolean warning
= FALSE
;
99 DB( g_print("\n[ui-transaction] update warning sign\n") );
101 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
103 cat
= ui_cat_comboboxentry_get(GTK_COMBO_BOX(data
->PO_grp
));
104 if(cat
!= NULL
&& cat
->key
> 0)
106 amount
= hb_amount_round(gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
)), 2);
109 amttype
= (amount
> 0) ? 1 : -1;
110 warning
= (category_type_get(cat
) != amttype
) ? TRUE
: FALSE
;
115 gtk_widget_show_all(data
->IB_warnsign
);
117 gtk_widget_hide(data
->IB_warnsign
);
122 static void deftransaction_update_transfer(GtkWidget
*widget
, gpointer user_data
)
124 struct deftransaction_data
*data
;
128 DB( g_print("\n[ui-transaction] update transfer\n") );
130 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
134 kacc
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_acc
));
136 if(kacc
== 0) { sensitive
= FALSE
; goto end
; }
139 * - target account selected
143 if( gtk_combo_box_get_active(GTK_COMBO_BOX(data
->NU_mode
)) == PAYMODE_INTXFER
)
145 Account
*srcacc
, *dstacc
;
147 kdst
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_accto
));
149 if(kdst
== 0) { sensitive
= FALSE
; goto end
; }
155 srcacc
= da_acc_get(kacc
);
156 dstacc
= da_acc_get(kdst
);
157 if(srcacc
->kcur
!= dstacc
->kcur
) {
163 DB( g_print(" sensitive %d\n", sensitive
) );
166 //gtk_widget_set_sensitive(gtk_dialog_get_action_area(GTK_DIALOG (data->window)), sensitive);
167 gtk_dialog_set_response_sensitive(GTK_DIALOG (data
->window
), GTK_RESPONSE_ACCEPT
, sensitive
);
168 gtk_dialog_set_response_sensitive(GTK_DIALOG (data
->window
), GTK_RESPONSE_ADD
, sensitive
);
169 gtk_dialog_set_response_sensitive(GTK_DIALOG (data
->window
), GTK_RESPONSE_ADDKEEP
, sensitive
);
174 static void deftransaction_update_payee(GtkWidget
*widget
, gpointer user_data
)
176 struct deftransaction_data
*data
;
181 DB( g_print("\n[ui-transaction] update payee\n") );
183 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
185 // only set for empty category
186 // 1635053 and also paymode unset
187 cat
= ui_cat_comboboxentry_get(GTK_COMBO_BOX(data
->PO_grp
));
188 paymode
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->NU_mode
));
189 if( (cat
== NULL
|| cat
->key
== 0) && (paymode
== PAYMODE_NONE
) )
191 pay
= ui_pay_comboboxentry_get(GTK_COMBO_BOX(data
->PO_pay
));
194 g_signal_handlers_block_by_func (G_OBJECT (data
->PO_grp
), G_CALLBACK (deftransaction_update_warnsign
), NULL
);
195 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_grp
), pay
->kcat
);
196 g_signal_handlers_unblock_by_func (G_OBJECT (data
->PO_grp
), G_CALLBACK (deftransaction_update_warnsign
), NULL
);
198 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->NU_mode
), pay
->paymode
);
204 static void deftransaction_update_accto(GtkWidget
*widget
, gpointer user_data
)
206 struct deftransaction_data
*data
;
209 DB( g_print("\n[ui-transaction] update accto\n") );
211 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
213 kacc
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_acc
));
215 DB( g_print(" acc is %d\n", kacc
) );
217 //g_signal_handlers_block_by_func (G_OBJECT (data->PO_accto), G_CALLBACK (deftransaction_update_transfer), NULL);
218 //ui_acc_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_accto), 0);
219 //g_signal_handlers_unblock_by_func (G_OBJECT (data->PO_accto), G_CALLBACK (deftransaction_update_transfer), NULL);
221 ui_acc_comboboxentry_populate_except(GTK_COMBO_BOX(data
->PO_accto
), GLOBALS
->h_acc
, kacc
, ACC_LST_INSERT_NORMAL
);
223 deftransaction_update_transfer(widget
, user_data
);
228 void deftransaction_set_amount_from_split(GtkWidget
*widget
, gdouble amount
)
230 struct deftransaction_data
*data
;
232 DB( g_print("\n[ui-transaction] set_amount_from_split\n") );
234 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
236 DB( g_print("- amount=%.2f\n", amount
) );
238 data
->ope
->amount
= amount
;
239 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data
->ST_amount
), amount
);
241 deftransaction_update(widget
, NULL
);
246 static void deftransaction_set(GtkWidget
*widget
, gpointer user_data
)
248 struct deftransaction_data
*data
;
252 DB( g_print("\n[ui-transaction] set\n") );
254 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
258 DB( g_print(" - ope=%p data=%p tags:%p\n", data
->ope
, data
, entry
->tags
) );
260 //DB( g_print(" set date to %d\n", entry->date) );
261 //g_object_set(GTK_DATE_ENTRY(data->PO_date), "date", (guint32)entry->ope_Date);
262 gtk_date_entry_set_date(GTK_DATE_ENTRY(data
->PO_date
), (guint
)entry
->date
);
264 txt
= (entry
->wording
!= NULL
) ? entry
->wording
: "";
265 gtk_entry_set_text(GTK_ENTRY(data
->ST_word
), txt
);
266 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data
->ST_amount
), entry
->amount
);
267 //gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_amount), (entry->ope_Flags & OF_INCOME) ? 1 : 0);
269 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data
->CM_cheque
), (entry
->flags
& OF_CHEQ2
) ? 1 : 0);
271 txt
= (entry
->info
!= NULL
) ? entry
->info
: "";
272 gtk_entry_set_text(GTK_ENTRY(data
->ST_info
), txt
);
273 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_grp
), entry
->kcat
);
274 ui_pay_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_pay
), entry
->kpay
);
276 tagstr
= transaction_tags_tostring(entry
);
278 DB( g_print(" - tags: '%s'\n", txt
) );
280 txt
= (tagstr
!= NULL
) ? tagstr
: "";
281 gtk_entry_set_text(GTK_ENTRY(data
->ST_tags
), txt
);
284 radio_set_active(GTK_CONTAINER(data
->RA_status
), entry
->status
);
286 //as we trigger an event on this
287 //let's place it at the end to avoid misvalue on the trigger function
288 g_signal_handlers_block_by_func (G_OBJECT (data
->PO_acc
), G_CALLBACK (deftransaction_update_accto
), NULL
);
290 ui_acc_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_acc
), entry
->kacc
);
291 ui_acc_comboboxentry_set_active(GTK_COMBO_BOX(data
->PO_accto
), entry
->kxferacc
);
293 g_signal_handlers_unblock_by_func (G_OBJECT (data
->PO_acc
), G_CALLBACK (deftransaction_update_accto
), NULL
);
295 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->NU_mode
), entry
->paymode
);
297 DB( g_print(" - acc is: %d\n", gtk_combo_box_get_active(GTK_COMBO_BOX(data
->PO_acc
)) ) );
301 void deftransaction_get(GtkWidget
*widget
, gpointer user_data
)
303 struct deftransaction_data
*data
;
309 DB( g_print("\n[ui-transaction] get\n") );
311 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
315 DB( g_print(" - ope = %p\n", entry
) );
317 //DB( g_print(" get date to %d\n", entry->ope_Date) );
318 entry
->date
= gtk_date_entry_get_date(GTK_DATE_ENTRY(data
->PO_date
));
319 //g_object_get(GTK_DATE_ENTRY(data->PO_date), "date", entry->ope_Date);
321 //free any previous string
324 g_free(entry
->wording
);
325 entry
->wording
= NULL
;
327 txt
= (gchar
*)gtk_entry_get_text(GTK_ENTRY(data
->ST_word
));
328 // ignore if entry is empty
331 entry
->wording
= g_strdup(txt
);
334 value
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
));
335 entry
->amount
= value
;
337 /* for internal transfer add, amount must be expense */
340 if( entry->paymode == PAYMODE_INTXFER && data->type == OPERATION_EDIT_ADD )
342 if( entry->amount > 0 )
347 //free any previous string
353 txt
= (gchar
*)gtk_entry_get_text(GTK_ENTRY(data
->ST_info
));
354 // ignore if entry is empty
357 entry
->info
= g_strdup(txt
);
360 entry
->paymode
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->NU_mode
));
361 entry
->kcat
= ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data
->PO_grp
));
362 entry
->kpay
= ui_pay_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data
->PO_pay
));
363 entry
->kacc
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_acc
));
364 entry
->kxferacc
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_accto
));
367 txt
= (gchar
*)gtk_entry_get_text(GTK_ENTRY(data
->ST_tags
));
368 DB( g_print(" - tags: '%s'\n", txt
) );
369 transaction_tags_parse(entry
, txt
);
371 entry
->status
= radio_get_active(GTK_CONTAINER(data
->RA_status
));
373 //#1615245: moved here, after get combo entry key
374 if( entry
->paymode
!= PAYMODE_INTXFER
)
376 //#677351: revert kxferacc to 0
382 entry
->flags
&= (OF_SPLIT
); //(split is set in hb_transaction)
384 if( data
->type
== TRANSACTION_EDIT_ADD
|| data
->type
== TRANSACTION_EDIT_INHERIT
)
385 entry
->flags
|= OF_ADDED
;
387 if( data
->type
== TRANSACTION_EDIT_MODIFY
)
388 entry
->flags
|= OF_CHANGED
;
390 active
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data
->CM_cheque
));
391 if(active
== 1) entry
->flags
|= OF_CHEQ2
;
393 //active = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_amount));
394 active
= entry
->amount
> 0 ? TRUE
: FALSE
;
395 if(active
== TRUE
) entry
->flags
|= OF_INCOME
;
402 static gboolean
deftransaction_amount_focusout(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer user_data
)
404 struct deftransaction_data
*data
;
408 DB( g_print("\n[ui-transaction] amount focus-out-event %d\n", gtk_widget_is_focus(widget
)) );
410 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
412 paymode
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->NU_mode
));
414 // for internal transfer add, amount must be expense by default
415 if( paymode
== PAYMODE_INTXFER
&& data
->type
== TRANSACTION_EDIT_ADD
)
417 amount
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
));
419 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data
->ST_amount
), amount
*= -1);
422 deftransaction_update_warnsign(widget
, NULL
);
428 static void deftransaction_toggleamount(GtkWidget
*widget
, GtkEntryIconPosition icon_pos
, GdkEvent
*event
, gpointer user_data
)
430 struct deftransaction_data
*data
;
435 DB( g_print("\n[ui-transaction] toggleamount\n") );
437 if(icon_pos
== GTK_ENTRY_ICON_PRIMARY
)
439 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
441 gtk_spin_button_update(GTK_SPIN_BUTTON(data
->ST_amount
));
443 value
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
));
445 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data
->ST_amount
), value
);
447 if( data
->ope
->flags
& OF_SPLIT
)
449 count
= da_splits_count(data
->ope
->splits
);
450 DB( g_print("- count = %d\n", count
) );
453 split
= data
->ope
->splits
[i
];
458 deftransaction_update_warnsign(widget
, NULL
);
464 static void deftransaction_button_split_cb(GtkWidget
*widget
, gpointer user_data
)
466 struct deftransaction_data
*data
;
471 DB( g_print("\n[ui-transaction] doing split\n") );
473 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
477 amount
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
));
478 ui_split_dialog(data
->window
, ope
->splits
, amount
, &deftransaction_set_amount_from_split
);
480 //eval split to garantee disabled items
481 ope
->flags
&= ~(OF_SPLIT
);
482 nbsplit
= da_splits_count(ope
->splits
);
484 data
->ope
->flags
|= (OF_SPLIT
);
486 deftransaction_update(data
->window
, NULL
);
495 static void deftransaction_paymode(GtkWidget
*widget
, gpointer user_data
)
497 struct deftransaction_data
*data
;
502 DB( g_print("\n[ui-transaction] paymode change\n") );
504 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
506 payment
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->NU_mode
));
509 /* todo: prefill the cheque number ? */
510 if( data
->type
!= TRANSACTION_EDIT_MODIFY
)
512 gboolean expense
= (gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
)) > 0 ? FALSE
: TRUE
);
514 DB( g_print(" - payment: %d\n", PAYMODE_CHECK
) );
515 DB( g_print(" - expense: %d\n", expense
) );
516 DB( g_print(" - acc is: %d\n", ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_acc
)) ) );
518 if(payment
== PAYMODE_CHECK
)
523 gint active
= ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data
->PO_acc
));
527 DB( g_print(" - should fill cheque number for account %d\n", active
) );
532 acc
= da_acc_get( active
);
535 cheque
= ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data
->CM_cheque
))==TRUE
? acc
->cheque2
: acc
->cheque1
);
536 cheque_str
= g_strdup_printf("%d", cheque
+ 1);
537 gtk_entry_set_text(GTK_ENTRY(data
->ST_info
), cheque_str
);
546 if(payment
== PAYMODE_CHECK
)
549 sensitive
= (payment
== PAYMODE_INTXFER
) ? FALSE
: TRUE
;
550 gtk_widget_set_sensitive(data
->BT_split
, sensitive
);
552 sensitive
= page
== 1 ? TRUE
: FALSE
;
553 hb_widget_visible(data
->CM_cheque
, sensitive
);
555 if(payment
== PAYMODE_INTXFER
)
558 // for internal transfer add, amount must be expense by default
559 gdouble amount
= gtk_spin_button_get_value(GTK_SPIN_BUTTON(data
->ST_amount
));
560 if( data
->type
== TRANSACTION_EDIT_ADD
)
563 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data
->ST_amount
), amount
*= -1);
566 //if( data->type == TRANSACTION_EDIT_MODIFY )
570 gtk_label_set_text_with_mnemonic (GTK_LABEL(data
->LB_accto
), _("From acc_ount:"));
574 gtk_label_set_text_with_mnemonic (GTK_LABEL(data
->LB_accto
), _("To acc_ount:"));
581 deftransaction_update_accto(widget
, user_data
);
582 DB( g_print(" payment: %d, page: %d\n", payment
, page
) );
584 sensitive
= page
== 2 ? TRUE
: FALSE
;
585 hb_widget_visible(data
->LB_accto
, sensitive
);
586 hb_widget_visible(data
->PO_accto
, sensitive
);
592 ** called from outside
594 gint
deftransaction_external_edit(GtkWindow
*parent
, Transaction
*old_txn
, Transaction
*new_txn
)
599 dialog
= create_deftransaction_window(GTK_WINDOW(parent
), TRANSACTION_EDIT_MODIFY
, FALSE
);
600 deftransaction_set_transaction(dialog
, new_txn
);
602 result
= gtk_dialog_run (GTK_DIALOG (dialog
));
603 if(result
== GTK_RESPONSE_ACCEPT
)
605 deftransaction_get(dialog
, NULL
);
607 account_balances_sub(old_txn
);
608 account_balances_add(new_txn
);
610 if( new_txn
->paymode
== PAYMODE_INTXFER
)
612 //nota: if kxfer is 0, the user may have just changed the paymode to xfer
613 DB( g_print(" - kxfer = %d\n", new_txn
->kxfer
) );
615 if(new_txn
->kxfer
> 0) //1) search a strong linked child
619 DB( g_print(" - old_txn: kacc=%d kxferacc=%d\n", old_txn
->kacc
, old_txn
->kxferacc
) );
621 //#1584342 was faultly old_txn
622 ltxn
= transaction_xfer_child_strong_get(new_txn
);
623 if(ltxn
!= NULL
) //should never be the case
625 DB( g_print(" - strong link found, do sync\n") );
626 transaction_xfer_sync_child(new_txn
, ltxn
);
630 DB( g_print(" - no, somethin' went wrong here...\n") );
635 //2) any standard transaction that match ?
636 transaction_xfer_search_or_add_child(GTK_WINDOW(dialog
), new_txn
, FALSE
);
640 //#1250061 : manage ability to break an internal xfer
641 if(old_txn
->paymode
== PAYMODE_INTXFER
&& new_txn
->paymode
!= PAYMODE_INTXFER
)
644 gboolean break_result
;
646 DB( g_print(" - should break internal xfer\n") );
648 p_dialog
= gtk_message_dialog_new
654 _("Do you want to break the internal transfer ?\n\n"
655 "Proceeding will delete the target transaction.")
658 break_result
= gtk_dialog_run( GTK_DIALOG( p_dialog
) );
659 gtk_widget_destroy( p_dialog
);
661 if(break_result
== GTK_RESPONSE_YES
)
663 transaction_xfer_remove_child(old_txn
);
665 else //force paymode to internal xfer
667 new_txn
->paymode
= PAYMODE_INTXFER
;
672 //1638035: manage account change
673 if( old_txn
->kacc
!= new_txn
->kacc
)
675 //locked from ui, but test anyway: forbid change for internal transfer
676 if( new_txn
->paymode
== PAYMODE_INTXFER
)
678 new_txn
->kacc
= old_txn
->kacc
;
682 //todo: maybe we should restrict this also to same currency account
683 account_balances_sub(new_txn
);
684 transaction_acc_move(new_txn
, old_txn
->kacc
, new_txn
->kacc
);
685 account_balances_add(new_txn
);
690 deftransaction_dispose(dialog
, NULL
);
691 gtk_widget_destroy (dialog
);
697 void deftransaction_set_transaction(GtkWidget
*widget
, Transaction
*ope
)
699 struct deftransaction_data
*data
;
702 DB( g_print("\n[ui-transaction] set transaction (from out)\n") );
704 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
708 DB( g_print(" - ope=%p data=%p\n", data
->ope
, data
) );
710 DB( g_print(" - call init\n") );
712 deftransaction_set(widget
, NULL
);
713 deftransaction_paymode(widget
, NULL
);
714 deftransaction_update(widget
, NULL
);
715 deftransaction_update_warnsign(widget
, NULL
);
720 void deftransaction_dispose(GtkWidget
*widget
, gpointer user_data
)
722 struct deftransaction_data
*data
;
724 DB( g_print("\n[ui-transaction] dispose\n") );
726 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
732 static void deftransaction_setup(struct deftransaction_data
*data
)
735 DB( g_print("\n[ui-transaction] setup\n") );
737 ui_pay_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_pay
), GLOBALS
->h_pay
);
738 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_grp
), GLOBALS
->h_cat
);
739 ui_acc_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_acc
), GLOBALS
->h_acc
, ACC_LST_INSERT_NORMAL
);
740 ui_acc_comboboxentry_populate(GTK_COMBO_BOX(data
->PO_accto
), GLOBALS
->h_acc
, ACC_LST_INSERT_NORMAL
);
742 if( data
->showtemplate
)
744 deftransaction_template_popover_populate (data
, GLOBALS
->arc_list
);
745 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(data
->modelfilter
));
750 create_popover (GtkWidget
*parent
,
756 popover
= gtk_popover_new (parent
);
757 gtk_popover_set_position (GTK_POPOVER (popover
), pos
);
758 gtk_container_add (GTK_CONTAINER (popover
), child
);
759 gtk_container_set_border_width (GTK_CONTAINER (popover
), SPACING_SMALL
);
760 gtk_widget_show (child
);
762 /* gtk_widget_set_margin_start (popover, SPACING_MEDIUM);
763 gtk_widget_set_margin_end (popover, SPACING_MEDIUM);
764 gtk_widget_set_margin_top (popover, SPACING_MEDIUM);
765 gtk_widget_set_margin_bottom (popover, SPACING_MEDIUM);*/
771 static void deftransaction_template_popover_onRowActivated(GtkTreeView
*treeview
,
773 GtkTreeViewColumn
*col
,
776 struct deftransaction_data
*data
;
780 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview
), GTK_TYPE_WINDOW
)), "inst_data");
781 model
= gtk_tree_view_get_model(treeview
);
783 if (gtk_tree_model_get_iter(model
, &iter
, path
))
788 gtk_tree_model_get(GTK_TREE_MODEL(model
), &iter
, LST_DSPTPL_DATAS
, &arc
, -1);
791 da_transaction_init_from_template(txn
, arc
);
792 if( da_splits_clone(arc
->splits
, txn
->splits
) > 0)
793 txn
->flags
|= OF_SPLIT
; //Flag that Splits are active
795 DB( g_print(" calls\n") );
797 deftransaction_set(GTK_WIDGET(treeview
), NULL
);
798 deftransaction_paymode(GTK_WIDGET(treeview
), NULL
);
799 deftransaction_update(GTK_WIDGET(treeview
), NULL
);
801 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(data
->MB_template
), FALSE
);
807 static void deftransaction_template_popover_populate(struct deftransaction_data
*data
, GList
*srclist
)
813 //insert all glist item into treeview
815 gtk_list_store_clear(GTK_LIST_STORE(model
));
817 list
= g_list_first(srclist
);
820 Archive
*entry
= list
->data
;
822 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
823 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
824 LST_DSPTPL_DATAS
, entry
,
825 LST_DSPTPL_NAME
, entry
->wording
,
828 //DB( g_print(" populate_treeview: %d %08x\n", i, list->data) );
830 list
= g_list_next(list
);
836 deftransaction_template_popover_refilter (GtkWidget
*widget
, gpointer user_data
)
838 struct deftransaction_data
*data
= user_data
;
840 DB( g_print(" text changed\n") );
842 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(data
->modelfilter
));
846 static gboolean
deftransaction_template_popover_func_visible (GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
848 struct deftransaction_data
*data
= user_data
;
851 gboolean visible
= TRUE
;
854 showsched
= gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data
->CM_showsched
));
856 gchar
*needle
= g_ascii_strdown(gtk_entry_get_text(GTK_ENTRY(data
->ST_search
)), -1);
858 gtk_tree_model_get (model
, iter
,
859 LST_DSPTPL_DATAS
, &entry
,
860 LST_DSPTPL_NAME
, &str
, -1);
864 if( (entry
->flags
& OF_AUTO
) && !showsched
)
870 gchar
*haystack
= g_ascii_strdown(str
, -1);
872 if (str
&& g_strrstr (haystack
, needle
) == NULL
)
877 DB( g_print("filter: '%s' '%s' %d\n", str
, needle
, visible
) );
889 static GtkWidget
*deftransaction_template_popover_create(struct deftransaction_data
*data
)
892 GtkCellRenderer
*renderer
;
893 GtkTreeViewColumn
*column
;
894 GtkWidget
*box
, *widget
, *scrollwin
, *treeview
;
896 box
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, SPACING_SMALL
);
898 widget
= make_search(NULL
);
899 data
->ST_search
= widget
;
900 gtk_box_pack_start (GTK_BOX(box
), widget
, FALSE
, FALSE
, 0);
903 scrollwin
= gtk_scrolled_window_new(NULL
,NULL
);
904 gtk_box_pack_start (GTK_BOX(box
), scrollwin
, TRUE
, TRUE
, 0);
905 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin
), GTK_SHADOW_ETCHED_IN
);
906 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
908 store
= gtk_list_store_new(NUM_LST_DSPTPL
,
912 data
->model
= GTK_TREE_MODEL(store
);
914 data
->modelfilter
= GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new(GTK_TREE_MODEL(data
->model
), NULL
));
915 gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(data
->modelfilter
), deftransaction_template_popover_func_visible
, data
, NULL
);
918 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(data
->modelfilter
));
919 data
->LV_arc
= treeview
;
920 gtk_container_add(GTK_CONTAINER(scrollwin
), treeview
);
922 gtk_widget_grab_focus(treeview
);
924 /* column for bug numbers */
925 renderer
= gtk_cell_renderer_text_new ();
926 column
= gtk_tree_view_column_new_with_attributes (NULL
,
931 //gtk_tree_view_column_set_resizable (column, TRUE);
932 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
933 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview
), FALSE
);
935 widget
= gtk_check_button_new_with_mnemonic(_("Show _scheduled"));
936 data
->CM_showsched
= widget
;
937 gtk_box_pack_start (GTK_BOX(box
), widget
, FALSE
, FALSE
, 0);
939 gtk_widget_show_all (box
);
942 g_signal_connect (data
->CM_showsched
, "toggled", G_CALLBACK (deftransaction_template_popover_refilter
), data
);
943 g_signal_connect (data
->ST_search
, "search-changed", G_CALLBACK (deftransaction_template_popover_refilter
), data
);
949 static GtkWidget
*deftransaction_make_block1(struct deftransaction_data
*data
)
951 GtkWidget
*group_grid
, *hbox
, *label
, *widget
, *image
;
954 group_grid
= gtk_grid_new ();
955 gtk_grid_set_row_spacing (GTK_GRID (group_grid
), SPACING_SMALL
);
956 gtk_grid_set_column_spacing (GTK_GRID (group_grid
), SPACING_MEDIUM
);
959 label
= make_label_widget(_("_Date:"));
960 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
961 widget
= gtk_date_entry_new();
962 data
->PO_date
= widget
;
963 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
964 gtk_widget_set_halign (widget
, GTK_ALIGN_START
);
965 gtk_widget_set_tooltip_text(widget
, _("Date accepted here are:\nday,\nday/month or month/day,\nand complete date into your locale"));
968 label
= make_label_widget(_("_Amount:"));
969 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
970 hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 0);
971 gtk_grid_attach (GTK_GRID (group_grid
), hbox
, 1, row
, 1, 1);
973 widget
= make_amount(label
);
974 data
->ST_amount
= widget
;
975 gtk_entry_set_icon_from_icon_name(GTK_ENTRY(widget
), GTK_ENTRY_ICON_PRIMARY
, ICONNAME_HB_TOGGLE_SIGN
);
976 gtk_entry_set_icon_tooltip_text(GTK_ENTRY(widget
), GTK_ENTRY_ICON_PRIMARY
, _("Toggle amount sign"));
977 gtk_box_pack_start (GTK_BOX (hbox
), widget
, TRUE
, TRUE
, 0);
979 image
= gtk_image_new_from_icon_name (ICONNAME_HB_BUTTON_SPLIT
, GTK_ICON_SIZE_BUTTON
);
980 widget
= gtk_button_new();
981 g_object_set (widget
, "image", image
, NULL
);
982 data
->BT_split
= widget
;
983 gtk_box_pack_start (GTK_BOX (hbox
), widget
, FALSE
, FALSE
, 0);
984 gtk_widget_set_tooltip_text(widget
, _("Transaction splits"));
987 label
= make_label_widget(_("Pa_yment:"));
988 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
989 widget
= make_paymode(label
);
990 data
->NU_mode
= widget
;
991 gtk_widget_set_halign (widget
, GTK_ALIGN_START
);
992 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
995 widget
= gtk_check_button_new_with_mnemonic(_("Of notebook _2"));
996 data
->CM_cheque
= widget
;
997 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 2, 1);
1000 label
= make_label_widget(_("_Info:"));
1001 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1002 widget
= make_string(label
);
1003 data
->ST_info
= widget
;
1004 gtk_widget_set_hexpand (widget
, TRUE
);
1005 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1008 label
= make_label_widget(_("A_ccount:"));
1009 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1010 widget
= ui_acc_comboboxentry_new(label
);
1011 data
->PO_acc
= widget
;
1012 gtk_widget_set_hexpand (widget
, TRUE
);
1013 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1016 label
= make_label_widget(_("To acc_ount:"));
1017 data
->LB_accto
= label
;
1018 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1019 widget
= ui_acc_comboboxentry_new(label
);
1020 data
->PO_accto
= widget
;
1021 gtk_widget_set_hexpand (widget
, TRUE
);
1022 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1025 label
= make_label_widget(_("_Payee:"));
1026 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1027 widget
= ui_pay_comboboxentry_new(label
);
1028 data
->PO_pay
= widget
;
1029 gtk_widget_set_hexpand (widget
, TRUE
);
1030 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1031 gtk_widget_set_tooltip_text(widget
, _("Autocompletion and direct seizure\nis available"));
1034 label
= make_label_widget(_("_Category:"));
1035 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1036 widget
= ui_cat_comboboxentry_new(label
);
1037 data
->PO_grp
= widget
;
1038 gtk_widget_set_hexpand (widget
, TRUE
);
1039 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1040 gtk_widget_set_tooltip_text(widget
, _("Autocompletion and direct seizure\nis available"));
1043 label
= make_label_widget(_("_Status:"));
1044 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1045 widget
= make_radio(CYA_TXN_STATUS
, TRUE
, GTK_ORIENTATION_HORIZONTAL
);
1046 data
->RA_status
= widget
;
1047 gtk_widget_set_halign (widget
, GTK_ALIGN_START
);
1048 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1051 label
= make_label_widget(_("M_emo:"));
1052 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1053 widget
= make_memo_entry(label
);
1054 data
->ST_word
= widget
;
1055 gtk_widget_set_hexpand (widget
, TRUE
);
1056 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1059 label
= make_label_widget(_("Ta_gs:"));
1060 gtk_grid_attach (GTK_GRID (group_grid
), label
, 0, row
, 1, 1);
1061 widget
= make_string(label
);
1062 data
->ST_tags
= widget
;
1063 gtk_widget_set_hexpand (widget
, TRUE
);
1064 gtk_grid_attach (GTK_GRID (group_grid
), widget
, 1, row
, 1, 1);
1071 deftransaction_getgeometry(GtkWidget
*widget
, GdkEventConfigure
*event
, gpointer user_data
)
1073 struct WinGeometry
*wg
;
1075 DB( g_print("\n[ui-transaction] get geometry\n") );
1078 wg
= &PREFS
->txn_wg
;
1079 gtk_window_get_size(GTK_WINDOW(widget
), &wg
->w
, NULL
);
1081 DB( g_print(" window: w=%d\n", wg
->w
) );
1087 GtkWidget
*create_deftransaction_window (GtkWindow
*parent
, gint type
, gboolean postmode
)
1089 struct deftransaction_data
*data
;
1090 struct WinGeometry
*wg
;
1091 GtkWidget
*dialog
, *content_area
, *content_grid
, *group_grid
;
1092 GtkWidget
*label
, *bar
;
1095 DB( g_print("\n[ui-transaction] new\n") );
1097 data
= g_malloc0(sizeof(struct deftransaction_data
));
1100 dialog = gtk_dialog_new_with_buttons (_(CYA_OPERATION[data->type]),
1101 GTK_WINDOW (parent),
1106 dialog
= gtk_dialog_new();
1107 gtk_window_set_title (GTK_WINDOW(dialog
), _(CYA_OPERATION
[type
]));
1108 gtk_window_set_transient_for (GTK_WINDOW(dialog
), GTK_WINDOW(parent
));
1113 //store our window private data
1114 g_object_set_data(G_OBJECT(dialog
), "inst_data", (gpointer
)data
);
1115 DB( g_print(" - window=%p, inst_data=%p\n", dialog
, data
) );
1117 data
->window
= dialog
;
1120 // if you add/remove response_id also change into deftransaction_update_transfer
1121 if(type
== TRANSACTION_EDIT_MODIFY
)
1123 gtk_dialog_add_buttons (GTK_DIALOG(dialog
),
1124 _("_Cancel"), GTK_RESPONSE_REJECT
,
1125 _("_OK"), GTK_RESPONSE_ACCEPT
,
1132 gtk_dialog_add_buttons (GTK_DIALOG(dialog
),
1133 _("_Close"), GTK_RESPONSE_REJECT
,
1134 _("_Add & keep"), GTK_RESPONSE_ADDKEEP
,
1135 _("_Add"), GTK_RESPONSE_ADD
,
1140 gtk_dialog_add_buttons (GTK_DIALOG(dialog
),
1141 _("_Close"), GTK_RESPONSE_REJECT
,
1142 _("_Post"), GTK_RESPONSE_ADD
,
1149 case TRANSACTION_EDIT_ADD
:
1150 gtk_window_set_icon_name(GTK_WINDOW (dialog
), ICONNAME_HB_OPE_ADD
);
1152 case TRANSACTION_EDIT_INHERIT
:
1153 gtk_window_set_icon_name(GTK_WINDOW (dialog
), ICONNAME_HB_OPE_HERIT
);
1155 case TRANSACTION_EDIT_MODIFY
:
1156 gtk_window_set_icon_name(GTK_WINDOW (dialog
), ICONNAME_HB_OPE_EDIT
);
1160 //gtk_window_set_decorated(GTK_WINDOW(dialog), TRUE);
1163 content_area
= gtk_dialog_get_content_area(GTK_DIALOG (dialog
));
1165 content_grid
= gtk_grid_new();
1166 gtk_grid_set_row_spacing (GTK_GRID (content_grid
), SPACING_LARGE
);
1167 gtk_grid_set_column_spacing (GTK_GRID (content_grid
), SPACING_LARGE
);
1168 //gtk_grid_set_column_homogeneous(GTK_GRID (content_grid), TRUE);
1169 gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid
), GTK_ORIENTATION_VERTICAL
);
1170 gtk_container_set_border_width (GTK_CONTAINER(content_grid
), SPACING_MEDIUM
);
1171 gtk_container_add (GTK_CONTAINER (content_area
), content_grid
);
1172 gtk_widget_show_all(content_grid
);
1176 data
->showtemplate
= FALSE
;
1177 if( data
->type
!= TRANSACTION_EDIT_MODIFY
&& da_archive_length() > 0 && !postmode
)
1179 GtkWidget
*box
, *menubutton
, *image
;
1181 data
->showtemplate
= TRUE
;
1183 menubutton
= gtk_menu_button_new ();
1184 data
->MB_template
= menubutton
;
1185 box
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, SPACING_SMALL
);
1186 label
= gtk_label_new_with_mnemonic (_("Use a _template"));
1187 gtk_box_pack_start (GTK_BOX(box
), label
, FALSE
, FALSE
, 0);
1188 image
= gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON
);
1189 gtk_box_pack_start (GTK_BOX(box
), image
, FALSE
, FALSE
, 0);
1190 gtk_container_add(GTK_CONTAINER(menubutton
), box
);
1192 gtk_menu_button_set_direction (GTK_MENU_BUTTON(menubutton
), GTK_ARROW_DOWN
);
1193 gtk_widget_set_halign (menubutton
, GTK_ALIGN_END
);
1194 gtk_grid_attach (GTK_GRID (content_grid
), menubutton
, 0, crow
, 1, 1);
1195 gtk_widget_show_all(menubutton
);
1198 GtkWidget
*template = deftransaction_template_popover_create(data
);
1199 GtkWidget
*popover
= create_popover (menubutton
, template, GTK_POS_BOTTOM
);
1200 gtk_widget_set_size_request (popover
, HB_MINWIDTH_LIST
, HB_MINHEIGHT_LIST
);
1201 gtk_widget_set_vexpand (popover
, TRUE
);
1202 gtk_widget_set_hexpand (popover
, TRUE
);
1204 /*gtk_widget_set_margin_start (popover, 10);
1205 gtk_widget_set_margin_end (popover, 10);
1206 gtk_widget_set_margin_bottom (popover, 10);*/
1208 gtk_menu_button_set_popover(GTK_MENU_BUTTON(menubutton
), popover
);
1210 g_signal_connect (GTK_TREE_VIEW(data
->LV_arc
), "row-activated", G_CALLBACK (deftransaction_template_popover_onRowActivated
), NULL
);
1215 group_grid
= deftransaction_make_block1(data
);
1216 //gtk_widget_set_hexpand (GTK_WIDGET(group_grid), TRUE);
1217 gtk_grid_attach (GTK_GRID (content_grid
), group_grid
, 0, crow
, 1, 1);
1218 gtk_widget_show_all(group_grid
);
1221 group_grid = deftransaction_make_block2(data);
1222 gtk_widget_set_hexpand (GTK_WIDGET(group_grid), TRUE);
1223 gtk_grid_attach (GTK_GRID (content_grid), group_grid, 1, crow, 1, 1);
1224 gtk_widget_show_all(group_grid);*/
1227 bar
= gtk_info_bar_new ();
1228 data
->IB_warnsign
= bar
;
1229 gtk_info_bar_set_message_type (GTK_INFO_BAR (bar
), GTK_MESSAGE_WARNING
);
1230 label
= gtk_label_new (_("Warning: amount and category sign don't match"));
1231 gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar
))), label
, TRUE
, TRUE
, 0);
1232 gtk_grid_attach (GTK_GRID (content_grid
), bar
, 0, crow
, 1, 1);
1235 //connect all our signals
1236 g_signal_connect (dialog
, "configure-event", G_CALLBACK (deftransaction_getgeometry
), (gpointer
)data
);
1239 g_signal_connect (G_OBJECT (data
->ST_amount
), "focus-out-event", G_CALLBACK (deftransaction_amount_focusout
), NULL
);
1240 g_signal_connect (G_OBJECT (data
->ST_amount
), "icon-release", G_CALLBACK (deftransaction_toggleamount
), NULL
);
1241 g_signal_connect (G_OBJECT (data
->BT_split
), "clicked", G_CALLBACK (deftransaction_button_split_cb
), NULL
);
1243 g_signal_connect (data
->NU_mode
, "changed", G_CALLBACK (deftransaction_paymode
), NULL
);
1244 g_signal_connect (data
->CM_cheque
, "toggled", G_CALLBACK (deftransaction_paymode
), NULL
);
1246 g_signal_connect (data
->PO_pay
, "changed", G_CALLBACK (deftransaction_update_payee
), NULL
);
1247 g_signal_connect (data
->PO_acc
, "changed", G_CALLBACK (deftransaction_update_accto
), NULL
);
1248 g_signal_connect (data
->PO_accto
, "changed", G_CALLBACK (deftransaction_update_transfer
), NULL
);
1249 g_signal_connect (data
->PO_grp
, "changed", G_CALLBACK (deftransaction_update_warnsign
), NULL
);
1252 //setup, init and show window
1253 deftransaction_setup(data
);
1255 wg
= &PREFS
->txn_wg
;
1256 gtk_window_set_default_size(GTK_WINDOW(dialog
), wg
->w
, -1);
1258 //gtk_widget_show_all (dialog);
1259 //gtk_widget_hide(data->IB_warnsign);