dialog-price-edit-db.c

00001 /********************************************************************\
00002  * dialog-price-editor.c -- price selector 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 #include <libguile.h>
00030 #include "guile-mappings.h"
00031 #include <time.h>
00032 
00033 #include "dialog-utils.h"
00034 #include "gnc-amount-edit.h"
00035 #include "gnc-commodity-edit.h"
00036 #include "gnc-general-select.h"
00037 #include "gnc-component-manager.h"
00038 #include "gnc-currency-edit.h"
00039 #include "gnc-date-edit.h"
00040 #include "gnc-engine.h"
00041 #include "gnc-gui-query.h"
00042 #include "gnc-pricedb.h"
00043 #include "gnc-session.h"
00044 #include "gnc-tree-view-price.h"
00045 #include "gnc-ui.h"
00046 #include "gnc-ui-util.h"
00047 #include "guile-util.h"
00048 #include "engine-helpers.h"
00049 #include "swig-runtime.h"
00050 
00051 
00052 #define DIALOG_PRICE_DB_CM_CLASS "dialog-price-edit-db"
00053 #define GCONF_SECTION "dialogs/edit_prices"
00054 
00055 /* This static indicates the debugging module that this .o belongs to.  */
00056 static QofLogModule log_module = GNC_MOD_GUI;
00057 
00058 
00059 void gnc_prices_dialog_window_destroy_cb (GtkObject *object, gpointer data);
00060 void gnc_prices_dialog_close_cb (GtkDialog *dialog, gpointer data);
00061 void gnc_prices_dialog_response (GtkDialog *dialog, gint response_id, gpointer data);
00062 void gnc_prices_dialog_edit_clicked (GtkWidget *widget, gpointer data);
00063 void gnc_prices_dialog_remove_clicked (GtkWidget *widget, gpointer data);
00064 void gnc_prices_dialog_remove_old_clicked (GtkWidget *widget, gpointer data);
00065 void gnc_prices_dialog_add_clicked (GtkWidget *widget, gpointer data);
00066 void gnc_prices_dialog_get_quotes_clicked (GtkWidget *widget, gpointer data);
00067 
00068 
00069 typedef struct
00070 {
00071   GtkWidget * dialog;
00072   QofSession *session;
00073   QofBook *book;
00074   GNCPriceDB *price_db;
00075 
00076   GncTreeViewPrice * price_tree;
00077 
00078   GtkWidget * edit_button;
00079   GtkWidget * remove_button;
00080 } PricesDialog;
00081 
00082 
00083 void
00084 gnc_prices_dialog_window_destroy_cb (GtkObject *object, gpointer data)
00085 {
00086   PricesDialog *pdb_dialog = data;
00087 
00088   ENTER(" ");
00089   gnc_unregister_gui_component_by_data (DIALOG_PRICE_DB_CM_CLASS, pdb_dialog);
00090 
00091   if (pdb_dialog->dialog) {
00092     gtk_widget_destroy(pdb_dialog->dialog);
00093     pdb_dialog->dialog = NULL;
00094   }
00095 
00096   g_free (pdb_dialog);
00097   LEAVE(" ");
00098 }
00099 
00100 void
00101 gnc_prices_dialog_close_cb (GtkDialog *dialog, gpointer data)
00102 {
00103   PricesDialog *pdb_dialog = data;
00104 
00105   ENTER(" ");
00106   gnc_close_gui_component_by_data (DIALOG_PRICE_DB_CM_CLASS, pdb_dialog);
00107   LEAVE(" ");
00108 }
00109 
00110 void
00111 gnc_prices_dialog_response (GtkDialog *dialog, gint response_id, gpointer data)
00112 {
00113   PricesDialog *pdb_dialog = data;
00114 
00115   ENTER(" ");
00116   gnc_close_gui_component_by_data (DIALOG_PRICE_DB_CM_CLASS, pdb_dialog);
00117   LEAVE(" ");
00118 }
00119 
00120 void
00121 gnc_prices_dialog_edit_clicked (GtkWidget *widget, gpointer data)
00122 {
00123   PricesDialog *pdb_dialog = data;
00124   GList *price_list;
00125 
00126   ENTER(" ");
00127   price_list = gnc_tree_view_price_get_selected_prices(pdb_dialog->price_tree);
00128   if (!price_list) {
00129     LEAVE("no price selected");
00130     return;
00131   }
00132   if (g_list_next(price_list)) {
00133     g_list_free(price_list);
00134     LEAVE("too many prices selected");
00135     return;
00136   }
00137 
00138   gnc_price_edit_dialog (pdb_dialog->dialog, pdb_dialog->session,
00139                          price_list->data, GNC_PRICE_EDIT);
00140   g_list_free(price_list);
00141   LEAVE(" ");
00142 }
00143 
00144 static void
00145 remove_helper(GNCPrice *price, GNCPriceDB *pdb)
00146 {
00147   gnc_pricedb_remove_price (pdb, price);
00148 }
00149 
00150 void
00151 gnc_prices_dialog_remove_clicked (GtkWidget *widget, gpointer data)
00152 {
00153   PricesDialog *pdb_dialog = data;
00154   GList *price_list;
00155   gint length, response;
00156   GtkWidget *dialog;
00157 
00158   ENTER(" ");
00159   price_list = gnc_tree_view_price_get_selected_prices(pdb_dialog->price_tree);
00160   if (!price_list) {
00161     LEAVE("no price selected");
00162     return;
00163   }
00164 
00165   length = g_list_length(price_list);
00166   if (length > 1) {
00167     gchar *message;
00168 
00169     message = g_strdup_printf
00170       (/* Translators: %d is the number of prices. This
00171           is a ngettext(3) message. */
00172        ngettext("Are you sure you want to delete the %d selected price?",
00173                 "Are you sure you want to delete the %d selected prices?",
00174                 length),
00175        length);
00176     dialog = gtk_message_dialog_new(GTK_WINDOW(pdb_dialog->dialog),
00177                                     GTK_DIALOG_DESTROY_WITH_PARENT,
00178                                     GTK_MESSAGE_QUESTION,
00179                                     GTK_BUTTONS_NONE,
00180                                     "%s", _("Delete prices?"));
00181     gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
00182                                              "%s", message);
00183     g_free(message);
00184     gtk_dialog_add_buttons(GTK_DIALOG(dialog),
00185                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00186                            GTK_STOCK_DELETE, GTK_RESPONSE_YES,
00187                            (gchar *)NULL);
00188     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
00189     response = gnc_dialog_run(GTK_DIALOG(dialog), "pricedb_remove_multiple");
00190     gtk_widget_destroy(dialog);
00191   } else {
00192     response = GTK_RESPONSE_YES;
00193   }
00194 
00195   if (response == GTK_RESPONSE_YES) {
00196     g_list_foreach(price_list, (GFunc)remove_helper, pdb_dialog->price_db);
00197   }
00198   g_list_free(price_list);
00199   LEAVE(" ");
00200 }
00201 
00202 void
00203 gnc_prices_dialog_remove_old_clicked (GtkWidget *widget, gpointer data)
00204 {
00205   PricesDialog *pdb_dialog = data;
00206   GladeXML *xml;
00207   GtkWidget *dialog, *button, *date, *label;
00208   gint result;
00209   gboolean delete_user, delete_last;
00210 
00211   ENTER(" ");
00212   xml = gnc_glade_xml_new ("price.glade", "Deletion Date");
00213   dialog = glade_xml_get_widget (xml, "Deletion Date");
00214   date = glade_xml_get_widget (xml, "date");
00215   label = glade_xml_get_widget (xml, "date_label");
00216   gnc_date_make_mnemonic_target (GNC_DATE_EDIT(date), label);
00217   glade_xml_signal_autoconnect_full(xml, gnc_glade_autoconnect_full_func, pdb_dialog);
00218   gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (pdb_dialog->dialog));
00219 
00220   result = gtk_dialog_run (GTK_DIALOG (dialog));
00221   if (result == GTK_RESPONSE_OK)
00222   {
00223     Timespec ts;
00224 
00225     DEBUG("deleting prices");
00226     ts.tv_sec = gnc_date_edit_get_date (GNC_DATE_EDIT (date));
00227     ts.tv_nsec = 0;
00228 
00229     button = glade_xml_get_widget (xml, "delete_manual");
00230     delete_user = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
00231     button = glade_xml_get_widget (xml, "delete_last");
00232     delete_last = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
00233 
00234     gnc_pricedb_remove_old_prices(pdb_dialog->price_db, ts,
00235                                   delete_user, delete_last);
00236   }
00237 
00238   gtk_widget_destroy(dialog);
00239   LEAVE(" ");
00240 }
00241 
00242 void
00243 gnc_prices_dialog_add_clicked (GtkWidget *widget, gpointer data)
00244 {
00245   PricesDialog *pdb_dialog = data;
00246   GNCPrice *price = NULL;
00247   GList *price_list;
00248 
00249   ENTER(" ");
00250   price_list = gnc_tree_view_price_get_selected_prices(pdb_dialog->price_tree);
00251   if (price_list) {
00252     price = price_list->data;
00253     g_list_free(price_list);
00254   }
00255   gnc_price_edit_dialog (pdb_dialog->dialog, pdb_dialog->session,
00256                          price, GNC_PRICE_NEW);
00257   LEAVE(" ");
00258 }
00259 
00260 void
00261 gnc_prices_dialog_get_quotes_clicked (GtkWidget *widget, gpointer data)
00262 {
00263   PricesDialog *pdb_dialog = data;
00264   SCM quotes_func;
00265   SCM book_scm;
00266   SCM scm_window;
00267 
00268   ENTER(" ");
00269   quotes_func = scm_c_eval_string ("gnc:book-add-quotes");
00270   if (!SCM_PROCEDUREP (quotes_func)) {
00271     LEAVE(" no procedure");
00272     return;
00273   }
00274 
00275   book_scm = gnc_book_to_scm (pdb_dialog->book);
00276   if (SCM_NFALSEP (scm_not (book_scm))) {
00277     LEAVE("no book");
00278     return;
00279   }
00280 
00281   scm_window =  SWIG_NewPointerObj(pdb_dialog->dialog,
00282                                    SWIG_TypeQuery("_p_GtkWidget"), 0);
00283 
00284   gnc_set_busy_cursor (NULL, TRUE);
00285   scm_call_2 (quotes_func, scm_window, book_scm);
00286   gnc_unset_busy_cursor (NULL);
00287 
00288   /* Without this, the summary bar on the accounts tab
00289    * won't reflect the new prices (bug #522095). */
00290   gnc_gui_refresh_all ();
00291 
00292   LEAVE(" ");
00293 }
00294 
00295 
00296 static void
00297 gnc_prices_dialog_selection_changed (GtkTreeSelection *treeselection,
00298                                      gpointer data)
00299 {
00300   PricesDialog *pdb_dialog = data;
00301   GList *price_list;
00302   gint length;
00303 
00304   ENTER(" ");
00305   price_list = gnc_tree_view_price_get_selected_prices(pdb_dialog->price_tree);
00306   length = g_list_length(price_list);
00307 
00308   gtk_widget_set_sensitive (pdb_dialog->edit_button,
00309                             length == 1);
00310   gtk_widget_set_sensitive (pdb_dialog->remove_button,
00311                             length >= 1);
00312   LEAVE("%d prices selected", length);
00313 }
00314 
00315 
00316 static gboolean
00317 gnc_price_dialog_filter_ns_func (gnc_commodity_namespace *namespace,
00318                                  gpointer data)
00319 {
00320   PricesDialog *pdb_dialog = data;
00321   const gchar *name;
00322   static GList *cm_list;
00323   GList *item;
00324 
00325   /* Never show the template list */
00326   name = gnc_commodity_namespace_get_name (namespace);
00327   if (safe_strcmp (name, "template") == 0)
00328     return FALSE;
00329 
00330   /* See if this namespace has commodities */
00331   cm_list = gnc_commodity_namespace_get_commodity_list(namespace);
00332   for (item = cm_list; item; item = g_list_next(item)) {
00333 
00334     /* For each commodity, see if there are prices */
00335     if (gnc_pricedb_has_prices(pdb_dialog->price_db, item->data, NULL)) {
00336       return TRUE;
00337     }
00338   }
00339 
00340   //  printf("Namespace %s not visible\n", name);
00341   return FALSE;
00342 }
00343 
00344 static gboolean
00345 gnc_price_dialog_filter_cm_func (gnc_commodity *commodity,
00346                                  gpointer data)
00347 {
00348   PricesDialog *pdb_dialog = data;
00349 
00350   /* Show any commodity that has prices */
00351   return gnc_pricedb_has_prices(pdb_dialog->price_db, commodity, NULL);
00352 }
00353 
00354 static void
00355 row_activated_cb (GtkTreeView *view, GtkTreePath *path,
00356                   GtkTreeViewColumn *column, gpointer data)
00357 {
00358   GtkTreeModel *model;
00359   GtkTreeIter iter;
00360 
00361   g_return_if_fail(view);
00362 
00363   model = gtk_tree_view_get_model(view);
00364   if (gtk_tree_model_get_iter(model, &iter, path))
00365   {
00366     if (gtk_tree_model_iter_has_child(model, &iter))
00367     {
00368       /* There are children, so it's not a price.
00369        * Just expand or collapse the row. */
00370       if (gtk_tree_view_row_expanded(view, path))
00371         gtk_tree_view_collapse_row(view, path);
00372       else
00373         gtk_tree_view_expand_row(view, path, FALSE);
00374     }
00375     else
00376       /* It's a price, so click the Edit button. */
00377       gnc_prices_dialog_edit_clicked(GTK_WIDGET(view), data);
00378   }
00379 }
00380 
00381 static void
00382 gnc_prices_dialog_create (GtkWidget * parent, PricesDialog *pdb_dialog)
00383 {
00384   GtkWidget *dialog, *scrolled_window;
00385   GladeXML *xml;
00386   GtkTreeView *view;
00387   GtkTreeSelection *selection;
00388 
00389   ENTER(" ");
00390   xml = gnc_glade_xml_new ("price.glade", "Prices Dialog");
00391 
00392   dialog = glade_xml_get_widget (xml, "Prices Dialog");
00393   pdb_dialog->dialog = dialog;
00394 
00395   pdb_dialog->session = gnc_get_current_session();
00396   pdb_dialog->book = qof_session_get_book(pdb_dialog->session);
00397   pdb_dialog->price_db = gnc_pricedb_get_db(pdb_dialog->book);
00398 
00399   glade_xml_signal_autoconnect_full(xml, gnc_glade_autoconnect_full_func, pdb_dialog);
00400 
00401   /* parent */
00402   if (parent != NULL)
00403     gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
00404 
00405   /* default to 'close' button */
00406   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
00407 
00408   /* price tree */
00409   scrolled_window = glade_xml_get_widget (xml, "price_list_window");
00410   view = gnc_tree_view_price_new(pdb_dialog->book,
00411                                  "gconf-section", GCONF_SECTION,
00412                                  "show-column-menu", TRUE,
00413                                  NULL);
00414   pdb_dialog->price_tree = GNC_TREE_VIEW_PRICE(view);
00415   gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET(view));
00416   gnc_tree_view_price_set_filter (pdb_dialog->price_tree,
00417                                   gnc_price_dialog_filter_ns_func,
00418                                   gnc_price_dialog_filter_cm_func,
00419                                   NULL,
00420                                   pdb_dialog, NULL);
00421 
00422   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
00423   gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
00424   g_signal_connect (G_OBJECT (selection), "changed",
00425                     G_CALLBACK (gnc_prices_dialog_selection_changed), pdb_dialog);
00426 
00427   g_signal_connect (G_OBJECT (view), "row-activated",
00428                     G_CALLBACK (row_activated_cb), pdb_dialog);
00429 
00430   /* buttons */
00431   {
00432     GtkWidget *button;
00433 
00434     button = glade_xml_get_widget (xml, "edit_button");
00435     pdb_dialog->edit_button = button;
00436 
00437     button = glade_xml_get_widget (xml, "remove_button");
00438     pdb_dialog->remove_button = button;
00439 
00440     if (!gnc_quote_source_fq_installed()) {
00441       button = glade_xml_get_widget (xml, "get_quotes_button");
00442       gtk_widget_set_sensitive(button, FALSE);
00443     }
00444   }
00445 
00446   gnc_restore_window_size(GCONF_SECTION, GTK_WINDOW(pdb_dialog->dialog));
00447   LEAVE(" ");
00448 }
00449 
00450 static void
00451 close_handler (gpointer user_data)
00452 {
00453   PricesDialog *pdb_dialog = user_data;
00454 
00455   ENTER(" ");
00456   gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(pdb_dialog->dialog));
00457 
00458   gtk_widget_destroy (GTK_WIDGET (pdb_dialog->dialog));
00459   LEAVE(" ");
00460 }
00461 
00462 static void
00463 refresh_handler (GHashTable *changes, gpointer user_data)
00464 {
00465   ENTER(" ");
00466   LEAVE(" ");
00467 }
00468 
00469 static gboolean
00470 show_handler (const char *class, gint component_id,
00471               gpointer user_data, gpointer iter_data)
00472 {
00473   PricesDialog *pdb_dialog = user_data;
00474 
00475   ENTER(" ");
00476   if (!pdb_dialog) {
00477     LEAVE("no data strucure");
00478     return(FALSE);
00479   }
00480 
00481   gtk_window_present (GTK_WINDOW(pdb_dialog->dialog));
00482   LEAVE(" ");
00483   return(TRUE);
00484 }
00485 
00486 /********************************************************************\
00487  * gnc_prices_dialog                                                *
00488  *   opens up a window showing all price information                *
00489  *                                                                  * 
00490  * Args:   parent  - the parent of the window to be created         *
00491  * Return: nothing                                                  *
00492 \********************************************************************/
00493 void
00494 gnc_prices_dialog (GtkWidget * parent)
00495 {
00496   PricesDialog *pdb_dialog;
00497   gint component_id;
00498 
00499   ENTER(" ");
00500   if (gnc_forall_gui_components (DIALOG_PRICE_DB_CM_CLASS, show_handler, NULL)) {
00501       LEAVE("existing dialog raised");
00502       return;
00503   }
00504 
00505   pdb_dialog = g_new0 (PricesDialog, 1);
00506 
00507   gnc_prices_dialog_create (parent, pdb_dialog);
00508 
00509   component_id = gnc_register_gui_component (DIALOG_PRICE_DB_CM_CLASS,
00510                                              refresh_handler, close_handler,
00511                                              pdb_dialog);
00512   gnc_gui_component_set_session (component_id, pdb_dialog->session);
00513 
00514   gtk_widget_grab_focus (GTK_WIDGET(pdb_dialog->price_tree));
00515 
00516   gtk_widget_show (pdb_dialog->dialog);
00517   LEAVE(" ");
00518 }

Generated on Thu Aug 28 05:05:26 2008 for GnuCash by  doxygen 1.5.2