GnuCash  5.6-150-g038405b370+
assistant-stock-split.c
1 /********************************************************************\
2  * assistant-stock-split.c -- stock split assistant for GnuCash *
3  * Copyright (C) 2001 Gnumatic, Inc. *
4  * Copyright (c) 2001 Dave Peticolas <dave@krondo.com> *
5  * Copyright (c) 2006 David Hampton <hampton@employees.org> *
6  * Copyright (C) 2011 Robert Fewell *
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License*
19  * along with this program; if not, contact: *
20  * *
21  * Free Software Foundation Voice: +1-617-542-5942 *
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
23  * Boston, MA 02110-1301, USA gnu@gnu.org *
24 \********************************************************************/
25 
26 #include <config.h>
27 
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30 
31 #include "Transaction.h"
32 #include "engine-helpers.h"
33 #include "dialog-utils.h"
34 #include "assistant-stock-split.h"
35 #include "gnc-amount-edit.h"
36 #include "gnc-component-manager.h"
37 #include "gnc-currency-edit.h"
38 #include "gnc-date-edit.h"
39 #include "qof.h"
40 #include "gnc-gui-query.h"
41 #include "gnc-tree-view-account.h"
42 #include "gnc-ui.h"
43 #include "gnc-ui-util.h"
44 
45 
46 #define ASSISTANT_STOCK_SPLIT_CM_CLASS "assistant-stock-split"
47 
48 enum split_cols
49 {
50  SPLIT_COL_ACCOUNT = 0,
51  SPLIT_COL_FULLNAME,
52  SPLIT_COL_MNEMONIC,
53  SPLIT_COL_SHARES,
54  NUM_SPLIT_COLS
55 };
56 
58 typedef struct
59 {
60  GtkWidget * window;
61  GtkWidget * assistant;
62 
63  /* account page data */
64  GtkWidget * account_view;
65  Account * acct;
66 
67  /* info page data */
68  GtkWidget * date_edit;
69  GtkWidget * distribution_edit;
70  GtkWidget * description_entry;
71  GtkWidget * price_edit;
72  GtkWidget * price_currency_edit;
73 
74  /* cash in lieu page data */
75  GtkWidget * cash_edit;
76  GtkWidget * memo_entry;
77  GtkWidget * income_tree;
78  GtkWidget * asset_tree;
80 
81 
83 void gnc_stock_split_assistant_window_destroy_cb (GtkWidget *object, gpointer user_data);
84 void gnc_stock_split_assistant_prepare (GtkAssistant *assistant,
85  GtkWidget *page,
86  gpointer user_data);
87 void gnc_stock_split_assistant_details_prepare (GtkAssistant *assistant,
88  gpointer user_data);
89 gboolean gnc_stock_split_assistant_details_complete (GtkAssistant *assistant,
90  gpointer user_data);
91 gboolean gnc_stock_split_assistant_cash_complete (GtkAssistant *assistant,
92  gpointer user_data);
93 void gnc_stock_split_assistant_finish (GtkAssistant *assistant,
94  gpointer user_data);
95 void gnc_stock_split_assistant_cancel (GtkAssistant *gtkassistant,
96  gpointer user_data);
97 
98 /******* implementations ***********************************************/
99 void
100 gnc_stock_split_assistant_window_destroy_cb (GtkWidget *object, gpointer user_data)
101 {
102  StockSplitInfo *info = user_data;
103 
104  gnc_unregister_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
105 
106  g_free (info);
107 }
108 
109 
110 static int
111 fill_account_list (StockSplitInfo *info, Account *selected_account)
112 {
113  GtkTreeRowReference *reference = NULL;
114  GtkTreeView *view;
115  GtkListStore *list;
116  GtkTreeIter iter;
117  GtkTreePath *path;
118  GList *accounts;
119  GList *node;
120  gint rows = 0;
121  gchar *full_name;
122 
123  view = GTK_TREE_VIEW(info->account_view);
124  list = GTK_LIST_STORE(gtk_tree_view_get_model(view));
125 
126  gtk_list_store_clear (list);
127 
128  accounts = gnc_account_get_descendants_sorted (gnc_get_current_root_account ());
129  for (node = accounts; node; node = node->next)
130  {
131  Account *account = node->data;
132  GNCPrintAmountInfo print_info;
133  const gnc_commodity *commodity;
134  gnc_numeric balance;
135 
136  if (!xaccAccountIsPriced(account))
137  continue;
138 
139  balance = xaccAccountGetBalance (account);
140  if (gnc_numeric_zero_p (balance))
141  continue;
142 
143  if (xaccAccountGetPlaceholder (account))
144  continue;
145 
146  commodity = xaccAccountGetCommodity (account);
147 
148  full_name = gnc_account_get_full_name (account);
149  print_info = gnc_account_print_info (account, FALSE);
150 
151  gtk_list_store_append(list, &iter);
152  gtk_list_store_set(list, &iter,
153  SPLIT_COL_ACCOUNT, account,
154  SPLIT_COL_FULLNAME, full_name,
155  SPLIT_COL_MNEMONIC, gnc_commodity_get_mnemonic(commodity),
156  SPLIT_COL_SHARES, xaccPrintAmount(balance, print_info),
157  -1);
158 
159  if (account == selected_account)
160  {
161  path = gtk_tree_model_get_path(GTK_TREE_MODEL(list), &iter);
162  reference = gtk_tree_row_reference_new(GTK_TREE_MODEL(list), path);
163  gtk_tree_path_free(path);
164  }
165 
166  g_free (full_name);
167 
168  rows++;
169  }
170  g_list_free(accounts);
171 
172  if (reference)
173  {
174  GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
175  path = gtk_tree_row_reference_get_path(reference);
176  gtk_tree_row_reference_free(reference);
177  if (path)
178  {
179  gtk_tree_selection_select_path(selection, path);
180  gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE, 0.5, 0.0);
181  gtk_tree_path_free(path);
182  }
183  }
184 
185  return rows;
186 }
187 
188 
189 static void
190 selection_changed_cb (GtkTreeSelection *selection,
191  gpointer user_data)
192 {
193  StockSplitInfo *info = user_data;
194  GtkTreeModel *list;
195  GtkTreeIter iter;
196 
197  if (!gtk_tree_selection_get_selected(selection, &list, &iter))
198  return;
199  gtk_tree_model_get(list, &iter,
200  SPLIT_COL_ACCOUNT, &info->acct,
201  -1);
202 }
203 
204 
205 static void
206 refresh_details_page (StockSplitInfo *info)
207 {
208  GNCPrintAmountInfo print_info;
209  gnc_commodity *commodity, *currency;
210  Account *account;
211  QofBook *book;
212  GNCPriceDB *db;
213  GList *prices;
214 
215  account = info->acct;
216 
217  g_return_if_fail (account != NULL);
218 
219  print_info = gnc_account_print_info (account, FALSE);
220 
221  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (info->distribution_edit),
222  print_info);
223  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (info->distribution_edit),
224  xaccAccountGetCommoditySCU (account));
225 
226  commodity = xaccAccountGetCommodity (account);
227  book = gnc_account_get_book (account);
228  db = gnc_pricedb_get_db(book);
229 
230  prices = gnc_pricedb_lookup_latest_any_currency(db, commodity);
231  if (prices)
232  {
233  /* Use the first existing price */
234  if (gnc_commodity_equiv (commodity, gnc_price_get_currency(prices->data)))
235  currency = gnc_price_get_commodity(prices->data);
236  else
237  currency = gnc_price_get_currency(prices->data);
238  }
239  else
240  {
241  /* Take a wild guess. */
242  currency = gnc_default_currency ();
243  }
244  gnc_price_list_destroy(prices);
245 
247  (GNC_CURRENCY_EDIT (info->price_currency_edit),
248  currency);
249 }
250 
251 
252 void gnc_stock_split_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
253  gpointer user_data)
254 {
255  gint currentpage = gtk_assistant_get_current_page(assistant);
256 
257  if (currentpage == 2) /* Current page is details page */
258  gnc_stock_split_assistant_details_prepare(assistant, user_data);
259 }
260 
261 
262 void
263 gnc_stock_split_assistant_details_prepare (GtkAssistant *assistant,
264  gpointer user_data)
265 {
266  StockSplitInfo *info = user_data;
267 
268  refresh_details_page(info);
269 }
270 
271 
272 gboolean
273 gnc_stock_split_assistant_details_complete (GtkAssistant *assistant,
274  gpointer user_data)
275 {
276  StockSplitInfo *info = user_data;
277  GNCPrintAmountInfo print_info;
278  gnc_commodity *currency;
279  gnc_numeric amount;
280  gint result;
281 
282  result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->distribution_edit),
283  &amount, TRUE, NULL);
284  if ( result != 0)
285  return FALSE; /* Parsing error or field is empty */
286 
287  if (gnc_numeric_zero_p (amount))
288  return FALSE; /* field value is 0 */
289 
290  currency = gnc_currency_edit_get_currency (GNC_CURRENCY_EDIT(info->price_currency_edit));
291  print_info = gnc_commodity_print_info (currency, FALSE);
292  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (info->price_edit), print_info);
293  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (info->price_edit), 0);
294 
295  result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(info->price_edit),
296  &amount, TRUE, NULL);
297  if (result == -1)
298  return TRUE; /* Optional field is empty */
299  else if ( result > 0)
300  return FALSE; /* Parsing error */
301  else if (gnc_numeric_negative_p (amount))
302  return FALSE; /* Negative price is not allowed */
303  else
304  return TRUE; /* Valid positive price */
305 }
306 
307 
308 gboolean
309 gnc_stock_split_assistant_cash_complete (GtkAssistant *assistant,
310  gpointer user_data)
311 {
312  StockSplitInfo *info = user_data;
313  gnc_numeric amount;
314  gint result;
315  Account *account;
316 
317  result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->cash_edit), &amount, TRUE, NULL);
318  if (result == -1)
319  return TRUE; /* Optional field is empty */
320  else if ( result > 0)
321  return FALSE; /* Parsing error */
322  else if (gnc_numeric_negative_p (amount))
323  return FALSE; /* Negative cash amount is not allowed */
324 
325  /* We have a positive cash amount */
326  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->income_tree));
327  if (!account)
328  return FALSE;
329 
330  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->asset_tree));
331  if (!account)
332  return FALSE;
333 
334  return TRUE;
335 }
336 
337 
338 void
339 gnc_stock_split_assistant_finish (GtkAssistant *assistant,
340  gpointer user_data)
341 {
342  StockSplitInfo *info = user_data;
343  GList *account_commits;
344  GList *node;
345 
346  gnc_numeric amount;
347  Transaction *trans;
348  Account *account;
349  Split *split;
350  time64 date;
351 
352  account = info->acct;
353  g_return_if_fail (account != NULL);
354 
355  amount = gnc_amount_edit_get_amount
356  (GNC_AMOUNT_EDIT (info->distribution_edit));
357  g_return_if_fail (!gnc_numeric_zero_p (amount));
358 
359  gnc_suspend_gui_refresh ();
360 
361  trans = xaccMallocTransaction (gnc_get_current_book ());
362 
363  xaccTransBeginEdit (trans);
364 
366 
367  date = gnc_date_edit_get_date (GNC_DATE_EDIT (info->date_edit));
369 
370  {
371  const char *description;
372 
373  description = gtk_entry_get_text (GTK_ENTRY (info->description_entry));
374  xaccTransSetDescription (trans, description);
375  }
376 
377  split = xaccMallocSplit (gnc_get_current_book ());
378 
379  xaccAccountBeginEdit (account);
380  account_commits = g_list_prepend (NULL, account);
381 
382  xaccTransAppendSplit (trans, split);
383 
384  xaccAccountInsertSplit (account, split);
385 
386  xaccSplitSetAmount (split, amount);
387  xaccSplitMakeStockSplit (split);
388  /* Set split-action with gnc_set_num_action which is the same as
389  * xaccSplitSetAction with these arguments */
390 
391  gnc_set_num_action (NULL, split, NULL, C_("Action Column", "Split"));
392 
393  amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (info->price_edit));
394  if (gnc_numeric_positive_p (amount))
395  {
396  QofBook *book;
397  GNCPrice *price;
398  GNCPriceDB *pdb;
399  GNCCurrencyEdit *ce;
400 
401  ce = GNC_CURRENCY_EDIT (info->price_currency_edit);
402  price = gnc_price_create (gnc_get_current_book ());
403 
404  gnc_price_begin_edit (price);
405  gnc_price_set_commodity (price, xaccAccountGetCommodity (account));
406  gnc_price_set_currency (price, gnc_currency_edit_get_currency (ce));
407  gnc_price_set_time64 (price, date);
408  gnc_price_set_source (price, PRICE_SOURCE_STOCK_SPLIT);
409  gnc_price_set_typestr (price, PRICE_TYPE_UNK);
410  gnc_price_set_value (price, amount);
411  gnc_price_commit_edit (price);
412 
413  book = gnc_get_current_book ();
414  pdb = gnc_pricedb_get_db (book);
415 
416  if (!gnc_pricedb_add_price (pdb, price))
417  gnc_error_dialog (GTK_WINDOW (info->window), "%s", _("Error adding price."));
418 
419  }
420 
421  amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (info->cash_edit));
422  if (gnc_numeric_positive_p (amount))
423  {
424  const char *memo;
425 
426  memo = gtk_entry_get_text (GTK_ENTRY (info->memo_entry));
427 
428  /* asset split */
429  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->asset_tree));
430 
431  split = xaccMallocSplit (gnc_get_current_book ());
432 
433  xaccAccountBeginEdit (account);
434  account_commits = g_list_prepend (account_commits, account);
435 
436  xaccAccountInsertSplit (account, split);
437 
438  xaccTransAppendSplit (trans, split);
439 
440  xaccSplitSetAmount (split, amount);
441  xaccSplitSetValue (split, amount);
442 
443  xaccSplitSetMemo (split, memo);
444 
445 
446  /* income split */
447  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->income_tree));
448 
449  split = xaccMallocSplit (gnc_get_current_book ());
450 
451  xaccAccountBeginEdit (account);
452  account_commits = g_list_prepend (account_commits, account);
453 
454  xaccAccountInsertSplit (account, split);
455 
456  xaccTransAppendSplit (trans, split);
457 
458  xaccSplitSetAmount (split, gnc_numeric_neg (amount));
459  xaccSplitSetValue (split, gnc_numeric_neg (amount));
460 
461  xaccSplitSetMemo (split, memo);
462  }
463 
464  xaccTransCommitEdit (trans);
465 
466  for (node = account_commits; node; node = node->next)
467  xaccAccountCommitEdit (node->data);
468  g_list_free (account_commits);
469 
470  gnc_resume_gui_refresh ();
471 
472  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
473 }
474 
475 
476 void
477 gnc_stock_split_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
478 {
479  StockSplitInfo *info = user_data;
480  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
481 }
482 
483 
484 static gboolean
485 gnc_stock_split_assistant_view_filter_income (Account *account,
486  gpointer data)
487 {
488  GNCAccountType type;
489 
490  type = xaccAccountGetType(account);
491  return (type == ACCT_TYPE_INCOME);
492 }
493 
494 
495 static gboolean
496 gnc_stock_split_assistant_view_filter_asset (Account *account,
497  gpointer data)
498 {
499  GNCAccountType type;
500 
501  type = xaccAccountGetType(account);
502  return ((type == ACCT_TYPE_BANK) || (type == ACCT_TYPE_CASH) ||
503  (type == ACCT_TYPE_ASSET));
504 }
505 
506 
507 static void
508 gnc_stock_split_details_valid_cb (GtkWidget *widget, gpointer user_data)
509 {
510  StockSplitInfo *info = user_data;
511  GtkAssistant *assistant = GTK_ASSISTANT(info->window);
512  gint num = gtk_assistant_get_current_page (assistant);
513  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
514 
515  gtk_assistant_set_page_complete (assistant, page,
516  gnc_stock_split_assistant_details_complete (assistant, user_data));
517 }
518 
519 
520 static void
521 gnc_stock_split_cash_valid_cb (GtkWidget *widget, gpointer user_data)
522 {
523  StockSplitInfo *info = user_data;
524  GtkAssistant *assistant = GTK_ASSISTANT(info->window);
525  gint num = gtk_assistant_get_current_page (assistant);
526  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
527 
528  gtk_assistant_set_page_complete (assistant, page,
529  gnc_stock_split_assistant_cash_complete (assistant, user_data));
530 }
531 
532 
533 static GtkWidget *
534 gnc_stock_split_assistant_create (StockSplitInfo *info)
535 {
536  GtkBuilder *builder;
537  GtkWidget *window;
538 
539  builder = gtk_builder_new();
540  gnc_builder_add_from_file (builder , "assistant-stock-split.glade", "stock_split_assistant");
541  window = GTK_WIDGET(gtk_builder_get_object (builder, "stock_split_assistant"));
542  info->window = window;
543 
544  // Set the name for this assistant so it can be easily manipulated with css
545  gtk_widget_set_name (GTK_WIDGET(window), "gnc-id-assistant-stock-split");
546 
547  /* Enable buttons on first, second, fourth and last page. */
548  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
549  GTK_WIDGET(gtk_builder_get_object(builder, "intro_page_label")),
550  TRUE);
551  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
552  GTK_WIDGET(gtk_builder_get_object(builder, "stock_account_page")),
553  TRUE);
554  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
555  GTK_WIDGET(gtk_builder_get_object(builder, "stock_cash_page")),
556  TRUE);
557  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
558  GTK_WIDGET(gtk_builder_get_object(builder, "finish_page_label")),
559  TRUE);
560 
561  /* Account page Widgets */
562  {
563  GtkTreeView *view;
564  GtkListStore *store;
565  GtkTreeSelection *selection;
566  GtkCellRenderer *renderer;
567  GtkTreeViewColumn *column;
568 
569  info->account_view = GTK_WIDGET(gtk_builder_get_object(builder, "account_view"));
570 
571  view = GTK_TREE_VIEW(info->account_view);
572 
573  // Set grid lines option to preference
574  gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(view), gnc_tree_view_get_grid_lines_pref ());
575 
576  store = gtk_list_store_new(NUM_SPLIT_COLS, G_TYPE_POINTER, G_TYPE_STRING,
577  G_TYPE_STRING, G_TYPE_STRING);
578  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
579  g_object_unref(store);
580 
581  renderer = gtk_cell_renderer_text_new();
582  column = gtk_tree_view_column_new_with_attributes(_("Account"), renderer,
583  "text", SPLIT_COL_FULLNAME,
584  NULL);
585  gtk_tree_view_append_column(view, column);
586 
587  renderer = gtk_cell_renderer_text_new();
588  column = gtk_tree_view_column_new_with_attributes(_("Symbol"), renderer,
589  "text", SPLIT_COL_MNEMONIC,
590  NULL);
591  gtk_tree_view_append_column(view, column);
592 
593  renderer = gtk_cell_renderer_text_new();
594  column = gtk_tree_view_column_new_with_attributes(_("Shares"), renderer,
595  "text", SPLIT_COL_SHARES,
596  NULL);
597  gtk_tree_view_append_column(view, column);
598 
599  selection = gtk_tree_view_get_selection(view);
600  gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
601  g_signal_connect (selection, "changed",
602  G_CALLBACK (selection_changed_cb), info);
603 
604  }
605 
606  /* Details Page Widgets */
607  {
608  GtkWidget *table;
609  GtkWidget *amount;
610  GtkWidget *date;
611  GtkWidget *label;
612 
613  table = GTK_WIDGET(gtk_builder_get_object(builder, "stock_details_table"));
614  info->description_entry = GTK_WIDGET(gtk_builder_get_object(builder, "description_entry"));
615 
616  date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
617  gtk_grid_attach (GTK_GRID(table), date, 1, 0, 1, 1);
618  gtk_widget_show (date);
619  info->date_edit = date;
620 
621  label = GTK_WIDGET(gtk_builder_get_object(builder, "date_label"));
622  gnc_date_make_mnemonic_target (GNC_DATE_EDIT(date), label);
623 
624  amount = gnc_amount_edit_new ();
625  g_signal_connect (amount, "changed",
626  G_CALLBACK (gnc_stock_split_details_valid_cb), info);
627  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
628  gtk_grid_attach (GTK_GRID(table), amount, 1, 1, 1, 1);
629  gtk_widget_show (amount);
630  info->distribution_edit = amount;
631 
632  label = GTK_WIDGET(gtk_builder_get_object(builder, "distribution_label"));
633  gnc_amount_edit_make_mnemonic_target (GNC_AMOUNT_EDIT(amount), label);
634 
635  amount = gnc_amount_edit_new ();
636  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (amount),
637  gnc_default_price_print_info (gnc_default_currency()));
638  g_signal_connect (amount, "changed",
639  G_CALLBACK (gnc_stock_split_details_valid_cb), info);
640  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
641  gtk_grid_attach (GTK_GRID(table), amount, 1, 5, 1, 1);
642  gtk_widget_show (amount);
643  info->price_edit = amount;
644 
645  label = GTK_WIDGET(gtk_builder_get_object(builder, "price_label"));
646  gnc_amount_edit_make_mnemonic_target (GNC_AMOUNT_EDIT(amount), label);
647 
648  info->price_currency_edit = gnc_currency_edit_new();
649  gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(info->price_currency_edit), gnc_default_currency());
650  gtk_widget_show (info->price_currency_edit);
651  gtk_grid_attach (GTK_GRID(table), info->price_currency_edit, 1, 6, 1, 1);
652  g_signal_connect (info->price_currency_edit, "changed",
653  G_CALLBACK (gnc_stock_split_details_valid_cb), info);
654  }
655 
656  /* Cash page Widgets */
657  {
658  GtkWidget *box;
659  GtkWidget *tree;
660  GtkWidget *amount;
661  GtkWidget *label;
662  GtkWidget *scroll;
663  GtkTreeSelection *selection;
664 
665  box = GTK_WIDGET(gtk_builder_get_object(builder, "cash_box"));
666  amount = gnc_amount_edit_new ();
667  g_signal_connect (amount, "changed",
668  G_CALLBACK (gnc_stock_split_cash_valid_cb), info);
669  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
670  gtk_box_pack_start (GTK_BOX (box), amount, TRUE, TRUE, 0);
671  info->cash_edit = amount;
672 
673  label = GTK_WIDGET(gtk_builder_get_object(builder, "cash_label"));
674  gtk_label_set_mnemonic_widget(GTK_LABEL(label), amount);
675 
676  info->memo_entry = GTK_WIDGET(gtk_builder_get_object(builder, "memo_entry"));
677 
678  /* income tree */
679  tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
680  info->income_tree = tree;
681  gnc_tree_view_account_set_filter (GNC_TREE_VIEW_ACCOUNT (tree),
682  gnc_stock_split_assistant_view_filter_income,
683  NULL, /* user data */
684  NULL /* destroy callback */);
685 
686  gtk_widget_show (tree);
687 
688  gtk_tree_view_expand_all (GTK_TREE_VIEW(tree));
689  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
690  gtk_tree_selection_unselect_all (selection);
691  g_signal_connect (selection, "changed",
692  G_CALLBACK (gnc_stock_split_cash_valid_cb), info);
693 
694  label = GTK_WIDGET(gtk_builder_get_object(builder, "income_label"));
695  gtk_label_set_mnemonic_widget (GTK_LABEL(label), tree);
696 
697  scroll = GTK_WIDGET(gtk_builder_get_object(builder, "income_scroll"));
698  gtk_container_add (GTK_CONTAINER (scroll), tree);
699 
700  /* asset tree */
701  tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
702  info->asset_tree = tree;
703  gnc_tree_view_account_set_filter (GNC_TREE_VIEW_ACCOUNT (tree),
704  gnc_stock_split_assistant_view_filter_asset,
705  NULL /* user data */,
706  NULL /* destroy callback */);
707 
708  gtk_widget_show (tree);
709 
710  label = GTK_WIDGET(gtk_builder_get_object(builder, "asset_label"));
711  gtk_label_set_mnemonic_widget (GTK_LABEL(label), tree);
712 
713  scroll = GTK_WIDGET(gtk_builder_get_object(builder, "asset_scroll"));
714  gtk_container_add (GTK_CONTAINER (scroll), tree);
715 
716  gtk_tree_view_expand_all (GTK_TREE_VIEW(tree));
717  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
718  gtk_tree_selection_unselect_all (selection);
719  g_signal_connect (selection, "changed",
720  G_CALLBACK (gnc_stock_split_cash_valid_cb), info);
721  }
722 
723  g_signal_connect (G_OBJECT(window), "destroy",
724  G_CALLBACK (gnc_stock_split_assistant_window_destroy_cb), info);
725 
726  gtk_builder_connect_signals(builder, info);
727  g_object_unref(G_OBJECT(builder));
728  return window;
729 
730 }
731 
732 static void
733 refresh_handler (GHashTable *changes, gpointer user_data)
734 {
735  StockSplitInfo *info = user_data;
736  Account *old_account;
737 
738  old_account = info->acct;
739 
740  if (fill_account_list (info, info->acct) == 0)
741  {
742  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
743  return;
744  }
745 
746  if (NULL == info->acct || old_account == info->acct) return;
747 }
748 
749 static void
750 close_handler (gpointer user_data)
751 {
752  StockSplitInfo *info = user_data;
753 
754  gtk_widget_destroy (info->window);
755 }
756 
757 /********************************************************************\
758  * gnc_stock_split_dialog *
759  * opens up a window to record a stock split *
760  * *
761  * Args: parent - the parent ofthis window *
762  * initial - the initial account to use *
763  * Return: nothing *
764 \********************************************************************/
765 void
766 gnc_stock_split_dialog (GtkWidget *parent, Account * initial)
767 {
768  StockSplitInfo *info;
769  gint component_id;
770 
771  info = g_new0 (StockSplitInfo, 1);
772 
773  info->acct = NULL;
774 
775  gnc_stock_split_assistant_create (info);
776 
777  component_id = gnc_register_gui_component (ASSISTANT_STOCK_SPLIT_CM_CLASS,
778  refresh_handler, close_handler,
779  info);
780 
781  gnc_gui_component_watch_entity_type (component_id,
782  GNC_ID_ACCOUNT,
783  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
784 
785  if (fill_account_list (info, initial) == 0)
786  {
787  gnc_warning_dialog (GTK_WINDOW (parent), "%s", _("You don't have any stock accounts with balances!"));
788  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
789  return;
790  }
791 
792  gtk_window_set_transient_for (GTK_WINDOW (info->window), GTK_WINDOW(parent));
793  gtk_widget_show_all (info->window);
794 
795  gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
796 }
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:92
void gnc_price_list_destroy(PriceList *prices)
gnc_price_list_destroy - destroy the given price list, calling gnc_price_unref on all the prices incl...
GNCPrice * gnc_price_create(QofBook *book)
gnc_price_create - returns a newly allocated and initialized price with a reference count of 1...
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
Definition: Transaction.h:381
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3))...
void xaccSplitMakeStockSplit(Split *s)
Mark a split to be of type stock split - after this, you shouldn&#39;t modify the value anymore...
Definition: Split.cpp:2001
GList * gnc_account_get_descendants_sorted(const Account *account)
This function returns a GList containing all the descendants of the specified account, sorted at each level.
Definition: Account.cpp:3022
void gnc_currency_edit_set_currency(GNCCurrencyEdit *gce, const gnc_commodity *currency)
Set the widget to display a certain currency name.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false. ...
Definition: Account.cpp:4506
utility functions for the GnuCash UI
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3237
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
Definition: Account.cpp:2716
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.
gboolean gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p)
Add a price to the pricedb.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
Definition: Account.h:110
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Return the pricedb associated with the book.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
Currency selection widget.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account&#39;s commodity that the split should have...
Definition: gmock-Split.cpp:77
void gnc_tree_view_account_set_filter(GncTreeViewAccount *view, gnc_tree_view_account_filter_func func, gpointer data, GSourceFunc destroy)
This function attaches a filter function to the given account tree.
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition: Account.cpp:3275
GtkTreeView implementation for gnucash account tree.
Income accounts are used to denote income.
Definition: Account.h:140
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
Create a new account tree view.
The bank account type denotes a savings or checking account held at a bank.
Definition: Account.h:107
gnc_commodity * gnc_currency_edit_get_currency(GNCCurrencyEdit *gce)
Retrieve the displayed currency of the widget.
PriceList * gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db, const gnc_commodity *commodity)
Find the most recent price between a commodity and all other commodities.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
Definition: Account.h:116
gnc_numeric xaccAccountGetBalance(const Account *acc)
Get the current balance of the account, which may include future splits.
Definition: Account.cpp:3430
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:101
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: gmock-Split.cpp:37
GtkWidget * gnc_currency_edit_new(void)
Create a new GNCCurrencyEdit widget which can be used to provide an easy way to enter ISO currency co...
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 * xaccAccountGetCommodity(const Account *acc)
Get the account&#39;s commodity.
Definition: Account.cpp:3371
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
Definition: Account.h:1052
gboolean xaccAccountGetPlaceholder(const Account *acc)
Get the "placeholder" flag for an account.
Definition: Account.cpp:4074
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
This function returns the account associated with the selected item in the account tree view...
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
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
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.