1 /*
2 * gedit-commands-file.c
3 * This file is part of gedit
4 *
5 * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
6 * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
7 * Copyright (C) 2002-2005 Paolo Maggi
8 * Copyright (C) 2014 Sébastien Wilmet
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "config.h"
25
26 #include "gedit-commands.h"
27 #include "gedit-commands-private.h"
28
29 #include <glib/gi18n.h>
30 #include <tepl/tepl.h>
31
32 #include "gedit-app.h"
33 #include "gedit-debug.h"
34 #include "gedit-document.h"
35 #include "gedit-document-private.h"
36 #include "gedit-tab.h"
37 #include "gedit-tab-private.h"
38 #include "gedit-window.h"
39 #include "gedit-window-private.h"
40 #include "gedit-notebook.h"
41 #include "gedit-statusbar.h"
42 #include "gedit-utils.h"
43 #include "gedit-file-chooser-dialog.h"
44 #include "gedit-file-chooser-open.h"
45 #include "gedit-close-confirmation-dialog.h"
46
47 /* useful macro */
48 #define GBOOLEAN_TO_POINTER(i) (GINT_TO_POINTER ((i) ? 2 : 1))
49 #define GPOINTER_TO_BOOLEAN(i) ((gboolean) ((GPOINTER_TO_INT(i) == 2) ? TRUE : FALSE))
50
51 #define GEDIT_IS_CLOSING_ALL "gedit-is-closing-all"
52 #define GEDIT_NOTEBOOK_TO_CLOSE "gedit-notebook-to-close"
53 #define GEDIT_IS_QUITTING "gedit-is-quitting"
54 #define GEDIT_IS_QUITTING_ALL "gedit-is-quitting-all"
55
56 void
_gedit_cmd_file_new(GSimpleAction * action,GVariant * parameter,gpointer user_data)57 _gedit_cmd_file_new (GSimpleAction *action,
58 GVariant *parameter,
59 gpointer user_data)
60 {
61 GeditWindow *window = GEDIT_WINDOW (user_data);
62
63 gedit_debug (DEBUG_COMMANDS);
64
65 gedit_window_create_tab (window, TRUE);
66 }
67
68 static GeditTab *
get_tab_from_file(GList * docs,GFile * file)69 get_tab_from_file (GList *docs,
70 GFile *file)
71 {
72 GList *l;
73
74 for (l = docs; l != NULL; l = l->next)
75 {
76 GeditDocument *doc;
77 GtkSourceFile *source_file;
78 GFile *location;
79
80 doc = l->data;
81 source_file = gedit_document_get_file (doc);
82 location = gtk_source_file_get_location (source_file);
83
84 if (location != NULL && g_file_equal (location, file))
85 {
86 return gedit_tab_get_from_document (doc);
87 }
88 }
89
90 return NULL;
91 }
92
93 static gboolean
is_duplicated_file(GSList * files,GFile * file)94 is_duplicated_file (GSList *files,
95 GFile *file)
96 {
97 GSList *l;
98
99 for (l = files; l != NULL; l = l->next)
100 {
101 if (g_file_equal (l->data, file))
102 {
103 return TRUE;
104 }
105 }
106
107 return FALSE;
108 }
109
110 /* File loading */
111 static GSList *
load_file_list(GeditWindow * window,const GSList * files,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create)112 load_file_list (GeditWindow *window,
113 const GSList *files,
114 const GtkSourceEncoding *encoding,
115 gint line_pos,
116 gint column_pos,
117 gboolean create)
118 {
119 GList *win_docs;
120 GSList *files_to_load = NULL;
121 GSList *loaded_files = NULL;
122 GeditTab *tab;
123 gboolean jump_to = TRUE; /* Whether to jump to the new tab */
124 const GSList *l;
125 gint num_loaded_files = 0;
126
127 gedit_debug (DEBUG_COMMANDS);
128
129 win_docs = gedit_window_get_documents (window);
130
131 /* Remove the files corresponding to documents already opened in
132 * "window" and remove duplicates from the "files" list.
133 */
134 for (l = files; l != NULL; l = l->next)
135 {
136 GFile *file = l->data;
137
138 if (is_duplicated_file (files_to_load, file))
139 {
140 continue;
141 }
142
143 tab = get_tab_from_file (win_docs, file);
144
145 if (tab == NULL)
146 {
147 files_to_load = g_slist_prepend (files_to_load, file);
148 }
149 else
150 {
151 if (l == files)
152 {
153 TeplView *view;
154
155 gedit_window_set_active_tab (window, tab);
156 jump_to = FALSE;
157 view = TEPL_VIEW (gedit_tab_get_view (tab));
158
159 if (line_pos > 0)
160 {
161 if (column_pos > 0)
162 {
163 tepl_view_goto_line_offset (view,
164 line_pos - 1,
165 column_pos - 1);
166 }
167 else
168 {
169 tepl_view_goto_line (view, line_pos - 1);
170 }
171 }
172 }
173
174 ++num_loaded_files;
175 loaded_files = g_slist_prepend (loaded_files,
176 gedit_tab_get_document (tab));
177 }
178 }
179
180 g_list_free (win_docs);
181
182 if (files_to_load == NULL)
183 {
184 return g_slist_reverse (loaded_files);
185 }
186
187 files_to_load = g_slist_reverse (files_to_load);
188 l = files_to_load;
189
190 tab = gedit_window_get_active_tab (window);
191 if (tab != NULL)
192 {
193 GeditDocument *doc;
194
195 doc = gedit_tab_get_document (tab);
196
197 if (tepl_buffer_is_untouched (TEPL_BUFFER (doc)) &&
198 gedit_tab_get_state (tab) == GEDIT_TAB_STATE_NORMAL)
199 {
200 _gedit_tab_load (tab,
201 l->data,
202 encoding,
203 line_pos,
204 column_pos,
205 create);
206
207 /* make sure the view has focus */
208 gtk_widget_grab_focus (GTK_WIDGET (gedit_tab_get_view (tab)));
209
210 l = g_slist_next (l);
211 jump_to = FALSE;
212
213 ++num_loaded_files;
214 loaded_files = g_slist_prepend (loaded_files,
215 gedit_tab_get_document (tab));
216 }
217 }
218
219 while (l != NULL)
220 {
221 g_return_val_if_fail (l->data != NULL, NULL);
222
223 tab = gedit_window_create_tab_from_location (window,
224 l->data,
225 encoding,
226 line_pos,
227 column_pos,
228 create,
229 jump_to);
230
231 if (tab != NULL)
232 {
233 jump_to = FALSE;
234
235 ++num_loaded_files;
236 loaded_files = g_slist_prepend (loaded_files,
237 gedit_tab_get_document (tab));
238 }
239
240 l = g_slist_next (l);
241 }
242
243 loaded_files = g_slist_reverse (loaded_files);
244
245 if (num_loaded_files == 1)
246 {
247 GeditDocument *doc;
248 gchar *uri_for_display;
249
250 g_return_val_if_fail (tab != NULL, loaded_files);
251
252 doc = gedit_tab_get_document (tab);
253 uri_for_display = _gedit_document_get_uri_for_display (doc);
254
255 gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
256 window->priv->generic_message_cid,
257 _("Loading file “%s”\342\200\246"),
258 uri_for_display);
259
260 g_free (uri_for_display);
261 }
262 else
263 {
264 gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
265 window->priv->generic_message_cid,
266 ngettext ("Loading %d file\342\200\246",
267 "Loading %d files\342\200\246",
268 num_loaded_files),
269 num_loaded_files);
270 }
271
272 g_slist_free (files_to_load);
273
274 return loaded_files;
275 }
276
277 /**
278 * gedit_commands_load_location:
279 * @window: a #GeditWindow
280 * @location: a #GFile to load
281 * @encoding: (allow-none): the #GtkSourceEncoding of @location
282 * @line_pos: the line position to place the cursor
283 * @column_pos: the line column to place the cursor
284 *
285 * Loads @location. Ignores non-existing locations.
286 */
287 void
gedit_commands_load_location(GeditWindow * window,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)288 gedit_commands_load_location (GeditWindow *window,
289 GFile *location,
290 const GtkSourceEncoding *encoding,
291 gint line_pos,
292 gint column_pos)
293 {
294 GSList *locations = NULL;
295 gchar *uri;
296 GSList *ret;
297
298 g_return_if_fail (GEDIT_IS_WINDOW (window));
299 g_return_if_fail (G_IS_FILE (location));
300 g_return_if_fail (gedit_utils_is_valid_location (location));
301
302 uri = g_file_get_uri (location);
303 gedit_debug_message (DEBUG_COMMANDS, "Loading URI '%s'", uri);
304 g_free (uri);
305
306 locations = g_slist_prepend (locations, location);
307
308 ret = load_file_list (window, locations, encoding, line_pos, column_pos, FALSE);
309 g_slist_free (ret);
310
311 g_slist_free (locations);
312 }
313
314 /**
315 * gedit_commands_load_locations:
316 * @window: a #GeditWindow
317 * @locations: (element-type Gio.File): the locations to load
318 * @encoding: (allow-none): the #GtkSourceEncoding
319 * @line_pos: the line position to place the cursor
320 * @column_pos: the line column to place the cursor
321 *
322 * Loads @locations. Ignore non-existing locations.
323 *
324 * Returns: (element-type Gedit.Document) (transfer container): the locations
325 * that were loaded.
326 */
327 GSList *
gedit_commands_load_locations(GeditWindow * window,const GSList * locations,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)328 gedit_commands_load_locations (GeditWindow *window,
329 const GSList *locations,
330 const GtkSourceEncoding *encoding,
331 gint line_pos,
332 gint column_pos)
333 {
334 g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
335 g_return_val_if_fail (locations != NULL && locations->data != NULL, NULL);
336
337 gedit_debug (DEBUG_COMMANDS);
338
339 return load_file_list (window, locations, encoding, line_pos, column_pos, FALSE);
340 }
341
342 /*
343 * From the command line we can specify a line position for the
344 * first doc. Beside specifying a non-existing file creates a
345 * titled document.
346 */
347 GSList *
_gedit_cmd_load_files_from_prompt(GeditWindow * window,GSList * files,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)348 _gedit_cmd_load_files_from_prompt (GeditWindow *window,
349 GSList *files,
350 const GtkSourceEncoding *encoding,
351 gint line_pos,
352 gint column_pos)
353 {
354 gedit_debug (DEBUG_COMMANDS);
355
356 return load_file_list (window, files, encoding, line_pos, column_pos, TRUE);
357 }
358
359 static void
file_chooser_open_done_cb(GeditFileChooserOpen * file_chooser,gboolean accept,GeditWindow * window)360 file_chooser_open_done_cb (GeditFileChooserOpen *file_chooser,
361 gboolean accept,
362 GeditWindow *window)
363 {
364 GSList *files;
365 const GtkSourceEncoding *encoding;
366 gchar *folder_uri;
367 GSList *loaded_documents;
368
369 gedit_debug (DEBUG_COMMANDS);
370
371 if (!accept)
372 {
373 g_object_unref (file_chooser);
374 return;
375 }
376
377 files = _gedit_file_chooser_open_get_files (file_chooser);
378 encoding = _gedit_file_chooser_get_encoding (GEDIT_FILE_CHOOSER (file_chooser));
379 folder_uri = _gedit_file_chooser_get_current_folder_uri (GEDIT_FILE_CHOOSER (file_chooser));
380 g_object_unref (file_chooser);
381
382 if (window == NULL)
383 {
384 window = gedit_app_create_window (GEDIT_APP (g_application_get_default ()), NULL);
385
386 gtk_widget_show (GTK_WIDGET (window));
387 gtk_window_present (GTK_WINDOW (window));
388 }
389
390 /* Remember the folder we navigated to. */
391 _gedit_window_set_file_chooser_folder_uri (window, GTK_FILE_CHOOSER_ACTION_OPEN, folder_uri);
392 g_free (folder_uri);
393
394 loaded_documents = gedit_commands_load_locations (window, files, encoding, 0, 0);
395
396 g_slist_free (loaded_documents);
397 g_slist_free_full (files, g_object_unref);
398 }
399
400 const gchar*
_get_currrent_doc_location(GeditWindow * window)401 _get_currrent_doc_location (GeditWindow *window)
402 {
403 GFile *default_path = NULL;
404 const gchar *default_uri = NULL;
405
406 if (window != NULL)
407 {
408 GeditDocument *doc;
409
410 doc = gedit_window_get_active_document (window);
411
412 if (doc != NULL)
413 {
414 GtkSourceFile *file = gedit_document_get_file (doc);
415 GFile *location = gtk_source_file_get_location (file);
416
417 if (location != NULL)
418 {
419 default_path = g_file_get_parent (location);
420 }
421 }
422
423 if (default_path != NULL)
424 {
425 default_uri = g_file_get_uri(default_path);
426 }
427 }
428
429 return default_uri;
430 }
431
432 void
_gedit_cmd_file_open(GSimpleAction * action,GVariant * parameter,gpointer user_data)433 _gedit_cmd_file_open (GSimpleAction *action,
434 GVariant *parameter,
435 gpointer user_data)
436 {
437 GeditWindow *window = NULL;
438 GeditFileChooserOpen *file_chooser;
439
440 gedit_debug (DEBUG_COMMANDS);
441
442 if (user_data != NULL)
443 {
444 window = GEDIT_WINDOW (user_data);
445 }
446
447 const gchar* default_uri = _get_currrent_doc_location (window);
448
449 file_chooser = _gedit_file_chooser_open_new ();
450
451 if (window != NULL)
452 {
453 const gchar *folder_uri;
454
455 _gedit_file_chooser_set_transient_for (GEDIT_FILE_CHOOSER (file_chooser),
456 GTK_WINDOW (window));
457
458 folder_uri = _gedit_window_get_file_chooser_folder_uri (window, GTK_FILE_CHOOSER_ACTION_OPEN);
459
460 if (default_uri != NULL)
461 {
462 folder_uri = default_uri;
463 }
464
465 if (folder_uri != NULL)
466 {
467 _gedit_file_chooser_set_current_folder_uri (GEDIT_FILE_CHOOSER (file_chooser),
468 folder_uri);
469 }
470 }
471
472 g_signal_connect (file_chooser,
473 "done",
474 G_CALLBACK (file_chooser_open_done_cb),
475 window);
476
477 _gedit_file_chooser_show (GEDIT_FILE_CHOOSER (file_chooser));
478 }
479
480 void
_gedit_cmd_file_reopen_closed_tab(GSimpleAction * action,GVariant * parameter,gpointer user_data)481 _gedit_cmd_file_reopen_closed_tab (GSimpleAction *action,
482 GVariant *parameter,
483 gpointer user_data)
484 {
485 GeditWindow *window = GEDIT_WINDOW (user_data);
486 GFile *file;
487
488 file = _gedit_window_pop_last_closed_doc (window);
489 if (file != NULL)
490 {
491 gedit_commands_load_location (window, file, NULL, 0, 0);
492 }
493 }
494
495 /* File saving */
496
497 /* FIXME: modify this dialog to be similar to the one provided by gtk+ for
498 * already existing files - Paolo (Oct. 11, 2005) */
499 static gboolean
replace_read_only_file(GtkWindow * parent,GFile * file)500 replace_read_only_file (GtkWindow *parent,
501 GFile *file)
502 {
503 GtkWidget *dialog;
504 gint ret;
505 gchar *parse_name;
506 gchar *name_for_display;
507
508 gedit_debug (DEBUG_COMMANDS);
509
510 parse_name = g_file_get_parse_name (file);
511
512 /* Truncate the name so it doesn't get insanely wide. Note that even
513 * though the dialog uses wrapped text, if the name doesn't contain
514 * white space then the text-wrapping code is too stupid to wrap it.
515 */
516 name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
517 g_free (parse_name);
518
519 dialog = gtk_message_dialog_new (parent,
520 GTK_DIALOG_DESTROY_WITH_PARENT,
521 GTK_MESSAGE_QUESTION,
522 GTK_BUTTONS_NONE,
523 _("The file “%s” is read-only."),
524 name_for_display);
525 g_free (name_for_display);
526
527 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
528 _("Do you want to try to replace it "
529 "with the one you are saving?"));
530
531 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
532 _("_Cancel"), GTK_RESPONSE_CANCEL,
533 _("_Replace"), GTK_RESPONSE_YES,
534 NULL);
535
536 gtk_dialog_set_default_response (GTK_DIALOG (dialog),
537 GTK_RESPONSE_CANCEL);
538
539 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
540
541 ret = gtk_dialog_run (GTK_DIALOG (dialog));
542
543 gtk_widget_destroy (dialog);
544
545 return ret == GTK_RESPONSE_YES;
546 }
547
548 static gboolean
change_compression(GtkWindow * parent,GFile * file,gboolean compressed)549 change_compression (GtkWindow *parent,
550 GFile *file,
551 gboolean compressed)
552 {
553 GtkWidget *dialog;
554 gint ret;
555 gchar *parse_name;
556 gchar *name_for_display;
557 const gchar *primary_message;
558 const gchar *button_label;
559
560 gedit_debug (DEBUG_COMMANDS);
561
562 parse_name = g_file_get_parse_name (file);
563
564 /* Truncate the name so it doesn't get insanely wide. Note that even
565 * though the dialog uses wrapped text, if the name doesn't contain
566 * white space then the text-wrapping code is too stupid to wrap it.
567 */
568 name_for_display = tepl_utils_str_middle_truncate (parse_name, 50);
569 g_free (parse_name);
570
571 if (compressed)
572 {
573 primary_message = _("Save the file using compression?");
574 }
575 else
576 {
577 primary_message = _("Save the file as plain text?");
578 }
579
580 dialog = gtk_message_dialog_new (parent,
581 GTK_DIALOG_DESTROY_WITH_PARENT,
582 GTK_MESSAGE_QUESTION,
583 GTK_BUTTONS_NONE,
584 "%s",
585 primary_message);
586
587 if (compressed)
588 {
589 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
590 _("The file “%s” was previously saved as plain "
591 "text and will now be saved using compression."),
592 name_for_display);
593
594 button_label = _("_Save Using Compression");
595 }
596 else
597 {
598 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
599 _("The file “%s” was previously saved "
600 "using compression and will now be saved as plain text."),
601 name_for_display);
602 button_label = _("_Save As Plain Text");
603 }
604
605 g_free (name_for_display);
606
607 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
608 _("_Cancel"), GTK_RESPONSE_CANCEL,
609 button_label, GTK_RESPONSE_YES,
610 NULL);
611
612 gtk_dialog_set_default_response (GTK_DIALOG (dialog),
613 GTK_RESPONSE_CANCEL);
614
615 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
616
617 ret = gtk_dialog_run (GTK_DIALOG (dialog));
618
619 gtk_widget_destroy (dialog);
620
621 return ret == GTK_RESPONSE_YES;
622 }
623
624 static GtkSourceCompressionType
get_compression_type_from_file(GFile * file)625 get_compression_type_from_file (GFile *file)
626 {
627 gchar *name;
628 gchar *content_type;
629 GtkSourceCompressionType type;
630
631 name = g_file_get_basename (file);
632 content_type = g_content_type_guess (name, NULL, 0, NULL);
633
634 type = gedit_utils_get_compression_type_from_content_type (content_type);
635
636 g_free (name);
637 g_free (content_type);
638
639 return type;
640 }
641
642 static void
tab_save_as_ready_cb(GeditTab * tab,GAsyncResult * result,GTask * task)643 tab_save_as_ready_cb (GeditTab *tab,
644 GAsyncResult *result,
645 GTask *task)
646 {
647 gboolean success = _gedit_tab_save_finish (tab, result);
648 g_task_return_boolean (task, success);
649 g_object_unref (task);
650 }
651
652 static void
save_dialog_response_cb(GeditFileChooserDialog * dialog,gint response_id,GTask * task)653 save_dialog_response_cb (GeditFileChooserDialog *dialog,
654 gint response_id,
655 GTask *task)
656 {
657 GeditTab *tab;
658 GeditWindow *window;
659 GeditDocument *doc;
660 GtkSourceFile *file;
661 GFile *location;
662 gchar *parse_name;
663 GtkSourceNewlineType newline_type;
664 GtkSourceCompressionType compression_type;
665 GtkSourceCompressionType current_compression_type;
666 const GtkSourceEncoding *encoding;
667
668 gedit_debug (DEBUG_COMMANDS);
669
670 tab = g_task_get_source_object (task);
671 window = g_task_get_task_data (task);
672
673 if (response_id != GTK_RESPONSE_ACCEPT)
674 {
675 gedit_file_chooser_dialog_destroy (dialog);
676 g_task_return_boolean (task, FALSE);
677 g_object_unref (task);
678 return;
679 }
680
681 doc = gedit_tab_get_document (tab);
682 file = gedit_document_get_file (doc);
683
684 location = gedit_file_chooser_dialog_get_file (dialog);
685 g_return_if_fail (location != NULL);
686
687 compression_type = get_compression_type_from_file (location);
688 current_compression_type = gtk_source_file_get_compression_type (file);
689
690 if ((compression_type == GTK_SOURCE_COMPRESSION_TYPE_NONE) !=
691 (current_compression_type == GTK_SOURCE_COMPRESSION_TYPE_NONE))
692 {
693 GtkWindow *dialog_window = gedit_file_chooser_dialog_get_window (dialog);
694
695 if (!change_compression (dialog_window,
696 location,
697 compression_type != GTK_SOURCE_COMPRESSION_TYPE_NONE))
698 {
699 gedit_file_chooser_dialog_destroy (dialog);
700 g_object_unref (location);
701
702 g_task_return_boolean (task, FALSE);
703 g_object_unref (task);
704 return;
705 }
706 }
707
708 encoding = gedit_file_chooser_dialog_get_encoding (dialog);
709 newline_type = gedit_file_chooser_dialog_get_newline_type (dialog);
710
711 gedit_file_chooser_dialog_destroy (dialog);
712
713 parse_name = g_file_get_parse_name (location);
714
715 gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
716 window->priv->generic_message_cid,
717 _("Saving file “%s”\342\200\246"),
718 parse_name);
719
720 g_free (parse_name);
721
722 /* Let's remember the dir we navigated to, even if the saving fails... */
723 {
724 GFile *folder;
725
726 folder = g_file_get_parent (location);
727 if (folder != NULL)
728 {
729 gchar *folder_uri;
730
731 folder_uri = g_file_get_uri (folder);
732 _gedit_window_set_file_chooser_folder_uri (window,
733 GTK_FILE_CHOOSER_ACTION_SAVE,
734 folder_uri);
735
736 g_object_unref (folder);
737 g_free (folder_uri);
738 }
739 }
740
741 _gedit_tab_save_as_async (tab,
742 location,
743 encoding,
744 newline_type,
745 compression_type,
746 g_task_get_cancellable (task),
747 (GAsyncReadyCallback) tab_save_as_ready_cb,
748 task);
749
750 g_object_unref (location);
751 }
752
753 static GtkFileChooserConfirmation
confirm_overwrite_callback(GeditFileChooserDialog * dialog,gpointer data)754 confirm_overwrite_callback (GeditFileChooserDialog *dialog,
755 gpointer data)
756 {
757 GtkFileChooserConfirmation res;
758 GFile *file;
759 GFileInfo *info;
760
761 gedit_debug (DEBUG_COMMANDS);
762
763 /* fall back to the default confirmation dialog */
764 res = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
765
766 file = gedit_file_chooser_dialog_get_file (dialog);
767
768 info = g_file_query_info (file,
769 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
770 G_FILE_QUERY_INFO_NONE,
771 NULL,
772 NULL);
773
774 if (info != NULL)
775 {
776 if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) &&
777 !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
778 {
779 GtkWindow *win;
780
781 win = gedit_file_chooser_dialog_get_window (dialog);
782
783 if (replace_read_only_file (win, file))
784 {
785 res = GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
786 }
787 else
788 {
789 res = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
790 }
791 }
792
793 g_object_unref (info);
794 }
795
796 g_object_unref (file);
797
798 return res;
799 }
800
801 /* Call save_as_tab_finish() in @callback. */
802 static void
save_as_tab_async(GeditTab * tab,GeditWindow * window,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)803 save_as_tab_async (GeditTab *tab,
804 GeditWindow *window,
805 GCancellable *cancellable,
806 GAsyncReadyCallback callback,
807 gpointer user_data)
808 {
809 GTask *task;
810 GeditFileChooserDialog *save_dialog;
811 GtkWindowGroup *window_group;
812 GtkWindow *dialog_window;
813 GeditDocument *doc;
814 GtkSourceFile *file;
815 GFile *location;
816 const GtkSourceEncoding *encoding;
817 GtkSourceNewlineType newline_type;
818
819 g_return_if_fail (GEDIT_IS_TAB (tab));
820 g_return_if_fail (GEDIT_IS_WINDOW (window));
821
822 gedit_debug (DEBUG_COMMANDS);
823
824 task = g_task_new (tab, cancellable, callback, user_data);
825 g_task_set_task_data (task, g_object_ref (window), g_object_unref);
826
827 /* Translators: "Save As" is the title of the file chooser window. */
828 save_dialog = gedit_file_chooser_dialog_create (C_("window title", "Save As"),
829 GTK_WINDOW (window),
830 _("_Save"),
831 _("_Cancel"));
832
833 gedit_file_chooser_dialog_set_do_overwrite_confirmation (save_dialog, TRUE);
834
835 g_signal_connect (save_dialog,
836 "confirm-overwrite",
837 G_CALLBACK (confirm_overwrite_callback),
838 NULL);
839
840 window_group = gedit_window_get_group (window);
841
842 dialog_window = gedit_file_chooser_dialog_get_window (save_dialog);
843
844 if (dialog_window != NULL)
845 {
846 gtk_window_group_add_window (window_group, dialog_window);
847 }
848
849 /* Save As dialog is modal to its main window */
850 gedit_file_chooser_dialog_set_modal (save_dialog, TRUE);
851
852 /* Set the suggested file name */
853 doc = gedit_tab_get_document (tab);
854 file = gedit_document_get_file (doc);
855 location = gtk_source_file_get_location (file);
856
857 if (location != NULL)
858 {
859 gedit_file_chooser_dialog_set_file (save_dialog, location);
860 }
861 else
862 {
863 const gchar *default_folder_uri;
864 GFile *default_folder;
865 gchar *docname;
866
867 default_folder_uri = _gedit_window_get_file_chooser_folder_uri (window,
868 GTK_FILE_CHOOSER_ACTION_SAVE);
869 if (default_folder_uri != NULL)
870 {
871 default_folder = g_file_new_for_uri (default_folder_uri);
872 }
873 else
874 {
875 /* It's logical to take the home dir by default, and it fixes
876 * a problem on MS Windows (hang in C:\windows\system32).
877 *
878 * FIXME: it would be better to use GtkFileChooserNative
879 * to permanently fix the hang problem on MS Windows.
880 */
881 default_folder = g_file_new_for_path (g_get_home_dir ());
882 }
883
884 gedit_file_chooser_dialog_set_current_folder (save_dialog, default_folder);
885 g_object_unref (default_folder);
886
887 docname = gedit_document_get_short_name_for_display (doc);
888 gedit_file_chooser_dialog_set_current_name (save_dialog, docname);
889 g_free (docname);
890 }
891
892 /* Set suggested encoding and newline type. */
893 encoding = gtk_source_file_get_encoding (file);
894
895 if (encoding == NULL)
896 {
897 encoding = gtk_source_encoding_get_utf8 ();
898 }
899
900 newline_type = gtk_source_file_get_newline_type (file);
901
902 gedit_file_chooser_dialog_set_encoding (GEDIT_FILE_CHOOSER_DIALOG (save_dialog),
903 encoding);
904
905 gedit_file_chooser_dialog_set_newline_type (GEDIT_FILE_CHOOSER_DIALOG (save_dialog),
906 newline_type);
907
908 g_signal_connect (save_dialog,
909 "response",
910 G_CALLBACK (save_dialog_response_cb),
911 task);
912
913 gedit_file_chooser_dialog_show (save_dialog);
914 }
915
916 static gboolean
save_as_tab_finish(GeditTab * tab,GAsyncResult * result)917 save_as_tab_finish (GeditTab *tab,
918 GAsyncResult *result)
919 {
920 g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
921
922 return g_task_propagate_boolean (G_TASK (result), NULL);
923 }
924
925 static void
save_as_tab_ready_cb(GeditTab * tab,GAsyncResult * result,GTask * task)926 save_as_tab_ready_cb (GeditTab *tab,
927 GAsyncResult *result,
928 GTask *task)
929 {
930 gboolean success = save_as_tab_finish (tab, result);
931
932 g_task_return_boolean (task, success);
933 g_object_unref (task);
934 }
935
936 static void
tab_save_ready_cb(GeditTab * tab,GAsyncResult * result,GTask * task)937 tab_save_ready_cb (GeditTab *tab,
938 GAsyncResult *result,
939 GTask *task)
940 {
941 gboolean success = _gedit_tab_save_finish (tab, result);
942
943 g_task_return_boolean (task, success);
944 g_object_unref (task);
945 }
946
947 /**
948 * gedit_commands_save_document_async:
949 * @document: the #GeditDocument to save.
950 * @window: a #GeditWindow.
951 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
952 * @callback: (scope async): a #GAsyncReadyCallback to call when the operation
953 * is finished.
954 * @user_data: (closure): the data to pass to the @callback function.
955 *
956 * Asynchronously save the @document. @document must belong to @window. The
957 * source object of the async task is @document (which will be the first
958 * parameter of the #GAsyncReadyCallback).
959 *
960 * When the operation is finished, @callback will be called. You can then call
961 * gedit_commands_save_document_finish() to get the result of the operation.
962 *
963 * Since: 3.14
964 */
965 void
gedit_commands_save_document_async(GeditDocument * document,GeditWindow * window,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)966 gedit_commands_save_document_async (GeditDocument *document,
967 GeditWindow *window,
968 GCancellable *cancellable,
969 GAsyncReadyCallback callback,
970 gpointer user_data)
971 {
972 GTask *task;
973 GeditTab *tab;
974 GtkSourceFile *file;
975 gchar *uri_for_display;
976
977 gedit_debug (DEBUG_COMMANDS);
978
979 g_return_if_fail (GEDIT_IS_DOCUMENT (document));
980 g_return_if_fail (GEDIT_IS_WINDOW (window));
981 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
982
983 task = g_task_new (document, cancellable, callback, user_data);
984
985 tab = gedit_tab_get_from_document (document);
986 file = gedit_document_get_file (document);
987
988 if (gedit_document_is_untitled (document) ||
989 gtk_source_file_is_readonly (file))
990 {
991 gedit_debug_message (DEBUG_COMMANDS, "Untitled or Readonly");
992
993 save_as_tab_async (tab,
994 window,
995 cancellable,
996 (GAsyncReadyCallback) save_as_tab_ready_cb,
997 task);
998 return;
999 }
1000
1001 uri_for_display = _gedit_document_get_uri_for_display (document);
1002 gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
1003 window->priv->generic_message_cid,
1004 _("Saving file “%s”\342\200\246"),
1005 uri_for_display);
1006
1007 g_free (uri_for_display);
1008
1009 _gedit_tab_save_async (tab,
1010 cancellable,
1011 (GAsyncReadyCallback) tab_save_ready_cb,
1012 task);
1013 }
1014
1015 /**
1016 * gedit_commands_save_document_finish:
1017 * @document: a #GeditDocument.
1018 * @result: a #GAsyncResult.
1019 *
1020 * Finishes an asynchronous document saving operation started with
1021 * gedit_commands_save_document_async().
1022 *
1023 * Note that there is no error parameter because the errors are already handled
1024 * by gedit.
1025 *
1026 * Returns: %TRUE if the document has been correctly saved, %FALSE otherwise.
1027 * Since: 3.14
1028 */
1029 gboolean
gedit_commands_save_document_finish(GeditDocument * document,GAsyncResult * result)1030 gedit_commands_save_document_finish (GeditDocument *document,
1031 GAsyncResult *result)
1032 {
1033 g_return_val_if_fail (g_task_is_valid (result, document), FALSE);
1034
1035 return g_task_propagate_boolean (G_TASK (result), NULL);
1036 }
1037
1038 static void
save_tab_ready_cb(GeditDocument * doc,GAsyncResult * result,gpointer user_data)1039 save_tab_ready_cb (GeditDocument *doc,
1040 GAsyncResult *result,
1041 gpointer user_data)
1042 {
1043 gedit_commands_save_document_finish (doc, result);
1044 }
1045
1046 /* Save tab asynchronously, but without results. */
1047 static void
save_tab(GeditTab * tab,GeditWindow * window)1048 save_tab (GeditTab *tab,
1049 GeditWindow *window)
1050 {
1051 GeditDocument *doc = gedit_tab_get_document (tab);
1052
1053 gedit_commands_save_document_async (doc,
1054 window,
1055 NULL,
1056 (GAsyncReadyCallback) save_tab_ready_cb,
1057 NULL);
1058 }
1059
1060 void
_gedit_cmd_file_save(GSimpleAction * action,GVariant * parameter,gpointer user_data)1061 _gedit_cmd_file_save (GSimpleAction *action,
1062 GVariant *parameter,
1063 gpointer user_data)
1064 {
1065 GeditWindow *window = GEDIT_WINDOW (user_data);
1066 GeditTab *tab;
1067
1068 gedit_debug (DEBUG_COMMANDS);
1069
1070 tab = gedit_window_get_active_tab (window);
1071 if (tab != NULL)
1072 {
1073 save_tab (tab, window);
1074 }
1075 }
1076
1077 static void
_gedit_cmd_file_save_as_cb(GeditTab * tab,GAsyncResult * result,gpointer user_data)1078 _gedit_cmd_file_save_as_cb (GeditTab *tab,
1079 GAsyncResult *result,
1080 gpointer user_data)
1081 {
1082 save_as_tab_finish (tab, result);
1083 }
1084
1085 void
_gedit_cmd_file_save_as(GSimpleAction * action,GVariant * parameter,gpointer user_data)1086 _gedit_cmd_file_save_as (GSimpleAction *action,
1087 GVariant *parameter,
1088 gpointer user_data)
1089 {
1090 GeditWindow *window = GEDIT_WINDOW (user_data);
1091 GeditTab *tab;
1092
1093 gedit_debug (DEBUG_COMMANDS);
1094
1095 tab = gedit_window_get_active_tab (window);
1096 if (tab != NULL)
1097 {
1098 save_as_tab_async (tab,
1099 window,
1100 NULL,
1101 (GAsyncReadyCallback) _gedit_cmd_file_save_as_cb,
1102 NULL);
1103 }
1104 }
1105
1106 static void
quit_if_needed(GeditWindow * window)1107 quit_if_needed (GeditWindow *window)
1108 {
1109 gboolean is_quitting;
1110 gboolean is_quitting_all;
1111
1112 is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window),
1113 GEDIT_IS_QUITTING));
1114
1115 is_quitting_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window),
1116 GEDIT_IS_QUITTING_ALL));
1117
1118 if (is_quitting)
1119 {
1120 gtk_widget_destroy (GTK_WIDGET (window));
1121 }
1122
1123 if (is_quitting_all)
1124 {
1125 GtkApplication *app;
1126
1127 app = GTK_APPLICATION (g_application_get_default ());
1128
1129 if (gtk_application_get_windows (app) == NULL)
1130 {
1131 g_application_quit (G_APPLICATION (app));
1132 }
1133 }
1134 }
1135
1136 static gboolean
really_close_tab(GeditTab * tab)1137 really_close_tab (GeditTab *tab)
1138 {
1139 GtkWidget *toplevel;
1140 GeditWindow *window;
1141
1142 gedit_debug (DEBUG_COMMANDS);
1143
1144 g_return_val_if_fail (gedit_tab_get_state (tab) == GEDIT_TAB_STATE_CLOSING,
1145 FALSE);
1146
1147 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
1148 g_return_val_if_fail (GEDIT_IS_WINDOW (toplevel), FALSE);
1149
1150 window = GEDIT_WINDOW (toplevel);
1151
1152 gedit_window_close_tab (window, tab);
1153
1154 if (gedit_window_get_active_tab (window) == NULL)
1155 {
1156 quit_if_needed (window);
1157 }
1158
1159 return FALSE;
1160 }
1161
1162 static void
close_tab(GeditTab * tab)1163 close_tab (GeditTab *tab)
1164 {
1165 GeditDocument *doc;
1166
1167 doc = gedit_tab_get_document (tab);
1168 g_return_if_fail (doc != NULL);
1169
1170 /* If the user has modified again the document, do not close the tab. */
1171 if (_gedit_document_needs_saving (doc))
1172 {
1173 return;
1174 }
1175
1176 /* Close the document only if it has been succesfully saved.
1177 * Tab state is set to CLOSING (it is a state without exiting
1178 * transitions) and the tab is closed in an idle handler.
1179 */
1180 _gedit_tab_mark_for_closing (tab);
1181
1182 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1183 (GSourceFunc) really_close_tab,
1184 tab,
1185 NULL);
1186 }
1187
1188 typedef struct _SaveAsData SaveAsData;
1189
1190 struct _SaveAsData
1191 {
1192 /* Reffed */
1193 GeditWindow *window;
1194
1195 /* List of reffed GeditTab's */
1196 GSList *tabs_to_save_as;
1197
1198 guint close_tabs : 1;
1199 };
1200
1201 static void save_as_documents_list (SaveAsData *data);
1202
1203 static void
save_as_documents_list_cb(GeditTab * tab,GAsyncResult * result,SaveAsData * data)1204 save_as_documents_list_cb (GeditTab *tab,
1205 GAsyncResult *result,
1206 SaveAsData *data)
1207 {
1208 gboolean saved = save_as_tab_finish (tab, result);
1209
1210 if (saved && data->close_tabs)
1211 {
1212 close_tab (tab);
1213 }
1214
1215 g_return_if_fail (tab == GEDIT_TAB (data->tabs_to_save_as->data));
1216 g_object_unref (data->tabs_to_save_as->data);
1217 data->tabs_to_save_as = g_slist_delete_link (data->tabs_to_save_as,
1218 data->tabs_to_save_as);
1219
1220 if (data->tabs_to_save_as != NULL)
1221 {
1222 save_as_documents_list (data);
1223 }
1224 else
1225 {
1226 g_object_unref (data->window);
1227 g_slice_free (SaveAsData, data);
1228 }
1229 }
1230
1231 static void
save_as_documents_list(SaveAsData * data)1232 save_as_documents_list (SaveAsData *data)
1233 {
1234 GeditTab *next_tab = GEDIT_TAB (data->tabs_to_save_as->data);
1235
1236 gedit_window_set_active_tab (data->window, next_tab);
1237
1238 save_as_tab_async (next_tab,
1239 data->window,
1240 NULL,
1241 (GAsyncReadyCallback) save_as_documents_list_cb,
1242 data);
1243 }
1244
1245 /*
1246 * The docs in the list must belong to the same GeditWindow.
1247 */
1248 static void
save_documents_list(GeditWindow * window,GList * docs)1249 save_documents_list (GeditWindow *window,
1250 GList *docs)
1251 {
1252 SaveAsData *data = NULL;
1253 GList *l;
1254
1255 gedit_debug (DEBUG_COMMANDS);
1256
1257 g_return_if_fail ((gedit_window_get_state (window) & GEDIT_WINDOW_STATE_PRINTING) == 0);
1258
1259 for (l = docs; l != NULL; l = l->next)
1260 {
1261 GeditDocument *doc;
1262 GeditTab *tab;
1263 GeditTabState state;
1264
1265 g_return_if_fail (GEDIT_IS_DOCUMENT (l->data));
1266 doc = l->data;
1267
1268 tab = gedit_tab_get_from_document (doc);
1269 state = gedit_tab_get_state (tab);
1270
1271 g_return_if_fail (state != GEDIT_TAB_STATE_PRINTING);
1272 g_return_if_fail (state != GEDIT_TAB_STATE_CLOSING);
1273
1274 if (state == GEDIT_TAB_STATE_NORMAL ||
1275 state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
1276 {
1277 if (_gedit_document_needs_saving (doc))
1278 {
1279 GtkSourceFile *file = gedit_document_get_file (doc);
1280
1281 /* FIXME: manage the case of local readonly files owned by the
1282 user is running gedit - Paolo (Dec. 8, 2005) */
1283 if (gedit_document_is_untitled (doc) ||
1284 gtk_source_file_is_readonly (file))
1285 {
1286 if (data == NULL)
1287 {
1288 data = g_slice_new (SaveAsData);
1289 data->window = g_object_ref (window);
1290 data->tabs_to_save_as = NULL;
1291 data->close_tabs = FALSE;
1292 }
1293
1294 data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as,
1295 g_object_ref (tab));
1296 }
1297 else
1298 {
1299 save_tab (tab, window);
1300 }
1301 }
1302 }
1303 else
1304 {
1305 /* If the state is:
1306 - GEDIT_TAB_STATE_LOADING: we do not save since we are sure the file is unmodified
1307 - GEDIT_TAB_STATE_REVERTING: we do not save since the user wants
1308 to return back to the version of the file she previously saved
1309 - GEDIT_TAB_STATE_SAVING: well, we are already saving (no need to save again)
1310 - GEDIT_TAB_STATE_PRINTING: there is not a
1311 real reason for not saving in this case, we do not save to avoid to run
1312 two operations using the message area at the same time (may be we can remove
1313 this limitation in the future). Note that SaveAll, ClosAll
1314 and Quit are unsensitive if the window state is PRINTING.
1315 - GEDIT_TAB_STATE_GENERIC_ERROR: we do not save since the document contains
1316 errors (I don't think this is a very frequent case, we should probably remove
1317 this state)
1318 - GEDIT_TAB_STATE_LOADING_ERROR: there is nothing to save
1319 - GEDIT_TAB_STATE_REVERTING_ERROR: there is nothing to save and saving the current
1320 document will overwrite the copy of the file the user wants to go back to
1321 - GEDIT_TAB_STATE_SAVING_ERROR: we do not save since we just failed to save, so there is
1322 no reason to automatically retry... we wait for user intervention
1323 - GEDIT_TAB_STATE_CLOSING: this state is invalid in this case
1324 */
1325
1326 gchar *uri_for_display;
1327
1328 uri_for_display = _gedit_document_get_uri_for_display (doc);
1329 gedit_debug_message (DEBUG_COMMANDS,
1330 "File '%s' not saved. State: %d",
1331 uri_for_display,
1332 state);
1333 g_free (uri_for_display);
1334 }
1335 }
1336
1337 if (data != NULL)
1338 {
1339 data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
1340 save_as_documents_list (data);
1341 }
1342 }
1343
1344 /**
1345 * gedit_commands_save_all_documents:
1346 * @window: a #GeditWindow.
1347 *
1348 * Asynchronously save all documents belonging to @window. The result of the
1349 * operation is not available, so it's difficult to know whether all the
1350 * documents are correctly saved.
1351 */
1352 void
gedit_commands_save_all_documents(GeditWindow * window)1353 gedit_commands_save_all_documents (GeditWindow *window)
1354 {
1355 GList *docs;
1356
1357 g_return_if_fail (GEDIT_IS_WINDOW (window));
1358
1359 gedit_debug (DEBUG_COMMANDS);
1360
1361 docs = gedit_window_get_documents (window);
1362
1363 save_documents_list (window, docs);
1364
1365 g_list_free (docs);
1366 }
1367
1368 void
_gedit_cmd_file_save_all(GSimpleAction * action,GVariant * parameter,gpointer user_data)1369 _gedit_cmd_file_save_all (GSimpleAction *action,
1370 GVariant *parameter,
1371 gpointer user_data)
1372 {
1373 gedit_commands_save_all_documents (GEDIT_WINDOW (user_data));
1374 }
1375
1376 /**
1377 * gedit_commands_save_document:
1378 * @window: a #GeditWindow.
1379 * @document: the #GeditDocument to save.
1380 *
1381 * Asynchronously save @document. @document must belong to @window. If you need
1382 * the result of the operation, use gedit_commands_save_document_async().
1383 */
1384 void
gedit_commands_save_document(GeditWindow * window,GeditDocument * document)1385 gedit_commands_save_document (GeditWindow *window,
1386 GeditDocument *document)
1387 {
1388 GeditTab *tab;
1389
1390 g_return_if_fail (GEDIT_IS_WINDOW (window));
1391 g_return_if_fail (GEDIT_IS_DOCUMENT (document));
1392
1393 gedit_debug (DEBUG_COMMANDS);
1394
1395 tab = gedit_tab_get_from_document (document);
1396 save_tab (tab, window);
1397 }
1398
1399 /* File revert */
1400 static void
do_revert(GeditWindow * window,GeditTab * tab)1401 do_revert (GeditWindow *window,
1402 GeditTab *tab)
1403 {
1404 GeditDocument *doc;
1405 gchar *docname;
1406
1407 gedit_debug (DEBUG_COMMANDS);
1408
1409 doc = gedit_tab_get_document (tab);
1410 docname = gedit_document_get_short_name_for_display (doc);
1411
1412 gedit_statusbar_flash_message (GEDIT_STATUSBAR (window->priv->statusbar),
1413 window->priv->generic_message_cid,
1414 _("Reverting the document “%s”\342\200\246"),
1415 docname);
1416
1417 g_free (docname);
1418
1419 _gedit_tab_revert (tab);
1420 }
1421
1422 static void
revert_dialog_response_cb(GtkDialog * dialog,gint response_id,GeditWindow * window)1423 revert_dialog_response_cb (GtkDialog *dialog,
1424 gint response_id,
1425 GeditWindow *window)
1426 {
1427 GeditTab *tab;
1428
1429 gedit_debug (DEBUG_COMMANDS);
1430
1431 /* FIXME: we are relying on the fact that the dialog is
1432 modal so the active tab can't be changed...
1433 not very nice - Paolo (Oct 11, 2005) */
1434 tab = gedit_window_get_active_tab (window);
1435 if (tab == NULL)
1436 {
1437 return;
1438 }
1439
1440 gtk_widget_destroy (GTK_WIDGET (dialog));
1441
1442 if (response_id == GTK_RESPONSE_OK)
1443 {
1444 do_revert (window, tab);
1445 }
1446 }
1447
1448 static GtkWidget *
revert_dialog(GeditWindow * window,GeditDocument * doc)1449 revert_dialog (GeditWindow *window,
1450 GeditDocument *doc)
1451 {
1452 GtkWidget *dialog;
1453 gchar *docname;
1454 gchar *primary_msg;
1455 gchar *secondary_msg;
1456 glong seconds;
1457
1458 gedit_debug (DEBUG_COMMANDS);
1459
1460 docname = gedit_document_get_short_name_for_display (doc);
1461 primary_msg = g_strdup_printf (_("Revert unsaved changes to document “%s”?"),
1462 docname);
1463 g_free (docname);
1464
1465 seconds = MAX (1, _gedit_document_get_seconds_since_last_save_or_load (doc));
1466
1467 if (seconds < 55)
1468 {
1469 secondary_msg = g_strdup_printf (
1470 ngettext ("Changes made to the document in the last %ld second "
1471 "will be permanently lost.",
1472 "Changes made to the document in the last %ld seconds "
1473 "will be permanently lost.",
1474 seconds),
1475 seconds);
1476 }
1477 else if (seconds < 75) /* 55 <= seconds < 75 */
1478 {
1479 secondary_msg = g_strdup (_("Changes made to the document in the last minute "
1480 "will be permanently lost."));
1481 }
1482 else if (seconds < 110) /* 75 <= seconds < 110 */
1483 {
1484 secondary_msg = g_strdup_printf (
1485 ngettext ("Changes made to the document in the last minute and "
1486 "%ld second will be permanently lost.",
1487 "Changes made to the document in the last minute and "
1488 "%ld seconds will be permanently lost.",
1489 seconds - 60 ),
1490 seconds - 60);
1491 }
1492 else if (seconds < 3600)
1493 {
1494 secondary_msg = g_strdup_printf (
1495 ngettext ("Changes made to the document in the last %ld minute "
1496 "will be permanently lost.",
1497 "Changes made to the document in the last %ld minutes "
1498 "will be permanently lost.",
1499 seconds / 60),
1500 seconds / 60);
1501 }
1502 else if (seconds < 7200)
1503 {
1504 gint minutes;
1505 seconds -= 3600;
1506
1507 minutes = seconds / 60;
1508 if (minutes < 5)
1509 {
1510 secondary_msg = g_strdup (_("Changes made to the document in the last hour "
1511 "will be permanently lost."));
1512 }
1513 else
1514 {
1515 secondary_msg = g_strdup_printf (
1516 ngettext ("Changes made to the document in the last hour and "
1517 "%d minute will be permanently lost.",
1518 "Changes made to the document in the last hour and "
1519 "%d minutes will be permanently lost.",
1520 minutes),
1521 minutes);
1522 }
1523 }
1524 else
1525 {
1526 gint hours;
1527
1528 hours = seconds / 3600;
1529
1530 secondary_msg = g_strdup_printf (
1531 ngettext ("Changes made to the document in the last %d hour "
1532 "will be permanently lost.",
1533 "Changes made to the document in the last %d hours "
1534 "will be permanently lost.",
1535 hours),
1536 hours);
1537 }
1538
1539 dialog = gtk_message_dialog_new (GTK_WINDOW (window),
1540 GTK_DIALOG_DESTROY_WITH_PARENT,
1541 GTK_MESSAGE_QUESTION,
1542 GTK_BUTTONS_NONE,
1543 "%s", primary_msg);
1544
1545 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
1546 "%s", secondary_msg);
1547 g_free (primary_msg);
1548 g_free (secondary_msg);
1549
1550 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1551
1552 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
1553 _("_Cancel"), GTK_RESPONSE_CANCEL,
1554 _("_Revert"), GTK_RESPONSE_OK,
1555 NULL);
1556
1557 gtk_dialog_set_default_response (GTK_DIALOG (dialog),
1558 GTK_RESPONSE_CANCEL);
1559
1560 return dialog;
1561 }
1562
1563 void
_gedit_cmd_file_revert(GSimpleAction * action,GVariant * parameter,gpointer user_data)1564 _gedit_cmd_file_revert (GSimpleAction *action,
1565 GVariant *parameter,
1566 gpointer user_data)
1567 {
1568 GeditWindow *window = GEDIT_WINDOW (user_data);
1569 GeditTab *tab;
1570 GeditDocument *doc;
1571 GtkWidget *dialog;
1572 GtkWindowGroup *window_group;
1573
1574 gedit_debug (DEBUG_COMMANDS);
1575
1576 tab = gedit_window_get_active_tab (window);
1577 g_return_if_fail (tab != NULL);
1578
1579 /* If we are already displaying a notification reverting will drop local
1580 * modifications or if the document has not been modified, do not bug
1581 * the user further.
1582 */
1583 if (gedit_tab_get_state (tab) == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
1584 _gedit_tab_get_can_close (tab))
1585 {
1586 do_revert (window, tab);
1587 return;
1588 }
1589
1590 doc = gedit_tab_get_document (tab);
1591 g_return_if_fail (doc != NULL);
1592 g_return_if_fail (!gedit_document_is_untitled (doc));
1593
1594 dialog = revert_dialog (window, doc);
1595
1596 window_group = gedit_window_get_group (window);
1597
1598 gtk_window_group_add_window (window_group, GTK_WINDOW (dialog));
1599
1600 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1601
1602 g_signal_connect (dialog,
1603 "response",
1604 G_CALLBACK (revert_dialog_response_cb),
1605 window);
1606
1607 gtk_widget_show (dialog);
1608 }
1609
1610 static void
tab_state_changed_while_saving(GeditTab * tab,GParamSpec * pspec,GeditWindow * window)1611 tab_state_changed_while_saving (GeditTab *tab,
1612 GParamSpec *pspec,
1613 GeditWindow *window)
1614 {
1615 GeditTabState state;
1616
1617 state = gedit_tab_get_state (tab);
1618
1619 gedit_debug_message (DEBUG_COMMANDS, "State while saving: %d\n", state);
1620
1621 /* When the state becomes NORMAL, it means the saving operation is
1622 * finished.
1623 */
1624 if (state == GEDIT_TAB_STATE_NORMAL)
1625 {
1626 g_signal_handlers_disconnect_by_func (tab,
1627 G_CALLBACK (tab_state_changed_while_saving),
1628 window);
1629
1630 close_tab (tab);
1631 }
1632 }
1633
1634 static void
save_and_close(GeditTab * tab,GeditWindow * window)1635 save_and_close (GeditTab *tab,
1636 GeditWindow *window)
1637 {
1638 gedit_debug (DEBUG_COMMANDS);
1639
1640 /* Trace tab state changes */
1641 g_signal_connect (tab,
1642 "notify::state",
1643 G_CALLBACK (tab_state_changed_while_saving),
1644 window);
1645
1646 save_tab (tab, window);
1647 }
1648
1649 static void
save_and_close_documents(GList * docs,GeditWindow * window,GeditNotebook * notebook)1650 save_and_close_documents (GList *docs,
1651 GeditWindow *window,
1652 GeditNotebook *notebook)
1653 {
1654 GList *tabs;
1655 GList *l;
1656 GSList *sl;
1657 SaveAsData *data = NULL;
1658 GSList *tabs_to_save_and_close = NULL;
1659 GList *tabs_to_close = NULL;
1660
1661 gedit_debug (DEBUG_COMMANDS);
1662
1663 g_return_if_fail ((gedit_window_get_state (window) & GEDIT_WINDOW_STATE_PRINTING) == 0);
1664
1665 if (notebook != NULL)
1666 {
1667 tabs = gtk_container_get_children (GTK_CONTAINER (notebook));
1668 }
1669 else
1670 {
1671 tabs = _gedit_window_get_all_tabs (window);
1672 }
1673
1674 for (l = tabs; l != NULL; l = l->next)
1675 {
1676 GeditTab *tab = GEDIT_TAB (l->data);
1677 GeditTabState state;
1678 GeditDocument *doc;
1679
1680 state = gedit_tab_get_state (tab);
1681 doc = gedit_tab_get_document (tab);
1682
1683 /* If the state is: ([*] invalid states)
1684 - GEDIT_TAB_STATE_NORMAL: close (and if needed save)
1685 - GEDIT_TAB_STATE_LOADING: close, we are sure the file is unmodified
1686 - GEDIT_TAB_STATE_REVERTING: since the user wants
1687 to return back to the version of the file she previously saved, we can close
1688 without saving (CHECK: are we sure this is the right behavior, suppose the case
1689 the original file has been deleted)
1690 - [*] GEDIT_TAB_STATE_SAVING: invalid, ClosAll
1691 and Quit are unsensitive if the window state is SAVING.
1692 - [*] GEDIT_TAB_STATE_PRINTING: there is not a
1693 real reason for not closing in this case, we do not save to avoid to run
1694 two operations using the message area at the same time (may be we can remove
1695 this limitation in the future). Note that ClosAll
1696 and Quit are unsensitive if the window state is PRINTING.
1697 - GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW: close (and if needed save)
1698 - GEDIT_TAB_STATE_LOADING_ERROR: close without saving (if the state is LOADING_ERROR then the
1699 document is not modified)
1700 - GEDIT_TAB_STATE_REVERTING_ERROR: we do not close since the document contains errors
1701 - GEDIT_TAB_STATE_SAVING_ERROR: we do not close since the document contains errors
1702 - GEDIT_TAB_STATE_GENERIC_ERROR: we do not close since the document contains
1703 errors (CHECK: we should problably remove this state)
1704 - [*] GEDIT_TAB_STATE_CLOSING: this state is invalid in this case
1705 */
1706
1707 g_return_if_fail (state != GEDIT_TAB_STATE_PRINTING);
1708 g_return_if_fail (state != GEDIT_TAB_STATE_CLOSING);
1709 g_return_if_fail (state != GEDIT_TAB_STATE_SAVING);
1710
1711 if (state != GEDIT_TAB_STATE_SAVING_ERROR &&
1712 state != GEDIT_TAB_STATE_GENERIC_ERROR &&
1713 state != GEDIT_TAB_STATE_REVERTING_ERROR)
1714 {
1715 if (g_list_index (docs, doc) >= 0 &&
1716 state != GEDIT_TAB_STATE_LOADING &&
1717 state != GEDIT_TAB_STATE_LOADING_ERROR &&
1718 state != GEDIT_TAB_STATE_REVERTING) /* FIXME: is this the right behavior with REVERTING ?*/
1719 {
1720 GtkSourceFile *file = gedit_document_get_file (doc);
1721
1722 /* The document must be saved before closing */
1723 g_return_if_fail (_gedit_document_needs_saving (doc));
1724
1725 /* FIXME: manage the case of local readonly files owned by the
1726 * user is running gedit - Paolo (Dec. 8, 2005) */
1727 if (gedit_document_is_untitled (doc) ||
1728 gtk_source_file_is_readonly (file))
1729 {
1730 if (data == NULL)
1731 {
1732 data = g_slice_new (SaveAsData);
1733 data->window = g_object_ref (window);
1734 data->tabs_to_save_as = NULL;
1735 data->close_tabs = TRUE;
1736 }
1737
1738 data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as,
1739 g_object_ref (tab));
1740 }
1741 else
1742 {
1743 tabs_to_save_and_close = g_slist_prepend (tabs_to_save_and_close, tab);
1744 }
1745 }
1746 else
1747 {
1748 /* The document can be closed without saving */
1749 tabs_to_close = g_list_prepend (tabs_to_close, tab);
1750 }
1751 }
1752 }
1753
1754 g_list_free (tabs);
1755
1756 /* Close all tabs to close (in a sync way) */
1757 gedit_window_close_tabs (window, tabs_to_close);
1758 g_list_free (tabs_to_close);
1759
1760 /* Save and close all the files in tabs_to_save_and_close */
1761 for (sl = tabs_to_save_and_close; sl != NULL; sl = sl->next)
1762 {
1763 save_and_close (GEDIT_TAB (sl->data), window);
1764 }
1765
1766 g_slist_free (tabs_to_save_and_close);
1767
1768 /* Save As and close all the files in data->tabs_to_save_as. */
1769 if (data != NULL)
1770 {
1771 data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
1772 save_as_documents_list (data);
1773 }
1774 }
1775
1776 static void
save_and_close_document(const GList * docs,GeditWindow * window)1777 save_and_close_document (const GList *docs,
1778 GeditWindow *window)
1779 {
1780 GeditTab *tab;
1781
1782 gedit_debug (DEBUG_COMMANDS);
1783
1784 g_return_if_fail (docs->next == NULL);
1785
1786 tab = gedit_tab_get_from_document (GEDIT_DOCUMENT (docs->data));
1787 g_return_if_fail (tab != NULL);
1788
1789 save_and_close (tab, window);
1790 }
1791
1792 static void
close_all_tabs(GeditWindow * window)1793 close_all_tabs (GeditWindow *window)
1794 {
1795 gedit_debug (DEBUG_COMMANDS);
1796
1797 /* There is no document to save -> close all tabs */
1798 gedit_window_close_all_tabs (window);
1799
1800 quit_if_needed (window);
1801 }
1802
1803 static void
close_document(GeditWindow * window,GeditDocument * doc)1804 close_document (GeditWindow *window,
1805 GeditDocument *doc)
1806 {
1807 GeditTab *tab;
1808
1809 gedit_debug (DEBUG_COMMANDS);
1810
1811 tab = gedit_tab_get_from_document (doc);
1812 g_return_if_fail (tab != NULL);
1813
1814 gedit_window_close_tab (window, tab);
1815 }
1816
1817 static void
close_confirmation_dialog_response_handler(GeditCloseConfirmationDialog * dlg,gint response_id,GeditWindow * window)1818 close_confirmation_dialog_response_handler (GeditCloseConfirmationDialog *dlg,
1819 gint response_id,
1820 GeditWindow *window)
1821 {
1822 GList *selected_documents;
1823 gboolean is_closing_all;
1824 GeditNotebook *notebook_to_close;
1825
1826 gedit_debug (DEBUG_COMMANDS);
1827
1828 is_closing_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window),
1829 GEDIT_IS_CLOSING_ALL));
1830
1831 notebook_to_close = g_object_get_data (G_OBJECT (window), GEDIT_NOTEBOOK_TO_CLOSE);
1832
1833 gtk_widget_hide (GTK_WIDGET (dlg));
1834
1835 switch (response_id)
1836 {
1837 /* Save and Close */
1838 case GTK_RESPONSE_YES:
1839 selected_documents = gedit_close_confirmation_dialog_get_selected_documents (dlg);
1840
1841 if (selected_documents == NULL)
1842 {
1843 if (is_closing_all)
1844 {
1845 /* There is no document to save -> close all tabs */
1846 /* We call gtk_widget_destroy before close_all_tabs
1847 * because close_all_tabs could destroy the gedit window */
1848 gtk_widget_destroy (GTK_WIDGET (dlg));
1849
1850 close_all_tabs (window);
1851 return;
1852 }
1853 else if (notebook_to_close)
1854 {
1855 gedit_notebook_remove_all_tabs (notebook_to_close);
1856 }
1857 else
1858 {
1859 g_return_if_reached ();
1860 }
1861 }
1862 else
1863 {
1864 if (is_closing_all || notebook_to_close)
1865 {
1866 GeditNotebook *notebook = is_closing_all ? NULL : notebook_to_close;
1867
1868 save_and_close_documents (selected_documents, window, notebook);
1869 }
1870 else
1871 {
1872 save_and_close_document (selected_documents, window);
1873 }
1874 }
1875
1876 g_list_free (selected_documents);
1877 break;
1878
1879 /* Close without Saving */
1880 case GTK_RESPONSE_NO:
1881 if (is_closing_all)
1882 {
1883 /* We call gtk_widget_destroy before close_all_tabs
1884 * because close_all_tabs could destroy the gedit window */
1885 gtk_widget_destroy (GTK_WIDGET (dlg));
1886
1887 close_all_tabs (window);
1888 return;
1889 }
1890 else if (notebook_to_close)
1891 {
1892 gedit_notebook_remove_all_tabs (notebook_to_close);
1893 }
1894 else
1895 {
1896 const GList *unsaved_documents;
1897
1898 unsaved_documents = gedit_close_confirmation_dialog_get_unsaved_documents (dlg);
1899 g_return_if_fail (unsaved_documents->next == NULL);
1900
1901 close_document (window, GEDIT_DOCUMENT (unsaved_documents->data));
1902 }
1903
1904 break;
1905
1906 /* Do not close */
1907 default:
1908 /* Reset is_quitting flag */
1909 g_object_set_data (G_OBJECT (window),
1910 GEDIT_IS_QUITTING,
1911 GBOOLEAN_TO_POINTER (FALSE));
1912
1913 g_object_set_data (G_OBJECT (window),
1914 GEDIT_IS_QUITTING_ALL,
1915 GBOOLEAN_TO_POINTER (FALSE));
1916 break;
1917 }
1918
1919 g_object_set_data (G_OBJECT (window), GEDIT_NOTEBOOK_TO_CLOSE, NULL);
1920
1921 gtk_widget_destroy (GTK_WIDGET (dlg));
1922 }
1923
1924 /* Returns TRUE if the tab can be immediately closed */
1925 static gboolean
tab_can_close(GeditTab * tab,GtkWindow * window)1926 tab_can_close (GeditTab *tab,
1927 GtkWindow *window)
1928 {
1929 GeditDocument *doc;
1930
1931 gedit_debug (DEBUG_COMMANDS);
1932
1933 doc = gedit_tab_get_document (tab);
1934
1935 if (!_gedit_tab_get_can_close (tab))
1936 {
1937 GtkWidget *dlg;
1938
1939 dlg = gedit_close_confirmation_dialog_new_single (window, doc);
1940 g_signal_connect (dlg,
1941 "response",
1942 G_CALLBACK (close_confirmation_dialog_response_handler),
1943 window);
1944
1945 gtk_widget_show (dlg);
1946
1947 return FALSE;
1948 }
1949
1950 return TRUE;
1951 }
1952
1953 /* FIXME: we probably need this one public for plugins...
1954 * maybe even a _list variant. Or maybe it's better make
1955 * gedit_window_close_tab always run the confirm dialog?
1956 * we should not allow closing a tab without resetting the
1957 * GEDIT_IS_CLOSING_ALL flag!
1958 */
1959 void
_gedit_cmd_file_close_tab(GeditTab * tab,GeditWindow * window)1960 _gedit_cmd_file_close_tab (GeditTab *tab,
1961 GeditWindow *window)
1962 {
1963 gedit_debug (DEBUG_COMMANDS);
1964
1965 g_return_if_fail (GTK_WIDGET (window) == gtk_widget_get_toplevel (GTK_WIDGET (tab)));
1966
1967 g_object_set_data (G_OBJECT (window),
1968 GEDIT_IS_CLOSING_ALL,
1969 GBOOLEAN_TO_POINTER (FALSE));
1970
1971 g_object_set_data (G_OBJECT (window),
1972 GEDIT_IS_QUITTING,
1973 GBOOLEAN_TO_POINTER (FALSE));
1974
1975 g_object_set_data (G_OBJECT (window),
1976 GEDIT_IS_QUITTING_ALL,
1977 GBOOLEAN_TO_POINTER (FALSE));
1978
1979 if (tab_can_close (tab, GTK_WINDOW (window)))
1980 {
1981 gedit_window_close_tab (window, tab);
1982 }
1983 }
1984
1985 void
_gedit_cmd_file_close(GSimpleAction * action,GVariant * parameter,gpointer user_data)1986 _gedit_cmd_file_close (GSimpleAction *action,
1987 GVariant *parameter,
1988 gpointer user_data)
1989 {
1990 GeditWindow *window = GEDIT_WINDOW (user_data);
1991 GeditTab *active_tab;
1992
1993 gedit_debug (DEBUG_COMMANDS);
1994
1995 active_tab = gedit_window_get_active_tab (window);
1996
1997 if (active_tab == NULL)
1998 {
1999 gtk_widget_destroy (GTK_WIDGET (window));
2000 return;
2001 }
2002
2003 _gedit_cmd_file_close_tab (active_tab, window);
2004 }
2005
2006 static void
file_close_dialog(GeditWindow * window,GList * unsaved_docs)2007 file_close_dialog (GeditWindow *window,
2008 GList *unsaved_docs)
2009 {
2010 GtkWidget *dlg;
2011
2012 if (unsaved_docs->next == NULL)
2013 {
2014 /* There is only one unsaved document */
2015 GeditTab *tab;
2016 GeditDocument *doc;
2017
2018 doc = GEDIT_DOCUMENT (unsaved_docs->data);
2019
2020 tab = gedit_tab_get_from_document (doc);
2021 g_return_if_fail (tab != NULL);
2022
2023 gedit_window_set_active_tab (window, tab);
2024
2025 dlg = gedit_close_confirmation_dialog_new_single (GTK_WINDOW (window), doc);
2026 }
2027 else
2028 {
2029 dlg = gedit_close_confirmation_dialog_new (GTK_WINDOW (window), unsaved_docs);
2030 }
2031
2032 g_signal_connect (dlg,
2033 "response",
2034 G_CALLBACK (close_confirmation_dialog_response_handler),
2035 window);
2036
2037 gtk_widget_show (dlg);
2038 }
2039
2040 static GList *
notebook_get_unsaved_documents(GeditNotebook * notebook)2041 notebook_get_unsaved_documents (GeditNotebook *notebook)
2042 {
2043 GList *children;
2044 GList *unsaved_docs = NULL;
2045 GList *l;
2046
2047 children = gtk_container_get_children (GTK_CONTAINER (notebook));
2048
2049 for (l = children; l != NULL; l = g_list_next (l))
2050 {
2051 GeditTab *tab = GEDIT_TAB (l->data);
2052
2053 if (!_gedit_tab_get_can_close (tab))
2054 {
2055 GeditDocument *doc;
2056
2057 doc = gedit_tab_get_document (tab);
2058 unsaved_docs = g_list_prepend (unsaved_docs, doc);
2059 }
2060 }
2061
2062 g_list_free (children);
2063
2064 return g_list_reverse (unsaved_docs);
2065 }
2066
2067 /* Close a notebook */
2068 void
_gedit_cmd_file_close_notebook(GeditWindow * window,GeditNotebook * notebook)2069 _gedit_cmd_file_close_notebook (GeditWindow *window,
2070 GeditNotebook *notebook)
2071 {
2072 GList *unsaved_docs;
2073
2074 g_object_set_data (G_OBJECT (window), GEDIT_IS_CLOSING_ALL, GBOOLEAN_TO_POINTER (FALSE));
2075 g_object_set_data (G_OBJECT (window), GEDIT_IS_QUITTING, GBOOLEAN_TO_POINTER (FALSE));
2076 g_object_set_data (G_OBJECT (window), GEDIT_IS_QUITTING_ALL, GBOOLEAN_TO_POINTER (FALSE));
2077
2078 g_object_set_data (G_OBJECT (window), GEDIT_NOTEBOOK_TO_CLOSE, notebook);
2079
2080 unsaved_docs = notebook_get_unsaved_documents (notebook);
2081
2082 if (unsaved_docs == NULL)
2083 {
2084 /* There is no document to save -> close the notebook */
2085 gedit_notebook_remove_all_tabs (GEDIT_NOTEBOOK (notebook));
2086 }
2087 else
2088 {
2089 file_close_dialog (window, unsaved_docs);
2090
2091 g_list_free (unsaved_docs);
2092 }
2093 }
2094
2095 /* Close all tabs */
2096 static void
file_close_all(GeditWindow * window,gboolean is_quitting)2097 file_close_all (GeditWindow *window,
2098 gboolean is_quitting)
2099 {
2100 GList *unsaved_docs;
2101
2102 gedit_debug (DEBUG_COMMANDS);
2103
2104 g_return_if_fail (!(gedit_window_get_state (window) &
2105 (GEDIT_WINDOW_STATE_SAVING |
2106 GEDIT_WINDOW_STATE_PRINTING)));
2107
2108 g_object_set_data (G_OBJECT (window),
2109 GEDIT_IS_CLOSING_ALL,
2110 GBOOLEAN_TO_POINTER (TRUE));
2111
2112 g_object_set_data (G_OBJECT (window),
2113 GEDIT_IS_QUITTING,
2114 GBOOLEAN_TO_POINTER (is_quitting));
2115
2116 unsaved_docs = gedit_window_get_unsaved_documents (window);
2117
2118 if (unsaved_docs != NULL)
2119 {
2120 file_close_dialog (window, unsaved_docs);
2121
2122 g_list_free (unsaved_docs);
2123 }
2124 else
2125 {
2126 /* There is no document to save -> close all tabs */
2127 gedit_window_close_all_tabs (window);
2128 quit_if_needed (window);
2129 }
2130 }
2131
2132 void
_gedit_cmd_file_close_all(GSimpleAction * action,GVariant * parameter,gpointer user_data)2133 _gedit_cmd_file_close_all (GSimpleAction *action,
2134 GVariant *parameter,
2135 gpointer user_data)
2136 {
2137 GeditWindow *window = GEDIT_WINDOW (user_data);
2138
2139 gedit_debug (DEBUG_COMMANDS);
2140
2141 g_return_if_fail (!(gedit_window_get_state (window) &
2142 (GEDIT_WINDOW_STATE_SAVING |
2143 GEDIT_WINDOW_STATE_PRINTING)));
2144
2145 file_close_all (window, FALSE);
2146 }
2147
2148 /* Quit */
2149 static void
quit_all(void)2150 quit_all (void)
2151 {
2152 GList *windows;
2153 GList *l;
2154 GApplication *app;
2155
2156 app = g_application_get_default ();
2157 windows = gedit_app_get_main_windows (GEDIT_APP (app));
2158
2159 if (windows == NULL)
2160 {
2161 g_application_quit (app);
2162 return;
2163 }
2164
2165 for (l = windows; l != NULL; l = g_list_next (l))
2166 {
2167 GeditWindow *window = l->data;
2168
2169 g_object_set_data (G_OBJECT (window),
2170 GEDIT_IS_QUITTING_ALL,
2171 GBOOLEAN_TO_POINTER (TRUE));
2172
2173 if (!(gedit_window_get_state (window) &
2174 (GEDIT_WINDOW_STATE_SAVING | GEDIT_WINDOW_STATE_PRINTING)))
2175 {
2176 file_close_all (window, TRUE);
2177 }
2178 }
2179
2180 g_list_free (windows);
2181 }
2182
2183 void
_gedit_cmd_file_quit(GSimpleAction * action,GVariant * parameter,gpointer user_data)2184 _gedit_cmd_file_quit (GSimpleAction *action,
2185 GVariant *parameter,
2186 gpointer user_data)
2187 {
2188 GeditWindow *window = GEDIT_WINDOW (user_data);
2189
2190 gedit_debug (DEBUG_COMMANDS);
2191
2192 if (window == NULL)
2193 {
2194 quit_all ();
2195 return;
2196 }
2197
2198 g_return_if_fail (!(gedit_window_get_state (window) &
2199 (GEDIT_WINDOW_STATE_SAVING |
2200 GEDIT_WINDOW_STATE_PRINTING)));
2201
2202 file_close_all (window, TRUE);
2203 }
2204
2205 /* ex:set ts=8 noet: */
2206