GnuCash 2.4.99
assistant-gconf-setup.c
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines