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