|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * qofinstance.c -- handler for fields common to all objects * 00003 * * 00004 * This program is free software; you can redistribute it and/or * 00005 * modify it under the terms of the GNU General Public License as * 00006 * published by the Free Software Foundation; either version 2 of * 00007 * the License, or (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License* 00015 * along with this program; if not, contact: * 00016 * * 00017 * Free Software Foundation Voice: +1-617-542-5942 * 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00019 * Boston, MA 02110-1301, USA gnu@gnu.org * 00020 * * 00021 \********************************************************************/ 00022 00023 /* 00024 * Object instance holds many common fields that most 00025 * gnucash objects use. 00026 * 00027 * Copyright (C) 2003 Linas Vepstas <linas@linas.org> 00028 * Copyright (c) 2007 David Hampton <hampton@employees.org> 00029 */ 00030 00031 #include "config.h" 00032 #include <glib.h> 00033 #include "qof.h" 00034 #include "kvp-util-p.h" 00035 #include "qofbook-p.h" 00036 #include "qofid-p.h" 00037 #include "qofinstance-p.h" 00038 00039 static QofLogModule log_module = QOF_MOD_ENGINE; 00040 00041 /* ========================================================== */ 00042 00043 enum 00044 { 00045 LAST_SIGNAL 00046 }; 00047 00048 enum 00049 { 00050 PROP_0, 00051 PROP_TYPE, 00052 PROP_GUID, 00053 PROP_COLLECTION, 00054 PROP_BOOK, 00055 PROP_KVP_DATA, 00056 PROP_LAST_UPDATE, 00057 PROP_EDITLEVEL, 00058 PROP_DESTROYING, 00059 PROP_DIRTY, 00060 PROP_INFANT, 00061 00062 PROP_VERSION, 00063 PROP_VERSION_CHECK, 00064 PROP_IDATA, 00065 }; 00066 00067 typedef struct QofInstancePrivate 00068 { 00069 // QofIdType e_type; /**< Entity type */ 00070 GncGUID guid; 00071 QofCollection *collection; 00073 /* The entity_table in which this instance is stored */ 00074 QofBook * book; 00075 00076 /* kvp_data is a key-value pair database for storing arbirtary 00077 * information associated with this instance. 00078 * See src/engine/kvp_doc.txt for a list and description of the 00079 * important keys. */ 00080 // KvpFrame *kvp_data; 00081 00082 /* Timestamp used to track the last modification to this 00083 * instance. Typically used to compare two versions of the 00084 * same object, to see which is newer. When used with the 00085 * SQL backend, this field is reserved for SQL use, to compare 00086 * the version in local memory to the remote, server version. 00087 */ 00088 Timespec last_update; 00089 00090 /* Keep track of nesting level of begin/end edit calls */ 00091 int editlevel; 00092 00093 /* In process of being destroyed */ 00094 gboolean do_free; 00095 00096 /* dirty/clean flag. If dirty, then this instance has been modified, 00097 * but has not yet been written out to storage (file/database) 00098 */ 00099 gboolean dirty; 00100 00101 /* True iff this instance has never been committed. */ 00102 gboolean infant; 00103 00104 /* version number, used for tracking multiuser updates */ 00105 gint32 version; 00106 guint32 version_check; /* data aging timestamp */ 00107 00108 /* -------------------------------------------------------------- */ 00109 /* Backend private expansion data */ 00110 guint32 idata; /* used by the sql backend for kvp management */ 00111 } QofInstancePrivate; 00112 00113 #define GET_PRIVATE(o) \ 00114 (G_TYPE_INSTANCE_GET_PRIVATE ((o), QOF_TYPE_INSTANCE, QofInstancePrivate)) 00115 00116 QOF_GOBJECT_GET_TYPE(QofInstance, qof_instance, G_TYPE_OBJECT, {}); 00117 QOF_GOBJECT_FINALIZE(qof_instance); 00118 00119 static void qof_instance_get_property (GObject *object, 00120 guint prop_id, 00121 GValue *value, 00122 GParamSpec *pspec); 00123 static void qof_instance_set_property (GObject *object, 00124 guint prop_id, 00125 const GValue *value, 00126 GParamSpec *pspec); 00127 static void qof_instance_dispose(GObject*); 00128 static void qof_instance_class_init(QofInstanceClass *klass) 00129 { 00130 GObjectClass *object_class = G_OBJECT_CLASS(klass); 00131 object_class->finalize = qof_instance_finalize; 00132 object_class->dispose = qof_instance_dispose; 00133 object_class->set_property = qof_instance_set_property; 00134 object_class->get_property = qof_instance_get_property; 00135 00136 g_type_class_add_private(klass, sizeof(QofInstancePrivate)); 00137 00138 klass->get_display_name = NULL; 00139 klass->refers_to_object = NULL; 00140 klass->get_typed_referring_object_list = NULL; 00141 00142 g_object_class_install_property 00143 (object_class, 00144 PROP_GUID, 00145 g_param_spec_boxed ("guid", 00146 "Object GncGUID", 00147 "The object Globally Unique ID.", 00148 GNC_TYPE_GUID, 00149 G_PARAM_READWRITE)); 00150 00151 g_object_class_install_property 00152 (object_class, 00153 PROP_COLLECTION, 00154 g_param_spec_pointer ("collection", 00155 "Object Collection", 00156 "A collection of like objects of which this " 00157 "particular object is amember. E.g.. A " 00158 "collection of accounts, or a collection of " 00159 "splits.", 00160 G_PARAM_READWRITE)); 00161 00162 g_object_class_install_property 00163 (object_class, 00164 PROP_BOOK, 00165 g_param_spec_object ("book", 00166 "Object Book", 00167 "The book that contains this object.", 00168 QOF_TYPE_BOOK, 00169 G_PARAM_READWRITE)); 00170 00171 g_object_class_install_property 00172 (object_class, 00173 PROP_KVP_DATA, 00174 g_param_spec_pointer ("kvp-data", 00175 "Object KVP Data", 00176 "A pointer to the key-value data associated " 00177 "with this object.", 00178 G_PARAM_READWRITE)); 00179 00180 g_object_class_install_property 00181 (object_class, 00182 PROP_LAST_UPDATE, 00183 g_param_spec_pointer ("last-update", 00184 "Object Last Update", 00185 "A pointer to the last time this object was " 00186 "updated. This value is present for use by " 00187 "backends and shouldnot be written by other " 00188 "code.", 00189 G_PARAM_READWRITE)); 00190 00191 g_object_class_install_property 00192 (object_class, 00193 PROP_EDITLEVEL, 00194 g_param_spec_int ("editlevel", 00195 "Object Edit Level", 00196 "The object edit level.", 00197 0, G_MAXINT32, 0, 00198 G_PARAM_READABLE)); 00199 00200 g_object_class_install_property 00201 (object_class, 00202 PROP_DESTROYING, 00203 g_param_spec_boolean ("destroying", 00204 "Object Destroying", 00205 "This flag is set to TRUE if the object is " 00206 "about to be destroyed.", 00207 FALSE, 00208 G_PARAM_READWRITE)); 00209 00210 g_object_class_install_property 00211 (object_class, 00212 PROP_DIRTY, 00213 g_param_spec_boolean ("dirty", 00214 "Object Dirty", 00215 "This flag is set to TRUE if the object has " 00216 "unsaved changes.", 00217 FALSE, 00218 G_PARAM_READWRITE)); 00219 00220 g_object_class_install_property 00221 (object_class, 00222 PROP_INFANT, 00223 g_param_spec_boolean ("infant", 00224 "Object Infant", 00225 "This flag is set to TRUE if the object has " 00226 "never been added to a book. This implies " 00227 "that its destruction does not affect the " 00228 "state of the book, and therefore the saved " 00229 "state of the data file.", 00230 FALSE, 00231 G_PARAM_READABLE)); 00232 00233 g_object_class_install_property 00234 (object_class, 00235 PROP_VERSION, 00236 g_param_spec_int ("version", 00237 "Version", 00238 "The version number of the current instance state.", 00239 0, 00240 G_MAXINT32, 00241 0, 00242 G_PARAM_READWRITE)); 00243 00244 g_object_class_install_property 00245 (object_class, 00246 PROP_VERSION_CHECK, 00247 g_param_spec_uint ("version-check", 00248 "Version Check", 00249 "The version check number of the current instance state.", 00250 0, 00251 G_MAXUINT32, 00252 0, 00253 G_PARAM_READWRITE)); 00254 00255 g_object_class_install_property 00256 (object_class, 00257 PROP_EDITLEVEL, 00258 g_param_spec_uint ("idata", 00259 "Object IData", 00260 "Per instance backend private data.", 00261 0, G_MAXUINT32, 0, 00262 G_PARAM_READWRITE)); 00263 } 00264 00265 static void 00266 qof_instance_init (QofInstance *inst) 00267 { 00268 QofInstancePrivate *priv; 00269 00270 priv = GET_PRIVATE(inst); 00271 priv->book = NULL; 00272 inst->kvp_data = kvp_frame_new(); 00273 priv->last_update.tv_sec = 0; 00274 priv->last_update.tv_nsec = -1; 00275 priv->editlevel = 0; 00276 priv->do_free = FALSE; 00277 priv->dirty = FALSE; 00278 priv->infant = TRUE; 00279 } 00280 00281 void 00282 qof_instance_init_data (QofInstance *inst, QofIdType type, QofBook *book) 00283 { 00284 QofInstancePrivate *priv; 00285 QofCollection *col; 00286 QofIdType col_type; 00287 00288 g_return_if_fail(QOF_IS_INSTANCE(inst)); 00289 priv = GET_PRIVATE(inst); 00290 g_return_if_fail(!priv->book); 00291 00292 priv->book = book; 00293 col = qof_book_get_collection (book, type); 00294 g_return_if_fail(col != NULL); 00295 00296 /* XXX We passed redundant info to this routine ... but I think that's 00297 * OK, it might eliminate programming errors. */ 00298 00299 col_type = qof_collection_get_type(col); 00300 if (safe_strcmp(col_type, type)) 00301 { 00302 PERR ("attempt to insert \"%s\" into \"%s\"", type, col_type); 00303 return; 00304 } 00305 priv = GET_PRIVATE(inst); 00306 inst->e_type = CACHE_INSERT (type); 00307 00308 do 00309 { 00310 guid_new(&priv->guid); 00311 00312 if (NULL == qof_collection_lookup_entity (col, &priv->guid)) 00313 break; 00314 00315 PWARN("duplicate id created, trying again"); 00316 } 00317 while (1); 00318 00319 priv->collection = col; 00320 00321 qof_collection_insert_entity (col, inst); 00322 } 00323 00324 static void 00325 qof_instance_dispose (GObject *instp) 00326 { 00327 QofInstancePrivate *priv; 00328 QofInstance* inst = QOF_INSTANCE(instp); 00329 00330 priv = GET_PRIVATE(instp); 00331 if (!priv->collection) 00332 return; 00333 qof_collection_remove_entity(inst); 00334 00335 CACHE_REMOVE(inst->e_type); 00336 inst->e_type = NULL; 00337 00338 G_OBJECT_CLASS(qof_instance_parent_class)->dispose(instp); 00339 } 00340 00341 static void 00342 qof_instance_finalize_real (GObject *instp) 00343 { 00344 QofInstancePrivate *priv; 00345 QofInstance* inst = QOF_INSTANCE(instp); 00346 00347 kvp_frame_delete (inst->kvp_data); 00348 inst->kvp_data = NULL; 00349 00350 priv = GET_PRIVATE(inst); 00351 priv->editlevel = 0; 00352 priv->do_free = FALSE; 00353 priv->dirty = FALSE; 00354 } 00355 00356 static void 00357 qof_instance_get_property (GObject *object, 00358 guint prop_id, 00359 GValue *value, 00360 GParamSpec *pspec) 00361 { 00362 QofInstance *inst; 00363 QofInstancePrivate *priv; 00364 00365 g_return_if_fail(QOF_IS_INSTANCE(object)); 00366 00367 inst = QOF_INSTANCE(object); 00368 priv = GET_PRIVATE(inst); 00369 00370 switch (prop_id) 00371 { 00372 case PROP_GUID: 00373 g_value_set_boxed(value, &priv->guid); 00374 break; 00375 case PROP_COLLECTION: 00376 g_value_set_pointer(value, priv->collection); 00377 break; 00378 case PROP_BOOK: 00379 g_value_set_object(value, priv->book); 00380 break; 00381 case PROP_KVP_DATA: 00382 g_value_set_pointer(value, inst->kvp_data); 00383 break; 00384 case PROP_LAST_UPDATE: 00385 g_value_set_pointer(value, &priv->last_update); 00386 break; 00387 case PROP_EDITLEVEL: 00388 g_value_set_int(value, priv->editlevel); 00389 break; 00390 case PROP_DESTROYING: 00391 g_value_set_boolean(value, priv->do_free); 00392 break; 00393 case PROP_DIRTY: 00394 g_value_set_boolean(value, qof_instance_get_dirty(inst)); 00395 break; 00396 case PROP_INFANT: 00397 g_value_set_boolean(value, priv->infant); 00398 break; 00399 case PROP_VERSION: 00400 g_value_set_int(value, priv->version); 00401 break; 00402 case PROP_VERSION_CHECK: 00403 g_value_set_uint(value, priv->version_check); 00404 break; 00405 case PROP_IDATA: 00406 g_value_set_uint(value, priv->idata); 00407 break; 00408 default: 00409 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 00410 break; 00411 } 00412 } 00413 00414 static void 00415 qof_instance_set_property (GObject *object, 00416 guint prop_id, 00417 const GValue *value, 00418 GParamSpec *pspec) 00419 { 00420 QofInstance *inst; 00421 QofInstancePrivate *priv; 00422 Timespec *ts; 00423 00424 g_return_if_fail(QOF_IS_INSTANCE(object)); 00425 00426 inst = QOF_INSTANCE(object); 00427 priv = GET_PRIVATE(inst); 00428 00429 switch (prop_id) 00430 { 00431 case PROP_GUID: 00432 qof_instance_set_guid(inst, g_value_get_boxed(value)); 00433 break; 00434 case PROP_COLLECTION: 00435 qof_instance_set_collection(inst, g_value_get_pointer(value)); 00436 break; 00437 case PROP_BOOK: 00438 qof_instance_set_book(inst, g_value_get_object(value)); 00439 break; 00440 case PROP_KVP_DATA: 00441 qof_instance_set_slots(inst, g_value_get_pointer(value)); 00442 break; 00443 case PROP_LAST_UPDATE: 00444 ts = g_value_get_pointer(value); 00445 qof_instance_set_last_update(inst, *ts); 00446 break; 00447 case PROP_DESTROYING: 00448 qof_instance_set_destroying(inst, g_value_get_boolean(value)); 00449 break; 00450 case PROP_DIRTY: 00451 qof_instance_set_dirty(inst); 00452 break; 00453 case PROP_VERSION: 00454 qof_instance_set_version(inst, g_value_get_int(value)); 00455 break; 00456 case PROP_VERSION_CHECK: 00457 qof_instance_set_version_check(inst, g_value_get_uint(value)); 00458 break; 00459 case PROP_IDATA: 00460 qof_instance_set_idata(inst, g_value_get_uint(value)); 00461 break; 00462 default: 00463 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 00464 break; 00465 } 00466 } 00467 00468 const GncGUID * 00469 qof_instance_get_guid (gconstpointer inst) 00470 { 00471 QofInstancePrivate *priv; 00472 00473 if (!inst) return NULL; 00474 g_return_val_if_fail(QOF_IS_INSTANCE(inst), guid_null()); 00475 priv = GET_PRIVATE(inst); 00476 return &(priv->guid); 00477 } 00478 00479 const GncGUID * 00480 qof_entity_get_guid (gconstpointer ent) 00481 { 00482 return ent ? qof_instance_get_guid(ent) : guid_null(); 00483 } 00484 00485 void 00486 qof_instance_set_guid (gpointer ptr, const GncGUID *guid) 00487 { 00488 QofInstancePrivate *priv; 00489 QofInstance *inst; 00490 QofCollection *col; 00491 00492 g_return_if_fail(QOF_IS_INSTANCE(ptr)); 00493 00494 inst = QOF_INSTANCE(ptr); 00495 priv = GET_PRIVATE(inst); 00496 if (guid_equal (guid, &priv->guid)) 00497 return; 00498 00499 col = priv->collection; 00500 qof_collection_remove_entity(inst); 00501 priv->guid = *guid; 00502 qof_collection_insert_entity(col, inst); 00503 } 00504 00505 void 00506 qof_instance_copy_guid (gpointer to, gconstpointer from) 00507 { 00508 g_return_if_fail(QOF_IS_INSTANCE(to)); 00509 g_return_if_fail(QOF_IS_INSTANCE(from)); 00510 00511 GET_PRIVATE(to)->guid = GET_PRIVATE(from)->guid; 00512 } 00513 00514 gint 00515 qof_instance_guid_compare(gconstpointer ptr1, gconstpointer ptr2) 00516 { 00517 const QofInstancePrivate *priv1, *priv2; 00518 00519 g_return_val_if_fail(QOF_IS_INSTANCE(ptr1), -1); 00520 g_return_val_if_fail(QOF_IS_INSTANCE(ptr2), 1); 00521 00522 priv1 = GET_PRIVATE(ptr1); 00523 priv2 = GET_PRIVATE(ptr2); 00524 00525 return guid_compare(&priv1->guid, &priv2->guid); 00526 } 00527 00528 QofCollection * 00529 qof_instance_get_collection (gconstpointer ptr) 00530 { 00531 00532 g_return_val_if_fail(QOF_IS_INSTANCE(ptr), NULL); 00533 return GET_PRIVATE(ptr)->collection; 00534 } 00535 00536 void 00537 qof_instance_set_collection (gconstpointer ptr, QofCollection *col) 00538 { 00539 g_return_if_fail(QOF_IS_INSTANCE(ptr)); 00540 GET_PRIVATE(ptr)->collection = col; 00541 } 00542 00543 QofBook * 00544 qof_instance_get_book (gconstpointer inst) 00545 { 00546 if (!inst) return NULL; 00547 g_return_val_if_fail(QOF_IS_INSTANCE(inst), NULL); 00548 return GET_PRIVATE(inst)->book; 00549 } 00550 00551 void 00552 qof_instance_set_book (gconstpointer inst, QofBook *book) 00553 { 00554 g_return_if_fail(QOF_IS_INSTANCE(inst)); 00555 GET_PRIVATE(inst)->book = book; 00556 } 00557 00558 void 00559 qof_instance_copy_book (gpointer ptr1, gconstpointer ptr2) 00560 { 00561 g_return_if_fail(QOF_IS_INSTANCE(ptr1)); 00562 g_return_if_fail(QOF_IS_INSTANCE(ptr2)); 00563 00564 GET_PRIVATE(ptr1)->book = GET_PRIVATE(ptr2)->book; 00565 } 00566 00567 gboolean 00568 qof_instance_books_equal (gconstpointer ptr1, gconstpointer ptr2) 00569 { 00570 const QofInstancePrivate *priv1, *priv2; 00571 00572 g_return_val_if_fail(QOF_IS_INSTANCE(ptr1), FALSE); 00573 g_return_val_if_fail(QOF_IS_INSTANCE(ptr2), FALSE); 00574 00575 priv1 = GET_PRIVATE(ptr1); 00576 priv2 = GET_PRIVATE(ptr2); 00577 00578 return (priv1->book == priv2->book); 00579 } 00580 00581 KvpFrame* 00582 qof_instance_get_slots (const QofInstance *inst) 00583 { 00584 if (!inst) return NULL; 00585 return inst->kvp_data; 00586 } 00587 00588 void 00589 qof_instance_set_slots (QofInstance *inst, KvpFrame *frm) 00590 { 00591 QofInstancePrivate *priv; 00592 00593 if (!inst) return; 00594 00595 priv = GET_PRIVATE(inst); 00596 if (inst->kvp_data && (inst->kvp_data != frm)) 00597 { 00598 kvp_frame_delete(inst->kvp_data); 00599 } 00600 00601 priv->dirty = TRUE; 00602 inst->kvp_data = frm; 00603 } 00604 00605 void 00606 qof_instance_set_last_update (QofInstance *inst, Timespec ts) 00607 { 00608 if (!inst) return; 00609 GET_PRIVATE(inst)->last_update = ts; 00610 } 00611 00612 gint 00613 qof_instance_get_editlevel (gconstpointer ptr) 00614 { 00615 g_return_val_if_fail(QOF_IS_INSTANCE(ptr), 0); 00616 return GET_PRIVATE(ptr)->editlevel; 00617 } 00618 00619 void qof_instance_increase_editlevel (gpointer ptr) 00620 { 00621 g_return_if_fail(QOF_IS_INSTANCE(ptr)); 00622 GET_PRIVATE(ptr)->editlevel++; 00623 } 00624 00625 void qof_instance_decrease_editlevel (gpointer ptr) 00626 { 00627 g_return_if_fail(QOF_IS_INSTANCE(ptr)); 00628 GET_PRIVATE(ptr)->editlevel--; 00629 } 00630 00631 void qof_instance_reset_editlevel (gpointer ptr) 00632 { 00633 g_return_if_fail(QOF_IS_INSTANCE(ptr)); 00634 GET_PRIVATE(ptr)->editlevel = 0; 00635 } 00636 00637 int 00638 qof_instance_version_cmp (const QofInstance *left, const QofInstance *right) 00639 { 00640 QofInstancePrivate *lpriv, *rpriv; 00641 00642 if (!left && !right) return 0; 00643 if (!left) return -1; 00644 if (!right) return +1; 00645 00646 lpriv = GET_PRIVATE(left); 00647 rpriv = GET_PRIVATE(right); 00648 if (lpriv->last_update.tv_sec < rpriv->last_update.tv_sec) return -1; 00649 if (lpriv->last_update.tv_sec > rpriv->last_update.tv_sec) return +1; 00650 if (lpriv->last_update.tv_nsec < rpriv->last_update.tv_nsec) return -1; 00651 if (lpriv->last_update.tv_nsec > rpriv->last_update.tv_nsec) return +1; 00652 return 0; 00653 } 00654 00655 gboolean 00656 qof_instance_get_destroying (gconstpointer ptr) 00657 { 00658 g_return_val_if_fail(QOF_IS_INSTANCE(ptr), FALSE); 00659 return GET_PRIVATE(ptr)->do_free; 00660 } 00661 00662 void 00663 qof_instance_set_destroying (gpointer ptr, gboolean value) 00664 { 00665 g_return_if_fail(QOF_IS_INSTANCE(ptr)); 00666 GET_PRIVATE(ptr)->do_free = value; 00667 } 00668 00669 gboolean 00670 qof_instance_get_dirty_flag (gconstpointer ptr) 00671 { 00672 g_return_val_if_fail(QOF_IS_INSTANCE(ptr), FALSE); 00673 return GET_PRIVATE(ptr)->dirty; 00674 } 00675 00676 void 00677 qof_instance_set_dirty_flag (gconstpointer inst, gboolean flag) 00678 { 00679 g_return_if_fail(QOF_IS_INSTANCE(inst)); 00680 GET_PRIVATE(inst)->dirty = flag; 00681 } 00682 00683 void 00684 qof_instance_mark_clean (QofInstance *inst) 00685 { 00686 if (!inst) return; 00687 GET_PRIVATE(inst)->dirty = FALSE; 00688 } 00689 00690 void 00691 qof_instance_print_dirty (const QofInstance *inst, gpointer dummy) 00692 { 00693 QofInstancePrivate *priv; 00694 00695 priv = GET_PRIVATE(inst); 00696 if (priv->dirty) 00697 { 00698 printf("%s instance %s is dirty.\n", inst->e_type, 00699 guid_to_string(&priv->guid)); 00700 } 00701 } 00702 00703 gboolean 00704 qof_instance_get_dirty (QofInstance *inst) 00705 { 00706 QofInstancePrivate *priv; 00707 QofCollection *coll; 00708 00709 if (!inst) 00710 { 00711 return FALSE; 00712 } 00713 00714 priv = GET_PRIVATE(inst); 00715 if (qof_get_alt_dirty_mode()) 00716 return priv->dirty; 00717 coll = priv->collection; 00718 if (qof_collection_is_dirty(coll)) 00719 { 00720 return priv->dirty; 00721 } 00722 priv->dirty = FALSE; 00723 return FALSE; 00724 } 00725 00726 void 00727 qof_instance_set_dirty(QofInstance* inst) 00728 { 00729 QofInstancePrivate *priv; 00730 QofCollection *coll; 00731 00732 priv = GET_PRIVATE(inst); 00733 priv->dirty = TRUE; 00734 if (!qof_get_alt_dirty_mode()) 00735 { 00736 coll = priv->collection; 00737 qof_collection_mark_dirty(coll); 00738 } 00739 } 00740 00741 gboolean 00742 qof_instance_get_infant(const QofInstance *inst) 00743 { 00744 g_return_val_if_fail(QOF_IS_INSTANCE(inst), FALSE); 00745 return GET_PRIVATE(inst)->infant; 00746 } 00747 00748 gint32 00749 qof_instance_get_version (gconstpointer inst) 00750 { 00751 g_return_val_if_fail(QOF_IS_INSTANCE(inst), 0); 00752 return GET_PRIVATE(inst)->version; 00753 } 00754 00755 void 00756 qof_instance_set_version (gpointer inst, gint32 vers) 00757 { 00758 g_return_if_fail(QOF_IS_INSTANCE(inst)); 00759 GET_PRIVATE(inst)->version = vers; 00760 } 00761 00762 void 00763 qof_instance_copy_version (gpointer to, gconstpointer from) 00764 { 00765 g_return_if_fail(QOF_IS_INSTANCE(to)); 00766 g_return_if_fail(QOF_IS_INSTANCE(from)); 00767 GET_PRIVATE(to)->version = GET_PRIVATE(from)->version; 00768 } 00769 00770 guint32 00771 qof_instance_get_version_check (gconstpointer inst) 00772 { 00773 g_return_val_if_fail(QOF_IS_INSTANCE(inst), 0); 00774 return GET_PRIVATE(inst)->version_check; 00775 } 00776 00777 void 00778 qof_instance_set_version_check (gpointer inst, guint32 value) 00779 { 00780 g_return_if_fail(QOF_IS_INSTANCE(inst)); 00781 GET_PRIVATE(inst)->version_check = value; 00782 } 00783 00784 void 00785 qof_instance_copy_version_check (gpointer to, gconstpointer from) 00786 { 00787 g_return_if_fail(QOF_IS_INSTANCE(to)); 00788 g_return_if_fail(QOF_IS_INSTANCE(from)); 00789 GET_PRIVATE(to)->version_check = GET_PRIVATE(from)->version_check; 00790 } 00791 00792 guint32 qof_instance_get_idata (gconstpointer inst) 00793 { 00794 if (!inst) 00795 { 00796 return 0; 00797 } 00798 g_return_val_if_fail(QOF_IS_INSTANCE(inst), 0); 00799 return GET_PRIVATE(inst)->idata; 00800 } 00801 00802 void qof_instance_set_idata(gpointer inst, guint32 idata) 00803 { 00804 if (!inst) 00805 { 00806 return; 00807 } 00808 if (idata < 0) 00809 { 00810 return; 00811 } 00812 g_return_if_fail(QOF_IS_INSTANCE(inst)); 00813 GET_PRIVATE(inst)->idata = idata; 00814 } 00815 00816 /* ========================================================== */ 00817 00818 /* Returns a displayable name to represent this object */ 00819 gchar* qof_instance_get_display_name(const QofInstance* inst) 00820 { 00821 g_return_val_if_fail( inst != NULL, NULL ); 00822 00823 if ( QOF_INSTANCE_GET_CLASS(inst)->get_display_name != NULL ) 00824 { 00825 return QOF_INSTANCE_GET_CLASS(inst)->get_display_name(inst); 00826 } 00827 else 00828 { 00829 /* Not implemented - return default string */ 00830 return g_strdup_printf("Object %s %p", 00831 qof_collection_get_type(qof_instance_get_collection(inst)), 00832 inst); 00833 } 00834 } 00835 00836 typedef struct 00837 { 00838 const QofInstance* inst; 00839 GList* list; 00840 } GetReferringObjectHelperData; 00841 00842 static void 00843 get_referring_object_instance_helper(QofInstance* inst, gpointer user_data) 00844 { 00845 QofInstance** pInst = (QofInstance**)user_data; 00846 00847 if (*pInst == NULL) 00848 { 00849 *pInst = inst; 00850 } 00851 } 00852 00853 static void 00854 get_referring_object_helper(QofCollection* coll, gpointer user_data) 00855 { 00856 QofInstance* first_instance = NULL; 00857 GetReferringObjectHelperData* data = (GetReferringObjectHelperData*)user_data; 00858 00859 qof_collection_foreach(coll, get_referring_object_instance_helper, &first_instance); 00860 00861 if (first_instance != NULL) 00862 { 00863 GList* new_list = qof_instance_get_typed_referring_object_list(first_instance, data->inst); 00864 data->list = g_list_concat(data->list, new_list); 00865 } 00866 } 00867 00868 /* Returns a list of objects referring to this object */ 00869 GList* qof_instance_get_referring_object_list(const QofInstance* inst) 00870 { 00871 GetReferringObjectHelperData data; 00872 00873 g_return_val_if_fail( inst != NULL, NULL ); 00874 00875 /* scan all collections */ 00876 data.inst = inst; 00877 data.list = NULL; 00878 00879 qof_book_foreach_collection(qof_instance_get_book(inst), 00880 get_referring_object_helper, 00881 &data); 00882 return data.list; 00883 } 00884 00885 static void 00886 get_typed_referring_object_instance_helper(QofInstance* inst, gpointer user_data) 00887 { 00888 GetReferringObjectHelperData* data = (GetReferringObjectHelperData*)user_data; 00889 00890 if (qof_instance_refers_to_object(inst, data->inst)) 00891 { 00892 data->list = g_list_prepend(data->list, inst); 00893 } 00894 } 00895 00896 GList* 00897 qof_instance_get_referring_object_list_from_collection(const QofCollection* coll, const QofInstance* ref) 00898 { 00899 GetReferringObjectHelperData data; 00900 00901 g_return_val_if_fail( coll != NULL, NULL ); 00902 g_return_val_if_fail( ref != NULL, NULL ); 00903 00904 data.inst = ref; 00905 data.list = NULL; 00906 00907 qof_collection_foreach(coll, get_typed_referring_object_instance_helper, &data); 00908 return data.list; 00909 } 00910 00911 GList* 00912 qof_instance_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref) 00913 { 00914 g_return_val_if_fail( inst != NULL, NULL ); 00915 g_return_val_if_fail( ref != NULL, NULL ); 00916 00917 if ( QOF_INSTANCE_GET_CLASS(inst)->get_typed_referring_object_list != NULL ) 00918 { 00919 return QOF_INSTANCE_GET_CLASS(inst)->get_typed_referring_object_list(inst, ref); 00920 } 00921 else 00922 { 00923 /* Not implemented - by default, loop through all objects of this object's type and check 00924 them individually. */ 00925 QofCollection* coll; 00926 00927 coll = qof_instance_get_collection(inst); 00928 return qof_instance_get_referring_object_list_from_collection(coll, ref); 00929 } 00930 } 00931 00932 /* Check if this object refers to a specific object */ 00933 gboolean qof_instance_refers_to_object(const QofInstance* inst, const QofInstance* ref) 00934 { 00935 g_return_val_if_fail( inst != NULL, FALSE ); 00936 g_return_val_if_fail( ref != NULL, FALSE ); 00937 00938 if ( QOF_INSTANCE_GET_CLASS(inst)->refers_to_object != NULL ) 00939 { 00940 return QOF_INSTANCE_GET_CLASS(inst)->refers_to_object(inst, ref); 00941 } 00942 else 00943 { 00944 /* Not implemented - default = NO */ 00945 return FALSE; 00946 } 00947 } 00948 00949 /* =================================================================== */ 00950 /* Entity edit and commit utilities */ 00951 /* =================================================================== */ 00952 00953 gboolean 00954 qof_begin_edit (QofInstance *inst) 00955 { 00956 QofInstancePrivate *priv; 00957 QofBackend * be; 00958 00959 if (!inst) return FALSE; 00960 00961 priv = GET_PRIVATE(inst); 00962 priv->editlevel++; 00963 if (1 < priv->editlevel) return FALSE; 00964 if (0 >= priv->editlevel) 00965 priv->editlevel = 1; 00966 00967 be = qof_book_get_backend(priv->book); 00968 if (be && qof_backend_begin_exists(be)) 00969 qof_backend_run_begin(be, inst); 00970 else 00971 priv->dirty = TRUE; 00972 00973 return TRUE; 00974 } 00975 00976 gboolean qof_commit_edit (QofInstance *inst) 00977 { 00978 QofInstancePrivate *priv; 00979 00980 if (!inst) return FALSE; 00981 00982 priv = GET_PRIVATE(inst); 00983 priv->editlevel--; 00984 if (0 < priv->editlevel) return FALSE; 00985 00986 #if 0 00987 if ((0 == priv->editlevel) && priv->dirty) 00988 { 00989 QofBackend * be = qof_book_get_backend(priv->book); 00990 if (be && qof_backend_commit_exists(be)) 00991 { 00992 qof_backend_run_commit(be, inst); 00993 } 00994 } 00995 #endif 00996 if (0 > priv->editlevel) 00997 { 00998 PERR ("unbalanced call - resetting (was %d)", priv->editlevel); 00999 priv->editlevel = 0; 01000 } 01001 return TRUE; 01002 } 01003 01004 gboolean 01005 qof_commit_edit_part2(QofInstance *inst, 01006 void (*on_error)(QofInstance *, QofBackendError), 01007 void (*on_done)(QofInstance *), 01008 void (*on_free)(QofInstance *)) 01009 { 01010 QofInstancePrivate *priv; 01011 QofBackend * be; 01012 gboolean dirty; 01013 01014 priv = GET_PRIVATE(inst); 01015 dirty = priv->dirty; 01016 01017 /* See if there's a backend. If there is, invoke it. */ 01018 be = qof_book_get_backend(priv->book); 01019 if (be && qof_backend_commit_exists(be)) 01020 { 01021 QofBackendError errcode; 01022 01023 /* clear errors */ 01024 do 01025 { 01026 errcode = qof_backend_get_error(be); 01027 } 01028 while (ERR_BACKEND_NO_ERR != errcode); 01029 01030 qof_backend_run_commit(be, inst); 01031 errcode = qof_backend_get_error(be); 01032 if (ERR_BACKEND_NO_ERR != errcode) 01033 { 01034 /* XXX Should perform a rollback here */ 01035 priv->do_free = FALSE; 01036 01037 /* Push error back onto the stack */ 01038 qof_backend_set_error (be, errcode); 01039 if (on_error) 01040 on_error(inst, errcode); 01041 return FALSE; 01042 } 01043 /* XXX the backend commit code should clear dirty!! */ 01044 priv->dirty = FALSE; 01045 } 01046 // if (dirty && qof_get_alt_dirty_mode() && 01047 // !(priv->infant && priv->do_free)) { 01048 // qof_collection_mark_dirty(priv->collection); 01049 // qof_book_mark_dirty(priv->book); 01050 // } 01051 priv->infant = FALSE; 01052 01053 if (priv->do_free) 01054 { 01055 if (on_free) 01056 on_free(inst); 01057 return TRUE; 01058 } 01059 01060 if (on_done) 01061 on_done(inst); 01062 return TRUE; 01063 } 01064 01065 /* ========================== END OF FILE ======================= */ 01066
1.7.4