GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gncEntryLedgerModel.c
1 /*
2  * gncEntryLedgerModel.c -- Model for GncEntry ledger
3  * Copyright (C) 2001, 2002, 2003 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 <glib.h>
27 #include <glib/gi18n.h>
28 
29 #include "Account.h"
30 #include "gnc-ui-util.h"
31 #include "qof.h" /* for g_strcmp0 */
32 
33 #include "datecell.h"
34 #include "checkboxcell.h"
35 
36 #include "gncEntryLedgerP.h"
37 #include "gncEntryLedgerModel.h"
38 
39 
42 /* GET_LABEL */
43 
44 static const char * get_iacct_label (VirtualLocation virt_loc, gpointer data)
45 {
46  return _("Income Account");
47 }
48 
49 static const char * get_bacct_label (VirtualLocation virt_loc, gpointer data)
50 {
51  return _("Expense Account");
52 }
53 
54 static const char * get_actn_label (VirtualLocation virt_loc, gpointer data)
55 {
56  return _("Action");
57 }
58 
59 static const char * get_date_label (VirtualLocation virt_loc, gpointer data)
60 {
61  return _("Date");
62 }
63 
64 static const char * get_desc_label (VirtualLocation virt_loc, gpointer data)
65 {
66  return _("Description");
67 }
68 
69 static const char * get_disc_label (VirtualLocation virt_loc, gpointer data)
70 {
71  return _("Discount");
72 }
73 
74 static const char * get_distype_label (VirtualLocation virt_loc, gpointer data)
75 {
76  return _("Discount Type");
77 }
78 
79 static const char * get_dishow_label (VirtualLocation virt_loc, gpointer data)
80 {
81  return _("Discount How");
82 }
83 
84 static const char * get_pric_label (VirtualLocation virt_loc, gpointer data)
85 {
86  return _("Unit Price");
87 }
88 
89 static const char * get_qty_label (VirtualLocation virt_loc, gpointer data)
90 {
91  return _("Quantity");
92 }
93 
94 static const char * get_taxtable_label (VirtualLocation virt_loc, gpointer data)
95 {
96  return _("Tax Table");
97 }
98 
99 static const char * get_taxable_label (VirtualLocation virt_loc, gpointer data)
100 {
101  return _("Taxable?");
102 }
103 
104 static const char * get_taxincluded_label (VirtualLocation virt_loc, gpointer data)
105 {
106  return _("Tax Included?");
107 }
108 
109 static const char * get_inv_label (VirtualLocation virt_loc, gpointer data)
110 {
111  return _("Invoiced?");
112 }
113 
114 static const char * get_value_label (VirtualLocation virt_loc, gpointer data)
115 {
116  return _("Subtotal");
117 }
118 
119 static const char * get_taxval_label (VirtualLocation virt_loc, gpointer data)
120 {
121  return _("Tax");
122 }
123 
124 static const char * get_billable_label (VirtualLocation virt_loc, gpointer data)
125 {
126  return _("Billable?");
127 }
128 
129 static const char * get_payment_label (VirtualLocation virt_loc, gpointer data)
130 {
131  return _("Payment");
132 }
133 
134 /* GET_ENTRY */
135 
136 static const char * get_iacct_entry (VirtualLocation virt_loc,
137  gboolean translate,
138  gboolean *conditionally_changed,
139  gpointer user_data)
140 {
141  static char *name = NULL;
142 
143  GncEntryLedger *ledger = user_data;
144  GncEntry *entry;
145 
146  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
147 
148  g_free (name);
149  name = gnc_get_account_name_for_register (gncEntryGetInvAccount (entry));
150  return name;
151 }
152 
153 static const char * get_bacct_entry (VirtualLocation virt_loc,
154  gboolean translate,
155  gboolean *conditionally_changed,
156  gpointer user_data)
157 {
158  static char *name = NULL;
159 
160  GncEntryLedger *ledger = user_data;
161  GncEntry *entry;
162 
163  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
164 
165  g_free (name);
166  name = gnc_get_account_name_for_register (gncEntryGetBillAccount (entry));
167  return name;
168 }
169 
170 static const char * get_actn_entry (VirtualLocation virt_loc,
171  gboolean translate,
172  gboolean *conditionally_changed,
173  gpointer user_data)
174 {
175  GncEntryLedger *ledger = user_data;
176  GncEntry *entry;
177 
178  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
179  return gncEntryGetAction (entry);
180 }
181 
182 static const char * get_date_entry (VirtualLocation virt_loc,
183  gboolean translate,
184  gboolean *conditionally_changed,
185  gpointer user_data)
186 {
187  GncEntryLedger *ledger = user_data;
188  GncEntry *entry;
189  Timespec ts;
190 
191  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
192 
193  ts = gncEntryGetDate (entry);
194  return gnc_print_date (ts);
195 }
196 
197 static const char * get_desc_entry (VirtualLocation virt_loc,
198  gboolean translate,
199  gboolean *conditionally_changed,
200  gpointer user_data)
201 {
202  GncEntryLedger *ledger = user_data;
203  GncEntry *entry;
204 
205  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
206  return gncEntryGetDescription (entry);
207 }
208 
209 static const char * get_disc_entry (VirtualLocation virt_loc,
210  gboolean translate,
211  gboolean *conditionally_changed,
212  gpointer user_data)
213 {
214  GncEntryLedger *ledger = user_data;
215  GncEntry *entry;
216  gnc_numeric discount;
217 
218  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
219  discount = gncEntryGetInvDiscount (entry);
220  if (gnc_numeric_zero_p (discount))
221  return NULL;
222 
223  return xaccPrintAmount (discount, gnc_default_print_info (FALSE));
224 }
225 
226 static const char * get_distype_entry (VirtualLocation virt_loc,
227  gboolean translate,
228  gboolean *conditionally_changed,
229  gpointer user_data)
230 {
231  GncEntryLedger *ledger = user_data;
232  GncEntry *entry;
233  char type;
234 
235  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
236  type = gncEntryGetInvDiscountType (entry);
237 
238  if (translate)
239  {
240  return gnc_entry_ledger_type_string_getter (type + '0');
241  }
242  else
243  {
244  static char s[2];
245  s[0] = '0' + type;
246  s[1] = '\0';
247  return s;
248  }
249 }
250 
251 static const char * get_dishow_entry (VirtualLocation virt_loc,
252  gboolean translate,
253  gboolean *conditionally_changed,
254  gpointer user_data)
255 {
256  GncEntryLedger *ledger = user_data;
257  GncEntry *entry;
258  char type;
259 
260  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
261  type = gncEntryGetInvDiscountHow (entry);
262 
263  if (translate)
264  {
265  return gnc_entry_ledger_how_string_getter (type + '0');
266  }
267  else
268  {
269  static char s[2];
270  s[0] = '0' + type;
271  s[1] = '\0';
272  return s;
273  }
274 }
275 
276 static const char * get_pric_entry (VirtualLocation virt_loc,
277  gboolean translate,
278  gboolean *conditionally_changed,
279  gpointer user_data)
280 {
281  GncEntryLedger *ledger = user_data;
282  GncEntry *entry;
283  gnc_numeric price;
284 
285  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
286  if (ledger->is_cust_doc)
287  price = gncEntryGetInvPrice (entry);
288  else
289  price = gncEntryGetBillPrice (entry);
290 
291  if (gnc_numeric_zero_p (price))
292  return NULL;
293 
294  return xaccPrintAmount (price, gnc_default_print_info (FALSE));
295 }
296 
297 static const char * get_qty_entry (VirtualLocation virt_loc,
298  gboolean translate,
299  gboolean *conditionally_changed,
300  gpointer user_data)
301 {
302  GncEntryLedger *ledger = user_data;
303  GncEntry *entry;
304  gnc_numeric qty;
305 
306  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
307  qty = gncEntryGetDocQuantity (entry, ledger->is_credit_note);
308 
309  if (gnc_numeric_zero_p (qty))
310  return NULL;
311 
312  return xaccPrintAmount (qty, gnc_default_print_info (FALSE));
313 }
314 
315 static const char * get_taxable_entry (VirtualLocation virt_loc,
316  gboolean translate,
317  gboolean *conditionally_changed,
318  gpointer user_data)
319 {
320  GncEntryLedger *ledger = user_data;
321  GncEntry *entry;
322  gboolean taxable;
323 
324  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
325  if (ledger->is_cust_doc)
326  taxable = gncEntryGetInvTaxable (entry);
327  else
328  taxable = gncEntryGetBillTaxable (entry);
329 
330  return gnc_checkbox_cell_get_string (taxable);
331 }
332 
333 static gboolean
334 gnc_entry_ledger_get_taxable_value (VirtualLocation virt_loc,
335  gboolean translate,
336  gboolean *conditionally_changed,
337  gpointer user_data)
338 {
339  GncEntryLedger *ledger = user_data;
340  gboolean is_current;
341 
342  is_current = virt_cell_loc_equal(ledger->table->current_cursor_loc.vcell_loc,
343  virt_loc.vcell_loc);
344  if (is_current)
345  return gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
346  else
347  {
348  const char *valstr =
349  get_taxable_entry (virt_loc, translate, conditionally_changed,
350  user_data);
351  if (valstr && *valstr == 'X')
352  return TRUE;
353  }
354  return FALSE;
355 }
356 
357 static const char * get_taxtable_entry (VirtualLocation virt_loc,
358  gboolean translate,
359  gboolean *conditionally_changed,
360  gpointer user_data)
361 {
362  GncEntryLedger *ledger = user_data;
363  GncEntry *entry;
365  gboolean taxable;
366 
367  /* load the cell properly; just shadow the value */
368  if (!conditionally_changed)
369  {
370  taxable = gnc_entry_ledger_get_taxable_value (virt_loc, translate,
371  conditionally_changed,
372  user_data);
373  if (!taxable)
374  return NULL;
375  }
376 
377  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
378  if (ledger->is_cust_doc)
379  table = gncEntryGetInvTaxTable (entry);
380  else
381  table = gncEntryGetBillTaxTable (entry);
382 
383  return gncTaxTableGetName (table);
384 }
385 
386 static const char * get_taxincluded_entry (VirtualLocation virt_loc,
387  gboolean translate,
388  gboolean *conditionally_changed,
389  gpointer user_data)
390 {
391  GncEntryLedger *ledger = user_data;
392  GncEntry *entry;
393  gboolean taxable, taxincluded;
394 
395  /* load the cell properly; just shadow the value */
396  if (!conditionally_changed)
397  {
398  taxable = gnc_entry_ledger_get_taxable_value (virt_loc, translate,
399  conditionally_changed,
400  user_data);
401  if (!taxable)
402  return NULL;
403  }
404 
405  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
406  if (ledger->is_cust_doc)
407  taxincluded = gncEntryGetInvTaxIncluded (entry);
408  else
409  taxincluded = gncEntryGetBillTaxIncluded (entry);
410 
411  return gnc_checkbox_cell_get_string (taxincluded);
412 }
413 
414 static const char * get_inv_entry (VirtualLocation virt_loc,
415  gboolean translate,
416  gboolean *conditionally_changed,
417  gpointer user_data)
418 {
419  GncEntryLedger *ledger = user_data;
420  GncEntry *entry;
421 
422  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
423 
424  return gnc_checkbox_cell_get_string (gncEntryGetInvoice (entry) != NULL);
425 
426  /* XXX: what if this entry doesn't belong to this invoice?
427  * Or, better question, what if this is the blank_entry on
428  * an invoice page? For the latter, don't worry about it;
429  * it will be added automatically during the Save operation
430  */
431 }
432 
433 static const char * get_value_entry (VirtualLocation virt_loc,
434  gboolean translate,
435  gboolean *conditionally_changed,
436  gpointer user_data)
437 {
438  GncEntryLedger *ledger = user_data;
439  gnc_numeric value;
440 
441  /* Check if this is the current cursor */
442  if (virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
443  virt_loc.vcell_loc))
444  {
445  /* Sign attention: this function works with values as seen
446  * on-screen in the ledger, so they are always in the proper sign.
447  */
448  gnc_entry_ledger_compute_value (ledger, &value, NULL);
449  }
450  else
451  {
452  GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
453 
454  if (entry == gnc_entry_ledger_get_blank_entry (ledger))
455  return NULL;
456 
457  /* Ledger should display values with the same sign as on the document
458  * so get the document value instead of the internal value here.
459  */
460  value = gncEntryGetDocValue (entry, TRUE, ledger->is_cust_doc, ledger->is_credit_note);
461  }
462 
463  return xaccPrintAmount (value, gnc_default_print_info (FALSE));
464 }
465 
466 static const char * get_taxval_entry (VirtualLocation virt_loc,
467  gboolean translate,
468  gboolean *conditionally_changed,
469  gpointer user_data)
470 {
471  GncEntryLedger *ledger = user_data;
472  gnc_numeric value;
473 
474  /* Check if this is the current cursor */
475  if (virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
476  virt_loc.vcell_loc))
477  {
478  /* Sign attention: this function works with values as seen
479  * on-screen in the ledger, so they are always in the proper sign.
480  */
481  gnc_entry_ledger_compute_value (ledger, NULL, &value);
482  }
483  else
484  {
485  GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
486 
487  if (entry == gnc_entry_ledger_get_blank_entry (ledger))
488  return NULL;
489 
490  /* Ledger should display values with the same sign as on the document
491  * so get the document value instead of the internal value here.
492  */
493  value = gncEntryGetDocTaxValue (entry, TRUE, ledger->is_cust_doc, ledger->is_credit_note);
494  }
495 
496  return xaccPrintAmount (value, gnc_default_print_info (FALSE));
497 }
498 
499 static const char * get_billable_entry (VirtualLocation virt_loc,
500  gboolean translate,
501  gboolean *conditionally_changed,
502  gpointer user_data)
503 {
504  GncEntryLedger *ledger = user_data;
505  GncEntry *entry;
506 
507  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
508  return gnc_checkbox_cell_get_string (gncEntryGetBillable (entry));
509 }
510 
511 static const char * get_payment_entry (VirtualLocation virt_loc,
512  gboolean translate,
513  gboolean *conditionally_changed,
514  gpointer user_data)
515 {
516  GncEntryLedger *ledger = user_data;
517  GncEntry *entry;
518  GncEntryPaymentType type;
519 
520  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
521 
522  if (!entry)
523  return "";
524 
525  type = gncEntryGetBillPayment (entry);
526 
527  switch (type)
528  {
529  case GNC_PAYMENT_CASH:
530  return _("Cash");
531  case GNC_PAYMENT_CARD:
532  return _("Charge");
533  default:
534  g_warning ("Invalid payment type: %d", type);
535  return "";
536  }
537 }
538 
539 /* GET_HELP */
540 
541 static char * get_acct_help (VirtualLocation virt_loc, gpointer user_data)
542 {
543  const char *help;
544  GncEntryLedger *ledger = user_data;
545 
546  help = gnc_table_get_entry (ledger->table, virt_loc);
547  if (!help || *help == '\0')
548  help = _("Enter the income/expense account for the Entry, "
549  "or choose one from the list");
550 
551  return g_strdup (help);
552 }
553 
554 static char * get_actn_help (VirtualLocation virt_loc, gpointer user_data)
555 {
556  GncEntryLedger *ledger = user_data;
557  const char *help;
558 
559  help = gnc_table_get_entry (ledger->table, virt_loc);
560  if (!help || *help == '\0')
561  help = _("Enter the type of Entry");
562 
563  return g_strdup (help);
564 }
565 
566 static char * get_date_help (VirtualLocation virt_loc, gpointer user_data)
567 {
568  GncEntryLedger *ledger = user_data;
569  BasicCell *cell;
570  char string[1024];
571  struct tm tm;
572  Timespec ts;
573  time64 tt;
574 
575  cell = gnc_table_get_cell (ledger->table, virt_loc);
576  if (!cell)
577  return NULL;
578 
579  if (!cell->value || *cell->value == '\0')
580  return NULL;
581 
582  gnc_date_cell_get_date ((DateCell *) cell, &ts);
583  tt = ts.tv_sec;
584  gnc_localtime_r (&tt, &tm);
585  qof_strftime (string, sizeof(string), _("%A %d %B %Y"), &tm);
586 
587  return g_strdup (string);
588 }
589 
590 static char * get_desc_help (VirtualLocation virt_loc, gpointer user_data)
591 {
592  GncEntryLedger *ledger = user_data;
593  const char *help;
594 
595  help = gnc_table_get_entry (ledger->table, virt_loc);
596  if (!help || *help == '\0')
597  help = _("Enter the Entry Description");
598 
599  return g_strdup (help);
600 }
601 
602 static char * get_disc_help (VirtualLocation virt_loc, gpointer user_data)
603 {
604  GncEntryLedger *ledger = user_data;
605  const char *help;
606  gint type;
607 
608  type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);
609 
610  switch (type)
611  {
612  case GNC_AMT_TYPE_VALUE:
613  help = _("Enter the Discount Amount");
614  break;
616  help = _("Enter the Discount Percent");
617  break;
618  default:
619  help = _("Enter the Discount ... unknown type");
620  break;
621  }
622 
623  return g_strdup (help);
624 }
625 
626 static char * get_distype_help (VirtualLocation virt_loc, gpointer user_data)
627 {
628  GncEntryLedger *ledger = user_data;
629  const char *help;
630  gint type;
631 
632  type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);
633 
634  switch (type)
635  {
636  case GNC_AMT_TYPE_VALUE:
637  help = _("Discount Type: Monetary Value");
638  break;
640  help = _("Discount Type: Percent");
641  break;
642  default:
643  help = _("Select the Discount Type");
644  break;
645  }
646  return g_strdup (help);
647 }
648 
649 static char * get_dishow_help (VirtualLocation virt_loc, gpointer user_data)
650 {
651  GncEntryLedger *ledger = user_data;
652  const char *help;
653  gint type;
654 
655  type = gnc_entry_ledger_get_type (ledger, ENTRY_DISHOW_CELL);
656 
657  switch (type)
658  {
659  case GNC_DISC_PRETAX:
660  help = _("Tax computed after discount is applied");
661  break;
662  case GNC_DISC_SAMETIME:
663  help = _("Discount and tax both applied on pretax value");
664  break;
665  case GNC_DISC_POSTTAX:
666  help = _("Discount computed after tax is applied");
667  break;
668  default:
669  help = _("Select how to compute the Discount and Taxes");
670  break;
671  }
672  return g_strdup (help);
673 }
674 
675 static char * get_pric_help (VirtualLocation virt_loc, gpointer user_data)
676 {
677  GncEntryLedger *ledger = user_data;
678  const char *help;
679 
680  help = gnc_table_get_entry (ledger->table, virt_loc);
681  if (!help || *help == '\0')
682  help = _("Enter the unit-Price for this Entry");
683 
684  return g_strdup (help);
685 }
686 
687 static char * get_qty_help (VirtualLocation virt_loc, gpointer user_data)
688 {
689  GncEntryLedger *ledger = user_data;
690  const char *help;
691 
692  help = gnc_table_get_entry (ledger->table, virt_loc);
693  if (!help || *help == '\0')
694  help = _("Enter the Quantity of units for this Entry");
695 
696  return g_strdup (help);
697 }
698 
699 static char * get_taxtable_help (VirtualLocation virt_loc, gpointer user_data)
700 {
701  GncEntryLedger *ledger = user_data;
702  const char *help;
703 
704  help = gnc_table_get_entry (ledger->table, virt_loc);
705  if (!help || *help == '\0')
706  help = _("Enter the Tax Table to apply to this entry");
707 
708  return g_strdup (help);
709 }
710 
711 static char * get_taxable_help (VirtualLocation virt_loc, gpointer user_data)
712 {
713  const char *help;
714 
715  help = _("Is this entry taxable?");
716 
717  return g_strdup (help);
718 }
719 
720 static char * get_taxincluded_help (VirtualLocation virt_loc, gpointer user_data)
721 {
722  const char *help;
723 
724  help = _("Is the tax already included in the price of this entry?");
725 
726  return g_strdup (help);
727 }
728 
729 static char * get_inv_help (VirtualLocation virt_loc, gpointer user_data)
730 {
731  GncEntryLedger *ledger = user_data;
732  const char *help;
733 
734  switch (ledger->type)
735  {
736  case GNCENTRY_ORDER_ENTRY:
737  case GNCENTRY_ORDER_VIEWER:
738  case GNCENTRY_BILL_ENTRY:
739  case GNCENTRY_BILL_VIEWER:
740  case GNCENTRY_EXPVOUCHER_ENTRY:
741  case GNCENTRY_EXPVOUCHER_VIEWER:
742  help = _("Is this entry invoiced?");
743  break;
744  case GNCENTRY_VEND_CREDIT_NOTE_ENTRY:
745  case GNCENTRY_VEND_CREDIT_NOTE_VIEWER:
746  case GNCENTRY_EMPL_CREDIT_NOTE_ENTRY:
747  case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER:
748  help = _("Is this entry credited?");
749  break;
750  case GNCENTRY_INVOICE_ENTRY:
751  case GNCENTRY_INVOICE_VIEWER:
752  help = _("Include this entry on this invoice?");
753  break;
754  case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
755  case GNCENTRY_CUST_CREDIT_NOTE_VIEWER:
756  help = _("Include this entry on this credit note?");
757  break;
758  default:
759  help = _("Unknown EntryLedger Type");
760  }
761 
762  return g_strdup (help);
763 }
764 
765 static char * get_value_help (VirtualLocation virt_loc, gpointer user_data)
766 {
767  GncEntryLedger *ledger = user_data;
768  const char *help;
769 
770  help = gnc_table_get_entry (ledger->table, virt_loc);
771  if (!help || *help == '\0')
772  help = _("The subtotal value of this entry ");
773 
774  return g_strdup (help);
775 }
776 
777 static char * get_taxval_help (VirtualLocation virt_loc, gpointer user_data)
778 {
779  GncEntryLedger *ledger = user_data;
780  const char *help;
781 
782  help = gnc_table_get_entry (ledger->table, virt_loc);
783  if (!help || *help == '\0')
784  help = _("The total tax of this entry ");
785 
786  return g_strdup (help);
787 }
788 
789 static char * get_billable_help (VirtualLocation virt_loc, gpointer user_data)
790 {
791  const char *help;
792 
793  help = _("Is this entry billable to a customer or job?");
794 
795  return g_strdup (help);
796 }
797 
798 static char * get_payment_help (VirtualLocation virt_loc, gpointer user_data)
799 {
800  const char *help;
801 
802  help = _("How did you pay for this item?");
803 
804  return g_strdup (help);
805 }
806 
807 /* GET_IO_FLAGS */
808 
809 static CellIOFlags get_standard_io_flags (VirtualLocation virt_loc,
810  gpointer user_data)
811 {
812  GncEntryLedger *ledger = user_data;
813  switch (ledger->type)
814  {
815  case GNCENTRY_ORDER_ENTRY:
816  case GNCENTRY_BILL_ENTRY:
817  case GNCENTRY_EXPVOUCHER_ENTRY:
818  {
819  GncEntry *entry =
820  gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
821 
822  /*
823  * If the type is an order_entry and the entry was invoiced,
824  * make the entry immutable
825  */
826  if (gncEntryGetInvoice (entry) != NULL)
827  return XACC_CELL_ALLOW_SHADOW;
828  }
829  /* FALL THROUGH */
830  default:
831  return XACC_CELL_ALLOW_ALL;
832  }
833 }
834 
835 static CellIOFlags get_typecell_io_flags (VirtualLocation virt_loc,
836  gpointer user_data)
837 {
838  return (get_standard_io_flags (virt_loc, user_data) |
839  XACC_CELL_ALLOW_EXACT_ONLY);
840 }
841 
842 static CellIOFlags get_inv_io_flags (VirtualLocation virt_loc,
843  gpointer user_data)
844 {
845  GncEntryLedger *ledger = user_data;
846 
847  switch (ledger->type)
848  {
849  case GNCENTRY_INVOICE_ENTRY:
850  case GNCENTRY_CUST_CREDIT_NOTE_ENTRY:
851  {
852  /* This cell should be immutable IFF this entry is attached to
853  * a bill, order, or something else.
854  */
855  GncEntry * entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
856 
857  if ((gncEntryGetOrder (entry) != NULL) || (gncEntryGetBill (entry) != NULL))
858  return XACC_CELL_ALLOW_ALL | XACC_CELL_ALLOW_EXACT_ONLY;
859 
860  }
861  /* FALL THROUGH */
862  default:
863  return XACC_CELL_ALLOW_SHADOW;
864  }
865 }
866 
867 static CellIOFlags get_value_io_flags (VirtualLocation virt_loc,
868  gpointer user_data)
869 {
870  return XACC_CELL_ALLOW_SHADOW;
871 }
872 
873 static CellIOFlags get_tax_io_flags (VirtualLocation virt_loc,
874  gpointer user_data)
875 {
876  GncEntryLedger *ledger = user_data;
877  gboolean taxable;
878 
879  taxable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
880 
881  /* Only print the taxtable and taxincluded cells if taxable is true */
882  if (taxable)
883  return get_standard_io_flags (virt_loc, user_data);
884 
885  /* Shadow the value, so the cell is loaded properly */
886  return XACC_CELL_ALLOW_SHADOW;
887 }
888 
889 static CellIOFlags get_taxincluded_io_flags (VirtualLocation virt_loc,
890  gpointer user_data)
891 {
892  CellIOFlags flags = get_tax_io_flags (virt_loc, user_data);
893  if (flags == XACC_CELL_ALLOW_SHADOW)
894  return flags;
895  return flags | XACC_CELL_ALLOW_EXACT_ONLY;
896 }
897 
898 static CellIOFlags get_qty_io_flags (VirtualLocation virt_loc, gpointer user_data)
899 {
900  GncEntryLedger *ledger = user_data;
901  GncEntry *entry;
902  CellIOFlags flags = get_standard_io_flags (virt_loc, user_data);
903 
904  /* If this isn't an invoice, or the flags are already read-only ... */
905  if (!ledger->is_cust_doc || flags == XACC_CELL_ALLOW_SHADOW)
906  return flags;
907 
908  /* ok, if this is an invoice ledger AND this entry is attached to a
909  * bill (i.e. it's billable), freeze the quantity
910  */
911  entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
912  if (gncEntryGetBillable (entry))
913  return XACC_CELL_ALLOW_SHADOW;
914 
915  return flags;
916 }
917 
918 /* GET BG_COLORS */
919 
920 static guint32
921 gnc_entry_ledger_get_color_internal (VirtualLocation virt_loc,
922  GncEntryLedger *ledger,
923  const guint32 *color_table,
924  gboolean foreground)
925 {
926  const char *cursor_name;
927  VirtualCell *vcell;
928  gboolean is_current;
929  guint32 colorbase = 0; /* By default return background colors */
930 
931  if (foreground)
932  colorbase = COLOR_UNKNOWN_FG; /* a bit of enum arithmetic */
933 
934  if (!ledger)
935  return color_table[colorbase + COLOR_UNKNOWN_BG];
936 
937  if (gnc_table_virtual_location_in_header (ledger->table, virt_loc))
938  return color_table[colorbase + COLOR_HEADER_BG];
939 
940  vcell = gnc_table_get_virtual_cell (ledger->table, virt_loc.vcell_loc);
941  if (!vcell || !vcell->cellblock)
942  return color_table[colorbase + COLOR_UNKNOWN_BG];
943 
944  if ((virt_loc.phys_col_offset < vcell->cellblock->start_col) ||
945  (virt_loc.phys_col_offset > vcell->cellblock->stop_col))
946  return color_table[colorbase + COLOR_UNKNOWN_BG];
947 
948  is_current = virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
949  virt_loc.vcell_loc);
950 
951  if (is_current)
952  return vcell->start_primary_color ?
953  color_table[colorbase + COLOR_PRIMARY_BG_ACTIVE] :
954  color_table[colorbase + COLOR_SECONDARY_BG_ACTIVE];
955 
956  return vcell->start_primary_color ?
957  color_table[colorbase + COLOR_PRIMARY_BG] : color_table[colorbase + COLOR_SECONDARY_BG];
958 
959 }
960 
961 static guint32
962 gnc_entry_ledger_get_fg_color (VirtualLocation virt_loc,
963  gpointer user_data)
964 {
965  GncEntryLedger *ledger = user_data;
966  return gnc_entry_ledger_get_color_internal (virt_loc, ledger, reg_colors_default, TRUE);
967 }
968 
969 static guint32
970 gnc_entry_ledger_get_gtkrc_fg_color (VirtualLocation virt_loc,
971  gpointer user_data)
972 {
973  GncEntryLedger *ledger = user_data;
974  return gnc_entry_ledger_get_color_internal (virt_loc, ledger, reg_colors_gtkrc, TRUE);
975 }
976 
977 static guint32
978 gnc_entry_ledger_get_bg_color (VirtualLocation virt_loc,
979  gboolean *hatching, gpointer user_data)
980 {
981  GncEntryLedger *ledger = user_data;
982 
983  if (hatching)
984  *hatching = FALSE;
985 
986  return gnc_entry_ledger_get_color_internal (virt_loc, ledger, reg_colors_default, FALSE);
987 }
988 
989 static guint32
990 gnc_entry_ledger_get_gtkrc_bg_color (VirtualLocation virt_loc,
991  gboolean *hatching, gpointer user_data)
992 {
993  GncEntryLedger *ledger = user_data;
994 
995  if (hatching)
996  *hatching = FALSE;
997 
998  return gnc_entry_ledger_get_color_internal (virt_loc, ledger, reg_colors_gtkrc, FALSE);
999 }
1000 
1001 /* SAVE CELLS */
1002 
1003 static void gnc_entry_ledger_save_cells (gpointer save_data,
1004  gpointer user_data)
1005 {
1006  GncEntryLedger *ledger = user_data;
1007  GncEntry *entry = save_data;
1008 
1009  g_return_if_fail (entry != NULL);
1010 
1011  /* copy the contents from the cursor to the split */
1012 
1013  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1014  ENTRY_IACCT_CELL, TRUE))
1015  {
1016  Account *acc;
1017 
1018  acc = gnc_entry_ledger_get_account (ledger, ENTRY_IACCT_CELL);
1019 
1020  if (acc != NULL)
1021  gncEntrySetInvAccount (entry, acc);
1022  }
1023 
1024  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1025  ENTRY_BACCT_CELL, TRUE))
1026  {
1027  Account *acc;
1028 
1029  acc = gnc_entry_ledger_get_account (ledger, ENTRY_BACCT_CELL);
1030 
1031  if (acc != NULL)
1032  gncEntrySetBillAccount (entry, acc);
1033  }
1034 
1035  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1036  ENTRY_ACTN_CELL, TRUE))
1037  {
1038  const char *value;
1039 
1040  value = gnc_table_layout_get_cell_value (ledger->table->layout,
1041  ENTRY_ACTN_CELL);
1042  gncEntrySetAction (entry, value);
1043  }
1044 
1045  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1046  ENTRY_DATE_CELL, TRUE))
1047  {
1048  BasicCell *cell;
1049  GDate date;
1050 
1051  cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DATE_CELL);
1052 
1053  /* commit any pending changes */
1054  gnc_date_cell_commit ((DateCell *) cell);
1055 
1056  gnc_date_cell_get_date_gdate ((DateCell *) cell, &date);
1057  gncEntrySetDateGDate (entry, &date);
1058  }
1059 
1060  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1061  ENTRY_DESC_CELL, TRUE))
1062  {
1063  const char *value;
1064 
1065  value = gnc_table_layout_get_cell_value (ledger->table->layout,
1066  ENTRY_DESC_CELL);
1067  gncEntrySetDescription (entry, value);
1068  }
1069 
1070  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1071  ENTRY_DISC_CELL, TRUE))
1072  {
1073  gnc_numeric amount;
1074 
1075  if (gnc_entry_ledger_get_numeric (ledger, ENTRY_DISC_CELL, &amount))
1076  gncEntrySetInvDiscount (entry, amount);
1077  }
1078 
1079  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1080  ENTRY_DISTYPE_CELL, TRUE))
1081  {
1082  gint type;
1083 
1084  type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);
1085 
1086  if (type != -1)
1087  gncEntrySetInvDiscountType (entry, type);
1088  }
1089 
1090  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1091  ENTRY_DISHOW_CELL, TRUE))
1092  {
1093  gint type;
1094 
1095  type = gnc_entry_ledger_get_type (ledger, ENTRY_DISHOW_CELL);
1096 
1097  if (type != -1)
1098  gncEntrySetInvDiscountHow (entry, type);
1099  }
1100 
1101  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1102  ENTRY_QTY_CELL, TRUE))
1103  {
1104  gnc_numeric amount;
1105 
1106  if (gnc_entry_ledger_get_numeric (ledger, ENTRY_QTY_CELL, &amount))
1107  {
1108  gncEntrySetDocQuantity (entry, amount, ledger->is_credit_note);
1109  }
1110  }
1111 
1112  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1113  ENTRY_BILLABLE_CELL, TRUE))
1114  {
1115  gboolean billable;
1116 
1117  billable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_BILLABLE_CELL);
1118  gncEntrySetBillable (entry, billable);
1119  }
1120 
1121  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1122  ENTRY_PAYMENT_CELL, TRUE))
1123  {
1124  const char *value;
1125 
1126  value = gnc_table_layout_get_cell_value (ledger->table->layout,
1127  ENTRY_PAYMENT_CELL);
1128  if (!g_strcmp0 (value, _("Cash")))
1129  gncEntrySetBillPayment (entry, GNC_PAYMENT_CASH);
1130  else if (!g_strcmp0 (value, _("Charge")))
1131  gncEntrySetBillPayment (entry, GNC_PAYMENT_CARD);
1132  else
1133  g_warning ("Invalid Payment cell: %s", value ? value : "(null)");
1134  }
1135 
1136  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1137  ENTRY_PRIC_CELL, TRUE))
1138  {
1139  gnc_numeric amount;
1140 
1141  if (gnc_entry_ledger_get_numeric (ledger, ENTRY_PRIC_CELL, &amount))
1142  {
1143  if (ledger->is_cust_doc)
1144  gncEntrySetInvPrice (entry, amount);
1145  else
1146  gncEntrySetBillPrice (entry, amount);
1147  }
1148  }
1149 
1150  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1151  ENTRY_TAXABLE_CELL, TRUE))
1152  {
1153  gboolean taxable;
1154 
1155  taxable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
1156  if (ledger->is_cust_doc)
1157  gncEntrySetInvTaxable (entry, taxable);
1158  else
1159  gncEntrySetBillTaxable (entry, taxable);
1160  }
1161 
1162  /* XXX: Only (re-set) these if taxable is TRUE? */
1163  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1164  ENTRY_TAXTABLE_CELL, TRUE))
1165  {
1166  GncTaxTable *table;
1167 
1168  table = gnc_entry_ledger_get_taxtable (ledger, ENTRY_TAXTABLE_CELL);
1169  if (table)
1170  {
1171  if (ledger->is_cust_doc)
1172  gncEntrySetInvTaxTable (entry, table);
1173  else
1174  gncEntrySetBillTaxTable (entry, table);
1175  }
1176  }
1177 
1178  if (gnc_table_layout_get_cell_changed (ledger->table->layout,
1179  ENTRY_TAXINCLUDED_CELL, TRUE))
1180  {
1181  gboolean taxincluded;
1182 
1183  taxincluded = gnc_entry_ledger_get_checkmark (ledger,
1184  ENTRY_TAXINCLUDED_CELL);
1185  if (ledger->is_cust_doc)
1186  gncEntrySetInvTaxIncluded (entry, taxincluded);
1187  else
1188  gncEntrySetBillTaxIncluded (entry, taxincluded);
1189  }
1190 
1191  if (ledger->type == GNCENTRY_INVOICE_ENTRY ||
1192  ledger->type == GNCENTRY_CUST_CREDIT_NOTE_ENTRY)
1193  {
1194  gboolean inv_value;
1195 
1196  inv_value = gnc_entry_ledger_get_checkmark (ledger, ENTRY_INV_CELL);
1197 
1198  if (inv_value)
1199  {
1200  /* Add this to the invoice (if it's not already attached) */
1201  if (gncEntryGetInvoice (entry) == NULL)
1202  gncInvoiceAddEntry (ledger->invoice, entry);
1203 
1204  }
1205  else
1206  {
1207  /* Remove from the invoice iff we're attached to an order or bill */
1208  if ((gncEntryGetOrder (entry) != NULL) ||
1209  (gncEntryGetBill (entry) != NULL))
1210  gncInvoiceRemoveEntry (ledger->invoice, entry);
1211  }
1212  }
1213 }
1214 
1215 /* Set Cell Handlers */
1216 
1217 static void gnc_entry_ledger_model_new_handlers (TableModel *model,
1218  GncEntryLedgerType type)
1219 {
1220  struct model_desc
1221  {
1222  const char * cell;
1223  gpointer entry_handler;
1224  gpointer label_handler;
1225  gpointer help_handler;
1226  gpointer io_flags_handler;
1227  } models[] =
1228  {
1229  { ENTRY_IACCT_CELL, get_iacct_entry, get_iacct_label, get_acct_help, get_standard_io_flags },
1230  { ENTRY_BACCT_CELL, get_bacct_entry, get_bacct_label, get_acct_help, get_standard_io_flags },
1231  { ENTRY_ACTN_CELL, get_actn_entry, get_actn_label, get_actn_help, get_standard_io_flags },
1232  { ENTRY_DATE_CELL, get_date_entry, get_date_label, get_date_help, get_standard_io_flags },
1233  { ENTRY_DESC_CELL, get_desc_entry, get_desc_label, get_desc_help, get_standard_io_flags },
1234  { ENTRY_DISC_CELL, get_disc_entry, get_disc_label, get_disc_help, get_standard_io_flags },
1235  { ENTRY_DISTYPE_CELL, get_distype_entry, get_distype_label, get_distype_help, get_typecell_io_flags },
1236  { ENTRY_DISHOW_CELL, get_dishow_entry, get_dishow_label, get_dishow_help, get_typecell_io_flags },
1237  { ENTRY_PRIC_CELL, get_pric_entry, get_pric_label, get_pric_help, get_standard_io_flags },
1238  { ENTRY_QTY_CELL, get_qty_entry, get_qty_label, get_qty_help, get_qty_io_flags },
1239  { ENTRY_TAXABLE_CELL, get_taxable_entry, get_taxable_label, get_taxable_help, get_typecell_io_flags },
1240  { ENTRY_TAXTABLE_CELL, get_taxtable_entry, get_taxtable_label, get_taxtable_help, get_tax_io_flags },
1241  { ENTRY_TAXINCLUDED_CELL, get_taxincluded_entry, get_taxincluded_label, get_taxincluded_help, get_taxincluded_io_flags },
1242  { ENTRY_INV_CELL, get_inv_entry, get_inv_label, get_inv_help, get_inv_io_flags },
1243  { ENTRY_VALUE_CELL, get_value_entry, get_value_label, get_value_help, get_value_io_flags },
1244  { ENTRY_TAXVAL_CELL, get_taxval_entry, get_taxval_label, get_taxval_help, get_value_io_flags },
1245  { ENTRY_BILLABLE_CELL, get_billable_entry, get_billable_label, get_billable_help, get_typecell_io_flags },
1246  { ENTRY_PAYMENT_CELL, get_payment_entry, get_payment_label, get_payment_help, get_standard_io_flags },
1247  };
1248  unsigned int i;
1249 
1250  gnc_table_model_set_default_fg_color_handler
1251  (model, gnc_entry_ledger_get_fg_color);
1252 
1253  gnc_table_model_set_fg_color_handler
1254  (model, gnc_entry_ledger_get_gtkrc_fg_color, "gtkrc");
1255 
1256  gnc_table_model_set_default_bg_color_handler
1257  (model, gnc_entry_ledger_get_bg_color);
1258 
1259  gnc_table_model_set_bg_color_handler
1260  (model, gnc_entry_ledger_get_gtkrc_bg_color, "gtkrc");
1261 
1262 
1263  for (i = 0; i < (sizeof(models) / sizeof(*models)); i++)
1264  {
1265  if (models[i].entry_handler)
1266  gnc_table_model_set_entry_handler (model, models[i].entry_handler,
1267  models[i].cell);
1268  if (models[i].label_handler)
1269  gnc_table_model_set_label_handler (model, models[i].label_handler,
1270  models[i].cell);
1271  if (models[i].help_handler)
1272  gnc_table_model_set_help_handler (model, models[i].help_handler,
1273  models[i].cell);
1274  if (models[i].io_flags_handler)
1275  gnc_table_model_set_io_flags_handler (model, models[i].io_flags_handler,
1276  models[i].cell);
1277  } /* for */
1278 
1279  /*
1280  model->cell_data_allocator = ;
1281  model->cell_data_deallocator = ;
1282  model->cell_data_copy = ;
1283  */
1284 
1285  gnc_table_model_set_post_save_handler (model, gnc_entry_ledger_save_cells);
1286 
1287  switch (type)
1288  {
1289  case GNCENTRY_ORDER_VIEWER:
1290  case GNCENTRY_INVOICE_VIEWER:
1291  case GNCENTRY_BILL_VIEWER:
1292  case GNCENTRY_EXPVOUCHER_VIEWER:
1293  case GNCENTRY_CUST_CREDIT_NOTE_VIEWER:
1294  case GNCENTRY_VEND_CREDIT_NOTE_VIEWER:
1295  case GNCENTRY_EMPL_CREDIT_NOTE_VIEWER:
1296  /* make this table read-only */
1297  gnc_table_model_set_read_only (model, TRUE);
1298  break;
1299  default:
1300  break;
1301  }
1302 }
1303 
1306 TableModel * gnc_entry_ledger_model_new (GncEntryLedgerType type)
1307 {
1308  TableModel * model;
1309 
1310  model = gnc_table_model_new ();
1311  gnc_entry_ledger_model_new_handlers (model, type);
1312 
1313  return model;
1314 }
const char * gnc_print_date(Timespec ts)
utility functions for the GnuCash UI
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
gboolean gnc_numeric_zero_p(gnc_numeric a)
Timespec gncEntryGetDate(const GncEntry *entry)
Definition: gncEntry.c:878
void gncEntrySetDocQuantity(GncEntry *entry, gnc_numeric quantity, gboolean is_cn)
Definition: gncEntry.c:563
struct tm * gnc_localtime_r(const time64 *secs, struct tm *time)
fill out a time struct from a 64-bit time value adjusted for the current time zone.
gchar * gnc_get_account_name_for_register(const Account *account)
Definition: gnc-ui-util.c:282
Account handling public routines.
void gncEntrySetDateGDate(GncEntry *entry, const GDate *date)
Definition: gncEntry.c:505
gsize qof_strftime(gchar *buf, gsize max, const gchar *format, const struct tm *tm)
gint64 time64
Definition: gnc-date.h:83
gnc_numeric gncEntryGetDocQuantity(const GncEntry *entry, gboolean is_cn)
Definition: gncEntry.c:925