[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