1 /********************************************************************\
2 * gncAddress.c -- an Address object *
3 * *
4 * This program is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU General Public License as *
6 * published by the Free Software Foundation; either version 2 of *
7 * the License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License*
15 * along with this program; if not, contact: *
16 * *
17 * Free Software Foundation Voice: +1-617-542-5942 *
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19 * Boston, MA 02110-1301, USA gnu@gnu.org *
20 * *
21 \********************************************************************/
22
23 /*
24 * Copyright (C) 2001 Derek Atkins
25 * Author: Derek Atkins <warlord@MIT.EDU>
26 */
27
28 #include <config.h>
29
30 #include <glib.h>
31 #include <qofinstance-p.h>
32
33 #include "gncAddress.h"
34 #include "gncAddressP.h"
35 #include "gncCustomerP.h"
36 #include "gnc-features.h"
37
38 struct _gncAddress
39 {
40 QofInstance inst;
41
42 QofBook * book;
43 QofInstance * parent;
44 gboolean dirty;
45 const char * name;
46 const char * addr1;
47 const char * addr2;
48 const char * addr3;
49 const char * addr4;
50 const char * phone;
51 const char * fax;
52 const char * email;
53 };
54
55 struct _gncAddressClass
56 {
57 QofInstanceClass parent_class;
58 };
59
60 static QofLogModule log_module = GNC_MOD_BUSINESS;
61
62 #define _GNC_MOD_NAME GNC_ADDRESS_MODULE_NAME
63
64 static inline void mark_address (GncAddress *address);
mark_address(GncAddress * address)65 void mark_address (GncAddress *address)
66 {
67 address->dirty = TRUE;
68
69 if (address->parent)
70 qof_instance_set_dirty(address->parent);
71 qof_event_gen (QOF_INSTANCE(address), QOF_EVENT_MODIFY, address->parent);
72 qof_event_gen (address->parent, QOF_EVENT_MODIFY, NULL);
73 }
74
75 enum
76 {
77 PROP_0,
78 PROP_NAME,
79 PROP_ADDR1,
80 PROP_ADDR2,
81 PROP_ADDR3,
82 PROP_ADDR4,
83 PROP_PHONE,
84 PROP_FAX,
85 PROP_EMAIL
86 };
87
88 /* GObject Initialization */
89 G_DEFINE_TYPE(GncAddress, gnc_address, QOF_TYPE_INSTANCE);
90
91 static void
gnc_address_init(GncAddress * addr)92 gnc_address_init(GncAddress* addr)
93 {
94 }
95
96 static void
gnc_address_dispose(GObject * addrp)97 gnc_address_dispose(GObject *addrp)
98 {
99 G_OBJECT_CLASS(gnc_address_parent_class)->dispose(addrp);
100 }
101
102 static void
gnc_address_finalize(GObject * addrp)103 gnc_address_finalize(GObject* addrp)
104 {
105 G_OBJECT_CLASS(gnc_address_parent_class)->finalize(addrp);
106 }
107
108 static void
gnc_address_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)109 gnc_address_get_property (GObject *object,
110 guint prop_id,
111 GValue *value,
112 GParamSpec *pspec)
113 {
114 GncAddress *address;
115
116 g_return_if_fail(GNC_IS_ADDRESS(object));
117
118 address = GNC_ADDRESS(object);
119 switch (prop_id)
120 {
121 case PROP_NAME:
122 g_value_set_string(value, address->name);
123 break;
124 case PROP_ADDR1:
125 g_value_set_string(value, address->addr1);
126 break;
127 case PROP_ADDR2:
128 g_value_set_string(value, address->addr2);
129 break;
130 case PROP_ADDR3:
131 g_value_set_string(value, address->addr3);
132 break;
133 case PROP_ADDR4:
134 g_value_set_string(value, address->addr4);
135 break;
136 case PROP_PHONE:
137 g_value_set_string(value, address->phone);
138 break;
139 case PROP_FAX:
140 g_value_set_string(value, address->fax);
141 break;
142 case PROP_EMAIL:
143 g_value_set_string(value, address->email);
144 break;
145 default:
146 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
147 break;
148 }
149 }
150
151 static void
gnc_address_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)152 gnc_address_set_property (GObject *object,
153 guint prop_id,
154 const GValue *value,
155 GParamSpec *pspec)
156 {
157 GncAddress *address;
158
159 g_return_if_fail(GNC_IS_ADDRESS(object));
160
161 address = GNC_ADDRESS(object);
162 switch (prop_id)
163 {
164 case PROP_NAME:
165 gncAddressSetName(address, g_value_get_string(value));
166 break;
167 case PROP_ADDR1:
168 gncAddressSetAddr1(address, g_value_get_string(value));
169 break;
170 case PROP_ADDR2:
171 gncAddressSetAddr2(address, g_value_get_string(value));
172 break;
173 case PROP_ADDR3:
174 gncAddressSetAddr3(address, g_value_get_string(value));
175 break;
176 case PROP_ADDR4:
177 gncAddressSetAddr4(address, g_value_get_string(value));
178 break;
179 case PROP_PHONE:
180 gncAddressSetPhone(address, g_value_get_string(value));
181 break;
182 case PROP_FAX:
183 gncAddressSetFax(address, g_value_get_string(value));
184 break;
185 case PROP_EMAIL:
186 gncAddressSetEmail(address, g_value_get_string(value));
187 break;
188 default:
189 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
190 break;
191 }
192 }
193
194 /** Returns a list of my type of object which refers to an object. For example, when called as
195 qof_instance_get_typed_referring_object_list(taxtable, account);
196 it will return the list of taxtables which refer to a specific account. The result should be the
197 same regardless of which taxtable object is used. The list must be freed by the caller but the
198 objects on the list must not.
199 */
200 static GList*
impl_get_typed_referring_object_list(const QofInstance * inst,const QofInstance * ref)201 impl_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
202 {
203 /* Refers to nothing. The parent field doesn't really count since the parent knows which address
204 belongs to it. */
205 return NULL;
206 }
207
208 static void
gnc_address_class_init(GncAddressClass * klass)209 gnc_address_class_init (GncAddressClass *klass)
210 {
211 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
212 QofInstanceClass* qof_class = QOF_INSTANCE_CLASS(klass);
213
214 gobject_class->dispose = gnc_address_dispose;
215 gobject_class->finalize = gnc_address_finalize;
216 gobject_class->set_property = gnc_address_set_property;
217 gobject_class->get_property = gnc_address_get_property;
218
219 qof_class->get_display_name = NULL;
220 qof_class->refers_to_object = NULL;
221 qof_class->get_typed_referring_object_list = impl_get_typed_referring_object_list;
222
223 g_object_class_install_property
224 (gobject_class,
225 PROP_NAME,
226 g_param_spec_string ("name",
227 "Address Name",
228 "The address name is an arbitrary string "
229 "assigned by the user. It is intended to "
230 "a short string to identify the address.",
231 NULL,
232 G_PARAM_READWRITE));
233
234 g_object_class_install_property
235 (gobject_class,
236 PROP_ADDR1,
237 g_param_spec_string ("addr1",
238 "Address Line 1",
239 "The address line 1 is an arbitrary string "
240 "assigned by the user. It is the first "
241 "line of the address.",
242 NULL,
243 G_PARAM_READWRITE));
244
245 g_object_class_install_property
246 (gobject_class,
247 PROP_ADDR2,
248 g_param_spec_string ("addr2",
249 "Address Line 2",
250 "The address line 2 is an arbitrary string "
251 "assigned by the user. It is the second "
252 "line of the address.",
253 NULL,
254 G_PARAM_READWRITE));
255
256 g_object_class_install_property
257 (gobject_class,
258 PROP_ADDR3,
259 g_param_spec_string ("addr3",
260 "Address Line 3",
261 "The address line 3 is an arbitrary string "
262 "assigned by the user. It is the third "
263 "line of the address.",
264 NULL,
265 G_PARAM_READWRITE));
266
267 g_object_class_install_property
268 (gobject_class,
269 PROP_ADDR4,
270 g_param_spec_string ("addr4",
271 "Address Line 4",
272 "The address line 4 is an arbitrary string "
273 "assigned by the user. It is the fourth "
274 "line of the address.",
275 NULL,
276 G_PARAM_READWRITE));
277
278 g_object_class_install_property
279 (gobject_class,
280 PROP_PHONE,
281 g_param_spec_string ("phone",
282 "Phone",
283 "The phone number is the number at this address.",
284 NULL,
285 G_PARAM_READWRITE));
286
287 g_object_class_install_property
288 (gobject_class,
289 PROP_FAX,
290 g_param_spec_string ("fax",
291 "Fax",
292 "The fax number at this address.",
293 NULL,
294 G_PARAM_READWRITE));
295
296 g_object_class_install_property
297 (gobject_class,
298 PROP_EMAIL,
299 g_param_spec_string ("email",
300 "E-mail address",
301 "The e-mail address at this address.",
302 NULL,
303 G_PARAM_READWRITE));
304 }
305
306 /* Create/Destroy functions */
307
308 GncAddress *
gncAddressCreate(QofBook * book,QofInstance * prnt)309 gncAddressCreate (QofBook *book, QofInstance *prnt)
310 {
311 GncAddress *addr;
312
313 if (!book) return NULL;
314
315 addr = g_object_new (GNC_TYPE_ADDRESS, NULL);
316 qof_instance_init_data(&addr->inst, GNC_ID_ADDRESS, book);
317 addr->book = book;
318 addr->dirty = FALSE;
319 addr->parent = prnt;
320
321 addr->name = CACHE_INSERT ("");
322 addr->addr1 = CACHE_INSERT ("");
323 addr->addr2 = CACHE_INSERT ("");
324 addr->addr3 = CACHE_INSERT ("");
325 addr->addr4 = CACHE_INSERT ("");
326 addr->phone = CACHE_INSERT ("");
327 addr->fax = CACHE_INSERT ("");
328 addr->email = CACHE_INSERT ("");
329
330 return addr;
331 }
332
333 static GncAddress *
qofAddressCreate(QofBook * book)334 qofAddressCreate (QofBook *book)
335 {
336 /* The address will get set later by another function */
337 return gncAddressCreate(book, NULL);
338 }
339
340 static void
qofAddressSetOwner(GncAddress * addr,QofInstance * ent)341 qofAddressSetOwner(GncAddress *addr, QofInstance *ent)
342 {
343 if (!addr || !ent)
344 {
345 return;
346 }
347 if (addr->parent == NULL)
348 {
349 addr->parent = ent;
350 }
351 }
352
353 static QofInstance*
qofAddressGetOwner(const GncAddress * addr)354 qofAddressGetOwner(const GncAddress *addr)
355 {
356
357 if (!addr)
358 {
359 return NULL;
360 }
361 return addr->parent;
362 }
363
364 void
gncAddressDestroy(GncAddress * addr)365 gncAddressDestroy (GncAddress *addr)
366 {
367 if (!addr) return;
368 qof_instance_set_destroying(addr, TRUE);
369 gncAddressCommitEdit (addr);
370 }
371
372 static void
gncAddressFree(GncAddress * addr)373 gncAddressFree (GncAddress *addr)
374 {
375 if (!addr) return;
376
377 qof_event_gen (&addr->inst, QOF_EVENT_DESTROY, NULL);
378
379 CACHE_REMOVE (addr->name);
380 CACHE_REMOVE (addr->addr1);
381 CACHE_REMOVE (addr->addr2);
382 CACHE_REMOVE (addr->addr3);
383 CACHE_REMOVE (addr->addr4);
384 CACHE_REMOVE (addr->phone);
385 CACHE_REMOVE (addr->fax);
386 CACHE_REMOVE (addr->email);
387
388 /* qof_instance_release (&addr->inst); */
389 g_object_unref (addr);
390 }
391
392
393 /* Set functions */
394
395 #define SET_STR(obj, member, str) { \
396 if (member == str) return; \
397 if (!g_strcmp0 (member, str)) return; \
398 gncAddressBeginEdit (obj); \
399 CACHE_REPLACE(member, str); \
400 }
401
gncAddressSetName(GncAddress * addr,const char * name)402 void gncAddressSetName (GncAddress *addr, const char *name)
403 {
404 if (!addr) return;
405 if (!name) return;
406 SET_STR(addr, addr->name, name);
407 mark_address (addr);
408 gncAddressCommitEdit (addr);
409 }
410
gncAddressSetAddr1(GncAddress * addr,const char * addr1)411 void gncAddressSetAddr1 (GncAddress *addr, const char *addr1)
412 {
413 if (!addr) return;
414 if (!addr1) return;
415 SET_STR(addr, addr->addr1, addr1);
416 mark_address (addr);
417 gncAddressCommitEdit (addr);
418 }
419
gncAddressSetAddr2(GncAddress * addr,const char * addr2)420 void gncAddressSetAddr2 (GncAddress *addr, const char *addr2)
421 {
422 if (!addr) return;
423 if (!addr2) return;
424 SET_STR(addr, addr->addr2, addr2);
425 mark_address (addr);
426 gncAddressCommitEdit (addr);
427 }
428
gncAddressSetAddr3(GncAddress * addr,const char * addr3)429 void gncAddressSetAddr3 (GncAddress *addr, const char *addr3)
430 {
431 if (!addr) return;
432 if (!addr3) return;
433 SET_STR(addr, addr->addr3, addr3);
434 mark_address (addr);
435 gncAddressCommitEdit (addr);
436 }
437
gncAddressSetAddr4(GncAddress * addr,const char * addr4)438 void gncAddressSetAddr4 (GncAddress *addr, const char *addr4)
439 {
440 if (!addr) return;
441 if (!addr4) return;
442 SET_STR(addr, addr->addr4, addr4);
443 mark_address (addr);
444 gncAddressCommitEdit (addr);
445 }
446
gncAddressSetPhone(GncAddress * addr,const char * phone)447 void gncAddressSetPhone (GncAddress *addr, const char *phone)
448 {
449 if (!addr) return;
450 if (!phone) return;
451 SET_STR(addr, addr->phone, phone);
452 mark_address (addr);
453 gncAddressCommitEdit (addr);
454 }
455
gncAddressSetFax(GncAddress * addr,const char * fax)456 void gncAddressSetFax (GncAddress *addr, const char *fax)
457 {
458 if (!addr) return;
459 if (!fax) return;
460 SET_STR(addr, addr->fax, fax);
461 mark_address (addr);
462 gncAddressCommitEdit (addr);
463 }
464
gncAddressSetEmail(GncAddress * addr,const char * email)465 void gncAddressSetEmail (GncAddress *addr, const char *email)
466 {
467 if (!addr) return;
468 if (!email) return;
469 SET_STR(addr, addr->email, email);
470 mark_address (addr);
471 gncAddressCommitEdit (addr);
472 }
473
gncAddressBeginEdit(GncAddress * addr)474 void gncAddressBeginEdit (GncAddress *addr)
475 {
476 qof_begin_edit (&addr->inst);
477 }
478
gncAddressOnError(QofInstance * inst,QofBackendError errcode)479 static void gncAddressOnError (QofInstance *inst, QofBackendError errcode)
480 {
481 PERR("Address QofBackend Failure: %d", errcode);
482 gnc_engine_signal_commit_error( errcode );
483 }
484
gncAddressOnDone(QofInstance * addr)485 static void gncAddressOnDone (QofInstance *addr) { }
486
address_free(QofInstance * inst)487 static void address_free (QofInstance *inst)
488 {
489 GncAddress *addr = (GncAddress *) inst;
490 gncAddressFree (addr);
491 }
492
gncAddressCommitEdit(GncAddress * addr)493 void gncAddressCommitEdit (GncAddress *addr)
494 {
495 /* GnuCash 2.6.3 and earlier didn't handle address kvp's... */
496 if (qof_instance_has_kvp(QOF_INSTANCE(addr)))
497 gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (addr)), GNC_FEATURE_KVP_EXTRA_DATA);
498
499 if (!qof_commit_edit (QOF_INSTANCE(addr))) return;
500 qof_commit_edit_part2 (&addr->inst, gncAddressOnError,
501 gncAddressOnDone, address_free);
502 }
503
504
505 /* Get Functions */
506
gncAddressGetName(const GncAddress * addr)507 const char * gncAddressGetName (const GncAddress *addr)
508 {
509 if (!addr) return NULL;
510 return addr->name;
511 }
512
gncAddressGetAddr1(const GncAddress * addr)513 const char * gncAddressGetAddr1 (const GncAddress *addr)
514 {
515 if (!addr) return NULL;
516 return addr->addr1;
517 }
518
gncAddressGetAddr2(const GncAddress * addr)519 const char * gncAddressGetAddr2 (const GncAddress *addr)
520 {
521 if (!addr) return NULL;
522 return addr->addr2;
523 }
524
gncAddressGetAddr3(const GncAddress * addr)525 const char * gncAddressGetAddr3 (const GncAddress *addr)
526 {
527 if (!addr) return NULL;
528 return addr->addr3;
529 }
530
gncAddressGetAddr4(const GncAddress * addr)531 const char * gncAddressGetAddr4 (const GncAddress *addr)
532 {
533 if (!addr) return NULL;
534 return addr->addr4;
535 }
536
gncAddressGetPhone(const GncAddress * addr)537 const char * gncAddressGetPhone (const GncAddress *addr)
538 {
539 if (!addr) return NULL;
540 return addr->phone;
541 }
542
gncAddressGetFax(const GncAddress * addr)543 const char * gncAddressGetFax (const GncAddress *addr)
544 {
545 if (!addr) return NULL;
546 return addr->fax;
547 }
548
gncAddressGetEmail(const GncAddress * addr)549 const char * gncAddressGetEmail (const GncAddress *addr)
550 {
551 if (!addr) return NULL;
552 return addr->email;
553 }
554
gncAddressIsDirty(const GncAddress * addr)555 gboolean gncAddressIsDirty (const GncAddress *addr)
556 {
557 if (!addr) return FALSE;
558 return addr->dirty;
559 }
560
gncAddressClearDirty(GncAddress * addr)561 void gncAddressClearDirty (GncAddress *addr)
562 {
563 if (!addr) return;
564 addr->dirty = FALSE;
565 }
566
gncAddressCompare(const GncAddress * a,const GncAddress * b)567 int gncAddressCompare (const GncAddress *a, const GncAddress *b)
568 {
569 if (!a && !b) return 0;
570 if (!a && b) return 1;
571 if (a && !b) return -1;
572
573 return g_strcmp0 (a->name, b->name);
574 }
575
576 gboolean
gncAddressEqual(const GncAddress * a,const GncAddress * b)577 gncAddressEqual(const GncAddress* a, const GncAddress* b)
578 {
579 if (a == NULL && b == NULL) return TRUE;
580 if (a == NULL || b == NULL) return FALSE;
581
582 g_return_val_if_fail(GNC_IS_ADDRESS(a), FALSE);
583 g_return_val_if_fail(GNC_IS_ADDRESS(b), FALSE);
584
585 if (g_strcmp0(a->name, b->name) != 0)
586 {
587 PWARN("names differ: %s vs %s", a->name, b->name);
588 return FALSE;
589 }
590 if (g_strcmp0(a->addr1, b->addr1) != 0)
591 {
592 PWARN("address lines 1 differ: %s vs %s", a->addr1, b->addr1);
593 return FALSE;
594 }
595 if (g_strcmp0(a->addr2, b->addr2) != 0)
596 {
597 PWARN("address lines 2 differ: %s vs %s", a->addr2, b->addr1);
598 return FALSE;
599 }
600 if (g_strcmp0(a->addr3, b->addr3) != 0)
601 {
602 PWARN("address lines 3 differ: %s vs %s", a->addr3, b->addr3);
603 return FALSE;
604 }
605 if (g_strcmp0(a->addr4, b->addr4) != 0)
606 {
607 PWARN("address lines 4 differ: %s vs %s", a->addr4, b->addr4);
608 return FALSE;
609 }
610 if (g_strcmp0(a->phone, b->phone) != 0)
611 {
612 PWARN("phone numbers differ: %s vs %s", a->phone, b->phone);
613 return FALSE;
614 }
615 if (g_strcmp0(a->fax, b->fax) != 0)
616 {
617 PWARN("fax numbers differ: %s vs %s", a->fax, b->fax);
618 return FALSE;
619 }
620 if (g_strcmp0(a->email, b->email) != 0)
621 {
622 PWARN("email addresses differ: %s vs %s", a->email, b->email);
623 return FALSE;
624 }
625
626 return TRUE;
627 }
628
629 static QofObject GncAddressDesc =
630 {
631 DI(.interface_version = ) QOF_OBJECT_VERSION,
632 DI(.e_type = ) GNC_ID_ADDRESS,
633 DI(.type_label = ) "Address",
634 DI(.create = ) (gpointer)qofAddressCreate,
635 DI(.book_begin = ) NULL,
636 DI(.book_end = ) NULL,
637 DI(.is_dirty = ) qof_collection_is_dirty,
638 DI(.mark_clean = ) qof_collection_mark_clean,
639 DI(.foreach = ) qof_collection_foreach,
640 DI(.printable = ) NULL,
641 DI(.version_cmp = ) (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
642 };
643
gncAddressRegister(void)644 gboolean gncAddressRegister (void)
645 {
646 static QofParam params[] =
647 {
648
649 { ADDRESS_NAME, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetName, (QofSetterFunc)gncAddressSetName },
650 { ADDRESS_ONE, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetAddr1, (QofSetterFunc)gncAddressSetAddr1 },
651 { ADDRESS_TWO, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetAddr2, (QofSetterFunc)gncAddressSetAddr2 },
652 { ADDRESS_THREE, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetAddr3, (QofSetterFunc)gncAddressSetAddr3 },
653 { ADDRESS_FOUR, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetAddr4, (QofSetterFunc)gncAddressSetAddr4 },
654 { ADDRESS_PHONE, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetPhone, (QofSetterFunc)gncAddressSetPhone },
655 { ADDRESS_FAX, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetFax, (QofSetterFunc)gncAddressSetFax },
656 { ADDRESS_EMAIL, QOF_TYPE_STRING, (QofAccessFunc)gncAddressGetEmail, (QofSetterFunc)gncAddressSetEmail },
657 { ADDRESS_OWNER, QOF_TYPE_CHOICE, (QofAccessFunc)qofAddressGetOwner, (QofSetterFunc)qofAddressSetOwner },
658 { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
659 { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
660 { NULL },
661 };
662
663 qof_class_register (GNC_ID_ADDRESS, (QofSortFunc)gncAddressCompare, params);
664 if (!qof_choice_add_class(GNC_ID_CUSTOMER, GNC_ID_ADDRESS, ADDRESS_OWNER))
665 {
666 return FALSE;
667 }
668
669 return qof_object_register(&GncAddressDesc);
670 }
671