GnuCash  5.6-150-g038405b370+
dialog-lot-viewer.c
1 /*******************************************************************\
2  * dialog-lot-viewer.c -- a basic lot viewer for GnuCash *
3  * Copyright (C) 2003 Linas Vepstas <linas@linas.org> *
4  * Copyright (C) 2011 Geert Janssens <geert@kobaltwit.be> *
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 
25 /* XXX todo: The button "view lot in register" is not implemented.
26  * it needs to open register window showing only the splits in the
27  * given lot ...
28  */
29 
30 #include <config.h>
31 
32 #include <gtk/gtk.h>
33 #include <glib/gi18n.h>
34 
35 #include "Account.h"
36 #include "cap-gains.h"
37 #include "gnc-commodity.h"
38 #include "qof.h"
39 #include "gnc-lot.h"
40 #include "Scrub3.h"
41 #include "ScrubBusiness.h"
42 #include "Transaction.h"
43 #include "engine-helpers.h"
44 #include "gncInvoice.h"
45 
46 #include "dialog-utils.h"
47 #include "dialog-lot-viewer.h"
48 #include "gnc-component-manager.h"
49 #include "gnc-prefs.h"
50 #include "gnc-ui-util.h"
51 #include "gnc-window.h"
52 #include "misc-gnome-utils.h"
53 #include "tree-view-utils.h"
54 
55 #define LOT_VIEWER_CM_CLASS "dialog-lot-viewer"
56 
57 enum lot_cols
58 {
59  LOT_COL_TYPE = 0,
60  LOT_COL_OPEN,
61  LOT_COL_CLOSE,
62  LOT_COL_TITLE,
63  LOT_COL_BALN,
64  LOT_COL_BALN_DOUBLE, // used only for sorting
65  LOT_COL_GAINS,
66  LOT_COL_GAINS_DOUBLE, // used only for sorting
67  LOT_COL_PNTR,
68  NUM_LOT_COLS
69 };
70 
71 enum split_cols
72 {
73  SPLIT_COL_DATE = 0,
74  SPLIT_COL_NUM,
75  SPLIT_COL_DESCRIPTION,
76  SPLIT_COL_AMOUNT,
77  SPLIT_COL_AMOUNT_DOUBLE, // used only for sorting
78  SPLIT_COL_VALUE,
79  SPLIT_COL_VALUE_DOUBLE, // used only for sorting
80  SPLIT_COL_GAIN_LOSS,
81  SPLIT_COL_GAIN_LOSS_DOUBLE, // used only for sorting
82  SPLIT_COL_BALANCE,
83  SPLIT_COL_BALANCE_DOUBLE, // used only for sorting
84  SPLIT_COL_PNTR,
85  NUM_SPLIT_COLS
86 };
87 
88 #define RESPONSE_VIEW 1
89 #define RESPONSE_DELETE 2
90 #define RESPONSE_SCRUB_LOT 3
91 #define RESPONSE_SCRUB_ACCOUNT 4
92 #define RESPONSE_NEW_LOT 5
93 
94 #define GNC_PREFS_GROUP "dialogs.lot-viewer"
95 #define GNC_PREF_HPOS "hpane-position"
96 #define GNC_PREF_VPOS "vpane-position"
97 
99 {
100  GtkWidget * window;
101 #ifdef LOTS_READY_FOR_SHOWTIME
102  GtkButton * regview_button;
103 #endif
104  GtkButton * delete_button;
105  GtkButton * scrub_lot_button;
106  GtkButton * new_lot_button;
107  GtkTreeView * lot_view;
108  GtkListStore * lot_store;
109  GtkTextView * lot_notes;
110  GtkEntry * title_entry;
111  GtkTreeView * split_in_lot_view;
112  GtkListStore * split_in_lot_store;
113  GtkTreeView * split_free_view;
114  GtkListStore * split_free_store;
115  GtkWidget * split_hpaned;
116  GtkButton * add_split_to_lot_button;
117  GtkButton * remove_split_from_lot_button;
118  GtkToggleButton * only_show_open_lots_checkbutton;
119 
120  Account * account;
121  GNCLot * selected_lot;
122 };
123 
124 static void gnc_lot_viewer_fill (GNCLotViewer *lv);
125 static void gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_list);
126 
127 /* ======================================================================== */
128 /* Callback prototypes */
129 
130 void lv_title_entry_changed_cb (GtkEntry *ent, gpointer user_data);
131 void lv_response_cb (GtkDialog *dialog, gint response, gpointer data);
132 void lv_window_destroy_cb (GtkWidget *object, gpointer user_data);
133 void lv_paned_notify_cb (GObject *gobject,
134  GParamSpec *pspec,
135  gpointer user_data);
136 
137 /* ======================================================================== */
138 /* Get the realized gains for this lot. This routine or a variant of it
139  * should probably be moved to gnc-lot.c.
140  * The conceptual difficulty here is that this works only if all of the
141  * realized gains in the lot are of the
142  */
143 
144 static gnc_commodity *
145 find_first_currency (GNCLot *lot)
146 {
147  SplitList *split_list, *node;
148 
149  split_list = gnc_lot_get_split_list(lot);
150  for (node = split_list; node; node = node->next)
151  {
152  Split *s = node->data;
153  Transaction *trans;
154  if (FALSE == gnc_numeric_zero_p(xaccSplitGetAmount(s))) continue;
155  trans = xaccSplitGetParent (s);
156  return xaccTransGetCurrency (trans);
157  }
158  return NULL;
159 }
160 
161 static gnc_numeric
162 get_realized_gains (GNCLot *lot, gnc_commodity *currency)
163 {
164  gnc_numeric zero = gnc_numeric_zero();
165  gnc_numeric gains = zero;
166  SplitList *split_list, *node;
167 
168  if (!currency) return zero;
169 
170  split_list = gnc_lot_get_split_list(lot);
171  for (node = split_list; node; node = node->next)
172  {
173  Split *s = node->data;
174  Transaction *trans;
175 
176  if (FALSE == gnc_numeric_zero_p(xaccSplitGetAmount(s))) continue;
177  trans = xaccSplitGetParent (s);
178  if (FALSE == gnc_commodity_equal (xaccTransGetCurrency(trans), currency)) continue;
179 
181  }
182  return gains;
183 }
184 
185 
186 /* ======================================================================== */
187 /* Populate the lot split list view based on the currently selected lot */
188 
189 static void
190 lv_show_splits_in_lot (GNCLotViewer *lv)
191 {
192  GNCLot *lot = lv->selected_lot;
193  SplitList *split_list;
194 
195  if (NULL == lot) return;
196 
197  split_list = gnc_lot_get_split_list (lot);
198  gnc_split_viewer_fill(lv, lv->split_in_lot_store, split_list);
199 }
200 
201 /* ======================================================================== */
202 /* Remove all splits from the split list view */
203 
204 static void
205 lv_clear_splits_in_lot (GNCLotViewer *lv)
206 {
207  gtk_list_store_clear (lv->split_in_lot_store);
208 }
209 
210 /* ======================================================================== */
211 /* Populate the free split list view */
212 
213 static void
214 lv_show_splits_free (GNCLotViewer *lv)
215 {
216  SplitList *split_list, *node;
217  SplitList *filtered_list = NULL;
218 
219  /* cleanup */
220  gtk_list_store_clear (lv->split_free_store);
221 
222  /* get splits */
223  split_list = xaccAccountGetSplitList(lv->account);
224 
225  /* filter splits */
226  for (node = split_list; node; node = node->next)
227  {
228  Split *split = node->data;
229  if (NULL == xaccSplitGetLot(split))
230  {
231  filtered_list = g_list_prepend (filtered_list, split);
232  }
233  }
234  filtered_list = g_list_reverse (filtered_list);
235 
236  /* display list */
237  gnc_split_viewer_fill(lv, lv->split_free_store, filtered_list);
238  g_list_free (filtered_list);
239  g_list_free (split_list);
240 }
241 
242 /* ======================================================================== */
243 /* Save potential changes to the currently selected lot */
244 
245 static void
246 lv_save_current_lot (GNCLotViewer *lv)
247 {
248  GNCLot *lot = lv->selected_lot;
249  const char * str;
250  char * notes;
251 
252  if (lot)
253  {
254  gnc_lot_begin_edit(lot);
255 
256  /* Get the title, save_the_title */
257  str = gtk_entry_get_text (lv->title_entry);
258  gnc_lot_set_title (lot, str);
259 
260  /* Get the notes, save the notes */
261  notes = xxxgtk_textview_get_text (lv->lot_notes);
262  gnc_lot_set_notes (lot, notes);
263  g_free(notes);
264 
265  gnc_lot_commit_edit(lot);
266  }
267 }
268 
269 /* ======================================================================== */
270 /* Clear all information related to the currently selected lot */
271 
272 static void
273 lv_unset_lot (GNCLotViewer *lv)
274 {
275  /* Set immediately, to avoid recursion in gtkentry "changed" cb. */
276  lv->selected_lot = NULL;
277 
278  /* Blank the title widget */
279  gtk_entry_set_text (lv->title_entry, "");
280  gtk_editable_set_editable (GTK_EDITABLE(lv->title_entry), FALSE);
281 
282  /* Blank the notes area */
283  xxxgtk_textview_set_text (lv->lot_notes, "");
284  gtk_text_view_set_editable (lv->lot_notes, FALSE);
285 
286  /* Erase the mini-view area */
287  lv_clear_splits_in_lot (lv);
288 
289 #ifdef LOTS_READY_FOR_SHOWTIME
290  gtk_widget_set_sensitive(GTK_WIDGET(lv->regview_button), FALSE);
291 #endif
292  gtk_widget_set_sensitive(GTK_WIDGET(lv->delete_button), FALSE);
293  gtk_widget_set_sensitive(GTK_WIDGET(lv->scrub_lot_button), FALSE);
294 }
295 
296 /* ======================================================================== */
297 /* Select a row in the lot list */
298 
299 static void
300 lv_select_row (GNCLotViewer *lv,
301  GNCLot *lot)
302 {
303  const char * str;
304 
305  lv_save_current_lot (lv);
306 
307  str = gnc_lot_get_title (lot);
308  if (!str) str = "";
309  gtk_entry_set_text (lv->title_entry, str);
310  gtk_editable_set_editable (GTK_EDITABLE(lv->title_entry), TRUE);
311 
312  /* Set the notes field */
313  str = gnc_lot_get_notes (lot);
314  if (!str) str = "";
315  xxxgtk_textview_set_text (lv->lot_notes, str);
316  gtk_text_view_set_editable (lv->lot_notes, TRUE);
317 
318  /* Don't set until end, to avoid recursion in gtkentry "changed" cb. */
319  lv->selected_lot = lot;
320  lv_show_splits_in_lot (lv);
321 
322 #ifdef LOTS_READY_FOR_SHOWTIME
323  gtk_widget_set_sensitive(GTK_WIDGET(lv->regview_button), TRUE);
324 #endif
325  gtk_widget_set_sensitive(GTK_WIDGET(lv->delete_button), TRUE);
326  gtk_widget_set_sensitive(GTK_WIDGET(lv->scrub_lot_button), TRUE);
327 }
328 
329 /* ======================================================================== */
330 /* Un-select a row of the lot list */
331 
332 static void
333 lv_unselect_row (GNCLotViewer *lv)
334 {
335  lv_save_current_lot (lv);
336  lv_unset_lot (lv);
337 }
338 
339 /* ======================================================================== */
340 /* Populate the lot list view */
341 
342 static void
343 gnc_lot_viewer_fill (GNCLotViewer *lv)
344 {
345  LotList *lot_list, *node;
346  GNCLot *this_lot, *selected_lot = NULL;
347  GtkListStore *store;
348  GtkTreeModel *model;
349  GtkTreeIter iter;
350  GtkTreeSelection *selection;
351  gboolean found = FALSE;
352 
353  lot_list = xaccAccountGetLotList (lv->account);
354 
355  selection = gtk_tree_view_get_selection(lv->lot_view);
356  if (gtk_tree_selection_get_selected (selection, &model, &iter))
357  gtk_tree_model_get(model, &iter, LOT_COL_PNTR, &selected_lot, -1);
358 
359  /* Crazy. Should update in place if possible. */
360  gtk_list_store_clear (lv->lot_store);
361 
362  for (node = lot_list; node; node = node->next)
363  {
364  char type_buff[200];
365  char baln_buff[200];
366  char gain_buff[200];
367  GNCLot *lot = node->data;
368  Split *esplit = gnc_lot_get_earliest_split (lot);
369  gnc_numeric amt_baln = gnc_lot_get_balance (lot);
370  gnc_commodity *currency = find_first_currency (lot);
371  gnc_numeric gains_baln = get_realized_gains (lot, currency);
372 
373  /* Skip closed lots when only open should be shown */
374  if (TRUE == gtk_toggle_button_get_active(lv->only_show_open_lots_checkbutton) && gnc_lot_is_closed (lot))
375  {
376  continue;
377  }
378 
379  store = lv->lot_store;
380  gtk_list_store_append(store, &iter);
381 
382  /* Part of invoice */
383  type_buff[0] = '\0';
384  if ( NULL != gncInvoiceGetInvoiceFromLot(lot) )
385  {
386  snprintf(type_buff, 200, "I");
387  }
388  gtk_list_store_set(store, &iter, LOT_COL_TYPE, type_buff, -1);
389 
390  /* Opening date */
391  if (esplit)
392  {
393  Transaction *etrans = xaccSplitGetParent (esplit);
394  time64 open_date = xaccTransGetDate (etrans);
395  gtk_list_store_set(store, &iter, LOT_COL_OPEN, open_date, -1);
396  }
397  else
398  gtk_list_store_set(store, &iter, LOT_COL_OPEN, G_MININT64, -1);
399 
400  /* Closing date */
401  if (gnc_lot_is_closed (lot))
402  {
403  Split *fsplit = gnc_lot_get_latest_split (lot);
404  Transaction *ftrans = xaccSplitGetParent (fsplit);
405  time64 close_date = xaccTransGetDate (ftrans);
406 
407  gtk_list_store_set(store, &iter, LOT_COL_CLOSE, close_date, -1);
408  }
409  else
410  {
411  gtk_list_store_set(store, &iter, LOT_COL_CLOSE, G_MAXINT64, -1);
412  }
413 
414  /* Title */
415  gtk_list_store_set(store, &iter, LOT_COL_TITLE, gnc_lot_get_title(lot), -1);
416 
417  /* Amount */
418  xaccSPrintAmount (baln_buff, amt_baln,
419  gnc_account_print_info (lv->account, TRUE));
420  gtk_list_store_set(store, &iter, LOT_COL_BALN, baln_buff, -1);
421  gtk_list_store_set(store, &iter, LOT_COL_BALN_DOUBLE, gnc_numeric_to_double (amt_baln), -1);
422 
423  /* Capital Gains/Losses Appreciation/Depreciation */
424  xaccSPrintAmount (gain_buff, gains_baln,
425  gnc_commodity_print_info (currency, TRUE));
426  gtk_list_store_set(store, &iter, LOT_COL_GAINS, gain_buff, -1);
427  gtk_list_store_set(store, &iter, LOT_COL_GAINS_DOUBLE, gnc_numeric_to_double (gains_baln), -1);
428 
429  /* Self-reference */
430  gtk_list_store_set(store, &iter, LOT_COL_PNTR, lot, -1);
431  }
432  g_list_free(lot_list);
433 
434  /* re-select the row that the user had previously selected,
435  * if possible. */
436  if (selected_lot)
437  {
438  model = GTK_TREE_MODEL(lv->lot_store);
439  if (gtk_tree_model_get_iter_first(model, &iter))
440  {
441  do
442  {
443  gtk_tree_model_get(model, &iter, LOT_COL_PNTR, &this_lot, -1);
444  if (this_lot == selected_lot)
445  {
446  gtk_tree_selection_select_iter(selection, &iter);
447  found = TRUE;
448  break;
449  }
450  }
451  while (gtk_tree_model_iter_next(model, &iter));
452  }
453  }
454 
455  if (!found)
456  gtk_tree_selection_unselect_all(selection);
457 }
458 
459 /* ======================================================================== */
460 /* Get selected split in a split list view */
461 
462 static Split *
463 lv_get_selected_split (GNCLotViewer *lv, GtkTreeView *view)
464 {
465  Split *split = NULL;
466  GtkTreeModel *model;
467  GtkTreeSelection *selection;
468  GtkTreeIter iter;
469 
470  selection = gtk_tree_view_get_selection(view);
471  if (gtk_tree_selection_get_selected (selection, &model, &iter))
472  {
473  gtk_tree_model_get(model, &iter, SPLIT_COL_PNTR, &split, -1);
474  }
475 
476  return split;
477 }
478 
479 /* ======================================================================== */
480 /* Check if split is main invoice split in lot */
481 
482 static gboolean
483 lv_can_remove_split_from_lot(Split * split, GNCLot * lot)
484 {
485  GncInvoice *lot_invoice, *txn_invoice;
486  Transaction *txn;
487 
488  lot_invoice = gncInvoiceGetInvoiceFromLot(lot);
489  txn = xaccSplitGetParent(split);
490  txn_invoice = gncInvoiceGetInvoiceFromTxn(txn);
491  if ( lot_invoice != NULL && lot_invoice == txn_invoice )
492  return FALSE;
493 
494  return TRUE;
495 }
496 
497 /* ======================================================================== */
498 /* Populate a split list view */
499 
500 static void
501 gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_list)
502 {
503  SplitList *node;
504  GtkTreeIter iter;
505  gboolean is_business_lot = FALSE;
506  gnc_numeric baln = gnc_numeric_zero();
507 
508  if (lv->selected_lot)
509  is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (gnc_lot_get_account (lv->selected_lot)));
510 
511  gtk_list_store_clear (lv->split_in_lot_store);
512  for (node = split_list; node; node = node->next)
513  {
514  Split *split = node->data;
515  char amtbuff[200];
516  char valbuff[200];
517  char gainbuff[200];
518  char balnbuff[200];
519  gnc_commodity *currency;
520  Transaction *trans = xaccSplitGetParent (split);
521  time64 date = xaccTransGetDate (trans);
522  gnc_numeric amnt, value, gains;
523 
524  /* Do not show gains splits, however do show empty business splits */
525  if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount(split))) continue;
526 
527  gtk_list_store_append(store, &iter);
528 
529  /* Date */
530  gtk_list_store_set (store, &iter, SPLIT_COL_DATE, date, -1);
531 
532  /* Num - retrieve number based on book option */
533  gtk_list_store_set (store, &iter, SPLIT_COL_NUM,
534  gnc_get_num_action (trans, split), -1);
535 
536  /* Description */
537  gtk_list_store_set (store, &iter, SPLIT_COL_DESCRIPTION, xaccTransGetDescription (trans), -1);
538 
539  /* Amount */
540  amnt = xaccSplitGetAmount (split);
541  xaccSPrintAmount (amtbuff, amnt,
542  gnc_account_print_info (lv->account, TRUE));
543  gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT, amtbuff, -1);
544  gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT_DOUBLE, gnc_numeric_to_double (amnt), -1);
545 
546  /* Value.
547  * For non-business accounts which are part of a lot,
548  * invert the sign on the first. */
549  currency = xaccTransGetCurrency (trans);
550  value = xaccSplitGetValue (split);
551  if (lv->selected_lot && !is_business_lot && (node != split_list))
552  value = gnc_numeric_neg (value);
553  xaccSPrintAmount (valbuff, value,
554  gnc_commodity_print_info (currency, TRUE));
555  gtk_list_store_set (store, &iter, SPLIT_COL_VALUE, valbuff, -1);
556  gtk_list_store_set (store, &iter, SPLIT_COL_VALUE_DOUBLE, gnc_numeric_to_double (value), -1);
557 
558  /* Gains. Blank if none. */
559  gains = xaccSplitGetCapGains (split);
560  if (gnc_numeric_zero_p(gains))
561  {
562  gainbuff[0] = 0;
563  }
564  else
565  {
566  xaccSPrintAmount (gainbuff, gains,
567  gnc_commodity_print_info (currency, TRUE));
568  }
569  gtk_list_store_set (store, &iter, SPLIT_COL_GAIN_LOSS, gainbuff, -1);
570  gtk_list_store_set (store, &iter, SPLIT_COL_GAIN_LOSS_DOUBLE, gnc_numeric_to_double (gains), -1);
571 
572  /* Balance of Gains */
573  baln = gnc_numeric_add_fixed (baln, amnt);
574  if (gnc_numeric_zero_p(baln))
575  {
576  balnbuff[0] = 0;
577  }
578  else
579  {
580  xaccSPrintAmount (balnbuff, baln,
581  gnc_account_print_info (lv->account, TRUE));
582  }
583  gtk_list_store_set (store, &iter, SPLIT_COL_BALANCE, balnbuff, -1);
584  gtk_list_store_set (store, &iter, SPLIT_COL_BALANCE_DOUBLE, gnc_numeric_to_double (baln), -1);
585 
586  /* Self-reference */
587  gtk_list_store_set(store, &iter, SPLIT_COL_PNTR, split, -1);
588  }
589 }
590 
591 /* ======================================================================== */
592 
593 static void
594 lv_update_split_buttons(GNCLotViewer *lv)
595 {
596  Split * split;
597  gtk_widget_set_sensitive(GTK_WIDGET(lv->add_split_to_lot_button), FALSE);
598  gtk_widget_set_sensitive(GTK_WIDGET(lv->remove_split_from_lot_button), FALSE);
599  if (NULL != lv->selected_lot)
600  {
601  if (NULL != lv_get_selected_split(lv, lv->split_free_view) )
602  {
603  gtk_widget_set_sensitive(GTK_WIDGET(lv->add_split_to_lot_button), TRUE);
604  }
605  split = lv_get_selected_split(lv, lv->split_in_lot_view);
606  if (NULL != split && TRUE == lv_can_remove_split_from_lot(split, lv->selected_lot))
607  {
608  gtk_widget_set_sensitive(GTK_WIDGET(lv->remove_split_from_lot_button), TRUE);
609  }
610  }
611 }
612 
613 static void lv_refresh(GNCLotViewer * lv)
614 {
615  gnc_lot_viewer_fill (lv);
616  lv_show_splits_free (lv);
617  lv_show_splits_in_lot (lv);
618 }
619 
620 /* ======================================================================== */
621 
622 static void
623 lv_refresh_handler (GHashTable *changes, gpointer user_data)
624 {
625  GNCLotViewer *lv = user_data;
626  lv_refresh (lv);
627 }
628 
629 static void
630 lv_close_handler (gpointer user_data)
631 {
632  GNCLotViewer *lv = user_data;
633 
634  lv_save_current_lot (lv);
635 
636  gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(lv->window));
637  gtk_widget_destroy (lv->window);
638 }
639 
640 /* =========================== Callbacks ============================ */
641 /* ======================================================================== */
642 /* The lot title in the entry widget changed */
643 
644 void
645 lv_title_entry_changed_cb (GtkEntry *ent, gpointer user_data)
646 {
647  GNCLotViewer *lv = user_data;
648  GtkTreeModel *model;
649  GtkTreeIter iter;
650  GtkTreeSelection *selection;
651  const char * title;
652  title = gtk_entry_get_text (lv->title_entry);
653 
654  selection = gtk_tree_view_get_selection(lv->lot_view);
655  if (gtk_tree_selection_get_selected (selection, &model, &iter))
656  {
657  gtk_list_store_set(GTK_LIST_STORE(model), &iter, LOT_COL_TITLE, title, -1);
658  }
659 }
660 
661 /* ======================================================================== */
662 /* Selection in the lot list view changed */
663 
664 static void
665 lv_selection_changed_cb (GtkTreeSelection *selection,
666  GNCLotViewer *lv)
667 {
668  GNCLot *lot;
669  GtkTreeModel *model;
670  GtkTreeIter iter;
671 
672  if (gtk_tree_selection_get_selected (selection, &model, &iter))
673  {
674  gtk_tree_model_get(model, &iter, LOT_COL_PNTR, &lot, -1);
675  lv_select_row(lv, lot);
676  }
677  else
678  {
679  lv_unselect_row(lv);
680  }
681  lv_update_split_buttons(lv);
682 }
683 
684 /* ======================================================================== */
685 /* Lot viewer window closed */
686 
687 void
688 lv_window_destroy_cb (GtkWidget *object, gpointer user_data)
689 {
690  GNCLotViewer *lv = user_data;
691  gnc_unregister_gui_component_by_data (LOT_VIEWER_CM_CLASS, lv);
692  g_free (lv);
693 }
694 
695 static void
696 lv_split_selection_changed_cb (GtkTreeSelection *selection,
697  GNCLotViewer *lv)
698 {
699  lv_update_split_buttons(lv);
700 }
701 
702 static void
703 lv_add_split_to_lot_cb (GtkWidget *widget, GNCLotViewer * lv)
704 {
705  Split *split;
706 
707  if ( NULL == lv->selected_lot ) return;
708  split = lv_get_selected_split(lv, lv->split_free_view);
709  if ( NULL == split ) return;
710 
711  gnc_suspend_gui_refresh();
712  xaccAccountBeginEdit(lv->account);
713  gnc_lot_add_split(lv->selected_lot, split);
714  xaccAccountCommitEdit(lv->account);
715  gnc_resume_gui_refresh();
716 
717  lv_refresh(lv);
718 }
719 
720 static void
721 lv_remove_split_from_lot_cb (GtkWidget *widget, GNCLotViewer * lv)
722 {
723  Split *split;
724 
725  if ( NULL == lv->selected_lot ) return;
726  split = lv_get_selected_split(lv, lv->split_in_lot_view);
727  if ( NULL == split ) return;
728 
729  if ( FALSE == lv_can_remove_split_from_lot(split, lv->selected_lot) )
730  return;
731 
732  gnc_suspend_gui_refresh();
733  xaccAccountBeginEdit(lv->account);
734  gnc_lot_remove_split(lv->selected_lot, split);
735  xaccAccountCommitEdit(lv->account);
736  gnc_resume_gui_refresh();
737 
738  lv_refresh(lv);
739 }
740 
741 static void
742 lv_only_show_open_lots_changed_cb (GtkWidget *widget, GNCLotViewer * lv)
743 {
744  lv_refresh(lv);
745 }
746 
747 /* ======================================================================== */
748 /* Any button was pressed */
749 
750 void
751 lv_response_cb (GtkDialog *dialog, gint response, gpointer data)
752 {
753  GNCLotViewer *lv = data;
754  GNCLot *lot = lv->selected_lot;
755 
756  switch (response)
757  {
758  case GTK_RESPONSE_CLOSE:
759  gnc_close_gui_component_by_data (LOT_VIEWER_CM_CLASS, lv);
760  return;
761 
762  case RESPONSE_VIEW:
763  if (NULL == lot)
764  return;
765  printf ("UNIMPLEMENTED: need to display register showing only this one lot.\n");
766  break;
767 
768  case RESPONSE_DELETE:
769  if (NULL == lot)
770  return;
771  /* Prevent broken invoices */
772  if (NULL != gncInvoiceGetInvoiceFromLot(lot))
773  return;
774  xaccAccountRemoveLot (gnc_lot_get_account(lot), lot);
775  gnc_lot_destroy (lot);
776  lv_unset_lot (lv);
777  gnc_lot_viewer_fill (lv);
778  break;
779 
780  case RESPONSE_SCRUB_LOT:
781  if (NULL == lot)
782  return;
783  if (xaccAccountIsAPARType (xaccAccountGetType(lv->account)))
784  gncScrubBusinessLot (lot);
785  else
786  xaccScrubLot (lot);
787  gnc_lot_viewer_fill (lv);
788  lv_show_splits_in_lot (lv);
789  break;
790 
791  case RESPONSE_SCRUB_ACCOUNT:
792  gnc_suspend_gui_refresh ();
793  if (xaccAccountIsAPARType (xaccAccountGetType(lv->account)))
794  gncScrubBusinessAccountLots (lv->account, gnc_window_show_progress);
795  else
796  xaccAccountScrubLots (lv->account);
797  gnc_resume_gui_refresh ();
798  gnc_lot_viewer_fill (lv);
799  lv_show_splits_free (lv);
800  lv_show_splits_in_lot (lv);
801  break;
802 
803  case RESPONSE_NEW_LOT:
804  lv_save_current_lot (lv);
805  lot = gnc_lot_make_default (lv->account);
806  xaccAccountInsertLot (lv->account, lot);
807  break;
808  }
809 }
810 
811 /* ======================================================================== */
812 
813 static gchar* lot_get_open_date (GNCLot *lot)
814 {
815  g_return_val_if_fail (lot, NULL);
816 
817  if (!gnc_lot_get_split_list (lot))
818  return g_strdup (_("Empty"));
819  else
821 }
822 
823 static gchar* lot_get_closing_date (GNCLot *lot)
824 {
825  g_return_val_if_fail (lot, NULL);
826 
827  if (!gnc_lot_get_split_list (lot))
828  return NULL;
829  else if (!gnc_lot_is_closed (lot))
830  return g_strdup (C_("Adjective", "Open"));
831  else
833 }
834 
835 typedef gchar* (*LotToDateFunc) (GNCLot *lot);
836 
837 static void lot_print_date (GtkTreeViewColumn *tree_column,
838  GtkCellRenderer *cell,
839  GtkTreeModel *tree_model,
840  GtkTreeIter *iter,
841  LotToDateFunc lot_to_date)
842 {
843  GNCLot *lot;
844  gchar *str = NULL;
845 
846  g_return_if_fail (cell && iter && tree_model);
847  gtk_tree_model_get (tree_model, iter, LOT_COL_PNTR, &lot, -1);
848 
849  if (lot)
850  str = lot_to_date (lot);
851 
852  g_object_set (G_OBJECT (cell), "text", str, NULL);
853  g_free (str);
854 }
855 
856 static void print_date (GtkTreeViewColumn *tree_column,
857  GtkCellRenderer *cell,
858  GtkTreeModel *tree_model,
859  GtkTreeIter *iter,
860  gpointer data)
861 {
862  time64 doc_date_time;
863  gchar *doc_date_str;
864  gint col = GPOINTER_TO_INT(data);
865 
866  g_return_if_fail (cell && iter && tree_model);
867 
868  gtk_tree_model_get (tree_model, iter, col, &doc_date_time, -1);
869 
870  doc_date_str = qof_print_date (doc_date_time);
871  g_object_set (G_OBJECT (cell), "text", doc_date_str, NULL);
872  g_free (doc_date_str);
873 }
874 
875 static void
876 configure_number_columns (GtkTreeViewColumn *column,
877  GtkCellRenderer *renderer, gint sort_column)
878 {
879  gtk_tree_view_column_set_sort_column_id (column, sort_column);
880  gtk_cell_renderer_set_alignment (renderer, 1.0, 0.5); // right align amount column
881  gtk_tree_view_column_set_alignment (column, 1.0);
882  gtk_cell_renderer_set_padding (renderer, 5, 0); // add padding so its not close to edge
883 }
884 
885 static void
886 lv_init_lot_view (GNCLotViewer *lv)
887 {
888  GtkTreeView *view;
889  GtkListStore *store;
890  GtkTreeViewColumn *column;
891  GtkTreeSelection *selection;
892  GtkCellRenderer *renderer;
893 
894  g_return_if_fail(GTK_IS_TREE_VIEW(lv->lot_view));
895 
896  view = lv->lot_view;
897  store = gtk_list_store_new(NUM_LOT_COLS, G_TYPE_STRING, G_TYPE_INT64,
898  G_TYPE_INT64, G_TYPE_STRING,
899  G_TYPE_STRING, G_TYPE_DOUBLE,
900  G_TYPE_STRING,G_TYPE_DOUBLE,
901  G_TYPE_POINTER);
902  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
903  g_object_unref(store);
904  lv->lot_store = store;
905 
906  /* Set up the columns */
907  renderer = gtk_cell_renderer_text_new();
908  column = gtk_tree_view_column_new_with_attributes(_("Type"), renderer,
909  "text", LOT_COL_TYPE, NULL);
910  gtk_tree_view_column_set_sort_column_id(column, LOT_COL_TYPE);
911  gtk_tree_view_append_column(view, column);
912 
913  renderer = gtk_cell_renderer_text_new();
914  column = gtk_tree_view_column_new_with_attributes(_("Opened"), renderer,
915  "text", LOT_COL_OPEN, NULL);
916  gtk_tree_view_column_set_sort_column_id(column, LOT_COL_OPEN);
917  tree_view_column_set_default_width (view, column, "31-12-2013");
918  gtk_tree_view_column_set_cell_data_func (column, renderer,
919  (GtkTreeCellDataFunc) lot_print_date,
920  lot_get_open_date, NULL);
921  gtk_tree_view_append_column(view, column);
922 
923  renderer = gtk_cell_renderer_text_new();
924  column = gtk_tree_view_column_new_with_attributes(_("Closed"), renderer,
925  "text", LOT_COL_CLOSE, NULL);
926  gtk_tree_view_column_set_sort_column_id(column, LOT_COL_CLOSE);
927  tree_view_column_set_default_width (view, column, "31-12-2013");
928  gtk_tree_view_column_set_cell_data_func (column, renderer,
929  (GtkTreeCellDataFunc) lot_print_date,
930  lot_get_closing_date, NULL);
931  gtk_tree_view_append_column(view, column);
932 
933  renderer = gtk_cell_renderer_text_new();
934  column = gtk_tree_view_column_new_with_attributes(_("Title"), renderer,
935  "text", LOT_COL_TITLE, NULL);
936  gtk_tree_view_column_set_sort_column_id(column, LOT_COL_TITLE);
937  gtk_tree_view_column_set_expand (column, TRUE);
938  gtk_tree_view_append_column(view, column);
939 
940  renderer = gtk_cell_renderer_text_new();
941  column = gtk_tree_view_column_new_with_attributes(_("Balance"), renderer,
942  "text", LOT_COL_BALN, NULL);
943  configure_number_columns (column, renderer, LOT_COL_BALN_DOUBLE);
944  gtk_tree_view_append_column(view, column);
945 
946  renderer = gtk_cell_renderer_text_new();
947  column = gtk_tree_view_column_new_with_attributes(_("Gains"), renderer,
948  "text", LOT_COL_GAINS, NULL);
949  configure_number_columns (column, renderer, LOT_COL_GAINS_DOUBLE);
950  gtk_tree_view_append_column(view, column);
951 
952  /* Set up signals */
953  selection = gtk_tree_view_get_selection(view);
954  g_signal_connect(selection, "changed",
955  G_CALLBACK(lv_selection_changed_cb), lv);
956  g_signal_connect(lv->only_show_open_lots_checkbutton, "toggled",
957  G_CALLBACK(lv_only_show_open_lots_changed_cb), lv);
958 
959 }
960 
961 /* ======================================================================== */
962 
963 static GtkListStore *
964 lv_init_split_view (GNCLotViewer *lv, GtkTreeView *view)
965 {
966  GtkListStore *store;
967  GtkTreeViewColumn *column;
968  GtkTreeSelection *selection;
969  GtkCellRenderer *renderer;
970 
971  g_return_val_if_fail(GTK_IS_TREE_VIEW(view), NULL);
972 
973  store = gtk_list_store_new(NUM_SPLIT_COLS, G_TYPE_INT64,
974  G_TYPE_STRING, G_TYPE_STRING,
975  G_TYPE_STRING, G_TYPE_DOUBLE,
976  G_TYPE_STRING, G_TYPE_DOUBLE,
977  G_TYPE_STRING, G_TYPE_DOUBLE,
978  G_TYPE_STRING, G_TYPE_DOUBLE,
979  G_TYPE_POINTER);
980  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
981  g_object_unref(store);
982 
983  /* Set up the columns */
984  renderer = gtk_cell_renderer_text_new();
985  column = gtk_tree_view_column_new_with_attributes(_("Date"), renderer,
986  "text", SPLIT_COL_DATE, NULL);
987  gtk_tree_view_column_set_sort_column_id(column, SPLIT_COL_DATE);
988  tree_view_column_set_default_width (view, column, "31-12-2013");
989  gtk_tree_view_column_set_cell_data_func (column, renderer,
990  (GtkTreeCellDataFunc) print_date,
991  GINT_TO_POINTER (SPLIT_COL_DATE), NULL);
992  gtk_tree_view_append_column(view, column);
993 
994  renderer = gtk_cell_renderer_text_new();
995  column = gtk_tree_view_column_new_with_attributes(_("Num"), renderer,
996  "text", SPLIT_COL_NUM, NULL);
997  gtk_tree_view_column_set_sort_column_id(column, SPLIT_COL_NUM);
998  gtk_tree_view_append_column(view, column);
999 
1000  renderer = gtk_cell_renderer_text_new();
1001  column = gtk_tree_view_column_new_with_attributes(_("Description"), renderer,
1002  "text", SPLIT_COL_DESCRIPTION, NULL);
1003 
1004  g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1005  /* as this column is the expander column, if ellipsize is set, the column
1006  width would be small, so set a minimum width */
1007  gtk_tree_view_column_set_min_width (column, 200);
1008 
1009  gtk_tree_view_column_set_sort_column_id(column, SPLIT_COL_DESCRIPTION);
1010  gtk_tree_view_column_set_expand (column, TRUE);
1011  gtk_tree_view_column_set_resizable (column, TRUE);
1012  gtk_tree_view_append_column(view, column);
1013 
1014  renderer = gtk_cell_renderer_text_new();
1015  column = gtk_tree_view_column_new_with_attributes(_("Amount"), renderer,
1016  "text", SPLIT_COL_AMOUNT, NULL);
1017  configure_number_columns (column, renderer, SPLIT_COL_AMOUNT_DOUBLE);
1018  gtk_tree_view_append_column(view, column);
1019 
1020  renderer = gtk_cell_renderer_text_new();
1021  column = gtk_tree_view_column_new_with_attributes(_("Value"), renderer,
1022  "text", SPLIT_COL_VALUE, NULL);
1023  configure_number_columns (column, renderer, SPLIT_COL_VALUE_DOUBLE);
1024  gtk_tree_view_append_column(view, column);
1025 
1026  renderer = gtk_cell_renderer_text_new();
1027  column = gtk_tree_view_column_new_with_attributes(_("Gain/Loss"), renderer,
1028  "text", SPLIT_COL_GAIN_LOSS, NULL);
1029  configure_number_columns (column, renderer, SPLIT_COL_GAIN_LOSS_DOUBLE);
1030  gtk_tree_view_append_column(view, column);
1031 
1032  renderer = gtk_cell_renderer_text_new();
1033  column = gtk_tree_view_column_new_with_attributes(_("Balance"), renderer,
1034  "text", SPLIT_COL_BALANCE, NULL);
1035  configure_number_columns (column, renderer, SPLIT_COL_BALANCE_DOUBLE);
1036  gtk_tree_view_append_column(view, column);
1037 
1038  /* Set up the selection callbacks */
1039  selection = gtk_tree_view_get_selection(view);
1040  g_signal_connect(selection, "changed",
1041  G_CALLBACK(lv_split_selection_changed_cb), lv);
1042 
1043  return store;
1044 }
1045 
1046 static void
1047 lv_init_split_views (GNCLotViewer *lv)
1048 {
1049  lv->split_free_store = lv_init_split_view (lv, lv->split_free_view);
1050  lv->split_in_lot_store = lv_init_split_view (lv, lv->split_in_lot_view);
1051 }
1052 
1053 static void
1054 lv_init_split_buttons (GNCLotViewer *lv)
1055 {
1056  /* Set up the add/remove callbacks */
1057  g_signal_connect(G_OBJECT(lv->add_split_to_lot_button), "clicked",
1058  G_CALLBACK(lv_add_split_to_lot_cb), lv);
1059  g_signal_connect(G_OBJECT(lv->remove_split_from_lot_button), "clicked",
1060  G_CALLBACK(lv_remove_split_from_lot_cb), lv);
1061 }
1062 
1063 /* ======================================================================== */
1064 
1065 static void
1066 window_realize_set_split_paned_position_cb (GtkWidget *widget, gpointer user_data)
1067 {
1068  GNCLotViewer *lv = user_data;
1069  gint width;
1070 
1071  gtk_window_get_size (GTK_WINDOW(lv->window), &width, NULL);
1072  gtk_paned_set_position (GTK_PANED(lv->split_hpaned), width / 2);
1073 }
1074 
1075 static void
1076 lv_create (GNCLotViewer *lv, GtkWindow *parent)
1077 {
1078  gchar *win_title;
1079  GtkBuilder *builder;
1080 
1081  builder = gtk_builder_new();
1082  gnc_builder_add_from_file (builder, "dialog-lot-viewer.glade", "lot_viewer_dialog");
1083 
1084  lv->window = GTK_WIDGET(gtk_builder_get_object (builder, "lot_viewer_dialog"));
1085 
1086  gtk_window_set_transient_for (GTK_WINDOW (lv->window), parent);
1087 
1088  // Set the name for this dialog so it can be easily manipulated with css
1089  gtk_widget_set_name (GTK_WIDGET(lv->window), "gnc-id-lot-viewer");
1090 
1091  win_title = g_strdup_printf (_("Lots in Account %s"),
1092  xaccAccountGetName(lv->account));
1093  gtk_window_set_title (GTK_WINDOW (lv->window), win_title);
1094  g_free (win_title);
1095 
1096 #ifdef LOTS_READY_FOR_SHOWTIME
1097  lv->regview_button = GTK_BUTTON(glade_xml_get_widget (builder, "regview_button"));
1098 #endif
1099  lv->delete_button = GTK_BUTTON(gtk_builder_get_object (builder, "delete_button"));
1100  lv->scrub_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "scrub_lot_button"));
1101  lv->new_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "new_lot_button"));
1102 
1103  lv->lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "lot_view"));
1104  lv->only_show_open_lots_checkbutton = GTK_TOGGLE_BUTTON(gtk_builder_get_object (builder, "only_show_open_lots_checkbutton"));
1105  lv_init_lot_view(lv);
1106  lv->lot_notes = GTK_TEXT_VIEW(gtk_builder_get_object (builder, "lot_notes_text"));
1107  lv->title_entry = GTK_ENTRY (gtk_builder_get_object (builder, "lot_title_entry"));
1108 
1109  lv->split_in_lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "split_in_lot_view"));
1110  lv->split_free_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "split_free_view"));
1111  lv->split_hpaned = GTK_WIDGET(gtk_builder_get_object (builder, "split_hpaned"));
1112  lv_init_split_views(lv);
1113 
1114  lv->add_split_to_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "add_split_to_lot_button"));
1115  lv->remove_split_from_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "remove_split_from_lot_button"));
1116  lv_init_split_buttons(lv);
1117 
1118  // Set grid lines option to preference
1119  gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(lv->lot_view), gnc_tree_view_get_grid_lines_pref ());
1120 
1121  // Set grid lines option to preference
1122  gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(lv->split_in_lot_view), gnc_tree_view_get_grid_lines_pref ());
1123 
1124  // Set grid lines option to preference
1125  gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(lv->split_free_view), gnc_tree_view_get_grid_lines_pref ());
1126 
1127 
1128  if (gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_SAVE_GEOMETRY))
1129  {
1130  GObject *object;
1131  object = gtk_builder_get_object (builder, "lot_vpaned");
1132  gnc_prefs_bind (GNC_PREFS_GROUP, GNC_PREF_VPOS, NULL, object, "position");
1133 
1134  object = gtk_builder_get_object (builder, "lot_hpaned");
1135  gnc_prefs_bind (GNC_PREFS_GROUP, GNC_PREF_HPOS, NULL, object, "position");
1136  }
1137 
1138  lv->selected_lot = NULL;
1139 
1140  /* set the split paned position to be halfway at the start */
1141  g_signal_connect (G_OBJECT(lv->window), "realize",
1142  G_CALLBACK(window_realize_set_split_paned_position_cb), lv);
1143 
1144  /* Setup signals */
1145  gtk_builder_connect_signals(builder, lv);
1146  g_object_unref(G_OBJECT(builder));
1147 
1148  lv_update_split_buttons(lv);
1149 
1150  gnc_restore_window_size(GNC_PREFS_GROUP, GTK_WINDOW(lv->window), parent);
1151 }
1152 
1153 /* ======================================================================== */
1154 
1155 GNCLotViewer *
1156 gnc_lot_viewer_dialog (GtkWindow *parent, Account *account)
1157 {
1158  GNCLotViewer *lv;
1159  gint component_id;
1160 
1161  if (!account) return NULL;
1162 
1163  lv = g_new0 (GNCLotViewer, 1);
1164  lv->account = account;
1165  lv_create (lv, parent);
1166  gnc_lot_viewer_fill (lv);
1167  lv_show_splits_free (lv);
1168 
1169  component_id = gnc_register_gui_component (LOT_VIEWER_CM_CLASS,
1170  lv_refresh_handler,
1171  lv_close_handler,
1172  lv);
1173 
1174  gnc_gui_component_watch_entity_type (component_id,
1175  GNC_ID_LOT,
1176  QOF_EVENT_CREATE | QOF_EVENT_ADD | QOF_EVENT_REMOVE | QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
1177 
1178  gtk_widget_show_all (lv->window);
1179  gnc_window_adjust_for_screen (GTK_WINDOW(lv->window));
1180 
1181  return lv;
1182 }
1183 
1184 /* ============================ END OF FILE =============================== */
High-Level API for imposing Lot constraints.
void tree_view_column_set_default_width(GtkTreeView *view, GtkTreeViewColumn *column, const gchar *sizing_text)
Set default width for a treeview column.
GList LotList
GList of GNCLots.
Definition: gnc-engine.h:205
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
SplitList * xaccAccountGetSplitList(const Account *acc)
The xaccAccountGetSplitList() routine returns a pointer to a GList of the splits in the account...
Definition: Account.cpp:3905
utility functions for the GnuCash UI
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3237
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value...
STRUCTS.
All arguments are required to have the same denominator, that denominator is to be used in the output...
Definition: gnc-numeric.h:206
Functions that are supported by all types of windows.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
void gnc_lot_add_split(GNCLot *lot, Split *split)
Adds a split to this lot.
Definition: gnc-lot.cpp:594
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
void xaccAccountInsertLot(Account *acc, GNCLot *lot)
The xaccAccountInsertLot() method will register the indicated lot with this account.
Definition: Account.cpp:2142
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
gnc_numeric xaccSplitGetCapGains(Split *split)
The xaccSplitGetCapGains() method returns the value of capital gains (if any) associated with the ind...
Definition: cap-gains.cpp:900
void xaccAccountScrubLots(Account *acc)
The xaccAccountScrubLots() routine makes sure that every split in the account is assigned to a lot...
Definition: Scrub3.cpp:159
Cleanup functions for business objects.
Split * gnc_lot_get_earliest_split(GNCLot *lot)
Convenience routine to identify the earliest date in the lot.
Definition: gnc-lot.cpp:673
void gncScrubBusinessAccountLots(Account *acc, QofPercentageFunc percentagefunc)
The gncScrubBusinessAccountLots() function will call gncScrubBusinessLot() on each lot in the given a...
GncInvoice * gncInvoiceGetInvoiceFromTxn(const Transaction *txn)
Given a transaction, find and return the Invoice.
Definition: gncInvoice.c:1326
Split * gnc_lot_get_latest_split(GNCLot *lot)
Convenience routineto identify the date this lot was closed.
Definition: gnc-lot.cpp:685
gdouble gnc_numeric_to_double(gnc_numeric n)
Convert numeric to floating-point value.
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
Definition: gnc-date.cpp:609
GList SplitList
GList of Split.
Definition: gnc-engine.h:207
Account handling public routines.
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Returns a list of all the splits in this lot.
Definition: gnc-lot.cpp:425
LotList * xaccAccountGetLotList(const Account *acc)
The xaccAccountGetLotList() routine returns a list of all lots in this account.
Definition: Account.cpp:3930
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition: gnc-lot.cpp:646
gboolean xaccAccountIsAPARType(GNCAccountType t)
Convenience function to check if the account is a valid business account type (meaning an Accounts Pa...
Definition: Account.cpp:4482
void gnc_prefs_bind(const gchar *group, const gchar *pref_name, const gchar *pref_value, gpointer object, const gchar *property)
Bind a setting to a g_object property.
Definition: gnc-prefs.c:181
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
Generic api to store and retrieve preferences.
GncInvoice * gncInvoiceGetInvoiceFromLot(GNCLot *lot)
Given a LOT, find and return the Invoice attached to the lot.
Definition: gncInvoice.c:1288
Business Invoice Interface.
GNCLot * gnc_lot_make_default(Account *acc)
Definition: gnc-lot.cpp:780
gboolean gnc_lot_is_closed(GNCLot *lot)
Returns closed status of the given lot.
Definition: gnc-lot.cpp:367
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:84
gboolean gncScrubBusinessLot(GNCLot *lot)
The gncScrubBusinessLot() function makes sure that the indicated lot has all the correct properties r...
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1477
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
gboolean xaccScrubLot(GNCLot *lot)
The xaccScrubLot() routine makes sure that the indicated lot is self-consistent and properly balanced...
Definition: Scrub3.cpp:85
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
Account * gnc_lot_get_account(const GNCLot *lot)
Returns the account with which this lot is associated.
Definition: gnc-lot.cpp:377
const char * xaccAccountGetName(const Account *acc)
Get the account&#39;s name.
Definition: Account.cpp:3259
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:245
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1518
Utilities to Automatically Compute Capital Gains/Losses.
Commodity handling public routines.
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Returns the lot balance.
Definition: gnc-lot.cpp:502
GNCLot * xaccSplitGetLot(const Split *split)
Returns the pointer to the debited/credited Lot where this split belongs to, or NULL if it doesn&#39;t be...
Definition: Split.cpp:1886
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69