GnuCash  5.6-150-g038405b370+
dialog-customer.c
1 /*
2  * dialog-customer.c -- Dialog for Customer entry
3  * Copyright (C) 2001 Derek Atkins
4  * Author: Derek Atkins <warlord@MIT.EDU>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, contact:
18  *
19  * Free Software Foundation Voice: +1-617-542-5942
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
21  * Boston, MA 02110-1301, USA gnu@gnu.org
22  */
23 
24 #include <config.h>
25 
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 
30 #include "dialog-utils.h"
31 #include "gnc-amount-edit.h"
32 #include "gnc-currency-edit.h"
33 #include "gnc-component-manager.h"
34 #include "gnc-ui.h"
35 #include "gnc-gui-query.h"
36 #include "gnc-ui-util.h"
37 #include "qof.h"
38 
39 #include "dialog-search.h"
40 #include "search-param.h"
41 #include "QuickFill.h"
42 #include "gnc-addr-quickfill.h"
43 
44 #include "gncAddress.h"
45 #include "gncCustomer.h"
46 #include "gncCustomerP.h"
47 
48 #include "business-gnome-utils.h"
49 #include "dialog-customer.h"
50 #include "dialog-job.h"
51 #include "dialog-order.h"
52 #include "dialog-invoice.h"
53 #include "dialog-payment.h"
54 
55 #define DIALOG_NEW_CUSTOMER_CM_CLASS "dialog-new-customer"
56 #define DIALOG_EDIT_CUSTOMER_CM_CLASS "dialog-edit-customer"
57 
58 #define GNC_PREFS_GROUP_SEARCH "dialogs.business.customer-search"
59 
60 void gnc_customer_taxtable_check_cb (GtkToggleButton *togglebutton,
61  gpointer user_data);
62 
63 void gnc_customer_window_ok_cb (GtkWidget *widget, gpointer data);
64 void gnc_customer_window_cancel_cb (GtkWidget *widget, gpointer data);
65 void gnc_customer_window_help_cb (GtkWidget *widget, gpointer data);
66 void gnc_customer_window_destroy_cb (GtkWidget *widget, gpointer data);
67 void gnc_customer_name_changed_cb (GtkWidget *widget, gpointer data);
68 void gnc_customer_terms_changed_cb (GtkWidget *widget, gpointer data);
69 void gnc_customer_taxincluded_changed_cb (GtkWidget *widget, gpointer data);
70 void gnc_customer_taxtable_changed_cb (GtkWidget *widget, gpointer data);
71 void gnc_customer_addr2_insert_cb(GtkEditable *editable,
72  gchar *new_text, gint new_text_length,
73  gint *position, gpointer user_data);
74 void gnc_customer_addr3_insert_cb(GtkEditable *editable,
75  gchar *new_text, gint new_text_length,
76  gint *position, gpointer user_data);
77 void gnc_customer_addr4_insert_cb(GtkEditable *editable,
78  gchar *new_text, gint new_text_length,
79  gint *position, gpointer user_data);
80 void gnc_customer_shipaddr2_insert_cb(GtkEditable *editable,
81  gchar *new_text, gint new_text_length,
82  gint *position, gpointer user_data);
83 void gnc_customer_shipaddr3_insert_cb(GtkEditable *editable,
84  gchar *new_text, gint new_text_length,
85  gint *position, gpointer user_data);
86 void gnc_customer_shipaddr4_insert_cb(GtkEditable *editable,
87  gchar *new_text, gint new_text_length,
88  gint *position, gpointer user_data);
89 gboolean
90 gnc_customer_addr2_key_press_cb( GtkEntry *entry, GdkEventKey *event,
91  gpointer user_data );
92 gboolean
93 gnc_customer_addr3_key_press_cb( GtkEntry *entry, GdkEventKey *event,
94  gpointer user_data );
95 gboolean
96 gnc_customer_addr4_key_press_cb( GtkEntry *entry, GdkEventKey *event,
97  gpointer user_data );
98 gboolean
99 gnc_customer_shipaddr2_key_press_cb( GtkEntry *entry, GdkEventKey *event,
100  gpointer user_data );
101 gboolean
102 gnc_customer_shipaddr3_key_press_cb( GtkEntry *entry, GdkEventKey *event,
103  gpointer user_data );
104 gboolean
105 gnc_customer_shipaddr4_key_press_cb( GtkEntry *entry, GdkEventKey *event,
106  gpointer user_data );
107 
108 #define ADDR_QUICKFILL "GncAddress-Quickfill"
109 
110 typedef enum
111 {
112  NEW_CUSTOMER,
113  EDIT_CUSTOMER
114 } CustomerDialogType;
115 
117 {
118  QofBook *book;
119  QofQuery *q;
120 };
121 
123 {
124  GtkWidget * dialog;
125 
126  GtkWidget * id_entry;
127  GtkWidget * company_entry;
128 
129  GtkWidget * name_entry;
130  GtkWidget * addr1_entry;
131  GtkWidget * addr2_entry;
132  GtkWidget * addr3_entry;
133  GtkWidget * addr4_entry;
134  GtkWidget * phone_entry;
135  GtkWidget * fax_entry;
136  GtkWidget * email_entry;
137 
138  GtkWidget * shipname_entry;
139  GtkWidget * shipaddr1_entry;
140  GtkWidget * shipaddr2_entry;
141  GtkWidget * shipaddr3_entry;
142  GtkWidget * shipaddr4_entry;
143  GtkWidget * shipphone_entry;
144  GtkWidget * shipfax_entry;
145  GtkWidget * shipemail_entry;
146 
147  GtkWidget * currency_edit;
148  GtkWidget * terms_menu;
149  GtkWidget * discount_amount;
150  GtkWidget * credit_amount;
151 
152  GtkWidget * active_check;
153  GtkWidget * taxincluded_menu;
154  GtkWidget * notes_text;
155 
156  GtkWidget * taxtable_check;
157  GtkWidget * taxtable_menu;
158 
159  GncTaxIncluded taxincluded;
160  GncBillTerm * terms;
161  CustomerDialogType dialog_type;
162  GncGUID customer_guid;
163  gint component_id;
164  QofBook * book;
165  GncCustomer * created_customer;
166 
167  GncTaxTable * taxtable;
168 
169  /* stored data for the description quickfill selection function */
170  QuickFill *addr2_quickfill;
171  QuickFill *addr3_quickfill;
172  QuickFill *addr4_quickfill;
173  gint addrX_start_selection;
174  gint addrX_end_selection;
175  guint addrX_selection_source_id;
176 };
177 
178 void
179 gnc_customer_taxtable_check_cb (GtkToggleButton *togglebutton,
180  gpointer user_data)
181 {
182  CustomerWindow *cw = user_data;
183 
184  if (gtk_toggle_button_get_active (togglebutton))
185  gtk_widget_set_sensitive (cw->taxtable_menu, TRUE);
186  else
187  gtk_widget_set_sensitive (cw->taxtable_menu, FALSE);
188 }
189 
190 static GncCustomer *
191 cw_get_customer (CustomerWindow *cw)
192 {
193  if (!cw)
194  return NULL;
195 
196  return gncCustomerLookup (cw->book, &cw->customer_guid);
197 }
198 
199 static void gnc_ui_to_customer (CustomerWindow *cw, GncCustomer *cust)
200 {
201  GtkTextBuffer* text_buffer;
202  GtkTextIter start, end;
203  gchar *text;
204  GncAddress *addr, *shipaddr;
205 
206  addr = gncCustomerGetAddr (cust);
207  shipaddr = gncCustomerGetShipAddr (cust);
208 
209  gnc_suspend_gui_refresh ();
210 
211  gncCustomerBeginEdit (cust);
212 
213  if (cw->dialog_type == NEW_CUSTOMER)
214  qof_event_gen(QOF_INSTANCE(cust), QOF_EVENT_ADD, NULL);
215 
216  gncCustomerSetID (cust, gtk_entry_get_text (GTK_ENTRY (cw->id_entry)));
217  gncCustomerSetName (cust, gtk_entry_get_text (GTK_ENTRY (cw->company_entry)));
218 
219  gncAddressSetName (addr, gtk_entry_get_text (GTK_ENTRY (cw->name_entry)));
220  gncAddressSetAddr1 (addr, gtk_entry_get_text (GTK_ENTRY (cw->addr1_entry)));
221  gncAddressSetAddr2 (addr, gtk_entry_get_text (GTK_ENTRY (cw->addr2_entry)));
222  gncAddressSetAddr3 (addr, gtk_entry_get_text (GTK_ENTRY (cw->addr3_entry)));
223  gncAddressSetAddr4 (addr, gtk_entry_get_text (GTK_ENTRY (cw->addr4_entry)));
224  gncAddressSetPhone (addr, gtk_entry_get_text (GTK_ENTRY (cw->phone_entry)));
225  gncAddressSetFax (addr, gtk_entry_get_text (GTK_ENTRY (cw->fax_entry)));
226  gncAddressSetEmail (addr, gtk_entry_get_text (GTK_ENTRY (cw->email_entry)));
227  gncAddressSetName (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipname_entry)));
228  gncAddressSetAddr1 (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipaddr1_entry)));
229  gncAddressSetAddr2 (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipaddr2_entry)));
230  gncAddressSetAddr3 (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipaddr3_entry)));
231  gncAddressSetAddr4 (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipaddr4_entry)));
232  gncAddressSetPhone (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipphone_entry)));
233  gncAddressSetFax (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipfax_entry)));
234  gncAddressSetEmail (shipaddr, gtk_entry_get_text (GTK_ENTRY (cw->shipemail_entry)));
235 
236  gncCustomerSetActive (cust, gtk_toggle_button_get_active
237  (GTK_TOGGLE_BUTTON (cw->active_check)));
238  gncCustomerSetTaxIncluded (cust, cw->taxincluded);
239 
240  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(cw->notes_text));
241  gtk_text_buffer_get_bounds (text_buffer, &start, &end);
242  text = gtk_text_buffer_get_text (text_buffer, &start, &end, FALSE);
243  gncCustomerSetNotes (cust, text);
244 
245  /* Parse and set the currency, terms, discount, and credit amounts */
246  gncCustomerSetCurrency (cust,
247  gnc_currency_edit_get_currency (GNC_CURRENCY_EDIT
248  (cw->currency_edit)));
249  gncCustomerSetTerms (cust, cw->terms);
250  gncCustomerSetDiscount (cust, gnc_amount_edit_get_amount
251  (GNC_AMOUNT_EDIT (cw->discount_amount)));
252  gncCustomerSetCredit (cust, gnc_amount_edit_get_amount
253  (GNC_AMOUNT_EDIT (cw->credit_amount)));
254 
255  gncCustomerSetTaxTableOverride
256  (cust, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cw->taxtable_check)));
257  gncCustomerSetTaxTable (cust, cw->taxtable);
258 
259  gncCustomerCommitEdit (cust);
260  gnc_resume_gui_refresh ();
261  g_free (text);
262 }
263 
264 static gboolean check_edit_amount (GtkWidget *amount,
265  gnc_numeric *min, gnc_numeric *max,
266  const char * error_message)
267 {
268  GError *error = NULL;
269  if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (amount), &error))
270  {
271  gnc_error_dialog (gnc_ui_get_gtk_window (amount), "%s", error->message);
272  g_error_free (error);
273  return TRUE;
274  }
275  /* We've got a valid-looking number; check mix/max */
276  if (min || max)
277  {
278  gnc_numeric val = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (amount));
279  if ((min && gnc_numeric_compare (*min, val) > 0) ||
280  (max && gnc_numeric_compare (val, *max) > 0))
281  {
282  if (error_message)
283  gnc_error_dialog (gnc_ui_get_gtk_window (amount), "%s", error_message);
284  return TRUE;
285  }
286  }
287  return FALSE;
288 }
289 
290 static gboolean check_entry_nonempty (GtkWidget *entry,
291  const char * error_message)
292 {
293  const char *res = gtk_entry_get_text (GTK_ENTRY (entry));
294  if (g_strcmp0 (res, "") == 0)
295  {
296  if (error_message)
297  gnc_error_dialog (gnc_ui_get_gtk_window (entry), "%s", error_message);
298  return TRUE;
299  }
300  return FALSE;
301 }
302 
303 void
304 gnc_customer_window_ok_cb (GtkWidget *widget, gpointer data)
305 {
306  CustomerWindow *cw = data;
307  gnc_numeric min, max;
308  gchar *string;
309  gnc_commodity *currency;
310  GNCPrintAmountInfo print_info;
311 
312  /* Check for valid company name */
313  if (check_entry_nonempty (cw->company_entry,
314  _("The Company Name field cannot be left blank, please "
315  "enter a company name or a person's name.")))
316  return;
317 
318  /* Verify terms, discount, and credit are valid (or empty) */
319  min = gnc_numeric_zero ();
320  max = gnc_numeric_create (100, 1);
321 
322  if (check_edit_amount (cw->discount_amount, &min, &max,
323  _("Discount percentage must be between 0-100 "
324  "or you must leave it blank.")))
325  return;
326 
327  currency = gnc_currency_edit_get_currency (GNC_CURRENCY_EDIT(cw->currency_edit));
328  print_info = gnc_commodity_print_info (currency, FALSE);
329  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (cw->credit_amount), print_info);
330  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (cw->credit_amount),
331  gnc_commodity_get_fraction (currency));
332 
333  if (check_edit_amount (cw->credit_amount, &min, NULL,
334  _("Credit must be a positive amount or "
335  "you must leave it blank.")))
336  return;
337 
338  /* Set the customer id if one has not been chosen */
339  if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (cw->id_entry)), "") == 0)
340  {
341  string = gncCustomerNextID (cw->book);
342  gtk_entry_set_text (GTK_ENTRY (cw->id_entry), string);
343  g_free(string);
344  }
345 
346  /* Now save it off */
347  {
348  GncCustomer *customer = cw_get_customer (cw);
349  if (customer)
350  {
351  gnc_ui_to_customer (cw, customer);
352  }
353  cw->created_customer = customer;
354  cw->customer_guid = *guid_null ();
355  }
356 
357  gnc_close_gui_component (cw->component_id);
358 }
359 
360 void
361 gnc_customer_window_cancel_cb (GtkWidget *widget, gpointer data)
362 {
363  CustomerWindow *cw = data;
364 
365  gnc_close_gui_component (cw->component_id);
366 }
367 
368 void
369 gnc_customer_window_help_cb (GtkWidget *widget, gpointer data)
370 {
371  CustomerWindow *cw = data;
372  gnc_gnome_help (GTK_WINDOW(cw->dialog), DF_MANUAL, DL_USAGE_CUSTOMER);
373 }
374 
375 void
376 gnc_customer_window_destroy_cb (GtkWidget *widget, gpointer data)
377 {
378  CustomerWindow *cw = data;
379  GncCustomer *customer = cw_get_customer (cw);
380 
381  gnc_suspend_gui_refresh ();
382 
383  if (cw->dialog_type == NEW_CUSTOMER && customer != NULL)
384  {
385  gncCustomerBeginEdit (customer);
386  gncCustomerDestroy (customer);
387  cw->customer_guid = *guid_null ();
388  }
389 
390  if (cw->addrX_selection_source_id)
391  g_source_remove (cw->addrX_selection_source_id);
392 
393  gnc_unregister_gui_component (cw->component_id);
394  gnc_resume_gui_refresh ();
395 
396  g_free (cw);
397 }
398 
399 void
400 gnc_customer_name_changed_cb (GtkWidget *widget, gpointer data)
401 {
402  CustomerWindow *cw = data;
403  if (!cw)
404  return;
405 
406  gnc_owner_window_set_title (GTK_WINDOW (cw->dialog),
407  (cw->dialog_type == EDIT_CUSTOMER) ?
408  _("Edit Customer") : _("New Customer"),
409  cw->company_entry, cw->id_entry);
410 }
411 
412 void
413 gnc_customer_terms_changed_cb (GtkWidget *widget, gpointer data)
414 {
415  GtkComboBox *cbox = GTK_COMBO_BOX (widget);
416  CustomerWindow *cw = data;
417 
418  if (!cw) return;
419  if (!cbox) return;
420 
421  cw->terms = gnc_simple_combo_get_value (cbox);
422 }
423 
424 void
425 gnc_customer_taxincluded_changed_cb (GtkWidget *widget, gpointer data)
426 {
427  GtkComboBox *cbox = GTK_COMBO_BOX (widget);
428  CustomerWindow *cw = data;
429 
430  if (!cw) return;
431  if (!cbox) return;
432 
433  cw->taxincluded = GPOINTER_TO_INT (gnc_simple_combo_get_value (cbox));
434 }
435 
436 void
437 gnc_customer_taxtable_changed_cb (GtkWidget *widget, gpointer data)
438 {
439  GtkComboBox *cbox = GTK_COMBO_BOX (widget);
440  CustomerWindow *cw = data;
441 
442  if (!cw) return;
443  if (!cbox) return;
444 
445  cw->taxtable = gnc_simple_combo_get_value (cbox);
446 }
447 
448 static void
449 gnc_customer_window_close_handler (gpointer user_data)
450 {
451  CustomerWindow *cw = user_data;
452 
453  gtk_widget_destroy (cw->dialog);
454  // cw has already been freed by this point.
455  // cw->dialog = NULL;
456 }
457 
458 static void
459 gnc_customer_window_refresh_handler (GHashTable *changes, gpointer user_data)
460 {
461  CustomerWindow *cw = user_data;
462  const EventInfo *info;
463  GncCustomer *customer = cw_get_customer (cw);
464 
465  /* If there isn't a customer behind us, close down */
466  if (!customer)
467  {
468  gnc_close_gui_component (cw->component_id);
469  return;
470  }
471 
472  /* Next, close if this is a destroy event */
473  if (changes)
474  {
475  info = gnc_gui_get_entity_events (changes, &cw->customer_guid);
476  if (info && (info->event_mask & QOF_EVENT_DESTROY))
477  {
478  gnc_close_gui_component (cw->component_id);
479  return;
480  }
481  }
482 }
483 
484 static gboolean
485 find_handler (gpointer find_data, gpointer user_data)
486 {
487  const GncGUID *customer_guid = find_data;
488  CustomerWindow *cw = user_data;
489 
490  return(cw && guid_equal(&cw->customer_guid, customer_guid));
491 }
492 
493 static CustomerWindow *
494 gnc_customer_new_window (GtkWindow *parent, QofBook *bookp, GncCustomer *cust)
495 {
496  CustomerWindow *cw;
497  GtkBuilder *builder;
498  GtkWidget *hbox, *edit;
499  gnc_commodity *currency;
500  GNCPrintAmountInfo print_info;
501 
502  /*
503  * Find an existing window for this customer. If found, bring it to
504  * the front.
505  */
506  if (cust)
507  {
508  GncGUID customer_guid;
509 
510  customer_guid = *gncCustomerGetGUID(cust);
511  cw = gnc_find_first_gui_component (DIALOG_EDIT_CUSTOMER_CM_CLASS,
512  find_handler, &customer_guid);
513  if (cw)
514  {
515  gtk_window_set_transient_for (GTK_WINDOW(cw->dialog), parent);
516  gtk_window_present (GTK_WINDOW(cw->dialog));
517  return(cw);
518  }
519  }
520 
521  /* Find the default currency */
522  if (cust)
523  currency = gncCustomerGetCurrency (cust);
524  else
525  currency = gnc_default_currency ();
526 
527  /*
528  * No existing customer window found. Build a new one.
529  */
530  cw = g_new0 (CustomerWindow, 1);
531 
532  cw->book = bookp;
533 
534  /* Find the dialog */
535  builder = gtk_builder_new();
536  gnc_builder_add_from_file (builder, "dialog-customer.glade", "terms_store");
537  gnc_builder_add_from_file (builder, "dialog-customer.glade", "tax_included_store");
538  gnc_builder_add_from_file (builder, "dialog-customer.glade", "taxtable_store");
539  gnc_builder_add_from_file (builder, "dialog-customer.glade", "customer_dialog");
540  cw->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "customer_dialog"));
541  gtk_window_set_transient_for (GTK_WINDOW(cw->dialog), parent);
542 
543  // Set the name for this dialog so it can be easily manipulated with css
544  gtk_widget_set_name (GTK_WIDGET(cw->dialog), "gnc-id-customer");
545  gnc_widget_style_context_add_class (GTK_WIDGET(cw->dialog), "gnc-class-customers");
546 
547  g_object_set_data (G_OBJECT (cw->dialog), "dialog_info", cw);
548 
549  /* Get entry points */
550  cw->id_entry = GTK_WIDGET (gtk_builder_get_object (builder, "id_entry"));
551  cw->company_entry = GTK_WIDGET (gtk_builder_get_object (builder, "company_entry"));
552 
553  cw->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry"));
554  cw->addr1_entry = GTK_WIDGET (gtk_builder_get_object (builder, "addr1_entry"));
555  cw->addr2_entry = GTK_WIDGET (gtk_builder_get_object (builder, "addr2_entry"));
556  cw->addr3_entry = GTK_WIDGET (gtk_builder_get_object (builder, "addr3_entry"));
557  cw->addr4_entry = GTK_WIDGET (gtk_builder_get_object (builder, "addr4_entry"));
558  cw->phone_entry = GTK_WIDGET (gtk_builder_get_object (builder, "phone_entry"));
559  cw->fax_entry = GTK_WIDGET (gtk_builder_get_object (builder, "fax_entry"));
560  cw->email_entry = GTK_WIDGET (gtk_builder_get_object (builder, "email_entry"));
561 
562  cw->shipname_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipname_entry"));
563  cw->shipaddr1_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipaddr1_entry"));
564  cw->shipaddr2_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipaddr2_entry"));
565  cw->shipaddr3_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipaddr3_entry"));
566  cw->shipaddr4_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipaddr4_entry"));
567  cw->shipphone_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipphone_entry"));
568  cw->shipfax_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipfax_entry"));
569  cw->shipemail_entry = GTK_WIDGET (gtk_builder_get_object (builder, "shipemail_entry"));
570 
571  cw->active_check = GTK_WIDGET (gtk_builder_get_object (builder, "active_check"));
572  cw->taxincluded_menu = GTK_WIDGET (gtk_builder_get_object (builder, "tax_included_menu"));
573  cw->notes_text = GTK_WIDGET (gtk_builder_get_object (builder, "notes_text"));
574 
575  cw->terms_menu = GTK_WIDGET (gtk_builder_get_object (builder, "terms_menu"));
576 
577  cw->taxtable_check = GTK_WIDGET (gtk_builder_get_object (builder, "taxtable_button"));
578  cw->taxtable_menu = GTK_WIDGET (gtk_builder_get_object (builder, "taxtable_menu"));
579 
580  /* Currency */
581  edit = gnc_currency_edit_new();
582  gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(edit), currency);
583  cw->currency_edit = edit;
584 
585  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "currency_box"));
586  gtk_box_pack_start (GTK_BOX (hbox), edit, TRUE, TRUE, 0);
587 
588  /* DISCOUNT: Percentage Value */
589  edit = gnc_amount_edit_new();
590  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (edit), TRUE);
591  print_info = gnc_integral_print_info ();
592  print_info.max_decimal_places = 5;
593  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (edit), print_info);
594  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (edit), 100000);
595  cw->discount_amount = edit;
596  gtk_widget_show (edit);
597 
598  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "discount_box"));
599  gtk_box_pack_start (GTK_BOX (hbox), edit, TRUE, TRUE, 0);
600 
601  /* CREDIT: Monetary Value */
602  edit = gnc_amount_edit_new();
603  print_info = gnc_commodity_print_info (currency, FALSE);
604  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (edit), TRUE);
605  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (edit), print_info);
606  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (edit),
607  gnc_commodity_get_fraction (currency));
608  cw->credit_amount = edit;
609  gtk_widget_show (edit);
610 
611  hbox = GTK_WIDGET (gtk_builder_get_object (builder, "credit_box"));
612  gtk_box_pack_start (GTK_BOX (hbox), edit, TRUE, TRUE, 0);
613 
614  /* Setup signals */
615  gtk_builder_connect_signals_full( builder,
616  gnc_builder_connect_full_func,
617  cw);
618 
619  /* Setup initial values */
620  if (cust != NULL)
621  {
622  GtkTextBuffer* text_buffer;
623  GncAddress *addr, *shipaddr;
624  const char *string;
625 
626  cw->dialog_type = EDIT_CUSTOMER;
627  cw->customer_guid = *gncCustomerGetGUID (cust);
628 
629  addr = gncCustomerGetAddr (cust);
630  shipaddr = gncCustomerGetShipAddr (cust);
631 
632  gtk_entry_set_text (GTK_ENTRY (cw->id_entry), gncCustomerGetID (cust));
633  gtk_entry_set_text (GTK_ENTRY (cw->company_entry), gncCustomerGetName (cust));
634 
635  /* Setup Address */
636  gtk_entry_set_text (GTK_ENTRY (cw->name_entry), gncAddressGetName (addr));
637  gtk_entry_set_text (GTK_ENTRY (cw->addr1_entry), gncAddressGetAddr1 (addr));
638  gtk_entry_set_text (GTK_ENTRY (cw->addr2_entry), gncAddressGetAddr2 (addr));
639  gtk_entry_set_text (GTK_ENTRY (cw->addr3_entry), gncAddressGetAddr3 (addr));
640  gtk_entry_set_text (GTK_ENTRY (cw->addr4_entry), gncAddressGetAddr4 (addr));
641  gtk_entry_set_text (GTK_ENTRY (cw->phone_entry), gncAddressGetPhone (addr));
642  gtk_entry_set_text (GTK_ENTRY (cw->fax_entry), gncAddressGetFax (addr));
643  gtk_entry_set_text (GTK_ENTRY (cw->email_entry), gncAddressGetEmail (addr));
644 
645  /* Setup Ship-to Address */
646  gtk_entry_set_text (GTK_ENTRY (cw->shipname_entry), gncAddressGetName (shipaddr));
647  gtk_entry_set_text (GTK_ENTRY (cw->shipaddr1_entry), gncAddressGetAddr1 (shipaddr));
648  gtk_entry_set_text (GTK_ENTRY (cw->shipaddr2_entry), gncAddressGetAddr2 (shipaddr));
649  gtk_entry_set_text (GTK_ENTRY (cw->shipaddr3_entry), gncAddressGetAddr3 (shipaddr));
650  gtk_entry_set_text (GTK_ENTRY (cw->shipaddr4_entry), gncAddressGetAddr4 (shipaddr));
651  gtk_entry_set_text (GTK_ENTRY (cw->shipphone_entry), gncAddressGetPhone (shipaddr));
652  gtk_entry_set_text (GTK_ENTRY (cw->shipfax_entry), gncAddressGetFax (shipaddr));
653  gtk_entry_set_text (GTK_ENTRY (cw->shipemail_entry), gncAddressGetEmail (shipaddr));
654 
655  /* Set toggle buttons */
656  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw->active_check),
657  gncCustomerGetActive (cust));
658 
659  string = gncCustomerGetNotes (cust);
660  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(cw->notes_text));
661  gtk_text_buffer_set_text (text_buffer, string, -1);
662 
663  cw->component_id =
664  gnc_register_gui_component (DIALOG_EDIT_CUSTOMER_CM_CLASS,
665  gnc_customer_window_refresh_handler,
666  gnc_customer_window_close_handler,
667  cw);
668  cw->terms = gncCustomerGetTerms (cust);
669 
670  }
671  else
672  {
673  cust = gncCustomerCreate (bookp);
674  cw->customer_guid = *gncCustomerGetGUID (cust);
675 
676  cw->dialog_type = NEW_CUSTOMER;
677  cw->component_id =
678  gnc_register_gui_component (DIALOG_NEW_CUSTOMER_CM_CLASS,
679  gnc_customer_window_refresh_handler,
680  gnc_customer_window_close_handler,
681  cw);
682 
683  /* XXX: get the global-default terms */
684  cw->terms = NULL;
685  }
686 
687  /* I know that cust exists here -- either passed in or just created */
688 
689  cw->taxincluded = gncCustomerGetTaxIncluded (cust);
690  gnc_taxincluded_combo (GTK_COMBO_BOX(cw->taxincluded_menu), cw->taxincluded);
691  gnc_billterms_combo (GTK_COMBO_BOX(cw->terms_menu), bookp, TRUE, cw->terms);
692 
693  cw->taxtable = gncCustomerGetTaxTable (cust);
694  gnc_taxtables_combo (GTK_COMBO_BOX(cw->taxtable_menu), bookp, TRUE, cw->taxtable);
695  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw->taxtable_check),
696  gncCustomerGetTaxTableOverride (cust));
697  gnc_customer_taxtable_check_cb (GTK_TOGGLE_BUTTON (cw->taxtable_check), cw);
698 
699  /* Set up the addr line quickfill */
700  cw->addr2_quickfill = gnc_get_shared_address_addr2_quickfill(cw->book, ADDR_QUICKFILL);
701  cw->addr3_quickfill = gnc_get_shared_address_addr3_quickfill(cw->book, ADDR_QUICKFILL);
702  cw->addr4_quickfill = gnc_get_shared_address_addr4_quickfill(cw->book, ADDR_QUICKFILL);
703 
704  /* Set the Discount, and Credit amounts */
705  gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (cw->discount_amount),
706  gncCustomerGetDiscount (cust));
707  gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (cw->credit_amount),
708  gncCustomerGetCredit (cust));
709 
710  gnc_gui_component_watch_entity_type (cw->component_id,
711  GNC_CUSTOMER_MODULE_NAME,
712  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
713 
714  gtk_widget_show_all (cw->dialog);
715  g_object_unref(G_OBJECT(builder));
716 
717  return cw;
718 }
719 
720 CustomerWindow *
721 gnc_ui_customer_edit (GtkWindow *parent, GncCustomer *cust)
722 {
723  CustomerWindow *cw;
724 
725  if (!cust) return NULL;
726 
727  cw = gnc_customer_new_window (parent, gncCustomerGetBook(cust), cust);
728 
729  return cw;
730 }
731 
732 CustomerWindow *
733 gnc_ui_customer_new (GtkWindow *parent, QofBook *bookp)
734 {
735  CustomerWindow *cw;
736 
737  /* Make sure required options exist */
738  if (!bookp) return NULL;
739 
740  cw = gnc_customer_new_window (parent, bookp, NULL);
741 
742  return cw;
743 }
744 
745 /* Functions for customer selection widgets */
746 
747 static void
748 invoice_customer_cb (GtkWindow *dialog, gpointer *cust_p, gpointer user_data)
749 {
750  struct _customer_select_window *sw = user_data;
751  GncOwner owner;
752  GncCustomer *cust;
753 
754  g_return_if_fail (cust_p && user_data);
755 
756  cust = *cust_p;
757 
758  if (!cust)
759  return;
760 
761  gncOwnerInitCustomer (&owner, cust);
762  gnc_invoice_search (dialog, NULL, &owner, sw->book);
763  return;
764 }
765 
766 static void
767 order_customer_cb (GtkWindow *dialog, gpointer *cust_p, gpointer user_data)
768 {
769  struct _customer_select_window *sw = user_data;
770  GncOwner owner;
771  GncCustomer *cust;
772 
773  g_return_if_fail (cust_p && user_data);
774 
775  cust = *cust_p;
776 
777  if (!cust)
778  return;
779 
780  gncOwnerInitCustomer (&owner, cust);
781  gnc_order_search (dialog, NULL, &owner, sw->book);
782  return;
783 }
784 
785 static void
786 jobs_customer_cb (GtkWindow *dialog, gpointer *cust_p, gpointer user_data)
787 {
788  struct _customer_select_window *sw = user_data;
789  GncOwner owner;
790  GncCustomer *cust;
791 
792  g_return_if_fail (cust_p && user_data);
793 
794  cust = *cust_p;
795 
796  if (!cust)
797  return;
798 
799  gncOwnerInitCustomer (&owner, cust);
800  gnc_job_search (dialog, NULL, &owner, sw->book);
801  return;
802 }
803 
804 static void
805 payment_customer_cb (GtkWindow *dialog, gpointer *cust_p, gpointer user_data)
806 {
807  struct _customer_select_window *sw = user_data;
808  GncOwner owner;
809  GncCustomer *cust;
810 
811  g_return_if_fail (cust_p && user_data);
812 
813  cust = *cust_p;
814 
815  if (!cust)
816  return;
817 
818  gncOwnerInitCustomer (&owner, cust);
819  gnc_ui_payment_new (dialog, &owner, sw->book);
820  return;
821 }
822 
823 static void
824 edit_customer_cb (GtkWindow *dialog, gpointer *cust_p, gpointer user_data)
825 {
826  GncCustomer *cust;
827 
828  g_return_if_fail (cust_p);
829  cust = *cust_p;
830 
831  if (!cust)
832  return;
833 
834  gnc_ui_customer_edit (dialog, cust);
835 
836  return;
837 }
838 
839 static gpointer
840 new_customer_cb (GtkWindow *dialog, gpointer user_data)
841 {
842  struct _customer_select_window *sw = user_data;
843  CustomerWindow *cw;
844 
845  g_return_val_if_fail (sw, NULL);
846 
847  cw = gnc_ui_customer_new (dialog, sw->book);
848  return cw_get_customer (cw);
849 }
850 
851 static void
852 free_userdata_cb (gpointer user_data)
853 {
854  struct _customer_select_window *sw = user_data;
855 
856  g_return_if_fail (sw);
857 
858  qof_query_destroy (sw->q);
859  g_free (sw);
860 }
861 
862 GNCSearchWindow *
863 gnc_customer_search (GtkWindow *parent, GncCustomer *start, QofBook *book)
864 {
865  QofQuery *q, *q2 = NULL;
866  QofIdType type = GNC_CUSTOMER_MODULE_NAME;
867  struct _customer_select_window *sw;
868  static GList *params = NULL;
869  static GList *columns = NULL;
870  static GNCSearchCallbackButton buttons[] =
871  {
872  { N_("View/Edit Customer"), edit_customer_cb, NULL, TRUE},
873  { N_("Customer's Jobs"), jobs_customer_cb, NULL, TRUE},
874  // { N_("Customer's Orders"), order_customer_cb, NULL, TRUE},
875  { N_("Customer's Invoices"), invoice_customer_cb, NULL, TRUE},
876  { N_("Process Payment"), payment_customer_cb, NULL, FALSE},
877  { NULL },
878  };
879  (void)order_customer_cb;
880 
881  g_return_val_if_fail (book, NULL);
882 
883  /* Build parameter list in reverse order */
884  if (params == NULL)
885  {
886  params = gnc_search_param_prepend (params, _("Shipping Contact"), NULL, type,
887  CUSTOMER_SHIPADDR, ADDRESS_NAME, NULL);
888  params = gnc_search_param_prepend (params, _("Billing Contact"), NULL, type,
889  CUSTOMER_ADDR, ADDRESS_NAME, NULL);
890  params = gnc_search_param_prepend (params, _("Customer ID"), NULL, type,
891  CUSTOMER_ID, NULL);
892  params = gnc_search_param_prepend (params, _("Company Name"), NULL, type,
893  CUSTOMER_NAME, NULL);
894  }
895 
896  /* Build the column list in reverse order */
897  if (columns == NULL)
898  {
899  columns = gnc_search_param_prepend (columns, _("Shipping Contact"), NULL, type,
900  CUSTOMER_SHIPADDR, ADDRESS_NAME, NULL);
901  columns = gnc_search_param_prepend (columns, _("Contact"), NULL, type,
902  CUSTOMER_ADDR, ADDRESS_NAME, NULL);
903  columns = gnc_search_param_prepend (columns, _("Company"), NULL, type,
904  CUSTOMER_NAME, NULL);
905  columns = gnc_search_param_prepend (columns, _("ID #"), NULL, type,
906  CUSTOMER_ID, NULL);
907  }
908 
909  /* Build the queries */
910  q = qof_query_create_for (type);
911  qof_query_set_book (q, book);
912 
913 #if 0
914  if (start)
915  {
916  q2 = qof_query_copy (q);
917  qof_query_add_guid_match (q2, g_slist_prepend (NULL, QOF_PARAM_GUID),
918  gncCustomerGetGUID (start), QOF_QUERY_AND);
919  }
920 #endif
921 
922  /* launch select dialog and return the result */
923  sw = g_new0 (struct _customer_select_window, 1);
924 
925  sw->book = book;
926  sw->q = q;
927 
928  return gnc_search_dialog_create (parent, type, _("Find Customer"),
929  params, columns, q, q2, buttons, NULL,
930  new_customer_cb, sw, free_userdata_cb,
931  GNC_PREFS_GROUP_SEARCH, NULL,
932  "gnc-class-customers");
933 }
934 
935 GNCSearchWindow *
936 gnc_customer_search_select (GtkWindow *parent, gpointer start, gpointer book)
937 {
938  if (!book) return NULL;
939 
940  return gnc_customer_search (parent, start, book);
941 }
942 
943 GNCSearchWindow *
944 gnc_customer_search_edit (GtkWindow *parent, gpointer start, gpointer book)
945 {
946  if (start)
947  gnc_ui_customer_edit (parent, start);
948 
949  return NULL;
950 }
951 
952 static gboolean
953 idle_select_region_addr2(gpointer user_data)
954 {
955  CustomerWindow *wdata = user_data;
956  g_return_val_if_fail(user_data, FALSE);
957 
958  /* g_warning("Selection start=%d end=%d",wdata->addrX_start_selection, wdata->addrX_end_selection); */
959 
960  gtk_editable_select_region(GTK_EDITABLE(wdata->addr2_entry),
961  wdata->addrX_start_selection,
962  wdata->addrX_end_selection);
963 
964  wdata->addrX_selection_source_id = 0;
965  return FALSE;
966 }
967 
968 static gboolean
969 idle_select_region_addr3(gpointer user_data)
970 {
971  CustomerWindow *wdata = user_data;
972  g_return_val_if_fail(user_data, FALSE);
973 
974  gtk_editable_select_region(GTK_EDITABLE(wdata->addr3_entry),
975  wdata->addrX_start_selection,
976  wdata->addrX_end_selection);
977 
978  wdata->addrX_selection_source_id = 0;
979  return FALSE;
980 }
981 static gboolean
982 idle_select_region_addr4(gpointer user_data)
983 {
984  CustomerWindow *wdata = user_data;
985  g_return_val_if_fail(user_data, FALSE);
986 
987  gtk_editable_select_region(GTK_EDITABLE(wdata->addr4_entry),
988  wdata->addrX_start_selection,
989  wdata->addrX_end_selection);
990  wdata->addrX_selection_source_id = 0;
991  return FALSE;
992 }
993 
994 static gboolean
995 idle_select_region_shipaddr2(gpointer user_data)
996 {
997  CustomerWindow *wdata = user_data;
998  g_return_val_if_fail(user_data, FALSE);
999 
1000  gtk_editable_select_region(GTK_EDITABLE(wdata->shipaddr2_entry),
1001  wdata->addrX_start_selection,
1002  wdata->addrX_end_selection);
1003 
1004  wdata->addrX_selection_source_id = 0;
1005  return FALSE;
1006 }
1007 
1008 static gboolean
1009 idle_select_region_shipaddr3(gpointer user_data)
1010 {
1011  CustomerWindow *wdata = user_data;
1012  g_return_val_if_fail(user_data, FALSE);
1013 
1014  gtk_editable_select_region(GTK_EDITABLE(wdata->shipaddr3_entry),
1015  wdata->addrX_start_selection,
1016  wdata->addrX_end_selection);
1017 
1018  wdata->addrX_selection_source_id = 0;
1019  return FALSE;
1020 }
1021 static gboolean
1022 idle_select_region_shipaddr4(gpointer user_data)
1023 {
1024  CustomerWindow *wdata = user_data;
1025  g_return_val_if_fail(user_data, FALSE);
1026 
1027  gtk_editable_select_region(GTK_EDITABLE(wdata->shipaddr4_entry),
1028  wdata->addrX_start_selection,
1029  wdata->addrX_end_selection);
1030  wdata->addrX_selection_source_id = 0;
1031  return FALSE;
1032 }
1033 
1034 /* Implementation of the steps common to all address lines. Returns
1035  * TRUE if anything was inserted by quickfill, otherwise FALSE. */
1036 static gboolean
1037 gnc_customer_addr_common_insert_cb(GtkEditable *editable,
1038  gchar *new_text, gint new_text_length,
1039  gint *position, gpointer user_data, QuickFill *qf)
1040 {
1041  CustomerWindow *wdata = user_data;
1042  gchar *concatenated_text;
1043  QuickFill *match;
1044  gint prefix_len, concatenated_text_len;
1045 
1046  if (new_text_length <= 0)
1047  return FALSE;
1048 
1049  /*g_warning("In gnc_customer_addr_common_insert_cb");*/
1050 
1051  {
1052  gchar *suffix = gtk_editable_get_chars(editable, *position, -1);
1053  /* If we are inserting in the middle, do nothing */
1054  if (*suffix)
1055  {
1056  g_free(suffix);
1057  return FALSE;
1058  }
1059  g_free(suffix);
1060  }
1061 
1062  {
1063  gchar *prefix = gtk_editable_get_chars(editable, 0, *position);
1064  prefix_len = strlen(prefix);
1065  concatenated_text = g_strconcat(prefix, new_text, (gchar*) NULL);
1066  concatenated_text_len = prefix_len + new_text_length;
1067  g_free(prefix);
1068  }
1069 
1070  match = gnc_quickfill_get_string_match(qf, concatenated_text);
1071  g_free(concatenated_text);
1072  if (match)
1073  {
1074  const char* match_str = gnc_quickfill_string(match);
1075  if (match_str)
1076  {
1077  gint match_str_len = strlen(match_str);
1078  if (match_str_len > concatenated_text_len)
1079  {
1080  /* g_warning("Got match \"%s\" match_str_len=%d new_text=%s position=%d prefix_len=%d", match_str, match_str_len, new_text, *position, prefix_len); */
1081 
1082  g_signal_handlers_block_matched (G_OBJECT (editable),
1083  G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, user_data);
1084 
1085  gtk_editable_insert_text(editable,
1086  match_str + prefix_len,
1087  match_str_len - prefix_len,
1088  position);
1089 
1090  g_signal_handlers_unblock_matched (G_OBJECT (editable),
1091  G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, user_data);
1092 
1093  /* stop the current insert */
1094  g_signal_stop_emission_by_name (G_OBJECT (editable), "insert_text");
1095 
1096  /* set the position */
1097  *position = concatenated_text_len;
1098 
1099  /* select region on idle, because it would be reset once this function
1100  finishes */
1101  wdata->addrX_start_selection = *position;
1102  wdata->addrX_end_selection = -1;
1103 
1104  return TRUE;
1105  }
1106  }
1107  }
1108  return FALSE;
1109 }
1110 
1111 void gnc_customer_addr2_insert_cb(GtkEditable *editable,
1112  gchar *new_text, gint new_text_length,
1113  gint *position, gpointer user_data)
1114 {
1115  CustomerWindow *wdata = user_data;
1116  gboolean r;
1117 
1118  /* The handling common to all address lines is done in this other
1119  * function. */
1120  r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
1121  position, user_data, wdata->addr2_quickfill);
1122 
1123  /* Did we insert something? Then set up the correct idle handler */
1124  if (r)
1125  {
1126  /* select region on idle, because it would be reset once this function
1127  finishes */
1128  wdata->addrX_selection_source_id = g_idle_add(idle_select_region_addr2,
1129  user_data);
1130  }
1131 }
1132 
1133 void gnc_customer_addr3_insert_cb(GtkEditable *editable,
1134  gchar *new_text, gint new_text_length,
1135  gint *position, gpointer user_data)
1136 {
1137  CustomerWindow *wdata = user_data;
1138  gboolean r;
1139 
1140  /* The handling common to all address lines is done in this other
1141  * function. */
1142  r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
1143  position, user_data, wdata->addr3_quickfill);
1144 
1145  /* Did we insert something? Then set up the correct idle handler */
1146  if (r)
1147  {
1148  wdata->addrX_selection_source_id = g_idle_add(idle_select_region_addr3,
1149  user_data);
1150  }
1151 }
1152 
1153 void gnc_customer_addr4_insert_cb(GtkEditable *editable,
1154  gchar *new_text, gint new_text_length,
1155  gint *position, gpointer user_data)
1156 {
1157  CustomerWindow *wdata = user_data;
1158  gboolean r;
1159 
1160  /* The handling common to all address lines is done in this other
1161  * function. */
1162  r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
1163  position, user_data, wdata->addr4_quickfill);
1164 
1165  /* Did we insert something? Then set up the correct idle handler */
1166  if (r)
1167  {
1168  wdata->addrX_selection_source_id = g_idle_add(idle_select_region_addr4,
1169  user_data);
1170  }
1171 }
1172 
1173 void gnc_customer_shipaddr2_insert_cb(GtkEditable *editable,
1174  gchar *new_text, gint new_text_length,
1175  gint *position, gpointer user_data)
1176 {
1177  CustomerWindow *wdata = user_data;
1178  gboolean r;
1179 
1180  /* The handling common to all address lines is done in this other
1181  * function. */
1182  r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
1183  position, user_data, wdata->addr2_quickfill);
1184 
1185  /* Did we insert something? Then set up the correct idle handler */
1186  if (r)
1187  {
1188  wdata->addrX_selection_source_id = g_idle_add(idle_select_region_shipaddr2,
1189  user_data);
1190  }
1191 }
1192 
1193 void gnc_customer_shipaddr3_insert_cb(GtkEditable *editable,
1194  gchar *new_text, gint new_text_length,
1195  gint *position, gpointer user_data)
1196 {
1197  CustomerWindow *wdata = user_data;
1198  gboolean r;
1199 
1200  /* The handling common to all address lines is done in this other
1201  * function. */
1202  r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
1203  position, user_data, wdata->addr3_quickfill);
1204 
1205  /* Did we insert something? Then set up the correct idle handler */
1206  if (r)
1207  {
1208  wdata->addrX_selection_source_id = g_idle_add(idle_select_region_shipaddr3,
1209  user_data);
1210  }
1211 }
1212 
1213 void gnc_customer_shipaddr4_insert_cb(GtkEditable *editable,
1214  gchar *new_text, gint new_text_length,
1215  gint *position, gpointer user_data)
1216 {
1217  CustomerWindow *wdata = user_data;
1218  gboolean r;
1219 
1220  /* The handling common to all address lines is done in this other
1221  * function. */
1222  r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
1223  position, user_data, wdata->addr4_quickfill);
1224 
1225  /* Did we insert something? Then set up the correct idle handler */
1226  if (r)
1227  {
1228  wdata->addrX_selection_source_id = g_idle_add(idle_select_region_shipaddr4,
1229  user_data);
1230  }
1231 }
1232 
1233 static gboolean
1234 gnc_customer_common_key_press_cb( GtkEntry *entry,
1235  GdkEventKey *event,
1236  gpointer user_data, GtkWidget* editable )
1237 {
1238  gboolean done_with_input = FALSE;
1239 
1240  /* Most "special" keys are allowed to be handled directly by
1241  * the entry's key press handler, but in some cases that doesn't
1242  * seem to work right, so handle them here.
1243  */
1244  switch ( event->keyval )
1245  {
1246  case GDK_KEY_Tab:
1247  case GDK_KEY_ISO_Left_Tab:
1248  if ( !( event->state & GDK_SHIFT_MASK) ) /* Complete on Tab,
1249  * but not Shift-Tab */
1250  {
1251  /* NOT done with input, though, since we need to focus to the next
1252  * field. Unselect the current field, though.
1253  */
1254  gtk_editable_select_region( GTK_EDITABLE(editable),
1255  0, 0 );
1256  }
1257  break;
1258  }
1259 
1260  return( done_with_input );
1261 }
1262 gboolean
1263 gnc_customer_addr2_key_press_cb( GtkEntry *entry,
1264  GdkEventKey *event,
1265  gpointer user_data )
1266 {
1267  CustomerWindow *wdata = user_data;
1268  return gnc_customer_common_key_press_cb(entry, event, user_data,
1269  wdata->addr2_entry);
1270 }
1271 gboolean
1272 gnc_customer_addr3_key_press_cb( GtkEntry *entry,
1273  GdkEventKey *event,
1274  gpointer user_data )
1275 {
1276  CustomerWindow *wdata = user_data;
1277  return gnc_customer_common_key_press_cb(entry, event, user_data,
1278  wdata->addr3_entry);
1279 }
1280 gboolean
1281 gnc_customer_addr4_key_press_cb( GtkEntry *entry,
1282  GdkEventKey *event,
1283  gpointer user_data )
1284 {
1285  CustomerWindow *wdata = user_data;
1286  return gnc_customer_common_key_press_cb(entry, event, user_data,
1287  wdata->addr4_entry);
1288 }
1289 gboolean
1290 gnc_customer_shipaddr2_key_press_cb( GtkEntry *entry,
1291  GdkEventKey *event,
1292  gpointer user_data )
1293 {
1294  CustomerWindow *wdata = user_data;
1295  return gnc_customer_common_key_press_cb(entry, event, user_data,
1296  wdata->shipaddr2_entry);
1297 }
1298 gboolean
1299 gnc_customer_shipaddr3_key_press_cb( GtkEntry *entry,
1300  GdkEventKey *event,
1301  gpointer user_data )
1302 {
1303  CustomerWindow *wdata = user_data;
1304  return gnc_customer_common_key_press_cb(entry, event, user_data,
1305  wdata->shipaddr3_entry);
1306 }
1307 gboolean
1308 gnc_customer_shipaddr4_key_press_cb( GtkEntry *entry,
1309  GdkEventKey *event,
1310  gpointer user_data )
1311 {
1312  CustomerWindow *wdata = user_data;
1313  return gnc_customer_common_key_press_cb(entry, event, user_data,
1314  wdata->shipaddr4_entry);
1315 }
Core Customer Interface.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
void gnc_currency_edit_set_currency(GNCCurrencyEdit *gce, const gnc_commodity *currency)
Set the widget to display a certain currency name.
utility functions for the GnuCash UI
GncTaxIncluded
How to interpret the TaxIncluded.
Definition: gncTaxTable.h:85
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
Definition: qofquery.cpp:1018
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
GtkWindow * gnc_ui_get_gtk_window(GtkWidget *widget)
Get a pointer to the widget&#39;s immediate top level GtkWindow.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
const gchar * QofIdType
QofIdType declaration.
Definition: qofid.h:80
Currency selection widget.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
void gnc_gnome_help(GtkWindow *parent, const char *file_name, const char *anchor)
Launch the systems default help browser, gnome&#39;s yelp for linux, and open to a given link within a gi...
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
Definition: guid.cpp:204
QuickFill * gnc_get_shared_address_addr3_quickfill(QofBook *book, const char *key)
Create/fetch a quickfill GncAddress description strings on the Addr3 part.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
gnc_commodity * gnc_currency_edit_get_currency(GNCCurrencyEdit *gce)
Retrieve the displayed currency of the widget.
QuickFill * gnc_quickfill_get_string_match(QuickFill *qf, const char *str)
Return a subnode in the tree whose strings all match the string &#39;str&#39; as the next substring...
Definition: QuickFill.c:179
#define gncCustomerGetGUID(x)
Definition: gncCustomer.h:158
void qof_query_add_guid_match(QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
DOCUMENT ME !!
Definition: qofquery.cpp:1310
credit, discount and shipaddr are unique to GncCustomer id, name, notes, terms, addr, currency, taxtable, taxtable_override taxincluded, active and jobs are identical to ::GncVendor.
const char * gnc_quickfill_string(QuickFill *qf)
For the given node &#39;qf&#39;, return the best-guess matching string.
Definition: QuickFill.c:123
GtkWidget * gnc_currency_edit_new(void)
Create a new GNCCurrencyEdit widget which can be used to provide an easy way to enter ISO currency co...
QuickFill * gnc_get_shared_address_addr2_quickfill(QofBook *book, const char *key)
Similar to the Account Names account name quickfill, we create a cached quickfill with the address li...
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition: guid.cpp:130
QuickFill is used to auto-complete typed user entries.
QuickFill * gnc_get_shared_address_addr4_quickfill(QofBook *book, const char *key)
Create/fetch a quickfill GncAddress description strings on the Addr4 part.
an Address object
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.cpp:231
The type used to store guids in C.
Definition: guid.h:75
A Query.
Definition: qofquery.cpp:74
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability.txt for an explanation of the following Code that handles refcount, parent, child, invisible and children is identical to that in ::GncBillTerm