/** * callback called by the button to launch the automatic association * between transactions and reconcile * * \param button * \param assistant * * \return FALSE * */ static gboolean gsb_assistant_reconcile_config_lauch_manu_asso ( GtkWidget *button, GtkWidget *assistant ) { GList *tmp_list; GtkTreeIter iter; GtkTreeModel *model; GtkTreeSelection *selection; GList *path_list; gint account_number = -1; GtkWidget *dialog; GtkWidget *label; GtkWidget *scrolled_window; GtkWidget *dialog_tree_view; GtkListStore *dialog_store; gint return_value; gint i; enum dialog_column { DIALOG_NAME = 0, DIALOG_INIT_DATE, DIALOG_FINAL_DATE, DIALOG_RECONCILE_NUMBER, DIALOG_NB_COL }; gint selected_reconcile_number; gint transaction_number; /* get the selection */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_transactions_to_link)); /* get the selected transactions */ path_list = gtk_tree_selection_get_selected_rows ( GTK_TREE_SELECTION (selection), &model ); if (!path_list) return FALSE; /* ok, we have a selection, before continuing, * we check that all the transactions are on the same account */ tmp_list = path_list; while (tmp_list) { GtkTreePath *path; path = tmp_list -> data; if (gtk_tree_model_get_iter ( GTK_TREE_MODEL (model), &iter, path )) { gtk_tree_model_get ( GTK_TREE_MODEL (model), &iter, TRANSACTION_NUMBER, &transaction_number, -1 ); if (account_number == -1) account_number = gsb_data_transaction_get_account_number (transaction_number); else { if (gsb_data_transaction_get_account_number (transaction_number) != account_number) { dialogue_error (_("All the selected transactions have to belong to the same account !")); /* erase the path_list */ g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL); g_list_free (path_list); return FALSE; } } } tmp_list = tmp_list -> next; } if (account_number == -1) { /* erase the path_list */ g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL); g_list_free (path_list); return FALSE; } /* ok, all the transactions belong to the same account, we can * show a dialog to select the reconcile */ dialog = gtk_dialog_new_with_buttons ( _("Selection of a reconciliation"), GTK_WINDOW ( assistant ), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, "gtk-cancel", GTK_RESPONSE_CANCEL, "gtk-ok", GTK_RESPONSE_OK, NULL ); gtk_window_set_default_size ( GTK_WINDOW ( dialog ), 770, 412 ); gtk_window_set_position ( GTK_WINDOW ( dialog ), GTK_WIN_POS_CENTER_ON_PARENT ); gtk_window_set_resizable ( GTK_WINDOW ( dialog ), TRUE ); gtk_container_set_border_width ( GTK_CONTAINER ( dialog ), 12 ); label = gtk_label_new ( _("Select the reconciliation to associate to the selected transactions: ") ); gtk_misc_set_alignment ( GTK_MISC ( label ), 0.0, 0.0 ); gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), label, FALSE, FALSE, 10 ); /* make the list */ scrolled_window = gtk_scrolled_window_new (FALSE, FALSE); gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_box_pack_start ( GTK_BOX ( dialog_get_content_area ( dialog ) ), scrolled_window, TRUE, TRUE, 0 ); dialog_store = gtk_list_store_new ( DIALOG_NB_COL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT ); dialog_tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (dialog_store)); g_object_unref (G_OBJECT(dialog_store)); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (dialog_tree_view), TRUE); gtk_container_add ( GTK_CONTAINER (scrolled_window), dialog_tree_view ); /* set the columns */ for (i=DIALOG_NAME ; i<DIALOG_RECONCILE_NUMBER ; i++) { GtkTreeViewColumn *column; GtkCellRenderer *cell; gchar *titles[] = { _("Reconciliation reference"), _("Initial date"), _("Final date") }; gfloat alignment[] = { COLUMN_LEFT, COLUMN_CENTER, COLUMN_CENTER }; cell = gtk_cell_renderer_text_new (); g_object_set ( G_OBJECT (cell), "xalign", alignment[i], NULL ); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_sizing ( column, GTK_TREE_VIEW_COLUMN_AUTOSIZE ); gtk_tree_view_column_set_alignment ( column, alignment[i] ); gtk_tree_view_column_pack_start ( column, cell, TRUE ); gtk_tree_view_column_set_title ( column, titles[i] ); gtk_tree_view_column_set_attributes (column, cell, "text", i, NULL); gtk_tree_view_column_set_expand ( column, TRUE ); gtk_tree_view_column_set_resizable ( column, TRUE ); gtk_tree_view_append_column ( GTK_TREE_VIEW(dialog_tree_view), column); } /* fill the tree view */ tmp_list = gsb_data_reconcile_get_reconcile_list (); while (tmp_list) { gint reconcile_number; reconcile_number = gsb_data_reconcile_get_no_reconcile (tmp_list -> data); if (gsb_data_reconcile_get_account (reconcile_number) == account_number) { gchar *init_date_str; gchar *final_date_str; init_date_str = gsb_format_gdate (gsb_data_reconcile_get_init_date (reconcile_number)); final_date_str = gsb_format_gdate (gsb_data_reconcile_get_final_date (reconcile_number)); gtk_list_store_append ( GTK_LIST_STORE (dialog_store), &iter ); gtk_list_store_set ( GTK_LIST_STORE (dialog_store), &iter, DIALOG_NAME, gsb_data_reconcile_get_name (reconcile_number), DIALOG_INIT_DATE, init_date_str, DIALOG_FINAL_DATE, final_date_str, DIALOG_RECONCILE_NUMBER, reconcile_number, -1 ); g_free (init_date_str); g_free (final_date_str); } tmp_list = tmp_list -> next; } gtk_widget_show_all (dialog); /* launch the dialog */ return_value = gtk_dialog_run (GTK_DIALOG (dialog)); if (return_value != GTK_RESPONSE_OK) { gtk_widget_destroy (dialog); return FALSE; } /* we get the selected reconcile */ if (!gtk_tree_selection_get_selected ( gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog_tree_view)), NULL, &iter )) { dialogue_warning (_("No selection found, the transactions are not modified.")); gtk_widget_destroy (dialog); return FALSE; } gtk_tree_model_get ( GTK_TREE_MODEL (dialog_store), &iter, DIALOG_RECONCILE_NUMBER, &selected_reconcile_number, -1 ); /* ok we have the reconcile number, we can destroy the dialog */ gtk_widget_destroy (dialog); /* and now, fill the selected transactions with that reconcile number */ tmp_list = g_list_last (path_list); while (tmp_list) { GtkTreePath *path; path = tmp_list -> data; if (gtk_tree_model_get_iter ( GTK_TREE_MODEL (model), &iter, path )) { gtk_tree_model_get ( GTK_TREE_MODEL (model), &iter, TRANSACTION_NUMBER, &transaction_number, -1 ); gtk_list_store_remove ( GTK_LIST_STORE (model), &iter ); gsb_data_transaction_set_reconcile_number ( transaction_number, selected_reconcile_number ); transactions_to_link--; } tmp_list = tmp_list -> prev; } /* erase the path_list */ g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL); g_list_free (path_list); /* now there is 2 way : * either transactions_to_link is 0, we go directly to the succes page * either it's not null, and the user should create more reconciles */ if (transactions_to_link) { gchar *string; /* update the labels */ string = g_strdup_printf (_("Still %d transactions to link with a reconciliation."), transactions_to_link); gtk_label_set_text ( GTK_LABEL (label_transactions_to_link_1), string); gtk_label_set_text ( GTK_LABEL (label_transactions_to_link_3), string); g_free (string); gtk_widget_grab_focus (treeview_transactions_to_link); } else { /* go to the success page */ gsb_assistant_set_next ( assistant, RECONCILE_ASSISTANT_MANUALLY_ASSOCIATE, RECONCILE_ASSISTANT_SUCCESS ); gsb_assistant_next_page (assistant); } return FALSE; }
/** * \brief Import QIF data. * * Open a QIF file and fills in data in a struct_compte_importation * data structure. * * \param assistant Not used. * \param imported A pointer to structure containing name and * format of imported file. * * \return TRUE on success. */ gboolean recuperation_donnees_qif ( GtkWidget *assistant, struct imported_file *imported ) { gchar *tmp_str; struct struct_compte_importation *imported_account; gint returned_value = 0; gboolean premier_compte = TRUE; FILE *qif_file; qif_file = utf8_fopen ( imported -> name, "r" ); if ( ! qif_file ) return FALSE; mismatch_dates = TRUE; /* qif_file pointe sur le qif_file qui a été reconnu comme qif */ rewind ( qif_file ); imported_account = g_malloc0 ( sizeof ( struct struct_compte_importation )); imported_account -> nom_de_compte = unique_imported_name ( _("Invalid QIF file") ); imported_account -> filename = my_strdup ( imported -> name ); imported_account -> origine = my_strdup ( "QIF" ); /* save filename */ imported_account -> real_filename = my_strdup (imported -> name); /* It is positioned on the first line of file */ returned_value = get_utf8_line_from_file ( qif_file, &tmp_str, imported -> coding_system ); do { GSList *tmp_list; gchar *account_name = NULL; gint order = 0; gboolean name_preced = FALSE; struct struct_ope_importation *imported_transaction; do { if ( returned_value != EOF && tmp_str && g_ascii_strncasecmp ( tmp_str, "!Account", 8 ) == 0 ) { /* create and fill the new account */ imported_account = g_malloc0 ( sizeof ( struct struct_compte_importation ) ); imported_account -> origine = my_strdup ( "QIF" ); /* save filename and account_name */ imported_account -> real_filename = my_strdup ( imported -> name ); imported_account -> filename = my_strdup ( imported -> name ); account_name = gsb_qif_get_account_name ( qif_file, imported -> coding_system ); imported_account -> nom_de_compte = unique_imported_name ( account_name ); g_free ( account_name ); name_preced = TRUE; premier_compte = FALSE; returned_value = get_utf8_line_from_file ( qif_file, &tmp_str, imported -> coding_system ); } else if ( returned_value != EOF && tmp_str && g_ascii_strncasecmp ( tmp_str, "!Type:Cat", 9 ) == 0 ) { do { returned_value = gsb_qif_recupere_categories ( qif_file, imported -> coding_system ); if ( returned_value == 0 ) tmp_str = last_header; } /* continue untill the end of the file or a change of account */ while ( returned_value != EOF && returned_value != 0 ); } else if ( returned_value != EOF && tmp_str && g_ascii_strncasecmp ( tmp_str, "!Type", 5 ) == 0 ) { gint account_type; account_type = gsb_qif_get_account_type ( tmp_str ) ; if ( account_type == -1 ) { name_preced = FALSE; continue; } else { if ( name_preced == FALSE ) { /* create and fill the new account */ imported_account = g_malloc0 ( sizeof ( struct struct_compte_importation ) ); imported_account -> origine = my_strdup ( "QIF" ); /* save filename and account_name */ imported_account -> real_filename = my_strdup ( imported -> name ); imported_account -> filename = my_strdup ( imported -> name ); imported_account -> nom_de_compte = unique_imported_name ( my_strdup ( _("Imported QIF account" ) ) ); premier_compte = FALSE; } if ( account_type == 6 ) { /* on considère le imported_account d'investissement comme un imported_account * bancaire mais met un warning car pas implémenté, aucune idée si ça passe ou pas... */ gchar *msg; msg = g_strdup_printf ( _("Grisbi found an investment account:\n%s\n" "which is not implemented yet. Nevertheless, Grisbi will try " "to import it as a bank account." ), imported -> name ); dialogue_warning ( msg ); g_free ( msg ); account_type = 0; } imported_account -> type_de_compte = account_type; returned_value = -2; } } else name_preced = FALSE; } while ( returned_value != EOF && returned_value != -2 ); if ( returned_value == EOF ) { if ( premier_compte ) { /* no account already saved, so send an error */ liste_comptes_importes_error = g_slist_append ( liste_comptes_importes_error, imported_account ); fclose ( qif_file ); return FALSE; } else { /* we have at least saved an account before, ok, enough for me */ fclose ( qif_file ); return TRUE; } } do { returned_value = gsb_qif_recupere_operations_from_account ( qif_file, imported -> coding_system, imported_account ); if ( returned_value == 0 ) tmp_str = last_header; } /* continue untill the end of the file or a change of account */ while ( returned_value != EOF && returned_value != 0 ); /* first, we need to check if the first transaction is an opening balance * or a normal transaction * update : money sometimes translate Opening balance... */ if ( g_slist_length ( imported_account -> operations_importees) > 0 ) { imported_transaction = imported_account -> operations_importees -> data; if ( imported_transaction -> tiers && (!g_ascii_strncasecmp ( imported_transaction -> tiers, "Opening Balance", 15 ) || !g_ascii_strcasecmp ( imported_transaction -> tiers, _("Opening Balance") ) ) ) { /* ok, we are on an opening balance, we transfer the first transaction * to the initial datas of the account */ /* get the initial amount */ imported_account -> solde = imported_transaction -> montant; /* get the name of account */ tmp_str = my_strdelimit (imported_transaction -> categ, "[]", ""); if ( imported_account -> nom_de_compte ) g_free ( imported_account -> nom_de_compte ); imported_account -> nom_de_compte = unique_imported_name ( tmp_str ); g_free (tmp_str); /* get the date of the file */ imported_account -> date_solde_qif = my_strdup ( imported_transaction -> date_tmp ); /* now, we can remove the first imported transaction */ imported_account -> operations_importees = g_slist_remove ( imported_account -> operations_importees, imported_transaction ); g_free (imported_transaction); } /* now we need to transform the dates of transaction into gdate */ /* try to understand the order */ order = gsb_qif_get_date_order ( imported_account -> operations_importees ); if (order == -1) dialogue_error ( _("Grisbi couldn't determine the format of the date into the qif file.\n" "Please contact the Grisbi team ([email protected]) to find " "the problem.\nFor now, all the dates will be imported as 01.01.1970") ); } tmp_list = imported_account -> operations_importees; while (tmp_list) { imported_transaction = tmp_list -> data; if (order == -1) /* we didn't find the order */ imported_transaction -> date = g_date_new_dmy ( 1,1,2000 ); else imported_transaction -> date = gsb_qif_get_date ( imported_transaction -> date_tmp, order ); tmp_list = tmp_list -> next; } /* set the date of the qif file */ if ( imported_account -> date_solde_qif ) imported_account -> date_fin = gsb_qif_get_date (imported_account -> date_solde_qif, order); /* add that account to the others */ liste_comptes_importes = g_slist_append ( liste_comptes_importes, imported_account ); } /* go to the next account */ while ( returned_value != EOF ); fclose ( qif_file ); return ( TRUE ); }