GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dialog-commodities.c
1 /********************************************************************\
2  * dialog-commodities.c -- commodities dialog *
3  * Copyright (C) 2001 Gnumatic, Inc. *
4  * Author: Dave Peticolas <[email protected]> *
5  * Copyright (C) 2003,2005 David Hampton *
6  * *
7  * This program is free software; you can redistribute it and/or *
8  * modify it under the terms of the GNU General Public License as *
9  * published by the Free Software Foundation; either version 2 of *
10  * the License, or (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License*
18  * along with this program; if not, contact: *
19  * *
20  * Free Software Foundation Voice: +1-617-542-5942 *
21  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22  * Boston, MA 02110-1301, USA [email protected] *
23 \********************************************************************/
24 
25 #include "config.h"
26 
27 #include <gtk/gtk.h>
28 #include <glib/gi18n.h>
29 
30 #include "dialog-commodity.h"
31 #include "dialog-utils.h"
32 #include "gnc-commodity.h"
33 #include "gnc-component-manager.h"
34 #include "qof.h"
36 #include "gnc-prefs.h"
37 #include "gnc-ui.h"
38 #include "gnc-ui-util.h"
39 #include "gnc-gnome-utils.h"
40 #include "gnc-session.h"
41 #include "gnome-utils/gnc-warnings.h"
42 
43 
44 #define DIALOG_COMMODITIES_CM_CLASS "dialog-commodities"
45 #define STATE_SECTION "dialogs/edit_commodities"
46 #define GNC_PREFS_GROUP "dialogs.commodities"
47 #define GNC_PREF_INCL_ISO "include-iso"
48 
49 /* This static indicates the debugging module that this .o belongs to. */
50 /* static short module = MOD_GUI; */
51 
52 typedef struct
53 {
54  GtkWidget * dialog;
55  QofSession *session;
56  QofBook *book;
57 
58  GncTreeViewCommodity * commodity_tree;
59  GtkWidget * edit_button;
60  GtkWidget * remove_button;
61  gboolean show_currencies;
62 
63  gboolean is_new;
65 
66 
67 void gnc_commodities_window_destroy_cb (GtkObject *object, CommoditiesDialog *cd);
68 void gnc_commodities_dialog_response (GtkDialog *dialog, gint response, CommoditiesDialog *cd);
69 void gnc_commodities_show_currencies_toggled (GtkToggleButton *toggle, CommoditiesDialog *cd);
70 
71 
72 
73 void
74 gnc_commodities_window_destroy_cb (GtkObject *object, CommoditiesDialog *cd)
75 {
76  gnc_unregister_gui_component_by_data (DIALOG_COMMODITIES_CM_CLASS, cd);
77 
78  g_free (cd);
79 }
80 
81 static void
82 edit_clicked (CommoditiesDialog *cd)
83 {
84  gnc_commodity *commodity;
85 
86  commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
87  if (commodity == NULL)
88  return;
89 
90  if (gnc_ui_edit_commodity_modal (commodity, cd->dialog))
91  gnc_gui_refresh_all ();
92 }
93 
94 static void
95 row_activated_cb (GtkTreeView *view, GtkTreePath *path,
96  GtkTreeViewColumn *column, CommoditiesDialog *cd)
97 {
98  GtkTreeModel *model;
99  GtkTreeIter iter;
100 
101  g_return_if_fail(view);
102 
103  model = gtk_tree_view_get_model(view);
104  if (gtk_tree_model_get_iter(model, &iter, path))
105  {
106  if (gtk_tree_model_iter_has_child(model, &iter))
107  {
108  /* There are children, so it's not a commodity.
109  * Just expand or collapse the row. */
110  if (gtk_tree_view_row_expanded(view, path))
111  gtk_tree_view_collapse_row(view, path);
112  else
113  gtk_tree_view_expand_row(view, path, FALSE);
114  }
115  else
116  /* It's a commodity, so click the Edit button. */
117  edit_clicked(cd);
118  }
119 }
120 
121 static void
122 remove_clicked (CommoditiesDialog *cd)
123 {
124  GNCPriceDB *pdb;
125  GList *node;
126  GList *prices;
127  GList *accounts;
128  gboolean can_delete;
129  gnc_commodity *commodity;
130  GtkWidget *dialog;
131  const gchar *message, *warning;
132  gint response;
133 
134  commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
135  if (commodity == NULL)
136  return;
137 
138  accounts = gnc_account_get_descendants (gnc_book_get_root_account(cd->book));
139  can_delete = TRUE;
140 
141  for (node = accounts; node; node = node->next)
142  {
143  Account *account = node->data;
144 
145  if (commodity == xaccAccountGetCommodity (account))
146  {
147  can_delete = FALSE;
148  break;
149  }
150  }
151 
152  /* FIXME check for transaction references */
153 
154  if (!can_delete)
155  {
156  const char *message = _("That commodity is currently used by "
157  "at least one of your accounts. You may "
158  "not delete it.");
159 
160  gnc_warning_dialog (cd->dialog, "%s", message);
161  g_list_free (accounts);
162  return;
163  }
164  g_list_free (accounts);
165 
166  pdb = gnc_pricedb_get_db (cd->book);
167  prices = gnc_pricedb_get_prices(pdb, commodity, NULL);
168  if (prices)
169  {
170  message = _("This commodity has price quotes. Are "
171  "you sure you want to delete the selected "
172  "commodity and its price quotes?");
173  warning = GNC_PREF_WARN_PRICE_COMM_DEL_QUOTES;
174  }
175  else
176  {
177  message = _("Are you sure you want to delete the "
178  "selected commodity?");
179  warning = GNC_PREF_WARN_PRICE_COMM_DEL;
180  }
181 
182  dialog = gtk_message_dialog_new(GTK_WINDOW(cd->dialog),
183  GTK_DIALOG_DESTROY_WITH_PARENT,
184  GTK_MESSAGE_QUESTION,
185  GTK_BUTTONS_NONE,
186  "%s", _("Delete commodity?"));
187  gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
188  "%s", message);
189  gtk_dialog_add_buttons(GTK_DIALOG(dialog),
190  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
191  GTK_STOCK_DELETE, GTK_RESPONSE_OK,
192  (gchar *)NULL);
193  response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
194  gtk_widget_destroy(dialog);
195 
196  if (response == GTK_RESPONSE_OK)
197  {
199 
200  ct = gnc_commodity_table_get_table (cd->book);
201  for (node = prices; node; node = node->next)
202  gnc_pricedb_remove_price(pdb, node->data);
203 
204  gnc_commodity_table_remove (ct, commodity);
205  gnc_commodity_destroy (commodity);
206  commodity = NULL;
207  }
208 
209  gnc_price_list_destroy(prices);
210  gnc_gui_refresh_all ();
211 }
212 
213 static void
214 add_clicked (CommoditiesDialog *cd)
215 {
216  gnc_commodity *commodity;
217  const char *name_space;
218 
219  commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
220  if (commodity)
221  name_space = gnc_commodity_get_namespace (commodity);
222  else
223  name_space = NULL;
224 
225  commodity = gnc_ui_new_commodity_modal (name_space, cd->dialog);
226 }
227 
228 void
229 gnc_commodities_dialog_response (GtkDialog *dialog,
230  gint response,
231  CommoditiesDialog *cd)
232 {
233  switch (response)
234  {
235  case GNC_RESPONSE_NEW:
236  add_clicked (cd);
237  return;
238 
239  case GNC_RESPONSE_DELETE:
240  remove_clicked (cd);
241  return;
242 
243  case GNC_RESPONSE_EDIT:
244  edit_clicked (cd);
245  return;
246 
247  case GTK_RESPONSE_CLOSE:
248  default:
249  gnc_close_gui_component_by_data (DIALOG_COMMODITIES_CM_CLASS, cd);
250  return;
251  }
252 }
253 
254 static void
255 gnc_commodities_dialog_selection_changed (GtkTreeSelection *selection,
256  CommoditiesDialog *cd)
257 {
258  gboolean remove_ok;
259  gnc_commodity *commodity;
260 
261  commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
262  remove_ok = commodity && !gnc_commodity_is_iso(commodity);
263  gtk_widget_set_sensitive (cd->edit_button, commodity != NULL);
264  gtk_widget_set_sensitive (cd->remove_button, remove_ok);
265 }
266 
267 void
268 gnc_commodities_show_currencies_toggled (GtkToggleButton *toggle,
269  CommoditiesDialog *cd)
270 {
271 
272  cd->show_currencies = gtk_toggle_button_get_active (toggle);
273  gnc_tree_view_commodity_refilter (cd->commodity_tree);
274 }
275 
276 static gboolean
277 gnc_commodities_dialog_filter_ns_func (gnc_commodity_namespace *name_space,
278  gpointer data)
279 {
280  CommoditiesDialog *cd = data;
281  const gchar *name;
282  GList *list;
283 
284  /* Never show the template list */
285  name = gnc_commodity_namespace_get_name (name_space);
286  if (g_strcmp0 (name, "template") == 0)
287  return FALSE;
288 
289  /* Check whether or not to show commodities */
290  if (!cd->show_currencies && gnc_commodity_namespace_is_iso(name))
291  return FALSE;
292 
293  /* Show any other namespace that has commodities */
295  return (list != NULL);
296 }
297 
298 static gboolean
299 gnc_commodities_dialog_filter_cm_func (gnc_commodity *commodity,
300  gpointer data)
301 {
302  CommoditiesDialog *cd = data;
303 
304  if (cd->show_currencies)
305  return TRUE;
306  return !gnc_commodity_is_iso(commodity);
307 }
308 
309 static void
310 gnc_commodities_dialog_create (GtkWidget * parent, CommoditiesDialog *cd)
311 {
312  GtkWidget *button;
313  GtkWidget *scrolled_window;
314  GtkBuilder *builder;
315  GtkTreeView *view;
316  GtkTreeSelection *selection;
317 
318  builder = gtk_builder_new();
319  gnc_builder_add_from_file (builder, "dialog-commodities.glade", "Securities Dialog");
320 
321  cd->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Securities Dialog"));
322  cd->session = gnc_get_current_session();
323  cd->book = qof_session_get_book(cd->session);
324  cd->show_currencies = gnc_prefs_get_bool(GNC_PREFS_GROUP, GNC_PREF_INCL_ISO);
325 
326  gtk_builder_connect_signals(builder, cd);
327 
328  /* parent */
329  if (parent != NULL)
330  gtk_window_set_transient_for (GTK_WINDOW (cd->dialog), GTK_WINDOW (parent));
331 
332  /* buttons */
333  cd->remove_button = GTK_WIDGET(gtk_builder_get_object (builder, "remove_button"));
334  cd->edit_button = GTK_WIDGET(gtk_builder_get_object (builder, "edit_button"));
335 
336  /* commodity tree */
337 
338  scrolled_window = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_list_window"));
339  view = gnc_tree_view_commodity_new(cd->book,
340  "state-section", STATE_SECTION,
341  "show-column-menu", TRUE,
342  NULL);
343  cd->commodity_tree = GNC_TREE_VIEW_COMMODITY(view);
344  gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(view));
345  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cd->commodity_tree), TRUE);
346  gnc_tree_view_commodity_set_filter (cd->commodity_tree,
347  gnc_commodities_dialog_filter_ns_func,
348  gnc_commodities_dialog_filter_cm_func,
349  cd, NULL);
350  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
351  g_signal_connect (G_OBJECT (selection), "changed",
352  G_CALLBACK (gnc_commodities_dialog_selection_changed), cd);
353 
354  g_signal_connect (G_OBJECT (cd->commodity_tree), "row-activated",
355  G_CALLBACK (row_activated_cb), cd);
356 
357  /* Show currency button */
358  button = GTK_WIDGET(gtk_builder_get_object (builder, "show_currencies_button"));
359  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), cd->show_currencies);
360 
361  g_object_unref(G_OBJECT(builder));
362  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(cd->dialog));
363 }
364 
365 static void
366 close_handler (gpointer user_data)
367 {
368  CommoditiesDialog *cd = user_data;
369 
370  gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(cd->dialog));
371 
372  gnc_prefs_set_bool(GNC_PREFS_GROUP, GNC_PREF_INCL_ISO, cd->show_currencies);
373 
374  gtk_widget_destroy(cd->dialog);
375 }
376 
377 static void
378 refresh_handler (GHashTable *changes, gpointer user_data)
379 {
380  CommoditiesDialog *cd = user_data;
381 
382  g_return_if_fail(cd != NULL);
383 
384  gnc_tree_view_commodity_refilter (cd->commodity_tree);
385 }
386 
387 static gboolean
388 show_handler (const char *klass, gint component_id,
389  gpointer user_data, gpointer iter_data)
390 {
391  CommoditiesDialog *cd = user_data;
392 
393  if (!cd)
394  return(FALSE);
395  gtk_window_present (GTK_WINDOW(cd->dialog));
396  return(TRUE);
397 }
398 
399 /********************************************************************\
400  * gnc_commodities_dialog *
401  * opens up a window to edit price information *
402  * *
403  * Args: parent - the parent of the window to be created *
404  * Return: nothing *
405 \********************************************************************/
406 void
407 gnc_commodities_dialog (GtkWidget * parent)
408 {
409  CommoditiesDialog *cd;
410  gint component_id;
411 
412  if (gnc_forall_gui_components (DIALOG_COMMODITIES_CM_CLASS,
413  show_handler, NULL))
414  return;
415 
416  cd = g_new0 (CommoditiesDialog, 1);
417 
418  gnc_commodities_dialog_create (parent, cd);
419 
420  component_id = gnc_register_gui_component (DIALOG_COMMODITIES_CM_CLASS,
421  refresh_handler, close_handler,
422  cd);
423  gnc_gui_component_set_session (component_id, cd->session);
424 
425  gtk_widget_grab_focus (GTK_WIDGET(cd->commodity_tree));
426 
427  gtk_widget_show (cd->dialog);
428 }
void gnc_price_list_destroy(PriceList *prices)
Definition: gnc-pricedb.c:701
GtkTreeView * gnc_tree_view_commodity_new(QofBook *book, const gchar *first_property_name,...)
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
void gnc_tree_view_commodity_set_filter(GncTreeViewCommodity *view, gnc_tree_view_commodity_ns_filter_func ns_func, gnc_tree_view_commodity_cm_filter_func cm_func, gpointer data, GDestroyNotify destroy)
utility functions for the GnuCash UI
gnc_commodity * gnc_ui_new_commodity_modal(const char *default_namespace, GtkWidget *parent)
gboolean gnc_ui_edit_commodity_modal(gnc_commodity *commodity, GtkWidget *parent)
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
GList * gnc_commodity_namespace_get_commodity_list(const gnc_commodity_namespace *name_space)
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Definition: gnc-pricedb.c:872
const char * gnc_commodity_namespace_get_name(const gnc_commodity_namespace *ns)
QofBook * qof_session_get_book(const QofSession *session)
gboolean gnc_prefs_set_bool(const gchar *group, const gchar *pref_name, gboolean value)
Definition: gnc-prefs.c:282
gboolean gnc_commodity_namespace_is_iso(const char *name_space)
Gnome specific utility functions.
gboolean gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
Definition: gnc-pricedb.c:1160
Generic api to store and retrieve preferences.
GList * gnc_account_get_descendants(const Account *account)
Definition: Account.c:2755
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
gnc_commodity * gnc_tree_view_commodity_get_selected_commodity(GncTreeViewCommodity *view)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:196
GtkTreeView implementation for gnucash commodity tree.
void gnc_commodity_table_remove(gnc_commodity_table *table, gnc_commodity *comm)
void gnc_tree_view_commodity_refilter(GncTreeViewCommodity *view)
"select" and "new" commodity windows
Commodity handling public routines.
void gnc_commodity_destroy(gnc_commodity *cm)
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
PriceList * gnc_pricedb_get_prices(GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency)
Definition: gnc-pricedb.c:1479