Updated versions in prep for a new version
[geda-gaf.git] / gschem / src / x_fileselect.c
blob46c3ea62fd822aa05be2116f2b5b56d4648186ce
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2008 Ales Hvezda
4 * Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include "gschem.h"
24 #ifdef HAVE_LIBDMALLOC
25 #include <dmalloc.h>
26 #endif
29 /*! \brief Creates filter for file chooser.
30 * \par Function Description
31 * This function adds file filters to <B>filechooser</B>.
33 * \param [in] filechooser The file chooser to add filter to.
35 static void
36 x_fileselect_setup_filechooser_filters (GtkFileChooser *filechooser)
38 GtkFileFilter *filter;
40 /* file filter for schematic files (*.sch) */
41 filter = gtk_file_filter_new ();
42 gtk_file_filter_set_name (filter, _("Schematics"));
43 gtk_file_filter_add_pattern (filter, "*.sch");
44 gtk_file_chooser_add_filter (filechooser, filter);
45 /* file filter for symbol files (*.sym) */
46 filter = gtk_file_filter_new ();
47 gtk_file_filter_set_name (filter, _("Symbols"));
48 gtk_file_filter_add_pattern (filter, "*.sym");
49 gtk_file_chooser_add_filter (filechooser, filter);
50 /* file filter for both symbol and schematic files (*.sym+*.sch) */
51 filter = gtk_file_filter_new ();
52 gtk_file_filter_set_name (filter, _("Schematics and symbols"));
53 gtk_file_filter_add_pattern (filter, "*.sym");
54 gtk_file_filter_add_pattern (filter, "*.sch");
55 gtk_file_chooser_add_filter (filechooser, filter);
56 /* file filter that match any file */
57 filter = gtk_file_filter_new ();
58 gtk_file_filter_set_name (filter, _("All files"));
59 gtk_file_filter_add_pattern (filter, "*");
60 gtk_file_chooser_add_filter (filechooser, filter);
64 /*! \brief Updates the preview when the selection changes.
65 * \par Function Description
66 * This is the callback function connected to the 'update-preview'
67 * signal of the <B>GtkFileChooser</B>.
69 * It updates the preview widget with the name of the newly selected
70 * file.
72 * \param [in] chooser The file chooser to add the preview to.
73 * \param [in] user_data A pointer on the preview widget.
75 static void
76 x_fileselect_callback_update_preview (GtkFileChooser *chooser,
77 gpointer user_data)
79 Preview *preview = PREVIEW (user_data);
80 gchar *filename, *preview_filename = NULL;
82 filename = gtk_file_chooser_get_preview_filename (chooser);
83 if (filename != NULL &&
84 !g_file_test (filename, G_FILE_TEST_IS_DIR)) {
85 preview_filename = filename;
88 /* update preview */
89 g_object_set (preview,
90 "filename", preview_filename,
91 "active", (preview_filename != NULL),
92 NULL);
94 g_free (filename);
97 /*! \brief Adds a preview to a file chooser.
98 * \par Function Description
99 * This function adds a preview section to the stock
100 * <B>GtkFileChooser</B>.
102 * The <B>Preview</B> object is inserted in a frame and alignment
103 * widget for accurate positionning.
105 * Other widgets can be added to this preview area for example to
106 * enable/disable the preview. Currently, the preview is always
107 * active.
109 * Function <B>x_fileselect_callback_update_preview()</B> is
110 * connected to the signal 'update-preview' of <B>GtkFileChooser</B>
111 * so that it redraws the preview area every time a new file is
112 * selected.
114 * \param [in] filechooser The file chooser to add the preview to.
116 static void
117 x_fileselect_add_preview (GtkFileChooser *filechooser)
119 GtkWidget *alignment, *frame, *preview;
121 frame = GTK_WIDGET (g_object_new (GTK_TYPE_FRAME,
122 "label", _("Preview"),
123 NULL));
124 alignment = GTK_WIDGET (g_object_new (GTK_TYPE_ALIGNMENT,
125 "right-padding", 5,
126 "left-padding", 5,
127 "xscale", 0.0,
128 "yscale", 0.0,
129 "xalign", 0.5,
130 "yalign", 0.5,
131 NULL));
132 preview = GTK_WIDGET (g_object_new (TYPE_PREVIEW,
133 "active", TRUE,
134 NULL));
135 gtk_container_add (GTK_CONTAINER (alignment), preview);
136 gtk_container_add (GTK_CONTAINER (frame), alignment);
137 gtk_widget_show_all (frame);
139 g_object_set (filechooser,
140 /* GtkFileChooser */
141 "use-preview-label", FALSE,
142 "preview-widget", frame,
143 NULL);
145 /* connect callback to update preview */
146 g_signal_connect (filechooser,
147 "update-preview",
148 G_CALLBACK (x_fileselect_callback_update_preview),
149 preview);
153 /*! \brief Opens a file chooser for opening one or more schematics.
154 * \par Function Description
155 * This function opens a file chooser dialog and wait for the user to
156 * select at least one file to load as <B>w_current</B>'s new pages.
158 * The function updates the user interface.
160 * At the end of the function, the w_current->toplevel's current page
161 * is set to the page of the last loaded page.
163 * \param [in] w_current The GSCHEM_TOPLEVEL environment.
165 void
166 x_fileselect_open(GSCHEM_TOPLEVEL *w_current)
168 PAGE *page = NULL;
169 GtkWidget *dialog;
171 dialog = gtk_file_chooser_dialog_new (_("Open..."),
172 GTK_WINDOW(w_current->main_window),
173 GTK_FILE_CHOOSER_ACTION_OPEN,
174 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
175 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
176 NULL);
178 /* Set the alternative button order (ok, cancel, help) for other systems */
179 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
180 GTK_RESPONSE_ACCEPT,
181 GTK_RESPONSE_CANCEL,
182 -1);
184 x_fileselect_add_preview (GTK_FILE_CHOOSER (dialog));
185 g_object_set (dialog,
186 /* GtkFileChooser */
187 "select-multiple", TRUE,
188 NULL);
189 /* add file filters to dialog */
190 x_fileselect_setup_filechooser_filters (GTK_FILE_CHOOSER (dialog));
191 gtk_widget_show (dialog);
192 if (gtk_dialog_run ((GtkDialog*)dialog) == GTK_RESPONSE_ACCEPT) {
193 GSList *tmp, *filenames =
194 gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (dialog));
196 /* open each file */
197 for (tmp = filenames; tmp != NULL;tmp = g_slist_next (tmp)) {
198 page = x_window_open_page (w_current, (gchar*)tmp->data);
200 /* Switch to the last page opened */
201 if ( page != NULL )
202 x_window_set_current_page (w_current, page);
204 /* free the list of filenames */
205 g_slist_foreach (filenames, (GFunc)g_free, NULL);
206 g_slist_free (filenames);
208 gtk_widget_destroy (dialog);
212 /*! \brief Opens a file chooser for saving the current page.
213 * \par Function Description
214 * This function opens a file chooser dialog and wait for the user to
215 * select a file where the <B>toplevel</B>'s current page will be
216 * saved.
218 * If the user cancels the operation (with the cancel button), the
219 * page is not saved.
221 * The function updates the user interface.
223 * \param [in] w_current The GSCHEM_TOPLEVEL environment.
225 void
226 x_fileselect_save (GSCHEM_TOPLEVEL *w_current)
228 TOPLEVEL *toplevel = w_current->toplevel;
229 GtkWidget *dialog;
231 dialog = gtk_file_chooser_dialog_new (_("Save as..."),
232 GTK_WINDOW(w_current->main_window),
233 GTK_FILE_CHOOSER_ACTION_SAVE,
234 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
235 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
236 NULL);
238 /* Set the alternative button order (ok, cancel, help) for other systems */
239 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
240 GTK_RESPONSE_ACCEPT,
241 GTK_RESPONSE_CANCEL,
242 -1);
244 /* set default response signal. This is usually triggered by the
245 "Return" key */
246 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
247 GTK_RESPONSE_ACCEPT);
249 g_object_set (dialog,
250 /* GtkFileChooser */
251 "select-multiple", FALSE,
252 /* only in GTK 2.8 */
253 /* "do-overwrite-confirmation", TRUE, */
254 NULL);
255 /* add file filters to dialog */
256 x_fileselect_setup_filechooser_filters (GTK_FILE_CHOOSER (dialog));
257 /* set the current filename or directory name if new document */
258 if ((toplevel->page_current->page_filename != NULL) &&
259 g_file_test (toplevel->page_current->page_filename,
260 G_FILE_TEST_EXISTS)) {
261 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog),
262 toplevel->page_current->page_filename);
263 } else {
264 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog),
265 "untitled.sch");
268 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
269 GTK_RESPONSE_ACCEPT);
270 gtk_widget_show (dialog);
271 if (gtk_dialog_run ((GtkDialog*)dialog) == GTK_RESPONSE_ACCEPT) {
272 gchar *filename =
273 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
275 /* If the file already exists, display a dialog box to check if
276 the user really wants to overwrite it. */
277 if ((filename != NULL) && g_file_test (filename, G_FILE_TEST_EXISTS)) {
278 GtkWidget *checkdialog =
279 gtk_message_dialog_new (GTK_WINDOW(dialog),
280 (GTK_DIALOG_MODAL |
281 GTK_DIALOG_DESTROY_WITH_PARENT),
282 GTK_MESSAGE_QUESTION,
283 GTK_BUTTONS_YES_NO,
284 _("The selected file `%s' already exists.\n\n"
285 "Would you like to overwrite it?"),
286 filename);
287 gtk_window_set_title (GTK_WINDOW (checkdialog), _("Overwrite file?"));
288 if (gtk_dialog_run (GTK_DIALOG (checkdialog)) != GTK_RESPONSE_YES) {
289 s_log_message (_("Save cancelled on user request\n"));
290 g_free (filename);
291 filename = NULL;
293 gtk_widget_destroy (checkdialog);
295 /* try saving current page of toplevel to file filename */
296 if (filename != NULL) {
297 x_window_save_page (w_current,
298 w_current->toplevel->page_current,
299 filename);
302 g_free (filename);
304 gtk_widget_destroy (dialog);
308 /*! \brief Load/Backup selection dialog.
309 * \par Function Description
310 * This function opens a message dialog and wait for the user to choose
311 * if load the backup or the original file.
313 * \todo Make this a registered callback function with user data,
314 * as we'd rather be passed a GSCHEM_TOPLEVEL than a TOPLEVEL.
316 * \param [in] toplevel The TOPLEVEL object.
317 * \param [in] message Message to display to user.
318 * \return TRUE if the user wants to load the backup file, FALSE otherwise.
320 int x_fileselect_load_backup(void *user_data, GString *message)
322 GtkWidget *dialog;
323 GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) user_data;
325 g_string_append(message, "\nIf you load the original file, the backup file will be overwritten in the next autosave timeout and it will be lost.\n\nDo you want to load the backup file?\n");
327 dialog = gtk_message_dialog_new (GTK_WINDOW(w_current->main_window),
328 GTK_DIALOG_MODAL,
329 GTK_MESSAGE_QUESTION,
330 GTK_BUTTONS_YES_NO,
331 "%s", message->str);
333 /* Set the alternative button order (ok, cancel, help) for other systems */
334 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
335 GTK_RESPONSE_YES,
336 GTK_RESPONSE_NO,
337 -1);
339 gtk_widget_show (dialog);
340 if (gtk_dialog_run ((GtkDialog*)dialog) == GTK_RESPONSE_YES) {
341 gtk_widget_destroy(dialog);
342 return TRUE;
344 else {
345 gtk_widget_destroy(dialog);
346 return FALSE;