diff --git a/ChangeLog b/ChangeLog index 74af8bdf13..d47632d892 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2006-03-04 David Hampton + * src/gnome-utils/gnc-tree-model-account.c: + * src/engine/Account.c: + * src/engine/Group.c: Rework the events generated by the + account/group files and consumed by the GncTreeModelAccount. + Should eliminate all g_value_inset and g_object_set_property + warnings related to changes in the account tree. + + * src/engine/Transaction.c: + * src/engine/gnc-event.h: Rename a data structure field. + * src/gnome-utils/dialog-account.c: Fix duplicate account name checking bug that prevented editing account info. diff --git a/src/engine/Account.c b/src/engine/Account.c index 71e7960bf4..073e367a1d 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -33,6 +33,7 @@ #include "Group.h" #include "GroupP.h" #include "TransactionP.h" +#include "gnc-event.h" #include "gnc-lot.h" #include "gnc-lot-p.h" #include "gnc-pricedb.h" @@ -330,6 +331,8 @@ static inline void acc_free (QofInstance *inst) void xaccAccountCommitEdit (Account *acc) { + GncEventData ed; + if(!qof_commit_edit(&acc->inst)) { return;} /* If marked for deletion, get rid of subaccounts first, @@ -375,6 +378,10 @@ xaccAccountCommitEdit (Account *acc) xaccGroupInsertAccount(acc->parent, acc); } + ed.node = acc; + ed.idx = 0; + qof_event_gen(&acc->inst.entity, QOF_EVENT_MODIFY, &ed); + if (qof_commit_edit_part2(&acc->inst, on_err, noop, acc_free)) gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY); } @@ -890,6 +897,7 @@ xaccAccountRecomputeBalance (Account * acc) gnc_numeric reconciled_balance; Split *last_split = NULL; GList *lp; + GncEventData ed; if (NULL == acc) return; if (acc->inst.editlevel > 0) return; @@ -934,6 +942,10 @@ xaccAccountRecomputeBalance (Account * acc) acc->reconciled_balance = reconciled_balance; acc->balance_dirty = FALSE; + + ed.node = acc; + ed.idx = 0; + qof_event_gen(&acc->inst.entity, QOF_EVENT_MODIFY, &ed); gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY); } diff --git a/src/engine/Group.c b/src/engine/Group.c index 3b272567f0..9699b3b159 100644 --- a/src/engine/Group.c +++ b/src/engine/Group.c @@ -32,6 +32,7 @@ #include "Group.h" #include "GroupP.h" #include "TransactionP.h" +#include "gnc-event.h" static QofLogModule log_module = GNC_MOD_ENGINE; @@ -626,6 +627,8 @@ xaccAccountRemoveGroup (Account *acc) void xaccGroupRemoveAccount (AccountGroup *grp, Account *acc) { + GncEventData ed; + if (!acc) return; /* Note this routine might be called on accounts which @@ -642,8 +645,15 @@ xaccGroupRemoveAccount (AccountGroup *grp, Account *acc) acc->parent = NULL; + /* Gather event data */ + ed.node = grp->parent; /* The parent account */ + ed.idx = g_list_index(grp->accounts, acc); + grp->accounts = g_list_remove (grp->accounts, acc); + /* Now send the event. */ + qof_event_gen(&acc->inst.entity, QOF_EVENT_REMOVE, &ed); + grp->saved = 0; /* if this was the last account in a group, delete @@ -696,6 +706,8 @@ group_sort_helper (gconstpointer a, gconstpointer b) void xaccGroupInsertAccount (AccountGroup *grp, Account *acc) { + GncEventData ed; + if (!grp || !grp->book) return; if (!acc) return; @@ -746,6 +758,11 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc) grp->accounts = g_list_insert_sorted (grp->accounts, acc, group_sort_helper); + + /* Gather event data */ + ed.node = acc; + ed.idx = 0; + qof_event_gen(&acc->inst.entity, QOF_EVENT_ADD, &ed); gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_ADD); acc->inst.dirty = TRUE; diff --git a/src/gnome-utils/gnc-tree-model-account.c b/src/gnome-utils/gnc-tree-model-account.c index 42ef933fd9..5b58135eda 100644 --- a/src/gnome-utils/gnc-tree-model-account.c +++ b/src/gnome-utils/gnc-tree-model-account.c @@ -36,6 +36,7 @@ #include "gnc-commodity.h" #include "gnc-gconf-utils.h" #include "gnc-engine.h" +#include "gnc-event.h" #include "gnc-gobject-utils.h" #include "gnc-ui-util.h" @@ -87,9 +88,10 @@ static void gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model, Account *toplevel); /** Component Manager Callback ******************************************/ -static void gnc_tree_model_account_event_handler (GUID *entity, QofIdType type, - GNCEngineEventType event_type, - gpointer user_data); +static void gnc_tree_model_account_event_handler (QofEntity *entity, + QofEventId event_type, + GncTreeModelAccount *model, + GncEventData *ed); /** The instance private data for a account tree model. */ typedef struct GncTreeModelAccountPrivate @@ -253,7 +255,7 @@ gnc_tree_model_account_dispose (GObject *object) priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); if (priv->event_handler_id) { - gnc_engine_unregister_event_handler (priv->event_handler_id); + qof_event_unregister_handler (priv->event_handler_id); priv->event_handler_id = 0; } @@ -304,8 +306,8 @@ gnc_tree_model_account_new (AccountGroup *group) gnc_tree_model_account_set_toplevel (model, account); } - priv->event_handler_id = - gnc_engine_register_event_handler (gnc_tree_model_account_event_handler, model); + priv->event_handler_id = qof_event_register_handler + ((QofEventHandler)gnc_tree_model_account_event_handler, model); LEAVE("model %p", model); return GTK_TREE_MODEL (model); @@ -1367,24 +1369,6 @@ gnc_tree_model_account_get_path_from_account (GncTreeModelAccount *model, /* Account Tree Model - Engine Event Handling Functions */ /************************************************************/ -/** This data structure maintains a record of a pending removal of an - * account from GnuCash. There is a chicken/egg problem whereby the - * account cannot be removed from the model before it is removed from - * the account group (throws the indices off), but after the account - * has been removed from the account group a path to the account - * can't be generated. This data structure holds a temporary copy of - * the account path to bridge this problem. */ -typedef struct _remove_data { - /** The guid of the account that was removed. */ - GUID guid; - /** A pointer to the model containing the account. */ - GncTreeModelAccount *model; - /** The path within the model to the account. */ - GtkTreePath *path; -} remove_data; - -static GSList *pending_removals = NULL; - /** This function performs common updating to the model after an * account has been added or removed. The parent entry needs to be * tapped on the shoulder so that it can correctly update the @@ -1406,11 +1390,12 @@ gnc_tree_model_account_path_changed (GncTreeModelAccount *model, { GtkTreeIter iter; - if (gtk_tree_path_up (path)) { - if (gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &iter, path)) { - gtk_tree_model_row_changed (GTK_TREE_MODEL(model), path, &iter); - gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL(model), path, &iter); - } + while (gtk_tree_path_get_depth(path) > 0) { + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &iter, path)) + break; + gtk_tree_model_row_changed (GTK_TREE_MODEL(model), path, &iter); + gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL(model), path, &iter); + gtk_tree_path_up(path); } do { @@ -1419,72 +1404,6 @@ gnc_tree_model_account_path_changed (GncTreeModelAccount *model, } -/** This function is a one-shot helper routine for the following - * gnc_tree_model_account_event_handler() function. It must be armed - * each time an item is removed from the model. This function will - * be called as an idle function some time after the user requests - * the deletion. This function will send the "row_deleted" - * signal to any/all parent models for each entry deleted. - * - * @internal - * - * @param unused - * - * @return FALSE. Tells the glib idle function to remove this - * handler, making it a one-shot that will be re-armed at the next - * item removal. - */ -static gboolean -gnc_tree_model_account_do_deletions (gpointer unused) -{ - GSList *iter, *next = NULL; - remove_data *data; - - for (iter = pending_removals; iter != NULL; iter = next) { - next = g_slist_next(iter); - data = iter->data; - pending_removals = g_slist_delete_link (pending_removals, iter); - - gtk_tree_model_row_deleted (GTK_TREE_MODEL(data->model), data->path); - gnc_tree_model_account_path_changed (data->model, data->path); - gtk_tree_path_free(data->path); - g_free(data); - } - - /* Remove me */ - return FALSE; -} - - -/** This function is a helper routine for the following - * gnc_tree_model_account_event_handler() function. It is called to - * add an item to the pending removal list. - * - * @param entity The guid value of the account that is being removed - * from the model. - * - * @param model A pointer to the tree model. - * - * @param path The path to the removed account. This can't be - * generated once the account is removed. - */ -static void -pending_list_add (GUID *entity, - GncTreeModelAccount *model, - GtkTreePath *path) -{ - remove_data *data; - - data = malloc(sizeof(*data)); - data->guid = *entity; - data->model = model; - data->path = path; - pending_removals = g_slist_append (pending_removals, data); - g_idle_add_full(G_PRIORITY_HIGH_IDLE, - gnc_tree_model_account_do_deletions, NULL, NULL); -} - - /** This function is the handler for all event messages from the * engine. Its purpose is to update the account tree model any time * an account is added to the engine or deleted from the engine. @@ -1514,88 +1433,80 @@ pending_list_add (GUID *entity, * @param user_data A pointer to the account tree model. */ static void -gnc_tree_model_account_event_handler (GUID *entity, QofIdType type, - GNCEngineEventType event_type, - gpointer user_data) +gnc_tree_model_account_event_handler (QofEntity *entity, + QofEventId event_type, + GncTreeModelAccount *model, + GncEventData *ed) { - GncTreeModelAccount *model; - GncTreeModelAccountPrivate *priv; - GtkTreePath *path; - GtkTreeIter iter; - Account *account; - const gchar *account_name; - - /* hard failures */ - g_return_if_fail(GNC_IS_TREE_MODEL_ACCOUNT(user_data)); - - /* soft failures */ - if (safe_strcmp(type, GNC_ID_ACCOUNT) != 0) - return; - - ENTER("entity %p of type %s, event %d, model %p", - entity, type, event_type, user_data); - model = (GncTreeModelAccount *)user_data; + GncTreeModelAccountPrivate *priv; + const gchar *parent_name; + GtkTreePath *path = NULL; + GtkTreeIter iter; + Account *account, *parent; + + g_return_if_fail(model); /* Required */ + if (!ed) return; /* Required for us. Not always sent. */ + + ENTER("entity %p of type %d, model %p, event_data %p", + entity, event_type, model, ed); + priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); + + /* What to do, that to do. */ + switch (event_type) { + case QOF_EVENT_ADD: + /* Tell the filters/views where the new account was added. */ + account = GNC_ACCOUNT(ed->node); + DEBUG("add account %p (%s)", account, xaccAccountGetName(account)); + path = gnc_tree_model_account_get_path_from_account(model, account); + if (!path) { + DEBUG("can't generate path"); + break; + } + if (!gnc_tree_model_account_get_iter(GTK_TREE_MODEL(model), &iter, path)) { + DEBUG("can't generate iter"); + break; + } + gtk_tree_model_row_inserted (GTK_TREE_MODEL(model), path, &iter); + if (gtk_tree_path_up (path)) + gnc_tree_model_account_path_changed(model, path); + break; + + case QOF_EVENT_REMOVE: + parent = ed->node ? GNC_ACCOUNT(ed->node) : priv->toplevel; + parent_name = ed->node ? xaccAccountGetName(parent) : "Root"; + DEBUG("remove child %d of account %p (%s)", ed->idx, parent, parent_name); + path = gnc_tree_model_account_get_path_from_account(model, parent); + if (!path) { + DEBUG("can't generate path"); + break; + } + gtk_tree_path_append_index (path, ed->idx); + gtk_tree_model_row_deleted (GTK_TREE_MODEL(model), path); + gnc_tree_model_account_path_changed(model, path); + break; + + case QOF_EVENT_MODIFY: + account = GNC_ACCOUNT(ed->node); + DEBUG("modify account %p (%s)", account, xaccAccountGetName(account)); + path = gnc_tree_model_account_get_path_from_account(model, account); + if (!path) { + DEBUG("can't generate path"); + break; + } + if (!gnc_tree_model_account_get_iter(GTK_TREE_MODEL(model), &iter, path)) { + DEBUG("can't generate iter"); + break; + } + gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter); + break; + + default: + DEBUG("unknown event type"); + return; + } - /* Get the account.*/ - priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - account = xaccAccountLookup (entity, priv->book); - if (!account) { - LEAVE("account not in this model's book"); - return; - } - account_name = xaccAccountGetName(account); - - switch (event_type) { - case GNC_EVENT_ADD: - /* Tell the filters/views where the new account was added. */ - DEBUG("add account %p (%s)", account, account_name); - if (gnc_tree_model_account_get_iter_from_account ( - model, account, &iter)) { - path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter); - gtk_tree_model_row_inserted (GTK_TREE_MODEL(model), path, &iter); - gnc_tree_model_account_path_changed (model, path); - gtk_tree_path_free(path); - } - break; - - case GNC_EVENT_REMOVE: - /* Record the path of this account for later use in destruction */ - DEBUG("remove account %p (%s)", account, account_name); - path = gnc_tree_model_account_get_path_from_account (model, account); - if (path == NULL) { - LEAVE("account not in model"); - return; - } - - pending_list_add(entity, model, path); - LEAVE(" "); - return; - - case GNC_EVENT_MODIFY: - DEBUG("modify account %p (%s)", account, account_name); - path = gnc_tree_model_account_get_path_from_account (model, account); - if (path == NULL) { - LEAVE("account not in model"); - return; - } - if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &iter, path)) { - gtk_tree_path_free(path); - LEAVE("can't find iter for path"); - return; - } - gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter); - gtk_tree_path_free(path); - LEAVE(" "); - return; - - case GNC_EVENT_DESTROY: - /* Tell the filters/view the account has been deleted. */ - DEBUG("destroy account %p (%s)", account, account_name); - break; - - default: - LEAVE("ignored event for %p (%s)", account, account_name); - return; - } - LEAVE(" new stamp %u", model->stamp); + if (path) + gtk_tree_path_free(path); + LEAVE(" "); + return; }