1 /*
2 * dialog-job.c -- Dialog for Job 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
29 #include "dialog-utils.h"
30 #include "gnc-amount-edit.h"
31 #include "gnc-component-manager.h"
32 #include "gnc-ui.h"
33 #include "gnc-gui-query.h"
34 #include "qof.h"
35 #include "dialog-search.h"
36 #include "search-param.h"
37
38 #include "gncBusiness.h"
39 #include "gncJob.h"
40 #include "gncJobP.h"
41
42 #include "business-gnome-utils.h"
43 #include "dialog-job.h"
44 #include "dialog-invoice.h"
45 #include "dialog-payment.h"
46
47 #define DIALOG_NEW_JOB_CM_CLASS "dialog-new-job"
48 #define DIALOG_EDIT_JOB_CM_CLASS "dialog-edit-job"
49
50 #define GNC_PREFS_GROUP_SEARCH "dialogs.business.job-search"
51
52 void gnc_job_window_ok_cb (GtkWidget *widget, gpointer data);
53 void gnc_job_window_cancel_cb (GtkWidget *widget, gpointer data);
54 void gnc_job_window_help_cb (GtkWidget *widget, gpointer data);
55 void gnc_job_window_destroy_cb (GtkWidget *widget, gpointer data);
56 void gnc_job_name_changed_cb (GtkWidget *widget, gpointer data);
57
58 typedef enum
59 {
60 NEW_JOB,
61 EDIT_JOB
62 } JobDialogType;
63
64 struct _job_select_window
65 {
66 QofBook *book;
67 GncOwner *owner;
68 QofQuery *q;
69 GncOwner owner_def;
70 };
71
72 struct _job_window
73 {
74 GtkWidget * dialog;
75 GtkWidget * id_entry;
76 GtkWidget * cust_edit;
77 GtkWidget * name_entry;
78 GtkWidget * desc_entry;
79 GtkWidget * rate_entry;
80 GtkWidget * active_check;
81
82 JobDialogType dialog_type;
83 GncGUID job_guid;
84 gint component_id;
85 QofBook * book;
86 GncJob * created_job;
87
88 GncOwner owner;
89
90 };
91
92 static GncJob *
jw_get_job(JobWindow * jw)93 jw_get_job (JobWindow *jw)
94 {
95 if (!jw)
96 return NULL;
97
98 return gncJobLookup (jw->book, &jw->job_guid);
99 }
100
gnc_ui_to_job(JobWindow * jw,GncJob * job)101 static void gnc_ui_to_job (JobWindow *jw, GncJob *job)
102 {
103 gnc_suspend_gui_refresh ();
104 gncJobBeginEdit (job);
105
106 qof_event_gen(QOF_INSTANCE(job), QOF_EVENT_ADD, NULL);
107
108 gncJobSetID (job, gtk_editable_get_chars (GTK_EDITABLE (jw->id_entry),
109 0, -1));
110 gncJobSetName (job, gtk_editable_get_chars (GTK_EDITABLE (jw->name_entry),
111 0, -1));
112 gncJobSetReference (job, gtk_editable_get_chars
113 (GTK_EDITABLE (jw->desc_entry), 0, -1));
114 gncJobSetRate (job, gnc_amount_edit_get_amount
115 (GNC_AMOUNT_EDIT (jw->rate_entry)));
116 gncJobSetActive (job, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
117 (jw->active_check)));
118 {
119 GncOwner * old = gncJobGetOwner (job);
120 gnc_owner_get_owner (jw->cust_edit, &(jw->owner));
121 if (! gncOwnerEqual (old, &(jw->owner)))
122 gncJobSetOwner (job, &(jw->owner));
123 }
124
125 gncJobCommitEdit (job);
126 gnc_resume_gui_refresh ();
127 }
128
129 static gboolean
gnc_job_verify_ok(JobWindow * jw)130 gnc_job_verify_ok (JobWindow *jw)
131 {
132 const char *res;
133 gchar *string;
134
135 /* Check for valid name */
136 res = gtk_entry_get_text (GTK_ENTRY (jw->name_entry));
137 if (g_strcmp0 (res, "") == 0)
138 {
139 const char *message = _("The Job must be given a name.");
140 gnc_error_dialog (GTK_WINDOW (jw->dialog), "%s", message);
141 return FALSE;
142 }
143
144 /* Check for owner */
145 gnc_owner_get_owner (jw->cust_edit, &(jw->owner));
146 res = gncOwnerGetName (&(jw->owner));
147 if (res == NULL || g_strcmp0 (res, "") == 0)
148 {
149 const char *message = _("You must choose an owner for this job.");
150 gnc_error_dialog (GTK_WINDOW (jw->dialog), "%s", message);
151 return FALSE;
152 }
153
154 /* Check for valid rate */
155 if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT(jw->rate_entry), NULL))
156 {
157 const char *message = _("The rate amount must be valid or you must leave it blank.");
158 gnc_error_dialog (GTK_WINDOW (jw->dialog), "%s", message);
159 return FALSE;
160 }
161
162 /* Set a valid id if one was not created */
163 res = gtk_entry_get_text (GTK_ENTRY (jw->id_entry));
164 if (g_strcmp0 (res, "") == 0)
165 {
166 string = gncJobNextID(jw->book);
167 gtk_entry_set_text (GTK_ENTRY (jw->id_entry), string);
168 g_free(string);
169 }
170
171 /* Now save it off */
172 {
173 GncJob *job = jw_get_job (jw);
174 if (job)
175 {
176 gnc_ui_to_job (jw, job);
177 }
178 }
179
180 /* Ok, it's been saved... Change to an editor.. */
181 jw->dialog_type = EDIT_JOB;
182
183 return TRUE;
184 }
185
186 void
gnc_job_window_ok_cb(GtkWidget * widget,gpointer data)187 gnc_job_window_ok_cb (GtkWidget *widget, gpointer data)
188 {
189 JobWindow *jw = data;
190
191 /* Make sure this is ok */
192 if (!gnc_job_verify_ok (jw))
193 return;
194
195 /* Now save off the job so we can return it */
196 jw->created_job = jw_get_job (jw);
197 jw->job_guid = *guid_null ();
198
199 gnc_close_gui_component (jw->component_id);
200 }
201
202 void
gnc_job_window_cancel_cb(GtkWidget * widget,gpointer data)203 gnc_job_window_cancel_cb (GtkWidget *widget, gpointer data)
204 {
205 JobWindow *jw = data;
206
207 gnc_close_gui_component (jw->component_id);
208 }
209
210 void
gnc_job_window_help_cb(GtkWidget * widget,gpointer data)211 gnc_job_window_help_cb (GtkWidget *widget, gpointer data)
212 {
213 JobWindow *jw = data;
214 gnc_gnome_help (GTK_WINDOW(jw->dialog), HF_HELP, HL_USAGE_JOB);
215 }
216
217
218 void
gnc_job_window_destroy_cb(GtkWidget * widget,gpointer data)219 gnc_job_window_destroy_cb (GtkWidget *widget, gpointer data)
220 {
221 JobWindow *jw = data;
222 GncJob *job = jw_get_job (jw);
223
224 gnc_suspend_gui_refresh ();
225
226 if (jw->dialog_type == NEW_JOB && job != NULL)
227 {
228 gncJobBeginEdit (job);
229 gncJobDestroy (job);
230 jw->job_guid = *guid_null ();
231 }
232
233 gnc_unregister_gui_component (jw->component_id);
234 gnc_resume_gui_refresh ();
235
236 g_free (jw);
237 }
238
239 void
gnc_job_name_changed_cb(GtkWidget * widget,gpointer data)240 gnc_job_name_changed_cb (GtkWidget *widget, gpointer data)
241 {
242 JobWindow *jw = data;
243 char *fullname, *title;
244 const char *name, *id;
245
246 if (!jw)
247 return;
248
249 name = gtk_entry_get_text (GTK_ENTRY (jw->name_entry));
250 if (!name || *name == '\0')
251 name = _("<No name>");
252
253 id = gtk_entry_get_text (GTK_ENTRY (jw->id_entry));
254
255 fullname = g_strconcat (name, " (", id, ")", (char *)NULL);
256
257 if (jw->dialog_type == EDIT_JOB)
258 title = g_strconcat (_("Edit Job"), " - ", fullname, (char *)NULL);
259 else
260 title = g_strconcat (_("New Job"), " - ", fullname, (char *)NULL);
261
262 gtk_window_set_title (GTK_WINDOW (jw->dialog), title);
263
264 g_free (fullname);
265 g_free (title);
266 }
267
268 static void
gnc_job_window_close_handler(gpointer user_data)269 gnc_job_window_close_handler (gpointer user_data)
270 {
271 JobWindow *jw = user_data;
272
273 gtk_widget_destroy (jw->dialog);
274 /* jw is already freed at this point
275 jw->dialog = NULL; */
276 }
277
278 static void
gnc_job_window_refresh_handler(GHashTable * changes,gpointer user_data)279 gnc_job_window_refresh_handler (GHashTable *changes, gpointer user_data)
280 {
281 JobWindow *jw = user_data;
282 const EventInfo *info;
283 GncJob *job = jw_get_job (jw);
284
285 /* If there isn't a job behind us, close down */
286 if (!job)
287 {
288 gnc_close_gui_component (jw->component_id);
289 return;
290 }
291
292 /* Next, close if this is a destroy event */
293 if (changes)
294 {
295 info = gnc_gui_get_entity_events (changes, &jw->job_guid);
296 if (info && (info->event_mask & QOF_EVENT_DESTROY))
297 {
298 gnc_close_gui_component (jw->component_id);
299 return;
300 }
301 }
302 }
303
304 static gboolean
find_handler(gpointer find_data,gpointer user_data)305 find_handler (gpointer find_data, gpointer user_data)
306 {
307 const GncGUID *job_guid = find_data;
308 JobWindow *jw = user_data;
309
310 return(jw && guid_equal(&jw->job_guid, job_guid));
311 }
312
313 static JobWindow *
gnc_job_new_window(GtkWindow * parent,QofBook * bookp,GncOwner * owner,GncJob * job)314 gnc_job_new_window (GtkWindow *parent, QofBook *bookp, GncOwner *owner, GncJob *job)
315 {
316 JobWindow *jw;
317 GtkBuilder *builder;
318 GtkWidget *owner_box, *owner_label, *edit, *hbox;
319
320 /*
321 * Find an existing window for this job. If found, bring it to
322 * the front.
323 */
324 if (job)
325 {
326 GncGUID job_guid;
327
328 job_guid = *gncJobGetGUID (job);
329 jw = gnc_find_first_gui_component (DIALOG_EDIT_JOB_CM_CLASS,
330 find_handler, &job_guid);
331 if (jw)
332 {
333 gtk_window_set_transient_for (GTK_WINDOW(jw->dialog), parent);
334 gtk_window_present (GTK_WINDOW(jw->dialog));
335 return(jw);
336 }
337 }
338
339 /*
340 * No existing job window found. Build a new one.
341 */
342 jw = g_new0 (JobWindow, 1);
343 jw->book = bookp;
344 gncOwnerCopy (owner, &(jw->owner)); /* save it off now, we know it's valid */
345
346 /* Load the Glade File */
347 builder = gtk_builder_new();
348 gnc_builder_add_from_file (builder, "dialog-job.glade", "job_dialog");
349
350 /* Find the dialog */
351 jw->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "job_dialog"));
352 gtk_window_set_transient_for (GTK_WINDOW(jw->dialog), parent);
353
354 // Set the name for this dialog so it can be easily manipulated with css
355 gtk_widget_set_name (GTK_WIDGET(jw->dialog), "gnc-id-job");
356 gnc_widget_style_context_add_class (GTK_WIDGET(jw->dialog), "gnc-class-jobs");
357
358 /* Get entry points */
359 jw->id_entry = GTK_WIDGET(gtk_builder_get_object (builder, "id_entry"));
360 jw->name_entry = GTK_WIDGET(gtk_builder_get_object (builder, "name_entry"));
361 jw->desc_entry = GTK_WIDGET(gtk_builder_get_object (builder, "desc_entry"));
362 jw->active_check = GTK_WIDGET(gtk_builder_get_object (builder, "active_check"));
363
364 owner_box = GTK_WIDGET(gtk_builder_get_object (builder, "customer_hbox"));
365 owner_label = GTK_WIDGET(gtk_builder_get_object (builder, "owner_label"));
366
367 edit = gnc_amount_edit_new();
368 gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (edit), TRUE);
369
370 jw->rate_entry = edit;
371 gtk_widget_show (edit);
372
373 hbox = GTK_WIDGET(gtk_builder_get_object (builder, "rate_entry"));
374 gtk_box_pack_start (GTK_BOX (hbox), edit, TRUE, TRUE, 0);
375
376 /* Setup signals */
377 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, jw);
378
379
380 /* Set initial entries */
381 if (job != NULL)
382 {
383 jw->job_guid = *gncJobGetGUID (job);
384
385 jw->dialog_type = EDIT_JOB;
386 jw->cust_edit = gnc_owner_edit_create (owner_label, owner_box,
387 bookp, owner);
388
389 gtk_entry_set_text (GTK_ENTRY (jw->id_entry), gncJobGetID (job));
390 gtk_entry_set_text (GTK_ENTRY (jw->name_entry), gncJobGetName (job));
391 gtk_entry_set_text (GTK_ENTRY (jw->desc_entry), gncJobGetReference (job));
392 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (jw->rate_entry),
393 gncJobGetRate (job));
394 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (jw->active_check),
395 gncJobGetActive (job));
396
397 jw->component_id = gnc_register_gui_component (DIALOG_EDIT_JOB_CM_CLASS,
398 gnc_job_window_refresh_handler,
399 gnc_job_window_close_handler,
400 jw);
401 }
402 else
403 {
404 job = gncJobCreate (bookp);
405 gncJobSetOwner (job, owner);
406 jw->job_guid = *gncJobGetGUID (job);
407
408 jw->dialog_type = NEW_JOB;
409
410 /* If we are passed a real owner, don't allow the user to change it */
411 if (owner->owner.undefined)
412 {
413 jw->cust_edit = gnc_owner_edit_create (owner_label, owner_box,
414 bookp, owner);
415 }
416 else
417 {
418 jw->cust_edit = gnc_owner_select_create (owner_label, owner_box,
419 bookp, owner);
420 }
421
422 jw->component_id = gnc_register_gui_component (DIALOG_NEW_JOB_CM_CLASS,
423 gnc_job_window_refresh_handler,
424 gnc_job_window_close_handler,
425 jw);
426 }
427
428 gnc_job_name_changed_cb (NULL, jw);
429 gnc_gui_component_watch_entity_type (jw->component_id,
430 GNC_JOB_MODULE_NAME,
431 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
432
433 gtk_widget_show_all (jw->dialog);
434
435 // The job name should have keyboard focus
436 gtk_widget_grab_focus(jw->name_entry);
437 // Or should the owner field have focus?
438 // if (GNC_IS_GENERAL_SEARCH(jw->cust_edit))
439 // {
440 // gnc_general_search_grab_focus(GNC_GENERAL_SEARCH(jw->cust_edit));
441 // }
442
443 g_object_unref(G_OBJECT(builder));
444
445 return jw;
446 }
447
448 JobWindow *
gnc_ui_job_new(GtkWindow * parent,GncOwner * ownerp,QofBook * bookp)449 gnc_ui_job_new (GtkWindow *parent, GncOwner *ownerp, QofBook *bookp)
450 {
451 JobWindow *jw;
452 GncOwner owner;
453
454 /* Make sure required options exist */
455 if (!bookp) return NULL;
456
457 if (ownerp)
458 {
459 g_return_val_if_fail ((gncOwnerGetType (ownerp) == GNC_OWNER_CUSTOMER) ||
460 (gncOwnerGetType (ownerp) == GNC_OWNER_VENDOR),
461 NULL);
462 gncOwnerCopy (ownerp, &owner);
463 }
464 else
465 gncOwnerInitCustomer (&owner, NULL); /* XXX */
466
467 jw = gnc_job_new_window (parent, bookp, &owner, NULL);
468 return jw;
469 }
470
471 JobWindow *
gnc_ui_job_edit(GtkWindow * parent,GncJob * job)472 gnc_ui_job_edit (GtkWindow *parent, GncJob *job)
473 {
474 JobWindow *jw;
475
476 if (!job) return NULL;
477
478 jw = gnc_job_new_window (parent, gncJobGetBook(job), gncJobGetOwner(job), job);
479 return jw;
480 }
481
482 /* Search functionality */
483
484 static void
edit_job_cb(GtkWindow * dialog,gpointer * job_p,gpointer user_data)485 edit_job_cb (GtkWindow *dialog, gpointer *job_p, gpointer user_data)
486 {
487 GncJob *job;
488
489 g_return_if_fail (job_p && user_data);
490
491 job = *job_p;
492
493 if (!job)
494 return;
495
496 gnc_ui_job_edit (dialog, job);
497 }
498
499 static void
invoice_job_cb(GtkWindow * dialog,gpointer * job_p,gpointer user_data)500 invoice_job_cb (GtkWindow *dialog, gpointer *job_p, gpointer user_data)
501 {
502 struct _job_select_window * sw = user_data;
503 GncJob *job;
504 GncOwner owner;
505
506 g_return_if_fail (job_p && user_data);
507
508 job = *job_p;
509 if (!job)
510 return;
511
512 gncOwnerInitJob (&owner, job);
513 gnc_invoice_search (dialog, NULL, &owner, sw->book);
514 }
515
516 static void
payment_job_cb(GtkWindow * dialog,gpointer * job_p,gpointer user_data)517 payment_job_cb (GtkWindow *dialog, gpointer *job_p, gpointer user_data)
518 {
519 struct _job_select_window *sw = user_data;
520 GncOwner owner;
521 GncJob *job;
522
523 g_return_if_fail (job_p && user_data);
524
525 job = *job_p;
526
527 if (!job)
528 return;
529
530 gncOwnerInitJob (&owner, job);
531 gnc_ui_payment_new (dialog, &owner, sw->book);
532 return;
533 }
534
535 static gpointer
new_job_cb(GtkWindow * dialog,gpointer user_data)536 new_job_cb (GtkWindow *dialog, gpointer user_data)
537 {
538 struct _job_select_window *sw = user_data;
539 JobWindow *jw;
540
541 g_return_val_if_fail (user_data, NULL);
542
543 jw = gnc_ui_job_new (dialog, sw->owner, sw->book);
544 return jw_get_job (jw);
545 }
546
547 static void
free_userdata_cb(gpointer user_data)548 free_userdata_cb (gpointer user_data)
549 {
550 struct _job_select_window *sw = user_data;
551
552 g_return_if_fail (sw);
553
554 qof_query_destroy (sw->q);
555 g_free (sw);
556 }
557
558 GNCSearchWindow *
gnc_job_search(GtkWindow * parent,GncJob * start,GncOwner * owner,QofBook * book)559 gnc_job_search (GtkWindow *parent, GncJob *start, GncOwner *owner, QofBook *book)
560 {
561 QofQuery *q, *q2 = NULL;
562 QofIdType type = GNC_JOB_MODULE_NAME;
563 struct _job_select_window *sw;
564 static GList *params = NULL;
565 static GList *columns = NULL;
566 static GNCSearchCallbackButton buttons[] =
567 {
568 { N_("View/Edit Job"), edit_job_cb, NULL, TRUE},
569 { N_("View Invoices"), invoice_job_cb, NULL, TRUE},
570 { N_("Process Payment"), payment_job_cb, NULL, FALSE},
571 { NULL },
572 };
573
574 g_return_val_if_fail (book, NULL);
575
576 /* Build parameter list in reverse order */
577 if (params == NULL)
578 {
579 params = gnc_search_param_prepend (params, _("Owner's Name"), NULL, type,
580 JOB_OWNER, OWNER_NAME, NULL);
581 params = gnc_search_param_prepend (params, _("Only Active?"), NULL, type,
582 JOB_ACTIVE, NULL);
583 params = gnc_search_param_prepend (params, _("Billing ID"), NULL, type,
584 JOB_REFERENCE, NULL);
585 params = gnc_search_param_prepend (params, _("Rate"), NULL, type,
586 JOB_RATE, NULL);
587 params = gnc_search_param_prepend (params, _("Job Number"), NULL, type,
588 JOB_ID, NULL);
589 params = gnc_search_param_prepend (params, _("Job Name"), NULL, type,
590 JOB_NAME, NULL);
591 }
592
593 /* Build the column list in reverse order */
594 if (columns == NULL)
595 {
596 columns = gnc_search_param_prepend (columns, _("Billing ID"), NULL, type,
597 JOB_REFERENCE, NULL);
598 columns = gnc_search_param_prepend (columns, _("Rate"), NULL, type,
599 JOB_RATE, NULL);
600 columns = gnc_search_param_prepend (columns, _("Company"), NULL, type,
601 JOB_OWNER, OWNER_NAME, NULL);
602 columns = gnc_search_param_prepend (columns, _("Job Name"), NULL, type,
603 JOB_NAME, NULL);
604 columns = gnc_search_param_prepend (columns, _("ID #"), NULL, type,
605 JOB_ID, NULL);
606 }
607
608 /* Build the queries */
609 q = qof_query_create_for (type);
610 qof_query_set_book (q, book);
611
612 /* If we have a start job but, for some reason, not an owner -- grab
613 * the owner from the starting job.
614 */
615 if ((!owner || !gncOwnerGetGUID (owner)) && start)
616 owner = gncJobGetOwner (start);
617
618 /* If owner is supplied, limit all searches to invoices who's owner
619 * is the supplied owner! Show all invoices by this owner.
620 */
621 if (owner && gncOwnerGetGUID (owner))
622 {
623 qof_query_add_guid_match (q, g_slist_prepend
624 (g_slist_prepend (NULL, QOF_PARAM_GUID),
625 JOB_OWNER),
626 gncOwnerGetGUID (owner), QOF_QUERY_AND);
627
628 q2 = qof_query_copy (q);
629 }
630
631 #if 0
632 if (start)
633 {
634 if (q2 == NULL)
635 q2 = qof_query_copy (q);
636
637 qof_query_add_guid_match (q2, g_slist_prepend (NULL, QOF_PARAM_GUID),
638 gncJobGetGUID (start), QOF_QUERY_AND);
639 }
640 #endif
641
642 /* launch select dialog and return the result */
643 sw = g_new0 (struct _job_select_window, 1);
644
645 if (owner)
646 {
647 gncOwnerCopy (owner, &(sw->owner_def));
648 sw->owner = &(sw->owner_def);
649 }
650 sw->book = book;
651 sw->q = q;
652
653 return gnc_search_dialog_create (parent, type, _("Find Job"),
654 params, columns, q, q2, buttons, NULL,
655 new_job_cb, sw, free_userdata_cb,
656 GNC_PREFS_GROUP_SEARCH, NULL,
657 "gnc-class-jobs");
658 }
659
660 /* Functions for widgets for job selection */
661
662 GNCSearchWindow *
gnc_job_search_select(GtkWindow * parent,gpointer start,gpointer book)663 gnc_job_search_select (GtkWindow *parent, gpointer start, gpointer book)
664 {
665 GncJob *j = start;
666 GncOwner owner, *ownerp;
667
668 if (!book) return NULL;
669
670 if (j)
671 {
672 ownerp = gncJobGetOwner (j);
673 gncOwnerCopy (ownerp, &owner);
674 }
675 else
676 gncOwnerInitCustomer (&owner, NULL); /* XXX */
677
678 return gnc_job_search (parent, start, &owner, book);
679 }
680
681 GNCSearchWindow *
gnc_job_search_edit(GtkWindow * parent,gpointer start,gpointer book)682 gnc_job_search_edit (GtkWindow *parent, gpointer start, gpointer book)
683 {
684 if (start)
685 gnc_ui_job_edit (parent, start);
686
687 return NULL;
688 }
689