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/>.
23 #include "list-operation.h"
25 /****************************************************************************/
27 /****************************************************************************/
36 /* our global datas */
37 extern struct HomeBank
*GLOBALS
;
38 extern struct Preferences
*PREFS
;
42 //extern gboolean minor_active;
45 /* This is not pretty. Of course you can also use a
46 * separate compare function for each sort ID value */
48 static gint
list_txn_sort_iter_compare_strings(gchar
*s1
, gchar
*s2
)
50 return hb_string_utf8_compare(s1
, s2
);
55 list_txn_sort_iter_compare_func (GtkTreeModel
*model
,
60 gint sortcol
= GPOINTER_TO_INT(userdata
);
62 Transaction
*ope1
, *ope2
;
65 gtk_tree_model_get(model
, a
, LST_DSPOPE_DATAS
, &ope1
, -1);
66 gtk_tree_model_get(model
, b
, LST_DSPOPE_DATAS
, &ope2
, -1);
70 case LST_DSPOPE_STATUS
:
71 if(!(retval
= (ope1
->flags
& OF_ADDED
) - (ope2
->flags
& OF_ADDED
) ) )
73 retval
= (ope1
->flags
& OF_CHANGED
) - (ope2
->flags
& OF_CHANGED
);
78 if(! (retval
= ope1
->date
- ope2
->date
) )
80 //g_print("sort on balance d1=%d, d2=%d %f %f\n", ope1->date, ope2->date, ope1->balance , ope2->balance);
82 tmpval
= ope1
->pos
- ope2
->pos
;
83 retval
= tmpval
> 0 ? 1 : -1;
85 //g_print("ret=%d\n", ret);
88 case LST_DSPOPE_ACCOUNT
:
92 a1
= da_acc_get(ope1
->kacc
);
93 a2
= da_acc_get(ope2
->kacc
);
94 retval
= list_txn_sort_iter_compare_strings((a1
!= NULL
) ? a1
->name
: NULL
, (a2
!= NULL
) ? a2
->name
: NULL
);
99 if(!(retval
= ope1
->paymode
- ope2
->paymode
))
101 retval
= list_txn_sort_iter_compare_strings(ope1
->info
, ope2
->info
);
105 case LST_DSPOPE_PAYEE
:
111 if( ope1
->paymode
== PAYMODE_INTXFER
)
113 Account
*acc
= da_acc_get(ope1
->kxferacc
);
114 name1
= (acc
!= NULL
) ? acc
->name
: NULL
;
118 Payee
*pay
= da_pay_get(ope1
->kpay
);
119 name1
= (pay
!= NULL
) ? pay
->name
: NULL
;
122 if( ope2
->paymode
== PAYMODE_INTXFER
)
124 Account
*acc
= da_acc_get(ope2
->kxferacc
);
125 name2
= (acc
!= NULL
) ? acc
->name
: NULL
;
129 Payee
*pay
= da_pay_get(ope2
->kpay
);
130 name2
= (pay
!= NULL
) ? pay
->name
: NULL
;
133 retval
= list_txn_sort_iter_compare_strings(name1
, name2
);
137 case LST_DSPOPE_MEMO
:
138 retval
= list_txn_sort_iter_compare_strings(ope1
->memo
, ope2
->memo
);
142 retval
= ope1
->status
- ope2
->status
;
145 case LST_DSPOPE_AMOUNT
:
146 case LST_DSPOPE_EXPENSE
:
147 case LST_DSPOPE_INCOME
:
148 tmpval
= ope1
->amount
- ope2
->amount
;
149 retval
= tmpval
> 0 ? 1 : -1;
152 case LST_DSPOPE_CATEGORY
:
156 c1
= da_cat_get(ope1
->kcat
);
157 c2
= da_cat_get(ope2
->kcat
);
158 if( c1
!= NULL
&& c2
!= NULL
)
160 retval
= list_txn_sort_iter_compare_strings(c1
->fullname
, c2
->fullname
);
165 case LST_DSPOPE_TAGS
:
169 t1
= tags_tostring(ope1
->tags
);
170 t2
= tags_tostring(ope2
->tags
);
171 retval
= list_txn_sort_iter_compare_strings(t1
, t2
);
178 g_return_val_if_reached(0);
185 static void list_txn_eval_future(GtkCellRenderer
*renderer
, Transaction
*txn
)
187 if(txn
->date
> GLOBALS
->today
)
189 g_object_set(renderer
,
190 // "scale-set", TRUE,
192 // "style-set", TRUE,
193 "style", PANGO_STYLE_OBLIQUE
,
198 g_object_set(renderer
, "scale-set", FALSE
, "style-set", FALSE
,
202 if( txn
->marker
== TXN_MARK_DUPDST
)
204 g_object_set(renderer
,
205 // "strikethrough-set", TRUE,
206 "strikethrough", TRUE
,
211 g_object_set(renderer
, "strikethrough-set", FALSE
,
215 if( txn
->marker
== TXN_MARK_DUPSRC
)
217 g_object_set(renderer
,
218 // "weight-set", TRUE,
219 "weight", PANGO_WEIGHT_BOLD
,
224 g_object_set(renderer
, "weight-set", FALSE
,
234 ** date cell function
236 static void list_txn_status_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
239 gchar
*iconname
= NULL
;
241 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &txn
, -1);
244 stat[0] = ( entry->ope_Flags & OF_ADDED ) ? data->istatus[2] : data->istatus[0];
245 stat[1] = ( entry->ope_Flags & OF_CHANGED) ? data->istatus[3] : data->istatus[0];
246 stat[2] = ( entry->ope_Flags & OF_VALID ) ? data->istatus[4] : data->istatus[0];
247 if( entry->ope_Flags & OF_REMIND ) stat[2] = data->istatus[1];
250 switch(GPOINTER_TO_INT(user_data
))
253 iconname
= ( txn
->flags
& OF_AUTO
) ? ICONNAME_HB_OPE_AUTO
: ( txn
->flags
& OF_ADDED
) ? ICONNAME_HB_OPE_NEW
: NULL
;
256 iconname
= ( txn
->flags
& OF_CHANGED
) ? ICONNAME_HB_OPE_EDIT
: NULL
;
259 iconname
= ( txn
->marker
== TXN_MARK_DUPDST
) ? ICONNAME_HB_OPE_SIMILAR
: NULL
;
262 if( entry->flags & OF_VALID )
263 iconname = ICONNAME_HB_OPE_VALID;
266 if( entry->flags & OF_REMIND )
267 iconname = ICONNAME_HB_OPE_REMIND;
271 g_object_set(renderer
, "icon-name", iconname
, NULL
);
276 ** account cell function
278 static void list_txn_account_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
283 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
285 acc
= da_acc_get(ope
->kacc
);
288 g_object_set(renderer
, "text", acc
->name
, NULL
);
291 g_object_set(renderer
, "text", "", NULL
);
295 ** date cell function
297 static void list_txn_date_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
303 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
304 list_txn_eval_future(renderer
, ope
);
308 g_date_set_julian (&date
, ope
->date
);
309 g_date_strftime (buffer
, 256-1, PREFS
->date_format
, &date
);
311 gchar
*ds
= g_strdup_printf ("%s [%02d]", buffer
, ope
->pos
);
312 g_object_set(renderer
, "text", ds
, NULL
);
315 g_object_set(renderer
, "text", buffer
, NULL
);
319 g_object_set(renderer
, "text", "????", NULL
);
323 ** info cell function
325 static void list_txn_info_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
329 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
331 switch(GPOINTER_TO_INT(user_data
))
334 g_object_set(renderer
, "icon-name", get_paymode_icon_name(ope
->paymode
), NULL
);
337 list_txn_eval_future(renderer
, ope
);
338 g_object_set(renderer
, "text", ope
->info
, NULL
);
344 ** payee cell function
346 static void list_txn_payee_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
350 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
351 list_txn_eval_future(renderer
, ope
);
354 if(ope
->paymode
== PAYMODE_INTXFER
)
356 Account
*acc
= da_acc_get(ope
->kxferacc
);
358 g_object_set(renderer
, "text", (acc
!= NULL
) ? acc
->name
: "", NULL
);
362 Payee
*pay
= da_pay_get(ope
->kpay
);
364 g_object_set(renderer
, "text", pay
!= NULL
? pay
->name
: "", NULL
);
370 ** tags cell function
372 static void list_txn_tags_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
377 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
378 list_txn_eval_future(renderer
, ope
);
380 if(ope
->tags
!= NULL
)
382 str
= tags_tostring(ope
->tags
);
383 g_object_set(renderer
, "text", str
, NULL
);
387 g_object_set(renderer
, "text", "", NULL
);
394 ** memo cell function
396 static void list_txn_memo_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
400 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
401 list_txn_eval_future(renderer
, ope
);
403 g_object_set(renderer
, "text", ope
->memo
, NULL
);
410 static void list_txn_clr_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
413 gchar
*iconname
= NULL
;
414 //const gchar *c = "";
416 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
419 /*case TXN_STATUS_CLEARED: c = "c"; break;
420 case TXN_STATUS_RECONCILED: c = "R"; break;
421 case TXN_STATUS_REMIND: c = "!"; break;*/
422 case TXN_STATUS_CLEARED
: iconname
= ICONNAME_HB_OPE_CLEARED
; break;
423 case TXN_STATUS_RECONCILED
: iconname
= ICONNAME_HB_OPE_RECONCILED
; break;
424 case TXN_STATUS_REMIND
: iconname
= ICONNAME_HB_OPE_REMIND
; break;
428 //g_object_set(renderer, "text", c, NULL);
429 g_object_set(renderer
, "icon-name", iconname
, NULL
);
435 ** amount cell function
437 static void list_txn_amount_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
440 gint column
= GPOINTER_TO_INT(user_data
);
441 gchar buf
[G_ASCII_DTOSTR_BUF_SIZE
];
446 // get the transaction
447 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
448 list_txn_eval_future(renderer
, ope
);
450 if(column
== LST_DSPOPE_BALANCE
)
451 amount
= ope
->balance
;
453 amount
= ope
->amount
;
455 if(column
== LST_DSPOPE_INCOME
|| column
== LST_DSPOPE_EXPENSE
)
457 type
= (ope
->flags
& OF_INCOME
) ? LST_DSPOPE_INCOME
: LST_DSPOPE_EXPENSE
;
460 g_object_set(renderer
, "markup", NULL
, NULL
);
467 hb_strfmon(buf
, G_ASCII_DTOSTR_BUF_SIZE
-1, amount
, ope
->kcur
, GLOBALS
->minor
);
469 color
= get_normal_color_amount(amount
);
470 if( (column
== LST_DSPOPE_BALANCE
) && (ope
->overdraft
== TRUE
) && (PREFS
->custom_colors
== TRUE
) )
472 color
= PREFS
->color_warn
;
475 g_object_set(renderer
,
486 ** category cell function
488 static void list_txn_category_cell_data_function (GtkTreeViewColumn
*col
, GtkCellRenderer
*renderer
, GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
493 gtk_tree_model_get(model
, iter
, LST_DSPOPE_DATAS
, &ope
, -1);
494 list_txn_eval_future(renderer
, ope
);
496 if(ope
->flags
& OF_SPLIT
)
498 g_object_set(renderer
, "text", _("- split -"), NULL
);
502 cat
= da_cat_get(ope
->kcat
);
505 g_object_set(renderer
, "text", cat
->fullname
, NULL
);
508 g_object_set(renderer
, "text", "", NULL
);
515 /* = = = = = = = = = = = = = = = = */
517 GString
*list_txn_to_string(GtkTreeView
*treeview
, gboolean clipboard
)
526 gchar
*info
, *payeename
, *categoryname
;
530 char amountbuf
[G_ASCII_DTOSTR_BUF_SIZE
];
532 node
= g_string_new(NULL
);
536 g_string_append (node
, "date\tpaymode\tinfo\tpayee\tmemo\tamount\tcategory\ttags\n");
538 g_string_append (node
, "date;paymode;info;payee;memo;amount;category;tags\n");
540 model
= gtk_tree_view_get_model(treeview
);
542 valid
= gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model
), &iter
);
545 gtk_tree_model_get (model
, &iter
,
546 LST_DSPOPE_DATAS
, &ope
,
549 hb_sprint_date(datebuf
, ope
->date
);
552 if(info
== NULL
) info
= "";
553 payee
= da_pay_get(ope
->kpay
);
554 payeename
= (payee
->name
== NULL
) ? "" : payee
->name
;
555 category
= da_cat_get(ope
->kcat
);
556 categoryname
= (category
->name
== NULL
) ? NULL
: category
->fullname
;
557 tags
= tags_tostring(ope
->tags
);
560 //g_ascii_dtostr (amountbuf, sizeof (amountbuf), ope->amount);
561 //#1750257 use locale numdigit
562 //g_ascii_formatd (amountbuf, sizeof (amountbuf), "%.2f", ope->amount);
563 g_snprintf(amountbuf
, sizeof (amountbuf
), "%.2f", ope
->amount
);
565 DB( g_print("amount = %f '%s'\n", ope
->amount
, amountbuf
) );
567 format
= (clipboard
== TRUE
) ? "%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\n" : "%s;%d;%s;%s;%s;%s;%s;%s\n";
568 g_string_append_printf(node
, format
,
575 categoryname
!= NULL
? categoryname
: "",
576 tags
!= NULL
? tags
: ""
582 valid
= gtk_tree_model_iter_next(GTK_TREE_MODEL(model
), &iter
);
585 //DB( g_print("text is:\n%s", node->str) );
591 gboolean
list_txn_column_id_isvisible(GtkTreeView
*treeview
, gint sort_id
)
593 GtkTreeViewColumn
*column
;
596 for(n
=0; n
< NUM_LST_DSPOPE
-1 ; n
++ ) // -1 cause account not to be processed
598 column
= gtk_tree_view_get_column (treeview
, n
);
602 if( gtk_tree_view_column_get_visible(column
) )
604 id
= gtk_tree_view_column_get_sort_column_id (column
);
614 static GtkTreeViewColumn
*list_txn_get_column(GList
*list
, gint search_id
)
616 GtkTreeViewColumn
*column
= NULL
;
620 tmp
= g_list_first(list
);
623 id
= gtk_tree_view_column_get_sort_column_id(tmp
->data
);
624 if( search_id
== id
)
629 tmp
= g_list_next(tmp
);
635 guint
list_txn_get_quicksearch_column_mask(GtkTreeView
*treeview
)
637 GtkTreeViewColumn
*column
;
642 for(n
=0; n
< NUM_LST_DSPOPE
-1 ; n
++ ) // -1 cause account not to be processed
644 column
= gtk_tree_view_get_column (treeview
, n
);
648 if( gtk_tree_view_column_get_visible(column
) )
650 id
= gtk_tree_view_column_get_sort_column_id (column
);
653 case LST_DSPOPE_MEMO
: mask
|= FLT_QSEARCH_MEMO
; break;
654 case LST_DSPOPE_INFO
: mask
|= FLT_QSEARCH_INFO
; break;
655 case LST_DSPOPE_PAYEE
: mask
|= FLT_QSEARCH_PAYEE
; break;
656 case LST_DSPOPE_CATEGORY
: mask
|= FLT_QSEARCH_CATEGORY
; break;
657 case LST_DSPOPE_TAGS
: mask
|= FLT_QSEARCH_TAGS
; break;
658 case LST_DSPOPE_AMOUNT
:
659 case LST_DSPOPE_EXPENSE
:
660 case LST_DSPOPE_INCOME
: mask
|= FLT_QSEARCH_AMOUNT
; break;
669 void list_txn_set_save_column_width(GtkTreeView
*treeview
, gboolean save_column_width
)
671 struct list_txn_data
*data
;
673 data
= g_object_get_data(G_OBJECT(treeview
), "inst_data");
676 data
->save_column_width
= save_column_width
;
681 void list_txn_set_column_acc_visible(GtkTreeView
*treeview
, gboolean visible
)
683 struct list_txn_data
*data
;
685 GtkTreeViewColumn
*column
;
687 data
= g_object_get_data(G_OBJECT(treeview
), "inst_data");
689 data
->showall
= visible
;
691 list
= gtk_tree_view_get_columns( treeview
);
692 //if acc visible: balance must be invisible
693 column
= list_txn_get_column(list
, LST_DSPOPE_ACCOUNT
);
695 gtk_tree_view_column_set_visible (column
, visible
);
696 column
= list_txn_get_column(list
, LST_DSPOPE_BALANCE
);
698 gtk_tree_view_column_set_visible (column
, !visible
);
705 void list_txn_sort_force(GtkTreeSortable
*sortable
, gpointer user_data
)
710 DB( g_print("list_txn_sort_force\n") );
712 gtk_tree_sortable_get_sort_column_id(sortable
, &sort_column_id
, &order
);
713 DB( g_print(" - id %d order %d\n", sort_column_id
, order
) );
715 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(sortable
), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID
, order
);
716 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(sortable
), sort_column_id
, order
);
720 static void list_txn_get_columns(GtkTreeView
*treeview
)
722 struct list_txn_data
*data
;
723 GtkTreeViewColumn
*column
;
726 DB( g_print("\n[list_txn] get columns position/width\n") );
728 data
= g_object_get_data(G_OBJECT(treeview
), "inst_data");
730 DB( g_print(" nbcol=%d, nbsortid=%d\n", NUM_LST_DSPOPE
, gtk_tree_view_get_n_columns (treeview
)) );
732 for(i
=0 ; i
< NUM_LST_DSPOPE
-1 ; i
++ ) // -1 'caus: account and blank column
734 column
= gtk_tree_view_get_column(treeview
, i
);
737 col_id
= gtk_tree_view_column_get_sort_column_id (column
);
742 visible
= gtk_tree_view_column_get_visible (column
);
743 if( col_id
== LST_DSPOPE_BALANCE
) //keep initial state of balance
744 visible
= data
->tvc_is_visible
;
748 PREFS
->lst_ope_columns
[i
] = col_id
;
749 //5.2 moved here to keep old width in case not visible
750 PREFS
->lst_ope_col_width
[col_id
-1] = gtk_tree_view_column_get_width(column
);
753 PREFS
->lst_ope_columns
[i
] = -col_id
;
755 DB( g_print(" col-%2d => %2d '%s' w=%d\n", i
, col_id
, gtk_tree_view_column_get_title(column
), PREFS
->lst_ope_col_width
[col_id
-1] ) );
757 else //should not occurs
758 PREFS
->lst_ope_columns
[i
] = 0;
764 static void list_txn_set_columns(GtkTreeView
*treeview
, gint
*col_id
)
766 struct list_txn_data
*data
;
767 GtkTreeViewColumn
*column
, *base
;
773 DB( g_print("\n[list_txn] set columns order/width\n") );
775 data
= g_object_get_data(G_OBJECT(treeview
), "inst_data");
778 DB( g_print("\n debug column sortid\n") );
780 for(i
=0; i
< NUM_LST_DSPOPE
-1 ; i
++ ) // -1 cause account not to be processed
782 DB( g_print(" - pos:%2d sortid:%2d\n", i
, col_id
[i
]) );
787 DB( g_print("\n apply column prefs\n") );
789 list
= gtk_tree_view_get_columns( treeview
);
793 for(i
=0; i
< NUM_LST_DSPOPE
-1 ; i
++ ) // -1 cause account not to be processed
795 /* hidden are stored as col_id negative */
797 column
= list_txn_get_column(list
, id
);
799 //DB( g_print(" - get column %d %p\n", id, column) );
803 DB( g_print(" - pos:%2d sortid:%2d (%s)\n", i
, col_id
[i
], gtk_tree_view_column_get_title(column
)) );
805 gtk_tree_view_move_column_after(treeview
, column
, base
);
808 visible
= col_id
[i
] < 0 ? FALSE
: TRUE
;
810 /* display exception for detail/import list */
811 if(data
->list_type
!= LIST_TXN_TYPE_BOOK
)
813 if( id
== LST_DSPOPE_AMOUNT
)
816 if( id
== LST_DSPOPE_STATUS
|| id
== LST_DSPOPE_EXPENSE
|| id
== LST_DSPOPE_INCOME
)
820 gtk_tree_view_column_set_visible (column
, visible
);
821 if( id
== LST_DSPOPE_BALANCE
)
823 data
->tvc_is_visible
= visible
;
826 if( id
== LST_DSPOPE_INFO
827 || id
== LST_DSPOPE_PAYEE
828 || id
== LST_DSPOPE_MEMO
829 || id
== LST_DSPOPE_CATEGORY
830 || id
== LST_DSPOPE_TAGS
831 || id
== LST_DSPOPE_ACCOUNT
)
833 gtk_tree_view_column_set_fixed_width( column
, PREFS
->lst_ope_col_width
[id
- 1]);
843 static void list_txn_sort_column_changed(GtkTreeSortable
*sortable
, gpointer user_data
)
845 struct list_txn_data
*data
= user_data
;
848 gboolean showBalance
;
850 gtk_tree_sortable_get_sort_column_id(sortable
, &id
, &order
);
852 DB( g_print("list_txn_columns_changed %d %d\n", id
, order
) );
854 //here save the transaction list columnid and sort order
855 PREFS
->lst_ope_sort_id
= id
;
856 PREFS
->lst_ope_sort_order
= order
;
858 //manage visibility of balance column
859 //showBalance = (id == LST_DSPOPE_DATE && order == GTK_SORT_ASCENDING) ? data->tvc_is_visible : FALSE;
860 showBalance
= (id
== LST_DSPOPE_DATE
) ? data
->tvc_is_visible
: FALSE
;
861 if(data
->showall
== TRUE
) showBalance
= FALSE
;
862 gtk_tree_view_column_set_visible (data
->tvc_balance
, showBalance
);
867 list_txn_column_popup_menuitem_on_activate (GtkCheckMenuItem
*checkmenuitem
,
870 GtkTreeViewColumn
*column
= user_data
;
872 DB( g_print("toggled\n") );
874 gtk_tree_view_column_set_visible(column
, gtk_check_menu_item_get_active(checkmenuitem
) );
878 static gboolean
list_txn_column_popup_callback ( GtkWidget
*button
,
882 struct list_txn_data
*data
= user_data
;
883 GtkWidget
*menu
, *menuitem
;
884 GtkTreeViewColumn
*column
;
888 if( ev
->button
== 3 )
890 DB( g_print("should popup\n") );
892 menu
= gtk_menu_new ();
894 //note: deactive this disable any menuitem action
895 g_signal_connect (menu
, "selection-done", G_CALLBACK (gtk_widget_destroy
), NULL
);
897 for(i
=0 ; i
< NUM_LST_DSPOPE
-1 ; i
++ ) // -1 'caus: account and blank column
899 column
= gtk_tree_view_get_column(GTK_TREE_VIEW(data
->treeview
), i
);
902 col_id
= gtk_tree_view_column_get_sort_column_id (column
);
905 || (col_id
== LST_DSPOPE_STATUS
)
906 || (col_id
== LST_DSPOPE_ACCOUNT
)
907 || (col_id
== LST_DSPOPE_DATE
)
908 || (col_id
== LST_DSPOPE_BALANCE
)
911 //if( (data->tvc_is_visible == FALSE) && (col_id == LST_DSPOPE_BALANCE) )
914 if( (data
->list_type
== LIST_TXN_TYPE_DETAIL
) &&
915 ( (col_id
== LST_DSPOPE_AMOUNT
)
916 || (col_id
== LST_DSPOPE_EXPENSE
)
917 || (col_id
== LST_DSPOPE_INCOME
)
922 menuitem
= gtk_check_menu_item_new_with_label ( gtk_tree_view_column_get_title (column
) );
923 gtk_menu_shell_append (GTK_MENU_SHELL (menu
), menuitem
);
924 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem
), gtk_tree_view_column_get_visible (column
) );
925 gtk_widget_show (menuitem
);
927 g_signal_connect (menuitem
, "activate",
928 G_CALLBACK (list_txn_column_popup_menuitem_on_activate
), column
);
933 gtk_menu_attach_to_widget (GTK_MENU (menu
), button
, NULL
);
934 gtk_menu_popup (GTK_MENU (menu
), NULL
, NULL
, NULL
, NULL
,
935 ev
->button
, ev
->time
);
942 static GtkTreeViewColumn
*
943 list_txn_column_amount_create(gint list_type
, gchar
*title
, gint sortcolumnid
, GtkTreeCellDataFunc func
)
945 GtkTreeViewColumn
*column
;
946 GtkCellRenderer
*renderer
;
948 renderer
= gtk_cell_renderer_text_new ();
949 g_object_set(renderer
, "xalign", 1.0, NULL
);
951 column
= gtk_tree_view_column_new_with_attributes(title
, renderer
, NULL
);
953 gtk_tree_view_column_set_alignment (column
, 0.5);
954 //gtk_tree_view_column_set_resizable(column, TRUE);
955 gtk_tree_view_column_set_sort_column_id (column
, sortcolumnid
);
956 if(list_type
== LIST_TXN_TYPE_BOOK
)
958 gtk_tree_view_column_set_reorderable(column
, TRUE
);
960 gtk_tree_view_column_set_cell_data_func(column
, renderer
, func
, GINT_TO_POINTER(sortcolumnid
), NULL
);
966 static GtkTreeViewColumn
*
967 list_txn_column_text_create(gint list_type
, gchar
*title
, gint sortcolumnid
, GtkTreeCellDataFunc func
, gpointer user_data
)
969 GtkTreeViewColumn
*column
;
970 GtkCellRenderer
*renderer
;
972 renderer
= gtk_cell_renderer_text_new ();
973 g_object_set(renderer
,
974 "ellipsize", PANGO_ELLIPSIZE_END
,
975 "ellipsize-set", TRUE
,
978 column
= gtk_tree_view_column_new_with_attributes(title
, renderer
, NULL
);
980 gtk_tree_view_column_set_alignment (column
, 0.5);
981 gtk_tree_view_column_set_resizable(column
, TRUE
);
983 gtk_tree_view_column_set_sort_column_id (column
, sortcolumnid
);
984 if(list_type
== LIST_TXN_TYPE_BOOK
)
986 gtk_tree_view_column_set_reorderable(column
, TRUE
);
987 gtk_tree_view_column_set_min_width (column
, HB_MINWIDTH_COLUMN
);
988 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_FIXED
);
990 gtk_tree_view_column_set_cell_data_func(column
, renderer
, func
, user_data
, NULL
);
996 static GtkTreeViewColumn
*
997 list_txn_column_info_create(gint list_type
)
999 GtkTreeViewColumn
*column
;
1000 GtkCellRenderer
*renderer
;
1002 column
= gtk_tree_view_column_new();
1003 gtk_tree_view_column_set_title(column
, _("Info"));
1005 renderer
= gtk_cell_renderer_pixbuf_new ();
1006 gtk_tree_view_column_pack_start(column
, renderer
, FALSE
);
1007 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_info_cell_data_function
, GINT_TO_POINTER(1), NULL
);
1009 renderer
= gtk_cell_renderer_text_new ();
1010 /*g_object_set(renderer,
1011 "ellipsize", PANGO_ELLIPSIZE_END,
1012 "ellipsize-set", TRUE,
1014 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1015 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_info_cell_data_function
, GINT_TO_POINTER(2), NULL
);
1017 gtk_tree_view_column_set_alignment (column
, 0.5);
1018 gtk_tree_view_column_set_resizable(column
, TRUE
);
1019 gtk_tree_view_column_set_sort_column_id (column
, LST_DSPOPE_INFO
);
1020 if(list_type
== LIST_TXN_TYPE_BOOK
)
1022 gtk_tree_view_column_set_reorderable(column
, TRUE
);
1023 gtk_tree_view_column_set_min_width (column
, HB_MINWIDTH_COLUMN
);
1024 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_FIXED
);
1031 static void list_txn_destroy( GtkWidget
*widget
, gpointer user_data
)
1033 struct list_txn_data
*data
;
1035 data
= g_object_get_data(G_OBJECT(widget
), "inst_data");
1037 DB( g_print ("\n[list_transaction] destroy event occurred\n") );
1039 if( data
->save_column_width
)
1041 list_txn_get_columns(GTK_TREE_VIEW(data
->treeview
));
1044 DB( g_print(" - view=%p, inst_data=%p\n", widget
, data
) );
1049 Transaction
*list_txn_get_active_transaction(GtkTreeView
*treeview
)
1051 GtkTreeModel
*model
;
1057 model
= gtk_tree_view_get_model(treeview
);
1058 list
= gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(treeview
), &model
);
1064 gtk_tree_model_get_iter(model
, &iter
, list
->data
);
1065 gtk_tree_model_get(model
, &iter
, LST_DSPOPE_DATAS
, &ope
, -1);
1068 g_list_foreach(list
, (GFunc
)gtk_tree_path_free
, NULL
);
1076 ** create our transaction list
1077 ** Status, Date, Info, Payee, Memo, (Amount), Expense, Income, Category
1079 GtkWidget
*create_list_transaction(gint list_type
, gboolean
*pref_columns
)
1081 struct list_txn_data
*data
;
1082 GtkListStore
*store
;
1083 GtkWidget
*treeview
;
1084 GtkCellRenderer
*renderer
;
1085 GtkTreeViewColumn
*column
, *col_acc
= NULL
, *col_status
= NULL
;
1088 data
= g_malloc0(sizeof(struct list_txn_data
));
1089 if(!data
) return NULL
;
1091 data
->list_type
= list_type
;
1092 data
->save_column_width
= FALSE
;
1094 /* create list store */
1095 store
= gtk_list_store_new(
1096 1, G_TYPE_POINTER
/*only really used column */
1100 treeview
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
));
1101 data
->treeview
= treeview
;
1102 g_object_unref(store
);
1104 //store our window private data
1105 g_object_set_data(G_OBJECT(treeview
), "inst_data", (gpointer
)data
);
1106 DB( g_print(" - treeview=%p, inst_data=%p\n", treeview
, data
) );
1108 // connect our dispose function
1109 g_signal_connect (treeview
, "destroy", G_CALLBACK (list_txn_destroy
), (gpointer
)data
);
1111 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview
), PREFS
->grid_lines
);
1112 //gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
1113 // COLUMN_DESCRIPTION);
1115 if(list_type
== LIST_TXN_TYPE_BOOK
)
1116 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
)), GTK_SELECTION_MULTIPLE
);
1118 /* column 1: Changes */
1119 column
= gtk_tree_view_column_new();
1120 //gtk_tree_view_column_set_title(column, _("Status"));
1121 col_status
= column
;
1123 renderer
= gtk_cell_renderer_pixbuf_new ();
1124 //gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
1125 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1126 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_status_cell_data_function
, GINT_TO_POINTER(1), NULL
);
1128 renderer
= gtk_cell_renderer_pixbuf_new ();
1129 //gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
1130 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1131 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_status_cell_data_function
, GINT_TO_POINTER(2), NULL
);
1133 renderer
= gtk_cell_renderer_pixbuf_new ();
1134 //gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
1135 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1136 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_status_cell_data_function
, GINT_TO_POINTER(3), NULL
);
1138 gtk_tree_view_column_set_sort_column_id (column
, LST_DSPOPE_STATUS
);
1139 //gtk_tree_view_column_set_resizable(column, TRUE);
1140 gtk_tree_view_column_set_alignment (column
, 0.5);
1141 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1143 //5.2 we always create the column and set it not visible
1144 column
= list_txn_column_text_create(list_type
, _("Account"), LST_DSPOPE_ACCOUNT
, list_txn_account_cell_data_function
, NULL
);
1145 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1148 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1149 "button-press-event",
1150 G_CALLBACK ( list_txn_column_popup_callback
),
1153 /* column 2: Date */
1154 column
= gtk_tree_view_column_new();
1155 gtk_tree_view_column_set_title(column
, _("Date"));
1156 renderer
= gtk_cell_renderer_text_new ();
1157 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1158 g_object_set(renderer
, "xalign", 1.0, NULL
);
1159 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_date_cell_data_function
, NULL
, NULL
);
1160 gtk_tree_view_column_set_sort_column_id (column
, LST_DSPOPE_DATE
);
1161 //gtk_tree_view_column_set_resizable(column, TRUE);
1162 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1164 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1165 "button-press-event",
1166 G_CALLBACK ( list_txn_column_popup_callback
),
1170 column
= list_txn_column_info_create(list_type
);
1171 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1173 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1174 "button-press-event",
1175 G_CALLBACK ( list_txn_column_popup_callback
),
1178 column
= list_txn_column_text_create(list_type
, _("Payee"), LST_DSPOPE_PAYEE
, list_txn_payee_cell_data_function
, NULL
);
1179 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1181 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1182 "button-press-event",
1183 G_CALLBACK ( list_txn_column_popup_callback
),
1186 column
= list_txn_column_text_create(list_type
, _("Memo"), LST_DSPOPE_MEMO
, list_txn_memo_cell_data_function
, NULL
);
1187 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1189 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1190 "button-press-event",
1191 G_CALLBACK ( list_txn_column_popup_callback
),
1194 /* column status CLR */
1195 column
= gtk_tree_view_column_new();
1196 gtk_tree_view_column_set_title(column
, _("Status"));
1198 //renderer = gtk_cell_renderer_text_new ();
1199 renderer
= gtk_cell_renderer_pixbuf_new();
1200 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1201 g_object_set(renderer
, "xalign", 1.0, NULL
);
1202 gtk_tree_view_column_set_cell_data_func(column
, renderer
, list_txn_clr_cell_data_function
, NULL
, NULL
);
1203 gtk_tree_view_column_set_reorderable(column
, TRUE
);
1204 gtk_tree_view_column_set_sort_column_id (column
, LST_DSPOPE_CLR
);
1205 //gtk_tree_view_column_set_sort_indicator (column, FALSE);
1206 //gtk_tree_view_column_set_resizable(column, TRUE);
1207 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1209 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1210 "button-press-event",
1211 G_CALLBACK ( list_txn_column_popup_callback
),
1215 column
= list_txn_column_amount_create(list_type
, _("Amount"), LST_DSPOPE_AMOUNT
, list_txn_amount_cell_data_function
);
1216 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1218 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1219 "button-press-event",
1220 G_CALLBACK ( list_txn_column_popup_callback
),
1223 column
= list_txn_column_amount_create(list_type
, _("Expense"), LST_DSPOPE_EXPENSE
, list_txn_amount_cell_data_function
);
1224 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1226 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1227 "button-press-event",
1228 G_CALLBACK ( list_txn_column_popup_callback
),
1231 column
= list_txn_column_amount_create(list_type
, _("Income"), LST_DSPOPE_INCOME
, list_txn_amount_cell_data_function
);
1232 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1234 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1235 "button-press-event",
1236 G_CALLBACK ( list_txn_column_popup_callback
),
1239 column
= list_txn_column_text_create(list_type
, _("Category"), LST_DSPOPE_CATEGORY
, list_txn_category_cell_data_function
, NULL
);
1240 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1242 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1243 "button-press-event",
1244 G_CALLBACK ( list_txn_column_popup_callback
),
1247 column
= list_txn_column_text_create(list_type
, _("Tags"), LST_DSPOPE_TAGS
, list_txn_tags_cell_data_function
, NULL
);
1248 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1250 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1251 "button-press-event",
1252 G_CALLBACK ( list_txn_column_popup_callback
),
1255 if(list_type
== LIST_TXN_TYPE_BOOK
)
1257 column
= list_txn_column_amount_create(list_type
, _("Balance"), LST_DSPOPE_BALANCE
, list_txn_amount_cell_data_function
);
1258 data
->tvc_balance
= column
;
1259 gtk_tree_view_column_set_clickable(column
, FALSE
);
1260 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1262 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column
)),
1263 "button-press-event",
1264 G_CALLBACK ( list_txn_column_popup_callback
),
1268 /* column 9: empty */
1269 column
= gtk_tree_view_column_new();
1270 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview
), column
);
1273 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_STATUS
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_STATUS
), NULL
);
1274 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_DATE
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_DATE
), NULL
);
1275 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_INFO
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_INFO
), NULL
);
1276 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_PAYEE
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_PAYEE
), NULL
);
1277 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_MEMO
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_MEMO
), NULL
);
1278 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_AMOUNT
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_AMOUNT
), NULL
);
1279 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_EXPENSE
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_EXPENSE
), NULL
);
1280 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_INCOME
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_INCOME
), NULL
);
1281 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_CATEGORY
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_CATEGORY
), NULL
);
1282 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_TAGS
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_TAGS
), NULL
);
1283 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_CLR
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_CLR
), NULL
);
1284 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store
), LST_DSPOPE_ACCOUNT
, list_txn_sort_iter_compare_func
, GINT_TO_POINTER(LST_DSPOPE_ACCOUNT
), NULL
);
1286 /* apply user preference for columns */
1287 list_txn_set_columns(GTK_TREE_VIEW(treeview
), pref_columns
);
1289 /* force account column for detail treeview */
1290 gtk_tree_view_move_column_after(GTK_TREE_VIEW(treeview
), col_acc
, col_status
);
1292 /* by default book don't display acc column, except shoall */
1293 //#1821850 detail account column visible
1294 gboolean visible
= (list_type
== LIST_TXN_TYPE_BOOK
) ? FALSE
: TRUE
;
1295 gtk_tree_view_column_set_visible (col_acc
, visible
);
1297 /* set initial sort order */
1298 DB( g_print("set sort to %d %d\n", PREFS
->lst_ope_sort_id
, PREFS
->lst_ope_sort_order
) );
1299 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store
), PREFS
->lst_ope_sort_id
, PREFS
->lst_ope_sort_order
);
1303 if(list_type
== LIST_TXN_TYPE_BOOK
)
1304 g_signal_connect (GTK_TREE_SORTABLE(store
), "sort-column-changed", G_CALLBACK (list_txn_sort_column_changed
), data
);