1 /* ************************************************************************** */
2 /*                                                                            */
3 /*     Copyright (C)	2000-2007 Cédric Auger (cedric@grisbi.org)	          */
4 /*			2006-2008 Benjamin Drieu (bdrieu@april.org)	                      */
5 /*			https://www.grisbi.org				                              */
6 /*                                                                            */
7 /*  This program is free software; you can redistribute it and/or modify      */
8 /*  it under the terms of the GNU General Public License as published by      */
9 /*  the Free Software Foundation; either version 2 of the License, or         */
10 /*  (at your option) any later version.                                       */
11 /*                                                                            */
12 /*  This program is distributed in the hope that it will be useful,           */
13 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of            */
14 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
15 /*  GNU General Public License for more details.                              */
16 /*                                                                            */
17 /*  You should have received a copy of the GNU General Public License         */
18 /*  along with this program; if not, write to the Free Software               */
19 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
20 /*                                                                            */
21 /* ************************************************************************** */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include "include.h"
28 #include <glib/gi18n.h>
29 
30 /*START_INCLUDE*/
31 #include "gsb_account.h"
32 #include "categories_onglet.h"
33 #include "dialog.h"
34 #include "grisbi_win.h"
35 #include "gsb_account_property.h"
36 #include "gsb_category.h"
37 #include "gsb_data_account.h"
38 #include "gsb_data_currency.h"
39 #include "gsb_data_import_rule.h"
40 #include "gsb_data_payment.h"
41 #include "gsb_data_scheduled.h"
42 #include "gsb_data_transaction.h"
43 #include "gsb_file.h"
44 #include "gsb_form_scheduler.h"
45 #include "gsb_real.h"
46 #include "gsb_scheduler_list.h"
47 #include "gsb_transactions_list.h"
48 #include "imputation_budgetaire.h"
49 #include "menu.h"
50 #include "navigation.h"
51 #include "structures.h"
52 #include "tiers_onglet.h"
53 #include "traitement_variables.h"
54 #include "transaction_list.h"
55 #include "utils_str.h"
56 #include "erreur.h"
57 /*END_INCLUDE*/
58 
59 /*START_STATIC*/
60 /*END_STATIC*/
61 
62 
63 /*START_EXTERN*/
64 /*END_EXTERN*/
65 
66 
67 
68 /**
69  * called to create a new account
70  * called by the account assistant, should not be used directly
71  * !! here is just to add an account, for new complete file see gsb_file_new
72  *
73  * \param none
74  *
75  * \return FALSE if problem, TRUE if ok
76  */
77 
gsb_account_new(KindAccount account_type,gint currency_number,gint bank_number,GsbReal init_amount,const gchar * name,gchar * name_icon)78 gboolean gsb_account_new ( KindAccount account_type,
79 			   gint currency_number,
80 			   gint bank_number,
81 			   GsbReal init_amount,
82 			   const gchar *name,
83                gchar *name_icon )
84 {
85     gint account_number;
86     GtkWidget *notebook_general;
87 
88     /*     create the new account */
89     account_number = gsb_data_account_new (account_type);
90     if ( account_number == -1 )
91     {
92 	dialogue_error_memory ();
93 	return FALSE;
94     }
95 
96     /* set the default method of payment */
97     gsb_data_payment_create_default (account_number);
98 
99     /* set the icon_name */
100     if ( name_icon )
101     {
102         GdkPixbuf *pixbuf;
103 
104         gsb_data_account_set_name_icon ( account_number, name_icon );
105         pixbuf = gdk_pixbuf_new_from_file_at_size ( name_icon , LOGO_WIDTH, LOGO_HEIGHT, NULL );
106         if (pixbuf)
107 		{
108             gsb_data_account_set_account_icon_pixbuf ( account_number, pixbuf );
109 			g_object_unref (G_OBJECT (pixbuf));
110 		}
111     }
112 
113     gsb_data_account_set_currency ( account_number, currency_number);
114     gsb_data_account_set_bank (account_number, bank_number);
115     gsb_data_account_set_init_balance (account_number, init_amount);
116     gsb_data_account_set_mini_balance_wanted ( account_number,
117 					       gsb_real_new ( 0,
118 							      gsb_data_currency_get_floating_point (currency_number) ) );
119     gsb_data_account_set_mini_balance_authorized (account_number,
120 						  gsb_real_new ( 0,
121 								 gsb_data_currency_get_floating_point (currency_number) ) );
122     gsb_data_account_set_name (account_number, name);
123 
124     /* update the main page */
125     run.mise_a_jour_liste_comptes_accueil = TRUE;
126 
127     /* update the accounts lists */
128 	grisbi_win_menu_move_to_acc_delete ();
129 	grisbi_win_menu_move_to_acc_new ();
130 
131     /* do the next part only if the widgets are created
132      * (can come here at the end of the new file assistant...) */
133     notebook_general = grisbi_win_get_notebook_general ( );
134     if (notebook_general)
135     {
136 		/* update the combofix for categ */
137 		gsb_category_update_combofix (FALSE);
138 
139 		/* update the name of accounts in form */
140 		gsb_account_update_combo_list (gsb_form_scheduler_get_element_widget (SCHEDULED_FORM_ACCOUNT),
141 									   FALSE);
142 
143          /* Add an entry in navigation pane. */
144         gsb_gui_navigation_add_account ( account_number, TRUE );
145 
146 		/* Go to accounts properties */
147         gtk_notebook_set_current_page ( GTK_NOTEBOOK ( notebook_general ), GSB_ACCOUNT_PAGE );
148         gtk_notebook_set_current_page ( GTK_NOTEBOOK ( grisbi_win_get_account_page () ),
149                         GSB_PROPERTIES_PAGE );
150 
151         gsb_account_property_fill_page ();
152     }
153 
154     gsb_file_set_modified ( TRUE );
155 
156     return TRUE;
157 }
158 
159 
160 
161 /**
162  * that function delete the current account selected
163  *
164  * \param   none
165  *
166  * \return  FALSE
167  * */
gsb_account_delete(void)168 gboolean gsb_account_delete ( void )
169 {
170     gint deleted_account;
171     gint page_number;
172     GSList *list_tmp;
173 	gchar* tmpstr;
174 
175     deleted_account = gsb_gui_navigation_get_current_account ();
176     devel_debug_int (deleted_account);
177 
178     tmpstr = g_strdup_printf (_("Delete account \"%s\"?"),
179                         gsb_data_account_get_name ( deleted_account ) ) ;
180 
181     if ( !dialogue_yes_no (_("This will irreversibly remove this account and all operations "
182                              "that were previously contained.  There is no undo for this. "
183                              "Usually it's a better way to close an account."),
184                            tmpstr, GTK_RESPONSE_NO ))
185     {
186         g_free ( tmpstr );
187 	    return FALSE;
188     }
189     g_free ( tmpstr );
190 
191     /* if the last account, close the file */
192     if ( gsb_data_account_get_accounts_amount () == 1 )
193     {
194         gsb_file_set_modified ( FALSE );
195         (void)gsb_file_close ();
196         return FALSE;
197     }
198 
199     /* delete the schedules transactions on that account */
200     list_tmp = gsb_data_scheduled_get_scheduled_list ();
201     while (list_tmp)
202     {
203         gint scheduled_number;
204 
205         scheduled_number = gsb_data_scheduled_get_scheduled_number ( list_tmp -> data );
206         list_tmp = list_tmp -> next;
207 
208         if ( gsb_data_scheduled_get_account_number (scheduled_number) == deleted_account )
209             gsb_data_scheduled_remove_scheduled (scheduled_number);
210     }
211 
212     /* remove all the transactions of that account */
213     list_tmp = gsb_data_transaction_get_complete_transactions_list ();
214     while (list_tmp)
215     {
216         gint transaction_number;
217 
218         transaction_number = gsb_data_transaction_get_transaction_number ( list_tmp -> data );
219 
220         /* better to go to the next transaction now */
221         list_tmp = list_tmp -> next;
222 
223         if (gsb_data_transaction_get_account_number (transaction_number) == deleted_account)
224         {
225             gint contra_transaction_number;
226 
227             /* we are on a transaction on the deleted account, we delete that transaction,
228              * but if it's a transfer, modify the contra-transaction to set transfer to deleted account */
229             contra_transaction_number = gsb_data_transaction_get_contra_transaction_number (
230                                         transaction_number);
231             if (contra_transaction_number > 0)
232             /* it's a transfer, modify the contra-transaction */
233                 gsb_data_transaction_set_contra_transaction_number ( contra_transaction_number, -1);
234 
235             /* now can remove the transaction */
236             transaction_list_remove_transaction ( transaction_number );
237             gsb_data_transaction_remove_transaction_without_check ( transaction_number );
238         }
239     }
240 
241     /* delete the payment_number */
242     list_tmp = gsb_data_account_get_sort_list ( deleted_account );
243     while (list_tmp)
244     {
245         gpointer ptr;
246         gint payment_number;
247 
248         ptr = list_tmp->data;
249         payment_number = GPOINTER_TO_INT ( ptr );
250         gsb_data_payment_remove ( payment_number );
251 
252         list_tmp = list_tmp -> next;
253     }
254 
255 	/* delete the rules if necessary */
256 	list_tmp = gsb_data_import_rule_get_from_account (deleted_account);
257 	if (list_tmp)
258 	{
259 		while (list_tmp)
260 		{
261 			ImportRule *import_rule;
262 
263 			import_rule = (ImportRule *) list_tmp->data;
264 			gsb_data_import_rule_remove (import_rule->import_rule_number);
265 
266 			list_tmp = list_tmp -> next;
267 		}
268 		g_slist_free (list_tmp);
269 	}
270 
271     /* delete the account */
272     gsb_data_account_delete ( deleted_account );
273 
274     /* check gsb_gui_navigation_get_current_account () and gsb_gui_navigation_get_current_account ()_onglet
275      * and put them on the first account if they are on the deleted account */
276     if ( gsb_gui_navigation_get_current_account () == deleted_account )
277     {
278         GtkWidget *notebook_general;
279         gint first_account;
280 
281         /* sélection du premier compte de la liste */
282         notebook_general = grisbi_win_get_notebook_general ();
283         page_number = gtk_notebook_get_current_page ( GTK_NOTEBOOK ( notebook_general ) );
284         first_account = gsb_data_account_first_no_closed_account ();
285 
286 		gtk_notebook_set_current_page ( GTK_NOTEBOOK ( notebook_general ), page_number );
287         gsb_gui_navigation_set_selection (GSB_ACCOUNT_PAGE, first_account, 0);
288         gsb_gui_navigation_change_account ( first_account );
289     }
290 
291     /* Update navigation pane. */
292     gsb_gui_navigation_remove_account ( deleted_account );
293 
294     /* update the name of accounts in form */
295     gsb_account_update_combo_list ( gsb_form_scheduler_get_element_widget (SCHEDULED_FORM_ACCOUNT), FALSE );
296 
297     run.mise_a_jour_liste_echeances_manuelles_accueil = TRUE;
298     run.mise_a_jour_liste_comptes_accueil = TRUE;
299     run.mise_a_jour_soldes_minimaux = TRUE;
300     run.mise_a_jour_fin_comptes_passifs = TRUE;
301 
302     gsb_file_set_modified ( TRUE );
303 
304     /* return */
305     return FALSE;
306 }
307 
308 
309 /**
310  * create a combobox containing the list of the accounts
311  *
312  * \param func Function to call when a line is selected (type : gboolean func ( GtkWidget *button, gpointer data )
313  * \param data data to send to the function
314  * \param include_closed If set to TRUE, include the closed accounts
315  *
316  * \return a new GtkCombobox containing the list of the accounts
317  * */
gsb_account_create_combo_list(GCallback func,gpointer data,gboolean include_closed)318 GtkWidget *gsb_account_create_combo_list ( GCallback func,
319 										  gpointer data,
320 										  gboolean include_closed)
321 {
322     GSList *list_tmp;
323     GtkListStore *store;
324     GtkCellRenderer *renderer;
325     GtkWidget *combobox;
326 
327     combobox = gtk_combo_box_new ();
328 
329     store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
330 
331 	list_tmp = gsb_data_account_get_list_accounts ();
332 
333 	while (list_tmp)
334 	{
335 		gint account_number;
336 		gchar *tmp_str;
337 		GtkTreeIter iter;
338 
339 		account_number = gsb_data_account_get_no_account (list_tmp->data);
340 
341 		if (account_number >= 0 && (!gsb_data_account_get_closed_account (account_number) || include_closed))
342 		{
343 			tmp_str = gsb_string_truncate (gsb_data_account_get_name (account_number));
344 			gtk_list_store_append (GTK_LIST_STORE (store), &iter);
345 			gtk_list_store_set (store, &iter, 0, tmp_str, 1, account_number, -1);
346 
347 			g_free (tmp_str);
348 		}
349 		list_tmp = list_tmp->next;
350 	}
351 
352     gtk_combo_box_set_model (GTK_COMBO_BOX (combobox), GTK_TREE_MODEL (store));
353 
354     /* by default, this is blank, so set the first */
355     gtk_combo_box_set_active ( GTK_COMBO_BOX (combobox), 0 );
356 
357     if (func)
358 		g_signal_connect (G_OBJECT (combobox),
359 						  "changed",
360 						  G_CALLBACK(func),
361 						  data);
362 
363     renderer = gtk_cell_renderer_text_new ();
364     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
365     gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, "text", 0, NULL);
366 
367     return combobox;
368 }
369 
370 /**
371  * update the list of accounts in a combo_box filled
372  * by gsb_account_create_combo_list
373  *
374  * \param combo_box
375  * \param include_closed
376  *
377  * \return FALSE
378  * */
gsb_account_update_combo_list(GtkWidget * combo_box,gboolean include_closed)379 gboolean gsb_account_update_combo_list ( GtkWidget *combo_box,
380 					 gboolean include_closed )
381 {
382     GSList *list_tmp;
383     GtkListStore *store;
384 
385     if ( !combo_box )
386         return FALSE;
387 
388     g_signal_handlers_block_by_func ( G_OBJECT ( combo_box ),
389                         G_CALLBACK ( gsb_form_scheduler_change_account ),
390                         NULL );
391 
392     store = GTK_LIST_STORE ( gtk_combo_box_get_model ( GTK_COMBO_BOX ( combo_box) ) );
393     gtk_list_store_clear ( store );
394 
395     list_tmp = gsb_data_account_get_list_accounts ();
396 
397     while (list_tmp)
398     {
399         gint account_number;
400 		gchar *tmp_str;
401         GtkTreeIter iter;
402 
403         account_number = gsb_data_account_get_no_account (list_tmp->data);
404 
405         if (account_number >= 0 && (!gsb_data_account_get_closed_account (account_number) || include_closed))
406         {
407 			tmp_str = gsb_string_truncate (gsb_data_account_get_name (account_number));
408 			gtk_list_store_append (GTK_LIST_STORE (store), &iter);
409 			gtk_list_store_set (store, &iter, 0, tmp_str, 1, account_number, -1);
410 
411 			g_free (tmp_str);
412         }
413         list_tmp = list_tmp->next;
414     }
415 
416     g_signal_handlers_unblock_by_func ( G_OBJECT ( combo_box ),
417                         G_CALLBACK ( gsb_form_scheduler_change_account ),
418                         NULL );
419 
420     return FALSE;
421 }
422 
423 /**
424  * get the selected account number in a combo_box filled by
425  * gsb_account_create_combo_list
426  *
427  * \param combo_box the accounts combo-box
428  *
429  * \return the account number selected or -1 if none active
430  * */
gsb_account_get_combo_account_number(GtkWidget * combo_box)431 gint gsb_account_get_combo_account_number ( GtkWidget *combo_box )
432 {
433     gint account_number;
434     GtkTreeIter iter;
435 
436     if (!combo_box
437 	||
438 	!GTK_IS_COMBO_BOX (combo_box))
439 	return -1;
440 
441     if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX (combo_box),
442 					  &iter ))
443 	return -1;
444 
445     gtk_tree_model_get ( GTK_TREE_MODEL (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box))),
446 			 &iter,
447 			 1, &account_number,
448 			 -1 );
449     return account_number;
450 }
451 
452 
453 /**
454  * the the account on the combo box
455  *
456  * \param combo_box the accounts combo-box
457  * \param account_number the account we want to set
458  *
459  * \return TRUE ok, FALSE pb
460  * */
gsb_account_set_combo_account_number(GtkWidget * combo_box,gint account_number)461 gboolean gsb_account_set_combo_account_number ( GtkWidget *combo_box,
462 						gint account_number )
463 
464 {
465     GtkTreeIter iter;
466     GtkTreeModel *model;
467 
468     if (!combo_box
469 	||
470 	!GTK_IS_COMBO_BOX (combo_box))
471 	return FALSE;
472 
473     model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
474 
475     if (!gtk_tree_model_get_iter_first (model, &iter))
476 	return FALSE;
477 
478     do
479     {
480 	gint account_test;
481 
482 	gtk_tree_model_get ( model,
483 			     &iter,
484 			     1, &account_test,
485 			     -1 );
486 	if (account_number == account_test)
487 	{
488 	    gtk_combo_box_set_active_iter ( GTK_COMBO_BOX (combo_box),
489 					    &iter );
490 	    return TRUE;
491 	}
492     }
493     while (gtk_tree_model_iter_next (model, &iter));
494 
495     return FALSE;
496 }
497 
498 
499 
500 /**
501  *  Create a menu with the list of accounts.  This list is
502  *  clickable and activates func if specified.
503  *  used for now to add a submenu item in a main menu
504  *
505  * \param func Function to call when a line is selected
506  * \param activate_currrent If set to TRUE, does not mark as
507  *        unsensitive current account
508  * \param include_closed If set to TRUE, include the closed accounts
509  *
510  * \return A newly created menu
511  * */
gsb_account_create_menu_list(GCallback func,gboolean activate_currrent,gboolean include_closed)512 GtkWidget *gsb_account_create_menu_list ( GCallback func,
513 					  gboolean activate_currrent,
514 					  gboolean include_closed )
515 {
516     GtkWidget *menu;
517     GtkWidget *item;
518     GSList *list_tmp;
519 
520     menu = gtk_menu_new ();
521 
522     list_tmp = gsb_data_account_get_list_accounts ();
523 
524     while ( list_tmp )
525     {
526 	gint i;
527 
528 	i = gsb_data_account_get_no_account ( list_tmp -> data );
529 
530 	if (  i >= 0 && ( !gsb_data_account_get_closed_account (i) || include_closed ) )
531 	{
532 	    item = gtk_menu_item_new_with_label ( gsb_data_account_get_name (i));
533 	    g_object_set_data ( G_OBJECT ( item ),
534 				  "account_number",
535 				  GINT_TO_POINTER (i));
536 	    if ( func )
537 		g_signal_connect ( G_OBJECT ( item ), "activate", G_CALLBACK(func), NULL );
538 	    gtk_menu_shell_append ( GTK_MENU_SHELL ( menu ), item );
539 
540 	    if ( !activate_currrent &&
541 		 gsb_gui_navigation_get_current_account () == i)
542 	    {
543 		gtk_widget_set_sensitive ( item, FALSE );
544 	    }
545 
546 	    gtk_widget_show ( item );
547 	}
548 	list_tmp = list_tmp -> next;
549     }
550 
551     return ( menu );
552 }
553 
554 
555 
556 
557 
558 /**
559  *
560  *
561  * \param
562  *
563  * \return
564  **/
gsb_account_get_account_from_combo(void)565 gint gsb_account_get_account_from_combo (void)
566 {
567     GtkWidget *combo;
568     gint account_number = -1;
569 
570     combo = g_object_get_data (G_OBJECT (grisbi_win_get_account_page ()), "account_combo");
571     account_number = gsb_account_get_combo_account_number (combo);
572 
573     return account_number;
574 }
575 
576 /**
577  *
578  *
579  * \param
580  *
581  * \return
582  * */
583 /* Local Variables: */
584 /* c-basic-offset: 4 */
585 /* End: */
586