[Gnucash-changes] r13778 - gnucash/trunk - Improve the performance of the listen_for_accounts function. Never

David Hampton hampton at cvs.gnucash.org
Fri Apr 14 01:36:42 EDT 2006


Author: hampton
Date: 2006-04-14 01:36:42 -0400 (Fri, 14 Apr 2006)
New Revision: 13778
Trac: http://svn.gnucash.org/trac/changeset/13778

Modified:
   gnucash/trunk/ChangeLog
   gnucash/trunk/src/gnome-utils/account-quickfill.c
Log:
Improve the performance of the listen_for_accounts function.  Never
rebuild the list_store from scratch as the time required to sort each
account insertion takes forever with a large number of accounts.


Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog	2006-04-14 03:49:14 UTC (rev 13777)
+++ gnucash/trunk/ChangeLog	2006-04-14 05:36:42 UTC (rev 13778)
@@ -1,5 +1,10 @@
 2006-04-13  David Hampton  <hampton at employees.org>
 
+	* src/gnome-utils/account-quickfill.c: Improve the performance of
+	the listen_for_accounts function.  Never rebuild the list_store
+	from scratch as the time required to sort each account insertion
+	takes forever with a large number of accounts.
+
 	* src/gnome-utils/window-main-summarybar.c:
 	* src/gnome/dialog-commodities.c:
 	* src/engine/engine.scm:

Modified: gnucash/trunk/src/gnome-utils/account-quickfill.c
===================================================================
--- gnucash/trunk/src/gnome-utils/account-quickfill.c	2006-04-14 03:49:14 UTC (rev 13777)
+++ gnucash/trunk/src/gnome-utils/account-quickfill.c	2006-04-14 05:36:42 UTC (rev 13778)
@@ -75,24 +75,31 @@
 
 
 typedef struct find_data {
-  Account *account;
-  GtkTreePath *found;
+  GList *accounts;
+  GList *refs;
 } find_data;
 
 static gboolean
-shared_quickfill_find_account (GtkTreeModel *model,
-			       GtkTreePath *path,
-			       GtkTreeIter *iter,
-			       gpointer user_data)
+shared_quickfill_find_accounts (GtkTreeModel *model,
+				GtkTreePath *path,
+				GtkTreeIter *iter,
+				gpointer user_data)
 {
   Account *account = NULL;
   find_data *data = user_data;
+  GtkTreeRowReference* ref;
+  GList *tmp;
 
   gtk_tree_model_get(model, iter, ACCOUNT_POINTER, &account, -1);
-  if (data->account == account) {
-    data->found = gtk_tree_path_copy(path);
-    return TRUE;
+  for (tmp = data->accounts; tmp; tmp = g_list_next(tmp)) {
+    if (tmp->data == account) {
+      ref = gtk_tree_row_reference_new(model, path);
+      data->refs = g_list_append(data->refs, ref);
+      data->accounts = g_list_remove_link(data->accounts, tmp);
+      return (data->accounts == NULL);
+    }
   }
+
   return FALSE;
 }
 
@@ -224,8 +231,9 @@
   const char *match_str;
   Account *account;
   GtkTreeIter iter;
-  find_data data;
-  gboolean skip;
+  find_data data = { 0 };
+  GtkTreePath *path;
+  GList *tmp;
 
   if (0 == (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_ADD | QOF_EVENT_REMOVE)))
     return;
@@ -248,67 +256,55 @@
     return;
   }
 
-  /* Does the account exist in the model? */
-  data.account = account;
-  data.found = NULL;
-  gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store),
-			 shared_quickfill_find_account, &data);
-
-  /* Should the account exist in the model? */
-  if (qfb->dont_add_cb) {
-    skip = (qfb->dont_add_cb) (account, qfb->dont_add_data);
-  } else {
-    skip = FALSE;
-  }
-
-  /* Synthesize new events to make the following case statement
-   * simpler. */
-  if (event_type == QOF_EVENT_MODIFY) {
-    if (skip && data.found) {
-      DEBUG("existing account now filtered");
-      event_type = QOF_EVENT_REMOVE;
-    } else if (!skip && !data.found) {
-      DEBUG("existing account no longer filtered");
-      event_type = QOF_EVENT_ADD;
-    }
-  }
-
   switch (event_type) {
     case QOF_EVENT_MODIFY:
       DEBUG("modify %s", name);
 
-      /* Did the account name change? */
-      if (data.found) {
-	gchar *old_name;
-	gint result;
-	if (gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
-				    &iter, data.found)) {
-	  gtk_tree_model_get(GTK_TREE_MODEL(qfb->list_store), &iter,
-			     ACCOUNT_NAME, &old_name,
+      /* Find the account (and all its descendants) in the model.  The
+       * full name of all these accounts has changed. */
+      data.accounts = xaccAccountGetDescendants(account);
+      data.accounts = g_list_prepend(data.accounts, account);
+      gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store),
+			     shared_quickfill_find_accounts, &data);
+
+      /* Update the existing items in the list store.  Its possible
+       * that the change has caused an existing item to now become
+       * hidden, in which case it needs to be removed from the list
+       * store.  Otherwise its a simple update of the name string. */
+      for (tmp = data.refs; tmp; tmp = g_list_next(tmp)) {
+	path = gtk_tree_row_reference_get_path(tmp->data);
+	gtk_tree_row_reference_free(tmp->data);
+	if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
+				    &iter, path))
+	  continue;
+	gtk_tree_model_get(GTK_TREE_MODEL(qfb->list_store), &iter,
+			   ACCOUNT_POINTER, &account,
+			   -1);
+	if (qfb->dont_add_cb &&
+	    qfb->dont_add_cb(account, qfb->dont_add_data)) {
+	  gtk_list_store_remove(qfb->list_store, &iter);
+	} else {
+	  gtk_list_store_set(qfb->list_store, &iter,
+			     ACCOUNT_NAME, xaccAccountGetFullName(account),
 			     -1);
-	  result = g_utf8_collate(name, old_name);
-	  g_free(old_name);
-	  if (result == 0) {
-	    /* The account name is unchanged. This routine doesn't
-	     * care what else might have changed, so bail now. */
-	    break;
-	  }
 	}
       }
 
-      /* Update qf */
-      gnc_quickfill_purge(qfb->qf);
-      xaccGroupForEachAccount (qfb->group, load_shared_qf_cb, qfb, TRUE);
-
-      /* Update list store */
-      if (data.found) {
-	if (gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
-				    &iter, data.found)) {
-	  gtk_list_store_set(qfb->list_store, &iter,
-			     ACCOUNT_NAME, name,
-			     ACCOUNT_POINTER, account,
-			     -1);
+      /* Any accounts that weren't found in the tree are accounts that
+       * were hidden but have now become visible. Add them to the list
+       * store. */
+      for (tmp = data.accounts; tmp; tmp = g_list_next(tmp)) {
+	account = tmp->data;
+	if (qfb->dont_add_cb) {
+	  if (qfb->dont_add_cb(account, qfb->dont_add_data)) {
+	    continue;
+	  }
 	}
+	gtk_list_store_append (qfb->list_store, &iter);
+	gtk_list_store_set (qfb->list_store, &iter,
+			    ACCOUNT_NAME, name,
+			    ACCOUNT_POINTER, account,
+			    -1);
       }
       break;
 
@@ -319,10 +315,17 @@
       gnc_quickfill_purge(qfb->qf);
       xaccGroupForEachAccount (qfb->group, load_shared_qf_cb, qfb, TRUE);
 
+      /* Does the account exist in the model? */
+      data.accounts = g_list_append(NULL, account);
+      gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store),
+			     shared_quickfill_find_accounts, &data);
+
       /* Remove from list store */
-      if (data.found) {
+      for (tmp = data.refs; tmp; tmp = g_list_next(tmp)) {
+	path = gtk_tree_row_reference_get_path (tmp->data);
+	gtk_tree_row_reference_free (tmp->data);
 	if (gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
-				    &iter, data.found)) {
+				    &iter, path)) {
 	  gtk_list_store_remove(qfb->list_store, &iter);
 	}
       }
@@ -330,6 +333,10 @@
 
     case QOF_EVENT_ADD:
       DEBUG("add %s", name);
+      if (qfb->dont_add_cb &&
+	  qfb->dont_add_cb(account, qfb->dont_add_data))
+	break;
+
       match = gnc_quickfill_get_string_match (qf, name);
       if (match) {
 	match_str = gnc_quickfill_string (match);
@@ -352,8 +359,11 @@
       DEBUG("other %s", name);
       break;
   }
-  if (data.found)
-    gtk_tree_path_free(data.found);
+
+  if (data.accounts)
+    g_list_free(data.accounts);
+  if (data.refs)
+    g_list_free(data.refs);
   g_free(name);
   LEAVE(" ");
 }



More information about the gnucash-changes mailing list