1 /* ************************************************************************** */
2 /*                                                                            */
3 /*     Copyright (C)    2000-2008 Cédric Auger (cedric@grisbi.org)            */
4 /*          2009-2010 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  * \file gsb_data_category.c
25  * work with the category structure, no GUI here
26  */
27 
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include "include.h"
34 #include <glib/gi18n.h>
35 
36 /*START_INCLUDE*/
37 #include "gsb_data_category.h"
38 #include "grisbi_win.h"
39 #include "meta_categories.h"
40 #include "gsb_category.h"
41 #include "gsb_data_account.h"
42 #include "gsb_data_scheduled.h"
43 #include "gsb_data_form.h"
44 #include "gsb_data_mix.h"
45 #include "gsb_data_transaction.h"
46 #include "gsb_form_widget.h"
47 #include "gsb_real.h"
48 #include "utils_str.h"
49 #include "erreur.h"
50 #include "structures.h"
51 /*END_INCLUDE*/
52 
53 /* struct Describe a category */
54 typedef struct _CategoryStruct		CategoryStruct;
55 
56 struct _CategoryStruct
57 {
58     /** @name category content */
59     gint category_number;
60     gchar *category_name;
61     gint category_type;		/**< 0:credit / 1:debit / 2:special (transfert, split...) */
62 
63     GSList *sub_category_list;
64 
65     /** @name gui category list content (not saved) */
66     gint category_nb_transactions;
67     gint category_nb_direct_transactions;
68     GsbReal category_balance;
69     GsbReal category_direct_balance;
70 };
71 
72 
73 /* struct Describe a sub-category */
74 typedef struct _SubCategoryStruct		SubCategoryStruct;
75 
76 struct _SubCategoryStruct
77 {
78     /** @name sub-category content */
79     gint sub_category_number;
80     gchar *sub_category_name;
81 
82     gint mother_category_number;
83 
84     /** @name gui sub-category list content (not saved)*/
85     gint sub_category_nb_transactions;
86     GsbReal sub_category_balance;
87 };
88 
89 
90 
91 /*START_STATIC*/
92 static void _gsb_data_category_free ( CategoryStruct *category );
93 static void _gsb_data_sub_category_free ( SubCategoryStruct *sub_category );
94 static GSList *gsb_data_category_append_sub_category_to_list ( GSList *list_category,
95 							GSList *sub_category_list );
96 static gint gsb_data_category_get_pointer_from_name_in_glist ( CategoryStruct *category,
97 							const gchar *name );
98 static gint gsb_data_category_get_pointer_from_sub_name_in_glist ( SubCategoryStruct *sub_category,
99 							    const gchar *name );
100 static gpointer gsb_data_category_get_structure_in_list ( gint no_category,
101                         GSList *list );
102 static gint gsb_data_category_max_number ( void );
103 static gint gsb_data_category_max_sub_category_number ( gint category_number );
104 static gint gsb_data_category_new ( const gchar *name );
105 static gint gsb_data_category_new_sub_category ( gint category_number,
106                         const gchar *name );
107 static void gsb_data_category_reset_counters ( void );
108 static gint gsb_data_sub_category_compare ( SubCategoryStruct * a, SubCategoryStruct * b );
109 /*END_STATIC*/
110 
111 /*START_EXTERN*/
112 /*END_EXTERN*/
113 
114 
115 /** contains the g_slist of CategoryStruct */
116 static GSList *category_list = NULL;
117 
118 /** a pointer to the last category used (to increase the speed) */
119 static CategoryStruct *category_buffer;
120 static SubCategoryStruct *sub_category_buffer;
121 
122 /** a empty category for the list of categories
123  * the number of the empty category is 0 */
124 static CategoryStruct *empty_category = NULL;
125 
126 
127 
128 /**
129  * set the categories global variables to NULL, usually when we init all the global variables
130  *
131  * \param none
132  *
133  * \return FALSE
134  * */
gsb_data_category_init_variables(gboolean cleanup)135 gboolean gsb_data_category_init_variables (gboolean cleanup)
136 {
137     /* free the memory used by the category list */
138     if ( category_list )
139     {
140 	    GSList* cat_tmp_list = category_list;
141 
142 		while ( cat_tmp_list )
143 	    {
144 			CategoryStruct *category;
145 
146 			category = cat_tmp_list -> data;
147 			cat_tmp_list = cat_tmp_list -> next;
148 			_gsb_data_category_free ( category );
149 	    }
150 	    g_slist_free (category_list);
151     }
152 
153 	if (cleanup)
154 	{
155 		category_list = NULL;
156 
157 		category_buffer = NULL;
158 		sub_category_buffer = NULL;
159 
160 		/* recreate the empty category */
161 		/* set an empty name for that empty categ, else every transaction
162 		 * without category will have that name */
163 		_gsb_data_category_free ( empty_category );
164 		empty_category = g_malloc0 ( sizeof ( CategoryStruct ));
165 		empty_category -> category_name = g_strdup(_("No category"));
166 	}
167 
168     return FALSE;
169 }
170 
171 
172 
173 /**
174  * find and return the structure of the category asked
175  *
176  * \param no_category number of category
177  *
178  * \return the adr of the struct of the category, empty_category or NULL if not exists
179  * */
gsb_data_category_get_structure(gint no_category)180 gpointer gsb_data_category_get_structure ( gint no_category )
181 {
182     if (!no_category)
183 	return empty_category;
184 
185     /* before checking all the categories, we check the category_buffer */
186 
187     if ( category_buffer
188 	 &&
189 	 category_buffer -> category_number == no_category )
190 	return category_buffer;
191 
192     return gsb_data_category_get_structure_in_list ( no_category,
193 						     category_list );
194 }
195 
196 
197 /**
198  * return the empty_category pointer
199  *
200  * \param
201  *
202  * \return a pointer to empty_category */
gsb_data_category_get_empty_category(void)203 gpointer gsb_data_category_get_empty_category ( void )
204 {
205     return gsb_data_category_get_structure (0);
206 }
207 
208 
209 
210 /**
211  * find and return the structure of the category in the list given in param
212  * don't use at this level the buffer because could be a bug for an imported list
213  * so for normal list, use always gsb_data_category_get_structure
214  *
215  * \param no_category number of category
216  * \param list the list of categories struct where we look for
217  *
218  * \return the adr of the struct of the category (NULL if doesn't exit)
219  * */
gsb_data_category_get_structure_in_list(gint no_category,GSList * list)220 gpointer gsb_data_category_get_structure_in_list ( gint no_category,
221                         GSList *list )
222 {
223     GSList *tmp;
224 
225     if (!no_category)
226 	return NULL;
227 
228     tmp = list;
229 
230     while ( tmp )
231     {
232 	CategoryStruct *category;
233 
234 	category = tmp -> data;
235 
236 	if ( category -> category_number == no_category )
237 	{
238 	    category_buffer = category;
239 	    return category;
240 	}
241 	tmp = tmp -> next;
242     }
243     return NULL;
244 }
245 
246 
247 
248 /**
249  * find and return the structure of the sub-category asked
250  *
251  * \param no_category number of category
252  * \param no_sub_category the number of the sub-category
253  *
254  * \return the adr of the struct of the sub-category (NULL if doesn't exit)
255  * */
gsb_data_category_get_sub_category_structure(gint no_category,gint no_sub_category)256 gpointer gsb_data_category_get_sub_category_structure ( gint no_category,
257                         gint no_sub_category )
258 {
259     GSList *tmp;
260     CategoryStruct *category;
261 
262     /* check empty sub-categ */
263     if (!no_sub_category)
264 	return NULL;
265 
266     /* before checking all the categories, we check the buffer */
267     if ( sub_category_buffer
268 	 &&
269 	 sub_category_buffer -> mother_category_number == no_category
270 	 &&
271 	 sub_category_buffer -> sub_category_number == no_sub_category )
272 	return sub_category_buffer;
273 
274     category = gsb_data_category_get_structure ( no_category );
275     if ( ! category )
276 	return NULL;
277 
278     tmp = category -> sub_category_list;
279 
280     while ( tmp )
281     {
282 	SubCategoryStruct *sub_category;
283 
284 	sub_category = tmp -> data;
285 
286 	if ( sub_category -> sub_category_number == no_sub_category )
287 	{
288 	    sub_category_buffer = sub_category;
289 	    return sub_category;
290 	}
291 	tmp = tmp -> next;
292     }
293     return NULL;
294 }
295 
296 
297 /**
298  * give the g_slist of categories structure
299  * usefull when want to check all categories
300  *
301  * \param none
302  *
303  * \return the g_slist of categories structure
304  * */
gsb_data_category_get_categories_list(void)305 GSList *gsb_data_category_get_categories_list ( void )
306 {
307     return category_list;
308 }
309 
310 
311 /**
312  * return the g_slist of the sub-categories of the category
313  *
314  * \param no_category the number of the category
315  *
316  * \return a g_slist of the struct of the sub-categories or NULL if problem
317  * */
gsb_data_category_get_sub_category_list(gint no_category)318 GSList *gsb_data_category_get_sub_category_list ( gint no_category )
319 {
320     CategoryStruct *category;
321 
322     category = gsb_data_category_get_structure ( no_category );
323 
324     if (!category)
325 	return 0;
326 
327     return category -> sub_category_list;
328 }
329 
330 
331 
332 /**
333  * return the number of the categories given in param
334  *
335  * \param category_ptr a pointer to the struct of the category
336  *
337  * \return the number of the category, 0 if problem
338  * */
gsb_data_category_get_no_category(gpointer category_ptr)339 gint gsb_data_category_get_no_category ( gpointer category_ptr )
340 {
341     CategoryStruct *category;
342 
343     if ( !category_ptr )
344 	return 0;
345 
346     category = category_ptr;
347     category_buffer = category;
348     return category -> category_number;
349 }
350 
351 
352 /**
353  * return the number of the sub-category given in param
354  *
355  * \param sub_category_ptr a pointer to the struct of the sub-category
356  *
357  * \return the number of the category, 0 if problem
358  * */
gsb_data_category_get_no_sub_category(gpointer sub_category_ptr)359 gint gsb_data_category_get_no_sub_category ( gpointer sub_category_ptr )
360 {
361     SubCategoryStruct *sub_category;
362 
363     /* if sub_category_ptr is NULL, we are on empty sub-category, the number is 0 */
364     if ( !sub_category_ptr )
365 	return 0;
366 
367     sub_category = sub_category_ptr;
368     sub_category_buffer = sub_category;
369     return sub_category -> sub_category_number;
370 }
371 
372 
373 
374 /** find and return the last number of category
375  * \param none
376  * \return last number of category
377  * */
gsb_data_category_max_number(void)378 gint gsb_data_category_max_number ( void )
379 {
380     GSList *tmp;
381     gint number_tmp = 0;
382 
383     tmp = category_list;
384 
385     while ( tmp )
386     {
387 	CategoryStruct *category;
388 
389 	category = tmp -> data;
390 
391 	if ( category -> category_number > number_tmp )
392 	    number_tmp = category -> category_number;
393 
394 	tmp = tmp -> next;
395     }
396     return number_tmp;
397 }
398 
399 
400 /**
401  * find and return the last number of the sub-categories
402  *
403  * \param
404  *
405  * \return last number of the sub-categories
406  * */
gsb_data_category_max_sub_category_number(gint category_number)407 gint gsb_data_category_max_sub_category_number ( gint category_number )
408 {
409     CategoryStruct *category;
410     GSList *tmp;
411     gint number_tmp = 0;
412 
413     category = gsb_data_category_get_structure ( category_number );
414     if (!category)
415 	return 0;
416 
417     tmp = category -> sub_category_list;
418 
419     while ( tmp )
420     {
421 	SubCategoryStruct *sub_category;
422 
423 	sub_category = tmp -> data;
424 
425 	if ( sub_category -> sub_category_number > number_tmp )
426 	    number_tmp = sub_category -> sub_category_number;
427 
428 	tmp = tmp -> next;
429     }
430     return number_tmp;
431 }
432 
433 
434 
435 /**
436  * create a new category, give it a number, append it to the list
437  * and return the number
438  * update combofix and mark file as modified
439  *
440  * \param name the name of the category (can be freed after, it's a copy) or NULL
441  *
442  * \return the number of the new category
443  * */
gsb_data_category_new(const gchar * name)444 gint gsb_data_category_new ( const gchar *name )
445 {
446     gint category_number;
447 
448     /* create the new category with a new number */
449 
450     category_number = gsb_data_category_new_with_number ( gsb_data_category_max_number () + 1 );
451 
452     /* append the name if necessary */
453 
454     if (name)
455 	gsb_data_category_set_name ( category_number,
456 				     name );
457     return category_number;
458 }
459 
460 
461 /**
462  * create a new category with a number, append it to the list
463  * and return the number
464  *
465  *
466  * \param number the number we want to give to that category
467  *
468  * \return the number of the new category
469  * */
gsb_data_category_new_with_number(gint number)470 gint gsb_data_category_new_with_number ( gint number )
471 {
472     CategoryStruct *category;
473 
474     category = g_malloc0 ( sizeof ( CategoryStruct ));
475     category -> category_number = number;
476 
477     category_list = g_slist_append ( category_list,
478 				     category );
479 
480     category_buffer = category;
481 
482     return category -> category_number;
483 }
484 
485 
486 
487 /**
488  * remove a category
489  * set all the categories of transaction which are this one to 0
490  * update combofix and mark file as modified
491  *
492  * \param no_category the category we want to remove
493  *
494  * \return TRUE ok
495  * */
gsb_data_category_remove(gint no_category)496 gboolean gsb_data_category_remove ( gint no_category )
497 {
498     CategoryStruct *category;
499 	GtkWidget *combofix;
500 
501     category = gsb_data_category_get_structure ( no_category );
502 
503     if (!category)
504 	return FALSE;
505 
506     category_list = g_slist_remove ( category_list,
507 				     category );
508 
509     _gsb_data_category_free (category);
510 
511 	combofix = gsb_form_widget_get_widget (TRANSACTION_FORM_CATEGORY);
512 	if ( combofix )
513 		gsb_category_update_combofix ( TRUE );
514 
515     return TRUE;
516 }
517 
518 /**
519  * This function is called to free the memory used by a category structure
520  */
_gsb_data_category_free(CategoryStruct * category)521 void _gsb_data_category_free ( CategoryStruct *category )
522 {
523     if ( ! category )
524         return;
525     /* free memory used by sub categories */
526     if ( category -> sub_category_list )
527     {
528         GSList* sub_tmp_list = category -> sub_category_list;
529         while ( sub_tmp_list )
530         {
531             SubCategoryStruct *sub_category;
532             sub_category = sub_tmp_list -> data;
533             sub_tmp_list = sub_tmp_list -> next;
534             _gsb_data_sub_category_free ( sub_category );
535         }
536         g_slist_free ( category -> sub_category_list );
537     }
538     if ( category -> category_name )
539         g_free ( category -> category_name );
540     g_free ( category );
541     if ( category_buffer == category )
542 	category_buffer = NULL;
543 }
544 
545 
546 /**
547  * This function is called to free the memory used by a sub category structure
548  */
_gsb_data_sub_category_free(SubCategoryStruct * sub_category)549 void _gsb_data_sub_category_free ( SubCategoryStruct *sub_category )
550 {
551     if ( ! sub_category )
552         return;
553     if ( sub_category -> sub_category_name )
554         g_free ( sub_category -> sub_category_name );
555     g_free ( sub_category );
556     if ( sub_category_buffer == sub_category )
557 	sub_category_buffer = NULL;
558 }
559 
560 
561 /**
562  * remove a sub-category from a category
563  * set all the categories of transaction which are this one to 0
564  * update combofix and mark file as modified
565  *
566  * \param no_category the category we want to remove
567  *
568  * \return TRUE ok
569  * */
gsb_data_category_sub_category_remove(gint no_category,gint no_sub_category)570 gboolean gsb_data_category_sub_category_remove ( gint no_category,
571                         gint no_sub_category )
572 {
573     CategoryStruct *category;
574     SubCategoryStruct *sub_category;
575 	GtkWidget *combofix;
576 
577     category = gsb_data_category_get_structure ( no_category );
578     sub_category = gsb_data_category_get_sub_category_structure ( no_category,
579 								  no_sub_category );
580 
581     if (!category
582 	||
583 	!sub_category)
584 	return FALSE;
585 
586     category -> sub_category_list = g_slist_remove ( category -> sub_category_list,
587 						     sub_category );
588 
589     _gsb_data_sub_category_free (sub_category);
590 
591 	combofix = gsb_form_widget_get_widget (TRANSACTION_FORM_CATEGORY);
592 	if ( combofix )
593 		gsb_category_update_combofix ( TRUE );
594 
595     return TRUE;
596 }
597 
598 
599 /**
600  * create a new sub-category, append it to the list
601  * and return the new number
602  *
603  * \param category_number the number of the mother
604  * \param name the name of the sub-category
605  *
606  * \return the number of the new sub-category or 0 if problem
607  * */
gsb_data_category_new_sub_category(gint category_number,const gchar * name)608 gint gsb_data_category_new_sub_category ( gint category_number,
609                         const gchar *name )
610 {
611     gint sub_category_number;
612 
613     sub_category_number = gsb_data_category_new_sub_category_with_number_and_name ( gsb_data_category_max_sub_category_number (category_number) + 1,
614 																				   category_number,
615                                                                                    name );
616 
617     return sub_category_number;
618 }
619 
620 /**
621  * compare the name of two sub-categories
622  * */
gsb_sub_category_cmp(gconstpointer a,gconstpointer b)623 static gint gsb_sub_category_cmp(gconstpointer a,
624                                  gconstpointer b)
625 {
626     const SubCategoryStruct *elt1 = a;
627     const SubCategoryStruct *elt2 = b;
628     return strcmp(elt1 -> sub_category_name, elt2 -> sub_category_name);
629 }
630 
631 /**
632  * create a new sub-category with a number, append it to the list
633  * and return the number
634  *
635  * \param number the number we want to give to that sub-category
636  * \param category_number the number of the mother
637  *
638  * \return the number of the new sub-category or 0 if problem
639  * */
gsb_data_category_new_sub_category_with_number_and_name(gint number,gint category_number,const gchar * name)640 gint gsb_data_category_new_sub_category_with_number_and_name ( gint number,
641                         gint category_number,
642                         const gchar * name)
643 {
644     CategoryStruct *category;
645     SubCategoryStruct *sub_category;
646 
647     category = gsb_data_category_get_structure ( category_number );
648 
649     if (!category)
650 	return 0;
651 
652     sub_category = g_malloc0 ( sizeof (SubCategoryStruct));
653     sub_category -> sub_category_number = number;
654     sub_category -> mother_category_number = category_number;
655 	if (name)
656 		sub_category -> sub_category_name = strdup(name);
657 
658     category -> sub_category_list = g_slist_insert_sorted ( category -> sub_category_list,
659                             sub_category,
660                             gsb_sub_category_cmp);
661 
662     sub_category_buffer = sub_category;
663 
664     return sub_category -> sub_category_number;
665 }
666 
667 
668 /**
669  * get a string like 'category : sub-category', a transaction number
670  * and fill the transaction with the category and sub-category
671  * if the category or sub-category doesn't exist, create them
672  *
673  * \param transaction_number
674  * \param string
675  * \param is_transaction TRUE if it's for a transaction, FALSE for a scheduled transaction
676  *
677  * \return TRUE ok, FALSE if fail
678  * */
gsb_data_category_fill_transaction_by_string(gint transaction_number,const gchar * string,gboolean is_transaction)679 gboolean gsb_data_category_fill_transaction_by_string ( gint transaction_number,
680                         const gchar *string,
681                         gboolean is_transaction )
682 {
683     gchar **tab_char;
684     gint category_number = 0;
685 
686     if (!string
687 	||
688 	!strlen (string))
689     {
690         /* no string so set no category */
691         gsb_data_mix_set_category_number ( transaction_number,
692                             0,
693                             is_transaction );
694         gsb_data_mix_set_sub_category_number ( transaction_number,
695                             0,
696                             is_transaction );
697 	    return TRUE;
698     }
699 
700     tab_char = g_strsplit ( string, " : ", 2 );
701     if (tab_char[0])
702     {
703         category_number = gsb_data_category_get_number_by_name ( tab_char[0],
704                             !etat.combofix_force_category,
705                             gsb_data_mix_get_amount (
706                             transaction_number, is_transaction).mantissa <0 );
707 	    gsb_data_mix_set_category_number ( transaction_number,
708                             category_number,
709                             is_transaction );
710     }
711 
712     if ( tab_char[1] && category_number )
713     {
714         gsb_data_mix_set_sub_category_number ( transaction_number,
715 					        gsb_data_category_get_sub_category_number_by_name ( category_number,
716 																			   tab_char[1],
717 																			   !etat.combofix_force_category ),
718 					        is_transaction );
719     }
720     else
721         gsb_data_mix_set_sub_category_number ( transaction_number, 0, is_transaction );
722 
723     g_strfreev (tab_char);
724 
725     return TRUE;
726 }
727 
728 /**
729  * return the number of the category which has the name in param
730  * create it if necessary
731  *
732  * \param name the name of the category
733  * \param create TRUE if we want to create it if it doen't exist
734  * \param category_type the type of the category if we create it
735  * 0:credit / 1:debit / 2:special (transfert, split...) *
736  * \return the number of the category or 0 if problem
737  * */
gsb_data_category_get_number_by_name(const gchar * name,gboolean create,gint category_type)738 gint gsb_data_category_get_number_by_name ( const gchar *name,
739                         gboolean create,
740 					    gint category_type )
741 {
742     GSList *list_tmp;
743     gint category_number = 0;
744 
745     list_tmp = g_slist_find_custom ( category_list,
746 				     name,
747 				     (GCompareFunc) gsb_data_category_get_pointer_from_name_in_glist );
748 
749     if ( list_tmp )
750     {
751 	CategoryStruct *category;
752 
753 	category = list_tmp -> data;
754 	category_number = category -> category_number;
755     }
756     else
757     {
758 	if (create)
759 	{
760 	    category_number = gsb_data_category_new (name);
761 	    gsb_data_category_set_type ( category_number, category_type );
762 	    gsb_category_update_combofix ( FALSE );
763 	}
764     }
765     return category_number;
766 }
767 
768 
769 
770 /**
771  * return the number of the sub-category which has the name in param
772  * create it if necessary
773  *
774  * \param category_number the number of the category
775  * \param name the name of the sub-category
776  * \param create TRUE if we want to create it if it doen't exist
777  *
778  * \return the number of the sub-category or 0 if problem
779  * */
gsb_data_category_get_sub_category_number_by_name(gint category_number,const gchar * name,gboolean create)780 gint gsb_data_category_get_sub_category_number_by_name ( gint category_number,
781 							 const gchar *name,
782 							 gboolean create )
783 {
784     GSList *list_tmp;
785     CategoryStruct *category;
786     gint sub_category_number = 0;
787 
788     category = gsb_data_category_get_structure ( category_number );
789 
790     if (!category)
791 	return 0;
792 
793     list_tmp = g_slist_find_custom ( category -> sub_category_list,
794 				     name,
795 				     (GCompareFunc) gsb_data_category_get_pointer_from_sub_name_in_glist );
796 
797     if ( list_tmp )
798     {
799 	SubCategoryStruct *sub_category;
800 
801 	sub_category = list_tmp -> data;
802 	sub_category_number = sub_category -> sub_category_number;
803     }
804     else
805     {
806 	if (create)
807 	{
808 	    sub_category_number = gsb_data_category_new_sub_category ( category_number,
809 								       name);
810 	    gsb_category_update_combofix ( FALSE );
811 	}
812     }
813     return sub_category_number;
814 }
815 
816 
817 
818 
819 /**
820  * used with g_slist_find_custom to find a category in the g_list
821  * by his name
822  *
823  * \param category the struct of the current category checked
824  * \param name the name we are looking for
825  *
826  * \return 0 if it's the same name
827  * */
gsb_data_category_get_pointer_from_name_in_glist(CategoryStruct * category,const gchar * name)828 gint gsb_data_category_get_pointer_from_name_in_glist ( CategoryStruct *category,
829 							const gchar *name )
830 {
831     return ( my_strcasecmp ( category -> category_name, name ));
832 }
833 
834 
835 /**
836  * used with g_slist_find_custom to find a sub-category in the g_list
837  * by his name
838  *
839  * \param sub_category the struct of the current sub_category checked
840  * \param name the name we are looking for
841  *
842  * \return 0 if it's the same name
843  * */
gsb_data_category_get_pointer_from_sub_name_in_glist(SubCategoryStruct * sub_category,const gchar * name)844 gint gsb_data_category_get_pointer_from_sub_name_in_glist ( SubCategoryStruct *sub_category,
845 							    const gchar *name )
846 {
847     if ( !sub_category -> sub_category_name
848 	 ||
849 	 !name )
850 	return 1;
851     return ( my_strcasecmp ( sub_category -> sub_category_name, name ) );
852 }
853 
854 
855 /**
856  * return the name of the category
857  * and the full name (ie category : sub-category if no_sub_category is given)
858  *
859  * \param no_category the number of the category
860  * \param no_sub_category if we want the full name of the category
861  * \param return_value_error if problem, the value we return
862  *
863  * \return the name of the category, category : sub-category or NULL/No category if problem
864  * 		the returned value need to be freed after use
865  * */
gsb_data_category_get_name(gint no_category,gint no_sub_category,const gchar * return_value_error)866 gchar *gsb_data_category_get_name ( gint no_category,
867 				    gint no_sub_category,
868 				    const gchar *return_value_error )
869 {
870     CategoryStruct *category;
871     gchar *return_value;
872 
873     category = gsb_data_category_get_structure ( no_category );
874 
875     if (!category || !no_category)
876     {
877         if ( return_value_error == NULL )
878             return NULL;
879         else
880 	        return my_strdup ( return_value_error );
881     }
882 
883     return_value = my_strdup ( category -> category_name );
884 
885     if ( no_sub_category )
886     {
887         SubCategoryStruct *sub_category;
888 
889         sub_category = gsb_data_category_get_sub_category_structure ( no_category,
890                                           no_sub_category );
891 
892         if ( sub_category )
893         {
894             gchar *tmp = return_value;
895             return_value = g_strconcat ( tmp,
896                          " : ",
897                          sub_category -> sub_category_name,
898                          NULL );
899             g_free ( tmp );
900         }
901     }
902     return return_value;
903 }
904 
905 
906 /**
907  * set the name of the category
908  * the value is dupplicate in memory
909  *
910  * \param no_category the number of the category
911  * \param name the name of the category
912  *
913  * \return TRUE if ok or FALSE if problem
914  * */
gsb_data_category_set_name(gint no_category,const gchar * name)915 gboolean gsb_data_category_set_name ( gint no_category,
916                         const gchar *name )
917 {
918     CategoryStruct *category;
919 
920     category = gsb_data_category_get_structure ( no_category );
921 
922     if ( !category )
923         return FALSE;
924 
925 
926     /* we free the last name */
927     if ( category -> category_name )
928         g_free ( category -> category_name );
929 
930     /* and copy the new one */
931     if ( name )
932     {
933         GtkWidget *combofix;
934 
935         category -> category_name = my_strdup ( name );
936         combofix = gsb_form_widget_get_widget ( TRANSACTION_FORM_CATEGORY);
937         if ( combofix )
938             gsb_category_update_combofix ( TRUE );
939     }
940     else
941         category -> category_name = NULL;
942 
943     return TRUE;
944 }
945 
946 /**
947  * return the name of the sub-category
948  *
949  * \param no_category the number of the category
950  * \param no_sub_category the number of the sub-category
951  * \param return_value_error if problem, return that value
952  *
953  * \return a newly allocated string with the name of the category
954  * 		or return_value_error to be freed too
955  * */
gsb_data_category_get_sub_category_name(gint no_category,gint no_sub_category,const gchar * return_value_error)956 gchar *gsb_data_category_get_sub_category_name ( gint no_category,
957 						 gint no_sub_category,
958 						 const gchar *return_value_error )
959 {
960     SubCategoryStruct *sub_category;
961 
962     sub_category = gsb_data_category_get_sub_category_structure ( no_category,
963 								  no_sub_category );
964 
965     if (!sub_category)
966 	return (my_strdup (return_value_error));
967 
968     return my_strdup (sub_category -> sub_category_name);
969 }
970 
971 
972 /**
973  * set the name of the sub-category
974  * the value is dupplicate in memory
975  *
976  * \param no_category the number of the category
977  * \param no_sub_category the number of the sub-category
978  * \param name the name of the sub-category
979  *
980  * \return TRUE if ok or FALSE if problem
981  * */
gsb_data_category_set_sub_category_name(gint no_category,gint no_sub_category,const gchar * name)982 gboolean gsb_data_category_set_sub_category_name ( gint no_category,
983 						   gint no_sub_category,
984 						   const gchar *name )
985 {
986     SubCategoryStruct *sub_category;
987 
988     sub_category = gsb_data_category_get_sub_category_structure ( no_category,
989 								  no_sub_category );
990 
991     if ( !sub_category )
992         return FALSE;
993 
994     /* we free the last name */
995 
996     if ( sub_category -> sub_category_name )
997 	g_free (sub_category -> sub_category_name);
998 
999     /* and copy the new one */
1000     if ( name )
1001     {
1002         GtkWidget *combofix;
1003 
1004         sub_category -> sub_category_name = my_strdup ( name );
1005         combofix = gsb_form_widget_get_widget ( TRANSACTION_FORM_CATEGORY);
1006         if ( combofix )
1007             gsb_category_update_combofix ( TRUE );
1008     }
1009     else
1010         sub_category -> sub_category_name = NULL;
1011 
1012     return TRUE;
1013 }
1014 
1015 
1016 /**
1017  * return a g_slist of g_slist of names of the categories
1018  *
1019  * \param set_debit TRUE if we want to have the debits
1020  * \param set_credit TRUE if we want to have the credits
1021  * \param set_special TRUE if we want to have the specials
1022  * \param set_split TRUE if we want to add the split to the specials category
1023  *
1024  * \return a g_slist of g_slist of gchar *
1025  * */
gsb_data_category_get_name_list(gboolean set_debit,gboolean set_credit,gboolean set_special,gboolean set_split)1026 GSList *gsb_data_category_get_name_list ( gboolean set_debit,
1027 					  gboolean set_credit,
1028 					  gboolean set_special,
1029 					  gboolean set_split )
1030 {
1031     GSList *return_list;
1032     GSList *tmp_list;
1033     GSList *debit_list = NULL;
1034     GSList *credit_list = NULL;
1035 
1036     return_list = NULL;
1037 
1038     /* fill debit_list and/or credit_list and them sub-categories */
1039     tmp_list = category_list;
1040 
1041     while ( tmp_list )
1042     {
1043 	CategoryStruct *category;
1044 
1045 	category = tmp_list -> data;
1046 
1047 	if ( category -> category_type )
1048 	{
1049 	    if ( set_debit )
1050 	    {
1051 		debit_list = g_slist_append ( debit_list, g_strdup ( category -> category_name ) );
1052 		debit_list = gsb_data_category_append_sub_category_to_list ( debit_list,
1053 									     category -> sub_category_list);
1054 	    }
1055 	}
1056 	else
1057 	{
1058 	    if ( set_credit )
1059 	    {
1060 		credit_list = g_slist_append ( credit_list, g_strdup ( category -> category_name ) );
1061 		credit_list = gsb_data_category_append_sub_category_to_list ( credit_list,
1062 									      category -> sub_category_list);
1063 	    }
1064 	}
1065 	tmp_list = tmp_list -> next;
1066     }
1067 
1068     /* append what we need to return_list */
1069 
1070     if ( set_debit )
1071 	return_list = g_slist_append ( return_list,
1072 				       debit_list );
1073     if ( set_credit )
1074 	return_list = g_slist_append ( return_list,
1075 				       credit_list );
1076 
1077     /* append the specials list if needed */
1078 
1079     if (set_special)
1080     {
1081 	GSList *special_list = NULL;
1082 
1083 	if (set_split)
1084 	    special_list = g_slist_append ( special_list, g_strdup ( _("Split of transaction") ) );
1085 	special_list = g_slist_append ( special_list, g_strdup ( _("Transfer") ) );
1086 
1087 	/* append the accounts name with a tab at the beginning */
1088 
1089 	tmp_list= gsb_data_account_get_list_accounts ();
1090 
1091 	while ( tmp_list )
1092 	{
1093 	    gint i;
1094 
1095 	    i = gsb_data_account_get_no_account ( tmp_list -> data );
1096 	    if ( ! gsb_data_account_get_closed_account (i) )
1097 		special_list = g_slist_append ( special_list,
1098 						g_strconcat ( "\t",
1099 							      gsb_data_account_get_name (i),
1100 							      NULL ));
1101 	    tmp_list = tmp_list -> next;
1102 	}
1103 	return_list = g_slist_append ( return_list,
1104 				       special_list );
1105     }
1106     return return_list;
1107 }
1108 
1109 
1110 /**
1111  * free the memory used by gsb_data_category_get_name_list
1112  *
1113  * \param liste
1114  *
1115  * \return
1116  */
gsb_data_categorie_free_name_list(GSList * liste)1117 void gsb_data_categorie_free_name_list ( GSList *liste )
1118 {
1119     gint nbre_list;
1120     gint i;
1121 
1122     nbre_list = g_slist_length ( liste );
1123     for ( i = 0; i < nbre_list; i++ )
1124     {
1125         GSList *tmp_list;
1126 
1127 		tmp_list = liste->data;
1128 		liste = liste->next;
1129 
1130 		g_slist_free_full (g_steal_pointer (&tmp_list), (GDestroyNotify) g_free);
1131     }
1132 
1133 	g_slist_free (g_steal_pointer (&liste));
1134 }
1135 
1136 
1137 
1138 /**
1139  * append the sub-categories name with a tab at the beginning
1140  * to the list of categories given in param
1141  *
1142  * \param category_list a g_slist of categories names
1143  * \param sub_category_list a g_slist which contains the sub categories to append
1144  *
1145  * \return the new category_list (normally shouldn't changed
1146  * */
gsb_data_category_append_sub_category_to_list(GSList * list_category,GSList * sub_category_list)1147 GSList *gsb_data_category_append_sub_category_to_list ( GSList *list_category,
1148 							GSList *sub_category_list )
1149 {
1150     GSList *tmp_list;
1151 
1152     if (!sub_category_list)
1153 		return list_category;
1154 
1155     tmp_list = sub_category_list;
1156 
1157     while (tmp_list)
1158     {
1159 	SubCategoryStruct *sub_category;
1160 
1161 	sub_category = tmp_list -> data;
1162 
1163 	list_category = g_slist_append (list_category,
1164 					 g_strconcat ( "\t",
1165 						       sub_category -> sub_category_name,
1166 						       NULL ));
1167 	tmp_list = tmp_list -> next;
1168     }
1169     return list_category;
1170 }
1171 
1172 
1173 
1174 
1175 /**
1176  * return the type of the category
1177  * 0:credit / 1:debit / 2:special (transfert, split...)
1178  *
1179  * \param no_category the number of the category
1180  * \param can_return_null if problem, return NULL if TRUE or "No category" if FALSE
1181  *
1182  * \return the name of the category or NULL/No category if problem
1183  * */
gsb_data_category_get_type(gint no_category)1184 gint gsb_data_category_get_type ( gint no_category )
1185 {
1186     CategoryStruct *category;
1187 
1188     category = gsb_data_category_get_structure ( no_category );
1189 
1190     if (!category)
1191 	return 0;
1192 
1193     return category -> category_type;
1194 }
1195 
1196 
1197 /**
1198  * set the type of the category
1199  * 0:credit / 1:debit / 2:special (transfert, split...)
1200  *
1201  * \param no_category the number of the category
1202  * \param name the name of the category
1203  *
1204  * \return TRUE if ok or FALSE if problem
1205  * */
gsb_data_category_set_type(gint no_category,gint category_type)1206 gboolean gsb_data_category_set_type ( gint no_category,
1207 				      gint category_type )
1208 {
1209     CategoryStruct *category;
1210 
1211     category = gsb_data_category_get_structure ( no_category );
1212 
1213     if (!category)
1214 	return FALSE;
1215 
1216     category -> category_type = category_type;
1217     return TRUE;
1218 }
1219 
1220 
1221 /**
1222  * return nb_transactions of the category
1223  *
1224  * \param no_category the number of the category
1225  *
1226  * \return nb_transactions of the category or 0 if problem
1227  * */
gsb_data_category_get_nb_transactions(gint no_category)1228 gint gsb_data_category_get_nb_transactions ( gint no_category )
1229 {
1230     CategoryStruct *category;
1231 
1232     category = gsb_data_category_get_structure ( no_category );
1233 
1234     if (!category)
1235 	return 0;
1236 
1237     return category -> category_nb_transactions;
1238 }
1239 
1240 
1241 
1242 /**
1243  * return nb_transactions of the sub-category
1244  *
1245  * \param no_category the number of the category
1246  * \param no_sub_category the number of the sub-category
1247  *
1248  * \return nb_transactions of the sub-category or 0 if problem
1249  * */
gsb_data_category_get_sub_category_nb_transactions(gint no_category,gint no_sub_category)1250 gint gsb_data_category_get_sub_category_nb_transactions ( gint no_category,
1251 							  gint no_sub_category )
1252 {
1253     SubCategoryStruct *sub_category;
1254 
1255     sub_category = gsb_data_category_get_sub_category_structure ( no_category,
1256 								  no_sub_category );
1257 
1258     if (!sub_category)
1259 	return 0;
1260 
1261     return sub_category -> sub_category_nb_transactions;
1262 }
1263 
1264 
1265 
1266 /**
1267  * return nb_direct_transactions of the category
1268  *
1269  * \param no_category the number of the category
1270  *
1271  * \return nb_direct_transactions of the category or 0 if problem
1272  * */
gsb_data_category_get_nb_direct_transactions(gint no_category)1273 gint gsb_data_category_get_nb_direct_transactions ( gint no_category )
1274 {
1275     CategoryStruct *category;
1276 
1277     category = gsb_data_category_get_structure ( no_category );
1278 
1279     if (!category)
1280 	return 0;
1281 
1282     return category -> category_nb_direct_transactions;
1283 }
1284 
1285 
1286 
1287 
1288 /**
1289  * return balance of the category
1290  *
1291  * \param no_category the number of the category
1292  *
1293  * \return balance of the category or 0 if problem
1294  * */
gsb_data_category_get_balance(gint no_category)1295 GsbReal gsb_data_category_get_balance ( gint no_category )
1296 {
1297     CategoryStruct *category;
1298 
1299     category = gsb_data_category_get_structure ( no_category );
1300 
1301     if (!category)
1302 	return null_real;
1303 
1304     return category -> category_balance;
1305 }
1306 
1307 
1308 /**
1309  * return balance of the sub-category
1310  *
1311  * \param no_category the number of the category
1312  * \param no_sub_category the number of the sub-category
1313  *
1314  * \return balance of the sub-category or 0 if problem
1315  * */
gsb_data_category_get_sub_category_balance(gint no_category,gint no_sub_category)1316 GsbReal gsb_data_category_get_sub_category_balance ( gint no_category,
1317 						      gint no_sub_category )
1318 {
1319     SubCategoryStruct *sub_category;
1320 
1321     sub_category = gsb_data_category_get_sub_category_structure ( no_category,
1322 								  no_sub_category );
1323 
1324     if (!sub_category)
1325 	return null_real;
1326 
1327     return sub_category -> sub_category_balance;
1328 }
1329 
1330 /**
1331  * return direct_balance of the category
1332  *
1333  * \param no_category the number of the category
1334  *
1335  * \return balance of the category or 0 if problem
1336  * */
gsb_data_category_get_direct_balance(gint no_category)1337 GsbReal gsb_data_category_get_direct_balance ( gint no_category )
1338 {
1339     CategoryStruct *category;
1340 
1341     category = gsb_data_category_get_structure ( no_category );
1342 
1343     if (!category)
1344 	return null_real;
1345 
1346     return category -> category_direct_balance;
1347 }
1348 
1349 
1350 
1351 /**
1352  * reset the counters of the categories and sub-categories
1353  *
1354  * \param
1355  *
1356  * \return
1357  * */
gsb_data_category_reset_counters(void)1358 void gsb_data_category_reset_counters ( void )
1359 {
1360     GSList *list_tmp;
1361 
1362     list_tmp = category_list;
1363 
1364     while ( list_tmp )
1365     {
1366 	CategoryStruct *category;
1367 	GSList *sub_list_tmp;
1368 
1369 	category = list_tmp -> data;
1370 	category -> category_balance = null_real;
1371 	category -> category_nb_transactions = 0;
1372 	category -> category_direct_balance = null_real;
1373 	category -> category_nb_direct_transactions = 0;
1374 
1375 	sub_list_tmp = category -> sub_category_list;
1376 
1377 	while ( sub_list_tmp )
1378 	{
1379 	    SubCategoryStruct *sub_category;
1380 
1381 	    sub_category = sub_list_tmp -> data;
1382 
1383 	    sub_category -> sub_category_nb_transactions = 0;
1384 	    sub_category -> sub_category_balance = null_real;
1385 
1386 	    sub_list_tmp = sub_list_tmp -> next;
1387 	}
1388 	list_tmp = list_tmp -> next;
1389     }
1390 
1391     /* reset the empty category */
1392     empty_category -> category_balance = null_real;
1393     empty_category -> category_nb_transactions = 0;
1394     empty_category -> category_direct_balance = null_real;
1395     empty_category -> category_nb_direct_transactions = 0;
1396 }
1397 
1398 
1399 
1400 /**
1401  * update the counters of the categories
1402  *
1403  * \param
1404  *
1405  * \return
1406  * */
gsb_data_category_update_counters(void)1407 void gsb_data_category_update_counters ( void )
1408 {
1409     GSList *list_tmp_transactions;
1410 	GrisbiWinEtat *w_etat;
1411 
1412 	w_etat = grisbi_win_get_w_etat ();
1413 
1414     gsb_data_category_reset_counters ();
1415 
1416     if ( w_etat->metatree_add_archive_in_totals )
1417         list_tmp_transactions = gsb_data_transaction_get_complete_transactions_list ();
1418     else
1419         list_tmp_transactions = gsb_data_transaction_get_transactions_list ();
1420 
1421     while ( list_tmp_transactions )
1422     {
1423     gint transaction_number_tmp;
1424     transaction_number_tmp = gsb_data_transaction_get_transaction_number (
1425                         list_tmp_transactions -> data );
1426 
1427     gsb_data_category_add_transaction_to_category ( transaction_number_tmp,
1428                         gsb_data_transaction_get_category_number ( transaction_number_tmp ),
1429                         gsb_data_transaction_get_sub_category_number (
1430                         transaction_number_tmp ) );
1431 
1432     list_tmp_transactions = list_tmp_transactions -> next;
1433     }
1434 }
1435 
1436 
1437 
1438 /**
1439  * Add the given transaction to a category in the counters if no
1440  * category is specified, add it to the blank category.
1441  *
1442  * \param transaction_number the transaction we want to work with
1443  *
1444  * \return
1445  * */
gsb_data_category_add_transaction_to_category(gint transaction_number,gint category_id,gint sub_category_id)1446 void gsb_data_category_add_transaction_to_category ( gint transaction_number,
1447 						     gint category_id,
1448 						     gint sub_category_id )
1449 {
1450     CategoryStruct *category;
1451     SubCategoryStruct *sub_category;
1452 
1453     /* if the transaction is a transfer or a split transaction, don't take it */
1454     if (gsb_data_transaction_get_split_of_transaction (transaction_number)
1455 	||
1456 	gsb_data_transaction_get_contra_transaction_number (transaction_number) > 0)
1457 	return;
1458 
1459     category = gsb_data_category_get_structure ( category_id );
1460     sub_category = gsb_data_category_get_sub_category_structure ( category_id,
1461 								  sub_category_id );
1462 
1463     /* should not happen, this is if the transaction has a categ which doesn't exist
1464      * we show a debug warning and get without categ */
1465     if (!category)
1466     {
1467         gchar *tmpstr;
1468 
1469         tmpstr = g_strdup_printf ( "The transaction %d has a category %d and sub-category %d but they don't exist.",
1470                        transaction_number,
1471                        category_id,
1472                        sub_category_id );
1473         warning_debug (tmpstr);
1474         g_free (tmpstr);
1475         category = empty_category;
1476     }
1477 
1478     /* ok, now category is on the structure or on empty_category */
1479     if ( category )
1480     {
1481 	category -> category_nb_transactions ++;
1482     if ( ! gsb_data_transaction_get_split_of_transaction ( transaction_number ) )
1483         category -> category_balance = gsb_real_add ( category -> category_balance,
1484                         gsb_data_transaction_get_adjusted_amount_for_currency (
1485                         transaction_number, category_tree_currency (), -1));
1486     }
1487 
1488     /* if we were on empty category, no sub-category */
1489     if (category == empty_category)
1490 	return;
1491 
1492     if ( sub_category )
1493     {
1494 	sub_category -> sub_category_nb_transactions ++;
1495     if ( ! gsb_data_transaction_get_split_of_transaction ( transaction_number ) )
1496         sub_category -> sub_category_balance = gsb_real_add (
1497                         sub_category -> sub_category_balance,
1498                         gsb_data_transaction_get_adjusted_amount_for_currency (
1499                         transaction_number, category_tree_currency (), -1));
1500     }
1501     else
1502     {
1503 	category -> category_nb_direct_transactions ++;
1504     if ( ! gsb_data_transaction_get_split_of_transaction ( transaction_number ) )
1505         category -> category_direct_balance = gsb_real_add (
1506                         category -> category_direct_balance,
1507                         gsb_data_transaction_get_adjusted_amount_for_currency (
1508                         transaction_number, category_tree_currency (), -1));
1509     }
1510 }
1511 
1512 
1513 /**
1514  * remove the given transaction to its category in the counters
1515  * if the transaction has no category, remove it to the blank category
1516  *
1517  * \param transaction_number the transaction we want to work with
1518  *
1519  * \return
1520  * */
gsb_data_category_remove_transaction_from_category(gint transaction_number)1521 void gsb_data_category_remove_transaction_from_category ( gint transaction_number )
1522 {
1523     CategoryStruct *category;
1524     SubCategoryStruct *sub_category;
1525 
1526     category = gsb_data_category_get_structure ( gsb_data_transaction_get_category_number (transaction_number));
1527     sub_category = gsb_data_category_get_sub_category_structure ( gsb_data_transaction_get_category_number (transaction_number),
1528 								  gsb_data_transaction_get_sub_category_number (transaction_number));
1529 
1530     if ( category )
1531     {
1532 	category -> category_nb_transactions --;
1533 	category -> category_balance = gsb_real_sub ( category -> category_balance,
1534 						      gsb_data_transaction_get_adjusted_amount_for_currency ( transaction_number,
1535 													      category_tree_currency (), -1));
1536 	if ( !category -> category_nb_transactions ) /* Cope with float errors */
1537 	    category -> category_balance = null_real;
1538     }
1539 
1540     if ( sub_category )
1541     {
1542 	sub_category -> sub_category_nb_transactions --;
1543 	sub_category -> sub_category_balance = gsb_real_sub ( sub_category -> sub_category_balance,
1544 							      gsb_data_transaction_get_adjusted_amount_for_currency ( transaction_number,
1545 														      category_tree_currency (), -1));
1546 	if ( !sub_category -> sub_category_nb_transactions ) /* Cope with float errors */
1547 	    sub_category -> sub_category_balance = null_real;
1548     }
1549     else
1550     {
1551 	if ( category )
1552 	{
1553 	    category -> category_nb_direct_transactions --;
1554 	    category -> category_direct_balance = gsb_real_sub ( category -> category_direct_balance,
1555 								 gsb_data_transaction_get_adjusted_amount_for_currency ( transaction_number,
1556 															 category_tree_currency (), -1));
1557 	}
1558     }
1559 }
1560 
1561 
1562 
1563 /**
1564  * Find if two sub categories are the same
1565  *
1566  * \param a		First sub-category to compare.
1567  * \param b		Second sub-category to compare.
1568  *
1569  * \return		Same as a <=> b.
1570  */
gsb_data_sub_category_compare(SubCategoryStruct * a,SubCategoryStruct * b)1571 gint gsb_data_sub_category_compare ( SubCategoryStruct * a, SubCategoryStruct * b )
1572 {
1573     if ( a != b && a -> sub_category_number == b -> sub_category_number )
1574     {
1575 	return 0;
1576     }
1577     return 1;
1578 }
1579 
1580 
1581 
1582 /**
1583  * \brief Debug check to verify if some sub categories are doubled.
1584  *
1585  * This is a bug caused in old version of Grisbi and this check has to
1586  * be there since we need to access to the structures directly without
1587  * resorting to numeric ids.
1588  *
1589  * \return	NULL if no error found.  A string describing any issue
1590  *		if any.
1591  */
gsb_debug_duplicate_categ_check(void)1592 gchar * gsb_debug_duplicate_categ_check (void)
1593 {
1594     GSList * tmp;
1595     gint num_duplicate = 0;
1596     gchar * output = (gchar*)"";
1597 
1598     tmp = category_list;
1599     while ( tmp )
1600     {
1601 	CategoryStruct * categ = tmp -> data;
1602 	GSList * tmp_sous_categ = categ -> sub_category_list;
1603 
1604 	while ( tmp_sous_categ )
1605 	{
1606 	    GSList * duplicate;
1607 	    duplicate = g_slist_find_custom ( categ -> sub_category_list,
1608 					      tmp_sous_categ -> data,
1609 					      (GCompareFunc) gsb_data_sub_category_compare );
1610 	    /* Second comparison is just there to find only one of them. */
1611 	    if ( duplicate && duplicate > tmp_sous_categ )
1612 	    {
1613 	        gchar* tmpstr1 = output;
1614 		gchar* tmpstr2 = g_strdup_printf (
1615 				_("In <i>%s</i>, <i>%s</i> is a duplicate of <i>%s</i>.\n"),
1616 				categ -> category_name,
1617 				((SubCategoryStruct *) tmp_sous_categ -> data) -> sub_category_name,
1618 				((SubCategoryStruct *) duplicate -> data) -> sub_category_name );
1619 		output = g_strconcat ( tmpstr1,
1620 				       tmpstr2,
1621 				       NULL );
1622 		g_free ( tmpstr2 );
1623 		num_duplicate ++;
1624 	    }
1625 	    tmp_sous_categ = tmp_sous_categ -> next;
1626 	}
1627 
1628 	tmp = tmp -> next;
1629     }
1630 
1631     if ( num_duplicate )
1632     {
1633 	output [ strlen ( output ) - 1 ] = '\0';
1634 	return output;
1635     }
1636 
1637     return NULL;
1638 }
1639 
1640 
1641 
1642 /**
1643  * Fix any duplicate in sub categories.
1644  *
1645  * \return	TRUE on success.  FALSE otherwise.
1646  */
gsb_debug_duplicate_categ_fix(void)1647 gboolean gsb_debug_duplicate_categ_fix (void)
1648 {
1649     GSList * tmp;
1650 
1651     tmp = category_list;
1652     while ( tmp )
1653     {
1654 	CategoryStruct * categ = tmp -> data;
1655 	GSList * tmp_sous_categ = categ -> sub_category_list;
1656 
1657 	while ( tmp_sous_categ )
1658 	{
1659 	    GSList * duplicate;
1660 	    duplicate = g_slist_find_custom ( categ -> sub_category_list,
1661 					      tmp_sous_categ -> data,
1662 					      (GCompareFunc) gsb_data_sub_category_compare );
1663 	    if ( duplicate )
1664 	    {
1665 		SubCategoryStruct * duplicate_categ = duplicate -> data;
1666 
1667 		duplicate_categ -> sub_category_number = gsb_data_category_max_sub_category_number ( categ -> category_number ) + 1;
1668 	    }
1669 	    tmp_sous_categ = tmp_sous_categ -> next;
1670 	}
1671 
1672 	tmp = tmp -> next;
1673     }
1674 
1675     return TRUE;
1676 }
1677 
1678 
1679 /**
1680  *
1681  *
1682  *
1683  * \param
1684  *
1685  * \return
1686  * */
1687 
gsb_data_category_test_create_category(gint no_category,const gchar * name,gint category_type)1688 gint gsb_data_category_test_create_category ( gint no_category,
1689                         const gchar *name,
1690                         gint category_type )
1691 {
1692     GSList *list_tmp;
1693     gint category_number = 0;
1694     CategoryStruct *category;
1695 
1696     list_tmp = g_slist_find_custom ( category_list,
1697                         name,
1698                         (GCompareFunc) gsb_data_category_get_pointer_from_name_in_glist );
1699 
1700     if ( list_tmp )
1701     {
1702         category = list_tmp -> data;
1703         return category -> category_number;
1704     }
1705     else
1706     {
1707         category = gsb_data_category_get_structure ( no_category );
1708 
1709         if ( !category )
1710         {
1711             category_number = gsb_data_category_new_with_number ( no_category );
1712             gsb_data_category_set_name ( category_number, name );
1713             gsb_data_category_set_type ( category_number, category_type );
1714         }
1715         else
1716         {
1717             category_number = gsb_data_category_new (name);
1718             gsb_data_category_set_type ( category_number, category_type );
1719             gsb_category_update_combofix ( FALSE );
1720         }
1721         return category_number;
1722     }
1723 }
1724 
1725 
1726 /**
1727  *
1728  *
1729  * \param
1730  *
1731  * \return
1732  * */
gsb_data_category_test_create_sub_category(gint no_category,gint no_sub_category,const gchar * name)1733 gboolean gsb_data_category_test_create_sub_category ( gint no_category,
1734                         gint no_sub_category,
1735                         const gchar *name )
1736 {
1737     GSList *list_tmp;
1738     CategoryStruct *category;
1739     SubCategoryStruct *sub_category;
1740 
1741     category = gsb_data_category_get_structure ( no_category );
1742     if ( !category )
1743         return FALSE;
1744 
1745     list_tmp = g_slist_find_custom ( category -> sub_category_list,
1746                         name,
1747                         (GCompareFunc) gsb_data_category_get_pointer_from_sub_name_in_glist );
1748 
1749     if ( list_tmp )
1750         return TRUE;
1751     else
1752     {
1753         sub_category = gsb_data_category_get_sub_category_structure ( no_category,
1754                         no_sub_category );
1755         if ( !sub_category )
1756         {
1757             gsb_data_category_new_sub_category_with_number_and_name (no_sub_category, no_category, name);
1758         }
1759         else
1760         {
1761             gsb_data_category_new_sub_category ( no_category, name );
1762             gsb_category_update_combofix ( FALSE );
1763         }
1764         return TRUE;
1765     }
1766     return FALSE;
1767 }
1768 
1769 
1770 /**
1771  * retourne le nombre de sous catégories
1772  *
1773  * \param   no_category
1774  *
1775  * \return  length of sub_category_list
1776  * */
gsb_data_category_get_sub_category_list_length(gint no_category)1777 gint gsb_data_category_get_sub_category_list_length ( gint no_category )
1778 {
1779     CategoryStruct *category;
1780 
1781     category = gsb_data_category_get_structure ( no_category );
1782 
1783     if ( !category )
1784         return 0;
1785 
1786     return g_slist_length ( category->sub_category_list );
1787 }
1788 
1789 
1790 /**
1791  * fill the category of the transaction from the string given in param
1792  * create the category if necessary
1793  * if string is NULL, free the category of the transaction
1794  *
1795  * \param transaction_number
1796  * \param string a string like "category : sub_category"
1797  * \param is_transaction TRUE if it's for a transaction, FALSE for a scheduled transaction
1798  *
1799  * \return
1800  * */
gsb_data_category_set_category_from_string(gint transaction_number,const gchar * string,gboolean is_transaction)1801 void gsb_data_category_set_category_from_string (gint transaction_number,
1802 												 const gchar *string,
1803 												 gboolean is_transaction)
1804 {
1805     gchar **tab_char;
1806     gint category_number;
1807 
1808     /* the simpliest is to split in 2 parts, transaction and scheduled,
1809      * but the 2 parts are exactly the same, exept the call to the functions */
1810     if (is_transaction)
1811     {
1812         if (!string || strlen (string) == 0)
1813         {
1814             gsb_data_transaction_set_category_number (transaction_number, 0);
1815             gsb_data_transaction_set_sub_category_number (transaction_number, 0);
1816             return;
1817         }
1818 
1819         tab_char = g_strsplit (string, " : ", 2);
1820 
1821         /* we don't mind if tab_char exists and others, all the checks will be done in ...get_number_by_name */
1822         category_number = gsb_data_category_get_number_by_name (g_strstrip (tab_char[0]),
1823 																!etat.combofix_force_category,
1824 																gsb_data_transaction_get_amount
1825 																(transaction_number).mantissa < 0);
1826         gsb_data_transaction_set_category_number (transaction_number, category_number);
1827 
1828         if (tab_char[1])
1829             gsb_data_transaction_set_sub_category_number (transaction_number,
1830 														  gsb_data_category_get_sub_category_number_by_name
1831 														  (category_number,
1832 														   g_strstrip (tab_char[1]),
1833 														   !etat.combofix_force_category));
1834     }
1835     else
1836     {
1837         if (!string)
1838         {
1839             gsb_data_scheduled_set_category_number (transaction_number, 0);
1840             gsb_data_scheduled_set_sub_category_number (transaction_number, 0);
1841             return;
1842         }
1843 
1844         tab_char = g_strsplit (string, " : ", 2);
1845 
1846         /* we don't mind if tab_char exists and others, all the checks will be done in ...get_number_by_name */
1847         category_number = gsb_data_category_get_number_by_name (tab_char[0],
1848 																!etat.combofix_force_category,
1849 																gsb_data_scheduled_get_amount
1850 																(transaction_number).mantissa <0);
1851         gsb_data_scheduled_set_category_number (transaction_number, category_number);
1852         if (tab_char[1])
1853             gsb_data_scheduled_set_sub_category_number (transaction_number,
1854 														gsb_data_category_get_sub_category_number_by_name
1855 														(category_number,
1856 														 tab_char[1],
1857 														 !etat.combofix_force_category));
1858     }
1859     g_strfreev (tab_char);
1860 }
1861 
1862 /**
1863  *
1864  *
1865  * \param
1866  *
1867  * \return
1868  * */
1869 /* Local Variables: */
1870 /* c-basic-offset: 4 */
1871 /* End: */
1872