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, &current_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 			      &current_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, &current_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, &current_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