GnuCash 2.4.99
dialog-commodities.c
00001 /********************************************************************\
00002  * dialog-commodities.c -- commodities dialog                       *
00003  * Copyright (C) 2001 Gnumatic, Inc.                                *
00004  * Author: Dave Peticolas <dave@krondo.com>                         *
00005  * Copyright (C) 2003,2005 David Hampton                            *
00006  *                                                                  *
00007  * This program is free software; you can redistribute it and/or    *
00008  * modify it under the terms of the GNU General Public License as   *
00009  * published by the Free Software Foundation; either version 2 of   *
00010  * the License, or (at your option) any later version.              *
00011  *                                                                  *
00012  * This program is distributed in the hope that it will be useful,  *
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00015  * GNU General Public License for more details.                     *
00016  *                                                                  *
00017  * You should have received a copy of the GNU General Public License*
00018  * along with this program; if not, contact:                        *
00019  *                                                                  *
00020  * Free Software Foundation           Voice:  +1-617-542-5942       *
00021  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00022  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00023 \********************************************************************/
00024 
00025 #include "config.h"
00026 
00027 #include <gtk/gtk.h>
00028 #include <glib/gi18n.h>
00029 
00030 #include "dialog-commodity.h"
00031 #include "dialog-utils.h"
00032 #include "gnc-commodity.h"
00033 #include "gnc-component-manager.h"
00034 #include "qof.h"
00035 #include "gnc-tree-view-commodity.h"
00036 #include "gnc-ui.h"
00037 #include "gnc-ui-util.h"
00038 #include "gnc-gconf-utils.h"
00039 #include "gnc-gnome-utils.h"
00040 #include "gnc-session.h"
00041 
00042 
00043 #define DIALOG_COMMODITIES_CM_CLASS "dialog-commodities"
00044 #define GCONF_SECTION "dialogs/edit_commodities"
00045 
00046 /* This static indicates the debugging module that this .o belongs to.  */
00047 /* static short module = MOD_GUI; */
00048 
00049 typedef struct
00050 {
00051     GtkWidget * dialog;
00052     QofSession *session;
00053     QofBook *book;
00054 
00055     GncTreeViewCommodity * commodity_tree;
00056     GtkWidget * edit_button;
00057     GtkWidget * remove_button;
00058     gboolean    show_currencies;
00059 
00060     gboolean new;
00061 } CommoditiesDialog;
00062 
00063 
00064 void gnc_commodities_window_destroy_cb (GtkObject *object, CommoditiesDialog *cd);
00065 void gnc_commodities_dialog_response (GtkDialog *dialog, gint response, CommoditiesDialog *cd);
00066 void gnc_commodities_show_currencies_toggled (GtkToggleButton *toggle, CommoditiesDialog *cd);
00067 
00068 
00069 
00070 void
00071 gnc_commodities_window_destroy_cb (GtkObject *object,   CommoditiesDialog *cd)
00072 {
00073     gnc_unregister_gui_component_by_data (DIALOG_COMMODITIES_CM_CLASS, cd);
00074 
00075     g_free (cd);
00076 }
00077 
00078 static void
00079 edit_clicked (CommoditiesDialog *cd)
00080 {
00081     gnc_commodity *commodity;
00082 
00083     commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
00084     if (commodity == NULL)
00085         return;
00086 
00087     if (gnc_ui_edit_commodity_modal (commodity, cd->dialog))
00088         gnc_gui_refresh_all ();
00089 }
00090 
00091 static void
00092 row_activated_cb (GtkTreeView *view, GtkTreePath *path,
00093                   GtkTreeViewColumn *column, CommoditiesDialog *cd)
00094 {
00095     GtkTreeModel *model;
00096     GtkTreeIter iter;
00097 
00098     g_return_if_fail(view);
00099 
00100     model = gtk_tree_view_get_model(view);
00101     if (gtk_tree_model_get_iter(model, &iter, path))
00102     {
00103         if (gtk_tree_model_iter_has_child(model, &iter))
00104         {
00105             /* There are children, so it's not a commodity.
00106              * Just expand or collapse the row. */
00107             if (gtk_tree_view_row_expanded(view, path))
00108                 gtk_tree_view_collapse_row(view, path);
00109             else
00110                 gtk_tree_view_expand_row(view, path, FALSE);
00111         }
00112         else
00113             /* It's a commodity, so click the Edit button. */
00114             edit_clicked(cd);
00115     }
00116 }
00117 
00118 static void
00119 remove_clicked (CommoditiesDialog *cd)
00120 {
00121     GNCPriceDB *pdb;
00122     GList *node;
00123     GList *prices;
00124     GList *accounts;
00125     gboolean do_delete;
00126     gboolean can_delete;
00127     gnc_commodity *commodity;
00128     GtkWidget *dialog;
00129     const gchar *message, *warning;
00130     gint response;
00131 
00132     commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
00133     if (commodity == NULL)
00134         return;
00135 
00136     accounts = gnc_account_get_descendants (gnc_book_get_root_account(cd->book));
00137     can_delete = TRUE;
00138     do_delete = FALSE;
00139 
00140     for (node = accounts; node; node = node->next)
00141     {
00142         Account *account = node->data;
00143 
00144         if (commodity == xaccAccountGetCommodity (account))
00145         {
00146             can_delete = FALSE;
00147             break;
00148         }
00149     }
00150 
00151     /* FIXME check for transaction references */
00152 
00153     if (!can_delete)
00154     {
00155         const char *message = _("That commodity is currently used by "
00156                                 "at least one of your accounts. You may "
00157                                 "not delete it.");
00158 
00159         gnc_warning_dialog (cd->dialog, "%s", message);
00160         g_list_free (accounts);
00161         return;
00162     }
00163     g_list_free (accounts);
00164 
00165     pdb = gnc_pricedb_get_db (cd->book);
00166     prices = gnc_pricedb_get_prices(pdb, commodity, NULL);
00167     if (prices)
00168     {
00169         message = _("This commodity has price quotes. Are "
00170                     "you sure you want to delete the selected "
00171                     "commodity and its price quotes?");
00172         warning = "delete_commodity2";
00173     }
00174     else
00175     {
00176         message = _("Are you sure you want to delete the "
00177                     "selected commodity?");
00178         warning = "delete_commodity";
00179     }
00180 
00181     dialog = gtk_message_dialog_new(GTK_WINDOW(cd->dialog),
00182                                     GTK_DIALOG_DESTROY_WITH_PARENT,
00183                                     GTK_MESSAGE_QUESTION,
00184                                     GTK_BUTTONS_NONE,
00185                                     "%s", _("Delete commodity?"));
00186     gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
00187             "%s", message);
00188     gtk_dialog_add_buttons(GTK_DIALOG(dialog),
00189                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00190                            GTK_STOCK_DELETE, GTK_RESPONSE_OK,
00191                            (gchar *)NULL);
00192     response = gnc_dialog_run(GTK_DIALOG(dialog), warning);
00193     gtk_widget_destroy(dialog);
00194 
00195     if (response == GTK_RESPONSE_OK)
00196     {
00197         gnc_commodity_table *ct;
00198 
00199         ct = gnc_commodity_table_get_table (cd->book);
00200         for (node = prices; node; node = node->next)
00201             gnc_pricedb_remove_price(pdb, node->data);
00202 
00203         gnc_commodity_table_remove (ct, commodity);
00204         gnc_commodity_destroy (commodity);
00205         commodity = NULL;
00206     }
00207 
00208     gnc_price_list_destroy(prices);
00209     gnc_gui_refresh_all ();
00210 }
00211 
00212 static void
00213 add_clicked (CommoditiesDialog *cd)
00214 {
00215     gnc_commodity *commodity;
00216     const char *namespace;
00217 
00218     commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
00219     if (commodity)
00220         namespace = gnc_commodity_get_namespace (commodity);
00221     else
00222         namespace = NULL;
00223 
00224     commodity = gnc_ui_new_commodity_modal (namespace, cd->dialog);
00225 }
00226 
00227 void
00228 gnc_commodities_dialog_response (GtkDialog *dialog,
00229                                  gint response,
00230                                  CommoditiesDialog *cd)
00231 {
00232     switch (response)
00233     {
00234     case GNC_RESPONSE_NEW:
00235         add_clicked (cd);
00236         return;
00237 
00238     case GNC_RESPONSE_DELETE:
00239         remove_clicked (cd);
00240         return;
00241 
00242     case GNC_RESPONSE_EDIT:
00243         edit_clicked (cd);
00244         return;
00245 
00246     case GTK_RESPONSE_CLOSE:
00247     default:
00248         gnc_close_gui_component_by_data (DIALOG_COMMODITIES_CM_CLASS, cd);
00249         return;
00250     }
00251 }
00252 
00253 static void
00254 gnc_commodities_dialog_selection_changed (GtkTreeSelection *selection,
00255         CommoditiesDialog *cd)
00256 {
00257     gboolean remove_ok;
00258     gnc_commodity *commodity;
00259 
00260     commodity = gnc_tree_view_commodity_get_selected_commodity (cd->commodity_tree);
00261     remove_ok = commodity && !gnc_commodity_is_iso(commodity);
00262     gtk_widget_set_sensitive (cd->edit_button, commodity != NULL);
00263     gtk_widget_set_sensitive (cd->remove_button, remove_ok);
00264 }
00265 
00266 void
00267 gnc_commodities_show_currencies_toggled (GtkToggleButton *toggle,
00268         CommoditiesDialog *cd)
00269 {
00270 
00271     cd->show_currencies = gtk_toggle_button_get_active (toggle);
00272     gnc_tree_view_commodity_refilter (cd->commodity_tree);
00273 }
00274 
00275 static gboolean
00276 gnc_commodities_dialog_filter_ns_func (gnc_commodity_namespace *namespace,
00277                                        gpointer data)
00278 {
00279     CommoditiesDialog *cd = data;
00280     const gchar *name;
00281     GList *list;
00282 
00283     /* Never show the template list */
00284     name = gnc_commodity_namespace_get_name (namespace);
00285     if (safe_strcmp (name, "template") == 0)
00286         return FALSE;
00287 
00288     /* Check whether or not to show commodities */
00289     if (!cd->show_currencies && gnc_commodity_namespace_is_iso(name))
00290         return FALSE;
00291 
00292     /* Show any other namespace that has commodities */
00293     list = gnc_commodity_namespace_get_commodity_list(namespace);
00294     return (list != NULL);
00295 }
00296 
00297 static gboolean
00298 gnc_commodities_dialog_filter_cm_func (gnc_commodity *commodity,
00299                                        gpointer data)
00300 {
00301     CommoditiesDialog *cd = data;
00302 
00303     if (cd->show_currencies)
00304         return TRUE;
00305     return !gnc_commodity_is_iso(commodity);
00306 }
00307 
00308 static void
00309 gnc_commodities_dialog_create (GtkWidget * parent, CommoditiesDialog *cd)
00310 {
00311     GtkWidget *button;
00312     GtkWidget *scrolled_window;
00313     GtkBuilder *builder;
00314     GtkTreeView *view;
00315     GtkTreeSelection *selection;
00316 
00317     builder = gtk_builder_new();
00318     gnc_builder_add_from_file (builder, "dialog-commodities.glade", "Securities Dialog");
00319 
00320     cd->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Securities Dialog"));
00321     cd->session = gnc_get_current_session();
00322     cd->book = qof_session_get_book(cd->session);
00323     cd->show_currencies = gnc_gconf_get_bool(GCONF_SECTION, "include_iso", NULL);
00324 
00325     gtk_builder_connect_signals(builder, cd);
00326 
00327     /* parent */
00328     if (parent != NULL)
00329         gtk_window_set_transient_for (GTK_WINDOW (cd->dialog), GTK_WINDOW (parent));
00330 
00331     /* buttons */
00332     cd->remove_button = GTK_WIDGET(gtk_builder_get_object (builder, "remove_button"));
00333     cd->edit_button = GTK_WIDGET(gtk_builder_get_object (builder, "edit_button"));
00334 
00335     /* commodity tree */
00336 
00337     scrolled_window = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_list_window"));
00338     view = gnc_tree_view_commodity_new(cd->book,
00339                                        "gconf-section", GCONF_SECTION,
00340                                        "show-column-menu", TRUE,
00341                                        NULL);
00342     cd->commodity_tree = GNC_TREE_VIEW_COMMODITY(view);
00343     gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(view));
00344     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cd->commodity_tree), TRUE);
00345     gnc_tree_view_commodity_set_filter (cd->commodity_tree,
00346                                         gnc_commodities_dialog_filter_ns_func,
00347                                         gnc_commodities_dialog_filter_cm_func,
00348                                         cd, NULL);
00349     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
00350     g_signal_connect (G_OBJECT (selection), "changed",
00351                       G_CALLBACK (gnc_commodities_dialog_selection_changed), cd);
00352 
00353     g_signal_connect (G_OBJECT (cd->commodity_tree), "row-activated",
00354                       G_CALLBACK (row_activated_cb), cd);
00355 
00356     /* Show currency button */
00357     button = GTK_WIDGET(gtk_builder_get_object (builder, "show_currencies_button"));
00358     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), cd->show_currencies);
00359 
00360     g_object_unref(G_OBJECT(builder));
00361     gnc_restore_window_size (GCONF_SECTION, GTK_WINDOW(cd->dialog));
00362 }
00363 
00364 static void
00365 close_handler (gpointer user_data)
00366 {
00367     CommoditiesDialog *cd = user_data;
00368 
00369     gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(cd->dialog));
00370 
00371     gnc_gconf_set_bool(GCONF_SECTION, "include_iso", cd->show_currencies, NULL);
00372 
00373     gtk_widget_destroy(cd->dialog);
00374 }
00375 
00376 static void
00377 refresh_handler (GHashTable *changes, gpointer user_data)
00378 {
00379     CommoditiesDialog *cd = user_data;
00380 
00381     g_return_if_fail(cd != NULL);
00382 
00383     gnc_tree_view_commodity_refilter (cd->commodity_tree);
00384 }
00385 
00386 static gboolean
00387 show_handler (const char *class, gint component_id,
00388               gpointer user_data, gpointer iter_data)
00389 {
00390     CommoditiesDialog *cd = user_data;
00391 
00392     if (!cd)
00393         return(FALSE);
00394     gtk_window_present (GTK_WINDOW(cd->dialog));
00395     return(TRUE);
00396 }
00397 
00398 /********************************************************************\
00399  * gnc_commodities_dialog                                           *
00400  *   opens up a window to edit price information                    *
00401  *                                                                  *
00402  * Args:   parent  - the parent of the window to be created         *
00403  * Return: nothing                                                  *
00404 \********************************************************************/
00405 void
00406 gnc_commodities_dialog (GtkWidget * parent)
00407 {
00408     CommoditiesDialog *cd;
00409     gint component_id;
00410 
00411     if (gnc_forall_gui_components (DIALOG_COMMODITIES_CM_CLASS,
00412                                    show_handler, NULL))
00413         return;
00414 
00415     cd = g_new0 (CommoditiesDialog, 1);
00416 
00417     gnc_commodities_dialog_create (parent, cd);
00418 
00419     component_id = gnc_register_gui_component (DIALOG_COMMODITIES_CM_CLASS,
00420                    refresh_handler, close_handler,
00421                    cd);
00422     gnc_gui_component_set_session (component_id, cd->session);
00423 
00424     gtk_widget_grab_focus (GTK_WIDGET(cd->commodity_tree));
00425 
00426     gtk_widget_show (cd->dialog);
00427 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines