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