1 /* ************************************************************************** */
2 /*                                                                            */
3 /*     Copyright (C)    2000-2008 Cédric Auger (cedric@grisbi.org)            */
4 /*          2003-2008 Benjamin Drieu (bdrieu@april.org)	                      */
5 /*                      2009-2018 Pierre Biava (grisbi@pierre.biava.name)     */
6 /*          https://www.grisbi.org/                                            */
7 /*                                                                            */
8 /*  This program is free software; you can redistribute it and/or modify      */
9 /*  it under the terms of the GNU General Public License as published by      */
10 /*  the Free Software Foundation; either version 2 of the License, or         */
11 /*  (at your option) any later version.                                       */
12 /*                                                                            */
13 /*  This program is distributed in the hope that it will be useful,           */
14 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of            */
15 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
16 /*  GNU General Public License for more details.                              */
17 /*                                                                            */
18 /*  You should have received a copy of the GNU General Public License         */
19 /*  along with this program; if not, write to the Free Software               */
20 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21 /*                                                                            */
22 /* ************************************************************************** */
23 
24 /**
25  * \file gsb_form_widget.c
26  * convenient functions to work with the elements in the form
27  */
28 
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include "include.h"
35 #include <glib/gi18n.h>
36 
37 /*START_INCLUDE*/
38 #include "gsb_form_widget.h"
39 #include "grisbi_app.h"
40 #include "gsb_calendar_entry.h"
41 #include "gsb_combo_box.h"
42 #include "gsb_currency.h"
43 #include "gsb_data_account.h"
44 #include "gsb_data_budget.h"
45 #include "gsb_data_category.h"
46 #include "gsb_data_form.h"
47 #include "gsb_data_payee.h"
48 #include "gsb_data_report.h"
49 #include "gsb_form.h"
50 #include "gsb_form_transaction.h"
51 #include "gsb_fyear.h"
52 #include "gsb_locale.h"
53 #include "gsb_payment_method.h"
54 #include "gtk_combofix.h"
55 #include "gsb_data_payment.h"
56 #include "structures.h"
57 #include "erreur.h"
58 /*END_INCLUDE*/
59 
60 /*START_STATIC*/
61 static GSList *		form_list_widgets = NULL; /* contains a list of struct_element according to the current form */
62 static gchar *		old_debit = NULL;
63 static gchar *		old_credit = NULL;
64 static gint			old_credit_payment_number = 0;
65 static gint			old_debit_payment_number = 0;
66 static gchar *		old_credit_payment_content = NULL;
67 static gchar *		old_debit_payment_content = NULL;
68 /*END_STATIC*/
69 
70 /*START_EXTERN*/
71 /*END_EXTERN*/
72 
73 
74 /******************************************************************************/
75 /* Private functions                                                          */
76 /******************************************************************************/
77 /**
78  *
79  *
80  * \param
81  * \param
82  *
83  * \return
84  **/
gsb_form_combo_selection_changed(GtkTreeSelection * tree_selection,gint * ptr_origin)85 static gboolean gsb_form_combo_selection_changed (GtkTreeSelection *tree_selection,
86 												  gint *ptr_origin)
87 {
88     GtkWidget *widget;
89     GtkTreeModel *model;
90     GtkTreeIter iter;
91     gchar *tmp_str;
92     gint element_number;
93     gint account_nb;
94 
95     element_number = GPOINTER_TO_INT (ptr_origin);
96 
97     if (!gtk_tree_selection_get_selected (GTK_TREE_SELECTION (tree_selection), &model, &iter))
98         return FALSE;
99 
100     gtk_tree_model_get (model, &iter, 1, &tmp_str, -1);
101 
102     if (tmp_str && strlen (tmp_str))
103     {
104         if (element_number == TRANSACTION_FORM_CATEGORY)
105         {
106 			widget = gsb_form_widget_get_widget (TRANSACTION_FORM_DEVISE);
107 			if (widget != NULL && gtk_widget_get_visible (widget))
108 			{
109 				if (g_str_has_prefix (tmp_str, _("Transfer : ")))
110 				{
111 					account_nb = gsb_form_get_account_number ();
112 					if (g_str_has_suffix (tmp_str, gsb_data_account_get_name (account_nb)))
113 						gtk_widget_hide (gsb_form_widget_get_widget (TRANSACTION_FORM_CHANGE));
114 					else
115 						gtk_widget_show (gsb_form_widget_get_widget (TRANSACTION_FORM_CHANGE));
116 				}
117 				else
118 					gtk_widget_hide (gsb_form_widget_get_widget (TRANSACTION_FORM_CHANGE));
119 			}
120 			else
121 			{
122 				widget = gsb_form_widget_get_widget (TRANSACTION_FORM_CHANGE);
123 				if (widget != NULL)
124 					gtk_widget_hide (widget);
125 			}
126         }
127     }
128     return FALSE;
129 }
130 
131 /**
132  * check if the given element can receive focus
133  *
134  * \param element_number
135  *
136  * \return TRUE : can receive focus, or FALSE
137  **/
gsb_form_widget_can_focus(gint element_number)138 static gboolean gsb_form_widget_can_focus (gint element_number)
139 {
140     GtkWidget *widget;
141 
142     /* if element_number is -1 or -2, the iteration while must
143      * stop, so return TRUE */
144     if (element_number == -1 || element_number == -2)
145 		return TRUE;
146 
147     widget = gsb_form_widget_get_widget (element_number);
148 	if (!widget)
149 		return FALSE;
150 
151 	if (!gtk_widget_get_visible (widget))
152 		return FALSE;
153 
154 	if (!gtk_widget_get_sensitive (widget))
155 		return FALSE;
156 
157     if (!(GTK_IS_COMBOFIX (widget)
158 		  || GTK_IS_ENTRY (widget)
159 		  || GTK_IS_BUTTON (widget)
160 		  || GTK_IS_COMBO_BOX (widget)))
161 	{
162 		return FALSE;
163 	}
164 
165 	return TRUE;
166 }
167 
168 /******************************************************************************/
169 /* Public Methods                                                             */
170 /******************************************************************************/
171 /**
172  * return the list which contains the widgets of the form
173  *
174  * \param
175  *
176  * \return a GSList with the pointers to the widgets of the form
177  **/
gsb_form_widget_get_list(void)178 GSList *gsb_form_widget_get_list (void)
179 {
180     return form_list_widgets;
181 }
182 
183 /**
184  * free the content of the list of the widget's form
185  * so free the content of the form
186  *
187  * \param
188  *
189  * \return FALSE
190  **/
gsb_form_widget_free_list(void)191 gboolean gsb_form_widget_free_list (void)
192 {
193 	GtkWidget *entry;
194 	GSList *tmp_list;
195     GtkWidget *widget_signals;
196 
197     devel_debug (NULL);
198 
199     if (!form_list_widgets)
200         return FALSE;
201 
202     tmp_list = form_list_widgets;
203     while (tmp_list)
204     {
205         struct_element *element;
206 
207         element = tmp_list->data;
208         if (!element)
209 		{
210 			tmp_list = tmp_list->next;
211             continue;
212 		}
213 
214         /* just to make sure... */
215         if (element->element_widget)
216         {
217             if (GTK_IS_WIDGET (element->element_widget))
218             {
219                 widget_signals = NULL;
220                 if (GTK_IS_ENTRY (element->element_widget))
221                 {
222                     widget_signals = element->element_widget;
223                 }
224                 else if (GTK_IS_COMBOFIX (element->element_widget))
225                 {
226                     widget_signals = gtk_combofix_get_entry (GTK_COMBOFIX (element->element_widget));
227 					/* if there is something in the combofix we destroy, the popup will
228 					 * be showed because destroying the gtk_entry will erase it directly,
229 					 * so the simpliest way to avoid that is to erase now the entry, but with
230 					 * gtk_combofix_set_text [cedric] (didn't succeed with another thing...) */
231 					gtk_combofix_set_text (GTK_COMBOFIX (element->element_widget), "");
232                     gsb_form_widget_set_empty (GTK_WIDGET (element->element_widget), TRUE);
233                 }
234 				else if (GTK_IS_COMBO_BOX (element->element_widget))
235 				{
236 					/* Ajout du 24/07/2017 : pour une raison encore indéterminée, les éléments de type GtkComboBox */
237 					/* provoquent un warning de la part de gtk (version 3.22.11) lorsque le widget est détruit :                                 */
238 					/* (grisbi:10426): Gtk-CRITICAL **: gtk_widget_is_drawable: assertion 'GTK_IS_WIDGET (widget)' failed */
239 					g_signal_handlers_block_by_func (element->element_widget,
240 													 gsb_payment_method_changed_callback,
241 													 NULL);
242 					if (element->element_number == TRANSACTION_FORM_TYPE)
243 					{
244 						element->element_widget = NULL;
245 						g_free (element);
246 						tmp_list = tmp_list->next;
247 						continue;
248 					}
249 					else if (element->element_number == TRANSACTION_FORM_PARTY)
250 					{
251 						entry = gtk_combofix_get_entry (GTK_COMBOFIX (element->element_widget));
252 						widget_signals = entry;
253 					}
254 				}
255 
256                 if (widget_signals)
257                 {
258                     g_signal_handlers_disconnect_by_func (G_OBJECT (widget_signals),
259 														  G_CALLBACK (gsb_form_entry_get_focus),
260 														  GINT_TO_POINTER (element->element_number));
261                     g_signal_handlers_disconnect_by_func (G_OBJECT (widget_signals),
262                         								  G_CALLBACK (gsb_form_entry_lose_focus),
263                         								  GINT_TO_POINTER (element->element_number));
264                     g_signal_handlers_disconnect_by_func (G_OBJECT (widget_signals),
265                         								  G_CALLBACK (gsb_form_button_press_event),
266                         								  GINT_TO_POINTER (element->element_number));
267                     g_signal_handlers_disconnect_by_func (G_OBJECT (widget_signals),
268                         								  G_CALLBACK (gsb_form_key_press_event),
269                         								  GINT_TO_POINTER (element->element_number));
270 					if (GTK_IS_COMBOFIX (widget_signals))
271                     	g_signal_handlers_disconnect_by_func (G_OBJECT (widget_signals),
272 															  G_CALLBACK (gsb_form_combo_selection_changed),
273                         									  GINT_TO_POINTER (element->element_number));
274                 }
275 
276 				gtk_widget_destroy (element->element_widget);
277                 element->element_widget = NULL;
278             }
279         }
280         else
281         {
282             alert_debug ("element_widget is NULL\n");
283         }
284         g_free (element);
285         tmp_list = tmp_list->next;
286     }
287     g_slist_free (form_list_widgets);
288     form_list_widgets = NULL;
289 
290 	return FALSE;
291 }
292 
293 /**
294  * create and return the widget according to its element number
295  *
296  * \param element_number the number corresponding to the widget wanted
297  * \param account_number used for method of payment and currency
298  *
299  * \return the widget or NULL (if the element number is zero)
300  **/
gsb_form_widget_create(gint element_number,gint account_number)301 GtkWidget *gsb_form_widget_create (gint element_number,
302 								   gint account_number)
303 {
304     GtkWidget *widget;
305     GSList *tmp_list;
306 
307 	if (!element_number)
308 		return NULL;
309 
310     widget = NULL;
311     switch (element_number)
312     {
313 		case TRANSACTION_FORM_DATE:
314 		case TRANSACTION_FORM_VALUE_DATE:
315 			widget = gsb_calendar_entry_new (FALSE);
316 			break;
317 
318 		case TRANSACTION_FORM_DEBIT:
319 			widget = gtk_entry_new ();
320 			g_object_set_data (G_OBJECT (widget), "element_number",
321 							   GINT_TO_POINTER (TRANSACTION_FORM_DEBIT));
322 			g_signal_connect (G_OBJECT (widget),
323 							  "changed",
324 							  G_CALLBACK (gsb_form_widget_amount_entry_changed),
325 							  NULL);
326 			break;
327 		case TRANSACTION_FORM_CREDIT:
328 			widget = gtk_entry_new ();
329 			g_object_set_data (G_OBJECT (widget), "element_number",
330 							   GINT_TO_POINTER (TRANSACTION_FORM_CREDIT));
331 			g_signal_connect (G_OBJECT (widget),
332 							  "changed",
333 							  G_CALLBACK (gsb_form_widget_amount_entry_changed),
334 							  NULL);
335 			break;
336 
337 		case TRANSACTION_FORM_NOTES:
338 		case TRANSACTION_FORM_CHEQUE:
339 		case TRANSACTION_FORM_VOUCHER:
340 		case TRANSACTION_FORM_BANK:
341 			widget = gtk_entry_new();
342 			break;
343 
344 		case TRANSACTION_FORM_EXERCICE:
345 			widget = gsb_fyear_make_combobox (TRUE);
346 			gtk_widget_set_tooltip_text (GTK_WIDGET (widget),
347 										 _("Choose the financial year"));
348 			break;
349 
350 		case TRANSACTION_FORM_PARTY:
351 			tmp_list = gsb_data_payee_get_name_and_report_list ();
352 			widget = gtk_combofix_new_with_properties (tmp_list,
353 													   etat.combofix_force_payee,
354 													   etat.combofix_case_sensitive,
355 													   FALSE,
356 													   METATREE_PAYEE);
357 			gsb_data_payee_free_name_and_report_list (tmp_list);
358 			break;
359 
360 		case TRANSACTION_FORM_CATEGORY:
361         	tmp_list = gsb_data_category_get_name_list (TRUE, TRUE, TRUE, TRUE);
362 			widget = gtk_combofix_new_with_properties (tmp_list,
363 													   etat.combofix_force_category,
364 													   etat.combofix_case_sensitive,
365 													   etat.combofix_mixed_sort,
366 													   METATREE_CATEGORY);
367 			gsb_data_categorie_free_name_list (tmp_list);
368 	    	break;
369 
370 		case TRANSACTION_FORM_FREE:
371 			alert_debug ("TRANSACTION_FORM_FREE returns an empty widget");
372 			break;
373 
374 		case TRANSACTION_FORM_BUDGET:
375 			tmp_list = gsb_data_budget_get_name_list (TRUE, TRUE);
376 			widget = gtk_combofix_new_with_properties (tmp_list,
377 													   etat.combofix_force_category,
378 													   etat.combofix_case_sensitive,
379 													   etat.combofix_mixed_sort,
380 													   METATREE_BUDGET);
381 			gsb_data_categorie_free_name_list (tmp_list);
382 			break;
383 
384 		case TRANSACTION_FORM_TYPE:
385 			widget = gtk_combo_box_new ();
386 			gsb_payment_method_create_combo_list (widget,
387 												  GSB_PAYMENT_DEBIT,
388 												  account_number,
389 												  0,
390 												  FALSE);
391 			gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
392 			gtk_widget_set_tooltip_text (GTK_WIDGET (widget),
393 										 _("Choose the method of payment"));
394 			g_signal_connect (G_OBJECT (widget),
395 							  "changed",
396 							  G_CALLBACK (gsb_payment_method_changed_callback),
397 							  NULL);
398 			break;
399 
400 		case TRANSACTION_FORM_DEVISE:
401 			widget = gsb_currency_make_combobox (FALSE);
402 			gtk_widget_set_tooltip_text (GTK_WIDGET (widget), _("Choose currency"));
403 			gsb_currency_set_combobox_history (widget,
404 											   gsb_data_account_get_currency (account_number));
405 			g_signal_connect (G_OBJECT (widget),
406 							  "changed",
407 							  G_CALLBACK (gsb_form_transaction_currency_changed),
408 							  NULL);
409 			break;
410 
411 		case TRANSACTION_FORM_CHANGE:
412 			widget = gtk_button_new_with_label (_("Change"));
413 			gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
414 			gtk_widget_set_tooltip_text (GTK_WIDGET (widget),
415 										 _("Define the change for that transaction"));
416 			g_signal_connect (G_OBJECT (widget),
417 							  "clicked",
418 							  G_CALLBACK (gsb_form_transaction_change_clicked),
419 							  NULL);
420 			break;
421 
422 		case TRANSACTION_FORM_CONTRA:
423 			/* no menu at beginning, appened when choose the contra-account */
424 			widget = gtk_combo_box_new ();
425 			gtk_widget_set_tooltip_text (GTK_WIDGET (widget),
426 						  _("Contra-transaction method of payment"));
427 			break;
428 
429 		case TRANSACTION_FORM_OP_NB:
430 		case TRANSACTION_FORM_MODE:
431 			widget = gtk_label_new (NULL);
432 			break;
433     }
434 
435     if (widget)
436     {
437 		/* force minimum width */
438 		gtk_widget_set_size_request (widget, FORM_COURT_WIDTH, -1);
439 
440 		/* first, append the widget to the list */
441 		struct_element *element;
442 
443 		element = g_malloc0 (sizeof (struct_element));
444 		element->element_number = element_number;
445 		element->element_widget = widget;
446 		form_list_widgets = g_slist_append (form_list_widgets, element);
447 
448 		/* set the signals */
449 		if (GTK_IS_ENTRY (widget))
450 		{
451 			g_signal_connect (G_OBJECT (widget),
452 							  "focus-in-event",
453 							  G_CALLBACK (gsb_form_widget_entry_get_focus),
454 							  GINT_TO_POINTER (element_number));
455 			g_signal_connect (G_OBJECT (widget),
456 					   	  	  "focus-out-event",
457 					   	  	  G_CALLBACK (gsb_form_entry_lose_focus),
458 					   	  	  GINT_TO_POINTER (element_number));
459 			g_signal_connect (G_OBJECT (widget),
460 					   	  	  "button-press-event",
461 					   	  	  G_CALLBACK (gsb_form_button_press_event),
462 					   	  	  GINT_TO_POINTER (element_number));
463 			g_signal_connect (G_OBJECT (widget),
464 					   	  	  "key-press-event",
465 					   	  	  G_CALLBACK (gsb_form_key_press_event),
466 					   	  	  GINT_TO_POINTER (element_number));
467 		}
468 		else
469 		{
470 			if (GTK_IS_COMBOFIX (widget))
471 	    	{
472 				GtkWidget *entry = NULL;
473 
474 				entry = gtk_combofix_get_entry (GTK_COMBOFIX (widget));
475 				if (GTK_IS_ENTRY (entry))
476 				{
477 					gtk_widget_set_size_request (widget, FORM_LONG_WIDTH, -1);
478 
479 					g_signal_connect (G_OBJECT (entry),
480 									  "focus-in-event",
481 									  G_CALLBACK (gsb_form_entry_get_focus),
482 									  GINT_TO_POINTER (element_number));
483 					g_signal_connect (G_OBJECT (entry),
484 									  "focus-out-event",
485 									  G_CALLBACK (gsb_form_entry_lose_focus),
486 									  GINT_TO_POINTER (element_number));
487 					g_signal_connect (G_OBJECT (entry),
488 									  "button-press-event",
489 									  G_CALLBACK (gsb_form_button_press_event),
490 									  GINT_TO_POINTER (element_number));
491 					g_signal_connect (G_OBJECT (entry),
492 									  "key-press-event",
493 									  G_CALLBACK (gsb_form_key_press_event),
494 									  GINT_TO_POINTER (element_number));
495 				}
496 				gtk_combofix_set_selection_callback (GTK_COMBOFIX (widget),
497 													 G_CALLBACK (gsb_form_combo_selection_changed),
498 													 GINT_TO_POINTER (element_number));
499 			}
500 			else
501 				/* neither an entry, neither a combofix or combo_box*/
502 				g_signal_connect (G_OBJECT (widget),
503 								  "key-press-event",
504 								  G_CALLBACK (gsb_form_key_press_event),
505 								  GINT_TO_POINTER (element_number));
506 		}
507     }
508     else
509 	{
510     	alert_debug ("Widget should not be NULL");
511     }
512 
513     return widget;
514 }
515 
516 /**
517  * return the pointer to the widget corresponding to the given element
518  *
519  * \param element_number
520  *
521  * \return the widget or NULL
522  **/
gsb_form_widget_get_widget(gint element_number)523 GtkWidget *gsb_form_widget_get_widget (gint element_number)
524 {
525     return gsb_form_get_element_widget_from_list (element_number,
526 												  form_list_widgets);
527 }
528 
529 /**
530  * get an element number and return its name
531  *
532  * \param element_number
533  *
534  * \return the name of the element or NULL if problem
535  **/
gsb_form_widget_get_name(gint element_number)536 const gchar *gsb_form_widget_get_name (gint element_number)
537 {
538     switch (element_number)
539     {
540 		case -1:
541 			/* that value shouldn't be there, it shows that a gsb_data_form_... returns
542 			 * an error value */
543 			warning_debug ("gsb_form_widget_get_name : a value in the form is -1 "
544 						   "which should not happen.\nA gsb_data_form_... "
545 						   "function must have returned an error value...");
546 			return NULL;
547 			break;
548 
549 		case TRANSACTION_FORM_DATE:
550 			return (N_("Date"));
551 			break;
552 
553 		case TRANSACTION_FORM_DEBIT:
554 			return (N_("Debit"));
555 			break;
556 
557 		case TRANSACTION_FORM_CREDIT:
558 			return (N_("Credit"));
559 			break;
560 
561 		case TRANSACTION_FORM_VALUE_DATE:
562 			return (N_("Value date"));
563 			break;
564 
565 		case TRANSACTION_FORM_EXERCICE:
566 			return (N_("Financial year"));
567 			break;
568 
569 		case TRANSACTION_FORM_PARTY:
570 			return (N_("Payee"));
571 			break;
572 
573 		case TRANSACTION_FORM_CATEGORY:
574 			return (N_("Categories : Sub-categories"));
575 			break;
576 
577 		case TRANSACTION_FORM_FREE:
578 			return (N_("Free"));
579 			break;
580 
581 		case TRANSACTION_FORM_BUDGET:
582 			return (N_("Budgetary line"));
583 			break;
584 
585 		case TRANSACTION_FORM_NOTES:
586 			return (N_("Notes"));
587 			break;
588 
589 		case TRANSACTION_FORM_TYPE:
590 			return (N_("Method of payment"));
591 			break;
592 
593 		case TRANSACTION_FORM_CHEQUE:
594 			return (N_("Cheque/Transfer number"));
595 			break;
596 
597 		case TRANSACTION_FORM_DEVISE:
598 			return (N_("Currency"));
599 			break;
600 
601 		case TRANSACTION_FORM_CHANGE:
602 			return (N_("Change"));
603 			break;
604 
605 		case TRANSACTION_FORM_VOUCHER:
606 			return (N_("Voucher"));
607 			break;
608 
609 		case TRANSACTION_FORM_BANK:
610 			return (N_("Bank references"));
611 			break;
612 
613 		case TRANSACTION_FORM_CONTRA:
614 			return (N_("Contra-transaction method of payment"));
615 			break;
616 
617 		case TRANSACTION_FORM_OP_NB:
618 			return (N_("Transaction number"));
619 			break;
620 
621 		case TRANSACTION_FORM_MODE:
622 			return (N_("Automatic/Manual"));
623 			break;
624     }
625     return NULL;
626 }
627 
628 /**
629  * return the number of the next valid element in the direction given in param
630  *
631  * \param account_number
632  * \param element_number
633  * \param direction GTK_DIR_LEFT, GTK_DIR_RIGHT, GTK_DIR_UP, GTK_DIR_DOWN
634  *
635  * \return 	the next element number
636  * 		-1 if problem or not change
637  * 		-2 if end of the form and need to finish it
638  **/
gsb_form_widget_next_element(gint account_number,gint element_number,gint direction)639 gint gsb_form_widget_next_element (gint account_number,
640 								   gint element_number,
641 								   gint direction)
642 {
643     gint row;
644     gint column;
645     gint return_value_number = 0;
646     gint form_column_number;
647     gint form_row_number;
648 
649     if (!gsb_data_form_look_for_value (element_number, &row, &column))
650 		return -1;
651 
652     form_column_number = gsb_data_form_get_nb_columns ();
653     form_row_number = gsb_data_form_get_nb_rows ();
654 
655     while (!gsb_form_widget_can_focus (return_value_number))
656     {
657 		switch (direction)
658 		{
659 			case GTK_DIR_LEFT:
660 			if (!column && !row)
661 			{
662 				/* we are at the upper left, go on the bottom right */
663 				column = form_column_number;
664 				row = form_row_number -1;
665 			}
666 
667 			if (--column == -1)
668 			{
669 				column = form_column_number - 1;
670 				row--;
671 			}
672 			return_value_number = gsb_data_form_get_value (column, row);
673 			break;
674 
675 			case GTK_DIR_RIGHT:
676 			if (column == (form_column_number - 1)
677 				 &&
678 				 row == (form_row_number - 1))
679 			{
680 				GrisbiAppConf *a_conf;
681 
682 				a_conf = (GrisbiAppConf *) grisbi_app_get_a_conf ();
683 
684 				/* we are on the bottom right, we finish the edition or
685 				 * go to the upper left */
686 				if (!a_conf->form_enter_key)
687 				{
688 				return_value_number = -2;
689 				continue;
690 				}
691 				column = -1;
692 				row = 0;
693 			}
694 
695 			if (++column == form_column_number)
696 			{
697 				column = 0;
698 				row++;
699 			}
700 			return_value_number = gsb_data_form_get_value (column, row);
701 			break;
702 
703 			case GTK_DIR_UP:
704 			if (!row)
705 			{
706 				return_value_number = -1;
707 				continue;
708 			}
709 
710 			row--;
711 			return_value_number = gsb_data_form_get_value (column, row);
712 			break;
713 
714 			case GTK_DIR_DOWN:
715 			if (row == (form_row_number - 1))
716 			{
717 				return_value_number = -1;
718 				continue;
719 			}
720 			row++;
721 			return_value_number = gsb_data_form_get_value (column, row);
722 			break;
723 
724 			default:
725 			return_value_number = -1;
726 		}
727     }
728     return return_value_number;
729 }
730 
731 /**
732  * set the focus on the given element
733  *
734  * \param element_number
735  *
736  * \return
737  **/
gsb_form_widget_set_focus(gint element_number)738 void gsb_form_widget_set_focus (gint element_number)
739 {
740     GtkWidget *widget;
741 
742     widget = gsb_form_widget_get_widget (element_number);
743 
744 	if (!widget)
745 		return;
746 
747 	if (GTK_IS_COMBOFIX (widget))
748 	{
749 		GtkWidget *entry;
750 
751 		entry = gtk_combofix_get_entry (GTK_COMBOFIX (widget));
752 		if (entry)
753 			gtk_widget_grab_focus (entry);
754 		else
755 			gtk_widget_grab_focus (widget);
756 	}
757 	else
758 		gtk_widget_grab_focus (widget);
759 
760 	return;
761 }
762 
763 /**
764  * check if the entry or combofix given in param is empty (ie grey) or not
765  *
766  * \param entry must be an entry
767  *
768  * \return TRUE : entry is free, FALSE : not free
769  **/
gsb_form_widget_check_empty(GtkWidget * entry)770 gboolean gsb_form_widget_check_empty (GtkWidget *entry)
771 {
772     if (!entry)
773 		return FALSE;
774 
775 	if (GTK_IS_ENTRY (entry))
776 		return GPOINTER_TO_INT (g_object_get_data (G_OBJECT(entry), "empty"));
777 
778 	entry = gtk_combofix_get_entry (GTK_COMBOFIX (entry));
779 	if (GTK_IS_ENTRY (entry))
780 		return GPOINTER_TO_INT (g_object_get_data (G_OBJECT(entry), "empty"));
781 
782 	return FALSE;
783 }
784 
785 /**
786  * set the style to the entry as empty or not
787  *
788  * \param entry must be an entry
789  * \param empty TRUE or FALSE
790  *
791  * \return
792  **/
gsb_form_widget_set_empty(GtkWidget * entry,gboolean empty)793 void gsb_form_widget_set_empty (GtkWidget *entry,
794                                 gboolean empty)
795 {
796     GtkStyleContext* context;
797 
798 	if (!entry)
799 		return;
800 
801 	if (!GTK_IS_ENTRY (entry))
802 		entry = gtk_combofix_get_entry (GTK_COMBOFIX (entry));
803 
804     if (!entry)
805         return;
806 
807     context = gtk_widget_get_style_context (entry);
808 
809     if (!empty)
810     {
811         gtk_widget_set_name (entry, "form_entry");
812         gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
813     }
814     else
815     {
816         gtk_widget_set_name (entry, "form_entry_empty");
817         gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
818     }
819 
820     g_object_set_data (G_OBJECT(entry), "empty", GINT_TO_POINTER (empty));
821 }
822 
823 /**
824  * called when an debit or credit entry get the focus,
825  * if the entry is free, set it normal and erase the help content
826  *
827  * \param entry
828  * \param ev
829  *
830  * \return FALSE
831  **/
gsb_form_widget_entry_get_focus(GtkWidget * entry,GdkEventFocus * ev,gint * ptr_origin)832 gboolean gsb_form_widget_entry_get_focus (GtkWidget *entry,
833 										  GdkEventFocus *ev,
834 										  gint *ptr_origin)
835 {
836     GtkWidget *widget;
837     GtkWidget *tmp_widget;
838     gint element_number;
839     gint account_number;
840 
841     /* still not found, if change the content of the form, something come in entry
842      * which is nothing, so protect here */
843 	if (!GTK_IS_WIDGET (entry) || !GTK_IS_ENTRY (entry))
844     	return FALSE;
845 
846     /* it clears the entry in question */
847     if (gsb_form_widget_check_empty (entry))
848     {
849         gtk_entry_set_text (GTK_ENTRY (entry), "");
850         gsb_form_widget_set_empty (entry, FALSE);
851     }
852     element_number = GPOINTER_TO_INT (ptr_origin);
853     account_number = gsb_form_get_account_number ();
854 
855     switch (element_number)
856     {
857 		case TRANSACTION_FORM_DEBIT :
858 			/* on met old_debit = NULl car avec g_free plantage */
859 			if (old_debit && strlen (old_debit) > 0)
860 				old_debit = NULL;
861 
862 			/* save the credit if necessary */
863 			widget = gsb_form_widget_get_widget (TRANSACTION_FORM_CREDIT);
864 			if (!gsb_form_widget_check_empty (widget))
865 				old_credit = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
866 
867 			/* we change the payment method to adapt it for the debit */
868 			widget = gsb_form_widget_get_widget (TRANSACTION_FORM_TYPE);
869 
870 			/* change the method of payment if necessary
871 			 * (if grey, it's a child of split so do nothing) */
872 			if (widget && gtk_widget_get_sensitive (widget))
873 			{
874 				/* change the signe of the method of payment and the contra */
875 				if (gsb_payment_method_get_combo_sign (widget) == GSB_PAYMENT_CREDIT)
876 				{
877 					old_credit_payment_number = gsb_payment_method_get_selected_number (widget);
878 
879 					tmp_widget = gsb_form_widget_get_widget (TRANSACTION_FORM_CHEQUE);
880 					if (tmp_widget && gtk_widget_get_visible (tmp_widget))
881 					{
882 						if (old_credit_payment_content)
883 							g_free (old_credit_payment_content);
884 						if (gsb_form_widget_check_empty (tmp_widget) == FALSE)
885 							old_credit_payment_content = g_strdup (gtk_entry_get_text (GTK_ENTRY (tmp_widget)));
886 						else
887 							old_credit_payment_content = NULL;
888 					}
889 
890 					gsb_payment_method_create_combo_list (widget,
891 														  GSB_PAYMENT_DEBIT,
892 														  account_number,
893 														  0,
894 														  FALSE);
895 
896 					widget = gsb_form_widget_get_widget (TRANSACTION_FORM_CONTRA);
897 					if (widget && gtk_widget_get_visible (widget))
898 						gsb_payment_method_create_combo_list (gsb_form_widget_get_widget (TRANSACTION_FORM_CONTRA),
899 															  GSB_PAYMENT_CREDIT,
900 															  account_number,
901 															  0,
902 															  TRUE);
903 				}
904 			}
905 			gsb_form_check_auto_separator (entry);
906 			break;
907 		case TRANSACTION_FORM_CREDIT :
908 			 /* on met old_credit = NULl car avec g_free plantage */
909 			if (old_credit && strlen (old_credit) > 0)
910 				old_credit = NULL;
911 
912 			/* save the debit if necessary */
913 			widget = gsb_form_widget_get_widget (TRANSACTION_FORM_DEBIT);
914 			if (!gsb_form_widget_check_empty (widget))
915 				old_debit = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
916 
917 			/* we change the payment method to adapt it for the debit */
918 			widget = gsb_form_widget_get_widget (TRANSACTION_FORM_TYPE);
919 
920 			/* change the method of payment if necessary
921 			 * (if grey, it's a child of split so do nothing) */
922 			if (widget && gtk_widget_get_sensitive (widget))
923 			{
924 				/* change the signe of the method of payment and the contra */
925 				if (gsb_payment_method_get_combo_sign (widget) == GSB_PAYMENT_DEBIT)
926 				{
927 					old_debit_payment_number = gsb_payment_method_get_selected_number (widget);
928 
929 					tmp_widget = gsb_form_widget_get_widget (TRANSACTION_FORM_CHEQUE);
930 					if (tmp_widget && gtk_widget_get_visible (tmp_widget))
931 					{
932 						if (old_debit_payment_content)
933 							g_free (old_debit_payment_content);
934 						if (gsb_form_widget_check_empty (tmp_widget) == FALSE)
935 							old_debit_payment_content = g_strdup (gtk_entry_get_text (GTK_ENTRY (tmp_widget)));
936 						else
937 							old_debit_payment_content = NULL;
938 					}
939 
940 					gsb_payment_method_create_combo_list (widget,
941 														  GSB_PAYMENT_CREDIT,
942 														  account_number,
943 														  0,
944 														  FALSE);
945 
946 					widget = gsb_form_widget_get_widget (TRANSACTION_FORM_CONTRA);
947 					if (widget && gtk_widget_get_visible (widget))
948 						gsb_payment_method_create_combo_list (widget,
949 															  GSB_PAYMENT_DEBIT,
950 															  account_number,
951 															  0,
952 															  TRUE);
953 				}
954 			}
955 			gsb_form_check_auto_separator (entry);
956 			break;
957     }
958 
959     /* sensitive the valid and cancel buttons */
960 	gsb_form_sensitive_cancel_valid_buttons (TRUE);
961 
962 	return FALSE;
963 }
964 
965 /**
966  *
967  *
968  * \param
969  *
970  * \return
971  **/
gsb_form_widget_get_old_credit(void)972 gchar *gsb_form_widget_get_old_credit (void)
973 {
974     if (old_credit && strlen (old_credit) > 0)
975         return g_strdup (old_credit);
976     else
977         return NULL;
978 }
979 
980 /**
981  *
982  *
983  * \param
984  *
985  * \return
986  **/
gsb_form_widget_get_old_debit(void)987 gchar *gsb_form_widget_get_old_debit (void)
988 {
989     if (old_debit && strlen (old_debit) > 0)
990         return g_strdup (old_debit);
991     else
992         return NULL;
993 }
994 
995 /**
996  * called when entry changed
997  * check the entry and set the entry red/invalid if not a good number
998  *
999  * \param entry
1000  * \param null
1001  *
1002  * \return FALSE
1003  **/
gsb_form_widget_amount_entry_changed(GtkWidget * entry,gpointer null)1004 gboolean gsb_form_widget_amount_entry_changed (GtkWidget *entry,
1005                                                gpointer null)
1006 {
1007     GtkStyleContext* context;
1008     gboolean valide;
1009     gint element_number;
1010 
1011     /* if we are in the form and the entry is empty, do nothing
1012      * because it's a special style too */
1013     element_number = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (entry), "element_number"));
1014 
1015     if (g_strcmp0 (gsb_form_widget_get_name (element_number),
1016                    gtk_entry_get_text (GTK_ENTRY (entry))) == 0)
1017         return FALSE;
1018 
1019     if (gsb_form_widget_check_empty (entry))
1020 	    return FALSE;
1021 
1022     context = gtk_widget_get_style_context (entry);
1023 
1024     /* if nothing in the entry, keep the normal style */
1025     if (!strlen (gtk_entry_get_text (GTK_ENTRY (entry))))
1026     {
1027         gtk_widget_set_name (entry, "form_entry_empty");
1028         gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
1029 
1030 	    return FALSE;
1031     }
1032 
1033     valide = gsb_form_widget_get_valide_amout_entry (gtk_entry_get_text (GTK_ENTRY (entry)));
1034     if (valide)
1035     {
1036         /* the entry is valid, make it normal */
1037         gtk_widget_set_name (entry, "form_entry");
1038     }
1039     else
1040     {
1041 	    /* the entry is not valid, make it red */
1042         gtk_widget_set_name (entry, "form_entry_error");
1043     }
1044     gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
1045 
1046     return FALSE;
1047 }
1048 
1049 /**
1050  *
1051  *
1052  * \param
1053  *
1054  * \return
1055  **/
gsb_form_widget_get_valide_amout_entry(const gchar * string)1056 gboolean gsb_form_widget_get_valide_amout_entry (const gchar *string)
1057 {
1058     const gchar *ptr;
1059     gchar *mon_decimal_point;
1060     gunichar decimal_point;
1061     gchar *mon_thousands_sep;
1062     gunichar thousands_sep = (gunichar) -1;
1063 
1064     ptr = string;
1065 
1066     if ((g_utf8_strchr (ptr, -1, '*') && g_utf8_strchr (ptr, -1, '+'))
1067      ||
1068      (g_utf8_strchr (ptr, -1, '*') && g_utf8_strchr (ptr, -1, '-')))
1069         return FALSE;
1070 
1071     mon_decimal_point = gsb_locale_get_mon_decimal_point ();
1072     decimal_point = g_utf8_get_char_validated (mon_decimal_point, -1);
1073     mon_thousands_sep = gsb_locale_get_mon_thousands_sep ();
1074     if (mon_thousands_sep)
1075         thousands_sep = g_utf8_get_char_validated (mon_thousands_sep, -1);
1076 
1077     while (g_utf8_strlen (ptr, -1) > 0)
1078     {
1079         gunichar ch;
1080 
1081         ch = g_utf8_get_char_validated (ptr, -1);
1082 
1083         if (!g_unichar_isdefined (ch))
1084         {
1085             g_free (mon_decimal_point);
1086             if (mon_thousands_sep)
1087                 g_free (mon_thousands_sep);
1088 
1089             return FALSE;
1090         }
1091 
1092         if (!g_ascii_isdigit (ch))
1093         {
1094 			if (ch == 0x00A0 || ch == 0x202F/* NON-BREAK SPACE || ESPACE INSÉCABLE ÉTROITE */)
1095 			{
1096 				 ptr = g_utf8_next_char (ptr);
1097 				continue;
1098 			}
1099             else if (g_unichar_isdefined (thousands_sep))
1100             {
1101                 if (ch != '.' && ch != ',' && ch != '+' && ch != '-'
1102                  && ch != '*' && ch != '/' && ch != thousands_sep)
1103                 {
1104                     g_free (mon_decimal_point);
1105                     g_free (mon_thousands_sep);
1106 
1107                     return FALSE;
1108                 }
1109 
1110                 if (ch == decimal_point
1111                  && g_utf8_strlen (ptr, -1) == 1
1112                  && g_utf8_strchr (string, -1, thousands_sep))
1113                 {
1114                     gchar **tab;
1115                     guint i = 1;    /* le premier champs peut etre < à 3 */
1116                     guint nbre_champs;
1117 
1118                     tab = g_strsplit (string, mon_thousands_sep, 0);
1119                     nbre_champs = g_strv_length (tab);
1120 
1121                     while (i < nbre_champs)
1122                     {
1123                         if (i < nbre_champs - 1 && g_utf8_strlen (tab[i], -1) != 3)
1124                         {
1125                             g_strfreev (tab);
1126                             g_free (mon_decimal_point);
1127                             g_free (mon_thousands_sep);
1128 
1129                             return FALSE;
1130                         }
1131                         else if (i == nbre_champs - 1 && g_utf8_strlen (tab[i], -1) != 4)
1132                         {
1133                             g_strfreev (tab);
1134                             g_free (mon_decimal_point);
1135                             g_free (mon_thousands_sep);
1136 
1137                             return FALSE;
1138                         }
1139                         i++;
1140                     }
1141                     g_strfreev (tab);
1142                 }
1143             }
1144             else if (ch != '.' && ch != ',' && ch != '+' && ch != '-' && ch != '*' && ch != '/')
1145                 return FALSE;
1146         }
1147 
1148         ptr = g_utf8_next_char (ptr);
1149     }
1150 
1151     g_free (mon_decimal_point);
1152     if (mon_thousands_sep)
1153         g_free (mon_thousands_sep);
1154 
1155     return TRUE;
1156 }
1157 
1158 /**
1159  *
1160  *
1161  * \param
1162  *
1163  * \return
1164  **/
gsb_form_widget_get_old_credit_payment_number(void)1165 gint gsb_form_widget_get_old_credit_payment_number (void)
1166 {
1167     return old_credit_payment_number;
1168 }
1169 
1170 /**
1171  *
1172  *
1173  * \param
1174  *
1175  * \return
1176  **/
gsb_form_widget_get_old_debit_payment_number(void)1177 gint gsb_form_widget_get_old_debit_payment_number (void)
1178 {
1179     return old_debit_payment_number;
1180 }
1181 
1182 /**
1183  *
1184  *
1185  * \param
1186  *
1187  * \return
1188  **/
gsb_form_widget_get_old_credit_payment_content(void)1189 const gchar *gsb_form_widget_get_old_credit_payment_content (void)
1190 {
1191     return old_credit_payment_content;
1192 }
1193 
1194 /**
1195  *
1196  *
1197  * \param
1198  *
1199  * \return
1200  **/
gsb_form_widget_get_old_debit_payment_content(void)1201 const gchar *gsb_form_widget_get_old_debit_payment_content (void)
1202 {
1203     return old_debit_payment_content;
1204 }
1205 
1206 /**
1207  * called when entry validated by Enter Tab lose focus
1208  * check the entry and set the entry red/invalid if not a good number
1209  *
1210  * \param entry
1211  *
1212  * \return TRUE if entry is valid
1213  **/
gsb_form_widget_amount_entry_validate(gint element_number)1214 gboolean gsb_form_widget_amount_entry_validate (gint element_number)
1215 {
1216     GtkWidget *entry;
1217     GtkStyleContext* context;
1218     const gchar *text;
1219     gchar *tmp_str;
1220     gchar *mon_decimal_point;
1221     gboolean valide;
1222     gboolean return_value;
1223 
1224     entry = gsb_form_widget_get_widget (element_number);
1225     if (gsb_form_widget_check_empty (entry))
1226         return TRUE;
1227 
1228     text = gtk_entry_get_text (GTK_ENTRY (entry));
1229     if (g_strcmp0 (gsb_form_widget_get_name (element_number), text) == 0)
1230         return TRUE;
1231 
1232     /* if nothing in the entry, set the widget empty */
1233     if (!strlen (text))
1234     {
1235         gsb_form_widget_set_empty (entry, TRUE);
1236         return TRUE;
1237     }
1238 
1239     context = gtk_widget_get_style_context  (entry);
1240 
1241     mon_decimal_point = gsb_locale_get_mon_decimal_point ();
1242     if (g_strrstr (text, gsb_locale_get_mon_decimal_point ()) == NULL)
1243         tmp_str = g_strconcat (text, mon_decimal_point, NULL);
1244     else
1245         tmp_str= g_strdup (text);
1246 
1247     valide = gsb_form_widget_get_valide_amout_entry (tmp_str);
1248     if (valide)
1249     {
1250         /* the entry is valid, make it normal */
1251         gtk_widget_set_name (entry, "form_entry");
1252         return_value = TRUE;
1253     }
1254     else
1255     {
1256         /* the entry is not valid, make it red */
1257         gtk_widget_set_name (entry, "form_entry_error");
1258         return_value = FALSE;
1259     }
1260 
1261     gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
1262 
1263     g_free (tmp_str);
1264     g_free (mon_decimal_point);
1265 
1266     return return_value;
1267 }
1268 
1269 /**
1270  * update the payee combofix in the form with the current current report
1271  *
1272  * \param report_number
1273  * \param sens              FALSE remove report TRUE add report
1274  *
1275  * \return FALSE
1276  **/
gsb_form_widget_update_payee_combofix(gint report_number,gint sens)1277 gboolean gsb_form_widget_update_payee_combofix (gint report_number,
1278 												gint sens)
1279 {
1280     if (sens)
1281         gtk_combofix_append_report (GTK_COMBOFIX (gsb_form_widget_get_widget
1282 												  (TRANSACTION_FORM_PARTY)),
1283 									gsb_data_report_get_report_name (report_number));
1284     else
1285         gtk_combofix_remove_report (GTK_COMBOFIX (gsb_form_widget_get_widget
1286 												  (TRANSACTION_FORM_PARTY)),
1287 									gsb_data_report_get_report_name (report_number));
1288 
1289     return FALSE;
1290 }
1291 
1292 /**
1293  * free the content of the list of structures of the form
1294  *
1295  * \param
1296  *
1297  * \return FALSE
1298  **/
gsb_form_widget_free_list_without_widgets(void)1299 gboolean gsb_form_widget_free_list_without_widgets (void)
1300 {
1301 	GSList *tmp_list;
1302 
1303     devel_debug (NULL);
1304 
1305     if (!form_list_widgets)
1306         return FALSE;
1307 
1308     tmp_list = form_list_widgets;
1309     while (tmp_list)
1310     {
1311         struct_element *element;
1312 
1313         element = tmp_list->data;
1314         g_free (element);
1315         tmp_list = tmp_list->next;
1316     }
1317     g_slist_free (form_list_widgets);
1318     form_list_widgets = NULL;
1319 
1320 	return FALSE;
1321 }
1322 
1323 /**
1324  *
1325  *
1326  * \param
1327  *
1328  * \return
1329  **/
1330 /* Local Variables: */
1331 /* c-basic-offset: 4 */
1332 /* End: */
1333 
1334