GnuCash  5.6-150-g038405b370+
dialog-order.c
1 /*
2  * dialog-order.c -- Dialog for Order entry
3  * Copyright (C) 2001,2002 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 <stdint.h>
29 
30 #include "dialog-utils.h"
31 #include "gnc-component-manager.h"
32 #include "gnc-date-edit.h"
33 #include "gnc-ui.h"
34 #include "gnc-gui-query.h"
35 #include "gnc-ui-util.h"
36 #include "qof.h"
37 #include "gnucash-register.h"
38 #include "gnucash-sheet.h"
39 #include "dialog-search.h"
40 #include "search-param.h"
41 
42 #include "gncOrder.h"
43 #include "gncOrderP.h"
44 
45 #include "gncEntryLedger.h"
46 
47 #include "dialog-order.h"
48 #include "dialog-invoice.h"
49 #include "business-gnome-utils.h"
50 #include "dialog-date-close.h"
51 #include "gnc-general-search.h"
52 
53 #define DIALOG_NEW_ORDER_CM_CLASS "dialog-new-order"
54 #define DIALOG_EDIT_ORDER_CM_CLASS "dialog-edit-order"
55 #define DIALOG_VIEW_ORDER_CM_CLASS "dialog-view-order"
56 
57 #define GNC_PREFS_GROUP_SEARCH "dialogs.business.order-search"
58 
59 void gnc_order_window_ok_cb (GtkWidget *widget, gpointer data);
60 void gnc_order_window_cancel_cb (GtkWidget *widget, gpointer data);
61 void gnc_order_window_help_cb (GtkWidget *widget, gpointer data);
62 void gnc_order_window_invoice_cb (GtkWidget *widget, gpointer data);
63 void gnc_order_window_close_order_cb (GtkWidget *widget, gpointer data);
64 void gnc_order_window_destroy_cb (GtkWidget *widget, gpointer data);
65 
66 typedef enum
67 {
68  NEW_ORDER,
69  EDIT_ORDER,
70  VIEW_ORDER
71 } OrderDialogType;
72 
74 {
75  QofBook *book;
76  GncOwner *owner;
77  QofQuery *q;
78  GncOwner owner_def;
79 };
80 
82 {
83  GtkWidget * dialog;
84 
85  GtkWidget * id_entry;
86  GtkWidget * ref_entry;
87  GtkWidget * notes_text;
88  GtkWidget * opened_date;
89  GtkWidget * closed_date;
90  GtkWidget * active_check;
91 
92  GtkWidget * cd_label;
93  GtkWidget * close_order_button;
94 
95  GtkWidget * owner_box;
96  GtkWidget * owner_label;
97  GtkWidget * owner_choice;
98 
99  GnucashRegister * reg;
100  GncEntryLedger * ledger;
101 
102  OrderDialogType dialog_type;
103  GncGUID order_guid;
104  gint component_id;
105  QofBook * book;
106  GncOrder * created_order;
107  GncOwner owner;
108 
109 };
110 
111 static void gnc_order_update_window (OrderWindow *ow);
112 
113 static GncOrder *
114 ow_get_order (OrderWindow *ow)
115 {
116  if (!ow)
117  return NULL;
118 
119  return gncOrderLookup (ow->book, &ow->order_guid);
120 }
121 
122 static void gnc_ui_to_order (OrderWindow *ow, GncOrder *order)
123 {
124  GtkTextBuffer* text_buffer;
125  GtkTextIter start, end;
126  gchar *text;
127  time64 tt;
128 
129  /* Do nothing if this is view only */
130  if (ow->dialog_type == VIEW_ORDER)
131  return;
132 
133  gnc_suspend_gui_refresh ();
134  gncOrderBeginEdit (order);
135 
136  gncOrderSetID (order, gtk_entry_get_text (GTK_ENTRY (ow->id_entry)));
137 
138  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(ow->notes_text));
139  gtk_text_buffer_get_bounds (text_buffer, &start, &end);
140  text = gtk_text_buffer_get_text (text_buffer, &start, &end, FALSE);
141  gncOrderSetNotes (order, text);
142 
143  gncOrderSetReference (order, gtk_entry_get_text (GTK_ENTRY (ow->ref_entry)));
144 
145  tt = gnc_date_edit_get_date (GNC_DATE_EDIT (ow->opened_date));
146  gncOrderSetDateOpened (order, tt);
147 
148  if (ow->active_check)
149  gncOrderSetActive (order, gtk_toggle_button_get_active
150  (GTK_TOGGLE_BUTTON (ow->active_check)));
151 
152  gnc_owner_get_owner (ow->owner_choice, &(ow->owner));
153  gncOrderSetOwner (order, &(ow->owner));
154 
155  gncOrderCommitEdit (order);
156  gnc_resume_gui_refresh ();
157  g_free (text);
158 }
159 
160 static gboolean
161 gnc_order_window_verify_ok (OrderWindow *ow)
162 {
163  const char *res;
164 
165  /* Check the ID */
166  res = gtk_entry_get_text (GTK_ENTRY (ow->id_entry));
167  if (g_strcmp0 (res, "") == 0)
168  {
169  gnc_error_dialog (GTK_WINDOW (ow->dialog), "%s",
170  _("The Order must be given an ID."));
171  return FALSE;
172  }
173 
174  /* Check the Owner */
175  gnc_owner_get_owner (ow->owner_choice, &(ow->owner));
176  res = gncOwnerGetName (&(ow->owner));
177  if (res == NULL || g_strcmp0 (res, "") == 0)
178  {
179  gnc_error_dialog (GTK_WINDOW (ow->dialog), "%s",
180  _("You need to supply Billing Information."));
181  return FALSE;
182  }
183 
184  return TRUE;
185 }
186 
187 static gboolean
188 gnc_order_window_ok_save (OrderWindow *ow)
189 {
190  if (!gnc_entry_ledger_check_close (ow->dialog, ow->ledger))
191  return FALSE;
192 
193  if (!gnc_order_window_verify_ok (ow))
194  return FALSE;
195 
196  /* Now save it off */
197  {
198  GncOrder *order = ow_get_order (ow);
199  if (order)
200  {
201  gnc_ui_to_order (ow, order);
202 
203  }
204  ow->created_order = order;
205  }
206  return TRUE;
207 }
208 
209 void
210 gnc_order_window_ok_cb (GtkWidget *widget, gpointer data)
211 {
212  OrderWindow *ow = data;
213 
214  if (!gnc_order_window_ok_save (ow))
215  return;
216 
217  /* Ok, we don't need this anymore */
218  ow->order_guid = *guid_null ();
219 
220  gnc_close_gui_component (ow->component_id);
221 }
222 
223 void
224 gnc_order_window_cancel_cb (GtkWidget *widget, gpointer data)
225 {
226  OrderWindow *ow = data;
227 
228  gnc_close_gui_component (ow->component_id);
229 }
230 
231 void
232 gnc_order_window_help_cb (GtkWidget *widget, gpointer data)
233 {
234  OrderWindow *ow = data;
235  gnc_gnome_help (GTK_WINDOW(ow->dialog), DF_MANUAL, DL_USAGE_BILL);
236 }
237 
238 void
239 gnc_order_window_invoice_cb (GtkWidget *widget, gpointer data)
240 {
241  OrderWindow *ow = data;
242 
243  /* make sure we're ok */
244  if (!gnc_order_window_verify_ok (ow))
245  return;
246 
247  /* Ok, go make an invoice */
248  gnc_invoice_search (gtk_window_get_transient_for(GTK_WINDOW(ow->dialog)), NULL, &(ow->owner), ow->book);
249 
250  /* refresh the window */
251  gnc_order_update_window (ow);
252 }
253 
254 void
255 gnc_order_window_close_order_cb (GtkWidget *widget, gpointer data)
256 {
257  OrderWindow *ow = data;
258  GncOrder *order;
259  GList *entries;
260  char *message, *label;
261  gboolean non_inv = FALSE;
262  time64 t = gnc_time (NULL);
263 
264  /* Make sure the order is ok */
265  if (!gnc_order_window_verify_ok (ow))
266  return;
267 
268  /* Make sure the order exists */
269  order = ow_get_order (ow);
270  if (!order)
271  return;
272 
273  /* Check that there is at least one Entry */
274  if (gncOrderGetEntries (order) == NULL)
275  {
276  gnc_error_dialog (GTK_WINDOW (ow->dialog), "%s",
277  _("The Order must have at least one Entry."));
278  return;
279  }
280 
281  /* Make sure we can close the order. Are there any uninvoiced entries? */
282  entries = gncOrderGetEntries (order);
283  for ( ; entries ; entries = entries->next)
284  {
285  GncEntry *entry = entries->data;
286  if (gncEntryGetInvoice (entry) == NULL)
287  {
288  non_inv = TRUE;
289  break;
290  }
291  }
292 
293  if (non_inv)
294  {
295  /* Damn; yes. Well, ask the user to make sure they REALLY want to
296  * close this order!
297  */
298 
299  message = _("This order contains entries that have not been invoiced. "
300  "Are you sure you want to close it out before "
301  "you invoice all the entries?");
302 
303  if (gnc_verify_dialog (GTK_WINDOW (ow->dialog), FALSE, "%s", message) == FALSE)
304  return;
305  }
306 
307  /* Ok, we can close this. Ask for verification and set the closed date */
308  message = _("Do you really want to close the order?");
309  label = _("Close Date");
310 
311  if (!gnc_dialog_date_close_parented (ow->dialog, message, label, TRUE, &t))
312  return;
313 
314  gncOrderSetDateClosed (order, t);
315 
316  /* save it off */
317  gnc_order_window_ok_save (ow);
318 
319  /* Reset the type; change to read-only */
320  ow->dialog_type = VIEW_ORDER;
321  gnc_entry_ledger_set_readonly (ow->ledger, TRUE);
322 
323  /* And redisplay the window */
324  gnc_order_update_window (ow);
325 }
326 
327 void
328 gnc_order_window_destroy_cb (GtkWidget *widget, gpointer data)
329 {
330  OrderWindow *ow = data;
331  GncOrder *order = ow_get_order (ow);
332 
333  gnc_suspend_gui_refresh ();
334 
335  if (ow->dialog_type == NEW_ORDER && order != NULL)
336  {
337  gncOrderBeginEdit (order);
338  gncOrderDestroy (order);
339  ow->order_guid = *guid_null ();
340  }
341 
342  if (ow->ledger)
343  gnc_entry_ledger_destroy (ow->ledger);
344  gnc_unregister_gui_component (ow->component_id);
345  gnc_resume_gui_refresh ();
346 
347  g_free (ow);
348 }
349 
350 static int
351 gnc_order_owner_changed_cb (GtkWidget *widget, gpointer data)
352 {
353  OrderWindow *ow = data;
354  GncOrder *order;
355 
356  if (!ow)
357  return FALSE;
358 
359  if (ow->dialog_type == VIEW_ORDER)
360  return FALSE;
361 
362  gnc_owner_get_owner (ow->owner_choice, &(ow->owner));
363 
364  /* Set the Order's owner now! */
365  order = ow_get_order (ow);
366  gncOrderSetOwner (order, &(ow->owner));
367 
368  if (ow->dialog_type == EDIT_ORDER)
369  return FALSE;
370 
371  /* Only set the reference during the New Job dialog */
372  switch (gncOwnerGetType (&(ow->owner)))
373  {
374  case GNC_OWNER_JOB:
375  {
376  char const *msg = gncJobGetReference (gncOwnerGetJob (&(ow->owner)));
377  gtk_entry_set_text (GTK_ENTRY (ow->ref_entry), msg ? msg : "");
378  break;
379  }
380  default:
381  gtk_entry_set_text (GTK_ENTRY (ow->ref_entry), "");
382  break;
383  }
384 
385  return FALSE;
386 }
387 
388 static void
389 gnc_order_window_close_handler (gpointer user_data)
390 {
391  OrderWindow *ow = user_data;
392 
393  gtk_widget_destroy (ow->dialog);
394 }
395 
396 static void
397 gnc_order_window_refresh_handler (GHashTable *changes, gpointer user_data)
398 {
399  OrderWindow *ow = user_data;
400  const EventInfo *info;
401  GncOrder *order = ow_get_order (ow);
402 
403  /* If there isn't a order behind us, close down */
404  if (!order)
405  {
406  gnc_close_gui_component (ow->component_id);
407  return;
408  }
409 
410  /* Next, close if this is a destroy event */
411  if (changes)
412  {
413  info = gnc_gui_get_entity_events (changes, &ow->order_guid);
414  if (info && (info->event_mask & QOF_EVENT_DESTROY))
415  {
416  gnc_close_gui_component (ow->component_id);
417  return;
418  }
419  }
420 }
421 
422 static void
423 gnc_order_update_window (OrderWindow *ow)
424 {
425  GncOrder *order;
426  GncOwner *owner;
427  gboolean hide_cd = FALSE;
428 
429  order = ow_get_order (ow);
430  owner = gncOrderGetOwner (order);
431 
432  if (ow->owner_choice)
433  {
434  gtk_container_remove (GTK_CONTAINER (ow->owner_box), ow->owner_choice);
435  gtk_widget_destroy (ow->owner_choice);
436  }
437 
438  switch (ow->dialog_type)
439  {
440  case VIEW_ORDER:
441  case EDIT_ORDER:
442  ow->owner_choice =
443  gnc_owner_edit_create (ow->owner_label, ow->owner_box, ow->book,
444  owner);
445  break;
446  case NEW_ORDER:
447  ow->owner_choice =
448  gnc_owner_select_create (ow->owner_label, ow->owner_box, ow->book,
449  owner);
450  break;
451  }
452 
453  g_signal_connect (ow->owner_choice, "changed",
454  G_CALLBACK (gnc_order_owner_changed_cb),
455  ow);
456 
457  gtk_widget_show_all (ow->dialog);
458 
459  {
460  GtkTextBuffer* text_buffer;
461  const char *string;
462  time64 tt;
463 
464  gtk_entry_set_text (GTK_ENTRY (ow->ref_entry),
465  gncOrderGetReference (order));
466 
467  string = gncOrderGetNotes (order);
468  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(ow->notes_text));
469  gtk_text_buffer_set_text (text_buffer, string, -1);
470 
471  tt = gncOrderGetDateOpened (order);
472  if (tt == INT64_MAX)
473  {
474  gnc_date_edit_set_time (GNC_DATE_EDIT (ow->opened_date),
475  gnc_time (NULL));
476  }
477  else
478  {
479  gnc_date_edit_set_time (GNC_DATE_EDIT (ow->opened_date), tt);
480  }
481 
482  /* If this is a "New Order Window" we can stop here! */
483  if (ow->dialog_type == NEW_ORDER)
484  return;
485 
486  tt = gncOrderGetDateClosed (order);
487  if (tt == INT64_MAX)
488  {
489  gnc_date_edit_set_time (GNC_DATE_EDIT (ow->closed_date),
490  gnc_time (NULL));
491  hide_cd = TRUE;
492  }
493  else
494  {
495  gnc_date_edit_set_time (GNC_DATE_EDIT (ow->closed_date), tt);
496  }
497 
498  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ow->active_check),
499  gncOrderGetActive (order));
500 
501  }
502 
503  gnc_gui_component_watch_entity_type (ow->component_id,
504  GNC_ORDER_MODULE_NAME,
505  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
506 
508 
509  if (hide_cd)
510  {
511  gtk_widget_hide (ow->closed_date);
512  gtk_widget_hide (ow->cd_label);
513  }
514 
515  if (ow->dialog_type == VIEW_ORDER)
516  {
517  /* Setup viewer for read-only access */
518  gtk_widget_set_sensitive (ow->id_entry, FALSE);
519  gtk_widget_set_sensitive (ow->opened_date, FALSE);
520  gtk_widget_set_sensitive (ow->closed_date, FALSE);
521  gtk_widget_set_sensitive (ow->notes_text, FALSE); /* XXX: Should notes remain writable? */
522 
523  /* Hide the 'close order' button */
524  gtk_widget_hide (ow->close_order_button);
525  }
526 }
527 
528 static gboolean
529 find_handler (gpointer find_data, gpointer user_data)
530 {
531  const GncGUID *order_guid = find_data;
532  OrderWindow *ow = user_data;
533 
534  return(ow && guid_equal(&ow->order_guid, order_guid));
535 }
536 
537 static OrderWindow *
538 gnc_order_new_window (GtkWindow *parent, QofBook *bookp, OrderDialogType type,
539  GncOrder *order, GncOwner *owner)
540 {
541  OrderWindow *ow;
542  GtkBuilder *builder;
543  GtkWidget *vbox, *regWidget, *hbox, *date;
544  GncEntryLedger *entry_ledger = NULL;
545  const char * class_name;
546 
547  switch (type)
548  {
549  case EDIT_ORDER:
550  class_name = DIALOG_EDIT_ORDER_CM_CLASS;
551  break;
552  case VIEW_ORDER:
553  default:
554  class_name = DIALOG_VIEW_ORDER_CM_CLASS;
555  break;
556  }
557 
558  /*
559  * Find an existing window for this order. If found, bring it to
560  * the front.
561  */
562  if (order)
563  {
564  GncGUID order_guid;
565 
566  order_guid = *gncOrderGetGUID(order);
567  ow = gnc_find_first_gui_component (class_name, find_handler,
568  &order_guid);
569  if (ow)
570  {
571  gtk_window_present (GTK_WINDOW(ow->dialog));
572  gtk_window_set_transient_for (GTK_WINDOW(ow->dialog), parent);
573  return(ow);
574  }
575  }
576 
577  /*
578  * No existing order window found. Build a new one.
579  */
580  ow = g_new0 (OrderWindow, 1);
581  ow->book = bookp;
582  ow->dialog_type = type;
583 
584  /* Save this for later */
585  gncOwnerCopy (owner, &(ow->owner));
586 
587  /* Find the dialog */
588  builder = gtk_builder_new();
589  gnc_builder_add_from_file (builder, "dialog-order.glade", "order_entry_dialog");
590  ow->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "order_entry_dialog"));
591  gtk_window_set_transient_for (GTK_WINDOW(ow->dialog), parent);
592 
593  // Set the name for this dialog so it can be easily manipulated with css
594  gtk_widget_set_name (GTK_WIDGET(ow->dialog), "gnc-id-order");
595  gnc_widget_style_context_add_class (GTK_WIDGET(ow->dialog), "gnc-class-orders");
596 
597  /* Grab the widgets */
598  ow->id_entry = GTK_WIDGET(gtk_builder_get_object (builder, "id_entry"));
599  ow->ref_entry = GTK_WIDGET(gtk_builder_get_object (builder, "ref_entry"));
600  ow->notes_text = GTK_WIDGET(gtk_builder_get_object (builder, "notes_text"));
601  ow->active_check = GTK_WIDGET(gtk_builder_get_object (builder, "active_check"));
602  ow->owner_box = GTK_WIDGET(gtk_builder_get_object (builder, "owner_hbox"));
603  ow->owner_label = GTK_WIDGET(gtk_builder_get_object (builder, "owner_label"));
604 
605  ow->cd_label = GTK_WIDGET(gtk_builder_get_object (builder, "cd_label"));
606  ow->close_order_button = GTK_WIDGET(gtk_builder_get_object (builder, "close_order_button"));
607 
608 
609  /* Setup Date Widgets */
610  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "opened_date_hbox"));
611  date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
612  gtk_box_pack_start (GTK_BOX (hbox), date, TRUE, TRUE, 0);
613  gtk_widget_show (date);
614  ow->opened_date = date;
615 
616  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "closed_date_hbox"));
617  date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
618  gtk_box_pack_start (GTK_BOX (hbox), date, TRUE, TRUE, 0);
619  gtk_widget_show (date);
620  ow->closed_date = date;
621 
622  /* Build the ledger */
623  switch (type)
624  {
625  case EDIT_ORDER:
626  entry_ledger = gnc_entry_ledger_new (ow->book, GNCENTRY_ORDER_ENTRY);
627  break;
628  case VIEW_ORDER:
629  default:
630  entry_ledger = gnc_entry_ledger_new (ow->book, GNCENTRY_ORDER_VIEWER);
631  break;
632  }
633 
634  /* Save the entry ledger for later */
635  ow->ledger = entry_ledger;
636 
637  /* Set the order for the entry_ledger */
638  gnc_entry_ledger_set_default_order (entry_ledger, order);
639 
640  /* Set watches on entries */
641  // entries = gncOrderGetEntries (order);
642  // gnc_entry_ledger_load (entry_ledger, entries);
643 
644  /* Watch the order of operations, here... */
645  regWidget = gnucash_register_new (gnc_entry_ledger_get_table (entry_ledger),
646  NULL);
647  ow->reg = GNUCASH_REGISTER (regWidget);
648  gnucash_sheet_set_window (gnucash_register_get_sheet (ow->reg), ow->dialog);
649  gnc_entry_ledger_set_parent (entry_ledger, ow->dialog);
650 
651  vbox = GTK_WIDGET(gtk_builder_get_object (builder, "ledger_vbox"));
652  gtk_box_pack_start (GTK_BOX(vbox), regWidget, TRUE, TRUE, 2);
653 
654  /* Setup signals */
655  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ow);
656 
657  /* Setup initial values */
658  ow->order_guid = *gncOrderGetGUID (order);
659 
660  gtk_entry_set_text (GTK_ENTRY (ow->id_entry), gncOrderGetID (order));
661 
662  ow->component_id =
663  gnc_register_gui_component (class_name,
664  gnc_order_window_refresh_handler,
665  gnc_order_window_close_handler,
666  ow);
667 
668  gnc_table_realize_gui (gnc_entry_ledger_get_table (entry_ledger));
669 
670  /* Now fill in a lot of the pieces and display properly */
671  gnc_order_update_window (ow);
672 
673  /* Maybe set the reference */
674  gnc_order_owner_changed_cb (ow->owner_choice, ow);
675 
676  g_object_unref(G_OBJECT(builder));
677 
678  return ow;
679 }
680 
681 static OrderWindow *
682 gnc_order_window_new_order (GtkWindow *parent, QofBook *bookp, GncOwner *owner)
683 {
684  OrderWindow *ow;
685  GtkBuilder *builder;
686  GncOrder *order;
687  gchar *string;
688  GtkWidget *hbox, *date;
689 
690  ow = g_new0 (OrderWindow, 1);
691  ow->book = bookp;
692  ow->dialog_type = NEW_ORDER;
693 
694  order = gncOrderCreate (bookp);
695  gncOrderSetOwner (order, owner);
696 
697  /* Save this for later */
698  gncOwnerCopy (owner, &(ow->owner));
699 
700  /* Find the dialog */
701  builder = gtk_builder_new();
702  gnc_builder_add_from_file (builder, "dialog-order.glade", "new_order_dialog");
703 
704  ow->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "new_order_dialog"));
705  gtk_window_set_transient_for (GTK_WINDOW(ow->dialog), parent);
706 
707  // Set the name for this dialog so it can be easily manipulated with css
708  gtk_widget_set_name (GTK_WIDGET(ow->dialog), "gnc-id-new-order");
709  gnc_widget_style_context_add_class (GTK_WIDGET(ow->dialog), "gnc-class-orders");
710 
711  g_object_set_data (G_OBJECT (ow->dialog), "dialog_info", ow);
712 
713  /* Grab the widgets */
714  ow->id_entry = GTK_WIDGET(gtk_builder_get_object (builder, "entry_id"));
715  ow->ref_entry = GTK_WIDGET(gtk_builder_get_object (builder, "entry_ref"));
716  ow->notes_text = GTK_WIDGET(gtk_builder_get_object (builder, "text_notes"));
717  ow->owner_box = GTK_WIDGET(gtk_builder_get_object (builder, "bill_owner_hbox"));
718  ow->owner_label = GTK_WIDGET(gtk_builder_get_object (builder, "bill_owner_label"));
719 
720  /* Setup date Widget */
721  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "date_opened_hbox"));
722  date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
723  gtk_box_pack_start (GTK_BOX (hbox), date, TRUE, TRUE, 0);
724  gtk_widget_show (date);
725  ow->opened_date = date;
726 
727  /* Setup signals */
728  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ow);
729 
730  /* Setup initial values */
731  ow->order_guid = *gncOrderGetGUID (order);
732  string = gncOrderNextID(bookp);
733  gtk_entry_set_text (GTK_ENTRY (ow->id_entry), string);
734  g_free(string);
735 
736  ow->component_id =
737  gnc_register_gui_component (DIALOG_NEW_ORDER_CM_CLASS,
738  gnc_order_window_refresh_handler,
739  gnc_order_window_close_handler,
740  ow);
741 
742  /* Now fill in a lot of the pieces and display properly */
743  gnc_order_update_window (ow);
744 
745  // The customer choice widget should have keyboard focus
746  if (GNC_IS_GENERAL_SEARCH(ow->owner_choice))
747  {
748  gnc_general_search_grab_focus(GNC_GENERAL_SEARCH(ow->owner_choice));
749  }
750 
751  /* Maybe set the reference */
752  gnc_order_owner_changed_cb (ow->owner_choice, ow);
753 
754  g_object_unref(G_OBJECT(builder));
755 
756  return ow;
757 }
758 
759 OrderWindow *
760 gnc_ui_order_edit (GtkWindow *parent, GncOrder *order)
761 {
762  OrderWindow *ow;
763  OrderDialogType type;
764 
765  if (!order) return NULL;
766 
767  type = EDIT_ORDER;
768  if (gncOrderGetDateClosed (order) == INT64_MAX)
769  type = VIEW_ORDER;
770 
771  ow = gnc_order_new_window (parent, gncOrderGetBook(order), type, order,
772  gncOrderGetOwner (order));
773 
774  return ow;
775 }
776 
777 OrderWindow *
778 gnc_ui_order_new (GtkWindow *parent, GncOwner *ownerp, QofBook *bookp)
779 {
780  OrderWindow *ow;
781  GncOwner owner;
782 
783  if (ownerp)
784  {
785  switch (gncOwnerGetType (ownerp))
786  {
787  case GNC_OWNER_CUSTOMER:
788  case GNC_OWNER_VENDOR:
789  case GNC_OWNER_JOB:
790  gncOwnerCopy (ownerp, &owner);
791  break;
792  default:
793  g_warning ("Cannot deal with unknown Owner types");
794  /* XXX: popup a warning? */
795  return NULL;
796  }
797  }
798  else
799  gncOwnerInitJob (&owner, NULL); /* XXX: pass in the owner type? */
800 
801  /* Make sure required options exist */
802  if (!bookp) return NULL;
803 
804  ow = gnc_order_window_new_order (parent, bookp, &owner);
805 
806  return ow;
807 }
808 
809 /* Functions for order selection widgets */
810 
811 static void
812 edit_order_cb (GtkWindow *dialog, gpointer *order_p, gpointer user_data)
813 {
814  GncOrder *order;
815 
816  g_return_if_fail (order_p && user_data);
817 
818  order = *order_p;
819 
820  if (order)
821  gnc_ui_order_edit (dialog, order);
822 
823  return;
824 }
825 
826 static gpointer
827 new_order_cb (GtkWindow *dialog, gpointer user_data)
828 {
829  struct _order_select_window *sw = user_data;
830  OrderWindow *ow;
831 
832  g_return_val_if_fail (user_data, NULL);
833 
834  ow = gnc_ui_order_new (dialog, sw->owner, sw->book);
835  return ow_get_order (ow);
836 }
837 
838 static void
839 free_order_cb (gpointer user_data)
840 {
841  struct _order_select_window *sw = user_data;
842 
843  g_return_if_fail (sw);
844 
845  qof_query_destroy (sw->q);
846  g_free (sw);
847 }
848 
849 GNCSearchWindow *
850 gnc_order_search (GtkWindow *parent, GncOrder *start, GncOwner *owner, QofBook *book)
851 {
852  QofIdType type = GNC_ORDER_MODULE_NAME;
853  struct _order_select_window *sw;
854  QofQuery *q, *q2 = NULL;
855  static GList *params = NULL;
856  static GList *columns = NULL;
857  static GNCSearchCallbackButton buttons[] =
858  {
859  { N_("View/Edit Order"), edit_order_cb, NULL, TRUE},
860  { NULL },
861  };
862 
863  g_return_val_if_fail (book, NULL);
864 
865  /* Build parameter list in reverse order */
866  if (params == NULL)
867  {
868  params = gnc_search_param_prepend (params, _("Order Notes"), NULL, type,
869  ORDER_NOTES, NULL);
870  params = gnc_search_param_prepend (params, _("Date Closed"), NULL, type,
871  ORDER_CLOSED, NULL);
872  params = gnc_search_param_prepend (params, _("Is Closed?"), NULL, type,
873  ORDER_IS_CLOSED, NULL);
874  params = gnc_search_param_prepend (params, _("Date Opened"), NULL, type,
875  ORDER_OPENED, NULL);
876  params = gnc_search_param_prepend (params, _("Owner Name"), NULL, type,
877  ORDER_OWNER, OWNER_NAME, NULL);
878  params = gnc_search_param_prepend (params, _("Order ID"), NULL, type,
879  ORDER_ID, NULL);
880  }
881 
882  /* Build the column list in reverse order */
883  if (columns == NULL)
884  {
885  columns = gnc_search_param_prepend (columns, _("Billing ID"), NULL, type,
886  ORDER_REFERENCE, NULL);
887  columns = gnc_search_param_prepend (columns, _("Company"), NULL, type,
888  ORDER_OWNER, OWNER_PARENT,
889  OWNER_NAME, NULL);
890  columns = gnc_search_param_prepend (columns, _("Closed"), NULL, type,
891  ORDER_CLOSED, NULL);
892  columns = gnc_search_param_prepend (columns, _("Opened"), NULL, type,
893  ORDER_OPENED, NULL);
894  columns = gnc_search_param_prepend (columns, _("Num"), NULL, type,
895  ORDER_ID, NULL);
896  }
897 
898  /* Build the queries */
899  q = qof_query_create_for (type);
900  qof_query_set_book (q, book);
901 
902  /* If owner is supplied, limit all searches to orders who's owner
903  * (or parent) is the supplied owner!
904  */
905  if (owner && gncOwnerGetGUID (owner))
906  {
907  QofQuery *tmp, *q3;
908 
909  q3 = qof_query_create_for (type);
910  qof_query_add_guid_match (q3, g_slist_prepend
911  (g_slist_prepend (NULL, QOF_PARAM_GUID),
912  ORDER_OWNER),
913  gncOwnerGetGUID (owner), QOF_QUERY_OR);
914  qof_query_add_guid_match (q3, g_slist_prepend
915  (g_slist_prepend (NULL, OWNER_PARENTG),
916  ORDER_OWNER),
917  gncOwnerGetGUID (owner), QOF_QUERY_OR);
918 
919  tmp = qof_query_merge (q, q3, QOF_QUERY_AND);
920  qof_query_destroy (q);
921  qof_query_destroy (q3);
922  q = tmp;
923  q2 = qof_query_copy (q);
924  }
925 
926 #if 0
927  if (start)
928  {
929  if (q2 == NULL)
930  q2 = qof_query_copy (q);
931 
932  qof_query_add_guid_match (q2, g_slist_prepend (NULL, QOF_PARAM_GUID),
933  gncOrderGetGUID (start), QOF_QUERY_AND);
934  }
935 #endif
936 
937  /* launch select dialog and return the result */
938  sw = g_new0 (struct _order_select_window, 1);
939 
940  if (owner)
941  {
942  gncOwnerCopy (owner, &(sw->owner_def));
943  sw->owner = &(sw->owner_def);
944  }
945  sw->book = book;
946  sw->q = q;
947 
948  return gnc_search_dialog_create (parent, type, _("Find Order"),
949  params, columns, q, q2,
950  buttons, NULL, new_order_cb,
951  sw, free_order_cb, GNC_PREFS_GROUP_SEARCH,
952  NULL, "gnc-class-orders");
953 }
954 
955 GNCSearchWindow *
956 gnc_order_search_select (GtkWindow *parent, gpointer start, gpointer book)
957 {
958  GncOrder *o = start;
959  GncOwner owner, *ownerp;
960 
961  if (!book) return NULL;
962 
963  if (o)
964  {
965  ownerp = gncOrderGetOwner (o);
966  gncOwnerCopy (ownerp, &owner);
967  }
968  else
969  gncOwnerInitCustomer (&owner, NULL); /* XXX */
970 
971  return gnc_order_search (parent, start, NULL, book);
972 }
973 
974 GNCSearchWindow *
975 gnc_order_search_edit (GtkWindow *parent, gpointer start, gpointer book)
976 {
977  if (start)
978  gnc_ui_order_edit (parent, start);
979 
980  return NULL;
981 }
const GncGUID * gncOwnerGetGUID(const GncOwner *owner)
Get the GncGUID of the immediate owner.
Definition: gncOwner.c:518
utility functions for the GnuCash UI
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
Definition: qofquery.cpp:1018
GncEntryLedger * gnc_entry_ledger_new(QofBook *book, GncEntryLedgerType type)
Create and return a new GncEntry Ledger.
GtkWidget * gnucash_register_new(Table *table, const gchar *state_section)
this already has scrollbars attached
const gchar * QofIdType
QofIdType declaration.
Definition: qofid.h:80
void gnc_table_refresh_gui(Table *table, gboolean do_scroll)
Refresh the whole GUI from the table.
Definition: table-gnome.c:165
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
void gnc_entry_ledger_set_default_order(GncEntryLedger *ledger, GncOrder *order)
Set the default order for this ledger.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
gboolean gnc_entry_ledger_check_close(GtkWidget *parent, GncEntryLedger *ledger)
This will ask the user if they really want to make a change.
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
Combine two queries together using the Boolean set (logical) operator &#39;op&#39;.
Definition: qofquery.cpp:1129
Public declarations of GnucashRegister class.
void qof_query_add_guid_match(QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
DOCUMENT ME !!
Definition: qofquery.cpp:1310
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Returns the GncOwnerType of this owner.
Definition: gncOwner.c:200
GncJob * gncOwnerGetJob(const GncOwner *owner)
If the given owner is of type GNC_OWNER_JOB, returns the pointer to the job object.
Definition: gncOwner.c:376
void gnc_entry_ledger_destroy(GncEntryLedger *ledger)
Destroy the GncEntry Ledger.
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition: guid.cpp:130
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
Table * gnc_entry_ledger_get_table(GncEntryLedger *ledger)
Get the Table.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
The type used to store guids in C.
Definition: guid.h:75
A Query.
Definition: qofquery.cpp:74