]> Dogcows Code - chaz/homebank/blob - src/list-operation.c
Merge branch 'upstream'
[chaz/homebank] / src / list-operation.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20
21 #include "homebank.h"
22
23 #include "list-operation.h"
24
25 /****************************************************************************/
26 /* Debug macros */
27 /****************************************************************************/
28 #define MYDEBUG 0
29
30 #if MYDEBUG
31 #define DB(x) (x);
32 #else
33 #define DB(x);
34 #endif
35
36 /* our global datas */
37 extern struct HomeBank *GLOBALS;
38 extern struct Preferences *PREFS;
39
40
41 //debug
42 //extern gboolean minor_active;
43
44
45 /* This is not pretty. Of course you can also use a
46 * separate compare function for each sort ID value */
47
48 static gint list_txn_sort_iter_compare_strings(gchar *s1, gchar *s2)
49 {
50 return hb_string_utf8_compare(s1, s2);
51 }
52
53
54 static gint
55 list_txn_sort_iter_compare_func (GtkTreeModel *model,
56 GtkTreeIter *a,
57 GtkTreeIter *b,
58 gpointer userdata)
59 {
60 gint sortcol = GPOINTER_TO_INT(userdata);
61 gint retval = 0;
62 Transaction *ope1, *ope2;
63 gdouble tmpval = 0;
64
65 gtk_tree_model_get(model, a, MODEL_TXN_POINTER, &ope1, -1);
66 gtk_tree_model_get(model, b, MODEL_TXN_POINTER, &ope2, -1);
67
68 switch (sortcol)
69 {
70 case LST_DSPOPE_STATUS:
71 if(!(retval = (ope1->flags & OF_ADDED) - (ope2->flags & OF_ADDED) ) )
72 {
73 retval = (ope1->flags & OF_CHANGED) - (ope2->flags & OF_CHANGED);
74 }
75 break;
76
77 case LST_DSPOPE_DATE:
78 if(! (retval = ope1->date - ope2->date) )
79 {
80 //g_print("sort on balance d1=%d, d2=%d %f %f\n", ope1->date, ope2->date, ope1->balance , ope2->balance);
81
82 tmpval = ope1->pos - ope2->pos;
83 retval = tmpval > 0 ? 1 : -1;
84 }
85 //g_print("ret=%d\n", ret);
86 break;
87
88 case LST_DSPOPE_ACCOUNT:
89 {
90 Account *a1, *a2;
91
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);
95 }
96 break;
97
98 case LST_DSPOPE_INFO:
99 if(!(retval = ope1->paymode - ope2->paymode))
100 {
101 retval = list_txn_sort_iter_compare_strings(ope1->info, ope2->info);
102 }
103 break;
104
105 case LST_DSPOPE_PAYEE:
106 {
107 //#1721980
108 gchar *name1 = NULL;
109 gchar *name2 = NULL;
110
111 if( ope1->paymode == PAYMODE_INTXFER )
112 {
113 Account *acc = da_acc_get(ope1->kxferacc);
114 name1 = (acc != NULL) ? acc->name : NULL;
115 }
116 else
117 {
118 Payee *pay = da_pay_get(ope1->kpay);
119 name1 = (pay != NULL) ? pay->name : NULL;
120 }
121
122 if( ope2->paymode == PAYMODE_INTXFER )
123 {
124 Account *acc = da_acc_get(ope2->kxferacc);
125 name2 = (acc != NULL) ? acc->name : NULL;
126 }
127 else
128 {
129 Payee *pay = da_pay_get(ope2->kpay);
130 name2 = (pay != NULL) ? pay->name : NULL;
131 }
132
133 retval = list_txn_sort_iter_compare_strings(name1, name2);
134 }
135 break;
136
137 case LST_DSPOPE_MEMO:
138 retval = list_txn_sort_iter_compare_strings(ope1->memo, ope2->memo);
139 break;
140
141 case LST_DSPOPE_CLR:
142 retval = ope1->status - ope2->status;
143 break;
144
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;
150 break;
151
152 case LST_DSPOPE_CATEGORY:
153 {
154 Category *c1, *c2;
155
156 c1 = da_cat_get(ope1->kcat);
157 c2 = da_cat_get(ope2->kcat);
158 if( c1 != NULL && c2 != NULL )
159 {
160 retval = list_txn_sort_iter_compare_strings(c1->fullname, c2->fullname);
161 }
162 }
163 break;
164
165 case LST_DSPOPE_TAGS:
166 {
167 gchar *t1, *t2;
168
169 t1 = tags_tostring(ope1->tags);
170 t2 = tags_tostring(ope2->tags);
171 retval = list_txn_sort_iter_compare_strings(t1, t2);
172 g_free(t2);
173 g_free(t1);
174 }
175 break;
176
177 default:
178 g_return_val_if_reached(0);
179 }
180
181 return retval;
182 }
183
184
185 static void list_txn_eval_future(GtkCellRenderer *renderer, Transaction *txn)
186 {
187 if(txn->date > GLOBALS->today)
188 {
189 g_object_set(renderer,
190 // "scale-set", TRUE,
191 "scale", 0.8,
192 // "style-set", TRUE,
193 "style", PANGO_STYLE_OBLIQUE,
194 NULL);
195 }
196 else
197 {
198 g_object_set(renderer, "scale-set", FALSE, "style-set", FALSE,
199 NULL);
200 }
201
202 if( txn->marker == TXN_MARK_DUPDST )
203 {
204 g_object_set(renderer,
205 // "strikethrough-set", TRUE,
206 "strikethrough", TRUE,
207 NULL);
208 }
209 else
210 {
211 g_object_set(renderer, "strikethrough-set", FALSE,
212 NULL);
213 }
214
215 if( txn->marker == TXN_MARK_DUPSRC )
216 {
217 g_object_set(renderer,
218 // "weight-set", TRUE,
219 "weight", PANGO_WEIGHT_BOLD,
220 NULL);
221 }
222 else
223 {
224 g_object_set(renderer, "weight-set", FALSE,
225 NULL);
226 }
227
228
229
230 }
231
232
233 /*
234 ** date cell function
235 */
236 static void list_txn_status_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
237 {
238 Transaction *txn;
239 gchar *iconname = NULL;
240
241 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &txn, -1);
242
243 /*
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];
248 */
249
250 switch(GPOINTER_TO_INT(user_data))
251 {
252 case 1:
253 iconname = ( txn->flags & OF_AUTO ) ? ICONNAME_HB_OPE_AUTO : ( txn->flags & OF_ADDED ) ? ICONNAME_HB_OPE_NEW : NULL;
254 break;
255 case 2:
256 iconname = ( txn->flags & OF_CHANGED ) ? ICONNAME_HB_OPE_EDIT : NULL;
257 break;
258 case 3:
259 iconname = ( txn->marker == TXN_MARK_DUPDST ) ? ICONNAME_HB_OPE_SIMILAR : NULL;
260 break;
261 /*case 3:
262 if( entry->flags & OF_VALID )
263 iconname = ICONNAME_HB_OPE_VALID;
264 else
265 {
266 if( entry->flags & OF_REMIND )
267 iconname = ICONNAME_HB_OPE_REMIND;
268 }
269 break;*/
270 }
271 g_object_set(renderer, "icon-name", iconname, NULL);
272 }
273
274
275 /*
276 ** account cell function
277 */
278 static void list_txn_account_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
279 {
280 Transaction *ope;
281 Account *acc;
282
283 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
284
285 acc = da_acc_get(ope->kacc);
286 if( acc )
287 {
288 g_object_set(renderer, "text", acc->name, NULL);
289 }
290 else
291 g_object_set(renderer, "text", "", NULL);
292 }
293
294 /*
295 ** date cell function
296 */
297 static void list_txn_date_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
298 {
299 Transaction *ope;
300 gchar buffer[256];
301 GDate date;
302
303 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
304 list_txn_eval_future(renderer, ope);
305
306 if(ope->date > 0)
307 {
308 g_date_set_julian (&date, ope->date);
309 g_date_strftime (buffer, 256-1, PREFS->date_format, &date);
310 #if MYDEBUG
311 gchar *ds = g_strdup_printf ("%s [%02d]", buffer, ope->pos );
312 g_object_set(renderer, "text", ds, NULL);
313 g_free(ds);
314 #else
315 g_object_set(renderer, "text", buffer, NULL);
316 #endif
317 }
318 else
319 g_object_set(renderer, "text", "????", NULL);
320 }
321
322 /*
323 ** info cell function
324 */
325 static void list_txn_info_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
326 {
327 Transaction *ope;
328
329 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
330
331 switch(GPOINTER_TO_INT(user_data))
332 {
333 case 1:
334 g_object_set(renderer, "icon-name", get_paymode_icon_name(ope->paymode), NULL);
335 break;
336 case 2:
337 list_txn_eval_future(renderer, ope);
338 g_object_set(renderer, "text", ope->info, NULL);
339 break;
340 }
341 }
342
343
344 static void list_txn_payeexfer_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
345 {
346 Transaction *ope;
347 gchar *direction = "";
348
349 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
350 list_txn_eval_future(renderer, ope);
351
352 if(ope->paymode == PAYMODE_INTXFER)
353 {
354 direction = ( ope->flags & OF_INCOME ) ? "<" : ">";
355 }
356 g_object_set(renderer, "text", direction, NULL);
357 }
358
359
360 /*
361 ** payee cell function
362 */
363 static void list_txn_payee_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
364 {
365 Transaction *ope;
366
367 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
368 list_txn_eval_future(renderer, ope);
369
370 //#926782
371 if(ope->paymode == PAYMODE_INTXFER)
372 {
373 Account *acc = da_acc_get(ope->kxferacc);
374
375 g_object_set(renderer, "text", (acc != NULL) ? acc->name : "", NULL);
376 }
377 else
378 {
379 Payee *pay = da_pay_get(ope->kpay);
380
381 g_object_set(renderer, "text", pay != NULL ? pay->name : "", NULL);
382 }
383 }
384
385
386 /*
387 ** tags cell function
388 */
389 static void list_txn_tags_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
390 {
391 Transaction *ope;
392 gchar *str;
393
394 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
395 list_txn_eval_future(renderer, ope);
396
397 if(ope->tags != NULL)
398 {
399 str = tags_tostring(ope->tags);
400 g_object_set(renderer, "text", str, NULL);
401 g_free(str);
402 }
403 else
404 g_object_set(renderer, "text", "", NULL);
405
406
407 }
408
409
410 /*
411 ** memo cell function
412 */
413 static void list_txn_memo_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
414 {
415 Transaction *ope;
416
417 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
418 list_txn_eval_future(renderer, ope);
419
420 g_object_set(renderer, "text", ope->memo, NULL);
421 }
422
423
424 /*
425 ** clr cell function
426 */
427 static void list_txn_clr_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
428 {
429 Transaction *ope;
430 gchar *iconname = NULL;
431 //const gchar *c = "";
432
433 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
434 switch(ope->status)
435 {
436 /*case TXN_STATUS_CLEARED: c = "c"; break;
437 case TXN_STATUS_RECONCILED: c = "R"; break;
438 case TXN_STATUS_REMIND: c = "!"; break;*/
439 case TXN_STATUS_CLEARED: iconname = ICONNAME_HB_OPE_CLEARED; break;
440 case TXN_STATUS_RECONCILED: iconname = ICONNAME_HB_OPE_RECONCILED; break;
441 case TXN_STATUS_REMIND: iconname = ICONNAME_HB_OPE_REMIND; break;
442
443 }
444
445 //g_object_set(renderer, "text", c, NULL);
446 g_object_set(renderer, "icon-name", iconname, NULL);
447
448 }
449
450
451 /*
452 ** amount cell function
453 */
454 static void list_txn_amount_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
455 {
456 struct list_txn_data *data = NULL;
457 GtkWidget *widget;
458 Transaction *ope;
459 gint column = GPOINTER_TO_INT(user_data);
460 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
461 gint type;
462 gdouble amount, samount;
463 gchar *color;
464
465 widget = gtk_tree_view_column_get_tree_view(col);
466 if( widget )
467 data = g_object_get_data(G_OBJECT(widget), "inst_data");
468
469 // get the transaction
470 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, MODEL_TXN_SPLITAMT, &samount, -1);
471 list_txn_eval_future(renderer, ope);
472
473 if(column == LST_DSPOPE_BALANCE)
474 amount = ope->balance;
475 else
476 amount = ope->amount;
477
478 //for detail display the split part (if any)
479 if( data && (data->list_type == LIST_TXN_TYPE_DETAIL) )
480 amount = samount;
481
482 if(column == LST_DSPOPE_INCOME || column == LST_DSPOPE_EXPENSE)
483 {
484 type = (ope->flags & OF_INCOME) ? LST_DSPOPE_INCOME : LST_DSPOPE_EXPENSE;
485 if( type != column)
486 {
487 g_object_set(renderer, "markup", NULL, NULL);
488 return;
489 }
490 }
491
492 //if(amount != 0)
493 //{
494 hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, amount, ope->kcur, GLOBALS->minor);
495
496 color = get_normal_color_amount(amount);
497 if( (column == LST_DSPOPE_BALANCE) && (ope->overdraft == TRUE) && (PREFS->custom_colors == TRUE) )
498 {
499 color = PREFS->color_warn;
500 }
501
502 g_object_set(renderer,
503 "foreground", color,
504 "text", buf,
505 NULL);
506 //}
507
508
509 }
510
511
512 /*
513 ** category cell function
514 */
515 static void list_txn_category_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
516 {
517 Transaction *ope;
518 Category *cat;
519
520 gtk_tree_model_get(model, iter, MODEL_TXN_POINTER, &ope, -1);
521 list_txn_eval_future(renderer, ope);
522
523 if(ope->flags & OF_SPLIT)
524 {
525 g_object_set(renderer, "text", _("- split -"), NULL);
526 }
527 else
528 {
529 cat = da_cat_get(ope->kcat);
530 if( cat != NULL )
531 {
532 g_object_set(renderer, "text", cat->fullname, NULL);
533 }
534 else
535 g_object_set(renderer, "text", "", NULL);
536
537 }
538
539 }
540
541
542 /* = = = = = = = = = = = = = = = = */
543
544 GString *list_txn_to_string(GtkTreeView *treeview, gboolean clipboard)
545 {
546 struct list_txn_data *data = NULL;
547 GtkTreeModel *model;
548 GtkTreeIter iter;
549 gboolean valid;
550 GString *node;
551 const gchar *format;
552 Transaction *ope;
553 gchar datebuf[16];
554 gchar *info, *payeename, *categoryname;
555 gdouble amount, samount;
556 Payee *payee;
557 Category *category;
558 gchar *tags;
559 char amountbuf[G_ASCII_DTOSTR_BUF_SIZE];
560
561 data = g_object_get_data(G_OBJECT(treeview), "inst_data");
562
563 node = g_string_new(NULL);
564
565 //title line
566 if(clipboard)
567 g_string_append (node, "date\tpaymode\tinfo\tpayee\tmemo\tamount\tcategory\ttags\n");
568 else
569 g_string_append (node, "date;paymode;info;payee;memo;amount;category;tags\n");
570
571 model = gtk_tree_view_get_model(treeview);
572
573 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
574 while (valid)
575 {
576 gtk_tree_model_get (model, &iter,
577 MODEL_TXN_POINTER, &ope,
578 MODEL_TXN_SPLITAMT, &samount,
579 -1);
580
581 hb_sprint_date(datebuf, ope->date);
582
583 info = ope->info;
584 if(info == NULL) info = "";
585 payee = da_pay_get(ope->kpay);
586 payeename = (payee->name == NULL) ? "" : payee->name;
587 category = da_cat_get(ope->kcat);
588 categoryname = (category->name == NULL) ? NULL : category->fullname;
589 tags = tags_tostring(ope->tags);
590
591 amount = ope->amount;
592 //for detail display the split part (if any)
593 if( data && (data->list_type == LIST_TXN_TYPE_DETAIL) )
594 amount = samount;
595
596 //#793719
597 //g_ascii_dtostr (amountbuf, sizeof (amountbuf), ope->amount);
598 //#1750257 use locale numdigit
599 //g_ascii_formatd (amountbuf, sizeof (amountbuf), "%.2f", ope->amount);
600 g_snprintf(amountbuf, sizeof (amountbuf), "%.2f", amount);
601
602 DB( g_print("amount = %f '%s'\n", amount, amountbuf) );
603
604 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";
605 g_string_append_printf(node, format,
606 datebuf,
607 ope->paymode,
608 info,
609 payeename,
610 ope->memo,
611 amountbuf,
612 categoryname != NULL ? categoryname : "",
613 tags != NULL ? tags : ""
614 );
615
616 //leak
617 g_free(tags);
618
619 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
620 }
621
622 //DB( g_print("text is:\n%s", node->str) );
623
624 return node;
625 }
626
627
628 gboolean list_txn_column_id_isvisible(GtkTreeView *treeview, gint sort_id)
629 {
630 GtkTreeViewColumn *column;
631 gint n, id;
632
633 for(n=0; n < NUM_LST_DSPOPE-1 ; n++ ) // -1 cause account not to be processed
634 {
635 column = gtk_tree_view_get_column (treeview, n);
636 if(column == NULL)
637 continue;
638
639 if( gtk_tree_view_column_get_visible(column) )
640 {
641 id = gtk_tree_view_column_get_sort_column_id (column);
642 if( sort_id == id )
643 return TRUE;
644 }
645 }
646
647 return FALSE;
648 }
649
650
651 static GtkTreeViewColumn *list_txn_get_column(GList *list, gint search_id)
652 {
653 GtkTreeViewColumn *column = NULL;
654 GList *tmp;
655 gint id;
656
657 tmp = g_list_first(list);
658 while (tmp != NULL)
659 {
660 id = gtk_tree_view_column_get_sort_column_id(tmp->data);
661 if( search_id == id )
662 {
663 column = tmp->data;
664 break;
665 }
666 tmp = g_list_next(tmp);
667 }
668 return column;
669 }
670
671
672 guint list_txn_get_quicksearch_column_mask(GtkTreeView *treeview)
673 {
674 GtkTreeViewColumn *column;
675 guint n, mask;
676 gint id;
677
678 mask = 0;
679 for(n=0; n < NUM_LST_DSPOPE-1 ; n++ ) // -1 cause account not to be processed
680 {
681 column = gtk_tree_view_get_column (treeview, n);
682 if(column == NULL)
683 continue;
684
685 if( gtk_tree_view_column_get_visible(column) )
686 {
687 id = gtk_tree_view_column_get_sort_column_id (column);
688 switch(id)
689 {
690 case LST_DSPOPE_MEMO: mask |= FLT_QSEARCH_MEMO; break;
691 case LST_DSPOPE_INFO: mask |= FLT_QSEARCH_INFO; break;
692 case LST_DSPOPE_PAYEE: mask |= FLT_QSEARCH_PAYEE; break;
693 case LST_DSPOPE_CATEGORY: mask |= FLT_QSEARCH_CATEGORY; break;
694 case LST_DSPOPE_TAGS: mask |= FLT_QSEARCH_TAGS; break;
695 case LST_DSPOPE_AMOUNT:
696 case LST_DSPOPE_EXPENSE:
697 case LST_DSPOPE_INCOME: mask |= FLT_QSEARCH_AMOUNT; break;
698 }
699 }
700 }
701
702 return mask;
703 }
704
705
706 void list_txn_set_save_column_width(GtkTreeView *treeview, gboolean save_column_width)
707 {
708 struct list_txn_data *data;
709
710 data = g_object_get_data(G_OBJECT(treeview), "inst_data");
711 if( data )
712 {
713 data->save_column_width = save_column_width;
714 }
715 }
716
717
718 void list_txn_set_column_acc_visible(GtkTreeView *treeview, gboolean visible)
719 {
720 struct list_txn_data *data;
721 GList *list;
722 GtkTreeViewColumn *column;
723
724 data = g_object_get_data(G_OBJECT(treeview), "inst_data");
725
726 data->showall = visible;
727
728 list = gtk_tree_view_get_columns( treeview );
729 //if acc visible: balance must be invisible
730 column = list_txn_get_column(list, LST_DSPOPE_ACCOUNT);
731 if(column)
732 gtk_tree_view_column_set_visible (column, visible);
733 column = list_txn_get_column(list, LST_DSPOPE_BALANCE);
734 if(column)
735 gtk_tree_view_column_set_visible (column, !visible);
736
737
738 g_list_free(list);
739 }
740
741
742 void list_txn_sort_force(GtkTreeSortable *sortable, gpointer user_data)
743 {
744 gint sort_column_id;
745 GtkSortType order;
746
747 DB( g_print("list_txn_sort_force\n") );
748
749 gtk_tree_sortable_get_sort_column_id(sortable, &sort_column_id, &order);
750 DB( g_print(" - id %d order %d\n", sort_column_id, order) );
751
752 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(sortable), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, order);
753 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(sortable), sort_column_id, order);
754 }
755
756
757 static void list_txn_get_columns(GtkTreeView *treeview)
758 {
759 struct list_txn_data *data;
760 GtkTreeViewColumn *column;
761 gint i, col_id;
762
763 DB( g_print("\n[list_txn] get columns position/width\n") );
764
765 data = g_object_get_data(G_OBJECT(treeview), "inst_data");
766
767 DB( g_print(" nbcol=%d, nbsortid=%d\n", NUM_LST_DSPOPE, gtk_tree_view_get_n_columns (treeview)) );
768
769 for(i=0 ; i < NUM_LST_DSPOPE-1 ; i++ ) // -1 'caus: account and blank column
770 {
771 column = gtk_tree_view_get_column(treeview, i);
772 if(column != NULL)
773 {
774 col_id = gtk_tree_view_column_get_sort_column_id (column);
775 if( col_id >= 0 )
776 {
777 gboolean visible;
778
779 visible = gtk_tree_view_column_get_visible (column);
780 if( col_id == LST_DSPOPE_BALANCE) //keep initial state of balance
781 visible = data->tvc_is_visible;
782
783 if( visible )
784 {
785 PREFS->lst_ope_columns[i] = col_id;
786 //5.2 moved here to keep old width in case not visible
787 PREFS->lst_ope_col_width[col_id-1] = gtk_tree_view_column_get_width(column);
788 }
789 else
790 PREFS->lst_ope_columns[i] = -col_id;
791
792 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] ) );
793 }
794 else //should not occurs
795 PREFS->lst_ope_columns[i] = 0;
796 }
797 }
798 }
799
800
801 static void list_txn_set_columns(GtkTreeView *treeview, gint *col_id)
802 {
803 struct list_txn_data *data;
804 GtkTreeViewColumn *column, *base;
805 gboolean visible;
806 GList *list;
807 gint i = 0;
808 gint id;
809
810 DB( g_print("\n[list_txn] set columns order/width\n") );
811
812 data = g_object_get_data(G_OBJECT(treeview), "inst_data");
813
814 #if MYDEBUG == 1
815 DB( g_print("\n debug column sortid\n") );
816
817 for(i=0; i < NUM_LST_DSPOPE-1 ; i++ ) // -1 cause account not to be processed
818 {
819 DB( g_print(" - pos:%2d sortid:%2d\n", i, col_id[i]) );
820 }
821 #endif
822
823
824 DB( g_print("\n apply column prefs\n") );
825
826 list = gtk_tree_view_get_columns( treeview );
827
828 base = NULL;
829
830 for(i=0; i < NUM_LST_DSPOPE-1 ; i++ ) // -1 cause account not to be processed
831 {
832 /* hidden are stored as col_id negative */
833 id = ABS(col_id[i]);
834 column = list_txn_get_column(list, id);
835
836 //DB( g_print(" - get column %d %p\n", id, column) );
837
838 if( column != NULL )
839 {
840 DB( g_print(" - pos:%2d sortid:%2d (%s)\n", i, col_id[i], gtk_tree_view_column_get_title(column)) );
841
842 gtk_tree_view_move_column_after(treeview, column, base);
843 base = column;
844
845 visible = col_id[i] < 0 ? FALSE : TRUE;
846
847 /* display exception for detail/import list */
848 if(data->list_type != LIST_TXN_TYPE_BOOK)
849 {
850 if( id == LST_DSPOPE_AMOUNT )
851 visible = TRUE;
852
853 if( id == LST_DSPOPE_STATUS || id == LST_DSPOPE_EXPENSE || id == LST_DSPOPE_INCOME )
854 visible = FALSE;
855 }
856
857 gtk_tree_view_column_set_visible (column, visible);
858 if( id == LST_DSPOPE_BALANCE )
859 {
860 data->tvc_is_visible = visible;
861 }
862
863 if( id == LST_DSPOPE_INFO
864 || id == LST_DSPOPE_PAYEE
865 || id == LST_DSPOPE_MEMO
866 || id == LST_DSPOPE_CATEGORY
867 || id == LST_DSPOPE_TAGS
868 || id == LST_DSPOPE_ACCOUNT )
869 {
870 gtk_tree_view_column_set_fixed_width( column, PREFS->lst_ope_col_width[id - 1]);
871 }
872 }
873
874 }
875
876 g_list_free(list );
877 }
878
879
880 static void list_txn_sort_column_changed(GtkTreeSortable *sortable, gpointer user_data)
881 {
882 struct list_txn_data *data = user_data;
883 gint id;
884 GtkSortType order;
885 gboolean showBalance;
886
887 gtk_tree_sortable_get_sort_column_id(sortable, &id, &order);
888
889 DB( g_print("list_txn_columns_changed %d %d\n", id, order) );
890
891 //here save the transaction list columnid and sort order
892 PREFS->lst_ope_sort_id = id;
893 PREFS->lst_ope_sort_order = order;
894
895 //manage visibility of balance column
896 //showBalance = (id == LST_DSPOPE_DATE && order == GTK_SORT_ASCENDING) ? data->tvc_is_visible : FALSE;
897 showBalance = (id == LST_DSPOPE_DATE) ? data->tvc_is_visible : FALSE;
898 if(data->showall == TRUE) showBalance = FALSE;
899 gtk_tree_view_column_set_visible (data->tvc_balance, showBalance);
900 }
901
902
903 static void
904 list_txn_column_popup_menuitem_on_activate (GtkCheckMenuItem *checkmenuitem,
905 gpointer user_data)
906 {
907 GtkTreeViewColumn *column = user_data;
908
909 DB( g_print("toggled\n") );
910
911 gtk_tree_view_column_set_visible(column, gtk_check_menu_item_get_active(checkmenuitem) );
912 }
913
914
915 static gboolean
916 list_txn_column_popup_callback ( GtkWidget *button,
917 GdkEventButton *ev,
918 gpointer user_data )
919 {
920 struct list_txn_data *data = user_data;
921 GtkWidget *menu, *menuitem;
922 GtkTreeViewColumn *column;
923 gint i, col_id;
924
925
926 if( ev->button == 3 )
927 {
928 DB( g_print("should popup\n") );
929
930 menu = gtk_menu_new ();
931
932 //note: deactive this disable any menuitem action
933 g_signal_connect (menu, "selection-done", G_CALLBACK (gtk_widget_destroy), NULL);
934
935 for(i=0 ; i < NUM_LST_DSPOPE-1 ; i++ ) // -1 'caus: account and blank column
936 {
937 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data->treeview), i);
938 if( column != NULL )
939 {
940 col_id = gtk_tree_view_column_get_sort_column_id (column);
941
942 if( (col_id == -1)
943 || (col_id == LST_DSPOPE_STATUS)
944 || (col_id == LST_DSPOPE_ACCOUNT)
945 || (col_id == LST_DSPOPE_DATE)
946 || (col_id == LST_DSPOPE_BALANCE)
947 )
948 continue;
949 //if( (data->tvc_is_visible == FALSE) && (col_id == LST_DSPOPE_BALANCE) )
950 // continue;
951
952 if( (data->list_type == LIST_TXN_TYPE_DETAIL) &&
953 ( (col_id == LST_DSPOPE_AMOUNT)
954 || (col_id == LST_DSPOPE_EXPENSE)
955 || (col_id == LST_DSPOPE_INCOME)
956 )
957 )
958 continue;
959
960 menuitem = gtk_check_menu_item_new_with_label ( gtk_tree_view_column_get_title (column) );
961 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
962 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), gtk_tree_view_column_get_visible (column) );
963 gtk_widget_show (menuitem);
964
965 g_signal_connect (menuitem, "activate",
966 G_CALLBACK (list_txn_column_popup_menuitem_on_activate), column);
967 }
968
969 }
970
971 gtk_menu_attach_to_widget (GTK_MENU (menu), button, NULL);
972 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
973 ev->button, ev->time);
974 }
975
976 return FALSE;
977 }
978
979
980 static GtkTreeViewColumn *
981 list_txn_column_amount_create(gint list_type, gchar *title, gint sortcolumnid, GtkTreeCellDataFunc func)
982 {
983 GtkTreeViewColumn *column;
984 GtkCellRenderer *renderer;
985
986 renderer = gtk_cell_renderer_text_new ();
987 g_object_set(renderer, "xalign", 1.0, NULL);
988
989 column = gtk_tree_view_column_new_with_attributes(title, renderer, NULL);
990
991 gtk_tree_view_column_set_alignment (column, 0.5);
992 //gtk_tree_view_column_set_resizable(column, TRUE);
993 gtk_tree_view_column_set_sort_column_id (column, sortcolumnid);
994 if(list_type == LIST_TXN_TYPE_BOOK)
995 {
996 gtk_tree_view_column_set_reorderable(column, TRUE);
997 }
998 gtk_tree_view_column_set_cell_data_func(column, renderer, func, GINT_TO_POINTER(sortcolumnid), NULL);
999
1000 return column;
1001 }
1002
1003
1004 static GtkTreeViewColumn *
1005 list_txn_column_text_create(gint list_type, gchar *title, gint sortcolumnid, GtkTreeCellDataFunc func, gpointer user_data)
1006 {
1007 GtkTreeViewColumn *column;
1008 GtkCellRenderer *renderer;
1009
1010 column = gtk_tree_view_column_new();
1011 gtk_tree_view_column_set_title(column, title);
1012
1013 //5.3 add > < for internal xfer
1014 if( sortcolumnid == LST_DSPOPE_PAYEE )
1015 {
1016 renderer = gtk_cell_renderer_text_new ();
1017 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1018 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_payeexfer_cell_data_function, NULL, NULL);
1019 }
1020
1021 renderer = gtk_cell_renderer_text_new ();
1022 g_object_set(renderer,
1023 "ellipsize", PANGO_ELLIPSIZE_END,
1024 "ellipsize-set", TRUE,
1025 //taken from nemo, not exactly a resize to content, but good compromise
1026 "width-chars", 40,
1027 NULL);
1028 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1029 gtk_tree_view_column_set_cell_data_func(column, renderer, func, NULL, NULL);
1030
1031 gtk_tree_view_column_set_alignment (column, 0.5);
1032 gtk_tree_view_column_set_resizable(column, TRUE);
1033
1034 gtk_tree_view_column_set_sort_column_id (column, sortcolumnid);
1035 if(list_type == LIST_TXN_TYPE_BOOK)
1036 {
1037 gtk_tree_view_column_set_reorderable(column, TRUE);
1038 gtk_tree_view_column_set_min_width (column, HB_MINWIDTH_COLUMN);
1039 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
1040 }
1041 gtk_tree_view_column_set_cell_data_func(column, renderer, func, user_data, NULL);
1042
1043 return column;
1044 }
1045
1046
1047 static GtkTreeViewColumn *
1048 list_txn_column_info_create(gint list_type)
1049 {
1050 GtkTreeViewColumn *column;
1051 GtkCellRenderer *renderer;
1052
1053 column = gtk_tree_view_column_new();
1054 gtk_tree_view_column_set_title(column, _("Info"));
1055
1056 renderer = gtk_cell_renderer_pixbuf_new ();
1057 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1058 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_info_cell_data_function, GINT_TO_POINTER(1), NULL);
1059
1060 renderer = gtk_cell_renderer_text_new ();
1061 g_object_set(renderer,
1062 "ellipsize", PANGO_ELLIPSIZE_END,
1063 "ellipsize-set", TRUE,
1064 //taken from nemo, not exactly a resize to content, but good compromise
1065 "width-chars", 40,
1066 NULL);
1067 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1068 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_info_cell_data_function, GINT_TO_POINTER(2), NULL);
1069
1070 gtk_tree_view_column_set_alignment (column, 0.5);
1071 gtk_tree_view_column_set_resizable(column, TRUE);
1072 gtk_tree_view_column_set_sort_column_id (column, LST_DSPOPE_INFO);
1073 if(list_type == LIST_TXN_TYPE_BOOK)
1074 {
1075 gtk_tree_view_column_set_reorderable(column, TRUE);
1076 gtk_tree_view_column_set_min_width (column, HB_MINWIDTH_COLUMN);
1077 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
1078 }
1079
1080 return column;
1081 }
1082
1083
1084 static void list_txn_destroy( GtkWidget *widget, gpointer user_data )
1085 {
1086 struct list_txn_data *data;
1087
1088 data = g_object_get_data(G_OBJECT(widget), "inst_data");
1089
1090 DB( g_print ("\n[list_transaction] destroy event occurred\n") );
1091
1092 if( data->save_column_width )
1093 {
1094 list_txn_get_columns(GTK_TREE_VIEW(data->treeview));
1095 }
1096
1097 DB( g_print(" - view=%p, inst_data=%p\n", widget, data) );
1098 g_free(data);
1099 }
1100
1101
1102 Transaction *list_txn_get_active_transaction(GtkTreeView *treeview)
1103 {
1104 GtkTreeModel *model;
1105 GList *list;
1106 Transaction *ope;
1107
1108 ope = NULL;
1109
1110 model = gtk_tree_view_get_model(treeview);
1111 list = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(treeview), &model);
1112
1113 if(list != NULL)
1114 {
1115 GtkTreeIter iter;
1116
1117 gtk_tree_model_get_iter(model, &iter, list->data);
1118 gtk_tree_model_get(model, &iter, MODEL_TXN_POINTER, &ope, -1);
1119 }
1120
1121 g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
1122 g_list_free(list);
1123
1124 return ope;
1125 }
1126
1127
1128 /*
1129 ** create our transaction list
1130 ** Status, Date, Info, Payee, Memo, (Amount), Expense, Income, Category
1131 */
1132 GtkWidget *create_list_transaction(gint list_type, gboolean *pref_columns)
1133 {
1134 struct list_txn_data *data;
1135 GtkListStore *store;
1136 GtkWidget *treeview;
1137 GtkCellRenderer *renderer;
1138 GtkTreeViewColumn *column, *col_acc = NULL, *col_status = NULL;
1139
1140
1141 data = g_malloc0(sizeof(struct list_txn_data));
1142 if(!data) return NULL;
1143
1144 data->list_type = list_type;
1145 data->save_column_width = FALSE;
1146
1147 /* create list store */
1148 store = gtk_list_store_new(
1149 2, G_TYPE_POINTER, // MODEL_TXN_POINTER
1150 G_TYPE_DOUBLE // MODEL_TXN_SPLITAMT amount part of split for detail only
1151 );
1152
1153 //treeview
1154 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1155 data->treeview = treeview;
1156 g_object_unref(store);
1157
1158 //store our window private data
1159 g_object_set_data(G_OBJECT(treeview), "inst_data", (gpointer)data);
1160 DB( g_print(" - treeview=%p, inst_data=%p\n", treeview, data) );
1161
1162 // connect our dispose function
1163 g_signal_connect (treeview, "destroy", G_CALLBACK (list_txn_destroy), (gpointer)data);
1164
1165 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
1166 //gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
1167 // COLUMN_DESCRIPTION);
1168
1169 if(list_type == LIST_TXN_TYPE_BOOK)
1170 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), GTK_SELECTION_MULTIPLE);
1171
1172 /* column 1: Changes */
1173 column = gtk_tree_view_column_new();
1174 //gtk_tree_view_column_set_title(column, _("Status"));
1175 col_status = column;
1176
1177 renderer = gtk_cell_renderer_pixbuf_new ();
1178 //gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
1179 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1180 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_status_cell_data_function, GINT_TO_POINTER(1), NULL);
1181
1182 renderer = gtk_cell_renderer_pixbuf_new ();
1183 //gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
1184 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1185 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_status_cell_data_function, GINT_TO_POINTER(2), NULL);
1186
1187 renderer = gtk_cell_renderer_pixbuf_new ();
1188 //gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
1189 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1190 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_status_cell_data_function, GINT_TO_POINTER(3), NULL);
1191
1192 gtk_tree_view_column_set_sort_column_id (column, LST_DSPOPE_STATUS);
1193 //gtk_tree_view_column_set_resizable(column, TRUE);
1194 gtk_tree_view_column_set_alignment (column, 0.5);
1195 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1196
1197 //5.2 we always create the column and set it not visible
1198 column = list_txn_column_text_create(list_type, _("Account"), LST_DSPOPE_ACCOUNT, list_txn_account_cell_data_function, NULL);
1199 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1200 col_acc = column;
1201 // add column popup
1202 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1203 "button-press-event",
1204 G_CALLBACK ( list_txn_column_popup_callback ),
1205 data );
1206
1207 /* column 2: Date */
1208 column = gtk_tree_view_column_new();
1209 gtk_tree_view_column_set_title(column, _("Date"));
1210 renderer = gtk_cell_renderer_text_new ();
1211 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1212 g_object_set(renderer, "xalign", 1.0, NULL);
1213 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_date_cell_data_function, NULL, NULL);
1214 gtk_tree_view_column_set_sort_column_id (column, LST_DSPOPE_DATE);
1215 //gtk_tree_view_column_set_resizable(column, TRUE);
1216 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1217 // add column popup
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 ),
1221 data );
1222
1223
1224 column = list_txn_column_info_create(list_type);
1225 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1226 // add column popup
1227 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1228 "button-press-event",
1229 G_CALLBACK ( list_txn_column_popup_callback ),
1230 data );
1231
1232 column = list_txn_column_text_create(list_type, _("Payee"), LST_DSPOPE_PAYEE, list_txn_payee_cell_data_function, NULL);
1233 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1234 // add column popup
1235 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1236 "button-press-event",
1237 G_CALLBACK ( list_txn_column_popup_callback ),
1238 data );
1239
1240 column = list_txn_column_text_create(list_type, _("Memo"), LST_DSPOPE_MEMO, list_txn_memo_cell_data_function, NULL);
1241 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1242 // add column popup
1243 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1244 "button-press-event",
1245 G_CALLBACK ( list_txn_column_popup_callback ),
1246 data );
1247
1248 /* column status CLR */
1249 column = gtk_tree_view_column_new();
1250 gtk_tree_view_column_set_title(column, _("Status"));
1251
1252 //renderer = gtk_cell_renderer_text_new ();
1253 renderer = gtk_cell_renderer_pixbuf_new();
1254 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1255 g_object_set(renderer, "xalign", 1.0, NULL);
1256 gtk_tree_view_column_set_cell_data_func(column, renderer, list_txn_clr_cell_data_function, NULL, NULL);
1257 gtk_tree_view_column_set_reorderable(column, TRUE);
1258 gtk_tree_view_column_set_sort_column_id (column, LST_DSPOPE_CLR);
1259 //gtk_tree_view_column_set_sort_indicator (column, FALSE);
1260 //gtk_tree_view_column_set_resizable(column, TRUE);
1261 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1262 // add column popup
1263 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1264 "button-press-event",
1265 G_CALLBACK ( list_txn_column_popup_callback ),
1266 data );
1267
1268
1269 column = list_txn_column_amount_create(list_type, _("Amount"), LST_DSPOPE_AMOUNT, list_txn_amount_cell_data_function);
1270 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1271 // add column popup
1272 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1273 "button-press-event",
1274 G_CALLBACK ( list_txn_column_popup_callback ),
1275 data );
1276
1277 column = list_txn_column_amount_create(list_type, _("Expense"), LST_DSPOPE_EXPENSE, list_txn_amount_cell_data_function);
1278 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1279 // add column popup
1280 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1281 "button-press-event",
1282 G_CALLBACK ( list_txn_column_popup_callback ),
1283 data );
1284
1285 column = list_txn_column_amount_create(list_type, _("Income"), LST_DSPOPE_INCOME, list_txn_amount_cell_data_function);
1286 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1287 // add column popup
1288 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1289 "button-press-event",
1290 G_CALLBACK ( list_txn_column_popup_callback ),
1291 data );
1292
1293 column = list_txn_column_text_create(list_type, _("Category"), LST_DSPOPE_CATEGORY, list_txn_category_cell_data_function, NULL);
1294 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1295 // add column popup
1296 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1297 "button-press-event",
1298 G_CALLBACK ( list_txn_column_popup_callback ),
1299 data );
1300
1301 column = list_txn_column_text_create(list_type, _("Tags"), LST_DSPOPE_TAGS, list_txn_tags_cell_data_function, NULL);
1302 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1303 // add column popup
1304 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1305 "button-press-event",
1306 G_CALLBACK ( list_txn_column_popup_callback ),
1307 data );
1308
1309 if(list_type == LIST_TXN_TYPE_BOOK)
1310 {
1311 column = list_txn_column_amount_create(list_type, _("Balance"), LST_DSPOPE_BALANCE, list_txn_amount_cell_data_function);
1312 data->tvc_balance = column;
1313 gtk_tree_view_column_set_clickable(column, FALSE);
1314 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1315 // add column popup
1316 g_signal_connect ( G_OBJECT (gtk_tree_view_column_get_button (column)),
1317 "button-press-event",
1318 G_CALLBACK ( list_txn_column_popup_callback ),
1319 data );
1320 }
1321
1322 /* column 9: empty */
1323 column = gtk_tree_view_column_new();
1324 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
1325
1326 /* sort */
1327 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);
1328 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);
1329 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);
1330 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);
1331 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);
1332 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);
1333 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);
1334 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);
1335 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);
1336 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);
1337 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);
1338 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);
1339
1340 /* apply user preference for columns */
1341 list_txn_set_columns(GTK_TREE_VIEW(treeview), pref_columns);
1342
1343 /* force account column for detail treeview */
1344 gtk_tree_view_move_column_after(GTK_TREE_VIEW(treeview), col_acc, col_status);
1345
1346 /* by default book don't display acc column, except shoall */
1347 //#1821850 detail account column visible
1348 gboolean visible = (list_type == LIST_TXN_TYPE_BOOK) ? FALSE: TRUE;
1349 gtk_tree_view_column_set_visible (col_acc, visible);
1350
1351 /* set initial sort order */
1352 DB( g_print("set sort to %d %d\n", PREFS->lst_ope_sort_id, PREFS->lst_ope_sort_order) );
1353 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), PREFS->lst_ope_sort_id, PREFS->lst_ope_sort_order);
1354
1355
1356 /* signals */
1357 if(list_type == LIST_TXN_TYPE_BOOK)
1358 g_signal_connect (GTK_TREE_SORTABLE(store), "sort-column-changed", G_CALLBACK (list_txn_sort_column_changed), data);
1359
1360 return(treeview);
1361 }
1362
1363
This page took 0.097803 seconds and 4 git commands to generate.