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