00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027
00028 #include <gtk/gtk.h>
00029 #include <glib/gi18n.h>
00030
00031 #include "Account.h"
00032 #include "gnc-ui-util.h"
00033 #include "qof.h"
00034 #include "gnc-component-manager.h"
00035 #include "gnc-gtk-utils.h"
00036
00037 #include "gncCustomer.h"
00038 #include "gncJob.h"
00039 #include "gncVendor.h"
00040 #include "gncOwner.h"
00041 #include "gncInvoice.h"
00042
00043 #include "gnc-general-search.h"
00044 #include "gncObject.h"
00045 #include "business-gnome-utils.h"
00046 #include "dialog-customer.h"
00047 #include "dialog-job.h"
00048 #include "dialog-vendor.h"
00049 #include "dialog-employee.h"
00050 #include "dialog-invoice.h"
00051
00052 typedef enum {
00053 GNCSEARCH_TYPE_SELECT,
00054 GNCSEARCH_TYPE_EDIT
00055 } GNCSearchType;
00056
00057 static GtkWidget * gnc_owner_new (GtkWidget *label, GtkWidget *hbox,
00058 GNCBook *book, GncOwner *owner,
00059 GNCSearchType type)
00060 {
00061 GtkWidget *edit;
00062 GNCSearchCB search_cb = NULL;
00063 const char *type_name = NULL;
00064 const char *text = NULL;
00065
00066 switch (type) {
00067 case GNCSEARCH_TYPE_SELECT:
00068 text = _("Select...");
00069 break;
00070 case GNCSEARCH_TYPE_EDIT:
00071 text = _("Edit...");
00072 };
00073
00074 switch (owner->type) {
00075 case GNC_OWNER_NONE:
00076 case GNC_OWNER_UNDEFINED:
00077 return NULL;
00078
00079 case GNC_OWNER_CUSTOMER:
00080 if (type == GNCSEARCH_TYPE_SELECT)
00081 search_cb = gnc_customer_search_select;
00082 else
00083 search_cb = gnc_customer_search_edit;
00084 type_name = GNC_CUSTOMER_MODULE_NAME;
00085 break;
00086
00087 case GNC_OWNER_JOB:
00088 if (type == GNCSEARCH_TYPE_SELECT)
00089 search_cb = gnc_job_search_select;
00090 else
00091 search_cb = gnc_job_search_edit;
00092 type_name = GNC_JOB_MODULE_NAME;
00093 break;
00094
00095 case GNC_OWNER_VENDOR:
00096 if (type == GNCSEARCH_TYPE_SELECT)
00097 search_cb = gnc_vendor_search_select;
00098 else
00099 search_cb = gnc_vendor_search_edit;
00100 type_name = GNC_VENDOR_MODULE_NAME;
00101 break;
00102
00103 case GNC_OWNER_EMPLOYEE:
00104 if (type == GNCSEARCH_TYPE_SELECT)
00105 search_cb = gnc_employee_search_select;
00106 else
00107 search_cb = gnc_employee_search_edit;
00108 type_name = GNC_EMPLOYEE_MODULE_NAME;
00109 break;
00110
00111 default:
00112 g_warning ("Unknown type");
00113 return NULL;
00114 }
00115
00116 edit = gnc_general_search_new (type_name, text, search_cb, book);
00117 if (!edit)
00118 return NULL;
00119
00120 gnc_general_search_set_selected (GNC_GENERAL_SEARCH (edit),
00121 owner->owner.undefined);
00122 gtk_box_pack_start (GTK_BOX (hbox), edit, FALSE, FALSE, 0);
00123 if (label)
00124 gtk_label_set_text (GTK_LABEL (label), _(gncObjectGetTypeLabel (type_name)));
00125
00126 return edit;
00127 }
00128
00129 GtkWidget * gnc_owner_select_create (GtkWidget *label, GtkWidget *hbox,
00130 GNCBook *book, GncOwner *owner)
00131 {
00132 g_return_val_if_fail (hbox != NULL, NULL);
00133 g_return_val_if_fail (book != NULL, NULL);
00134 g_return_val_if_fail (owner != NULL, NULL);
00135
00136 return gnc_owner_new (label, hbox, book, owner, GNCSEARCH_TYPE_SELECT);
00137 }
00138
00139 GtkWidget * gnc_owner_edit_create (GtkWidget *label, GtkWidget *hbox,
00140 GNCBook *book, GncOwner *owner)
00141 {
00142 g_return_val_if_fail (hbox != NULL, NULL);
00143 g_return_val_if_fail (book != NULL, NULL);
00144 g_return_val_if_fail (owner != NULL, NULL);
00145
00146 return gnc_owner_new (label, hbox, book, owner, GNCSEARCH_TYPE_EDIT);
00147 }
00148
00149 void gnc_owner_get_owner (GtkWidget *widget, GncOwner *owner)
00150 {
00151 g_return_if_fail (widget != NULL);
00152 g_return_if_fail (owner != NULL);
00153
00154
00155
00156
00157 owner->owner.undefined =
00158 gnc_general_search_get_selected (GNC_GENERAL_SEARCH (widget));
00159 }
00160
00161 void gnc_owner_set_owner (GtkWidget *widget, GncOwner *owner)
00162 {
00163 g_return_if_fail (widget != NULL);
00164 g_return_if_fail (owner != NULL);
00165
00166
00167
00168
00169
00170 gnc_general_search_set_selected (GNC_GENERAL_SEARCH (widget),
00171 owner->owner.undefined);
00172 }
00173
00174 typedef struct _invoice_select_info {
00175 GtkWidget *label;
00176 GNCBook *book;
00177 GncOwner owner;
00178 gboolean have_owner;
00179 } GncISI;
00180
00181 static GNCSearchWindow *
00182 gnc_invoice_select_search_cb (gpointer start, gpointer isip)
00183 {
00184 GncISI *isi = isip;
00185
00186 if (!isi) return NULL;
00187 g_assert(isi->book);
00188
00189 return gnc_invoice_search (start,
00190 isi->have_owner ? &isi->owner : NULL,
00191 isi->book);
00192 }
00193
00194 static void
00195 gnc_invoice_select_search_set_label(GncISI* isi)
00196 {
00197 GncOwnerType owner_type;
00198 GncOwner *tmp;
00199 char *label;
00200
00201 g_assert(isi);
00202 if (!isi->label) return;
00203
00204 tmp = &isi->owner;
00205 owner_type = gncOwnerGetType(tmp);
00206 while (owner_type == GNC_OWNER_JOB) {
00207 tmp = gncOwnerGetEndOwner(tmp);
00208 owner_type = gncOwnerGetType(tmp);
00209 }
00210
00211
00212 switch (owner_type) {
00213 case GNC_OWNER_VENDOR:
00214 label = _("Bill");
00215 break;
00216 case GNC_OWNER_EMPLOYEE:
00217 label = _("Voucher");
00218 break;
00219 default:
00220 label = _("Invoice");
00221 }
00222
00223 gtk_label_set_text(GTK_LABEL(isi->label), label);
00224 }
00225
00226 GtkWidget * gnc_invoice_select_create (GtkWidget *hbox, GNCBook *book,
00227 const GncOwner *owner,
00228 GncInvoice *invoice,
00229 GtkWidget *label)
00230 {
00231 GtkWidget *edit;
00232 GncISI *isi;
00233
00234 g_return_val_if_fail (hbox != NULL, NULL);
00235 g_return_val_if_fail (book != NULL, NULL);
00236
00237
00238 isi = g_new0(GncISI, 1);
00239 if (!isi)
00240 return NULL;
00241
00242 if (owner) {
00243 gncOwnerCopy(owner, &isi->owner);
00244 isi->have_owner = TRUE;
00245 } else {
00246 gncOwnerInitCustomer(&isi->owner, NULL);
00247 }
00248 isi->book = book;
00249 isi->label = label;
00250
00251 edit = gnc_general_search_new (GNC_INVOICE_MODULE_NAME, _("Select..."),
00252 gnc_invoice_select_search_cb, isi);
00253 if (!edit) {
00254 g_free(isi);
00255 return NULL;
00256 }
00257
00258 gnc_general_search_set_selected (GNC_GENERAL_SEARCH (edit), invoice);
00259 gtk_box_pack_start (GTK_BOX (hbox), edit, FALSE, FALSE, 0);
00260 g_object_set_data_full(G_OBJECT(edit), "isi-state", isi, g_free);
00261
00262
00263 gnc_invoice_select_search_set_label(isi);
00264
00265 return edit;
00266 }
00267
00268 GncInvoice * gnc_invoice_get_invoice (GtkWidget *widget)
00269 {
00270 g_return_val_if_fail (widget != NULL, NULL);
00271
00272 return gnc_general_search_get_selected (GNC_GENERAL_SEARCH (widget));
00273 }
00274
00275 void gnc_invoice_set_invoice (GtkWidget *widget, GncInvoice *invoice)
00276 {
00277 g_return_if_fail (widget != NULL);
00278 g_return_if_fail (invoice != NULL);
00279
00280 gnc_general_search_set_selected (GNC_GENERAL_SEARCH (widget), invoice);
00281 }
00282
00283 void gnc_invoice_set_owner (GtkWidget *widget, GncOwner *owner)
00284 {
00285 GncISI *isi;
00286
00287 g_return_if_fail (widget != NULL);
00288 g_return_if_fail (owner != NULL);
00289
00290 isi = g_object_get_data(G_OBJECT(widget), "isi-state");
00291 g_assert(isi);
00292
00293 if (isi->owner.owner.undefined == owner->owner.undefined)
00294 return;
00295
00296 gncOwnerCopy(owner, &isi->owner);
00297 isi->have_owner = TRUE;
00298 gnc_general_search_set_selected(GNC_GENERAL_SEARCH(widget), NULL);
00299
00300
00301 gnc_invoice_select_search_set_label(isi);
00302 }
00303
00304 void
00305 gnc_fill_account_select_combo (GtkWidget *combo, GNCBook *book,
00306 GList *acct_types)
00307 {
00308 GtkListStore *store;
00309 GtkEntry *entry;
00310 GList *list, *node;
00311 char *text;
00312
00313 g_return_if_fail (combo && GTK_IS_COMBO_BOX_ENTRY(combo));
00314 g_return_if_fail (book);
00315 g_return_if_fail (acct_types);
00316
00317
00318 text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
00319
00320 list = gnc_account_get_descendants (gnc_book_get_root_account (book));
00321
00322
00323 entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo)));
00324 gtk_entry_set_text(entry, "");
00325 store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
00326 gtk_list_store_clear(store);
00327
00328
00329 for (node = list; node; node = node->next) {
00330 Account *account = node->data;
00331 char *name;
00332
00333
00334 if (g_list_index (acct_types, (gpointer)xaccAccountGetType (account))
00335 == -1)
00336 continue;
00337
00338 name = xaccAccountGetFullName (account);
00339 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), name);
00340 g_free(name);
00341 }
00342 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
00343
00344 g_list_free (list);
00345
00346 gnc_cbe_set_by_string(GTK_COMBO_BOX_ENTRY(combo), text);
00347
00348 if (text)
00349 g_free (text);
00350 }
00351
00352 GList *
00353 gnc_business_account_types (GncOwner *owner)
00354 {
00355 g_return_val_if_fail (owner, NULL);
00356
00357 switch (gncOwnerGetType (owner)) {
00358 case GNC_OWNER_CUSTOMER:
00359 return (g_list_prepend (NULL, (gpointer)ACCT_TYPE_RECEIVABLE));
00360 case GNC_OWNER_VENDOR:
00361 case GNC_OWNER_EMPLOYEE:
00362 return (g_list_prepend (NULL, (gpointer)ACCT_TYPE_PAYABLE));
00363 break;
00364 default:
00365 return (g_list_prepend (NULL, (gpointer)ACCT_TYPE_NONE));
00366 }
00367 }
00368
00369
00370
00371
00372 typedef const char * (*GenericLookup_t)(gpointer);
00373
00374 typedef struct {
00375 gint component_id;
00376 GtkWidget * omenu;
00377 GNCBook * book;
00378 gboolean none_ok;
00379 const char * (*get_name)(gpointer);
00380 GList * (*get_list)(GNCBook*);
00381
00382 gboolean building_menu;
00383 gpointer result;
00384 gpointer * result_p;
00385
00386 void (*changed_cb)(GtkWidget*, gpointer);
00387 gpointer cb_arg;
00388 } OpMenuData;
00389
00390 #define DO_ADD_ITEM(s,o) { \
00391 add_menu_item (menu, (s), omd, (o)); \
00392 if (omd->result == (o)) current = index; \
00393 index++; \
00394 }
00395
00396 static void
00397 business_option_changed (GtkWidget *widget, gpointer data)
00398 {
00399 OpMenuData *omd = data;
00400
00401 g_return_if_fail (omd);
00402 omd->result = g_object_get_data (G_OBJECT (widget), "this_item");
00403
00404 if (!omd->building_menu) {
00405 if (omd->result_p)
00406 *(omd->result_p) = omd->result;
00407
00408 if (omd->changed_cb)
00409 (omd->changed_cb)(omd->omenu, omd->cb_arg);
00410 }
00411 }
00412
00413 static void
00414 add_menu_item (GtkWidget *menu, const char *label, OpMenuData *omd,
00415 gpointer this_item)
00416 {
00417 GtkWidget *item = gtk_menu_item_new_with_label (label);
00418 g_object_set_data (G_OBJECT (item), "this_item", this_item);
00419 g_signal_connect (G_OBJECT (item), "activate",
00420 G_CALLBACK (business_option_changed), omd);
00421 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
00422 gtk_widget_show (item);
00423 }
00424
00425 static void
00426 generic_omenu_destroy_cb (GtkWidget *widget, gpointer data)
00427 {
00428 OpMenuData *omd = data;
00429
00430 gnc_unregister_gui_component (omd->component_id);
00431 g_free (omd);
00432 }
00433
00434 static void
00435 build_generic_optionmenu (OpMenuData *omd)
00436 {
00437 GList *items;
00438 GtkWidget *menu;
00439 int current = 0, index = 0;
00440
00441
00442 if (omd->get_list == NULL)
00443 return;
00444
00445
00446 items = (omd->get_list)(omd->book);
00447
00448
00449 menu = gtk_menu_new ();
00450
00451 omd->building_menu = TRUE;
00452
00453 if (omd->none_ok || items == NULL)
00454 DO_ADD_ITEM (_("None"), NULL);
00455
00456 for ( ; items; items = items->next)
00457 DO_ADD_ITEM ((omd->get_name)(items->data), items->data);
00458
00459 gtk_option_menu_set_menu (GTK_OPTION_MENU (omd->omenu), menu);
00460 gtk_option_menu_set_history (GTK_OPTION_MENU (omd->omenu), current);
00461 gtk_widget_show (menu);
00462
00463 omd->building_menu = FALSE;
00464 }
00465
00466 static void
00467 generic_omenu_refresh_handler (GHashTable *changes, gpointer user_data)
00468 {
00469 OpMenuData *omd = user_data;
00470 build_generic_optionmenu (omd);
00471 }
00472
00473 static OpMenuData *
00474 make_generic_optionmenu (GtkWidget *omenu, GNCBook *book,
00475 gboolean none_ok, GNCIdType type_name,
00476 GList * (*get_list)(GNCBook*),
00477 GenericLookup_t get_name,
00478 gpointer *result)
00479 {
00480 OpMenuData *omd;
00481
00482 omd = g_object_get_data (G_OBJECT (omenu), "menu-data");
00483
00484
00485
00486
00487
00488
00489 if (!omd) {
00490 omd = g_new0 (OpMenuData, 1);
00491 omd->omenu = omenu;
00492 omd->book = book;
00493 omd->result_p = result;
00494 omd->none_ok = none_ok;
00495 omd->get_name = get_name;
00496 omd->get_list = get_list;
00497 g_object_set_data (G_OBJECT (omenu), "menu-data", omd);
00498
00499 if (result)
00500 omd->result = *result;
00501
00502 omd->component_id =
00503 gnc_register_gui_component ("generic-omenu-refresh-hook",
00504 generic_omenu_refresh_handler,
00505 NULL, omd);
00506
00507
00508 if (type_name)
00509 gnc_gui_component_watch_entity_type (omd->component_id,
00510 type_name,
00511 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
00512
00513 g_signal_connect (G_OBJECT (omenu), "destroy",
00514 G_CALLBACK (generic_omenu_destroy_cb), omd);
00515
00516 }
00517
00518 build_generic_optionmenu (omd);
00519
00520 return omd;
00521 }
00522
00523 void
00524 gnc_ui_optionmenu_set_changed_callback (GtkWidget *omenu,
00525 void (*changed_cb)(GtkWidget*,gpointer),
00526 gpointer cb_arg)
00527 {
00528 OpMenuData *omd;
00529
00530 if (!omenu) return;
00531
00532 omd = g_object_get_data (G_OBJECT (omenu), "menu-data");
00533 g_return_if_fail (omd);
00534
00535 omd->changed_cb = changed_cb;
00536 omd->cb_arg = cb_arg;
00537 }
00538
00539 gpointer
00540 gnc_ui_optionmenu_get_value (GtkWidget *omenu)
00541 {
00542 OpMenuData *omd;
00543
00544 if (!omenu) return NULL;
00545
00546 omd = g_object_get_data (G_OBJECT (omenu), "menu-data");
00547 g_return_val_if_fail (omd, NULL);
00548
00549 return omd->result;
00550 }
00551
00552 void
00553 gnc_ui_optionmenu_set_value (GtkWidget *omenu, gpointer data)
00554 {
00555 OpMenuData *omd;
00556 GtkWidget *menu;
00557 GList *node;
00558 gint counter;
00559
00560 if (!omenu) return;
00561
00562 omd = g_object_get_data (G_OBJECT (omenu), "menu-data");
00563 g_return_if_fail (omd);
00564
00565 menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (omenu));
00566 g_return_if_fail (menu);
00567
00568
00569 for (counter = 0, node = ((GTK_MENU_SHELL (menu))->children);
00570 node;
00571 node = node->next, counter++)
00572 {
00573 GObject *menuitem = node->data;
00574 gpointer this_object = g_object_get_data (menuitem, "this_item");
00575
00576 if (this_object == data) {
00577 gtk_option_menu_set_history (GTK_OPTION_MENU (omd->omenu), counter);
00578 return;
00579 }
00580 }
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590 void
00591 gnc_ui_billterms_optionmenu (GtkWidget *omenu, GNCBook *book,
00592 gboolean none_ok, GncBillTerm **choice)
00593 {
00594 if (!omenu || !book) return;
00595
00596 make_generic_optionmenu (omenu, book, none_ok, GNC_BILLTERM_MODULE_NAME,
00597 gncBillTermGetTerms,
00598 (GenericLookup_t)gncBillTermGetName,
00599 (gpointer *)choice);
00600 }
00601
00602 void
00603 gnc_ui_taxtables_optionmenu (GtkWidget *omenu, GNCBook *book,
00604 gboolean none_ok, GncTaxTable **choice)
00605 {
00606 if (!omenu || !book) return;
00607
00608 make_generic_optionmenu (omenu, book, none_ok, GNC_TAXTABLE_MODULE_NAME,
00609 gncTaxTableGetTables,
00610 (GenericLookup_t)gncTaxTableGetName,
00611 (gpointer *)choice);
00612 }
00613
00614 void
00615 gnc_ui_taxincluded_optionmenu (GtkWidget *omenu, GncTaxIncluded *choice)
00616 {
00617 GtkWidget *menu;
00618 OpMenuData *omd;
00619 int current = 0, index = 0;
00620
00621 if (!omenu) return;
00622
00623 omd = make_generic_optionmenu (omenu, NULL, FALSE, NULL, NULL, NULL,
00624 (gpointer *)choice);
00625
00626 g_return_if_fail (omd);
00627
00628 menu = gtk_menu_new ();
00629
00630 add_menu_item (menu, _("Yes"), omd,
00631 GINT_TO_POINTER (GNC_TAXINCLUDED_YES));
00632 if (*choice == GNC_TAXINCLUDED_YES) current = index;
00633 index++;
00634
00635 add_menu_item (menu, _("No"), omd,
00636 GINT_TO_POINTER (GNC_TAXINCLUDED_NO));
00637 if (*choice == GNC_TAXINCLUDED_NO) current = index;
00638 index++;
00639
00640 add_menu_item (menu, _("Use Global"), omd,
00641 GINT_TO_POINTER (GNC_TAXINCLUDED_USEGLOBAL));
00642 if (*choice == GNC_TAXINCLUDED_USEGLOBAL) current = index;
00643 index++;
00644
00645 gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu);
00646 gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), current);
00647 gtk_widget_show (menu);
00648 }