qofinstance.c

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

Generated on Mon Sep 8 05:04:20 2008 for GnuCash by  doxygen 1.5.2