GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dialog-order.c
1 /*
2  * dialog-order.c -- Dialog for Order entry
3  * Copyright (C) 2001,2002 Derek Atkins
4  * Author: Derek Atkins <[email protected]>
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 [email protected]
22  */
23 
24 #include "config.h"
25 
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 
29 #include "dialog-utils.h"
30 #include "gnc-component-manager.h"
31 #include "gnc-date-edit.h"
32 #include "gnc-ui.h"
33 #include "gnc-gui-query.h"
34 #include "gnc-ui-util.h"
35 #include "qof.h"
36 #include "gnucash-sheet.h"
37 #include "dialog-search.h"
38 #include "search-param.h"
39 
40 #include "gncOrder.h"
41 #include "gncOrderP.h"
42 
43 #include "gncEntryLedger.h"
44 
45 #include "dialog-order.h"
46 #include "dialog-invoice.h"
47 #include "business-gnome-utils.h"
48 #include "dialog-date-close.h"
49 #include "gnome-search/gnc-general-search.h"
50 
51 #define DIALOG_NEW_ORDER_CM_CLASS "dialog-new-order"
52 #define DIALOG_EDIT_ORDER_CM_CLASS "dialog-edit-order"
53 #define DIALOG_VIEW_ORDER_CM_CLASS "dialog-view-order"
54 
55 #define GNC_PREFS_GROUP_SEARCH "dialogs.business.order-search"
56 
57 void gnc_order_window_ok_cb (GtkWidget *widget, gpointer data);
58 void gnc_order_window_cancel_cb (GtkWidget *widget, gpointer data);
59 void gnc_order_window_help_cb (GtkWidget *widget, gpointer data);
60 void gnc_order_window_invoice_cb (GtkWidget *widget, gpointer data);
61 void gnc_order_window_close_order_cb (GtkWidget *widget, gpointer data);
62 void gnc_order_window_destroy_cb (GtkWidget *widget, gpointer data);
63 
64 typedef enum
65 {
66  NEW_ORDER,
67  EDIT_ORDER,
68  VIEW_ORDER
69 } OrderDialogType;
70 
72 {
73  QofBook * book;
74  GncOwner * owner;
75  QofQuery * q;
76  GncOwner owner_def;
77 };
78 
80 {
81  GtkWidget * dialog;
82 
83  GtkWidget * id_entry;
84  GtkWidget * ref_entry;
85  GtkWidget * notes_text;
86  GtkWidget * opened_date;
87  GtkWidget * closed_date;
88  GtkWidget * active_check;
89 
90  GtkWidget * cd_label;
91  GtkWidget * hide1;
92  GtkWidget * hide2;
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  Timespec ts;
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_editable_get_chars
137  (GTK_EDITABLE (ow->id_entry), 0, -1));
138 
139  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(ow->notes_text));
140  gtk_text_buffer_get_bounds (text_buffer, &start, &end);
141  text = gtk_text_buffer_get_text (text_buffer, &start, &end, FALSE);
142  gncOrderSetNotes (order, text);
143 
144  gncOrderSetReference (order, gtk_editable_get_chars
145  (GTK_EDITABLE (ow->ref_entry), 0, -1));
146 
147  ts = gnc_date_edit_get_date_ts (GNC_DATE_EDIT (ow->opened_date));
148  gncOrderSetDateOpened (order, ts);
149 
150  if (ow->active_check)
151  gncOrderSetActive (order, gtk_toggle_button_get_active
152  (GTK_TOGGLE_BUTTON (ow->active_check)));
153 
154  gnc_owner_get_owner (ow->owner_choice, &(ow->owner));
155  gncOrderSetOwner (order, &(ow->owner));
156 
157  gncOrderCommitEdit (order);
158  gnc_resume_gui_refresh ();
159 }
160 
161 static gboolean
162 gnc_order_window_verify_ok (OrderWindow *ow)
163 {
164  const char *res;
165 
166  /* Check the ID */
167  res = gtk_entry_get_text (GTK_ENTRY (ow->id_entry));
168  if (g_strcmp0 (res, "") == 0)
169  {
170  gnc_error_dialog (ow->dialog, "%s",
171  _("The Order must be given an ID."));
172  return FALSE;
173  }
174 
175  /* Check the Owner */
176  gnc_owner_get_owner (ow->owner_choice, &(ow->owner));
177  res = gncOwnerGetName (&(ow->owner));
178  if (res == NULL || g_strcmp0 (res, "") == 0)
179  {
180  gnc_error_dialog (ow->dialog, "%s",
181  _("You need to supply Billing Information."));
182  return FALSE;
183  }
184 
185  return TRUE;
186 }
187 
188 static gboolean
189 gnc_order_window_ok_save (OrderWindow *ow)
190 {
191  if (!gnc_entry_ledger_check_close (ow->dialog, ow->ledger))
192  return FALSE;
193 
194  if (!gnc_order_window_verify_ok (ow))
195  return FALSE;
196 
197  /* Now save it off */
198  {
199  GncOrder *order = ow_get_order (ow);
200  if (order)
201  {
202  gnc_ui_to_order (ow, order);
203 
204  }
205  ow->created_order = order;
206  }
207  return TRUE;
208 }
209 
210 void
211 gnc_order_window_ok_cb (GtkWidget *widget, gpointer data)
212 {
213  OrderWindow *ow = data;
214 
215  if (!gnc_order_window_ok_save (ow))
216  return;
217 
218  /* Ok, we don't need this anymore */
219  ow->order_guid = *guid_null ();
220 
221  gnc_close_gui_component (ow->component_id);
222 }
223 
224 void
225 gnc_order_window_cancel_cb (GtkWidget *widget, gpointer data)
226 {
227  OrderWindow *ow = data;
228 
229  gnc_close_gui_component (ow->component_id);
230 }
231 
232 void
233 gnc_order_window_help_cb (GtkWidget *widget, gpointer data)
234 {
235  gnc_gnome_help(HF_HELP, HL_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 (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  Timespec ts;
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 (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 (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  timespecFromTime64 (&ts, gnc_time (NULL));
312  if (!gnc_dialog_date_close_parented (ow->dialog, message, label, TRUE, &ts))
313  return;
314 
315  gncOrderSetDateClosed (order, ts);
316 
317  /* save it off */
318  gnc_order_window_ok_save (ow);
319 
320  /* Reset the type; change to read-only */
321  ow->dialog_type = VIEW_ORDER;
322  gnc_entry_ledger_set_readonly (ow->ledger, TRUE);
323 
324  /* And redisplay the window */
325  gnc_order_update_window (ow);
326 }
327 
328 void
329 gnc_order_window_destroy_cb (GtkWidget *widget, gpointer data)
330 {
331  OrderWindow *ow = data;
332  GncOrder *order = ow_get_order (ow);
333 
334  gnc_suspend_gui_refresh ();
335 
336  if (ow->dialog_type == NEW_ORDER && order != NULL)
337  {
338  gncOrderBeginEdit (order);
339  gncOrderDestroy (order);
340  ow->order_guid = *guid_null ();
341  }
342 
343  if (ow->ledger)
344  gnc_entry_ledger_destroy (ow->ledger);
345  gnc_unregister_gui_component (ow->component_id);
346  gnc_resume_gui_refresh ();
347 
348  g_free (ow);
349 }
350 
351 static int
352 gnc_order_owner_changed_cb (GtkWidget *widget, gpointer data)
353 {
354  OrderWindow *ow = data;
355  GncOrder *order;
356 
357  if (!ow)
358  return FALSE;
359 
360  if (ow->dialog_type == VIEW_ORDER)
361  return FALSE;
362 
363  gnc_owner_get_owner (ow->owner_choice, &(ow->owner));
364 
365  /* Set the Order's owner now! */
366  order = ow_get_order (ow);
367  gncOrderSetOwner (order, &(ow->owner));
368 
369  if (ow->dialog_type == EDIT_ORDER)
370  return FALSE;
371 
372  /* Only set the reference during the New Job dialog */
373  switch (gncOwnerGetType (&(ow->owner)))
374  {
375  case GNC_OWNER_JOB:
376  {
377  char const *msg = gncJobGetReference (gncOwnerGetJob (&(ow->owner)));
378  gtk_entry_set_text (GTK_ENTRY (ow->ref_entry), msg ? msg : "");
379  break;
380  }
381  default:
382  gtk_entry_set_text (GTK_ENTRY (ow->ref_entry), "");
383  break;
384  }
385 
386  return FALSE;
387 }
388 
389 static void
390 gnc_order_window_close_handler (gpointer user_data)
391 {
392  OrderWindow *ow = user_data;
393 
394  gtk_widget_destroy (ow->dialog);
395 }
396 
397 static void
398 gnc_order_window_refresh_handler (GHashTable *changes, gpointer user_data)
399 {
400  OrderWindow *ow = user_data;
401  const EventInfo *info;
402  GncOrder *order = ow_get_order (ow);
403 
404  /* If there isn't a order behind us, close down */
405  if (!order)
406  {
407  gnc_close_gui_component (ow->component_id);
408  return;
409  }
410 
411  /* Next, close if this is a destroy event */
412  if (changes)
413  {
414  info = gnc_gui_get_entity_events (changes, &ow->order_guid);
415  if (info && (info->event_mask & QOF_EVENT_DESTROY))
416  {
417  gnc_close_gui_component (ow->component_id);
418  return;
419  }
420  }
421 }
422 
423 static void
424 gnc_order_update_window (OrderWindow *ow)
425 {
426  GncOrder *order;
427  GncOwner *owner;
428  gboolean hide_cd = FALSE;
429 
430  order = ow_get_order (ow);
431  owner = gncOrderGetOwner (order);
432 
433  if (ow->owner_choice)
434  {
435  gtk_container_remove (GTK_CONTAINER (ow->owner_box), ow->owner_choice);
436  gtk_widget_destroy (ow->owner_choice);
437  }
438 
439  switch (ow->dialog_type)
440  {
441  case VIEW_ORDER:
442  case EDIT_ORDER:
443  ow->owner_choice =
444  gnc_owner_edit_create (ow->owner_label, ow->owner_box, ow->book,
445  owner);
446  break;
447  case NEW_ORDER:
448  ow->owner_choice =
449  gnc_owner_select_create (ow->owner_label, ow->owner_box, ow->book,
450  owner);
451  break;
452  }
453 
454  g_signal_connect (ow->owner_choice, "changed",
455  G_CALLBACK (gnc_order_owner_changed_cb),
456  ow);
457 
458  gtk_widget_show_all (ow->dialog);
459 
460  {
461  GtkTextBuffer* text_buffer;
462  const char *string;
463  Timespec ts, ts_zero = {0, 0};
464 
465  gtk_entry_set_text (GTK_ENTRY (ow->ref_entry),
466  gncOrderGetReference (order));
467 
468  string = gncOrderGetNotes (order);
469  text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(ow->notes_text));
470  gtk_text_buffer_set_text (text_buffer, string, -1);
471 
472  ts = gncOrderGetDateOpened (order);
473  if (timespec_equal (&ts, &ts_zero))
474  {
475  gnc_date_edit_set_time (GNC_DATE_EDIT (ow->opened_date),
476  gnc_time (NULL));
477  }
478  else
479  {
480  gnc_date_edit_set_time_ts (GNC_DATE_EDIT (ow->opened_date), ts);
481  }
482 
483  /* If this is a "New Order Window" we can stop here! */
484  if (ow->dialog_type == NEW_ORDER)
485  return;
486 
487  ts = gncOrderGetDateClosed (order);
488  if (timespec_equal (&ts, &ts_zero))
489  {
490  gnc_date_edit_set_time (GNC_DATE_EDIT (ow->closed_date),
491  gnc_time (NULL));
492  hide_cd = TRUE;
493  }
494  else
495  {
496  gnc_date_edit_set_time_ts (GNC_DATE_EDIT (ow->closed_date), ts);
497  }
498 
499  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ow->active_check),
500  gncOrderGetActive (order));
501 
502  }
503 
504  gnc_gui_component_watch_entity_type (ow->component_id,
505  GNC_ORDER_MODULE_NAME,
506  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
507 
508  gnc_table_refresh_gui (gnc_entry_ledger_get_table (ow->ledger), TRUE);
509 
510  if (hide_cd)
511  {
512  gtk_widget_hide (ow->closed_date);
513  gtk_widget_hide (ow->cd_label);
514  gtk_widget_hide (ow->hide1);
515  gtk_widget_hide (ow->hide2);
516  }
517 
518  if (ow->dialog_type == VIEW_ORDER)
519  {
520  /* Setup viewer for read-only access */
521  gtk_widget_set_sensitive (ow->id_entry, FALSE);
522  gtk_widget_set_sensitive (ow->opened_date, FALSE);
523  gtk_widget_set_sensitive (ow->closed_date, FALSE);
524  gtk_widget_set_sensitive (ow->notes_text, FALSE); /* XXX: Should notes remain writable? */
525 
526  /* Hide the 'close order' button */
527  gtk_widget_hide (ow->close_order_button);
528  }
529 }
530 
531 static gboolean
532 find_handler (gpointer find_data, gpointer user_data)
533 {
534  const GncGUID *order_guid = find_data;
535  OrderWindow *ow = user_data;
536 
537  return(ow && guid_equal(&ow->order_guid, order_guid));
538 }
539 
540 static OrderWindow *
541 gnc_order_new_window (QofBook *bookp, OrderDialogType type,
542  GncOrder *order, GncOwner *owner)
543 {
544  OrderWindow *ow;
545  GtkBuilder *builder;
546  GtkWidget *vbox, *regWidget, *hbox, *date;
547  GncEntryLedger *entry_ledger = NULL;
548  const char * class_name;
549 
550  switch (type)
551  {
552  case EDIT_ORDER:
553  class_name = DIALOG_EDIT_ORDER_CM_CLASS;
554  break;
555  case VIEW_ORDER:
556  default:
557  class_name = DIALOG_VIEW_ORDER_CM_CLASS;
558  break;
559  }
560 
561  /*
562  * Find an existing window for this order. If found, bring it to
563  * the front.
564  */
565  if (order)
566  {
567  GncGUID order_guid;
568 
569  order_guid = *gncOrderGetGUID(order);
570  ow = gnc_find_first_gui_component (class_name, find_handler,
571  &order_guid);
572  if (ow)
573  {
574  gtk_window_present (GTK_WINDOW(ow->dialog));
575  return(ow);
576  }
577  }
578 
579  /*
580  * No existing order window found. Build a new one.
581  */
582  ow = g_new0 (OrderWindow, 1);
583  ow->book = bookp;
584  ow->dialog_type = type;
585 
586  /* Save this for later */
587  gncOwnerCopy (owner, &(ow->owner));
588 
589  /* Find the dialog */
590  builder = gtk_builder_new();
591  gnc_builder_add_from_file (builder, "dialog-order.glade", "Order Entry Dialog");
592  ow->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Order Entry Dialog"));
593 
594  /* Grab the widgets */
595  ow->id_entry = GTK_WIDGET(gtk_builder_get_object (builder, "id_entry"));
596  ow->ref_entry = GTK_WIDGET(gtk_builder_get_object (builder, "ref_entry"));
597  ow->notes_text = GTK_WIDGET(gtk_builder_get_object (builder, "notes_text"));
598  ow->active_check = GTK_WIDGET(gtk_builder_get_object (builder, "active_check"));
599  ow->owner_box = GTK_WIDGET(gtk_builder_get_object (builder, "owner_hbox"));
600  ow->owner_label = GTK_WIDGET(gtk_builder_get_object (builder, "owner_label"));
601 
602  ow->cd_label = GTK_WIDGET(gtk_builder_get_object (builder, "cd_label"));
603  ow->hide1 = GTK_WIDGET(gtk_builder_get_object (builder, "hide1"));
604  ow->hide2 = GTK_WIDGET(gtk_builder_get_object (builder, "hide2"));
605  ow->close_order_button = GTK_WIDGET(gtk_builder_get_object (builder, "close_order_button"));
606 
607 
608  /* Setup Date Widgets */
609  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "opened_date_hbox"));
610  date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
611  gtk_box_pack_start (GTK_BOX (hbox), date, TRUE, TRUE, 0);
612  gtk_widget_show (date);
613  ow->opened_date = date;
614 
615  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "closed_date_hbox"));
616  date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
617  gtk_box_pack_start (GTK_BOX (hbox), date, TRUE, TRUE, 0);
618  gtk_widget_show (date);
619  ow->closed_date = date;
620 
621  /* Build the ledger */
622  switch (type)
623  {
624  case EDIT_ORDER:
625  entry_ledger = gnc_entry_ledger_new (ow->book, GNCENTRY_ORDER_ENTRY);
626  break;
627  case VIEW_ORDER:
628  default:
629  entry_ledger = gnc_entry_ledger_new (ow->book, GNCENTRY_ORDER_VIEWER);
630  break;
631  }
632 
633  /* Save the entry ledger for later */
634  ow->ledger = entry_ledger;
635 
636  /* Set the order for the entry_ledger */
637  gnc_entry_ledger_set_default_order (entry_ledger, order);
638 
639  /* Set watches on entries */
640  // entries = gncOrderGetEntries (order);
641  // gnc_entry_ledger_load (entry_ledger, entries);
642 
643  /* Watch the order of operations, here... */
644  regWidget = gnucash_register_new (gnc_entry_ledger_get_table (entry_ledger));
645  gnc_table_init_gui( regWidget, NULL);
646  ow->reg = GNUCASH_REGISTER (regWidget);
647  gnucash_sheet_set_window (gnucash_register_get_sheet (ow->reg), ow->dialog);
648  gnc_entry_ledger_set_parent (entry_ledger, ow->dialog);
649 
650  vbox = GTK_WIDGET(gtk_builder_get_object (builder, "ledger_vbox"));
651  // gtk_box_pack_start (GTK_BOX(vbox), toolbar, FALSE, FALSE, 2);
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 (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 
706  g_object_set_data (G_OBJECT (ow->dialog), "dialog_info", ow);
707 
708  /* Grab the widgets */
709  ow->id_entry = GTK_WIDGET(gtk_builder_get_object (builder, "entry_id"));
710  ow->ref_entry = GTK_WIDGET(gtk_builder_get_object (builder, "entry_ref"));
711  ow->notes_text = GTK_WIDGET(gtk_builder_get_object (builder, "text_notes"));
712  ow->owner_box = GTK_WIDGET(gtk_builder_get_object (builder, "bill_owner_hbox"));
713  ow->owner_label = GTK_WIDGET(gtk_builder_get_object (builder, "bill_owner_label"));
714 
715  /* Setup date Widget */
716  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "date_opened_hbox"));
717  date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
718  gtk_box_pack_start (GTK_BOX (hbox), date, TRUE, TRUE, 0);
719  gtk_widget_show (date);
720  ow->opened_date = date;
721 
722  /* Setup signals */
723  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, ow);
724 
725  /* Setup initial values */
726  ow->order_guid = *gncOrderGetGUID (order);
727  string = gncOrderNextID(bookp);
728  gtk_entry_set_text (GTK_ENTRY (ow->id_entry), string);
729  g_free(string);
730 
731  ow->component_id =
732  gnc_register_gui_component (DIALOG_NEW_ORDER_CM_CLASS,
733  gnc_order_window_refresh_handler,
734  gnc_order_window_close_handler,
735  ow);
736 
737  /* Now fill in a lot of the pieces and display properly */
738  gnc_order_update_window (ow);
739 
740  // The customer choice widget should have keyboard focus
741  if (GNC_IS_GENERAL_SEARCH(ow->owner_choice))
742  {
743  gnc_general_search_grab_focus(GNC_GENERAL_SEARCH(ow->owner_choice));
744  }
745 
746  /* Maybe set the reference */
747  gnc_order_owner_changed_cb (ow->owner_choice, ow);
748 
749  g_object_unref(G_OBJECT(builder));
750 
751  return ow;
752 }
753 
754 OrderWindow *
755 gnc_ui_order_edit (GncOrder *order)
756 {
757  OrderWindow *ow;
758  OrderDialogType type;
759 
760  if (!order) return NULL;
761 
762  type = EDIT_ORDER;
763  {
764  Timespec ts = gncOrderGetDateClosed (order);
765  if (ts.tv_sec || ts.tv_nsec)
766  type = VIEW_ORDER;
767  }
768 
769  ow = gnc_order_new_window (gncOrderGetBook(order), type, order,
770  gncOrderGetOwner (order));
771 
772  return ow;
773 }
774 
775 OrderWindow *
776 gnc_ui_order_new (GncOwner *ownerp, QofBook *bookp)
777 {
778  OrderWindow *ow;
779  GncOwner owner;
780 
781  if (ownerp)
782  {
783  switch (gncOwnerGetType (ownerp))
784  {
785  case GNC_OWNER_CUSTOMER:
786  case GNC_OWNER_VENDOR:
787  case GNC_OWNER_JOB:
788  gncOwnerCopy (ownerp, &owner);
789  break;
790  default:
791  g_warning ("Cannot deal with unknown Owner types");
792  /* XXX: popup a warning? */
793  return NULL;
794  }
795  }
796  else
797  gncOwnerInitJob (&owner, NULL); /* XXX: pass in the owner type? */
798 
799  /* Make sure required options exist */
800  if (!bookp) return NULL;
801 
802  ow = gnc_order_window_new_order (bookp, &owner);
803 
804  return ow;
805 }
806 
807 /* Functions for order selection widgets */
808 
809 static void
810 edit_order_cb (gpointer *order_p, gpointer user_data)
811 {
812  GncOrder *order;
813 
814  g_return_if_fail (order_p && user_data);
815 
816  order = *order_p;
817 
818  if (order)
819  gnc_ui_order_edit (order);
820 
821  return;
822 }
823 
824 static gpointer
825 new_order_cb (gpointer user_data)
826 {
827  struct _order_select_window *sw = user_data;
828  OrderWindow *ow;
829 
830  g_return_val_if_fail (user_data, NULL);
831 
832  ow = gnc_ui_order_new (sw->owner, sw->book);
833  return ow_get_order (ow);
834 }
835 
836 static void
837 free_order_cb (gpointer user_data)
838 {
839  struct _order_select_window *sw = user_data;
840 
841  g_return_if_fail (sw);
842 
843  qof_query_destroy (sw->q);
844  g_free (sw);
845 }
846 
848 gnc_order_search (GncOrder *start, GncOwner *owner, QofBook *book)
849 {
850  QofIdType type = GNC_ORDER_MODULE_NAME;
851  struct _order_select_window *sw;
852  QofQuery *q, *q2 = NULL;
853  static GList *params = NULL;
854  static GList *columns = NULL;
855  static GNCSearchCallbackButton buttons[] =
856  {
857  { N_("View/Edit Order"), edit_order_cb, NULL, TRUE},
858  { NULL },
859  };
860 
861  g_return_val_if_fail (book, NULL);
862 
863  /* Build parameter list in reverse order */
864  if (params == NULL)
865  {
866  params = gnc_search_param_prepend (params, _("Order Notes"), NULL, type,
867  ORDER_NOTES, NULL);
868  params = gnc_search_param_prepend (params, _("Date Closed"), NULL, type,
869  ORDER_CLOSED, NULL);
870  params = gnc_search_param_prepend (params, _("Is Closed?"), NULL, type,
871  ORDER_IS_CLOSED, NULL);
872  params = gnc_search_param_prepend (params, _("Date Opened"), NULL, type,
873  ORDER_OPENED, NULL);
874  params = gnc_search_param_prepend (params, _("Owner Name "), NULL, type,
875  ORDER_OWNER, OWNER_NAME, NULL);
876  params = gnc_search_param_prepend (params, _("Order ID"), NULL, type,
877  ORDER_ID, NULL);
878  }
879 
880  /* Build the column list in reverse order */
881  if (columns == NULL)
882  {
883  columns = gnc_search_param_prepend (columns, _("Billing ID"), NULL, type,
884  ORDER_REFERENCE, NULL);
885  columns = gnc_search_param_prepend (columns, _("Company"), NULL, type,
886  ORDER_OWNER, OWNER_PARENT,
887  OWNER_NAME, NULL);
888  columns = gnc_search_param_prepend (columns, _("Closed"), NULL, type,
889  ORDER_CLOSED, NULL);
890  columns = gnc_search_param_prepend (columns, _("Opened"), NULL, type,
891  ORDER_OPENED, NULL);
892  columns = gnc_search_param_prepend (columns, _("Num"), NULL, type,
893  ORDER_ID, NULL);
894  }
895 
896  /* Build the queries */
897  q = qof_query_create_for (type);
898  qof_query_set_book (q, book);
899 
900  /* If owner is supplied, limit all searches to orders who's owner
901  * (or parent) is the supplied owner!
902  */
903  if (owner && gncOwnerGetGUID (owner))
904  {
905  QofQuery *tmp, *q3;
906 
907  q3 = qof_query_create_for (type);
908  qof_query_add_guid_match (q3, g_slist_prepend
909  (g_slist_prepend (NULL, QOF_PARAM_GUID),
910  ORDER_OWNER),
911  gncOwnerGetGUID (owner), QOF_QUERY_OR);
912  qof_query_add_guid_match (q3, g_slist_prepend
913  (g_slist_prepend (NULL, OWNER_PARENTG),
914  ORDER_OWNER),
915  gncOwnerGetGUID (owner), QOF_QUERY_OR);
916 
917  tmp = qof_query_merge (q, q3, QOF_QUERY_AND);
918  qof_query_destroy (q);
919  qof_query_destroy (q3);
920  q = tmp;
921  q2 = qof_query_copy (q);
922  }
923 
924 #if 0
925  if (start)
926  {
927  if (q2 == NULL)
928  q2 = qof_query_copy (q);
929 
930  qof_query_add_guid_match (q2, g_slist_prepend (NULL, QOF_PARAM_GUID),
931  gncOrderGetGUID (start), QOF_QUERY_AND);
932  }
933 #endif
934 
935  /* launch select dialog and return the result */
936  sw = g_new0 (struct _order_select_window, 1);
937 
938  if (owner)
939  {
940  gncOwnerCopy (owner, &(sw->owner_def));
941  sw->owner = &(sw->owner_def);
942  }
943  sw->book = book;
944  sw->q = q;
945 
946  return gnc_search_dialog_create (type, _("Find Order"),
947  params, columns, q, q2,
948  buttons, NULL, new_order_cb,
949  sw, free_order_cb, GNC_PREFS_GROUP_SEARCH,
950  NULL);
951 }
952 
954 gnc_order_search_select (gpointer start, gpointer book)
955 {
956  GncOrder *o = start;
957  GncOwner owner, *ownerp;
958 
959  if (!book) return NULL;
960 
961  if (o)
962  {
963  ownerp = gncOrderGetOwner (o);
964  gncOwnerCopy (ownerp, &owner);
965  }
966  else
967  gncOwnerInitCustomer (&owner, NULL); /* XXX */
968 
969  return gnc_order_search (start, NULL, book);
970 }
971 
973 gnc_order_search_edit (gpointer start, gpointer book)
974 {
975  if (start)
976  gnc_ui_order_edit (start);
977 
978  return NULL;
979 }
const GncGUID * gncOwnerGetGUID(const GncOwner *owner)
Definition: gncOwner.c:496
utility functions for the GnuCash UI
gboolean timespec_equal(const Timespec *ta, const Timespec *tb)
QofQuery * qof_query_copy(QofQuery *q)
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
struct _QofQuery QofQuery
Definition: qofquery.h:90
Definition: guid.h:65
const gchar * QofIdType
Definition: qofid.h:85
void qof_query_destroy(QofQuery *q)
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
void qof_query_set_book(QofQuery *q, QofBook *book)
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
void gnc_table_init_gui(GtkWidget *widget, gchar *state_section)
Definition: table-gnome.c:157
void gnc_gnome_help(const char *file_name, const char *anchor)
void qof_query_add_guid_match(QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
GncOwnerType gncOwnerGetType(const GncOwner *owner)
Definition: gncOwner.c:201
GncJob * gncOwnerGetJob(const GncOwner *owner)
Definition: gncOwner.c:354
const GncGUID * guid_null(void)
time64 gnc_time(time64 *tbuf)
get the current local time
void timespecFromTime64(Timespec *ts, time64 t)