|
GnuCash 2.4.99
|
00001 /* 00002 * assistant-gconf-setup.c -- install gconf keys where they can be found. 00003 * 00004 * Copyright (c) 2005 David Hampton <hampton@employees.org> 00005 * Copyright (c) 2011 Robert Fewell 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 00034 #include "config.h" 00035 00036 #include <gtk/gtk.h> 00037 #include <glib/gi18n.h> 00038 #include <glib/gstdio.h> 00039 #include <stdlib.h> 00040 #include <errno.h> 00041 #include <sys/types.h> 00042 00043 #include "dialog-utils.h" 00044 #include "assistant-gconf-setup.h" 00045 #include "assistant-utils.h" 00046 #include "gnc-path.h" 00047 #include "gnc-gconf-utils.h" 00048 #include "gnc-gui-query.h" 00049 #include "gnc-gnome-utils.h" 00050 #include "gnc-ui.h" 00051 00052 #define WHO_DOES "who_does" 00053 #define WHO_GNUCASH 1 00054 #define WHO_USER 2 00055 #define WHO_ALREADY_DONE 3 00056 00057 #define HOW "how" 00058 #define HOW_UPDATE 1 00059 #define HOW_INSTALL 2 00060 00061 #define SCRIPT_NAME "update-gnucash-gconf" 00062 00063 #define PATH_STRING1 "xml:readwrite:$(HOME)/.gconf\n" 00064 #define PATH_STRING2 "xml:readonly:%s\n" 00065 00066 typedef struct 00067 { 00068 GtkWidget *dialog; 00069 GtkWidget *assistant; 00070 GtkWidget *update_path; 00071 GtkWidget *install_data; 00072 GtkWidget *program1; 00073 GtkWidget *user1; 00074 GtkWidget *update_text; 00075 GtkWidget *program2; 00076 GtkWidget *user2; 00077 GtkWidget *install_text; 00078 GtkWidget *finish_page; 00079 00080 } gconf_data; 00081 00082 00083 /******************** 00084 * Declarations 00085 ********************/ 00086 void assistant_gconf_prepare (GtkAssistant *assistant, GtkWidget *page, gconf_data *data); 00087 void assistant_gconf_cancel (GtkAssistant *gtkassistant, gpointer user_data); 00088 void assistant_gconf_finish (GtkAssistant *assistant, gpointer user_data); 00089 00090 void assistant_gconf_update_cb (GtkToggleButton *button, gpointer user_data); 00091 void assistant_gconf_install_cb (GtkToggleButton *button, gpointer user_data); 00092 00093 void assistant_gconf_update_prep (GtkAssistant *assistant, gpointer user_data); 00094 void assistant_gconf_step_prep (GtkAssistant *assistant, gpointer user_data); 00095 void assistant_gconf_install_prep (GtkAssistant *assistant, gpointer user_data); 00096 void assistant_gconf_finish_prep (GtkAssistant *assistant, gpointer user_data); 00097 00098 00099 /******************** 00100 * Work Functions 00101 ********************/ 00102 00123 static gboolean 00124 assistant_gconf_update_path (GError **error) 00125 { 00126 gchar *path_filename, *data_filename; 00127 gchar *contents, **lines, *line; 00128 gboolean found_user_dir = FALSE; 00129 FILE *output; 00130 gchar *gconfdir; 00131 00132 data_filename = g_build_filename(g_get_home_dir(), ".gconf", (char *)NULL); 00133 path_filename = g_build_filename(g_get_home_dir(), ".gconf.path", (char *)NULL); 00134 if (g_file_test(path_filename, G_FILE_TEST_EXISTS)) 00135 { 00136 if (!g_file_get_contents(path_filename, &contents, NULL, error)) 00137 { 00138 g_free(path_filename); 00139 g_free(data_filename); 00140 return FALSE; 00141 } 00142 00143 lines = g_strsplit_set(contents, "\r\n", -1); 00144 for (line = *lines; line; line++) 00145 { 00146 if (line[0] == '#') 00147 continue; 00148 if ((strstr(line, "$(HOME)/.gconf") == 0) || 00149 (strstr(line, "~/.gconf") == 0) || 00150 (strstr(line, data_filename))) 00151 { 00152 found_user_dir = TRUE; 00153 break; 00154 } 00155 } 00156 g_strfreev(lines); 00157 } 00158 00159 output = g_fopen(path_filename, "a"); 00160 if (output == NULL) 00161 { 00162 *error = g_error_new (G_FILE_ERROR, 00163 g_file_error_from_errno(errno), 00164 "Error opening file %s for writing.", 00165 path_filename); 00166 g_free(path_filename); 00167 g_free(data_filename); 00168 return FALSE; 00169 } 00170 00171 fprintf(output, "\n######## The following lines were added by GnuCash. ########\n"); 00172 if (!found_user_dir) 00173 fprintf(output, PATH_STRING1); 00174 gconfdir = gnc_path_get_gconfdir (TRUE); 00175 fprintf(output, PATH_STRING2, gconfdir); 00176 g_free (gconfdir); 00177 fprintf(output, "############## End of lines added by GnuCash. ##############\n"); 00178 if (fclose(output) != 0) 00179 { 00180 *error = g_error_new (G_FILE_ERROR, 00181 g_file_error_from_errno(errno), 00182 "Error closing file %s.", 00183 path_filename); 00184 g_free(path_filename); 00185 g_free(data_filename); 00186 return FALSE; 00187 } 00188 00189 g_free(path_filename); 00190 g_free(data_filename); 00191 return TRUE; 00192 } 00193 00194 00209 static gboolean 00210 assistant_gconf_install_keys (GError **error) 00211 { 00212 return g_spawn_command_line_sync(SCRIPT_NAME, NULL, NULL, NULL, error); 00213 } 00214 00215 00216 /******************** 00217 * Update Page 00218 *******************/ 00219 00224 void 00225 assistant_gconf_update_prep (GtkAssistant *assistant, gpointer user_data) 00226 { 00227 gconf_data *data = user_data; 00228 GtkTextBuffer *textbuffer; 00229 GtkWidget *textview; 00230 gchar *msg; 00231 gchar *gconfdir = gnc_path_get_gconfdir (TRUE); 00232 00233 gint num = gtk_assistant_get_current_page (assistant); 00234 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num); 00235 00236 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->update_path))) 00237 { 00238 g_object_set_data(G_OBJECT(assistant), HOW, GINT_TO_POINTER(HOW_UPDATE)); 00239 00240 textview = data->update_text; 00241 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); 00242 msg = g_strdup_printf(PATH_STRING1 PATH_STRING2, gconfdir); 00243 gtk_text_buffer_set_text(textbuffer, msg, -1); 00244 g_free (gconfdir); 00245 } 00246 else 00247 { 00248 g_object_set_data(G_OBJECT(assistant), HOW, GINT_TO_POINTER(HOW_INSTALL)); 00249 gtk_assistant_set_current_page (assistant, num + 2); 00250 } 00251 } 00252 00253 00254 /* Call back for update radio buttons */ 00255 void 00256 assistant_gconf_update_cb (GtkToggleButton *button, gpointer user_data) 00257 { 00258 gconf_data *data = user_data; 00259 GtkAssistant *assistant = GTK_ASSISTANT(data->dialog); 00260 00261 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->program1))) 00262 { 00263 g_object_set_data(G_OBJECT(assistant), WHO_DOES, GINT_TO_POINTER(WHO_GNUCASH)); 00264 } 00265 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->user1))) 00266 { 00267 g_object_set_data(G_OBJECT(assistant), WHO_DOES, GINT_TO_POINTER(WHO_USER)); 00268 } 00269 else 00270 { 00271 g_object_set_data(G_OBJECT(assistant), WHO_DOES, GINT_TO_POINTER(WHO_ALREADY_DONE)); 00272 } 00273 } 00274 00275 00276 /* Call back for Install radio buttons */ 00277 void 00278 assistant_gconf_install_cb (GtkToggleButton *button, gpointer user_data) 00279 { 00280 gconf_data *data = user_data; 00281 GtkAssistant *assistant = GTK_ASSISTANT(data->dialog); 00282 00283 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->program2))) 00284 { 00285 g_object_set_data(G_OBJECT(assistant), WHO_DOES, GINT_TO_POINTER(WHO_GNUCASH)); 00286 } 00287 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->user2))) 00288 { 00289 g_object_set_data(G_OBJECT(assistant), WHO_DOES, GINT_TO_POINTER(WHO_USER)); 00290 } 00291 else 00292 { 00293 g_object_set_data(G_OBJECT(assistant), WHO_DOES, GINT_TO_POINTER(WHO_ALREADY_DONE)); 00294 } 00295 } 00296 00297 00298 /******************** 00299 * Step over Page 00300 ********************/ 00301 00305 void 00306 assistant_gconf_step_prep (GtkAssistant *assistant, gpointer user_data) 00307 { 00308 gconf_data *data = user_data; 00309 gint num = gtk_assistant_get_current_page (assistant); 00310 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num); 00311 gtk_assistant_set_current_page (assistant, num + 2); 00312 } 00313 00314 00315 /******************** 00316 * Install Page 00317 ********************/ 00318 00322 void 00323 assistant_gconf_install_prep (GtkAssistant *assistant, gpointer user_data) 00324 { 00325 gconf_data *data = user_data; 00326 GtkTextBuffer *textbuffer; 00327 GtkWidget *textview; 00328 00329 textview = data->install_text; 00330 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); 00331 gtk_text_buffer_set_text(textbuffer, SCRIPT_NAME, -1); 00332 } 00333 00334 00335 /******************** 00336 * Finish Page 00337 ********************/ 00338 00343 void 00344 assistant_gconf_finish_prep (GtkAssistant *assistant, gpointer user_data) 00345 { 00346 gconf_data *data = user_data; 00347 gint who, how; 00348 gchar *text; 00349 00350 const gchar *pgm_path = 00351 _("When you click Apply, GnuCash will modify your ~/.gconf.path file " 00352 "and restart the gconf backend. There will be a short delay before " 00353 "GnuCash is loaded."); 00354 const gchar *pgm_install = 00355 _("When you click Apply, GnuCash will install the gconf data into your " 00356 "local ~/.gconf file and restart the gconf backend. The %s script " 00357 "must be found in your search path for this to work correctly."); 00358 const gchar *user_path = 00359 _("You have chosen to correct the problem by yourself. When you click " 00360 "Apply, GnuCash will exit. Please correct the problem and restart " 00361 "the gconf backend with the command 'gconftool-2 --shutdown' before " 00362 "restarting GnuCash. If you have not already done so, you can click " 00363 "the Back button and copy the necessary text from the dialog."); 00364 const gchar *user_install = 00365 _("You have chosen to correct the problem by yourself. When you " 00366 "click Apply, GnuCash will exit. Please run the %s script which " 00367 "will install the configuration data and restart the gconf backend."); 00368 const gchar *user_did = 00369 _("You have already corrected the problem and restarted the gconf " 00370 "backend with the command 'gconftool-2 --shutdown'. When you click " 00371 "Apply, there will be a short delay before GnuCash is loaded."); 00372 00373 who = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(assistant), WHO_DOES)); 00374 switch (who) 00375 { 00376 case WHO_ALREADY_DONE: 00377 gtk_label_set_text(GTK_LABEL(data->finish_page), user_did); 00378 break; 00379 00380 case WHO_USER: 00381 how = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(assistant), HOW)); 00382 if (how == HOW_INSTALL) 00383 { 00384 text = g_strdup_printf(user_install, SCRIPT_NAME); 00385 gtk_label_set_text(GTK_LABEL(data->finish_page), text); 00386 g_free(text); 00387 } 00388 else 00389 { 00390 gtk_label_set_text(GTK_LABEL(data->finish_page), user_path); 00391 } 00392 break; 00393 00394 default: 00395 how = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(assistant), HOW)); 00396 if (how == HOW_INSTALL) 00397 { 00398 text = g_strdup_printf(pgm_install, SCRIPT_NAME); 00399 gtk_label_set_text(GTK_LABEL(data->finish_page), text); 00400 g_free(text); 00401 } 00402 else 00403 { 00404 gtk_label_set_text(GTK_LABEL(data->finish_page), pgm_path); 00405 } 00406 break; 00407 } 00408 } 00409 00410 00416 void 00417 assistant_gconf_finish (GtkAssistant *assistant, gpointer user_data) 00418 { 00419 gconf_data *data = user_data; 00420 GtkWidget *window; 00421 gint value, value2; 00422 GError *error = NULL; 00423 gboolean keep_going = TRUE; 00424 00425 /* What to do... what to do... */ 00426 value = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(assistant), WHO_DOES)); 00427 switch (value) 00428 { 00429 case WHO_ALREADY_DONE: 00430 break; 00431 00432 case WHO_USER: 00433 keep_going = FALSE; 00434 break; 00435 00436 default: 00437 value2 = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(assistant), HOW)); 00438 switch (value2) 00439 { 00440 case HOW_INSTALL: 00441 if (!assistant_gconf_install_keys(&error)) 00442 { 00443 keep_going = FALSE; 00444 gnc_error_dialog(NULL, "%s", error->message); 00445 g_error_free(error); 00446 } 00447 break; 00448 00449 default: 00450 if (!assistant_gconf_update_path(&error)) 00451 { 00452 keep_going = FALSE; 00453 gnc_error_dialog(NULL, "%s", error->message); 00454 g_error_free(error); 00455 } 00456 break; 00457 } 00458 break; 00459 } 00460 /* Hide the Assistant */ 00461 gtk_widget_hide(GTK_WIDGET(data->dialog)); 00462 00463 if (keep_going) 00464 { 00465 gtk_main_quit(); 00466 } 00467 else 00468 { 00469 exit(42); 00470 } 00471 } 00472 00473 00474 /************************************* 00475 * Assistant Creation and call backs 00476 ************************************/ 00477 void 00478 assistant_gconf_prepare (GtkAssistant *assistant, GtkWidget *page, 00479 gconf_data *data) 00480 { 00481 gint currentpage = gtk_assistant_get_current_page(assistant); 00482 00483 switch (gtk_assistant_get_current_page(assistant)) 00484 { 00485 case 2: 00486 /* Current page is update search path */ 00487 assistant_gconf_update_prep(assistant, data); 00488 break; 00489 case 3: 00490 /* Current page is a step page */ 00491 assistant_gconf_step_prep(assistant, data); 00492 break; 00493 case 4: 00494 /* Current page is install page */ 00495 assistant_gconf_install_prep(assistant, data); 00496 break; 00497 case 5: 00498 /* Current page is finish page */ 00499 assistant_gconf_finish_prep(assistant, data); 00500 break; 00501 } 00502 } 00503 00504 00508 void 00509 assistant_gconf_cancel (GtkAssistant *gtkassistant, 00510 gpointer user_data) 00511 { 00512 gconf_data *data = user_data; 00513 gtk_widget_destroy(GTK_WIDGET(data->dialog)); 00514 exit(41); 00515 } 00516 00517 00526 static GtkWidget * 00527 gnc_gnome_install_gconf_schemas (void) 00528 { 00529 gconf_data *data; 00530 GtkBuilder *builder; 00531 GtkWidget *dialog; 00532 GError *error = NULL; 00533 00534 00535 data = g_new0 (gconf_data, 1); 00536 builder = gtk_builder_new(); 00537 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer1"); 00538 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer2"); 00539 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer3"); 00540 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer4"); 00541 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer5"); 00542 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer6"); 00543 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer7"); 00544 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "textbuffer8"); 00545 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "GConf Setup Assistant"); 00546 00547 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "GConf Setup Assistant")); 00548 data->dialog = dialog; 00549 00550 /* Set the colors for the assistant */ 00551 gnc_assistant_set_colors (GTK_ASSISTANT (data->dialog)); 00552 00553 /* Enable buttons on all pages. */ 00554 gtk_assistant_set_page_complete (GTK_ASSISTANT (dialog), 00555 GTK_WIDGET(gtk_builder_get_object(builder, "start_page")), 00556 TRUE); 00557 gtk_assistant_set_page_complete (GTK_ASSISTANT (dialog), 00558 GTK_WIDGET(gtk_builder_get_object(builder, "choose_page")), 00559 TRUE); 00560 gtk_assistant_set_page_complete (GTK_ASSISTANT (dialog), 00561 GTK_WIDGET(gtk_builder_get_object(builder, "update_page")), 00562 TRUE); 00563 gtk_assistant_set_page_complete (GTK_ASSISTANT (dialog), 00564 GTK_WIDGET(gtk_builder_get_object(builder, "step_page")), 00565 TRUE); 00566 gtk_assistant_set_page_complete (GTK_ASSISTANT (dialog), 00567 GTK_WIDGET(gtk_builder_get_object(builder, "install_page")), 00568 TRUE); 00569 gtk_assistant_set_page_complete (GTK_ASSISTANT (dialog), 00570 GTK_WIDGET(gtk_builder_get_object(builder, "finish_page")), 00571 TRUE); 00572 00573 /* Choose page */ 00574 data->update_path = GTK_WIDGET(gtk_builder_get_object (builder, "update_path")); 00575 00576 /* Update page */ 00577 data->program1 = GTK_WIDGET(gtk_builder_get_object (builder, "program1")); 00578 data->user1 = GTK_WIDGET(gtk_builder_get_object (builder, "user1")); 00579 data->update_text = GTK_WIDGET(gtk_builder_get_object (builder, "update_text")); 00580 00581 /* Install page */ 00582 data->program2 = GTK_WIDGET(gtk_builder_get_object (builder, "program2")); 00583 data->user2 = GTK_WIDGET(gtk_builder_get_object (builder, "user2")); 00584 data->install_text = GTK_WIDGET(gtk_builder_get_object (builder, "install_text")); 00585 00586 /* Finish page */ 00587 data->finish_page = GTK_WIDGET(gtk_builder_get_object (builder, "finish_page")); 00588 00589 gtk_builder_connect_signals(builder, data); 00590 g_object_unref(G_OBJECT(builder)); 00591 00592 gtk_widget_show_all(dialog); 00593 00594 /* This won't return until the dialog is finished */ 00595 gtk_main(); 00596 00597 /* Destroy the Assistant dialog */ 00598 gtk_widget_destroy(GTK_WIDGET(data->dialog)); 00599 00600 /* Kill the backend daemon. When it restarts it will find our changes */ 00601 if (!g_spawn_command_line_sync("gconftool-2 --shutdown", NULL, NULL, 00602 NULL, &error)) 00603 { 00604 gnc_warning_dialog(NULL, "%s", error->message); 00605 g_error_free(error); 00606 } 00607 00608 return dialog; 00609 } 00610 00611 00612 /* This routine checks to see if GnuCash's gconf schemas are visible 00613 * to the user. The schemas typically should be visible, as rpm and 00614 * deb installs will put the schemas in the default system location. 00615 * For things like network installs or developers, this function will 00616 * present a warning dialog that asks the user whether to setup 00617 * gconf, continue without the schemas, or quit. If the user chooses 00618 * to set up the schemas, this function will invoke an assistant to 00619 * walk the user through making the schemas visible. 00620 */ 00621 void 00622 assistant_gconf_install_check_schemas (void) 00623 { 00624 GtkBuilder *builder; 00625 GtkWidget *dialog; 00626 gboolean done = FALSE; 00627 gint response; 00628 00629 if (gnc_gconf_schemas_found()) 00630 { 00631 gnc_gconf_unset_dir(GCONF_WARNINGS_TEMP, NULL); 00632 return; 00633 } 00634 00635 #ifdef G_OS_WIN32 00636 { 00637 /* automatically update the search path on windows */ 00638 GError *error = NULL; 00639 if (!assistant_gconf_update_path (&error)) 00640 { 00641 gnc_error_dialog (NULL, error->message); 00642 g_error_free (error); 00643 exit(42); 00644 } 00645 else 00646 { 00647 if (!g_spawn_command_line_sync("gconftool-2 --shutdown", NULL, NULL, 00648 NULL, &error)) 00649 { 00650 gnc_warning_dialog(NULL, error->message); 00651 g_error_free(error); 00652 } 00653 return; 00654 } 00655 } 00656 #endif /* G_OS_WIN32 */ 00657 00658 builder = gtk_builder_new(); 00659 gnc_builder_add_from_file (builder, "assistant-gconf-setup.glade", "GConf Query"); 00660 00661 if (!builder) 00662 { 00663 gnc_error_dialog(NULL, "The glade UI files were not found. Your installation is incomplete and cannot be run."); 00664 exit(-1); /* quit immediately */ 00665 } 00666 g_assert(builder); 00667 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "GConf Query")); 00668 g_assert(dialog); 00669 do 00670 { 00671 response = gtk_dialog_run(GTK_DIALOG(dialog)); 00672 00673 switch (response) 00674 { 00675 case GTK_RESPONSE_CANCEL: 00676 default: 00677 exit(42); 00678 /* never returns */ 00679 00680 case GTK_RESPONSE_NO: 00681 /* User wants to run without setting up gconf */ 00682 done = TRUE; 00683 break; 00684 00685 case GTK_RESPONSE_ACCEPT: 00686 gtk_widget_hide(dialog); 00687 gnc_gnome_install_gconf_schemas(); 00688 done = TRUE; 00689 break; 00690 00691 case GTK_RESPONSE_HELP: 00692 gnc_gnome_help(HF_HELP, HL_GCONF); 00693 break; 00694 } 00695 } 00696 while (!done); 00697 00698 g_object_unref(G_OBJECT(builder)); 00699 gtk_widget_destroy(dialog); 00700 } 00701
1.7.4