mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13778 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
5f3491f7d3
commit
5d4b4c7b22
@ -1,5 +1,10 @@
|
|||||||
2006-04-13 David Hampton <hampton@employees.org>
|
2006-04-13 David Hampton <hampton@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-utils/window-main-summarybar.c:
|
||||||
* src/gnome/dialog-commodities.c:
|
* src/gnome/dialog-commodities.c:
|
||||||
* src/engine/engine.scm:
|
* src/engine/engine.scm:
|
||||||
|
@ -75,24 +75,31 @@ shared_quickfill_destroy (QofBook *book, gpointer key, gpointer user_data)
|
|||||||
|
|
||||||
|
|
||||||
typedef struct find_data {
|
typedef struct find_data {
|
||||||
Account *account;
|
GList *accounts;
|
||||||
GtkTreePath *found;
|
GList *refs;
|
||||||
} find_data;
|
} find_data;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
shared_quickfill_find_account (GtkTreeModel *model,
|
shared_quickfill_find_accounts (GtkTreeModel *model,
|
||||||
GtkTreePath *path,
|
GtkTreePath *path,
|
||||||
GtkTreeIter *iter,
|
GtkTreeIter *iter,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
Account *account = NULL;
|
Account *account = NULL;
|
||||||
find_data *data = user_data;
|
find_data *data = user_data;
|
||||||
|
GtkTreeRowReference* ref;
|
||||||
|
GList *tmp;
|
||||||
|
|
||||||
gtk_tree_model_get(model, iter, ACCOUNT_POINTER, &account, -1);
|
gtk_tree_model_get(model, iter, ACCOUNT_POINTER, &account, -1);
|
||||||
if (data->account == account) {
|
for (tmp = data->accounts; tmp; tmp = g_list_next(tmp)) {
|
||||||
data->found = gtk_tree_path_copy(path);
|
if (tmp->data == account) {
|
||||||
return TRUE;
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +231,9 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type,
|
|||||||
const char *match_str;
|
const char *match_str;
|
||||||
Account *account;
|
Account *account;
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
find_data data;
|
find_data data = { 0 };
|
||||||
gboolean skip;
|
GtkTreePath *path;
|
||||||
|
GList *tmp;
|
||||||
|
|
||||||
if (0 == (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_ADD | QOF_EVENT_REMOVE)))
|
if (0 == (event_type & (QOF_EVENT_MODIFY | QOF_EVENT_ADD | QOF_EVENT_REMOVE)))
|
||||||
return;
|
return;
|
||||||
@ -248,67 +256,55 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type,
|
|||||||
return;
|
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) {
|
switch (event_type) {
|
||||||
case QOF_EVENT_MODIFY:
|
case QOF_EVENT_MODIFY:
|
||||||
DEBUG("modify %s", name);
|
DEBUG("modify %s", name);
|
||||||
|
|
||||||
/* Did the account name change? */
|
/* Find the account (and all its descendants) in the model. The
|
||||||
if (data.found) {
|
* full name of all these accounts has changed. */
|
||||||
gchar *old_name;
|
data.accounts = xaccAccountGetDescendants(account);
|
||||||
gint result;
|
data.accounts = g_list_prepend(data.accounts, account);
|
||||||
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
|
gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store),
|
||||||
&iter, data.found)) {
|
shared_quickfill_find_accounts, &data);
|
||||||
gtk_tree_model_get(GTK_TREE_MODEL(qfb->list_store), &iter,
|
|
||||||
ACCOUNT_NAME, &old_name,
|
/* 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);
|
-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 */
|
/* Any accounts that weren't found in the tree are accounts that
|
||||||
gnc_quickfill_purge(qfb->qf);
|
* were hidden but have now become visible. Add them to the list
|
||||||
xaccGroupForEachAccount (qfb->group, load_shared_qf_cb, qfb, TRUE);
|
* store. */
|
||||||
|
for (tmp = data.accounts; tmp; tmp = g_list_next(tmp)) {
|
||||||
/* Update list store */
|
account = tmp->data;
|
||||||
if (data.found) {
|
if (qfb->dont_add_cb) {
|
||||||
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(qfb->list_store),
|
if (qfb->dont_add_cb(account, qfb->dont_add_data)) {
|
||||||
&iter, data.found)) {
|
continue;
|
||||||
gtk_list_store_set(qfb->list_store, &iter,
|
}
|
||||||
ACCOUNT_NAME, name,
|
|
||||||
ACCOUNT_POINTER, account,
|
|
||||||
-1);
|
|
||||||
}
|
}
|
||||||
|
gtk_list_store_append (qfb->list_store, &iter);
|
||||||
|
gtk_list_store_set (qfb->list_store, &iter,
|
||||||
|
ACCOUNT_NAME, name,
|
||||||
|
ACCOUNT_POINTER, account,
|
||||||
|
-1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -319,10 +315,17 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type,
|
|||||||
gnc_quickfill_purge(qfb->qf);
|
gnc_quickfill_purge(qfb->qf);
|
||||||
xaccGroupForEachAccount (qfb->group, load_shared_qf_cb, qfb, TRUE);
|
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 */
|
/* 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),
|
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);
|
gtk_list_store_remove(qfb->list_store, &iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,6 +333,10 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type,
|
|||||||
|
|
||||||
case QOF_EVENT_ADD:
|
case QOF_EVENT_ADD:
|
||||||
DEBUG("add %s", name);
|
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);
|
match = gnc_quickfill_get_string_match (qf, name);
|
||||||
if (match) {
|
if (match) {
|
||||||
match_str = gnc_quickfill_string (match);
|
match_str = gnc_quickfill_string (match);
|
||||||
@ -352,8 +359,11 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type,
|
|||||||
DEBUG("other %s", name);
|
DEBUG("other %s", name);
|
||||||
break;
|
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);
|
g_free(name);
|
||||||
LEAVE(" ");
|
LEAVE(" ");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user