1 /*
2 * gedit-tab.c
3 * This file is part of gedit
4 *
5 * Copyright (C) 2005 - Paolo Maggi
6 * Copyright (C) 2014, 2015 - Sébastien Wilmet
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "gedit-tab.h"
23 #include "gedit-tab-private.h"
24
25 #include <stdlib.h>
26 #include <glib/gi18n.h>
27 #include <tepl/tepl.h>
28
29 #include "gedit-app.h"
30 #include "gedit-app-private.h"
31 #include "gedit-recent.h"
32 #include "gedit-utils.h"
33 #include "gedit-io-error-info-bar.h"
34 #include "gedit-print-job.h"
35 #include "gedit-print-preview.h"
36 #include "gedit-debug.h"
37 #include "gedit-document.h"
38 #include "gedit-document-private.h"
39 #include "gedit-enum-types.h"
40 #include "gedit-settings.h"
41 #include "gedit-view-frame.h"
42
43 #define GEDIT_TAB_KEY "GEDIT_TAB_KEY"
44
45 struct _GeditTab
46 {
47 GtkBox parent_instance;
48
49 GeditTabState state;
50
51 GSettings *editor_settings;
52
53 GeditViewFrame *frame;
54
55 GtkWidget *info_bar;
56 GtkWidget *info_bar_hidden;
57
58 GeditPrintJob *print_job;
59 GtkWidget *print_preview;
60
61 GtkSourceFileSaverFlags save_flags;
62
63 guint idle_scroll;
64
65 gint auto_save_interval;
66 guint auto_save_timeout;
67
68 GCancellable *cancellable;
69
70 guint editable : 1;
71 guint auto_save : 1;
72
73 guint ask_if_externally_modified : 1;
74 };
75
76 typedef struct _SaverData SaverData;
77 typedef struct _LoaderData LoaderData;
78
79 struct _SaverData
80 {
81 GtkSourceFileSaver *saver;
82
83 GTimer *timer;
84
85 /* Notes about the create_backup saver flag:
86 * - At the beginning of a new file saving, force_no_backup is FALSE.
87 * The create_backup flag is set to the saver if it is enabled in
88 * GSettings and if it isn't an auto-save.
89 * - If creating the backup gives an error, and if the user wants to
90 * save the file without the backup, force_no_backup is set to TRUE
91 * and the create_backup flag is removed from the saver.
92 * force_no_backup as TRUE means that the create_backup flag should
93 * never be added again to the saver (for the current file saving).
94 * - When another error occurs and if the user explicitly retry again
95 * the file saving, the create_backup flag is added to the saver if
96 * (1) it is enabled in GSettings, (2) if force_no_backup is FALSE.
97 * - The create_backup flag is added when the user expressed his or her
98 * willing to save the file, by pressing a button for example. For an
99 * auto-save, the create_backup flag is thus not added initially, but
100 * can be added later when an error occurs and the user clicks on a
101 * button in the info bar to retry the file saving.
102 */
103 guint force_no_backup : 1;
104 };
105
106 struct _LoaderData
107 {
108 GeditTab *tab;
109 GtkSourceFileLoader *loader;
110 GTimer *timer;
111 gint line_pos;
112 gint column_pos;
113 guint user_requested_encoding : 1;
114 };
115
116 G_DEFINE_TYPE (GeditTab, gedit_tab, GTK_TYPE_BOX)
117
118 enum
119 {
120 PROP_0,
121 PROP_NAME,
122 PROP_STATE,
123 PROP_AUTO_SAVE,
124 PROP_AUTO_SAVE_INTERVAL,
125 PROP_CAN_CLOSE,
126 LAST_PROP
127 };
128
129 static GParamSpec *properties[LAST_PROP];
130
131 enum
132 {
133 DROP_URIS,
134 LAST_SIGNAL
135 };
136
137 static guint signals[LAST_SIGNAL];
138
139 static gboolean gedit_tab_auto_save (GeditTab *tab);
140
141 static void launch_loader (GTask *loading_task,
142 const GtkSourceEncoding *encoding);
143
144 static void launch_saver (GTask *saving_task);
145
146 static SaverData *
saver_data_new(void)147 saver_data_new (void)
148 {
149 return g_slice_new0 (SaverData);
150 }
151
152 static void
saver_data_free(SaverData * data)153 saver_data_free (SaverData *data)
154 {
155 if (data != NULL)
156 {
157 if (data->saver != NULL)
158 {
159 g_object_unref (data->saver);
160 }
161
162 if (data->timer != NULL)
163 {
164 g_timer_destroy (data->timer);
165 }
166
167 g_slice_free (SaverData, data);
168 }
169 }
170
171 static LoaderData *
loader_data_new(void)172 loader_data_new (void)
173 {
174 return g_slice_new0 (LoaderData);
175 }
176
177 static void
loader_data_free(LoaderData * data)178 loader_data_free (LoaderData *data)
179 {
180 if (data != NULL)
181 {
182 if (data->loader != NULL)
183 {
184 g_object_unref (data->loader);
185 }
186
187 if (data->timer != NULL)
188 {
189 g_timer_destroy (data->timer);
190 }
191
192 g_slice_free (LoaderData, data);
193 }
194 }
195
196 static void
set_editable(GeditTab * tab,gboolean editable)197 set_editable (GeditTab *tab,
198 gboolean editable)
199 {
200 GeditView *view;
201 gboolean val;
202
203 tab->editable = editable != FALSE;
204
205 view = gedit_tab_get_view (tab);
206
207 val = (tab->state == GEDIT_TAB_STATE_NORMAL &&
208 tab->editable);
209
210 gtk_text_view_set_editable (GTK_TEXT_VIEW (view), val);
211 }
212
213 static void
install_auto_save_timeout(GeditTab * tab)214 install_auto_save_timeout (GeditTab *tab)
215 {
216 if (tab->auto_save_timeout == 0)
217 {
218 g_return_if_fail (tab->auto_save_interval > 0);
219
220 tab->auto_save_timeout = g_timeout_add_seconds (tab->auto_save_interval * 60,
221 (GSourceFunc) gedit_tab_auto_save,
222 tab);
223 }
224 }
225
226 static void
remove_auto_save_timeout(GeditTab * tab)227 remove_auto_save_timeout (GeditTab *tab)
228 {
229 gedit_debug (DEBUG_TAB);
230
231 if (tab->auto_save_timeout > 0)
232 {
233 g_source_remove (tab->auto_save_timeout);
234 tab->auto_save_timeout = 0;
235 }
236 }
237
238 static void
update_auto_save_timeout(GeditTab * tab)239 update_auto_save_timeout (GeditTab *tab)
240 {
241 GeditDocument *doc;
242 GtkSourceFile *file;
243
244 gedit_debug (DEBUG_TAB);
245
246 doc = gedit_tab_get_document (tab);
247 file = gedit_document_get_file (doc);
248
249 if (tab->state == GEDIT_TAB_STATE_NORMAL &&
250 tab->auto_save &&
251 !gedit_document_is_untitled (doc) &&
252 !gtk_source_file_is_readonly (file))
253 {
254 install_auto_save_timeout (tab);
255 }
256 else
257 {
258 remove_auto_save_timeout (tab);
259 }
260 }
261
262 static void
gedit_tab_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)263 gedit_tab_get_property (GObject *object,
264 guint prop_id,
265 GValue *value,
266 GParamSpec *pspec)
267 {
268 GeditTab *tab = GEDIT_TAB (object);
269
270 switch (prop_id)
271 {
272 case PROP_NAME:
273 g_value_take_string (value, _gedit_tab_get_name (tab));
274 break;
275
276 case PROP_STATE:
277 g_value_set_enum (value, gedit_tab_get_state (tab));
278 break;
279
280 case PROP_AUTO_SAVE:
281 g_value_set_boolean (value, gedit_tab_get_auto_save_enabled (tab));
282 break;
283
284 case PROP_AUTO_SAVE_INTERVAL:
285 g_value_set_int (value, gedit_tab_get_auto_save_interval (tab));
286 break;
287
288 case PROP_CAN_CLOSE:
289 g_value_set_boolean (value, _gedit_tab_get_can_close (tab));
290 break;
291
292 default:
293 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
294 break;
295 }
296 }
297
298 static void
gedit_tab_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)299 gedit_tab_set_property (GObject *object,
300 guint prop_id,
301 const GValue *value,
302 GParamSpec *pspec)
303 {
304 GeditTab *tab = GEDIT_TAB (object);
305
306 switch (prop_id)
307 {
308 case PROP_AUTO_SAVE:
309 gedit_tab_set_auto_save_enabled (tab, g_value_get_boolean (value));
310 break;
311
312 case PROP_AUTO_SAVE_INTERVAL:
313 gedit_tab_set_auto_save_interval (tab, g_value_get_int (value));
314 break;
315
316 default:
317 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
318 break;
319 }
320 }
321
322 static void
gedit_tab_dispose(GObject * object)323 gedit_tab_dispose (GObject *object)
324 {
325 GeditTab *tab = GEDIT_TAB (object);
326
327 g_clear_object (&tab->editor_settings);
328 g_clear_object (&tab->print_job);
329 g_clear_object (&tab->print_preview);
330
331 remove_auto_save_timeout (tab);
332
333 if (tab->idle_scroll != 0)
334 {
335 g_source_remove (tab->idle_scroll);
336 tab->idle_scroll = 0;
337 }
338
339 if (tab->cancellable != NULL)
340 {
341 g_cancellable_cancel (tab->cancellable);
342 g_clear_object (&tab->cancellable);
343 }
344
345 G_OBJECT_CLASS (gedit_tab_parent_class)->dispose (object);
346 }
347
348 static void
gedit_tab_grab_focus(GtkWidget * widget)349 gedit_tab_grab_focus (GtkWidget *widget)
350 {
351 GeditTab *tab = GEDIT_TAB (widget);
352
353 GTK_WIDGET_CLASS (gedit_tab_parent_class)->grab_focus (widget);
354
355 if (tab->info_bar != NULL)
356 {
357 gtk_widget_grab_focus (tab->info_bar);
358 }
359 else
360 {
361 GeditView *view = gedit_tab_get_view (tab);
362 gtk_widget_grab_focus (GTK_WIDGET (view));
363 }
364 }
365
366 static void
gedit_tab_drop_uris(GeditTab * tab,gchar ** uri_list)367 gedit_tab_drop_uris (GeditTab *tab,
368 gchar **uri_list)
369 {
370 gedit_debug (DEBUG_TAB);
371 }
372
373 static void
gedit_tab_class_init(GeditTabClass * klass)374 gedit_tab_class_init (GeditTabClass *klass)
375 {
376 GObjectClass *object_class = G_OBJECT_CLASS (klass);
377 GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
378
379 object_class->dispose = gedit_tab_dispose;
380 object_class->get_property = gedit_tab_get_property;
381 object_class->set_property = gedit_tab_set_property;
382
383 gtkwidget_class->grab_focus = gedit_tab_grab_focus;
384
385 properties[PROP_NAME] =
386 g_param_spec_string ("name",
387 "Name",
388 "The tab's name",
389 NULL,
390 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
391
392 properties[PROP_STATE] =
393 g_param_spec_enum ("state",
394 "State",
395 "The tab's state",
396 GEDIT_TYPE_TAB_STATE,
397 GEDIT_TAB_STATE_NORMAL,
398 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
399
400 properties[PROP_AUTO_SAVE] =
401 g_param_spec_boolean ("autosave",
402 "Autosave",
403 "Autosave feature",
404 TRUE,
405 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
406
407 properties[PROP_AUTO_SAVE_INTERVAL] =
408 g_param_spec_int ("autosave-interval",
409 "AutosaveInterval",
410 "Time between two autosaves",
411 0,
412 G_MAXINT,
413 0,
414 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
415
416 properties[PROP_CAN_CLOSE] =
417 g_param_spec_boolean ("can-close",
418 "Can close",
419 "Whether the tab can be closed",
420 TRUE,
421 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
422
423 g_object_class_install_properties (object_class, LAST_PROP, properties);
424
425 signals[DROP_URIS] =
426 g_signal_new_class_handler ("drop-uris",
427 G_TYPE_FROM_CLASS (klass),
428 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
429 G_CALLBACK (gedit_tab_drop_uris),
430 NULL, NULL, NULL,
431 G_TYPE_NONE,
432 1,
433 G_TYPE_STRV);
434 }
435
436 /**
437 * gedit_tab_get_state:
438 * @tab: a #GeditTab
439 *
440 * Gets the #GeditTabState of @tab.
441 *
442 * Returns: the #GeditTabState of @tab
443 */
444 GeditTabState
gedit_tab_get_state(GeditTab * tab)445 gedit_tab_get_state (GeditTab *tab)
446 {
447 g_return_val_if_fail (GEDIT_IS_TAB (tab), GEDIT_TAB_STATE_NORMAL);
448
449 return tab->state;
450 }
451
452 static void
set_cursor_according_to_state(GtkTextView * view,GeditTabState state)453 set_cursor_according_to_state (GtkTextView *view,
454 GeditTabState state)
455 {
456 GdkDisplay *display;
457 GdkCursor *cursor;
458 GdkWindow *text_window;
459 GdkWindow *left_window;
460
461 display = gtk_widget_get_display (GTK_WIDGET (view));
462
463 text_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_TEXT);
464 left_window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_LEFT);
465
466 if ((state == GEDIT_TAB_STATE_LOADING) ||
467 (state == GEDIT_TAB_STATE_REVERTING) ||
468 (state == GEDIT_TAB_STATE_SAVING) ||
469 (state == GEDIT_TAB_STATE_PRINTING) ||
470 (state == GEDIT_TAB_STATE_CLOSING))
471 {
472 cursor = gdk_cursor_new_from_name (display, "progress");
473
474 if (text_window != NULL)
475 gdk_window_set_cursor (text_window, cursor);
476 if (left_window != NULL)
477 gdk_window_set_cursor (left_window, cursor);
478
479 g_clear_object (&cursor);
480 }
481 else
482 {
483 cursor = gdk_cursor_new_from_name (display, "text");
484
485 if (text_window != NULL)
486 gdk_window_set_cursor (text_window, cursor);
487 if (left_window != NULL)
488 gdk_window_set_cursor (left_window, NULL);
489
490 g_clear_object (&cursor);
491 }
492 }
493
494 static void
view_realized(GtkTextView * view,GeditTab * tab)495 view_realized (GtkTextView *view,
496 GeditTab *tab)
497 {
498 set_cursor_according_to_state (view, tab->state);
499 }
500
501 static void
set_view_properties_according_to_state(GeditTab * tab,GeditTabState state)502 set_view_properties_according_to_state (GeditTab *tab,
503 GeditTabState state)
504 {
505 GeditView *view;
506 gboolean val;
507 gboolean hl_current_line;
508
509 hl_current_line = g_settings_get_boolean (tab->editor_settings,
510 GEDIT_SETTINGS_HIGHLIGHT_CURRENT_LINE);
511
512 view = gedit_tab_get_view (tab);
513
514 val = ((state == GEDIT_TAB_STATE_NORMAL) &&
515 tab->editable);
516 gtk_text_view_set_editable (GTK_TEXT_VIEW (view), val);
517
518 val = ((state != GEDIT_TAB_STATE_LOADING) &&
519 (state != GEDIT_TAB_STATE_CLOSING));
520 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), val);
521
522 val = ((state != GEDIT_TAB_STATE_LOADING) &&
523 (state != GEDIT_TAB_STATE_CLOSING) &&
524 (hl_current_line));
525 gtk_source_view_set_highlight_current_line (GTK_SOURCE_VIEW (view), val);
526 }
527
528 static void
gedit_tab_set_state(GeditTab * tab,GeditTabState state)529 gedit_tab_set_state (GeditTab *tab,
530 GeditTabState state)
531 {
532 g_return_if_fail ((state >= 0) && (state < GEDIT_TAB_NUM_OF_STATES));
533
534 if (tab->state == state)
535 {
536 return;
537 }
538
539 tab->state = state;
540
541 set_view_properties_according_to_state (tab, state);
542
543 /* Hide or show the document.
544 * For GEDIT_TAB_STATE_LOADING_ERROR, tab->frame is either shown or
545 * hidden, depending on the error.
546 */
547 if (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
548 {
549 gtk_widget_hide (GTK_WIDGET (tab->frame));
550 }
551 else if (state != GEDIT_TAB_STATE_LOADING_ERROR)
552 {
553 gtk_widget_show (GTK_WIDGET (tab->frame));
554 }
555
556 set_cursor_according_to_state (GTK_TEXT_VIEW (gedit_tab_get_view (tab)),
557 state);
558
559 update_auto_save_timeout (tab);
560
561 g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_STATE]);
562 g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_CAN_CLOSE]);
563 }
564
565 static void
document_location_notify_handler(GtkSourceFile * file,GParamSpec * pspec,GeditTab * tab)566 document_location_notify_handler (GtkSourceFile *file,
567 GParamSpec *pspec,
568 GeditTab *tab)
569 {
570 gedit_debug (DEBUG_TAB);
571
572 /* Notify the change in the location */
573 g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
574 }
575
576 static void
document_shortname_notify_handler(TeplFile * file,GParamSpec * pspec,GeditTab * tab)577 document_shortname_notify_handler (TeplFile *file,
578 GParamSpec *pspec,
579 GeditTab *tab)
580 {
581 gedit_debug (DEBUG_TAB);
582
583 /* Notify the change in the shortname */
584 g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
585 }
586
587 static void
document_modified_changed(GtkTextBuffer * document,GeditTab * tab)588 document_modified_changed (GtkTextBuffer *document,
589 GeditTab *tab)
590 {
591 g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_NAME]);
592 g_object_notify_by_pspec (G_OBJECT (tab), properties[PROP_CAN_CLOSE]);
593 }
594
595 static void
set_info_bar(GeditTab * tab,GtkWidget * info_bar,GtkResponseType default_response)596 set_info_bar (GeditTab *tab,
597 GtkWidget *info_bar,
598 GtkResponseType default_response)
599 {
600 gedit_debug (DEBUG_TAB);
601
602 if (tab->info_bar == info_bar)
603 {
604 return;
605 }
606
607 if (info_bar == NULL)
608 {
609 /* Don't destroy the old info_bar right away,
610 we want the hide animation. */
611 if (tab->info_bar_hidden != NULL)
612 {
613 gtk_widget_destroy (tab->info_bar_hidden);
614 }
615
616 tab->info_bar_hidden = tab->info_bar;
617 gtk_widget_hide (tab->info_bar_hidden);
618
619 tab->info_bar = NULL;
620 }
621 else
622 {
623 if (tab->info_bar != NULL)
624 {
625 gedit_debug_message (DEBUG_TAB, "Replacing existing notification");
626 gtk_widget_destroy (tab->info_bar);
627 }
628
629 /* Make sure to stop a possibly still ongoing hiding animation. */
630 if (tab->info_bar_hidden != NULL)
631 {
632 gtk_widget_destroy (tab->info_bar_hidden);
633 tab->info_bar_hidden = NULL;
634 }
635
636 tab->info_bar = info_bar;
637 gtk_box_pack_start (GTK_BOX (tab), info_bar, FALSE, FALSE, 0);
638
639 /* Note this must be done after the info bar is added to the window */
640 if (default_response != GTK_RESPONSE_NONE)
641 {
642 gtk_info_bar_set_default_response (GTK_INFO_BAR (info_bar),
643 default_response);
644 }
645
646 gtk_widget_show (info_bar);
647 }
648 }
649
650 static void
remove_tab(GeditTab * tab)651 remove_tab (GeditTab *tab)
652 {
653 GtkWidget *notebook;
654
655 notebook = gtk_widget_get_parent (GTK_WIDGET (tab));
656 gtk_container_remove (GTK_CONTAINER (notebook), GTK_WIDGET (tab));
657 }
658
659 static void
io_loading_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * loading_task)660 io_loading_error_info_bar_response (GtkWidget *info_bar,
661 gint response_id,
662 GTask *loading_task)
663 {
664 LoaderData *data = g_task_get_task_data (loading_task);
665 GFile *location;
666 const GtkSourceEncoding *encoding;
667
668 location = gtk_source_file_loader_get_location (data->loader);
669
670 switch (response_id)
671 {
672 case GTK_RESPONSE_OK:
673 encoding = gedit_conversion_error_info_bar_get_encoding (GTK_WIDGET (info_bar));
674
675 set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
676 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_LOADING);
677
678 launch_loader (loading_task, encoding);
679 break;
680
681 case GTK_RESPONSE_YES:
682 /* This means that we want to edit the document anyway */
683 set_editable (data->tab, TRUE);
684 set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
685 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
686
687 g_task_return_boolean (loading_task, TRUE);
688 g_object_unref (loading_task);
689 break;
690
691 default:
692 if (location != NULL)
693 {
694 gedit_recent_remove_if_local (location);
695 }
696
697 remove_tab (data->tab);
698
699 g_task_return_boolean (loading_task, FALSE);
700 g_object_unref (loading_task);
701 break;
702 }
703 }
704
705 static void
file_already_open_warning_info_bar_response(GtkWidget * info_bar,gint response_id,GeditTab * tab)706 file_already_open_warning_info_bar_response (GtkWidget *info_bar,
707 gint response_id,
708 GeditTab *tab)
709 {
710 GeditView *view = gedit_tab_get_view (tab);
711
712 if (response_id == GTK_RESPONSE_YES)
713 {
714 set_editable (tab, TRUE);
715 }
716
717 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
718
719 gtk_widget_grab_focus (GTK_WIDGET (view));
720 }
721
722 static void
load_cancelled(GtkWidget * bar,gint response_id,GTask * loading_task)723 load_cancelled (GtkWidget *bar,
724 gint response_id,
725 GTask *loading_task)
726 {
727 LoaderData *data = g_task_get_task_data (loading_task);
728
729 g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (data->tab->info_bar));
730
731 g_cancellable_cancel (g_task_get_cancellable (loading_task));
732 remove_tab (data->tab);
733 }
734
735 static void
unrecoverable_reverting_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * loading_task)736 unrecoverable_reverting_error_info_bar_response (GtkWidget *info_bar,
737 gint response_id,
738 GTask *loading_task)
739 {
740 LoaderData *data = g_task_get_task_data (loading_task);
741 GeditView *view;
742
743 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
744
745 set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
746
747 view = gedit_tab_get_view (data->tab);
748 gtk_widget_grab_focus (GTK_WIDGET (view));
749
750 g_task_return_boolean (loading_task, FALSE);
751 g_object_unref (loading_task);
752 }
753
754 #define MAX_MSG_LENGTH 100
755
756 static void
show_loading_info_bar(GTask * loading_task)757 show_loading_info_bar (GTask *loading_task)
758 {
759 LoaderData *data = g_task_get_task_data (loading_task);
760 TeplProgressInfoBar *bar;
761 GeditDocument *doc;
762 gchar *name;
763 gchar *dirname = NULL;
764 gchar *msg = NULL;
765 gchar *name_markup;
766 gchar *dirname_markup;
767 gint len;
768
769 if (data->tab->info_bar != NULL)
770 {
771 return;
772 }
773
774 gedit_debug (DEBUG_TAB);
775
776 doc = gedit_tab_get_document (data->tab);
777
778 name = gedit_document_get_short_name_for_display (doc);
779 len = g_utf8_strlen (name, -1);
780
781 /* if the name is awfully long, truncate it and be done with it,
782 * otherwise also show the directory (ellipsized if needed)
783 */
784 if (len > MAX_MSG_LENGTH)
785 {
786 gchar *str;
787
788 str = tepl_utils_str_middle_truncate (name, MAX_MSG_LENGTH);
789 g_free (name);
790 name = str;
791 }
792 else
793 {
794 GtkSourceFile *file = gedit_document_get_file (doc);
795 GFile *location = gtk_source_file_get_location (file);
796
797 if (location != NULL)
798 {
799 gchar *str = gedit_utils_location_get_dirname_for_display (location);
800
801 /* use the remaining space for the dir, but use a min of 20 chars
802 * so that we do not end up with a dirname like "(a...b)".
803 * This means that in the worst case when the filename is long 99
804 * we have a title long 99 + 20, but I think it's a rare enough
805 * case to be acceptable. It's justa darn title afterall :)
806 */
807 dirname = tepl_utils_str_middle_truncate (str,
808 MAX (20, MAX_MSG_LENGTH - len));
809 g_free (str);
810 }
811 }
812
813 name_markup = g_markup_printf_escaped ("<b>%s</b>", name);
814
815 if (data->tab->state == GEDIT_TAB_STATE_REVERTING)
816 {
817 if (dirname != NULL)
818 {
819 dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
820
821 /* Translators: the first %s is a file name (e.g. test.txt) the second one
822 is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
823 msg = g_strdup_printf (_("Reverting %s from %s"),
824 name_markup,
825 dirname_markup);
826 g_free (dirname_markup);
827 }
828 else
829 {
830 msg = g_strdup_printf (_("Reverting %s"), name_markup);
831 }
832
833 bar = tepl_progress_info_bar_new ("document-revert", msg, TRUE);
834 }
835 else
836 {
837 if (dirname != NULL)
838 {
839 dirname_markup = g_markup_printf_escaped ("<b>%s</b>", dirname);
840
841 /* Translators: the first %s is a file name (e.g. test.txt) the second one
842 is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
843 msg = g_strdup_printf (_("Loading %s from %s"),
844 name_markup,
845 dirname_markup);
846 g_free (dirname_markup);
847 }
848 else
849 {
850 msg = g_strdup_printf (_("Loading %s"), name_markup);
851 }
852
853 bar = tepl_progress_info_bar_new ("document-open", msg, TRUE);
854 }
855
856 g_signal_connect_object (bar,
857 "response",
858 G_CALLBACK (load_cancelled),
859 loading_task,
860 0);
861
862 set_info_bar (data->tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
863
864 g_free (msg);
865 g_free (name);
866 g_free (name_markup);
867 g_free (dirname);
868 }
869
870 static void
show_saving_info_bar(GTask * saving_task)871 show_saving_info_bar (GTask *saving_task)
872 {
873 GeditTab *tab = g_task_get_source_object (saving_task);
874 TeplProgressInfoBar *bar;
875 GeditDocument *doc;
876 gchar *short_name;
877 gchar *from;
878 gchar *to = NULL;
879 gchar *from_markup;
880 gchar *to_markup;
881 gchar *msg = NULL;
882 gint len;
883
884 if (tab->info_bar != NULL)
885 {
886 return;
887 }
888
889 gedit_debug (DEBUG_TAB);
890
891 doc = gedit_tab_get_document (tab);
892
893 short_name = gedit_document_get_short_name_for_display (doc);
894
895 len = g_utf8_strlen (short_name, -1);
896
897 /* if the name is awfully long, truncate it and be done with it,
898 * otherwise also show the directory (ellipsized if needed)
899 */
900 if (len > MAX_MSG_LENGTH)
901 {
902 from = tepl_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
903 g_free (short_name);
904 }
905 else
906 {
907 gchar *str;
908 SaverData *data;
909 GFile *location;
910
911 data = g_task_get_task_data (saving_task);
912 location = gtk_source_file_saver_get_location (data->saver);
913
914 from = short_name;
915 to = g_file_get_parse_name (location);
916 str = tepl_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
917 g_free (to);
918
919 to = str;
920 }
921
922 from_markup = g_markup_printf_escaped ("<b>%s</b>", from);
923
924 if (to != NULL)
925 {
926 to_markup = g_markup_printf_escaped ("<b>%s</b>", to);
927
928 /* Translators: the first %s is a file name (e.g. test.txt) the second one
929 is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
930 msg = g_strdup_printf (_("Saving %s to %s"), from_markup, to_markup);
931 g_free (to_markup);
932 }
933 else
934 {
935 msg = g_strdup_printf (_("Saving %s"), from_markup);
936 }
937
938 bar = tepl_progress_info_bar_new ("document-save", msg, FALSE);
939
940 set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
941
942 g_free (msg);
943 g_free (to);
944 g_free (from);
945 g_free (from_markup);
946 }
947
948 static void
info_bar_set_progress(GeditTab * tab,goffset size,goffset total_size)949 info_bar_set_progress (GeditTab *tab,
950 goffset size,
951 goffset total_size)
952 {
953 TeplProgressInfoBar *progress_info_bar;
954
955 if (tab->info_bar == NULL)
956 {
957 return;
958 }
959
960 gedit_debug_message (DEBUG_TAB, "%" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT, size, total_size);
961
962 g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
963
964 progress_info_bar = TEPL_PROGRESS_INFO_BAR (tab->info_bar);
965
966 if (total_size != 0)
967 {
968 gdouble frac = (gdouble)size / (gdouble)total_size;
969
970 tepl_progress_info_bar_set_fraction (progress_info_bar, frac);
971 }
972 else if (size != 0)
973 {
974 tepl_progress_info_bar_pulse (progress_info_bar);
975 }
976 else
977 {
978 tepl_progress_info_bar_set_fraction (progress_info_bar, 0);
979 }
980 }
981
982 /* Returns whether progress info should be shown. */
983 static gboolean
should_show_progress_info(GTimer ** timer,goffset size,goffset total_size)984 should_show_progress_info (GTimer **timer,
985 goffset size,
986 goffset total_size)
987 {
988 gdouble elapsed_time;
989 gdouble total_time;
990 gdouble remaining_time;
991
992 g_assert (timer != NULL);
993
994 if (*timer == NULL)
995 {
996 return TRUE;
997 }
998
999 elapsed_time = g_timer_elapsed (*timer, NULL);
1000
1001 /* Wait a little, because at the very beginning it's maybe not very
1002 * accurate (it takes initially more time for the first bytes, the
1003 * following chunks should arrive more quickly, as a rough guess).
1004 */
1005 if (elapsed_time < 0.5)
1006 {
1007 return FALSE;
1008 }
1009
1010 /* elapsed_time / total_time = size / total_size */
1011 total_time = (elapsed_time * total_size) / size;
1012
1013 remaining_time = total_time - elapsed_time;
1014
1015 /* Approximately more than 3 seconds remaining. */
1016 if (remaining_time > 3.0)
1017 {
1018 /* Once the progress info bar is shown, it must remain
1019 * shown until the end, so we don't need the timer
1020 * anymore.
1021 */
1022 g_timer_destroy (*timer);
1023 *timer = NULL;
1024
1025 return TRUE;
1026 }
1027
1028 return FALSE;
1029 }
1030
1031 static gboolean
scroll_to_cursor(GeditTab * tab)1032 scroll_to_cursor (GeditTab *tab)
1033 {
1034 GeditView *view;
1035
1036 view = gedit_tab_get_view (tab);
1037 tepl_view_scroll_to_cursor (TEPL_VIEW (view));
1038
1039 tab->idle_scroll = 0;
1040 return G_SOURCE_REMOVE;
1041 }
1042
1043 static void
unrecoverable_saving_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1044 unrecoverable_saving_error_info_bar_response (GtkWidget *info_bar,
1045 gint response_id,
1046 GTask *saving_task)
1047 {
1048 GeditTab *tab = g_task_get_source_object (saving_task);
1049 GeditView *view;
1050
1051 gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
1052
1053 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1054
1055 view = gedit_tab_get_view (tab);
1056 gtk_widget_grab_focus (GTK_WIDGET (view));
1057
1058 g_task_return_boolean (saving_task, FALSE);
1059 g_object_unref (saving_task);
1060 }
1061
1062 /* Sets the save flags after an info bar response. */
1063 static void
response_set_save_flags(GTask * saving_task,GtkSourceFileSaverFlags save_flags)1064 response_set_save_flags (GTask *saving_task,
1065 GtkSourceFileSaverFlags save_flags)
1066 {
1067 GeditTab *tab = g_task_get_source_object (saving_task);
1068 SaverData *data = g_task_get_task_data (saving_task);
1069 gboolean create_backup;
1070
1071 create_backup = g_settings_get_boolean (tab->editor_settings,
1072 GEDIT_SETTINGS_CREATE_BACKUP_COPY);
1073
1074 /* If we are here, it means that the user expressed his or her willing
1075 * to save the file, by pressing a button in the info bar. So even if
1076 * the file saving was initially an auto-save, we set the create_backup
1077 * flag (if the conditions are met).
1078 */
1079 if (create_backup && !data->force_no_backup)
1080 {
1081 save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
1082 }
1083 else
1084 {
1085 save_flags &= ~GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
1086 }
1087
1088 gtk_source_file_saver_set_flags (data->saver, save_flags);
1089 }
1090
1091 static void
invalid_character_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1092 invalid_character_info_bar_response (GtkWidget *info_bar,
1093 gint response_id,
1094 GTask *saving_task)
1095 {
1096 if (response_id == GTK_RESPONSE_YES)
1097 {
1098 GeditTab *tab = g_task_get_source_object (saving_task);
1099 SaverData *data = g_task_get_task_data (saving_task);
1100 GtkSourceFileSaverFlags save_flags;
1101
1102 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1103
1104 /* Don't bug the user again with this... */
1105 tab->save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
1106
1107 save_flags = gtk_source_file_saver_get_flags (data->saver);
1108 save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_INVALID_CHARS;
1109 response_set_save_flags (saving_task, save_flags);
1110
1111 /* Force saving */
1112 launch_saver (saving_task);
1113 }
1114 else
1115 {
1116 unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1117 }
1118 }
1119
1120 static void
cant_create_backup_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1121 cant_create_backup_error_info_bar_response (GtkWidget *info_bar,
1122 gint response_id,
1123 GTask *saving_task)
1124 {
1125 if (response_id == GTK_RESPONSE_YES)
1126 {
1127 GeditTab *tab = g_task_get_source_object (saving_task);
1128 SaverData *data = g_task_get_task_data (saving_task);
1129 GtkSourceFileSaverFlags save_flags;
1130
1131 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1132
1133 data->force_no_backup = TRUE;
1134 save_flags = gtk_source_file_saver_get_flags (data->saver);
1135 response_set_save_flags (saving_task, save_flags);
1136
1137 /* Force saving */
1138 launch_saver (saving_task);
1139 }
1140 else
1141 {
1142 unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1143 }
1144 }
1145
1146 static void
externally_modified_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1147 externally_modified_error_info_bar_response (GtkWidget *info_bar,
1148 gint response_id,
1149 GTask *saving_task)
1150 {
1151 if (response_id == GTK_RESPONSE_YES)
1152 {
1153 GeditTab *tab = g_task_get_source_object (saving_task);
1154 SaverData *data = g_task_get_task_data (saving_task);
1155 GtkSourceFileSaverFlags save_flags;
1156
1157 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1158
1159 /* ignore_modification_time should not be persisted in save
1160 * flags across saves (i.e. tab->save_flags is not modified).
1161 */
1162 save_flags = gtk_source_file_saver_get_flags (data->saver);
1163 save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
1164 response_set_save_flags (saving_task, save_flags);
1165
1166 /* Force saving */
1167 launch_saver (saving_task);
1168 }
1169 else
1170 {
1171 unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1172 }
1173 }
1174
1175 static void
recoverable_saving_error_info_bar_response(GtkWidget * info_bar,gint response_id,GTask * saving_task)1176 recoverable_saving_error_info_bar_response (GtkWidget *info_bar,
1177 gint response_id,
1178 GTask *saving_task)
1179 {
1180 if (response_id == GTK_RESPONSE_OK)
1181 {
1182 GeditTab *tab = g_task_get_source_object (saving_task);
1183 SaverData *data = g_task_get_task_data (saving_task);
1184 const GtkSourceEncoding *encoding;
1185
1186 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1187
1188 encoding = gedit_conversion_error_info_bar_get_encoding (GTK_WIDGET (info_bar));
1189 g_return_if_fail (encoding != NULL);
1190
1191 gtk_source_file_saver_set_encoding (data->saver, encoding);
1192 launch_saver (saving_task);
1193 }
1194 else
1195 {
1196 unrecoverable_saving_error_info_bar_response (info_bar, response_id, saving_task);
1197 }
1198 }
1199
1200 static void
externally_modified_notification_info_bar_response(GtkWidget * info_bar,gint response_id,GeditTab * tab)1201 externally_modified_notification_info_bar_response (GtkWidget *info_bar,
1202 gint response_id,
1203 GeditTab *tab)
1204 {
1205 GeditView *view;
1206
1207 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
1208
1209 view = gedit_tab_get_view (tab);
1210
1211 if (response_id == GTK_RESPONSE_OK)
1212 {
1213 _gedit_tab_revert (tab);
1214 }
1215 else
1216 {
1217 tab->ask_if_externally_modified = FALSE;
1218
1219 /* go back to normal state */
1220 gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
1221 }
1222
1223 gtk_widget_grab_focus (GTK_WIDGET (view));
1224 }
1225
1226 static void
display_externally_modified_notification(GeditTab * tab)1227 display_externally_modified_notification (GeditTab *tab)
1228 {
1229 TeplInfoBar *info_bar;
1230 GeditDocument *doc;
1231 GtkSourceFile *file;
1232 GFile *location;
1233 gboolean document_modified;
1234
1235 doc = gedit_tab_get_document (tab);
1236 file = gedit_document_get_file (doc);
1237
1238 /* we're here because the file we're editing changed on disk */
1239 location = gtk_source_file_get_location (file);
1240 g_return_if_fail (location != NULL);
1241
1242 document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc));
1243 info_bar = tepl_io_error_info_bar_externally_modified (location, document_modified);
1244
1245 set_info_bar (tab, GTK_WIDGET (info_bar), GTK_RESPONSE_OK);
1246
1247 g_signal_connect (info_bar,
1248 "response",
1249 G_CALLBACK (externally_modified_notification_info_bar_response),
1250 tab);
1251 }
1252
1253 static gboolean
view_focused_in(GtkWidget * widget,GdkEventFocus * event,GeditTab * tab)1254 view_focused_in (GtkWidget *widget,
1255 GdkEventFocus *event,
1256 GeditTab *tab)
1257 {
1258 GeditDocument *doc;
1259 GtkSourceFile *file;
1260
1261 g_return_val_if_fail (GEDIT_IS_TAB (tab), GDK_EVENT_PROPAGATE);
1262
1263 /* we try to detect file changes only in the normal state */
1264 if (tab->state != GEDIT_TAB_STATE_NORMAL)
1265 {
1266 return GDK_EVENT_PROPAGATE;
1267 }
1268
1269 /* we already asked, don't bug the user again */
1270 if (!tab->ask_if_externally_modified)
1271 {
1272 return GDK_EVENT_PROPAGATE;
1273 }
1274
1275 doc = gedit_tab_get_document (tab);
1276 file = gedit_document_get_file (doc);
1277
1278 /* If file was never saved or is remote we do not check */
1279 if (gtk_source_file_is_local (file))
1280 {
1281 gtk_source_file_check_file_on_disk (file);
1282
1283 if (gtk_source_file_is_externally_modified (file))
1284 {
1285 gedit_tab_set_state (tab, GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
1286
1287 display_externally_modified_notification (tab);
1288 }
1289 }
1290
1291 return GDK_EVENT_PROPAGATE;
1292 }
1293
1294 static void
on_drop_uris(GeditView * view,gchar ** uri_list,GeditTab * tab)1295 on_drop_uris (GeditView *view,
1296 gchar **uri_list,
1297 GeditTab *tab)
1298 {
1299 g_signal_emit (G_OBJECT (tab), signals[DROP_URIS], 0, uri_list);
1300 }
1301
1302 static void
gedit_tab_init(GeditTab * tab)1303 gedit_tab_init (GeditTab *tab)
1304 {
1305 gboolean auto_save;
1306 gint auto_save_interval;
1307 GeditDocument *doc;
1308 GeditView *view;
1309 GtkSourceFile *file;
1310 TeplFile *tepl_file;
1311
1312 tab->state = GEDIT_TAB_STATE_NORMAL;
1313
1314 tab->editor_settings = g_settings_new ("org.gnome.gedit.preferences.editor");
1315
1316 tab->editable = TRUE;
1317
1318 tab->ask_if_externally_modified = TRUE;
1319
1320 gtk_orientable_set_orientation (GTK_ORIENTABLE (tab),
1321 GTK_ORIENTATION_VERTICAL);
1322
1323 /* Manage auto save data */
1324 auto_save = g_settings_get_boolean (tab->editor_settings,
1325 GEDIT_SETTINGS_AUTO_SAVE);
1326 g_settings_get (tab->editor_settings, GEDIT_SETTINGS_AUTO_SAVE_INTERVAL,
1327 "u", &auto_save_interval);
1328 tab->auto_save = auto_save != FALSE;
1329 tab->auto_save_interval = auto_save_interval;
1330
1331 /* Create the frame */
1332 tab->frame = gedit_view_frame_new ();
1333 gtk_widget_show (GTK_WIDGET (tab->frame));
1334
1335 gtk_box_pack_end (GTK_BOX (tab), GTK_WIDGET (tab->frame), TRUE, TRUE, 0);
1336
1337 doc = gedit_tab_get_document (tab);
1338 g_object_set_data (G_OBJECT (doc), GEDIT_TAB_KEY, tab);
1339
1340 file = gedit_document_get_file (doc);
1341 tepl_file = tepl_buffer_get_file (TEPL_BUFFER (doc));
1342
1343 g_signal_connect_object (file,
1344 "notify::location",
1345 G_CALLBACK (document_location_notify_handler),
1346 tab,
1347 0);
1348
1349 g_signal_connect_object (tepl_file,
1350 "notify::short-name",
1351 G_CALLBACK (document_shortname_notify_handler),
1352 tab,
1353 0);
1354
1355 g_signal_connect (doc,
1356 "modified_changed",
1357 G_CALLBACK (document_modified_changed),
1358 tab);
1359
1360 view = gedit_tab_get_view (tab);
1361
1362 g_signal_connect_after (view,
1363 "focus-in-event",
1364 G_CALLBACK (view_focused_in),
1365 tab);
1366
1367 g_signal_connect_after (view,
1368 "realize",
1369 G_CALLBACK (view_realized),
1370 tab);
1371
1372 g_signal_connect (view,
1373 "drop-uris",
1374 G_CALLBACK (on_drop_uris),
1375 tab);
1376 }
1377
1378 GeditTab *
_gedit_tab_new(void)1379 _gedit_tab_new (void)
1380 {
1381 return g_object_new (GEDIT_TYPE_TAB, NULL);
1382 }
1383
1384 /**
1385 * gedit_tab_get_view:
1386 * @tab: a #GeditTab
1387 *
1388 * Gets the #GeditView inside @tab.
1389 *
1390 * Returns: (transfer none): the #GeditView inside @tab
1391 */
1392 GeditView *
gedit_tab_get_view(GeditTab * tab)1393 gedit_tab_get_view (GeditTab *tab)
1394 {
1395 g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1396
1397 return gedit_view_frame_get_view (tab->frame);
1398 }
1399
1400 /**
1401 * gedit_tab_get_document:
1402 * @tab: a #GeditTab
1403 *
1404 * Gets the #GeditDocument associated to @tab.
1405 *
1406 * Returns: (transfer none): the #GeditDocument associated to @tab
1407 */
1408 GeditDocument *
gedit_tab_get_document(GeditTab * tab)1409 gedit_tab_get_document (GeditTab *tab)
1410 {
1411 GeditView *view;
1412
1413 g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1414
1415 view = gedit_view_frame_get_view (tab->frame);
1416
1417 return GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
1418 }
1419
1420 #define MAX_DOC_NAME_LENGTH 40
1421
1422 gchar *
_gedit_tab_get_name(GeditTab * tab)1423 _gedit_tab_get_name (GeditTab *tab)
1424 {
1425 GeditDocument *doc;
1426 gchar *name;
1427 gchar *docname;
1428 gchar *tab_name;
1429
1430 g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1431
1432 doc = gedit_tab_get_document (tab);
1433
1434 name = gedit_document_get_short_name_for_display (doc);
1435
1436 /* Truncate the name so it doesn't get insanely wide. */
1437 docname = tepl_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
1438
1439 if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
1440 {
1441 tab_name = g_strdup_printf ("*%s", docname);
1442 }
1443 else
1444 {
1445 tab_name = g_strdup (docname);
1446 }
1447
1448 g_free (docname);
1449 g_free (name);
1450
1451 return tab_name;
1452 }
1453
1454 gchar *
_gedit_tab_get_tooltip(GeditTab * tab)1455 _gedit_tab_get_tooltip (GeditTab *tab)
1456 {
1457 GeditDocument *doc;
1458 gchar *tip;
1459 gchar *uri;
1460 gchar *ruri;
1461 gchar *ruri_markup;
1462
1463 g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1464
1465 doc = gedit_tab_get_document (tab);
1466
1467 uri = _gedit_document_get_uri_for_display (doc);
1468 g_return_val_if_fail (uri != NULL, NULL);
1469
1470 ruri = tepl_utils_replace_home_dir_with_tilde (uri);
1471 g_free (uri);
1472
1473 ruri_markup = g_markup_printf_escaped ("<i>%s</i>", ruri);
1474
1475 switch (tab->state)
1476 {
1477 gchar *content_type;
1478 gchar *mime_type;
1479 gchar *content_description;
1480 gchar *content_full_description;
1481 gchar *encoding;
1482 GtkSourceFile *file;
1483 const GtkSourceEncoding *enc;
1484
1485 case GEDIT_TAB_STATE_LOADING_ERROR:
1486 tip = g_strdup_printf (_("Error opening file %s"),
1487 ruri_markup);
1488 break;
1489
1490 case GEDIT_TAB_STATE_REVERTING_ERROR:
1491 tip = g_strdup_printf (_("Error reverting file %s"),
1492 ruri_markup);
1493 break;
1494
1495 case GEDIT_TAB_STATE_SAVING_ERROR:
1496 tip = g_strdup_printf (_("Error saving file %s"),
1497 ruri_markup);
1498 break;
1499 default:
1500 content_type = gedit_document_get_content_type (doc);
1501 mime_type = gedit_document_get_mime_type (doc);
1502 content_description = g_content_type_get_description (content_type);
1503
1504 if (content_description == NULL)
1505 content_full_description = g_strdup (mime_type);
1506 else
1507 content_full_description = g_strdup_printf ("%s (%s)",
1508 content_description, mime_type);
1509
1510 g_free (content_type);
1511 g_free (mime_type);
1512 g_free (content_description);
1513
1514 file = gedit_document_get_file (doc);
1515 enc = gtk_source_file_get_encoding (file);
1516
1517 if (enc == NULL)
1518 {
1519 enc = gtk_source_encoding_get_utf8 ();
1520 }
1521
1522 encoding = gtk_source_encoding_to_string (enc);
1523
1524 tip = g_markup_printf_escaped ("<b>%s</b> %s\n\n"
1525 "<b>%s</b> %s\n"
1526 "<b>%s</b> %s",
1527 _("Name:"), ruri,
1528 _("MIME Type:"), content_full_description,
1529 _("Encoding:"), encoding);
1530
1531 g_free (encoding);
1532 g_free (content_full_description);
1533 break;
1534 }
1535
1536 g_free (ruri);
1537 g_free (ruri_markup);
1538
1539 return tip;
1540 }
1541
1542 GdkPixbuf *
_gedit_tab_get_icon(GeditTab * tab)1543 _gedit_tab_get_icon (GeditTab *tab)
1544 {
1545 const gchar *icon_name;
1546 GdkPixbuf *pixbuf = NULL;
1547
1548 g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
1549
1550 switch (tab->state)
1551 {
1552 case GEDIT_TAB_STATE_PRINTING:
1553 icon_name = "printer-printing-symbolic";
1554 break;
1555
1556 case GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW:
1557 icon_name = "printer-symbolic";
1558 break;
1559
1560 case GEDIT_TAB_STATE_LOADING_ERROR:
1561 case GEDIT_TAB_STATE_REVERTING_ERROR:
1562 case GEDIT_TAB_STATE_SAVING_ERROR:
1563 case GEDIT_TAB_STATE_GENERIC_ERROR:
1564 icon_name = "dialog-error-symbolic";
1565 break;
1566
1567 case GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION:
1568 icon_name = "dialog-warning-symbolic";
1569 break;
1570
1571 default:
1572 icon_name = NULL;
1573 }
1574
1575 if (icon_name != NULL)
1576 {
1577 GdkScreen *screen;
1578 GtkIconTheme *theme;
1579 gint icon_size;
1580
1581 screen = gtk_widget_get_screen (GTK_WIDGET (tab));
1582 theme = gtk_icon_theme_get_for_screen (screen);
1583 g_return_val_if_fail (theme != NULL, NULL);
1584
1585 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_size);
1586
1587 pixbuf = gtk_icon_theme_load_icon (theme, icon_name, icon_size, 0, NULL);
1588 }
1589
1590 return pixbuf;
1591 }
1592
1593 /**
1594 * gedit_tab_get_from_document:
1595 * @doc: a #GeditDocument
1596 *
1597 * Gets the #GeditTab associated with @doc.
1598 *
1599 * Returns: (transfer none): the #GeditTab associated with @doc
1600 */
1601 GeditTab *
gedit_tab_get_from_document(GeditDocument * doc)1602 gedit_tab_get_from_document (GeditDocument *doc)
1603 {
1604 g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
1605
1606 return g_object_get_data (G_OBJECT (doc), GEDIT_TAB_KEY);
1607 }
1608
1609 static void
loader_progress_cb(goffset size,goffset total_size,GTask * loading_task)1610 loader_progress_cb (goffset size,
1611 goffset total_size,
1612 GTask *loading_task)
1613 {
1614 LoaderData *data = g_task_get_task_data (loading_task);
1615
1616 g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_LOADING ||
1617 data->tab->state == GEDIT_TAB_STATE_REVERTING);
1618
1619 if (should_show_progress_info (&data->timer, size, total_size))
1620 {
1621 show_loading_info_bar (loading_task);
1622 info_bar_set_progress (data->tab, size, total_size);
1623 }
1624 }
1625
1626 static void
goto_line(GTask * loading_task)1627 goto_line (GTask *loading_task)
1628 {
1629 LoaderData *data = g_task_get_task_data (loading_task);
1630 GeditDocument *doc = gedit_tab_get_document (data->tab);
1631 GtkTextIter iter;
1632
1633 /* Move the cursor at the requested line if any. */
1634 if (data->line_pos > 0)
1635 {
1636 TeplView *view = TEPL_VIEW (gedit_tab_get_view (data->tab));
1637
1638 tepl_view_goto_line_offset (view,
1639 data->line_pos - 1,
1640 MAX (0, data->column_pos - 1));
1641 return;
1642 }
1643
1644 /* If enabled, move to the position stored in the metadata. */
1645 if (g_settings_get_boolean (data->tab->editor_settings, GEDIT_SETTINGS_RESTORE_CURSOR_POSITION))
1646 {
1647 gchar *pos;
1648 gint offset;
1649
1650 pos = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_POSITION);
1651
1652 offset = pos != NULL ? atoi (pos) : 0;
1653 g_free (pos);
1654
1655 gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc),
1656 &iter,
1657 MAX (0, offset));
1658
1659 /* make sure it's a valid position, if the file
1660 * changed we may have ended up in the middle of
1661 * a utf8 character cluster */
1662 if (!gtk_text_iter_is_cursor_position (&iter))
1663 {
1664 gtk_text_iter_set_line_offset (&iter, 0);
1665 }
1666 }
1667
1668 /* Otherwise to the top. */
1669 else
1670 {
1671 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc), &iter);
1672 }
1673
1674 gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
1675 }
1676
1677 static gboolean
file_already_opened(GeditDocument * doc,GFile * location)1678 file_already_opened (GeditDocument *doc,
1679 GFile *location)
1680 {
1681 GList *all_documents;
1682 GList *l;
1683 gboolean already_opened = FALSE;
1684
1685 if (location == NULL)
1686 {
1687 return FALSE;
1688 }
1689
1690 all_documents = gedit_app_get_documents (GEDIT_APP (g_application_get_default ()));
1691
1692 for (l = all_documents; l != NULL; l = l->next)
1693 {
1694 GeditDocument *cur_doc = l->data;
1695 GtkSourceFile *cur_file;
1696 GFile *cur_location;
1697
1698 if (cur_doc == doc)
1699 {
1700 continue;
1701 }
1702
1703 cur_file = gedit_document_get_file (cur_doc);
1704 cur_location = gtk_source_file_get_location (cur_file);
1705
1706 if (cur_location != NULL &&
1707 g_file_equal (location, cur_location))
1708 {
1709 already_opened = TRUE;
1710 break;
1711 }
1712 }
1713
1714 g_list_free (all_documents);
1715
1716 return already_opened;
1717 }
1718
1719 static void
successful_load(GTask * loading_task)1720 successful_load (GTask *loading_task)
1721 {
1722 LoaderData *data = g_task_get_task_data (loading_task);
1723 GeditDocument *doc = gedit_tab_get_document (data->tab);
1724 GtkSourceFile *file = gedit_document_get_file (doc);
1725 GFile *location;
1726
1727 if (data->user_requested_encoding)
1728 {
1729 const GtkSourceEncoding *encoding = gtk_source_file_loader_get_encoding (data->loader);
1730 const gchar *charset = gtk_source_encoding_get_charset (encoding);
1731
1732 gedit_document_set_metadata (doc,
1733 GEDIT_METADATA_ATTRIBUTE_ENCODING, charset,
1734 NULL);
1735 }
1736
1737 goto_line (loading_task);
1738
1739 /* Scroll to the cursor when the document is loaded, we need to do it in
1740 * an idle as after the document is loaded the textview is still
1741 * redrawing and relocating its internals.
1742 */
1743 if (data->tab->idle_scroll == 0)
1744 {
1745 data->tab->idle_scroll = g_idle_add ((GSourceFunc)scroll_to_cursor, data->tab);
1746 }
1747
1748 location = gtk_source_file_loader_get_location (data->loader);
1749
1750 /* If the document is readonly we don't care how many times the file
1751 * is opened.
1752 */
1753 if (!gtk_source_file_is_readonly (file) &&
1754 file_already_opened (doc, location))
1755 {
1756 TeplInfoBar *info_bar;
1757
1758 set_editable (data->tab, FALSE);
1759
1760 info_bar = tepl_io_error_info_bar_file_already_open (location);
1761
1762 g_signal_connect (info_bar,
1763 "response",
1764 G_CALLBACK (file_already_open_warning_info_bar_response),
1765 data->tab);
1766
1767 set_info_bar (data->tab, GTK_WIDGET (info_bar), GTK_RESPONSE_CANCEL);
1768 }
1769
1770 /* When loading from stdin, the contents may not be saved, so set the
1771 * buffer as modified.
1772 */
1773 if (location == NULL)
1774 {
1775 gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), TRUE);
1776 }
1777
1778 data->tab->ask_if_externally_modified = TRUE;
1779
1780 g_signal_emit_by_name (doc, "loaded");
1781 }
1782
1783 static void
load_cb(GtkSourceFileLoader * loader,GAsyncResult * result,GTask * loading_task)1784 load_cb (GtkSourceFileLoader *loader,
1785 GAsyncResult *result,
1786 GTask *loading_task)
1787 {
1788 LoaderData *data = g_task_get_task_data (loading_task);
1789 GeditDocument *doc;
1790 GFile *location = gtk_source_file_loader_get_location (loader);
1791 gboolean create_named_new_doc;
1792 GError *error = NULL;
1793
1794 g_clear_pointer (&data->timer, g_timer_destroy);
1795
1796 gtk_source_file_loader_load_finish (loader, result, &error);
1797
1798 if (error != NULL)
1799 {
1800 gedit_debug_message (DEBUG_TAB, "File loading error: %s", error->message);
1801
1802 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1803 {
1804 g_task_return_boolean (loading_task, FALSE);
1805 g_object_unref (loading_task);
1806
1807 g_error_free (error);
1808 return;
1809 }
1810 }
1811
1812 doc = gedit_tab_get_document (data->tab);
1813
1814 g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_LOADING ||
1815 data->tab->state == GEDIT_TAB_STATE_REVERTING);
1816
1817 set_info_bar (data->tab, NULL, GTK_RESPONSE_NONE);
1818
1819 /* Special case creating a named new doc. */
1820 create_named_new_doc = (_gedit_document_get_create (doc) &&
1821 g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
1822 g_file_has_uri_scheme (location, "file"));
1823
1824 if (create_named_new_doc)
1825 {
1826 g_error_free (error);
1827 error = NULL;
1828 }
1829
1830 if (g_error_matches (error,
1831 GTK_SOURCE_FILE_LOADER_ERROR,
1832 GTK_SOURCE_FILE_LOADER_ERROR_CONVERSION_FALLBACK))
1833 {
1834 GtkWidget *info_bar;
1835 const GtkSourceEncoding *encoding;
1836
1837 /* Set the tab as not editable as we have an error, the user can
1838 * decide to make it editable again.
1839 */
1840 set_editable (data->tab, FALSE);
1841
1842 encoding = gtk_source_file_loader_get_encoding (loader);
1843
1844 info_bar = gedit_io_loading_error_info_bar_new (location, encoding, error);
1845
1846 g_signal_connect (info_bar,
1847 "response",
1848 G_CALLBACK (io_loading_error_info_bar_response),
1849 loading_task);
1850
1851 set_info_bar (data->tab, info_bar, GTK_RESPONSE_CANCEL);
1852
1853 if (data->tab->state == GEDIT_TAB_STATE_LOADING)
1854 {
1855 gtk_widget_show (GTK_WIDGET (data->tab->frame));
1856 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_LOADING_ERROR);
1857 }
1858 else
1859 {
1860 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_REVERTING_ERROR);
1861 }
1862
1863 /* The loading was successful, despite some invalid characters. */
1864 successful_load (loading_task);
1865 gedit_recent_add_document (doc);
1866
1867 g_error_free (error);
1868 return;
1869 }
1870
1871 if (error != NULL)
1872 {
1873 GtkWidget *info_bar;
1874
1875 if (data->tab->state == GEDIT_TAB_STATE_LOADING)
1876 {
1877 gtk_widget_hide (GTK_WIDGET (data->tab->frame));
1878 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_LOADING_ERROR);
1879 }
1880 else
1881 {
1882 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_REVERTING_ERROR);
1883 }
1884
1885 if (location != NULL)
1886 {
1887 gedit_recent_remove_if_local (location);
1888 }
1889
1890 if (data->tab->state == GEDIT_TAB_STATE_LOADING_ERROR)
1891 {
1892 const GtkSourceEncoding *encoding;
1893
1894 encoding = gtk_source_file_loader_get_encoding (loader);
1895
1896 info_bar = gedit_io_loading_error_info_bar_new (location, encoding, error);
1897
1898 g_signal_connect (info_bar,
1899 "response",
1900 G_CALLBACK (io_loading_error_info_bar_response),
1901 loading_task);
1902 }
1903 else
1904 {
1905 g_return_if_fail (data->tab->state == GEDIT_TAB_STATE_REVERTING_ERROR);
1906
1907 info_bar = gedit_unrecoverable_reverting_error_info_bar_new (location, error);
1908
1909 g_signal_connect (info_bar,
1910 "response",
1911 G_CALLBACK (unrecoverable_reverting_error_info_bar_response),
1912 loading_task);
1913 }
1914
1915 set_info_bar (data->tab, info_bar, GTK_RESPONSE_CANCEL);
1916
1917 g_error_free (error);
1918 return;
1919 }
1920
1921 g_assert (error == NULL);
1922
1923 gedit_tab_set_state (data->tab, GEDIT_TAB_STATE_NORMAL);
1924 successful_load (loading_task);
1925
1926 if (!create_named_new_doc)
1927 {
1928 gedit_recent_add_document (doc);
1929 }
1930
1931 g_task_return_boolean (loading_task, TRUE);
1932 g_object_unref (loading_task);
1933 }
1934
1935 /* The returned list may contain duplicated encodings. Only the first occurrence
1936 * of a duplicated encoding should be kept, like it is done by
1937 * gtk_source_file_loader_set_candidate_encodings().
1938 */
1939 static GSList *
get_candidate_encodings(GeditTab * tab)1940 get_candidate_encodings (GeditTab *tab)
1941 {
1942 GSList *candidates = NULL;
1943 GeditDocument *doc;
1944 GtkSourceFile *file;
1945 gchar *metadata_charset;
1946 const GtkSourceEncoding *file_encoding;
1947
1948 candidates = gedit_settings_get_candidate_encodings (NULL);
1949
1950 /* Prepend the encoding stored in the metadata. */
1951 doc = gedit_tab_get_document (tab);
1952 metadata_charset = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_ENCODING);
1953
1954 if (metadata_charset != NULL)
1955 {
1956 const GtkSourceEncoding *metadata_enc;
1957
1958 metadata_enc = gtk_source_encoding_get_from_charset (metadata_charset);
1959
1960 if (metadata_enc != NULL)
1961 {
1962 candidates = g_slist_prepend (candidates, (gpointer)metadata_enc);
1963 }
1964 }
1965
1966 /* Finally prepend the GtkSourceFile's encoding, if previously set by a
1967 * file loader or file saver.
1968 */
1969 file = gedit_document_get_file (doc);
1970 file_encoding = gtk_source_file_get_encoding (file);
1971
1972 if (file_encoding != NULL)
1973 {
1974 candidates = g_slist_prepend (candidates, (gpointer)file_encoding);
1975 }
1976
1977 g_free (metadata_charset);
1978 return candidates;
1979 }
1980
1981 static void
launch_loader(GTask * loading_task,const GtkSourceEncoding * encoding)1982 launch_loader (GTask *loading_task,
1983 const GtkSourceEncoding *encoding)
1984 {
1985 LoaderData *data = g_task_get_task_data (loading_task);
1986 GSList *candidate_encodings = NULL;
1987 GeditDocument *doc;
1988
1989 if (encoding != NULL)
1990 {
1991 data->user_requested_encoding = TRUE;
1992 candidate_encodings = g_slist_append (NULL, (gpointer) encoding);
1993 }
1994 else
1995 {
1996 data->user_requested_encoding = FALSE;
1997 candidate_encodings = get_candidate_encodings (data->tab);
1998 }
1999
2000 gtk_source_file_loader_set_candidate_encodings (data->loader, candidate_encodings);
2001 g_slist_free (candidate_encodings);
2002
2003 doc = gedit_tab_get_document (data->tab);
2004 g_signal_emit_by_name (doc, "load");
2005
2006 if (data->timer != NULL)
2007 {
2008 g_timer_destroy (data->timer);
2009 }
2010
2011 data->timer = g_timer_new ();
2012
2013 gtk_source_file_loader_load_async (data->loader,
2014 G_PRIORITY_DEFAULT,
2015 g_task_get_cancellable (loading_task),
2016 (GFileProgressCallback) loader_progress_cb,
2017 loading_task,
2018 NULL,
2019 (GAsyncReadyCallback) load_cb,
2020 loading_task);
2021 }
2022
2023 static void
load_async(GeditTab * tab,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2024 load_async (GeditTab *tab,
2025 GFile *location,
2026 const GtkSourceEncoding *encoding,
2027 gint line_pos,
2028 gint column_pos,
2029 gboolean create,
2030 GCancellable *cancellable,
2031 GAsyncReadyCallback callback,
2032 gpointer user_data)
2033 {
2034 GeditDocument *doc;
2035 GtkSourceFile *file;
2036 GTask *loading_task;
2037 LoaderData *data;
2038
2039 g_return_if_fail (GEDIT_IS_TAB (tab));
2040 g_return_if_fail (G_IS_FILE (location));
2041 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2042 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2043
2044 gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
2045
2046 doc = gedit_tab_get_document (tab);
2047 file = gedit_document_get_file (doc);
2048 gtk_source_file_set_location (file, location);
2049
2050 loading_task = g_task_new (NULL, cancellable, callback, user_data);
2051
2052 data = loader_data_new ();
2053 g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
2054
2055 data->tab = tab;
2056 data->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
2057 data->line_pos = line_pos;
2058 data->column_pos = column_pos;
2059
2060 _gedit_document_set_create (doc, create);
2061
2062 launch_loader (loading_task, encoding);
2063 }
2064
2065 static gboolean
load_finish(GeditTab * tab,GAsyncResult * result)2066 load_finish (GeditTab *tab,
2067 GAsyncResult *result)
2068 {
2069 g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
2070
2071 return g_task_propagate_boolean (G_TASK (result), NULL);
2072 }
2073
2074 void
_gedit_tab_load(GeditTab * tab,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,gboolean create)2075 _gedit_tab_load (GeditTab *tab,
2076 GFile *location,
2077 const GtkSourceEncoding *encoding,
2078 gint line_pos,
2079 gint column_pos,
2080 gboolean create)
2081 {
2082 if (tab->cancellable != NULL)
2083 {
2084 g_cancellable_cancel (tab->cancellable);
2085 g_object_unref (tab->cancellable);
2086 }
2087
2088 tab->cancellable = g_cancellable_new ();
2089
2090 load_async (tab,
2091 location,
2092 encoding,
2093 line_pos,
2094 column_pos,
2095 create,
2096 tab->cancellable,
2097 (GAsyncReadyCallback) load_finish,
2098 NULL);
2099 }
2100
2101 static void
load_stream_async(GeditTab * tab,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2102 load_stream_async (GeditTab *tab,
2103 GInputStream *stream,
2104 const GtkSourceEncoding *encoding,
2105 gint line_pos,
2106 gint column_pos,
2107 GCancellable *cancellable,
2108 GAsyncReadyCallback callback,
2109 gpointer user_data)
2110 {
2111 GeditDocument *doc;
2112 GtkSourceFile *file;
2113 GTask *loading_task;
2114 LoaderData *data;
2115
2116 g_return_if_fail (GEDIT_IS_TAB (tab));
2117 g_return_if_fail (G_IS_INPUT_STREAM (stream));
2118 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2119 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2120
2121 gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
2122
2123 doc = gedit_tab_get_document (tab);
2124 file = gedit_document_get_file (doc);
2125
2126 gtk_source_file_set_location (file, NULL);
2127
2128 loading_task = g_task_new (NULL, cancellable, callback, user_data);
2129
2130 data = loader_data_new ();
2131 g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
2132
2133 data->tab = tab;
2134 data->loader = gtk_source_file_loader_new_from_stream (GTK_SOURCE_BUFFER (doc),
2135 file,
2136 stream);
2137 data->line_pos = line_pos;
2138 data->column_pos = column_pos;
2139
2140 _gedit_document_set_create (doc, FALSE);
2141
2142 launch_loader (loading_task, encoding);
2143 }
2144
2145 void
_gedit_tab_load_stream(GeditTab * tab,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gint column_pos)2146 _gedit_tab_load_stream (GeditTab *tab,
2147 GInputStream *stream,
2148 const GtkSourceEncoding *encoding,
2149 gint line_pos,
2150 gint column_pos)
2151 {
2152 if (tab->cancellable != NULL)
2153 {
2154 g_cancellable_cancel (tab->cancellable);
2155 g_object_unref (tab->cancellable);
2156 }
2157
2158 tab->cancellable = g_cancellable_new ();
2159
2160 load_stream_async (tab,
2161 stream,
2162 encoding,
2163 line_pos,
2164 column_pos,
2165 tab->cancellable,
2166 (GAsyncReadyCallback) load_finish,
2167 NULL);
2168 }
2169
2170 static void
revert_async(GeditTab * tab,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2171 revert_async (GeditTab *tab,
2172 GCancellable *cancellable,
2173 GAsyncReadyCallback callback,
2174 gpointer user_data)
2175 {
2176 GeditDocument *doc;
2177 GtkSourceFile *file;
2178 GFile *location;
2179 GTask *loading_task;
2180 LoaderData *data;
2181
2182 g_return_if_fail (GEDIT_IS_TAB (tab));
2183 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2184 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
2185 tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
2186
2187 if (tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2188 {
2189 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2190 }
2191
2192 doc = gedit_tab_get_document (tab);
2193 file = gedit_document_get_file (doc);
2194 location = gtk_source_file_get_location (file);
2195 g_return_if_fail (location != NULL);
2196
2197 gedit_tab_set_state (tab, GEDIT_TAB_STATE_REVERTING);
2198
2199 loading_task = g_task_new (NULL, cancellable, callback, user_data);
2200
2201 data = loader_data_new ();
2202 g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
2203
2204 data->tab = tab;
2205 data->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
2206 data->line_pos = 0;
2207 data->column_pos = 0;
2208
2209 launch_loader (loading_task, NULL);
2210 }
2211
2212 void
_gedit_tab_revert(GeditTab * tab)2213 _gedit_tab_revert (GeditTab *tab)
2214 {
2215 if (tab->cancellable != NULL)
2216 {
2217 g_cancellable_cancel (tab->cancellable);
2218 g_object_unref (tab->cancellable);
2219 }
2220
2221 tab->cancellable = g_cancellable_new ();
2222
2223 revert_async (tab,
2224 tab->cancellable,
2225 (GAsyncReadyCallback) load_finish,
2226 NULL);
2227 }
2228
2229 static void
close_printing(GeditTab * tab)2230 close_printing (GeditTab *tab)
2231 {
2232 if (tab->print_preview != NULL)
2233 {
2234 gtk_widget_destroy (tab->print_preview);
2235 }
2236
2237 g_clear_object (&tab->print_job);
2238 g_clear_object (&tab->print_preview);
2239
2240 /* destroy the info bar */
2241 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2242
2243 gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
2244 }
2245
2246 static void
saver_progress_cb(goffset size,goffset total_size,GTask * saving_task)2247 saver_progress_cb (goffset size,
2248 goffset total_size,
2249 GTask *saving_task)
2250 {
2251 GeditTab *tab = g_task_get_source_object (saving_task);
2252 SaverData *data = g_task_get_task_data (saving_task);
2253
2254 g_return_if_fail (tab->state == GEDIT_TAB_STATE_SAVING);
2255
2256 if (should_show_progress_info (&data->timer, size, total_size))
2257 {
2258 show_saving_info_bar (saving_task);
2259 info_bar_set_progress (tab, size, total_size);
2260 }
2261 }
2262
2263 static void
save_cb(GtkSourceFileSaver * saver,GAsyncResult * result,GTask * saving_task)2264 save_cb (GtkSourceFileSaver *saver,
2265 GAsyncResult *result,
2266 GTask *saving_task)
2267 {
2268 GeditTab *tab = g_task_get_source_object (saving_task);
2269 SaverData *data = g_task_get_task_data (saving_task);
2270 GeditDocument *doc = gedit_tab_get_document (tab);
2271 GFile *location = gtk_source_file_saver_get_location (saver);
2272 GError *error = NULL;
2273
2274 g_return_if_fail (tab->state == GEDIT_TAB_STATE_SAVING);
2275
2276 gtk_source_file_saver_save_finish (saver, result, &error);
2277
2278 if (error != NULL)
2279 {
2280 gedit_debug_message (DEBUG_TAB, "File saving error: %s", error->message);
2281 }
2282
2283 if (data->timer != NULL)
2284 {
2285 g_timer_destroy (data->timer);
2286 data->timer = NULL;
2287 }
2288
2289 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2290
2291 if (error != NULL)
2292 {
2293 GtkWidget *info_bar;
2294
2295 gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING_ERROR);
2296
2297 if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
2298 error->code == GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED)
2299 {
2300 /* This error is recoverable */
2301 info_bar = gedit_externally_modified_saving_error_info_bar_new (location, error);
2302 g_return_if_fail (info_bar != NULL);
2303
2304 g_signal_connect (info_bar,
2305 "response",
2306 G_CALLBACK (externally_modified_error_info_bar_response),
2307 saving_task);
2308 }
2309 else if (error->domain == G_IO_ERROR &&
2310 error->code == G_IO_ERROR_CANT_CREATE_BACKUP)
2311 {
2312 /* This error is recoverable */
2313 info_bar = GTK_WIDGET (tepl_io_error_info_bar_cant_create_backup (location, error));
2314 g_return_if_fail (info_bar != NULL);
2315
2316 g_signal_connect (info_bar,
2317 "response",
2318 G_CALLBACK (cant_create_backup_error_info_bar_response),
2319 saving_task);
2320 }
2321 else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
2322 error->code == GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS)
2323 {
2324 /* If we have any invalid char in the document we must warn the user
2325 * as it can make the document useless if it is saved.
2326 */
2327 info_bar = GTK_WIDGET (tepl_io_error_info_bar_invalid_characters (location));
2328 g_return_if_fail (info_bar != NULL);
2329
2330 g_signal_connect (info_bar,
2331 "response",
2332 G_CALLBACK (invalid_character_info_bar_response),
2333 saving_task);
2334 }
2335 else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR ||
2336 (error->domain == G_IO_ERROR &&
2337 error->code != G_IO_ERROR_INVALID_DATA &&
2338 error->code != G_IO_ERROR_PARTIAL_INPUT))
2339 {
2340 /* These errors are _NOT_ recoverable */
2341 gedit_recent_remove_if_local (location);
2342
2343 info_bar = gedit_unrecoverable_saving_error_info_bar_new (location, error);
2344 g_return_if_fail (info_bar != NULL);
2345
2346 g_signal_connect (info_bar,
2347 "response",
2348 G_CALLBACK (unrecoverable_saving_error_info_bar_response),
2349 saving_task);
2350 }
2351 else
2352 {
2353 const GtkSourceEncoding *encoding;
2354
2355 /* This error is recoverable */
2356 g_return_if_fail (error->domain == G_CONVERT_ERROR ||
2357 error->domain == G_IO_ERROR);
2358
2359 encoding = gtk_source_file_saver_get_encoding (saver);
2360
2361 info_bar = gedit_conversion_error_while_saving_info_bar_new (location, encoding, error);
2362 g_return_if_fail (info_bar != NULL);
2363
2364 g_signal_connect (info_bar,
2365 "response",
2366 G_CALLBACK (recoverable_saving_error_info_bar_response),
2367 saving_task);
2368 }
2369
2370 set_info_bar (tab, info_bar, GTK_RESPONSE_CANCEL);
2371 }
2372 else
2373 {
2374 gedit_recent_add_document (doc);
2375
2376 gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
2377
2378 tab->ask_if_externally_modified = TRUE;
2379
2380 g_signal_emit_by_name (doc, "saved");
2381 g_task_return_boolean (saving_task, TRUE);
2382 g_object_unref (saving_task);
2383 }
2384
2385 if (error != NULL)
2386 {
2387 g_error_free (error);
2388 }
2389 }
2390
2391 static void
launch_saver(GTask * saving_task)2392 launch_saver (GTask *saving_task)
2393 {
2394 GeditTab *tab = g_task_get_source_object (saving_task);
2395 GeditDocument *doc = gedit_tab_get_document (tab);
2396 SaverData *data = g_task_get_task_data (saving_task);
2397
2398 gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
2399
2400 g_signal_emit_by_name (doc, "save");
2401
2402 if (data->timer != NULL)
2403 {
2404 g_timer_destroy (data->timer);
2405 }
2406
2407 data->timer = g_timer_new ();
2408
2409 gtk_source_file_saver_save_async (data->saver,
2410 G_PRIORITY_DEFAULT,
2411 g_task_get_cancellable (saving_task),
2412 (GFileProgressCallback) saver_progress_cb,
2413 saving_task,
2414 NULL,
2415 (GAsyncReadyCallback) save_cb,
2416 saving_task);
2417 }
2418
2419 /* Gets the initial save flags, when launching a new FileSaver. */
2420 static GtkSourceFileSaverFlags
get_initial_save_flags(GeditTab * tab,gboolean auto_save)2421 get_initial_save_flags (GeditTab *tab,
2422 gboolean auto_save)
2423 {
2424 GtkSourceFileSaverFlags save_flags;
2425 gboolean create_backup;
2426
2427 save_flags = tab->save_flags;
2428
2429 create_backup = g_settings_get_boolean (tab->editor_settings,
2430 GEDIT_SETTINGS_CREATE_BACKUP_COPY);
2431
2432 /* In case of autosaving, we need to preserve the backup that was produced
2433 * the last time the user "manually" saved the file. So we don't set the
2434 * CREATE_BACKUP flag for an automatic file saving.
2435 */
2436 if (create_backup && !auto_save)
2437 {
2438 save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_CREATE_BACKUP;
2439 }
2440
2441 return save_flags;
2442 }
2443
2444 void
_gedit_tab_save_async(GeditTab * tab,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2445 _gedit_tab_save_async (GeditTab *tab,
2446 GCancellable *cancellable,
2447 GAsyncReadyCallback callback,
2448 gpointer user_data)
2449 {
2450 GTask *saving_task;
2451 SaverData *data;
2452 GeditDocument *doc;
2453 GtkSourceFile *file;
2454 GtkSourceFileSaverFlags save_flags;
2455
2456 g_return_if_fail (GEDIT_IS_TAB (tab));
2457 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
2458 tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
2459 tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
2460
2461 /* The Save and Save As window actions are insensitive when the print
2462 * preview is shown, but it's still possible to save several documents
2463 * at once (with the Save All action or when quitting gedit). In that
2464 * case, the print preview is simply closed. Handling correctly the
2465 * document saving when the print preview is shown is more complicated
2466 * and error-prone, it doesn't worth the effort. (the print preview
2467 * would need to be updated when the filename changes, dealing with file
2468 * saving errors is also more complicated, etc).
2469 */
2470 if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
2471 {
2472 close_printing (tab);
2473 }
2474
2475 doc = gedit_tab_get_document (tab);
2476 g_return_if_fail (!gedit_document_is_untitled (doc));
2477
2478 saving_task = g_task_new (tab, cancellable, callback, user_data);
2479
2480 data = saver_data_new ();
2481 g_task_set_task_data (saving_task, data, (GDestroyNotify) saver_data_free);
2482
2483 save_flags = get_initial_save_flags (tab, FALSE);
2484
2485 if (tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2486 {
2487 /* We already told the user about the external modification:
2488 * hide the message bar and set the save flag.
2489 */
2490 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2491 save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
2492 }
2493
2494 file = gedit_document_get_file (doc);
2495
2496 data->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
2497
2498 gtk_source_file_saver_set_flags (data->saver, save_flags);
2499
2500 launch_saver (saving_task);
2501 }
2502
2503 gboolean
_gedit_tab_save_finish(GeditTab * tab,GAsyncResult * result)2504 _gedit_tab_save_finish (GeditTab *tab,
2505 GAsyncResult *result)
2506 {
2507 g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
2508
2509 return g_task_propagate_boolean (G_TASK (result), NULL);
2510 }
2511
2512 static void
auto_save_finished_cb(GeditTab * tab,GAsyncResult * result,gpointer user_data)2513 auto_save_finished_cb (GeditTab *tab,
2514 GAsyncResult *result,
2515 gpointer user_data)
2516 {
2517 _gedit_tab_save_finish (tab, result);
2518 }
2519
2520 static gboolean
gedit_tab_auto_save(GeditTab * tab)2521 gedit_tab_auto_save (GeditTab *tab)
2522 {
2523 GTask *saving_task;
2524 SaverData *data;
2525 GeditDocument *doc;
2526 GtkSourceFile *file;
2527 GtkSourceFileSaverFlags save_flags;
2528
2529 gedit_debug (DEBUG_TAB);
2530
2531 doc = gedit_tab_get_document (tab);
2532 file = gedit_document_get_file (doc);
2533
2534 g_return_val_if_fail (!gedit_document_is_untitled (doc), G_SOURCE_REMOVE);
2535 g_return_val_if_fail (!gtk_source_file_is_readonly (file), G_SOURCE_REMOVE);
2536
2537 if (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
2538 {
2539 gedit_debug_message (DEBUG_TAB, "Document not modified");
2540
2541 return G_SOURCE_CONTINUE;
2542 }
2543
2544 if (tab->state != GEDIT_TAB_STATE_NORMAL)
2545 {
2546 gedit_debug_message (DEBUG_TAB, "Retry after 30 seconds");
2547
2548 tab->auto_save_timeout = g_timeout_add_seconds (30,
2549 (GSourceFunc) gedit_tab_auto_save,
2550 tab);
2551
2552 /* Destroy the old timeout. */
2553 return G_SOURCE_REMOVE;
2554 }
2555
2556 /* Set auto_save_timeout to 0 since the timeout is going to be destroyed */
2557 tab->auto_save_timeout = 0;
2558
2559 saving_task = g_task_new (tab,
2560 NULL,
2561 (GAsyncReadyCallback) auto_save_finished_cb,
2562 NULL);
2563
2564 data = saver_data_new ();
2565 g_task_set_task_data (saving_task, data, (GDestroyNotify) saver_data_free);
2566
2567 data->saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (doc), file);
2568
2569 save_flags = get_initial_save_flags (tab, TRUE);
2570 gtk_source_file_saver_set_flags (data->saver, save_flags);
2571
2572 launch_saver (saving_task);
2573
2574 return G_SOURCE_REMOVE;
2575 }
2576
2577 /* Call _gedit_tab_save_finish() in @callback, there is no
2578 * _gedit_tab_save_as_finish().
2579 */
2580 void
_gedit_tab_save_as_async(GeditTab * tab,GFile * location,const GtkSourceEncoding * encoding,GtkSourceNewlineType newline_type,GtkSourceCompressionType compression_type,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2581 _gedit_tab_save_as_async (GeditTab *tab,
2582 GFile *location,
2583 const GtkSourceEncoding *encoding,
2584 GtkSourceNewlineType newline_type,
2585 GtkSourceCompressionType compression_type,
2586 GCancellable *cancellable,
2587 GAsyncReadyCallback callback,
2588 gpointer user_data)
2589 {
2590 GTask *saving_task;
2591 SaverData *data;
2592 GeditDocument *doc;
2593 GtkSourceFile *file;
2594 GtkSourceFileSaverFlags save_flags;
2595
2596 g_return_if_fail (GEDIT_IS_TAB (tab));
2597 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
2598 tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
2599 tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
2600 g_return_if_fail (G_IS_FILE (location));
2601 g_return_if_fail (encoding != NULL);
2602
2603 /* See note at _gedit_tab_save_async(). */
2604 if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
2605 {
2606 close_printing (tab);
2607 }
2608
2609 saving_task = g_task_new (tab, cancellable, callback, user_data);
2610
2611 data = saver_data_new ();
2612 g_task_set_task_data (saving_task, data, (GDestroyNotify) saver_data_free);
2613
2614 doc = gedit_tab_get_document (tab);
2615
2616 /* reset the save flags, when saving as */
2617 tab->save_flags = GTK_SOURCE_FILE_SAVER_FLAGS_NONE;
2618
2619 save_flags = get_initial_save_flags (tab, FALSE);
2620
2621 if (tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2622 {
2623 /* We already told the user about the external modification:
2624 * hide the message bar and set the save flag.
2625 */
2626 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2627 save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
2628 }
2629
2630 file = gedit_document_get_file (doc);
2631
2632 data->saver = gtk_source_file_saver_new_with_target (GTK_SOURCE_BUFFER (doc),
2633 file,
2634 location);
2635
2636 gtk_source_file_saver_set_encoding (data->saver, encoding);
2637 gtk_source_file_saver_set_newline_type (data->saver, newline_type);
2638 gtk_source_file_saver_set_compression_type (data->saver, compression_type);
2639 gtk_source_file_saver_set_flags (data->saver, save_flags);
2640
2641 launch_saver (saving_task);
2642 }
2643
2644 #define GEDIT_PAGE_SETUP_KEY "gedit-page-setup-key"
2645 #define GEDIT_PRINT_SETTINGS_KEY "gedit-print-settings-key"
2646
2647 static GtkPageSetup *
get_page_setup(GeditTab * tab)2648 get_page_setup (GeditTab *tab)
2649 {
2650 gpointer data;
2651 GeditDocument *doc;
2652
2653 doc = gedit_tab_get_document (tab);
2654
2655 data = g_object_get_data (G_OBJECT (doc),
2656 GEDIT_PAGE_SETUP_KEY);
2657
2658 if (data == NULL)
2659 {
2660 return _gedit_app_get_default_page_setup (GEDIT_APP (g_application_get_default ()));
2661 }
2662 else
2663 {
2664 return gtk_page_setup_copy (GTK_PAGE_SETUP (data));
2665 }
2666 }
2667
2668 static GtkPrintSettings *
get_print_settings(GeditTab * tab)2669 get_print_settings (GeditTab *tab)
2670 {
2671 gpointer data;
2672 GeditDocument *doc;
2673 GtkPrintSettings *settings;
2674 gchar *name;
2675
2676 doc = gedit_tab_get_document (tab);
2677
2678 data = g_object_get_data (G_OBJECT (doc),
2679 GEDIT_PRINT_SETTINGS_KEY);
2680
2681 if (data == NULL)
2682 {
2683 settings = _gedit_app_get_default_print_settings (GEDIT_APP (g_application_get_default ()));
2684 }
2685 else
2686 {
2687 settings = gtk_print_settings_copy (GTK_PRINT_SETTINGS (data));
2688 }
2689
2690 /* Be sure the OUTPUT_URI is unset, because otherwise the
2691 * OUTPUT_BASENAME is not taken into account.
2692 */
2693 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, NULL);
2694
2695 name = gedit_document_get_short_name_for_display (doc);
2696 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME, name);
2697
2698 g_free (name);
2699
2700 return settings;
2701 }
2702
2703 /* FIXME: show the info bar only if the operation will be "long" */
2704 static void
printing_cb(GeditPrintJob * job,GeditPrintJobStatus status,GeditTab * tab)2705 printing_cb (GeditPrintJob *job,
2706 GeditPrintJobStatus status,
2707 GeditTab *tab)
2708 {
2709 g_return_if_fail (TEPL_IS_PROGRESS_INFO_BAR (tab->info_bar));
2710
2711 gtk_widget_show (tab->info_bar);
2712
2713 tepl_progress_info_bar_set_text (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
2714 gedit_print_job_get_status_string (job));
2715
2716 tepl_progress_info_bar_set_fraction (TEPL_PROGRESS_INFO_BAR (tab->info_bar),
2717 gedit_print_job_get_progress (job));
2718 }
2719
2720 static void
store_print_settings(GeditTab * tab,GeditPrintJob * job)2721 store_print_settings (GeditTab *tab,
2722 GeditPrintJob *job)
2723 {
2724 GeditDocument *doc;
2725 GtkPrintSettings *settings;
2726 GtkPageSetup *page_setup;
2727
2728 doc = gedit_tab_get_document (tab);
2729
2730 settings = gedit_print_job_get_print_settings (job);
2731
2732 /* clear n-copies settings since we do not want to
2733 * persist that one */
2734 gtk_print_settings_unset (settings,
2735 GTK_PRINT_SETTINGS_N_COPIES);
2736
2737 /* remember settings for this document */
2738 g_object_set_data_full (G_OBJECT (doc),
2739 GEDIT_PRINT_SETTINGS_KEY,
2740 g_object_ref (settings),
2741 (GDestroyNotify)g_object_unref);
2742
2743 /* make them the default */
2744 _gedit_app_set_default_print_settings (GEDIT_APP (g_application_get_default ()),
2745 settings);
2746
2747 page_setup = gedit_print_job_get_page_setup (job);
2748
2749 /* remember page setup for this document */
2750 g_object_set_data_full (G_OBJECT (doc),
2751 GEDIT_PAGE_SETUP_KEY,
2752 g_object_ref (page_setup),
2753 (GDestroyNotify)g_object_unref);
2754
2755 /* make it the default */
2756 _gedit_app_set_default_page_setup (GEDIT_APP (g_application_get_default ()),
2757 page_setup);
2758 }
2759
2760 static void
done_printing_cb(GeditPrintJob * job,GeditPrintJobResult result,GError * error,GeditTab * tab)2761 done_printing_cb (GeditPrintJob *job,
2762 GeditPrintJobResult result,
2763 GError *error,
2764 GeditTab *tab)
2765 {
2766 GeditView *view;
2767
2768 g_return_if_fail (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW ||
2769 tab->state == GEDIT_TAB_STATE_PRINTING);
2770
2771 if (result == GEDIT_PRINT_JOB_RESULT_OK)
2772 {
2773 store_print_settings (tab, job);
2774 }
2775
2776 /* TODO Show the error in an info bar. */
2777 if (error != NULL)
2778 {
2779 g_warning ("Printing error: %s", error->message);
2780 g_error_free (error);
2781 error = NULL;
2782 }
2783
2784 close_printing (tab);
2785
2786 view = gedit_tab_get_view (tab);
2787 gtk_widget_grab_focus (GTK_WIDGET (view));
2788 }
2789
2790 static void
show_preview_cb(GeditPrintJob * job,GeditPrintPreview * preview,GeditTab * tab)2791 show_preview_cb (GeditPrintJob *job,
2792 GeditPrintPreview *preview,
2793 GeditTab *tab)
2794 {
2795 g_return_if_fail (tab->print_preview == NULL);
2796
2797 /* destroy the info bar */
2798 set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
2799
2800 tab->print_preview = GTK_WIDGET (preview);
2801 g_object_ref_sink (tab->print_preview);
2802
2803 gtk_box_pack_end (GTK_BOX (tab), tab->print_preview, TRUE, TRUE, 0);
2804
2805 gtk_widget_show (tab->print_preview);
2806 gtk_widget_grab_focus (tab->print_preview);
2807
2808 gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
2809 }
2810
2811 static void
print_cancelled(GtkWidget * bar,gint response_id,GeditTab * tab)2812 print_cancelled (GtkWidget *bar,
2813 gint response_id,
2814 GeditTab *tab)
2815 {
2816 gedit_debug (DEBUG_TAB);
2817
2818 if (tab->print_job != NULL)
2819 {
2820 gedit_print_job_cancel (tab->print_job);
2821 }
2822 }
2823
2824 static void
add_printing_info_bar(GeditTab * tab)2825 add_printing_info_bar (GeditTab *tab)
2826 {
2827 TeplProgressInfoBar *bar;
2828
2829 bar = tepl_progress_info_bar_new ("document-print", NULL, TRUE);
2830
2831 g_signal_connect (bar,
2832 "response",
2833 G_CALLBACK (print_cancelled),
2834 tab);
2835
2836 set_info_bar (tab, GTK_WIDGET (bar), GTK_RESPONSE_NONE);
2837
2838 /* hide until we start printing */
2839 gtk_widget_hide (GTK_WIDGET (bar));
2840 }
2841
2842 void
_gedit_tab_print(GeditTab * tab)2843 _gedit_tab_print (GeditTab *tab)
2844 {
2845 GeditView *view;
2846 GtkPageSetup *setup;
2847 GtkPrintSettings *settings;
2848 GtkPrintOperationResult res;
2849 GError *error = NULL;
2850
2851 g_return_if_fail (GEDIT_IS_TAB (tab));
2852
2853 /* FIXME: currently we can have just one printoperation going on at a
2854 * given time, so before starting the print we close the preview.
2855 * Would be nice to handle it properly though.
2856 */
2857 if (tab->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)
2858 {
2859 close_printing (tab);
2860 }
2861
2862 g_return_if_fail (tab->print_job == NULL);
2863 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2864
2865 view = gedit_tab_get_view (tab);
2866
2867 tab->print_job = gedit_print_job_new (view);
2868
2869 add_printing_info_bar (tab);
2870
2871 g_signal_connect_object (tab->print_job,
2872 "printing",
2873 G_CALLBACK (printing_cb),
2874 tab,
2875 0);
2876
2877 g_signal_connect_object (tab->print_job,
2878 "show-preview",
2879 G_CALLBACK (show_preview_cb),
2880 tab,
2881 0);
2882
2883 g_signal_connect_object (tab->print_job,
2884 "done",
2885 G_CALLBACK (done_printing_cb),
2886 tab,
2887 0);
2888
2889 gedit_tab_set_state (tab, GEDIT_TAB_STATE_PRINTING);
2890
2891 setup = get_page_setup (tab);
2892 settings = get_print_settings (tab);
2893
2894 res = gedit_print_job_print (tab->print_job,
2895 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
2896 setup,
2897 settings,
2898 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))),
2899 &error);
2900
2901 /* TODO: manage res in the correct way */
2902 if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
2903 {
2904 /* FIXME: go in error state */
2905 g_warning ("Async print preview failed (%s)", error->message);
2906 g_error_free (error);
2907
2908 close_printing (tab);
2909 }
2910
2911 g_object_unref (setup);
2912 g_object_unref (settings);
2913 }
2914
2915 void
_gedit_tab_mark_for_closing(GeditTab * tab)2916 _gedit_tab_mark_for_closing (GeditTab *tab)
2917 {
2918 g_return_if_fail (GEDIT_IS_TAB (tab));
2919 g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
2920
2921 gedit_tab_set_state (tab, GEDIT_TAB_STATE_CLOSING);
2922 }
2923
2924 gboolean
_gedit_tab_get_can_close(GeditTab * tab)2925 _gedit_tab_get_can_close (GeditTab *tab)
2926 {
2927 GeditDocument *doc;
2928
2929 g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE);
2930
2931 /* if we are loading or reverting, the tab can be closed */
2932 if (tab->state == GEDIT_TAB_STATE_LOADING ||
2933 tab->state == GEDIT_TAB_STATE_LOADING_ERROR ||
2934 tab->state == GEDIT_TAB_STATE_REVERTING ||
2935 tab->state == GEDIT_TAB_STATE_REVERTING_ERROR) /* CHECK: I'm not sure this is the right behavior for REVERTING ERROR */
2936 {
2937 return TRUE;
2938 }
2939
2940 /* Do not close tab with saving errors */
2941 if (tab->state == GEDIT_TAB_STATE_SAVING_ERROR)
2942 {
2943 return FALSE;
2944 }
2945
2946 doc = gedit_tab_get_document (tab);
2947
2948 if (_gedit_document_needs_saving (doc))
2949 {
2950 return FALSE;
2951 }
2952
2953 return TRUE;
2954 }
2955
2956 /**
2957 * gedit_tab_get_auto_save_enabled:
2958 * @tab: a #GeditTab
2959 *
2960 * Gets the current state for the autosave feature
2961 *
2962 * Return value: %TRUE if the autosave is enabled, else %FALSE
2963 **/
2964 gboolean
gedit_tab_get_auto_save_enabled(GeditTab * tab)2965 gedit_tab_get_auto_save_enabled (GeditTab *tab)
2966 {
2967 gedit_debug (DEBUG_TAB);
2968
2969 g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE);
2970
2971 return tab->auto_save;
2972 }
2973
2974 /**
2975 * gedit_tab_set_auto_save_enabled:
2976 * @tab: a #GeditTab
2977 * @enable: enable (%TRUE) or disable (%FALSE) auto save
2978 *
2979 * Enables or disables the autosave feature. It does not install an
2980 * autosave timeout if the document is new or is read-only
2981 **/
2982 void
gedit_tab_set_auto_save_enabled(GeditTab * tab,gboolean enable)2983 gedit_tab_set_auto_save_enabled (GeditTab *tab,
2984 gboolean enable)
2985 {
2986 gedit_debug (DEBUG_TAB);
2987
2988 g_return_if_fail (GEDIT_IS_TAB (tab));
2989
2990 enable = enable != FALSE;
2991
2992 if (tab->auto_save != enable)
2993 {
2994 tab->auto_save = enable;
2995 update_auto_save_timeout (tab);
2996 return;
2997 }
2998 }
2999
3000 /**
3001 * gedit_tab_get_auto_save_interval:
3002 * @tab: a #GeditTab
3003 *
3004 * Gets the current interval for the autosaves
3005 *
3006 * Return value: the value of the autosave
3007 **/
3008 gint
gedit_tab_get_auto_save_interval(GeditTab * tab)3009 gedit_tab_get_auto_save_interval (GeditTab *tab)
3010 {
3011 gedit_debug (DEBUG_TAB);
3012
3013 g_return_val_if_fail (GEDIT_IS_TAB (tab), 0);
3014
3015 return tab->auto_save_interval;
3016 }
3017
3018 /**
3019 * gedit_tab_set_auto_save_interval:
3020 * @tab: a #GeditTab
3021 * @interval: the new interval
3022 *
3023 * Sets the interval for the autosave feature.
3024 */
3025 void
gedit_tab_set_auto_save_interval(GeditTab * tab,gint interval)3026 gedit_tab_set_auto_save_interval (GeditTab *tab,
3027 gint interval)
3028 {
3029 g_return_if_fail (GEDIT_IS_TAB (tab));
3030 g_return_if_fail (interval > 0);
3031
3032 gedit_debug (DEBUG_TAB);
3033
3034 if (tab->auto_save_interval != interval)
3035 {
3036 tab->auto_save_interval = interval;
3037 remove_auto_save_timeout (tab);
3038 update_auto_save_timeout (tab);
3039 }
3040 }
3041
3042 void
gedit_tab_set_info_bar(GeditTab * tab,GtkWidget * info_bar)3043 gedit_tab_set_info_bar (GeditTab *tab,
3044 GtkWidget *info_bar)
3045 {
3046 g_return_if_fail (GEDIT_IS_TAB (tab));
3047 g_return_if_fail (info_bar == NULL || GTK_IS_WIDGET (info_bar));
3048
3049 /* FIXME: this can cause problems with the tab state machine */
3050 set_info_bar (tab, info_bar, GTK_RESPONSE_NONE);
3051 }
3052
3053 GeditViewFrame *
_gedit_tab_get_view_frame(GeditTab * tab)3054 _gedit_tab_get_view_frame (GeditTab *tab)
3055 {
3056 return tab->frame;
3057 }
3058
3059 /* ex:set ts=8 noet: */
3060