1 /* ************************************************************************** */
2 /*                                                                            */
3 /*     Copyright (C)    2000-2008 Cédric Auger (cedric@grisbi.org)            */
4 /*          2004-2008 Benjamin Drieu (bdrieu@april.org)                       */
5 /*      2009 Thomas Peel (thomas.peel@live.fr)                                */
6 /*          2008-2021 Pierre Biava (grisbi@pierre.biava.name)                 */
7 /*          https://www.grisbi.org/                                           */
8 /*                                                                            */
9 /*  This program is free software; you can redistribute it and/or modify      */
10 /*  it under the terms of the GNU General Public License as published by      */
11 /*  the Free Software Foundation; either version 2 of the License, or         */
12 /*  (at your option) any later version.                                       */
13 /*                                                                            */
14 /*  This program is distributed in the hope that it will be useful,           */
15 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of            */
16 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
17 /*  GNU General Public License for more details.                              */
18 /*                                                                            */
19 /*  You should have received a copy of the GNU General Public License         */
20 /*  along with this program; if not, write to the Free Software               */
21 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
22 /*                                                                            */
23 /* ************************************************************************** */
24 
25 /* \file gsb_scheduler_list.c : functions for the scheduled list */
26 
27 
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include "include.h"
34 #include <gdk/gdkkeysyms.h>
35 #include <glib/gi18n.h>
36 
37 /*START_INCLUDE*/
38 #include "gsb_scheduler_list.h"
39 #include "bet_data_finance.h"
40 #include "bet_finance_ui.h"
41 #include "dialog.h"
42 #include "grisbi_app.h"
43 #include "gsb_automem.h"
44 #include "gsb_calendar.h"
45 #include "gsb_data_account.h"
46 #include "gsb_data_category.h"
47 #include "gsb_data_currency.h"
48 #include "gsb_data_payee.h"
49 #include "gsb_data_scheduled.h"
50 #include "gsb_dirs.h"
51 #include "gsb_file.h"
52 #include "gsb_form.h"
53 #include "gsb_form_scheduler.h"
54 #include "gsb_real.h"
55 #include "gsb_rgba.h"
56 #include "gsb_scheduler.h"
57 #include "gsb_transactions_list.h"
58 #include "menu.h"
59 #include "mouse.h"
60 #include "navigation.h"
61 #include "structures.h"
62 #include "traitement_variables.h"
63 #include "utils.h"
64 #include "utils_dates.h"
65 #include "utils_real.h"
66 #include "utils_str.h"
67 #include "erreur.h"
68 /*END_INCLUDE*/
69 
70 /*START_GLOBAL*/
71 /* lists of number of scheduled transactions taken or to be taken */
72 GSList *				scheduled_transactions_to_take;
73 GSList *				scheduled_transactions_taken;
74 /*END_GLOBAL*/
75 
76 /*START_EXTERN*/
77 /*END_EXTERN*/
78 
79 /*START_STATIC*/
80 /* the total of % of scheduled columns can be > 100 because all the columns are not showed at the same time */
81 static gint scheduler_col_width_init[SCHEDULER_COL_VISIBLE_COLUMNS] = {10, 12, 36, 12, 12, 24, 12};
82 
83 /* used to save and restore the width of the scheduled list */
84 static gint					scheduler_col_width[SCHEDULER_COL_VISIBLE_COLUMNS];
85 static gint					scheduler_current_tree_view_width = 0;
86 
87 /* set the tree view and models as static, we can access to them
88  * by the functions gsb_scheduler_list_get_tree_view...
89  * don't call them directly */
90 static GtkWidget *			tree_view_scheduler_list;
91 static GtkTreeModel *		tree_model_scheduler_list;
92 static GtkTreeModelSort *	tree_model_sort_scheduler_list;
93 static GtkSortType			sort_type;
94 static GtkTreeViewColumn *	scheduler_list_column[SCHEDULER_COL_VISIBLE_COLUMNS];
95 static gint					last_scheduled_number;
96 
97 /* première ope planifiee de la liste */
98 static gint					first_scheduler_list_number = -1;
99 
100 /* toolbar */
101 static GtkWidget *			scheduler_toolbar;
102 
103 /* Used to display/hide comments in scheduler list */
104 static GtkWidget *			scheduler_display_hide_notes = NULL;
105 
106 /* here are the 3 buttons on the scheduler toolbar
107  * which can been unsensitive or sensitive */
108 static GtkWidget *			scheduler_button_execute = NULL;
109 static GtkWidget *			scheduler_button_delete = NULL;
110 static GtkWidget *			scheduler_button_edit = NULL;
111 
112 /* popup view menu */
113 static const gchar *		periodicity_names[] = {N_("Unique view"), N_("Week view"), N_("Month view"),
114 												   N_("Two months view"), N_("Quarter view"),
115 												   N_("Year view"), N_("Custom view"), NULL,};
116 
117 static gboolean				view_menu_block_cb = FALSE;
118 
119 static const gchar *		j_m_a_names[] = {N_("days"), N_("weeks"), N_("months"), N_("years"), NULL};
120 /*END_STATIC*/
121 
122 /******************************************************************************/
123 /* Private functions                                                          */
124 /******************************************************************************/
125 /**
126  * called when the user choose a custom periodicity on the toolbar
127  *
128  * \param
129  *
130  * \return TRUE : did his choice, FALSE : cancel the choice
131  **/
gsb_scheduler_list_popup_custom_periodicity_dialog(void)132 static gboolean gsb_scheduler_list_popup_custom_periodicity_dialog (void)
133 {
134     GtkWidget *combobox;
135     GtkWidget *dialog;
136     GtkWidget *entry;
137     GtkWidget *hbox;
138     GtkWidget *hbox2;
139     GtkWidget *label;
140     GtkWidget *paddingbox;
141     int i;
142 
143     dialog = gtk_dialog_new_with_buttons (_("Show scheduled transactions"),
144 										  GTK_WINDOW (grisbi_app_get_active_window (NULL)),
145 										  GTK_DIALOG_MODAL,
146 										  "gtk-cancel", GTK_RESPONSE_CANCEL,
147 										  "gtk-apply", GTK_RESPONSE_OK,
148 										  NULL);
149 
150     gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
151     gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
152 
153     /* Ugly dance to avoid side effects on dialog's vbox. */
154     hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
155     gtk_box_pack_start (GTK_BOX (dialog_get_content_area (dialog)), hbox, FALSE, FALSE, 0);
156 	paddingbox = new_paddingbox_with_title (hbox, TRUE, _("Scheduler frequency"));
157     gtk_container_set_border_width (GTK_CONTAINER (hbox), MARGIN_BOX);
158     gtk_container_set_border_width (GTK_CONTAINER (paddingbox), MARGIN_BOX);
159 
160     hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
161     gtk_box_pack_start (GTK_BOX (paddingbox), hbox2, FALSE, FALSE, 0);
162 
163     label = gtk_label_new (_("Show transactions for the next: "));
164     gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
165     entry = gsb_automem_spin_button_new (&etat.affichage_echeances_perso_nb_libre, NULL, NULL);
166     gtk_box_pack_start (GTK_BOX (hbox2), entry, FALSE, FALSE, MARGIN_BOX);
167 
168     /* combobox for userdefined frequency */
169     combobox = gtk_combo_box_text_new ();
170     gtk_box_pack_start (GTK_BOX (hbox2), combobox, FALSE, FALSE, 0);
171 
172     for (i = 0; j_m_a_names[i]; i++)
173     {
174         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combobox), g_dgettext (NULL, j_m_a_names[i]));
175     }
176     gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), etat.affichage_echeances_perso_j_m_a);
177 
178     gtk_widget_show_all (dialog);
179 
180     switch (gtk_dialog_run (GTK_DIALOG (dialog)))
181     {
182 		case GTK_RESPONSE_OK:
183 			etat.affichage_echeances_perso_j_m_a = gtk_combo_box_get_active (GTK_COMBO_BOX (combobox));
184 			etat.affichage_echeances_perso_nb_libre = utils_str_atoi (gtk_entry_get_text (GTK_ENTRY(entry)));
185 			gtk_widget_destroy (dialog);
186 			return TRUE;
187     }
188 
189     gtk_widget_destroy (dialog);
190     return FALSE;
191 }
192 
193 /**
194  * called from the toolbar to change the scheduler view
195  *
196  * \param periodicity 	the new view wanted
197  * \param item		not used
198  *
199  * \return FALSE
200  **/
gsb_scheduler_list_change_scheduler_view(GtkWidget * item,gpointer pointer_periodicity)201 static void gsb_scheduler_list_change_scheduler_view (GtkWidget *item,
202 													  gpointer pointer_periodicity)
203 {
204     gchar *tmp_str;
205     gint periodicity;
206 
207     periodicity = GPOINTER_TO_INT (pointer_periodicity);
208     if (view_menu_block_cb || periodicity == etat.affichage_echeances)
209         return;
210 
211     if (periodicity == SCHEDULER_PERIODICITY_CUSTOM_VIEW)
212     {
213         if (!gsb_scheduler_list_popup_custom_periodicity_dialog ())
214             return;
215     }
216 
217     tmp_str = g_strconcat (_("Scheduled transactions"), " : ",
218 						   g_dgettext (NULL, periodicity_names[periodicity]),
219 						   NULL);
220     grisbi_win_headings_update_title (tmp_str);
221     grisbi_win_headings_update_suffix ("");
222     g_free (tmp_str);
223 
224     etat.affichage_echeances = periodicity;
225     gsb_scheduler_list_fill_list (gsb_scheduler_list_get_tree_view ());
226     gsb_scheduler_list_set_background_color (gsb_scheduler_list_get_tree_view ());
227     gsb_scheduler_list_select (-1);
228 
229     gsb_file_set_modified (TRUE);
230 
231     return;
232 }
233 
234 /**
235  * Called to edit a specific transaction but the number of transaction
236  * is passed via a pointer (by g_signal_connect)
237  *
238  * \param scheduled_number a pointer which is the number of the transaction
239  *
240  * \return FALSE
241  **/
gsb_scheduler_list_edit_transaction_by_pointer(gint * scheduled_number)242 static gboolean gsb_scheduler_list_edit_transaction_by_pointer (gint *scheduled_number)
243 {
244 	gint number;
245 
246 	number = GPOINTER_TO_INT (scheduled_number);
247 	devel_debug_int (number);
248 
249 	if (number == -1)
250 		gsb_scheduler_list_select (-1);
251 	gsb_scheduler_list_edit_transaction (number);
252 
253 	return FALSE;
254 }
255 
256 /**
257  * change the showed information on the list :
258  * either show the frequency and mode of the scheduled
259  * either show the notes
260  *
261  * \param
262  *
263  * \return FALSE
264  */
gsb_scheduler_list_show_notes(GtkWidget * item)265 static gboolean gsb_scheduler_list_show_notes (GtkWidget *item)
266 {
267     if (scheduler_display_hide_notes)
268     {
269 		GrisbiAppConf *a_conf;
270 
271 		a_conf = (GrisbiAppConf *) grisbi_app_get_a_conf ();
272 		if (a_conf->display_toolbar != GSB_BUTTON_ICON)
273         {
274             if (etat.affichage_commentaire_echeancier)
275                 gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), _("Frequency/Mode"));
276             else
277                 gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), _("Notes"));
278         }
279 
280         if (etat.affichage_commentaire_echeancier)
281             gtk_widget_set_tooltip_text (GTK_WIDGET (item),
282 										 _("Display the frequency and mode of scheduled transactions"));
283         else
284             gtk_widget_set_tooltip_text (GTK_WIDGET (item),
285 										 _("Display the notes of scheduled transactions"));
286     }
287 
288     gtk_tree_view_column_set_visible (GTK_TREE_VIEW_COLUMN (scheduler_list_column[COL_NB_FREQUENCY]),
289 									  !etat.affichage_commentaire_echeancier);
290     gtk_tree_view_column_set_visible (GTK_TREE_VIEW_COLUMN (scheduler_list_column[COL_NB_MODE]),
291 									  !etat.affichage_commentaire_echeancier);
292     gtk_tree_view_column_set_visible (GTK_TREE_VIEW_COLUMN (scheduler_list_column[COL_NB_NOTES]),
293 									  etat.affichage_commentaire_echeancier);
294 
295     etat.affichage_commentaire_echeancier = !etat.affichage_commentaire_echeancier;
296 
297     return FALSE;
298 }
299 
300 /**
301  * Pop up a menu with several actions to apply to current scheduled.
302  *
303  * \param
304  *
305  * \return
306  **/
gsb_scheduler_list_popup_scheduled_context_menu(GtkWidget * tree_view,GtkTreePath * path)307 static void gsb_scheduler_list_popup_scheduled_context_menu (GtkWidget *tree_view,
308 															 GtkTreePath *path)
309 {
310     GtkWidget *menu;
311     GtkWidget *menu_item;
312     GtkTreeModel *model;
313     GtkTreeIter iter;
314     gint scheduled_number;
315 	gint virtual_transaction;
316 
317 	menu = gtk_menu_new ();
318 
319 	/* Récupération des données de la ligne sélectionnée */
320 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
321     gtk_tree_model_get_iter (model, &iter, path);
322     gtk_tree_model_get (model,
323 						&iter,
324 						SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_transaction,
325 						SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_number,
326 						-1);
327 
328 	if (virtual_transaction)
329 		scheduled_number = 0;
330 
331     /* Edit transaction */
332 	menu_item = GTK_WIDGET (utils_menu_item_new_from_image_label ("gtk-edit-16.png", _("Edit transaction")));
333     g_signal_connect_swapped (G_OBJECT (menu_item),
334 							  "activate",
335                         	  G_CALLBACK (gsb_scheduler_list_edit_transaction_by_pointer),
336                         	  GINT_TO_POINTER (scheduled_number));
337     if (scheduled_number <= 0)
338         gtk_widget_set_sensitive (menu_item, FALSE);
339 
340     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
341 
342     /* Clone transaction */
343     menu_item = GTK_WIDGET (utils_menu_item_new_from_image_label ("gtk-copy-16.png", _("Clone transaction")));
344     g_signal_connect (G_OBJECT (menu_item),
345                        "activate",
346                        G_CALLBACK (gsb_scheduler_list_clone_selected_scheduled),
347                        GINT_TO_POINTER (scheduled_number));
348     if (scheduled_number <= 0)
349         gtk_widget_set_sensitive (menu_item, FALSE);
350 
351     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
352 
353     /* Separator */
354     gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
355 
356     /* New transaction */
357     menu_item = GTK_WIDGET (utils_menu_item_new_from_image_label  ("gsb-new-transaction-16.png",
358 																   _("New transaction")));
359     g_signal_connect_swapped (G_OBJECT (menu_item),
360                         	  "activate",
361                         	  G_CALLBACK (gsb_scheduler_list_edit_transaction_by_pointer),
362                         	  GINT_TO_POINTER (-1));
363     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
364 
365     /* Delete transaction */
366     menu_item = GTK_WIDGET (utils_menu_item_new_from_image_label ("gtk-delete-16.png", _("Delete transaction")));
367     g_signal_connect (G_OBJECT (menu_item),
368                        "activate",
369                        G_CALLBACK (gsb_scheduler_list_delete_scheduled_transaction_by_menu),
370                        NULL);
371 
372     if (scheduled_number <= 0)
373         gtk_widget_set_sensitive (menu_item, FALSE);
374 
375     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
376 
377     /* Separator */
378     gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
379 
380     /* Display/hide notes */
381     if (etat.affichage_commentaire_echeancier)
382         menu_item = GTK_WIDGET (utils_menu_item_new_from_image_label ("gsb-comments-16.png", _("Displays notes")));
383     else
384         menu_item = GTK_WIDGET (utils_menu_item_new_from_image_label ("gsb-comments-16.png",
385 																	  _("Displays Frequency/Mode")));
386 
387     g_signal_connect_swapped (G_OBJECT (menu_item),
388                         	  "activate",
389                         	  G_CALLBACK (gsb_scheduler_list_show_notes),
390                         	  scheduler_display_hide_notes);
391     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
392 
393     /* Separator */
394     gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
395 
396     /* Execute transaction */
397     menu_item = utils_menu_item_new_from_image_label ("gtk-execute-16.png",_("Execute transaction"));
398     g_signal_connect_swapped (G_OBJECT (menu_item),
399                         	  "activate",
400                         	  G_CALLBACK (gsb_scheduler_list_execute_transaction),
401                         	  NULL);
402     if (scheduled_number <= 0)
403         gtk_widget_set_sensitive (menu_item, FALSE);
404 
405     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
406 
407     /* Finish all. */
408     gtk_widget_show_all (menu);
409 
410 #if GTK_CHECK_VERSION (3,22,0)
411 	gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
412 #else
413 	gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
414 #endif
415 }
416 
417 /**
418  * called when the selection of the list change
419  *
420  * \param selection
421  * \param null not used
422  *
423  * \return FALSE
424  **/
gsb_scheduler_list_select_line(GtkWidget * tree_view,GtkTreePath * path)425 static void gsb_scheduler_list_select_line (GtkWidget *tree_view,
426 											GtkTreePath *path)
427 {
428     GtkTreeModel *model;
429     GtkTreeIter iter;
430 	gint virtual_transaction;
431     gint tmp_number = 0;
432     gint account_number;
433 	GrisbiAppConf *a_conf;
434 
435 	devel_debug (NULL);
436 	a_conf = (GrisbiAppConf *) grisbi_app_get_a_conf ();
437 
438 	/* Récupération des données de la ligne sélectionnée */
439 	model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
440     gtk_tree_model_get_iter (model, &iter, path);
441     gtk_tree_model_get (model,
442 						&iter,
443 						SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_transaction,
444 						SCHEDULER_COL_NB_TRANSACTION_NUMBER, &tmp_number,
445 						-1);
446 
447 	if (virtual_transaction)
448 		tmp_number = 0;
449 
450 	/* protect last_scheduled_number because when refill the list, set selection to 0 and so last_scheduled_number... */
451 	last_scheduled_number = tmp_number;
452 
453     /* if a_conf->show_transaction_selected_in_form => edit the scheduled transaction */
454     if (tmp_number != 0 && a_conf->show_transaction_selected_in_form)
455             gsb_scheduler_list_edit_transaction (tmp_number);
456     else if (tmp_number == 0)
457     {
458         gsb_form_scheduler_clean ();
459         account_number = gsb_data_scheduled_get_account_number (tmp_number);
460         gsb_form_clean (account_number);
461     }
462 
463     /* sensitive/unsensitive the button execute */
464     gtk_widget_set_sensitive (scheduler_button_execute,
465 							  (tmp_number > 0)
466 							  && !gsb_data_scheduled_get_mother_scheduled_number (tmp_number));
467 
468     /* sensitive/unsensitive the button edit */
469     gtk_widget_set_sensitive (scheduler_button_edit, (tmp_number > 0));
470 
471     /* sensitive/unsensitive the button delete */
472     gtk_widget_set_sensitive (scheduler_button_delete, (tmp_number > 0));
473 
474     gsb_menu_set_menus_select_scheduled_sensitive (tmp_number > 0);
475 }
476 
477 /**
478  * called when we press a button on the list
479  *
480  * \param tree_view
481  * \param ev
482  *
483  * \return FALSE
484  **/
gsb_scheduler_list_button_press(GtkWidget * tree_view,GdkEventButton * ev)485 static gboolean gsb_scheduler_list_button_press (GtkWidget *tree_view,
486 												 GdkEventButton *ev)
487 {
488 	if (ev->button == RIGHT_BUTTON)
489 	{
490         GtkTreePath *path = NULL;
491 
492 		/* show the popup */
493         if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view ), ev->x, ev->y, &path, NULL, NULL, NULL))
494         {
495             gsb_scheduler_list_popup_scheduled_context_menu (tree_view, path);
496             gtk_tree_path_free (path);
497         }
498 	}
499 
500     else if (ev->type == GDK_2BUTTON_PRESS)
501     {
502          /* if double-click => edit the scheduled transaction */
503         gint current_scheduled_number;
504 
505         current_scheduled_number = gsb_scheduler_list_get_current_scheduled_number ();
506 
507         if (current_scheduled_number)
508             gsb_scheduler_list_edit_transaction (current_scheduled_number);
509     }
510 	else if (ev->button == LEFT_BUTTON)
511 	{
512         GtkTreePath *path = NULL;
513 
514 		/* select line */
515         if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view ), ev->x, ev->y, &path, NULL, NULL, NULL))
516         {
517             gsb_scheduler_list_select_line (tree_view, path);
518             gtk_tree_path_free (path);
519         }
520 	}
521 
522     return FALSE;
523 }
524 
525 /**
526  * affichage du popup view menu
527  *
528  * \param button
529  * \param event
530  * \param user data
531  *
532  * \return
533  */
gsb_scheduler_list_popup_scheduler_view(GtkWidget * button,GdkEvent * event,gpointer user_data)534 static gboolean gsb_scheduler_list_popup_scheduler_view (GtkWidget *button,
535 														 GdkEvent  *event,
536 														 gpointer   user_data)
537 {
538     GtkWidget *menu, *item;
539     GSList *group = NULL;
540     gint nbre_echeances;
541     gint i;
542 
543     view_menu_block_cb = TRUE;
544     menu = gtk_menu_new ();
545 
546     /* on enlève la ligne blanche */
547     nbre_echeances = gtk_tree_model_iter_n_children (tree_model_scheduler_list, NULL) - 1;
548 
549     for (i = 0 ; periodicity_names[i] ; i++)
550     {
551         gchar *tmp_str;
552 
553         if (i == etat.affichage_echeances)
554         {
555             if (i == SCHEDULER_PERIODICITY_CUSTOM_VIEW)
556             {
557                 tmp_str = g_strdup_printf ("%s (%d - %d %s)",
558 										   g_dgettext (NULL, periodicity_names[i]),
559                                 		   nbre_echeances,
560                                 		   etat.affichage_echeances_perso_nb_libre,
561                                 		   g_dgettext (NULL,
562                                 		   j_m_a_names[etat.affichage_echeances_perso_j_m_a]));
563             }
564             else
565             {
566                 tmp_str = g_strdup_printf ("%s (%d)",
567 										   g_dgettext (NULL, periodicity_names[i]),
568 										   nbre_echeances);
569             }
570             item = gtk_radio_menu_item_new_with_label (group, tmp_str);
571 
572             g_free (tmp_str);
573         }
574         else
575             item = gtk_radio_menu_item_new_with_label (group, g_dgettext (NULL, periodicity_names[i]));
576 
577         group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
578         if (i == etat.affichage_echeances)
579             gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
580 
581         g_signal_connect (G_OBJECT (item),
582 						  "toggled",
583 						  G_CALLBACK (gsb_scheduler_list_change_scheduler_view),
584 						  GINT_TO_POINTER (i));
585 
586         gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
587     }
588 
589     gtk_widget_show_all (menu);
590 #if GTK_CHECK_VERSION (3,22,0)
591 	gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
592 #else
593     gtk_menu_popup (GTK_MENU (menu), NULL, button, set_popup_position, button, 1, gtk_get_current_event_time ());
594 #endif
595     view_menu_block_cb = FALSE;
596 
597     return TRUE;
598 }
599 
600 /**
601  * default sorting function for scheduler list :
602  * sort by date, the column number 0
603  * perhaps later sort by different columns ??
604  *
605  * \param
606  * \param
607  * \param
608  * \param
609  *
610  * \return the result of comparison
611  **/
gsb_scheduler_list_default_sort_function(GtkTreeModel * model,GtkTreeIter * iter_1,GtkTreeIter * iter_2,gpointer null)612 static gint gsb_scheduler_list_default_sort_function (GtkTreeModel *model,
613 													  GtkTreeIter *iter_1,
614 													  GtkTreeIter *iter_2,
615 													  gpointer null)
616 {
617     GDate *date_1;
618     GDate *date_2;
619     gchar *date_str;
620     gint number_1;
621     gint number_2;
622     gint return_value = 0;
623 
624     /* first, we sort by date (col 0) */
625     gtk_tree_model_get (model,
626                         iter_1,
627                         COL_NB_DATE, &date_str,
628                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &number_1,
629                         -1);
630     date_1 = gsb_parse_date_string (date_str);
631     g_free (date_str);
632 
633     gtk_tree_model_get (model,
634                         iter_2,
635                         COL_NB_DATE, &date_str,
636                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &number_2,
637                         -1);
638     date_2 = gsb_parse_date_string (date_str);
639     g_free (date_str);
640 
641     if (number_1 == -1)
642     {
643         if (date_1) g_date_free (date_1);
644         if (date_2) g_date_free (date_2);
645         if (sort_type == GTK_SORT_ASCENDING)
646             return 1;
647         else
648             return -1;
649     }
650     else if (number_2 == -1)
651     {
652         if (date_1) g_date_free (date_1);
653         if (date_2) g_date_free (date_2);
654         if (sort_type == GTK_SORT_ASCENDING)
655             return -1;
656         else
657             return 1;
658     }
659 
660     if (date_1 &&  date_2)
661         return_value = g_date_compare (date_1, date_2);
662 
663     if (return_value)
664     {
665         if (date_1) g_date_free (date_1);
666         if (date_2) g_date_free (date_2);
667 
668         return return_value;
669     }
670     /* if we are here it's because we are in a child of split */
671     if (number_1 < 0)
672     {
673         if (sort_type == GTK_SORT_ASCENDING)
674             return 1;
675         else
676             return -1;
677     }
678     if (number_2 < 0)
679     {
680         if (sort_type == GTK_SORT_ASCENDING)
681             return -1;
682         else
683             return 1;
684     }
685 
686     if (!return_value)
687         return_value = number_1 - number_2;
688 
689     if (date_1) g_date_free (date_1);
690     if (date_2) g_date_free (date_2);
691 
692     return return_value;
693 }
694 
695 /**
696  *
697  *
698  * \param
699  * \param
700  *
701  * \return
702  **/
gsb_scheduler_list_sort_column_clicked(GtkTreeViewColumn * tree_view_column,gint * column_ptr)703 static gboolean gsb_scheduler_list_sort_column_clicked (GtkTreeViewColumn *tree_view_column,
704 														gint *column_ptr)
705 {
706     gint current_column;
707     gint new_column;
708 
709     gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (tree_model_sort_scheduler_list),
710 										  &current_column,
711 										  &sort_type);
712 
713     new_column = GPOINTER_TO_INT (column_ptr);
714 
715     /* if the new column is the same as the old one, we change the sort type */
716     if (new_column == current_column)
717     {
718         if (sort_type == GTK_SORT_ASCENDING)
719             sort_type = GTK_SORT_DESCENDING;
720         else
721             sort_type = GTK_SORT_ASCENDING;
722     }
723     else
724 	/* we sort by another column, so sort type by default is descending */
725 	sort_type = GTK_SORT_ASCENDING;
726 
727     gtk_tree_view_column_set_sort_indicator (scheduler_list_column[current_column], FALSE);
728     gtk_tree_view_column_set_sort_indicator (scheduler_list_column[new_column], TRUE);
729 
730     gtk_tree_view_column_set_sort_order (scheduler_list_column[new_column], sort_type);
731     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (tree_model_sort_scheduler_list),
732 										  new_column,
733 										  sort_type);
734 
735     gsb_scheduler_list_set_background_color (gsb_scheduler_list_get_tree_view ());
736 
737     if (last_scheduled_number > 0)
738         gsb_scheduler_list_select (last_scheduled_number);
739     else
740         gsb_scheduler_list_select (-1);
741 
742     return FALSE;
743 }
744 
745 /**
746  *
747  *
748  * \param
749  * \param
750  * \param
751  * \param
752  *
753  * \return
754  **/
gsb_scheduler_list_sort_function_by_account(GtkTreeModel * model,GtkTreeIter * iter_1,GtkTreeIter * iter_2,gint * column_ptr)755 static gint gsb_scheduler_list_sort_function_by_account (GtkTreeModel *model,
756 														 GtkTreeIter *iter_1,
757                         								 GtkTreeIter *iter_2,
758                         								 gint *column_ptr)
759 {
760     gchar *str_1;
761     gchar *str_2;
762     gint number_1;
763     gint number_2;
764     gint virtual_op_1 = 0;
765     gint virtual_op_2 = 0;
766     gint return_value = 0;
767 
768     /* first, we sort by account (col 0) */
769     gtk_tree_model_get (model,
770                         iter_1,
771                         COL_NB_ACCOUNT, &str_1,
772                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &number_1,
773                         SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_op_1,
774                         -1);
775 
776     gtk_tree_model_get (model,
777                         iter_2,
778                         COL_NB_ACCOUNT, &str_2,
779                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &number_2,
780                         SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_op_2,
781                         -1);
782 
783     if (number_1 == -1)
784     {
785         if (sort_type == GTK_SORT_ASCENDING)
786             return 1;
787         else
788             return -1;
789     }
790     else if (number_2 == -1)
791     {
792         if (sort_type == GTK_SORT_ASCENDING)
793             return -1;
794         else
795             return 1;
796     }
797 
798     if (sort_type == GTK_SORT_ASCENDING)
799         return_value = virtual_op_1 - virtual_op_2;
800     else
801         return_value = virtual_op_2 - virtual_op_1;
802 
803     if (return_value)
804         return return_value;
805 
806     if (str_1)
807     {
808         if (str_2)
809             return_value = g_utf8_collate (str_1, str_2);
810         else
811         {
812             g_free (str_1);
813             return -1;
814         }
815     }
816     else if (str_2)
817     {
818         g_free (str_2);
819         if (sort_type == GTK_SORT_ASCENDING)
820             return 1;
821         else
822             return -1;
823     }
824 
825     if (return_value == 0)
826         return_value = number_1 - number_2;
827 
828     g_free (str_1);
829     g_free (str_2);
830 
831     return return_value;
832 }
833 
834 /**
835  *
836  *
837  * \param
838  * \param
839  * \param
840  * \param
841  *
842  * \return
843  **/
gsb_scheduler_list_sort_function_by_payee(GtkTreeModel * model,GtkTreeIter * iter_1,GtkTreeIter * iter_2,gint * column_ptr)844 static gint gsb_scheduler_list_sort_function_by_payee (GtkTreeModel *model,
845 													   GtkTreeIter *iter_1,
846                         							   GtkTreeIter *iter_2,
847                         							   gint *column_ptr)
848 {
849     gchar *str_1;
850     gchar *str_2;
851     gint number_1;
852     gint number_2;
853     gint virtual_op_1 = 0;
854     gint virtual_op_2 = 0;
855     gint return_value = 0;
856 
857     /* first, we sort by payee (col 0) */
858     gtk_tree_model_get (model,
859                         iter_1,
860                         COL_NB_PARTY, &str_1,
861                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &number_1,
862                         SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_op_1,
863                         -1);
864 
865     gtk_tree_model_get (model,
866                         iter_2,
867                         COL_NB_PARTY, &str_2,
868                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &number_2,
869                         SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_op_2,
870                         -1);
871 
872     if (number_1 == -1)
873     {
874         if (sort_type == GTK_SORT_ASCENDING)
875             return 1;
876         else
877             return -1;
878     }
879     else if (number_2 == -1)
880     {
881         if (sort_type == GTK_SORT_ASCENDING)
882             return -1;
883         else
884             return 1;
885     }
886 
887     if (sort_type == GTK_SORT_ASCENDING)
888         return_value = virtual_op_1 - virtual_op_2;
889     else
890         return_value = virtual_op_2 - virtual_op_1;
891 
892     if (return_value)
893         return return_value;
894 
895     if (str_1)
896     {
897         if (str_2)
898             return_value = g_utf8_collate (str_1, str_2);
899         else
900         {
901             g_free (str_1);
902             return -1;
903         }
904     }
905     else if (str_2)
906     {
907         g_free (str_2);
908         if (sort_type == GTK_SORT_ASCENDING)
909             return 1;
910         else
911             return -1;
912     }
913 
914     if (return_value == 0)
915         return_value = number_1 - number_2;
916 
917     g_free (str_1);
918     g_free (str_2);
919 
920     return return_value;
921 }
922 
923 /**
924  * create and append the columns of the tree_view
925  *
926  * \param tree_view the tree_view
927  *
928  * \return
929  **/
gsb_scheduler_list_create_list_columns(GtkWidget * tree_view)930 static void gsb_scheduler_list_create_list_columns (GtkWidget *tree_view)
931 {
932     gint i;
933     const gchar *scheduler_titles[] = {N_("Date"), N_("Account"), N_("Payee"),
934 									   N_("Frequency"), N_("Mode"), N_("Notes"), N_("Amount")};
935     gfloat col_justs[] =
936 	{
937 		COLUMN_CENTER, COLUMN_LEFT, COLUMN_LEFT, COLUMN_CENTER,
938 		COLUMN_CENTER, COLUMN_LEFT, COLUMN_RIGHT, COLUMN_RIGHT
939     };
940 
941     for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS ; i++)
942     {
943         GtkCellRenderer *cell_renderer;
944 
945         cell_renderer = gtk_cell_renderer_text_new ();
946 
947         gtk_cell_renderer_set_alignment (GTK_CELL_RENDERER (cell_renderer), col_justs[i], 0);
948         switch (i)
949         {
950             case 0:
951                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
952 																					 cell_renderer,
953                                             										 "text", i,
954                                             										 "cell-background-rgba",
955 																					 SCHEDULER_COL_NB_BACKGROUND,
956                                             										 "font-desc",
957 																					 SCHEDULER_COL_NB_FONT,
958                                             										 "foreground",
959 																					 SCHEDULER_COL_NB_TEXT_COLOR,
960 									      										 	 NULL);
961                 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (tree_model_sort_scheduler_list),
962 												 i,
963                                             	 (GtkTreeIterCompareFunc) gsb_scheduler_list_default_sort_function,
964                                             	 NULL,
965                                             	 NULL);
966                 gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]), TRUE);
967 
968                 /* use the click to sort the list */
969                 g_signal_connect (G_OBJECT (scheduler_list_column[i]),
970 								  "clicked",
971 								  G_CALLBACK (gsb_scheduler_list_sort_column_clicked),
972 								  GINT_TO_POINTER (i));
973                 break;
974             case 1:
975                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
976                                             										 cell_renderer,
977                                             										 "text", i,
978                                             										 "cell-background-rgba",
979 																					 SCHEDULER_COL_NB_BACKGROUND,
980                                             										 "font-desc",
981 																					 SCHEDULER_COL_NB_FONT,
982                                             										 "foreground",
983 																					 SCHEDULER_COL_NB_TEXT_COLOR,
984                                             										 NULL);
985                 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (tree_model_sort_scheduler_list),
986                                             	 i,
987                                             	 (GtkTreeIterCompareFunc) gsb_scheduler_list_sort_function_by_account,
988                                             	 NULL,
989                                             	 NULL);
990                 gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]), TRUE);
991 
992                 /* use the click to sort the list */
993                 g_signal_connect (G_OBJECT (scheduler_list_column[i]),
994 								  "clicked",
995 								  G_CALLBACK (gsb_scheduler_list_sort_column_clicked),
996 								  GINT_TO_POINTER (i));
997                 break;
998             case 2:
999                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
1000                                             										 cell_renderer,
1001                                             										 "text", i,
1002                                             										 "cell-background-rgba",
1003 																					 SCHEDULER_COL_NB_BACKGROUND,
1004                                             										 "font-desc",
1005 																					 SCHEDULER_COL_NB_FONT,
1006                                             										 "foreground",
1007 																					 SCHEDULER_COL_NB_TEXT_COLOR,
1008                                             										 NULL);
1009                 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (tree_model_sort_scheduler_list),
1010                                             	 i,
1011                                             	 (GtkTreeIterCompareFunc) gsb_scheduler_list_sort_function_by_payee,
1012                                             	 NULL,
1013                                             	 NULL);
1014                 gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]), TRUE);
1015 
1016                 /* use the click to sort the list */
1017                 g_signal_connect (G_OBJECT (scheduler_list_column[i]),
1018 								  "clicked",
1019 								  G_CALLBACK (gsb_scheduler_list_sort_column_clicked),
1020 								  GINT_TO_POINTER (i));
1021                 break;
1022             case 3:
1023                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
1024                                             										 cell_renderer,
1025                                             										 "text", i,
1026                                             										 "cell-background-rgba",
1027 																					 SCHEDULER_COL_NB_BACKGROUND,
1028                                             										 "font-desc",
1029 																					 SCHEDULER_COL_NB_FONT,
1030                                             										 "foreground",
1031 																					 SCHEDULER_COL_NB_TEXT_COLOR,
1032                                             										 NULL);
1033                 break;
1034             case 4:
1035                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
1036                                             										 cell_renderer,
1037                                             										 "text", i,
1038                                             										 "cell-background-rgba",
1039 																					 SCHEDULER_COL_NB_BACKGROUND,
1040                                             										 "font-desc",
1041 																					 SCHEDULER_COL_NB_FONT,
1042                                             										 "foreground",
1043 																					 SCHEDULER_COL_NB_TEXT_COLOR,
1044                                             										 NULL);
1045                 break;
1046             case 5:
1047                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
1048                                             										 cell_renderer,
1049                                             										 "text", i,
1050                                             										 "cell-background-rgba",
1051 																					 SCHEDULER_COL_NB_BACKGROUND,
1052                                             										 "font-desc",
1053 																					 SCHEDULER_COL_NB_FONT,
1054                                             										 "foreground",
1055 																					 SCHEDULER_COL_NB_TEXT_COLOR,
1056                                             										 NULL);
1057                 break;
1058             case 6:
1059                 scheduler_list_column[i] = gtk_tree_view_column_new_with_attributes (gettext (scheduler_titles[i]),
1060                                             										 cell_renderer,
1061                                             										 "text", i,
1062                                             										 "cell-background-rgba",
1063 																					 SCHEDULER_COL_NB_BACKGROUND,
1064                                             										 "foreground",
1065 																					 SCHEDULER_COL_NB_AMOUNT_COLOR,
1066                                             										 "font-desc",
1067 																					 SCHEDULER_COL_NB_FONT,
1068                                             										 NULL);
1069 				gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (cell_renderer), MARGIN_BOX, 0);
1070                 break;
1071         }
1072 
1073         gtk_tree_view_column_set_alignment (GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]), col_justs[i]);
1074 
1075         gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
1076                           GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]));
1077 
1078         /* automatic and resizeable sizing */
1079         gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]),
1080                           GTK_TREE_VIEW_COLUMN_FIXED);
1081         gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (scheduler_list_column[i]), TRUE);
1082     }
1083 }
1084 
1085 /**
1086  * set the scheduler tree_model
1087  *
1088  * \param model
1089  *
1090  * \return
1091  **/
gsb_scheduler_list_set_model(GtkTreeModel * model)1092 static void gsb_scheduler_list_set_model (GtkTreeModel *model)
1093 {
1094     tree_model_scheduler_list = model;
1095 }
1096 
1097 /**
1098  * set the scheduler tree  model sort
1099  *
1100  * \param tree_model_sort
1101  *
1102  * \return
1103  **/
gsb_scheduler_list_set_sorted_model(GtkTreeModelSort * tree_model_sort)1104 static void gsb_scheduler_list_set_sorted_model (GtkTreeModelSort *tree_model_sort)
1105 {
1106     tree_model_sort_scheduler_list = tree_model_sort;
1107 }
1108 
1109 /**
1110  * create and return the tree store of the scheduler list
1111  *
1112  * \param
1113  *
1114  * \return a gtk_tree_store
1115  **/
gsb_scheduler_list_create_model(void)1116 static GtkTreeModel *gsb_scheduler_list_create_model (void)
1117 {
1118     GtkTreeStore *store;
1119     GtkTreeModel *sortable;
1120 
1121     store = gtk_tree_store_new (SCHEDULER_COL_NB_TOTAL,
1122 								G_TYPE_STRING,					/* COL_NB_DATE */
1123 				 				G_TYPE_STRING,					/* COL_NB_ACCOUNT */
1124 				 				G_TYPE_STRING,					/* COL_NB_PARTY */
1125 				 				G_TYPE_STRING,					/* COL_NB_FREQUENCY */
1126 				 				G_TYPE_STRING,					/* COL_NB_MODE */
1127 				 				G_TYPE_STRING,					/* COL_NB_NOTES */
1128 				 				G_TYPE_STRING,					/* COL_NB_AMOUNT */
1129 				 				GDK_TYPE_RGBA,					/* SCHEDULER_COL_NB_BACKGROUND */
1130 				 				GDK_TYPE_RGBA,					/* SCHEDULER_COL_NB_SAVE_BACKGROUND */
1131 				 				G_TYPE_STRING,					/* SCHEDULER_COL_NB_AMOUNT_COLOR */
1132 				 				G_TYPE_INT,						/* SCHEDULER_COL_NB_TRANSACTION_NUMBER */
1133 				 				PANGO_TYPE_FONT_DESCRIPTION,	/* SCHEDULER_COL_NB_FONT */
1134 				 				G_TYPE_INT,						/* SCHEDULER_COL_NB_VIRTUAL_TRANSACTION */
1135 				 				G_TYPE_STRING);					/* SCHEDULER_COL_NB_TEXT_COLOR */
1136 
1137     gsb_scheduler_list_set_model (GTK_TREE_MODEL (store));
1138     sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1139     gsb_scheduler_list_set_sorted_model (GTK_TREE_MODEL_SORT (sortable));
1140     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (tree_model_sort_scheduler_list), 0, GTK_SORT_ASCENDING);
1141     gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sortable),
1142 											 (GtkTreeIterCompareFunc) gsb_scheduler_list_default_sort_function,
1143 											 NULL,
1144 											 NULL);
1145 
1146     return sortable;
1147 }
1148 
1149 /**
1150  * Create the toolbar that contains all elements needed to manipulate
1151  * the scheduler.
1152  *
1153  * \param
1154  *
1155  * \return A newly created hbox.
1156  **/
gsb_scheduler_list_create_toolbar(void)1157 static GtkWidget *gsb_scheduler_list_create_toolbar (void)
1158 {
1159     GtkWidget *toolbar;
1160     GtkToolItem *item;
1161 
1162     toolbar = gtk_toolbar_new ();
1163 
1164     /* new scheduled button */
1165     item = utils_buttons_tool_button_new_from_image_label ("gsb-new-scheduled-24.png", _("New scheduled"));
1166     gtk_widget_set_tooltip_text (GTK_WIDGET (item),
1167 								 _("Prepare form to create a new scheduled transaction"));
1168     g_signal_connect_swapped (G_OBJECT (item),
1169 							  "clicked",
1170 							  G_CALLBACK (gsb_scheduler_list_edit_transaction),
1171 							  GINT_TO_POINTER (-1));
1172     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
1173 
1174     /* delete button */
1175     scheduler_button_delete = GTK_WIDGET (utils_buttons_tool_button_new_from_image_label ("gtk-delete-24.png",
1176 																						  _("Delete")));
1177     gtk_widget_set_sensitive (scheduler_button_delete, FALSE);
1178     gtk_widget_set_tooltip_text (GTK_WIDGET (scheduler_button_delete),
1179 								 _("Delete selected scheduled transaction"));
1180     g_signal_connect (G_OBJECT (scheduler_button_delete),
1181                         "clicked",
1182                         G_CALLBACK (gsb_scheduler_list_delete_scheduled_transaction_by_menu),
1183                         NULL);
1184     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (scheduler_button_delete), -1);
1185 
1186     /* edit button */
1187     scheduler_button_edit = GTK_WIDGET (utils_buttons_tool_button_new_from_image_label ("gtk-edit-24.png", _("Edit")));
1188     gtk_widget_set_sensitive (scheduler_button_edit, FALSE);
1189     gtk_widget_set_tooltip_text (GTK_WIDGET (scheduler_button_edit), _("Edit selected transaction"));
1190     g_signal_connect_swapped (G_OBJECT (scheduler_button_edit),
1191 										"clicked",
1192                         				G_CALLBACK (gsb_scheduler_list_edit_transaction),
1193                         				0);
1194     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (scheduler_button_edit), -1);
1195 
1196     /* Display/hide comments */
1197     scheduler_display_hide_notes = GTK_WIDGET (utils_buttons_tool_button_new_from_image_label ("gsb-comments-24.png",
1198 																							   _("Notes")));
1199     gtk_widget_set_tooltip_text (GTK_WIDGET (scheduler_display_hide_notes),
1200 								 _("Display the notes of scheduled transactions"));
1201     g_signal_connect (G_OBJECT (scheduler_display_hide_notes),
1202                       "clicked",
1203                       G_CALLBACK (gsb_scheduler_list_show_notes),
1204                       NULL);
1205     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (scheduler_display_hide_notes), -1);
1206 
1207     /* Execute transaction */
1208     scheduler_button_execute = GTK_WIDGET (utils_buttons_tool_button_new_from_image_label ("gtk-execute-24.png",
1209 																						   _("Execute")));
1210     gtk_widget_set_sensitive (scheduler_button_execute, FALSE);
1211     gtk_widget_set_tooltip_text (GTK_WIDGET (scheduler_button_execute), _("Execute current scheduled transaction"));
1212     g_signal_connect_swapped (G_OBJECT (scheduler_button_execute),
1213 							  "clicked",
1214                         	  G_CALLBACK (gsb_scheduler_list_execute_transaction),
1215                         	  NULL);
1216     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (scheduler_button_execute), -1);
1217 
1218 	/* View button */
1219     item = utils_buttons_tool_button_new_from_image_label ("gtk-select-color-24.png", _("View"));
1220     gtk_widget_set_tooltip_text (GTK_WIDGET (item),
1221 								 _("Change display mode of scheduled transaction list"));
1222     g_signal_connect (G_OBJECT (item),
1223                       "clicked",
1224                       G_CALLBACK (gsb_scheduler_list_popup_scheduler_view),
1225                       NULL);
1226     gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
1227 
1228     return toolbar;
1229 }
1230 
1231 /**
1232  * return the scheduler tree_model
1233  *
1234  * \param
1235  *
1236  * \return the scheduler tree_model
1237  **/
gsb_scheduler_list_get_model(void)1238 static GtkTreeModel *gsb_scheduler_list_get_model (void)
1239 {
1240     return tree_model_scheduler_list;
1241 }
1242 
1243 /**
1244  * get the iter of the scheduled transaction given in param
1245  *
1246  * \param scheduled_number
1247  *
1248  * \return a newly allocated GtkTreeIter or NULL if not found
1249  **/
gsb_scheduler_list_get_iter_from_scheduled_number(gint scheduled_number)1250 static GtkTreeIter *gsb_scheduler_list_get_iter_from_scheduled_number (gint scheduled_number)
1251 {
1252     GtkTreeIter iter;
1253     GtkTreeModel *model;
1254 
1255     model = GTK_TREE_MODEL (gsb_scheduler_list_get_model ());
1256 
1257     if (!scheduled_number || !model)
1258 		return NULL;
1259 
1260     /* we go through the list in the model untill we find the transaction */
1261     if (gtk_tree_model_get_iter_first (model, &iter))
1262     {
1263 		do
1264 		{
1265 			GtkTreeIter iter_child;
1266 			gint scheduled_number_tmp;
1267 
1268 			gtk_tree_model_get (GTK_TREE_MODEL (model),
1269 								&iter,
1270 								SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_number_tmp,
1271 								-1);
1272 			if (scheduled_number == scheduled_number_tmp)
1273 				return (gtk_tree_iter_copy (&iter));
1274 
1275 			/* gtk_tree_iter_next doesn't go in the children, so if the current transaction
1276 			 * has children, we have to look for the transaction here, and go down into the children */
1277 			if (gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &iter_child, &iter))
1278 			{
1279 				/* ok so iter_child is on a split child, we go to see all the splits */
1280 				do
1281 				{
1282 					gtk_tree_model_get (GTK_TREE_MODEL (model),
1283 										&iter_child,
1284 										SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_number_tmp,
1285 										-1);
1286 					if (scheduled_number == scheduled_number_tmp)
1287 						return (gtk_tree_iter_copy (&iter_child));
1288 				}
1289 			while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model),&iter_child));
1290 			}
1291 		}
1292 		while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model),&iter));
1293 
1294     }
1295     return NULL;
1296 }
1297 
1298 /**
1299  * switch the expander of the split given in param
1300  *
1301  * \param scheduled_number the scheduled split we want to switch
1302  *
1303  * \return FALSE
1304  **/
gsb_scheduler_list_switch_expander(gint scheduled_number)1305 static gboolean gsb_scheduler_list_switch_expander (gint scheduled_number)
1306 {
1307     GtkTreeIter *iter;
1308     GtkTreePath *path;
1309     GtkTreePath *path_sorted;
1310 
1311     if (!gsb_data_scheduled_get_split_of_scheduled (scheduled_number)
1312 	 || !tree_view_scheduler_list)
1313 		return FALSE;
1314 
1315     iter = gsb_scheduler_list_get_iter_from_scheduled_number (scheduled_number);
1316 
1317     path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_scheduler_list), iter);
1318     path_sorted = gtk_tree_model_sort_convert_child_path_to_path (tree_model_sort_scheduler_list, path);
1319     if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (tree_view_scheduler_list), path_sorted))
1320 		gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view_scheduler_list), path_sorted);
1321     else
1322 		gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view_scheduler_list), path_sorted, FALSE);
1323     gtk_tree_path_free (path);
1324     gtk_tree_path_free (path_sorted);
1325     gtk_tree_iter_free (iter);
1326 
1327     return FALSE;
1328 }
1329 
1330 /**
1331  * called when a key is pressed on the scheduled transactions list
1332  *
1333  * \param tree_view
1334  * \param ev
1335  *
1336  * \return FALSE
1337  **/
gsb_scheduler_list_key_press(GtkWidget * tree_view,GdkEventKey * ev)1338 static gboolean gsb_scheduler_list_key_press (GtkWidget *tree_view,
1339 											  GdkEventKey *ev)
1340 {
1341     gint scheduled_number;
1342 
1343     scheduled_number = gsb_scheduler_list_get_current_scheduled_number ();
1344 
1345     switch (ev->keyval)
1346     {
1347 		case GDK_KEY_Return :		/* touches entrée */
1348 		case GDK_KEY_KP_Enter :
1349 
1350 			if (scheduled_number)
1351 				gsb_scheduler_list_edit_transaction (scheduled_number);
1352 			break;
1353 
1354 
1355 		case GDK_KEY_Delete :               /*  del  */
1356 
1357 			if (scheduled_number > 0)
1358 				gsb_scheduler_list_delete_scheduled_transaction (scheduled_number, TRUE);
1359 			break;
1360 
1361 		case GDK_KEY_Left:
1362 			/* if we press left, give back the focus to the tree at left */
1363 			gtk_widget_grab_focus (gsb_gui_navigation_get_tree_view ());
1364 			break;
1365 
1366 		case GDK_KEY_space:
1367 			/* space open/close a split */
1368 			gsb_scheduler_list_switch_expander (scheduled_number);
1369 			break;
1370     }
1371     return (FALSE);
1372 }
1373 
1374 /**
1375  * called when the size of the tree view changed, to keep the same ration
1376  * between the columns
1377  *
1378  * \param tree_view	    the tree view of the scheduled transactions list
1379  * \param allocation	the new size
1380  * \param null
1381  *
1382  * \return FALSE
1383  **/
gsb_scheduler_list_size_allocate(GtkWidget * tree_view,GtkAllocation * allocation,gpointer null)1384 static void gsb_scheduler_list_size_allocate (GtkWidget *tree_view,
1385 											  GtkAllocation *allocation,
1386 											  gpointer null)
1387 {
1388     gint i;
1389 	//~ devel_debug_int (allocation->width);
1390 
1391 	if (gsb_gui_navigation_get_current_page () != GSB_SCHEDULER_PAGE)
1392 		return;
1393 
1394 	if (allocation->width == scheduler_current_tree_view_width)
1395     {
1396 		gint somme = 0;
1397 
1398         /* size of the tree view didn't change, but we received an allocated signal
1399          * it happens several times, and especially when we change the columns,
1400          * so we update the colums */
1401 
1402         /* sometimes, when the list is not visible, he will set all the columns to 1%...
1403          * we block that here */
1404         if (gtk_tree_view_column_get_width (scheduler_list_column[0]) == 1)
1405             return;
1406 
1407         for (i=0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS -1; i++)
1408         {
1409 			if (gtk_tree_view_column_get_visible (scheduler_list_column[i]))
1410 			{
1411 				scheduler_col_width[i] = (gtk_tree_view_column_get_width (
1412 										  scheduler_list_column[i]) * 100) / allocation->width + 1;
1413 				somme+= scheduler_col_width[i];
1414 			}
1415 		}
1416 		scheduler_col_width[i] = 100 - somme;
1417 		gsb_file_set_modified (TRUE);
1418 
1419 		return;
1420     }
1421 
1422     /* the size of the tree view changed, we keep the ration between the columns,
1423      * we don't set the size of the last column to avoid the calculate problems,
1424      * it will take the end of the width alone */
1425     scheduler_current_tree_view_width = allocation->width;
1426 
1427 	for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS -1 ; i++)
1428     {
1429         gint width;
1430 
1431         width = (scheduler_col_width[i] * (allocation->width))/ 100;
1432         if (width > 0 && gtk_tree_view_column_get_visible (scheduler_list_column[i]))
1433             gtk_tree_view_column_set_fixed_width (scheduler_list_column[i], width);
1434     }
1435 
1436 	/* update tree_view */
1437 	gsb_scheduler_list_update_tree_view (tree_view);
1438 }
1439 
1440 /**
1441  * create and configure the tree view of the scheduled transactions
1442  *
1443  * \param
1444  *
1445  * \return the tree_view
1446  **/
gsb_scheduler_list_create_tree_view(void)1447 static GtkWidget *gsb_scheduler_list_create_tree_view (void)
1448 {
1449     GtkWidget * tree_view;
1450 
1451     tree_view = gtk_tree_view_new ();
1452 	gtk_widget_set_name (tree_view, "tree_view");
1453 
1454     /* can select only one line */
1455     gtk_tree_selection_set_mode (GTK_TREE_SELECTION (gtk_tree_view_get_selection (GTK_TREE_VIEW(tree_view))),
1456 								 GTK_SELECTION_SINGLE);
1457 
1458     g_signal_connect (G_OBJECT (tree_view),
1459 					  "size-allocate",
1460                        G_CALLBACK (gsb_scheduler_list_size_allocate),
1461                        NULL);
1462     g_signal_connect (G_OBJECT (tree_view),
1463                        "button-press-event",
1464                        G_CALLBACK (gsb_scheduler_list_button_press),
1465                        NULL);
1466 
1467     g_signal_connect (G_OBJECT (tree_view),
1468                        "key-press-event",
1469                        G_CALLBACK (gsb_scheduler_list_key_press),
1470                        NULL);
1471 
1472     gtk_widget_show (tree_view);
1473 
1474     last_scheduled_number = -1;
1475 
1476     return tree_view;
1477 }
1478 
1479 /**
1480  * fill the row pointed by the iter with the content of
1481  * the char tab given in param
1482  *
1483  * \param store
1484  * \param iter
1485  * \param line a tab of gchar with SCHEDULER_COL_VISIBLE_COLUMNS of size, which is the text content of the line
1486  *
1487  * \return FALSE
1488  **/
gsb_scheduler_list_fill_transaction_row(GtkTreeStore * store,GtkTreeIter * iter,gchar * line[SCHEDULER_COL_VISIBLE_COLUMNS])1489 static gboolean gsb_scheduler_list_fill_transaction_row (GtkTreeStore *store,
1490 														 GtkTreeIter *iter,
1491 														 gchar *line[SCHEDULER_COL_VISIBLE_COLUMNS])
1492 {
1493     gchar *color_str = NULL;
1494     gint i;
1495 
1496     if (line[COL_NB_AMOUNT] && g_utf8_strchr (line[COL_NB_AMOUNT], -1, '-'))
1497         color_str = (gchar*)"red";
1498 
1499     for (i=0 ; i<SCHEDULER_COL_VISIBLE_COLUMNS ; i++)
1500     {
1501 		if (!line[i])
1502 			continue;
1503 
1504 		if (i == 6)
1505             gtk_tree_store_set (store, iter, i, line[i], SCHEDULER_COL_NB_AMOUNT_COLOR, color_str, -1);
1506         else
1507             gtk_tree_store_set (store, iter, i, line[i], -1);
1508     }
1509 
1510     return FALSE;
1511 }
1512 
1513 /**
1514  * fill the char tab in the param with the transaction given in param
1515  *
1516  * \param scheduled_number
1517  * \param  line a tab of gchar with SCHEDULER_COL_VISIBLE_COLUMNS of size, which will contain the text of the line
1518  *
1519  * \return FALSE
1520  **/
gsb_scheduler_list_fill_transaction_text(gint scheduled_number,gchar * line[SCHEDULER_COL_VISIBLE_COLUMNS])1521 static gboolean gsb_scheduler_list_fill_transaction_text (gint scheduled_number,
1522 														  gchar *line[SCHEDULER_COL_VISIBLE_COLUMNS])
1523 {
1524     if (gsb_data_scheduled_get_mother_scheduled_number (scheduled_number))
1525     {
1526 		/* for child split we set all to NULL except the party, we show the category instead */
1527 		line[COL_NB_DATE] = NULL;
1528 		line[COL_NB_FREQUENCY] = NULL;
1529 		line[COL_NB_ACCOUNT] = NULL;
1530 		line[COL_NB_MODE] = NULL;
1531 
1532 		if (gsb_data_scheduled_get_category_number (scheduled_number))
1533 			line[COL_NB_PARTY] = gsb_data_category_get_name (gsb_data_scheduled_get_category_number
1534 															 (scheduled_number),
1535 															 gsb_data_scheduled_get_sub_category_number
1536 															 (scheduled_number),
1537 															 NULL);
1538 		else
1539 		{
1540 			/* there is no category, it can be a transfer */
1541 			if (gsb_data_scheduled_get_account_number_transfer (scheduled_number) >= 0 && scheduled_number > 0)
1542 			{
1543 				/* it's a transfer */
1544 				if (gsb_data_scheduled_get_amount (scheduled_number).mantissa < 0)
1545 					line[COL_NB_PARTY] = g_strdup_printf (_("Transfer to %s"),
1546 														  gsb_data_account_get_name
1547 														  (gsb_data_scheduled_get_account_number_transfer
1548 														   (scheduled_number)));
1549 				else
1550 					line[COL_NB_PARTY] = g_strdup_printf (_("Transfer from %s"),
1551 														  gsb_data_account_get_name
1552 														  (gsb_data_scheduled_get_account_number_transfer
1553 														   (scheduled_number)));
1554 			}
1555 			else
1556 				/* it's not a transfer, so no category */
1557 				line[COL_NB_PARTY] = NULL;
1558 		}
1559     }
1560     else
1561     {
1562 		/* fill her for normal scheduled transaction (not children) */
1563 		gint frequency;
1564 
1565 		line[COL_NB_DATE] = gsb_format_gdate (gsb_data_scheduled_get_date (scheduled_number));
1566 		frequency = gsb_data_scheduled_get_frequency (scheduled_number);
1567 
1568 		if (frequency == SCHEDULER_PERIODICITY_CUSTOM_VIEW)
1569 		{
1570 			switch (gsb_data_scheduled_get_user_interval (scheduled_number))
1571 			{
1572 				case PERIODICITY_DAYS:
1573 					line[COL_NB_FREQUENCY] = g_strdup_printf (_("%d days"),
1574 															  gsb_data_scheduled_get_user_entry (scheduled_number));
1575 					break;
1576 
1577 				case PERIODICITY_WEEKS:
1578 					line[COL_NB_FREQUENCY] = g_strdup_printf (_("%d weeks"),
1579 															  gsb_data_scheduled_get_user_entry (scheduled_number));
1580 					break;
1581 
1582 				case PERIODICITY_MONTHS:
1583 					line[COL_NB_FREQUENCY] = g_strdup_printf (_("%d months"),
1584 															  gsb_data_scheduled_get_user_entry (scheduled_number));
1585 					break;
1586 
1587 				case PERIODICITY_YEARS:
1588 					line[COL_NB_FREQUENCY] = g_strdup_printf (_("%d years"),
1589 															  gsb_data_scheduled_get_user_entry (scheduled_number));
1590 			}
1591 		}
1592 		else
1593 		{
1594 			if (frequency < SCHEDULER_PERIODICITY_NB_CHOICES && frequency >= 0)
1595 			{
1596 				gchar * names[] = {_("Once"), _("Weekly"), _("Monthly"),
1597 					_("Bimonthly"), _("Quarterly"), _("Yearly") };
1598 
1599 				line[COL_NB_FREQUENCY] = g_strdup (names [frequency]);
1600 			}
1601 		}
1602 		line[COL_NB_ACCOUNT] = g_strdup (gsb_data_account_get_name (gsb_data_scheduled_get_account_number
1603 																	(scheduled_number)));
1604 		line[COL_NB_PARTY] = g_strdup (gsb_data_payee_get_name (gsb_data_scheduled_get_party_number
1605 																(scheduled_number), TRUE));
1606 
1607 		if (gsb_data_scheduled_get_automatic_scheduled (scheduled_number))
1608 			line[COL_NB_MODE]= g_strdup (_("Automatic"));
1609 		else
1610 			line[COL_NB_MODE] = g_strdup (_("Manual"));
1611     }
1612 
1613     /* that can be filled for mother and children of split */
1614     line[COL_NB_NOTES] = g_strdup (gsb_data_scheduled_get_notes (scheduled_number));
1615 
1616     /* if it's a white line don't fill the amount
1617      * (in fact fill nothing, but normally all before was set to NULL,
1618      * there is only the amount, we want NULL and not 0) */
1619     if (scheduled_number < 0)
1620         line[COL_NB_AMOUNT] = NULL;
1621     else
1622         line[COL_NB_AMOUNT] = utils_real_get_string_with_currency (
1623                         gsb_data_scheduled_get_amount (scheduled_number),
1624                         gsb_data_scheduled_get_currency_number (scheduled_number),
1625                         TRUE);
1626 
1627     return FALSE;
1628 }
1629 
1630 /**
1631  * the same as gsb_scheduler_list_get_iter_from_scheduled_number but
1632  * return a gslist of iter corresponding to that scheduled number,
1633  * so there is only 1 iter for the once view, but more than 1 for the other views
1634  * use when changin the scheduled, to change also the virtuals ones on the screen
1635  *
1636  * \param scheduled_number
1637  *
1638  * \return a gslist of pointer to the iters, need to be free, or NULL if not found
1639  **/
gsb_scheduler_list_get_iter_list_from_scheduled_number(gint scheduled_number)1640 static GSList *gsb_scheduler_list_get_iter_list_from_scheduled_number (gint scheduled_number)
1641 {
1642     GtkTreeIter iter;
1643     GtkTreeModel *model;
1644     gint mother_number;
1645     gboolean return_iter = TRUE;
1646     GSList *iter_list = NULL;
1647 
1648     if (!scheduled_number)
1649 		return NULL;
1650 
1651     /* that function is called too for deleting a scheduled transaction,
1652      * and it can be already deleted, so we cannot call gsb_data_scheduled_... here
1653      * but... we need to know if it's a child split, so we call it, in all
1654      * the cases, if the transactions doesn't exist we will have no mother, so very good !*/
1655 
1656     mother_number = gsb_data_scheduled_get_mother_scheduled_number (scheduled_number);
1657 
1658     model = gsb_scheduler_list_get_model ();
1659 
1660     /* go throw the list to find the transaction */
1661     if (!gtk_tree_model_get_iter_first (model, &iter))
1662 		return NULL;
1663 
1664     while (return_iter)
1665     {
1666 		gint scheduled_transaction_buf;
1667 
1668 		gtk_tree_model_get (model,
1669 							&iter,
1670 					 		SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_transaction_buf,
1671 					 		-1);
1672 
1673 		if (scheduled_transaction_buf == scheduled_number)
1674 		{
1675 			iter_list = g_slist_append (iter_list, gtk_tree_iter_copy (&iter));
1676 
1677 			/* we have found the correct iter, but we want to continue to search,
1678 			 * so we have to go back to the mother if necessary
1679 			 * after that scheduled_transaction_buf is on the child, not on the
1680 			 * mother so we will continue to the next scheduled transasction */
1681 
1682 			if (mother_number)
1683 			{
1684 				GtkTreeIter *child_iter;
1685 
1686 				child_iter = gtk_tree_iter_copy (&iter);
1687 				gtk_tree_model_iter_parent (model, &iter, child_iter);
1688 				gtk_tree_iter_free (child_iter);
1689 			}
1690 
1691 		}
1692 
1693 		if (scheduled_transaction_buf == mother_number)
1694 		{
1695 			GtkTreeIter *mother_iter;
1696 
1697 			mother_iter = gtk_tree_iter_copy (&iter);
1698 			return_iter = gtk_tree_model_iter_children (model, &iter, mother_iter);
1699 			gtk_tree_iter_free (mother_iter);
1700 		}
1701 		else
1702 			return_iter = gtk_tree_model_iter_next (model, &iter);
1703     }
1704     return iter_list;
1705 }
1706 
1707 /**
1708  * remove the orphan transactions
1709  *
1710  * \param orphan list
1711  *
1712  * \return void
1713  */
gsb_scheduler_list_remove_orphan_list(GSList * orphan_scheduled,GDate * end_date)1714 static void gsb_scheduler_list_remove_orphan_list (GSList *orphan_scheduled,
1715 												   GDate *end_date)
1716 {
1717     GSList *tmp_list;
1718     gchar *string = NULL;
1719     GArray *garray;
1720 
1721     garray = g_array_new (FALSE, FALSE, sizeof (gint));
1722     tmp_list = orphan_scheduled;
1723     while (tmp_list)
1724     {
1725         gint scheduled_number;
1726 
1727         scheduled_number = gsb_data_scheduled_get_scheduled_number (tmp_list->data);
1728 
1729         if (!gsb_scheduler_list_append_new_scheduled (scheduled_number, end_date))
1730         {
1731             /* on sauvegarde le numéro de l'opération */
1732             g_array_append_val (garray, scheduled_number);
1733             if (string == NULL)
1734                 string = utils_str_itoa (scheduled_number);
1735             else
1736                 string = g_strconcat (string, " - ",
1737                     utils_str_itoa (scheduled_number), NULL);
1738         }
1739 
1740         tmp_list = tmp_list->next;
1741     }
1742 
1743     /* if string is not null, there is still some children
1744      * which didn't find their mother. show them now */
1745     if (string)
1746     {
1747         gchar *message;
1748         gint result;
1749 
1750         message = g_strdup_printf (_("Some scheduled children didn't find their mother in the list, "
1751 									 "this shouldn't happen and there is probably a bug behind that.\n\n"
1752 									 "The concerned children number are:\n %s\n\n"
1753 									 "Do you want to delete it?"),
1754 								   string);
1755 
1756         result = dialogue_yes_no (message, _("Remove orphan children"), GTK_RESPONSE_CANCEL);
1757 
1758         if (result == TRUE)
1759         {
1760             gint i;
1761 
1762             for (i = 0; i < (gint) garray->len; i++)
1763                 gsb_data_scheduled_remove_scheduled (g_array_index (garray, gint, i));
1764 
1765         }
1766 
1767         g_free (message);
1768         g_free (string);
1769         g_array_free (garray, TRUE);
1770     }
1771 }
1772 
1773 /**
1774  * set the text red if the variance is non zero
1775  *
1776  * \param
1777  * \param
1778  *
1779  * \return
1780  **/
gsb_scheduler_list_set_color_of_mother(gint mother_scheduled_number,gboolean is_red)1781 static gboolean gsb_scheduler_list_set_color_of_mother (gint mother_scheduled_number,
1782 														gboolean is_red)
1783 {
1784     GtkTreeIter *iter = NULL;
1785     gchar *color_str = NULL;
1786     gint i;
1787 
1788     iter = gsb_scheduler_list_get_iter_from_scheduled_number (mother_scheduled_number);
1789     if (!iter)
1790         return FALSE;
1791 
1792     if (is_red)
1793         color_str = (gchar*)"red";
1794 
1795     for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS -1 ; i++)
1796     {
1797         gtk_tree_store_set (GTK_TREE_STORE (tree_model_scheduler_list),
1798 							iter,
1799 							SCHEDULER_COL_NB_TEXT_COLOR, color_str,
1800 							-1);
1801     }
1802 
1803     return TRUE;
1804 }
1805 
1806 /**
1807  * set the scheduler tree view
1808  *
1809  * \param tree_view
1810  *
1811  * \return
1812  **/
gsb_scheduler_list_set_tree_view(GtkWidget * tree_view)1813 static void gsb_scheduler_list_set_tree_view (GtkWidget *tree_view)
1814 {
1815     tree_view_scheduler_list = tree_view;
1816 }
1817 
1818 /**
1819  *
1820  *
1821  * \param
1822  * \param
1823  * \param
1824  *
1825  * \return
1826  **/
gsb_scheduler_list_set_virtual_amount_with_loan(gint scheduled_number,gchar * line[SCHEDULER_COL_VISIBLE_COLUMNS],gint account_number)1827 static void gsb_scheduler_list_set_virtual_amount_with_loan (gint scheduled_number,
1828 															 gchar *line[SCHEDULER_COL_VISIBLE_COLUMNS],
1829 															 gint account_number)
1830 {
1831 	gdouble amount;
1832 
1833 	amount = bet_data_loan_get_other_echeance_amount (account_number);
1834 	line[COL_NB_AMOUNT] = utils_real_get_string_with_currency (gsb_real_opposite (gsb_real_double_to_real (amount)),
1835 															   gsb_data_scheduled_get_currency_number (scheduled_number),
1836 															   TRUE);
1837 }
1838 
1839 /**
1840  *
1841  *
1842  * \param
1843  * \param
1844  *
1845  * \return
1846  **/
gsb_scheduler_list_update_white_child(gint white_line_number,gint mother_scheduled_number)1847 static gboolean gsb_scheduler_list_update_white_child (gint white_line_number,
1848 													   gint mother_scheduled_number)
1849 {
1850     GtkTreeIter *iter = NULL;
1851     GSList *tmp_list;
1852     GsbReal total_split = null_real;
1853     GsbReal variance;
1854     gchar *tmp_str;
1855 
1856     if (!tree_model_scheduler_list)
1857         return FALSE;
1858 
1859     iter = gsb_scheduler_list_get_iter_from_scheduled_number (white_line_number);
1860     if (!iter)
1861         return FALSE;
1862 
1863     tmp_list = gsb_data_scheduled_get_scheduled_list ();
1864     while (tmp_list)
1865     {
1866         gint split_scheduled_number;
1867 
1868         split_scheduled_number = gsb_data_scheduled_get_scheduled_number (tmp_list->data);
1869 
1870         if (gsb_data_scheduled_get_mother_scheduled_number (split_scheduled_number) == mother_scheduled_number)
1871         {
1872             total_split = gsb_real_add (total_split, gsb_data_scheduled_get_amount (split_scheduled_number));
1873         }
1874         tmp_list = tmp_list->next;
1875     }
1876 
1877     variance = gsb_real_sub (gsb_data_scheduled_get_amount (mother_scheduled_number), total_split);
1878 
1879     /* show the variance and sub-total only if different of the scheduled */
1880     if (variance.mantissa)
1881     {
1882         gchar *amount_string;
1883         gchar *variance_string;
1884         gint currency_number;
1885 
1886         currency_number = gsb_data_scheduled_get_currency_number (mother_scheduled_number);
1887         amount_string = utils_real_get_string_with_currency (total_split, currency_number, TRUE);
1888         variance_string = utils_real_get_string_with_currency (variance, currency_number, TRUE);
1889 
1890         tmp_str = g_strdup_printf (_("Total: %s (variance : %s)"), amount_string, variance_string);
1891 
1892         g_free (amount_string);
1893         g_free (variance_string);
1894 
1895         gsb_scheduler_list_set_color_of_mother (mother_scheduled_number, TRUE);
1896     }
1897     else
1898     {
1899         tmp_str = (gchar*)"";
1900         gsb_scheduler_list_set_color_of_mother (mother_scheduled_number, FALSE);
1901     }
1902 
1903     gtk_tree_store_set (GTK_TREE_STORE (tree_model_scheduler_list), iter, 2, tmp_str, -1);
1904 
1905     if (tmp_str && strlen (tmp_str))
1906         g_free (tmp_str);
1907 
1908     return TRUE;
1909 }
1910 
1911 /******************************************************************************/
1912 /* Public functions                                                           */
1913 /******************************************************************************/
1914 /**
1915  * libère la mémoire utilisée par GSLists de création des opérations
1916  * arrivées à éhéance
1917  *
1918  * \param
1919  *
1920  * \return
1921  **/
gsb_scheduler_list_free_variables(void)1922 void gsb_scheduler_list_free_variables (void)
1923 {
1924     if (scheduled_transactions_to_take)
1925     {
1926         g_slist_free (scheduled_transactions_to_take);
1927     }
1928     if (scheduled_transactions_taken)
1929     {
1930         g_slist_free (scheduled_transactions_taken);
1931     }
1932 }
1933 
1934 /**
1935  *
1936  *
1937  * \param
1938  *
1939  * \return
1940  **/
gsb_scheduler_list_init_variables(void)1941 void gsb_scheduler_list_init_variables (void)
1942 {
1943     if (scheduled_transactions_to_take)
1944     {
1945         g_slist_free (scheduled_transactions_to_take);
1946         scheduled_transactions_to_take = NULL;
1947     }
1948     if (scheduled_transactions_taken)
1949     {
1950         g_slist_free (scheduled_transactions_taken);
1951         scheduled_transactions_taken = NULL;
1952     }
1953 
1954     /* on réinitialise tous les widgets */
1955     scheduler_display_hide_notes = NULL;
1956     scheduler_button_execute = NULL;
1957     scheduler_button_delete = NULL;
1958     scheduler_button_edit = NULL;
1959 }
1960 
1961 /**
1962  * create the scheduler list
1963  *
1964  * \param
1965  *
1966  * \return a vbox widget containing the list
1967  **/
gsb_scheduler_list_create_list(void)1968 GtkWidget *gsb_scheduler_list_create_list (void)
1969 {
1970     GtkWidget *vbox, *scrolled_window;
1971     GtkWidget *tree_view;
1972     GtkWidget *frame;
1973 	GtkTreeModel *tree_model;
1974 
1975     devel_debug (NULL);
1976 
1977     /* first, a vbox */
1978     vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, MARGIN_BOX);
1979 
1980     /* frame pour la barre d'outils */
1981     frame = gtk_frame_new (NULL);
1982     gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1983 
1984     /* création de la barre d'outils */
1985     scheduler_toolbar = gsb_scheduler_list_create_toolbar ();
1986     gtk_container_add (GTK_CONTAINER (frame), scheduler_toolbar);
1987 
1988     /* create the scrolled window */
1989     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1990     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
1991 				     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1992     gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
1993 					  GTK_SHADOW_IN);
1994     gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
1995     gtk_widget_show (scrolled_window);
1996 
1997     /* we create and set the tree_view in the page */
1998     tree_view = gsb_scheduler_list_create_tree_view ();
1999 	gtk_widget_set_margin_end (tree_view, MARGIN_END);
2000     gsb_scheduler_list_set_tree_view (tree_view);
2001     gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
2002 
2003     /* set the color of selected row */
2004 	gtk_widget_set_name (tree_view, "tree_view");
2005 
2006     /* create the store and set it in the tree_view */
2007     tree_model = gsb_scheduler_list_create_model ();
2008     gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), tree_model);
2009     g_object_unref (G_OBJECT(tree_model));
2010 
2011     /* create the columns */
2012     gsb_scheduler_list_create_list_columns (tree_view);
2013 
2014     /* begin by hiding the notes */
2015     gsb_scheduler_list_show_notes (scheduler_display_hide_notes);
2016 
2017 	gtk_widget_show_all (vbox);
2018 
2019     return vbox;
2020 }
2021 
2022 
2023 /**
2024  *
2025  *
2026  *
2027  */
gsb_gui_scheduler_toolbar_set_style(gint toolbar_style)2028 void gsb_gui_scheduler_toolbar_set_style (gint toolbar_style)
2029 {
2030     gtk_toolbar_set_style (GTK_TOOLBAR (scheduler_toolbar), toolbar_style);
2031 }
2032 
2033 
2034 /**
2035  * return the scheduler tree view
2036  *
2037  * \param
2038  *
2039  * \return the scheduler tree_view
2040  **/
gsb_scheduler_list_get_tree_view(void)2041 GtkWidget *gsb_scheduler_list_get_tree_view (void)
2042 {
2043     return tree_view_scheduler_list;
2044 }
2045 
2046 /**
2047  * called to execute a sheduled transaction, either by the button on the toolbar,
2048  * either by click on the first page
2049  * if scheduled_number is 0, get the selected transaction
2050  *
2051  * \param scheduled_number
2052  *
2053  * \return FALSE
2054  **/
gsb_scheduler_list_execute_transaction(gint scheduled_number)2055 gboolean gsb_scheduler_list_execute_transaction (gint scheduled_number)
2056 {
2057     devel_debug_int (scheduled_number);
2058 
2059     if (!scheduled_number)
2060 		scheduled_number = gsb_scheduler_list_get_current_scheduled_number ();
2061 
2062     gsb_scheduler_list_edit_transaction (scheduled_number);
2063 
2064     /* the only difference for now between an execution and a edition of scheduled is here :
2065      * set the flag to say that we execute the scheduled transaction
2066      * and hide the scheduler part of the form */
2067     g_object_set_data (G_OBJECT (gsb_form_get_form_widget ()), "execute_scheduled", GINT_TO_POINTER (TRUE));
2068     gtk_widget_hide (gsb_form_get_scheduler_part ());
2069 
2070     return FALSE;
2071 }
2072 
2073 /**
2074  * fill the scheduled transactions list
2075  *
2076  * \para tree_view
2077  *
2078  * \return FALSE
2079  **/
gsb_scheduler_list_fill_list(GtkWidget * tree_view)2080 gboolean gsb_scheduler_list_fill_list (GtkWidget *tree_view)
2081 {
2082     GSList *tmp_list;
2083     GDate *end_date;
2084     GtkTreeIter iter;
2085     GSList *orphan_scheduled = NULL;
2086 	GrisbiAppConf *a_conf;
2087 
2088     devel_debug (NULL);
2089 
2090     /* get the last date we want to see the transactions */
2091     end_date = gsb_scheduler_list_get_end_date_scheduled_showed ();
2092 
2093 	if (!tree_model_scheduler_list || !GTK_IS_TREE_STORE (tree_model_scheduler_list))
2094 		return  FALSE;
2095 	else
2096 	    gtk_tree_store_clear (GTK_TREE_STORE (tree_model_scheduler_list));
2097 
2098     /* fill the list */
2099     tmp_list = gsb_data_scheduled_get_scheduled_list ();
2100 
2101     while (tmp_list)
2102     {
2103         gint scheduled_number;
2104 
2105         scheduled_number = gsb_data_scheduled_get_scheduled_number (tmp_list->data);
2106 
2107         if (!end_date || g_date_compare (gsb_data_scheduled_get_date (scheduled_number), end_date) <= 0)
2108         {
2109             if (!gsb_scheduler_list_append_new_scheduled (scheduled_number, end_date))
2110                 /* the scheduled transaction was not added, add to orphan scheduledlist */
2111                 orphan_scheduled = g_slist_append (orphan_scheduled, tmp_list->data);
2112         }
2113         tmp_list = tmp_list->next;
2114     }
2115 
2116     /* if there are some orphan sheduler (children of breakdonw which didn't find their mother */
2117     if (orphan_scheduled)
2118     {
2119         gsb_scheduler_list_remove_orphan_list (orphan_scheduled, end_date);
2120         g_slist_free (orphan_scheduled);
2121     }
2122 
2123     /* create and append the white line */
2124     gtk_tree_store_append (GTK_TREE_STORE (tree_model_scheduler_list), &iter, NULL);
2125     gtk_tree_store_set (GTK_TREE_STORE (tree_model_scheduler_list),
2126                         &iter,
2127                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, gsb_data_scheduled_new_white_line (0),
2128                         -1);
2129 
2130 	/* get first scheduled of the list */
2131 	a_conf = (GrisbiAppConf *) grisbi_app_get_a_conf ();
2132 	if (!a_conf->select_scheduled_in_list)
2133 	{
2134 		GtkWidget *tree_view;
2135 		GtkTreeModel *model;
2136 
2137 		tree_view = gsb_scheduler_list_get_tree_view ();
2138 
2139 		model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
2140 		gtk_tree_model_get_iter_first (model, &iter);
2141 		gtk_tree_model_get (model,
2142 							&iter,
2143 							SCHEDULER_COL_NB_TRANSACTION_NUMBER, &first_scheduler_list_number,
2144 							-1);
2145 	}
2146 	return TRUE;
2147 }
2148 
2149 /**
2150  * send a "row-changed" to all the row of the showed transactions,
2151  * so in fact re-draw the list and colors
2152  *
2153  * \param
2154  *
2155  * \return
2156  **/
gsb_scheduler_list_redraw(void)2157 gboolean gsb_scheduler_list_redraw (void)
2158 {
2159     GtkTreeIter iter;
2160     GtkTreeModel *tree_model;
2161 
2162     tree_model = gsb_scheduler_list_get_model ();
2163 
2164     if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree_model), &iter))
2165     {
2166 		do
2167 		{
2168 			GtkTreePath *path;
2169 			GtkTreeIter child_iter;
2170 
2171 			path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model), &iter);
2172 			gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &iter);
2173 			gtk_tree_path_free(path);
2174 
2175 			/* update the children if necessary */
2176 			if (gtk_tree_model_iter_children (GTK_TREE_MODEL (tree_model), &child_iter, &iter))
2177 			{
2178 				do
2179 				{
2180 					path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model), &child_iter);
2181 					gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model), path, &child_iter);
2182 					gtk_tree_path_free(path);
2183 				}
2184 				while (gtk_tree_model_iter_next (GTK_TREE_MODEL (tree_model), &child_iter));
2185 			}
2186 		}
2187 		while (gtk_tree_model_iter_next (GTK_TREE_MODEL (tree_model), &iter));
2188     }
2189     return FALSE;
2190 }
2191 
2192 /**
2193  * append the scheduled transaction to the tree_view given in param
2194  * if that transaction need to be appended several times (untill end_date),
2195  * it's done here
2196  *
2197  * \param scheduled_number
2198  * \param end_date
2199  *
2200  * \return TRUE : scheduled added, FALSE : not added (usually for children who didn't find their mother)
2201  **/
gsb_scheduler_list_append_new_scheduled(gint scheduled_number,GDate * end_date)2202 gboolean gsb_scheduler_list_append_new_scheduled (gint scheduled_number,
2203 												  GDate *end_date)
2204 {
2205 	GDate *tmp_date;
2206     GDate *pGDateCurrent;
2207     GtkTreeIter *mother_iter = NULL;
2208     gchar *line[SCHEDULER_COL_VISIBLE_COLUMNS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
2209     gint mother_scheduled_number;
2210 	gint fixed_date = 0;
2211 	gint split_transaction;
2212 	gint transfer_account = 0;
2213     gint virtual_transaction = 0;
2214 	gboolean first_is_different = FALSE;
2215 
2216     /* devel_debug_int (scheduled_number); */
2217     if (!tree_model_scheduler_list)
2218         return FALSE;
2219 
2220     /* get the mother iter if needed */
2221     mother_scheduled_number = gsb_data_scheduled_get_mother_scheduled_number (scheduled_number);
2222     if (mother_scheduled_number)
2223     {
2224         gint white_line_number;
2225 
2226         mother_iter = gsb_scheduler_list_get_iter_from_scheduled_number (mother_scheduled_number);
2227         if (!mother_iter)
2228             /* it's a child but didn't find the mother, it can happen in old files previous to 0.6
2229              * where the children wer saved before the mother, return FALSE here will add that
2230              * child to a list to append it again later */
2231             return FALSE;
2232 
2233         white_line_number = gsb_data_scheduled_get_white_line (mother_scheduled_number);
2234         gsb_scheduler_list_update_white_child (white_line_number, mother_scheduled_number);
2235     }
2236 
2237 	/* set the good date */
2238 	tmp_date = gsb_data_scheduled_get_date (scheduled_number);
2239 	pGDateCurrent = gsb_date_copy (tmp_date);
2240 	fixed_date = gsb_data_scheduled_get_fixed_date (scheduled_number);
2241 	if (fixed_date)
2242 	{
2243 		g_date_set_day (pGDateCurrent, fixed_date);
2244 		if (!g_date_valid (pGDateCurrent))
2245 		{
2246 			g_date_free (pGDateCurrent);
2247 			pGDateCurrent = gsb_date_get_last_day_of_month (tmp_date);
2248 		}
2249 	}
2250 
2251 	  /* fill the text line */
2252 	split_transaction = gsb_data_scheduled_get_split_of_scheduled (scheduled_number);
2253 	if (split_transaction)
2254 	{
2255 		gint init_sch_with_loan;
2256 
2257 		transfer_account = gsb_data_scheduled_get_account_number_transfer (scheduled_number+1);
2258 		init_sch_with_loan = gsb_data_account_get_bet_init_sch_with_loan (transfer_account);
2259 		if (init_sch_with_loan) /* cette transaction concerne un prêt */
2260 		{
2261 			first_is_different = bet_data_loan_get_loan_first_is_different (transfer_account);
2262 			if (first_is_different) /* les autres échéances sont différentes */
2263 			{
2264 				GSList *children_numbers_list;
2265 				GsbReal amount;
2266 
2267 				amount = bet_finance_get_loan_amount_at_date (scheduled_number,
2268 															  transfer_account,
2269 															  pGDateCurrent,
2270 															  FALSE);
2271 				gsb_data_scheduled_set_amount (scheduled_number, amount);
2272 
2273 				/* on traite les opérations filles */
2274 				children_numbers_list = gsb_data_scheduled_get_children (scheduled_number, TRUE);
2275 				while (children_numbers_list)
2276 				{
2277 					gint child_number;
2278 
2279 					child_number = GPOINTER_TO_INT (children_numbers_list->data);
2280 					if (child_number)
2281 					{
2282 						amount = bet_finance_get_loan_amount_at_date (child_number,
2283 																	  transfer_account,
2284 																	  pGDateCurrent,
2285 																	  FALSE);
2286 						gsb_data_scheduled_set_amount (child_number, amount);
2287 					}
2288 
2289 					children_numbers_list = children_numbers_list->next;
2290 				}
2291 				g_slist_free (children_numbers_list);
2292 			}
2293 		}
2294 	}
2295     gsb_scheduler_list_fill_transaction_text (scheduled_number, line);
2296 
2297     do
2298     {
2299         GtkTreeIter iter;
2300 
2301         gtk_tree_store_append (GTK_TREE_STORE (tree_model_scheduler_list), &iter, mother_iter);
2302 
2303 		if (scheduled_number > 0)
2304 			gsb_scheduler_list_fill_transaction_row (GTK_TREE_STORE (tree_model_scheduler_list), &iter, line);
2305 
2306         /* set the number of scheduled transaction to 0 if it's not the first one
2307          * (when more than one showed) */
2308         gtk_tree_store_set (GTK_TREE_STORE (tree_model_scheduler_list),
2309 							&iter,
2310 							SCHEDULER_COL_NB_TRANSACTION_NUMBER, scheduled_number,
2311 							SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, virtual_transaction,
2312 							-1);
2313 
2314         /* if it's a split, we append a white line now */
2315         if (split_transaction && !virtual_transaction)
2316         {
2317             gint white_line_number;
2318 
2319             white_line_number = gsb_data_scheduled_get_white_line (scheduled_number);
2320             if (white_line_number == -1)
2321                 white_line_number = gsb_data_scheduled_new_white_line (scheduled_number);
2322 
2323             gsb_scheduler_list_append_new_scheduled (white_line_number, end_date);
2324             gsb_scheduler_list_update_white_child (white_line_number, scheduled_number);
2325         }
2326 
2327         /* if it's a split, we show only one time and color the background */
2328         if (mother_iter)
2329         {
2330             gtk_tree_store_set (GTK_TREE_STORE (tree_model_scheduler_list),
2331 								&iter,
2332 								SCHEDULER_COL_NB_BACKGROUND, gsb_rgba_get_couleur ("background_split"),
2333 								-1);
2334         }
2335         else
2336         {
2337             pGDateCurrent = gsb_scheduler_get_next_date (scheduled_number, pGDateCurrent);
2338 
2339             line[COL_NB_DATE] = gsb_format_gdate (pGDateCurrent);
2340 
2341             /* now, it's not real transactions */
2342 			if (first_is_different && virtual_transaction == 0)
2343 				gsb_scheduler_list_set_virtual_amount_with_loan (scheduled_number, line, transfer_account);
2344 
2345 			virtual_transaction ++;
2346         }
2347     }
2348     while (pGDateCurrent && end_date && g_date_compare (end_date, pGDateCurrent) >= 0 && !mother_iter);
2349 
2350     if (mother_iter)
2351         gtk_tree_iter_free (mother_iter);
2352 
2353     return TRUE;
2354 }
2355 
2356 /**
2357  * remove the given scheduled transaction from the list
2358  * and too all the corresponding virtual transactions
2359  *
2360  * \param transaction_number
2361  *
2362  * \return FALSE
2363  **/
gsb_scheduler_list_remove_transaction_from_list(gint scheduled_number)2364 gboolean gsb_scheduler_list_remove_transaction_from_list (gint scheduled_number)
2365 {
2366     GSList *iter_list;
2367 
2368     devel_debug_int (scheduled_number);
2369 
2370     if (!scheduled_number || !gsb_scheduler_list_get_model ())
2371 		return FALSE;
2372 
2373     /* at this level, normally the transaction is already deleted,
2374      * so we cannot call gsb_data_scheduled_... we have only the number
2375      * to remove it from the list */
2376 
2377     iter_list = gsb_scheduler_list_get_iter_list_from_scheduled_number (scheduled_number);
2378 
2379     if (iter_list)
2380     {
2381 		GtkTreeStore *store;
2382 		GSList *tmp_list;
2383 
2384 		store = GTK_TREE_STORE (gsb_scheduler_list_get_model ());
2385 		tmp_list = iter_list;
2386 
2387 		while (tmp_list)
2388 		{
2389 			GtkTreeIter *iter;
2390 
2391 			iter = tmp_list->data;
2392 
2393 			gtk_tree_store_remove (store, iter);
2394 			gtk_tree_iter_free (iter);
2395 			tmp_list = tmp_list->next;
2396 		}
2397     }
2398     else
2399     {
2400         gchar *tmp_str;
2401 
2402         tmp_str = g_strdup_printf (_("in gsb_scheduler_list_remove_transaction_from_list, "
2403 									 "ask to remove the transaction no %d,\nbut didn't find the iter in the list...\n"
2404 									 "It's normal if appending a new scheduled transaction, but abnormal else..."),
2405 								   scheduled_number);
2406         warning_debug (tmp_str);
2407         g_free (tmp_str);
2408     }
2409     return FALSE;
2410 }
2411 
2412 /**
2413  * update the scheduled transaction in the list (and all the virtuals too)
2414  *
2415  * \param scheduled_number
2416  *
2417  * \return FALSE
2418  **/
gsb_scheduler_list_update_transaction_in_list(gint scheduled_number)2419 gboolean gsb_scheduler_list_update_transaction_in_list (gint scheduled_number)
2420 {
2421     GtkTreeStore *store;
2422     GtkTreeIter iter;
2423     GDate *pGDateCurrent;
2424     gchar *line[SCHEDULER_COL_VISIBLE_COLUMNS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};;
2425 
2426     devel_debug_int (scheduled_number);
2427 
2428     if (!scheduled_number || !gsb_scheduler_list_get_model ())
2429         return FALSE;
2430 
2431     /* the same transaction can be showed more than one time because of the different views,
2432      * not so difficult, go throw the list and for each iter corresponding to the scheduled
2433      * transaction, re-fill the line */
2434     store = GTK_TREE_STORE (gsb_scheduler_list_get_model ());
2435 
2436     pGDateCurrent = gsb_date_copy (gsb_data_scheduled_get_date (scheduled_number));
2437 
2438     /* fill the text line */
2439     gsb_scheduler_list_fill_transaction_text (scheduled_number, line);
2440 
2441     if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
2442     {
2443         do
2444         {
2445             GtkTreeIter child_iter;
2446             gint scheduled_number_tmp;
2447 
2448             gtk_tree_model_get (GTK_TREE_MODEL (store),
2449                                 &iter,
2450                                 SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_number_tmp,
2451                                 -1);
2452             if (scheduled_number_tmp == scheduled_number)
2453             {
2454                 gsb_scheduler_list_fill_transaction_row (GTK_TREE_STORE (store), &iter, line);
2455 
2456                 /* go to the next date if ever there is several lines of that scheduled */
2457                 pGDateCurrent = gsb_scheduler_get_next_date (scheduled_number, pGDateCurrent);
2458 
2459                 line[COL_NB_DATE] = gsb_format_gdate (pGDateCurrent);
2460             }
2461 
2462             /* i still haven't found a function to go line by line, including the children,
2463              * so do another do/while into the first one */
2464             if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child_iter, &iter))
2465             {
2466                 gint white_line_number = 0;
2467                 gint mother_number = 0;
2468 
2469 				/* we are on the child */
2470                 do
2471                 {
2472                     gtk_tree_model_get (GTK_TREE_MODEL (store),
2473                                         &child_iter,
2474                                         SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_number_tmp,
2475                                         -1);
2476 
2477                     if (scheduled_number_tmp < -1)
2478                     {
2479                         white_line_number = scheduled_number_tmp;
2480                         mother_number = gsb_data_scheduled_get_mother_scheduled_number (white_line_number);
2481                     }
2482 
2483 					if (scheduled_number_tmp > 0)
2484 					{
2485 						GsbReal amount;
2486 						gchar *tmp_str;
2487 						gchar *color_str = NULL;
2488 
2489 						amount = gsb_data_scheduled_get_amount (scheduled_number_tmp);
2490 						tmp_str = utils_real_get_string_with_currency (amount,
2491 																	   gsb_data_scheduled_get_currency_number
2492 																	   (scheduled_number_tmp),
2493 																	   TRUE);
2494 						if (line[COL_NB_AMOUNT] && g_utf8_strchr (line[COL_NB_AMOUNT], -1, '-'))
2495 							color_str = (gchar*)"red";
2496 						else
2497 						{
2498 							g_free (color_str);
2499 							color_str = NULL;
2500 						}
2501 						gtk_tree_store_set (store,
2502 											&child_iter,
2503 											COL_NB_AMOUNT, tmp_str,
2504 											SCHEDULER_COL_NB_AMOUNT_COLOR, color_str,
2505 											-1);
2506 					}
2507                 }
2508                 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &child_iter));
2509 
2510                 gsb_scheduler_list_update_white_child (white_line_number, mother_number);
2511             }
2512         }
2513         while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
2514     }
2515 
2516     return FALSE;
2517 }
2518 
2519 /**
2520  * set the background colors of the list
2521  * just for normal scheduled transactions, not for children of split
2522  *
2523  * \param tree_view
2524  *
2525  * \return FALSE
2526  **/
gsb_scheduler_list_set_background_color(GtkWidget * tree_view)2527 gboolean gsb_scheduler_list_set_background_color (GtkWidget *tree_view)
2528 {
2529     GtkTreeStore *store;
2530     GtkTreeModel *sort_model;
2531     GtkTreePath *sorted_path;
2532     GtkTreePath *path;
2533     gint current_color;
2534 
2535     if (!tree_view)
2536         return FALSE;
2537 
2538     sort_model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
2539     store = GTK_TREE_STORE (gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (sort_model)));
2540 
2541     current_color = 0;
2542     sorted_path = gtk_tree_path_new_first ();
2543 
2544     while ((path = gtk_tree_model_sort_convert_path_to_child_path (GTK_TREE_MODEL_SORT (sort_model), sorted_path)))
2545     {
2546         GtkTreeIter iter;
2547         gint virtual_transaction;
2548 
2549         gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
2550 
2551         gtk_tree_model_get (GTK_TREE_MODEL (store),
2552 							&iter,
2553 							SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_transaction,
2554 							-1);
2555 
2556         if (virtual_transaction)
2557             gtk_tree_store_set (store,
2558 								&iter,
2559 								SCHEDULER_COL_NB_BACKGROUND, gsb_rgba_get_couleur ("background_scheduled"),
2560 								-1);
2561         else
2562         {
2563             gtk_tree_store_set (store,
2564                         		&iter,
2565                         		SCHEDULER_COL_NB_BACKGROUND,
2566                         		gsb_rgba_get_couleur_with_indice ("couleur_fond", current_color),
2567                         		-1);
2568             current_color = !current_color;
2569         }
2570 
2571         gtk_tree_path_free (path);
2572 
2573         /* needn't to go in a child because the color is always the same, so
2574          * gtk_tree_path_next is enough */
2575         gtk_tree_path_next (sorted_path);
2576     }
2577 
2578     return FALSE;
2579 }
2580 
2581 /**
2582  * select the given scheduled transaction
2583  *
2584  * \param scheduled_number
2585  *
2586  * \return FALSE
2587  **/
gsb_scheduler_list_select(gint scheduled_number)2588 gboolean gsb_scheduler_list_select (gint scheduled_number)
2589 {
2590     GtkTreeIter *iter;
2591     GtkTreeIter iter_sort;
2592     GtkTreePath *path = NULL;
2593     gint mother_number;
2594 
2595     devel_debug_int (scheduled_number);
2596 
2597     /* if it's a split child, we must open the mother to select it */
2598     mother_number = gsb_data_scheduled_get_mother_scheduled_number (scheduled_number);
2599     if (mother_number)
2600     {
2601         GtkTreeIter *iter_mother;
2602         GtkTreeIter iter_mother_sort;
2603 
2604         iter_mother = gsb_scheduler_list_get_iter_from_scheduled_number (mother_number);
2605         if (iter_mother)
2606         {
2607 
2608             gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (tree_model_sort_scheduler_list),
2609 															&iter_mother_sort,
2610 															iter_mother);
2611             path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort_scheduler_list), &iter_mother_sort);
2612             gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view_scheduler_list), path, TRUE);
2613             gtk_tree_iter_free (iter_mother);
2614         }
2615     }
2616 
2617     /* now can work with the transaction we want to select */
2618     iter = gsb_scheduler_list_get_iter_from_scheduled_number (scheduled_number);
2619 
2620     if (!iter)
2621         return FALSE;
2622 
2623     gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (tree_model_sort_scheduler_list),
2624 													&iter_sort,
2625 													iter);
2626 
2627     gtk_tree_selection_select_iter (GTK_TREE_SELECTION (gtk_tree_view_get_selection
2628 														(GTK_TREE_VIEW (tree_view_scheduler_list))),
2629 									&iter_sort);
2630 
2631     /* move the tree view to the selection */
2632     if (path == NULL)
2633         path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_model_sort_scheduler_list), &iter_sort);
2634 
2635     gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tree_view_scheduler_list), path, NULL, FALSE, 0.0, 0.0);
2636 
2637     gtk_tree_iter_free (iter);
2638     gtk_tree_path_free (path);
2639 
2640     return FALSE;
2641 }
2642 
2643 /**
2644  * find the date untill we want to show the scheduled transactions
2645  * on the scheduled list, with the user configuration
2646  *
2647  * \param
2648  *
2649  * \return a newly allocated final date or NULL for unique view
2650  **/
gsb_scheduler_list_get_end_date_scheduled_showed(void)2651 GDate *gsb_scheduler_list_get_end_date_scheduled_showed (void)
2652 {
2653     GDate *end_date;
2654 	GrisbiAppConf *a_conf;
2655 
2656 	a_conf = (GrisbiAppConf *) grisbi_app_get_a_conf ();
2657 
2658 	/* on récupère la date du jour et la met dans end_date pour les
2659     * vérifications ultérieures */
2660     end_date = gdate_today ();
2661 
2662     /* on calcule la date de fin de l'affichage */
2663     switch (etat.affichage_echeances)
2664     {
2665 		case SCHEDULER_PERIODICITY_ONCE_VIEW:
2666 			return NULL;
2667 			break;
2668 
2669 		case SCHEDULER_PERIODICITY_WEEK_VIEW:
2670 			g_date_add_days (end_date, 7);
2671 			g_date_add_months (end_date, 0);
2672 			break;
2673 
2674 		case SCHEDULER_PERIODICITY_MONTH_VIEW:
2675 			g_date_add_months (end_date, 1);
2676 			end_date->day = 1;
2677 			g_date_subtract_days (end_date, 1);
2678 			break;
2679 
2680 		case SCHEDULER_PERIODICITY_TWO_MONTHS_VIEW:
2681 			g_date_add_months (end_date, 2);
2682 			end_date->day = 1;
2683 			g_date_subtract_days (end_date, 1);
2684 			break;
2685 
2686 		case SCHEDULER_PERIODICITY_TRIMESTER_VIEW:
2687 			g_date_add_months (end_date, 3);
2688 			end_date->day = 1;
2689 			g_date_subtract_days (end_date, 1);
2690 			break;
2691 
2692 		case SCHEDULER_PERIODICITY_YEAR_VIEW:
2693 			g_date_add_years (end_date, 1);
2694 			end_date->day = 1;
2695 			end_date->month = 1;
2696 			g_date_subtract_days (end_date, 1);
2697 			break;
2698 
2699 		case SCHEDULER_PERIODICITY_CUSTOM_VIEW:
2700 			switch (etat.affichage_echeances_perso_j_m_a)
2701 			{
2702 				case PERIODICITY_DAYS:
2703 					g_date_add_days (end_date, etat.affichage_echeances_perso_nb_libre);
2704 					break;
2705 
2706 				case PERIODICITY_WEEKS:
2707 					g_date_add_days (end_date, etat.affichage_echeances_perso_nb_libre * 7);
2708 					break;
2709 
2710 				case PERIODICITY_MONTHS:
2711 					g_date_add_months (end_date, etat.affichage_echeances_perso_nb_libre);
2712 					if (a_conf->execute_scheduled_of_month)	/* dans ce cas on affiche toutes les transactions du mois */
2713 					{
2714 						GDate *tmp_date;
2715 
2716 						tmp_date = end_date;
2717 						end_date = gsb_date_get_last_day_of_month (tmp_date);
2718 						g_date_free (tmp_date);
2719 					}
2720 					break;
2721 
2722 				case PERIODICITY_YEARS:
2723 					g_date_add_years (end_date, etat.affichage_echeances_perso_nb_libre);
2724 					break;
2725 			}
2726     }
2727     return end_date;
2728 }
2729 
2730 /**
2731  * get the current selected transaction and return it
2732  * if it's a virtual transaction, return 0
2733  *
2734  * \param
2735  *
2736  * \return the current scheduled transaction number
2737  **/
gsb_scheduler_list_get_current_scheduled_number(void)2738 gint gsb_scheduler_list_get_current_scheduled_number (void)
2739 {
2740     GList *list_tmp;
2741     GtkTreeModel *model;
2742     GtkTreeIter iter;
2743     GtkWidget *tree_view;
2744     gint scheduled_number;
2745     gint virtual_transaction;
2746 
2747     tree_view = gsb_scheduler_list_get_tree_view ();
2748     list_tmp = gtk_tree_selection_get_selected_rows (gtk_tree_view_get_selection
2749 													 (GTK_TREE_VIEW (tree_view)),
2750 													 &model);
2751 
2752     if (!list_tmp)
2753 		return 0;
2754 
2755     gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, list_tmp->data);
2756     gtk_tree_model_get (GTK_TREE_MODEL (model),
2757 						&iter,
2758 						SCHEDULER_COL_NB_TRANSACTION_NUMBER, &scheduled_number,
2759 						SCHEDULER_COL_NB_VIRTUAL_TRANSACTION, &virtual_transaction,
2760 						-1);
2761 
2762     g_list_free_full (list_tmp, (GDestroyNotify) gtk_tree_path_free);
2763 
2764     if (virtual_transaction)
2765 		return 0;
2766     else
2767 		return scheduled_number;
2768 }
2769 
2770 /**
2771  * edit the scheduling transaction given in param
2772  *
2773  * \param scheduled_number the number, -1 if new scheduled transaction or < -1 if new child of split
2774  *
2775  * \return FALSE
2776  **/
gsb_scheduler_list_edit_transaction(gint scheduled_number)2777 gboolean gsb_scheduler_list_edit_transaction (gint scheduled_number)
2778 {
2779     devel_debug_int (scheduled_number);
2780     if (scheduled_number == 0)
2781 	{
2782 		gint tmp_number;
2783 
2784 		tmp_number = gsb_scheduler_list_get_current_scheduled_number ();
2785         gsb_form_fill_by_transaction (tmp_number, FALSE, TRUE);
2786 		last_scheduled_number = tmp_number;
2787 	}
2788     else
2789 	{
2790         gsb_form_fill_by_transaction (scheduled_number, FALSE, TRUE);
2791 		last_scheduled_number = scheduled_number;
2792 	}
2793 
2794     return FALSE;
2795 }
2796 
2797 /**
2798  * delete the current selected transaction, but called by menu
2799  * just call gsb_scheduler_list_delete_scheduled_transaction with show_warning = TRUE
2800  * because cannot do that by the signal
2801  *
2802  * \param button
2803  * \param
2804  *
2805  * \return FALSE
2806  **/
gsb_scheduler_list_delete_scheduled_transaction_by_menu(GtkWidget * button,gpointer null)2807 gboolean gsb_scheduler_list_delete_scheduled_transaction_by_menu (GtkWidget *button,
2808 																  gpointer null)
2809 {
2810     gsb_scheduler_list_delete_scheduled_transaction (0, TRUE);
2811     return FALSE;
2812 }
2813 
2814 /**
2815  * delete the scheduled transaction
2816  *
2817  * \param scheduled_number the transaction to delete
2818  * \param show_warning TRUE to warn, FALSE to delete directly
2819  * 		!!this don't affect the question to delete only the occurence or the whole scheduled transaction
2820  * 		it affects only for children of split, and especially deleting the white line child
2821  *
2822  * \return FALSE
2823  **/
gsb_scheduler_list_delete_scheduled_transaction(gint scheduled_number,gboolean show_warning)2824 gboolean gsb_scheduler_list_delete_scheduled_transaction (gint scheduled_number,
2825 														  gboolean show_warning)
2826 {
2827     gchar *tmp_str;
2828     gint mother_number = 0;
2829     gint result;
2830     gint msg_no = 0;
2831 
2832     devel_debug_int (scheduled_number);
2833 
2834     if (!scheduled_number)
2835         scheduled_number = gsb_scheduler_list_get_current_scheduled_number ();
2836 
2837     /* return for white line only if show_warning is set
2838      * (means the action is not automatic) */
2839     if (scheduled_number <= 0 && show_warning)
2840 		return FALSE;
2841 
2842     mother_number = gsb_data_scheduled_get_mother_scheduled_number (scheduled_number);
2843 
2844     /* show a warning */
2845     if (show_warning)
2846     {
2847 		if (mother_number)
2848         {
2849             /* ask all the time for a child */
2850             tmp_str = g_strdup_printf (_("Do you really want to delete the child of the "
2851 										 "scheduled transaction with party '%s' ?"),
2852 									   gsb_data_payee_get_name (gsb_data_scheduled_get_party_number
2853 															    (scheduled_number),
2854 															    FALSE));
2855             if (!dialogue_conditional_yes_no_with_items ("tab_delete_msg", "delete-child-scheduled", tmp_str))
2856             {
2857                 g_free (tmp_str);
2858 
2859 				return FALSE;
2860             }
2861             g_free (tmp_str);
2862         }
2863         else
2864         {
2865             /* for a normal scheduled, ask only if no frequency, else, it will
2866              * have another dialog to delete the occurence or the transaction */
2867             tmp_str = g_strdup_printf (_("Do you really want to delete the scheduled "
2868 										 "transaction with party '%s' ?"),
2869 									   gsb_data_payee_get_name (gsb_data_scheduled_get_party_number
2870 															    (scheduled_number),
2871 															    FALSE));
2872             if (!gsb_data_scheduled_get_frequency (scheduled_number)
2873 				&& !dialogue_conditional_yes_no_with_items ("tab_delete_msg", "delete-scheduled", tmp_str))
2874             {
2875                 g_free (tmp_str);
2876 
2877 				return FALSE;
2878             }
2879             g_free (tmp_str);
2880         }
2881     }
2882 
2883     /* split with child of split or normal scheduled,
2884      * for a child, we directly delete it, for mother, ask
2885      * for just that occurrence or the complete transaction */
2886     if (mother_number)
2887     {
2888         gint white_line_number;
2889 
2890         /* !!important to remove first from the list... */
2891         gsb_scheduler_list_remove_transaction_from_list (scheduled_number);
2892         gsb_data_scheduled_remove_scheduled (scheduled_number);
2893 
2894         white_line_number = gsb_data_scheduled_get_white_line (mother_number);
2895         gsb_scheduler_list_update_white_child (white_line_number, mother_number);
2896     }
2897     else
2898     {
2899         /* ask if we want to remove only the current one (so only change the date
2900          * for the next) or all (so remove the transaction */
2901         if (gsb_data_scheduled_get_frequency (scheduled_number))
2902         {
2903             GtkWidget *checkbox;
2904             GtkWidget *dialog = NULL;
2905             GtkWidget *vbox;
2906             gchar *occurrences;
2907 			ConditionalMsg *warning;
2908 
2909 			warning = (ConditionalMsg*) dialogue_get_tab_delete_msg ();
2910             msg_no = dialogue_conditional_yes_no_get_no_struct (warning,
2911 																"delete-scheduled-occurrences");
2912 
2913             if (msg_no < 0)
2914 				return FALSE;
2915 
2916             if ((warning+msg_no)->hidden)
2917 				result = (warning+msg_no)->default_answer;
2918             else
2919             {
2920 				tmp_str = utils_real_get_string (gsb_data_scheduled_get_amount (scheduled_number));
2921 				occurrences = g_strdup_printf (_("Do you want to delete just this occurrence or "
2922 												 "the whole scheduled transaction?\n\n%s : %s [%s %s]"),
2923 											   gsb_format_gdate (gsb_data_scheduled_get_date (scheduled_number)),
2924 											   gsb_data_payee_get_name (gsb_data_scheduled_get_party_number
2925 																		(scheduled_number),
2926 																		FALSE),
2927 											   tmp_str,
2928 											   gsb_data_currency_get_name (gsb_data_scheduled_get_currency_number
2929 																		   (scheduled_number)));
2930 				g_free (tmp_str);
2931 
2932 				dialog = dialogue_special_no_run (GTK_MESSAGE_QUESTION,
2933 												  GTK_BUTTONS_NONE,
2934 												  occurrences,
2935 												  _("Delete this scheduled transaction?"));
2936 
2937 				gtk_dialog_add_buttons (GTK_DIALOG(dialog),
2938 										"gtk-cancel", 2,
2939 								 		_("All the occurrences"), 1,
2940 								 		_("Only this one"), 0,
2941 								 		NULL);
2942 
2943 				vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
2944 
2945 				checkbox = gtk_check_button_new_with_label (_("Keep this choice and no longer see this message?"));
2946 				g_signal_connect (G_OBJECT (checkbox),
2947 								  "toggled",
2948 								  G_CALLBACK (dialogue_update_struct_message),
2949 								  (warning+msg_no));
2950 				gtk_box_pack_start (GTK_BOX (vbox), checkbox, TRUE, TRUE, MARGIN_BOX);
2951 				gtk_widget_show_all (checkbox);
2952 
2953 				result = gtk_dialog_run (GTK_DIALOG (dialog));
2954 
2955 				(warning+msg_no)->default_answer = result;
2956 				g_free (occurrences);
2957 				gtk_widget_destroy (dialog);
2958             }
2959         }
2960         else
2961             result = 1;
2962 
2963         switch (result)
2964         {
2965             case 0:
2966             if (gsb_scheduler_increase_scheduled (scheduled_number))
2967                 gsb_scheduler_list_update_transaction_in_list (scheduled_number);
2968             break;
2969 
2970             case 1:
2971             /* !!important to remove first from the list... */
2972             gsb_scheduler_list_remove_transaction_from_list (scheduled_number);
2973             gsb_data_scheduled_remove_scheduled (scheduled_number);
2974             break;
2975         }
2976     }
2977 
2978     gsb_scheduler_list_set_background_color (gsb_scheduler_list_get_tree_view ());
2979 
2980     gsb_calendar_update ();
2981     run.mise_a_jour_liste_echeances_manuelles_accueil = TRUE;
2982 
2983     gsb_file_set_modified (TRUE);
2984 
2985     return FALSE;
2986 }
2987 
2988 /**
2989  * Clone selected transaction if any.  Update user interface as well.
2990  *
2991  * \param menu_item
2992  * \param scheduled_number
2993  *
2994  * \return FALSE
2995  */
gsb_scheduler_list_clone_selected_scheduled(GtkWidget * menu_item,gint * scheduled_number)2996 gboolean gsb_scheduler_list_clone_selected_scheduled (GtkWidget *menu_item,
2997 													  gint *scheduled_number)
2998 {
2999     gint new_scheduled_number;
3000     gint tmp_scheduled_number;
3001 
3002     if (scheduled_number == NULL)
3003         tmp_scheduled_number = gsb_scheduler_list_get_current_scheduled_number ();
3004     else
3005         tmp_scheduled_number = GPOINTER_TO_INT (scheduled_number);
3006 
3007     new_scheduled_number = gsb_data_scheduled_new_scheduled ();
3008 
3009     gsb_data_scheduled_copy_scheduled (tmp_scheduled_number, new_scheduled_number);
3010 
3011     if (gsb_data_scheduled_get_split_of_scheduled (tmp_scheduled_number))
3012     {
3013         GSList *tmp_list;
3014 
3015         tmp_list = g_slist_copy (gsb_data_scheduled_get_scheduled_list ());
3016 
3017         while (tmp_list)
3018         {
3019             gint split_scheduled_number;
3020 
3021             split_scheduled_number = gsb_data_scheduled_get_scheduled_number (tmp_list->data);
3022 
3023             if (gsb_data_scheduled_get_mother_scheduled_number (split_scheduled_number) == tmp_scheduled_number)
3024             {
3025                 gint new_number;
3026 
3027                 new_number = gsb_data_scheduled_new_scheduled ();
3028                 gsb_data_scheduled_copy_scheduled (split_scheduled_number, new_number);
3029                 gsb_data_scheduled_set_mother_scheduled_number (new_number, new_scheduled_number);
3030             }
3031 
3032             tmp_list = tmp_list->next;
3033         }
3034     }
3035 
3036     gsb_scheduler_list_fill_list (gsb_scheduler_list_get_tree_view ());
3037     gsb_scheduler_list_set_background_color (gsb_scheduler_list_get_tree_view ());
3038     gsb_scheduler_list_select (new_scheduled_number);
3039 
3040     gsb_file_set_modified (TRUE);
3041 
3042     return FALSE;
3043 }
3044 
3045 /**
3046  *
3047  *
3048  * \param
3049  *
3050  * \return
3051  **/
gsb_scheduler_list_set_largeur_col(void)3052 gboolean gsb_scheduler_list_set_largeur_col (void)
3053 {
3054     gint i;
3055     gint width;
3056 
3057     for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS ; i++)
3058     {
3059         width = (scheduler_col_width[i] * (scheduler_current_tree_view_width)) / 100;
3060         if (width > 0)
3061             gtk_tree_view_column_set_fixed_width (scheduler_list_column[i], width);
3062     }
3063 
3064     return FALSE;
3065 }
3066 
3067 /**
3068  *
3069  *
3070  * \param
3071  *
3072  * \return
3073  **/
gsb_scheduler_list_get_toolbar(void)3074 GtkWidget *gsb_scheduler_list_get_toolbar (void)
3075 {
3076     return scheduler_toolbar;
3077 }
3078 
3079 /**
3080  *
3081  *
3082  * \param
3083  *
3084  * \return
3085  **/
gsb_scheduler_list_get_scheduled_transactions_taken(void)3086 GSList *gsb_scheduler_list_get_scheduled_transactions_taken (void)
3087 {
3088 	return scheduled_transactions_taken;
3089 }
3090 
3091 /**
3092  *
3093  *
3094  * \param
3095  *
3096  * \return
3097  **/
gsb_scheduler_list_get_scheduled_transactions_to_take(void)3098 GSList *gsb_scheduler_list_get_scheduled_transactions_to_take (void)
3099 {
3100 	return scheduled_transactions_to_take;
3101 }
3102 
3103 /**
3104  * Initialise le tableau des largeurs de colonnes du treeview des opérations
3105  *
3106  * \param description 	Chaine contenant la largeurs des colonnes
3107  * 						Si NULL utilise les donnes par défaut.
3108  *
3109  * \return
3110  **/
gsb_scheduler_list_init_tab_width_col_treeview(const gchar * description)3111 void gsb_scheduler_list_init_tab_width_col_treeview (const gchar *description)
3112 {
3113     gint i;
3114 
3115 	if (description && strlen (description))
3116 	{
3117 		gchar **pointeur_char;
3118 		gint somme = 0; 			/* calcul du % de la dernière colonne */
3119 
3120 		/* the transactions columns are xx-xx-xx-xx and we want to set in scheduler_col_width[1-2-3...] */
3121 		pointeur_char = g_strsplit (description, "-", 0);
3122 		if (g_strv_length (pointeur_char) != SCHEDULER_COL_VISIBLE_COLUMNS)
3123 		{
3124 			/* defaut value for width of columns */
3125 			for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS ; i++)
3126 				scheduler_col_width[i] = scheduler_col_width_init[i];
3127 			g_strfreev (pointeur_char);
3128 
3129 			return;
3130 		}
3131 
3132 		for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS -1 ; i++)
3133 		{
3134 			if (strlen ((const gchar *) pointeur_char[i]) == 0)
3135 				scheduler_col_width[i] = scheduler_col_width_init[i];
3136 			else
3137 				scheduler_col_width[i] = utils_str_atoi (pointeur_char[i]);
3138 
3139 			if (i != 5)
3140 				somme+= scheduler_col_width[i];
3141 		}
3142 		scheduler_col_width[i] = 100 - somme;
3143 		g_strfreev (pointeur_char);
3144 
3145 		/* si scheduler_col_width[i] est < scheduler_col_width_init[i] on reinitialise la largeur des colonnes */
3146 		if (scheduler_col_width[i] < scheduler_col_width_init[i])
3147 		{
3148 			/* defaut value for width of columns */
3149 			for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS; i++)
3150 			{
3151 				scheduler_col_width[i] = scheduler_col_width_init[i];
3152 			}
3153 		}
3154 	}
3155 	else
3156 	{
3157 		for (i = 0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS; i++)
3158 		{
3159 			scheduler_col_width[i] = scheduler_col_width_init[i];
3160 		}
3161 	}
3162 }
3163 
3164 /**
3165  * retourne une chaine formatée des largeurs de colonnes du treeview prévisions
3166  *
3167  * \param
3168  *
3169  * \return a newly allocated chain to be released
3170  **/
gsb_scheduler_list_get_largeur_col_treeview_to_string(void)3171 gchar *gsb_scheduler_list_get_largeur_col_treeview_to_string (void)
3172 {
3173     gchar *first_string_to_free;
3174     gchar *second_string_to_free;
3175 	gchar *tmp_str = NULL;
3176 	gint i = 0;
3177 
3178     for (i=0 ; i < SCHEDULER_COL_VISIBLE_COLUMNS ; i++)
3179     {
3180         if (tmp_str)
3181         {
3182 			first_string_to_free = tmp_str;
3183 			second_string_to_free = utils_str_itoa (scheduler_col_width[i]);
3184             tmp_str = g_strconcat (first_string_to_free, "-", second_string_to_free,  NULL);
3185             g_free (first_string_to_free);
3186             g_free (second_string_to_free);
3187         }
3188         else
3189             tmp_str  = utils_str_itoa (scheduler_col_width[i]);
3190     }
3191 
3192 	return tmp_str;
3193 }
3194 
3195 /**
3196  *
3197  *
3198  * \param
3199  *
3200  * \return
3201  **/
gsb_scheduler_list_update_tree_view(GtkWidget * tree_view)3202 void gsb_scheduler_list_update_tree_view (GtkWidget *tree_view)
3203 {
3204 	GrisbiAppConf *a_conf;
3205 
3206 	devel_debug (NULL);
3207 	a_conf = (GrisbiAppConf *) grisbi_app_get_a_conf ();
3208 
3209 	gsb_scheduler_list_fill_list (tree_view);
3210 	gsb_scheduler_list_set_background_color (tree_view);
3211 
3212 	if (!a_conf->select_scheduled_in_list && last_scheduled_number == -1)
3213 		last_scheduled_number = first_scheduler_list_number;
3214 
3215 	gsb_scheduler_list_select (last_scheduled_number);
3216 
3217 }
3218 
3219 /**
3220  *
3221  *
3222  * \param
3223  *
3224  * \return
3225  **/
gsb_scheduler_list_set_current_tree_view_width(gint new_tree_view_width)3226 void gsb_scheduler_list_set_current_tree_view_width (gint new_tree_view_width)
3227 {
3228 	scheduler_current_tree_view_width = new_tree_view_width;
3229 }
3230 
3231 /**
3232  *
3233  *
3234  * \param
3235  *
3236  * \return
3237  **/
3238 /* Local Variables: */
3239 /* c-basic-offset: 4 */
3240 /* End: */
3241