/** * 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_auto_asso ( GtkWidget *button, GtkWidget *assistant ) { GSList *tmp_list; /* we will use the list already created */ tmp_list = list_association; while (tmp_list) { struct association_transaction_reconcile *association; association = tmp_list -> data; gsb_data_transaction_set_reconcile_number ( association -> transaction_number, association -> reconcile_number ); tmp_list = tmp_list -> next; } transactions_to_link = transactions_to_link - g_slist_length (list_association); g_slist_free (list_association); list_association = NULL; /* 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 reconciliations */ 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_2), string); g_free (string); gtk_misc_set_alignment ( GTK_MISC (label_transactions_to_link_2), 0, 0.5 ); gtk_label_set_text ( GTK_LABEL (label_possible_association), _("There is no transaction that Grisbi can link.\n" "Check if you created all the necesssary reconciliations.")); gtk_widget_set_sensitive ( button_run_association, FALSE ); } else { /* go to the success page */ gsb_assistant_set_next ( assistant, RECONCILE_ASSISTANT_AUTOMATICALLY_ASSOCIATE, RECONCILE_ASSISTANT_SUCCESS ); gsb_assistant_next_page (assistant); } return FALSE; }
/** * callback called when there is a change in the menu * change the next page to show according to the menu * * \param button * \param assistant * * \return FALSE * */ static gboolean gsb_assistant_reconcile_config_page_menu_toggled ( GtkWidget *button, GtkWidget *assistant ) { gint new_next_page; new_next_page = GPOINTER_TO_INT ( g_object_get_data (G_OBJECT (button), "next_page")); gsb_assistant_set_next ( assistant, RECONCILE_ASSISTANT_MENU, new_next_page ); return FALSE; }
/** * Add a page to the Grisbi assistant. * * \param assistant Grisbi assistant to add a page to. * \param widget Widget containing the new page to insert. * \param position Number of the page to insert. Page 0 is * reserved to the explanation label. * \param prev Page to display when the "Previous" button is * clicked. * \param next Page to display when the "Next" button is clicked. * \param enter_callback A callback to connect to the "switch-page" callback * of the Grisbi assistant notebook. (the callback should * be : gboolean callback ( GtkWidget *assistant, gint new_page ) ) */ void gsb_assistant_add_page ( GtkWidget * assistant, GtkWidget * widget, gint position, gint prev, gint next, GCallback enter_callback ) { GtkWidget * notebook; gchar *tmpstr; notebook = g_object_get_data ( G_OBJECT(assistant), "notebook" ); gtk_notebook_insert_page ( GTK_NOTEBOOK(notebook), widget, gtk_label_new(NULL), position ); gsb_assistant_set_prev ( assistant, position, prev ); gsb_assistant_set_next ( assistant, position, next ); tmpstr = g_strdup_printf ( "enter%d", position ); g_object_set_data ( G_OBJECT(assistant), tmpstr, enter_callback ); g_free (tmpstr); gtk_widget_show_all ( widget ); }
/** * Create and initialize a new grisbi assistant. It is basically * composed of a GtkDialog with a notebook that is switched from page * to page when user click on dialog buttons. * * \param title Title of the assistant. * \param explanation Short text to display in the first * page of the assistant. * \param image_filename Icon to display in the title. (if NULL, use grisbi.png, default logo) * \param enter_callback A callback to connect to the "switch-page" callback when go to the first page * of the Grisbi assistant notebook. (the callback should * be : gboolean callback ( GtkWidget *assistant, gint new_page ) ) * */ GtkWidget * gsb_assistant_new ( const gchar * title, const gchar * explanation, gchar * image_filename, GCallback enter_callback ) { GtkWidget * assistant, *notebook, *hbox, *label, *image, *view, *eb; GtkWidget * button_cancel, * button_prev, * button_next; GtkWidget *button_select; GtkStyle * style; GtkTextBuffer * buffer; gchar *tmpstr; gint width = 140; assistant = gtk_dialog_new_with_buttons ( title, GTK_WINDOW ( run.window ), GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR, NULL ); gtk_window_set_default_size ( GTK_WINDOW ( assistant ), 800, 500 ); gtk_window_set_position ( GTK_WINDOW ( assistant ), GTK_WIN_POS_CENTER_ON_PARENT ); gtk_window_set_resizable ( GTK_WINDOW ( assistant ), TRUE ); g_object_set_data ( G_OBJECT ( run.window ), "assistant", assistant ); button_select = gtk_toggle_button_new_with_label ( _("Select all") ); gtk_widget_set_size_request ( button_select, width, -1 ); gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( assistant )->action_area ), button_select, FALSE, FALSE, 0 ); g_object_set_data ( G_OBJECT(assistant), "button_select", button_select ); button_cancel = gtk_dialog_add_button ( GTK_DIALOG(assistant), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL ); gtk_widget_set_size_request ( button_cancel, width, -1 ); g_object_set_data ( G_OBJECT(assistant), "button_cancel", button_cancel ); button_prev = gtk_dialog_add_button ( GTK_DIALOG(assistant), GTK_STOCK_GO_BACK, GTK_RESPONSE_NO ); gtk_widget_set_size_request ( button_prev, width, -1 ); g_object_set_data ( G_OBJECT(assistant), "button_prev", button_prev ); gtk_widget_set_sensitive ( button_prev, FALSE ); button_next = gtk_dialog_add_button ( GTK_DIALOG(assistant), GTK_STOCK_GO_FORWARD, GTK_RESPONSE_YES ); gtk_widget_set_size_request ( button_next, width, -1 ); g_object_set_data ( G_OBJECT(assistant), "button_next", button_next ); eb = gtk_event_box_new (); style = gtk_widget_get_style ( eb ); gtk_widget_modify_bg ( eb, 0, &(style -> bg[GTK_STATE_ACTIVE]) ); hbox = gtk_hbox_new ( FALSE, 12 ); gtk_container_add ( GTK_CONTAINER(eb), hbox ); gtk_container_set_border_width ( GTK_CONTAINER(hbox), 12 ); label = gtk_label_new ( NULL ); tmpstr = g_markup_printf_escaped ( "<b><span size=\"x-large\">%s</span></b>", title ); gtk_label_set_markup ( GTK_LABEL(label), tmpstr ); g_free ( tmpstr ); gtk_box_pack_start ( GTK_BOX(hbox), label, TRUE, TRUE, 0 ); if (!image_filename) image_filename = "grisbi.png"; tmpstr = g_build_filename ( gsb_dirs_get_pixmaps_dir ( ), image_filename, NULL); image = gtk_image_new_from_file ( tmpstr ); g_free ( tmpstr ); gtk_box_pack_start ( GTK_BOX(hbox), image, FALSE, FALSE, 0 ); gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(assistant) -> vbox ), eb, FALSE, FALSE, 0 ); notebook = gtk_notebook_new (); gtk_notebook_set_show_tabs ( GTK_NOTEBOOK(notebook), FALSE ); gtk_notebook_set_show_border ( GTK_NOTEBOOK(notebook), FALSE ); gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(assistant) -> vbox ), notebook, TRUE, TRUE, 0 ); view = gtk_text_view_new (); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); tmpstr = g_strconcat ( "\n", explanation, "\n", NULL ); gtk_text_buffer_set_text (buffer, tmpstr, -1); g_free ( tmpstr ); gtk_text_view_set_editable ( GTK_TEXT_VIEW(view), FALSE ); gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW(view), FALSE ); gtk_text_view_set_left_margin ( GTK_TEXT_VIEW(view), 12 ); gtk_text_view_set_right_margin ( GTK_TEXT_VIEW(view), 12 ); /* Create some handy fonts. */ gtk_text_buffer_create_tag ( buffer, "bold", "weight", PANGO_WEIGHT_BOLD, NULL ); gtk_text_buffer_create_tag ( buffer, "x-large", "scale", PANGO_SCALE_X_LARGE, NULL ); gtk_text_buffer_create_tag ( buffer, "indented", "left-margin", 24, NULL ); gtk_notebook_append_page ( GTK_NOTEBOOK(notebook), view, gtk_label_new(NULL) ); g_signal_connect_after ( notebook, "switch-page", G_CALLBACK ( gsb_assistant_change_page ), assistant ); gsb_assistant_set_next ( assistant, 0, 1 ); g_object_set_data ( G_OBJECT(assistant), "notebook", notebook ); /* need to set (gchar *) because title is const gchar, the good way should be my_strdup, * but we don't touch/free title later so it should be ok... */ g_object_set_data ( G_OBJECT(assistant), "title", (gchar *) title ); g_object_set_data ( G_OBJECT(assistant), "enter0", enter_callback ); return assistant; }
/** * 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; }