|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * gncTaxTable.c -- the Gnucash Tax Table interface * 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 * Copyright (C) 2002 Derek Atkins 00025 * Copyright (C) 2003 Linas Vepstas <linas@linas.org> 00026 * Author: Derek Atkins <warlord@MIT.EDU> 00027 */ 00028 00029 #include "config.h" 00030 00031 #include <glib.h> 00032 00033 #include "gncTaxTableP.h" 00034 00035 struct _gncTaxTable 00036 { 00037 QofInstance inst; 00038 char * name; 00039 GncTaxTableEntryList* entries; 00040 Timespec modtime; /* internal date of last modtime */ 00041 00042 /* See src/doc/business.txt for an explanation of the following */ 00043 /* Code that handles this is *identical* to that in gncBillTerm */ 00044 gint64 refcount; 00045 GncTaxTable * parent; /* if non-null, we are an immutable child */ 00046 GncTaxTable * child; /* if non-null, we have not changed */ 00047 gboolean invisible; 00048 GList * children; /* list of children for disconnection */ 00049 }; 00050 00051 struct _gncTaxTableClass 00052 { 00053 QofInstanceClass parent_class; 00054 }; 00055 00056 struct _gncTaxTableEntry 00057 { 00058 GncTaxTable * table; 00059 Account * account; 00060 GncAmountType type; 00061 gnc_numeric amount; 00062 }; 00063 00064 struct _book_info 00065 { 00066 GList * tables; /* visible tables */ 00067 }; 00068 00069 static QofLogModule log_module = GNC_MOD_BUSINESS; 00070 00071 /* =============================================================== */ 00072 /* You must edit the functions in this block in tandem. KEEP THEM IN 00073 SYNC! */ 00074 00075 #define GNC_RETURN_ENUM_AS_STRING(x,s) case (x): return (s); 00076 const char * 00077 gncAmountTypeToString (GncAmountType type) 00078 { 00079 switch (type) 00080 { 00081 GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_VALUE, "VALUE"); 00082 GNC_RETURN_ENUM_AS_STRING(GNC_AMT_TYPE_PERCENT, "PERCENT"); 00083 default: 00084 g_warning ("asked to translate unknown amount type %d.\n", type); 00085 break; 00086 } 00087 return(NULL); 00088 } 00089 00090 const char * 00091 gncTaxIncludedTypeToString (GncTaxIncluded type) 00092 { 00093 switch (type) 00094 { 00095 GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_YES, "YES"); 00096 GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_NO, "NO"); 00097 GNC_RETURN_ENUM_AS_STRING(GNC_TAXINCLUDED_USEGLOBAL, "USEGLOBAL"); 00098 default: 00099 g_warning ("asked to translate unknown taxincluded type %d.\n", type); 00100 break; 00101 } 00102 return(NULL); 00103 } 00104 #undef GNC_RETURN_ENUM_AS_STRING 00105 #define GNC_RETURN_ON_MATCH(s,x) \ 00106 if(safe_strcmp((s), (str)) == 0) { *type = x; return(TRUE); } 00107 gboolean 00108 gncAmountStringToType (const char *str, GncAmountType *type) 00109 { 00110 GNC_RETURN_ON_MATCH ("VALUE", GNC_AMT_TYPE_VALUE); 00111 GNC_RETURN_ON_MATCH ("PERCENT", GNC_AMT_TYPE_PERCENT); 00112 g_warning ("asked to translate unknown amount type string %s.\n", 00113 str ? str : "(null)"); 00114 00115 return(FALSE); 00116 } 00117 00118 gboolean 00119 gncTaxIncludedStringToType (const char *str, GncTaxIncluded *type) 00120 { 00121 GNC_RETURN_ON_MATCH ("YES", GNC_TAXINCLUDED_YES); 00122 GNC_RETURN_ON_MATCH ("NO", GNC_TAXINCLUDED_NO); 00123 GNC_RETURN_ON_MATCH ("USEGLOBAL", GNC_TAXINCLUDED_USEGLOBAL); 00124 g_warning ("asked to translate unknown taxincluded type string %s.\n", 00125 str ? str : "(null)"); 00126 00127 return(FALSE); 00128 } 00129 #undef GNC_RETURN_ON_MATCH 00130 00131 /* =============================================================== */ 00132 /* Misc inline functions */ 00133 00134 #define _GNC_MOD_NAME GNC_ID_TAXTABLE 00135 00136 #define SET_STR(obj, member, str) { \ 00137 char * tmp; \ 00138 \ 00139 if (!safe_strcmp (member, str)) return; \ 00140 gncTaxTableBeginEdit (obj); \ 00141 tmp = CACHE_INSERT (str); \ 00142 CACHE_REMOVE (member); \ 00143 member = tmp; \ 00144 } 00145 00146 static inline void 00147 mark_table (GncTaxTable *table) 00148 { 00149 qof_instance_set_dirty(&table->inst); 00150 qof_event_gen (&table->inst, QOF_EVENT_MODIFY, NULL); 00151 } 00152 00153 static inline void 00154 maybe_resort_list (GncTaxTable *table) 00155 { 00156 struct _book_info *bi; 00157 00158 if (table->parent || table->invisible) return; 00159 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME); 00160 bi->tables = g_list_sort (bi->tables, (GCompareFunc)gncTaxTableCompare); 00161 } 00162 00163 static inline void 00164 mod_table (GncTaxTable *table) 00165 { 00166 timespecFromTime_t (&table->modtime, time(NULL)); 00167 } 00168 00169 static inline void addObj (GncTaxTable *table) 00170 { 00171 struct _book_info *bi; 00172 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME); 00173 bi->tables = g_list_insert_sorted (bi->tables, table, 00174 (GCompareFunc)gncTaxTableCompare); 00175 } 00176 00177 static inline void remObj (GncTaxTable *table) 00178 { 00179 struct _book_info *bi; 00180 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME); 00181 bi->tables = g_list_remove (bi->tables, table); 00182 } 00183 00184 static inline void 00185 gncTaxTableAddChild (GncTaxTable *table, GncTaxTable *child) 00186 { 00187 g_return_if_fail(table); 00188 g_return_if_fail(child); 00189 g_return_if_fail(qof_instance_get_destroying(table) == FALSE); 00190 00191 table->children = g_list_prepend(table->children, child); 00192 } 00193 00194 static inline void 00195 gncTaxTableRemoveChild (GncTaxTable *table, const GncTaxTable *child) 00196 { 00197 g_return_if_fail(table); 00198 g_return_if_fail(child); 00199 00200 if (qof_instance_get_destroying(table)) return; 00201 00202 table->children = g_list_remove(table->children, child); 00203 } 00204 00205 /* =============================================================== */ 00206 00207 enum 00208 { 00209 PROP_0, 00210 PROP_NAME, 00211 PROP_INVISIBLE, 00212 PROP_REFCOUNT 00213 }; 00214 00215 /* GObject Initialization */ 00216 G_DEFINE_TYPE(GncTaxTable, gnc_taxtable, QOF_TYPE_INSTANCE); 00217 00218 static void 00219 gnc_taxtable_init(GncTaxTable* tt) 00220 { 00221 } 00222 00223 static void 00224 gnc_taxtable_dispose(GObject *ttp) 00225 { 00226 G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp); 00227 } 00228 00229 static void 00230 gnc_taxtable_finalize(GObject* ttp) 00231 { 00232 G_OBJECT_CLASS(gnc_taxtable_parent_class)->dispose(ttp); 00233 } 00234 00235 static void 00236 gnc_taxtable_get_property (GObject *object, 00237 guint prop_id, 00238 GValue *value, 00239 GParamSpec *pspec) 00240 { 00241 GncTaxTable *tt; 00242 00243 g_return_if_fail(GNC_IS_TAXTABLE(object)); 00244 00245 tt = GNC_TAXTABLE(object); 00246 switch (prop_id) 00247 { 00248 case PROP_NAME: 00249 g_value_set_string(value, tt->name); 00250 break; 00251 case PROP_INVISIBLE: 00252 g_value_set_boolean(value, tt->invisible); 00253 break; 00254 case PROP_REFCOUNT: 00255 g_value_set_uint64(value, tt->refcount); 00256 break; 00257 default: 00258 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 00259 break; 00260 } 00261 } 00262 00263 static void 00264 gnc_taxtable_set_property (GObject *object, 00265 guint prop_id, 00266 const GValue *value, 00267 GParamSpec *pspec) 00268 { 00269 GncTaxTable *tt; 00270 00271 g_return_if_fail(GNC_IS_TAXTABLE(object)); 00272 00273 tt = GNC_TAXTABLE(object); 00274 switch (prop_id) 00275 { 00276 case PROP_NAME: 00277 gncTaxTableSetName(tt, g_value_get_string(value)); 00278 break; 00279 case PROP_INVISIBLE: 00280 if (g_value_get_boolean(value)) 00281 { 00282 gncTaxTableMakeInvisible(tt); 00283 } 00284 break; 00285 case PROP_REFCOUNT: 00286 gncTaxTableSetRefcount(tt, g_value_get_uint64(value)); 00287 break; 00288 default: 00289 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 00290 break; 00291 } 00292 } 00293 00295 static gchar* 00296 impl_get_display_name(const QofInstance* inst) 00297 { 00298 GncTaxTable* tt; 00299 00300 g_return_val_if_fail(inst != NULL, FALSE); 00301 g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE); 00302 00303 tt = GNC_TAXTABLE(inst); 00304 return g_strdup_printf("Tax table %s", tt->name); 00305 } 00306 00308 static gboolean 00309 impl_refers_to_object(const QofInstance* inst, const QofInstance* ref) 00310 { 00311 GncTaxTable* tt; 00312 00313 g_return_val_if_fail(inst != NULL, FALSE); 00314 g_return_val_if_fail(GNC_IS_TAXTABLE(inst), FALSE); 00315 00316 tt = GNC_TAXTABLE(inst); 00317 00318 if (GNC_IS_ACCOUNT(ref)) 00319 { 00320 GList* node; 00321 00322 for (node = tt->entries; node != NULL; node = node->next) 00323 { 00324 GncTaxTableEntry* tte = node->data; 00325 00326 if (tte->account == GNC_ACCOUNT(ref)) 00327 { 00328 return TRUE; 00329 } 00330 } 00331 } 00332 00333 return FALSE; 00334 } 00335 00342 static GList* 00343 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref) 00344 { 00345 if (!GNC_IS_ACCOUNT(ref)) 00346 { 00347 return NULL; 00348 } 00349 00350 return qof_instance_get_referring_object_list_from_collection(qof_instance_get_collection(inst), ref); 00351 } 00352 00353 static void 00354 gnc_taxtable_class_init (GncTaxTableClass *klass) 00355 { 00356 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 00357 QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass); 00358 00359 gobject_class->dispose = gnc_taxtable_dispose; 00360 gobject_class->finalize = gnc_taxtable_finalize; 00361 gobject_class->set_property = gnc_taxtable_set_property; 00362 gobject_class->get_property = gnc_taxtable_get_property; 00363 00364 qof_class->get_display_name = impl_get_display_name; 00365 qof_class->refers_to_object = impl_refers_to_object; 00366 qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list; 00367 00368 g_object_class_install_property 00369 (gobject_class, 00370 PROP_NAME, 00371 g_param_spec_string ("name", 00372 "TaxTable Name", 00373 "The accountName is an arbitrary string " 00374 "assigned by the user. It is intended to " 00375 "a short, 10 to 30 character long string " 00376 "that is displayed by the GUI as the " 00377 "tax table mnemonic.", 00378 NULL, 00379 G_PARAM_READWRITE)); 00380 00381 g_object_class_install_property 00382 (gobject_class, 00383 PROP_INVISIBLE, 00384 g_param_spec_boolean ("invisible", 00385 "Invisible", 00386 "TRUE if the tax table is invisible. FALSE if visible.", 00387 FALSE, 00388 G_PARAM_READWRITE)); 00389 00390 g_object_class_install_property 00391 (gobject_class, 00392 PROP_REFCOUNT, 00393 g_param_spec_uint64("ref-count", 00394 "Reference count", 00395 "The ref-count property contains number of times this tax table " 00396 "is referenced.", 00397 0, /* min */ 00398 G_MAXUINT64, /* max */ 00399 0, /* default */ 00400 G_PARAM_READWRITE)); 00401 } 00402 00403 /* Create/Destroy Functions */ 00404 GncTaxTable * 00405 gncTaxTableCreate (QofBook *book) 00406 { 00407 GncTaxTable *table; 00408 if (!book) return NULL; 00409 00410 table = g_object_new (GNC_TYPE_TAXTABLE, NULL); 00411 qof_instance_init_data (&table->inst, _GNC_MOD_NAME, book); 00412 table->name = CACHE_INSERT (""); 00413 addObj (table); 00414 qof_event_gen (&table->inst, QOF_EVENT_CREATE, NULL); 00415 return table; 00416 } 00417 00418 void 00419 gncTaxTableDestroy (GncTaxTable *table) 00420 { 00421 if (!table) return; 00422 qof_instance_set_destroying(table, TRUE); 00423 qof_instance_set_dirty (&table->inst); 00424 gncTaxTableCommitEdit (table); 00425 } 00426 00427 static void 00428 gncTaxTableFree (GncTaxTable *table) 00429 { 00430 GList *list; 00431 GncTaxTable *child; 00432 00433 if (!table) return; 00434 00435 qof_event_gen (&table->inst, QOF_EVENT_DESTROY, NULL); 00436 CACHE_REMOVE (table->name); 00437 remObj (table); 00438 00439 /* destroy the list of entries */ 00440 for (list = table->entries; list; list = list->next) 00441 gncTaxTableEntryDestroy (list->data); 00442 g_list_free (table->entries); 00443 00444 if (!qof_instance_get_destroying(table)) 00445 PERR("free a taxtable without do_free set!"); 00446 00447 /* disconnect from parent */ 00448 if (table->parent) 00449 gncTaxTableRemoveChild(table->parent, table); 00450 00451 /* disconnect from the children */ 00452 for (list = table->children; list; list = list->next) 00453 { 00454 child = list->data; 00455 gncTaxTableSetParent(child, NULL); 00456 } 00457 g_list_free(table->children); 00458 00459 /* qof_instance_release (&table->inst); */ 00460 g_object_unref (table); 00461 } 00462 00463 /* =============================================================== */ 00464 00465 GncTaxTableEntry * gncTaxTableEntryCreate (void) 00466 { 00467 GncTaxTableEntry *entry; 00468 entry = g_new0 (GncTaxTableEntry, 1); 00469 entry->amount = gnc_numeric_zero (); 00470 return entry; 00471 } 00472 00473 void gncTaxTableEntryDestroy (GncTaxTableEntry *entry) 00474 { 00475 if (!entry) return; 00476 g_free (entry); 00477 } 00478 00479 /* =============================================================== */ 00480 /* Set Functions */ 00481 00482 void gncTaxTableSetName (GncTaxTable *table, const char *name) 00483 { 00484 if (!table || !name) return; 00485 SET_STR (table, table->name, name); 00486 mark_table (table); 00487 maybe_resort_list (table); 00488 gncTaxTableCommitEdit (table); 00489 } 00490 00491 void gncTaxTableSetParent (GncTaxTable *table, GncTaxTable *parent) 00492 { 00493 if (!table) return; 00494 gncTaxTableBeginEdit (table); 00495 if (table->parent) 00496 gncTaxTableRemoveChild(table->parent, table); 00497 table->parent = parent; 00498 if (parent) 00499 gncTaxTableAddChild(parent, table); 00500 table->refcount = 0; 00501 gncTaxTableMakeInvisible (table); 00502 gncTaxTableCommitEdit (table); 00503 } 00504 00505 void gncTaxTableSetChild (GncTaxTable *table, GncTaxTable *child) 00506 { 00507 if (!table) return; 00508 gncTaxTableBeginEdit (table); 00509 table->child = child; 00510 gncTaxTableCommitEdit (table); 00511 } 00512 00513 void gncTaxTableIncRef (GncTaxTable *table) 00514 { 00515 if (!table) return; 00516 if (table->parent || table->invisible) return; /* children dont need refcounts */ 00517 gncTaxTableBeginEdit (table); 00518 table->refcount++; 00519 gncTaxTableCommitEdit (table); 00520 } 00521 00522 void gncTaxTableDecRef (GncTaxTable *table) 00523 { 00524 if (!table) return; 00525 if (table->parent || table->invisible) return; /* children dont need refcounts */ 00526 gncTaxTableBeginEdit (table); 00527 table->refcount--; 00528 g_return_if_fail (table->refcount >= 0); 00529 gncTaxTableCommitEdit (table); 00530 } 00531 00532 void gncTaxTableSetRefcount (GncTaxTable *table, gint64 refcount) 00533 { 00534 if (!table) return; 00535 table->refcount = refcount; 00536 } 00537 00538 void gncTaxTableMakeInvisible (GncTaxTable *table) 00539 { 00540 struct _book_info *bi; 00541 if (!table) return; 00542 gncTaxTableBeginEdit (table); 00543 table->invisible = TRUE; 00544 bi = qof_book_get_data (qof_instance_get_book(table), _GNC_MOD_NAME); 00545 bi->tables = g_list_remove (bi->tables, table); 00546 gncTaxTableCommitEdit (table); 00547 } 00548 00549 void gncTaxTableEntrySetAccount (GncTaxTableEntry *entry, Account *account) 00550 { 00551 if (!entry || !account) return; 00552 if (entry->account == account) return; 00553 entry->account = account; 00554 if (entry->table) 00555 { 00556 mark_table (entry->table); 00557 mod_table (entry->table); 00558 } 00559 } 00560 00561 void gncTaxTableEntrySetType (GncTaxTableEntry *entry, GncAmountType type) 00562 { 00563 if (!entry) return; 00564 if (entry->type == type) return; 00565 entry->type = type; 00566 if (entry->table) 00567 { 00568 mark_table (entry->table); 00569 mod_table (entry->table); 00570 } 00571 } 00572 00573 void gncTaxTableEntrySetAmount (GncTaxTableEntry *entry, gnc_numeric amount) 00574 { 00575 if (!entry) return; 00576 if (gnc_numeric_eq (entry->amount, amount)) return; 00577 entry->amount = amount; 00578 if (entry->table) 00579 { 00580 mark_table (entry->table); 00581 mod_table (entry->table); 00582 } 00583 } 00584 00585 void gncTaxTableAddEntry (GncTaxTable *table, GncTaxTableEntry *entry) 00586 { 00587 if (!table || !entry) return; 00588 if (entry->table == table) return; /* already mine */ 00589 00590 gncTaxTableBeginEdit (table); 00591 if (entry->table) 00592 gncTaxTableRemoveEntry (entry->table, entry); 00593 00594 entry->table = table; 00595 table->entries = g_list_insert_sorted (table->entries, entry, 00596 (GCompareFunc)gncTaxTableEntryCompare); 00597 mark_table (table); 00598 mod_table (table); 00599 gncTaxTableCommitEdit (table); 00600 } 00601 00602 void gncTaxTableRemoveEntry (GncTaxTable *table, GncTaxTableEntry *entry) 00603 { 00604 if (!table || !entry) return; 00605 gncTaxTableBeginEdit (table); 00606 entry->table = NULL; 00607 table->entries = g_list_remove (table->entries, entry); 00608 mark_table (table); 00609 mod_table (table); 00610 gncTaxTableCommitEdit (table); 00611 } 00612 00613 void gncTaxTableChanged (GncTaxTable *table) 00614 { 00615 if (!table) return; 00616 gncTaxTableBeginEdit (table); 00617 table->child = NULL; 00618 gncTaxTableCommitEdit (table); 00619 } 00620 00621 /* =============================================================== */ 00622 00623 void gncTaxTableBeginEdit (GncTaxTable *table) 00624 { 00625 qof_begin_edit(&table->inst); 00626 } 00627 00628 static void gncTaxTableOnError (QofInstance *inst, QofBackendError errcode) 00629 { 00630 PERR("TaxTable QofBackend Failure: %d", errcode); 00631 gnc_engine_signal_commit_error( errcode ); 00632 } 00633 00634 static void gncTaxTableOnDone (QofInstance *inst) {} 00635 00636 static void table_free (QofInstance *inst) 00637 { 00638 GncTaxTable *table = (GncTaxTable *) inst; 00639 gncTaxTableFree (table); 00640 } 00641 00642 void gncTaxTableCommitEdit (GncTaxTable *table) 00643 { 00644 if (!qof_commit_edit (QOF_INSTANCE(table))) return; 00645 qof_commit_edit_part2 (&table->inst, gncTaxTableOnError, 00646 gncTaxTableOnDone, table_free); 00647 } 00648 00649 00650 /* =============================================================== */ 00651 /* Get Functions */ 00652 00653 GncTaxTable *gncTaxTableLookupByName (QofBook *book, const char *name) 00654 { 00655 GList *list = gncTaxTableGetTables (book); 00656 00657 for ( ; list; list = list->next) 00658 { 00659 GncTaxTable *table = list->data; 00660 if (!safe_strcmp (table->name, name)) 00661 return list->data; 00662 } 00663 return NULL; 00664 } 00665 00666 GList * gncTaxTableGetTables (QofBook *book) 00667 { 00668 struct _book_info *bi; 00669 if (!book) return NULL; 00670 00671 bi = qof_book_get_data (book, _GNC_MOD_NAME); 00672 return bi->tables; 00673 } 00674 00675 const char *gncTaxTableGetName (const GncTaxTable *table) 00676 { 00677 if (!table) return NULL; 00678 return table->name; 00679 } 00680 00681 static GncTaxTableEntry *gncTaxTableEntryCopy (const GncTaxTableEntry *entry) 00682 { 00683 GncTaxTableEntry *e; 00684 if (!entry) return NULL; 00685 00686 e = gncTaxTableEntryCreate (); 00687 gncTaxTableEntrySetAccount (e, entry->account); 00688 gncTaxTableEntrySetType (e, entry->type); 00689 gncTaxTableEntrySetAmount (e, entry->amount); 00690 00691 return e; 00692 } 00693 00694 static GncTaxTable *gncTaxTableCopy (const GncTaxTable *table) 00695 { 00696 GncTaxTable *t; 00697 GList *list; 00698 00699 if (!table) return NULL; 00700 t = gncTaxTableCreate (qof_instance_get_book(table)); 00701 gncTaxTableSetName (t, table->name); 00702 for (list = table->entries; list; list = list->next) 00703 { 00704 GncTaxTableEntry *entry, *e; 00705 entry = list->data; 00706 e = gncTaxTableEntryCopy (entry); 00707 gncTaxTableAddEntry (t, e); 00708 } 00709 return t; 00710 } 00711 00712 GncTaxTable *gncTaxTableReturnChild (GncTaxTable *table, gboolean make_new) 00713 { 00714 GncTaxTable *child = NULL; 00715 00716 if (!table) return NULL; 00717 if (table->child) return table->child; 00718 if (table->parent || table->invisible) return table; 00719 if (make_new) 00720 { 00721 child = gncTaxTableCopy (table); 00722 gncTaxTableSetChild (table, child); 00723 gncTaxTableSetParent (child, table); 00724 } 00725 return child; 00726 } 00727 00728 GncTaxTable *gncTaxTableGetParent (const GncTaxTable *table) 00729 { 00730 if (!table) return NULL; 00731 return table->parent; 00732 } 00733 00734 GncTaxTableEntryList* gncTaxTableGetEntries (const GncTaxTable *table) 00735 { 00736 if (!table) return NULL; 00737 return table->entries; 00738 } 00739 00740 gint64 gncTaxTableGetRefcount (const GncTaxTable *table) 00741 { 00742 if (!table) return 0; 00743 return table->refcount; 00744 } 00745 00746 Timespec gncTaxTableLastModified (const GncTaxTable *table) 00747 { 00748 Timespec ts = { 0 , 0 }; 00749 if (!table) return ts; 00750 return table->modtime; 00751 } 00752 00753 gboolean gncTaxTableGetInvisible (const GncTaxTable *table) 00754 { 00755 if (!table) return FALSE; 00756 return table->invisible; 00757 } 00758 00759 Account * gncTaxTableEntryGetAccount (const GncTaxTableEntry *entry) 00760 { 00761 if (!entry) return NULL; 00762 return entry->account; 00763 } 00764 00765 GncAmountType gncTaxTableEntryGetType (const GncTaxTableEntry *entry) 00766 { 00767 if (!entry) return 0; 00768 return entry->type; 00769 } 00770 00771 gnc_numeric gncTaxTableEntryGetAmount (const GncTaxTableEntry *entry) 00772 { 00773 if (!entry) return gnc_numeric_zero(); 00774 return entry->amount; 00775 } 00776 00777 /* This is a semi-private function (meaning that it's not declared in 00778 * the header) used for SQL Backend testing. */ 00779 GncTaxTable* gncTaxTableEntryGetTable( const GncTaxTableEntry* entry ) 00780 { 00781 if (!entry) return NULL; 00782 return entry->table; 00783 } 00784 00785 int gncTaxTableEntryCompare (const GncTaxTableEntry *a, const GncTaxTableEntry *b) 00786 { 00787 char *name_a, *name_b; 00788 int retval; 00789 00790 if (!a && !b) return 0; 00791 if (!a) return -1; 00792 if (!b) return 1; 00793 00794 name_a = gnc_account_get_full_name (a->account); 00795 name_b = gnc_account_get_full_name (b->account); 00796 retval = safe_strcmp(name_a, name_b); 00797 g_free(name_a); 00798 g_free(name_b); 00799 00800 if (retval) 00801 return retval; 00802 00803 return gnc_numeric_compare (a->amount, b->amount); 00804 } 00805 00806 int gncTaxTableCompare (const GncTaxTable *a, const GncTaxTable *b) 00807 { 00808 if (!a && !b) return 0; 00809 if (!a) return -1; 00810 if (!b) return 1; 00811 return safe_strcmp (a->name, b->name); 00812 } 00813 00814 gboolean gncTaxTableEntryEqual(const GncTaxTableEntry *a, const GncTaxTableEntry *b) 00815 { 00816 if (a == NULL && b == NULL) return TRUE; 00817 if (a == NULL || b == NULL) return FALSE; 00818 00819 if (!xaccAccountEqual(a->account, b->account, TRUE)) 00820 { 00821 PWARN("accounts differ"); 00822 return FALSE; 00823 } 00824 00825 if (a->type != b->type) 00826 { 00827 PWARN("types differ"); 00828 return FALSE; 00829 } 00830 00831 if (!gnc_numeric_equal(a->amount, b->amount)) 00832 { 00833 PWARN("amounts differ"); 00834 return FALSE; 00835 } 00836 00837 return TRUE; 00838 } 00839 00840 gboolean gncTaxTableEqual(const GncTaxTable *a, const GncTaxTable *b) 00841 { 00842 if (a == NULL && b == NULL) return TRUE; 00843 if (a == NULL || b == NULL) return FALSE; 00844 00845 g_return_val_if_fail(GNC_IS_TAXTABLE(a), FALSE); 00846 g_return_val_if_fail(GNC_IS_TAXTABLE(b), FALSE); 00847 00848 if (safe_strcmp(a->name, b->name) != 0) 00849 { 00850 PWARN("Names differ: %s vs %s", a->name, b->name); 00851 return FALSE; 00852 } 00853 00854 if (a->invisible != b->invisible) 00855 { 00856 PWARN("invisible flags differ"); 00857 return FALSE; 00858 } 00859 00860 if ((a->entries != NULL) != (b->entries != NULL)) 00861 { 00862 PWARN("only one has entries"); 00863 return FALSE; 00864 } 00865 00866 if (a->entries != NULL && b->entries != NULL) 00867 { 00868 GncTaxTableEntryList* a_node; 00869 GncTaxTableEntryList* b_node; 00870 00871 for (a_node = a->entries, b_node = b->entries; 00872 a_node != NULL && b_node != NULL; 00873 a_node = a_node->next, b_node = b_node->next) 00874 { 00875 if (!gncTaxTableEntryEqual((GncTaxTableEntry*)a_node->data, 00876 (GncTaxTableEntry*)b_node->data)) 00877 { 00878 PWARN("entries differ"); 00879 return FALSE; 00880 } 00881 } 00882 00883 if (a_node != NULL || b_node != NULL) 00884 { 00885 PWARN("Unequal number of entries"); 00886 return FALSE; 00887 } 00888 } 00889 00890 #if 0 00891 /* See src/doc/business.txt for an explanation of the following */ 00892 /* Code that handles this is *identical* to that in gncBillTerm */ 00893 gint64 refcount; 00894 GncTaxTable * parent; /* if non-null, we are an immutable child */ 00895 GncTaxTable * child; /* if non-null, we have not changed */ 00896 GList * children; /* list of children for disconnection */ 00897 #endif 00898 00899 return TRUE; 00900 } 00901 00902 /* 00903 * This will add value to the account-value for acc, creating a new 00904 * list object if necessary 00905 */ 00906 GList *gncAccountValueAdd (GList *list, Account *acc, gnc_numeric value) 00907 { 00908 GList *li; 00909 GncAccountValue *res = NULL; 00910 00911 g_return_val_if_fail (acc, list); 00912 g_return_val_if_fail (gnc_numeric_check (value) == GNC_ERROR_OK, list); 00913 00914 /* Try to find the account in the list */ 00915 for (li = list; li; li = li->next) 00916 { 00917 res = li->data; 00918 if (res->account == acc) 00919 { 00920 res->value = gnc_numeric_add (res->value, value, GNC_DENOM_AUTO, 00921 GNC_HOW_DENOM_LCD); 00922 return list; 00923 } 00924 } 00925 /* Nope, didn't find it. */ 00926 00927 res = g_new0 (GncAccountValue, 1); 00928 res->account = acc; 00929 res->value = value; 00930 return g_list_prepend (list, res); 00931 } 00932 00933 /* Merge l2 into l1. l2 is not touched. */ 00934 GList *gncAccountValueAddList (GList *l1, GList *l2) 00935 { 00936 GList *li; 00937 00938 for (li = l2; li; li = li->next ) 00939 { 00940 GncAccountValue *val = li->data; 00941 l1 = gncAccountValueAdd (l1, val->account, val->value); 00942 } 00943 00944 return l1; 00945 } 00946 00947 /* return the total for this list */ 00948 gnc_numeric gncAccountValueTotal (GList *list) 00949 { 00950 gnc_numeric total = gnc_numeric_zero (); 00951 00952 for ( ; list ; list = list->next) 00953 { 00954 GncAccountValue *val = list->data; 00955 total = gnc_numeric_add (total, val->value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD); 00956 } 00957 return total; 00958 } 00959 00960 /* Destroy a list of accountvalues */ 00961 void gncAccountValueDestroy (GList *list) 00962 { 00963 GList *node; 00964 for ( node = list; node ; node = node->next) 00965 g_free (node->data); 00966 00967 g_list_free (list); 00968 } 00969 00970 /* Package-Private functions */ 00971 00972 static void _gncTaxTableCreate (QofBook *book) 00973 { 00974 struct _book_info *bi; 00975 00976 if (!book) return; 00977 00978 bi = g_new0 (struct _book_info, 1); 00979 qof_book_set_data (book, _GNC_MOD_NAME, bi); 00980 } 00981 00982 static void _gncTaxTableDestroy (QofBook *book) 00983 { 00984 struct _book_info *bi; 00985 00986 if (!book) return; 00987 00988 bi = qof_book_get_data (book, _GNC_MOD_NAME); 00989 00990 g_list_free (bi->tables); 00991 g_free (bi); 00992 } 00993 00994 static QofObject gncTaxTableDesc = 00995 { 00996 DI(.interface_version = ) QOF_OBJECT_VERSION, 00997 DI(.e_type = ) _GNC_MOD_NAME, 00998 DI(.type_label = ) "Tax Table", 00999 DI(.create = ) (gpointer)gncTaxTableCreate, 01000 DI(.book_begin = ) _gncTaxTableCreate, 01001 DI(.book_end = ) _gncTaxTableDestroy, 01002 DI(.is_dirty = ) qof_collection_is_dirty, 01003 DI(.mark_clean = ) qof_collection_mark_clean, 01004 DI(.foreach = ) qof_collection_foreach, 01005 DI(.printable = ) NULL, 01006 DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp, 01007 }; 01008 01009 gboolean gncTaxTableRegister (void) 01010 { 01011 static QofParam params[] = 01012 { 01013 { GNC_TT_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncTaxTableGetName, (QofSetterFunc)gncTaxTableSetName }, 01014 { GNC_TT_REFCOUNT, QOF_TYPE_INT64, (QofAccessFunc)gncTaxTableGetRefcount, (QofSetterFunc)gncTaxTableSetRefcount }, 01015 { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL }, 01016 { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL }, 01017 { NULL }, 01018 }; 01019 01020 qof_class_register (_GNC_MOD_NAME, (QofSortFunc)gncTaxTableCompare, params); 01021 01022 return qof_object_register (&gncTaxTableDesc); 01023 } 01024 01025 /* need a QOF tax table entry object */ 01026 //gncTaxTableEntrySetType_q int32 01027 //gint gncTaxTableEntryGetType_q (GncTaxTableEntry *entry);
1.7.4