00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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 (
00171
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
00289
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
00326 name = gnc_commodity_namespace_get_name (namespace);
00327 if (safe_strcmp (name, "template") == 0)
00328 return FALSE;
00329
00330
00331 cm_list = gnc_commodity_namespace_get_commodity_list(namespace);
00332 for (item = cm_list; item; item = g_list_next(item)) {
00333
00334
00335 if (gnc_pricedb_has_prices(pdb_dialog->price_db, item->data, NULL)) {
00336 return TRUE;
00337 }
00338 }
00339
00340
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
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
00369
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
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
00402 if (parent != NULL)
00403 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
00404
00405
00406 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
00407
00408
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
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
00488
00489
00490
00491
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 }