29 #include <glib/gi18n.h>
34 #include "dialog-utils.h"
35 #include "gnc-component-manager.h"
39 #include "gnc-gui-query.h"
40 #include "gnome-utils/gnc-warnings.h"
42 #include "pricecell.h"
43 #include "dialog-tax-table.h"
44 #include "register/register-core/checkboxcell.h"
46 #include "gncEntryLedgerP.h"
47 #include "gncEntryLedgerControl.h"
56 if (!ledger)
return FALSE;
58 blank_entry = gnc_entry_ledger_get_blank_entry (ledger);
60 entry = gnc_entry_ledger_get_current_entry (ledger);
61 if (entry == NULL)
return FALSE;
64 if (!gnc_table_current_cursor_changed (ledger->table, FALSE))
66 if (!do_commit)
return FALSE;
68 if (entry == blank_entry)
70 if (ledger->blank_entry_edited)
74 ledger->blank_entry_edited = FALSE;
84 gnc_suspend_gui_refresh ();
86 if (!gncEntryIsOpen (entry))
87 gncEntryBeginEdit (entry);
89 gnc_table_save_cells (ledger->table, entry);
91 if (entry == blank_entry)
96 gncEntrySetDateEntered (blank_entry, ts);
100 case GNCENTRY_ORDER_ENTRY:
101 gncOrderAddEntry (ledger->order, blank_entry);
103 case GNCENTRY_INVOICE_ENTRY:
104 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
106 gncInvoiceAddEntry (ledger->invoice, blank_entry);
108 case GNCENTRY_BILL_ENTRY:
109 case GNCENTRY_EXPVOUCHER_ENTRY:
110 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
111 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
117 g_warning (
"blank entry traversed in a viewer");
122 if (entry == blank_entry)
126 ledger->blank_entry_guid = *
guid_null ();
131 ledger->blank_entry_edited = TRUE;
135 gncEntryCommitEdit (entry);
137 gnc_table_clear_current_cursor_changes (ledger->table);
139 gnc_resume_gui_refresh ();
146 const char *cell_name,
147 const char *cell_msg)
152 cell = (
ComboCell *) gnc_table_layout_get_cell (ledger->table->layout,
154 g_return_val_if_fail (cell, TRUE);
155 name = cell->cell.value;
156 if (!name || *name ==
'\0')
158 const char *format = (
"%s %s");
159 const char *gen_msg = _(
"Invalid Entry: You need to supply an account in the right currency for this position.");
161 gnc_error_dialog (ledger->parent, format, gen_msg, cell_msg);
176 gnc_entry_ledger_compute_value (ledger, &value, NULL);
181 switch (ledger->type)
183 case GNCENTRY_INVOICE_ENTRY:
184 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
185 if (!gnc_entry_ledger_verify_acc_cell_ok (ledger, ENTRY_IACCT_CELL,
186 _(
"This account should usually be of type income.")))
189 case GNCENTRY_BILL_ENTRY:
190 case GNCENTRY_EXPVOUCHER_ENTRY:
191 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
192 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
193 if (!gnc_entry_ledger_verify_acc_cell_ok (ledger, ENTRY_BACCT_CELL,
194 _(
"This account should usually be of type expense or asset.")))
198 g_warning (
"Unhandled ledger type");
206 static void gnc_entry_ledger_move_cursor (
VirtualLocation *p_new_virt_loc,
217 old_entry = gnc_entry_ledger_get_current_entry (ledger);
218 new_entry = gnc_entry_ledger_get_entry (ledger, new_virt_loc.vcell_loc);
220 gnc_suspend_gui_refresh ();
221 saved = gnc_entry_ledger_save (ledger, old_entry != new_entry);
222 gnc_resume_gui_refresh ();
230 gnc_entry_ledger_display_refresh (ledger);
232 if (ledger->traverse_to_new)
233 new_entry = gnc_entry_ledger_get_blank_entry (ledger);
237 if (gnc_entry_ledger_find_entry (ledger, new_entry, &vcell_loc))
239 gnc_table_get_virtual_cell (ledger->table, vcell_loc);
240 new_virt_loc.vcell_loc = vcell_loc;
243 new_virt_loc.vcell_loc = ledger->table->current_cursor_loc.vcell_loc;
246 gnc_table_find_close_valid_cell (ledger->table, &new_virt_loc, FALSE);
248 *p_new_virt_loc = new_virt_loc;
259 GSList *param_list = NULL;
260 GSList *primary_sort_params = NULL;
261 const char* should_be_null = (use_invoice ? ENTRY_BILL : ENTRY_INVOICE);
267 query = qof_query_create_for (GNC_ID_ENTRY);
273 qof_query_string_predicate (QOF_COMPARE_EQUAL, desc,
274 QOF_STRING_MATCH_CASEINSENSITIVE, FALSE);
277 param_list = qof_query_build_param_list (ENTRY_DESC, NULL);
284 qof_query_build_param_list (should_be_null,
285 QOF_PARAM_GUID, NULL),
286 NULL, QOF_QUERY_AND);
290 primary_sort_params = qof_query_build_param_list(ENTRY_DATE_ENTERED, NULL);
305 gboolean use_invoice;
307 GList *entries = NULL;
311 case GNCENTRY_INVOICE_ENTRY:
312 case GNCENTRY_INVOICE_VIEWER:
313 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
314 case GNCENTRY_CUST_CREDIT_NOTE_VIEWER:
322 query = new_query_for_entry_desc(reg, desc, use_invoice);
342 gnc_find_entry_in_reg_by_desc(
GncEntryLedger *reg,
const char* desc)
344 int virt_row, virt_col;
345 int num_rows, num_cols;
349 g_assert(reg->table);
350 if (!reg || !reg->table)
353 num_rows = reg->table->num_virt_rows;
354 num_cols = reg->table->num_virt_cols;
358 for (virt_row = num_rows - 1; virt_row >= 0; virt_row--)
359 for (virt_col = num_cols - 1; virt_col >= 0; virt_col--)
364 entry = gnc_entry_ledger_get_entry(reg, vcell_loc);
366 if (entry == last_entry)
369 if (g_strcmp0 (desc, gncEntryGetDescription (entry)) == 0)
379 static void set_value_combo_cell(
BasicCell *cell,
const char *new_value)
381 if (!cell || !new_value)
383 if (g_strcmp0 (new_value, gnc_basic_cell_get_value (cell)) == 0)
386 gnc_combo_cell_set_value ((
ComboCell *) cell, new_value);
387 gnc_basic_cell_set_changed (cell, TRUE);
398 gnc_price_cell_set_value (pcell, new_value);
399 gnc_basic_cell_set_changed (cell, TRUE);
404 gncTableTraversalDir dir,
410 const char* cell_name;
413 char *account_name = NULL;
416 g_assert(ledger->table);
417 blank_entry = gnc_entry_ledger_get_blank_entry (ledger);
420 if (dir != GNC_TABLE_TRAVERSE_RIGHT)
423 entry = gnc_entry_ledger_get_current_entry (ledger);
427 cell_name = gnc_table_get_current_cell_name (ledger->table);
430 switch (ledger->type)
432 case GNCENTRY_ORDER_ENTRY:
433 case GNCENTRY_INVOICE_ENTRY:
434 case GNCENTRY_BILL_ENTRY:
435 case GNCENTRY_EXPVOUCHER_ENTRY:
436 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
437 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
438 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
446 if (blank_entry == NULL)
450 if (entry != blank_entry)
454 if (!gnc_cell_name_equal (cell_name, ENTRY_DESC_CELL))
459 if (gnc_table_layout_get_cell_changed (ledger->table->layout,
460 ENTRY_ACTN_CELL, TRUE)
461 || gnc_table_layout_get_cell_changed (ledger->table->layout,
462 ENTRY_QTY_CELL, TRUE)
463 || gnc_table_layout_get_cell_changed (ledger->table->layout,
464 ENTRY_PRIC_CELL, TRUE)
465 || gnc_table_layout_get_cell_changed (ledger->table->layout,
466 ENTRY_DISC_CELL, TRUE)
467 || gnc_table_layout_get_cell_changed (ledger->table->layout,
468 ENTRY_DISTYPE_CELL, TRUE)
469 || gnc_table_layout_get_cell_changed (ledger->table->layout,
470 ENTRY_DISHOW_CELL, TRUE)
471 || gnc_table_layout_get_cell_changed (ledger->table->layout,
472 ENTRY_IACCT_CELL, TRUE)
473 || gnc_table_layout_get_cell_changed (ledger->table->layout,
474 ENTRY_BACCT_CELL, TRUE)
475 || gnc_table_layout_get_cell_changed (ledger->table->layout,
476 ENTRY_TAXABLE_CELL, TRUE)
477 || gnc_table_layout_get_cell_changed (ledger->table->layout,
478 ENTRY_TAXINCLUDED_CELL, TRUE)
479 || gnc_table_layout_get_cell_changed (ledger->table->layout,
480 ENTRY_TAXTABLE_CELL, TRUE)
481 || gnc_table_layout_get_cell_changed (ledger->table->layout,
482 ENTRY_VALUE_CELL, TRUE)
483 || gnc_table_layout_get_cell_changed (ledger->table->layout,
484 ENTRY_TAXVAL_CELL, TRUE)
485 || gnc_table_layout_get_cell_changed (ledger->table->layout,
486 ENTRY_BILLABLE_CELL, TRUE)
487 || gnc_table_layout_get_cell_changed (ledger->table->layout,
488 ENTRY_PAYMENT_CELL, TRUE))
492 if (!gnc_table_layout_get_cell_changed (ledger->table->layout,
493 ENTRY_DESC_CELL, TRUE))
497 desc = gnc_table_layout_get_cell_value (ledger->table->layout, ENTRY_DESC_CELL);
498 if ((desc == NULL) || (*desc ==
'\0'))
507 find_entry_in_book_by_desc(ledger, desc);
512 if (auto_entry == NULL)
516 gnc_suspend_gui_refresh ();
519 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_ACTN_CELL);
520 set_value_combo_cell (cell, gncEntryGetAction (auto_entry));
523 switch (ledger->type)
525 case GNCENTRY_INVOICE_ENTRY:
526 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
527 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_IACCT_CELL);
530 case GNCENTRY_EXPVOUCHER_ENTRY:
531 case GNCENTRY_BILL_ENTRY:
532 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
533 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
534 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_BACCT_CELL);
537 case GNCENTRY_ORDER_ENTRY:
543 set_value_combo_cell (cell, account_name);
544 g_free (account_name);
552 switch (ledger->type)
554 case GNCENTRY_INVOICE_ENTRY:
555 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
556 orig_is_cn = gncInvoiceGetIsCreditNote (gncEntryGetInvoice (auto_entry));
559 orig_is_cn = gncInvoiceGetIsCreditNote (gncEntryGetBill (auto_entry));
562 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_QTY_CELL);
569 switch (ledger->type)
571 case GNCENTRY_INVOICE_ENTRY:
572 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
573 price = gncEntryGetInvPrice (auto_entry);
576 price = gncEntryGetBillPrice (auto_entry);
581 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_PRIC_CELL);
582 set_value_price_cell (cell, price);
589 gboolean taxable, taxincluded;
591 switch (ledger->type)
593 case GNCENTRY_INVOICE_ENTRY:
594 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
595 taxable = gncEntryGetInvTaxable (auto_entry);
596 taxincluded = gncEntryGetInvTaxIncluded (auto_entry);
597 taxtable = gncEntryGetInvTaxTable (auto_entry);
600 taxable = gncEntryGetBillTaxable (auto_entry);
601 taxincluded = gncEntryGetBillTaxIncluded (auto_entry);
602 taxtable = gncEntryGetBillTaxTable (auto_entry);
607 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXABLE_CELL);
608 gnc_checkbox_cell_set_flag ((
CheckboxCell *) cell, taxable);
609 gnc_basic_cell_set_changed (cell, TRUE);
612 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXINCLUDED_CELL);
613 gnc_checkbox_cell_set_flag ((
CheckboxCell *) cell, taxincluded);
614 gnc_basic_cell_set_changed (cell, TRUE);
617 cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXTABLE_CELL);
618 set_value_combo_cell(cell, gncTaxTableGetName (taxtable));
622 gnc_resume_gui_refresh ();
626 GNC_PREF_TAB_TRANS_MEMORISED) )
629 const char *cell_name = ENTRY_QTY_CELL;
631 if (gnc_table_get_current_cell_location (ledger->table, cell_name,
633 *p_new_virt_loc = new_virt_loc;
639 static gboolean gnc_entry_ledger_traverse (
VirtualLocation *p_new_virt_loc,
640 gncTableTraversalDir dir,
648 char const *cell_name;
649 gboolean exact_traversal;
651 if (!ledger)
return FALSE;
653 exact_traversal = (dir == GNC_TABLE_TRAVERSE_POINTER);
655 entry = gnc_entry_ledger_get_current_entry (ledger);
660 changed = gnc_table_current_cursor_changed (ledger->table, FALSE);
664 virt_loc = *p_new_virt_loc;
666 cell_name = gnc_table_get_current_cell_name (ledger->table);
673 char *cell_name = NULL;
675 switch (ledger->type)
677 case GNCENTRY_INVOICE_ENTRY:
678 case GNCENTRY_INVOICE_VIEWER:
679 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
680 case GNCENTRY_CUST_CREDIT_NOTE_VIEWER:
681 cell_name = ENTRY_IACCT_CELL;
683 case GNCENTRY_BILL_ENTRY:
684 case GNCENTRY_BILL_VIEWER:
685 case GNCENTRY_EXPVOUCHER_ENTRY:
686 case GNCENTRY_EXPVOUCHER_VIEWER:
687 case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
688 case GNCENTRY_VEND_CREDIT_NOTE_VIEWER:
689 case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
690 case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER:
691 cell_name = ENTRY_BACCT_CELL;
694 g_warning (
"Unhandled ledger type");
701 if (!gnc_cell_name_equal (cell_name, cell_name))
704 if (!gnc_table_layout_get_cell_changed (ledger->table->layout,
708 cell = (
ComboCell *) gnc_table_layout_get_cell (ledger->table->layout,
713 name = cell->cell.value;
714 if (!name || *name ==
'\0')
718 if (!gnc_entry_ledger_get_account_by_name (ledger, (
BasicCell *) cell,
720 &ledger->full_refresh))
734 if (!gnc_cell_name_equal (cell_name, ENTRY_TAXTABLE_CELL))
737 if (!gnc_table_layout_get_cell_changed (ledger->table->layout,
738 ENTRY_TAXTABLE_CELL, FALSE))
741 cell = (
ComboCell *) gnc_table_layout_get_cell (ledger->table->layout,
742 ENTRY_TAXTABLE_CELL);
746 name = cell->cell.value;
747 if (!name || *name ==
'\0')
750 table = gncTaxTableLookupByName (ledger->book, cell->cell.value);
755 const char *format = _(
"The tax table %s does not exist. "
756 "Would you like to create it?");
757 if (!gnc_verify_dialog (ledger->parent, TRUE, format, name))
761 ledger->full_refresh = FALSE;
763 table = gnc_ui_tax_table_new_from_name (ledger->book, name);
767 ledger->full_refresh = TRUE;
769 name = (
char *)gncTaxTableGetName (table);
770 gnc_combo_cell_set_value (cell, name);
771 gnc_basic_cell_set_changed (&cell->cell, TRUE);
784 if (!changed && !ledger->blank_entry_edited)
787 if (dir != GNC_TABLE_TRAVERSE_RIGHT)
790 virt_loc = ledger->table->current_cursor_loc;
794 virt_loc = ledger->table->current_cursor_loc;
795 if (gnc_table_move_tab (ledger->table, &virt_loc, TRUE))
798 *p_new_virt_loc = ledger->table->current_cursor_loc;
806 if (!gnc_entry_ledger_verify_can_save (ledger))
811 (p_new_virt_loc->vcell_loc.virt_row)++;
812 p_new_virt_loc->phys_row_offset = 0;
813 p_new_virt_loc->phys_col_offset = 0;
815 ledger->traverse_to_new = TRUE;
825 if (!gnc_table_virtual_cell_out_of_bounds (ledger->table,
828 if (gnc_entry_ledger_auto_completion (ledger, dir, p_new_virt_loc))
833 gnc_table_find_close_valid_cell (ledger->table, &virt_loc, exact_traversal);
836 new_entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
837 if (entry == new_entry)
839 *p_new_virt_loc = virt_loc;
850 if (!gnc_entry_ledger_verify_can_save (ledger))
852 *p_new_virt_loc = ledger->table->current_cursor_loc;
870 const char *title = _(
"Save the current entry?");
871 const char *message =
872 _(
"The current entry has been changed. However, this entry is "
873 "part of an existing order. Would you like to record the change "
874 "and effectively change your order?");
876 switch (ledger->type)
878 case GNCENTRY_INVOICE_ENTRY:
879 case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
880 if (gncEntryGetOrder (entry) != NULL)
882 dialog = gtk_message_dialog_new(GTK_WINDOW(ledger->parent),
883 GTK_DIALOG_DESTROY_WITH_PARENT,
884 GTK_MESSAGE_QUESTION,
887 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
889 gtk_dialog_add_buttons(GTK_DIALOG(dialog),
890 _(
"_Don't Record"), GTK_RESPONSE_REJECT,
891 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
892 _(
"_Record"), GTK_RESPONSE_ACCEPT,
894 response = gnc_dialog_run(GTK_DIALOG(dialog), GNC_PREF_WARN_INV_ENTRY_MOD);
895 gtk_widget_destroy(dialog);
901 response = GTK_RESPONSE_ACCEPT;
908 case GTK_RESPONSE_ACCEPT:
911 case GTK_RESPONSE_REJECT:
916 new_entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
918 gnc_entry_ledger_cancel_cursor_changes (ledger);
920 if (gnc_entry_ledger_find_entry (ledger, new_entry, &vcell_loc))
921 virt_loc.vcell_loc = vcell_loc;
923 gnc_table_find_close_valid_cell (ledger->table, &virt_loc,
926 *p_new_virt_loc = virt_loc;
931 case GTK_RESPONSE_CANCEL:
943 control = gnc_table_control_new ();
944 control->move_cursor = gnc_entry_ledger_move_cursor;
945 control->traverse = gnc_entry_ledger_traverse;
951 void gnc_entry_ledger_cancel_cursor_changes (
GncEntryLedger *ledger)
958 virt_loc = ledger->table->current_cursor_loc;
960 if (!gnc_table_current_cursor_changed (ledger->table, FALSE))
964 gnc_table_clear_current_cursor_changes (ledger->table);
966 if (gnc_table_find_close_valid_cell (ledger->table, &virt_loc, FALSE))
967 gnc_table_move_cursor_gui (ledger->table, virt_loc);
969 gnc_table_refresh_gui (ledger->table, TRUE);
973 gnc_entry_ledger_check_close_internal (GtkWidget *parent,
977 const char *message = _(
"The current entry has been changed. "
978 "Would you like to save it?");
981 virt_loc = ledger->table->current_cursor_loc;
983 if (gnc_entry_ledger_traverse (&virt_loc, GNC_TABLE_TRAVERSE_POINTER,
987 if (!gnc_entry_ledger_verify_can_save (ledger))
990 if (dontask || gnc_verify_dialog (parent, TRUE,
"%s", message))
991 gnc_entry_ledger_save (ledger, TRUE);
993 gnc_entry_ledger_cancel_cursor_changes (ledger);
1001 if (!ledger)
return TRUE;
1003 return gnc_entry_ledger_check_close_internal (NULL, ledger, TRUE);
1007 gnc_entry_ledger_check_close (GtkWidget *parent,
GncEntryLedger *ledger)
1009 if (!ledger)
return TRUE;
1011 if (gnc_entry_ledger_changed (ledger))
1013 gboolean dontask = FALSE;
1015 if (ledger->type == GNCENTRY_INVOICE_ENTRY ||
1016 ledger->type == GNCENTRY_CUST_CREDIT_NOTE_ENTRY)
1019 gboolean only_inv_changed = FALSE;
1021 if (gnc_table_current_cursor_changed (ledger->table, FALSE) == 1 &&
1022 gnc_table_layout_get_cell_changed (ledger->table->layout,
1023 ENTRY_INV_CELL, TRUE))
1024 only_inv_changed = TRUE;
1026 inv_value = gnc_entry_ledger_get_checkmark (ledger, ENTRY_INV_CELL);
1028 if (inv_value && only_inv_changed)
1037 return gnc_entry_ledger_check_close_internal (parent, ledger, dontask);
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
void qof_query_add_term(QofQuery *query, QofQueryParamList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
Dialog for create/edit an account.
utility functions for the GnuCash UI
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *primary_sort_params, QofQueryParamList *secondary_sort_params, QofQueryParamList *tertiary_sort_params)
Use a 64-bit unsigned int timespec.
gboolean gnc_numeric_zero_p(gnc_numeric a)
gboolean gnc_table_move_vertical_position(Table *table, VirtualLocation *virt_loc, int phys_row_offset)
void qof_query_set_sort_increasing(QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
struct _QofQuery QofQuery
void qof_query_set_max_results(QofQuery *q, int n)
gchar * gnc_get_account_name_for_register(const Account *account)
Account handling public routines.
void qof_query_destroy(QofQuery *q)
void qof_query_set_book(QofQuery *q, QofBook *book)
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
GDate gncEntryGetDateGDate(const GncEntry *entry)
The ComboCell object implements a cell handler with a "combination-box" pull-down menu in it...
void qof_query_add_guid_match(QofQuery *q, QofQueryParamList *param_list, const GncGUID *guid, QofQueryOp op)
Generic api to store and retrieve preferences.
GList * qof_query_run(QofQuery *query)
const GncGUID * guid_null(void)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Declarations for the Table object.
time64 gnc_time(time64 *tbuf)
get the current local time
#define QOF_QUERY_FIRST_TERM
gnc_numeric gncEntryGetDocQuantity(const GncEntry *entry, gboolean is_cn)