static void gnc_entry_ledger_move_cursor (VirtualLocation *p_new_virt_loc, gpointer user_data) { GncEntryLedger *ledger = user_data; VirtualLocation new_virt_loc = *p_new_virt_loc; GncEntry *new_entry; GncEntry *old_entry; gboolean saved; if (!ledger) return; old_entry = gnc_entry_ledger_get_current_entry (ledger); new_entry = gnc_entry_ledger_get_entry (ledger, new_virt_loc.vcell_loc); gnc_suspend_gui_refresh (); saved = gnc_entry_ledger_save (ledger, old_entry != new_entry); gnc_resume_gui_refresh (); /* redrawing can muck everything up */ if (saved) { VirtualCellLocation vcell_loc; /* redraw */ gnc_entry_ledger_display_refresh (ledger); if (ledger->traverse_to_new) new_entry = gnc_entry_ledger_get_blank_entry (ledger); /* if the entry we were going to is still in the register, * then it may have moved. Find out where it is now. */ if (gnc_entry_ledger_find_entry (ledger, new_entry, &vcell_loc)) { VirtualCell *vcell; vcell = gnc_table_get_virtual_cell (ledger->table, vcell_loc); new_virt_loc.vcell_loc = vcell_loc; } else new_virt_loc.vcell_loc = ledger->table->current_cursor_loc.vcell_loc; } gnc_table_find_close_valid_cell (ledger->table, &new_virt_loc, FALSE); *p_new_virt_loc = new_virt_loc; }
/* XXX This code is a cut-n-paste job from the SplitRegister code; * the split-register should be generalized to the point where a cut-n-paste * like this isn't required, and this should be trashed. */ void gnc_entry_ledger_load (GncEntryLedger *ledger, GList *entry_list) { GncEntry *blank_entry, *find_entry; CursorBuffer *cursor_buffer; Table *table; GList *node; CellBlock *cursor_header, *cursor; VirtualCellLocation vcell_loc; VirtualLocation save_loc; gboolean start_primary_color = TRUE; int new_entry_row = -1; if (!ledger) return; /* Load up cells */ load_discount_type_cells (ledger); load_discount_how_cells (ledger); gnc_entry_ledger_load_xfer_cells (ledger); blank_entry = gnc_entry_ledger_get_blank_entry (ledger); if (blank_entry == NULL && ledger->invoice == NULL && entry_list == NULL) return; if (blank_entry == NULL && ledger->invoice) { switch (ledger->type) { case GNCENTRY_ORDER_ENTRY: case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_BILL_ENTRY: case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: gnc_suspend_gui_refresh (); blank_entry = gncEntryCreate (ledger->book); gncEntrySetDateGDate (blank_entry, &ledger->last_date_entered); ledger->blank_entry_guid = *gncEntryGetGUID (blank_entry); gnc_resume_gui_refresh (); /* The rest of this does not apply to expense vouchers */ if (ledger->type != GNCENTRY_EXPVOUCHER_ENTRY) { const GncOwner *owner = gncOwnerGetEndOwner (gncInvoiceGetOwner (ledger->invoice)); GncTaxTable *table = NULL; GncTaxIncluded taxincluded_p = GNC_TAXINCLUDED_USEGLOBAL; gboolean taxincluded = FALSE; gnc_numeric discount = gnc_numeric_zero (); gnc_numeric price = gnc_numeric_zero (); /* Determine the Price from Customer's or Vendor's Job */ switch (gncOwnerGetType (gncInvoiceGetOwner (ledger->invoice))) { case GNC_OWNER_JOB: price = gncJobGetRate( gncOwnerGetJob (gncInvoiceGetOwner (ledger->invoice))); break; default: break; } /* Determine the TaxIncluded and Discount values */ switch (gncOwnerGetType (owner)) { case GNC_OWNER_CUSTOMER: taxincluded_p = gncCustomerGetTaxIncluded (owner->owner.customer); discount = gncCustomerGetDiscount (owner->owner.customer); break; case GNC_OWNER_VENDOR: taxincluded_p = gncVendorGetTaxIncluded (owner->owner.vendor); break; default: break; } /* Compute the default taxincluded */ switch (taxincluded_p) { case GNC_TAXINCLUDED_YES: taxincluded = TRUE; break; case GNC_TAXINCLUDED_NO: taxincluded = FALSE; break; case GNC_TAXINCLUDED_USEGLOBAL: if (ledger->prefs_group) { taxincluded = gnc_prefs_get_bool (ledger->prefs_group, GNC_PREF_TAX_INCL); } else { taxincluded = FALSE; } break; } /* Compute the proper taxtable */ switch (gncOwnerGetType (owner)) { case GNC_OWNER_CUSTOMER: table = gnc_business_get_default_tax_table (ledger->book, GNC_OWNER_CUSTOMER); if (gncCustomerGetTaxTableOverride (owner->owner.customer)) table = gncCustomerGetTaxTable (owner->owner.customer); break; case GNC_OWNER_VENDOR: table = gnc_business_get_default_tax_table (ledger->book, GNC_OWNER_VENDOR); if (gncVendorGetTaxTableOverride (owner->owner.vendor)) table = gncVendorGetTaxTable (owner->owner.vendor); break; default: break; } if (ledger->is_cust_doc) { gncEntrySetInvTaxTable (blank_entry, table); gncEntrySetInvTaxIncluded (blank_entry, taxincluded); gncEntrySetInvDiscount (blank_entry, discount); gncEntrySetInvPrice (blank_entry, price); } else { gncEntrySetBillTaxTable (blank_entry, table); gncEntrySetBillTaxIncluded (blank_entry, taxincluded); gncEntrySetBillPrice (blank_entry, price); } } break; default: ledger->blank_entry_guid = *guid_null (); break; } ledger->blank_entry_edited = FALSE; } table = ledger->table; gnc_table_leave_update (table, table->current_cursor_loc); save_loc = table->current_cursor_loc; /* Figure out where we are going to */ if (ledger->traverse_to_new) { find_entry = blank_entry; } else if (ledger->hint_entry) { find_entry = ledger->hint_entry; } else { find_entry = gnc_entry_ledger_get_current_entry(ledger); /* XXX: get current entry (cursor_hint_xxx) */ } /* If the current cursor has changed we save the values for later * possible restoration. */ if (gnc_table_current_cursor_changed (table, TRUE) && (find_entry == gnc_entry_ledger_get_current_entry (ledger))) { cursor_buffer = gnc_cursor_buffer_new (); gnc_table_save_current_cursor (table, cursor_buffer); } else cursor_buffer = NULL; /* disable move callback -- we don't want the cascade of * callbacks while we are fiddling with loading the register */ gnc_table_control_allow_move (table->control, FALSE); /* invalidate the cursor */ { VirtualLocation virt_loc; virt_loc.vcell_loc.virt_row = -1; virt_loc.vcell_loc.virt_col = -1; virt_loc.phys_row_offset = -1; virt_loc.phys_col_offset = -1; gnc_table_move_cursor_gui (table, virt_loc); } /* make sure that the header is loaded */ vcell_loc.virt_row = 0; vcell_loc.virt_col = 0; cursor_header = gnc_table_layout_get_cursor (table->layout, CURSOR_HEADER); gnc_table_set_vcell (table, cursor_header, NULL, TRUE, TRUE, vcell_loc); vcell_loc.virt_row++; /* get the current time and reset the dividing row */ table->model->dividing_row_upper = -1; table->model->dividing_row = -1; table->model->dividing_row_lower = -1; cursor = gnc_table_layout_get_cursor (table->layout, "cursor"); /* Populate the table */ for (node = entry_list; node; node = node->next) { GncEntry *entry = node->data; /* Don't load the blank entry */ if (entry == blank_entry) continue; /* If this is the first load of the ledger, fill the quickfill cells */ { /* XXX */ } if (entry == find_entry) new_entry_row = vcell_loc.virt_row; gnc_table_set_vcell (table, cursor, gncEntryGetGUID (entry), TRUE, start_primary_color, vcell_loc); vcell_loc.virt_row++; /* Flip color for the next guy */ start_primary_color = !start_primary_color; } /* Add the blank entry at the end. */ if (blank_entry) { gnc_table_set_vcell (table, cursor, gncEntryGetGUID (blank_entry), TRUE, start_primary_color, vcell_loc); if (find_entry == blank_entry) new_entry_row = vcell_loc.virt_row; vcell_loc.virt_row++; } /* Resize the table */ gnc_table_set_size (table, vcell_loc.virt_row, 1); /* Restore the cursor to its rightful position */ if (new_entry_row > 0) save_loc.vcell_loc.virt_row = new_entry_row; if (gnc_table_find_close_valid_cell (table, &save_loc, FALSE)) { gnc_table_move_cursor_gui (table, save_loc); if (find_entry == gnc_entry_ledger_get_current_entry (ledger)) gnc_table_restore_current_cursor (table, cursor_buffer); } gnc_cursor_buffer_destroy (cursor_buffer); cursor_buffer = NULL; /* Reset the ledger */ ledger->traverse_to_new = FALSE; ledger->hint_entry = NULL; /* Set the cell fractions */ gnc_table_refresh_gui (table, TRUE); gnc_entry_ledger_show_entry (ledger, table->current_cursor_loc.vcell_loc); /* Set completion character */ gnc_combo_cell_set_complete_char ((ComboCell *) gnc_table_layout_get_cell (table->layout, ENTRY_IACCT_CELL), gnc_get_account_separator ()); gnc_combo_cell_set_complete_char ((ComboCell *) gnc_table_layout_get_cell (table->layout, ENTRY_BACCT_CELL), gnc_get_account_separator ()); /* enable callback for cursor user-driven moves */ gnc_table_control_allow_move (table->control, TRUE); }
static gboolean gnc_entry_ledger_traverse (VirtualLocation *p_new_virt_loc, gncTableTraversalDir dir, gpointer user_data) { GncEntryLedger *ledger = user_data; GncEntry *entry, *new_entry; gint response; VirtualLocation virt_loc; int changed; char const *cell_name; gboolean exact_traversal; if (!ledger) return FALSE; exact_traversal = (dir == GNC_TABLE_TRAVERSE_POINTER); entry = gnc_entry_ledger_get_current_entry (ledger); if (!entry) return FALSE; /* no changes, make sure we aren't going off the end */ changed = gnc_table_current_cursor_changed (ledger->table, FALSE); if (!changed) return FALSE; virt_loc = *p_new_virt_loc; cell_name = gnc_table_get_current_cell_name (ledger->table); /* See if we are leaving the account field */ do { ComboCell *cell; char *name; char *cell_name = NULL; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_INVOICE_VIEWER: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_VIEWER: cell_name = ENTRY_IACCT_CELL; break; case GNCENTRY_BILL_ENTRY: case GNCENTRY_BILL_VIEWER: case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_EXPVOUCHER_VIEWER: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_VIEWER: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER: cell_name = ENTRY_BACCT_CELL; break; default: g_warning ("Unhandled ledger type"); break; } if (!cell_name) break; if (!gnc_cell_name_equal (cell_name, cell_name)) break; if (!gnc_table_layout_get_cell_changed (ledger->table->layout, cell_name, FALSE)) break; cell = (ComboCell *) gnc_table_layout_get_cell (ledger->table->layout, cell_name); if (!cell) break; name = cell->cell.value; if (!name || *name == '\0') break; /* Create the account if necessary. Also checks for a placeholder */ if (!gnc_entry_ledger_get_account_by_name (ledger, (BasicCell *) cell, cell->cell.value, &ledger->full_refresh)) return TRUE; } while (FALSE); /* See if we are leaving the TaxTable field */ do { ComboCell *cell; GncTaxTable *table; char *name; if (!gnc_cell_name_equal (cell_name, ENTRY_TAXTABLE_CELL)) break; if (!gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXTABLE_CELL, FALSE)) break; cell = (ComboCell *) gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXTABLE_CELL); if (!cell) break; name = cell->cell.value; if (!name || *name == '\0') break; table = gncTaxTableLookupByName (ledger->book, cell->cell.value); if (table) break; { const char *format = _("The tax table %s does not exist. " "Would you like to create it?"); if (!gnc_verify_dialog (ledger->parent, TRUE, format, name)) break; } ledger->full_refresh = FALSE; table = gnc_ui_tax_table_new_from_name (ledger->book, name); if (!table) break; ledger->full_refresh = TRUE; name = (char *)gncTaxTableGetName (table); gnc_combo_cell_set_value (cell, name); gnc_basic_cell_set_changed (&cell->cell, TRUE); } while (FALSE); /* See if we are tabbing off the end of the very last line * (i.e. the blank entry) */ do { VirtualLocation virt_loc; if (!changed && !ledger->blank_entry_edited) break; if (dir != GNC_TABLE_TRAVERSE_RIGHT) break; virt_loc = ledger->table->current_cursor_loc; if (gnc_table_move_vertical_position (ledger->table, &virt_loc, 1)) break; virt_loc = ledger->table->current_cursor_loc; if (gnc_table_move_tab (ledger->table, &virt_loc, TRUE)) break; *p_new_virt_loc = ledger->table->current_cursor_loc; /* Yep, we're trying to leave the blank entry -- make sure * we are allowed to do so by verifying the current cursor. * If the current cursor is ok, then move on! */ /* Verify that the cursor is ok. If we can't save the cell, don't move! */ if (!gnc_entry_ledger_verify_can_save (ledger)) { return TRUE; } (p_new_virt_loc->vcell_loc.virt_row)++; p_new_virt_loc->phys_row_offset = 0; p_new_virt_loc->phys_col_offset = 0; ledger->traverse_to_new = TRUE; /* If we're here, we're tabbing off the end of the 'blank entry' */ return FALSE; } while (FALSE); /* Now see if we are changing cursors. If not, we may be able to * auto-complete. */ if (!gnc_table_virtual_cell_out_of_bounds (ledger->table, virt_loc.vcell_loc)) { if (gnc_entry_ledger_auto_completion (ledger, dir, p_new_virt_loc)) return FALSE; } /* Check for going off the end */ gnc_table_find_close_valid_cell (ledger->table, &virt_loc, exact_traversal); /* Same entry, no problem -- we're just moving backwards in the cursor */ new_entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc); if (entry == new_entry) { *p_new_virt_loc = virt_loc; return FALSE; } /* If we are here, then we are trying to leave the cursor. Make sure * the cursor we are leaving is valid. If so, ask the user if the * changes should be recorded. If not, don't go anywhere. */ /* Verify this cursor -- if it's not valid, don't let them move on */ if (!gnc_entry_ledger_verify_can_save (ledger)) { *p_new_virt_loc = ledger->table->current_cursor_loc; return TRUE; } /* * XXX GNCENTRY_INVOICE_EDIT processing to be added: * 1) check if the qty field changed. * 2) if so, check if this entry is part of an order. * 3) if so, ask if they want to change the entry or * split the entry into two parts. */ /* Ok, we are changing lines and the current entry has * changed. We only ask them what they want to do in * limited cases -- usually just let the change go through. */ { GtkWidget *dialog; const char *title = _("Save the current entry?"); const char *message = _("The current entry has been changed. However, this entry is " "part of an existing order. Would you like to record the change " "and effectively change your order?"); switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: if (gncEntryGetOrder (entry) != NULL) { dialog = gtk_message_dialog_new(GTK_WINDOW(ledger->parent), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", title); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", message); gtk_dialog_add_buttons(GTK_DIALOG(dialog), _("_Don't Record"), GTK_RESPONSE_REJECT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Record"), GTK_RESPONSE_ACCEPT, NULL); response = gnc_dialog_run(GTK_DIALOG(dialog), "invoice_entry_changed"); gtk_widget_destroy(dialog); break; } /* FALL THROUGH */ default: response = GTK_RESPONSE_ACCEPT; break; } } switch (response) { case GTK_RESPONSE_ACCEPT: break; case GTK_RESPONSE_REJECT: { VirtualCellLocation vcell_loc; GncEntry *new_entry; new_entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc); gnc_entry_ledger_cancel_cursor_changes (ledger); if (gnc_entry_ledger_find_entry (ledger, new_entry, &vcell_loc)) virt_loc.vcell_loc = vcell_loc; gnc_table_find_close_valid_cell (ledger->table, &virt_loc, exact_traversal); *p_new_virt_loc = virt_loc; } break; case GTK_RESPONSE_CANCEL: default: return TRUE; } return FALSE; }
static gboolean gnc_entry_ledger_save (GncEntryLedger *ledger, gboolean do_commit) { GncEntry *blank_entry; GncEntry *entry; if (!ledger) return FALSE; blank_entry = gnc_entry_ledger_get_blank_entry (ledger); entry = gnc_entry_ledger_get_current_entry (ledger); if (entry == NULL) return FALSE; /* Try to avoid heavy-weight updates if nothing has changed */ if (!gnc_table_current_cursor_changed (ledger->table, FALSE)) { if (!do_commit) return FALSE; if (entry == blank_entry) { if (ledger->blank_entry_edited) { ledger->last_date_entered = gncEntryGetDateGDate (entry); ledger->blank_entry_guid = *guid_null (); ledger->blank_entry_edited = FALSE; blank_entry = NULL; } else return FALSE; } return TRUE; } gnc_suspend_gui_refresh (); if (!gncEntryIsOpen (entry)) gncEntryBeginEdit (entry); gnc_table_save_cells (ledger->table, entry); if (entry == blank_entry) { Timespec ts; ts.tv_sec = time(NULL); ts.tv_nsec = 0; gncEntrySetDateEntered (blank_entry, ts); switch (ledger->type) { case GNCENTRY_ORDER_ENTRY: gncOrderAddEntry (ledger->order, blank_entry); break; case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: /* Anything entered on an invoice entry must be part of the invoice! */ gncInvoiceAddEntry (ledger->invoice, blank_entry); break; case GNCENTRY_BILL_ENTRY: case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: /* Anything entered on an invoice entry must be part of the invoice! */ gncBillAddEntry (ledger->invoice, blank_entry); break; default: /* Nothing to do for viewers */ g_warning ("blank entry traversed in a viewer"); break; } } if (entry == blank_entry) { if (do_commit) { ledger->blank_entry_guid = *guid_null (); blank_entry = NULL; ledger->last_date_entered = gncEntryGetDateGDate (entry); } else ledger->blank_entry_edited = TRUE; } if (do_commit) gncEntryCommitEdit (entry); gnc_table_clear_current_cursor_changes (ledger->table); gnc_resume_gui_refresh (); return TRUE; }
static gboolean gnc_entry_ledger_auto_completion (GncEntryLedger *ledger, gncTableTraversalDir dir, VirtualLocation *p_new_virt_loc) { GncEntry *entry; GncEntry *blank_entry; GncEntry *auto_entry; const char* cell_name; const char *desc; BasicCell *cell = NULL; char *account_name = NULL; char *new_value = NULL; g_assert(ledger); g_assert(ledger->table); blank_entry = gnc_entry_ledger_get_blank_entry (ledger); /* auto-completion is only triggered by a tab out */ if (dir != GNC_TABLE_TRAVERSE_RIGHT) return FALSE; entry = gnc_entry_ledger_get_current_entry (ledger); if (entry == NULL) return FALSE; cell_name = gnc_table_get_current_cell_name (ledger->table); /* Auto-completion is done only in an entry ledger */ switch (ledger->type) { case GNCENTRY_ORDER_ENTRY: case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_BILL_ENTRY: case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: break; default: return FALSE; } /* Further conditions before we actually do auto-completion: */ /* There must be a blank entry */ if (blank_entry == NULL) return FALSE; /* we must be on the blank entry */ if (entry != blank_entry) return FALSE; /* and leaving the description cell */ if (!gnc_cell_name_equal (cell_name, ENTRY_DESC_CELL)) return FALSE; /* nothing but the date and description should be changed */ /* FIXME, this should be refactored. */ if (gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_ACTN_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_QTY_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_PRIC_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISC_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISTYPE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DISHOW_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_IACCT_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_BACCT_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXABLE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXINCLUDED_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXTABLE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_VALUE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_TAXVAL_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_BILLABLE_CELL, TRUE) || gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_PAYMENT_CELL, TRUE)) return FALSE; /* and the description should indeed be changed */ if (!gnc_table_layout_get_cell_changed (ledger->table->layout, ENTRY_DESC_CELL, TRUE)) return FALSE; /* to a non-empty value */ desc = gnc_table_layout_get_cell_value (ledger->table->layout, ENTRY_DESC_CELL); if ((desc == NULL) || (*desc == '\0')) return FALSE; /* Ok, we are sure we want to trigger auto-completion. Now find an * entry to copy the values from. FIXME: Currently we only use * the entries from the current invoice/bill, but it would be * better to draw this from a larger set of entries. */ auto_entry = /* Use this for book-wide auto-completion of the invoice entries */ find_entry_in_book_by_desc(ledger, desc); /* #else */ /* gnc_find_entry_in_reg_by_desc(ledger, desc); */ /* #endif */ if (auto_entry == NULL) return FALSE; /* now perform the completion */ gnc_suspend_gui_refresh (); /* Auto-complete the action field */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_ACTN_CELL); set_value_combo_cell (cell, gncEntryGetAction (auto_entry)); /* Auto-complete the account field */ switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_IACCT_CELL); account_name = gnc_get_account_name_for_register (gncEntryGetInvAccount(auto_entry)); break; case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_BILL_ENTRY: case GNCENTRY_VEND_CREDIT_NOTE_ENTRY: case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY: cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_BACCT_CELL); account_name = gnc_get_account_name_for_register (gncEntryGetBillAccount(auto_entry)); break; case GNCENTRY_ORDER_ENTRY: default: cell = NULL; account_name = NULL; break; } set_value_combo_cell (cell, account_name); g_free (account_name); /* Auto-complete quantity cell * Note: we always autofill a positive quantity value. This allows us to * - reuse invoice entries on credit note ledgers, meaning you can credit * some invoice entry via autofill without having to manually fix the sign * on the credit note. * - autofill credit note entries on other credit note entries (without having * to juggle sign reversals internally) * - autofill credit note entries on invoice ledgers * * Disadvantage: invoice entries with explicitly set negative quantities will * be autofilled to positive quantities in later uses. But it seems less common * to me to require a negative entry again next time. */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_QTY_CELL); set_value_price_cell (cell, gnc_numeric_abs(gncEntryGetQuantity (auto_entry))); /* Auto-complete price cell */ { gnc_numeric price; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: price = gncEntryGetInvPrice (auto_entry); break; default: price = gncEntryGetBillPrice (auto_entry); } /* Auto-complete price cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_PRIC_CELL); set_value_price_cell (cell, price); } /* We intentionally skip the discount column */ /* Taxable?, Tax-include?, Tax table */ { gboolean taxable, taxincluded; GncTaxTable *taxtable; switch (ledger->type) { case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_CUST_CREDIT_NOTE_ENTRY: taxable = gncEntryGetInvTaxable (auto_entry); taxincluded = gncEntryGetInvTaxIncluded (auto_entry); taxtable = gncEntryGetInvTaxTable (auto_entry); break; default: taxable = gncEntryGetBillTaxable (auto_entry); taxincluded = gncEntryGetBillTaxIncluded (auto_entry); taxtable = gncEntryGetBillTaxTable (auto_entry); } /* Taxable? cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXABLE_CELL); gnc_checkbox_cell_set_flag ((CheckboxCell *) cell, taxable); gnc_basic_cell_set_changed (cell, TRUE); /* taxincluded? cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXINCLUDED_CELL); gnc_checkbox_cell_set_flag ((CheckboxCell *) cell, taxincluded); gnc_basic_cell_set_changed (cell, TRUE); /* Taxable? cell */ cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_TAXTABLE_CELL); set_value_combo_cell(cell, gncTaxTableGetName (taxtable)); } gnc_resume_gui_refresh (); /* now move to the non-empty amount column unless config setting says not */ if ( !gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "tab_includes_transfer_on_memorised", NULL) ) { VirtualLocation new_virt_loc; const char *cell_name = ENTRY_QTY_CELL; if (gnc_table_get_current_cell_location (ledger->table, cell_name, &new_virt_loc)) *p_new_virt_loc = new_virt_loc; } return TRUE; }