From a860643922461a2c3d878a6dac3b0cc2475e5829 Mon Sep 17 00:00:00 2001 From: Robert Fewell <14uBobIT@gmail.com> Date: Mon, 1 Aug 2016 14:30:24 +0100 Subject: [PATCH] Transaction Association List Dialog This new dialog creates a list view of transaction associations and allows them to be checked to see if they are still available and be able to jump to the corresponding transaction in the register or open the associated entry. --- po/POTFILES.in | 2 + src/gnome/CMakeLists.txt | 2 + src/gnome/Makefile.am | 2 + src/gnome/dialog-trans-assoc.c | 367 ++++++++++++++++++ src/gnome/dialog-trans-assoc.h | 28 ++ src/gnome/gnc-plugin-basic-commands.c | 15 + .../org.gnucash.dialogs.gschema.xml.in.in | 11 + src/gnome/gtkbuilder/Makefile.am | 1 + src/gnome/gtkbuilder/dialog-trans-assoc.glade | 185 +++++++++ src/gnome/ui/gnc-plugin-basic-commands-ui.xml | 1 + 10 files changed, 614 insertions(+) create mode 100644 src/gnome/dialog-trans-assoc.c create mode 100644 src/gnome/dialog-trans-assoc.h create mode 100644 src/gnome/gtkbuilder/dialog-trans-assoc.glade diff --git a/po/POTFILES.in b/po/POTFILES.in index 11174a1a3d..d05232a934 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -220,6 +220,7 @@ src/gnome/dialog-sx-editor.c src/gnome/dialog-sx-from-trans.c src/gnome/dialog-sx-since-last-run.c src/gnome/dialog-tax-info.c +src/gnome/dialog-trans-assoc.c src/gnome/gnc-budget-view.c src/gnome/gnc-plugin-account-tree.c src/gnome/gnc-plugin-basic-commands.c @@ -256,6 +257,7 @@ src/gnome/gtkbuilder/dialog-print-check.glade src/gnome/gtkbuilder/dialog-progress.glade src/gnome/gtkbuilder/dialog-sx.glade src/gnome/gtkbuilder/dialog-tax-info.glade +src/gnome/gtkbuilder/dialog-trans-assoc.glade src/gnome/gtkbuilder/gnc-plugin-page-budget.glade src/gnome/gtkbuilder/gnc-plugin-page-register2.glade src/gnome/gtkbuilder/gnc-plugin-page-register.glade diff --git a/src/gnome/CMakeLists.txt b/src/gnome/CMakeLists.txt index 9079fb091f..d22675c4cd 100644 --- a/src/gnome/CMakeLists.txt +++ b/src/gnome/CMakeLists.txt @@ -20,6 +20,7 @@ SET (gnc_gnome_noinst_HEADERS dialog-sx-editor2.h dialog-sx-from-trans.h dialog-sx-since-last-run.h + dialog-trans-assoc.h gnc-budget-view.h gnc-plugin-account-tree.h gnc-plugin-basic-commands.h @@ -65,6 +66,7 @@ SET (gnc_gnome_SOURCES dialog-sx-from-trans.c dialog-sx-since-last-run.c dialog-tax-info.c + dialog-trans-assoc.c gnc-budget-view.c gnc-plugin-account-tree.c gnc-plugin-basic-commands.c diff --git a/src/gnome/Makefile.am b/src/gnome/Makefile.am index 54d36cc973..e07ae2ab7d 100644 --- a/src/gnome/Makefile.am +++ b/src/gnome/Makefile.am @@ -44,6 +44,7 @@ libgnc_gnome_la_SOURCES = \ dialog-sx-from-trans.c \ dialog-sx-since-last-run.c \ dialog-tax-info.c \ + dialog-trans-assoc.c \ gnc-budget-view.c \ gnc-plugin-account-tree.c \ gnc-plugin-basic-commands.c \ @@ -93,6 +94,7 @@ noinst_HEADERS = \ dialog-sx-editor2.h \ dialog-sx-from-trans.h \ dialog-sx-since-last-run.h \ + dialog-trans-assoc.h \ gnc-budget-view.h \ gnc-plugin-account-tree.h \ gnc-plugin-basic-commands.h \ diff --git a/src/gnome/dialog-trans-assoc.c b/src/gnome/dialog-trans-assoc.c new file mode 100644 index 0000000000..77eeeb3e87 --- /dev/null +++ b/src/gnome/dialog-trans-assoc.c @@ -0,0 +1,367 @@ +/********************************************************************\ + * dialog-trans-assoc.c -- Transaction associations dialog * + * Copyright (C) 2016 Robert Fewell * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * +\********************************************************************/ + +#include "config.h" + +#include +#include + +#include "dialog-trans-assoc.h" + +#include "dialog-utils.h" +#include "gnc-component-manager.h" +#include "Query.h" +#include "Transaction.h" + +#include "gnc-plugin-page-register.h" +#include "gnc-main-window.h" + +#include "gnc-ui-util.h" +#include "gnc-gnome-utils.h" +#include "Account.h" + +#define DIALOG_ASSOC_CM_CLASS "dialog-trans-assoc" +#define GNC_PREFS_GROUP "dialogs.trans-assoc" + +/** Enumeration for the tree-store */ +enum GncAssocColumn {DATE_TRANS, DESC_TRANS, URI, AVAILABLE, URI_SPLIT}; + +typedef struct +{ + GtkWidget *dialog; + GtkWidget *view; +}AssocDialog; + +/* This static indicates the debugging module that this .o belongs to. */ +static QofLogModule log_module = GNC_MOD_GUI; + +void gnc_assoc_dialog_window_destroy_cb (GtkWidget *object, gpointer user_data); +void gnc_assoc_dialog_close_cb (GtkDialog *dialog, gpointer user_data); +void gnc_assoc_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data); + + +void +gnc_assoc_dialog_window_destroy_cb (GtkWidget *object, gpointer user_data) +{ + AssocDialog *assoc_dialog = user_data; + + ENTER(" "); + gnc_unregister_gui_component_by_data (DIALOG_ASSOC_CM_CLASS, assoc_dialog); + + if (assoc_dialog->dialog) + { + gtk_widget_destroy (assoc_dialog->dialog); + assoc_dialog->dialog = NULL; + } + g_free (assoc_dialog); + LEAVE(" "); +} + +void +gnc_assoc_dialog_close_cb (GtkDialog *dialog, gpointer user_data) +{ + AssocDialog *assoc_dialog = user_data; + + ENTER(" "); + gnc_close_gui_component_by_data (DIALOG_ASSOC_CM_CLASS, assoc_dialog); + LEAVE(" "); +} + +static void +assoc_dialog_update (AssocDialog *assoc_dialog) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean valid; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW(assoc_dialog->view)); + + /* Get first row in list store */ + valid = gtk_tree_model_get_iter_first (model, &iter); + + while (valid) + { + GNetworkMonitor *nm; + GSocketConnectable *conn; + gchar *uri; + gchar *filename; + + gtk_tree_model_get (model, &iter, URI, &uri, -1); + + filename = g_filename_from_uri (uri, NULL, NULL); + + if (filename != NULL) + { + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + gtk_list_store_set (GTK_LIST_STORE(model), &iter, AVAILABLE, _("File Found"), -1); + else + gtk_list_store_set (GTK_LIST_STORE(model), &iter, AVAILABLE, _("File Not Found"), -1); + } + else + { + nm = g_network_monitor_get_default (); + conn = g_network_address_parse_uri (uri, 80, NULL); + + if (conn != NULL) + { + if (g_network_monitor_can_reach (nm, conn, NULL, NULL)) + gtk_list_store_set (GTK_LIST_STORE(model), &iter, AVAILABLE, _("Address Found"), -1); + else + gtk_list_store_set (GTK_LIST_STORE(model), &iter, AVAILABLE, _("Address Not Found"), -1); + } + } + g_free (filename); + g_free (uri); + valid = gtk_tree_model_iter_next (model, &iter); + } +} + +void +gnc_assoc_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data) +{ + AssocDialog *assoc_dialog = user_data; + + switch (response_id) + { + case GTK_RESPONSE_APPLY: + assoc_dialog_update (assoc_dialog); + return; + + case GTK_RESPONSE_CLOSE: + default: + gnc_close_gui_component_by_data (DIALOG_ASSOC_CM_CLASS, assoc_dialog); + return; + } +} + +static void +row_selected_cb (GtkTreeView *view, GtkTreePath *path, + GtkTreeViewColumn *col, gpointer user_data) +{ + AssocDialog *assoc_dialog = user_data; + GncPluginPage *page; + GNCSplitReg *gsr; + Account *account; + GtkTreeModel *model; + GtkTreeIter iter; + Split *split; + const gchar *uri; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW(assoc_dialog->view)); + + if (!gtk_tree_model_get_iter (model, &iter, path)) + return; /* path describes a non-existing row - should not happen */ + + gtk_tree_model_get (model, &iter, URI, &uri, URI_SPLIT, &split, -1); + + if ((gtk_tree_view_get_column (GTK_TREE_VIEW(assoc_dialog->view), URI) == col) || + (gtk_tree_view_get_column (GTK_TREE_VIEW(assoc_dialog->view), AVAILABLE) == col)) + { + gnc_launch_assoc (uri); + } + else + { + /* This should never be true, but be paranoid */ + if (split == NULL) + return; + + account = xaccSplitGetAccount (split); + if (!account) + return; + + page = gnc_plugin_page_register_new (account, FALSE); + gnc_main_window_open_page (NULL, page); + gsr = gnc_plugin_page_register_get_gsr (page); + gnc_split_reg_raise (gsr); + + if (gsr == NULL) + return; + + gnc_split_reg_jump_to_split (gsr, split); + } +} + +static void +get_trans_info (AssocDialog *assoc_dialog) +{ + QofBook *book = gnc_get_current_book(); + Account *root = gnc_book_get_root_account (book); + GList *accts, *ptr; + GtkTreeModel *model; + GtkTreeIter iter; + GList *splits, *trans_list = NULL; + + /* Get list of Accounts */ + accts = gnc_account_get_descendants_sorted (root); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW(assoc_dialog->view)); + + /* Go through list of accounts */ + for (ptr = accts; ptr; ptr = g_list_next (ptr)) + { + Query *query = qof_query_create_for (GNC_ID_SPLIT); + Account *acc = ptr->data; + + qof_query_set_book (query, book); + xaccQueryAddSingleAccountMatch (query, acc, QOF_QUERY_AND); + + /* Run the query */ + for (splits = qof_query_run (query); splits; splits = splits->next) + { + Split *split = splits->data; + Transaction *trans = xaccSplitGetParent (split); + const gchar *uri; + + // Look for trans already in trans_list + if (g_list_find (trans_list, trans) != NULL) + continue; + + uri = xaccTransGetAssociation (trans); + + if (g_strcmp0 (uri, "") != 0 && g_strcmp0 (uri, NULL) != 0) + { + Timespec ts = {0,0}; + xaccTransGetDatePostedTS (trans, &ts); + + if (ts.tv_sec == 0) + ts.tv_sec = gnc_time (NULL); + + gtk_list_store_append (GTK_LIST_STORE(model), &iter); + + gtk_list_store_set (GTK_LIST_STORE(model), &iter, + DATE_TRANS, gnc_print_date (ts), + DESC_TRANS, xaccTransGetDescription (trans), + URI, uri, AVAILABLE, _("Unknown"), URI_SPLIT, split, -1); + } + trans_list = g_list_prepend (trans_list, trans); // add trans to trans_list + } + qof_query_destroy (query); + g_list_free (splits); + } + g_list_free (accts); + g_list_free (trans_list); +} + +static void +gnc_assoc_dialog_create (AssocDialog *assoc_dialog) +{ + GtkWidget *dialog; + GtkBuilder *builder; + GtkTreeSelection *selection; + + ENTER(" "); + builder = gtk_builder_new(); + gnc_builder_add_from_file (builder, "dialog-trans-assoc.glade", "list-store"); + + gnc_builder_add_from_file (builder, "dialog-trans-assoc.glade", "Transaction Association Dialog"); + + dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Transaction Association Dialog")); + assoc_dialog->dialog = dialog; + + assoc_dialog->view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview")); + + g_signal_connect (assoc_dialog->view, "row-activated", + G_CALLBACK(row_selected_cb), (gpointer)assoc_dialog); + + /* Enable alternative line colors */ + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(assoc_dialog->view), TRUE); + + /* default to 'close' button */ + gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(assoc_dialog->view)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, assoc_dialog); + + g_object_unref (G_OBJECT(builder)); + + gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(assoc_dialog->dialog)); + get_trans_info (assoc_dialog); + + LEAVE(" "); +} + +static void +close_handler (gpointer user_data) +{ + AssocDialog *assoc_dialog = user_data; + + ENTER(" "); + gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(assoc_dialog->dialog)); + gtk_widget_destroy (GTK_WIDGET(assoc_dialog->dialog)); + LEAVE(" "); +} + +static void +refresh_handler (GHashTable *changes, gpointer user_data) +{ + ENTER(" "); + LEAVE(" "); +} + +static gboolean +show_handler (const char *klass, gint component_id, + gpointer user_data, gpointer iter_data) +{ + AssocDialog *assoc_dialog = user_data; + + ENTER(" "); + if (!assoc_dialog) + { + LEAVE("No data strucure"); + return(FALSE); + } + gtk_window_present (GTK_WINDOW(assoc_dialog->dialog)); + LEAVE(" "); + return(TRUE); +} + +/********************************************************************\ + * gnc_trans_assoc_dialog * + * opens a window showing the Associations of all Transactions * + * * + * Args: parent - the parent of the window to be created * + * Return: nothing * +\********************************************************************/ +void +gnc_trans_assoc_dialog () +{ + AssocDialog *assoc_dialog; + + ENTER(" "); + if (gnc_forall_gui_components (DIALOG_ASSOC_CM_CLASS, show_handler, NULL)) + { + LEAVE("Existing dialog raised"); + return; + } + assoc_dialog = g_new0 (AssocDialog, 1); + + gnc_assoc_dialog_create (assoc_dialog); + + gnc_register_gui_component (DIALOG_ASSOC_CM_CLASS, + refresh_handler, close_handler, + assoc_dialog); + + gtk_widget_show (assoc_dialog->dialog); + LEAVE(" "); +} diff --git a/src/gnome/dialog-trans-assoc.h b/src/gnome/dialog-trans-assoc.h new file mode 100644 index 0000000000..fa82fcb8a5 --- /dev/null +++ b/src/gnome/dialog-trans-assoc.h @@ -0,0 +1,28 @@ +/********************************************************************\ + * dialog-trans-assoc.h -- Transaction associations dialog * + * Copyright (C) 2016 Robert Fewell * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gnu@gnu.org * +\********************************************************************/ + +#ifndef DIALOG_TRANS_ASSOC_H +#define DIALOG_TRANS_ASSOC_H + +void gnc_trans_assoc_dialog (void); + +#endif diff --git a/src/gnome/gnc-plugin-basic-commands.c b/src/gnome/gnc-plugin-basic-commands.c index 1d588208c6..dd52ee5662 100644 --- a/src/gnome/gnc-plugin-basic-commands.c +++ b/src/gnome/gnc-plugin-basic-commands.c @@ -47,6 +47,7 @@ #include "dialog-imap-editor.h" #include "dialog-sx-since-last-run.h" #include "dialog-totd.h" +#include "dialog-trans-assoc.h" #include "assistant-acct-period.h" #include "assistant-loan.h" #include "gnc-engine.h" @@ -90,6 +91,7 @@ static void gnc_main_window_cmd_tools_close_book (GtkAction *action, GncMainWind static void gnc_main_window_cmd_tools_find_transactions (GtkAction *action, GncMainWindowActionData *data); static void gnc_main_window_cmd_tools_price_editor (GtkAction *action, GncMainWindowActionData *data); static void gnc_main_window_cmd_tools_imap_editor (GtkAction *action, GncMainWindowActionData *data); +static void gnc_main_window_cmd_tools_trans_assoc (GtkAction *action, GncMainWindowActionData *data); static void gnc_main_window_cmd_tools_commodity_editor (GtkAction *action, GncMainWindowActionData *data); static void gnc_main_window_cmd_help_totd (GtkAction *action, GncMainWindowActionData *data); @@ -208,6 +210,11 @@ static GtkActionEntry gnc_plugin_actions [] = N_("View and Delete Bayesian and Non Bayesian information"), G_CALLBACK (gnc_main_window_cmd_tools_imap_editor) }, + { + "ToolsTransAssocAction", NULL, N_("_Transaction Associations"), NULL, + N_("View all Transaction Associations"), + G_CALLBACK (gnc_main_window_cmd_tools_trans_assoc) + }, /* Help menu */ @@ -617,6 +624,14 @@ gnc_main_window_cmd_tools_imap_editor (GtkAction *action, GncMainWindowActionDat gnc_unset_busy_cursor(NULL); } +static void +gnc_main_window_cmd_tools_trans_assoc (GtkAction *action, GncMainWindowActionData *data) +{ + gnc_set_busy_cursor (NULL, TRUE); + gnc_trans_assoc_dialog (); + gnc_unset_busy_cursor (NULL); +} + static void gnc_main_window_cmd_tools_price_editor (GtkAction *action, GncMainWindowActionData *data) { diff --git a/src/gnome/gschemas/org.gnucash.dialogs.gschema.xml.in.in b/src/gnome/gschemas/org.gnucash.dialogs.gschema.xml.in.in index 36ab8fc30b..52130c6faf 100644 --- a/src/gnome/gschemas/org.gnucash.dialogs.gschema.xml.in.in +++ b/src/gnome/gschemas/org.gnucash.dialogs.gschema.xml.in.in @@ -19,6 +19,7 @@ + @@ -223,4 +224,14 @@ followed by the width and height of the window. + + + + (-1,-1,-1,-1) + Last window position and size + This setting describes the size and position of the window when it was last closed. + The numbers are the X and Y coordinates of the top left corner of the window + followed by the width and height of the window. + + diff --git a/src/gnome/gtkbuilder/Makefile.am b/src/gnome/gtkbuilder/Makefile.am index 110e324500..ebf0dd249d 100644 --- a/src/gnome/gtkbuilder/Makefile.am +++ b/src/gnome/gtkbuilder/Makefile.am @@ -14,6 +14,7 @@ gtkbuilder_DATA = \ dialog-progress.glade \ dialog-sx.glade \ dialog-tax-info.glade \ + dialog-trans-assoc.glade \ gnc-plugin-page-budget.glade \ gnc-plugin-page-register.glade \ gnc-plugin-page-register2.glade \ diff --git a/src/gnome/gtkbuilder/dialog-trans-assoc.glade b/src/gnome/gtkbuilder/dialog-trans-assoc.glade new file mode 100644 index 0000000000..d87d6642f1 --- /dev/null +++ b/src/gnome/gtkbuilder/dialog-trans-assoc.glade @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + True + True + True + True + 6 + Transaction Association Dialog + 600 + 400 + True + normal + + + + + False + + + False + end + + + _Locate Association + True + True + True + True + + + False + False + 0 + + + + + gtk-close + True + True + True + True + False + True + + + False + False + 1 + + + + + False + False + end + 0 + + + + + True + False + All Transaction Associations + + + False + False + 5 + 1 + + + + + True + True + automatic + automatic + + + True + True + list-store + + + True + Date + 0.5 + + + + 0 + + + + + + + True + Description + 0.5 + + + + 1 + + + + + + + True + Association + 0.5 + + + + 2 + + + + + + + True + Available ? + 0.5 + + + 10 + + + 3 + + + + + + + + + True + True + 2 + + + + + True + False + 5 + To jump to Transaction, double click on Date or Description columns on + row required or Association and Available to Open the Association + + + False + False + 3 + + + + + + Check + close_button + + + diff --git a/src/gnome/ui/gnc-plugin-basic-commands-ui.xml b/src/gnome/ui/gnc-plugin-basic-commands-ui.xml index a6a8cc3126..022727c9c0 100644 --- a/src/gnome/ui/gnc-plugin-basic-commands-ui.xml +++ b/src/gnome/ui/gnc-plugin-basic-commands-ui.xml @@ -57,6 +57,7 @@ +