1 /* ************************************************************************** */
2 /* */
3 /* Copyright (C) 2004-2008 Benjamin Drieu (bdrieu@april.org) */
4 /* 2008-2011 Pierre Biava (grisbi@pierre.biava.name) */
5 /* https://www.grisbi.org/ */
6 /* */
7 /* This program is free software; you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation; either version 2 of the License, or */
10 /* (at your option) any later version. */
11 /* */
12 /* This program is distributed in the hope that it will be useful, */
13 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
14 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
15 /* GNU General Public License for more details. */
16 /* */
17 /* You should have received a copy of the GNU General Public License */
18 /* along with this program; if not, write to the Free Software */
19 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20 /* */
21 /* ************************************************************************** */
22
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "include.h"
29 #include <glib/gi18n.h>
30
31 /*START_INCLUDE*/
32 #include "metatree.h"
33 #include "categories_onglet.h"
34 #include "dialog.h"
35 #include "grisbi_win.h"
36 #include "gsb_account_property.h"
37 #include "gsb_automem.h"
38 #include "gsb_data_account.h"
39 #include "gsb_data_budget.h"
40 #include "gsb_data_category.h"
41 #include "gsb_data_payee.h"
42 #include "gsb_data_scheduled.h"
43 #include "gsb_data_transaction.h"
44 #include "gsb_file.h"
45 #include "gsb_real.h"
46 #include "gsb_rgba.h"
47 #include "gsb_transactions_list.h"
48 #include "gtk_combofix.h"
49 #include "imputation_budgetaire.h"
50 #include "navigation.h"
51 #include "structures.h"
52 #include "tiers_onglet.h"
53 #include "traitement_variables.h"
54 #include "transaction_list.h"
55 #include "transaction_list_select.h"
56 #include "utils.h"
57 #include "utils_dates.h"
58 #include "utils_real.h"
59 #include "utils_str.h"
60 #include "erreur.h"
61 /*END_INCLUDE*/
62
63
64 /*START_STATIC*/
65 static void button_delete_div_sub_div_clicked (GtkWidget *togglebutton,
66 gpointer value);
67 static gboolean division_node_maybe_expand ( GtkTreeModel *model, GtkTreePath *path,
68 GtkTreeIter *iter, gpointer data );
69 static void fill_division_zero ( GtkTreeModel * model,
70 MetatreeInterface * iface,
71 GtkTreeIter * iter );
72 static void fill_sub_division_zero ( GtkTreeModel * model,
73 MetatreeInterface * iface,
74 GtkTreeIter * iter,
75 gint division );
76 static void fill_transaction_row ( GtkTreeModel * model, GtkTreeIter * iter,
77 gint transaction_number );
78 static gboolean find_associated_transactions ( MetatreeInterface * iface,
79 gint no_division, gint no_sub_division );
80 static gboolean find_destination_blob ( MetatreeInterface * iface, GtkTreeModel * model,
81 gint division, gint sub_division,
82 gint * no_div, gint * no_sub_div );
83 static GtkTreeIter *get_iter_from_sub_div_zero ( GtkTreeModel *model,
84 MetatreeInterface *iface,
85 GtkTreeIter *parent_iter );
86 static GtkTreeIter * get_iter_from_transaction ( GtkTreeModel * model,
87 gint transaction_number );
88 static void metatree_button_action_sub_div_clicked ( GtkWidget *togglebutton,
89 GdkEventButton *event,
90 gint *pointeur );
91 static gint metatree_create_division_from_sub_division ( MetatreeInterface *iface,
92 gint no_division,
93 gint no_sub_division );
94 static void metatree_fill_new_division ( MetatreeInterface * iface, GtkTreeModel * model,
95 gint div_id );
96 static void metatree_fill_new_sub_division ( MetatreeInterface * iface,
97 GtkTreeModel * model,
98 gint div_id, gint sub_div_id );
99 static void metatree_division_set_name ( MetatreeInterface *iface,
100 gint no_division,
101 gint no_sub_division,
102 gint new_division );
103 static gboolean metatree_find_destination_blob ( MetatreeInterface *iface,
104 GtkTreeModel *model,
105 gint division,
106 gint sub_division,
107 gint *no_div,
108 gint *no_sub_div,
109 enum MetaTreeRowType type_division );
110 static gboolean metatree_get ( GtkTreeModel * model, GtkTreePath * path,
111 gint column, gint *data );
112 static GtkWidget *metatree_get_combofix ( MetatreeInterface *iface,
113 gint division,
114 gint sub_division,
115 enum MetaTreeRowType type_division );
116 static GSList *metatree_get_combofix_list ( MetatreeInterface *iface,
117 gint division,
118 gint sub_division,
119 gboolean show_sub_division );
120 static gboolean metatree_get_row_properties ( GtkTreeModel * tree_model, GtkTreePath * path,
121 gchar ** text, gint * no_div, gint * no_sub_div,
122 gint * no_transaction, gint * data );
123 static enum MetaTreeRowType metatree_get_row_type ( GtkTreeModel * tree_model,
124 GtkTreePath * path );
125 static gboolean metatree_model_is_displayed ( GtkTreeModel * model );
126 static void metatree_move_scheduled_with_div_sub_div ( MetatreeInterface *iface,
127 GtkTreeModel *model,
128 gint no_division,
129 gint no_sub_division,
130 gint new_division,
131 gint new_sub_division );
132 static gint metatree_move_sub_division_to_division ( MetatreeInterface *iface,
133 gint no_division,
134 gint no_sub_division,
135 gint new_division );
136 static void metatree_move_transactions_to_sub_div ( MetatreeInterface *iface,
137 GtkTreeModel *model,
138 gint no_division,
139 gint no_sub_division,
140 gint new_division,
141 gint new_sub_division );
142 static void metatree_new_sub_division ( GtkTreeModel * model, gint div_id );
143 static void metatree_remove_iter_and_select_next ( GtkTreeView * tree_view,
144 GtkTreeModel * model,
145 GtkTreeIter * iter );
146 static void metatree_reset_transactions_without_div_sub_div ( MetatreeInterface *iface,
147 GtkTreeModel *model,
148 gint no_division,
149 gint new_division,
150 gint new_sub_division );
151 static void metatree_sub_division_set_name ( MetatreeInterface *iface,
152 gint no_division,
153 gint no_sub_division,
154 gint new_division,
155 gint new_sub_division );
156 static void metatree_update_tree_view ( MetatreeInterface *iface );
157 static void move_all_sub_divisions_to_division ( GtkTreeModel *model,
158 gint orig_division,
159 gint dest_division );
160 static void move_sub_division_to_division ( GtkTreeModel *model,
161 gint no_dest_division,
162 gint no_orig_division,
163 gint no_orig_sub_division );
164 static void move_transaction_to_sub_division ( gint transaction_number,
165 GtkTreeModel * model,
166 GtkTreePath * orig_path, GtkTreePath * dest_path,
167 gint no_division, gint no_sub_division );
168 static void move_transactions_to_division_payee (GtkTreeModel * model,
169 MetatreeInterface * iface,
170 gint orig_div, gint dest_div );
171 static gboolean search_for_div_or_subdiv ( GtkTreeModel *model, GtkTreePath *path,
172 GtkTreeIter *iter, gpointer * pointers);
173 static gboolean search_for_transaction ( GtkTreeModel *model, GtkTreePath *path,
174 GtkTreeIter *iter, gpointer * pointers);
175 static void supprimer_sub_division ( GtkTreeView * tree_view, GtkTreeModel * model,
176 MetatreeInterface * iface,
177 gint sub_division, gint division );
178 /*END_STATIC*/
179
180
181 /*START_EXTERN*/
182 /*END_EXTERN*/
183
184 /* Save the choice for the deleting of division */
185 static gint button_move_selected = 0;
186 static gint button_action_selected = 0;
187
188 static gint metatree_find_payee = 0;
189 static gint metatree_find_notes = 0;
190
191
192 /**
193 * Determine whether a model is displayed. That is, in metatree's
194 * meaning, it contains at least an iter.
195 *
196 * \param model A GtkTreeModel to test.
197 *
198 * \return TRUE on success.
199 */
metatree_model_is_displayed(GtkTreeModel * model)200 gboolean metatree_model_is_displayed ( GtkTreeModel * model )
201 {
202 GtkTreeIter iter;
203
204 return gtk_tree_model_get_iter_first ( model, &iter );
205 }
206
207
208
209 /**
210 * Utility function that returns some values associated to an entry.
211 *
212 * \param tree_model Tree model that contains entry.
213 * \param path A GtkTreePath pointing to entry to test.
214 * \param text A pointer to a char array that will be filled
215 * with the text content of entry if non null
216 * (aka META_TREE_TEXT_COLUMN).
217 * \param no_div A pointer to an int that will be filled
218 * with the division of entry if non null (aka
219 * META_TREE_NO_DIV_COLUMN).
220 * \param no_sub_div A pointer to an int that will be filled
221 * with the sub division of entry if non null
222 * (aka META_TREE_NO_SUB_DIV_COLUMN).
223 * \param no_transaction A pointer to an int that will be filled
224 * with the sub division of entry if non null
225 * (aka META_TREE_NO_SUB_DIV_COLUMN).
226 * \param data A pointer to an int that will be filled
227 * with the pointer associated to entry if non
228 * null (aka META_TREE_NO_SUB_DIV_COLUMN).
229 *
230 * \return TRUE on success.
231 */
metatree_get_row_properties(GtkTreeModel * tree_model,GtkTreePath * path,gchar ** text,gint * no_div,gint * no_sub_div,gint * no_transaction,gint * data)232 gboolean metatree_get_row_properties ( GtkTreeModel * tree_model, GtkTreePath * path,
233 gchar ** text, gint * no_div, gint * no_sub_div,
234 gint * no_transaction, gint * data )
235 {
236 GtkTreeIter iter;
237 gint tmp_lvl1, tmp_lvl2, tmp_lvl3;
238 gint tmp_data;
239 gchar * tmp_text;
240
241 if ( !gtk_tree_model_get_iter ( GTK_TREE_MODEL(tree_model), &iter, path ) )
242 {
243 /* This can be because drag is not possible, so no croak */
244 return FALSE;
245 }
246
247 gtk_tree_model_get ( GTK_TREE_MODEL(tree_model), &iter,
248 META_TREE_TEXT_COLUMN, &tmp_text,
249 META_TREE_NO_DIV_COLUMN, &tmp_lvl1,
250 META_TREE_NO_SUB_DIV_COLUMN, &tmp_lvl2,
251 META_TREE_NO_TRANSACTION_COLUMN, &tmp_lvl3,
252 META_TREE_POINTER_COLUMN, &tmp_data,
253 -1);
254
255 if ( text ) *text = tmp_text;
256 if ( no_div ) *no_div = tmp_lvl1;
257 if ( no_sub_div ) *no_sub_div = tmp_lvl2;
258 if ( no_transaction ) *no_transaction = tmp_lvl3;
259 if ( data ) *data = tmp_data;
260
261 return TRUE;
262 }
263
264
265
266 /**
267 * Determine row type, which can be division, sub division,
268 * transaction or invalid.
269 *
270 * \param tree_model GtkTreeModel containing the entry to test.
271 * \param path A GtkTreePath pointing to entry to test.
272 *
273 * \return Type of entry.
274 */
metatree_get_row_type(GtkTreeModel * tree_model,GtkTreePath * path)275 enum MetaTreeRowType metatree_get_row_type ( GtkTreeModel * tree_model,
276 GtkTreePath * path )
277 {
278 gint no_div, no_sub_div, no_transaction;
279
280 if ( metatree_get_row_properties ( tree_model, path, NULL, &no_div, &no_sub_div, &no_transaction, NULL ) )
281 {
282 if (no_div)
283 {
284 if (no_sub_div)
285 return META_TREE_SUB_DIV;
286 else
287 return META_TREE_DIV;
288 }
289 else
290 if (no_transaction)
291 return META_TREE_TRANSACTION;
292 }
293 return META_TREE_INVALID;
294 }
295
296
297
298 /**
299 * get the content of the column and path in param
300 * fill the data field with that content
301 *
302 * \param model
303 * \param path row we want the content
304 * \param column column we want the content
305 * \param data a pointer to a gint to be filled with the content
306 *
307 * \return TRUE ok, FALSE problem
308 */
metatree_get(GtkTreeModel * model,GtkTreePath * path,gint column,gint * data)309 gboolean metatree_get ( GtkTreeModel * model, GtkTreePath * path,
310 gint column, gint *data )
311 {
312 GtkTreeIter iter;
313
314 if ( gtk_tree_model_get_iter ( model, &iter, path ) && data )
315 {
316 gtk_tree_model_get ( model, &iter, column, data, -1 );
317 return TRUE;
318 }
319 return FALSE;
320 }
321
322
323
324 /**
325 * Fill a division row with textual representation of a division
326 * structure, in the form: "Name (num transactions) Balance".
327 *
328 * \param model The GtkTreeModel that contains iter.
329 * \param iface A pointer to the metatree interface to use
330 * \param iter Iter to fill with division data.
331 * \param division Division structure number. (category number, payee number or budget number)
332 */
fill_division_row(GtkTreeModel * model,MetatreeInterface * iface,GtkTreeIter * iter,gint division)333 void fill_division_row ( GtkTreeModel * model, MetatreeInterface * iface,
334 GtkTreeIter * iter, gint division )
335 {
336 gchar *balance = NULL;
337 gchar *string_tmp;
338 GtkTreeIter dumb_iter;
339 GtkTreePath * path;
340 enum MetaTreeRowType type;
341 gint number_transactions;
342
343 if ( ! metatree_model_is_displayed ( model ) )
344 return;
345
346 path = gtk_tree_model_get_path ( model, iter );
347 type = metatree_get_row_type ( model, path );
348
349 gtk_tree_path_free ( path );
350 if ( type != META_TREE_DIV && type != META_TREE_INVALID )
351 return;
352
353 string_tmp = iface -> div_name (division);
354 number_transactions = iface -> div_nb_transactions (division);
355
356 if (number_transactions)
357 {
358 gchar *label;
359
360 label = g_strdup_printf ( "%s (%d)", string_tmp, number_transactions);
361 g_free (string_tmp);
362 string_tmp = label;
363 balance = utils_real_get_string_with_currency ( iface -> div_balance ( division ),
364 iface -> tree_currency (), TRUE );
365
366 /* add a white child to show the arrow to open it */
367 if ( ! gtk_tree_model_iter_has_child ( model, iter )
368 &&
369 (iface -> depth == 1 || !division ))
370 gtk_tree_store_append (GTK_TREE_STORE (model), &dumb_iter, iter );
371 }
372
373 /* set 0 for the sub-div, so no categ/no budget have 0 for div and 0 for sub-div */
374 gtk_tree_store_set (GTK_TREE_STORE(model), iter,
375 META_TREE_TEXT_COLUMN, string_tmp,
376 META_TREE_POINTER_COLUMN, division,
377 META_TREE_BALANCE_COLUMN, balance,
378 META_TREE_XALIGN_COLUMN, 1.0,
379 META_TREE_NO_DIV_COLUMN, division,
380 META_TREE_NO_SUB_DIV_COLUMN, 0,
381 META_TREE_NO_TRANSACTION_COLUMN, 0,
382 META_TREE_FONT_COLUMN, 800,
383 META_TREE_DATE_COLUMN, NULL,
384 -1);
385 g_free (string_tmp);
386 if (balance)
387 g_free (balance);
388 }
389
390
391
392 /**
393 * Fill a sub-division row with textual representation of a
394 * sub-division structure, in the form: "Name (num transactions)
395 * Balance".
396 *
397 * \param model The GtkTreeModel that contains iter.
398 * \param iface A pointer to the metatree interface to use
399 * \param iter Iter to fill with sub-division data.
400 * \param division Division structure number (parent).
401 * \param sub_division Sub-division structure number.
402 */
fill_sub_division_row(GtkTreeModel * model,MetatreeInterface * iface,GtkTreeIter * iter,gint division,gint sub_division)403 void fill_sub_division_row ( GtkTreeModel *model,
404 MetatreeInterface *iface,
405 GtkTreeIter *iter,
406 gint division,
407 gint sub_division )
408 {
409 gchar *balance = NULL;
410 gchar *string_tmp;
411 GtkTreeIter dumb_iter;
412 GtkTreePath * path;
413 enum MetaTreeRowType type;
414 gint number_transactions = 0;
415
416 if ( ! metatree_model_is_displayed ( model ) )
417 return;
418
419 /* if no division, there is no sub division */
420 if (!division)
421 return;
422
423 path = gtk_tree_model_get_path ( model, iter );
424 type = metatree_get_row_type ( model, path );
425 gtk_tree_path_free ( path );
426
427 if ( type != META_TREE_SUB_DIV && type != META_TREE_INVALID )
428 return;
429
430 string_tmp = iface -> sub_div_name (division, sub_division);
431 number_transactions = iface -> sub_div_nb_transactions ( division, sub_division );
432
433 if ( number_transactions )
434 {
435 gchar *label;
436
437 label = g_strdup_printf ( "%s (%d)",
438 string_tmp,
439 number_transactions );
440 g_free (string_tmp);
441 string_tmp = label;
442
443 if ( ! gtk_tree_model_iter_has_child ( model, iter ) )
444 gtk_tree_store_append (GTK_TREE_STORE (model), &dumb_iter, iter );
445
446 balance = utils_real_get_string_with_currency ( iface -> sub_div_balance ( division, sub_division ),
447 iface -> tree_currency (), TRUE );
448 }
449
450 gtk_tree_store_set ( GTK_TREE_STORE (model), iter,
451 META_TREE_TEXT_COLUMN, string_tmp,
452 META_TREE_POINTER_COLUMN, sub_division,
453 META_TREE_BALANCE_COLUMN, balance,
454 META_TREE_XALIGN_COLUMN, 1.0,
455 META_TREE_NO_DIV_COLUMN, division,
456 META_TREE_NO_SUB_DIV_COLUMN, sub_division,
457 META_TREE_NO_TRANSACTION_COLUMN, 0,
458 META_TREE_FONT_COLUMN, 400,
459 META_TREE_DATE_COLUMN, NULL,
460 -1 );
461 g_free (string_tmp);
462 if (balance)
463 g_free (balance);
464 }
465
466
467
468 /**
469 * fill the line transaction for each category/sub-category
470 *
471 * \param model The GtkTreeModel that contains iter.
472 */
fill_transaction_row(GtkTreeModel * model,GtkTreeIter * iter,gint transaction_number)473 void fill_transaction_row ( GtkTreeModel *model,
474 GtkTreeIter *iter,
475 gint transaction_number )
476 {
477 gchar * account; /* no need to be freed */
478 gchar * amount = NULL;
479 gchar * label = NULL;
480 gchar * notes = NULL;
481 gchar *str_to_free;
482 const gchar *string;
483 GtkTreePath * path;
484 enum MetaTreeRowType type;
485
486 if ( ! metatree_model_is_displayed ( model ) )
487 return;
488
489 path = gtk_tree_model_get_path ( model, iter );
490 type = metatree_get_row_type ( model, path );
491 gtk_tree_path_free (path);
492 if ( type != META_TREE_TRANSACTION && type != META_TREE_INVALID)
493 return;
494
495 string = gsb_data_transaction_get_notes ( transaction_number);
496
497 if ( string && strlen ( string ) > 0 )
498 {
499 if ( strlen ( string ) > 30 )
500 {
501 const gchar *tmp;
502
503 tmp = string + 30;
504
505 tmp = strchr ( tmp, ' ' );
506 if ( !tmp )
507 {
508 /* We do not risk splitting the string
509 in the middle of a UTF-8 accent
510 ... the end is probably near btw. */
511 notes = my_strdup ( string );
512 }
513 else
514 {
515 gchar * trunc = g_strndup ( string, ( tmp - string ) );
516 notes = g_strconcat ( trunc, " ...", NULL );
517 g_free ( trunc );
518 }
519 }
520 else
521 {
522 notes = my_strdup ( string );
523 }
524 }
525 else
526 {
527 notes = my_strdup (gsb_data_payee_get_name (
528 gsb_data_transaction_get_party_number ( transaction_number),
529 TRUE));
530 }
531
532 label = gsb_format_gdate ( gsb_data_transaction_get_date (transaction_number));
533
534 if ( notes )
535 {
536 str_to_free = label;
537 label = g_strconcat ( label, " : ", notes, NULL );
538 g_free (notes);
539 g_free (str_to_free);
540 }
541
542 if ( gsb_data_transaction_get_mother_transaction_number ( transaction_number))
543 {
544 str_to_free = label;
545 label = g_strconcat ( label, " (", _("split"), ")", NULL );
546 g_free (str_to_free);
547 }
548
549 amount = utils_real_get_string_with_currency ( gsb_data_transaction_get_amount (transaction_number),
550 gsb_data_transaction_get_currency_number (transaction_number), TRUE );
551 account = gsb_data_account_get_name ( gsb_data_transaction_get_account_number (transaction_number));
552 gtk_tree_store_set ( GTK_TREE_STORE(model), iter,
553 META_TREE_POINTER_COLUMN, transaction_number,
554 META_TREE_TEXT_COLUMN, label,
555 META_TREE_ACCOUNT_COLUMN, account,
556 META_TREE_BALANCE_COLUMN, amount,
557 META_TREE_NO_DIV_COLUMN, 0,
558 META_TREE_NO_SUB_DIV_COLUMN, 0,
559 META_TREE_NO_TRANSACTION_COLUMN, transaction_number,
560 META_TREE_XALIGN_COLUMN, 1.0,
561 META_TREE_FONT_COLUMN, 400,
562 META_TREE_DATE_COLUMN, gsb_data_transaction_get_date ( transaction_number ),
563 -1);
564 g_free(amount);
565 g_free(label);
566 }
567
568
569
570 /**
571 * Handle request for a new division. Normally called when user
572 * clicked on the "New foo" button.
573 *
574 * \param model Model to create a new division for.
575 */
metatree_new_division(GtkTreeModel * model)576 void metatree_new_division ( GtkTreeModel *model )
577 {
578 MetatreeInterface * iface;
579 gint div_id;
580
581 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
582 g_return_if_fail ( iface );
583
584 div_id = iface -> add_div ();
585
586 metatree_fill_new_division ( iface, model, div_id );
587
588 gsb_file_set_modified ( TRUE );
589 }
590
591
592
593 /**
594 * \todo Document this
595 *
596 *
597 *
598 */
metatree_fill_new_division(MetatreeInterface * iface,GtkTreeModel * model,gint div_id)599 void metatree_fill_new_division ( MetatreeInterface * iface,
600 GtkTreeModel *model,
601 gint div_id )
602 {
603 GtkTreeIter iter, sub_iter;
604 GtkTreeView * tree_view;
605
606 gchar* strtmp = g_strdup_printf ("metatree_fill_new_division %d", div_id);
607 devel_debug ( strtmp );
608 g_free ( strtmp );
609
610 g_return_if_fail ( iface );
611 if ( ! metatree_model_is_displayed ( model ) )
612 return;
613
614 gtk_tree_store_append ( GTK_TREE_STORE(model), &iter, NULL );
615 fill_division_row ( model, iface, &iter, div_id );
616
617 if ( iface -> depth > 1 )
618 {
619 gtk_tree_store_append (GTK_TREE_STORE (model), &sub_iter, &iter);
620 fill_sub_division_row ( GTK_TREE_MODEL(model), iface, &sub_iter,
621 div_id, 0 );
622 }
623
624 tree_view = g_object_get_data ( G_OBJECT(model), "tree-view" );
625 g_return_if_fail ( tree_view );
626
627 gtk_tree_selection_select_iter ( gtk_tree_view_get_selection ( tree_view ), &iter );
628 gtk_tree_view_scroll_to_cell ( tree_view,
629 gtk_tree_model_get_path ( model, &iter ),
630 gtk_tree_view_get_column ( tree_view, 0 ),
631 TRUE, 0.5, 0.0 );
632 }
633
634
635
636
637
638
639 /**
640 * Handle request for a new division. Normally called when user
641 * clicked on the "New foo" button.
642 *
643 * \param model Model to create a new division for.
644 */
metatree_new_sub_division(GtkTreeModel * model,gint div_id)645 void metatree_new_sub_division ( GtkTreeModel *model, gint div_id )
646 {
647 MetatreeInterface * iface;
648 gint sub_div_id;
649
650 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
651 g_return_if_fail ( iface );
652
653 sub_div_id = iface -> add_sub_div ( div_id );
654 if ( !sub_div_id )
655 return;
656
657 metatree_fill_new_sub_division ( iface, model, div_id, sub_div_id );
658
659 gsb_file_set_modified ( TRUE );
660 }
661
662
663
664 /**
665 * \todo Document this
666 *
667 *
668 *
669 */
metatree_fill_new_sub_division(MetatreeInterface * iface,GtkTreeModel * model,gint div_id,gint sub_div_id)670 void metatree_fill_new_sub_division ( MetatreeInterface *iface,
671 GtkTreeModel *model,
672 gint div_id,
673 gint sub_div_id )
674 {
675 GtkTreeIter iter, * parent_iter;
676 GtkTreeView * tree_view;
677 gchar* strtmp;
678
679 g_return_if_fail ( iface );
680 if ( ! metatree_model_is_displayed ( model ) )
681 return;
682
683 strtmp = g_strdup_printf ("div : %d - sub-div : %d", div_id, sub_div_id);
684 devel_debug ( strtmp );
685 g_free ( strtmp );
686
687 parent_iter = get_iter_from_div ( model, div_id, 0 );
688
689 gtk_tree_store_append ( GTK_TREE_STORE(model), &iter, parent_iter );
690 fill_sub_division_row ( model, iface, &iter,
691 div_id,
692 sub_div_id );
693
694 tree_view = g_object_get_data ( G_OBJECT(model), "tree-view" );
695 g_return_if_fail ( tree_view );
696
697 gtk_tree_selection_select_iter ( gtk_tree_view_get_selection ( tree_view ), &iter );
698 gtk_tree_view_scroll_to_cell ( tree_view,
699 gtk_tree_model_get_path ( model, &iter ),
700 gtk_tree_view_get_column ( tree_view, 0 ),
701 TRUE, 0.5, 0.0 );
702 }
703
704
705
706
707 /**
708 * \todo Document this
709 *
710 *
711 */
appui_sur_ajout_sub_division(GtkTreeModel * model)712 void appui_sur_ajout_sub_division ( GtkTreeModel * model )
713 {
714 MetatreeInterface * iface;
715 GtkTreeIter parent_iter;
716 GtkTreeView * tree_view;
717 GtkTreeSelection * selection;
718
719 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
720 tree_view = g_object_get_data ( G_OBJECT(model), "tree-view" );
721 if ( !iface || !tree_view )
722 return;
723
724 selection = gtk_tree_view_get_selection ( tree_view );
725 if ( selection && gtk_tree_selection_get_selected ( selection, &model, &parent_iter ) )
726 {
727 GtkTreePath * path = gtk_tree_model_get_path ( model, &parent_iter );
728 gint div_id;
729
730 /* Get parent division id */
731 metatree_get_row_properties ( model, path, NULL, &div_id, NULL, NULL, NULL ) ;
732 if ( !div_id )
733 return;
734
735 metatree_new_sub_division ( model, div_id );
736
737 gsb_file_set_modified ( TRUE );
738
739 gtk_tree_path_free ( path );
740 }
741 }
742
743
744
745 /**
746 * remove a division or a sub-division from a metatree
747 *
748 * \param tree_view
749 *
750 * \return FALSE
751 */
supprimer_division(GtkTreeView * tree_view)752 gboolean supprimer_division ( GtkTreeView * tree_view )
753 {
754 GtkTreeSelection * selection;
755 GtkTreeModel * model = NULL;
756 GtkTreeIter iter;
757 GtkTreePath * path;
758 gint no_division = 0, no_sub_division = 0;
759 gint current_number = 0;
760 gint nbre_trans_s_s_div = 0; /* nbre de transactions sans sous-division */
761
762 MetatreeInterface * iface;
763
764 devel_debug (NULL);
765
766 selection = gtk_tree_view_get_selection ( tree_view );
767 if ( selection && gtk_tree_selection_get_selected(selection, &model, &iter))
768 {
769 gtk_tree_model_get ( model, &iter,
770 META_TREE_POINTER_COLUMN, ¤t_number,
771 META_TREE_NO_DIV_COLUMN, &no_division,
772 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_division,
773 -1 );
774 }
775
776 if (!current_number)
777 {
778 /* FIXME: tell the truth ;-) */
779 dialogue_warning_hint ( _("This should not theorically happen."),
780 _("Can't remove selected division."));
781 return FALSE;
782 }
783
784 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
785
786 /* get the type of the delete */
787 path = gtk_tree_model_get_path ( model, &iter );
788 switch ( metatree_get_row_type ( model, path ) )
789 {
790 case META_TREE_TRANSACTION:
791 metatree_remove_transaction ( tree_view, iface, current_number, TRUE );
792 return FALSE;
793 case META_TREE_DIV:
794 /* Nothing, do the grunt job after. */
795 break;
796 case META_TREE_SUB_DIV:
797 /* We asked to remove a sub-categ or sub-budget and have a
798 * function for that. */
799 supprimer_sub_division ( tree_view, model, iface, no_sub_division, no_division );
800 return FALSE;
801 case META_TREE_TRANS_S_S_DIV:
802 case META_TREE_INVALID:
803 default:
804 warning_debug ( "tried to remove an invalid entry" );
805 return FALSE;
806 }
807
808 /* ok, now we know that we really want to delete a division */
809 /* is the division contains some transactions ? */
810 if ( find_associated_transactions ( iface, no_division, 0 ) )
811 {
812 gint new_division, new_sub_division;
813
814 /* some transactions have that division, we ask to move them
815 * to another division or juste erase the division, and it
816 * will become blanck for the transactions */
817
818 /* fill new_division and new_sub_division (nota = 0)*/
819 if ( ! find_destination_blob ( iface, model, no_division, 0,
820 &new_division, &new_sub_division ) )
821 return FALSE;
822
823 /* now we have new_division filled, new_sub_division is always 0 because
824 * here we remove only a division
825 * so only division choice to move the transactions
826 * to remove a sub-division, go to see supprimer_sub_division */
827
828 /* two ways now :
829 * either we have no div, so we just remove the division and all the
830 * sub-divisions and set the transactions to no division
831 * either we have a new div, we have to move the sub-div of the
832 * last div to the new div, and move the transactions too */
833
834 if (new_division)
835 {
836 /* there is a new division, we have to move the sub-division to another division */
837 move_all_sub_divisions_to_division (model, no_division, new_division);
838
839 /* on regarde s'il y a des transactions sans sous-division */
840 nbre_trans_s_s_div = iface -> sub_div_nb_transactions ( no_division, 0 );
841 if ( nbre_trans_s_s_div > 0 )
842 metatree_move_transactions_to_sub_div ( iface, model,
843 no_division, no_sub_division, new_division, new_sub_division );
844 }
845 else
846 {
847 /* there is no new div so juste set the transactions to 0 */
848 metatree_reset_transactions_without_div_sub_div ( iface, model, no_division,
849 new_division, new_sub_division );
850 }
851
852 /* fait le tour des échéances pour mettre le nouveau numéro de division et sub_division */
853 metatree_move_scheduled_with_div_sub_div ( iface, model,
854 no_division, no_sub_division,
855 new_division, new_sub_division );
856
857 /* update value in the tree view */
858 metatree_update_tree_view ( iface );
859 }
860
861 /* supprime dans la liste des division */
862 iface -> remove_div ( no_division );
863 metatree_remove_iter_and_select_next ( tree_view, model, &iter );
864
865 gsb_file_set_modified ( TRUE );
866
867 return FALSE;
868 }
869
870
871
872 /**
873 * remove a sub-division from a metatree
874 *
875 * \param tree_view
876 * \param model
877 * \param iface the metatree interface
878 * \param sub_division the sub-division number we want to remove
879 * \param division the division number (parent)
880 *
881 * \return
882 */
supprimer_sub_division(GtkTreeView * tree_view,GtkTreeModel * model,MetatreeInterface * iface,gint sub_division,gint division)883 void supprimer_sub_division ( GtkTreeView * tree_view, GtkTreeModel * model,
884 MetatreeInterface * iface,
885 gint sub_division, gint division )
886 {
887 GtkTreeIter iter, *parent_iter, * it;
888 GtkTreePath *path;
889
890 devel_debug (NULL);
891
892 if ( find_associated_transactions ( iface, division,
893 sub_division ) )
894 {
895 gint nouveau_no_division, nouveau_no_sub_division;
896 GSList *list_tmp_transactions;
897 GSList *list_num = NULL; /* mémorise les transactions à transferer */
898
899 /* fill nouveau_no_division and nouveau_no_sub_division */
900 if ( ! find_destination_blob ( iface, model, division, sub_division,
901 &nouveau_no_division, &nouveau_no_sub_division ) )
902 return;
903
904 /* move the transactions to the new division numbers, need to do for
905 * archived transactions too */
906 list_tmp_transactions = gsb_data_transaction_get_complete_transactions_list ();
907 while ( list_tmp_transactions )
908 {
909 gint transaction_number_tmp;
910 transaction_number_tmp = gsb_data_transaction_get_transaction_number (
911 list_tmp_transactions -> data);
912
913 if ( ( iface -> transaction_div_id (transaction_number_tmp) == division)
914 &&
915 ( iface -> transaction_sub_div_id (transaction_number_tmp) == sub_division))
916 {
917 iface -> add_transaction_to_sub_div ( transaction_number_tmp,
918 nouveau_no_division,
919 nouveau_no_sub_division );
920 iface -> transaction_set_div_id (transaction_number_tmp, nouveau_no_division);
921 iface -> transaction_set_sub_div_id (transaction_number_tmp, nouveau_no_sub_division);
922 list_num = g_slist_append ( list_num, GINT_TO_POINTER (
923 transaction_number_tmp) );
924 }
925 list_tmp_transactions = list_tmp_transactions -> next;
926 }
927
928 /* fait le tour des échéances pour mettre le nouveau numéro de division et sub_division */
929 metatree_move_scheduled_with_div_sub_div ( iface, model,
930 division, sub_division,
931 nouveau_no_division, nouveau_no_sub_division );
932 /* Fill sub division */
933 if ( nouveau_no_division && nouveau_no_sub_division == 0 )
934 {
935 parent_iter = get_iter_from_div ( model, nouveau_no_division, 0 );
936 it = get_iter_from_sub_div_zero ( model, iface, parent_iter );
937 }
938 else
939 it = get_iter_from_div ( model, nouveau_no_division, nouveau_no_sub_division );
940
941 if ( it )
942 {
943 GtkTreeIter child_iter;
944 gint transaction_number;
945
946 if ( nouveau_no_division && nouveau_no_sub_division == 0 )
947 fill_sub_division_zero ( model, iface, it,nouveau_no_division );
948 else
949 fill_sub_division_row ( model, iface, it,
950 nouveau_no_division,
951 nouveau_no_sub_division );
952
953 path = gtk_tree_model_get_path ( model, it );
954 if ( gtk_tree_view_row_expanded ( tree_view, path ) )
955 {
956 while ( list_num )
957 {
958 transaction_number = GPOINTER_TO_INT ( list_num -> data );
959 gtk_tree_store_append ( GTK_TREE_STORE(model), &child_iter, it );
960 fill_transaction_row ( model, &child_iter, transaction_number);
961 list_num = list_num -> next;
962 }
963 g_slist_free ( list_num );
964 gtk_tree_path_free ( path );
965 }
966 }
967
968 /* Fill division as well */
969 it = get_iter_from_div ( model, nouveau_no_division, 0 );
970 if ( it )
971 fill_division_row ( model, iface, it, nouveau_no_division );
972
973 /* update value in the tree view */
974 metatree_update_tree_view ( iface );
975 }
976
977 /* supprime dans la liste des divisions */
978 iface -> remove_sub_div (division, sub_division);
979
980 metatree_remove_iter_and_select_next ( tree_view, model, &iter );
981
982 /* Fill old division */
983 it = get_iter_from_div ( model, division, 0 );
984 if ( it )
985 fill_division_row ( model, iface, it, division );
986
987 gsb_file_set_modified ( TRUE );
988 }
989
990
991
992 /**
993 * Remove a transaction from a metatree
994 * if delete_transaction is TRUE, will delete the transaction
995 * before removing it from the metatree
996 * for now, the transaction MUST NOT be deleted at this call
997 * (if we don't want that function deletes the transaction)
998 *
999 * \param tree_view
1000 * \param iface the metatree interface
1001 * \param transaction the transaction number we want to remove
1002 * \param sub_division the parent sub-division number
1003 * \param division the division number (parent)
1004 *
1005 * \return
1006 */
metatree_remove_transaction(GtkTreeView * tree_view,MetatreeInterface * iface,gint transaction,gboolean delete_transaction)1007 void metatree_remove_transaction ( GtkTreeView * tree_view,
1008 MetatreeInterface * iface,
1009 gint transaction,
1010 gboolean delete_transaction )
1011 {
1012 GtkTreeModel *model;
1013 gint division, sub_division;
1014 GtkTreeIter iter, *it;
1015
1016 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
1017
1018 division = iface -> transaction_div_id ( transaction );
1019 sub_division = iface -> transaction_sub_div_id ( transaction );
1020
1021 /* remove the transaction from memory and list, and show the warnings */
1022 if (delete_transaction)
1023 if (!gsb_transactions_list_delete_transaction (transaction, TRUE))
1024 return;
1025
1026 /* Fill parent sub division */
1027 it = get_iter_from_div ( model, division, sub_division );
1028 if ( it )
1029 fill_sub_division_row ( model, iface, it, division, sub_division );
1030
1031 /* Fill division as well */
1032 it = get_iter_from_div ( model, division, 0 );
1033 if ( it )
1034 fill_division_row ( model, iface, it, division );
1035
1036 metatree_remove_iter_and_select_next ( tree_view, model, &iter );
1037 gsb_file_set_modified ( TRUE );
1038 }
1039
1040
1041
1042 /**
1043 * callback when expand a row
1044 *
1045 * \param treeview
1046 * \param iter
1047 * \param tree_path
1048 * \param user_data not used
1049 *
1050 * \return FALSE
1051 *
1052 */
division_column_expanded(GtkTreeView * treeview,GtkTreeIter * iter,GtkTreePath * tree_path,gpointer user_data)1053 gboolean division_column_expanded ( GtkTreeView * treeview, GtkTreeIter * iter,
1054 GtkTreePath * tree_path, gpointer user_data )
1055 {
1056 GtkTreeModel * model;
1057 GtkTreeIter child_iter;
1058 gchar *name;
1059 gint no_division, no_sub_division;
1060 MetatreeInterface * iface;
1061
1062 /* Get model and metatree interface */
1063 model = gtk_tree_view_get_model(treeview);
1064
1065 if (! gtk_tree_model_iter_children( model, &child_iter, iter ))
1066 return FALSE;
1067 gtk_tree_model_get ( model, &child_iter, META_TREE_TEXT_COLUMN, &name, -1 );
1068
1069 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
1070
1071 /* If there is already an entry there, don't populate it. */
1072 if ( !name )
1073 {
1074 gboolean first = TRUE;
1075 GSList *list_tmp_transactions;
1076
1077 gtk_tree_model_get ( model, iter,
1078 META_TREE_NO_DIV_COLUMN, &no_division,
1079 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_division,
1080 -1 );
1081
1082 list_tmp_transactions = gsb_data_transaction_get_metatree_transactions_list ();
1083
1084 while ( list_tmp_transactions )
1085 {
1086 gint transaction_number_tmp;
1087 transaction_number_tmp = gsb_data_transaction_get_transaction_number (
1088 list_tmp_transactions -> data);
1089
1090 /* set the transaction if the same div/sub-div
1091 * or if no categ (must check if no transfer or split) */
1092 if ( transaction_number_tmp &&
1093 ( (iface -> transaction_div_id ( transaction_number_tmp) == no_division &&
1094 iface -> transaction_sub_div_id ( transaction_number_tmp) == no_sub_division )
1095 ||
1096 ( !no_division &&
1097 !iface -> transaction_div_id ( transaction_number_tmp) &&
1098 !gsb_data_transaction_get_split_of_transaction (transaction_number_tmp) &&
1099 gsb_data_transaction_get_contra_transaction_number (transaction_number_tmp) == 0)))
1100
1101 {
1102 if ( !first )
1103 {
1104 gtk_tree_store_append ( GTK_TREE_STORE(model), &child_iter, iter );
1105 }
1106 else
1107 {
1108 first = FALSE;
1109 }
1110
1111 fill_transaction_row ( model, &child_iter, transaction_number_tmp);
1112 }
1113 list_tmp_transactions = list_tmp_transactions -> next;
1114 }
1115 g_slist_free ( list_tmp_transactions );
1116 }
1117
1118 /* on colorise les lignes du tree_view */
1119 utils_set_tree_store_background_color ( GTK_WIDGET ( treeview ), META_TREE_BACKGROUND_COLOR );
1120
1121 return FALSE;
1122 }
1123
1124
1125 /**
1126 * callback when collapse a row
1127 *
1128 * \param treeview
1129 * \param iter
1130 * \param tree_path
1131 * \param user_data not used
1132 *
1133 * \return FALSE
1134 *
1135 */
division_column_collapsed(GtkTreeView * treeview,GtkTreeIter * iter,GtkTreePath * tree_path,gpointer user_data)1136 gboolean division_column_collapsed ( GtkTreeView *treeview,
1137 GtkTreeIter *iter,
1138 GtkTreePath *tree_path,
1139 gpointer user_data )
1140 {
1141 /* on colorise les lignes du tree_view */
1142 utils_set_tree_store_background_color ( GTK_WIDGET ( treeview ), META_TREE_BACKGROUND_COLOR );
1143
1144 return FALSE;
1145 }
1146
1147
1148 /**
1149 * \todo Document this
1150 *
1151 *
1152 */
division_activated(GtkTreeView * treeview,GtkTreePath * path,GtkTreeViewColumn * col,gpointer userdata)1153 gboolean division_activated ( GtkTreeView * treeview, GtkTreePath * path,
1154 GtkTreeViewColumn * col, gpointer userdata )
1155 {
1156 GtkTreeIter iter;
1157 GtkTreeModel *model;
1158 gint no_division, no_sub_division;
1159
1160 model = gtk_tree_view_get_model(treeview);
1161
1162 if ( gtk_tree_model_get_iter ( model, &iter, path ) )
1163 {
1164 gint transaction_number;
1165
1166 gtk_tree_model_get( model, &iter,
1167 META_TREE_NO_DIV_COLUMN, &no_division,
1168 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_division,
1169 META_TREE_POINTER_COLUMN, &transaction_number,
1170 -1);
1171
1172 /* We do not jump to a transaction if a division is specified */
1173 if ( transaction_number && !no_division && !no_sub_division )
1174 {
1175 GtkTreePath *tmp_path;
1176 gint account_number;
1177 gint archive_number;
1178
1179 account_number = gsb_data_transaction_get_account_number ( transaction_number );
1180 if ( gsb_data_account_exists ( account_number ) == FALSE )
1181 {
1182 gchar *tmp_str;
1183
1184 tmp_str = g_strdup_printf ( _("The selected operation belongs to the account N°%d\n"
1185 "that no longer exists.\n"
1186 "Please contact the Grisbi's team on devel@listes.grisbi.org to find what "
1187 "happened to your current file."),
1188 account_number );
1189 dialogue_error_hint ( tmp_str, _("The account no longer exists") );
1190 g_free ( tmp_str );
1191
1192 return FALSE;
1193 }
1194
1195 archive_number = gsb_data_transaction_get_archive_number ( transaction_number );
1196
1197 /* If transaction is an archive return */
1198 if ( archive_number )
1199 {
1200 gsb_transactions_list_add_transactions_from_archive (archive_number, account_number, FALSE );
1201 }
1202 /* If transaction is reconciled, show reconciled transactions. */
1203 if ( gsb_data_transaction_get_marked_transaction ( transaction_number ) == OPERATION_RAPPROCHEE
1204 &&
1205 gsb_data_account_get_r ( account_number ) == FALSE )
1206 {
1207 gsb_transactions_list_mise_a_jour_affichage_r ( TRUE );
1208 }
1209
1210 gsb_gui_navigation_change_account ( account_number );
1211 gsb_account_property_fill_page ();
1212 grisbi_win_general_notebook_set_page ( GSB_ACCOUNT_PAGE );
1213 gsb_gui_navigation_set_selection ( GSB_ACCOUNT_PAGE,
1214 gsb_data_transaction_get_account_number (transaction_number),
1215 0);
1216
1217 /* move selected iter */
1218 tmp_path = gtk_tree_model_get_path ( model, &iter );
1219 gtk_tree_view_scroll_to_cell ( treeview, tmp_path, NULL, FALSE, 0.0, 0.0 );
1220 gtk_tree_path_free (tmp_path);
1221
1222 transaction_list_select ( transaction_number );
1223 }
1224 }
1225
1226 return FALSE;
1227 }
1228
1229
1230
1231 /**
1232 * \todo Document this
1233 *
1234 *
1235 */
division_row_drop_possible(GtkTreeDragDest * drag_dest,GtkTreePath * dest_path,GtkSelectionData * selection_data)1236 gboolean division_row_drop_possible ( GtkTreeDragDest *drag_dest,
1237 GtkTreePath *dest_path,
1238 GtkSelectionData *selection_data )
1239 {
1240 if ( dest_path && selection_data )
1241 {
1242 enum MetaTreeRowType orig_type, dest_type;
1243 GtkTreePath * orig_path;
1244 GtkTreeModel * model;
1245 gint orig_no_div, no_div;
1246 gint current_number;
1247
1248 gtk_tree_get_row_drag_data (selection_data, &model, &orig_path);
1249
1250 if ( model == GTK_TREE_MODEL( gsb_gui_navigation_get_model ( ) ) )
1251 {
1252 return gsb_gui_navigation_row_drop_possible ( drag_dest, dest_path, selection_data );
1253 }
1254
1255 orig_type = metatree_get_row_type ( model, orig_path );
1256 dest_type = metatree_get_row_type ( model, dest_path );
1257
1258 if ( ! metatree_get ( model, dest_path, META_TREE_NO_DIV_COLUMN,
1259 &no_div ) ||
1260 ! metatree_get ( model, orig_path, META_TREE_NO_DIV_COLUMN,
1261 &orig_no_div ) ||
1262 ! metatree_get ( model, dest_path, META_TREE_POINTER_COLUMN,
1263 ¤t_number ) )
1264 {
1265 return FALSE;
1266 }
1267
1268 switch ( orig_type )
1269 {
1270 case META_TREE_SUB_DIV:
1271 if ( dest_type == META_TREE_DIV &&
1272 ! gtk_tree_path_is_ancestor ( dest_path, orig_path ) &&
1273 current_number &&
1274 orig_no_div != 0 &&
1275 no_div != 0 ) /* i.e. ancestor is no "No division" */
1276 return TRUE;
1277 break;
1278
1279 case META_TREE_TRANSACTION:
1280 if ( dest_type == META_TREE_DIV ||
1281 dest_type == META_TREE_SUB_DIV )
1282 return TRUE;
1283 break;
1284
1285 case META_TREE_TRANS_S_S_DIV:
1286 case META_TREE_INVALID:
1287 case META_TREE_DIV:
1288 default:
1289 break;
1290 }
1291 }
1292
1293 return FALSE;
1294 }
1295
1296
1297
1298 /**
1299 * callback when a metatree receive a drag and drop signal
1300 *
1301 * \param drag_dest
1302 * \param dest_path
1303 * \param selection_data
1304 *
1305 * \return FALSE
1306 */
division_drag_data_received(GtkTreeDragDest * drag_dest,GtkTreePath * dest_path,GtkSelectionData * selection_data)1307 gboolean division_drag_data_received ( GtkTreeDragDest *drag_dest,
1308 GtkTreePath *dest_path,
1309 GtkSelectionData *selection_data )
1310 {
1311 gchar *tmpstr = gtk_tree_path_to_string (dest_path);
1312 gchar *tmpstr2 = g_strdup_printf ( "Dest path : %s", tmpstr);
1313 devel_debug (tmpstr2);
1314 g_free (tmpstr);
1315 g_free (tmpstr2);
1316
1317 if ( dest_path && selection_data )
1318 {
1319 GtkWidget *tree_view = NULL;
1320 GtkTreeModel *model;
1321 GtkTreePath *orig_path;
1322 gchar *name;
1323 gint no_dest_division, no_dest_sub_division, no_orig_division, no_orig_sub_division;
1324 enum MetaTreeRowType orig_type;
1325 MetatreeInterface * iface;
1326 gint transaction_number;
1327
1328 /* get the orig_path */
1329 gtk_tree_get_row_drag_data (selection_data, &model, &orig_path);
1330
1331 /* if we are on the navigation list, work with it */
1332 if ( model == GTK_TREE_MODEL( gsb_gui_navigation_get_model ( ) ) )
1333 {
1334 return gsb_gui_navigation_drag_data_received ( drag_dest, dest_path, selection_data );
1335 }
1336
1337 /* get metatree interface */
1338 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
1339 if ( ! iface )
1340 return FALSE;
1341
1342 metatree_get_row_properties ( model, orig_path,
1343 NULL, &no_orig_division, &no_orig_sub_division,
1344 &transaction_number, NULL );
1345
1346 /* get the type of row (div, sub-div, transaction) */
1347 orig_type = metatree_get_row_type ( model, orig_path );
1348
1349 /* get the destination param */
1350 metatree_get_row_properties ( model, dest_path,
1351 &name, &no_dest_division, &no_dest_sub_division,
1352 NULL, NULL );
1353 if ( ! name )
1354 {
1355 gtk_tree_path_up ( dest_path );
1356 metatree_get_row_properties ( model, dest_path,
1357 &name, &no_dest_division, &no_dest_sub_division,
1358 NULL, NULL );
1359 }
1360
1361 switch ( orig_type )
1362 {
1363 /* move a transaction */
1364 case META_TREE_TRANSACTION:
1365 if (transaction_number)
1366 move_transaction_to_sub_division ( transaction_number, model,
1367 orig_path, dest_path,
1368 no_dest_division, no_dest_sub_division );
1369 break;
1370
1371 /* move a sub-division */
1372 case META_TREE_SUB_DIV:
1373 move_sub_division_to_division (model,
1374 no_dest_division,
1375 no_orig_division, no_orig_sub_division );
1376 break;
1377
1378 case META_TREE_DIV:
1379 case META_TREE_TRANS_S_S_DIV:
1380 case META_TREE_INVALID:
1381 default:
1382 break;
1383 }
1384 /* on colorise les lignes du tree_view */
1385 switch ( iface -> content )
1386 {
1387 case 0:
1388 tree_view = payees_get_tree_view ( );
1389 break;
1390 case 1:
1391 tree_view = categories_get_tree_view ( );
1392 break;
1393 case 2:
1394 tree_view = budgetary_lines_get_tree_view ( );
1395 break;
1396 }
1397 utils_set_tree_store_background_color ( tree_view, META_TREE_BACKGROUND_COLOR );
1398
1399 }
1400
1401 return FALSE;
1402 }
1403
1404
1405
1406 /**
1407 * move a transaction to another sub-division
1408 *
1409 * \param transaction_number
1410 * \param model
1411 * \param orig_path
1412 * \param dest_path
1413 * \param no_division new division to the transaction
1414 * \param no_sub_division new sub-division to the transaction or 0 for no sub-division
1415 *
1416 * \return
1417 */
move_transaction_to_sub_division(gint transaction_number,GtkTreeModel * model,GtkTreePath * orig_path,GtkTreePath * dest_path,gint no_division,gint no_sub_division)1418 void move_transaction_to_sub_division ( gint transaction_number,
1419 GtkTreeModel *model,
1420 GtkTreePath *orig_path,
1421 GtkTreePath *dest_path,
1422 gint no_division,
1423 gint no_sub_division )
1424 {
1425 GtkTreeIter orig_iter, child_iter, dest_iter, parent_iter, gd_parent_iter;
1426 MetatreeInterface * iface;
1427 gint old_div, old_sub_div;
1428
1429 if ( !model )
1430 return;
1431
1432 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
1433
1434 /* Insert new row */
1435 if ( dest_path )
1436 gtk_tree_model_get_iter ( model, &dest_iter, dest_path );
1437 else
1438 {
1439 GtkTreeIter * p_iter = get_iter_from_div ( model,
1440 no_division, no_sub_division );
1441 if ( p_iter )
1442 dest_iter = *p_iter;
1443 }
1444
1445 /* Avoid filling "empty" not yet selected subdivisions */
1446 if ( gtk_tree_model_iter_children ( model, &child_iter, &dest_iter ) )
1447 {
1448 gchar * name;
1449
1450 gtk_tree_model_get ( model, &child_iter,
1451 META_TREE_TEXT_COLUMN, &name, -1 );
1452 if ( name )
1453 gtk_tree_store_insert ( GTK_TREE_STORE (model),
1454 &child_iter, &dest_iter, 0 );
1455 }
1456 else
1457 gtk_tree_store_append ( GTK_TREE_STORE (model),
1458 &child_iter, &dest_iter );
1459
1460 /* get the old div */
1461 old_div = iface -> transaction_div_id (transaction_number);
1462 old_sub_div = iface -> transaction_sub_div_id (transaction_number);
1463
1464 /* Update old parents */
1465 iface -> remove_transaction_from_sub_div ( transaction_number );
1466
1467 /* Change parameters of the transaction */
1468 iface -> transaction_set_div_id ( transaction_number, no_division );
1469 iface -> transaction_set_sub_div_id ( transaction_number, no_sub_division );
1470 gsb_transactions_list_update_transaction (transaction_number);
1471
1472 /* met à jour la transaction dans la liste corrige bug d'affichage */
1473 fill_transaction_row ( model, &child_iter, transaction_number);
1474
1475 /* Update new parents */
1476 if ( iface -> depth > 1 )
1477 {
1478 iface -> add_transaction_to_sub_div ( transaction_number,
1479 no_division, no_sub_division );
1480 if ( no_sub_division == 0 )
1481 fill_sub_division_zero ( model, iface, &dest_iter,
1482 no_division );
1483 else
1484 fill_sub_division_row ( model, iface, &dest_iter,
1485 no_division, no_sub_division );
1486 if ( gtk_tree_model_iter_parent ( model, &parent_iter, &dest_iter ) )
1487 fill_division_row ( model, iface, &parent_iter, no_division );
1488 }
1489 else
1490 {
1491 iface -> add_transaction_to_div ( transaction_number, no_division );
1492 fill_division_row ( model, iface, &dest_iter, no_division );
1493 }
1494
1495 /* update the old parent division and sub-division */
1496 if ( orig_path
1497 &&
1498 gtk_tree_model_get_iter ( model, &orig_iter, orig_path ) )
1499 {
1500 if ( gtk_tree_model_iter_parent ( model, &parent_iter, &orig_iter ) )
1501 {
1502 if ( iface -> depth > 1 )
1503 {
1504 if ( old_div == 0 )
1505 fill_division_zero ( model, iface, &parent_iter );
1506 else if ( old_sub_div == 0 )
1507 fill_sub_division_zero ( model, iface, &parent_iter,
1508 old_div );
1509 else
1510 fill_sub_division_row ( model, iface, &parent_iter,
1511 old_div, old_sub_div );
1512 if ( gtk_tree_model_iter_parent ( model, &gd_parent_iter,
1513 &parent_iter ) )
1514 fill_division_row ( model, iface, &gd_parent_iter,
1515 old_div );
1516 }
1517 else
1518 fill_division_row ( model, iface, &parent_iter, old_div );
1519 }
1520 /* Remove old row */
1521 gtk_tree_store_remove ( GTK_TREE_STORE (model), &orig_iter );
1522 }
1523
1524 /* We did some modifications */
1525 gsb_file_set_modified ( TRUE );
1526 }
1527
1528 /**
1529 * move a sub-division to a new division
1530 *
1531 * \param model
1532 * \param no_dest_division number of the division where we want to move the sub-division
1533 * \param no_orig_division number of the initial division containing the sub-division we want to move
1534 * \param no_orig_sub_division number of the initial sub-division we want to move to another division or 0 if no sub-division
1535 *
1536 * \return
1537 */
move_sub_division_to_division(GtkTreeModel * model,gint no_dest_division,gint no_orig_division,gint no_orig_sub_division)1538 void move_sub_division_to_division ( GtkTreeModel *model,
1539 gint no_dest_division,
1540 gint no_orig_division,
1541 gint no_orig_sub_division )
1542 {
1543 GtkTreeIter iter, orig_parent_iter;
1544 GtkTreeIter *orig_iter, *iter_parent;
1545 MetatreeInterface * iface;
1546 gint no_dest_sub_division = 0;
1547 GSList *list_tmp_transactions;
1548
1549 if ( !model )
1550 return;
1551
1552 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
1553
1554 /* create the new sub-division in memory with the same name of the origin sub-division */
1555 if (no_orig_sub_division)
1556 no_dest_sub_division = iface -> get_sub_div_pointer_from_name ( no_dest_division,
1557 iface -> sub_div_name (no_orig_division, no_orig_sub_division),
1558 1 );
1559
1560 /* if no_orig_sub_division is 0, we are on payee tree, so the transactions are
1561 * directly added to the division */
1562 iter_parent = get_iter_from_div (model, no_dest_division, 0);
1563
1564 if (no_orig_sub_division)
1565 {
1566 /* there is a sub-division, append a new one to the new division
1567 * to add the transactions */
1568 gtk_tree_store_append ( GTK_TREE_STORE(model), &iter, iter_parent);
1569 }
1570 else
1571 {
1572 /* we are on payee tree, just set the iter on the new division to add the transactions */
1573 iter = *iter_parent;
1574 }
1575
1576 /* fill the new sub-division (or dest division for payee) with the transactions */
1577 list_tmp_transactions = gsb_data_transaction_get_complete_transactions_list ();
1578
1579 while ( list_tmp_transactions )
1580 {
1581 gint transaction_number_tmp;
1582 transaction_number_tmp = gsb_data_transaction_get_transaction_number (list_tmp_transactions -> data);
1583
1584 if ( transaction_number_tmp &&
1585 iface -> transaction_div_id (transaction_number_tmp) == no_orig_division &&
1586 iface -> transaction_sub_div_id (transaction_number_tmp) == no_orig_sub_division )
1587 {
1588 GtkTreePath * path;
1589
1590 path = gtk_tree_model_get_path ( model, &iter );
1591 move_transaction_to_sub_division ( transaction_number_tmp, model,
1592 NULL, path,
1593 no_dest_division,
1594 no_dest_sub_division );
1595 }
1596 list_tmp_transactions = list_tmp_transactions -> next;
1597 }
1598
1599 /* set orig_iter to the initial sub-division */
1600 orig_iter = get_iter_from_div ( model, no_orig_division, no_orig_sub_division );
1601
1602 /* Update original parent. */
1603 if ( gtk_tree_model_iter_parent ( model, &orig_parent_iter, orig_iter ) )
1604 {
1605 fill_division_row ( model, iface, &orig_parent_iter, no_orig_division );
1606 }
1607
1608 /* Remove original division. */
1609 iface -> remove_sub_div ( no_orig_division, no_orig_sub_division );
1610 gtk_tree_store_remove ( GTK_TREE_STORE(model), orig_iter );
1611 gtk_tree_iter_free (orig_iter);
1612
1613 /* If it was no sub-division, recreate it. */
1614 if ( !no_orig_sub_division )
1615 {
1616 metatree_fill_new_sub_division ( iface, model,
1617 no_orig_division, no_orig_sub_division );
1618 }
1619
1620 /* Update dest at last. */
1621 fill_sub_division_row ( model, iface, &iter,
1622 no_dest_division, no_dest_sub_division );
1623 gtk_tree_iter_free (iter_parent);
1624 gsb_file_set_modified ( TRUE );
1625 }
1626
1627 /**
1628 * get all the sub-divisions of the orig_division and move them to the dest_division
1629 * move only the sub-divisions with some transactions
1630 *
1631 * \param model
1632 * \param orig_division
1633 * \param dest_division
1634 *
1635 * \return
1636 * */
move_all_sub_divisions_to_division(GtkTreeModel * model,gint orig_division,gint dest_division)1637 void move_all_sub_divisions_to_division ( GtkTreeModel *model,
1638 gint orig_division,
1639 gint dest_division )
1640 {
1641 MetatreeInterface *iface;
1642 GSList *sub_div_list;
1643 GSList *tmp_list;
1644
1645 if (!model)
1646 return;
1647
1648 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
1649
1650 /* the easyest way first, if we have no sub-division (ie we are on payee),
1651 * directly move the sub-division (transactions) the the new division */
1652 if (!iface -> content)
1653 {
1654 move_transactions_to_division_payee (model, iface,
1655 orig_division, dest_division );
1656 return;
1657 }
1658
1659 /* if we come here, we are on metatree with sub-division */
1660 sub_div_list = iface -> div_sub_div_list (orig_division);
1661 tmp_list = sub_div_list;
1662 while (tmp_list)
1663 {
1664 gint orig_sub_division;
1665 GtkTreeIter *iter;
1666
1667 orig_sub_division = iface -> sub_div_id (tmp_list -> data);
1668
1669 /* check if transactions in the sub-division, move only when there
1670 * is some transactions */
1671 iter = get_iter_from_div (model, orig_division, orig_sub_division);
1672
1673 /* go to the next before erase it */
1674 tmp_list = tmp_list -> next;
1675
1676 if (gtk_tree_model_iter_has_child (model, iter))
1677 move_sub_division_to_division (model, dest_division,
1678 orig_division, orig_sub_division );
1679 gtk_tree_iter_free (iter);
1680 }
1681 }
1682
1683
1684 /**
1685 * \todo Document this
1686 *
1687 *
1688 */
division_node_maybe_expand(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)1689 gboolean division_node_maybe_expand ( GtkTreeModel *model,
1690 GtkTreePath *path,
1691 GtkTreeIter *iter,
1692 gpointer data )
1693 {
1694 GtkTreeView * tree_view = g_object_get_data ( G_OBJECT(model), "tree-view" );
1695
1696 if ( tree_view )
1697 {
1698 if ( GPOINTER_TO_INT( data ) == gtk_tree_path_get_depth ( path ) )
1699 gtk_tree_view_expand_to_path ( tree_view, path );
1700 }
1701
1702 return FALSE;
1703 }
1704
1705
1706
1707 /**
1708 * Iterates over all divisions tree nodes and expand nodes that are
1709 * not deeper than specified depth.
1710 *
1711 * \param bouton Widget that triggered this callback. Not used.
1712 * \param depth Maximum depth for nodes to expand.
1713 */
expand_arbre_division(GtkWidget * bouton,gint depth)1714 void expand_arbre_division ( GtkWidget *bouton, gint depth )
1715 {
1716 GtkTreeView *tree_view = g_object_get_data ( G_OBJECT(bouton), "tree-view" );
1717 GtkTreeModel *model;
1718
1719 if ( tree_view )
1720 {
1721 gtk_tree_view_collapse_all ( tree_view );
1722 model = gtk_tree_view_get_model ( tree_view );
1723 gtk_tree_model_foreach ( model, division_node_maybe_expand, GINT_TO_POINTER ( depth ) );
1724
1725 /* on colorise les lignes du tree_view */
1726 utils_set_tree_store_background_color ( GTK_WIDGET ( tree_view ), META_TREE_BACKGROUND_COLOR );
1727 }
1728 }
1729
1730
1731
1732 /**
1733 * called when there is some transactions associated to the category, budget or payee
1734 * show a dialog and ask another categ/budget/payee to move the concerned transactions
1735 * and fill no_div and no_sub_div with the user choice
1736 *
1737 * \param iface
1738 * \param model
1739 * \param division the current (old) division number
1740 * \param sub_division the current (old) sub-division number
1741 * \param no_div a pointer to gint for the choice of division chosen by user
1742 * \param no_sub_div a pointer to gint for the choice of sub-division chosen by user
1743 *
1744 * \return FALSE to stop the process, TRUE to continue
1745 * no_div will contain the new division, no_sub_div the new sub-division
1746 * if no move of transactions, no_div and no_sub_div are set to 0
1747 * if move to another division but no sub-division, no_sub_div is set to 0
1748 * */
find_destination_blob(MetatreeInterface * iface,GtkTreeModel * model,gint division,gint sub_division,gint * no_div,gint * no_sub_div)1749 gboolean find_destination_blob ( MetatreeInterface * iface,
1750 GtkTreeModel * model,
1751 gint division,
1752 gint sub_division,
1753 gint *no_div,
1754 gint *no_sub_div )
1755 {
1756 GtkWidget *dialog, *hbox, *button_delete, *combofix, *button_move;
1757 GSList *liste_combofix, *division_list, *liste_division_credit, *liste_division_debit;
1758 gint resultat, nouveau_no_division, nouveau_no_sub_division;
1759 gchar* hint;
1760 gchar **split_division;
1761 gchar* text;
1762 gchar *tmpstr;
1763
1764 /* create the box to move change the division and sub-div of the transactions */
1765 if (sub_division)
1766 hint = g_strdup_printf (_("'%s : %s' still contains transactions or archived transactions."),
1767 iface -> div_name (division),
1768 iface -> sub_div_name (division, sub_division));
1769 else
1770 hint = g_strdup_printf (_("'%s' still contains transactions or archived transactions."),
1771 iface -> div_name ( division ));
1772
1773 if (iface -> content == METATREE_PAYEE)
1774 text = g_strdup_printf (_("If you want to remove it but want to keep transactions, "
1775 "you can transfer them to another %s. Otherwise, "
1776 "transactions can be simply deleted along with their division."),
1777 _( iface -> meta_name ) );
1778 else
1779 text = g_strdup_printf (_("If you want to remove it but want to keep transactions, "
1780 "you can transfer them to another (sub-)%s. Otherwise, "
1781 "transactions can be simply deleted along with their division."),
1782 _( iface -> meta_name ) );
1783
1784 dialog = dialogue_special_no_run ( GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, text , hint );
1785
1786 g_free ( hint );
1787 g_free ( text );
1788
1789 hbox = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, MARGIN_BOX );
1790 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), hbox,
1791 FALSE, FALSE, 0 );
1792
1793 if ( iface -> content == METATREE_PAYEE)
1794 tmpstr = g_strdup_printf ( _("Transfer transactions to payee") );
1795 else
1796 tmpstr = g_strdup_printf (_("Transfer transactions to %s"), _(iface -> meta_name));
1797
1798 button_move = gtk_radio_button_new_with_label ( NULL, tmpstr );
1799 g_free ( tmpstr );
1800 gtk_box_pack_start ( GTK_BOX ( hbox ), button_move,
1801 FALSE, FALSE, 0 );
1802
1803 /* create the list containing division and sub-division
1804 * without the current division to delete */
1805 division_list = iface -> div_list ( );
1806 liste_combofix = NULL;
1807 liste_division_credit = NULL;
1808 liste_division_debit = NULL;
1809
1810 while ( division_list )
1811 {
1812 gint tmp_division;
1813 GSList *sub_division_list;
1814
1815 tmp_division = iface -> div_id (division_list -> data);
1816 /* if we are on the current division and no sub-division, go to the next */
1817 if ( division && !sub_division && division == tmp_division )
1818 {
1819 division_list = division_list -> next;
1820 continue;
1821 }
1822
1823 /* get the division */
1824 switch ( iface -> div_type (tmp_division))
1825 {
1826 case 1:
1827 liste_division_debit = g_slist_append ( liste_division_debit,
1828 my_strdup (iface -> div_name (tmp_division)));
1829 break;
1830 default:
1831 liste_division_credit = g_slist_append ( liste_division_credit,
1832 my_strdup (iface -> div_name (tmp_division)));
1833 break;
1834 }
1835
1836 /* we add the sub-divisions only if we remove the sub-divisions,
1837 * else we let only the division */
1838 if (!sub_division)
1839 {
1840 division_list = division_list -> next;
1841 continue;
1842 }
1843
1844 /* get the sub-divisions */
1845 sub_division_list = iface -> div_sub_div_list (tmp_division);
1846
1847 while ( sub_division_list )
1848 {
1849 gint tmp_sub_division;
1850
1851 tmp_sub_division = iface -> sub_div_id (sub_division_list -> data);
1852 if (division == tmp_division && tmp_sub_division == sub_division)
1853 {
1854 sub_division_list = sub_division_list -> next;
1855 continue;
1856 }
1857
1858 switch ( iface -> div_type (tmp_division))
1859 {
1860 case 1:
1861 liste_division_debit = g_slist_append ( liste_division_debit,
1862 g_strconcat ( "\t",
1863 iface -> sub_div_name (tmp_division, tmp_sub_division),
1864 NULL ) );
1865 break;
1866 case 0:
1867 liste_division_credit = g_slist_append ( liste_division_credit,
1868 g_strconcat ( "\t",
1869 iface -> sub_div_name (tmp_division, tmp_sub_division),
1870 NULL ) );
1871 break;
1872 default:
1873 break;
1874 }
1875 sub_division_list = sub_division_list -> next;
1876 }
1877 division_list = division_list -> next;
1878 }
1879
1880 /* create the combofix complex with the divisions and sub-divisions */
1881 liste_combofix = g_slist_append ( liste_combofix, liste_division_debit );
1882 liste_combofix = g_slist_append ( liste_combofix, liste_division_credit );
1883
1884 combofix = gtk_combofix_new ( liste_combofix, iface->content);
1885 gtk_combofix_set_force_text ( GTK_COMBOFIX (combofix), TRUE );
1886 gtk_box_pack_start ( GTK_BOX ( hbox ), combofix, TRUE, TRUE, 0 );
1887
1888 /* other choice, just remove the division */
1889 hbox = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, MARGIN_BOX );
1890 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), hbox,
1891 FALSE, FALSE, 0 );
1892
1893 if ( iface -> content == METATREE_PAYEE)
1894 tmpstr = g_strdup_printf( _("Just remove this payee.") );
1895 else if ( !sub_division )
1896 tmpstr = g_strdup_printf(_("Just remove this %s."), _(iface -> meta_name) );
1897 else
1898 tmpstr = g_strdup_printf(_("Just remove this sub-%s."), _(iface -> meta_name) );
1899
1900 button_delete = gtk_radio_button_new_with_label (
1901 gtk_radio_button_get_group ( GTK_RADIO_BUTTON ( button_move ) ),
1902 tmpstr );
1903 g_free ( tmpstr );
1904 gtk_box_pack_start ( GTK_BOX ( hbox ), button_delete, FALSE, FALSE, 0 );
1905
1906 if ( button_move_selected == 1 )
1907 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( button_delete ), TRUE );
1908
1909 /* set the signals */
1910 g_signal_connect ( G_OBJECT ( button_move ),
1911 "toggled",
1912 G_CALLBACK ( button_delete_div_sub_div_clicked ),
1913 GINT_TO_POINTER (0));
1914
1915 g_signal_connect ( G_OBJECT ( button_delete ),
1916 "toggled",
1917 G_CALLBACK ( button_delete_div_sub_div_clicked ),
1918 GINT_TO_POINTER (1));
1919
1920 gtk_widget_show_all ( dialog );
1921
1922 resultat = gtk_dialog_run ( GTK_DIALOG ( dialog ) );
1923
1924 if ( resultat != GTK_RESPONSE_OK )
1925 {
1926 gtk_widget_destroy ( GTK_WIDGET ( dialog ) );
1927 return FALSE;
1928 }
1929
1930 nouveau_no_division = 0;
1931 nouveau_no_sub_division = 0;
1932
1933 if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( button_move )) )
1934 {
1935 /* we want to move the transactions */
1936 if ( !strlen (gtk_combofix_get_text ( GTK_COMBOFIX ( combofix ))))
1937 {
1938 text = g_strdup_printf (
1939 _("It is compulsory to specify a destination %s "
1940 "to move transactions but no %s was entered."),
1941 _(iface -> meta_name), _(iface -> meta_name) );
1942 hint = g_strdup_printf ( _("Please enter a %s!"),
1943 _(iface -> meta_name) );
1944 dialogue_warning_hint ( text , hint );
1945 g_free ( text );
1946 g_free ( hint );
1947
1948 gtk_widget_destroy (dialog);
1949 return (find_destination_blob ( iface, model,
1950 division, sub_division,
1951 no_div, no_sub_div ));
1952 }
1953
1954 /* get the new (sub-)divisions */
1955 split_division = g_strsplit ( gtk_combofix_get_text ( GTK_COMBOFIX ( combofix )),
1956 " : ", 2 );
1957
1958 nouveau_no_division = iface -> get_div_pointer_from_name ( split_division[0], 0 );
1959
1960 if (nouveau_no_division)
1961 nouveau_no_sub_division = iface -> get_sub_div_pointer_from_name (
1962 nouveau_no_division, split_division[1], 0 );
1963
1964 g_strfreev ( split_division );
1965 }
1966
1967 gtk_widget_destroy ( GTK_WIDGET ( dialog ) );
1968
1969 /* return the new number of division and sub-division
1970 * if don't want to move the transactions, 0 and 0 will be returned */
1971 if ( no_div)
1972 *no_div = nouveau_no_division;
1973 if ( no_sub_div )
1974 *no_sub_div = nouveau_no_sub_division;
1975 return TRUE;
1976 }
1977
1978
1979 /**
1980 * Find transactions that are associated with a div or subdiv.
1981 *
1982 * \param iface A MetatreeInterface to use.
1983 * \param no_division Division id to search for.
1984 * \param no_sub_division Subdivision id to search for, or 0 to search
1985 * only on division.
1986 *
1987 * \return TRUE if transactions are associated.
1988 *
1989 * \todo Return number of transactions instead, to produce nicer
1990 * dialogs.
1991 */
find_associated_transactions(MetatreeInterface * iface,gint no_division,gint no_sub_division)1992 gboolean find_associated_transactions ( MetatreeInterface * iface,
1993 gint no_division,
1994 gint no_sub_division )
1995 {
1996 GSList *tmp_list;
1997
1998 /* we need to check all the transactions, even in archives */
1999 tmp_list = gsb_data_transaction_get_complete_transactions_list ();
2000
2001 while ( tmp_list )
2002 {
2003 gint transaction_number_tmp;
2004 transaction_number_tmp = gsb_data_transaction_get_transaction_number (tmp_list -> data);
2005
2006 if ( iface -> transaction_div_id (transaction_number_tmp) == no_division &&
2007 ( !no_sub_division ||
2008 iface -> transaction_sub_div_id (transaction_number_tmp) == no_sub_division ) )
2009 {
2010 return TRUE;
2011 }
2012 else
2013 tmp_list = tmp_list -> next;
2014 }
2015
2016
2017 /* check also the scheduled transactions */
2018 tmp_list = gsb_data_scheduled_get_scheduled_list ();
2019
2020 while ( tmp_list )
2021 {
2022 gint scheduled_number;
2023
2024 scheduled_number = gsb_data_scheduled_get_scheduled_number (tmp_list -> data);
2025
2026 if ( iface -> scheduled_div_id (scheduled_number) == no_division &&
2027 ( !no_sub_division ||
2028 iface -> scheduled_div_id (scheduled_number) == no_sub_division ) )
2029 {
2030 return TRUE;
2031 }
2032 else
2033 tmp_list = tmp_list -> next;
2034 }
2035
2036 return FALSE;
2037 }
2038
2039
2040
2041
2042 /**
2043 * return the the iter of a div and sub_div
2044 *
2045 * \param model
2046 * \param div
2047 * \param sub_div 0 if just div
2048 *
2049 * \return a newly allocated GtkTreeIter or NULL
2050 */
get_iter_from_div(GtkTreeModel * model,int div,int sub_div)2051 GtkTreeIter *get_iter_from_div ( GtkTreeModel * model, int div, int sub_div )
2052 {
2053 gpointer pointeurs[3] = { GINT_TO_POINTER (div), GINT_TO_POINTER (sub_div), NULL };
2054
2055 gtk_tree_model_foreach ( model, (GtkTreeModelForeachFunc) search_for_div_or_subdiv,
2056 pointeurs );
2057
2058 return (GtkTreeIter *) pointeurs[2];
2059 }
2060
2061
2062 /**
2063 * this is a tree model foreach function
2064 *
2065 * \param model
2066 * \param path
2067 * \param iter
2068 * \param pointers a structure { gpointer div, gpointer sub_div, gpointer }
2069 * div and sub-div transformed by GINT_TO_POINTER
2070 *
2071 * \return FALSE not found, TRUE found
2072 */
search_for_div_or_subdiv(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer * pointers)2073 gboolean search_for_div_or_subdiv ( GtkTreeModel *model,
2074 GtkTreePath *path,
2075 GtkTreeIter *iter,
2076 gpointer *pointers )
2077 {
2078 int no_div, no_sub_div;
2079 gchar *text;
2080
2081 gtk_tree_model_get ( GTK_TREE_MODEL(model), iter,
2082 META_TREE_TEXT_COLUMN, &text,
2083 META_TREE_NO_DIV_COLUMN, &no_div,
2084 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_div,
2085 -1 );
2086
2087 /* This is a kludge because we want to skip "dummy" iters that are
2088 * here only to provide a slider.*/
2089 if ( !text )
2090 return FALSE;
2091
2092 if ( ! pointers[0] && ( !pointers[1] || !GPOINTER_TO_INT (pointers[1]))
2093 &&
2094 !no_div && !no_sub_div )
2095 {
2096 pointers[2] = gtk_tree_iter_copy (iter);
2097 return TRUE;
2098 }
2099
2100 if ( no_div == GPOINTER_TO_INT (pointers[0]))
2101 {
2102 if ( ( !GPOINTER_TO_INT (pointers[1])) ||
2103 ( no_sub_div == GPOINTER_TO_INT (pointers[1])))
2104 {
2105 pointers[2] = gtk_tree_iter_copy (iter);
2106 return TRUE;
2107 }
2108 }
2109 return FALSE;
2110 }
2111
2112
2113 /**
2114 * return the the iter of a transaction
2115 *
2116 * \param model
2117 * \param transaction_number
2118 *
2119 * \return a newly allocated GtkTreeIter or NULL
2120 */
get_iter_from_transaction(GtkTreeModel * model,gint transaction_number)2121 GtkTreeIter *get_iter_from_transaction ( GtkTreeModel * model,
2122 gint transaction_number )
2123 {
2124 gpointer pointeurs[2] = { GINT_TO_POINTER (transaction_number), NULL };
2125
2126 gtk_tree_model_foreach ( model, (GtkTreeModelForeachFunc)
2127 search_for_transaction, pointeurs );
2128
2129 return (GtkTreeIter *) pointeurs[1];
2130 }
2131
2132
2133 /**
2134 * this is a tree model foreach function
2135 *
2136 * \param model
2137 * \param path
2138 * \param iter
2139 * \param pointers a structure { gpointer transaction_number, gpointer }
2140 * transaction_number transformed by GINT_TO_POINTER
2141 *
2142 * \return FALSE not found, TRUE found
2143 */
search_for_transaction(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer * pointers)2144 gboolean search_for_transaction ( GtkTreeModel *model,
2145 GtkTreePath *path,
2146 GtkTreeIter *iter,
2147 gpointer *pointers )
2148 {
2149 gint current_number;
2150
2151 gtk_tree_model_get ( GTK_TREE_MODEL(model), iter,
2152 META_TREE_POINTER_COLUMN, ¤t_number,
2153 -1 );
2154
2155 if ( current_number == GPOINTER_TO_INT (pointers[0] ))
2156 {
2157 pointers[1] = gtk_tree_iter_copy (iter);
2158 return TRUE;
2159 }
2160 return FALSE;
2161 }
2162
2163
2164
2165
2166
2167 /**
2168 * Update a transaction in a tree model if it is possible to find its
2169 * associated GtkTreeIter. This function is not responsible to remove
2170 * old transaction if transaction has changed in a way that would
2171 * move it in the tree (i.e, its category has changed and we want to
2172 * update the category tree).
2173 *
2174 * \param iface A MetatreeInterface to use.
2175 * \param model Tree model to update.
2176 * \param transaction_number Transaction to update if associated GtkTreeIter exists.
2177 */
update_transaction_in_tree(MetatreeInterface * iface,GtkTreeModel * model,gint transaction_number)2178 void update_transaction_in_tree ( MetatreeInterface * iface,
2179 GtkTreeModel * model,
2180 gint transaction_number )
2181 {
2182 GtkTreeIter *transaction_iter;
2183 GtkTreeIter *div_iter;
2184 GtkTreeIter *sub_div_iter = NULL;
2185 GtkTreePath *transaction_path;
2186 GtkTreePath *div_path;
2187 GtkTreePath *sub_div_path = NULL;
2188 gint div_id;
2189 gint sub_div_id;
2190 GtkTreeIter child_iter;
2191
2192 if ( !transaction_number || !metatree_model_is_displayed ( model ) )
2193 return;
2194
2195 div_id = iface -> transaction_div_id (transaction_number);
2196 sub_div_id = iface -> transaction_sub_div_id (transaction_number);
2197
2198 /* Fill in division if existing. */
2199 div_iter = get_iter_from_div ( model, div_id, 0 );
2200 if ( div_iter )
2201 {
2202 fill_division_row ( model, iface, div_iter, div_id );
2203 }
2204 else
2205 {
2206 metatree_fill_new_division ( iface, model, div_id );
2207 div_iter = get_iter_from_div ( model, div_id, 0 );
2208 }
2209
2210 /* Fill in sub-division if existing. */
2211 if ( iface -> depth != 1 )
2212 {
2213 sub_div_iter = get_iter_from_div ( model, div_id, sub_div_id );
2214 if ( sub_div_iter )
2215 {
2216 fill_sub_division_row ( model, iface, sub_div_iter, div_id, sub_div_id );
2217 }
2218 else
2219 {
2220 metatree_fill_new_sub_division ( iface, model, div_id, sub_div_id );
2221 sub_div_iter = get_iter_from_div ( model, div_id, sub_div_id );
2222 }
2223 }
2224
2225 /* Fill in transaction if existing. */
2226 transaction_iter = get_iter_from_transaction ( model, transaction_number );
2227
2228 if ( transaction_iter )
2229 {
2230 div_path = gtk_tree_model_get_path ( model, div_iter );
2231 if ( sub_div_iter )
2232 sub_div_path = gtk_tree_model_get_path ( model, sub_div_iter );
2233 transaction_path = gtk_tree_model_get_path ( model, transaction_iter );
2234 if ( ( iface -> depth != 1 &&
2235 ! gtk_tree_path_is_ancestor ( sub_div_path, transaction_path ) ) ||
2236 ! gtk_tree_path_is_ancestor ( div_path, transaction_path ) )
2237 {
2238 gtk_tree_store_remove ( GTK_TREE_STORE(model), transaction_iter );
2239 transaction_iter = NULL;
2240 }
2241 }
2242
2243 /* If no transaction iter is found, this either means transactions
2244 * for this division hasn't been shown yet, so no need to fill it;
2245 * or that it is a new transaction, so we need to append it to
2246 * subdivision row. */
2247 if ( ! transaction_iter )
2248 {
2249 gchar *text;
2250
2251 if ( ! gtk_tree_model_iter_children ( model, &child_iter,
2252 ( iface -> depth == 1 ? div_iter : sub_div_iter ) ) )
2253 /* Panic, something went wrong. */
2254 return;
2255
2256 gtk_tree_model_get ( model, &child_iter, META_TREE_TEXT_COLUMN, &text, -1 );
2257
2258 /* Text is set only if division has been expanded previously,
2259 * so we can add an iter. Otherwise, this will be done by the
2260 * expanded callback. */
2261 if ( text )
2262 {
2263 gtk_tree_store_append ( GTK_TREE_STORE(model), &child_iter,
2264 ( iface -> depth == 1 ? div_iter : sub_div_iter ) );
2265 transaction_iter = &child_iter;
2266 }
2267 }
2268
2269 if ( transaction_iter )
2270 fill_transaction_row ( model, transaction_iter, transaction_number );
2271 }
2272
2273
2274
2275 /**
2276 * Remove selected iter from metatree and select next iter.
2277 *
2278 * \param tree_view Tree view that contains selection.
2279 * \param model Model pertaining to tree view.
2280 * \param iter Iter to remove.
2281 */
metatree_remove_iter_and_select_next(GtkTreeView * tree_view,GtkTreeModel * model,GtkTreeIter * iter)2282 void metatree_remove_iter_and_select_next ( GtkTreeView * tree_view,
2283 GtkTreeModel * model,
2284 GtkTreeIter * iter )
2285 {
2286 GtkTreeSelection * selection;
2287
2288 selection = gtk_tree_view_get_selection ( tree_view );
2289 if ( selection && gtk_tree_selection_get_selected ( selection, &model, iter ) )
2290 {
2291 GtkTreeIter * next = gtk_tree_iter_copy ( iter );
2292 GtkTreePath * path = gtk_tree_model_get_path ( model, iter );
2293
2294 g_return_if_fail ( path );
2295 if ( ! gtk_tree_model_iter_next ( model, next ) )
2296 {
2297 gtk_tree_path_up ( path );
2298 if ( gtk_tree_path_get_depth ( path ) )
2299 gtk_tree_path_next ( path );
2300 }
2301
2302 gtk_tree_store_remove ( GTK_TREE_STORE(model), iter );
2303 gtk_tree_selection_select_path ( selection, path );
2304
2305 gtk_tree_iter_free ( next );
2306 gtk_tree_path_free ( path );
2307 }
2308 }
2309
2310
2311
2312 /**
2313 * Performs actions needed when selection of a metatree has changed.
2314 * First, update the headings bar accordingly. Then update
2315 * sensitiveness of linked widgets.
2316 *
2317 * \return TRUE
2318 */
metatree_selection_changed(GtkTreeSelection * selection,GtkTreeModel * model)2319 gboolean metatree_selection_changed ( GtkTreeSelection *selection, GtkTreeModel *model )
2320 {
2321 MetatreeInterface *iface;
2322 GtkTreeView *tree_view;
2323 GtkTreeIter iter;
2324 GtkTreePath *path;
2325 gboolean selection_is_set = FALSE;
2326 gint div_id = 0, sub_div_id = 0, current_number = 0;
2327 gint indice;
2328
2329 iface = g_object_get_data ( G_OBJECT ( model ), "metatree-interface" );
2330 tree_view = g_object_get_data ( G_OBJECT ( model ), "tree-view" );
2331 if ( !iface || !tree_view )
2332 return FALSE;
2333
2334 if ( selection && gtk_tree_selection_get_selected ( selection, &model, &iter ) )
2335 {
2336 gchar *text = NULL;
2337 gchar *balance = NULL;
2338
2339 if ( !model)
2340 return FALSE;
2341
2342 gtk_tree_model_get ( GTK_TREE_MODEL ( model ), &iter,
2343 META_TREE_NO_DIV_COLUMN, &div_id,
2344 META_TREE_NO_SUB_DIV_COLUMN, &sub_div_id,
2345 META_TREE_POINTER_COLUMN, ¤t_number,
2346 -1);
2347
2348 /* save the new_position */
2349 path = gtk_tree_model_get_path ( model, &iter );
2350 iface -> hold_position_set_path ( path );
2351
2352 /* get the indice of the path */
2353 indice = gtk_tree_path_get_depth ( path );
2354 if ( ( indice == 2 && iface -> content == 0 ) || ( div_id == 0 && current_number > 0 ) )
2355 indice = 4; /* the selected line is a transaction */
2356
2357 switch ( indice )
2358 {
2359 case 1:
2360 metatree_set_linked_widgets_sensitive ( model, TRUE, "selection" );
2361 iface -> hold_position_set_expand ( FALSE );
2362
2363 text = g_strconcat ( _(iface -> meta_name), " : ", iface -> div_name ( div_id ), NULL );
2364 balance = utils_real_get_string_with_currency ( iface -> div_balance ( div_id ),
2365 iface -> tree_currency (), TRUE );
2366 break;
2367 case 2:
2368 metatree_set_linked_widgets_sensitive ( model, TRUE, "selection" );
2369 iface -> hold_position_set_expand ( FALSE );
2370
2371 text = g_strconcat ( _(iface -> meta_name), " : ",
2372 ( div_id ? iface -> div_name ( div_id ) : _(iface->no_div_label) ),
2373 " : ",
2374 ( sub_div_id ? iface -> sub_div_name ( div_id, sub_div_id ) :
2375 _( iface->no_sub_div_label ) ),
2376 NULL );
2377
2378 balance = utils_real_get_string_with_currency ( iface -> sub_div_balance ( div_id, sub_div_id ),
2379 iface -> tree_currency (), TRUE );
2380 break;
2381 case 3:
2382 /* if we are on a transaction, get the div_id of the transaction */
2383 div_id = iface -> transaction_div_id ( current_number );
2384 sub_div_id = iface -> transaction_sub_div_id ( current_number );
2385 metatree_set_linked_widgets_sensitive ( model, FALSE, "selection" );
2386 /* save the new expand */
2387 iface -> hold_position_set_expand ( TRUE );
2388
2389 text = g_strconcat ( _(iface -> meta_name), " : ",
2390 ( div_id ? iface -> div_name ( div_id ) : _(iface->no_div_label) ),
2391 " : ",
2392 ( sub_div_id ? iface -> sub_div_name ( div_id, sub_div_id ) :
2393 _( iface->no_sub_div_label ) ),
2394 NULL );
2395
2396 balance = utils_real_get_string_with_currency ( iface -> sub_div_balance ( div_id, sub_div_id ),
2397 iface -> tree_currency (), TRUE );
2398 break;
2399 case 4:
2400 /* if we are on a transaction, get the div_id of the transaction */
2401 div_id = iface -> transaction_div_id ( current_number );
2402 metatree_set_linked_widgets_sensitive ( model, FALSE, "selection" );
2403 /* save the new expand */
2404 iface -> hold_position_set_expand ( TRUE );
2405
2406 text = g_strconcat ( _(iface -> meta_name), " : ", iface -> div_name ( div_id ), NULL );
2407 balance = utils_real_get_string_with_currency ( iface -> div_balance ( div_id ),
2408 iface -> tree_currency (), TRUE );
2409 break;
2410 }
2411
2412 grisbi_win_headings_update_title ( text );
2413 grisbi_win_headings_update_suffix ( balance );
2414 g_free ( text );
2415 g_free ( balance );
2416 selection_is_set = TRUE;
2417 }
2418
2419 /* Update sensitiveness of linked widgets. */
2420 /* metatree_set_linked_widgets_sensitive ( model, selection_is_set, "selection" ); */
2421 if ( !div_id || ( sub_div_id <= 0 && current_number <= 0 ) )
2422 {
2423 metatree_set_linked_widgets_sensitive ( model, FALSE, "selection" );
2424 }
2425
2426 if ( selection_is_set
2427 &&
2428 metatree_get_row_type ( model, gtk_tree_model_get_path ( model, &iter ) ) == META_TREE_DIV
2429 &&
2430 div_id )
2431 {
2432 metatree_set_linked_widgets_sensitive ( model, TRUE, "sub-division" );
2433 }
2434 else
2435 {
2436 metatree_set_linked_widgets_sensitive ( model, FALSE, "sub-division" );
2437 }
2438
2439 return TRUE;
2440 }
2441
2442
2443 /**
2444 * Link a widget to a metatree. This means, in some events like
2445 * selection change, it will be set sensitive or unsensitive.
2446 *
2447 * \param model Model to link widget to.
2448 * \param widget Widget to link to metatree.
2449 * \param link_type A string representing different links. Should
2450 * be "selection" for a widget that is sensitive
2451 * only if a line is selected or "sub-division"
2452 * for a widget that is sensitive only if a first
2453 * level entry is selected.
2454 */
metatree_register_widget_as_linked(GtkTreeModel * model,GtkWidget * widget,const gchar * link_type)2455 void metatree_register_widget_as_linked ( GtkTreeModel * model,
2456 GtkWidget * widget,
2457 const gchar * link_type )
2458 {
2459 GSList * links;
2460
2461 g_return_if_fail ( widget != NULL );
2462 g_return_if_fail ( model != NULL );
2463 g_return_if_fail ( link_type && strlen ( link_type ) );
2464
2465 links = g_object_get_data ( G_OBJECT(model), link_type );
2466 g_object_set_data ( G_OBJECT(model), link_type, g_slist_append ( links, widget ) );
2467 }
2468
2469
2470
2471 /**
2472 * Set widgets linked to a metatree (normally, buttons) sensitive or
2473 * unsensitive.
2474 *
2475 * \param model Model widgets are linked to.
2476 * \param sensitive Set widgets sensitive if TRUE, unsensitive otherwise.
2477 * \param link_type A string representing different links. Should
2478 * be "selection" for a widget that is sensitive
2479 * only if a line is selected or "sub-division"
2480 * for a widget that is sensitive only if a first
2481 * level entry is selected.
2482 */
metatree_set_linked_widgets_sensitive(GtkTreeModel * model,gboolean sensitive,const gchar * link_type)2483 void metatree_set_linked_widgets_sensitive ( GtkTreeModel * model,
2484 gboolean sensitive,
2485 const gchar * link_type )
2486 {
2487 GSList * links = g_object_get_data ( G_OBJECT(model), link_type );
2488
2489 while ( links )
2490 {
2491 if ( links -> data && GTK_IS_WIDGET ( links -> data ) )
2492 {
2493 gtk_widget_set_sensitive ( GTK_WIDGET (
2494 links -> data ), sensitive );
2495 }
2496 links = links -> next;
2497 }
2498 }
2499
2500
2501
2502 /**
2503 * Compare two iters from a metatree. If they both contain a date
2504 * (from the META_TREE_DATE_COLUMN field), then a date comparison is
2505 * done. Otherwise, it compares dates. Normally, it is called as a
2506 * backend function from gtk_tree_sortable_set_sort_func().
2507 *
2508 * \param model Sortable tree model that triggered the sort.
2509 * \param a First iter to compare.
2510 * \param b Second iter to compare.
2511 * \param user_data Not used.
2512 *
2513 * \return Same as a > b
2514 */
metatree_sort_column(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer user_data)2515 gboolean metatree_sort_column ( GtkTreeModel * model,
2516 GtkTreeIter * a, GtkTreeIter * b,
2517 gpointer user_data )
2518 {
2519 GDate * date_a = NULL, * date_b = NULL;
2520 gchar *string_a = NULL, *string_b = NULL;
2521 gint no_div_a, no_sous_div_a, no_div_b, no_sous_div_b;
2522 gint return_value;
2523
2524 gtk_tree_model_get ( model, a,
2525 META_TREE_DATE_COLUMN, &date_a,
2526 META_TREE_TEXT_COLUMN, &string_a,
2527 META_TREE_NO_DIV_COLUMN, &no_div_a,
2528 META_TREE_NO_SUB_DIV_COLUMN, &no_sous_div_a, -1 );
2529 gtk_tree_model_get ( model, b,
2530 META_TREE_DATE_COLUMN, &date_b,
2531 META_TREE_TEXT_COLUMN, &string_b,
2532 META_TREE_NO_DIV_COLUMN, &no_div_b,
2533 META_TREE_NO_SUB_DIV_COLUMN, &no_sous_div_b, -1 );
2534
2535 /* on affiche en premier les opérations sans div sous_division */
2536 if ( no_div_a == 0 )
2537 {
2538 g_free ( string_a );
2539 g_free ( string_b );
2540
2541 return -1;
2542 }
2543
2544 if ( no_div_b == 0 )
2545 {
2546 g_free ( string_a );
2547 g_free ( string_b );
2548
2549 return 1;
2550 }
2551
2552 if ( no_div_a == no_div_b && no_sous_div_a == 0 )
2553 {
2554 g_free ( string_a );
2555 g_free ( string_b );
2556
2557 return -1;
2558 }
2559
2560 if ( no_div_a == no_div_b && no_sous_div_b == 0 )
2561 {
2562 g_free ( string_a );
2563 g_free ( string_b );
2564
2565 return 1;
2566 }
2567
2568 if ( !string_b )
2569 {
2570 g_free ( string_a );
2571 return 1;
2572 }
2573
2574 if ( !string_a )
2575 {
2576 g_free ( string_b );
2577 return -1;
2578 }
2579
2580 if ( !date_a && !date_b )
2581 {
2582 return_value = g_utf8_collate ( string_a, string_b );
2583 g_free ( string_a );
2584 g_free ( string_b );
2585
2586 return return_value;
2587 }
2588
2589 g_free ( string_a );
2590 g_free ( string_b );
2591
2592 if ( !date_b )
2593 return 1;
2594 else if ( !date_a )
2595 return -1;
2596
2597 return_value = g_date_compare ( date_a, date_b );
2598
2599 return return_value;
2600 }
2601
2602
2603 /**
2604 * Fill an empty division row with textual representation of a division
2605 * structure, in the form: "Name (num transactions) Balance".
2606 *
2607 * \param model The GtkTreeModel that contains iter.
2608 * \param iface A pointer to the metatree interface to use
2609 * \param iter Iter to fill with division data.
2610 * \param division Division structure number. (category number, payee number or budget number)
2611 */
fill_division_zero(GtkTreeModel * model,MetatreeInterface * iface,GtkTreeIter * iter)2612 void fill_division_zero ( GtkTreeModel * model,
2613 MetatreeInterface * iface,
2614 GtkTreeIter * iter )
2615 {
2616 gchar *balance = NULL;
2617 gchar *string_tmp;
2618 GtkTreeIter dumb_iter;
2619 gint number_transactions;
2620
2621 devel_debug ( NULL );
2622 if ( ! metatree_model_is_displayed ( model ) )
2623 return;
2624
2625 string_tmp = iface -> div_name ( 0 );
2626 number_transactions = iface -> div_nb_transactions ( 0 );
2627
2628 if (number_transactions)
2629 {
2630 gchar *label;
2631
2632 label = g_strdup_printf ( "%s (%d)",
2633 string_tmp,
2634 number_transactions);
2635 g_free (string_tmp);
2636 string_tmp = label;
2637
2638 balance = utils_real_get_string_with_currency ( iface -> div_balance ( 0 ),
2639 iface -> tree_currency (), TRUE );
2640
2641 /* add a white child to show the arrow to open it */
2642 if ( ! gtk_tree_model_iter_has_child ( model, iter )
2643 &&
2644 (iface -> depth == 1 ))
2645 gtk_tree_store_append (GTK_TREE_STORE (model), &dumb_iter, iter );
2646 }
2647
2648 /* set 0 for the sub-div, so no categ/no budget have 0 for div and 0 for sub-div */
2649 gtk_tree_store_set (GTK_TREE_STORE(model), iter,
2650 META_TREE_TEXT_COLUMN, string_tmp,
2651 META_TREE_POINTER_COLUMN, 0,
2652 META_TREE_BALANCE_COLUMN, balance,
2653 META_TREE_XALIGN_COLUMN, 1.0,
2654 META_TREE_NO_DIV_COLUMN, 0,
2655 META_TREE_NO_SUB_DIV_COLUMN, 0,
2656 META_TREE_NO_TRANSACTION_COLUMN, 0,
2657 META_TREE_FONT_COLUMN, 800,
2658 META_TREE_DATE_COLUMN, NULL,
2659 -1);
2660 g_free (string_tmp);
2661 if (balance)
2662 g_free (balance);
2663 }
2664
2665
2666 /**
2667 * Fill an empty sub-division row with textual representation of a
2668 * sub-division structure, in the form: "Name (num transactions)
2669 * Balance".
2670 *
2671 * \param model The GtkTreeModel that contains iter.
2672 * \param iface A pointer to the metatree interface to use
2673 * \param iter Iter to fill with sub-division data.
2674 * \param division Division structure number (parent).
2675 * \param sub_division Sub-division structure number.
2676 */
fill_sub_division_zero(GtkTreeModel * model,MetatreeInterface * iface,GtkTreeIter * iter,gint division)2677 void fill_sub_division_zero ( GtkTreeModel * model,
2678 MetatreeInterface * iface,
2679 GtkTreeIter * iter,
2680 gint division )
2681 {
2682 gchar *balance = NULL;
2683 gchar *string_tmp;
2684 GtkTreeIter dumb_iter;
2685 gint number_transactions = 0;
2686
2687 /* devel_debug_int ( division ); */
2688
2689 if ( ! metatree_model_is_displayed ( model ) )
2690 return;
2691
2692 /* if no division, there is no sub division */
2693 if (!division)
2694 return;
2695
2696 string_tmp = iface -> sub_div_name (division, 0);
2697 /* on a affaire à un tiers */
2698 if ( string_tmp == NULL)
2699 return;
2700
2701 number_transactions = iface -> sub_div_nb_transactions ( division, 0 );
2702
2703 if ( number_transactions )
2704 {
2705 gchar *label;
2706
2707 label = g_strdup_printf ( "%s (%d)",
2708 string_tmp,
2709 number_transactions );
2710 g_free (string_tmp);
2711 string_tmp = label;
2712
2713 if ( ! gtk_tree_model_iter_has_child ( model, iter ) )
2714 gtk_tree_store_append (GTK_TREE_STORE (model), &dumb_iter, iter );
2715
2716 balance = utils_real_get_string_with_currency ( iface -> sub_div_balance ( division, 0 ),
2717 iface -> tree_currency (), TRUE );
2718 }
2719
2720 gtk_tree_store_set ( GTK_TREE_STORE (model), iter,
2721 META_TREE_TEXT_COLUMN, string_tmp,
2722 META_TREE_POINTER_COLUMN, 0,
2723 META_TREE_BALANCE_COLUMN, balance,
2724 META_TREE_XALIGN_COLUMN, 1.0,
2725 META_TREE_NO_DIV_COLUMN, division,
2726 META_TREE_NO_SUB_DIV_COLUMN, 0,
2727 META_TREE_NO_TRANSACTION_COLUMN, 0,
2728 META_TREE_FONT_COLUMN, 400,
2729 META_TREE_DATE_COLUMN, NULL,
2730 -1 );
2731 g_free (string_tmp);
2732 if (balance)
2733 g_free (balance);
2734 }
2735
2736
2737 /**
2738 *
2739 *
2740 *
2741 *
2742 *
2743 * */
get_iter_from_sub_div_zero(GtkTreeModel * model,MetatreeInterface * iface,GtkTreeIter * parent_iter)2744 GtkTreeIter *get_iter_from_sub_div_zero ( GtkTreeModel *model,
2745 MetatreeInterface *iface,
2746 GtkTreeIter *parent_iter )
2747 {
2748 GtkTreeIter dest_iter;
2749 GtkTreeIter child_iter;
2750 gint i;
2751
2752 dest_iter = *parent_iter;
2753 for (i = 0; i< gtk_tree_model_iter_n_children (model, &dest_iter); i++ )
2754 {
2755 if ( gtk_tree_model_iter_nth_child (model, &child_iter, &dest_iter, i) )
2756 {
2757 gchar *name;
2758
2759 gtk_tree_model_get ( model, &child_iter,
2760 META_TREE_TEXT_COLUMN, &name, -1 );
2761 if ( name && g_utf8_collate (
2762 name, _(iface->no_sub_div_label) ) == 0 )
2763 break;
2764 }
2765 }
2766
2767 return gtk_tree_iter_copy (&child_iter);
2768 }
2769
2770
2771 /**
2772 *
2773 *
2774 *
2775 *
2776 *
2777 * */
move_transactions_to_division_payee(GtkTreeModel * model,MetatreeInterface * iface,gint orig_div,gint dest_div)2778 void move_transactions_to_division_payee (GtkTreeModel * model,
2779 MetatreeInterface * iface,
2780 gint orig_div, gint dest_div )
2781 {
2782 GSList *list_tmp_transactions;
2783
2784 devel_debug_int ( dest_div);
2785
2786 if ( !model )
2787 return;
2788
2789 iface = g_object_get_data ( G_OBJECT(model), "metatree-interface" );
2790
2791 /* fill the dest division for payee with the transactions */
2792 list_tmp_transactions = gsb_data_transaction_get_complete_transactions_list ();
2793
2794 while ( list_tmp_transactions )
2795 {
2796 gint transaction_number_tmp;
2797 transaction_number_tmp = gsb_data_transaction_get_transaction_number (
2798 list_tmp_transactions -> data);
2799
2800 if ( transaction_number_tmp &&
2801 iface -> transaction_div_id (transaction_number_tmp) == orig_div )
2802 {
2803 iface -> transaction_set_div_id (
2804 transaction_number_tmp, dest_div );
2805 iface -> transaction_set_sub_div_id (
2806 transaction_number_tmp, 0 );
2807 gsb_transactions_list_update_transaction (
2808 transaction_number_tmp );
2809 iface -> add_transaction_to_div ( transaction_number_tmp,
2810 dest_div );
2811 }
2812 list_tmp_transactions = list_tmp_transactions -> next;
2813 }
2814
2815 /* We did some modifications */
2816 gsb_file_set_modified ( TRUE );
2817 }
2818
2819
2820 /**
2821 *
2822 *
2823 *
2824 *
2825 * */
button_delete_div_sub_div_clicked(GtkWidget * togglebutton,gpointer value)2826 static void button_delete_div_sub_div_clicked (GtkWidget *togglebutton,
2827 gpointer value)
2828 {
2829 button_move_selected = GPOINTER_TO_INT (value);
2830 }
2831
2832
2833 /**
2834 * called when there is some transactions associated to the category, budget or payee
2835 * show a dialog and ask another categ/budget/payee to move the concerned transactions
2836 * and fill no_div and no_sub_div with the user choice
2837 *
2838 * \param iface
2839 * \param model
2840 * \param division the current (old) division number
2841 * \param sub_division the current (old) sub-division number
2842 * \param no_div a pointer to gint for the choice of division chosen by user
2843 * \param no_sub_div a pointer to gint for the choice of sub-division chosen by user
2844 *
2845 * \return FALSE to stop the process, TRUE to continue
2846 * no_div will contain the new division, no_sub_div the new sub-division
2847 * if no move of transactions, no_div and no_sub_div are set to 0
2848 * if move to another division but no sub-division, no_sub_div is set to 0
2849 * */
metatree_find_destination_blob(MetatreeInterface * iface,GtkTreeModel * model,gint division,gint sub_division,gint * no_div,gint * no_sub_div,enum MetaTreeRowType type_division)2850 gboolean metatree_find_destination_blob ( MetatreeInterface *iface,
2851 GtkTreeModel *model,
2852 gint division,
2853 gint sub_division,
2854 gint *no_div,
2855 gint *no_sub_div,
2856 enum MetaTreeRowType type_division )
2857 {
2858 GtkWidget *dialog;
2859 GtkWidget *hbox;
2860 GtkWidget *button;
2861 GtkWidget *entry;
2862 GtkWidget *label;
2863 GtkWidget *combofix;
2864 gint nouveau_no_division;
2865 gint nouveau_no_sub_division;
2866 gint resultat;
2867 gchar **split_division;
2868 gchar *tmp_str;
2869 gchar* hint;
2870 gchar* text;
2871
2872 if ( type_division == META_TREE_TRANS_S_S_DIV )
2873 {
2874 hint = g_strdup_printf ( _("Transfer all transactions in a \n%s."),
2875 gettext ( iface -> meta_sub_name ) );
2876
2877 text = NULL;
2878 }
2879 else
2880 {
2881 /* create the box to move change the division and sub-div of the transactions */
2882 hint = g_strdup_printf ( _("Choose action for \"%s\"."),
2883 ( !sub_division ?
2884 iface -> div_name ( division ) :
2885 iface -> sub_div_name ( division, sub_division ) ) );
2886
2887 text = g_strdup_printf (
2888 _("You can transfer content from \"%s\" in another %s or %s.\n"
2889 "Otherwise you can transfer \"%s\" in another %s "
2890 "or transform \"%s\" to %s."),
2891 iface -> sub_div_name ( division, sub_division ),
2892 gettext ( iface -> meta_name_minus ),
2893 gettext ( iface -> meta_sub_name ),
2894 iface -> sub_div_name ( division, sub_division ),
2895 gettext (iface -> meta_name_minus),
2896 iface -> sub_div_name ( division, sub_division ),
2897 gettext ( iface -> meta_name_minus ) );
2898 }
2899
2900 dialog = dialogue_special_no_run ( GTK_MESSAGE_INFO,
2901 GTK_BUTTONS_OK_CANCEL,
2902 text, hint );
2903
2904 gtk_widget_set_size_request ( dialog, -1, -1 );
2905
2906 g_free ( hint );
2907 g_free ( text );
2908
2909 if ( sub_division )
2910 {
2911 GtkWidget *vbox;
2912 gchar *tmp_str_1;
2913 gchar *tmp_str_2;
2914 gchar *tmp_str_3;
2915
2916 tmp_str_1 = g_strdup_printf ( _("Transfer the transactions in a %s or %s"),
2917 gettext ( iface -> meta_name_minus ),
2918 gettext ( iface -> meta_sub_name ) );
2919 tmp_str_2 = g_strdup_printf(_("Transfer \"%s\" in other %s"),
2920 iface -> sub_div_name ( division, sub_division ),
2921 gettext ( iface -> meta_name_minus ) );
2922 tmp_str_3 = g_strdup_printf(_("Convert \"%s\" in new %s"),
2923 iface -> sub_div_name ( division, sub_division ),
2924 gettext ( iface -> meta_name_minus ) );
2925
2926 button = gsb_automem_radiobutton3_new ( tmp_str_1,
2927 tmp_str_2,
2928 tmp_str_3,
2929 &button_action_selected,
2930 G_CALLBACK ( metatree_button_action_sub_div_clicked ),
2931 &button_action_selected,
2932 GTK_ORIENTATION_VERTICAL );
2933
2934 g_free ( tmp_str_1 );
2935 g_free ( tmp_str_2 );
2936 g_free ( tmp_str_3 );
2937
2938 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), button, FALSE, FALSE, 0 );
2939
2940 /* create the list containing division and sub-division without the current division */
2941 hbox = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, MARGIN_BOX );
2942 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), hbox, FALSE, FALSE, 0 );
2943
2944 label = gtk_label_new ( _("Select the destination: ") );
2945 utils_labels_set_alignment ( GTK_LABEL ( label ), 0, 0 );
2946 gtk_box_pack_start ( GTK_BOX ( hbox ), label, TRUE, TRUE, 0 );
2947
2948 vbox = gtk_box_new ( GTK_ORIENTATION_VERTICAL, 0 );
2949 gtk_box_pack_start ( GTK_BOX ( hbox ), vbox, TRUE, TRUE, 0 );
2950
2951 combofix = metatree_get_combofix ( iface, division, sub_division, type_division );
2952 gtk_combofix_set_force_text ( GTK_COMBOFIX ( combofix ), FALSE );
2953 gtk_box_pack_start ( GTK_BOX ( vbox ), combofix, TRUE, TRUE, 0 );
2954 g_object_set_data ( G_OBJECT ( button ), "label", label );
2955 g_object_set_data ( G_OBJECT ( button ), "combofix", combofix );
2956 }
2957 else
2958 {
2959 /* on reset le choix */
2960 button_action_selected = 0;
2961
2962 hbox = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, MARGIN_BOX );
2963 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), hbox, FALSE, FALSE, 0 );
2964
2965 label = gtk_label_new ( _("Select the destination: ") );
2966 utils_labels_set_alignment ( GTK_LABEL ( label ), 0, 0 );
2967 gtk_box_pack_start ( GTK_BOX ( hbox ), label, TRUE, TRUE, 0 );
2968
2969 combofix = metatree_get_combofix ( iface, division, sub_division, type_division );
2970 gtk_combofix_set_force_text ( GTK_COMBOFIX ( combofix ), FALSE );
2971 gtk_box_pack_start ( GTK_BOX ( hbox ), combofix, TRUE, TRUE, 0 );
2972 }
2973
2974 gtk_widget_show_all ( dialog );
2975 entry = gtk_combofix_get_entry (GTK_COMBOFIX (combofix));
2976 gtk_widget_grab_focus (entry);
2977 gtk_editable_set_position ( GTK_EDITABLE (entry), 0 );
2978
2979 resultat = gtk_dialog_run ( GTK_DIALOG ( dialog ) );
2980
2981 if ( resultat != GTK_RESPONSE_OK )
2982 {
2983 gtk_widget_destroy ( GTK_WIDGET ( dialog ) );
2984
2985 return FALSE;
2986 }
2987
2988 nouveau_no_division = 0;
2989 nouveau_no_sub_division = 0;
2990
2991 if ( button_action_selected < 2 )
2992 {
2993 /* we want to move the content */
2994 if ( !strlen ( gtk_combofix_get_text ( GTK_COMBOFIX ( combofix ) ) ) )
2995 {
2996 text = g_strdup_printf (
2997 _("It is compulsory to specify a destination %s "
2998 "to move content but no %s was entered."),
2999 gettext ( iface -> meta_name_minus ),
3000 gettext ( iface -> meta_name_minus ) );
3001 hint = g_strdup_printf ( _("Please enter a %s!"), _(iface -> meta_name_minus) );
3002
3003 dialogue_warning_hint ( text , hint );
3004
3005 g_free ( text );
3006 g_free ( hint );
3007
3008 gtk_widget_destroy (dialog);
3009
3010 return ( metatree_find_destination_blob ( iface, model,
3011 division, sub_division,
3012 no_div, no_sub_div, type_division ) );
3013 }
3014
3015 /* get the new (sub-)divisions */
3016 split_division = g_strsplit ( gtk_combofix_get_text ( GTK_COMBOFIX ( combofix ) ), " : ", 2 );
3017
3018 nouveau_no_division = iface -> get_div_pointer_from_name ( split_division[0], 0 );
3019
3020 if (nouveau_no_division)
3021 {
3022 nouveau_no_sub_division = iface -> get_sub_div_pointer_from_name (
3023 nouveau_no_division, split_division[1], 0 );
3024
3025 if ( split_division[1] && nouveau_no_sub_division == 0 )
3026 {
3027 tmp_str = g_strdup_printf ( _("Warning you can not create %s."),
3028 _(iface -> meta_name_minus) );
3029 dialogue_warning( tmp_str );
3030
3031 g_free ( tmp_str );
3032
3033 gtk_widget_destroy ( dialog );
3034
3035 return ( metatree_find_destination_blob ( iface, model,
3036 division, sub_division,
3037 no_div, no_sub_div, type_division ) );
3038 }
3039 }
3040
3041 g_strfreev ( split_division );
3042 }
3043
3044 gtk_widget_destroy ( GTK_WIDGET ( dialog ) );
3045
3046 /* return the new number of division and sub-division
3047 * if don't want to move the transactions, 0 and 0 will be returned */
3048 if ( no_div)
3049 *no_div = nouveau_no_division;
3050 if ( no_sub_div )
3051 *no_sub_div = nouveau_no_sub_division;
3052
3053 return TRUE;
3054 }
3055
3056
3057 /**
3058 *
3059 *
3060 * \param
3061 *
3062 */
metatree_manage_sub_divisions(GtkWidget * tree_view)3063 void metatree_manage_sub_divisions ( GtkWidget *tree_view )
3064 {
3065 GtkTreeSelection *selection;
3066 GtkTreeModel *model;
3067 GtkTreeIter iter;
3068 GtkTreeIter *it;
3069 GtkTreePath *path = NULL;
3070 gint no_division = 0;
3071 gint no_sub_division = 0;
3072 gint new_division;
3073 gint new_sub_division;
3074 gint profondeur;
3075 MetatreeInterface *iface;
3076 enum MetaTreeRowType type_division;
3077
3078 devel_debug (NULL);
3079
3080 selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( tree_view ) );
3081 if ( selection && gtk_tree_selection_get_selected ( selection, &model, &iter ) )
3082 {
3083 gtk_tree_model_get ( model, &iter,
3084 META_TREE_NO_DIV_COLUMN, &no_division,
3085 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_division,
3086 -1 );
3087 }
3088 else
3089 return;
3090
3091 iface = g_object_get_data ( G_OBJECT ( model ), "metatree-interface" );
3092 type_division = metatree_get_row_type_from_tree_view ( tree_view );
3093
3094 if ( !metatree_find_destination_blob ( iface, model, no_division, no_sub_division,
3095 &new_division, &new_sub_division, type_division ) )
3096 return;
3097
3098 /* printf ("no_division = %d no_sub_division = %d\n", no_division, no_sub_division);
3099 * printf ("new_division = %d new_sub_division = %d\n", new_division, new_sub_division);
3100 *
3101 */
3102 /* Transfert d'opérations dans une catégorie ou une sous catégorie */
3103 if ( button_action_selected == 0 && no_division && new_division )
3104 {
3105 metatree_move_transactions_to_sub_div ( iface, model,
3106 no_division, no_sub_division, new_division, new_sub_division );
3107
3108 /* update the model */
3109 switch (iface->content )
3110 {
3111 case METATREE_CATEGORY:
3112 categories_fill_list ();
3113 break;
3114 case METATREE_BUDGET:
3115 payees_fill_list ();
3116 break;
3117 }
3118
3119 /* fait le tour des échéances pour mettre le nouveau numéro de division et sub_division */
3120 metatree_move_scheduled_with_div_sub_div ( iface, model,
3121 no_division, no_sub_division,
3122 new_division, new_sub_division );
3123
3124 /* update value in the tree view */
3125 metatree_update_tree_view ( iface );
3126 }
3127
3128 if ( button_action_selected == 1 && no_division && no_sub_division && new_division )
3129 {
3130 new_sub_division = metatree_move_sub_division_to_division ( iface,
3131 no_division, no_sub_division, new_division );
3132
3133 /* update the model */
3134 switch (iface->content )
3135 {
3136 case METATREE_CATEGORY:
3137 categories_fill_list ();
3138 break;
3139 case METATREE_BUDGET:
3140 payees_fill_list ();
3141 break;
3142 }
3143
3144 /* fait le tour des échéances pour mettre le nouveau numéro de division et sub_division */
3145 metatree_move_scheduled_with_div_sub_div ( iface, model,
3146 no_division, no_sub_division,
3147 new_division, new_sub_division );
3148
3149 /* update value in the tree view */
3150 metatree_update_tree_view ( iface );
3151 }
3152
3153 if ( button_action_selected == 2 && new_division == 0 && new_sub_division == 0 )
3154 {
3155 new_division = metatree_create_division_from_sub_division ( iface, no_division, no_sub_division );
3156
3157 /* update the model */
3158 switch (iface->content )
3159 {
3160 case METATREE_CATEGORY:
3161 categories_fill_list ();
3162 break;
3163 case METATREE_BUDGET:
3164 payees_fill_list ();
3165 break;
3166 }
3167
3168 /* fait le tour des échéances pour mettre le nouveau numéro de division et sub_division */
3169 metatree_move_scheduled_with_div_sub_div ( iface, model,
3170 no_division, no_sub_division,
3171 new_division, new_sub_division );
3172
3173 /* update value in the tree view */
3174 metatree_update_tree_view ( iface );
3175 }
3176 /* restitue l'état du tree_view */
3177 /* old path */
3178 if ( iface -> content == 1 )
3179 path = categories_hold_position_get_path ( );
3180 else if ( iface -> content == 2 )
3181 path = budgetary_hold_position_get_path ( );
3182
3183 profondeur = gtk_tree_path_get_depth ( path );
3184 while ( profondeur > 1 )
3185 {
3186 gtk_tree_path_up ( path );
3187 profondeur = gtk_tree_path_get_depth ( path );
3188 }
3189 gtk_tree_view_expand_to_path ( GTK_TREE_VIEW ( tree_view ), path );
3190 gtk_tree_path_free ( path );
3191
3192 /* new path */
3193 it = get_iter_from_div ( model, new_division, 0 );
3194 if ( it )
3195 {
3196 path = gtk_tree_model_get_path ( model, it );
3197 gtk_tree_view_expand_to_path ( GTK_TREE_VIEW ( tree_view ), path );
3198 gtk_tree_path_free ( path );
3199 }
3200
3201 /* We did some modifications */
3202 gsb_file_set_modified ( TRUE );
3203 }
3204
3205
3206 /**
3207 *
3208 *
3209 * \param
3210 *
3211 */
metatree_get_row_type_from_tree_view(GtkWidget * tree_view)3212 enum MetaTreeRowType metatree_get_row_type_from_tree_view ( GtkWidget *tree_view )
3213 {
3214 GtkTreeSelection *selection;
3215 GtkTreeModel *model;
3216 GtkTreeIter iter;
3217 enum MetaTreeRowType type_division;
3218
3219 selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( tree_view ) );
3220 if ( selection && gtk_tree_selection_get_selected ( selection, &model, &iter ) )
3221 {
3222 GtkTreePath *path;
3223 GtkTreeIter parent;
3224 gint no_division = 0;
3225 gint no_sub_division = 0;
3226
3227 gtk_tree_model_get ( model, &iter,
3228 META_TREE_NO_DIV_COLUMN, &no_division,
3229 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_division,
3230 -1 );
3231
3232 if ( no_sub_division == 0
3233 &&
3234 gtk_tree_model_iter_parent ( GTK_TREE_MODEL ( model ), &parent, &iter ) )
3235 {
3236 gint nbre_trans_s_s_div = 0; /* nbre de transactions sans sous-division */
3237
3238 nbre_trans_s_s_div = metatree_get_nbre_transactions_sans_sub_div ( tree_view );
3239 if ( nbre_trans_s_s_div > 0 )
3240 return META_TREE_TRANS_S_S_DIV;
3241 }
3242
3243 path = gtk_tree_model_get_path ( model, &iter );
3244 type_division = metatree_get_row_type ( model, path );
3245
3246 gtk_tree_path_free ( path );
3247
3248 return type_division;
3249 }
3250
3251 return META_TREE_INVALID;
3252 }
3253
3254
3255 /**
3256 *
3257 *
3258 *
3259 *
3260 * */
metatree_button_action_sub_div_clicked(GtkWidget * togglebutton,GdkEventButton * event,gint * pointeur)3261 void metatree_button_action_sub_div_clicked ( GtkWidget *togglebutton,
3262 GdkEventButton *event,
3263 gint *pointeur )
3264 {
3265 if ( pointeur )
3266 {
3267 GtkWidget *parent = NULL;
3268 GtkWidget *label = NULL;
3269 GtkWidget *combofix = NULL;
3270 GtkWidget *entry;
3271 GSList *list;
3272 gint value = 0;
3273
3274 value = GPOINTER_TO_INT ( g_object_get_data ( G_OBJECT ( togglebutton ), "pointer" ) );
3275 *pointeur = value;
3276 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON ( togglebutton ), TRUE );
3277
3278 parent = gtk_widget_get_parent ( togglebutton );
3279 if ( parent )
3280 {
3281 label = g_object_get_data ( G_OBJECT ( parent ), "label" );
3282 combofix = g_object_get_data ( G_OBJECT ( parent ), "combofix" );
3283 }
3284 if ( ! combofix )
3285 return;
3286
3287 entry = gtk_combofix_get_entry (GTK_COMBOFIX (combofix));
3288 switch ( value )
3289 {
3290 case 0:
3291 gtk_widget_set_sensitive ( label, TRUE );
3292 gtk_widget_set_sensitive ( combofix, TRUE );
3293 list = g_object_get_data ( G_OBJECT ( combofix ), "list_1" );
3294 gtk_combofix_set_list ( GTK_COMBOFIX ( combofix ), list );
3295 gtk_widget_grab_focus (entry);
3296 gtk_editable_set_position (GTK_EDITABLE (entry), 0);
3297 break;
3298 case 1:
3299 gtk_widget_set_sensitive ( label, TRUE );
3300 gtk_widget_set_sensitive ( combofix, TRUE );
3301 list = g_object_get_data ( G_OBJECT ( combofix ), "list_2" );
3302 gtk_combofix_set_list ( GTK_COMBOFIX ( combofix ), list );
3303 gtk_widget_grab_focus (entry);
3304 gtk_editable_set_position (GTK_EDITABLE (entry), 0);
3305 break;
3306 case 2:
3307 gtk_widget_set_sensitive ( label, FALSE );
3308 gtk_widget_set_sensitive ( combofix, FALSE );
3309 break;
3310 }
3311 }
3312 }
3313
3314
3315 /**
3316 *
3317 *
3318 *
3319 *
3320 * */
metatree_move_scheduled_with_div_sub_div(MetatreeInterface * iface,GtkTreeModel * model,gint no_division,gint no_sub_division,gint new_division,gint new_sub_division)3321 void metatree_move_scheduled_with_div_sub_div ( MetatreeInterface *iface,
3322 GtkTreeModel *model,
3323 gint no_division,
3324 gint no_sub_division,
3325 gint new_division,
3326 gint new_sub_division )
3327 {
3328 GSList *list_tmp;
3329
3330 /* fait le tour des échéances pour mettre le nouveau numéro de division et sub_division */
3331 list_tmp = gsb_data_scheduled_get_scheduled_list ( );
3332
3333 while ( list_tmp )
3334 {
3335 gint scheduled_number;
3336
3337 scheduled_number = gsb_data_scheduled_get_scheduled_number ( list_tmp -> data );
3338
3339 if ( iface -> scheduled_div_id ( scheduled_number ) == no_division )
3340 {
3341 if ( ( no_sub_division && iface -> scheduled_sub_div_id (scheduled_number) == no_sub_division )
3342 ||
3343 no_sub_division == 0 )
3344 {
3345 iface -> scheduled_set_div_id ( scheduled_number, new_division );
3346 iface -> scheduled_set_sub_div_id ( scheduled_number, new_sub_division );
3347 }
3348 }
3349
3350 list_tmp = list_tmp -> next;
3351 }
3352 }
3353
3354
3355 /**
3356 *
3357 *
3358 *
3359 *
3360 * */
metatree_reset_transactions_without_div_sub_div(MetatreeInterface * iface,GtkTreeModel * model,gint no_division,gint new_division,gint new_sub_division)3361 void metatree_reset_transactions_without_div_sub_div ( MetatreeInterface *iface,
3362 GtkTreeModel *model,
3363 gint no_division,
3364 gint new_division,
3365 gint new_sub_division )
3366 {
3367 GSList *list_tmp;
3368
3369 /* move the transactions, need to to that for archived transactions too */
3370 list_tmp = gsb_data_transaction_get_complete_transactions_list ();
3371
3372 while ( list_tmp )
3373 {
3374 gint transaction_number_tmp;
3375
3376 transaction_number_tmp =
3377 gsb_data_transaction_get_transaction_number ( list_tmp -> data );
3378
3379 if ( iface -> transaction_div_id ( transaction_number_tmp ) == no_division )
3380 move_transaction_to_sub_division ( transaction_number_tmp, model,
3381 NULL, NULL,
3382 new_division, new_sub_division );
3383
3384 list_tmp = list_tmp -> next;
3385 }
3386 }
3387
3388
3389 /**
3390 *
3391 *
3392 *
3393 *
3394 * */
metatree_update_tree_view(MetatreeInterface * iface)3395 void metatree_update_tree_view ( MetatreeInterface *iface )
3396 {
3397 /* update value in the tree view */
3398 switch ( iface -> content )
3399 {
3400 case METATREE_PAYEE:
3401 transaction_list_update_element ( ELEMENT_PARTY );
3402 gsb_data_payee_update_counters ( );
3403 break;
3404 case METATREE_CATEGORY:
3405 transaction_list_update_element ( ELEMENT_CATEGORY );
3406 gsb_data_category_update_counters ();
3407 break;
3408 case METATREE_BUDGET:
3409 transaction_list_update_element ( ELEMENT_BUDGET );
3410 gsb_data_budget_update_counters ( );
3411 break;
3412 }
3413 }
3414
3415
3416 /**
3417 *
3418 *
3419 *
3420 *
3421 * */
metatree_get_nbre_transactions_sans_sub_div(GtkWidget * tree_view)3422 gint metatree_get_nbre_transactions_sans_sub_div ( GtkWidget *tree_view )
3423 {
3424 GtkTreeSelection *selection;
3425 GtkTreeModel *model;
3426 GtkTreeIter iter;
3427 gint nbre_trans_s_s_div = 0; /* nbre de transactions sans sous-division */
3428
3429 selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( tree_view ) );
3430 if ( selection && gtk_tree_selection_get_selected ( selection, &model, &iter ) )
3431 {
3432 gint no_division = 0;
3433 MetatreeInterface *iface;
3434
3435 gtk_tree_model_get ( model, &iter,
3436 META_TREE_NO_DIV_COLUMN, &no_division,
3437 -1 );
3438
3439 iface = g_object_get_data ( G_OBJECT ( model ), "metatree-interface" );
3440 nbre_trans_s_s_div = iface -> sub_div_nb_transactions ( no_division, 0 );
3441 }
3442
3443 return nbre_trans_s_s_div;
3444 }
3445
3446
3447 /**
3448 *
3449 *
3450 *
3451 *
3452 * */
metatree_get_combofix(MetatreeInterface * iface,gint division,gint sub_division,enum MetaTreeRowType type_division)3453 GtkWidget *metatree_get_combofix ( MetatreeInterface *iface,
3454 gint division,
3455 gint sub_division,
3456 enum MetaTreeRowType type_division )
3457 {
3458 GtkWidget *combofix;
3459 GSList *liste_combofix;
3460
3461 liste_combofix = metatree_get_combofix_list ( iface, division, sub_division, TRUE );
3462
3463 combofix = gtk_combofix_new ( liste_combofix, iface->content );
3464 g_object_set_data ( G_OBJECT ( combofix ), "list_1", liste_combofix );
3465
3466 liste_combofix = metatree_get_combofix_list ( iface, division, 0, FALSE );
3467 g_object_set_data ( G_OBJECT ( combofix ), "list_2", liste_combofix );
3468
3469 return combofix;
3470 }
3471
3472
metatree_get_combofix_list(MetatreeInterface * iface,gint division,gint sub_division,gboolean show_sub_division)3473 GSList *metatree_get_combofix_list ( MetatreeInterface *iface,
3474 gint division,
3475 gint sub_division,
3476 gboolean show_sub_division )
3477 {
3478 GSList *liste_combofix;
3479 GSList *division_list;
3480 GSList *liste_division_credit;
3481 GSList *liste_division_debit;
3482 gint show_division;
3483
3484 division_list = iface -> div_list ( );
3485 liste_combofix = NULL;
3486 liste_division_credit = NULL;
3487 liste_division_debit = NULL;
3488 show_division = g_slist_length ( iface -> div_sub_div_list ( division ) );
3489
3490 while ( division_list )
3491 {
3492 gint tmp_division;
3493 GSList *sub_division_list;
3494
3495 tmp_division = iface -> div_id ( division_list -> data );
3496
3497 /* if we are on the current division and no sub-( go to the next */
3498 if ( division && show_division == 0 && division == tmp_division )
3499 {
3500 division_list = division_list -> next;
3501 continue;
3502 }
3503
3504 /* get the division */
3505 switch ( iface -> div_type ( tmp_division ) )
3506 {
3507 case 1:
3508 liste_division_debit = g_slist_append ( liste_division_debit,
3509 my_strdup (iface -> div_name ( tmp_division ) ) );
3510 break;
3511 default:
3512 liste_division_credit = g_slist_append ( liste_division_credit,
3513 my_strdup (iface -> div_name ( tmp_division ) ) );
3514 break;
3515 }
3516
3517 sub_division_list = iface -> div_sub_div_list ( tmp_division );
3518
3519 if ( show_sub_division == 0 )
3520 {
3521 division_list = division_list -> next;
3522 continue;
3523 }
3524
3525 /* add the sub-divisions if necessary */
3526 while ( sub_division_list )
3527 {
3528 gint tmp_sub_division;
3529
3530 tmp_sub_division = iface -> sub_div_id (sub_division_list -> data);
3531 if ( division == tmp_division && tmp_sub_division == sub_division )
3532 {
3533 sub_division_list = sub_division_list -> next;
3534 continue;
3535 }
3536
3537 switch ( iface -> div_type (tmp_division))
3538 {
3539 case 1:
3540 liste_division_debit = g_slist_append ( liste_division_debit,
3541 g_strconcat ( "\t",
3542 iface -> sub_div_name ( tmp_division, tmp_sub_division ),
3543 NULL ) );
3544 break;
3545 case 0:
3546 liste_division_credit = g_slist_append ( liste_division_credit,
3547 g_strconcat ( "\t",
3548 iface -> sub_div_name ( tmp_division, tmp_sub_division ),
3549 NULL ) );
3550 break;
3551 default:
3552 break;
3553 }
3554
3555 sub_division_list = sub_division_list -> next;
3556 }
3557
3558 division_list = division_list -> next;
3559 }
3560
3561 /* create the combofix complex with the divisions and sub-divisions */
3562 liste_combofix = g_slist_append ( liste_combofix, liste_division_debit );
3563 liste_combofix = g_slist_append ( liste_combofix, liste_division_credit );
3564
3565 return liste_combofix;
3566 }
3567
3568
3569 /**
3570 *
3571 *
3572 *
3573 *
3574 * */
metatree_move_transactions_to_sub_div(MetatreeInterface * iface,GtkTreeModel * model,gint no_division,gint no_sub_division,gint new_division,gint new_sub_division)3575 void metatree_move_transactions_to_sub_div ( MetatreeInterface *iface,
3576 GtkTreeModel *model,
3577 gint no_division,
3578 gint no_sub_division,
3579 gint new_division,
3580 gint new_sub_division )
3581 {
3582 GSList *list_tmp;
3583
3584 /* move the transactions, need to to that for archived transactions too */
3585 list_tmp = gsb_data_transaction_get_complete_transactions_list ();
3586
3587 while ( list_tmp )
3588 {
3589 gint transaction_number_tmp;
3590
3591 transaction_number_tmp =
3592 gsb_data_transaction_get_transaction_number ( list_tmp -> data );
3593
3594 if ( iface -> transaction_div_id ( transaction_number_tmp ) == no_division
3595 &&
3596 iface -> transaction_sub_div_id ( transaction_number_tmp ) == no_sub_division )
3597 {
3598 /* Change parameters of the transaction */
3599 iface -> transaction_set_div_id ( transaction_number_tmp, new_division );
3600 iface -> transaction_set_sub_div_id ( transaction_number_tmp, new_sub_division );
3601 gsb_transactions_list_update_transaction ( transaction_number_tmp );
3602 }
3603
3604 list_tmp = list_tmp -> next;
3605 }
3606 }
3607
3608
metatree_move_sub_division_to_division(MetatreeInterface * iface,gint no_division,gint no_sub_division,gint new_division)3609 gint metatree_move_sub_division_to_division ( MetatreeInterface *iface,
3610 gint no_division,
3611 gint no_sub_division,
3612 gint new_division )
3613 {
3614 GSList *list_tmp;
3615 gint new_sub_division = 0;
3616
3617 /* create the new_sub_division */
3618 new_sub_division = iface -> add_sub_div ( new_division );
3619
3620 /* set name */
3621 metatree_sub_division_set_name ( iface,
3622 no_division, no_sub_division,
3623 new_division, new_sub_division );
3624
3625 /* remove old subdivision */
3626 iface -> remove_sub_div ( no_division, no_sub_division );
3627
3628 /* move the transactions, need to to that for archived transactions too */
3629 list_tmp = gsb_data_transaction_get_complete_transactions_list ();
3630
3631 while ( list_tmp )
3632 {
3633 gint transaction_number_tmp;
3634
3635 transaction_number_tmp =
3636 gsb_data_transaction_get_transaction_number ( list_tmp -> data );
3637
3638 if ( iface -> transaction_div_id ( transaction_number_tmp ) == no_division
3639 &&
3640 iface -> transaction_sub_div_id ( transaction_number_tmp ) == no_sub_division )
3641 {
3642 /* Change parameters of the transaction */
3643 iface -> transaction_set_div_id ( transaction_number_tmp, new_division );
3644 iface -> transaction_set_sub_div_id ( transaction_number_tmp, new_sub_division );
3645 gsb_transactions_list_update_transaction ( transaction_number_tmp );
3646 }
3647
3648 list_tmp = list_tmp -> next;
3649 }
3650
3651 return new_sub_division;
3652 }
3653
3654
3655 /**
3656 *
3657 *
3658 *
3659 *
3660 * */
metatree_create_division_from_sub_division(MetatreeInterface * iface,gint no_division,gint no_sub_division)3661 gint metatree_create_division_from_sub_division ( MetatreeInterface *iface,
3662 gint no_division,
3663 gint no_sub_division )
3664 {
3665 GSList *list_tmp;
3666 gint new_division = 0;
3667
3668 /* create the new_sub_division */
3669 new_division = iface -> add_div ( );
3670
3671 /* set name */
3672 metatree_division_set_name ( iface,
3673 no_division, no_sub_division,
3674 new_division );
3675
3676 /* remove old subdivision */
3677 iface -> remove_sub_div ( no_division, no_sub_division );
3678
3679 /* move the transactions, need to to that for archived transactions too */
3680 list_tmp = gsb_data_transaction_get_complete_transactions_list ();
3681
3682 while ( list_tmp )
3683 {
3684 gint transaction_number_tmp;
3685
3686 transaction_number_tmp =
3687 gsb_data_transaction_get_transaction_number ( list_tmp -> data );
3688
3689 if ( iface -> transaction_div_id ( transaction_number_tmp ) == no_division
3690 &&
3691 iface -> transaction_sub_div_id ( transaction_number_tmp ) == no_sub_division )
3692 {
3693 /* Change parameters of the transaction */
3694 iface -> transaction_set_div_id ( transaction_number_tmp, new_division );
3695 iface -> transaction_set_sub_div_id ( transaction_number_tmp, 0 );
3696 gsb_transactions_list_update_transaction ( transaction_number_tmp );
3697 }
3698
3699 list_tmp = list_tmp -> next;
3700 }
3701
3702 return new_division;
3703 }
3704
3705 /**
3706 *
3707 *
3708 *
3709 *
3710 * */
metatree_division_set_name(MetatreeInterface * iface,gint no_division,gint no_sub_division,gint new_division)3711 void metatree_division_set_name ( MetatreeInterface *iface,
3712 gint no_division,
3713 gint no_sub_division,
3714 gint new_division )
3715 {
3716 /* update value in the tree view */
3717 switch ( iface -> content )
3718 {
3719 case 1:
3720 gsb_data_category_set_name ( new_division,
3721 iface -> sub_div_name ( no_division, no_sub_division ) );
3722 break;
3723 case 2:
3724 gsb_data_budget_set_name ( new_division,
3725 iface -> sub_div_name ( no_division, no_sub_division ) );
3726 break;
3727 }
3728 }
3729
3730
3731 /**
3732 *
3733 *
3734 *
3735 *
3736 * */
metatree_sub_division_set_name(MetatreeInterface * iface,gint no_division,gint no_sub_division,gint new_division,gint new_sub_division)3737 void metatree_sub_division_set_name ( MetatreeInterface *iface,
3738 gint no_division,
3739 gint no_sub_division,
3740 gint new_division,
3741 gint new_sub_division )
3742 {
3743 /* update value in the tree view */
3744 switch ( iface -> content )
3745 {
3746 case 1:
3747 gsb_data_category_set_sub_category_name ( new_division,
3748 new_sub_division,
3749 iface -> sub_div_name ( no_division, no_sub_division ) );
3750 break;
3751 case 2:
3752 gsb_data_budget_set_sub_budget_name ( new_division,
3753 new_sub_division,
3754 iface -> sub_div_name ( no_division, no_sub_division ) );
3755 break;
3756 }
3757 }
3758
3759
3760 /**
3761 *
3762 *
3763 *
3764 *
3765 * \param iface
3766 * \param model
3767 * \param division the current (old) division number
3768 * \param sub_division the current (old) sub-division number
3769 * \param no_div a pointer to gint for the choice of division chosen by user
3770 * \param no_sub_div a pointer to gint for the choice of sub-division chosen by user
3771 *
3772 * \return FALSE to stop the process, TRUE to continue
3773 * no_div will contain the new division, no_sub_div the new sub-division
3774 * if no move of transactions, no_div and no_sub_div are set to 0
3775 * if move to another division but no sub-division, no_sub_div is set to 0
3776 * */
metatree_select_transactions_destination(MetatreeInterface * iface,GtkTreeModel * model,gint transaction_number,gint division,gint sub_division,gint * no_div,gint * no_sub_div)3777 static gboolean metatree_select_transactions_destination ( MetatreeInterface *iface,
3778 GtkTreeModel *model,
3779 gint transaction_number,
3780 gint division,
3781 gint sub_division,
3782 gint *no_div,
3783 gint *no_sub_div )
3784 {
3785 GtkWidget *dialog;
3786 GtkWidget *vbox;
3787 GtkWidget *hbox;
3788 GtkWidget *button_1;
3789 GtkWidget *button_2;
3790 GtkWidget *entry;
3791 GtkWidget *label;
3792 GtkWidget *combofix;
3793 gchar **split_division;
3794 gchar *hint;
3795 gchar *text;
3796 gchar *tmp_str_1;
3797 gchar *tmp_str_2;
3798 gint nouveau_no_division = 0;
3799 gint nouveau_no_sub_division = 0;
3800 gint resultat;
3801 gint number;
3802
3803 /* create the box to move change the division and sub-div of the transactions */
3804 hint = g_strdup_printf ( _("Select transactions in \"%s\"."),
3805 ( !sub_division ?
3806 iface -> div_name ( division ) :
3807 iface -> sub_div_name ( division, sub_division ) ) );
3808
3809 text = g_strdup_printf (
3810 _("You can transfer content from \"%s\" in another %s or %s.\n"),
3811 iface -> sub_div_name ( division, sub_division ),
3812 gettext ( iface -> meta_name_minus ),
3813 gettext ( iface -> meta_sub_name ) );
3814
3815 dialog = dialogue_special_no_run ( GTK_MESSAGE_INFO,
3816 GTK_BUTTONS_OK_CANCEL,
3817 text, hint );
3818
3819 gtk_widget_set_size_request ( dialog, -1, -1 );
3820
3821 g_free ( hint );
3822 g_free ( text );
3823
3824 number = gsb_data_transaction_get_party_number ( transaction_number );
3825 tmp_str_1 = g_strdup_printf ( _("Use payee: \"%s\" to find the transactions"),
3826 gsb_data_payee_get_name ( number, FALSE ) );
3827 button_1 = gsb_automem_checkbutton_new ( tmp_str_1,
3828 &metatree_find_payee,
3829 NULL,
3830 NULL );
3831
3832 g_free ( tmp_str_1 );
3833 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), button_1, FALSE, FALSE, 0 );
3834
3835 tmp_str_2 = g_strdup ( gsb_data_transaction_get_notes ( transaction_number ) );
3836 if ( tmp_str_2 )
3837 {
3838 tmp_str_1 = g_strdup_printf ( _("Use note: \"%s\" to find the transactions"), tmp_str_2 );
3839 button_2 = gsb_automem_checkbutton_new ( tmp_str_1,
3840 &metatree_find_notes,
3841 NULL,
3842 NULL );
3843
3844 g_free ( tmp_str_1 );
3845 g_free ( tmp_str_2 );
3846 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), button_2, FALSE, FALSE, 0 );
3847 }
3848
3849 /* create the list containing division and sub-division without the current division */
3850 hbox = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, MARGIN_BOX );
3851 gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), hbox, FALSE, FALSE, 0 );
3852
3853 label = gtk_label_new ( _("Select the destination: ") );
3854 utils_labels_set_alignment ( GTK_LABEL ( label ), 0, 0 );
3855 gtk_box_pack_start ( GTK_BOX ( hbox ), label, TRUE, TRUE, 0 );
3856
3857 vbox = gtk_box_new ( GTK_ORIENTATION_VERTICAL, 0 );
3858 gtk_box_pack_start ( GTK_BOX ( hbox ), vbox, TRUE, TRUE, 0 );
3859
3860 combofix = metatree_get_combofix ( iface, division, sub_division, META_TREE_TRANSACTION );
3861 gtk_combofix_set_force_text ( GTK_COMBOFIX ( combofix ), FALSE );
3862 gtk_box_pack_start ( GTK_BOX ( vbox ), combofix, TRUE, TRUE, 0 );
3863
3864 gtk_widget_show_all ( dialog );
3865 entry = gtk_combofix_get_entry (GTK_COMBOFIX (combofix));
3866 gtk_widget_grab_focus (entry);
3867 gtk_editable_set_position (GTK_EDITABLE (entry), 0);
3868
3869 resultat = gtk_dialog_run ( GTK_DIALOG ( dialog ) );
3870
3871 if ( resultat != GTK_RESPONSE_OK )
3872 {
3873 gtk_widget_destroy ( GTK_WIDGET ( dialog ) );
3874
3875 return FALSE;
3876 }
3877
3878 if ( metatree_find_payee == 0 && metatree_find_notes == 0 )
3879 {
3880 tmp_str_1 = g_strdup ( _("You must select at least one search element") );
3881 tmp_str_2 = g_strdup ( _("WARNING") );
3882
3883 dialogue_warning_hint ( tmp_str_1 , tmp_str_2 );
3884
3885 g_free ( tmp_str_1 );
3886 g_free ( tmp_str_2 );
3887
3888 gtk_widget_destroy (dialog);
3889
3890 return ( metatree_select_transactions_destination ( iface, model,
3891 transaction_number,
3892 division, sub_division,
3893 no_div, no_sub_div ) );
3894 }
3895
3896 /* we want to move the content */
3897 if ( !strlen ( gtk_combofix_get_text ( GTK_COMBOFIX ( combofix ) ) ) )
3898 {
3899 tmp_str_1 = g_strdup_printf (
3900 _("It is compulsory to specify a destination %s "
3901 "to move content but no %s was entered."),
3902 gettext ( iface -> meta_name_minus ),
3903 gettext ( iface -> meta_name_minus ) );
3904 tmp_str_2 = g_strdup_printf ( _("Please enter a %s!"), _(iface -> meta_name_minus) );
3905
3906 dialogue_warning_hint ( tmp_str_1 , tmp_str_2 );
3907
3908 g_free ( tmp_str_1 );
3909 g_free ( tmp_str_2 );
3910
3911 gtk_widget_destroy (dialog);
3912
3913 return ( metatree_select_transactions_destination ( iface, model,
3914 transaction_number,
3915 division, sub_division,
3916 no_div, no_sub_div ) );
3917 }
3918
3919 /* get the new (sub-)division */
3920 split_division = g_strsplit ( gtk_combofix_get_text ( GTK_COMBOFIX ( combofix ) ), " : ", 2 );
3921
3922 nouveau_no_division = iface -> get_div_pointer_from_name ( split_division[0], 0 );
3923
3924 if (nouveau_no_division)
3925 {
3926 nouveau_no_sub_division = iface -> get_sub_div_pointer_from_name (
3927 nouveau_no_division, split_division[1], 0 );
3928
3929 if ( split_division[1] && nouveau_no_sub_division == 0 )
3930 {
3931 tmp_str_1 = g_strdup_printf ( _("Warning you can not create %s."),
3932 _(iface -> meta_name_minus) );
3933 dialogue_warning( tmp_str_1 );
3934
3935 g_free ( tmp_str_1 );
3936
3937 gtk_widget_destroy ( dialog );
3938
3939 return ( metatree_select_transactions_destination ( iface, model,
3940 transaction_number,
3941 division, sub_division,
3942 no_div, no_sub_div ) );
3943 }
3944 }
3945
3946 g_strfreev ( split_division );
3947
3948 gtk_widget_destroy ( GTK_WIDGET ( dialog ) );
3949
3950 /* return the new number of division and sub-division
3951 * if don't want to move the transactions, 0 and 0 will be returned */
3952 if ( no_div)
3953 *no_div = nouveau_no_division;
3954 if ( no_sub_div )
3955 *no_sub_div = nouveau_no_sub_division;
3956
3957 return TRUE;
3958 }
3959
3960
3961 /**
3962 * cette fonction déplace les opérations de même modèle dans la nouvelle catégorie/sous catégorie
3963 *
3964 * \param tree_view
3965 *
3966 * \return
3967 *
3968 */
metatree_transfer_identical_transactions(GtkWidget * tree_view)3969 void metatree_transfer_identical_transactions ( GtkWidget *tree_view )
3970 {
3971 GtkTreeSelection *selection;
3972 GtkTreeModel *model;
3973 GtkTreeIter iter;
3974 GtkTreeIter parent;
3975 GtkTreeIter *it;
3976 GtkTreePath *path = NULL;
3977 GSList *list_tmp;
3978 gchar *tmp_str = NULL;
3979 gchar *search_str_1 = NULL;
3980 gchar *search_str_2 = NULL;
3981 gint no_division = 0;
3982 gint no_sub_division = 0;
3983 gint no_transaction = 0;
3984 gint new_division;
3985 gint new_sub_division;
3986 gint profondeur;
3987 MetatreeInterface *iface;
3988
3989 devel_debug (NULL);
3990
3991 selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( tree_view ) );
3992 if ( selection && gtk_tree_selection_get_selected ( selection, &model, &iter ) )
3993 {
3994 gtk_tree_model_get ( model,
3995 &iter,
3996 META_TREE_NO_TRANSACTION_COLUMN, &no_transaction,
3997 -1 );
3998 }
3999 else
4000 return;
4001
4002 if ( no_transaction <= 0 )
4003 return;
4004
4005 /* on détermine la division sous division à partir de la transaction */
4006 path = gtk_tree_model_get_path ( model, &iter );
4007 gtk_tree_path_up ( path );
4008 gtk_tree_model_iter_parent ( model, &parent, &iter );
4009 gtk_tree_model_get ( model,
4010 &parent,
4011 META_TREE_NO_DIV_COLUMN, &no_division,
4012 META_TREE_NO_SUB_DIV_COLUMN, &no_sub_division,
4013 -1 );
4014
4015 iface = g_object_get_data ( G_OBJECT ( model ), "metatree-interface" );
4016 if ( !metatree_select_transactions_destination ( iface, model, no_transaction, no_division, no_sub_division,
4017 &new_division, &new_sub_division ) )
4018 return;
4019
4020 /* move the transactions, need to to that for archived transactions too */
4021 list_tmp = gsb_data_transaction_get_complete_transactions_list ();
4022
4023 if ( metatree_find_payee )
4024 {
4025 tmp_str = g_strdup ( gsb_data_payee_get_name (
4026 gsb_data_transaction_get_party_number ( no_transaction ), TRUE ) );
4027 if ( tmp_str )
4028 search_str_1 = g_utf8_collate_key ( tmp_str, -1 );
4029 g_free ( tmp_str );
4030 }
4031
4032 if ( metatree_find_notes )
4033 {
4034 tmp_str = g_strdup ( gsb_data_transaction_get_notes ( no_transaction ) );
4035 if ( tmp_str )
4036 search_str_2 = g_utf8_collate_key ( tmp_str, -1 );
4037 g_free ( tmp_str );
4038 }
4039
4040 while ( list_tmp )
4041 {
4042 gint transaction_number_tmp;
4043
4044 transaction_number_tmp =
4045 gsb_data_transaction_get_transaction_number ( list_tmp -> data );
4046
4047 if ( iface -> transaction_div_id ( transaction_number_tmp ) == no_division
4048 &&
4049 iface -> transaction_sub_div_id ( transaction_number_tmp ) == no_sub_division )
4050 {
4051 gboolean trouve = FALSE;
4052
4053 if ( search_str_1 )
4054 {
4055 gchar *tmp_key = NULL;
4056
4057 tmp_str = g_strdup ( gsb_data_payee_get_name (
4058 gsb_data_transaction_get_party_number ( transaction_number_tmp ), TRUE ) );
4059
4060 if ( tmp_str )
4061 tmp_key = g_utf8_collate_key ( tmp_str, -1 );
4062
4063 if ( tmp_key )
4064 trouve = !strcmp ( tmp_key, search_str_1 );
4065 else
4066 trouve = FALSE;
4067
4068 g_free ( tmp_key );
4069 g_free ( tmp_str );
4070 }
4071 if ( search_str_2 )
4072 {
4073 gchar *tmp_key = NULL;
4074
4075 tmp_str = g_strdup ( gsb_data_transaction_get_notes ( transaction_number_tmp ) );
4076
4077 if ( tmp_str )
4078 tmp_key = g_utf8_collate_key ( tmp_str, -1 );
4079
4080 if ( tmp_key )
4081 trouve = !strcmp ( tmp_key, search_str_2 );
4082 else
4083 trouve = FALSE;
4084
4085 g_free ( tmp_key );
4086 g_free ( tmp_str );
4087 }
4088
4089 if ( trouve )
4090 {
4091 /* Change parameters of the transaction */
4092 iface -> transaction_set_div_id ( transaction_number_tmp, new_division );
4093 iface -> transaction_set_sub_div_id ( transaction_number_tmp, new_sub_division );
4094 gsb_transactions_list_update_transaction ( transaction_number_tmp );
4095 }
4096 }
4097
4098 list_tmp = list_tmp -> next;
4099 }
4100
4101 g_free ( search_str_1 );
4102 g_free ( search_str_2 );
4103
4104 /* met à jour le tree_view */
4105 metatree_update_tree_view ( iface );
4106
4107 /* restitue l'état du tree_view */
4108 /* old path */
4109 if ( iface -> content == 1 )
4110 path = categories_hold_position_get_path ( );
4111 else if ( iface -> content == 2 )
4112 path = budgetary_hold_position_get_path ( );
4113
4114 profondeur = gtk_tree_path_get_depth ( path );
4115 while ( profondeur > 1 )
4116 {
4117 gtk_tree_path_up ( path );
4118 profondeur = gtk_tree_path_get_depth ( path );
4119 }
4120 gtk_tree_view_expand_to_path ( GTK_TREE_VIEW ( tree_view ), path );
4121 gtk_tree_path_free ( path );
4122
4123 /* new path */
4124 it = get_iter_from_div ( model, new_division, 0 );
4125 if ( it )
4126 {
4127 path = gtk_tree_model_get_path ( model, it );
4128 gtk_tree_view_expand_to_path ( GTK_TREE_VIEW ( tree_view ), path );
4129 gtk_tree_path_free ( path );
4130 }
4131
4132 /* We did some modifications */
4133 gsb_file_set_modified ( TRUE );
4134 }
4135
4136
4137 /**
4138 *
4139 *
4140 * \param
4141 *
4142 * \return
4143 *
4144 */
4145 /* Local Variables: */
4146 /* c-basic-offset: 4 */
4147 /* End: */
4148