gnucash master: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sat Aug 20 19:12:49 EDT 2016


Updated	 via  https://github.com/Gnucash/gnucash/commit/5cd57e24 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/258d994e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6f70e08b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/47953c9b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/531f0f3c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a8606439 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5f75f106 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/57666b43 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5bb53c04 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8f9d1dcf (commit)
	from  https://github.com/Gnucash/gnucash/commit/90b7a6f6 (commit)



commit 5cd57e24d9a9c75db159ea0b5b89e837d80876c5
Merge: 90b7a6f 258d994
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Aug 20 16:12:02 2016 -0700

    Merge branch 'trans-assoc' from Bob Fewell.


commit 258d994e2c37b47d504544450a4daec441ad2ddb
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Aug 19 11:57:14 2016 +0100

    Change Transaction Association Dialog
    
    Update dialog to reflect the use of relative paths by the addition of a
    toggle column indicating such.

diff --git a/src/gnome/dialog-trans-assoc.c b/src/gnome/dialog-trans-assoc.c
index e9ae812..59cf0d6 100644
--- a/src/gnome/dialog-trans-assoc.c
+++ b/src/gnome/dialog-trans-assoc.c
@@ -34,7 +34,8 @@
 
 #include "gnc-plugin-page-register.h"
 #include "gnc-main-window.h"
-
+#include "gnc-prefs.h"
+#include "gnc-ui.h"
 #include "gnc-ui-util.h"
 #include "gnc-gnome-utils.h"
 #include "Account.h"
@@ -43,12 +44,14 @@
 #define GNC_PREFS_GROUP         "dialogs.trans-assoc"
 
 /** Enumeration for the tree-store */
-enum GncAssocColumn {DATE_TRANS, DESC_TRANS, URI, AVAILABLE, URI_SPLIT};
+enum GncAssocColumn {DATE_TRANS, DESC_TRANS, URI_U, AVAILABLE, URI_SPLIT, URI, URI_RELATIVE};
 
 typedef struct
 {
     GtkWidget    *dialog;
     GtkWidget    *view;
+    const gchar  *path_head;
+    gboolean      valid_path_head;
 }AssocDialog;
 
 /* This static indicates the debugging module that this .o belongs to.  */
@@ -136,6 +139,41 @@ assoc_dialog_sort (AssocDialog *assoc_dialog)
     gtk_tree_sortable_set_sort_column_id (sortable, URI, order);
 }
 
+static const gchar *
+convert_uri_relative_to_uri (AssocDialog *assoc_dialog, const gchar *uri)
+{
+    const gchar *new_uri;
+
+    if (assoc_dialog->valid_path_head && g_str_has_prefix (uri,"file:/") &&
+        !g_str_has_prefix (uri,"file://")) // path is relative
+    {
+        const gchar *part = uri + strlen ("file:");
+        new_uri = g_strconcat (assoc_dialog->path_head, part, NULL);
+    }
+    else
+        new_uri = g_strdup (uri);
+
+    return new_uri;
+}
+
+static gchar *
+convert_uri_to_filename (AssocDialog *assoc_dialog, const gchar *uri)
+{
+    const gchar *new_uri = convert_uri_relative_to_uri (assoc_dialog, uri);
+    gchar *filename = g_filename_from_uri (new_uri, NULL, NULL);
+
+    return filename;
+}
+
+static gchar *
+convert_uri_to_unescaped (AssocDialog *assoc_dialog, const gchar *uri)
+{
+    const gchar *new_uri = convert_uri_relative_to_uri (assoc_dialog, uri);
+    gchar *uri_u = g_uri_unescape_string (new_uri, NULL);
+
+    return uri_u;
+}
+
 static void
 assoc_dialog_update (AssocDialog *assoc_dialog)
 {
@@ -157,7 +195,7 @@ assoc_dialog_update (AssocDialog *assoc_dialog)
 
         gtk_tree_model_get (model, &iter, URI, &uri, -1);
 
-        filename = g_filename_from_uri (uri, NULL, NULL);
+        filename = convert_uri_to_filename (assoc_dialog, uri);
 
         if (filename != NULL)
         {
@@ -179,8 +217,8 @@ assoc_dialog_update (AssocDialog *assoc_dialog)
                     gtk_list_store_set (GTK_LIST_STORE(model), &iter, AVAILABLE, _("Address Not Found"), -1);
             }
         }
-        g_free (filename);
         g_free (uri);
+        g_free (filename);
         valid = gtk_tree_model_iter_next (model, &iter);
     }
 }
@@ -212,28 +250,38 @@ 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;
+    GtkTreeModel  *model = gtk_tree_view_get_model (GTK_TREE_VIEW(assoc_dialog->view));
     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 */
+        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))
+    // Open associated link
+    if (gtk_tree_view_get_column (GTK_TREE_VIEW(assoc_dialog->view), URI_U) == col)
     {
-        gnc_launch_assoc (uri);
+        const gchar *uri_out = convert_uri_relative_to_uri (assoc_dialog, uri);
+        gchar *uri_scheme = g_uri_parse_scheme (uri_out);
+
+        if (uri_scheme != NULL) // make sure we have a schme entry
+        {
+            gnc_launch_assoc (uri_out);
+            g_free (uri_scheme);
+        }
+        else
+            gnc_error_dialog (NULL, "%s", _("This transaction is not associated with a valid URI."));
     }
-    else
+
+    // Open transaction
+    if (gtk_tree_view_get_column (GTK_TREE_VIEW(assoc_dialog->view), DESC_TRANS) == col)
     {
+        GncPluginPage *page;
+        GNCSplitReg   *gsr;
+        Account       *account;
+
         /* This should never be true, but be paranoid */
         if (split == NULL)
             return;
@@ -293,6 +341,8 @@ get_trans_info (AssocDialog *assoc_dialog)
 
             if (g_strcmp0 (uri, "") != 0 && g_strcmp0 (uri, NULL) != 0)
             {
+                gchar *uri_u;
+                gboolean rel = FALSE;
                 Timespec ts = {0,0};
                 xaccTransGetDatePostedTS (trans, &ts);
 
@@ -301,10 +351,18 @@ get_trans_info (AssocDialog *assoc_dialog)
 
                 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
 
+                if (g_str_has_prefix (uri,"file:/") && !g_str_has_prefix (uri,"file://")) // path is relative
+                    rel = TRUE;
+
+                uri_u = convert_uri_to_unescaped (assoc_dialog, uri);
+
                 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);
+                                    URI_U, uri_u, AVAILABLE, _("Unknown"),
+                                    URI_SPLIT, split, URI, uri, URI_RELATIVE, rel, -1);
+
+                g_free (uri_u);
             }
             trans_list = g_list_prepend (trans_list, trans); // add trans to trans_list
         }
@@ -318,9 +376,12 @@ get_trans_info (AssocDialog *assoc_dialog)
 static void
 gnc_assoc_dialog_create (AssocDialog *assoc_dialog)
 {
-    GtkWidget        *dialog;
-    GtkBuilder       *builder;
-    GtkTreeSelection *selection;
+    GtkWidget         *dialog;
+    GtkBuilder        *builder;
+    GtkTreeSelection  *selection;
+    GtkWidget         *path_head;
+    GtkTreeViewColumn *tree_column;
+    GtkCellRenderer   *cr;
 
     ENTER(" ");
     builder = gtk_builder_new();
@@ -332,6 +393,43 @@ gnc_assoc_dialog_create (AssocDialog *assoc_dialog)
     assoc_dialog->dialog = dialog;
 
     assoc_dialog->view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
+    path_head = GTK_WIDGET(gtk_builder_get_object (builder, "path-head"));
+
+    assoc_dialog->path_head = gnc_prefs_get_string (GNC_PREFS_GROUP_GENERAL, "assoc-head");
+
+    if ((assoc_dialog->path_head != NULL) && (g_strcmp0 (assoc_dialog->path_head, "") != 0)) // not default entry
+    {
+        gchar *uri_u = g_uri_unescape_string (assoc_dialog->path_head, NULL);
+        gchar *path_head_str = g_filename_from_uri (uri_u, NULL, NULL);
+        gchar *path_head_label;
+
+        assoc_dialog->valid_path_head = TRUE;
+
+        // test for current folder being present
+        if (g_file_test (path_head_str, G_FILE_TEST_IS_DIR))
+            path_head_label = g_strconcat (_("Path head for files is, "), path_head_str, NULL);
+        else
+            path_head_label = g_strconcat (_("Path head does not exist, "), path_head_str, NULL);
+
+        gtk_label_set_text (GTK_LABEL(path_head), path_head_label);
+        g_free (path_head_label);
+        g_free (uri_u);
+        g_free (path_head_str);
+    }
+    else
+        assoc_dialog->valid_path_head = FALSE;
+
+    /* Need to add toggle renderers here to get the xalign to work. */
+    tree_column = gtk_tree_view_column_new();
+    gtk_tree_view_column_set_title (tree_column, _("Relative"));
+    gtk_tree_view_append_column (GTK_TREE_VIEW(assoc_dialog->view), tree_column);
+    gtk_tree_view_column_set_alignment (tree_column, 0.5);
+    gtk_tree_view_column_set_expand (tree_column, TRUE);
+    cr = gtk_cell_renderer_toggle_new();
+    gtk_tree_view_column_pack_start (tree_column, cr, TRUE);
+    // connect 'active' and set 'xalign' property of the cell renderer
+    gtk_tree_view_column_set_attributes (tree_column, cr, "active", URI_RELATIVE, NULL);
+    gtk_cell_renderer_set_alignment (cr, 0.5, 0.5);
 
     g_signal_connect (assoc_dialog->view, "row-activated",
                       G_CALLBACK(row_selected_cb), (gpointer)assoc_dialog);
diff --git a/src/gnome/gtkbuilder/dialog-trans-assoc.glade b/src/gnome/gtkbuilder/dialog-trans-assoc.glade
index 6eaaffa..721a9d5 100644
--- a/src/gnome/gtkbuilder/dialog-trans-assoc.glade
+++ b/src/gnome/gtkbuilder/dialog-trans-assoc.glade
@@ -8,12 +8,16 @@
       <column type="gchararray"/>
       <!-- column-name desc -->
       <column type="gchararray"/>
-      <!-- column-name uri -->
+      <!-- column-name uri_u -->
       <column type="gchararray"/>
       <!-- column-name available -->
       <column type="gchararray"/>
       <!-- column-name split -->
       <column type="gpointer"/>
+      <!-- column-name uri -->
+      <column type="gchararray"/>
+      <!-- column-name uri_relative -->
+      <column type="gboolean"/>
     </columns>
   </object>
   <object class="GtkDialog" id="Transaction Association Dialog">
@@ -32,6 +36,19 @@
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox2">
         <property name="can_focus">False</property>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">All Transaction Associations</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="padding">2</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child internal-child="action_area">
           <object class="GtkHButtonBox" id="dialog-action_area1">
             <property name="can_focus">False</property>
@@ -89,16 +106,15 @@
           </packing>
         </child>
         <child>
-          <object class="GtkLabel" id="label1">
+          <object class="GtkLabel" id="path-head">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="label" translatable="yes">All Transaction Associations</property>
           </object>
           <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
             <property name="padding">5</property>
-            <property name="position">1</property>
+            <property name="position">2</property>
           </packing>
         </child>
         <child>
@@ -139,7 +155,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkTreeViewColumn" id="uri entry">
+                  <object class="GtkTreeViewColumn" id="uri-entry">
                     <property name="resizable">True</property>
                     <property name="title" translatable="yes">Association</property>
                     <property name="alignment">0.5</property>
@@ -172,7 +188,7 @@
           <packing>
             <property name="expand">True</property>
             <property name="fill">True</property>
-            <property name="position">2</property>
+            <property name="position">3</property>
           </packing>
         </child>
         <child>
@@ -180,13 +196,14 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="ypad">5</property>
-            <property name="label" translatable="yes">To jump to Transaction, double click on Date or Description columns on
- row required or Association and Available to Open the Association</property>
+            <property name="label" translatable="yes">     To jump to the Transaction, double click on the entry in the
+Description column or Association column to open the Association</property>
           </object>
           <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
-            <property name="position">3</property>
+            <property name="padding">5</property>
+            <property name="position">4</property>
           </packing>
         </child>
       </object>

commit 6f70e08bdfe1964bf6d009345f09560d277f68d1
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Aug 16 16:38:22 2016 +0100

    Add check for path being relative.
    
    If the preference "assoc-head" is set and file path is a sub directory
    then only this part is saved to the transaction making the full path
    portable. Paths outside of "assoc-head" will be saved in full. There is
    also a test to make sure the URI passed to the open call has a valid
    scheme otherwise the windows version will crash.

diff --git a/src/gnome/gnc-split-reg.c b/src/gnome/gnc-split-reg.c
index f394941..ed7e19b 100644
--- a/src/gnome/gnc-split-reg.c
+++ b/src/gnome/gnc-split-reg.c
@@ -902,7 +902,9 @@ static void
 gsr_default_associate_handler_file (GNCSplitReg *gsr, Transaction *trans, gboolean have_uri)
 {
     GtkWidget *dialog;
-    gint response;
+    gint       response;
+    gboolean   valid_path_head = FALSE;
+    gchar     *path_head = gnc_prefs_get_string (GNC_PREFS_GROUP_GENERAL, "assoc-head");
 
     dialog = gtk_file_chooser_dialog_new (_("Associate File with Transaction"),
                                      GTK_WINDOW(gsr->window),
@@ -914,20 +916,34 @@ gsr_default_associate_handler_file (GNCSplitReg *gsr, Transaction *trans, gboole
 
     gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER(dialog), FALSE);
 
+    if ((path_head != NULL) && (g_strcmp0 (path_head, "") != 0)) // not default entry
+        valid_path_head = TRUE;
+
     if (have_uri)
     {
-        GtkWidget *extra_widget;
-        gchar *uri_label = g_strconcat (_("Existing Association is "), xaccTransGetAssociation (trans), NULL);
+        gchar *new_uri;
+        gchar *uri_label;
+        gchar *filename;
 
-        extra_widget = gtk_label_new (uri_label);
+        const gchar *uri = xaccTransGetAssociation (trans);
 
-        gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), extra_widget);
+        if (valid_path_head && g_str_has_prefix (uri,"file:/") && !g_str_has_prefix (uri,"file://")) 
+        {
+            const gchar *part = uri + strlen ("file:");
+            new_uri = g_strconcat (path_head, part, NULL);
+        }
+        else
+            new_uri = g_strdup (uri);
 
-        gtk_file_chooser_set_uri (GTK_FILE_CHOOSER(dialog), xaccTransGetAssociation (trans));
+        filename = g_uri_unescape_string (new_uri, NULL);
+        uri_label = g_strconcat (_("Existing Association is "), filename, NULL);
+        gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), gtk_label_new (uri_label));
+        gtk_file_chooser_set_uri (GTK_FILE_CHOOSER(dialog), new_uri);
 
         g_free (uri_label);
+        g_free (new_uri);
+        g_free (filename);
     }
-
     response = gtk_dialog_run (GTK_DIALOG (dialog));
 
     if (response == GTK_RESPONSE_REJECT)
@@ -936,10 +952,22 @@ gsr_default_associate_handler_file (GNCSplitReg *gsr, Transaction *trans, gboole
     if (response == GTK_RESPONSE_ACCEPT)
     {
 	gchar *dialog_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
-        DEBUG("File URI: %s\n", dialog_uri);
-        xaccTransSetAssociation (trans, dialog_uri);
+
+        PINFO("Dialog File URI: %s\n", dialog_uri);
+
+        if (valid_path_head && g_str_has_prefix (dialog_uri, path_head))
+        {
+            gchar *part = dialog_uri + strlen (path_head);
+            gchar *new_uri = g_strconcat ("file:", part, NULL);
+            xaccTransSetAssociation (trans, new_uri);
+            g_free (new_uri);
+        }
+        else
+            xaccTransSetAssociation (trans, dialog_uri);
+
         g_free (dialog_uri);
     }
+    g_free (path_head);
     gtk_widget_destroy (dialog);
 }
 
@@ -984,9 +1012,9 @@ gsr_default_associate_handler_location (GNCSplitReg *gsr, Transaction *trans, gb
     // set the default response
     gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
 
-    // run the dialog
     gtk_widget_show_all (dialog);
 
+    // run the dialog
     response = gtk_dialog_run (GTK_DIALOG (dialog));
 
     if (response == GTK_RESPONSE_REJECT)
@@ -1062,6 +1090,8 @@ gsr_default_execassociated_handler (GNCSplitReg *gsr, gpointer data)
     Split *split = gnc_split_register_get_current_split (reg);
     GtkWidget *dialog;
     const char *uri;
+    const char *run_uri;
+    gchar *uri_scheme;
 
     /* get the current split based on cursor position */
     if (split == NULL)
@@ -1082,11 +1112,36 @@ gsr_default_execassociated_handler (GNCSplitReg *gsr, gpointer data)
 #endif
 
     uri = xaccTransGetAssociation (trans);
+
     if (g_strcmp0 (uri, "") == 0 && g_strcmp0 (uri, NULL) == 0)
         gnc_error_dialog (NULL, "%s", _("This transaction is not associated with a URI."));
     else
-        gnc_launch_assoc (uri);
+    {
+        if (g_str_has_prefix (uri,"file:/") && !g_str_has_prefix (uri,"file://")) // Check for relative path
+        {
+            gchar *path_head = gnc_prefs_get_string (GNC_PREFS_GROUP_GENERAL, "assoc-head");
+
+            if ((path_head != NULL) && (g_strcmp0 (path_head, "") != 0)) // not default entry
+            {
+                const gchar *part = uri + strlen ("file:");
+                run_uri = g_strconcat (path_head, part, NULL);
+            }
+            else
+                run_uri = g_strdup (uri);
+        }
+        else
+            run_uri = g_strdup (uri);
 
+        uri_scheme = g_uri_parse_scheme (run_uri);
+
+        if (uri_scheme != NULL) // make sure we have a scheme entry
+        {
+            gnc_launch_assoc (run_uri);
+            g_free (uri_scheme);
+        }
+        else
+            gnc_error_dialog (NULL, "%s", _("This transaction is not associated with a valid URI."));
+    }
     return;
 }
 

commit 47953c9b733180faf5aed667cc06c0e838a1fcd1
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Aug 16 16:33:56 2016 +0100

    Add Preference path head for Trans. Associations
    
    Add a preference for setting the path head for Transaction Associations
    based on a GtkFileChooserButton. An additional button is used to clear
    this setting when required.

diff --git a/src/gnome-utils/dialog-preferences.c b/src/gnome-utils/dialog-preferences.c
index 470ec6b..aa46340 100644
--- a/src/gnome-utils/dialog-preferences.c
+++ b/src/gnome-utils/dialog-preferences.c
@@ -693,6 +693,143 @@ gnc_prefs_connect_font_button (GtkFontButton *fb)
 
 /****************************************************************************/
 
+/** Callback for a GtkFileChooser widget to store a value in the preferences database.
+ *
+ *  @internal
+ *
+ *  @param fc A pointer to the file chooser widget emitting signal.
+ */
+static void
+file_chooser_selected_cb (GtkFileChooser *fc, gpointer user_data)
+{
+    GtkImage    *image = g_object_get_data (G_OBJECT(fc), "path_head_error");
+    const gchar *group = g_object_get_data (G_OBJECT(fc), "group");
+    const gchar *pref = g_object_get_data (G_OBJECT(fc), "pref");
+    gchar       *folder = gtk_file_chooser_get_uri (fc);
+
+    gtk_widget_hide (GTK_WIDGET(image));
+
+    if (!gnc_prefs_set_string (group, pref, folder))
+        PINFO("Failed to save preference at %s, %s with %s", group, pref, folder);
+
+    g_free (folder);
+}
+
+/** Connect a GtkFileChooserButton widget to its stored value in the preferences database.
+ *
+ *  @internal
+ *
+ *  @param fb A pointer to the file chooser button that should be connected.
+ *
+ *  @param boxname The Hbox name that contains the GtkFileChooserButton and Clear button
+ */
+static void
+gnc_prefs_connect_file_chooser_button (GtkFileChooserButton *fcb, const gchar *boxname)
+{
+    GtkImage *image;
+    gchar *group, *pref;
+    gchar *uri;
+    gboolean folder_set = TRUE;
+
+    g_return_if_fail(GTK_FILE_CHOOSER_BUTTON(fcb));
+
+    if (boxname == NULL)
+        gnc_prefs_split_widget_name (gtk_buildable_get_name(GTK_BUILDABLE(fcb)), &group, &pref);
+    else
+        gnc_prefs_split_widget_name (boxname, &group, &pref);
+
+    uri = gnc_prefs_get_string (group, pref);
+
+    PINFO("Uri is %s", uri);
+
+    if ((uri != NULL) && (g_strcmp0 (uri, "") != 0)) // default entry
+    {
+        gchar *path_head = g_filename_from_uri (uri, NULL, NULL);
+
+        // test for current folder present and set chooser to it
+        if (g_file_test (path_head, G_FILE_TEST_IS_DIR))
+            gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER(fcb), uri);
+        else
+            folder_set = FALSE;
+
+        g_free (path_head);
+    }
+
+    image = g_object_get_data(G_OBJECT(fcb), "path_head_error");
+
+    if (folder_set) // If current folder missing, display error and tt message
+        gtk_widget_hide (GTK_WIDGET(image));
+    else
+    {
+        gchar *uri_u = g_uri_unescape_string (uri, NULL);
+        gchar *path_head = g_filename_from_uri (uri_u, NULL, NULL);
+        gchar *ttip = g_strconcat (_("Path does not exist, "), path_head, NULL);
+
+        gtk_widget_set_tooltip_text(GTK_WIDGET(image), ttip);
+        gtk_widget_show (GTK_WIDGET(image));
+
+        g_free (ttip);
+        g_free (uri_u);
+        g_free (path_head);
+    }
+
+    g_signal_connect (GTK_FILE_CHOOSER(fcb), "selection-changed",
+                      G_CALLBACK(file_chooser_selected_cb), NULL);
+
+    g_object_set_data_full (G_OBJECT(fcb),"group", g_strdup (group), (GDestroyNotify) g_free);
+    g_object_set_data_full (G_OBJECT(fcb),"pref", g_strdup (pref), (GDestroyNotify) g_free);
+
+    g_free (group);
+    g_free (pref);
+    g_free (uri);
+
+    gtk_widget_show_all(GTK_WIDGET(fcb));
+}
+
+/** Callback for a 'Clear' button for GtkFileChooserButton widget.
+ *
+ *  @internal
+ *
+ *  @param button A pointer to the button widget emitting signal.
+ *
+ *  @param user_data A Pointer to the GtkFileChooserButton widget.
+ */
+static void
+file_chooser_clear_cb (GtkButton *button, gpointer user_data)
+{
+    GtkFileChooserButton *fcb = GTK_FILE_CHOOSER_BUTTON(user_data);
+    const gchar          *group = g_object_get_data (G_OBJECT(fcb), "group");
+    const gchar          *pref = g_object_get_data (G_OBJECT(fcb), "pref");
+    GtkImage             *image = g_object_get_data (G_OBJECT(fcb), "path_head_error");
+    GtkWidget            *box;
+    GtkWidget            *fcb_new;
+    gchar                *boxname;
+
+    /* We need to distroy the GtkFileChooserButton and recreate as there
+       does not seem to be away of resetting the folder path to NONE */
+    box = gtk_widget_get_parent (GTK_WIDGET(fcb));
+    gtk_widget_destroy (GTK_WIDGET(fcb));
+
+    if (!gnc_prefs_set_string (group, pref, ""))
+        PINFO("Failed to Clear preference at %s, %s", group, pref);
+
+    fcb_new = gtk_file_chooser_button_new (_("Select a folder"),
+                             GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+
+    g_object_set_data (G_OBJECT(fcb_new), "path_head_error", image);
+
+    gtk_box_pack_start (GTK_BOX (box), fcb_new, TRUE, TRUE, 0);
+    gtk_box_reorder_child (GTK_BOX (box),fcb_new, 0);
+    gtk_widget_show (fcb_new);
+
+    boxname = g_strconcat ("pref/", group, "/", pref, NULL);
+
+    gnc_prefs_connect_file_chooser_button (GTK_FILE_CHOOSER_BUTTON(fcb_new), boxname);
+    g_free (boxname);
+}
+
+/****************************************************************************/
+
 /** Connect a GtkRadioButton widget to its stored value in the preferences database.
  *
  *  @internal
@@ -716,8 +853,8 @@ gnc_prefs_connect_radio_button (GtkRadioButton *button)
 
     gnc_prefs_bind (group, pref, G_OBJECT (button), "active");
 
-    g_free(group);
-    g_free(pref);
+    g_free (group);
+    g_free (pref);
 }
 
 /****************************************************************************/
@@ -974,9 +1111,14 @@ gnc_prefs_connect_one (const gchar *name,
 
     if (GTK_IS_FONT_BUTTON(widget))
     {
-        DEBUG("  %s - entry", name);
+        DEBUG("  %s - font button", name);
         gnc_prefs_connect_font_button(GTK_FONT_BUTTON(widget));
     }
+    else if (GTK_IS_FILE_CHOOSER_BUTTON(widget))
+    {
+        DEBUG("  %s - file chooser button", name);
+        gnc_prefs_connect_file_chooser_button(GTK_FILE_CHOOSER_BUTTON(widget), NULL);
+    }
     else if (GTK_IS_RADIO_BUTTON(widget))
     {
         DEBUG("  %s - radio button", name);
@@ -1027,6 +1169,11 @@ gnc_prefs_connect_one (const gchar *name,
             DEBUG("  %s - date_edit", name);
             gnc_prefs_connect_date_edit(GNC_DATE_EDIT(widget_child), name );
         }
+        else if (GTK_FILE_CHOOSER_BUTTON(widget_child))
+        {
+            DEBUG("  %s - file chooser buuton", name);
+            gnc_prefs_connect_file_chooser_button(GTK_FILE_CHOOSER_BUTTON(widget_child), name );
+        }
     }
     else
     {
@@ -1052,7 +1199,7 @@ gnc_preferences_dialog_create(void)
 {
     GtkBuilder *builder;
     GtkWidget *dialog, *notebook, *label, *image;
-    GtkWidget *box, *date, *period, *currency;
+    GtkWidget *box, *date, *period, *currency, *fcb, *button;
     GHashTable *prefs_table;
     GDate* gdate = NULL;
     gchar buf[128];
@@ -1165,6 +1312,19 @@ gnc_preferences_dialog_create(void)
     gtk_widget_show (currency);
     gtk_box_pack_start(GTK_BOX (box), currency, TRUE, TRUE, 0);
 
+    box = GTK_WIDGET(gtk_builder_get_object (builder,
+                     "pref/" GNC_PREFS_GROUP_GENERAL "/assoc-head"));
+    fcb = gtk_file_chooser_button_new (_("Select a folder"),
+                             GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+    gtk_box_pack_start (GTK_BOX (box), fcb, TRUE, TRUE, 0);
+    button = gtk_button_new_with_label (_("Clear"));
+    gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
+    gtk_widget_show (button);
+    g_signal_connect (GTK_BUTTON(button), "clicked",
+                      G_CALLBACK(file_chooser_clear_cb), fcb);
+
+    image = GTK_WIDGET(gtk_builder_get_object (builder, "path_head_error"));
+    g_object_set_data(G_OBJECT(fcb), "path_head_error", image);
 
     /* Add to the list of interesting widgets */
     gnc_prefs_build_widget_table(builder, dialog);
diff --git a/src/gnome-utils/gtkbuilder/dialog-preferences.glade b/src/gnome-utils/gtkbuilder/dialog-preferences.glade
index c794545..966eacc 100644
--- a/src/gnome-utils/gtkbuilder/dialog-preferences.glade
+++ b/src/gnome-utils/gtkbuilder/dialog-preferences.glade
@@ -2,6 +2,94 @@
 <interface>
   <requires lib="gtk+" version="2.24"/>
   <!-- interface-naming-policy project-wide -->
+  <object class="GtkAdjustment" id="auto_decimal_places_adj">
+    <property name="lower">1</property>
+    <property name="upper">8</property>
+    <property name="value">2</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">4</property>
+  </object>
+  <object class="GtkAdjustment" id="autosave_interval_minutes_adj">
+    <property name="upper">99999</property>
+    <property name="value">3</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="date_backmonth_adj">
+    <property name="upper">11</property>
+    <property name="value">6</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">4</property>
+  </object>
+  <object class="GtkListStore" id="date_formats">
+    <columns>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name example -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">US</col>
+        <col id="1" translatable="yes">07/31/2013</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">UK</col>
+        <col id="1" translatable="yes">31/07/2013</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Europe</col>
+        <col id="1" translatable="yes">31.07.2013</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">ISO</col>
+        <col id="1" translatable="yes">2013-07-31</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Locale</col>
+        <col id="1" translatable="yes">(dummy)</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkAdjustment" id="key_length_adj">
+    <property name="lower">1</property>
+    <property name="upper">999</property>
+    <property name="value">2</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="max_transactions_adj">
+    <property name="upper">999999</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="new_search_limit_adj">
+    <property name="lower">1</property>
+    <property name="upper">100</property>
+    <property name="value">1</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="retain_days_adj">
+    <property name="lower">1</property>
+    <property name="upper">99999</property>
+    <property name="value">30</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="save_on_close_adj">
+    <property name="upper">300</property>
+    <property name="value">20</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="tab_width_adj">
+    <property name="lower">1</property>
+    <property name="upper">100</property>
+    <property name="value">30</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkDialog" id="GnuCash Preferences">
     <property name="can_focus">False</property>
     <property name="title" translatable="yes">GnuCash Preferences</property>
@@ -1255,7 +1343,7 @@ many months before the current month:</property>
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="border_width">6</property>
-                <property name="n_rows">25</property>
+                <property name="n_rows">27</property>
                 <property name="n_columns">4</property>
                 <child>
                   <placeholder/>
@@ -1312,6 +1400,72 @@ many months before the current month:</property>
                   <placeholder/>
                 </child>
                 <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
                   <object class="GtkLabel" id="label50">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
@@ -1625,8 +1779,8 @@ many months before the current month:</property>
                     <property name="use_markup">True</property>
                   </object>
                   <packing>
-                    <property name="top_attach">23</property>
-                    <property name="bottom_attach">24</property>
+                    <property name="top_attach">25</property>
+                    <property name="bottom_attach">26</property>
                     <property name="x_options">GTK_FILL</property>
                     <property name="y_options"/>
                   </packing>
@@ -1641,8 +1795,8 @@ many months before the current month:</property>
                     <property name="mnemonic_widget">pref/dialogs.search/new-search-limit</property>
                   </object>
                   <packing>
-                    <property name="top_attach">24</property>
-                    <property name="bottom_attach">25</property>
+                    <property name="top_attach">26</property>
+                    <property name="bottom_attach">27</property>
                     <property name="x_options">GTK_FILL</property>
                     <property name="y_options"/>
                     <property name="x_padding">12</property>
@@ -1667,8 +1821,8 @@ many months before the current month:</property>
                   <packing>
                     <property name="left_attach">1</property>
                     <property name="right_attach">2</property>
-                    <property name="top_attach">24</property>
-                    <property name="bottom_attach">25</property>
+                    <property name="top_attach">26</property>
+                    <property name="bottom_attach">27</property>
                     <property name="x_options">GTK_FILL</property>
                     <property name="y_options"/>
                   </packing>
@@ -1859,48 +2013,6 @@ many months before the current month:</property>
                   </packing>
                 </child>
                 <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
                   <object class="GtkCheckButton" id="pref/general/save-on-close-expires">
                     <property name="label" translatable="yes">Enable timeout on "Save changes on closing" question</property>
                     <property name="visible">True</property>
@@ -1920,6 +2032,12 @@ many months before the current month:</property>
                   </packing>
                 </child>
                 <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
                   <object class="GtkLabel" id="label15">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
@@ -1985,25 +2103,77 @@ many months before the current month:</property>
                   </packing>
                 </child>
                 <child>
-                  <placeholder/>
+                  <object class="GtkLabel" id="label20">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">22</property>
+                    <property name="bottom_attach">23</property>
+                  </packing>
                 </child>
                 <child>
-                  <placeholder/>
+                  <object class="GtkLabel" id="label21">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">24</property>
+                    <property name="bottom_attach">25</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="pref/general/assoc-head">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="tooltip_markup">Path head for Transaction Associated files </property>
+                    <property name="tooltip_text" translatable="yes">Path head for Transaction Associated files </property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">23</property>
+                    <property name="bottom_attach">24</property>
+                  </packing>
                 </child>
                 <child>
                   <placeholder/>
                 </child>
                 <child>
-                  <object class="GtkLabel" id="label19">
+                  <object class="GtkHBox" id="hbox5">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
+                    <child>
+                      <object class="GtkLabel" id="label19">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Path head for Transaction Association Files</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkImage" id="path_head_error">
+                        <property name="can_focus">False</property>
+                        <property name="stock">gtk-dialog-warning</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
                   </object>
                   <packing>
-                    <property name="top_attach">22</property>
-                    <property name="bottom_attach">23</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"/>
+                    <property name="top_attach">23</property>
+                    <property name="bottom_attach">24</property>
                   </packing>
                 </child>
               </object>
@@ -2435,6 +2605,15 @@ many months before the current month:</property>
                   </packing>
                 </child>
                 <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
                   <object class="GtkLabel" id="label47">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
@@ -2451,6 +2630,12 @@ many months before the current month:</property>
                   </packing>
                 </child>
                 <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
                   <object class="GtkCheckButton" id="pref/general.register/future-after-blank-transaction">
                     <property name="label" translatable="yes">_Future transactions after blank transaction</property>
                     <property name="visible">True</property>
@@ -3643,92 +3828,4 @@ many months before the current month:</property>
       <action-widget response="-7">closebutton2</action-widget>
     </action-widgets>
   </object>
-  <object class="GtkAdjustment" id="auto_decimal_places_adj">
-    <property name="lower">1</property>
-    <property name="upper">8</property>
-    <property name="value">2</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">4</property>
-  </object>
-  <object class="GtkAdjustment" id="autosave_interval_minutes_adj">
-    <property name="upper">99999</property>
-    <property name="value">3</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="date_backmonth_adj">
-    <property name="upper">11</property>
-    <property name="value">6</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">4</property>
-  </object>
-  <object class="GtkListStore" id="date_formats">
-    <columns>
-      <!-- column-name name -->
-      <column type="gchararray"/>
-      <!-- column-name example -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">US</col>
-        <col id="1" translatable="yes">07/31/2013</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">UK</col>
-        <col id="1" translatable="yes">31/07/2013</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Europe</col>
-        <col id="1" translatable="yes">31.07.2013</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">ISO</col>
-        <col id="1" translatable="yes">2013-07-31</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Locale</col>
-        <col id="1" translatable="yes">(dummy)</col>
-      </row>
-    </data>
-  </object>
-  <object class="GtkAdjustment" id="key_length_adj">
-    <property name="lower">1</property>
-    <property name="upper">999</property>
-    <property name="value">2</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="max_transactions_adj">
-    <property name="upper">999999</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="new_search_limit_adj">
-    <property name="lower">1</property>
-    <property name="upper">100</property>
-    <property name="value">1</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="retain_days_adj">
-    <property name="lower">1</property>
-    <property name="upper">99999</property>
-    <property name="value">30</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="save_on_close_adj">
-    <property name="upper">300</property>
-    <property name="value">20</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="tab_width_adj">
-    <property name="lower">1</property>
-    <property name="upper">100</property>
-    <property name="value">30</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
 </interface>
diff --git a/src/gnome/gschemas/org.gnucash.gschema.xml.in.in b/src/gnome/gschemas/org.gnucash.gschema.xml.in.in
index ff5fb3c..61a3106 100644
--- a/src/gnome/gschemas/org.gnucash.gschema.xml.in.in
+++ b/src/gnome/gschemas/org.gnucash.gschema.xml.in.in
@@ -15,6 +15,11 @@
       <summary>Character to use as separator between account names</summary>
       <description>This setting determines the character that will be used between components of an account name. Possible values are any single non-alphanumeric unicode character, or any of the following strings: "colon" "slash", "backslash", "dash" and "period".</description>
     </key>
+    <key name="assoc-head" type="s">
+      <default>''</default>
+      <summary>Transaction Associations head path</summary>
+      <description>This is the path head for the Transaction file Associations</description>
+    </key>
     <key name="file-compression" type="b">
       <default>true</default>
       <summary>Compress the data file</summary>

commit 531f0f3c37f0ebd9e3c601327a959700e794e212
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Aug 2 09:41:07 2016 +0100

    Add sort button for Associations

diff --git a/src/gnome/dialog-trans-assoc.c b/src/gnome/dialog-trans-assoc.c
index 77eeeb3..e9ae812 100644
--- a/src/gnome/dialog-trans-assoc.c
+++ b/src/gnome/dialog-trans-assoc.c
@@ -86,6 +86,56 @@ gnc_assoc_dialog_close_cb (GtkDialog *dialog, gpointer user_data)
     LEAVE(" ");
 }
 
+static gint
+sort_iter_compare_func (GtkTreeModel *model,
+                        GtkTreeIter  *a,
+                        GtkTreeIter  *b,
+                        gpointer  user_data)
+{
+    gint ret = 0;
+    gchar *uri1, *uri2;
+
+    gtk_tree_model_get (model, a, URI, &uri1, -1);
+    gtk_tree_model_get (model, b, URI, &uri2, -1);
+
+    ret = g_utf8_collate (uri1, uri2);
+
+    g_free (uri1);
+    g_free (uri2);
+
+    return ret;
+}
+
+static void
+assoc_dialog_sort (AssocDialog *assoc_dialog)
+{
+    GtkTreeModel *model;
+    GtkTreeSortable *sortable;
+    gint id;
+    GtkSortType order;
+
+    model = gtk_tree_view_get_model (GTK_TREE_VIEW(assoc_dialog->view));
+
+    sortable = GTK_TREE_SORTABLE(model);
+
+    if (gtk_tree_sortable_get_sort_column_id (sortable, &id, &order))
+    {
+        if (order == GTK_SORT_ASCENDING)
+            order = GTK_SORT_DESCENDING;
+        else
+            order = GTK_SORT_ASCENDING;
+    }
+    else
+    {
+        gtk_tree_sortable_set_sort_func (sortable, URI, sort_iter_compare_func,
+                                assoc_dialog, NULL);
+
+        order = GTK_SORT_ASCENDING;
+    }
+    /* set sort order */
+    gtk_tree_sortable_set_sort_column_id (sortable, URI, order);
+}
+
 static void
 assoc_dialog_update (AssocDialog *assoc_dialog)
 {
@@ -146,6 +196,10 @@ gnc_assoc_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user
         assoc_dialog_update (assoc_dialog);
         return;
 
+    case -8:
+        assoc_dialog_sort (assoc_dialog);
+        return;
+
     case GTK_RESPONSE_CLOSE:
     default:
         gnc_close_gui_component_by_data (DIALOG_ASSOC_CM_CLASS, assoc_dialog);
diff --git a/src/gnome/gtkbuilder/dialog-trans-assoc.glade b/src/gnome/gtkbuilder/dialog-trans-assoc.glade
index d87d664..6eaaffa 100644
--- a/src/gnome/gtkbuilder/dialog-trans-assoc.glade
+++ b/src/gnome/gtkbuilder/dialog-trans-assoc.glade
@@ -37,6 +37,20 @@
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
             <child>
+              <object class="GtkButton" id="sort">
+                <property name="label" translatable="yes">_Sort Association</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkButton" id="Check">
                 <property name="label" translatable="yes">_Locate Association</property>
                 <property name="visible">True</property>
@@ -47,7 +61,7 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
-                <property name="position">0</property>
+                <property name="position">1</property>
               </packing>
             </child>
             <child>
@@ -63,7 +77,7 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
-                <property name="position">1</property>
+                <property name="position">2</property>
               </packing>
             </child>
           </object>
@@ -178,6 +192,7 @@
       </object>
     </child>
     <action-widgets>
+      <action-widget response="-8">sort</action-widget>
       <action-widget response="-10">Check</action-widget>
       <action-widget response="-6">close_button</action-widget>
     </action-widgets>

commit a860643922461a2c3d878a6dac3b0cc2475e5829
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Aug 1 14:30:24 2016 +0100

    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.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 11174a1..d05232a 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 9079fb0..d22675c 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 54d36cc..e07ae2a 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 0000000..77eeeb3
--- /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 at gnu.org                   *
+\********************************************************************/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#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 0000000..fa82fcb
--- /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 at 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 1d58820..dd52ee5 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 */
 
@@ -618,6 +625,14 @@ gnc_main_window_cmd_tools_imap_editor (GtkAction *action, GncMainWindowActionDat
 }
 
 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)
 {
     gnc_set_busy_cursor(NULL, TRUE);
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 36ab8fc..52130c6 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 @@
     <child name="new-hierarchy" schema="org.gnucash.dialogs.new-hierarchy"/>
     <child name="search" schema="org.gnucash.dialogs.search"/>
     <child name="transfer" schema="org.gnucash.dialogs.transfer"/>
+    <child name="trans-assoc" schema="org.gnucash.dialogs.trans-assoc"/>
   </schema>
 
   <schema id="org.gnucash.dialogs.account" path="/org/gnucash/dialogs/account/">
@@ -223,4 +224,14 @@
         followed by the width and height of the window.</description>
     </key>
   </schema>
+
+  <schema id="org.gnucash.dialogs.trans-assoc" path="/org/gnucash/dialogs/trans-assoc/">
+    <key type="(iiii)" name="last-geometry">
+      <default>(-1,-1,-1,-1)</default>
+      <summary>Last window position and size</summary>
+      <description>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.</description>
+    </key>
+  </schema>
 </schemalist>
diff --git a/src/gnome/gtkbuilder/Makefile.am b/src/gnome/gtkbuilder/Makefile.am
index 110e324..ebf0dd2 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 0000000..d87d664
--- /dev/null
+++ b/src/gnome/gtkbuilder/dialog-trans-assoc.glade
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkListStore" id="list-store">
+    <columns>
+      <!-- column-name date -->
+      <column type="gchararray"/>
+      <!-- column-name desc -->
+      <column type="gchararray"/>
+      <!-- column-name uri -->
+      <column type="gchararray"/>
+      <!-- column-name available -->
+      <column type="gchararray"/>
+      <!-- column-name split -->
+      <column type="gpointer"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="Transaction Association Dialog">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="has_focus">True</property>
+    <property name="can_default">True</property>
+    <property name="border_width">6</property>
+    <property name="title" translatable="yes">Transaction Association Dialog</property>
+    <property name="default_width">600</property>
+    <property name="default_height">400</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">normal</property>
+    <signal name="destroy" handler="gnc_assoc_dialog_window_destroy_cb" swapped="no"/>
+    <signal name="response" handler="gnc_assoc_dialog_response_cb" swapped="no"/>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox2">
+        <property name="can_focus">False</property>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="Check">
+                <property name="label" translatable="yes">_Locate Association</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="close_button">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">All Transaction Associations</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="padding">5</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow2">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <child>
+              <object class="GtkTreeView" id="treeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">list-store</property>
+                <child>
+                  <object class="GtkTreeViewColumn" id="trans-date">
+                    <property name="resizable">True</property>
+                    <property name="title" translatable="yes">Date</property>
+                    <property name="alignment">0.5</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="trans-desc">
+                    <property name="resizable">True</property>
+                    <property name="title" translatable="yes">Description</property>
+                    <property name="alignment">0.5</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                      <attributes>
+                        <attribute name="text">1</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="uri entry">
+                    <property name="resizable">True</property>
+                    <property name="title" translatable="yes">Association</property>
+                    <property name="alignment">0.5</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext3"/>
+                      <attributes>
+                        <attribute name="text">2</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="available">
+                    <property name="resizable">True</property>
+                    <property name="title" translatable="yes">Available ?</property>
+                    <property name="alignment">0.5</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext4">
+                        <property name="xpad">10</property>
+                      </object>
+                      <attributes>
+                        <attribute name="text">3</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="ypad">5</property>
+            <property name="label" translatable="yes">To jump to Transaction, double click on Date or Description columns on
+ row required or Association and Available to Open the Association</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-10">Check</action-widget>
+      <action-widget response="-6">close_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/src/gnome/ui/gnc-plugin-basic-commands-ui.xml b/src/gnome/ui/gnc-plugin-basic-commands-ui.xml
index a6a8cc3..022727c 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 @@
         <menuitem name="ToolsFinancialCalculator" action="ToolsFinancialCalculatorAction"/>
         <menuitem name="ToolsBookClose" action="ToolsBookCloseAction"/>
         <menuitem name="ToolsImapEditor" action="ToolsImapEditorAction"/>
+        <menuitem name="ToolsTransAssoc" action="ToolsTransAssocAction"/>
       </placeholder>
     </menu>
 

commit 5f75f106ee1f9a766bf66d58f84816884cf77c0e
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Aug 1 12:45:35 2016 +0100

    Add option to recn cell type to be read only
    
    Use added read only option to make Associate cell read only

diff --git a/src/register/ledger-core/split-register-load.c b/src/register/ledger-core/split-register-load.c
index 94cf37f..c84d68d 100644
--- a/src/register/ledger-core/split-register-load.c
+++ b/src/register/ledger-core/split-register-load.c
@@ -83,6 +83,7 @@ gnc_split_register_load_associate_cells (SplitRegister *reg)
     /* FIXME: These should get moved to an i18n function */
     gnc_recn_cell_set_valid_flags (cell, "fw ", ' ');
     gnc_recn_cell_set_flag_order (cell, "fw ");
+    gnc_recn_cell_set_read_only (cell, TRUE);
 }
 
 static void
diff --git a/src/register/register-core/recncell.c b/src/register/register-core/recncell.c
index 3cce659..763f23c 100644
--- a/src/register/register-core/recncell.c
+++ b/src/register/register-core/recncell.c
@@ -74,6 +74,9 @@ gnc_recn_cell_enter (BasicCell *_cell,
             ! (cell->confirm_cb (cell->flag, cell->confirm_data)))
         return FALSE;
 
+    if (cell->read_only == TRUE)
+        return FALSE;
+
     /* Find the current flag in the list of flags */
     this_flag = strchr (cell->flag_order, cell->flag);
 
@@ -111,6 +114,7 @@ gnc_recn_cell_init (RecnCell *cell)
     cell->get_string = NULL;
     cell->valid_flags = "";
     cell->flag_order = "";
+    cell->read_only = FALSE;
 
     cell->cell.enter_cell = gnc_recn_cell_enter;
     cell->cell.set_value = gnc_recn_cell_set_value;
@@ -207,3 +211,10 @@ gnc_recn_cell_set_flag_order (RecnCell *cell, const char *flags)
 
     cell->flag_order = (char *)flags;
 }
+
+void
+gnc_recn_cell_set_read_only (RecnCell *cell, gboolean read_only)
+{
+    g_return_if_fail (cell != NULL);
+    cell->read_only = read_only;
+}
diff --git a/src/register/register-core/recncell.h b/src/register/register-core/recncell.h
index 7017b9c..c3343ac 100644
--- a/src/register/register-core/recncell.h
+++ b/src/register/register-core/recncell.h
@@ -57,6 +57,7 @@ typedef struct
     RecnCellStringGetter get_string;
     RecnCellConfirm confirm_cb;
     gpointer confirm_data;
+    gboolean read_only;
 } RecnCell;
 
 BasicCell * gnc_recn_cell_new (void);
@@ -81,5 +82,7 @@ void gnc_recn_cell_set_string_getter (RecnCell *cell,
 void gnc_recn_cell_set_valid_flags (RecnCell *cell, const char *flags,
                                     char default_flag);
 void gnc_recn_cell_set_flag_order (RecnCell *cell, const char *flags);
+
+void gnc_recn_cell_set_read_only (RecnCell *cell, gboolean read_only);
 /** @} */
 #endif

commit 57666b43ba50da2f56660f00836a24bcb75e836a
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Aug 1 12:44:25 2016 +0100

    Make a distinction between file/link Association
    
    Show a 'f' in the register for a file association and a 'w' for a link

diff --git a/src/register/ledger-core/split-register-layout.c b/src/register/ledger-core/split-register-layout.c
index e08bd9d..74f5c2c 100644
--- a/src/register/ledger-core/split-register-layout.c
+++ b/src/register/ledger-core/split-register-layout.c
@@ -696,7 +696,7 @@ gnc_split_register_layout_add_cells (SplitRegister *reg,
                            ASSOC_CELL,
                            RECN_CELL_TYPE_NAME,
                            N_("Associate:A") + 10,
-                           CELL_ALIGN_LEFT,
+                           CELL_ALIGN_CENTER,
                            FALSE,
                            FALSE);
 
diff --git a/src/register/ledger-core/split-register-load.c b/src/register/ledger-core/split-register-load.c
index 87fdcf3..94cf37f 100644
--- a/src/register/ledger-core/split-register-load.c
+++ b/src/register/ledger-core/split-register-load.c
@@ -81,8 +81,8 @@ gnc_split_register_load_associate_cells (SplitRegister *reg)
     if (!cell) return;
 
     /* FIXME: These should get moved to an i18n function */
-    gnc_recn_cell_set_valid_flags (cell, "@ ", ' ');
-    gnc_recn_cell_set_flag_order (cell, "@ ");
+    gnc_recn_cell_set_valid_flags (cell, "fw ", ' ');
+    gnc_recn_cell_set_flag_order (cell, "fw ");
 }
 
 static void
diff --git a/src/register/ledger-core/split-register-model.c b/src/register/ledger-core/split-register-model.c
index 5feee0b..db3d5d6 100644
--- a/src/register/ledger-core/split-register-model.c
+++ b/src/register/ledger-core/split-register-model.c
@@ -319,6 +319,13 @@ gnc_split_register_get_action_label (VirtualLocation virt_loc,
 }
 
 static const char *
+gnc_split_register_get_associate_label (VirtualLocation virt_loc,
+                                   gpointer user_data)
+{
+    return _("Associate:A") + 10;
+}
+
+static const char *
 gnc_split_register_get_xfrm_label (VirtualLocation virt_loc,
                                    gpointer user_data)
 {
@@ -340,13 +347,6 @@ gnc_split_register_get_memo_label (VirtualLocation virt_loc,
 }
 
 static const char *
-gnc_split_register_get_associate_label (VirtualLocation virt_loc,
-                                   gpointer user_data)
-{
-    return _("Associate:A");
-}
-
-static const char *
 gnc_split_register_get_type_label (VirtualLocation virt_loc,
                                    gpointer user_data)
 {
@@ -786,7 +786,12 @@ gnc_split_register_get_associate_entry (VirtualLocation virt_loc,
 
     // Check for uri is empty or NULL
     if (g_strcmp0 (uri, "") != 0 && g_strcmp0 (uri, NULL) != 0)
-        associate = '@';
+    {
+        if (g_str_has_prefix (uri, "file:"))
+            associate = 'f';
+        else
+            associate = 'w';
+    }
     else
         associate = ' ';
 
@@ -809,7 +814,6 @@ gnc_split_register_get_associate_value (SplitRegister *reg,
     return gnc_recn_cell_get_flag (cell);
 }
 
-
 static const char *
 gnc_split_register_get_type_entry (VirtualLocation virt_loc,
                                    gboolean translate,

commit 5bb53c044a239e63119829f1988a027acd175dba
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Aug 1 12:42:45 2016 +0100

    Indicate an Association in the Register
    
    Use the field below the reconcile and type entry on the transaction
    lines to indicate a file/link association.

diff --git a/src/register/ledger-core/split-register-layout.c b/src/register/ledger-core/split-register-layout.c
index b1905ae..e08bd9d 100644
--- a/src/register/ledger-core/split-register-layout.c
+++ b/src/register/ledger-core/split-register-layout.c
@@ -125,6 +125,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, ACTN_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_LEDGER_NUM_ACTN);
@@ -134,6 +135,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_JOURNAL);
@@ -154,6 +156,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_JOURNAL_NUM_ACTN);
@@ -163,6 +166,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SPLIT);
@@ -209,6 +213,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         copy_cursor_row (layout, curs, curs_last, 0);
 
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, ACTN_CELL,  1, 3);
         gnc_table_layout_set_cell (layout, curs, MEMO_CELL, 1, 4);
 
@@ -217,6 +222,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         copy_cursor_row (layout, curs, curs_last, 0);
 
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 3);
         gnc_table_layout_set_cell (layout, curs, MEMO_CELL, 1, 4);
 
@@ -246,6 +252,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         copy_cursor_row (layout, curs, curs_last, 0);
 
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 3);
         gnc_table_layout_set_cell (layout, curs, MEMO_CELL, 1, 4);
 
@@ -297,6 +304,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, ACTN_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_LEDGER_NUM_ACTN);
@@ -306,6 +314,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, ACTN_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_JOURNAL);
@@ -331,6 +340,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_JOURNAL_NUM_ACTN);
@@ -339,6 +349,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SPLIT);
@@ -390,6 +401,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, ACTN_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_LEDGER_NUM_ACTN);
@@ -399,6 +411,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_JOURNAL);
@@ -419,6 +432,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_JOURNAL_NUM_ACTN);
@@ -428,6 +442,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SPLIT);
@@ -469,6 +484,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, ACTN_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_LEDGER_NUM_ACTN);
@@ -478,6 +494,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_JOURNAL);
@@ -497,6 +514,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
 
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_DOUBLE_JOURNAL_NUM_ACTN);
@@ -506,6 +524,7 @@ gnc_split_register_set_cells (SplitRegister *reg, TableLayout *layout)
         gnc_table_layout_set_cell (layout, curs, TNUM_CELL,  1, 1);
         gnc_table_layout_set_cell (layout, curs, NOTES_CELL, 1, 2);
         gnc_table_layout_set_cell (layout, curs, VNOTES_CELL, 1, 3);
+        gnc_table_layout_set_cell (layout, curs, ASSOC_CELL,  1, 4);
 
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SPLIT);
@@ -674,6 +693,14 @@ gnc_split_register_layout_add_cells (SplitRegister *reg,
                            FALSE);
 
     gnc_register_add_cell (layout,
+                           ASSOC_CELL,
+                           RECN_CELL_TYPE_NAME,
+                           N_("Associate:A") + 10,
+                           CELL_ALIGN_LEFT,
+                           FALSE,
+                           FALSE);
+
+    gnc_register_add_cell (layout,
                            BALN_CELL,
                            PRICE_CELL_TYPE_NAME,
                            N_("sample:999,999.000") + 7,
@@ -783,7 +810,7 @@ gnc_split_register_layout_add_cells (SplitRegister *reg,
                            TYPE_CELL,
                            RECN_CELL_TYPE_NAME,
                            N_("Type:T") + 5,
-                           CELL_ALIGN_LEFT,
+                           CELL_ALIGN_CENTER,
                            FALSE,
                            FALSE);
 
diff --git a/src/register/ledger-core/split-register-load.c b/src/register/ledger-core/split-register-load.c
index 0737fc4..87fdcf3 100644
--- a/src/register/ledger-core/split-register-load.c
+++ b/src/register/ledger-core/split-register-load.c
@@ -69,6 +69,23 @@ gnc_split_register_load_recn_cells (SplitRegister *reg)
 }
 
 static void
+gnc_split_register_load_associate_cells (SplitRegister *reg)
+{
+    RecnCell *cell;
+
+    if (!reg) return;
+
+    cell = (RecnCell *)
+           gnc_table_layout_get_cell (reg->table->layout, ASSOC_CELL);
+
+    if (!cell) return;
+
+    /* FIXME: These should get moved to an i18n function */
+    gnc_recn_cell_set_valid_flags (cell, "@ ", ' ');
+    gnc_recn_cell_set_flag_order (cell, "@ ");
+}
+
+static void
 gnc_split_register_load_type_cells (SplitRegister *reg)
 {
     RecnCell *cell;
@@ -491,6 +508,7 @@ gnc_split_register_load (SplitRegister *reg, GList * slist,
 
         /* load up account names into the transfer combobox menus */
         gnc_split_register_load_xfer_cells (reg, default_account);
+        gnc_split_register_load_associate_cells (reg);
         gnc_split_register_load_recn_cells (reg);
         gnc_split_register_load_type_cells (reg);
     }
diff --git a/src/register/ledger-core/split-register-model.c b/src/register/ledger-core/split-register-model.c
index 15e3847..5feee0b 100644
--- a/src/register/ledger-core/split-register-model.c
+++ b/src/register/ledger-core/split-register-model.c
@@ -340,6 +340,13 @@ gnc_split_register_get_memo_label (VirtualLocation virt_loc,
 }
 
 static const char *
+gnc_split_register_get_associate_label (VirtualLocation virt_loc,
+                                   gpointer user_data)
+{
+    return _("Associate:A");
+}
+
+static const char *
 gnc_split_register_get_type_label (VirtualLocation virt_loc,
                                    gpointer user_data)
 {
@@ -759,6 +766,51 @@ gnc_split_register_get_border (VirtualLocation virt_loc,
 }
 
 static const char *
+gnc_split_register_get_associate_entry (VirtualLocation virt_loc,
+                                   gboolean translate,
+                                   gboolean *conditionally_changed,
+                                   gpointer user_data)
+{
+    SplitRegister *reg = user_data;
+    Transaction *trans;
+    char associate;
+    static char s[2];
+    const char *uri;
+
+    trans = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
+    if (!trans)
+        return NULL;
+
+    // get the existing uri
+    uri = xaccTransGetAssociation (trans);
+
+    // Check for uri is empty or NULL
+    if (g_strcmp0 (uri, "") != 0 && g_strcmp0 (uri, NULL) != 0)
+        associate = '@';
+    else
+        associate = ' ';
+
+    s[0] = associate;
+    s[1] = '\0';
+
+    return s;
+}
+
+static char
+gnc_split_register_get_associate_value (SplitRegister *reg,
+                                   VirtualLocation virt_loc)
+{
+    RecnCell *cell;
+
+    cell = (RecnCell *)gnc_table_layout_get_cell (reg->table->layout, ASSOC_CELL);
+    if (!cell)
+        return '\0';
+
+    return gnc_recn_cell_get_flag (cell);
+}
+
+
+static const char *
 gnc_split_register_get_type_entry (VirtualLocation virt_loc,
                                    gboolean translate,
                                    gboolean *conditionally_changed,
@@ -2332,6 +2384,10 @@ gnc_split_register_model_new (void)
                                        TCRED_CELL);
 
     gnc_table_model_set_entry_handler (model,
+                                       gnc_split_register_get_associate_entry,
+                                       ASSOC_CELL);
+
+    gnc_table_model_set_entry_handler (model,
                                        gnc_split_register_get_type_entry,
                                        TYPE_CELL);
 
@@ -2425,6 +2481,10 @@ gnc_split_register_model_new (void)
                                        TBALN_CELL);
 
     gnc_table_model_set_label_handler (model,
+                                       gnc_split_register_get_associate_label,
+                                       ASSOC_CELL);
+
+    gnc_table_model_set_label_handler (model,
                                        gnc_split_register_get_type_label,
                                        TYPE_CELL);
 
@@ -2560,6 +2620,9 @@ gnc_split_register_model_new (void)
         model, gnc_split_register_get_recn_io_flags, RECN_CELL);
 
     gnc_table_model_set_io_flags_handler(
+        model, gnc_split_register_get_recn_io_flags, ASSOC_CELL);
+
+    gnc_table_model_set_io_flags_handler(
         model, gnc_split_register_get_recn_io_flags, TYPE_CELL);
 
     gnc_table_model_set_io_flags_handler(
diff --git a/src/register/ledger-core/split-register.h b/src/register/ledger-core/split-register.h
index 55626ac..a00265b 100644
--- a/src/register/ledger-core/split-register.h
+++ b/src/register/ledger-core/split-register.h
@@ -180,6 +180,7 @@ typedef enum
  *  @{
  */
 #define ACTN_CELL  "action"
+#define ASSOC_CELL "associate"
 #define BALN_CELL  "balance"
 #define CRED_CELL  "credit"
 #define DATE_CELL  "date"

commit 8f9d1dcf392c30a548a86b24c796c03650537f0f
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Aug 1 12:30:31 2016 +0100

    Change associate file/link to show existing entry
    
    Currently there is no way of knowing what the existing association is
    and so what dialog to use. Changed the file dialog to use existing uri
    along with a label in case the uri does not exist and populated the
    entry in the link dialog with the existing uri.
    
    Also added a test for when entry is cleared and also being NULL to
    control menu sensitivity and also added a remove button to clear entry

diff --git a/src/gnome/gnc-plugin-page-register.c b/src/gnome/gnc-plugin-page-register.c
index 59fb7ca..6cb3873 100644
--- a/src/gnome/gnc-plugin-page-register.c
+++ b/src/gnome/gnc-plugin-page-register.c
@@ -937,7 +937,10 @@ gnc_plugin_page_register_ui_update (gpointer various, GncPluginPageRegister *pag
     uri = xaccTransGetAssociation(trans);
     action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
                                          "ExecAssociatedTransactionAction");
-    gtk_action_set_sensitive (GTK_ACTION(action), uri ? TRUE:FALSE);
+    if (g_strcmp0 (uri, "") != 0 && g_strcmp0 (uri, NULL) != 0)
+        gtk_action_set_sensitive (GTK_ACTION(action), TRUE);
+    else
+        gtk_action_set_sensitive (GTK_ACTION(action), FALSE);
 
     /* If we are in a readonly book, make any modifying action inactive */
     if (qof_book_is_readonly(gnc_get_current_book()))
@@ -3488,10 +3491,9 @@ gnc_plugin_page_register_cmd_associate_file_transaction (GtkAction *action,
     g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
 
     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(plugin_page);
-    gsr_default_associate_handler_file(priv->gsr, NULL);
+    gsr_default_associate_handler (priv->gsr, TRUE);
     gnc_plugin_page_register_ui_update (NULL, plugin_page);
     LEAVE(" ");
-
 }
 
 static void
@@ -3505,10 +3507,9 @@ gnc_plugin_page_register_cmd_associate_location_transaction (GtkAction *action,
     g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
 
     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(plugin_page);
-    gsr_default_associate_handler_location(priv->gsr, NULL);
+    gsr_default_associate_handler (priv->gsr, FALSE);
     gnc_plugin_page_register_ui_update (NULL, plugin_page);
     LEAVE(" ");
-
 }
 
 static void
diff --git a/src/gnome/gnc-split-reg.c b/src/gnome/gnc-split-reg.c
index 3c002ab..f394941 100644
--- a/src/gnome/gnc-split-reg.c
+++ b/src/gnome/gnc-split-reg.c
@@ -107,11 +107,10 @@ void gsr_default_copy_txn_handler ( GNCSplitReg *w, gpointer ud );
 void gsr_default_paste_handler    ( GNCSplitReg *w, gpointer ud );
 void gsr_default_paste_txn_handler( GNCSplitReg *w, gpointer ud );
 void gsr_default_void_txn_handler ( GNCSplitReg *w, gpointer ud );
-void gsr_default_unvoid_txn_handler  ( GNCSplitReg *w, gpointer ud );
+void gsr_default_unvoid_txn_handler ( GNCSplitReg *w, gpointer ud );
 void gsr_default_reverse_txn_handler ( GNCSplitReg *w, gpointer ud );
-void gsr_default_associate_handler_file   ( GNCSplitReg *w, gpointer ud );
-void gsr_default_associate_handler_location   ( GNCSplitReg *w, gpointer ud );
-void gsr_default_execassociated_handler   ( GNCSplitReg *w, gpointer ud );
+void gsr_default_associate_handler ( GNCSplitReg *w, gboolean uri_is_file );
+void gsr_default_execassociated_handler ( GNCSplitReg *w, gpointer ud );
 
 static void gsr_emit_simple_signal( GNCSplitReg *gsr, const char *sigName );
 static void gsr_emit_help_changed( GnucashRegister *reg, gpointer user_data );
@@ -899,156 +898,179 @@ gnc_split_reg_reinitialize_trans_cb(GtkWidget *widget, gpointer data)
     gsr_emit_simple_signal( gsr, "reinit_ent" );
 }
 
-/**
- * Associates a file URI with the current transaction.
- **/
-void
-gsr_default_associate_handler_file( GNCSplitReg *gsr, gpointer data )
+static void
+gsr_default_associate_handler_file (GNCSplitReg *gsr, Transaction *trans, gboolean have_uri)
 {
-    CursorClass cursor_class;
-    SplitRegister *reg;
-    Transaction *trans;
-    Split *split;
     GtkWidget *dialog;
+    gint response;
 
-    reg = gnc_ledger_display_get_split_register( gsr->ledger );
+    dialog = gtk_file_chooser_dialog_new (_("Associate File with Transaction"),
+                                     GTK_WINDOW(gsr->window),
+                                     GTK_FILE_CHOOSER_ACTION_OPEN,
+                                     GTK_STOCK_REMOVE, GTK_RESPONSE_REJECT,
+                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                     NULL);
 
-    /* get the current split based on cursor position */
-    split = gnc_split_register_get_current_split(reg);
-    if (split == NULL)
+    gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER(dialog), FALSE);
+
+    if (have_uri)
     {
-        gnc_split_register_cancel_cursor_split_changes (reg);
-        return;
+        GtkWidget *extra_widget;
+        gchar *uri_label = g_strconcat (_("Existing Association is "), xaccTransGetAssociation (trans), NULL);
+
+        extra_widget = gtk_label_new (uri_label);
+
+        gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(dialog), extra_widget);
+
+        gtk_file_chooser_set_uri (GTK_FILE_CHOOSER(dialog), xaccTransGetAssociation (trans));
+
+        g_free (uri_label);
     }
 
-    trans = xaccSplitGetParent(split);
-    cursor_class = gnc_split_register_get_current_cursor_class (reg);
+    response = gtk_dialog_run (GTK_DIALOG (dialog));
 
-    if (cursor_class == CURSOR_CLASS_NONE)
-        return;
+    if (response == GTK_RESPONSE_REJECT)
+        xaccTransSetAssociation (trans, "");
 
-    if (is_trans_readonly_and_warn(trans))
-        return;
+    if (response == GTK_RESPONSE_ACCEPT)
+    {
+	gchar *dialog_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+        DEBUG("File URI: %s\n", dialog_uri);
+        xaccTransSetAssociation (trans, dialog_uri);
+        g_free (dialog_uri);
+    }
+    gtk_widget_destroy (dialog);
+}
+
+static void
+gsr_default_associate_handler_location (GNCSplitReg *gsr, Transaction *trans, gboolean have_uri)
+{
+    GtkWidget *dialog, *entry, *label, *content_area;
+    gint response;
 
-    dialog = gtk_file_chooser_dialog_new ("Associate File with Transaction",
+    dialog = gtk_dialog_new_with_buttons (_("Associate Location with Transaction"),
                                      GTK_WINDOW(gsr->window),
-                                     GTK_FILE_CHOOSER_ACTION_OPEN,
+                                     GTK_DIALOG_MODAL,
+                                     GTK_STOCK_REMOVE, GTK_RESPONSE_REJECT,
                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
                                      NULL);
 
-	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER(dialog), 0);
-	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
- 	{
-		char *uri;
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
 
-	    uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
-        DEBUG("File URI: %s\n", uri);
-	    xaccTransSetAssociation(trans, uri);
+    // add the entry text
+    entry = gtk_entry_new ();
+    gtk_entry_set_width_chars (GTK_ENTRY (entry), 80);
+    gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+
+    // add a label and set entry text if required
+    if (have_uri)
+    {
+        label = gtk_label_new (_("Amend URL:"));
+        gtk_entry_set_text (GTK_ENTRY (entry), xaccTransGetAssociation (trans));
     }
+    else
+        label = gtk_label_new (_("Enter URL:"));
 
-	gtk_widget_destroy (dialog);
+    // pack label and entry to content area
+    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+    gtk_container_add (GTK_CONTAINER (content_area), label);
+    gtk_container_add (GTK_CONTAINER (content_area), entry);
 
+    // set spacings
+    gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+
+    // set the default response
+    gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+
+    // run the dialog
+    gtk_widget_show_all (dialog);
+
+    response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+    if (response == GTK_RESPONSE_REJECT)
+        xaccTransSetAssociation (trans, "");
+
+    if (response == GTK_RESPONSE_ACCEPT)
+    {
+        const gchar *dialog_uri = gtk_entry_get_text (GTK_ENTRY (entry));
+        DEBUG("Location URI: %s\n", dialog_uri);
+        xaccTransSetAssociation (trans, dialog_uri);
+    }
+    gtk_widget_destroy (dialog);
 }
 
 /**
- * Associates a location URI with the current transaction.
+ * Associates a URI with the current transaction.
  **/
 void
-gsr_default_associate_handler_location( GNCSplitReg *gsr, gpointer data )
+gsr_default_associate_handler (GNCSplitReg *gsr, gboolean uri_is_file)
 {
-    CursorClass cursor_class;
-    SplitRegister *reg;
+    SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
+    Split *split = gnc_split_register_get_current_split (reg);
     Transaction *trans;
-    Split *split;
-    GtkWidget *dialog, *entry, *label, *content_area;
-
-    reg = gnc_ledger_display_get_split_register( gsr->ledger );
+    CursorClass cursor_class;
+    const gchar *uri;
+    gboolean have_uri = FALSE;
 
     /* get the current split based on cursor position */
-    split = gnc_split_register_get_current_split(reg);
     if (split == NULL)
     {
         gnc_split_register_cancel_cursor_split_changes (reg);
         return;
     }
 
-    trans = xaccSplitGetParent(split);
+    trans = xaccSplitGetParent (split);
     cursor_class = gnc_split_register_get_current_cursor_class (reg);
 
     if (cursor_class == CURSOR_CLASS_NONE)
         return;
 
-    if (is_trans_readonly_and_warn(trans))
+    if (is_trans_readonly_and_warn (trans))
         return;
 
-    dialog = gtk_dialog_new_with_buttons ("Associate Location with Transaction",
-                                     GTK_WINDOW(gsr->window),
-                                     GTK_DIALOG_MODAL,
-                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                     NULL);
-
-    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-
-    // add a label
-    label = gtk_label_new ("Please enter URL:");
-    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
-    gtk_container_add (GTK_CONTAINER (content_area), label);
-
-    // add the entry text
-    entry = gtk_entry_new ();
-    gtk_entry_set_width_chars(GTK_ENTRY (entry), 80);
-    gtk_entry_set_activates_default(GTK_ENTRY (entry), TRUE);
-    gtk_container_add (GTK_CONTAINER (content_area), entry);
-
-    // set spacings
-    gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
-    gtk_container_set_border_width (GTK_CONTAINER (label), 5);
-    gtk_container_set_border_width (GTK_CONTAINER (content_area), 5);
-
-    // set the default response
-    gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
-
-    // run the dialog
-    gtk_widget_show_all (dialog);
+    // get the existing uri
+    uri = xaccTransGetAssociation (trans);
 
-    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    // Check for uri is empty or NULL
+    if (g_strcmp0 (uri, "") != 0 && g_strcmp0 (uri, NULL) != 0)
     {
-		const char *uri;
+        have_uri = TRUE;
 
-        uri = gtk_entry_get_text (GTK_ENTRY (entry));
-        DEBUG("Location URI: %s\n", uri);
-        xaccTransSetAssociation(trans, uri);
+        if (g_str_has_prefix (uri, "file:")) // use the correct dialog
+            uri_is_file = TRUE;
+        else
+            uri_is_file = FALSE;
     }
 
-     gtk_widget_destroy (dialog);
-
+    if (uri_is_file == TRUE)
+        gsr_default_associate_handler_file (gsr, trans, have_uri);
+    else
+        gsr_default_associate_handler_location (gsr, trans, have_uri);
 }
+
 /**
  * Executes the associated link with the current transaction.
  **/
 void
-gsr_default_execassociated_handler( GNCSplitReg *gsr, gpointer data )
+gsr_default_execassociated_handler (GNCSplitReg *gsr, gpointer data)
 {
     CursorClass cursor_class;
-    SplitRegister *reg;
+    SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
     Transaction *trans;
-    Split *split;
+    Split *split = gnc_split_register_get_current_split (reg);
     GtkWidget *dialog;
     const char *uri;
 
-    reg = gnc_ledger_display_get_split_register( gsr->ledger );
-
     /* get the current split based on cursor position */
-    split = gnc_split_register_get_current_split(reg);
     if (split == NULL)
     {
         gnc_split_register_cancel_cursor_split_changes (reg);
         return;
     }
 
-    trans = xaccSplitGetParent(split);
+    trans = xaccSplitGetParent (split);
     cursor_class = gnc_split_register_get_current_cursor_class (reg);
 
     if (cursor_class == CURSOR_CLASS_NONE)
@@ -1059,18 +1081,11 @@ gsr_default_execassociated_handler( GNCSplitReg *gsr, gpointer data )
         xaccTransDump (trans, "ExecAssociated");
 #endif
 
-    uri = xaccTransGetAssociation(trans);
-    if (!uri)
-    {
-        const gchar *message =
-            _("This transaction is not associated with a URI.");
-        gnc_error_dialog(NULL, "%s", message);
-        return;
-    }
+    uri = xaccTransGetAssociation (trans);
+    if (g_strcmp0 (uri, "") == 0 && g_strcmp0 (uri, NULL) == 0)
+        gnc_error_dialog (NULL, "%s", _("This transaction is not associated with a URI."));
     else
-    {
-        gnc_launch_assoc(uri);
-    }
+        gnc_launch_assoc (uri);
 
     return;
 }
diff --git a/src/gnome/gnc-split-reg.h b/src/gnome/gnc-split-reg.h
index 5bd7552..ac5f9c3 100644
--- a/src/gnome/gnc-split-reg.h
+++ b/src/gnome/gnc-split-reg.h
@@ -244,8 +244,7 @@ void gnc_split_reg_balancing_entry (GNCSplitReg *gsr, Account *account,
                                     time64 statement_date, gnc_numeric balancing_amount);
 
 void gsr_default_delete_handler( GNCSplitReg *gsr, gpointer data );
-void gsr_default_associate_handler_file( GNCSplitReg *gsr, gpointer data );
-void gsr_default_associate_handler_location( GNCSplitReg *gsr, gpointer data );
+void gsr_default_associate_handler (GNCSplitReg *gsr, gboolean uri_is_file);
 void gsr_default_execassociated_handler( GNCSplitReg *gsr, gpointer data );
 void gnc_split_reg_enter( GNCSplitReg *gsr, gboolean next_transaction );
 void gsr_default_delete_handler( GNCSplitReg *gsr, gpointer data );



Summary of changes:
 po/POTFILES.in                                     |   2 +
 src/gnome-utils/dialog-preferences.c               | 168 ++++++-
 .../gtkbuilder/dialog-preferences.glade            | 387 +++++++++------
 src/gnome/CMakeLists.txt                           |   2 +
 src/gnome/Makefile.am                              |   2 +
 src/gnome/dialog-trans-assoc.c                     | 519 +++++++++++++++++++++
 .../{dialog-imap-editor.h => dialog-trans-assoc.h} |  10 +-
 src/gnome/gnc-plugin-basic-commands.c              |  15 +
 src/gnome/gnc-plugin-page-register.c               |  11 +-
 src/gnome/gnc-split-reg.c                          | 272 +++++++----
 src/gnome/gnc-split-reg.h                          |   3 +-
 .../gschemas/org.gnucash.dialogs.gschema.xml.in.in |  11 +
 src/gnome/gschemas/org.gnucash.gschema.xml.in.in   |   5 +
 src/gnome/gtkbuilder/Makefile.am                   |   1 +
 src/gnome/gtkbuilder/dialog-trans-assoc.glade      | 217 +++++++++
 src/gnome/ui/gnc-plugin-basic-commands-ui.xml      |   1 +
 src/register/ledger-core/split-register-layout.c   |  29 +-
 src/register/ledger-core/split-register-load.c     |  19 +
 src/register/ledger-core/split-register-model.c    |  67 +++
 src/register/ledger-core/split-register.h          |   1 +
 src/register/register-core/recncell.c              |  11 +
 src/register/register-core/recncell.h              |   3 +
 22 files changed, 1493 insertions(+), 263 deletions(-)
 create mode 100644 src/gnome/dialog-trans-assoc.c
 copy src/gnome/{dialog-imap-editor.h => dialog-trans-assoc.h} (85%)
 create mode 100644 src/gnome/gtkbuilder/dialog-trans-assoc.glade



More information about the gnucash-changes mailing list