1 /* ************************************************************************** */
2 /* */
3 /* Copyright (C) 2000-2006 Cédric Auger (cedric@grisbi.org) */
4 /* https://www.grisbi.org/ */
5 /* 2009 Pierre Biava (grisbi@pierre.biava.name) */
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_currency_link.c
25 * work with the currency_link 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_currency_link.h"
38 #include "utils_dates.h"
39 #include "dialog.h"
40 #include "gsb_real.h"
41 /*END_INCLUDE*/
42
43
44 /**
45 * \struct
46 * Describe a currency_link
47 */
48 typedef struct _CurrencyLink CurrencyLink;
49
50 struct _CurrencyLink
51 {
52 gint currency_link_number;
53
54 gint first_currency;
55 gint second_currency;
56 gint fixed_link; /* si = 1 le lien entre devises est fixe */
57 GsbReal change_rate;
58 GDate *modified_date;
59
60 /* a link is invalid when :
61 * - it's a comparison between 2 same currencies
62 * - the same link exists before
63 * it's set invalid while the configuration */
64 gboolean invalid_link;
65
66 };
67
68 /*START_STATIC*/
69 static void _g_data_currency_link_free ( CurrencyLink *currency_link );
70 static gboolean gsb_data_currency_link_check_for_invalid ( gint currency_link_number );
71 static gpointer gsb_data_currency_link_get_structure ( gint currency_link_number );
72 static gint gsb_data_currency_link_max_number ( void );
73 /*END_STATIC*/
74
75 /*START_EXTERN*/
76 /*END_EXTERN*/
77
78 /** contains the g_slist of CurrencyLink */
79 static GSList *currency_link_list = NULL;
80
81 /** a pointer to the last currency_link used (to increase the speed) */
82 static CurrencyLink *currency_link_buffer;
83
84
85 /**
86 * set the currency_links global variables to NULL, usually when we init all the global variables
87 *
88 * \param none
89 *
90 * \return FALSE
91 * */
gsb_data_currency_link_init_variables(void)92 gboolean gsb_data_currency_link_init_variables ( void )
93 {
94 if ( currency_link_list )
95 {
96 GSList* tmp_list = currency_link_list;
97 while ( tmp_list )
98 {
99 CurrencyLink *currency_link;
100 currency_link = tmp_list -> data;
101 tmp_list = tmp_list -> next;
102 _g_data_currency_link_free ( currency_link );
103 }
104 g_slist_free ( currency_link_list );
105 }
106 currency_link_list = NULL;
107 currency_link_buffer = NULL;
108 return FALSE;
109 }
110
111
112 /**
113 * find and return the structure of the currency_link asked
114 *
115 * \param currency_link_number number of currency_link
116 *
117 * \return the adr of the struct of the currency_link (NULL if doesn't exit)
118 * */
gsb_data_currency_link_get_structure(gint currency_link_number)119 gpointer gsb_data_currency_link_get_structure ( gint currency_link_number )
120 {
121 GSList *tmp;
122
123 if (!currency_link_number)
124 return NULL;
125
126 /* before checking all the currency_links, we check the buffer */
127
128 if ( currency_link_buffer
129 &&
130 currency_link_buffer -> currency_link_number == currency_link_number )
131 return currency_link_buffer;
132
133 tmp = currency_link_list;
134
135 while ( tmp )
136 {
137 CurrencyLink *currency_link;
138
139 currency_link = tmp -> data;
140
141 if ( currency_link -> currency_link_number == currency_link_number )
142 {
143 currency_link_buffer = currency_link;
144 return currency_link;
145 }
146 tmp = tmp -> next;
147 }
148 return NULL;
149 }
150
151 /**
152 * return the number of the currency_link given in param
153 *
154 * \param currency_link_ptr a pointer to the struct of the currency_link
155 *
156 * \return the number of the currency_link, 0 if problem
157 * */
gsb_data_currency_link_get_no_currency_link(gpointer currency_link_ptr)158 gint gsb_data_currency_link_get_no_currency_link ( gpointer currency_link_ptr )
159 {
160 CurrencyLink *currency_link;
161
162 if ( !currency_link_ptr )
163 return 0;
164
165 currency_link = currency_link_ptr;
166 currency_link_buffer = currency_link;
167 return currency_link -> currency_link_number;
168 }
169
170
171 /**
172 * give the g_slist of currency_link structure
173 * usefull when want to check all currency_links
174 *
175 * \param none
176 *
177 * \return the g_slist of currency_links structure
178 * */
gsb_data_currency_link_get_currency_link_list(void)179 GSList *gsb_data_currency_link_get_currency_link_list ( void )
180 {
181 return currency_link_list;
182 }
183
184
185
186 /**
187 * find and return the last number of currency_link
188 *
189 * \param none
190 *
191 * \return last number of currency_link
192 * */
gsb_data_currency_link_max_number(void)193 gint gsb_data_currency_link_max_number ( void )
194 {
195 GSList *tmp;
196 gint number_tmp = 0;
197
198 tmp = currency_link_list;
199
200 while ( tmp )
201 {
202 CurrencyLink *currency_link;
203
204 currency_link = tmp -> data;
205
206 if ( currency_link -> currency_link_number > number_tmp )
207 number_tmp = currency_link -> currency_link_number;
208
209 tmp = tmp -> next;
210 }
211 return number_tmp;
212 }
213
214
215 /**
216 * create a new currency_link, give him a number, append it to the list
217 * and return the number
218 *
219 * \param currency_link_number the number of the new currency link or 0 for automatic
220 * (should be always automatic, except while loading a file)
221 *
222 * \return the number of the new currency_link
223 * */
gsb_data_currency_link_new(gint currency_link_number)224 gint gsb_data_currency_link_new ( gint currency_link_number )
225 {
226 CurrencyLink *currency_link;
227
228 currency_link = g_malloc0 ( sizeof ( CurrencyLink ));
229
230 if (currency_link_number)
231 currency_link -> currency_link_number = currency_link_number;
232 else
233 currency_link -> currency_link_number = gsb_data_currency_link_max_number () + 1;
234
235 currency_link -> modified_date = gdate_today ( );
236
237 currency_link_list = g_slist_append ( currency_link_list, currency_link );
238
239 return currency_link -> currency_link_number;
240 }
241
242
243 /**
244 * This internal function is called to free the memory used by a CurrencyLink structure.
245 */
_g_data_currency_link_free(CurrencyLink * currency_link)246 static void _g_data_currency_link_free ( CurrencyLink *currency_link )
247 {
248 if ( ! currency_link )
249 return ;
250 if ( currency_link -> modified_date )
251 g_date_free ( currency_link -> modified_date );
252 g_free (currency_link);
253 if ( currency_link_buffer == currency_link )
254 currency_link_buffer = NULL;
255 }
256
257 /**
258 * remove a currency_link
259 * set all the currency_links of transaction which are this one to 0
260 * update combofix and mark file as modified
261 *
262 * \param currency_link_number the currency_link we want to remove
263 *
264 * \return TRUE ok
265 * */
gsb_data_currency_link_remove(gint currency_link_number)266 gboolean gsb_data_currency_link_remove ( gint currency_link_number )
267 {
268 CurrencyLink *currency_link;
269
270 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
271
272 if (!currency_link)
273 return FALSE;
274
275 currency_link_list = g_slist_remove ( currency_link_list,
276 currency_link );
277
278 _g_data_currency_link_free ( currency_link );
279
280 return TRUE;
281 }
282
283
284 /**
285 * set a new number for the currency_link
286 * normally used only while loading the file because
287 * the number are given automaticly
288 *
289 * \param currency_link_number the number of the currency_link
290 * \param new_no_currency_link the new number of the currency_link
291 *
292 * \return the new number or 0 if the currency_link doen't exist
293 * */
gsb_data_currency_link_set_new_number(gint currency_link_number,gint new_no_currency_link)294 gint gsb_data_currency_link_set_new_number ( gint currency_link_number,
295 gint new_no_currency_link )
296 {
297 CurrencyLink *currency_link;
298
299 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
300
301 if (!currency_link)
302 return 0;
303
304 currency_link -> currency_link_number = new_no_currency_link;
305 return new_no_currency_link;
306 }
307
308
309
310 /**
311 * return the first_currency of the currency_link
312 *
313 * \param currency_link_number the number of the currency_link
314 *
315 * \return the first_currency of the currency_link or 0 if fail
316 * */
gsb_data_currency_link_get_first_currency(gint currency_link_number)317 gint gsb_data_currency_link_get_first_currency ( gint currency_link_number )
318 {
319 CurrencyLink *currency_link;
320
321 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
322
323 if (!currency_link)
324 return 0;
325
326 return currency_link -> first_currency;
327 }
328
329
330 /**
331 * set the first_currency of the currency_link
332 * check and fill the invalid flag
333 *
334 * \param currency_link_number the number of the currency_link
335 * \param first_currency the first_currency of the currency_link
336 *
337 * \return TRUE if ok or FALSE if problem
338 * */
gsb_data_currency_link_set_first_currency(gint currency_link_number,gint first_currency)339 gboolean gsb_data_currency_link_set_first_currency ( gint currency_link_number,
340 gint first_currency )
341 {
342 CurrencyLink *currency_link;
343
344 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
345
346 if (!currency_link)
347 return FALSE;
348
349 currency_link -> first_currency = first_currency;
350 gsb_data_currency_link_check_for_invalid (currency_link_number);
351
352 return TRUE;
353 }
354
355
356 /**
357 * return the second_currency of the currency_link
358 *
359 * \param currency_link_number the number of the currency_link
360 *
361 * \return the second_currency of the currency_link or 0 if fail
362 * */
gsb_data_currency_link_get_second_currency(gint currency_link_number)363 gint gsb_data_currency_link_get_second_currency ( gint currency_link_number )
364 {
365 CurrencyLink *currency_link;
366
367 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
368
369 if (!currency_link)
370 return 0;
371
372 return currency_link -> second_currency;
373 }
374
375
376 /**
377 * set the second_currency of the currency_link
378 * check and fill the invalid flag
379 *
380 * \param currency_link_number the number of the currency_link
381 * \param second_currency the second_currency of the currency_link
382 *
383 * \return TRUE if ok or FALSE if problem
384 * */
gsb_data_currency_link_set_second_currency(gint currency_link_number,gint second_currency)385 gboolean gsb_data_currency_link_set_second_currency ( gint currency_link_number,
386 gint second_currency )
387 {
388 CurrencyLink *currency_link;
389
390 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
391
392 if (!currency_link)
393 return FALSE;
394
395 currency_link -> second_currency = second_currency;
396 gsb_data_currency_link_check_for_invalid (currency_link_number);
397
398 return TRUE;
399 }
400
401
402 /**
403 * return the change_rate of the currency_link *
404 * \param currency_link_number the number of the currency_link
405 *
406 * \return the change_rate of the currency_link or 0 if problem
407 * */
gsb_data_currency_link_get_change_rate(gint currency_link_number)408 GsbReal gsb_data_currency_link_get_change_rate ( gint currency_link_number )
409 {
410 CurrencyLink *currency_link;
411
412 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
413
414 if (!currency_link)
415 return null_real;
416
417 return currency_link -> change_rate;
418 }
419
420
421 /**
422 * set the change_rate of the currency_link
423 *
424 * \param currency_link_number the number of the currency_link
425 * \param the of the currency_link
426 *
427 * \return TRUE if ok or FALSE if problem
428 * */
gsb_data_currency_link_set_change_rate(gint currency_link_number,GsbReal change_rate)429 gboolean gsb_data_currency_link_set_change_rate ( gint currency_link_number,
430 GsbReal change_rate )
431 {
432 CurrencyLink *currency_link;
433
434 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
435
436 if (!currency_link)
437 return FALSE;
438
439 currency_link -> change_rate = change_rate;
440
441 return TRUE;
442 }
443
444
445
446 /**
447 * return the invalid_link of the currency_link
448 * the flag invalid is set automatickly by gsb_data_currency_link_check_for_invalid
449 * when change 1 of the currency
450 *
451 * \param currency_link_number the number of the currency_link
452 *
453 * \return TRUE if the link is invalid
454 * */
gsb_data_currency_link_get_invalid_link(gint currency_link_number)455 gint gsb_data_currency_link_get_invalid_link ( gint currency_link_number )
456 {
457 CurrencyLink *currency_link;
458
459 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
460
461 if (!currency_link)
462 return 0;
463
464 return currency_link -> invalid_link;
465 }
466
467
468
469 /**
470 * return the message error because of the invalid link
471 *
472 * \param currency_link_number the number of the currency_link
473 *
474 * \return a const gchar formatted with markup : error the message
475 * */
gsb_data_currency_link_get_invalid_message(gint currency_link_number)476 const gchar *gsb_data_currency_link_get_invalid_message ( gint currency_link_number )
477 {
478 CurrencyLink *currency_link;
479
480 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
481
482 if (!currency_link)
483 return 0;
484
485 if (!currency_link -> invalid_link)
486 return NULL;
487
488 if ( currency_link -> first_currency == currency_link -> second_currency)
489 return dialogue_make_red ( _("Warning : the two currencies of the link are identicals.") );
490
491 return dialogue_make_red ( _("Warning : that link is already defined.") );
492 }
493
494
495 /**
496 * check if the link is invalid and set the flag
497 * a link is invalid if :
498 * - the 2 currencies are the same
499 * - another similar link exists already
500 * an invalid link will not be used by grisbi and showed as invalid in the configuration
501 *
502 * \param currency_link_number the number of the currency_link to check
503 *
504 * \return TRUE if invalid, FALSE if not
505 * */
gsb_data_currency_link_check_for_invalid(gint currency_link_number)506 gboolean gsb_data_currency_link_check_for_invalid ( gint currency_link_number )
507 {
508 CurrencyLink *currency_link;
509 GSList *tmp_list;
510
511 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
512
513 if (!currency_link)
514 return FALSE;
515
516 /* first check : if the 2 currencies are identical */
517
518 if ( currency_link -> first_currency == currency_link -> second_currency)
519 {
520 currency_link -> invalid_link = TRUE;
521 return TRUE;
522 }
523
524 /* second check : if that link exists already */
525
526 tmp_list = currency_link_list;
527
528 while (tmp_list)
529 {
530 CurrencyLink *tmp_currency_link;
531
532 tmp_currency_link = tmp_list -> data;
533
534 if ( tmp_currency_link -> currency_link_number != currency_link -> currency_link_number
535 &&
536 (( tmp_currency_link -> first_currency == currency_link -> first_currency
537 &&
538 tmp_currency_link -> second_currency == currency_link -> second_currency )
539 ||
540 ( tmp_currency_link -> first_currency == currency_link -> second_currency
541 &&
542 tmp_currency_link -> second_currency == currency_link -> first_currency )))
543 {
544 currency_link -> invalid_link = TRUE;
545 return TRUE;
546 }
547
548 tmp_list = tmp_list -> next;
549 }
550
551 /* it's ok, the link is valid */
552 currency_link -> invalid_link = FALSE;
553
554 return FALSE;
555 }
556
557
558 /**
559 * look for a link between the 2 currencies given in the param
560 *
561 * \param currency_1 the number of the first currency
562 * \param currency_2 the number of the second currency
563 *
564 * \return the number of the link, 0 if not found, -1 if they are the same currencies
565 * */
gsb_data_currency_link_search(gint currency_1,gint currency_2)566 gint gsb_data_currency_link_search ( gint currency_1,
567 gint currency_2 )
568 {
569 GSList *tmp_list;
570
571 if (!currency_1
572 ||
573 !currency_2 )
574 return 0;
575
576 if ( currency_1 == currency_2 )
577 return -1;
578
579 tmp_list = currency_link_list;
580
581 while (tmp_list)
582 {
583 CurrencyLink *tmp_currency_link;
584
585 tmp_currency_link = tmp_list -> data;
586
587 if ( !tmp_currency_link -> invalid_link
588 &&
589 (( tmp_currency_link -> first_currency == currency_1
590 &&
591 tmp_currency_link -> second_currency == currency_2 )
592 ||
593 ( tmp_currency_link -> first_currency == currency_2
594 &&
595 tmp_currency_link -> second_currency == currency_1 )))
596 return tmp_currency_link -> currency_link_number;
597
598 tmp_list = tmp_list -> next;
599 }
600 return 0;
601 }
602
603
604 /**
605 * get the GDate of the currency link
606 *
607 * \param currency_link_number
608 *
609 * \return the GDate of the currency link
610 * */
gsb_data_currency_link_get_modified_date(gint currency_link_number)611 GDate *gsb_data_currency_link_get_modified_date ( gint currency_link_number )
612 {
613 CurrencyLink *currency_link;
614
615 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
616
617 if (!currency_link)
618 return NULL;
619
620 return currency_link -> modified_date;
621 }
622
623
624 /**
625 * set the GDate of the currency link
626 *
627 * \param currency_link_number
628 * \param date
629 *
630 * \return TRUE if ok
631 * */
gsb_data_currency_link_set_modified_date(gint currency_link_number,GDate * date)632 gboolean gsb_data_currency_link_set_modified_date ( gint currency_link_number,
633 GDate *date )
634 {
635 CurrencyLink *currency_link;
636
637 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
638
639 if ( !currency_link )
640 return FALSE;
641
642 if ( !date )
643 return FALSE;
644
645 if ( currency_link -> modified_date )
646 g_date_free ( currency_link -> modified_date );
647
648 currency_link -> modified_date = gsb_date_copy ( date );
649
650 return TRUE;
651 }
652
653
654 /**
655 * return the change_link_currency flag
656 *
657 * \param currency_link_number the number of the currency_link
658 *
659 * \return TRUE if ok or FALSE if no ok
660 * */
gsb_data_currency_link_get_fixed_link(gint currency_link_number)661 gboolean gsb_data_currency_link_get_fixed_link ( gint currency_link_number )
662 {
663 CurrencyLink *currency_link;
664
665 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
666
667 if ( !currency_link )
668 return FALSE;
669
670 return currency_link -> fixed_link;
671 }
672
673
674 /**
675 * set the change_link_currency flag
676 *
677 * \param currency_link_number the number of the currency_link
678 * \param the change_link_currency flag for the currency_link
679 *
680 * \return TRUE if ok or FALSE if problem
681 * */
gsb_data_currency_link_set_fixed_link(gint currency_link_number,gboolean fixed_link)682 gboolean gsb_data_currency_link_set_fixed_link ( gint currency_link_number,
683 gboolean fixed_link )
684 {
685 CurrencyLink *currency_link;
686
687 currency_link = gsb_data_currency_link_get_structure ( currency_link_number );
688
689 if ( !currency_link )
690 return FALSE;
691
692 currency_link -> fixed_link = fixed_link;
693
694 return TRUE;
695 }
696
697
698 /* Local Variables: */
699 /* c-basic-offset: 4 */
700 /* End: */
701