]> Dogcows Code - chaz/homebank/blob - src/ui-split.c
import homebank-5.2.4
[chaz/homebank] / src / ui-split.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 ofdeftransaction_amountchanged
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 #include "homebank.h"
21
22 #include "ui-split.h"
23 #include "ui-transaction.h"
24 #include "ui-archive.h"
25 #include "gtk-dateentry.h"
26 #include "ui-payee.h"
27 #include "ui-category.h"
28 #include "ui-account.h"
29 #include "hb-split.h"
30
31
32
33
34 /****************************************************************************/
35 /* Debug macros */
36 /****************************************************************************/
37 #define MYDEBUG 0
38
39 #if MYDEBUG
40 #define DB(x) (x);
41 #else
42 #define DB(x);
43 #endif
44
45 /* our global datas */
46 extern struct HomeBank *GLOBALS;
47 extern struct Preferences *PREFS;
48
49
50 #define GTK_RESPONSE_SPLIT_REM 10888
51
52
53 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
54 static void list_split_number_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
55 {
56 GtkTreePath *path;
57 gint *indices;
58 gchar num[16];
59
60 path = gtk_tree_model_get_path(model, iter);
61 indices = gtk_tree_path_get_indices(path);
62 //num = gtk_tree_path_to_string(path);
63 g_snprintf(num, 15, "%d", 1 + *indices);
64 gtk_tree_path_free(path);
65
66 g_object_set(renderer, "text", num, NULL);
67
68 }
69
70
71 static void list_split_amount_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
72 {
73 Split *split;
74 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
75 gdouble amount;
76 gchar *color;
77
78 gtk_tree_model_get(model, iter, 0, &split, -1);
79
80 //hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, amount, ope->kcur, GLOBALS->minor);
81 amount = split->amount;
82 g_snprintf(buf, G_ASCII_DTOSTR_BUF_SIZE-1, "%.2f", amount);
83
84 color = get_normal_color_amount(amount);
85 g_object_set(renderer,
86 "foreground", color,
87 "text", buf,
88 NULL);
89
90 }
91
92
93 static void list_split_memo_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
94 {
95 Split *split;
96
97 gtk_tree_model_get(model, iter, 0, &split, -1);
98
99 g_object_set(renderer, "text", split->memo, NULL);
100 }
101
102
103 static void list_split_category_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
104 {
105 Split *split;
106 Category *cat;
107
108 gtk_tree_model_get(model, iter, 0, &split, -1);
109
110 cat = da_cat_get(split->kcat);
111 if( cat != NULL )
112 {
113 g_object_set(renderer, "text", cat->fullname, NULL);
114 }
115 else
116 g_object_set(renderer, "text", "", NULL);
117 }
118
119
120 static void list_split_populate(struct ui_split_dialog_data *data)
121 {
122 GtkTreeModel *model;
123 GtkTreeIter iter;
124 Split *split;
125 gint count, i;
126
127 DB( g_print("\n[list_split] populate\n") );
128
129 count = da_splits_length (data->tmp_splits);
130
131 if( count <= 0 )
132 return;
133
134 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split));
135
136 gtk_list_store_clear (GTK_LIST_STORE(model));
137
138 g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
139 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_split), NULL); /* Detach model from view */
140
141 /* populate */
142 for(i=0 ; i < count ; i++)
143 {
144 split = da_splits_get(data->tmp_splits, i);
145
146 DB( g_print("- set split %d : %d, %.2f, %s\n", i, split->kcat, split->amount, split->memo) );
147
148 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
149 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
150 0, split,
151 -1);
152
153 }
154
155 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_split), model); /* Re-attach model to view */
156 g_object_unref(model);
157 }
158
159
160
161
162
163 static GtkWidget *
164 list_split_new(void)
165 {
166 GtkListStore *store;
167 GtkWidget *treeview;
168 GtkCellRenderer *renderer;
169 GtkTreeViewColumn *column;
170
171 DB( g_print("\n[ui_split_listview] new\n") );
172
173
174 // create list store
175 store = gtk_list_store_new(1,
176 G_TYPE_POINTER
177 );
178
179 // treeview
180 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
181 g_object_unref(store);
182
183 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
184
185 //column 0: line number
186 renderer = gtk_cell_renderer_text_new ();
187 g_object_set(renderer, "xalign", 1.0, NULL);
188 column = gtk_tree_view_column_new_with_attributes("#", renderer, NULL);
189 gtk_tree_view_column_set_alignment (column, 1.0);
190 gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_number_cell_data_function, NULL, NULL);
191 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
192 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
193
194
195 // column 1: category
196 renderer = gtk_cell_renderer_text_new ();
197 g_object_set(renderer,
198 "ellipsize", PANGO_ELLIPSIZE_END,
199 "ellipsize-set", TRUE,
200 NULL);
201
202 column = gtk_tree_view_column_new_with_attributes(_("Category"), renderer, NULL);
203
204 //gtk_tree_view_column_set_alignment (column, 0.5);
205 gtk_tree_view_column_set_resizable(column, TRUE);
206
207 //gtk_tree_view_column_set_sort_column_id (column, sortcolumnid);
208 //gtk_tree_view_column_set_fixed_width( column, HB_MINWIDTH_LIST);
209 gtk_tree_view_column_set_expand (column, TRUE);
210 gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_category_cell_data_function, NULL, NULL);
211 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
212
213 // column 2: memo
214 renderer = gtk_cell_renderer_text_new ();
215 g_object_set(renderer,
216 "ellipsize", PANGO_ELLIPSIZE_END,
217 "ellipsize-set", TRUE,
218 NULL);
219
220 column = gtk_tree_view_column_new_with_attributes(_("Memo"), renderer, NULL);
221
222 //gtk_tree_view_column_set_alignment (column, 0.5);
223 gtk_tree_view_column_set_resizable(column, TRUE);
224
225 //gtk_tree_view_column_set_sort_column_id (column, sortcolumnid);
226 //gtk_tree_view_column_set_fixed_width( column, HB_MINWIDTH_LIST);
227 gtk_tree_view_column_set_expand (column, TRUE);
228 gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_memo_cell_data_function, NULL, NULL);
229 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
230
231
232 // column 3: amount
233 renderer = gtk_cell_renderer_text_new ();
234 g_object_set(renderer, "xalign", 1.0, NULL);
235
236 column = gtk_tree_view_column_new_with_attributes(_("Amount"), renderer, NULL);
237
238 gtk_tree_view_column_set_alignment (column, 1.0);
239 gtk_tree_view_column_set_resizable(column, TRUE);
240 //gtk_tree_view_column_set_sort_column_id (column, sortcolumnid);
241 gtk_tree_view_column_set_fixed_width( column, HB_MINWIDTH_LIST);
242 gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_amount_cell_data_function, NULL, NULL);
243 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
244
245
246 // column empty
247 //column = gtk_tree_view_column_new();
248 //gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
249
250
251 // treeviewattribute
252 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE);
253 gtk_tree_view_set_reorderable (GTK_TREE_VIEW(treeview), TRUE);
254
255 //gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), ui_acc_listview_compare_func, NULL, NULL);
256 //gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
257
258 return treeview;
259 }
260
261
262
263
264 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
265
266 static void ui_split_dialog_filter_text_handler (GtkEntry *entry,
267 const gchar *text,
268 gint length,
269 gint *position,
270 gpointer data)
271 {
272 GtkEditable *editable = GTK_EDITABLE(entry);
273 gint i, count=0;
274 gchar *result = g_new0 (gchar, length+1);
275
276 for (i=0; i < length; i++)
277 {
278 if (text[i]=='|')
279 continue;
280 result[count++] = text[i];
281 }
282
283
284 if (count > 0) {
285 g_signal_handlers_block_by_func (G_OBJECT (editable),
286 G_CALLBACK (ui_split_dialog_filter_text_handler),
287 data);
288 gtk_editable_insert_text (editable, result, count, position);
289 g_signal_handlers_unblock_by_func (G_OBJECT (editable),
290 G_CALLBACK (ui_split_dialog_filter_text_handler),
291 data);
292 }
293 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
294
295 g_free (result);
296 }
297
298
299 static void ui_split_dialog_cb_eval_order(struct ui_split_dialog_data *data)
300 {
301 GtkTreeModel *model;
302 GtkTreeIter iter;
303 gboolean valid;
304 guint i;
305
306 DB( g_print("\n[ui_split_dialog] eval order\n") );
307
308 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split));
309 i=1; valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
310 while (valid)
311 {
312 Split *split;
313
314 gtk_tree_model_get (model, &iter, 0, &split, -1);
315 split->pos = i;
316
317 DB( g_print("split pos: %d '%s' %.2f\n", i, split->memo, split->amount) );
318
319 i++; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
320 }
321
322 da_splits_sort(data->tmp_splits);
323 }
324
325
326 static void ui_split_dialog_cb_eval_split(GtkWidget *widget, gpointer user_data)
327 {
328 struct ui_split_dialog_data *data;
329 gboolean tmpval = FALSE;
330 gdouble amount;
331 gint count;
332
333 DB( g_print("\n[ui_split_dialog] eval split\n") );
334
335 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
336
337 amount= g_strtod(gtk_entry_get_text(GTK_ENTRY(data->ST_amount)), NULL);
338
339 tmpval = hb_amount_round(amount, 2) != 0.0 ? TRUE : FALSE;
340 gtk_widget_set_sensitive (data->BT_apply, tmpval);
341
342 count = gtk_tree_model_iter_n_children(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split)), NULL);
343 if( count >= TXN_MAX_SPLIT )
344 tmpval = FALSE;
345 gtk_widget_set_sensitive (data->BT_add, tmpval);
346
347 DB( g_print(" - txt='%s' amt=%.2f, nbsplit=%d, valid=%d\n", gtk_entry_get_text(GTK_ENTRY(data->ST_amount)), amount, count, tmpval) );
348
349 }
350
351
352 static void ui_split_dialog_update(GtkWidget *widget, gpointer user_data)
353 {
354 struct ui_split_dialog_data *data;
355 gboolean tmpval;
356 guint count;
357
358 DB( g_print("\n[ui_split_dialog] update\n") );
359
360 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
361
362 count = da_splits_length (data->tmp_splits);
363
364 //btn: edit/rem
365 tmpval = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)), NULL, NULL);
366 gtk_widget_set_sensitive (data->BT_edit, (data->isedited) ? FALSE : tmpval);
367 gtk_widget_set_sensitive (data->BT_rem, (data->isedited) ? FALSE : tmpval);
368
369 //btn: remall
370 tmpval = (count > 1) ? TRUE : FALSE;
371 gtk_widget_set_sensitive (data->BT_remall, (data->isedited) ? FALSE : tmpval);
372
373 ui_split_dialog_cb_eval_split(widget, NULL);
374
375 //btn: add/apply
376 /*amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount));
377 tmpval = hb_amount_round(amount, 2) != 0.0 ? TRUE : FALSE;
378 gtk_widget_set_sensitive (data->BT_apply, tmpval);
379
380 if( count >= TXN_MAX_SPLIT )
381 tmpval = FALSE;
382 gtk_widget_set_sensitive (data->BT_add, tmpval);
383 */
384
385 //btn: show/hide
386 gtk_widget_set_sensitive (data->LV_split, !data->isedited);
387
388 hb_widget_visible (data->BT_add, !data->isedited);
389
390 hb_widget_visible (data->IM_edit, data->isedited);
391 hb_widget_visible (data->BT_apply, data->isedited);
392 hb_widget_visible (data->BT_cancel, data->isedited);
393 }
394
395
396 static void ui_split_dialog_edit_end(GtkWidget *widget, gpointer user_data)
397 {
398 struct ui_split_dialog_data *data;
399
400 DB( g_print("\n[ui_split_dialog] edit_end\n") );
401
402 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
403
404 g_signal_handler_block(data->PO_cat, data->hid_cat);
405 g_signal_handler_block(data->ST_amount, data->hid_amt);
406
407 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat), 0);
408 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount), 0.0);
409 gtk_entry_set_text(GTK_ENTRY(data->ST_memo), "");
410
411 g_signal_handler_unblock(data->ST_amount, data->hid_amt);
412 g_signal_handler_unblock(data->PO_cat, data->hid_cat);
413
414 data->isedited = FALSE;
415 }
416
417
418 static void ui_split_dialog_edit_start(GtkWidget *widget, gpointer user_data)
419 {
420 struct ui_split_dialog_data *data;
421 GtkTreeSelection *selection;
422 GtkTreeModel *model;
423 GtkTreeIter iter;
424
425 DB( g_print("\n[ui_split_dialog] edit_start\n") );
426
427 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
428
429 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split));
430 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split));
431 if (gtk_tree_selection_get_selected(selection, &model, &iter))
432 {
433 Split *split;
434 gchar *txt;
435
436 gtk_tree_model_get(model, &iter, 0, &split, -1);
437
438 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat), split->kcat);
439 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount), split->amount);
440 txt = (split->memo != NULL) ? split->memo : "";
441 gtk_entry_set_text(GTK_ENTRY(data->ST_memo), txt);
442
443 data->isedited = TRUE;
444
445 ui_split_dialog_update (data->dialog, user_data);
446 }
447 }
448
449
450
451 static void ui_split_dialog_cancel_cb(GtkWidget *widget, gpointer user_data)
452 {
453 //struct ui_split_dialog_data *data;
454
455 DB( g_print("\n[ui_split_dialog] cancel\n") );
456
457 //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
458
459 ui_split_dialog_edit_end(widget, user_data);
460 ui_split_dialog_update (widget, user_data);
461 }
462
463
464 static void ui_split_dialog_apply_cb(GtkWidget *widget, gpointer user_data)
465 {
466 struct ui_split_dialog_data *data;
467 GtkTreeSelection *selection;
468 GtkTreeModel *model;
469 GtkTreeIter iter;
470
471 DB( g_print("\n[ui_split_dialog] apply\n") );
472
473 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
474
475 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split));
476 if (gtk_tree_selection_get_selected(selection, &model, &iter))
477 {
478 Split *split;
479 gdouble amount;
480
481 gtk_tree_model_get(model, &iter, 0, &split, -1);
482 gtk_spin_button_update (GTK_SPIN_BUTTON(data->ST_amount));
483 amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount));
484 if(amount)
485 {
486 split->kcat = ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data->PO_cat));
487 g_free(split->memo);
488 split->memo = g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_memo)));
489 split->amount = amount;
490 }
491 }
492
493 ui_split_dialog_edit_end(widget, user_data);
494 ui_split_dialog_compute (widget, data);
495 ui_split_dialog_update (widget, user_data);
496 }
497
498
499 static void ui_split_dialog_removeall_cb(GtkWidget *widget, gpointer user_data)
500 {
501 struct ui_split_dialog_data *data;
502
503 DB( g_print("\n[ui_split_dialog] removeall_cb\n") );
504
505 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
506
507 gtk_list_store_clear (GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(data->LV_split))));
508 da_split_destroy(data->tmp_splits);
509 data->tmp_splits = da_split_new ();
510
511 ui_split_dialog_compute (widget, data);
512 ui_split_dialog_update (widget, user_data);
513 }
514
515
516 static void ui_split_dialog_remove_cb(GtkWidget *widget, gpointer user_data)
517 {
518 struct ui_split_dialog_data *data;
519 GtkTreeSelection *selection;
520 GtkTreeModel *model;
521 GtkTreeIter iter;
522
523 DB( g_print("\n[ui_split_dialog] remove_cb\n") );
524
525 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
526
527 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split));
528 if (gtk_tree_selection_get_selected(selection, &model, &iter))
529 {
530 Split *split;
531
532 gtk_tree_model_get(model, &iter, 0, &split, -1);
533 //todo: not implemented yet
534 da_splits_remove(data->tmp_splits, split);
535 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
536 }
537
538 ui_split_dialog_compute (widget, data);
539 ui_split_dialog_update (widget, user_data);
540 }
541
542
543 static void ui_split_dialog_add_cb(GtkWidget *widget, gpointer user_data)
544 {
545 struct ui_split_dialog_data *data;
546 GtkTreeModel *model;
547 GtkTreeIter iter;
548 Split *split;
549 guint count;
550 gdouble amount;
551
552 DB( g_print("\n[ui_split_dialog] add\n") );
553
554 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
555
556 count = da_splits_length (data->tmp_splits);
557 if( count <= TXN_MAX_SPLIT )
558 {
559 split = da_split_malloc ();
560 gtk_spin_button_update (GTK_SPIN_BUTTON(data->ST_amount));
561 amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount));
562 if(amount)
563 {
564 split->amount = amount;
565 split->kcat = ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data->PO_cat));
566 split->memo = g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_memo)));
567
568 DB( g_print("- get split : %d, %.2f, %s\n", split->kcat, split->amount, split->memo) );
569
570 da_splits_append (data->tmp_splits, split);
571
572 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split));
573 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
574 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
575 0, split,
576 -1);
577
578 ui_split_dialog_compute (widget, data);
579
580 }
581 else
582 {
583 //todo: msg max number reached
584 da_split_free(split);
585 }
586 }
587
588 ui_split_dialog_edit_end(widget, user_data);
589 ui_split_dialog_update (widget, user_data);
590 }
591
592
593 static void ui_split_dialog_cb_activate_split(GtkWidget *widget, gpointer user_data)
594 {
595 struct ui_split_dialog_data *data;
596
597 DB( g_print("\n[ui_split_dialog] cb activate split\n") );
598
599 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
600
601 if( data->isedited == TRUE )
602 ui_split_dialog_apply_cb(widget, NULL);
603 else
604 ui_split_dialog_add_cb(widget, NULL);
605 }
606
607
608 static void ui_split_rowactivated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data)
609 {
610 DB( g_print("\n[ui_split_dialog] rowactivated\n") );
611
612 ui_split_dialog_edit_start(GTK_WIDGET(treeview), NULL);
613 }
614
615
616 static void ui_split_selection(GtkTreeSelection *treeselection, gpointer user_data)
617 {
618 DB( g_print("\n[ui_split_dialog] selection\n") );
619
620 ui_split_dialog_update (GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), user_data);
621 }
622
623
624 void ui_split_dialog_compute(GtkWidget *widget, gpointer user_data)
625 {
626 struct ui_split_dialog_data *data;
627 gint i, count, nbvalid;
628 gchar buf[48];
629 gboolean sensitive;
630 GtkTreeModel *model;
631 GtkTreeIter iter;
632 gboolean valid;
633
634 DB( g_print("\n[ui_split_dialog] compute\n") );
635
636 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
637
638 nbvalid = 0;
639 data->sumsplit = 0.0;
640 data->remsplit = 0.0;
641
642 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split));
643 i=0; valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
644 while (valid)
645 {
646 Split *split;
647
648 gtk_tree_model_get (model, &iter,
649 0, &split,
650 -1);
651
652 data->sumsplit += split->amount;
653 if( hb_amount_round(split->amount, 2) != 0.0 )
654 nbvalid++;
655
656 /* Make iter point to the next row in the list store */
657 i++; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
658 }
659 count = i;
660
661 DB( g_print("- count=%d, nbvalid=%d\n", count, nbvalid ) );
662
663 data->remsplit = data->amount - data->sumsplit;
664
665
666 //validation: 2 split min
667 sensitive = FALSE;
668 if( (count == 0) || nbvalid >= 2 )
669 sensitive = TRUE;
670 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->dialog), GTK_RESPONSE_ACCEPT, sensitive);
671
672 if( hb_amount_round(data->amount, 2) != 0.0 )
673 {
674 if(!data->remsplit)
675 g_sprintf(buf, "----");
676 else
677 g_snprintf(buf, 48, "%.2f", data->remsplit);
678
679 gtk_label_set_label(GTK_LABEL(data->LB_remain), buf);
680
681 g_snprintf(buf, 48, "%.2f", data->amount);
682 gtk_label_set_label(GTK_LABEL(data->LB_txnamount), buf);
683 }
684
685 g_snprintf(buf, 48, "%.2f", data->sumsplit);
686 gtk_label_set_text(GTK_LABEL(data->LB_sumsplit), buf);
687
688 }
689
690
691 static void ui_split_dialog_setup(struct ui_split_dialog_data *data)
692 {
693 guint count;
694
695 DB( g_print("\n[ui_split_dialog] set\n") );
696
697 count = da_splits_length(data->tmp_splits);
698 data->nbsplit = count > 1 ? count-1 : 0;
699
700 DB( g_print("- count = %d\n", count) );
701 list_split_populate (data);
702
703 data->isedited = FALSE;
704
705 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data->PO_cat), GLOBALS->h_cat);
706
707 ui_split_dialog_compute(data->dialog, data);
708 ui_split_dialog_update (data->dialog, data);
709 }
710
711
712 GtkWidget *ui_split_dialog (GtkWidget *parent, GPtrArray **src_splits, gdouble amount, void (update_callbackFunction(GtkWidget*, gdouble)))
713 {
714 struct ui_split_dialog_data *data;
715 GtkWidget *dialog, *content, *table, *box, *scrollwin;
716 GtkWidget *label, *widget;
717 gint row;
718
719 DB( g_print("\n[ui_split_dialog] new\n") );
720
721 data = g_malloc0(sizeof(struct ui_split_dialog_data));
722
723 dialog = gtk_dialog_new_with_buttons (_("Transaction splits"),
724 GTK_WINDOW(parent),
725 0,
726 _("_Cancel"),
727 GTK_RESPONSE_CANCEL,
728 NULL);
729
730 //store our dialog private data
731 g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)data);
732 DB( g_print(" - window=%p, inst_data=%p\n", dialog, data) );
733
734 g_signal_connect (dialog, "destroy",
735 G_CALLBACK (gtk_widget_destroyed), &dialog);
736
737 data->dialog = dialog;
738
739 //gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Remove"), GTK_RESPONSE_SPLIT_REM);
740 gtk_dialog_add_button(GTK_DIALOG(dialog), _("_OK"), GTK_RESPONSE_ACCEPT);
741
742 //todo: init should move
743 //clone splits or create new
744 data->src_splits = *src_splits;
745 data->amount = amount;
746 data->sumsplit = amount;
747
748 if( *src_splits != NULL )
749 data->tmp_splits = da_splits_clone(*src_splits);
750 else
751 data->tmp_splits = da_split_new();
752
753 //dialog contents
754 content = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
755
756 table = gtk_grid_new ();
757 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
758 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_TINY);
759 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_TINY);
760 gtk_box_pack_start (GTK_BOX (content), table, TRUE, TRUE, 0);
761
762 row = 0;
763
764 scrollwin = gtk_scrolled_window_new(NULL,NULL);
765 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
766 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
767 gtk_widget_set_size_request(scrollwin, HB_MINWIDTH_LIST, HB_MINHEIGHT_LIST);
768 gtk_widget_set_hexpand (scrollwin, TRUE);
769 gtk_widget_set_vexpand (scrollwin, TRUE);
770 data->LV_split = list_split_new();
771 gtk_container_add(GTK_CONTAINER(scrollwin), data->LV_split);
772 gtk_grid_attach (GTK_GRID (table), scrollwin, 0, row, 4, 1);
773
774 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_TINY);
775 gtk_widget_set_valign (box, GTK_ALIGN_CENTER);
776 gtk_grid_attach (GTK_GRID (table), box, 4, row, 1, 1);
777
778 widget = make_image_button(ICONNAME_LIST_REMOVE_ALL, _("Remove all"));
779 data->BT_remall = widget;
780 gtk_box_pack_end (GTK_BOX (box), widget, FALSE, FALSE, 0);
781
782 widget = make_image_button(ICONNAME_LIST_REMOVE, _("Remove"));
783 data->BT_rem = widget;
784 gtk_box_pack_end (GTK_BOX(box), widget, FALSE, FALSE, 0);
785
786 widget = make_image_button(ICONNAME_HB_OPE_EDIT, _("Edit"));
787 data->BT_edit = widget;
788 gtk_box_pack_end (GTK_BOX(box), widget, FALSE, FALSE, 0);
789
790 row++;
791 label = gtk_label_new(_("Category"));
792 gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
793 gtk_grid_attach (GTK_GRID (table), label, 0, row, 1, 1);
794
795 label = gtk_label_new(_("Memo"));
796 gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
797 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
798
799 label = gtk_label_new(_("Amount"));
800 gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
801 gtk_grid_attach (GTK_GRID (table), label, 2, row, 1, 1);
802
803
804 row++;
805 widget = ui_cat_comboboxentry_new(NULL);
806 data->PO_cat = widget;
807 gtk_grid_attach (GTK_GRID (table), widget, 0, row, 1, 1);
808
809 widget = make_string(NULL);
810 data->ST_memo= widget;
811 gtk_grid_attach (GTK_GRID (table), widget, 1, row, 1, 1);
812
813 widget = make_amount(NULL);
814 data->ST_amount = widget;
815 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
816
817 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_TINY);
818 gtk_grid_attach (GTK_GRID (table), box, 3, row, 1, 1);
819
820 widget = gtk_image_new_from_icon_name (ICONNAME_HB_OPE_EDIT, GTK_ICON_SIZE_BUTTON);
821 data->IM_edit = widget;
822 gtk_box_pack_start (GTK_BOX(box), widget, TRUE, TRUE, 0);
823
824 widget = make_image_button(ICONNAME_LIST_ADD, _("Add"));
825 data->BT_add = widget;
826 gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
827
828 widget = make_image_button(ICONNAME_EMBLEM_OK, _("Apply"));
829 data->BT_apply = widget;
830 gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
831
832 widget = make_image_button(ICONNAME_WINDOW_CLOSE, _("Cancel"));
833 data->BT_cancel = widget;
834 gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0);
835
836
837 if( hb_amount_round(data->amount, 2) != 0.0 )
838 {
839 row++;
840 label = gtk_label_new(_("Transaction amount:"));
841 gtk_widget_set_halign (label, GTK_ALIGN_END);
842 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
843 widget = gtk_label_new(NULL);
844 gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
845 data->LB_txnamount = widget;
846 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
847
848 row++;
849 label = gtk_label_new(_("Unassigned:"));
850 gtk_widget_set_halign (label, GTK_ALIGN_END);
851 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
852 widget = gtk_label_new(NULL);
853 gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
854 data->LB_remain = widget;
855 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
856
857 row++;
858 widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
859 gtk_grid_attach (GTK_GRID (table), widget, 1, row, 2, 1);
860
861 }
862
863 row++;
864 label = gtk_label_new(_("Sum of splits:"));
865 gtk_widget_set_halign (label, GTK_ALIGN_END);
866 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
867 widget = gtk_label_new(NULL);
868 gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
869 data->LB_sumsplit = widget;
870 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
871
872
873 //connect all our signals
874 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)), "changed", G_CALLBACK (ui_split_selection), data);
875 g_signal_connect (GTK_TREE_VIEW(data->LV_split), "row-activated", G_CALLBACK (ui_split_rowactivated), data);
876
877 g_signal_connect (data->ST_memo, "insert-text", G_CALLBACK(ui_split_dialog_filter_text_handler), data);
878
879 data->hid_cat = g_signal_connect (data->PO_cat , "changed" , G_CALLBACK (ui_split_dialog_cb_eval_split), data);
880 data->hid_amt = g_signal_connect (data->ST_amount, "changed", G_CALLBACK (ui_split_dialog_cb_eval_split), data);
881 //data->hid_amt = g_signal_connect (data->ST_amount, "value-changed", G_CALLBACK (ui_split_dialog_cb_eval_split), data);
882
883 //todo: add enter validate
884 g_signal_connect (data->ST_amount, "activate", G_CALLBACK (ui_split_dialog_cb_activate_split), NULL);
885
886
887 g_signal_connect (data->BT_edit , "clicked", G_CALLBACK (ui_split_dialog_edit_start), NULL);
888 g_signal_connect (data->BT_rem , "clicked", G_CALLBACK (ui_split_dialog_remove_cb), NULL);
889 g_signal_connect (data->BT_remall, "clicked", G_CALLBACK (ui_split_dialog_removeall_cb), NULL);
890
891 g_signal_connect (data->BT_add , "clicked", G_CALLBACK (ui_split_dialog_add_cb), NULL);
892 g_signal_connect (data->BT_apply , "clicked", G_CALLBACK (ui_split_dialog_apply_cb), NULL);
893 g_signal_connect (data->BT_cancel, "clicked", G_CALLBACK (ui_split_dialog_cancel_cb), NULL);
894
895 //gtk_window_set_default_size(GTK_WINDOW(dialog), 480, -1);
896 gtk_widget_show_all (dialog);
897
898 //setup, init and show dialog
899 ui_split_dialog_setup(data);
900
901 //wait for the user
902 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
903
904 switch (result)
905 {
906 // sum split and alter txn amount
907 case GTK_RESPONSE_ACCEPT:
908 if( da_splits_length(data->tmp_splits) )
909 {
910 ui_split_dialog_cb_eval_order(data);
911 // here we swap src_splits <> tmp_splits
912 *src_splits = data->tmp_splits;
913 data->tmp_splits = data->src_splits;
914 update_callbackFunction(parent, data->sumsplit);
915 }
916 else
917 {
918 //remove split and revert back original amount
919 da_split_destroy(*src_splits);
920 *src_splits = NULL;
921 update_callbackFunction(parent, data->amount);
922 }
923 break;
924 /*case GTK_RESPONSE_SPLIT_REM:
925 da_split_destroy(*src_splits);
926 *src_splits = NULL;
927 update_callbackFunction(parent, data->sumsplit);
928 break;
929 */
930 default:
931 //do_nothing_since_dialog_was_cancelled ();
932 break;
933 }
934
935 // debug
936 /*#if MYDEBUG == 1
937 {
938 guint i;
939
940 for(i=0;i<TXN_MAX_SPLIT;i++)
941 {
942 Split *split = data->ope_splits[i];
943 if(data->ope_splits[i] == NULL)
944 break;
945 g_print(" split %d : %d, %.2f, %s\n", i, split->kcat, split->amount, split->memo);
946 }
947 }
948 #endif*/
949
950 // cleanup and destroy
951 //GLOBALS->changes_count += data->change;
952 gtk_widget_destroy (dialog);
953
954 da_split_destroy (data->tmp_splits);
955 g_free(data);
956
957 return NULL;
958 }
959
This page took 0.076599 seconds and 4 git commands to generate.