Implement auto-completion in the invoice/bill entry ledger.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@19887 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Christian Stimming 2010-11-27 21:01:15 +00:00
parent 2bf78f0e8e
commit 578e9e2f55

View File

@ -2,6 +2,7 @@
* gncEntryLedgerControl.c -- Control for GncEntry ledger
* Copyright (C) 2001, 2002, 2003 Derek Atkins
* Author: Derek Atkins <warlord@MIT.EDU>
* Copyright (C) 2010 Christian Stimming <christian@cstimming.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -37,6 +38,8 @@
#include "table-allgui.h"
#include "pricecell.h"
#include "dialog-tax-table.h"
#include "core-utils/gnc-gconf-utils.h"
#include "register/register-core/checkboxcell.h"
#include "gncEntryLedgerP.h"
#include "gncEntryLedgerControl.h"
@ -245,6 +248,8 @@ gnc_find_entry_in_reg_by_desc(GncEntryLedger *reg, const char* desc)
int num_rows, num_cols;
GncEntry *last_entry;
g_assert(reg);
g_assert(reg->table);
if (!reg || !reg->table)
return NULL;
@ -273,6 +278,29 @@ gnc_find_entry_in_reg_by_desc(GncEntryLedger *reg, const char* desc)
return NULL;
}
static void set_value_combo_cell(BasicCell *cell, const char *new_value)
{
if (!cell || !new_value)
return;
if (safe_strcmp (new_value, gnc_basic_cell_get_value (cell)) == 0)
return;
gnc_combo_cell_set_value ((ComboCell *) cell, new_value);
gnc_basic_cell_set_changed (cell, TRUE);
}
static void set_value_price_cell(BasicCell *cell, gnc_numeric new_value)
{
PriceCell *pcell = (PriceCell*) cell;
if (!cell)
return;
if (gnc_numeric_equal (new_value, gnc_price_cell_get_value(pcell)))
return;
gnc_price_cell_set_value (pcell, new_value);
gnc_basic_cell_set_changed (cell, TRUE);
}
static gboolean
gnc_entry_ledger_auto_completion (GncEntryLedger *ledger,
gncTableTraversalDir dir,
@ -283,7 +311,12 @@ gnc_entry_ledger_auto_completion (GncEntryLedger *ledger,
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 */
@ -296,69 +329,180 @@ gnc_entry_ledger_auto_completion (GncEntryLedger *ledger,
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:
/* 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, num, and description should be changed */
/* FIXME, this should be refactored. */
if (gnc_table_layout_get_cell_changed (ledger->table->layout,
ENTRY_INV_CELL, TRUE) ||
gnc_table_layout_get_cell_changed (ledger->table->layout,
ENTRY_ACTN_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))
return FALSE;
/* and the description should 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;
/* find an entry to auto-complete on; FIXME: Get this from somewhere else */
auto_entry = gnc_find_entry_in_reg_by_desc(ledger, desc);
if (auto_entry == NULL)
return FALSE;
#if 0
gnc_suspend_gui_refresh ();
/* now perform the completion */
/* FIXME: only first shot */
gncEntrySetInvAccount(entry, gncEntryGetInvAccount(auto_entry));
gncEntrySetInvPrice(entry, gncEntryGetInvPrice(auto_entry));
gnc_resume_gui_refresh ();
/* FIXME: now move to the non-empty amount column unless config setting says not */
#endif
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 = gnc_find_entry_in_reg_by_desc(ledger, desc);
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:
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:
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 */
cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_QTY_CELL);
set_value_price_cell (cell, gncEntryGetQuantity (auto_entry));
/* Auto-complete price cell */
{
gnc_numeric price;
switch (ledger->type)
{
case GNCENTRY_INVOICE_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:
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;