GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 <[email protected]> *
5  * Copyright (c) 2006 David Hampton <[email protected]> *
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 [email protected] *
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 "assistant-utils.h"
36 #include "gnc-amount-edit.h"
37 #include "gnc-component-manager.h"
38 #include "gnc-currency-edit.h"
39 #include "gnc-date-edit.h"
40 #include "qof.h"
41 #include "gnc-gui-query.h"
42 #include "gnc-tree-view-account.h"
43 #include "gnc-ui.h"
44 #include "gnc-ui-util.h"
45 
46 
47 #define ASSISTANT_STOCK_SPLIT_CM_CLASS "assistant-stock-split"
48 
49 enum split_cols
50 {
51  SPLIT_COL_ACCOUNT = 0,
52  SPLIT_COL_FULLNAME,
53  SPLIT_COL_MNEMONIC,
54  SPLIT_COL_SHARES,
55  NUM_SPLIT_COLS
56 };
57 
59 typedef struct
60 {
61  GtkWidget * window;
62  GtkWidget * assistant;
63 
64  /* account page data */
65  GtkWidget * account_view;
66  Account * acct;
67 
68  /* info page data */
69  GtkWidget * date_edit;
70  GtkWidget * distribution_edit;
71  GtkWidget * description_entry;
72  GtkWidget * price_edit;
73  GtkWidget * price_currency_edit;
74 
75  /* cash in lieu page data */
76  GtkWidget * cash_edit;
77  GtkWidget * memo_entry;
78  GtkWidget * income_tree;
79  GtkWidget * asset_tree;
81 
82 
84 void gnc_stock_split_assistant_window_destroy_cb (GtkObject *object, gpointer user_data);
85 void gnc_stock_split_assistant_prepare (GtkAssistant *assistant,
86  GtkWidget *page,
87  gpointer user_data);
88 void gnc_stock_split_assistant_details_prepare (GtkAssistant *assistant,
89  gpointer user_data);
90 gboolean gnc_stock_split_assistant_details_complete (GtkAssistant *assistant,
91  gpointer user_data);
92 gboolean gnc_stock_split_assistant_cash_complete (GtkAssistant *assistant,
93  gpointer user_data);
94 void gnc_stock_split_assistant_finish (GtkAssistant *assistant,
95  gpointer user_data);
96 void gnc_stock_split_assistant_cancel (GtkAssistant *gtkassistant,
97  gpointer user_data);
98 
99 /******* implementations ***********************************************/
100 void
101 gnc_stock_split_assistant_window_destroy_cb (GtkObject *object, gpointer user_data)
102 {
103  StockSplitInfo *info = user_data;
104 
105  gnc_unregister_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
106 
107  g_free (info);
108 }
109 
110 
111 static int
112 fill_account_list (StockSplitInfo *info, Account *selected_account)
113 {
114  GtkTreeRowReference *reference = NULL;
115  GtkTreeView *view;
116  GtkListStore *list;
117  GtkTreeIter iter;
118  GtkTreePath *path;
119  GList *accounts;
120  GList *node;
121  gint rows = 0;
122  gchar *full_name;
123 
124  view = GTK_TREE_VIEW(info->account_view);
125  list = GTK_LIST_STORE(gtk_tree_view_get_model(view));
126 
127  gtk_list_store_clear (list);
128 
129  accounts = gnc_account_get_descendants_sorted (gnc_get_current_root_account ());
130  for (node = accounts; node; node = node->next)
131  {
132  Account *account = node->data;
133  GNCPrintAmountInfo print_info;
134  const gnc_commodity *commodity;
135  gnc_numeric balance;
136 
137  if (!xaccAccountIsPriced(account))
138  continue;
139 
140  balance = xaccAccountGetBalance (account);
141  if (gnc_numeric_zero_p (balance))
142  continue;
143 
144  if (xaccAccountGetPlaceholder (account))
145  continue;
146 
147  commodity = xaccAccountGetCommodity (account);
148 
149  full_name = gnc_account_get_full_name (account);
150  print_info = gnc_account_print_info (account, FALSE);
151 
152  gtk_list_store_append(list, &iter);
153  gtk_list_store_set(list, &iter,
154  SPLIT_COL_ACCOUNT, account,
155  SPLIT_COL_FULLNAME, full_name,
156  SPLIT_COL_MNEMONIC, gnc_commodity_get_mnemonic(commodity),
157  SPLIT_COL_SHARES, xaccPrintAmount(balance, print_info),
158  -1);
159 
160  if (account == selected_account)
161  {
162  path = gtk_tree_model_get_path(GTK_TREE_MODEL(list), &iter);
163  reference = gtk_tree_row_reference_new(GTK_TREE_MODEL(list), path);
164  gtk_tree_path_free(path);
165  }
166 
167  g_free (full_name);
168 
169  rows++;
170  }
171  g_list_free(accounts);
172 
173  if (reference)
174  {
175  GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
176  path = gtk_tree_row_reference_get_path(reference);
177  gtk_tree_row_reference_free(reference);
178  if (path)
179  {
180  gtk_tree_selection_select_path(selection, path);
181  gtk_tree_view_scroll_to_cell(view, path, NULL, TRUE, 0.5, 0.0);
182  gtk_tree_path_free(path);
183  }
184  }
185 
186  return rows;
187 }
188 
189 
190 static void
191 selection_changed_cb (GtkTreeSelection *selection,
192  gpointer user_data)
193 {
194  StockSplitInfo *info = user_data;
195  GtkTreeModel *list;
196  GtkTreeIter iter;
197 
198  if (!gtk_tree_selection_get_selected(selection, &list, &iter))
199  return;
200  gtk_tree_model_get(list, &iter,
201  SPLIT_COL_ACCOUNT, &info->acct,
202  -1);
203 }
204 
205 
206 static void
207 refresh_details_page (StockSplitInfo *info)
208 {
209  GNCPrintAmountInfo print_info;
210  gnc_commodity *commodity, *currency;
211  Account *account;
212  QofBook *book;
213  GNCPriceDB *db;
214  GList *prices;
215 
216  account = info->acct;
217 
218  g_return_if_fail (account != NULL);
219 
220  print_info = gnc_account_print_info (account, FALSE);
221 
222  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (info->distribution_edit),
223  print_info);
224  gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT (info->distribution_edit),
225  xaccAccountGetCommoditySCU (account));
226 
227  commodity = xaccAccountGetCommodity (account);
228  book = gnc_account_get_book (account);
229  db = gnc_pricedb_get_db(book);
230 
231  prices = gnc_pricedb_lookup_latest_any_currency(db, commodity);
232  if (prices)
233  {
234  /* Use the first existing price */
235  currency = gnc_price_get_currency(prices->data);
236  }
237  else
238  {
239  /* Take a wild guess. */
240  currency = gnc_default_currency ();
241  }
242  gnc_price_list_destroy(prices);
243 
245  (GNC_CURRENCY_EDIT (info->price_currency_edit),
246  currency);
247 }
248 
249 
250 void gnc_stock_split_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
251  gpointer user_data)
252 {
253  gint currentpage = gtk_assistant_get_current_page(assistant);
254 
255  if (currentpage == 2) /* Current page is details page */
256  gnc_stock_split_assistant_details_prepare(assistant, user_data);
257 }
258 
259 
260 void
261 gnc_stock_split_assistant_details_prepare (GtkAssistant *assistant,
262  gpointer user_data)
263 {
264  StockSplitInfo *info = user_data;
265 
266  refresh_details_page(info);
267 }
268 
269 
270 gboolean
271 gnc_stock_split_assistant_details_complete (GtkAssistant *assistant,
272  gpointer user_data)
273 {
274  StockSplitInfo *info = user_data;
275  gnc_numeric amount;
276  gint result;
277 
278  result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->distribution_edit), &amount, TRUE);
279  if ( result != 0)
280  return FALSE; /* Parsing error or field is empty */
281 
282  if (gnc_numeric_zero_p (amount))
283  return FALSE; /* field value is 0 */
284 
285  result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->price_edit), &amount, TRUE);
286  if (result == -1)
287  return TRUE; /* Optional field is empty */
288  else if ( result > 0)
289  return FALSE; /* Parsing error */
290  else if (gnc_numeric_negative_p (amount))
291  return FALSE; /* Negative price is not allowed */
292  else
293  return TRUE; /* Valid positive price */
294 }
295 
296 
297 gboolean
298 gnc_stock_split_assistant_cash_complete (GtkAssistant *assistant,
299  gpointer user_data)
300 {
301  StockSplitInfo *info = user_data;
302  gnc_numeric amount;
303  gint result;
304  Account *account;
305 
306  result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->cash_edit), &amount, TRUE);
307  if (result == -1)
308  return TRUE; /* Optional field is empty */
309  else if ( result > 0)
310  return FALSE; /* Parsing error */
311  else if (gnc_numeric_negative_p (amount))
312  return FALSE; /* Negative cash amount is not allowed */
313 
314  /* We have a positive cash amount */
315  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->income_tree));
316  if (!account)
317  return FALSE;
318 
319  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->asset_tree));
320  if (!account)
321  return FALSE;
322 
323  return TRUE;
324 }
325 
326 
327 void
328 gnc_stock_split_assistant_finish (GtkAssistant *assistant,
329  gpointer user_data)
330 {
331  StockSplitInfo *info = user_data;
332  GList *account_commits;
333  GList *node;
334 
335  gnc_numeric amount;
336  Transaction *trans;
337  Account *account;
338  Split *split;
339  time64 date;
340 
341  account = info->acct;
342  g_return_if_fail (account != NULL);
343 
344  amount = gnc_amount_edit_get_amount
345  (GNC_AMOUNT_EDIT (info->distribution_edit));
346  g_return_if_fail (!gnc_numeric_zero_p (amount));
347 
348  gnc_suspend_gui_refresh ();
349 
350  trans = xaccMallocTransaction (gnc_get_current_book ());
351 
352  xaccTransBeginEdit (trans);
353 
355 
356  date = gnc_date_edit_get_date (GNC_DATE_EDIT (info->date_edit));
358 
359  {
360  const char *description;
361 
362  description = gtk_entry_get_text (GTK_ENTRY (info->description_entry));
363  xaccTransSetDescription (trans, description);
364  }
365 
366  split = xaccMallocSplit (gnc_get_current_book ());
367 
368  xaccAccountBeginEdit (account);
369  account_commits = g_list_prepend (NULL, account);
370 
371  xaccTransAppendSplit (trans, split);
372 
373  xaccAccountInsertSplit (account, split);
374 
375  xaccSplitSetAmount (split, amount);
376  xaccSplitMakeStockSplit (split);
377  /* Set split-action with gnc_set_num_action which is the same as
378  * xaccSplitSetAction with these arguments */
379  /* Translators: This string has a disambiguation prefix */
380  gnc_set_num_action (NULL, split, NULL, Q_("Action Column|Split"));
381 
382  amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (info->price_edit));
383  if (gnc_numeric_positive_p (amount))
384  {
385  QofBook *book;
386  GNCPrice *price;
387  GNCPriceDB *pdb;
388  GNCCurrencyEdit *ce;
389  Timespec ts;
390 
391  ce = GNC_CURRENCY_EDIT (info->price_currency_edit);
392 
393  ts.tv_sec = date;
394  ts.tv_nsec = 0;
395 
396  price = gnc_price_create (gnc_get_current_book ());
397 
398  gnc_price_begin_edit (price);
399  gnc_price_set_commodity (price, xaccAccountGetCommodity (account));
400  gnc_price_set_currency (price, gnc_currency_edit_get_currency (ce));
401  gnc_price_set_time (price, ts);
402  gnc_price_set_source (price, "user:stock-split");
403  gnc_price_set_typestr (price, "unknown");
404  gnc_price_set_value (price, amount);
405  gnc_price_commit_edit (price);
406 
407  book = gnc_get_current_book ();
408  pdb = gnc_pricedb_get_db (book);
409 
410  if (!gnc_pricedb_add_price (pdb, price))
411  gnc_error_dialog (info->window, "%s", _("Error adding price."));
412 
413  gnc_price_unref (price);
414  }
415 
416  amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (info->cash_edit));
417  if (gnc_numeric_positive_p (amount))
418  {
419  const char *memo;
420 
421  memo = gtk_entry_get_text (GTK_ENTRY (info->memo_entry));
422 
423  /* asset split */
424  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->asset_tree));
425 
426  split = xaccMallocSplit (gnc_get_current_book ());
427 
428  xaccAccountBeginEdit (account);
429  account_commits = g_list_prepend (account_commits, account);
430 
431  xaccAccountInsertSplit (account, split);
432 
433  xaccTransAppendSplit (trans, split);
434 
435  xaccSplitSetAmount (split, amount);
436  xaccSplitSetValue (split, amount);
437 
438  xaccSplitSetMemo (split, memo);
439 
440 
441  /* income split */
442  account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->income_tree));
443 
444  split = xaccMallocSplit (gnc_get_current_book ());
445 
446  xaccAccountBeginEdit (account);
447  account_commits = g_list_prepend (account_commits, account);
448 
449  xaccAccountInsertSplit (account, split);
450 
451  xaccTransAppendSplit (trans, split);
452 
453  xaccSplitSetAmount (split, gnc_numeric_neg (amount));
454  xaccSplitSetValue (split, gnc_numeric_neg (amount));
455 
456  xaccSplitSetMemo (split, memo);
457  }
458 
459  xaccTransCommitEdit (trans);
460 
461  for (node = account_commits; node; node = node->next)
462  xaccAccountCommitEdit (node->data);
463  g_list_free (account_commits);
464 
465  gnc_resume_gui_refresh ();
466 
467  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
468 }
469 
470 
471 void
472 gnc_stock_split_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
473 {
474  StockSplitInfo *info = user_data;
475  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
476 }
477 
478 
479 static gboolean
480 gnc_stock_split_assistant_view_filter_income (Account *account,
481  gpointer data)
482 {
483  GNCAccountType type;
484 
485  type = xaccAccountGetType(account);
486  return (type == ACCT_TYPE_INCOME);
487 }
488 
489 
490 static gboolean
491 gnc_stock_split_assistant_view_filter_asset (Account *account,
492  gpointer data)
493 {
494  GNCAccountType type;
495 
496  type = xaccAccountGetType(account);
497  return ((type == ACCT_TYPE_BANK) || (type == ACCT_TYPE_CASH) ||
498  (type == ACCT_TYPE_ASSET));
499 }
500 
501 
502 static void
503 gnc_stock_split_details_valid_cb (GtkWidget *widget, gpointer user_data)
504 {
505  StockSplitInfo *info = user_data;
506  GtkAssistant *assistant = GTK_ASSISTANT(info->window);
507  gint num = gtk_assistant_get_current_page (assistant);
508  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
509 
510  gtk_assistant_set_page_complete (assistant, page,
511  gnc_stock_split_assistant_details_complete (assistant, user_data));
512 }
513 
514 
515 static void
516 gnc_stock_split_cash_valid_cb (GtkWidget *widget, gpointer user_data)
517 {
518  StockSplitInfo *info = user_data;
519  GtkAssistant *assistant = GTK_ASSISTANT(info->window);
520  gint num = gtk_assistant_get_current_page (assistant);
521  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
522 
523  gtk_assistant_set_page_complete (assistant, page,
524  gnc_stock_split_assistant_cash_complete (assistant, user_data));
525 }
526 
527 
528 static GtkWidget *
529 gnc_stock_split_assistant_create (StockSplitInfo *info)
530 {
531  GtkBuilder *builder;
532  GtkWidget *window;
533 
534  builder = gtk_builder_new();
535  gnc_builder_add_from_file (builder , "assistant-stock-split.glade", "Stock Split Assistant");
536  window = GTK_WIDGET(gtk_builder_get_object (builder, "Stock Split Assistant"));
537  info->window = window;
538 
539  /* Set the assistant colors */
540  gnc_assistant_set_colors (GTK_ASSISTANT (info->window));
541 
542  /* Enable buttons on first, second, fourth and last page. */
543  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
544  GTK_WIDGET(gtk_builder_get_object(builder, "intro_page_label")),
545  TRUE);
546  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
547  GTK_WIDGET(gtk_builder_get_object(builder, "stock_account_page")),
548  TRUE);
549  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
550  GTK_WIDGET(gtk_builder_get_object(builder, "stock_cash_page")),
551  TRUE);
552  gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
553  GTK_WIDGET(gtk_builder_get_object(builder, "finish_page_label")),
554  TRUE);
555 
556  /* Account page Widgets */
557  {
558  GtkTreeView *view;
559  GtkListStore *store;
560  GtkTreeSelection *selection;
561  GtkCellRenderer *renderer;
562  GtkTreeViewColumn *column;
563 
564  info->account_view = GTK_WIDGET(gtk_builder_get_object(builder, "account_view"));
565 
566  view = GTK_TREE_VIEW(info->account_view);
567 
568  store = gtk_list_store_new(NUM_SPLIT_COLS, G_TYPE_POINTER, G_TYPE_STRING,
569  G_TYPE_STRING, G_TYPE_STRING);
570  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
571  g_object_unref(store);
572 
573  renderer = gtk_cell_renderer_text_new();
574  column = gtk_tree_view_column_new_with_attributes(_("Account"), renderer,
575  "text", SPLIT_COL_FULLNAME,
576  NULL);
577  gtk_tree_view_append_column(view, column);
578 
579  renderer = gtk_cell_renderer_text_new();
580  column = gtk_tree_view_column_new_with_attributes(_("Symbol"), renderer,
581  "text", SPLIT_COL_MNEMONIC,
582  NULL);
583  gtk_tree_view_append_column(view, column);
584 
585  renderer = gtk_cell_renderer_text_new();
586  column = gtk_tree_view_column_new_with_attributes(_("Shares"), renderer,
587  "text", SPLIT_COL_SHARES,
588  NULL);
589  gtk_tree_view_append_column(view, column);
590 
591  selection = gtk_tree_view_get_selection(view);
592  gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
593  g_signal_connect (selection, "changed",
594  G_CALLBACK (selection_changed_cb), info);
595 
596  }
597 
598  /* Details Page Widgets */
599  {
600  GtkWidget *table;
601  GtkWidget *amount;
602  GtkWidget *date;
603  GtkWidget *label;
604 
605  table = GTK_WIDGET(gtk_builder_get_object(builder, "stock_details_table"));
606  info->description_entry = GTK_WIDGET(gtk_builder_get_object(builder, "description_entry"));
607 
608  date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
609  gtk_table_attach_defaults (GTK_TABLE (table), date, 1, 2, 0, 1);
610  gtk_widget_show (date);
611  info->date_edit = date;
612 
613  label = GTK_WIDGET(gtk_builder_get_object(builder, "date_label"));
614  gnc_date_make_mnemonic_target (GNC_DATE_EDIT(date), label);
615 
616  amount = gnc_amount_edit_new ();
617  g_signal_connect (amount, "changed",
618  G_CALLBACK (gnc_stock_split_details_valid_cb), info);
619  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
620  gtk_table_attach_defaults (GTK_TABLE (table), amount, 1, 2, 1, 2);
621  gtk_widget_show (amount);
622  info->distribution_edit = amount;
623 
624  label = GTK_WIDGET(gtk_builder_get_object(builder, "distribution_label"));
625  gtk_label_set_mnemonic_widget(GTK_LABEL(label), amount);
626 
627  amount = gnc_amount_edit_new ();
628  gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (amount),
629  gnc_default_price_print_info ());
630  g_signal_connect (amount, "changed",
631  G_CALLBACK (gnc_stock_split_details_valid_cb), info);
632  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
633  gtk_table_attach_defaults (GTK_TABLE (table), amount, 1, 2, 5, 6);
634  gtk_widget_show (amount);
635  info->price_edit = amount;
636 
637  label = GTK_WIDGET(gtk_builder_get_object(builder, "price_label"));
638  gtk_label_set_mnemonic_widget(GTK_LABEL(label), amount);
639 
640  info->price_currency_edit = gnc_currency_edit_new();
641  gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(info->price_currency_edit), gnc_default_currency());
642  gtk_widget_show (info->price_currency_edit);
643  gtk_table_attach_defaults (GTK_TABLE (table), info->price_currency_edit, 1, 2, 6, 7);
644  }
645 
646  /* Cash page Widgets */
647  {
648  GtkWidget *box;
649  GtkWidget *tree;
650  GtkWidget *amount;
651  GtkWidget *label;
652  GtkWidget *scroll;
653  GtkTreeSelection *selection;
654 
655  box = GTK_WIDGET(gtk_builder_get_object(builder, "cash_box"));
656  amount = gnc_amount_edit_new ();
657  g_signal_connect (amount, "changed",
658  G_CALLBACK (gnc_stock_split_cash_valid_cb), info);
659  gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (amount), TRUE);
660  gtk_box_pack_start (GTK_BOX (box), amount, TRUE, TRUE, 0);
661  info->cash_edit = amount;
662 
663  label = GTK_WIDGET(gtk_builder_get_object(builder, "cash_label"));
664  gtk_label_set_mnemonic_widget(GTK_LABEL(label), amount);
665 
666  info->memo_entry = GTK_WIDGET(gtk_builder_get_object(builder, "memo_entry"));
667 
668  /* income tree */
669  tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
670  info->income_tree = tree;
671  gnc_tree_view_account_set_filter (GNC_TREE_VIEW_ACCOUNT (tree),
672  gnc_stock_split_assistant_view_filter_income,
673  NULL, /* user data */
674  NULL /* destroy callback */);
675 
676  gtk_widget_show (tree);
677 
678  gtk_tree_view_expand_all (GTK_TREE_VIEW(tree));
679  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
680  gtk_tree_selection_unselect_all (selection);
681  g_signal_connect (selection, "changed",
682  G_CALLBACK (gnc_stock_split_cash_valid_cb), info);
683 
684  label = GTK_WIDGET(gtk_builder_get_object(builder, "income_label"));
685  gtk_label_set_mnemonic_widget (GTK_LABEL(label), tree);
686 
687  scroll = GTK_WIDGET(gtk_builder_get_object(builder, "income_scroll"));
688  gtk_container_add (GTK_CONTAINER (scroll), tree);
689 
690  /* asset tree */
691  tree = GTK_WIDGET(gnc_tree_view_account_new (FALSE));
692  info->asset_tree = tree;
693  gnc_tree_view_account_set_filter (GNC_TREE_VIEW_ACCOUNT (tree),
694  gnc_stock_split_assistant_view_filter_asset,
695  NULL /* user data */,
696  NULL /* destroy callback */);
697 
698  gtk_widget_show (tree);
699 
700  label = GTK_WIDGET(gtk_builder_get_object(builder, "asset_label"));
701  gtk_label_set_mnemonic_widget (GTK_LABEL(label), tree);
702 
703  scroll = GTK_WIDGET(gtk_builder_get_object(builder, "asset_scroll"));
704  gtk_container_add (GTK_CONTAINER (scroll), tree);
705 
706  gtk_tree_view_expand_all (GTK_TREE_VIEW(tree));
707  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
708  gtk_tree_selection_unselect_all (selection);
709  g_signal_connect (selection, "changed",
710  G_CALLBACK (gnc_stock_split_cash_valid_cb), info);
711  }
712 
713  g_signal_connect (G_OBJECT(window), "destroy",
714  G_CALLBACK (gnc_stock_split_assistant_window_destroy_cb), info);
715 
716  gtk_builder_connect_signals(builder, info);
717  g_object_unref(G_OBJECT(builder));
718  return window;
719 
720 }
721 
722 static void
723 refresh_handler (GHashTable *changes, gpointer user_data)
724 {
725  StockSplitInfo *info = user_data;
726  Account *old_account;
727 
728  old_account = info->acct;
729 
730  if (fill_account_list (info, info->acct) == 0)
731  {
732  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
733  return;
734  }
735 
736  if (NULL == info->acct || old_account == info->acct) return;
737 }
738 
739 static void
740 close_handler (gpointer user_data)
741 {
742  StockSplitInfo *info = user_data;
743 
744  gtk_widget_destroy (info->window);
745 }
746 
747 /********************************************************************\
748  * gnc_stock_split_dialog *
749  * opens up a window to record a stock split *
750  * *
751  * Args: parent - the parent ofthis window *
752  * initial - the initial account to use *
753  * Return: nothing *
754 \********************************************************************/
755 void
756 gnc_stock_split_dialog (GtkWidget *parent, Account * initial)
757 {
758  StockSplitInfo *info;
759  gint component_id;
760 
761  info = g_new0 (StockSplitInfo, 1);
762 
763  info->acct = NULL;
764 
765  gnc_stock_split_assistant_create (info);
766 
767  component_id = gnc_register_gui_component (ASSISTANT_STOCK_SPLIT_CM_CLASS,
768  refresh_handler, close_handler,
769  info);
770 
771  gnc_gui_component_watch_entity_type (component_id,
772  GNC_ID_ACCOUNT,
773  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
774 
775  if (fill_account_list (info, initial) == 0)
776  {
777  gnc_warning_dialog (parent, "%s", _("You don't have any stock accounts with balances!"));
778  gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
779  return;
780  }
781 
782  gtk_widget_show_all (info->window);
783 
784  gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
785 }
void xaccSplitSetValue(Split *s, gnc_numeric amt)
Definition: Split.c:1294
void gnc_price_list_destroy(PriceList *prices)
Definition: gnc-pricedb.c:701
GNCPrice * gnc_price_create(QofBook *book)
Definition: gnc-pricedb.c:236
#define xaccTransAppendSplit(t, s)
Definition: Transaction.h:357
Transaction * xaccMallocTransaction(QofBook *book)
Definition: Transaction.c:513
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
Definition: Transaction.c:1920
void xaccSplitMakeStockSplit(Split *s)
Definition: Split.c:2060
GList * gnc_account_get_descendants_sorted(const Account *account)
Definition: Account.c:2777
void gnc_currency_edit_set_currency(GNCCurrencyEdit *gce, const gnc_commodity *currency)
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
gboolean xaccAccountIsPriced(const Account *acc)
Definition: Account.c:4249
utility functions for the GnuCash UI
GNCAccountType xaccAccountGetType(const Account *acc)
Definition: Account.c:3009
int xaccAccountGetCommoditySCU(const Account *acc)
Definition: Account.c:2458
gnc_numeric gnc_numeric_neg(gnc_numeric a)
void gnc_price_unref(GNCPrice *p)
Definition: gnc-pricedb.c:272
gboolean gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p)
Definition: gnc-pricedb.c:1053
void xaccTransSetDescription(Transaction *trans, const char *desc)
Definition: Transaction.c:2085
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
gboolean gnc_numeric_zero_p(gnc_numeric a)
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Definition: gnc-pricedb.c:872
gboolean gnc_numeric_negative_p(gnc_numeric a)
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Definition: Transaction.c:1354
gnc_commodity * gnc_default_currency(void)
Definition: gnc-ui-util.c:939
Currency selection widget.
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
Definition: Split.c:1258
void gnc_tree_view_account_set_filter(GncTreeViewAccount *view, gnc_tree_view_account_filter_func func, gpointer data, GSourceFunc destroy)
gchar * gnc_account_get_full_name(const Account *account)
Definition: Account.c:3038
GtkTreeView implementation for gnucash account tree.
void xaccSplitSetMemo(Split *split, const char *memo)
Definition: Split.c:1774
GtkTreeView * gnc_tree_view_account_new(gboolean show_root)
gnc_commodity * gnc_currency_edit_get_currency(GNCCurrencyEdit *gce)
PriceList * gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db, const gnc_commodity *commodity)
Definition: gnc-pricedb.c:1373
void xaccTransCommitEdit(Transaction *trans)
Definition: Transaction.c:1579
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
gnc_numeric xaccAccountGetBalance(const Account *acc)
Definition: Account.c:3229
GNCAccountType
Definition: Account.h:96
gboolean gnc_numeric_positive_p(gnc_numeric a)
Split * xaccMallocSplit(QofBook *book)
Definition: Split.c:582
GtkWidget * gnc_currency_edit_new(void)
Definition: SplitP.h:71
void xaccAccountBeginEdit(Account *acc)
Definition: Account.c:1280
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
#define xaccAccountInsertSplit(acc, s)
Definition: Account.h:972
gboolean xaccAccountGetPlaceholder(const Account *acc)
Definition: Account.c:3912
Account * gnc_tree_view_account_get_selected_account(GncTreeViewAccount *view)
time64 gnc_time(time64 *tbuf)
get the current local time
gint64 time64
Definition: gnc-date.h:83
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
Definition: Account.c:1321