Logo Search packages:      
Sourcecode: gaby version File versions  Download package

gtk_main.c

/*  Gaby
 *  Copyright (C) 1998-1999 Frederic Peters
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#define APP_DECLARED

#include "gaby.h"
#include "files.h"
#include "tables.h"
#include "records.h"
#include "windows.h"
#include "gtk_main.h"
#include "gtk_menu.h"

#ifdef USE_GNOME
GnomeApp *app;
#else
GtkWidget *app;
#endif

static GtkWidget* standard_create (GList *view_plugins);
static gboolean delete_event(GtkWidget *win, gpointer data);

static gboolean only_the_view()
{
      GList *options, *o;
      gchar *s;
      gboolean res = FALSE;
      
      options = get_plugin_options("Main");     /* not really a plug-in :) */
      o = options;
      if ( options != NULL ) {
            s = options->data;
            if ( strcmp(s, "only the view") == 0 ) {
                  res = TRUE;
            }
            g_free(s);
            options = g_list_next(options);
      }
      if ( o != NULL ) g_list_free(o);

      return res;
}

#ifdef USE_GNOME

void create_main_window ( GList *view_plugins )
{
      GtkWidget *appbar;
      GString *title=g_string_new("");

      g_string_sprintf(title, "%s %s (%s)", PACKAGE, VERSION, appname );
      
      app = GNOME_APP(gnome_app_new("gaby", title->str));
      g_string_free(title,1);
      gtk_signal_connect (GTK_OBJECT (app), "delete_event", 
                        GTK_SIGNAL_FUNC (delete_event), NULL);
      
      gnome_app_set_contents( app, standard_create(view_plugins));

      /* we don't create menubars and statusbar if they are already provided
       * by the view plug-in _or_ if there is 'only the view' present in the
       * desc file ('plugins_options'->'Main'->'only the view') */

      if ( ! only_the_view() ) {
            if ( app->statusbar == NULL ) {
                  appbar = gnome_appbar_new(TRUE, TRUE, 
                              GNOME_PREFERENCES_USER);
                  gnome_app_set_statusbar(app, appbar);
            }

            if ( app->menubar == NULL ) {
                  menubar_create( view_plugins );
            }
      }

#ifdef DEBUG_GABY
      debug_print("[create_main_window] before showing app: %d\n",
                        (int)(time(NULL)));
#endif
      gtk_widget_show(GTK_WIDGET(app));
#ifdef DEBUG_GABY
      debug_print("[create_main_window] after showing app:  %d\n",
                        (int)(time(NULL)));
#endif
      
      statusbar_message(_("Welcome to Gaby !"), NULL);
}

#else /* USE_GNOME */

static GtkWidget* statusbar_create();

void create_main_window ( GList *view_plugins )
{
      GtkWidget *win;
      GtkWidget *vbox;
      GtkWidget *sb;
      GtkWidget *m;
      GString *title=g_string_new("");
      gboolean olv;

      g_string_sprintf(title, "%s %s (%s)", PACKAGE, VERSION, appname );

      win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      app = win;
      gtk_signal_connect (GTK_OBJECT (win), "delete_event", 
                              GTK_SIGNAL_FUNC (delete_event), NULL);
      gtk_window_set_title (GTK_WINDOW (win), title->str );
      g_string_free(title, 1);
      gtk_window_set_policy (GTK_WINDOW (win), TRUE, TRUE, FALSE);
      gtk_widget_set_usize (GTK_WIDGET(win), 400, 400);
      
      vbox = gtk_vbox_new(FALSE, 0);
      gtk_container_add(GTK_CONTAINER(win), vbox );

      m = standard_create(view_plugins);
      gtk_container_border_width(GTK_CONTAINER(m), 5);
      
      olv = only_the_view();
      if ( ! olv ) {
            gtk_box_pack_start(GTK_BOX(vbox),
                  menubar_create( view_plugins),
                  FALSE, TRUE, 0);
      }
      
      gtk_box_pack_start(GTK_BOX(vbox), m, TRUE, TRUE, 0);

      if ( ! olv ) {
            sb = statusbar_create();
            gtk_object_set_data(GTK_OBJECT(win), "statusbar", sb );
            gtk_box_pack_start(GTK_BOX(vbox), sb, FALSE, TRUE, 0);
      } else {
            gtk_object_set_data(GTK_OBJECT(win), "statusbar", NULL );
      }
            
      gtk_widget_show(vbox);
      gtk_widget_show(win);
      
      statusbar_message(_("Welcome to Gaby !"), win);
}

static GtkWidget* statusbar_create()
{
      GtkWidget *sb;
      
      sb = gtk_statusbar_new();
      
      gtk_widget_show(sb);
      return sb;
}


#endif /* ! USE_GNOME */


static GtkWidget* standard_create (GList *view_plugins)
{
      struct window_info *a;
      GtkWidget *w;
      ViewPluginData *d;
      char *s;
      gabywindow *win;

      a = misc_load_main(view_plugins);
      if ( a == NULL || a->view == NULL || a->view->type == NULL) {
#ifdef DEBUG_GABY
            debug_print("main window not avail\n");
#endif
            gaby_errno = CUSTOM_ERROR;
            gaby_message = strdup(_("Gaby was unable to create the main window. Check your installation."));
            gaby_perror_in_a_box();
            exit(-6);
      }
      d = a->view->type;
      win = g_new0(gabywindow, 1);
      win->view = a->view;
      win->parent = GTK_WIDGET(app);
      win->bound_windows = NULL;
      win->what = NULL;
      win->updated = FALSE;
      
      d->view_create(win, TRUE);
      w = win->widget;
      
      if ( a->width != -1 || a->height != -1 ) {
#ifdef DEBUG_GABY
            debug_print("[standard_create] width : %d, height : %d\n", 
                        a->width, a->height );
#endif
            gtk_window_set_default_size(GTK_WINDOW(app), a->width, a->height);
      }
      
      list_windows = g_list_append(list_windows, win);
      d->view_fill(win);
      
      s = g_malloc(strlen(a->view->name) + 2 + strlen(d->i18n_name) + 5);
      sprintf(s, "%s [%s]", a->view->name, d->i18n_name);
      win->name = s;
      
      g_free(a);
      gtk_widget_show(w);

      return w;
}

void create_other_defaults_windows ( GList *view_plugins )
{
      GList *l, *l_o;
      struct window_info *winfo;
      gabywindow *win;

      l_o = misc_load_other_windows(view_plugins);
      l = l_o;

      while ( l != NULL ) {
            winfo = (struct window_info *)l->data;
            l = g_list_next(l);
            win = new_view_create(winfo);
            if ( win == NULL ) {
                  g_free(winfo);
                  continue;
            }
            if ( winfo->visible ) {
                  gtk_widget_show(win->parent);
            }
            g_free(winfo);
      }

      g_list_free(l_o);
}

void statusbar_message(gchar *msg, GtkWidget *a)
{
#ifdef USE_GNOME
      if ( strlen(msg) == 0 )
            return;
      gnome_app_flash(app, msg);
#else
      GtkWidget *sb;
      static GtkWidget *win;

      if ( a != NULL ) win = a;

      sb = gtk_object_get_data(GTK_OBJECT(win), "statusbar");
      
      if ( sb == NULL ) {
            g_print(msg);
      } else {
            gtk_statusbar_push ( 
                  GTK_STATUSBAR (sb), 
                  gtk_statusbar_get_context_id(
                        GTK_STATUSBAR(sb), "Statusbar"), 
                  msg );
      }
#endif      /* ! USE_GNOME */
}

static gboolean delete_event(GtkWidget *win, gpointer data)
{
#ifdef DEBUG_GABY
      debug_print("[delete_event]\n");
#endif
      return gaby_quit();
}

#if 0
void win_fill(GtkWidget *w, gpointer data)
{
      ViewPluginData *vpd;
      
      if ( ! w || ! w->window ) return;
      
      vpd = gtk_object_get_data(GTK_OBJECT(w), "vpd");
      vpd->view_fill(w);
}
#endif

gint reread_cb(struct location *loc)
{
#if 0
      GList *allw = list_windows;

#ifdef DEBUG_GABY
      debug_print("rereading %s\n", loc->filename);
#endif
      table_reread_file(loc->table, loc);
      
      g_list_foreach(allw, (GFunc)win_fill, NULL);
#endif /* 0 */
      
      return TRUE;
}

static void focus_in_event (GtkWidget *w, gabywindow *window)
{
      window->focused = TRUE;
}

static void focus_out_event (GtkWidget *w, gabywindow *window)
{
      window->focused = FALSE;
}

/**
 * new_view_create
 * @wi: misc info about the window to be created
 *
 * Description:
 * This function creates a new window holding a view plug-in
 *
 * Returns: the window (gabywindow*) created
 **/
gabywindow* new_view_create ( struct window_info *wi )
{
      gabywindow *window;
      GtkWidget *win;
      GtkWidget *wid;
      GString *st = g_string_new("");
      ViewPluginData *vpd;
      char *s;
      int nb = 2;
      view *v = wi->view;
      
      vpd = v->type;
      g_string_sprintf(st, "%s [%s]", v->name, vpd->i18n_name );
#if 1
      if ( window_already_there(st->str) ) {
            do {
                  g_string_sprintf(st, "%s [%s] (%d)", 
                        v->name, vpd->i18n_name, nb);
                  nb++;
            } while ( window_already_there(st->str) );
      }
#endif
      nb--;
      
#ifdef USE_GNOME
      win = gnome_app_new("gaby", st->str);
#if 0
      /* this allows the window manager to iconize the window when iconizing
       * the main window but I don't like this behaviour :) */
      gtk_window_set_transient_for(GTK_WINDOW(win), GTK_WINDOW(app));
#endif

#else /* ! USE_GNOME */
      win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_title(GTK_WINDOW (win), st->str );
      gtk_window_set_policy (GTK_WINDOW (win), TRUE, TRUE, FALSE);
/*
      gtk_widget_set_usize (GTK_WIDGET(win), 400, 400);
*/
      gtk_container_border_width(GTK_CONTAINER(win), 5);
#endif /* USE_GNOME */

      window = g_new0(gabywindow, 1);
      window->view = v;
      window->id = 0;
      window->updated = FALSE;
      window->focused = FALSE;
      window->bound_windows = NULL;
      window->widget = NULL;
      window->parent = win;

      vpd->view_create(window, FALSE);
      if ( window->widget == NULL ) {
            g_free(window);
            gtk_widget_destroy(win);
            g_string_free(st, 1);
            return NULL;
      }
      
      wid = window->widget;

      /* in case someone wants to go in the wrong way 
       *   (actually this is to help moving to the new API) */
      gtk_object_set_data(GTK_OBJECT(wid), "window", window );
      
      if ( wid == NULL ) {
            g_string_free(st, 1);
            gtk_widget_destroy(win);
            return NULL;
      }
      gtk_container_border_width(GTK_CONTAINER(wid), 5);

      /* it would be better to give 'window' as 2nd arg but that doesn't
       * work. Hence this ugly thing */
      gtk_signal_connect(GTK_OBJECT(win), "delete_event", 
                        GTK_SIGNAL_FUNC(delete_view), NULL );
      gtk_object_set_data(GTK_OBJECT(win), "window", window );

      gtk_signal_connect(GTK_OBJECT(win), "focus_in_event", 
                        GTK_SIGNAL_FUNC(focus_in_event), window );
      gtk_signal_connect(GTK_OBJECT(win), "focus_out_event", 
                        GTK_SIGNAL_FUNC(focus_out_event), window );
      
      vpd->view_fill(window);
#ifdef DEBUG_GABY
      debug_print("[new_view_create] view_fill succeeded\n");
#endif
      gtk_widget_show(wid);
      
      /* 
       * this is officially the strangest thing I saw in my life (and one of
       * the hardest bug to track).
       * while the commented line should obviously work, it doesn't.
       * Better yet : if we don't bother with nb we can remove one of the
       * '+5' :

s = g_malloc(strlen(v->name) + 2 + strlen(vpd->i18n_name->str) + 5 );
       
       * and it works (for nb == 1) while this one :

s = g_malloc(strlen(v->name) + 2 + strlen(vpd->i18n_name->str) + 5 + 
                              ( 1 > 1 ) ? 5 : 0 );
                        
       * doesn't (note the logic in the 2nd line).
       *
       * if you want to know :
       * 
       * $ gcc --version
       *  egcs-2.91.63
       *  
       * experimental ? :)
       *
       */
      s = g_malloc(strlen(v->name) + 2 + strlen(vpd->i18n_name) + 5 + 
/*                ( nb > 1 ) ? 5 : 0 );   */
                  5 );
      if ( nb == 1 ) {
            sprintf(s, "%s [%s]", v->name, vpd->i18n_name);
      } else {
            sprintf(s, "%s [%s] (%d)", v->name, vpd->i18n_name, nb);
      }
#ifdef DEBUG_GABY
      debug_print("[new_view_create] name : %s\n", s);
#endif
      window->name = s;
      
      gtk_object_set_data(GTK_OBJECT(wid), "parent", win);
      
#ifdef USE_GNOME
      gnome_app_set_contents(GNOME_APP(win), wid );
#else
      gtk_container_add(GTK_CONTAINER(win), wid);
#endif
      
      if ( wi->height != -1 || wi->width != -1 ) {
            gtk_window_set_default_size(GTK_WINDOW(win), 
                                    wi->width, wi->height );
      }

      /* gnome documentation says this */
      gtk_window_set_wmclass(GTK_WINDOW(win), "view", "Gaby");

      g_string_free(st, 1);

#ifdef DEBUG_GABY
      debug_print("[new_view_create] adding this view (%p) to list_windows (%p)\n", window, list_windows);
#endif
      list_windows = g_list_append(list_windows, window);

#ifdef DEBUG_GABY
      debug_print("[new_view_create] the end\n");
#endif
      /* WARNING!
       *  the widget returned is not suitable for bound windows and other
       *  functions like that, those requires a widget (available looking for
       *  the 'child' data) : */
      
      return window;
}

static void sel_st_row_changed( GtkCList *clist, gint row, gint column,
                        GdkEventButton *event, GtkWidget *wid)
{
#ifdef USE_GNOME
      gnome_dialog_set_sensitive(GNOME_DIALOG(wid), 0, 
                              ( clist->selection != NULL ) );
#else
      gtk_widget_set_sensitive(wid, ( clist->selection != NULL ) );
#endif
}

static void sel_st_ok(GtkWidget *but, GtkWidget *dialog)
{
      GtkWidget *clist = gtk_object_get_data(GTK_OBJECT(dialog), "clist");
      gchar *text;
      subtable **st;
      void (*callback) (subtable *st);
      subtable *this_st;
      gboolean *val;

      gtk_clist_get_text(GTK_CLIST(clist), 
                  GPOINTER_TO_INT(GTK_CLIST(clist)->selection->data), 
                  0, &text );
      this_st = get_subtable_by_name(text);
      
      st = gtk_object_get_data(GTK_OBJECT(dialog), "subtable");
      callback = gtk_object_get_data(GTK_OBJECT(dialog), "callback");

      val = gtk_object_get_data(GTK_OBJECT(dialog), "visible");
      gtk_widget_hide(dialog);
      
      if ( st != NULL ) {
            *st = this_st;
            *val = FALSE;
      } else {
            callback(this_st);
            *val = FALSE;
      }
}

static void sel_st_cancel(GtkWidget *but, GtkWidget *dlg)
{
      GtkWidget *dialog = dlg;
      gboolean *val;
      
      //while ( dialog->parent ) dialog = dialog->parent;
      
      val = gtk_object_get_data(GTK_OBJECT(dialog), "visible");

      *val = FALSE;
      gtk_widget_hide(dialog);
            /* BUG! segfaults in gtk+ if gtk_widget_destroy 
             * is applied (???) */
}

/**
 * select_subtable_dialog
 * @text: text to show in the label
 * @callback: function to use as callback after successful selection
 * @st: pointer to the subtable variable which will hold the selection
 *
 * Description:
 * This function creates a dialog with a list filled with subtable names.
 *
 * Returns: a gboolean pointer you can use together with wait_dialog_to_finish
 * (don't forget to g_free it if you don't use this function)
 **/
gboolean* select_subtable_dialog (char *text, void (* callback) (subtable *st),
                          subtable **st)
{
      GtkWidget *dialog;
      GtkWidget *vbox, *clist;
      GtkWidget *label;
#ifndef USE_GNOME
      GtkWidget *button, *buttonok;
#endif
      GList *subtables = list_subtables;
      gboolean *ret;

#ifdef USE_GNOME
      dialog = gnome_dialog_new(_("Select a subtable"), 
                        GNOME_STOCK_BUTTON_OK, 
                        GNOME_STOCK_BUTTON_CANCEL, 
                        NULL );
      gnome_dialog_set_close(GNOME_DIALOG(dialog), FALSE);
      vbox = GNOME_DIALOG(dialog)->vbox;

      gnome_dialog_button_connect(GNOME_DIALOG(dialog), 0, sel_st_ok, dialog);
      gnome_dialog_button_connect(GNOME_DIALOG(dialog), 1, 
                                          sel_st_cancel, dialog);
#else
      dialog = gtk_dialog_new();
      vbox = GTK_DIALOG(dialog)->vbox;
      
      button = gtk_button_new_with_label(_("OK"));
      gtk_widget_show(button);
      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, 
                        FALSE, FALSE, 0 );
      gtk_signal_connect(GTK_OBJECT(button), "clicked", sel_st_ok, dialog );
      buttonok = button;

      button = gtk_button_new_with_label(_("Cancel"));
      gtk_widget_show(button);
      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, 
                        FALSE, FALSE, 0 );
      gtk_signal_connect(GTK_OBJECT(button), "clicked", sel_st_cancel,dialog);
#endif

      label = gtk_label_new(text);
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0 );
      
      clist = gtk_clist_new(1);
      gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0 );
      
      subtables = g_list_first(subtables);
      while ( subtables != NULL ) {
            gtk_clist_append(GTK_CLIST(clist), 
                        &((subtable*)subtables->data)->i18n_name );
            subtables = g_list_next(subtables);
      }

#ifdef USE_GNOME
      gtk_signal_connect(GTK_OBJECT(clist), "select_row", 
                                    sel_st_row_changed, dialog );
      gtk_signal_connect(GTK_OBJECT(clist), "unselect_row", 
                                    sel_st_row_changed, dialog );
      sel_st_row_changed(GTK_CLIST(clist), 0, 0, NULL, dialog);
#else
      gtk_signal_connect(GTK_OBJECT(clist), "select_row", 
                                    sel_st_row_changed, buttonok );
      gtk_signal_connect(GTK_OBJECT(clist), "unselect_row", 
                                    sel_st_row_changed, buttonok );
      sel_st_row_changed(GTK_CLIST(clist), 0, 0, NULL, buttonok);
#endif
      
      gtk_widget_show(clist);
      gtk_object_set_data(GTK_OBJECT(dialog), "clist", clist );

      if ( st != NULL ) {
            gtk_object_set_data(GTK_OBJECT(dialog), "subtable", st);
      } else {
            gtk_object_set_data(GTK_OBJECT(dialog), "callback", callback);
      }
      
      ret = g_new0(gboolean, 1);
      *ret = TRUE;
      gtk_object_set_data(GTK_OBJECT(dialog), "visible", ret);
      
      gtk_widget_show(dialog);

      return ret;
}

/** wait_dialog_to_finish
 * @val: as returned by select_subtable_dialog
 *
 * Description:
 * This functions waits for a dialog to finish
 **/
void wait_dialog_to_finish(gboolean *val)
{
      while ( *val == TRUE ) {
            if ( gtk_events_pending() )
                  gtk_main_iteration();
      }
      g_free(val);
}


Generated by  Doxygen 1.6.0   Back to index