GnuCash 2.4.99
SX-book.c
00001 /********************************************************************\
00002  * SX-book.c -- scheduled transaction dataset access                *
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  * FILE:
00024  * SX-book.c
00025  *
00026  * FUNCTION:
00027  * Anchor Scheduled Transaction Info into the book.
00028  * See src/doc/books.txt for design overview.
00029  *
00030  * HISTORY:
00031  * Copyright (c) 2003 Linas Vepstas <linas@linas.org>
00032  */
00033 
00034 #include "config.h"
00035 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #include <glib.h>
00040 
00041 #include "gnc-engine.h"
00042 #include "Account.h"
00043 #include "Split.h"
00044 #include "SchedXaction.h"
00045 #include "SX-book.h"
00046 #include "SX-book-p.h"
00047 #include "gnc-event.h"
00048 
00049 #undef G_LOG_DOMAIN
00050 #define G_LOG_DOMAIN "gnc.engine.sx"
00051 
00052 /* XXX this whole file is crufty, it doesn't really use entities
00053  * in the most efficient/best way */
00054 
00055 /* ====================================================================== */
00056 
00057 static Account *
00058 gnc_collection_get_template_root( const QofCollection *col )
00059 {
00060     return qof_collection_get_data (col);
00061 }
00062 
00063 Account *
00064 gnc_book_get_template_root( const QofBook *book )
00065 {
00066     QofCollection *col;
00067     if (!book) return NULL;
00068     col = qof_book_get_collection (book, GNC_ID_SXTG);
00069     return gnc_collection_get_template_root (col);
00070 }
00071 
00072 static void
00073 gnc_collection_set_template_root (QofCollection *col,
00074                                   Account *templateRoot)
00075 {
00076     Account *old_root;
00077     if (!col) return;
00078 
00079     old_root = gnc_collection_get_template_root (col);
00080     if (old_root == templateRoot) return;
00081 
00082     qof_collection_set_data (col, templateRoot);
00083 
00084     if (old_root)
00085     {
00086         xaccAccountBeginEdit (old_root);
00087         xaccAccountDestroy (old_root);
00088     }
00089 }
00090 
00091 
00092 void
00093 gnc_book_set_template_root (QofBook *book, Account *templateRoot)
00094 {
00095     QofCollection *col;
00096     if (!book) return;
00097 
00098     if (templateRoot && gnc_account_get_book(templateRoot) != book)
00099     {
00100         g_critical("cannot mix and match books freely!");
00101         return;
00102     }
00103 
00104     col = qof_book_get_collection (book, GNC_ID_SXTG);
00105     gnc_collection_set_template_root (col, templateRoot);
00106 }
00107 
00108 
00109 /* ====================================================================== */
00110 /* gncObject function implementation and registration */
00111 
00112 static void
00113 sxtg_book_begin (QofBook *book)
00114 {
00115     Account *root;
00116 
00117     root = xaccMallocAccount(book);
00118     xaccAccountBeginEdit(root);
00119     xaccAccountSetType(root, ACCT_TYPE_ROOT);
00120     xaccAccountSetName(root, "Template Root");
00121     xaccAccountCommitEdit(root);
00122     gnc_book_set_template_root (book, root);
00123 }
00124 
00125 static void
00126 sxtg_book_end (QofBook *book)
00127 {
00128 //    gnc_book_set_template_root (book, NULL);
00129 }
00130 
00131 static gboolean
00132 sxtg_is_dirty(const QofCollection *col)
00133 {
00134     Account *root;
00135     GList *descendants, *node;
00136     gboolean dirty = FALSE;
00137 
00138     root = gnc_collection_get_template_root(col);
00139     descendants = gnc_account_get_descendants(root);
00140     for (node = descendants; node; node = g_list_next(node))
00141     {
00142         if (qof_instance_is_dirty(node->data))
00143         {
00144             dirty = TRUE;
00145             break;
00146         }
00147     }
00148     g_list_free(descendants);
00149 
00150     return dirty;
00151 }
00152 
00153 static void
00154 sxtg_mark_clean(QofCollection *col)
00155 {
00156     Account *root;
00157     GList *descendants;
00158 
00159     root = gnc_collection_get_template_root(col);
00160     qof_collection_mark_clean(col);
00161 
00162     descendants = gnc_account_get_descendants(root);
00163     g_list_foreach(descendants, (GFunc)qof_instance_mark_clean, NULL);
00164     g_list_free(descendants);
00165 }
00166 
00167 #ifdef _MSC_VER
00168 /* MSVC compiler doesn't have C99 "designated initializers"
00169  * so we wrap them in a macro that is empty on MSVC. */
00170 # define DI(x) /* */
00171 #else
00172 # define DI(x) x
00173 #endif
00174 static QofObject sxtg_object_def =
00175 {
00176     DI(.interface_version = ) QOF_OBJECT_VERSION,
00177     DI(.e_type            = ) GNC_ID_SXTG,
00178     DI(.type_label        = ) "Scheduled Transaction Templates",
00179     DI(.create            = ) NULL,
00180     DI(.book_begin        = ) sxtg_book_begin,
00181     DI(.book_end          = ) sxtg_book_end,
00182     DI(.is_dirty          = ) sxtg_is_dirty,
00183     DI(.mark_clean        = ) sxtg_mark_clean,
00184     DI(.foreach           = ) NULL,
00185     DI(.printable         = ) NULL,
00186 };
00187 
00188 /* ====================================================================== */
00189 
00190 SchedXactions*
00191 gnc_collection_get_schedxactions(const QofCollection *col)
00192 {
00193     SchedXactions *rtn = qof_collection_get_data(col);
00194     // @@assert(rtn != null);
00195     return rtn;
00196 }
00197 
00198 SchedXactions*
00199 gnc_book_get_schedxactions(QofBook *book)
00200 {
00201     QofCollection *col;
00202     col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
00203     return gnc_collection_get_schedxactions(col);
00204 }
00205 
00206 void
00207 gnc_sxes_add_sx(SchedXactions *sxes, SchedXaction *sx)
00208 {
00209     if (g_list_find(sxes->sx_list, sx) != NULL)
00210         return;
00211     sxes->sx_list = g_list_append(sxes->sx_list, sx);
00212     qof_event_gen(&sxes->inst, GNC_EVENT_ITEM_ADDED, (gpointer)sx);
00213 }
00214 
00215 void
00216 gnc_sxes_del_sx(SchedXactions *sxes, SchedXaction *sx)
00217 {
00218     GList *to_remove;
00219     to_remove = g_list_find(sxes->sx_list, sx);
00220     if (to_remove == NULL)
00221         return;
00222     sxes->sx_list = g_list_delete_link(sxes->sx_list, to_remove);
00223     qof_event_gen(&sxes->inst, GNC_EVENT_ITEM_REMOVED, (gpointer)sx);
00224 }
00225 
00226 /* ====================================================================== */
00227 /* SX-trans stuff */
00228 
00229 /* GObject initialization */
00230 QOF_GOBJECT_IMPL(gnc_schedxactions, SchedXactions, QOF_TYPE_INSTANCE);
00231 
00232 static void
00233 gnc_schedxactions_init(SchedXactions* sxs)
00234 {
00235 }
00236 
00237 static void
00238 gnc_schedxactions_dispose_real (GObject *sxsp)
00239 {
00240 }
00241 
00242 static void
00243 gnc_schedxactions_finalize_real(GObject* sxsp)
00244 {
00245 }
00246 
00247 static void
00248 mark_sx_clean(gpointer data, gpointer user_data)
00249 {
00250     SchedXaction *sx = (SchedXaction *) data;
00251     qof_instance_mark_clean (QOF_INSTANCE(sx));
00252 }
00253 
00254 static void
00255 book_sxes_setup(QofBook *book)
00256 {
00257     QofCollection *col;
00258     SchedXactions *sxes;
00259 
00260     col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
00261     sxes = g_object_new (GNC_TYPE_SCHEDXACTIONS, NULL);
00262     g_assert(sxes);
00263     qof_instance_init_data(&sxes->inst, GNC_ID_SXES, book);
00264     sxes->sx_list = NULL;
00265     sxes->sx_notsaved = TRUE;
00266     qof_collection_set_data(col, sxes);
00267 }
00268 
00269 static void
00270 book_sxes_end(QofBook* book)
00271 {
00272     QofCollection *col;
00273     SchedXactions *sxes;
00274 
00275     col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
00276     sxes = qof_collection_get_data(col);
00277     if (sxes != NULL)
00278     {
00279         g_object_unref(sxes);
00280         qof_collection_set_data(col, NULL);
00281     }
00282 }
00283 
00284 static void
00285 book_sxns_mark_saved(QofCollection *col)
00286 {
00287     SchedXactions *sxl;
00288     sxl = gnc_collection_get_schedxactions(col);
00289     if (!sxl)
00290         return;
00291     sxl->sx_notsaved = FALSE;
00292     g_list_foreach(sxl->sx_list,
00293                    mark_sx_clean,
00294                    NULL);
00295 }
00296 
00297 static gboolean
00298 book_sxlist_notsaved(const QofCollection *col)
00299 {
00300     GList *sxlist;
00301     SchedXactions *sxl;
00302 
00303     sxl = gnc_collection_get_schedxactions(col);
00304     if (!sxl) return FALSE;
00305     if (sxl->sx_notsaved) return TRUE;
00306 
00307     for (sxlist = sxl->sx_list;
00308             sxlist != NULL;
00309             sxlist = g_list_next(sxlist))
00310     {
00311         SchedXaction *sx;
00312         sx = (SchedXaction *) (sxlist->data);
00313         if (xaccSchedXactionIsDirty( sx ))
00314             return TRUE;
00315     }
00316 
00317     return FALSE;
00318 }
00319 
00320 static QofObject sxes_object_def =
00321 {
00322     DI(.interface_version = ) QOF_OBJECT_VERSION,
00323     DI(.e_type            = ) GNC_ID_SXES,
00324     DI(.type_label        = ) "Scheduled Transactions List",
00325     DI(.create            = ) NULL,
00326     DI(.book_begin        = ) book_sxes_setup,
00327     DI(.book_end          = ) book_sxes_end,
00328     DI(.is_dirty          = ) book_sxlist_notsaved,
00329     DI(.mark_clean        = ) book_sxns_mark_saved,
00330     DI(.foreach           = ) NULL,
00331     DI(.printable         = ) NULL,
00332     DI(.version_cmp       = ) NULL
00333 };
00334 
00335 static QofObject sxtt_object_def =
00336 {
00337     DI(.interface_version = ) QOF_OBJECT_VERSION,
00338     DI(.e_type            = ) GNC_ID_SXTT,
00339     DI(.type_label        = ) "Scheduled Transaction Templates",
00340     DI(.create            = ) NULL,
00341     DI(.book_begin        = ) NULL,
00342     DI(.book_end          = ) NULL,
00343     DI(.is_dirty          = ) NULL,
00344     DI(.mark_clean        = ) NULL,
00345     DI(.foreach           = ) NULL,
00346     DI(.printable         = ) NULL,
00347     DI(.version_cmp       = ) NULL,
00348 };
00349 
00350 gboolean
00351 gnc_sxtt_register (void)
00352 {
00353     if (!qof_object_register(&sxes_object_def))
00354         return FALSE;
00355     if (!qof_object_register(&sxtg_object_def))
00356         return FALSE;
00357     return qof_object_register(&sxtt_object_def);
00358 }
00359 
00360 GList*
00361 gnc_sx_get_sxes_referencing_account(QofBook *book, Account *acct)
00362 {
00363     GList *rtn = NULL;
00364     const GncGUID *acct_guid = qof_entity_get_guid(QOF_INSTANCE(acct));
00365     GList *sx_list;
00366     SchedXactions *sxactions = gnc_book_get_schedxactions(book);
00367     g_return_val_if_fail( sxactions != NULL, rtn);
00368     for (sx_list = sxactions->sx_list; sx_list != NULL; sx_list = sx_list->next)
00369     {
00370         SchedXaction *sx = (SchedXaction*)sx_list->data;
00371         GList *splits = xaccSchedXactionGetSplits(sx);
00372         for (; splits != NULL; splits = splits->next)
00373         {
00374             Split *s = (Split*)splits->data;
00375             KvpFrame *frame = kvp_frame_get_frame(xaccSplitGetSlots(s), GNC_SX_ID);
00376             GncGUID *sx_split_acct_guid = kvp_frame_get_guid(frame, GNC_SX_ACCOUNT);
00377             if (guid_equal(acct_guid, sx_split_acct_guid))
00378             {
00379                 rtn = g_list_append(rtn, sx);
00380             }
00381         }
00382     }
00383     return rtn;
00384 }
00385 
00386 /* ========================== END OF FILE =============================== */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines