hello-world/settings/main.c

Go to the documentation of this file.
00001 /*
00002  * File Name: main.c
00003  */
00004 
00005 /*
00006  * This file is part of hello-world-settings.
00007  *
00008  * hello-world is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * hello-world is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2009 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 #include "config.h"
00032 
00033 // system include files, between < >
00034 #include <glib.h>
00035 #include <gtk/gtk.h>
00036 #include <signal.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <sys/types.h>
00040 #include <unistd.h>
00041 
00042 // ereader include files, between < >
00043 #include <libergtk/ergtk.h>
00044 #include <liberutils/gconf_utils.h>
00045 
00046 // local include files, between " "
00047 #include "log.h"
00048 #include "i18n.h"
00049 #include "ipc.h"
00050 #include "main.h"
00051 #include "menu.h"
00052 #include "screen_utils.h"
00053 
00054 
00055 //----------------------------------------------------------------------------
00056 // Type Declarations
00057 //----------------------------------------------------------------------------
00058 
00059 typedef enum
00060         {
00061             RADIO_FIRST,
00062             RADIO_SECOND,
00063             RADIO_THIRD,
00064             N_RADIO
00065         } TODO_radioButton_e;
00066 
00067 //----------------------------------------------------------------------------
00068 // Constants
00069 //----------------------------------------------------------------------------
00070 
00071 static const char  *rc_filename = DATADIR "/" PACKAGE_NAME ".rc";
00072 
00073 // registry access
00074 #define GCONF_ROOT              "/apps/er/" PACKAGE
00075 #define GCONF_TODO_ENTRY        GCONF_ROOT "/todo_entry"
00076 #define GCONF_TODO_RADIOBUTTON  GCONF_ROOT "/todo_radiobutton"
00077 
00078 // screen layout
00079 static const int        WINDOW_TOP_PADDING      =  40;
00080 static const int        WINDOW_BOTTOM_PADDING   =  20;
00081 static const int        WINDOW_H_PADDING        =  20;
00082 static const int        SCREENITEMS_V_SPACING   =  20;
00083 static const int        SCREENITEMS_H_SPACING   =  20;
00084 static const int        BUTTONS_H_SPACING       =  20;
00085 static const int        ENTRY_LABEL_WIDTH       = 200;
00086 
00087 #define WINDOW_MIN_WIDTH  700
00088 #define WINDOW_MIN_HEIGHT 625
00089 
00090 #if (WINDOW_MIN_WIDTH * WINDOW_MIN_HEIGHT) < (1024 * 1280 / 3)
00091 #error  Window size must be at least 1/3rd of screen size
00092 #error  this forces display mgr to use a 16 colour (flashing) waveform when the window appears
00093 #endif
00094 
00095 // TODO radio-button text
00096 static  struct
00097         {
00098             GtkWidget   *widget;                        // screen widget (button)
00099             const gchar *TODO_radio_button_text;        // text on radio button
00100             const gchar *TODO_registry_value;           // value stored in registry
00101         }               g_radio_buttons[N_RADIO]
00102         =
00103         {   //widget    button_text       registry_value
00104             { NULL, N_("<Radio one>"  ), "first-radio-selection"  },
00105             { NULL, N_("<Radio two>"  ), "second-radio-selection" },
00106             { NULL, N_("<Radio three>"), "third-radio-selection"  }
00107         };
00108 
00109 //----------------------------------------------------------------------------
00110 // Static Variables
00111 //----------------------------------------------------------------------------
00112 
00113 static GtkWidget        *g_title         = NULL;  // screen title
00114 static GtkWidget        *g_label_TODO    = NULL;  // TODO user input field
00115 static GtkWidget        *g_entry_TODO    = NULL;  // 
00116 static GtkWidget        *g_button_cancel = NULL;  // button "Cancel"
00117 static GtkWidget        *g_button_save   = NULL;  // button "Save"
00118 
00119 //============================================================================
00120 // Local Function Definitions
00121 //============================================================================
00122 
00123 static void     load_settings           ( void );
00124 static void     main_set_text           ( void );
00125 static void     save_settings           ( void );
00126 
00127 // signal handlers
00128 static void     on_cancel_clicked       ( GtkButton *button, gpointer user_data );
00129 static gboolean on_focus_out            ( GtkWidget *widget, GdkEventFocus *event, gpointer user_data );
00130 static void     on_save_clicked         ( GtkButton *button, gpointer user_data );
00131 static gboolean on_startup_complete     ( gpointer data );
00132 
00133 //============================================================================
00134 // Functions Implementation
00135 //============================================================================
00136 
00137 // print usage text and quit
00138 static void usage (const char *argv_0)
00139 {
00140     static const char *usage_text = 
00141                         "\n"
00142                         "usage: %s [options]\n"
00143                         "\n"
00144                         "options:\n"
00145                         "    --help\n"
00146                         "        Print help text and quit\n";
00147 
00148     printf(usage_text, argv_0);
00149 
00150     exit(1);
00151 }
00152 
00153 // get command-line options
00154 static void parse_arguments (int argc, char **argv)
00155 {
00156     int  i;
00157 
00158     // parse options
00159     for (i = 1 ; i < argc ; i++)
00160     {
00161         if (strcmp(argv[i], "--help") == 0)
00162         {
00163             usage(argv[0]);
00164         }
00165         else
00166         {
00167             ERRORPRINTF("ignore unknown option [%s]", argv[i]);
00168             usage(argv[0]);
00169         }
00170     }
00171 }
00172 
00173 
00174 // set locale (language)
00175 void main_set_locale (const char *locale)
00176 {
00177     LOGPRINTF("entry: locale [%s]", locale);
00178 
00179     g_setenv("LANG", locale, TRUE);
00180     setlocale(LC_ALL, "");
00181 
00182     main_set_text();
00183     menu_set_text();
00184 }
00185 
00186 
00187 // create main screen layout
00188 static GtkWidget *create_screen_layout (void)
00189 {
00190     GtkWidget   *background = NULL;  // return value
00191     GtkWidget   *widget;
00192     GtkWidget   *previous;
00193     GtkWidget   **p_widget;
00194     GtkBox      *vbox;
00195     GtkBox      *vbox2;
00196     GtkBox      *hbox;
00197     GtkLabel    *label;
00198     int         i;
00199 
00200     LOGPRINTF("entry");
00201 
00202     // object hierarchy:
00203     //     background (alignment)
00204     //       |
00205     widget = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
00206     gtk_alignment_set_padding( GTK_ALIGNMENT(widget),
00207                                WINDOW_TOP_PADDING,
00208                                WINDOW_BOTTOM_PADDING,
00209                                WINDOW_H_PADDING,
00210                                WINDOW_H_PADDING  );
00211     gtk_widget_show(widget);
00212     background = widget;
00213     //       |
00214     //       |-- vbox
00215     //             |
00216     widget = gtk_vbox_new(FALSE, SCREENITEMS_V_SPACING);
00217     gtk_container_add(GTK_CONTAINER(background), widget);
00218     gtk_widget_show(widget);
00219     vbox = GTK_BOX(widget);
00220     //             |
00221     //             |-- g_title
00222     //             |
00223     widget = create_screen_title( &g_title );
00224     gtk_box_pack_start(vbox, widget, FALSE, FALSE, 0);
00225     //             |
00226     //             |-- hbox
00227     //             |     |-- g_label_TODO
00228     //             |     |-- g_entry_TODO
00229     //             |
00230     widget = gtk_hbox_new(FALSE, SCREENITEMS_H_SPACING);
00231     gtk_box_pack_start(vbox, widget, FALSE, FALSE, 0);
00232     gtk_widget_show(widget);
00233     hbox = GTK_BOX(widget);
00234     //             |
00235     p_widget = &g_label_TODO;
00236     widget = gtk_label_new(NULL);
00237     gtk_widget_set_name(widget, "irex-hello-instruction");
00238     gtk_widget_set_size_request(widget, ENTRY_LABEL_WIDTH, -1 );
00239     gtk_box_pack_start(hbox, widget, FALSE, FALSE, 0);
00240     label = GTK_LABEL(widget);
00241     gtk_label_set_line_wrap(label, TRUE);
00242     gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE);
00243     gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.5);
00244     g_signal_connect(widget, "destroy", G_CALLBACK(gtk_widget_destroyed), p_widget);
00245     gtk_widget_show(widget);
00246     g_assert(*p_widget == NULL);
00247     *p_widget = widget;
00248     //             |
00249     p_widget = &g_entry_TODO;
00250     widget = ergtk_entry_new();
00251     gtk_widget_set_name(widget, "irex-hello-entry");
00252     gtk_box_pack_end(hbox, widget, TRUE, TRUE, 0);
00253     g_signal_connect(widget, "destroy", G_CALLBACK(gtk_widget_destroyed), p_widget);
00254     gtk_widget_show(widget);
00255     g_assert(*p_widget == NULL);
00256     *p_widget = widget;
00257     //             |
00258     //             |-- separator
00259     //             |
00260     widget = create_separator();
00261     gtk_box_pack_start(vbox, widget, FALSE, FALSE, 0);
00262     gtk_widget_show(widget);
00263     //             |
00264     //             |-- vbox2
00265     //             |     |-- g_radiobutton_TODO[..].widget
00266     //             |
00267     widget = gtk_vbox_new(FALSE, 0);
00268     gtk_box_pack_start(vbox, widget, FALSE, FALSE, 0);
00269     gtk_widget_show(widget);
00270     vbox2 = GTK_BOX(widget);
00271     //             |
00272     previous = NULL;
00273     for (i = 0 ; i < N_RADIO ; i++)
00274     {
00275         p_widget = &(g_radio_buttons[i].widget);
00276         widget = gtk_radio_button_new_with_label_from_widget(
00277                                                 previous ? GTK_RADIO_BUTTON(previous) : NULL,
00278                                                 NULL );
00279         gtk_box_pack_start(vbox2, widget, FALSE, FALSE, 0);
00280         g_signal_connect(widget, "destroy", G_CALLBACK(gtk_widget_destroyed), p_widget);
00281         gtk_widget_show(widget);
00282         g_assert(*p_widget == NULL);
00283         *p_widget = widget;
00284 
00285         previous = widget;
00286     }
00287     //             |
00288     //             |-- separator
00289     //             |
00290     widget = create_separator();
00291     gtk_box_pack_start(vbox, widget, FALSE, FALSE, 0);
00292     gtk_widget_show(widget);
00293     //             |
00294     //             |-- filler (event box)
00295     //             |     Note: filler takes no space itself, but puts buttons at double V spacing
00296     //             |
00297     widget = gtk_event_box_new();
00298     gtk_widget_set_size_request(widget, -1, -1);
00299     gtk_box_pack_start(vbox, widget, FALSE, FALSE, 0);
00300     gtk_widget_show(widget);
00301     //             |
00302     //             |-- hbox
00303     //                   |-- g_button_cancel
00304     //                   |-- g_button_save
00305     //
00306     widget = gtk_hbox_new(FALSE, BUTTONS_H_SPACING);
00307     gtk_box_pack_end(vbox, widget, FALSE, FALSE, 0);
00308     gtk_widget_show(widget);
00309     hbox = GTK_BOX(widget);
00310     //
00311     p_widget = &g_button_cancel;
00312     widget = gtk_button_new_with_label(NULL);
00313     gtk_box_pack_end(hbox, widget, FALSE, FALSE, 0);
00314     g_signal_connect(widget, "clicked", G_CALLBACK(on_cancel_clicked),    NULL);
00315     g_signal_connect(widget, "destroy", G_CALLBACK(gtk_widget_destroyed), p_widget);
00316     gtk_widget_show(widget);
00317     g_assert(*p_widget == NULL);
00318     *p_widget = widget;
00319     //
00320     p_widget = &g_button_save;
00321     widget = gtk_button_new_with_label(NULL);
00322     gtk_box_pack_end(hbox, widget, FALSE, FALSE, 0);
00323     g_signal_connect(widget, "clicked", G_CALLBACK(on_save_clicked),      NULL);
00324     g_signal_connect(widget, "destroy", G_CALLBACK(gtk_widget_destroyed), p_widget);
00325     gtk_widget_show(widget);
00326     g_assert(*p_widget == NULL);
00327     *p_widget = widget;
00328 
00329     main_set_text();
00330     load_settings();
00331     gtk_widget_grab_focus(g_button_cancel);
00332     
00333     return background;
00334 }
00335 
00336 
00337 // set screen texts
00338 static void main_set_text (void)
00339 {
00340     int         i;
00341     GtkWidget   *widget;
00342 
00343     LOGPRINTF("entry");
00344 
00345     if (g_title)
00346     {
00347         gtk_label_set_text(GTK_LABEL(g_title), _("Hello world - Settings"));
00348     }
00349 
00350     if (g_label_TODO)
00351     {
00352         gtk_label_set_text(GTK_LABEL(g_label_TODO), _("<your text here>"));
00353     }
00354 
00355     for (i = 0 ; i < N_RADIO ; i++)
00356     {
00357         widget = g_radio_buttons[i].widget;
00358         if (widget)
00359         {
00360             gtk_button_set_label( GTK_BUTTON(widget), _(g_radio_buttons[i].TODO_radio_button_text)  );
00361         }
00362     }
00363 
00364     if (g_button_cancel)
00365     {
00366         gtk_button_set_label(GTK_BUTTON(g_button_cancel), _("Cancel"));
00367     }
00368 
00369     if (g_button_save)
00370     {
00371         gtk_button_set_label(GTK_BUTTON(g_button_save), _("Save & Close"));
00372     }
00373 }
00374 
00375 
00376 // terminate application
00377 void main_quit (void)
00378 {
00379     WARNPRINTF("entry");
00380     
00381     // clean up modules
00382     menu_destroy();
00383     ergconf_finalize();
00384 
00385     // clean up widgets
00386     if (g_main_window)
00387     {
00388         gtk_widget_destroy(g_main_window);
00389         g_main_window = NULL;
00390     }    
00391     
00392     // clean up gtk
00393     if (gtk_main_level() > 0)
00394     {
00395         WARNPRINTF("quit main loop");
00396         gtk_main_quit();
00397     }
00398     else
00399     {
00400         WARNPRINTF("no main loop to quit, exit directly");
00401         _exit(0);
00402     }
00403 }
00404 
00405 
00406 // terminate signal
00407 static void on_sigterm (int signo)
00408 {
00409     WARNPRINTF("    -- entry " PACKAGE_NAME "-settings, my pid [%d]", getpid());
00410 
00411     // stop main process, prepare to quit application
00412     main_quit();
00413 
00414     WARNPRINTF("    -- leave " PACKAGE_NAME "-settings");
00415 }
00416 
00417 
00418 // report startup completed
00419 static gboolean on_startup_complete (gpointer data)
00420 {
00421     LOGPRINTF("entry");
00422 
00423     ipc_sys_startup_complete();
00424 
00425     return FALSE;  // don't call me again
00426 }
00427 
00428 
00429 // button "cancel" clicked
00430 static void on_cancel_clicked (GtkButton *button, gpointer user_data)
00431 {
00432     LOGPRINTF("entry");
00433 
00434     main_quit();
00435 }
00436 
00437 
00438 // button "save" clicked
00439 static void on_save_clicked (GtkButton *button, gpointer user_data)
00440 {
00441     LOGPRINTF("entry");
00442 
00443     save_settings();
00444     main_quit();
00445 }
00446 
00447 
00448 // main window looses focus
00449 static gboolean on_focus_out (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
00450 {
00451     LOGPRINTF("entry");
00452 
00453     main_quit();
00454 
00455     return FALSE;
00456 }
00457 
00458 
00459 // main function
00460 int main (int argc, char *argv[])
00461 {
00462     GtkWidget        *widget;
00463     GtkWindow        *window;
00464     struct sigaction on_term;
00465 
00466     // parse command-line arguments
00467     parse_arguments(argc, argv);
00468 
00469     // catch the SIGTERM signal
00470     memset(&on_term, 0x00, sizeof(on_term));
00471     on_term.sa_handler = on_sigterm;
00472     sigaction(SIGTERM, &on_term, NULL);
00473 #if LOGGING_ON
00474     sigaction(SIGINT,  &on_term, NULL);
00475 #endif
00476 
00477     // init domain for translations
00478     textdomain(GETTEXT_PACKAGE);
00479     
00480     // init gtk, list the default rc files
00481     gtk_init(&argc, &argv);
00482     gchar** files = gtk_rc_get_default_files();
00483     while( *files )
00484     {
00485         WARNPRINTF("gtk_rc_get_default_files [%s]", *files);
00486         files++;
00487     }
00488 
00489     // init GConf library
00490     ergconf_initialize();
00491 
00492     // init modules
00493     ipc_set_services();
00494     menu_init();
00495 
00496     // open the RC file associated with this program
00497     WARNPRINTF("gtk_rc_parse [%s]", rc_filename);
00498     gtk_rc_parse(rc_filename);
00499 
00500     // create the top level window 
00501     widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00502     gtk_widget_set_size_request(widget, WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT);
00503     window = GTK_WINDOW(widget);
00504     gtk_window_set_type_hint( window, GDK_WINDOW_TYPE_HINT_DIALOG);
00505     gtk_window_set_title(     window, "");
00506     gtk_window_set_keep_above(window, TRUE);
00507     gtk_widget_realize(widget);
00508     gdk_window_set_decorations(widget->window, GDK_DECOR_BORDER);
00509     g_signal_connect(window, "focus-out-event", G_CALLBACK (on_focus_out), NULL);
00510     g_main_window = widget;
00511 
00512     // add screen details
00513     widget = create_screen_layout();
00514     gtk_container_add(GTK_CONTAINER(window), widget);
00515 
00516     // make sure everything is visible 
00517     gtk_widget_show(GTK_WIDGET(window));
00518 
00519     // tell system daemon we are ready to go
00520     g_idle_add(on_startup_complete, NULL);
00521     
00522     // run the main loop
00523     LOGPRINTF("before gtk_main");
00524     gtk_main();
00525     LOGPRINTF("after gtk_main");
00526 
00527     // clean up modules
00528 
00529     return 0;
00530 }
00531 
00532 
00533 // run error dialog
00534 void run_error_dialog (const gchar *msg)
00535 {
00536     GtkWidget   *dialog = NULL;
00537 
00538     ERRORPRINTF("entry: msg [%s]", msg);
00539 
00540     dialog = gtk_message_dialog_new( GTK_WINDOW(g_main_window),
00541                                      GTK_DIALOG_DESTROY_WITH_PARENT,
00542                                      GTK_MESSAGE_ERROR,
00543                                      GTK_BUTTONS_OK,
00544                                      msg );
00545 
00546     gtk_dialog_run( GTK_DIALOG(dialog) );
00547     gtk_widget_destroy( dialog );
00548 }
00549 
00550 
00551 // load settings from registry
00552 void load_settings (void)
00553 {
00554     gchar       *cp;
00555     gint        i;
00556     gboolean    b;
00557     GtkWidget   *widget;
00558 
00559     LOGPRINTF("entry");
00560 
00561     //TODO start
00562     ERRORPRINTF("Missing implementation: load values from registry");
00563 
00564     // entry field
00565     if (g_entry_TODO)
00566     {
00567         cp = ergconf_get_string( GCONF_TODO_ENTRY );
00568         LOGPRINTF("GCONF_TODO_ENTRY [%s]", cp);
00569         gtk_entry_set_text(GTK_ENTRY(g_entry_TODO), cp ? cp : "");
00570         g_free(cp);
00571     }
00572 
00573     // radio button
00574     cp = ergconf_get_string( GCONF_TODO_RADIOBUTTON );
00575     LOGPRINTF("GCONF_TODO_RADIOBUTTON [%s]", cp);
00576     for ( i = 0 ; i < N_RADIO ; i++ )
00577     {
00578         b = FALSE;
00579         if ( cp  &&  strcmp(cp, g_radio_buttons[i].TODO_registry_value) == 0 )
00580         {
00581             b = TRUE;
00582         }
00583 
00584         widget = g_radio_buttons[i].widget;
00585         if (widget)
00586         {
00587             gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), b );
00588         }
00589     }
00590     g_free(cp);
00591 
00592     //TODO end
00593 }
00594 
00595 
00596 // save settings to registry
00597 // Note: no need to compare with old values, just write to registry,
00598 //       GConf compares with current registry values and writes only when needed
00599 void save_settings (void)
00600 {
00601     const gchar *cp;
00602     gint        i;
00603     gboolean    b;
00604     GtkWidget   *widget;
00605 
00606     LOGPRINTF("entry");
00607 
00608     //TODO start
00609     ERRORPRINTF("Missing implementation: save values to registry");
00610 
00611     // entry field
00612     if (g_entry_TODO)
00613     {
00614         cp = gtk_entry_get_text( GTK_ENTRY(g_entry_TODO) );
00615         ergconf_set_string( GCONF_TODO_ENTRY, cp );
00616     }
00617 
00618     // radio button
00619     cp = NULL;
00620     for ( i = 0 ; cp == NULL && i < N_RADIO ; i++ )
00621     {
00622         widget = g_radio_buttons[i].widget;
00623         if (widget)
00624         {
00625             b = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) );
00626             if ( b )
00627             {
00628                 cp = g_radio_buttons[i].TODO_registry_value;
00629             }
00630         }
00631     }
00632     if (cp == NULL)
00633     {
00634         ERRORPRINTF("none of the g_radio_buttons selected");
00635         cp = "";
00636     }
00637     ergconf_set_string( GCONF_TODO_RADIOBUTTON, cp );
00638 
00639     //TODO end
00640 }
00641 
Generated by  doxygen 1.6.2-20100208