/* * Convert a model/owner pair into a gtk_tree_model_path. This * routine should only be called from the file * gnc-tree-view-owner.c. */ GtkTreePath * gnc_tree_model_owner_get_path_from_owner (GncTreeModelOwner *model, GncOwner *owner) { GtkTreeIter tree_iter; GtkTreePath *tree_path; ENTER("model %p, owner %p", model, owner); gnc_leave_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), NULL); gnc_leave_return_val_if_fail (owner != NULL, NULL); if (!gnc_tree_model_owner_get_iter_from_owner (model, owner, &tree_iter)) { LEAVE("no iter"); return NULL; } tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &tree_iter); if (tree_path) { gchar *path_string = gtk_tree_path_to_string(tree_path); LEAVE("path (2) %s", path_string); g_free(path_string); } else { LEAVE("no path"); } return tree_path; }
static gboolean gnc_tree_view_owner_get_iter_from_owner (GncTreeViewOwner *view, GncOwner *owner, GtkTreeIter *s_iter) { GtkTreeModel *model, *f_model, *s_model; GtkTreeIter iter, f_iter; g_return_val_if_fail(GNC_IS_TREE_VIEW_OWNER(view), FALSE); g_return_val_if_fail(owner != NULL, FALSE); g_return_val_if_fail(s_iter != NULL, FALSE); ENTER("view %p, owner %p (%s)", view, owner, gncOwnerGetName(owner)); /* Reach down to the real model and get an iter for this owner */ s_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); f_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(s_model)); model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(f_model)); if (!gnc_tree_model_owner_get_iter_from_owner ( GNC_TREE_MODEL_OWNER(model), owner, &iter)) { LEAVE("model_get_iter_from_owner failed"); return FALSE; } /* convert back to a sort iter */ gtk_tree_model_filter_convert_child_iter_to_iter ( GTK_TREE_MODEL_FILTER(f_model), &f_iter, &iter); gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(s_model), s_iter, &f_iter); LEAVE(" "); return TRUE; }
/** This function is the handler for all event messages from the * engine. Its purpose is to update the owner tree model any time * an owner is added to the engine or deleted from the engine. * This change to the model is then propagated to any/all overlying * filters and views. This function listens to the ADD, REMOVE, and * DESTROY events. * * @internal * * @warning There is a "Catch 22" situation here. * gtk_tree_model_row_deleted() can't be called until after the item * has been deleted from the real model (which is the engine's * owner tree for us), but once the owner has been deleted from * the engine we have no way to determine the path to pass to * row_deleted(). This is a PITA, but the only other choice is to * have this model mirror the engine's owners instead of * referencing them directly. * * @param entity The guid of the affected item. * * @param type The type of the affected item. This function only * cares about items of type "owner". * * @param event type The type of the event. This function only cares * about items of type ADD, REMOVE, MODIFY, and DESTROY. * * @param user_data A pointer to the owner tree model. */ static void gnc_tree_model_owner_event_handler (QofInstance *entity, QofEventId event_type, GncTreeModelOwner *model, GncEventData *ed) { GncTreeModelOwnerPrivate *priv; GtkTreePath *path = NULL; GtkTreeIter iter; GncOwner owner; g_return_if_fail(model); /* Required */ if (!GNC_IS_OWNER(entity)) return; ENTER("entity %p of type %d, model %p, event_data %p", entity, event_type, model, ed); priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); qofOwnerSetEntity (&owner, entity); if (gncOwnerGetType(&owner) != priv->owner_type) { LEAVE("model type and owner type differ"); return; } if (qof_instance_get_book (entity) != priv->book) { LEAVE("not in this book"); return; } /* What to do, that to do. */ switch (event_type) { case QOF_EVENT_ADD: /* Tell the filters/views where the new owner was added. */ DEBUG("add owner %p (%s)", &owner, gncOwnerGetName(&owner)); /* First update our copy of the owner list. This isn't done automatically */ priv->owner_list = gncBusinessGetOwnerList (priv->book, gncOwnerTypeToQofIdType(priv->owner_type), TRUE); increment_stamp(model); if (!gnc_tree_model_owner_get_iter_from_owner (model, &owner, &iter)) { LEAVE("can't generate iter"); break; } path = gnc_tree_model_owner_get_path(GTK_TREE_MODEL(model), &iter); if (!path) { DEBUG("can't generate path"); break; } gtk_tree_model_row_inserted (GTK_TREE_MODEL(model), path, &iter); break; case QOF_EVENT_REMOVE: if (!ed) /* Required for a remove. */ break; DEBUG("remove owner %d (%s) from owner_list %p", ed->idx, gncOwnerGetName(&owner), priv->owner_list); path = gtk_tree_path_new(); if (!path) { DEBUG("can't generate path"); break; } increment_stamp(model); gtk_tree_path_append_index (path, ed->idx); gtk_tree_model_row_deleted (GTK_TREE_MODEL(model), path); break; case QOF_EVENT_MODIFY: DEBUG("modify owner %p (%s)", &owner, gncOwnerGetName(&owner)); if (!gnc_tree_model_owner_get_iter_from_owner (model, &owner, &iter)) { LEAVE("can't generate iter"); return; } path = gnc_tree_model_owner_get_path(GTK_TREE_MODEL(model), &iter); if (!path) { DEBUG("can't generate path"); break; } gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter); break; default: LEAVE("unknown event type"); return; } if (path) gtk_tree_path_free(path); LEAVE(" "); return; }