|
GnuCash 2.4.99
|
00001 /* 00002 * gnc-tree-model-owner.c -- GtkTreeModel implementation to 00003 * display owners in a GtkTreeView. 00004 * 00005 * Copyright (C) 2011 Geert Janssens <geert@kobaltwit.be> 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License as 00009 * published by the Free Software Foundation; either version 2 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, contact: 00019 * 00020 * Free Software Foundation Voice: +1-617-542-5942 00021 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00022 * Boston, MA 02110-1301, USA gnu@gnu.org 00023 */ 00024 00025 #include "config.h" 00026 00027 #include <gtk/gtk.h> 00028 #include <glib/gi18n.h> 00029 #include <string.h> 00030 00031 #include "gnc-tree-model-owner.h" 00032 #include "gnc-component-manager.h" 00033 #include "gncOwner.h" 00034 #include "gnc-commodity.h" 00035 #include "gnc-gconf-utils.h" 00036 #include "gnc-engine.h" 00037 #include "gnc-event.h" 00038 #include "gnc-gobject-utils.h" 00039 #include "gnc-ui-balances.h" 00040 #include "gnc-ui-util.h" 00041 00042 #define TREE_MODEL_OWNER_CM_CLASS "tree-model-owner" 00043 00045 static QofLogModule log_module = GNC_MOD_GUI; 00046 00048 static void gnc_tree_model_owner_class_init (GncTreeModelOwnerClass *klass); 00049 static void gnc_tree_model_owner_init (GncTreeModelOwner *model); 00050 static void gnc_tree_model_owner_finalize (GObject *object); 00051 static void gnc_tree_model_owner_dispose (GObject *object); 00052 00054 static void gnc_tree_model_owner_tree_model_init (GtkTreeModelIface *iface); 00055 static GtkTreeModelFlags gnc_tree_model_owner_get_flags (GtkTreeModel *tree_model); 00056 static int gnc_tree_model_owner_get_n_columns (GtkTreeModel *tree_model); 00057 static GType gnc_tree_model_owner_get_column_type (GtkTreeModel *tree_model, 00058 int index); 00059 static gboolean gnc_tree_model_owner_get_iter (GtkTreeModel *tree_model, 00060 GtkTreeIter *iter, 00061 GtkTreePath *path); 00062 static GtkTreePath *gnc_tree_model_owner_get_path (GtkTreeModel *tree_model, 00063 GtkTreeIter *iter); 00064 static void gnc_tree_model_owner_get_value (GtkTreeModel *tree_model, 00065 GtkTreeIter *iter, 00066 int column, 00067 GValue *value); 00068 static gboolean gnc_tree_model_owner_iter_next (GtkTreeModel *tree_model, 00069 GtkTreeIter *iter); 00070 static gboolean gnc_tree_model_owner_iter_children (GtkTreeModel *tree_model, 00071 GtkTreeIter *iter, 00072 GtkTreeIter *parent); 00073 static gboolean gnc_tree_model_owner_iter_has_child (GtkTreeModel *tree_model, 00074 GtkTreeIter *iter); 00075 static int gnc_tree_model_owner_iter_n_children (GtkTreeModel *tree_model, 00076 GtkTreeIter *iter); 00077 static gboolean gnc_tree_model_owner_iter_nth_child (GtkTreeModel *tree_model, 00078 GtkTreeIter *iter, 00079 GtkTreeIter *parent, 00080 int n); 00081 static gboolean gnc_tree_model_owner_iter_parent (GtkTreeModel *tree_model, 00082 GtkTreeIter *iter, 00083 GtkTreeIter *child); 00084 00086 static void gnc_tree_model_owner_event_handler (QofInstance *entity, 00087 QofEventId event_type, 00088 GncTreeModelOwner *model, 00089 GncEventData *ed); 00090 00092 typedef struct GncTreeModelOwnerPrivate 00093 { 00094 QofBook *book; 00095 GncOwnerType owner_type; 00096 OwnerList *owner_list; 00097 gint event_handler_id; 00098 const gchar *negative_color; 00099 } GncTreeModelOwnerPrivate; 00100 00101 #define GNC_TREE_MODEL_OWNER_GET_PRIVATE(o) \ 00102 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_MODEL_OWNER, GncTreeModelOwnerPrivate)) 00103 00104 00105 /************************************************************/ 00106 /* Owner Tree Model - Misc Functions */ 00107 /************************************************************/ 00108 00115 static void 00116 gnc_tree_model_owner_update_color (GConfEntry *entry, gpointer user_data) 00117 { 00118 GncTreeModelOwnerPrivate *priv; 00119 GncTreeModelOwner *model; 00120 GConfValue *value; 00121 gboolean use_red; 00122 00123 g_return_if_fail(GNC_IS_TREE_MODEL_OWNER(user_data)); 00124 model = user_data; 00125 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00126 value = gconf_entry_get_value(entry); 00127 use_red = gconf_value_get_bool(value); 00128 priv->negative_color = use_red ? "red" : "black"; 00129 } 00130 /************************************************************/ 00131 /* g_object required functions */ 00132 /************************************************************/ 00133 00135 static GtkObjectClass *parent_class = NULL; 00136 00137 GType 00138 gnc_tree_model_owner_get_type (void) 00139 { 00140 static GType gnc_tree_model_owner_type = 0; 00141 00142 if (gnc_tree_model_owner_type == 0) 00143 { 00144 static const GTypeInfo our_info = 00145 { 00146 sizeof (GncTreeModelOwnerClass), /* class_size */ 00147 NULL, /* base_init */ 00148 NULL, /* base_finalize */ 00149 (GClassInitFunc) gnc_tree_model_owner_class_init, 00150 NULL, /* class_finalize */ 00151 NULL, /* class_data */ 00152 sizeof (GncTreeModelOwner), /* */ 00153 0, /* n_preallocs */ 00154 (GInstanceInitFunc) gnc_tree_model_owner_init 00155 }; 00156 00157 static const GInterfaceInfo tree_model_info = 00158 { 00159 (GInterfaceInitFunc) gnc_tree_model_owner_tree_model_init, 00160 NULL, 00161 NULL 00162 }; 00163 00164 gnc_tree_model_owner_type = g_type_register_static (GNC_TYPE_TREE_MODEL, 00165 GNC_TREE_MODEL_OWNER_NAME, 00166 &our_info, 0); 00167 00168 g_type_add_interface_static (gnc_tree_model_owner_type, 00169 GTK_TYPE_TREE_MODEL, 00170 &tree_model_info); 00171 } 00172 00173 return gnc_tree_model_owner_type; 00174 } 00175 00176 static void 00177 gnc_tree_model_owner_class_init (GncTreeModelOwnerClass *klass) 00178 { 00179 GObjectClass *o_class; 00180 00181 parent_class = g_type_class_peek_parent (klass); 00182 00183 o_class = G_OBJECT_CLASS (klass); 00184 00185 /* GObject signals */ 00186 o_class->finalize = gnc_tree_model_owner_finalize; 00187 o_class->dispose = gnc_tree_model_owner_dispose; 00188 00189 g_type_class_add_private(klass, sizeof(GncTreeModelOwnerPrivate)); 00190 } 00191 00192 static void 00193 gnc_tree_model_owner_init (GncTreeModelOwner *model) 00194 { 00195 GncTreeModelOwnerPrivate *priv; 00196 gboolean red; 00197 00198 ENTER("model %p", model); 00199 while (model->stamp == 0) 00200 { 00201 model->stamp = g_random_int (); 00202 } 00203 00204 red = gnc_gconf_get_bool(GCONF_GENERAL, KEY_NEGATIVE_IN_RED, NULL); 00205 00206 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00207 priv->book = NULL; 00208 priv->owner_list = NULL; 00209 priv->owner_type = GNC_OWNER_NONE; 00210 priv->negative_color = red ? "red" : "black"; 00211 00212 gnc_gconf_general_register_cb(KEY_NEGATIVE_IN_RED, 00213 gnc_tree_model_owner_update_color, 00214 model); 00215 00216 LEAVE(" "); 00217 } 00218 00219 static void 00220 gnc_tree_model_owner_finalize (GObject *object) 00221 { 00222 GncTreeModelOwnerPrivate *priv; 00223 GncTreeModelOwner *model; 00224 00225 g_return_if_fail (object != NULL); 00226 g_return_if_fail (GNC_IS_TREE_MODEL_OWNER (object)); 00227 00228 ENTER("model %p", object); 00229 00230 model = GNC_TREE_MODEL_OWNER (object); 00231 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00232 00233 gnc_gconf_general_remove_cb(KEY_NEGATIVE_IN_RED, 00234 gnc_tree_model_owner_update_color, 00235 model); 00236 00237 priv->book = NULL; 00238 priv->owner_list = NULL; 00239 00240 if (G_OBJECT_CLASS (parent_class)->finalize) 00241 G_OBJECT_CLASS(parent_class)->finalize (object); 00242 LEAVE(" "); 00243 } 00244 00245 static void 00246 gnc_tree_model_owner_dispose (GObject *object) 00247 { 00248 GncTreeModelOwnerPrivate *priv; 00249 GncTreeModelOwner *model; 00250 00251 g_return_if_fail (object != NULL); 00252 g_return_if_fail (GNC_IS_TREE_MODEL_OWNER (object)); 00253 00254 ENTER("model %p", object); 00255 00256 model = GNC_TREE_MODEL_OWNER (object); 00257 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00258 00259 if (priv->event_handler_id) 00260 { 00261 qof_event_unregister_handler (priv->event_handler_id); 00262 priv->event_handler_id = 0; 00263 } 00264 00265 gnc_gconf_general_remove_cb(KEY_NEGATIVE_IN_RED, 00266 gnc_tree_model_owner_update_color, 00267 model); 00268 00269 if (G_OBJECT_CLASS (parent_class)->dispose) 00270 G_OBJECT_CLASS (parent_class)->dispose (object); 00271 LEAVE(" "); 00272 } 00273 00274 00275 /************************************************************/ 00276 /* New Model Creation */ 00277 /************************************************************/ 00278 00279 GtkTreeModel * 00280 gnc_tree_model_owner_new (GncOwnerType owner_type) 00281 { 00282 GncTreeModelOwner *model; 00283 GncTreeModelOwnerPrivate *priv; 00284 const GList *item; 00285 00286 ENTER("owner_type %d", owner_type); 00287 item = gnc_gobject_tracking_get_list(GNC_TREE_MODEL_OWNER_NAME); 00288 for ( ; item; item = g_list_next(item)) 00289 { 00290 model = (GncTreeModelOwner *)item->data; 00291 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00292 if (priv->owner_type == owner_type) 00293 { 00294 g_object_ref(G_OBJECT(model)); 00295 LEAVE("returning existing model %p", model); 00296 return GTK_TREE_MODEL(model); 00297 } 00298 } 00299 00300 model = g_object_new (GNC_TYPE_TREE_MODEL_OWNER, 00301 NULL); 00302 00303 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00304 priv->book = gnc_get_current_book(); 00305 priv->owner_type = owner_type; 00306 priv->owner_list = gncBusinessGetOwnerList (priv->book, gncOwnerTypeToQofIdType(owner_type), TRUE); 00307 00308 priv->event_handler_id = qof_event_register_handler 00309 ((QofEventHandler)gnc_tree_model_owner_event_handler, model); 00310 00311 LEAVE("model %p", model); 00312 return GTK_TREE_MODEL (model); 00313 } 00314 00315 00316 /************************************************************/ 00317 /* Gnc Tree Model Debugging Utility Function */ 00318 /************************************************************/ 00319 00320 #define ITER_STRING_LEN 128 00321 00322 static const gchar * 00323 iter_to_string (GtkTreeIter *iter) 00324 { 00325 #ifdef G_THREADS_ENABLED 00326 static GStaticPrivate gtmits_buffer_key = G_STATIC_PRIVATE_INIT; 00327 gchar *string; 00328 00329 string = g_static_private_get (>mits_buffer_key); 00330 if (string == NULL) 00331 { 00332 string = g_malloc(ITER_STRING_LEN + 1); 00333 g_static_private_set (>mits_buffer_key, string, g_free); 00334 } 00335 #else 00336 static char string[ITER_STRING_LEN + 1]; 00337 #endif 00338 00339 if (iter) 00340 snprintf(string, ITER_STRING_LEN, 00341 "[stamp:%x data:%p (%s), %p, %d]", 00342 iter->stamp, iter->user_data, 00343 gncOwnerGetName ((GncOwner *) iter->user_data), 00344 iter->user_data2, GPOINTER_TO_INT(iter->user_data3)); 00345 else 00346 strcpy(string, "(null)"); 00347 return string; 00348 } 00349 00350 00351 /************************************************************/ 00352 /* Gtk Tree Model Required Interface Functions */ 00353 /************************************************************/ 00354 00355 static void 00356 gnc_tree_model_owner_tree_model_init (GtkTreeModelIface *iface) 00357 { 00358 iface->get_flags = gnc_tree_model_owner_get_flags; 00359 iface->get_n_columns = gnc_tree_model_owner_get_n_columns; 00360 iface->get_column_type = gnc_tree_model_owner_get_column_type; 00361 iface->get_iter = gnc_tree_model_owner_get_iter; 00362 iface->get_path = gnc_tree_model_owner_get_path; 00363 iface->get_value = gnc_tree_model_owner_get_value; 00364 iface->iter_next = gnc_tree_model_owner_iter_next; 00365 iface->iter_children = gnc_tree_model_owner_iter_children; 00366 iface->iter_has_child = gnc_tree_model_owner_iter_has_child; 00367 iface->iter_n_children = gnc_tree_model_owner_iter_n_children; 00368 iface->iter_nth_child = gnc_tree_model_owner_iter_nth_child; 00369 iface->iter_parent = gnc_tree_model_owner_iter_parent; 00370 } 00371 00372 static GtkTreeModelFlags 00373 gnc_tree_model_owner_get_flags (GtkTreeModel *tree_model) 00374 { 00375 return 0; 00376 } 00377 00378 static int 00379 gnc_tree_model_owner_get_n_columns (GtkTreeModel *tree_model) 00380 { 00381 g_return_val_if_fail(GNC_IS_TREE_MODEL_OWNER(tree_model), -1); 00382 00383 return GNC_TREE_MODEL_OWNER_NUM_COLUMNS; 00384 } 00385 00386 static GType 00387 gnc_tree_model_owner_get_column_type (GtkTreeModel *tree_model, 00388 int index) 00389 { 00390 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (tree_model), G_TYPE_INVALID); 00391 g_return_val_if_fail ((index < GNC_TREE_MODEL_OWNER_NUM_COLUMNS) && (index >= 0), G_TYPE_INVALID); 00392 00393 switch (index) 00394 { 00395 case GNC_TREE_MODEL_OWNER_COL_NAME: 00396 case GNC_TREE_MODEL_OWNER_COL_TYPE: 00397 case GNC_TREE_MODEL_OWNER_COL_CURRENCY: 00398 case GNC_TREE_MODEL_OWNER_COL_ID: 00399 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_NAME: 00400 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_1: 00401 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_2: 00402 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_3: 00403 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_4: 00404 case GNC_TREE_MODEL_OWNER_COL_PHONE: 00405 case GNC_TREE_MODEL_OWNER_COL_FAX: 00406 case GNC_TREE_MODEL_OWNER_COL_EMAIL: 00407 case GNC_TREE_MODEL_OWNER_COL_BALANCE: 00408 case GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT: 00409 case GNC_TREE_MODEL_OWNER_COL_NOTES: 00410 00411 case GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE: 00412 return G_TYPE_STRING; 00413 00414 case GNC_TREE_MODEL_OWNER_COL_ACTIVE: 00415 return G_TYPE_BOOLEAN; 00416 00417 default: 00418 g_assert_not_reached (); 00419 return G_TYPE_INVALID; 00420 } 00421 } 00422 00423 static gboolean 00424 gnc_tree_model_owner_get_iter (GtkTreeModel *tree_model, 00425 GtkTreeIter *iter, 00426 GtkTreePath *path) 00427 { 00428 GncTreeModelOwnerPrivate *priv; 00429 GncTreeModelOwner *model; 00430 GncOwner *owner; 00431 gint *indices; 00432 00433 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (tree_model), FALSE); 00434 00435 { 00436 gchar *path_string = gtk_tree_path_to_string(path); 00437 ENTER("model %p, iter %p, path %s", tree_model, iter, path_string); 00438 g_free(path_string); 00439 } 00440 00441 model = GNC_TREE_MODEL_OWNER (tree_model); 00442 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00443 00444 /* We keep a simple list of owners, not a tree, so only depth 1 is valid */ 00445 if (gtk_tree_path_get_depth (path) != 1) 00446 { 00447 LEAVE("bad depth"); 00448 return FALSE; 00449 } 00450 00451 indices = gtk_tree_path_get_indices (path); 00452 00453 owner = g_list_nth_data (priv->owner_list, indices[0]); 00454 if (owner == NULL) 00455 { 00456 iter->stamp = 0; 00457 LEAVE("bad index"); 00458 return FALSE; 00459 } 00460 00461 iter->stamp = model->stamp; 00462 iter->user_data = owner; 00463 iter->user_data2 = GINT_TO_POINTER (indices[0]); 00464 iter->user_data3 = NULL; 00465 00466 LEAVE("iter %s", iter_to_string (iter)); 00467 return TRUE; 00468 } 00469 00470 static GtkTreePath * 00471 gnc_tree_model_owner_get_path (GtkTreeModel *tree_model, 00472 GtkTreeIter *iter) 00473 { 00474 GncTreeModelOwner *model = GNC_TREE_MODEL_OWNER (tree_model); 00475 GncTreeModelOwnerPrivate *priv; 00476 GncOwner *owner; 00477 GtkTreePath *path; 00478 gint i; 00479 00480 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), NULL); 00481 g_return_val_if_fail (iter != NULL, NULL); 00482 g_return_val_if_fail (iter->user_data != NULL, NULL); 00483 g_return_val_if_fail (iter->stamp == model->stamp, NULL); 00484 00485 ENTER("model %p, iter %s", model, iter_to_string(iter)); 00486 00487 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00488 if (priv->owner_list == NULL) 00489 { 00490 LEAVE("failed (1)"); 00491 return NULL; 00492 } 00493 00494 owner = (GncOwner *) iter->user_data; 00495 00496 path = gtk_tree_path_new (); 00497 i = g_list_index (priv->owner_list, owner); 00498 if (i == -1) 00499 { 00500 gtk_tree_path_free (path); 00501 LEAVE("failed (3)"); 00502 return NULL; 00503 } 00504 gtk_tree_path_prepend_index (path, i); 00505 00506 { 00507 gchar *path_string = gtk_tree_path_to_string(path); 00508 LEAVE("path (4) %s", path_string); 00509 g_free(path_string); 00510 } 00511 return path; 00512 } 00513 00514 static void 00515 gnc_tree_model_owner_set_color(GncTreeModelOwner *model, 00516 gboolean negative, 00517 GValue *value) 00518 { 00519 GncTreeModelOwnerPrivate *priv; 00520 00521 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00522 if (negative) 00523 g_value_set_static_string (value, priv->negative_color); 00524 else 00525 g_value_set_static_string (value, "black"); 00526 } 00527 00528 static void 00529 gnc_tree_model_owner_get_value (GtkTreeModel *tree_model, 00530 GtkTreeIter *iter, 00531 int column, 00532 GValue *value) 00533 { 00534 GncTreeModelOwner *model = GNC_TREE_MODEL_OWNER (tree_model); 00535 GncTreeModelOwnerPrivate *priv; 00536 GncOwner *owner; 00537 gboolean negative; /* used to set "deficit style" also known as red numbers */ 00538 gchar *string = NULL; 00539 time_t last_date; 00540 00541 g_return_if_fail (GNC_IS_TREE_MODEL_OWNER (model)); 00542 g_return_if_fail (iter != NULL); 00543 g_return_if_fail (iter->user_data != NULL); 00544 g_return_if_fail (iter->stamp == model->stamp); 00545 00546 ENTER("model %p, iter %s, col %d", tree_model, 00547 iter_to_string(iter), column); 00548 00549 owner = (GncOwner *) iter->user_data; 00550 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00551 00552 switch (column) 00553 { 00554 case GNC_TREE_MODEL_OWNER_COL_NAME: 00555 g_value_init (value, G_TYPE_STRING); 00556 g_value_set_string (value, gncOwnerGetName (owner)); 00557 break; 00558 case GNC_TREE_MODEL_OWNER_COL_TYPE: 00559 g_value_init (value, G_TYPE_STRING); 00560 g_value_set_string (value, 00561 gncOwnerTypeToQofIdType (gncOwnerGetType (owner))); 00562 break; 00563 case GNC_TREE_MODEL_OWNER_COL_ID: 00564 g_value_init (value, G_TYPE_STRING); 00565 g_value_set_string (value, gncOwnerGetID (owner)); 00566 break; 00567 case GNC_TREE_MODEL_OWNER_COL_CURRENCY: 00568 g_value_init (value, G_TYPE_STRING); 00569 g_value_set_string (value, 00570 gnc_commodity_get_fullname(gncOwnerGetCurrency (owner))); 00571 break; 00572 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_NAME: 00573 g_value_init (value, G_TYPE_STRING); 00574 string = g_strdup (gncAddressGetName (gncOwnerGetAddr (owner))); 00575 if (string) 00576 g_value_take_string (value, string); 00577 else 00578 g_value_set_static_string (value, ""); 00579 break; 00580 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_1: 00581 g_value_init (value, G_TYPE_STRING); 00582 string = g_strdup (gncAddressGetAddr1 (gncOwnerGetAddr (owner))); 00583 if (string) 00584 g_value_take_string (value, string); 00585 else 00586 g_value_set_static_string (value, ""); 00587 break; 00588 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_2: 00589 g_value_init (value, G_TYPE_STRING); 00590 string = g_strdup (gncAddressGetAddr2 (gncOwnerGetAddr (owner))); 00591 if (string) 00592 g_value_take_string (value, string); 00593 else 00594 g_value_set_static_string (value, ""); 00595 break; 00596 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_3: 00597 g_value_init (value, G_TYPE_STRING); 00598 string = g_strdup (gncAddressGetAddr3 (gncOwnerGetAddr (owner))); 00599 if (string) 00600 g_value_take_string (value, string); 00601 else 00602 g_value_set_static_string (value, ""); 00603 break; 00604 case GNC_TREE_MODEL_OWNER_COL_ADDRESS_4: 00605 g_value_init (value, G_TYPE_STRING); 00606 string = g_strdup (gncAddressGetAddr4 (gncOwnerGetAddr (owner))); 00607 if (string) 00608 g_value_take_string (value, string); 00609 else 00610 g_value_set_static_string (value, ""); 00611 break; 00612 case GNC_TREE_MODEL_OWNER_COL_PHONE: 00613 g_value_init (value, G_TYPE_STRING); 00614 string = g_strdup (gncAddressGetPhone (gncOwnerGetAddr (owner))); 00615 if (string) 00616 g_value_take_string (value, string); 00617 else 00618 g_value_set_static_string (value, ""); 00619 break; 00620 case GNC_TREE_MODEL_OWNER_COL_FAX: 00621 g_value_init (value, G_TYPE_STRING); 00622 string = g_strdup (gncAddressGetFax (gncOwnerGetAddr (owner))); 00623 if (string) 00624 g_value_take_string (value, string); 00625 else 00626 g_value_set_static_string (value, ""); 00627 break; 00628 case GNC_TREE_MODEL_OWNER_COL_EMAIL: 00629 g_value_init (value, G_TYPE_STRING); 00630 string = g_strdup (gncAddressGetEmail (gncOwnerGetAddr (owner))); 00631 if (string) 00632 g_value_take_string (value, string); 00633 else 00634 g_value_set_static_string (value, ""); 00635 break; 00636 00637 case GNC_TREE_MODEL_OWNER_COL_BALANCE: 00638 g_value_init (value, G_TYPE_STRING); 00639 string = gnc_ui_owner_get_print_balance(owner, &negative); 00640 g_value_take_string (value, string); 00641 break; 00642 00643 case GNC_TREE_MODEL_OWNER_COL_BALANCE_REPORT: 00644 g_value_init (value, G_TYPE_STRING); 00645 string = gnc_ui_owner_get_print_report_balance(owner, &negative); 00646 g_value_take_string (value, string); 00647 break; 00648 case GNC_TREE_MODEL_OWNER_COL_COLOR_BALANCE: 00649 g_value_init (value, G_TYPE_STRING); 00650 string = gnc_ui_owner_get_print_balance(owner, &negative); 00651 gnc_tree_model_owner_set_color(model, negative, value); 00652 g_free(string); 00653 break; 00654 00655 case GNC_TREE_MODEL_OWNER_COL_NOTES: 00656 g_value_init (value, G_TYPE_STRING); 00657 switch (gncOwnerGetType (owner)) 00658 { 00659 case GNC_OWNER_NONE: 00660 case GNC_OWNER_UNDEFINED: 00661 case GNC_OWNER_EMPLOYEE: 00662 case GNC_OWNER_JOB: 00663 default: 00664 g_value_set_static_string (value, ""); 00665 break; 00666 case GNC_OWNER_VENDOR: 00667 g_value_set_string (value, gncVendorGetNotes (gncOwnerGetVendor (owner))); 00668 break; 00669 case GNC_OWNER_CUSTOMER: 00670 g_value_set_string (value, gncCustomerGetNotes (gncOwnerGetCustomer (owner))); 00671 break; 00672 } 00673 break; 00674 00675 case GNC_TREE_MODEL_OWNER_COL_ACTIVE: 00676 g_value_init (value, G_TYPE_BOOLEAN); 00677 g_value_set_boolean (value, gncOwnerGetActive (owner)); 00678 break; 00679 00680 default: 00681 g_assert_not_reached (); 00682 } 00683 LEAVE(" "); 00684 } 00685 00686 static gboolean 00687 gnc_tree_model_owner_iter_next (GtkTreeModel *tree_model, 00688 GtkTreeIter *iter) 00689 { 00690 GncTreeModelOwner *model = GNC_TREE_MODEL_OWNER (tree_model); 00691 GncTreeModelOwnerPrivate *priv; 00692 GncOwner *owner; 00693 gint i; 00694 00695 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), FALSE); 00696 g_return_val_if_fail (iter != NULL, FALSE); 00697 g_return_val_if_fail (iter->user_data != NULL, FALSE); 00698 g_return_val_if_fail (iter->stamp == model->stamp, FALSE); 00699 00700 ENTER("model %p, iter %s", tree_model, iter_to_string (iter)); 00701 00702 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00703 00704 /* Get the *next* sibling owner. */ 00705 i = GPOINTER_TO_INT (iter->user_data2); 00706 owner = g_list_nth_data (priv->owner_list, i + 1); 00707 if (owner == NULL) 00708 { 00709 iter->stamp = 0; 00710 LEAVE("failed (3)"); 00711 return FALSE; 00712 } 00713 00714 iter->user_data = owner; 00715 iter->user_data2 = GINT_TO_POINTER (i + 1); 00716 iter->user_data3 = NULL; 00717 00718 LEAVE("iter %s", iter_to_string(iter)); 00719 return TRUE; 00720 } 00721 00722 static gboolean 00723 gnc_tree_model_owner_iter_children (GtkTreeModel *tree_model, 00724 GtkTreeIter *iter, 00725 GtkTreeIter *parent_iter) 00726 { 00727 GncTreeModelOwnerPrivate *priv; 00728 GncTreeModelOwner *model; 00729 00730 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (tree_model), FALSE); 00731 ENTER("model %p, iter %p (to be filed in), parent %s", 00732 tree_model, iter, (parent_iter ? iter_to_string(parent_iter) : "(null)")); 00733 00734 model = GNC_TREE_MODEL_OWNER (tree_model); 00735 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00736 00737 /* Owner lists don't have children, so this function call only 00738 * makes sense if no parent_iter was supplied. In that case, 00739 * return the first owner in the list */ 00740 if (!parent_iter) 00741 { 00742 iter->user_data = g_list_nth_data (priv->owner_list, 0); 00743 iter->user_data2 = GINT_TO_POINTER (0); 00744 iter->user_data3 = NULL; 00745 iter->stamp = model->stamp; 00746 LEAVE("iter (2) %s", iter_to_string(iter)); 00747 return TRUE; 00748 } 00749 else 00750 { 00751 iter->stamp = 0; 00752 LEAVE("failed (owners don't have children)"); 00753 return FALSE; 00754 } 00755 } 00756 00757 static gboolean 00758 gnc_tree_model_owner_iter_has_child (GtkTreeModel *tree_model, 00759 GtkTreeIter *iter) 00760 { 00761 /* Owner lists don't have children, so always return false */ 00762 return FALSE; 00763 } 00764 00765 static int 00766 gnc_tree_model_owner_iter_n_children (GtkTreeModel *tree_model, 00767 GtkTreeIter *iter) 00768 { 00769 GncTreeModelOwner *model; 00770 GncTreeModelOwnerPrivate *priv; 00771 00772 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (tree_model), -1); 00773 00774 model = GNC_TREE_MODEL_OWNER (tree_model); 00775 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE (model); 00776 00777 /* Owner lists don't have children, so always return 0, except for 00778 * the special case this request comes for the special "root" iter 00779 * (NULL). For that exception we return the size of the ower list. 00780 */ 00781 if (iter == NULL) 00782 return (gint) g_list_length (priv->owner_list); 00783 00784 g_return_val_if_fail ( 00785 GNC_TREE_MODEL_OWNER (tree_model)->stamp == iter->stamp, -1); 00786 00787 return 0; 00788 } 00789 00790 static gboolean 00791 gnc_tree_model_owner_iter_nth_child (GtkTreeModel *tree_model, 00792 GtkTreeIter *iter, 00793 GtkTreeIter *parent_iter, 00794 int n) 00795 { 00796 GncTreeModelOwner *model; 00797 GncTreeModelOwnerPrivate *priv; 00798 00799 if (parent_iter) 00800 { 00801 gchar *parent_string; 00802 parent_string = g_strdup(iter_to_string(parent_iter)); 00803 ENTER("model %p, iter %s, parent_iter %s, n %d", 00804 tree_model, iter_to_string(iter), 00805 parent_string, n); 00806 g_free(parent_string); 00807 } 00808 else 00809 { 00810 ENTER("model %p, iter %s, parent_iter (null), n %d", 00811 tree_model, iter_to_string(iter), n); 00812 } 00813 gnc_leave_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (tree_model), FALSE); 00814 00815 model = GNC_TREE_MODEL_OWNER (tree_model); 00816 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00817 00818 /* Owner lists don't have children, so this function call only 00819 * makes sense if no parent_iter was supplied. In that case, 00820 * return the first owner in the list */ 00821 if (!parent_iter) 00822 { 00823 iter->user_data = g_list_nth_data (priv->owner_list, n); 00824 iter->user_data2 = GINT_TO_POINTER (n); 00825 iter->user_data3 = NULL; 00826 iter->stamp = model->stamp; 00827 LEAVE("iter (2) %s", iter_to_string(iter)); 00828 return TRUE; 00829 } 00830 else 00831 { 00832 iter->stamp = 0; 00833 LEAVE("failed (owners don't have children)"); 00834 return FALSE; 00835 } 00836 } 00837 00838 static gboolean 00839 gnc_tree_model_owner_iter_parent (GtkTreeModel *tree_model, 00840 GtkTreeIter *iter, 00841 GtkTreeIter *child) 00842 { 00843 /* Owner lists don't have children, so always return false */ 00844 iter->stamp = 0; 00845 return FALSE; 00846 } 00847 00848 00849 /************************************************************/ 00850 /* Owner Tree View Filter Functions */ 00851 /************************************************************/ 00852 00853 /* 00854 * Convert a model/iter pair to a gnucash owner. This routine should 00855 * only be called from an owner tree view filter function. 00856 */ 00857 GncOwner * 00858 gnc_tree_model_owner_get_owner (GncTreeModelOwner *model, 00859 GtkTreeIter *iter) 00860 { 00861 g_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), NULL); 00862 g_return_val_if_fail (iter != NULL, NULL); 00863 g_return_val_if_fail (iter->user_data != NULL, NULL); 00864 g_return_val_if_fail (iter->stamp == model->stamp, NULL); 00865 00866 return (GncOwner *) iter->user_data; 00867 } 00868 00869 /* 00870 * Convert a model/owner pair into a gtk_tree_model_iter. This 00871 * routine should only be called from the file 00872 * gnc-tree-view-owner.c. 00873 */ 00874 gboolean 00875 gnc_tree_model_owner_get_iter_from_owner (GncTreeModelOwner *model, 00876 GncOwner *owner, 00877 GtkTreeIter *iter) 00878 { 00879 GncTreeModelOwnerPrivate *priv; 00880 GList *owner_in_list; 00881 00882 ENTER("model %p, owner %p, iter %p", model, owner, iter); 00883 gnc_leave_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), FALSE); 00884 gnc_leave_return_val_if_fail ((owner != NULL), FALSE); 00885 gnc_leave_return_val_if_fail ((iter != NULL), FALSE); 00886 00887 00888 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 00889 owner_in_list = g_list_find_custom (priv->owner_list, (gconstpointer)owner, (GCompareFunc)gncOwnerGCompareFunc); 00890 if (owner_in_list) 00891 { 00892 iter->stamp = model->stamp; 00893 iter->user_data = owner_in_list->data; 00894 iter->user_data2 = GINT_TO_POINTER (g_list_position (priv->owner_list, owner_in_list)); 00895 iter->user_data3 = NULL; 00896 LEAVE("iter %s", iter_to_string (iter)); 00897 return TRUE; 00898 } 00899 else 00900 { 00901 iter->stamp = 0; 00902 iter->user_data = NULL; 00903 LEAVE("Owner not found in list"); 00904 return FALSE; 00905 } 00906 } 00907 00908 /* 00909 * Convert a model/owner pair into a gtk_tree_model_path. This 00910 * routine should only be called from the file 00911 * gnc-tree-view-owner.c. 00912 */ 00913 GtkTreePath * 00914 gnc_tree_model_owner_get_path_from_owner (GncTreeModelOwner *model, 00915 GncOwner *owner) 00916 { 00917 GtkTreeIter tree_iter; 00918 GtkTreePath *tree_path; 00919 00920 ENTER("model %p, owner %p", model, owner); 00921 gnc_leave_return_val_if_fail (GNC_IS_TREE_MODEL_OWNER (model), NULL); 00922 gnc_leave_return_val_if_fail (owner != NULL, NULL); 00923 00924 if (!gnc_tree_model_owner_get_iter_from_owner (model, owner, 00925 &tree_iter)) 00926 { 00927 LEAVE("no iter"); 00928 return NULL; 00929 } 00930 00931 tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &tree_iter); 00932 if (tree_path) 00933 { 00934 gchar *path_string = gtk_tree_path_to_string(tree_path); 00935 LEAVE("path (2) %s", path_string); 00936 g_free(path_string); 00937 } 00938 else 00939 { 00940 LEAVE("no path"); 00941 } 00942 return tree_path; 00943 } 00944 00945 /************************************************************/ 00946 /* Owner Tree Model - Engine Event Handling Functions */ 00947 /************************************************************/ 00948 00949 static void 00950 increment_stamp(GncTreeModelOwner *model) 00951 { 00952 do model->stamp++; 00953 while (!model->stamp); 00954 } 00955 00984 static void 00985 gnc_tree_model_owner_event_handler (QofInstance *entity, 00986 QofEventId event_type, 00987 GncTreeModelOwner *model, 00988 GncEventData *ed) 00989 { 00990 GncTreeModelOwnerPrivate *priv; 00991 GtkTreePath *path = NULL; 00992 GtkTreeIter iter; 00993 GncOwner owner; 00994 00995 g_return_if_fail(model); /* Required */ 00996 00997 if (!GNC_IS_OWNER(entity)) 00998 return; 00999 01000 ENTER("entity %p of type %d, model %p, event_data %p", 01001 entity, event_type, model, ed); 01002 priv = GNC_TREE_MODEL_OWNER_GET_PRIVATE(model); 01003 01004 qofOwnerSetEntity (&owner, entity); 01005 if (gncOwnerGetType(&owner) != priv->owner_type) 01006 { 01007 LEAVE("model type and owner type differ"); 01008 return; 01009 } 01010 01011 if (qof_instance_get_book (entity) != priv->book) 01012 { 01013 LEAVE("not in this book"); 01014 return; 01015 } 01016 01017 /* What to do, that to do. */ 01018 switch (event_type) 01019 { 01020 case QOF_EVENT_ADD: 01021 /* Tell the filters/views where the new owner was added. */ 01022 DEBUG("add owner %p (%s)", &owner, gncOwnerGetName(&owner)); 01023 /* First update our copy of the owner list. This isn't done automatically */ 01024 priv->owner_list = gncBusinessGetOwnerList (priv->book, 01025 gncOwnerTypeToQofIdType(priv->owner_type), TRUE); 01026 increment_stamp(model); 01027 if (!gnc_tree_model_owner_get_iter_from_owner (model, &owner, &iter)) 01028 { 01029 LEAVE("can't generate iter"); 01030 break; 01031 } 01032 path = gnc_tree_model_owner_get_path(GTK_TREE_MODEL(model), &iter); 01033 if (!path) 01034 { 01035 DEBUG("can't generate path"); 01036 break; 01037 } 01038 gtk_tree_model_row_inserted (GTK_TREE_MODEL(model), path, &iter); 01039 break; 01040 01041 case QOF_EVENT_REMOVE: 01042 if (!ed) /* Required for a remove. */ 01043 break; 01044 DEBUG("remove owner %d (%s) from owner_list %p", ed->idx, 01045 gncOwnerGetName(&owner), priv->owner_list); 01046 path = gtk_tree_path_new(); 01047 if (!path) 01048 { 01049 DEBUG("can't generate path"); 01050 break; 01051 } 01052 increment_stamp(model); 01053 gtk_tree_path_append_index (path, ed->idx); 01054 gtk_tree_model_row_deleted (GTK_TREE_MODEL(model), path); 01055 break; 01056 01057 case QOF_EVENT_MODIFY: 01058 DEBUG("modify owner %p (%s)", &owner, gncOwnerGetName(&owner)); 01059 if (!gnc_tree_model_owner_get_iter_from_owner (model, &owner, &iter)) 01060 { 01061 LEAVE("can't generate iter"); 01062 return; 01063 } 01064 path = gnc_tree_model_owner_get_path(GTK_TREE_MODEL(model), &iter); 01065 if (!path) 01066 { 01067 DEBUG("can't generate path"); 01068 break; 01069 } 01070 gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter); 01071 break; 01072 01073 default: 01074 LEAVE("unknown event type"); 01075 return; 01076 } 01077 01078 if (path) 01079 gtk_tree_path_free(path); 01080 LEAVE(" "); 01081 return; 01082 }
1.7.4