[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: CVS update: i_callbacks.c



  User: cnieves 
  Date: 06/10/04 16:11:40

  Modified:    .        i_callbacks.c x_dialog.c x_fileselect.c x_window.c
  Log:
  Commited patch from Patrick Bernaud, improving the close confirmation
  
  dialog, and adding functions to open, close, save and change page.
  
  
  
  
  Revision  Changes    Path
  1.67      +16 -266   eda/geda/gaf/gschem/src/i_callbacks.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: i_callbacks.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/gschem/src/i_callbacks.c,v
  retrieving revision 1.66
  retrieving revision 1.67
  diff -u -b -r1.66 -r1.67
  --- i_callbacks.c	30 Sep 2006 16:01:36 -0000	1.66
  +++ i_callbacks.c	4 Oct 2006 20:11:40 -0000	1.67
  @@ -182,43 +182,13 @@
   {
     TOPLEVEL *toplevel = (TOPLEVEL*)data;
     PAGE *page;
  -  gchar *filename;
   
     exit_if_null (toplevel);
   
  -  g_free (toplevel->cwd);
  -  toplevel->cwd = g_get_current_dir ();
  -#ifdef __MINGW32__
  -  u_basic_strip_trailing(toplevel->cwd, G_DIR_SEPARATOR);
  -#endif
  -  filename = g_strdup_printf ("%s%c%s_%d.sch",
  -                              toplevel->cwd,
  -                              G_DIR_SEPARATOR,
  -                              toplevel->series_name,
  -                              ++toplevel->num_untitled);
  -
     /* create a new page */
  -  page = s_page_new (toplevel, filename);
  -  /* change current page to page */
  -  s_page_goto (toplevel, page);
  -  g_free (filename);
  +  page = x_window_open_untitled_page (toplevel);
  +  s_log_message (_("New page created [%s]\n"), page->page_filename);
   
  -  s_log_message (_("New page created [%s]\n"),
  -                 toplevel->page_current->page_filename);
  -
  -  /* Run the new page hook */
  -  if (scm_hook_empty_p(new_page_hook) == SCM_BOOL_F &&
  -      page != NULL) {
  -    scm_run_hook(new_page_hook,
  -		 scm_cons(g_make_page_smob(toplevel, page),
  -			  SCM_EOL));
  -  }
  -  
  -  x_pagesel_update (toplevel);
  -  i_update_menus (toplevel);
  -  i_set_filename (toplevel, toplevel->page_current->page_filename);
  -  x_manual_resize (toplevel);
  -  a_zoom_extents(toplevel, toplevel->page_current->object_head, 0);
     o_undo_savestate (toplevel, UNDO_ALL);
     
   }
  @@ -248,28 +218,17 @@
   DEFINE_I_CALLBACK(file_new_window)
   {
     TOPLEVEL *w_current;
  +  PAGE *page;
          
     w_current = s_toplevel_new ();
     x_window_setup (w_current);
   
     exit_if_null(w_current);
   
  -  g_free (w_current->cwd);
  -  w_current->cwd = g_get_current_dir ();
  -#ifdef __MINGW32__
  -  u_basic_strip_trailing(w_current->cwd, G_DIR_SEPARATOR);
  -#endif
  -  g_free (w_current->page_current->page_filename);
  -  w_current->page_current->page_filename = g_strdup_printf (
  -    "%s%c%s_%d.sch",
  -    w_current->cwd,
  -    G_DIR_SEPARATOR,
  -    w_current->series_name,
  -    ++w_current->num_untitled);
  -
     s_log_message(_("New Window created\n"));
  -  i_set_filename(w_current, w_current->page_current->page_filename);
  -  x_repaint_background(w_current);
  +  
  +  page = x_window_open_untitled_page (w_current);
  +
   }
   
   /*! \todo Finish function documentation!!!
  @@ -358,22 +317,9 @@
                                  w_current->page_current->page_filename);
   #endif
     } else {
  -
  -    if (f_save(w_current, w_current->page_current->page_filename) ) {
  -	    s_log_message(_("Saved [%s]\n"),w_current->page_current->page_filename);
  -	    /* don't know if should be kept going to select mode... */
  -	    w_current->page_current->CHANGED = 0;
  -	    i_set_state_msg(w_current, SELECT, _("Saved"));
  -	    i_update_toolbar(w_current);
  -            i_update_menus(w_current);
  -      x_pagesel_update (w_current);
  -    } else {
  -      	    s_log_message(_("Could NOT save [%s]\n"), w_current->page_current->page_filename);
  -
  -	    i_set_state_msg(w_current, SELECT, _("Error while trying to save"));
  -	    i_update_toolbar(w_current);
  -            i_update_menus(w_current);
  -    } 
  +    x_window_save_page (w_current,
  +                        w_current->page_current,
  +                        w_current->page_current->page_filename);
     }
   }
   
  @@ -1758,45 +1704,12 @@
   {
     TOPLEVEL *toplevel = (TOPLEVEL*)data;
     PAGE *page;
  -  gchar *filename;
   
     exit_if_null(toplevel);
   
  -  g_free (toplevel->cwd);
  -  toplevel->cwd = g_get_current_dir ();
  -#ifdef __MINGW32__
  -  u_basic_strip_trailing(toplevel->cwd, G_DIR_SEPARATOR);
  -#endif
  -  filename = g_strdup_printf ("%s%c%s_%d.sch",
  -                              toplevel->cwd,
  -                              G_DIR_SEPARATOR,
  -                              toplevel->series_name,
  -                              ++toplevel->num_untitled);
  -
  -  /* create the new page */
  -  page = s_page_new (toplevel, filename);
  -  /* change current page to page */
  -  s_page_goto (toplevel, page);
  -  g_free (filename);
  -
  -  s_log_message(_("New Page created [%s]\n"),
  -                toplevel->page_current->page_filename);
  -  
  -  /* Run the new page hook */
  -  if (scm_hook_empty_p(new_page_hook) == SCM_BOOL_F &&
  -      page != NULL) {
  -    scm_run_hook(new_page_hook,
  -		 scm_cons(g_make_page_smob(toplevel, page),
  -			  SCM_EOL));
  -  }
  -  
  -  /* Do a zoom extents */
  -  a_zoom_extents(toplevel, toplevel->page_current->object_head, 0);
  -  
  -  x_pagesel_update (toplevel);
  -  i_update_menus (toplevel);
  -  i_set_filename (toplevel, toplevel->page_current->page_filename);
  -  o_redraw_all (toplevel);
  +  /* create a new page */
  +  page = x_window_open_untitled_page (toplevel);
  +  s_log_message (_("New page created [%s]\n"), page->page_filename);
     
   }
   
  @@ -1808,97 +1721,15 @@
   DEFINE_I_CALLBACK(page_close)
   {
     TOPLEVEL *w_current = (TOPLEVEL *) data;
  -  PAGE *p_current;
  -  PAGE *p_save;
   
     exit_if_null(w_current);
   
     if (w_current->page_current->CHANGED) {
  -    x_fileselect_save (w_current);
  -    return;
  -  }
  -
  -  /* Can we go up in the hierarchy first? */
  -  p_current = s_hierarchy_find_page(w_current->page_head, 
  -                                    w_current->page_current->up);
  -  if (p_current) {
  -    s_log_message(_("Closing [%s]\n"),
  -                  w_current->page_current->page_filename);
  -    s_page_delete (w_current, w_current->page_current);
  -
  -    s_page_goto (w_current, p_current);
  -
  -    i_set_filename(w_current, w_current->page_current->page_filename);
  -    x_scrollbars_update(w_current);
  -    o_redraw_all(w_current);
  -    x_pagesel_update (w_current);
  -    i_update_menus(w_current);
  -    return;
  -  }
  -
  -  /* is there a page before current? */
  -  if (w_current->page_current->prev &&
  -      w_current->page_current->prev->pid != -1) {
  -        /* yes, change to previous page */
  -        p_current = w_current->page_current->prev;
  -        s_log_message(_("Closing [%s]\n"),
  -                      w_current->page_current->page_filename);
  -        s_page_delete (w_current, w_current->page_current);
  -        
  -        s_page_goto (w_current, p_current);
  -        
  -        i_set_filename(w_current, w_current->page_current->page_filename);
  -        x_scrollbars_update(w_current);
  -        o_redraw_all(w_current);
  -        x_pagesel_update (w_current);
  -        i_update_menus(w_current);
  -        return;
  -      }
  -
  -  /* is there a page after current? */
  -  if (w_current->page_current->next) {
  -    /* yes, change to next page */
  -    g_assert (w_current->page_current->next->pid != -1);
  -    
  -    p_current = w_current->page_current->next;
  -    s_log_message(_("Closing [%s]\n"),
  -                  w_current->page_current->page_filename);
  -    s_page_delete (w_current, w_current->page_current);
  -    
  -    s_page_goto (w_current, p_current);
  -    
  -    i_set_filename(w_current, w_current->page_current->page_filename);
  -    x_scrollbars_update(w_current);
  -    o_redraw_all(w_current);
  -    x_pagesel_update (w_current);
  -    i_update_menus(w_current);
  -    return;
  +    x_dialog_close_changed_page (w_current, w_current->page_current);
  +  } else {
  +    x_window_close_page (w_current, w_current->page_current);
     }
   
  -  /* finally go here if you can't delete the page */
  -  /* because it's the last page being displayed */
  -  /* s_log_message("Cannot close current page\n");*/
  -  /* now the code creates a new page, and closes the old one */
  -  p_save = w_current->page_current;
  -  i_callback_page_new(w_current, 0, NULL);
  -  w_current->page_current = p_save;	
  -
  -  g_assert (w_current->page_current->next != NULL);
  -  g_assert (w_current->page_current->next->pid != -1);
  -  
  -  p_current = w_current->page_current->next;
  -  s_log_message(_("Closing [%s]\n"),
  -                w_current->page_current->page_filename);
  -  s_page_delete (w_current, w_current->page_current);
  -
  -  s_page_goto (w_current, p_current);
  -  
  -  i_set_filename(w_current, w_current->page_current->page_filename);
  -  x_scrollbars_update(w_current);
  -  o_redraw_all(w_current);
  -  x_pagesel_update (w_current);
  -  i_update_menus(w_current);
  -
   }
   
   /*! \todo Finish function documentation!!!
  @@ -1981,91 +1812,10 @@
   DEFINE_I_CALLBACK(page_discard)
   {
     TOPLEVEL *w_current = (TOPLEVEL*)data;
  -  PAGE *p_current;
  -  PAGE *p_save;
   
     exit_if_null(w_current);
   
  -  /* Can we go up in the hierarchy first? */
  -  p_current = s_hierarchy_find_page(w_current->page_head, 
  -                                    w_current->page_current->up);
  -  if (p_current) {
  -    s_log_message(_("Closing [%s]\n"),
  -                  w_current->page_current->page_filename);
  -    s_page_delete (w_current, w_current->page_current);
  -
  -    s_page_goto (w_current, p_current);
  -
  -    i_set_filename(w_current, w_current->page_current->page_filename);
  -    x_scrollbars_update(w_current);
  -    o_redraw_all(w_current);
  -    x_pagesel_update (w_current);
  -    i_update_menus(w_current);
  -    return;
  -  }
  -
  -  /* is there a page before current? */
  -  if (w_current->page_current->prev &&
  -      w_current->page_current->prev->pid != -1) {
  -        /* yes, change to previous page */
  -        p_current = w_current->page_current->prev;
  -        s_log_message(_("Discarding page [%s]\n"),
  -                      w_current->page_current->page_filename);
  -        s_page_delete (w_current, w_current->page_current);
  -
  -        s_page_goto (w_current, p_current);
  -        
  -        i_set_filename(w_current, w_current->page_current->page_filename);
  -        x_scrollbars_update(w_current);
  -        o_redraw_all(w_current);
  -        x_pagesel_update (w_current);
  -        i_update_menus(w_current);
  -        return;
  -      }
  -
  -  /* is there a page after current? */
  -  if (w_current->page_current->next) {
  -    /* yes, change to next page */
  -    g_assert (w_current->page_current->next->pid != -1);
  -
  -    p_current = w_current->page_current->next;
  -    s_log_message(_("Discarding page [%s]\n"),
  -                  w_current->page_current->page_filename);
  -    s_page_delete (w_current, w_current->page_current);
  -
  -    s_page_goto (w_current, p_current);
  -    
  -    i_set_filename(w_current, w_current->page_current->page_filename);
  -    x_scrollbars_update(w_current);
  -    o_redraw_all(w_current);
  -    x_pagesel_update (w_current);
  -    i_update_menus(w_current);
  -    return;
  -  }
  -
  -  /* finally go here if you can't delete the page */
  -  /* because it's the last page being displayed */
  -  /* s_log_message("Cannot close current page\n");*/
  -  /* now the code creates a new page, and closes the old one */
  -  p_save = w_current->page_current;
  -  i_callback_page_new(w_current, 0, NULL);
  -  w_current->page_current = p_save;	
  -
  -  g_assert (w_current->page_current->next != NULL);
  -  g_assert (w_current->page_current->next->pid != -1);
  -  
  -  p_current = w_current->page_current->next;
  -  s_log_message(_("Discarding page [%s]\n"),
  -                w_current->page_current->page_filename);
  -  s_page_delete (w_current, w_current->page_current);
  -
  -  s_page_goto (w_current, p_current);
  -
  -  i_set_filename(w_current, w_current->page_current->page_filename);
  -  x_scrollbars_update(w_current);
  -  o_redraw_all(w_current);
  -  x_pagesel_update (w_current);
  -  i_update_menus(w_current);
  +  x_window_close_page (w_current, w_current->page_current);
     
   }
   
  
  
  
  1.61      +760 -135  eda/geda/gaf/gschem/src/x_dialog.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: x_dialog.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/gschem/src/x_dialog.c,v
  retrieving revision 1.60
  retrieving revision 1.61
  diff -u -b -r1.60 -r1.61
  --- x_dialog.c	7 Sep 2006 02:41:28 -0000	1.60
  +++ x_dialog.c	4 Oct 2006 20:11:40 -0000	1.61
  @@ -1542,141 +1542,6 @@
   
   /***************** End of Fill Type dialog box ***********************/
   
  -/***************** Start of Exit dialog box **************************/
  -
  -/*! \todo Finish function documentation!!!
  - *  \brief
  - *  \par Function Description
  - *
  - */
  -int exit_dialog_keypress(GtkWidget * widget, GdkEventKey * event, 
  -			 TOPLEVEL * w_current)
  -{
  -   if (strcmp(gdk_keyval_name(event->keyval), "Escape") == 0) {
  -	exit_dialog_cancel(NULL, w_current);	
  -        return TRUE;
  -   }
  -
  -   return FALSE;
  -}
  -
  -/*! \todo Finish function documentation!!!
  - *  \brief
  - *  \par Function Description
  - *
  - */
  -void exit_dialog_ok(GtkWidget *w, TOPLEVEL *w_current)
  -{
  -  gtk_grab_remove(w_current->exwindow);
  -  gtk_widget_destroy(w_current->exwindow);
  -  w_current->exwindow = NULL;
  -
  -  /* go through and change ALL changed flags to 0 */
  -#if 0
  -  w_current->page_current->CHANGED = 0;
  -#endif
  -  s_page_clear_changed(w_current->page_head);
  -  i_callback_file_close(w_current, 0, NULL);
  -}
  -
  -/*! \todo Finish function documentation!!!
  - *  \brief
  - *  \par Function Description
  - *
  - */
  -void exit_dialog_cancel(GtkWidget *w, TOPLEVEL *w_current)
  -{
  -  gtk_grab_remove(w_current->exwindow);
  -  gtk_widget_destroy(w_current->exwindow);
  -  w_current->exwindow = NULL;
  -
  -  /* leave this one */
  -  w_current->event_state = SELECT;
  -}
  -
  -/*! \todo Finish function documentation!!!
  - *  \brief
  - *  \par Function Description
  - *
  - */
  -void exit_dialog (TOPLEVEL *w_current)
  -{
  -  GtkWidget *exit_dialog;
  -  GtkWidget *vbox1;
  -  GtkWidget *label1;
  -  GtkWidget *hseparator1;
  -  GtkWidget *hbuttonbox1;
  -  GtkWidget *button1;
  -  GtkWidget *button2;
  -
  -  if (!w_current->exwindow)
  -  {
  -
  -    exit_dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  -    w_current->exwindow = exit_dialog;
  -    gtk_window_set_title (GTK_WINDOW (exit_dialog), "Discard Changes?");
  -    gtk_window_set_position (GTK_WINDOW (exit_dialog), GTK_WIN_POS_MOUSE);
  -    gtk_window_set_modal (GTK_WINDOW (exit_dialog), TRUE);
  -    gtk_window_set_default_size (GTK_WINDOW (exit_dialog), 240, 160);
  -    gtk_widget_show (exit_dialog);
  -
  -    gtk_signal_connect(GTK_OBJECT(w_current->exwindow),
  -                       "destroy",
  -                       GTK_SIGNAL_FUNC(destroy_window),
  -                       &w_current->exwindow);
  -    
  -    gtk_signal_connect(GTK_OBJECT(w_current->exwindow),
  -                       "key_press_event",
  -                       (GtkSignalFunc) exit_dialog_keypress, w_current);
  -
  -    vbox1 = gtk_vbox_new (FALSE, 0);
  -    gtk_widget_show (vbox1);
  -    gtk_container_add (GTK_CONTAINER (exit_dialog), vbox1);
  -
  -    label1 = gtk_label_new(
  -                           _("There are unsaved schematics!\n"
  -                             "\n"
  -                             "Are you sure?\n"
  -                             "OK will discard ALL changes!"));
  -    gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_CENTER);
  -    gtk_widget_show (label1);
  -    gtk_box_pack_start (GTK_BOX (vbox1), label1, TRUE, TRUE, 0);
  -    hseparator1 = gtk_hseparator_new ();
  -    gtk_widget_show (hseparator1);
  -    gtk_box_pack_start (GTK_BOX (vbox1), hseparator1, FALSE, FALSE, 0);
  -
  -    hbuttonbox1 = gtk_hbutton_box_new ();
  -    gtk_widget_show (hbuttonbox1);
  -    gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, FALSE, FALSE, 0);
  -    gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1), 10);
  -
  -    button1 = gtk_button_new_from_stock (GTK_STOCK_OK);
  -    gtk_widget_show (button1);
  -    gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1);
  -    GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
  -    gtk_signal_connect(GTK_OBJECT (button1), "clicked",
  -                       GTK_SIGNAL_FUNC(exit_dialog_ok), w_current);
  -
  -    button2 = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
  -    gtk_widget_show (button2);
  -    gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2);
  -    GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
  -    gtk_signal_connect(GTK_OBJECT (button2), "clicked",
  -                       GTK_SIGNAL_FUNC(exit_dialog_cancel),
  -                       w_current);
  -
  -    gtk_widget_grab_focus (button2);
  -    gtk_widget_grab_default (button2);
  -  }
  -
  -  if (!GTK_WIDGET_VISIBLE (w_current->exwindow)) {
  -    gtk_widget_show(w_current->exwindow);
  -    gtk_grab_add(w_current->exwindow);
  -  }
  -}
  -
  -/***************** End of Exit dialog box ****************************/
  -
   /***************** Start of Arc dialog box ***************************/
   
   /*! \todo Finish function documentation!!!
  @@ -4372,3 +4237,763 @@
   }
   
   /*********** End of major symbol changed dialog box *******/
  +
  +/***************** Start of Close Confirmation dialog box ************/
  +
  +#define TYPE_CLOSE_CONFIRMATION_DIALOG            (close_confirmation_dialog_get_type ())
  +#define CLOSE_CONFIRMATION_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialog))
  +#define CLOSE_CONFIRMATION_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
  +#define IS_CLOSE_CONFIRMATION_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG))
  +#define IS_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG))
  +#define CLOSE_CONFIRMATION_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
  +
  +
  +typedef struct _CloseConfirmationDialog      CloseConfirmationDialog;
  +typedef struct _CloseConfirmationDialogClass CloseConfirmationDialogClass;
  +
  +struct _CloseConfirmationDialog 
  +{
  +	GtkDialog parent;
  +
  +  GtkListStore *store_unsaved_pages;
  +  
  +};
  +
  +struct _CloseConfirmationDialogClass 
  +{
  +	GtkDialogClass parent_class;
  +  
  +};
  +
  +
  +enum {
  +  PROP_UNSAVED_PAGE=1,
  +  PROP_UNSAVED_PAGES,
  +  PROP_SELECTED_PAGES,
  +};
  +
  +enum {
  +  COLUMN_SAVE,
  +  COLUMN_PAGE,
  +  NUM_COLUMNS
  +};
  +
  +
  +static gpointer close_confirmation_dialog_parent_class = NULL;
  +
  +
  +static void close_confirmation_dialog_class_init (CloseConfirmationDialogClass *klass);
  +static void close_confirmation_dialog_init (CloseConfirmationDialog *self);
  +static void close_confirmation_dialog_set_property (GObject      *object,
  +                                                    guint         property_id,
  +                                                    const GValue *value,
  +                                                    GParamSpec   *pspec);
  +static void close_confirmation_dialog_get_property (GObject      *object,
  +                                                    guint         property_id,
  +                                                    GValue       *value,
  +                                                    GParamSpec   *pspec);
  +static GObject* close_confirmation_dialog_constructor (GType type,
  +                                                       guint n_construct_properties,
  +                                                       GObjectConstructParam *construct_params);
  +
  +GList *close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog *dialog);
  +
  +
  +
  +GType
  +close_confirmation_dialog_get_type ()
  +{
  +  static GType close_confirmation_dialog_type = 0;
  +  
  +  if (!close_confirmation_dialog_type) {
  +    static const GTypeInfo close_confirmation_dialog_info = {
  +      sizeof(CloseConfirmationDialogClass),
  +      NULL, /* base_init */
  +      NULL, /* base_finalize */
  +      (GClassInitFunc) close_confirmation_dialog_class_init,
  +      NULL, /* class_finalize */
  +      NULL, /* class_data */
  +      sizeof(CloseConfirmationDialog),
  +      0,    /* n_preallocs */
  +      (GInstanceInitFunc) close_confirmation_dialog_init,
  +    };
  +                
  +    close_confirmation_dialog_type =
  +      g_type_register_static (GTK_TYPE_DIALOG,
  +                              "CloseConfirmationDialog",
  +                              &close_confirmation_dialog_info, 0);
  +  }
  +  
  +  return close_confirmation_dialog_type;
  +}
  +
  +static void
  +close_confirmation_dialog_class_init (CloseConfirmationDialogClass *klass)
  +{
  +  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  +
  +  close_confirmation_dialog_parent_class = g_type_class_peek_parent (klass);
  + 
  +  gobject_class->constructor  = close_confirmation_dialog_constructor;
  +  gobject_class->set_property = close_confirmation_dialog_set_property;
  +  gobject_class->get_property = close_confirmation_dialog_get_property;
  +
  +  g_object_class_install_property (
  +    gobject_class, PROP_UNSAVED_PAGE,
  +    g_param_spec_pointer ("unsaved-page",
  +                          "",
  +                          "",
  +                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
  +  g_object_class_install_property (
  +    gobject_class, PROP_UNSAVED_PAGES,
  +    g_param_spec_pointer ("unsaved-pages",
  +                          "",
  +                          "",
  +                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
  +  g_object_class_install_property (
  +    gobject_class, PROP_SELECTED_PAGES,
  +    g_param_spec_pointer ("selected-pages",
  +                          "",
  +                          "",
  +                          G_PARAM_READABLE));
  +
  +}
  +
  +static void
  +close_confirmation_dialog_init (CloseConfirmationDialog *self)
  +{
  +  /* create model for treeview and populate */
  +  self->store_unsaved_pages = gtk_list_store_new (NUM_COLUMNS,
  +                                                  G_TYPE_BOOLEAN,  /* save? */
  +                                                  G_TYPE_POINTER); /* page */
  +  
  +}
  +
  +/*! \brief Returns the number of pages in the model.
  + *  \par Function Description
  + *  This function determines the number of pages with unsaved changes
  + *  from the model.
  + *
  + *  \param in model The tree model.
  + *  \returns The number of pages with unsaved changes.
  + */
  +static gint
  +count_pages (GtkTreeModel *model)
  +{
  +  GtkTreeIter iter;
  +  gint n_pages;
  +  
  +  gtk_tree_model_get_iter_first (model, &iter);
  +  for (n_pages = 1;
  +       gtk_tree_model_iter_next (model, &iter);
  +       n_pages++);
  +
  +  return n_pages;
  +}
  +
  +/*! \brief Returns the name to use for the given page in the model.
  + *  \par Function Description
  + *  This function determines the text to be used to identify a
  + *  specific page from the model of pages with unsaved changes.
  + *
  + *  If <B>piter</B> is NULL, the name for the first page of the model
  + *  is returned. Otherwise, it returns the name for the page defined
  + *  by the pointed iterator.
  + *
  + *  The returned value must be freed by caller.
  + *
  + *  \param in model The tree model.
  + *  \param in piter A pointer on a GtkTreeIter of model or NULL.
  + *  \returns The name for the page.
  + */
  +static gchar*
  +get_page_name (GtkTreeModel *model, GtkTreeIter *piter)
  +{
  +  GtkTreeIter iter;
  +  PAGE *page;
  +  
  +  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
  +
  +  if (piter == NULL) {
  +    gtk_tree_model_get_iter_first (model, &iter);
  +  } else {
  +    iter = *piter;
  +  }
  +
  +  gtk_tree_model_get (model, &iter,
  +                      COLUMN_PAGE, &page,
  +                      -1);
  +  g_assert (page != NULL && page->page_filename != NULL);
  +  return g_path_get_basename (page->page_filename);
  +}
  +
  +/*! \brief Sets the contents of the name cell in the treeview of dialog.
  + *  \par Function Description
  + *  This functions sets the cell of the treeview with the short name
  + *  of the page obtained with <B>get_page_name()</B>.
  + *
  + *  \param in tree_column A GtkTreeColumn.
  + *  \param in cell        The GtkCellRenderer that is being rendered by
  + *                        tree_column.
  + *  \param in tree_model  The GtkTreeModel being rendered.
  + *  \param in iter        A GtkTreeIter of the current row rendered.
  + *  \param in data        .
  + */
  +static void
  +close_confirmation_dialog_set_page_name (GtkTreeViewColumn *tree_column,
  +                                         GtkCellRenderer   *cell,
  +                                         GtkTreeModel      *tree_model,
  +                                         GtkTreeIter       *iter,
  +                                         gpointer           data)
  +{
  +  gchar *page_name;
  +
  +  page_name = get_page_name (tree_model, iter);
  +  g_object_set (cell,
  +                "text", page_name,
  +                NULL);
  +  g_free (page_name);
  +  
  +}
  +
  +/*! \brief Callback function for the toggled signal of check box in treeview.
  + *  \par Function Description
  + *  This functions changes the value of the save column in the model
  + *  for the affected row when user toggles the check box in the
  + *  treeview.
  + *
  + *  \param in cell_renderer The GtkCellRendererToggle.
  + *  \param in path          The GtkTreePath to the concerned row in model.
  + *  \param in user          The dialog as user data.
  + */
  +static void
  +close_confirmation_dialog_callback_renderer_toggled (GtkCellRendererToggle *cell_renderer,
  +                                                     gchar                 *path,
  +                                                     gpointer               user_data)
  +{
  +  CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (user_data);
  +  GtkTreeModel *model;
  +	GtkTreeIter iter;
  +  gboolean save;
  +
  +  model = GTK_TREE_MODEL (dialog->store_unsaved_pages);
  +
  +  gtk_tree_model_get_iter_from_string (model, &iter, path);
  +	gtk_tree_model_get (model, &iter,
  +                      COLUMN_SAVE, &save,
  +                      -1);
  +	gtk_list_store_set (GTK_LIST_STORE (model), &iter,
  +                      COLUMN_SAVE, (save != TRUE),
  +                      -1);
  +  
  +}
  +
  +/*! \brief Adds a treeview to confirmation dialog for selecting of pages.
  + *  \par Function Description
  + *  This function adds a treeview and caption to display the content
  + *  of the dialog model of pages with unsaved changes.
  + *
  + *  The treeview displays the page names with check boxes.
  + *
  + *  \param in dialog The dialog.
  + *  \returns A pointer on the GtkVBox to add to dialog.
  + */
  +static GtkWidget*
  +close_confirmation_dialog_build_page_list (CloseConfirmationDialog *dialog)
  +{
  +  GtkWidget *vbox, *scrolled_window, *treeview, *label;
  +  GtkCellRenderer *renderer;
  +  GtkTreeViewColumn *column;
  +  const gchar *text;
  +
  +  /* place the treeview and its caption into their own box */
  +  vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
  +                                   /* GtkBox */
  +                                   "homogeneous", FALSE,
  +                                   "spacing",     8,
  +                                   NULL));
  +
  +  /* the list of pages with changes */
  +  /*  - scrolled window as container for the treeview first */
  +  scrolled_window = GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
  +                                              /* GtkScrolledWindow */
  +                                              "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
  +                                              "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
  +                                              "shadow-type",       GTK_SHADOW_IN,
  +                                              NULL));
  +  /*  - then the treeview */
  +  /* create model for treeview and populate */
  +  treeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
  +                                       /* GtkTreeView */
  +                                       "enable-search",   FALSE,
  +                                       "headers-visible", FALSE,
  +                                       "model",           dialog->store_unsaved_pages,
  +                                       NULL));
  +  renderer = gtk_cell_renderer_toggle_new ();
  +  g_signal_connect (renderer, "toggled",
  +                    G_CALLBACK (
  +                      close_confirmation_dialog_callback_renderer_toggled),
  +                    dialog);
  +  column   = gtk_tree_view_column_new_with_attributes ("Save?",
  +                                                       renderer,
  +                                                       "active", COLUMN_SAVE,
  +                                                       NULL);
  +  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
  +  
  +  renderer = gtk_cell_renderer_text_new ();
  +  column = GTK_TREE_VIEW_COLUMN (
  +    g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
  +                  /* GtkTreeViewColumn */
  +                  "title", _("Name"),
  +                  NULL));
  +  gtk_tree_view_column_pack_start (column, renderer, TRUE);
  +  gtk_tree_view_column_set_cell_data_func (column, renderer,
  +                                           close_confirmation_dialog_set_page_name,
  +                                           NULL, NULL);
  +  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
  +  
  +	gtk_container_add (GTK_CONTAINER (scrolled_window), treeview);
  +  
  +	gtk_box_pack_end (GTK_BOX (vbox), scrolled_window,
  +                    TRUE, TRUE, 0);
  +
  +  /* the caption label above the list of pages */
  +  label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
  +                                    /* GtkMisc */
  +                                    "xalign",          0.0,
  +                                    "yalign",          0.0,
  +                                    /* GtkLabel */
  +                                    "wrap",            TRUE,
  +                                    "mnemonic-widget", treeview,
  +                                    NULL));
  +  text = _("S_elect the schematics you want to save:");
  +  gtk_label_set_text_with_mnemonic (GTK_LABEL (label), text);
  +  gtk_label_set_mnemonic_widget (GTK_LABEL (label), treeview);
  +	gtk_box_pack_start (GTK_BOX (vbox), label,
  +                      FALSE, FALSE, 0);
  +  
  +  return vbox;
  +}
  +
  +static GObject*
  +close_confirmation_dialog_constructor (GType type,
  +                                       guint n_construct_properties,
  +                                       GObjectConstructParam *construct_params)
  +{
  +  GObject *object;
  +  CloseConfirmationDialog *dialog;
  +  GtkWidget *hbox, *image, *vbox, *label;
  +  GtkTreeIter iter;
  +  gboolean ret, single_page;
  +  gchar *tmp, *str;
  +
  +  /* chain up to constructor of parent class */
  +  object =
  +    G_OBJECT_CLASS (close_confirmation_dialog_parent_class)->constructor (
  +      type,
  +      n_construct_properties,
  +      construct_params);
  +  dialog = CLOSE_CONFIRMATION_DIALOG (object);
  +
  +  g_object_set (dialog,
  +                /* GtkDialog */
  +                "has-separator",     FALSE,
  +                /* GtkWindow */
  +                "resizable",         FALSE,
  +                "skip-taskbar-hint", TRUE,
  +                /* GtkContainer */
  +                "border-width",      5,
  +                NULL);
  +  g_object_set (GTK_DIALOG (dialog)->vbox,
  +                /* GtkBox */
  +                "spacing", 14,
  +                NULL);
  +  g_object_set (GTK_DIALOG (dialog)->action_area,
  +                /* GtkBox */
  +                "spacing",      6,
  +                /* GtkContainer */
  +                "border-width", 5,
  +                NULL);
  +                
  +  /* check if there is one or more than one page with changes */
  +  ret = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
  +                                         dialog->store_unsaved_pages),
  +                                       &iter);
  +  g_assert (ret);
  +  single_page = !gtk_tree_model_iter_next (GTK_TREE_MODEL (
  +                                             dialog->store_unsaved_pages),
  +                                           &iter);
  +
  +  /* here starts the layout of the dialog */
  +	hbox = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX,
  +                                   /* GtkContainer */
  +                                   "border-width", 5,
  +                                   /* GtkBox */
  +                                   "homogeneous",  FALSE,
  +                                   "spacing",      12,
  +                                   NULL));
  +
  +  /* warning image */
  +	image = g_object_new (GTK_TYPE_IMAGE,
  +                        /* GtkMisc */
  +                        "xalign",    0.5,
  +                        "yalign",    0.0,
  +                        /* GtkImage */
  +                        "stock",     GTK_STOCK_DIALOG_WARNING,
  +                        "icon-size", GTK_ICON_SIZE_DIALOG,
  +                        NULL);
  +	gtk_box_pack_start (GTK_BOX (hbox), image,
  +                      FALSE, FALSE, 0);
  +
  +  /* vertical box on the right hand side of the dialog */
  +  vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
  +                                   /* GtkBox */
  +                                   "homogeneous", FALSE,
  +                                   "spacing",     12,
  +                                   NULL));
  +
  +  /* primary label */
  +  if (single_page) {
  +    /* single page */
  +    gchar *page_name;
  +    
  +    page_name = get_page_name (GTK_TREE_MODEL (dialog->store_unsaved_pages),
  +                               NULL);
  +    tmp = g_strdup_printf (
  +      _("Save the changes to schematic \"%s\" before closing?"),
  +      page_name);
  +    g_free (page_name);
  +  } else {
  +    /* multi page */
  +    tmp = g_strdup_printf (
  +      _("There is %d schematics with unsaved changes. "
  +        "Save changes before closing?"),
  +      count_pages (GTK_TREE_MODEL (dialog->store_unsaved_pages)));
  +  }
  +  str = g_strconcat ("<big><b>", tmp, "</b></big>", NULL);
  +  g_free (tmp);
  +  label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
  +                                    /* GtkMisc */
  +                                    "xalign",     0.0,
  +                                    "yalign",     0.0,
  +                                    "selectable", TRUE,
  +                                    /* GtkLabel */
  +                                    "wrap",       TRUE,
  +                                    "use-markup", TRUE,
  +                                    "label",      str,
  +                                    NULL));
  +  g_free (str);
  +	gtk_box_pack_start (GTK_BOX (vbox), label,
  +                      FALSE, FALSE, 0);
  +
  +  if (!single_page) {
  +    /* more than one page with changes, display each page and offer */
  +    /* the opportunity to save them before exiting */
  +    gtk_box_pack_start (GTK_BOX (vbox),
  +                        close_confirmation_dialog_build_page_list (dialog),
  +                        FALSE, FALSE, 0);
  +  }
  +  
  +  /* secondary label */
  +  str = _("If you don't save, all your changes will be permanently lost.");
  +  label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
  +                                    /* GtkMisc */
  +                                    "xalign",     0.0,
  +                                    "yalign",     0.0,
  +                                    "selectable", TRUE,
  +                                    /* GtkLabel */
  +                                    "wrap",       TRUE,
  +                                    "label",      str,
  +                                    NULL));
  +	gtk_box_pack_start (GTK_BOX (vbox), label,
  +                      FALSE, FALSE, 0);
  +
  +  
  +	gtk_box_pack_start (GTK_BOX (hbox), vbox,
  +                      FALSE, FALSE, 0);
  +
  +
  +  /* add buttons to dialog action area */
  +  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
  +                          _("_Close without saving"), GTK_RESPONSE_NO,
  +                          GTK_STOCK_CANCEL,           GTK_RESPONSE_CANCEL,
  +                          GTK_STOCK_SAVE,             GTK_RESPONSE_YES,
  +                          NULL);
  +
  +  /* all done, let's show the contents of the dialog */
  +	gtk_widget_show_all (hbox);
  +
  +	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, 
  +	                    FALSE, FALSE, 0);
  +  
  +  return object;
  +};
  +
  +static void
  +close_confirmation_dialog_set_property (GObject      *object,
  +                                        guint         property_id,
  +                                        const GValue *value,
  +                                        GParamSpec   *pspec)
  +{
  +  CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (object);
  +  GtkTreeIter iter;
  +  gpointer data;
  +  GList *p_current;
  +
  +  switch(property_id) {
  +    case PROP_UNSAVED_PAGE:
  +      data = g_value_get_pointer (value);
  +      if (data != NULL) {
  +        /* add single page to model */
  +        gtk_list_store_append (dialog->store_unsaved_pages,
  +                               &iter);
  +        gtk_list_store_set (dialog->store_unsaved_pages,
  +                            &iter,
  +                            COLUMN_SAVE, TRUE,
  +                            COLUMN_PAGE, data,
  +                            -1);
  +      }
  +      break;
  +      
  +    case PROP_UNSAVED_PAGES:
  +      data = g_value_get_pointer (value);
  +      /* add set of pages to model */
  +      for (p_current = (GList*)data;
  +           p_current != NULL;
  +           p_current = g_list_next (p_current)) {
  +        gtk_list_store_append (dialog->store_unsaved_pages,
  +                               &iter);
  +        gtk_list_store_set (dialog->store_unsaved_pages,
  +                            &iter,
  +                            COLUMN_SAVE, TRUE,
  +                            COLUMN_PAGE, p_current->data,
  +                            -1);
  +      }
  +      break;
  +      
  +    default:
  +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  +  }
  +  
  +}
  +
  +static void
  +close_confirmation_dialog_get_property (GObject    *object,
  +                                        guint       property_id,
  +                                        GValue     *value,
  +                                        GParamSpec *pspec)
  +{
  +  CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (object);
  +
  +  switch(property_id) {
  +    case PROP_SELECTED_PAGES:
  +      g_value_set_pointer (
  +        value,
  +        close_confirmation_dialog_get_selected_pages (dialog));
  +      break;
  +      
  +    default:
  +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  +  }
  +  
  +}
  +
  +/*! \brief Helps building a list of selected page to save.
  + *  \par Function Description
  + *  This is the <B>GtkTreeModelForeachFunc</B> for function
  + *  <B>close_confirmation_dialog_get_selected_pages()</B>.
  + *
  + *  It builds from the tree model a list of PAGEs for which a save
  + *  action has been requested. Each selected page is appended to the
  + *  GList pointed by <B>data</B>
  + *
  + *  \param in model The tree model.
  + *  \param in path  .
  + *  \param in iter  .
  + *  \param in data  A pointer on a GList* to fill.
  + *  \returns FALSE to continue walking the tree.
  + */
  +static gboolean
  +get_selected_pages (GtkTreeModel *model,
  +                    GtkTreePath  *path,
  +                    GtkTreeIter  *iter,
  +                    gpointer     data)
  +{
  +  PAGE *page;
  +  gboolean save;
  +  
  +  gtk_tree_model_get (model, iter,
  +                      COLUMN_SAVE, &save,
  +                      COLUMN_PAGE, &page,
  +                      -1);
  +  if (save) {
  +    g_assert (page != NULL);
  +    *(GList**)data = g_list_append (*(GList**)data, page);
  +  }
  +
  +  return FALSE;
  +}
  +
  +/*! \brief Returns a list of the selected pages with changes to save.
  + *  \par Function Description
  + *  This function returns the pages that the user has selected in the
  + *  confirmation dialog.
  + *
  + *  The returned list must be freed.
  + *
  + *  \param in dialog The dialog.
  + *  \returns A GList of selected PAGE* in dialog.
  + */
  +GList*
  +close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog *dialog)
  +{
  +  GList *selected = NULL;
  +
  +  gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->store_unsaved_pages),
  +                          (GtkTreeModelForeachFunc)get_selected_pages,
  +                          &selected);
  +  
  +  return selected;
  +}
  +
  +
  +/*! \brief Asks for confirmation before closing a changed page.
  + *  \par Function Description
  + *  This function asks the user to confirm its closing order for
  + *  page <B>page</B> while it still has unsaved changes.
  + *
  + *  It displays a message dialog inviting the user to cancel the
  + *  closing, or to discard the changes or to save the changes to a
  + *  file.
  + *
  + *  \param in toplevel The toplevel environment.
  + *  \param in page     The page to close.
  + */
  +void
  +x_dialog_close_changed_page (TOPLEVEL *toplevel, PAGE *page)
  +{
  +	GtkWidget *dialog;
  +
  +  g_return_if_fail (page != NULL && page->CHANGED);
  +  
  +  dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
  +                                     "unsaved-page", page,
  +                                     NULL));
  +  switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
  +      case GTK_RESPONSE_NO:
  +        /* action selected: close without saving */
  +        /* close the page, discard changes */
  +        x_window_close_page (toplevel, page);
  +        break;
  +        
  +      case GTK_RESPONSE_CANCEL:
  +        /* action selected: cancel */
  +        /* nothing to do */
  +        break;
  +
  +      case GTK_RESPONSE_YES:
  +        /* action selected: save */
  +        /* prompts user for the filename and ultimate confirmation */
  +        s_page_goto (toplevel, page);
  +        x_fileselect_save (toplevel);
  +        /* has the page been really saved? */
  +        if (!page->CHANGED) {
  +          x_window_close_page (toplevel, page);
  +        }
  +        /* no, user has cancelled the save and page has changes */
  +        /* do not close page */
  +        break;
  +        
  +      default:
  +        g_assert_not_reached ();
  +  }
  +  gtk_widget_destroy (dialog);
  +
  +}
  +
  +/*! \brief Asks for confirmation before closing a window.
  + *  \par Function Description
  + *  This function asks the user to confirm its closing order for
  + *  the given window.
  + *
  + *  The user is given the possibility to save the pages that currently
  + *  have unsaved changes, if any.
  + *
  + *  It returns TRUE if the user really accepts the close of the
  + *  window. Otherwise the user has somehow cancelled and the window
  + *  must not be closed.
  + *  
  + *  \param in toplevel The toplevel environment.
  + *  \returns TRUE if the window can be closed, FALSE otherwise.
  + */
  +gboolean
  +x_dialog_close_window (TOPLEVEL *toplevel)
  +{
  +	GtkWidget *dialog;
  +  PAGE *p_current;
  +  GList *unsaved_pages, *p_unsaved;
  +  gboolean ret = FALSE;
  +
  +  /* build a list of unsaved pages */
  +  g_assert (toplevel->page_head != NULL &&
  +            toplevel->page_head->next != NULL);
  +  for (p_current = toplevel->page_head->next, unsaved_pages = NULL;
  +       p_current != NULL;
  +       p_current = p_current->next) {
  +    if (p_current->CHANGED) {
  +      unsaved_pages = g_list_append (unsaved_pages, (gpointer)p_current);
  +    }
  +  }
  +
  +  if (unsaved_pages == NULL) {
  +    /* no page with unsaved changes, close window */
  +    return TRUE;
  +  }
  +
  +  dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
  +                                     "unsaved-pages", unsaved_pages,
  +                                     NULL));
  +  g_list_free (unsaved_pages);
  +  switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
  +      case GTK_RESPONSE_NO:
  +        /* action selected: close without saving */
  +        /* discard changes, ok to close window */
  +        ret = TRUE;
  +        break;
  +        
  +      case GTK_RESPONSE_CANCEL:
  +        /* action selected: cancel */
  +        /* do not close window */
  +        ret = FALSE;
  +        break;
  +
  +      case GTK_RESPONSE_YES:
  +        /* action selected: save */
  +        /* prompts user for the filename and ultimate confirmation for */
  +        /* each selected page */
  +        g_object_get (dialog,
  +                      "selected-pages", &unsaved_pages,
  +                      NULL);
  +        for (p_unsaved = unsaved_pages, ret = TRUE;
  +             p_unsaved != NULL;
  +             p_unsaved = g_list_next (p_unsaved)) {
  +          p_current = (PAGE*)p_unsaved->data;
  +          
  +          s_page_goto (toplevel, p_current);
  +          x_fileselect_save (toplevel);
  +          /* if user cancelled previous, do not close window */
  +          ret &= !p_current->CHANGED;
  +        }
  +        g_list_free (unsaved_pages);
  +        break;
  +        
  +      default:
  +        g_assert_not_reached ();
  +  }
  +  gtk_widget_destroy (dialog);
  +
  +  return ret;
  +}
  +
  +/***************** End of Close Confirmation dialog box **************/
  +
  
  
  
  1.30      +10 -101   eda/geda/gaf/gschem/src/x_fileselect.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: x_fileselect.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/gschem/src/x_fileselect.c,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -b -r1.29 -r1.30
  --- x_fileselect.c	23 Sep 2006 16:09:30 -0000	1.29
  +++ x_fileselect.c	4 Oct 2006 20:11:40 -0000	1.30
  @@ -151,75 +151,6 @@
     
   }
   
  -/*! \brief Opens a file.
  - *  \par Function Description
  - *  This is an helper function for <B>x_fileselect_open()</B>. It
  - *  opens a single file and creates a new page for it in the specified
  - *  toplevel environnement if it does not already exists.
  - *
  - *  If the file is already loaded, it changes the toplevel
  - *  environement's current page to the existing page. Otherwise the
  - *  toplevel's current page is changed to be the newly created page.
  - *
  - *  It handles possible errors while reading file. It also updates the
  - *  user interface.
  - *
  - *  \param [in] filename The name of the file to open.
  - *  \param [in] toplevel The toplevel environment.
  - */
  -static void
  -x_fileselect_open_file (gchar *filename, TOPLEVEL *toplevel)
  -{
  -  PAGE *page;
  -
  -  g_return_if_fail (filename != NULL);
  -  g_return_if_fail (toplevel != NULL);
  -  g_return_if_fail (g_file_test (filename, G_FILE_TEST_EXISTS));
  -
  -  /* search in toplevel for a page with name filename */
  -  page = s_page_search (toplevel, filename);
  -  if (page == NULL) {
  -    /* create a new page and make it the current page for toplevel */
  -    s_page_goto (toplevel, s_page_new (toplevel, filename));
  -
  -    toplevel->DONT_REDRAW = 1;
  -
  -    /* open the file in current page */
  -    f_open(toplevel, filename);
  -    /* test value returned by f_open() */
  -    /* TBD */
  -
  -    /* update GUI, redraw */
  -    i_set_filename (toplevel, toplevel->page_current->page_filename);
  -    x_repaint_background (toplevel);
  -    x_manual_resize (toplevel);
  -    a_zoom_extents (toplevel, 
  -                    toplevel->page_current->object_head,
  -                    A_PAN_DONT_REDRAW);
  -    o_undo_savestate (toplevel, UNDO_ALL);
  -    /* now update the scrollbars */
  -    x_hscrollbar_update (toplevel);
  -    x_vscrollbar_update (toplevel);
  -    x_pagesel_update (toplevel);
  -
  -    toplevel->DONT_REDRAW = 0;
  -
  -    o_redraw_all(toplevel);
  -
  -  } else {
  -    /* change to this page */
  -    s_page_goto (toplevel, page);
  -
  -    /* update GUI and redraw */
  -    x_pagesel_update (toplevel);
  -    i_set_filename (toplevel, toplevel->page_current->page_filename);
  -    x_scrollbars_update (toplevel);
  -    o_redraw_all(toplevel);
  -
  -  }
  -  
  -}
  -
   /*! \brief Opens a file chooser for opening one or more schematics.
    *  \par Function Description
    *  This function opens a file chooser dialog and wait for the user to
  @@ -252,13 +183,13 @@
     x_fileselect_setup_filechooser_filters (GTK_FILE_CHOOSER (dialog));
     gtk_widget_show (dialog);
     if (gtk_dialog_run ((GtkDialog*)dialog) == GTK_RESPONSE_ACCEPT) {
  -    GSList *filenames =
  +    GSList *tmp, *filenames =
         gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog));
   
       /* open each file */
  -    g_slist_foreach (filenames,
  -                     (GFunc)x_fileselect_open_file,
  -                     (gpointer)toplevel);
  +    for (tmp = filenames; tmp != NULL;tmp = g_slist_next (tmp)) {
  +      x_window_open_page (toplevel, (gchar*)tmp->data);
  +    }
       
       /* free the list of filenames */
       g_slist_foreach (filenames, (GFunc)g_free, NULL);
  @@ -309,32 +240,10 @@
         gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
   
       /* try saving current page of toplevel to file filename */
  -    if (filename != NULL &&
  -        f_save (toplevel, filename)) {
  -      s_log_message (_("Saved As [%s]\n"), filename);
  -
  -      /* replace page filename with new one, do not free filename */
  -      g_free (toplevel->page_current->page_filename);
  -      toplevel->page_current->page_filename = filename;
  -
  -      /* reset the changed flag of current page*/
  -      toplevel->page_current->CHANGED = 0;
  -
  -      i_set_filename (toplevel, toplevel->page_current->page_filename);
  -
  -      x_pagesel_update (toplevel);
  -
  -    } else {
  -      /* report error in log and status bar */
  -      s_log_message (_("Could NOT save [%s]\n"),
  -                     toplevel->page_current->page_filename);
  -
  -      i_set_state_msg (toplevel, SELECT, _("Error while trying to save"));
  -
  -      i_update_toolbar (toplevel);
  -
  -      g_free (filename);
  -
  +    if (filename != NULL) {
  +      x_window_save_page (toplevel,
  +                          toplevel->page_current,
  +                          filename);
       }
     }
     gtk_widget_destroy (dialog);
  
  
  
  1.48      +270 -2    eda/geda/gaf/gschem/src/x_window.c
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: x_window.c
  ===================================================================
  RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/gschem/src/x_window.c,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -b -r1.47 -r1.48
  --- x_window.c	4 Oct 2006 19:10:30 -0000	1.47
  +++ x_window.c	4 Oct 2006 20:11:40 -0000	1.48
  @@ -739,8 +739,9 @@
   {
     gboolean last_window = FALSE;
   
  -  if (s_page_check_changed(w_current->page_head)) {
  -    exit_dialog(w_current);
  +  /* last chance to save possible unsaved pages */
  +  if (!x_dialog_close_window (w_current)) {
  +    /* user somehow cancelled the close */
       return;
     }
   
  @@ -909,5 +910,272 @@
     return w_current;
   }
   
  +/*! \brief Opens a new untitled page.
  + *  \par Function Description
  + *  This function creates an empty, untitled page in <B>toplevel</B>.
  + *
  + *  It returns a pointer on the new page.
  + *
  + *  The new page becomes the current page of <B>toplevel</B>.
  + *
  + *  The name of the untitled page is build from configuration data
  + *  ('untitled-name') and a counter for uniqueness.
  + *
  + *  \param [in] toplevel The toplevel environment.
  + *  \returns A pointer on the new page.
  + */
  +PAGE*
  +x_window_open_untitled_page (TOPLEVEL *toplevel)
  +{
  +  PAGE *page;
  +  gchar *cwd, *tmp, *filename;
  + 
  +  cwd = g_get_current_dir ();
  +  tmp = g_strdup_printf ("%s_%d.sch",
  +                         toplevel->untitled_name,
  +                         toplevel->num_untitled++);
  +  filename = g_build_filename (cwd, tmp, NULL);
  +  g_free (cwd);
  +  g_free (tmp);
  +   
  +  page = x_window_open_page (toplevel, filename);
  +  
  +  g_free (filename);
  +
  +  if (scm_hook_empty_p (new_page_hook) == SCM_BOOL_F) {
  +    scm_run_hook (new_page_hook,
  +                  scm_cons (g_make_page_smob (toplevel, page), SCM_EOL));
  +  }
  +  
  +  a_zoom_extents(toplevel, page->object_head, 0);
  +  
  +  return page;
  +}
  +
  +/*! \brief Opens a new page from a file.
  + *  \par Function Description
  + *  This function opens the file whose name is <B>filename</B> in a
  + *  new PAGE of <B>toplevel</B>.
  + *
  + *  If there is no page for <B>filename</B> in <B>toplevel</B>'s list
  + *  of pages, it creates a new PAGE, loads the file in it and returns
  + *  a pointer on the new page. Otherwise it returns a pointer on the
  + *  existing page.
  + *
  + *  The opened page becomes the current page of <B>toplevel</B>.
  + *
  + *  \param [in] toplevel The toplevel environment.
  + *  \param [in] filename The name of the file to open.
  + *  \returns A pointer on the new page.
  + */
  +PAGE*
  +x_window_open_page (TOPLEVEL *toplevel, const gchar *filename)
  +{
  +  PAGE *old_current, *page;
  +
  +  g_return_val_if_fail (toplevel != NULL, NULL);
  +  g_return_val_if_fail (filename != NULL, NULL);
  +  
  +  /* save current page for restore after opening */
  +  old_current = toplevel->page_current;
  +
  +  /* is file already loaded? */
  +  page = s_page_search (toplevel, filename);
  +  if (page == NULL) {
  +    /* no, create a page and load file in it */
  +    page = s_page_new (toplevel, filename);
  +    s_page_goto (toplevel, page);
  +    
  +    if (!quiet_mode) {
  +      printf(_("Loading schematic [%s]\n"), filename);
  +    }
  +
  +    if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
  +      f_open (toplevel, (gchar *) filename);
  +    }
  +    
  +    i_set_filename (toplevel, toplevel->page_current->page_filename);
  +    a_zoom_extents (toplevel,
  +                    toplevel->page_current->object_head,
  +                    A_PAN_DONT_REDRAW);
  +    o_undo_savestate (toplevel, UNDO_ALL);
  +
  +    x_pagesel_update (toplevel);
  +    
  +  }
  +
  +  /* display the page in window */
  +  x_window_set_current_page (toplevel, page);
  +  
  +  return page;
  +}
  +
  +/*! \brief Changes the current page.
  + *  \par Function Description
  + *  This function displays the specified page <B>page</B> in the
  + *  window attached to <B>toplevel</B>.
  + *
  + *  It changes the <B>toplevel</B>'s current page to <B>page</B>,
  + *  draws it and updates the user interface.
  + *
  + *  <B>page</B> has to be in the list of PAGEs attached to <B>toplevel</B>.
  + *
  + *  \param [in] toplevel The toplevel environment.
  + *  \param [in] page     The page to become current page.
  + */
  +void
  +x_window_set_current_page (TOPLEVEL *toplevel, PAGE *page)
  +{
  +  g_return_if_fail (toplevel != NULL);
  +  g_return_if_fail (page != NULL);
   
  +  s_page_goto (toplevel, page);
   
  +  i_update_menus (toplevel);
  +  i_set_filename (toplevel, page->page_filename);
  +
  +  x_pagesel_update (toplevel);
  +  
  +  x_repaint_background (toplevel);
  +  x_manual_resize (toplevel);
  +  x_hscrollbar_update (toplevel);
  +  x_vscrollbar_update (toplevel);
  +
  +  toplevel->DONT_REDRAW = 0;
  +  o_redraw_all (toplevel);
  +  
  +}
  +
  +/*! \brief Saves a page to a file.
  + *  \par Function Description
  + *  This function saves the page <B>page</B> to a file named
  + *  <B>filename</B>.
  + *
  + *  It returns the value returned by function <B>f_save()</B> trying
  + *  to save page <B>page</B> to file <B>filename</B> (1 on success, 0
  + *  on failure).
  + *
  + *  <B>page</B> may not be the current page of <B>toplevel</B>. The
  + *  current page of <B>toplevel</B> is not affected by this function.
  + *
  + *  \param [in] toplevel The toplevel environment.
  + *  \param [in] page     The page to save.
  + *  \param [in] filename The name of the file in which to save page.
  + *  \returns 1 on success, 0 otherwise.
  + */
  +gint
  +x_window_save_page (TOPLEVEL *toplevel, PAGE *page, const gchar *filename)
  +{
  +  PAGE *old_current;
  +  const gchar *log_msg, *state_msg;
  +  gint ret;
  +
  +  g_return_val_if_fail (toplevel != NULL, 0);
  +  g_return_val_if_fail (page     != NULL, 0);
  +  g_return_val_if_fail (filename != NULL, 0);
  +  
  +  /* save current page for restore after opening */
  +  old_current = toplevel->page_current;
  +
  +  /* change to page */
  +  s_page_goto (toplevel, page);
  +  /* and try saving current page to filename */
  +  ret = (gint)f_save (toplevel, filename);
  +  if (ret != 1) {
  +    /* an error occured when saving page to file */
  +    log_msg   = _("Could NOT save page [%s]\n");
  +    state_msg = _("Error while trying to save");
  +    
  +  } else {
  +    /* successful save of page to file, update page... */
  +    /* change page name if necessary and prepare log message */
  +    if (g_ascii_strcasecmp (page->page_filename, filename) != 0) {
  +      g_free (page->page_filename);
  +      page->page_filename = g_strdup (filename);
  +
  +      log_msg = _("Saved as [%s]\n");
  +    } else {
  +      log_msg = _("Saved [%s]\n");
  +    }
  +    state_msg = _("Saved");
  +      
  +    /* reset page CHANGED flag */
  +    page->CHANGED = 0;
  +    
  +  }
  +
  +  /* log status of operation */
  +  s_log_message (log_msg, filename);
  +  
  +  /* update display and page manager */
  +  i_set_state_msg  (toplevel, SELECT, state_msg);
  +  i_set_filename   (toplevel, page->page_filename);
  +  i_update_toolbar (toplevel);
  +  i_update_menus   (toplevel);
  +  x_pagesel_update (toplevel);
  +
  +  /* restore current page in toplevel */
  +  s_page_goto (toplevel, old_current);
  +
  +  return ret;
  +}
  +
  +/*! \brief Closes a page.
  + *  \par Function Description
  + *  This function closes the page <B>page</B> of toplevel
  + *  <B>toplevel</B>.
  + *
  + *  If necessary, the current page of <B>toplevel</B> is changed to
  + *  the next valid page or to a new untitled page.
  + *
  + *  \param [in] toplevel The toplevel environment.
  + *  \param [in] page     The page to close.
  + */
  +void
  +x_window_close_page (TOPLEVEL *toplevel, PAGE *page)
  +{
  +  PAGE *new_current = NULL;
  +
  +  g_return_if_fail (toplevel != NULL);
  +  g_return_if_fail (page     != NULL);
  +
  +  g_assert (page->pid != -1);
  +
  +  if (page == toplevel->page_current) {
  +    /* as it will delete current page, select new current page */
  +    /* first look up in page hierarchy */
  +    new_current = s_hierarchy_find_page (toplevel->page_head, page->up);
  +    if (new_current == NULL) {
  +      /* no up in hierarchy, choice is next, prev, new page */
  +      if (page->prev && page->prev->pid != -1) {
  +        new_current = page->prev;
  +      } else if (page->next != NULL) {
  +        new_current = page->next;
  +      } else {
  +        /* need to add a new untitled page */
  +        new_current = NULL;
  +      }
  +    }
  +    /* new_current will be the new current page at the end of the function */
  +  }
  +
  +  s_log_message (page->CHANGED ?
  +                 _("Discarding page [%s]\n") : _("Closing [%s]\n"),
  +                 page->page_filename);
  +  /* remove page from toplevel list of page and free */
  +  s_page_delete (toplevel, page);
  +
  +  if (toplevel->page_current == NULL) {
  +    /* page was the current page of toplevel, set new current */
  +    if (new_current == NULL) {
  +      /* empty page list in toplevel, create new page */
  +      new_current = x_window_open_untitled_page (toplevel);
  +    } else {
  +      /* change to new_current and update display */
  +      x_window_set_current_page (toplevel, new_current);
  +    }    
  +    g_assert (new_current != NULL);
  +    
  +  }
  +
  +}
  
  
  


_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs