1 #include <config.h>
2 #include <time.h>
3 #include <sys/types.h>
4 #include <string.h>
5 #include <glib/gi18n.h>
6 #include <gtk/gtk.h>
7 #include <libpeas/peas-extension-set.h>
8
9 #include "xed-ui.h"
10 #include "xed-window.h"
11 #include "xed-window-private.h"
12 #include "xed-app.h"
13 #include "xed-notebook.h"
14 #include "xed-statusbar.h"
15 #include "xed-searchbar.h"
16 #include "xed-view-frame.h"
17 #include "xed-utils.h"
18 #include "xed-commands.h"
19 #include "xed-debug.h"
20 #include "xed-document.h"
21 #include "xed-document-private.h"
22 #include "xed-panel.h"
23 #include "xed-documents-panel.h"
24 #include "xed-plugins-engine.h"
25 #include "xed-window-activatable.h"
26 #include "xed-enum-types.h"
27 #include "xed-dirs.h"
28 #include "xed-status-menu-button.h"
29 #include "xed-highlight-mode-selector.h"
30 #include "xed-settings.h"
31
32 #define LANGUAGE_NONE (const gchar *)"LangNone"
33 #define TAB_WIDTH_DATA "XedWindowTabWidthData"
34 #define LANGUAGE_DATA "XedWindowLanguageData"
35
36 #define XED_WINDOW_DEFAULT_WIDTH 650
37 #define XED_WINDOW_DEFAULT_HEIGHT 500
38
39 /* Signals */
40 enum
41 {
42 TAB_ADDED,
43 TAB_REMOVED,
44 TABS_REORDERED,
45 ACTIVE_TAB_CHANGED,
46 ACTIVE_TAB_STATE_CHANGED,
47 LAST_SIGNAL
48 };
49
50 static guint signals[LAST_SIGNAL] = { 0 };
51
52 enum
53 {
54 PROP_0,
55 PROP_STATE
56 };
57
58 enum
59 {
60 TARGET_URI_LIST = 100
61 };
62
63 G_DEFINE_TYPE_WITH_PRIVATE (XedWindow, xed_window, GTK_TYPE_APPLICATION_WINDOW)
64
65 static void recent_manager_changed (GtkRecentManager *manager, XedWindow *window);
66
67 static void
xed_window_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)68 xed_window_get_property (GObject *object,
69 guint prop_id,
70 GValue *value,
71 GParamSpec *pspec)
72 {
73 XedWindow *window = XED_WINDOW(object);
74
75 switch (prop_id)
76 {
77 case PROP_STATE:
78 g_value_set_enum (value, xed_window_get_state (window));
79 break;
80 default:
81 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
82 break;
83 }
84 }
85
86 static void
save_panes_state(XedWindow * window)87 save_panes_state (XedWindow *window)
88 {
89 gint panel_page;
90
91 xed_debug (DEBUG_WINDOW);
92
93 if (window->priv->side_panel_size > 0)
94 {
95 g_settings_set_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_SIZE, window->priv->side_panel_size);
96 }
97
98 panel_page = _xed_panel_get_active_item_id (XED_PANEL (window->priv->side_panel));
99 if (panel_page != 0)
100 {
101 g_settings_set_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_ACTIVE_PAGE, panel_page);
102 }
103
104 if (window->priv->bottom_panel_size > 0)
105 {
106 g_settings_set_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_SIZE, window->priv->bottom_panel_size);
107 }
108
109 panel_page = _xed_panel_get_active_item_id (XED_PANEL(window->priv->bottom_panel));
110 if (panel_page != 0)
111 {
112 g_settings_set_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE, panel_page);
113 }
114
115 g_settings_apply (window->priv->window_settings);
116 }
117
118 static gboolean
on_key_pressed(GtkWidget * widget,GdkEventKey * event,XedWindow * window)119 on_key_pressed (GtkWidget *widget,
120 GdkEventKey *event,
121 XedWindow *window)
122 {
123 if (event->state & GDK_CONTROL_MASK &&
124 (event->keyval == GDK_KEY_KP_Tab ||
125 event->keyval == GDK_KEY_Tab ||
126 event->keyval == GDK_KEY_ISO_Left_Tab)) {
127 int current_page = gtk_notebook_get_current_page (window->priv->notebook);
128 int num_pages = gtk_notebook_get_n_pages (window->priv->notebook);
129 if (event->state & GDK_SHIFT_MASK)
130 gtk_notebook_set_current_page (window->priv->notebook, (current_page - 1) % num_pages);
131 else
132 gtk_notebook_set_current_page (window->priv->notebook, (current_page + 1) % num_pages);
133 return GDK_EVENT_STOP;
134 }
135 else if (event->keyval == GDK_KEY_Escape)
136 {
137 XedTab *tab;
138 XedViewFrame *frame;
139
140 tab = xed_window_get_active_tab (window);
141
142 if (tab != NULL)
143 {
144 frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab));
145
146 if (xed_view_frame_get_search_popup_visible (frame))
147 {
148 return GDK_EVENT_PROPAGATE;
149 }
150 }
151
152 xed_searchbar_hide (XED_SEARCHBAR (window->priv->searchbar));
153 return GDK_EVENT_STOP;
154 }
155 else if (event->keyval == GDK_KEY_Alt_L)
156 {
157 if (gtk_widget_is_visible (window->priv->menubar)) {
158 if (!g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_MENUBAR_VISIBLE)) {
159 gtk_widget_hide (window->priv->menubar);
160 }
161 }
162 else {
163 if (!_xed_window_is_fullscreen (window)) {
164 gtk_widget_show (window->priv->menubar);
165 }
166 }
167
168 return GDK_EVENT_STOP;
169 }
170
171 return GDK_EVENT_PROPAGATE;
172 }
173
174 static void
save_window_state(GtkWidget * widget)175 save_window_state (GtkWidget *widget)
176 {
177 XedWindow *window = XED_WINDOW (widget);
178
179 if ((window->priv->window_state &
180 (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
181 {
182 GtkAllocation allocation;
183
184 gtk_widget_get_allocation (widget, &allocation);
185
186 window->priv->width = allocation.width;
187 window->priv->height = allocation.height;
188
189 g_settings_set (window->priv->window_settings, XED_SETTINGS_WINDOW_SIZE,
190 "(ii)", window->priv->width, window->priv->height);
191 }
192 }
193
194 static void
xed_window_dispose(GObject * object)195 xed_window_dispose (GObject *object)
196 {
197 XedWindow *window;
198
199 xed_debug (DEBUG_WINDOW);
200
201 window = XED_WINDOW (object);
202
203 /* Stop tracking removal of panes otherwise we always
204 * end up with thinking we had no pane active, since they
205 * should all be removed below */
206 if (window->priv->bottom_panel_item_removed_handler_id != 0)
207 {
208 g_signal_handler_disconnect (window->priv->bottom_panel, window->priv->bottom_panel_item_removed_handler_id);
209 window->priv->bottom_panel_item_removed_handler_id = 0;
210 }
211
212 /* First of all, force collection so that plugins
213 * really drop some of the references.
214 */
215 peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default()));
216
217 /* save the panes position and make sure to deactivate plugins
218 * for this window, but only once */
219 if (!window->priv->dispose_has_run)
220 {
221 save_window_state (GTK_WIDGET (window));
222 save_panes_state (window);
223
224 /* Note that unreffing the extension will automatically remove
225 all extensions which in turn will deactivate the extension */
226 g_object_unref (window->priv->extensions);
227
228 peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default ()));
229
230 window->priv->dispose_has_run = TRUE;
231 }
232
233 if (window->priv->recents_handler_id != 0)
234 {
235 GtkRecentManager *recent_manager;
236 recent_manager = gtk_recent_manager_get_default ();
237 g_signal_handler_disconnect (recent_manager, window->priv->recents_handler_id);
238 window->priv->recents_handler_id = 0;
239 }
240
241 if (window->priv->favorites_handler_id != 0)
242 {
243 XAppFavorites *favorites;
244 favorites = xapp_favorites_get_default ();
245 g_signal_handler_disconnect (favorites, window->priv->favorites_handler_id);
246 window->priv->favorites_handler_id = 0;
247 }
248
249 g_clear_object (&window->priv->manager);
250 g_clear_object (&window->priv->message_bus);
251 g_clear_object (&window->priv->window_group);
252 g_clear_object (&window->priv->default_location);
253
254 /* We must free the settings after saving the panels */
255 g_clear_object (&window->priv->editor_settings);
256 g_clear_object (&window->priv->ui_settings);
257 g_clear_object (&window->priv->window_settings);
258
259 /* Now that there have broken some reference loops, force collection again. */
260 peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default ()));
261
262 G_OBJECT_CLASS (xed_window_parent_class)->dispose (object);
263 }
264
265 static void
xed_window_finalize(GObject * object)266 xed_window_finalize (GObject *object)
267 {
268 xed_debug (DEBUG_WINDOW);
269
270 G_OBJECT_CLASS (xed_window_parent_class)->finalize (object);
271 }
272
273 static gboolean
xed_window_window_state_event(GtkWidget * widget,GdkEventWindowState * event)274 xed_window_window_state_event (GtkWidget *widget,
275 GdkEventWindowState *event)
276 {
277 XedWindow *window = XED_WINDOW (widget);
278
279 window->priv->window_state = event->new_window_state;
280 g_settings_set_int (window->priv->window_settings, XED_SETTINGS_WINDOW_STATE, window->priv->window_state);
281
282 return FALSE;
283 }
284
285 static gboolean
xed_window_configure_event(GtkWidget * widget,GdkEventConfigure * event)286 xed_window_configure_event (GtkWidget *widget,
287 GdkEventConfigure *event)
288 {
289 XedWindow *window = XED_WINDOW (widget);
290
291 if (gtk_widget_get_realized (widget) &&
292 (window->priv->window_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
293 {
294 save_window_state (widget);
295 }
296
297 return GTK_WIDGET_CLASS (xed_window_parent_class)->configure_event (widget, event);
298 }
299
300 /*
301 * GtkWindow catches keybindings for the menu items _before_ passing them to
302 * the focused widget. This is unfortunate and means that pressing ctrl+V
303 * in an entry on a panel ends up pasting text in the TextView.
304 * Here we override GtkWindow's handler to do the same things that it
305 * does, but in the opposite order and then we chain up to the grand
306 * parent handler, skipping gtk_window_key_press_event.
307 */
308 static gboolean
xed_window_key_press_event(GtkWidget * widget,GdkEventKey * event)309 xed_window_key_press_event (GtkWidget *widget,
310 GdkEventKey *event)
311 {
312 static gpointer grand_parent_class = NULL;
313 GtkWindow *window = GTK_WINDOW(widget);
314 gboolean handled = FALSE;
315
316 if (grand_parent_class == NULL)
317 {
318 grand_parent_class = g_type_class_peek_parent (xed_window_parent_class);
319 }
320
321 /* handle focus widget key events */
322 if (!handled)
323 {
324 handled = gtk_window_propagate_key_event (window, event);
325 }
326
327 /* handle mnemonics and accelerators */
328 if (!handled)
329 {
330 handled = gtk_window_activate_key (window, event);
331 }
332
333 /* Chain up, invokes binding set */
334 if (!handled)
335 {
336 handled = GTK_WIDGET_CLASS (grand_parent_class)->key_press_event (widget, event);
337 }
338
339 return handled;
340 }
341
342 static void
xed_window_tab_removed(XedWindow * window,XedTab * tab)343 xed_window_tab_removed (XedWindow *window,
344 XedTab *tab)
345 {
346 peas_engine_garbage_collect (PEAS_ENGINE (xed_plugins_engine_get_default ()));
347 }
348
349 static void
xed_window_class_init(XedWindowClass * klass)350 xed_window_class_init (XedWindowClass *klass)
351 {
352 GObjectClass *object_class = G_OBJECT_CLASS(klass);
353 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
354
355 klass->tab_removed = xed_window_tab_removed;
356
357 object_class->dispose = xed_window_dispose;
358 object_class->finalize = xed_window_finalize;
359 object_class->get_property = xed_window_get_property;
360
361 widget_class->window_state_event = xed_window_window_state_event;
362 widget_class->configure_event = xed_window_configure_event;
363 widget_class->key_press_event = xed_window_key_press_event;
364
365 signals[TAB_ADDED] = g_signal_new ("tab_added", G_OBJECT_CLASS_TYPE(object_class),
366 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, tab_added),
367 NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, XED_TYPE_TAB);
368
369 signals[TAB_REMOVED] = g_signal_new ("tab_removed", G_OBJECT_CLASS_TYPE(object_class),
370 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, tab_removed),
371 NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, XED_TYPE_TAB);
372
373 signals[TABS_REORDERED] = g_signal_new ("tabs_reordered", G_OBJECT_CLASS_TYPE(object_class),
374 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, tabs_reordered),
375 NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
376
377 signals[ACTIVE_TAB_CHANGED] = g_signal_new ("active_tab_changed", G_OBJECT_CLASS_TYPE(object_class),
378 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, active_tab_changed),
379 NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, XED_TYPE_TAB);
380
381 signals[ACTIVE_TAB_STATE_CHANGED] = g_signal_new ("active_tab_state_changed", G_OBJECT_CLASS_TYPE(object_class),
382 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(XedWindowClass, active_tab_state_changed),
383 NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
384
385 g_object_class_install_property (object_class, PROP_STATE, g_param_spec_flags ("state",
386 "State",
387 "The window's state",
388 XED_TYPE_WINDOW_STATE,
389 XED_WINDOW_STATE_NORMAL,
390 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
391 }
392
393 static void
menu_item_select_cb(GtkMenuItem * proxy,XedWindow * window)394 menu_item_select_cb (GtkMenuItem *proxy,
395 XedWindow *window)
396 {
397 GtkAction *action;
398 char *message;
399
400 action = gtk_activatable_get_related_action (GTK_ACTIVATABLE(proxy));
401 g_return_if_fail(action != NULL);
402
403 g_object_get (G_OBJECT(action), "tooltip", &message, NULL);
404 if (message)
405 {
406 gtk_statusbar_push (GTK_STATUSBAR(window->priv->statusbar), window->priv->tip_message_cid, message);
407 g_free (message);
408 }
409 }
410
411 static void
menu_item_deselect_cb(GtkMenuItem * proxy,XedWindow * window)412 menu_item_deselect_cb (GtkMenuItem *proxy,
413 XedWindow *window)
414 {
415 gtk_statusbar_pop (GTK_STATUSBAR(window->priv->statusbar), window->priv->tip_message_cid);
416 }
417
418 static void
connect_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,XedWindow * window)419 connect_proxy_cb (GtkUIManager *manager,
420 GtkAction *action,
421 GtkWidget *proxy,
422 XedWindow *window)
423 {
424 if (GTK_IS_MENU_ITEM(proxy))
425 {
426 g_signal_connect(proxy, "select", G_CALLBACK (menu_item_select_cb), window);
427 g_signal_connect(proxy, "deselect", G_CALLBACK (menu_item_deselect_cb), window);
428 }
429 }
430
431 static void
disconnect_proxy_cb(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy,XedWindow * window)432 disconnect_proxy_cb (GtkUIManager *manager,
433 GtkAction *action,
434 GtkWidget *proxy,
435 XedWindow *window)
436 {
437 if (GTK_IS_MENU_ITEM(proxy))
438 {
439 g_signal_handlers_disconnect_by_func(proxy, G_CALLBACK (menu_item_select_cb), window);
440 g_signal_handlers_disconnect_by_func(proxy, G_CALLBACK (menu_item_deselect_cb), window);
441 }
442 }
443
444 /* Returns TRUE if toolbar is visible */
445 static gboolean
set_toolbar_style(XedWindow * window,XedWindow * origin)446 set_toolbar_style (XedWindow *window,
447 XedWindow *origin)
448 {
449 gboolean visible;
450 GtkAction *action;
451
452 if (origin == NULL)
453 {
454 visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_TOOLBAR_VISIBLE);
455 }
456 else
457 {
458 visible = gtk_widget_get_visible (origin->priv->toolbar);
459 }
460
461 /* Set visibility */
462 if (visible)
463 {
464 gtk_widget_show (window->priv->toolbar);
465 }
466 else
467 {
468 gtk_widget_hide (window->priv->toolbar);
469 }
470
471 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewToolbar");
472
473 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) != visible)
474 {
475 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
476 }
477
478 return visible;
479 }
480
481 /* Returns TRUE if menu bar is visible */
482 static gboolean
set_menubar_style(XedWindow * window,XedWindow * origin)483 set_menubar_style (XedWindow *window,
484 XedWindow *origin)
485 {
486 GtkAction *action;
487 gboolean visible;
488
489 if (origin == NULL)
490 {
491 visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_MENUBAR_VISIBLE);
492 }
493 else
494 {
495 visible = gtk_widget_get_visible (origin->priv->menubar);
496 }
497
498 if (visible)
499 {
500 gtk_widget_show (window->priv->menubar);
501 }
502 else
503 {
504 gtk_widget_hide (window->priv->menubar);
505 }
506
507 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewMenubar");
508
509 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
510 {
511 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
512 }
513
514 return visible;
515 }
516
517 static void
update_next_prev_doc_sensitivity(XedWindow * window,XedTab * tab)518 update_next_prev_doc_sensitivity (XedWindow *window,
519 XedTab *tab)
520 {
521 gint tab_number;
522 GtkNotebook *notebook;
523 GtkAction *action;
524
525 xed_debug (DEBUG_WINDOW);
526
527 notebook = GTK_NOTEBOOK(_xed_window_get_notebook (window));
528
529 tab_number = gtk_notebook_page_num (notebook, GTK_WIDGET(tab));
530 g_return_if_fail(tab_number >= 0);
531
532 action = gtk_action_group_get_action (window->priv->action_group, "DocumentsPreviousDocument");
533 gtk_action_set_sensitive (action, tab_number != 0);
534
535 action = gtk_action_group_get_action (window->priv->action_group, "DocumentsNextDocument");
536 gtk_action_set_sensitive (action, tab_number < gtk_notebook_get_n_pages (notebook) - 1);
537 }
538
539 static void
update_next_prev_doc_sensitivity_per_window(XedWindow * window)540 update_next_prev_doc_sensitivity_per_window (XedWindow *window)
541 {
542 XedTab *tab;
543 GtkAction *action;
544
545 xed_debug (DEBUG_WINDOW);
546
547 tab = xed_window_get_active_tab (window);
548 if (tab != NULL)
549 {
550 update_next_prev_doc_sensitivity (window, tab);
551 return;
552 }
553
554 action = gtk_action_group_get_action (window->priv->action_group, "DocumentsPreviousDocument");
555 gtk_action_set_sensitive (action, FALSE);
556
557 action = gtk_action_group_get_action (window->priv->action_group, "DocumentsNextDocument");
558 gtk_action_set_sensitive (action, FALSE);
559
560 }
561
562 static void
received_clipboard_contents(GtkClipboard * clipboard,GtkSelectionData * selection_data,XedWindow * window)563 received_clipboard_contents (GtkClipboard *clipboard,
564 GtkSelectionData *selection_data,
565 XedWindow *window)
566 {
567 gboolean sensitive;
568 GtkAction *action;
569
570 /* getting clipboard contents is async, so we need to
571 * get the current tab and its state */
572
573 if (window->priv->active_tab != NULL)
574 {
575 XedTabState state;
576 gboolean state_normal;
577
578 state = xed_tab_get_state (window->priv->active_tab);
579 state_normal = (state == XED_TAB_STATE_NORMAL);
580 sensitive = state_normal && gtk_selection_data_targets_include_text (selection_data);
581 }
582 else
583 {
584 sensitive = FALSE;
585 }
586
587 action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
588
589 if (action != NULL)
590 {
591 gtk_action_set_sensitive (action, sensitive);
592 }
593
594 g_object_unref (window);
595 }
596
597 static void
set_paste_sensitivity_according_to_clipboard(XedWindow * window,GtkClipboard * clipboard)598 set_paste_sensitivity_according_to_clipboard (XedWindow *window,
599 GtkClipboard *clipboard)
600 {
601 GdkDisplay *display;
602
603 display = gtk_clipboard_get_display (clipboard);
604 if (gdk_display_supports_selection_notification (display))
605 {
606 gtk_clipboard_request_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"),
607 (GtkClipboardReceivedFunc) received_clipboard_contents, g_object_ref (window));
608 }
609 else
610 {
611 GtkAction *action;
612 action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
613
614 /* XFIXES extension not available, make
615 * Paste always sensitive */
616 gtk_action_set_sensitive (action, TRUE);
617 }
618 }
619
620 static void
set_sensitivity_according_to_tab(XedWindow * window,XedTab * tab)621 set_sensitivity_according_to_tab (XedWindow *window,
622 XedTab *tab)
623 {
624 XedDocument *doc;
625 XedView *view;
626 GtkAction *action;
627 gboolean b;
628 gboolean state_normal;
629 gboolean editable;
630 XedTabState state;
631 GtkClipboard *clipboard;
632 gboolean enable_syntax_hl;
633
634 g_return_if_fail (XED_TAB (tab));
635
636 xed_debug (DEBUG_WINDOW);
637
638 enable_syntax_hl = g_settings_get_boolean (window->priv->editor_settings, XED_SETTINGS_SYNTAX_HIGHLIGHTING);
639
640 state = xed_tab_get_state (tab);
641 state_normal = (state == XED_TAB_STATE_NORMAL);
642
643 view = xed_tab_get_view (tab);
644 editable = gtk_text_view_get_editable (GTK_TEXT_VIEW(view));
645
646 doc = XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
647
648 clipboard = gtk_widget_get_clipboard (GTK_WIDGET(window),
649 GDK_SELECTION_CLIPBOARD);
650
651 action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
652 gtk_action_set_sensitive (
653 action,
654 (state_normal || (state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
655 || (state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW))
656 && !xed_document_get_readonly (doc));
657
658 action = gtk_action_group_get_action (window->priv->action_group, "FileSaveAs");
659 gtk_action_set_sensitive (
660 action,
661 (state_normal || (state == XED_TAB_STATE_SAVING_ERROR)
662 || (state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
663 || (state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW)));
664
665 action = gtk_action_group_get_action (window->priv->action_group, "FileRevert");
666 gtk_action_set_sensitive (
667 action,
668 (state_normal || (state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION))
669 && !xed_document_is_untitled (doc));
670
671 action = gtk_action_group_get_action (window->priv->action_group, "FilePrintPreview");
672 gtk_action_set_sensitive (action, state_normal);
673
674 action = gtk_action_group_get_action (window->priv->action_group, "FilePrint");
675 gtk_action_set_sensitive (action, (state_normal || (state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW)));
676
677 action = gtk_action_group_get_action (window->priv->close_action_group, "FileClose");
678
679 gtk_action_set_sensitive (
680 action,
681 (state != XED_TAB_STATE_CLOSING) && (state != XED_TAB_STATE_SAVING)
682 && (state != XED_TAB_STATE_SHOWING_PRINT_PREVIEW)
683 && (state != XED_TAB_STATE_PRINTING) && (state != XED_TAB_STATE_PRINT_PREVIEWING)
684 && (state != XED_TAB_STATE_SAVING_ERROR));
685
686 action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
687 gtk_action_set_sensitive (action, state_normal && gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER(doc)));
688
689 action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
690 gtk_action_set_sensitive (action, state_normal && gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER(doc)));
691
692 action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
693 gtk_action_set_sensitive (action,
694 state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
695
696 action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
697 gtk_action_set_sensitive (action,
698 (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
699 && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
700
701 action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
702 if (state_normal && editable)
703 {
704 set_paste_sensitivity_according_to_clipboard (window, clipboard);
705 }
706 else
707 {
708 gtk_action_set_sensitive (action, FALSE);
709 }
710
711 action = gtk_action_group_get_action (window->priv->action_group, "EditDelete");
712 gtk_action_set_sensitive (action,
713 state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
714
715 action = gtk_action_group_get_action (window->priv->action_group, "SearchFind");
716 gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
717
718 action = gtk_action_group_get_action (window->priv->action_group, "SearchReplace");
719 gtk_action_set_sensitive (action, state_normal && editable);
720
721 b = TRUE;
722 action = gtk_action_group_get_action (window->priv->action_group, "SearchFindNext");
723 gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
724
725 action = gtk_action_group_get_action (window->priv->action_group, "SearchFindPrevious");
726 gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
727
728 action = gtk_action_group_get_action (window->priv->action_group, "SearchGoToLine");
729 gtk_action_set_sensitive (action, (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
730
731 action = gtk_action_group_get_action (window->priv->action_group, "ViewHighlightMode");
732 gtk_action_set_sensitive (action, (state != XED_TAB_STATE_CLOSING) && enable_syntax_hl);
733
734 update_next_prev_doc_sensitivity (window, tab);
735
736 peas_extension_set_call (window->priv->extensions, "update_state");
737 }
738
739 void
_xed_recent_add(XedWindow * window,GFile * location,const gchar * mime)740 _xed_recent_add (XedWindow *window,
741 GFile *location,
742 const gchar *mime)
743 {
744 GtkRecentManager *recent_manager;
745 GtkRecentData *recent_data;
746 gchar *uri;
747
748 static gchar *groups[2] = { "xed", NULL };
749
750 recent_manager = gtk_recent_manager_get_default ();
751
752 recent_data = g_slice_new(GtkRecentData);
753
754 recent_data->display_name = NULL;
755 recent_data->description = NULL;
756 recent_data->mime_type = (gchar *) mime;
757 recent_data->app_name = (gchar *) g_get_application_name ();
758 recent_data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
759 recent_data->groups = groups;
760 recent_data->is_private = FALSE;
761
762 uri = g_file_get_uri (location);
763
764 gtk_recent_manager_add_full (recent_manager, uri, recent_data);
765
766 g_free (uri);
767 g_free (recent_data->app_exec);
768
769 g_slice_free(GtkRecentData, recent_data);
770 }
771
772 void
_xed_recent_remove(XedWindow * window,GFile * location)773 _xed_recent_remove (XedWindow *window,
774 GFile *location)
775 {
776 GtkRecentManager *recent_manager;
777 gchar *uri;
778
779 recent_manager = gtk_recent_manager_get_default ();
780
781 uri = g_file_get_uri (location);
782 gtk_recent_manager_remove_item (recent_manager, uri, NULL);
783 g_free (uri);
784 }
785
786 static void
open_recent_file(GFile * location,XedWindow * window)787 open_recent_file (GFile *location,
788 XedWindow *window)
789 {
790 GSList *locations = NULL;
791 GSList *loaded = NULL;
792
793 locations = g_slist_prepend (locations, (gpointer) location);
794
795 loaded = xed_commands_load_locations (window, locations, NULL, 0);
796
797 if (!loaded || loaded->next) /* if it doesn't contain just 1 element */
798 {
799 _xed_recent_remove (window, location);
800 }
801
802 g_slist_free (locations);
803 g_slist_free (loaded);
804 }
805
806 static void
recents_menu_activate(GtkAction * action,XedWindow * window)807 recents_menu_activate (GtkAction *action,
808 XedWindow *window)
809 {
810 GtkRecentInfo *info;
811 GFile *location;
812 const gchar *uri;
813
814 info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
815 g_return_if_fail (info != NULL);
816
817 uri = gtk_recent_info_get_uri (info);
818 location = g_file_new_for_uri (uri);
819
820 if (location)
821 {
822 open_recent_file (location, window);
823 g_object_unref (location);
824 }
825 }
826
827 static gint
sort_recents_mru(GtkRecentInfo * a,GtkRecentInfo * b)828 sort_recents_mru (GtkRecentInfo *a,
829 GtkRecentInfo *b)
830 {
831 return (gtk_recent_info_get_modified (b) - gtk_recent_info_get_modified (a));
832 }
833
834 static void
835 update_recent_files_menu (XedWindow *window);
836
837 static void
recent_manager_changed(GtkRecentManager * manager,XedWindow * window)838 recent_manager_changed (GtkRecentManager *manager,
839 XedWindow *window)
840 {
841 /* regenerate the menu when the model changes */
842 update_recent_files_menu (window);
843 }
844
845 /*
846 * Manually construct the inline recents list in the File menu.
847 * Hopefully gtk 2.12 will add support for it.
848 */
849 static void
update_recent_files_menu(XedWindow * window)850 update_recent_files_menu (XedWindow *window)
851 {
852 XedWindowPrivate *p = window->priv;
853 GtkRecentManager *recent_manager;
854 gint max_recents;
855 GList *actions, *l, *items;
856 GList *filtered_items = NULL;
857 guint i;
858
859 xed_debug (DEBUG_WINDOW);
860
861 max_recents = g_settings_get_uint (window->priv->ui_settings, XED_SETTINGS_MAX_RECENTS);
862
863 g_return_if_fail(p->recents_action_group != NULL);
864
865 if (p->recents_menu_ui_id != 0)
866 {
867 gtk_ui_manager_remove_ui (p->manager, p->recents_menu_ui_id);
868 }
869
870 actions = gtk_action_group_list_actions (p->recents_action_group);
871 for (l = actions; l != NULL; l = l->next)
872 {
873 g_signal_handlers_disconnect_by_func(GTK_ACTION (l->data), G_CALLBACK (recents_menu_activate), window);
874 gtk_action_group_remove_action (p->recents_action_group, GTK_ACTION(l->data));
875 }
876 g_list_free (actions);
877
878 p->recents_menu_ui_id = gtk_ui_manager_new_merge_id (p->manager);
879
880 recent_manager = gtk_recent_manager_get_default ();
881 items = gtk_recent_manager_get_items (recent_manager);
882
883 /* filter */
884 for (l = items; l != NULL; l = l->next)
885 {
886 GtkRecentInfo *info = l->data;
887 if (!gtk_recent_info_has_group (info, "xed"))
888 {
889 continue;
890 }
891
892 filtered_items = g_list_prepend (filtered_items, info);
893 }
894
895 /* sort */
896 filtered_items = g_list_sort (filtered_items, (GCompareFunc) sort_recents_mru);
897
898 i = 0;
899 for (l = filtered_items; l != NULL; l = l->next)
900 {
901 gchar *action_name;
902 const gchar *display_name;
903 gchar *escaped;
904 gchar *label;
905 gchar *uri;
906 gchar *ruri;
907 gchar *tip;
908 GtkAction *action;
909 GtkRecentInfo *info = l->data;
910 GFile *location;
911
912 /* clamp */
913 if (i >= max_recents)
914 {
915 break;
916 }
917
918 i++;
919
920 action_name = g_strdup_printf ("recent-info-%d", i);
921
922 display_name = gtk_recent_info_get_display_name (info);
923 escaped = xed_utils_escape_underscores (display_name, -1);
924 if (i >= 10)
925 {
926 label = g_strdup_printf ("%d. %s", i, escaped);
927 }
928 else
929 label = g_strdup_printf ("_%d. %s", i, escaped);
930 g_free (escaped);
931
932 /* gtk_recent_info_get_uri_display (info) is buggy and
933 * works only for local files */
934 location = g_file_new_for_uri (gtk_recent_info_get_uri (info));
935 uri = g_file_get_parse_name (location);
936 g_object_unref (location);
937 ruri = xed_utils_replace_home_dir_with_tilde (uri);
938 g_free (uri);
939
940 /* Translators: %s is a URI */
941 tip = g_strdup_printf (_("Open '%s'"), ruri);
942 g_free (ruri);
943
944 action = gtk_action_new (action_name, label, tip, NULL);
945
946 g_object_set_data_full (G_OBJECT(action), "gtk-recent-info", gtk_recent_info_ref (info),
947 (GDestroyNotify) gtk_recent_info_unref);
948
949 g_signal_connect(action, "activate", G_CALLBACK (recents_menu_activate), window);
950
951 gtk_action_group_add_action (p->recents_action_group, action);
952 g_object_unref (action);
953
954 gtk_ui_manager_add_ui (p->manager, p->recents_menu_ui_id, "/MenuBar/FileMenu/FileRecentsMenu/FileRecentsPlaceholder",
955 action_name, action_name, GTK_UI_MANAGER_MENUITEM, FALSE);
956
957 g_free (action_name);
958 g_free (label);
959 g_free (tip);
960 }
961
962 g_list_free (filtered_items);
963
964 g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
965 g_list_free (items);
966 }
967
968 static void
toolbar_visibility_changed(GtkWidget * toolbar,XedWindow * window)969 toolbar_visibility_changed (GtkWidget *toolbar,
970 XedWindow *window)
971 {
972 gboolean visible;
973 GtkAction *action;
974
975 visible = gtk_widget_get_visible (toolbar);
976
977 g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_TOOLBAR_VISIBLE, visible);
978
979 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewToolbar");
980
981 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
982 {
983 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
984 }
985 }
986
987
988
989 static void
favorite_activated(GtkAction * action,gpointer user_data)990 favorite_activated (GtkAction *action,
991 gpointer user_data)
992 {
993 GFile *location;
994
995 location = g_file_new_for_uri (gtk_action_get_name (action));
996 xed_commands_load_location (XED_WINDOW (user_data), location, NULL, 0);
997
998 g_object_unref (location);
999 }
1000
1001 static void
update_favorites_menu(XedWindow * window)1002 update_favorites_menu (XedWindow *window)
1003 {
1004 XedWindowPrivate *p = window->priv;
1005 XAppFavorites *favorites;
1006 GList *actions, *l;
1007 GList *items = NULL;
1008
1009 xed_debug (DEBUG_WINDOW);
1010
1011 g_return_if_fail (p->favorites_action_group != NULL);
1012
1013 if (p->favorites_menu_ui_id != 0)
1014 {
1015 gtk_ui_manager_remove_ui (p->manager, p->favorites_menu_ui_id);
1016 }
1017
1018 actions = gtk_action_group_list_actions (p->favorites_action_group);
1019 for (l = actions; l != NULL; l = l->next)
1020 {
1021 g_signal_handlers_disconnect_by_func(GTK_ACTION (l->data), G_CALLBACK (favorite_activated), window);
1022 gtk_action_group_remove_action (p->favorites_action_group, GTK_ACTION(l->data));
1023 }
1024 g_list_free (actions);
1025
1026 p->favorites_menu_ui_id = gtk_ui_manager_new_merge_id (p->manager);
1027
1028 favorites = xapp_favorites_get_default ();
1029
1030 const gchar *supported_mimetypes[2] = {
1031 "text/plain",
1032 NULL
1033 };
1034
1035 items = xapp_favorites_create_actions (favorites, supported_mimetypes);
1036
1037 for (l = items; l != NULL; l = l->next)
1038 {
1039 GtkAction *action = GTK_ACTION (l->data);
1040 const gchar *name = gtk_action_get_name (action);
1041
1042 g_signal_connect (action, "activate", G_CALLBACK (favorite_activated), window);
1043
1044 gtk_action_group_add_action (p->favorites_action_group, action);
1045
1046 gtk_ui_manager_add_ui (p->manager, p->favorites_menu_ui_id, "/MenuBar/FileMenu/XAppFavoritesMenu/XAppFavorites",
1047 name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
1048 }
1049
1050 g_list_free_full (items, g_object_unref);
1051 }
1052
1053 static GtkWidget *
create_toolbar_button(GtkAction * action)1054 create_toolbar_button (GtkAction *action)
1055 {
1056 GtkWidget *button;
1057 GtkWidget *image;
1058
1059 button = gtk_button_new ();
1060 image = gtk_image_new ();
1061
1062 gtk_button_set_image (GTK_BUTTON (button), image);
1063 gtk_style_context_add_class (gtk_widget_get_style_context (button), "flat");
1064 gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
1065 gtk_button_set_label (GTK_BUTTON (button), NULL);
1066 gtk_widget_set_tooltip_text (button, gtk_action_get_tooltip (action));
1067
1068 return button;
1069 }
1070
1071 static void
create_menu_bar_and_toolbar(XedWindow * window,GtkWidget * main_box)1072 create_menu_bar_and_toolbar (XedWindow *window,
1073 GtkWidget *main_box)
1074 {
1075 GtkActionGroup *action_group;
1076 GtkAction *action;
1077 GtkUIManager *manager;
1078 GtkRecentManager *recent_manager;
1079 GError *error = NULL;
1080 GtkToolItem *tool_item;
1081 GtkWidget *tool_box;
1082 GtkWidget *box;
1083 GtkWidget *separator;
1084 GtkWidget *button;
1085 XAppFavorites *favorites;
1086
1087 xed_debug (DEBUG_WINDOW);
1088
1089 manager = gtk_ui_manager_new ();
1090 window->priv->manager = manager;
1091
1092 gtk_window_add_accel_group (GTK_WINDOW(window), gtk_ui_manager_get_accel_group (manager));
1093
1094 action_group = gtk_action_group_new ("XedWindowAlwaysSensitiveActions");
1095 gtk_action_group_set_translation_domain (action_group, NULL);
1096 gtk_action_group_add_actions (action_group, xed_always_sensitive_menu_entries,
1097 G_N_ELEMENTS(xed_always_sensitive_menu_entries), window);
1098 gtk_action_group_add_toggle_actions (action_group, xed_always_sensitive_toggle_menu_entries,
1099 G_N_ELEMENTS(xed_always_sensitive_toggle_menu_entries), window);
1100
1101 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1102 g_object_unref (action_group);
1103 window->priv->always_sensitive_action_group = action_group;
1104
1105 action_group = gtk_action_group_new ("XedWindowActions");
1106 gtk_action_group_set_translation_domain (action_group, NULL);
1107 gtk_action_group_add_actions (action_group, xed_menu_entries, G_N_ELEMENTS(xed_menu_entries), window);
1108 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1109 g_object_unref (action_group);
1110 window->priv->action_group = action_group;
1111
1112 action_group = gtk_action_group_new ("XedQuitWindowActions");
1113 gtk_action_group_set_translation_domain (action_group, NULL);
1114 gtk_action_group_add_actions (action_group, xed_quit_menu_entries, G_N_ELEMENTS(xed_quit_menu_entries), window);
1115
1116 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1117 g_object_unref (action_group);
1118 window->priv->quit_action_group = action_group;
1119
1120 action_group = gtk_action_group_new ("XedCloseWindowActions");
1121 gtk_action_group_set_translation_domain (action_group, NULL);
1122 gtk_action_group_add_actions (action_group, xed_close_menu_entries, G_N_ELEMENTS(xed_close_menu_entries), window);
1123
1124 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1125 g_object_unref (action_group);
1126 window->priv->close_action_group = action_group;
1127
1128 action_group = gtk_action_group_new ("XedWindowPanesActions");
1129 gtk_action_group_set_translation_domain (action_group, NULL);
1130 gtk_action_group_add_toggle_actions (action_group, xed_panes_toggle_menu_entries,
1131 G_N_ELEMENTS(xed_panes_toggle_menu_entries), window);
1132
1133 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1134 g_object_unref (action_group);
1135 window->priv->panes_action_group = action_group;
1136
1137 gtk_ui_manager_add_ui_from_resource (manager, "/org/x/editor/ui/xed-ui.xml", &error);
1138 if (error != NULL)
1139 {
1140 g_warning ("Could not add ui definition: %s", error->message);
1141 g_error_free (error);
1142 }
1143
1144 /* show tooltips in the statusbar */
1145 g_signal_connect(manager, "connect_proxy", G_CALLBACK (connect_proxy_cb), window);
1146 g_signal_connect(manager, "disconnect_proxy", G_CALLBACK (disconnect_proxy_cb), window);
1147
1148 /* recent files menu */
1149 action_group = gtk_action_group_new ("RecentFilesActions");
1150 gtk_action_group_set_translation_domain (action_group, NULL);
1151 window->priv->recents_action_group = action_group;
1152 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1153 g_object_unref (action_group);
1154
1155 recent_manager = gtk_recent_manager_get_default ();
1156 window->priv->recents_handler_id = g_signal_connect(recent_manager, "changed", G_CALLBACK (recent_manager_changed),
1157 window);
1158 update_recent_files_menu (window);
1159
1160 action_group = gtk_action_group_new ("FavoriteFilesActions");
1161 gtk_action_group_set_translation_domain (action_group, NULL);
1162 window->priv->favorites_action_group = action_group;
1163 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1164 g_object_unref (action_group);
1165
1166 favorites = xapp_favorites_get_default ();
1167 window->priv->favorites_handler_id = g_signal_connect_swapped (favorites,
1168 "changed", G_CALLBACK (update_favorites_menu),
1169 window);
1170
1171 update_favorites_menu (window);
1172
1173 /* list of open documents menu */
1174 action_group = gtk_action_group_new ("DocumentsListActions");
1175 gtk_action_group_set_translation_domain (action_group, NULL);
1176 window->priv->documents_list_action_group = action_group;
1177 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1178 g_object_unref (action_group);
1179
1180 window->priv->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
1181 gtk_box_pack_start (GTK_BOX(main_box), window->priv->menubar, FALSE, FALSE, 0);
1182
1183 window->priv->toolbar = gtk_toolbar_new ();
1184 gtk_style_context_add_class (gtk_widget_get_style_context (window->priv->toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
1185 gtk_box_pack_start (GTK_BOX(main_box), window->priv->toolbar, FALSE, FALSE, 0);
1186
1187 tool_item = gtk_tool_item_new ();
1188 gtk_tool_item_set_expand ((tool_item), TRUE);
1189 gtk_toolbar_insert (GTK_TOOLBAR (window->priv->toolbar), (tool_item), 0);
1190
1191 tool_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
1192 gtk_container_add (GTK_CONTAINER (tool_item), tool_box);
1193
1194 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1195 gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1196
1197 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
1198 button = create_toolbar_button (action);
1199 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1200
1201 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileOpen");
1202 button = create_toolbar_button (action);
1203 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1204
1205 action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
1206 button = create_toolbar_button (action);
1207 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1208
1209 separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
1210 gtk_box_pack_start (GTK_BOX (tool_box), separator, FALSE, FALSE, 0);
1211
1212 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1213 gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1214
1215 action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
1216 button = create_toolbar_button (action);
1217 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1218
1219 action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
1220 button = create_toolbar_button (action);
1221 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1222
1223 separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
1224 gtk_box_pack_start (GTK_BOX (tool_box), separator, FALSE, FALSE, 0);
1225
1226 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1227 gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1228
1229 action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
1230 button = create_toolbar_button (action);
1231 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1232
1233 action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
1234 button = create_toolbar_button (action);
1235 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1236
1237 action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
1238 button = create_toolbar_button (action);
1239 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1240
1241 separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
1242 gtk_box_pack_start (GTK_BOX (tool_box), separator, FALSE, FALSE, 0);
1243
1244 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1245 gtk_box_pack_start (GTK_BOX (tool_box), box, FALSE, FALSE, 0);
1246
1247 action = gtk_action_group_get_action (window->priv->action_group, "SearchFind");
1248 button = create_toolbar_button (action);
1249 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1250
1251 action = gtk_action_group_get_action (window->priv->action_group, "SearchReplace");
1252 button = create_toolbar_button (action);
1253 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
1254
1255 gtk_widget_show_all (GTK_WIDGET (window->priv->toolbar));
1256
1257 set_toolbar_style (window, NULL);
1258 set_menubar_style (window, NULL);
1259
1260 g_signal_connect_after(G_OBJECT (window->priv->toolbar), "show", G_CALLBACK (toolbar_visibility_changed), window);
1261 g_signal_connect_after(G_OBJECT (window->priv->toolbar), "hide", G_CALLBACK (toolbar_visibility_changed), window);
1262 }
1263
1264 static void
documents_list_menu_activate(GtkToggleAction * action,XedWindow * window)1265 documents_list_menu_activate (GtkToggleAction *action,
1266 XedWindow *window)
1267 {
1268 gint n;
1269 if (gtk_toggle_action_get_active (action) == FALSE)
1270 {
1271 return;
1272 }
1273 n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION(action));
1274 gtk_notebook_set_current_page (GTK_NOTEBOOK(window->priv->notebook), n);
1275 }
1276
1277 static gchar *
get_menu_tip_for_tab(XedTab * tab)1278 get_menu_tip_for_tab (XedTab *tab)
1279 {
1280 XedDocument *doc;
1281 gchar *uri;
1282 gchar *ruri;
1283 gchar *tip;
1284
1285 doc = xed_tab_get_document (tab);
1286
1287 uri = xed_document_get_uri_for_display (doc);
1288 ruri = xed_utils_replace_home_dir_with_tilde (uri);
1289 g_free (uri);
1290
1291 /* Translators: %s is a URI */
1292 tip = g_strdup_printf (_("Activate '%s'"), ruri);
1293 g_free (ruri);
1294
1295 return tip;
1296 }
1297
1298 static void
update_documents_list_menu(XedWindow * window)1299 update_documents_list_menu (XedWindow *window)
1300 {
1301 XedWindowPrivate *p = window->priv;
1302 GList *actions, *l;
1303 gint n, i;
1304 guint id;
1305 GSList *group = NULL;
1306
1307 xed_debug (DEBUG_WINDOW);
1308
1309 g_return_if_fail(p->documents_list_action_group != NULL);
1310
1311 if (p->documents_list_menu_ui_id != 0)
1312 {
1313 gtk_ui_manager_remove_ui (p->manager, p->documents_list_menu_ui_id);
1314 }
1315
1316 actions = gtk_action_group_list_actions (p->documents_list_action_group);
1317 for (l = actions; l != NULL; l = l->next)
1318 {
1319 g_signal_handlers_disconnect_by_func(GTK_ACTION (l->data), G_CALLBACK (documents_list_menu_activate), window);
1320 gtk_action_group_remove_action (p->documents_list_action_group, GTK_ACTION(l->data));
1321 }
1322 g_list_free (actions);
1323
1324 n = gtk_notebook_get_n_pages (GTK_NOTEBOOK(p->notebook));
1325
1326 id = (n > 0) ? gtk_ui_manager_new_merge_id (p->manager) : 0;
1327
1328 for (i = 0; i < n; i++)
1329 {
1330 GtkWidget *tab;
1331 GtkRadioAction *action;
1332 gchar *action_name;
1333 gchar *tab_name;
1334 gchar *name;
1335 gchar *tip;
1336 gchar *accel;
1337
1338 tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK(p->notebook), i);
1339
1340 /* NOTE: the action is associated to the position of the tab in
1341 * the notebook not to the tab itself! This is needed to work
1342 * around the gtk+ bug #170727: gtk leaves around the accels
1343 * of the action. Since the accel depends on the tab position
1344 * the problem is worked around, action with the same name always
1345 * get the same accel.
1346 */
1347 action_name = g_strdup_printf ("Tab_%d", i);
1348 tab_name = _xed_tab_get_name (XED_TAB(tab));
1349 name = xed_utils_escape_underscores (tab_name, -1);
1350 tip = get_menu_tip_for_tab (XED_TAB(tab));
1351
1352 /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
1353 accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL;
1354
1355 action = gtk_radio_action_new (action_name, name, tip, NULL, i);
1356
1357 if (group != NULL)
1358 {
1359 gtk_radio_action_set_group (action, group);
1360 }
1361
1362 /* note that group changes each time we add an action, so it must be updated */
1363 group = gtk_radio_action_get_group (action);
1364
1365 gtk_action_group_add_action_with_accel (p->documents_list_action_group, GTK_ACTION(action), accel);
1366
1367 g_signal_connect(action, "activate", G_CALLBACK (documents_list_menu_activate), window);
1368
1369 gtk_ui_manager_add_ui (p->manager, id, "/MenuBar/DocumentsMenu/DocumentsListPlaceholder", action_name,
1370 action_name, GTK_UI_MANAGER_MENUITEM, FALSE);
1371
1372 if (XED_TAB (tab) == p->active_tab)
1373 {
1374 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), TRUE);
1375 }
1376
1377 g_object_unref (action);
1378
1379 g_free (action_name);
1380 g_free (tab_name);
1381 g_free (name);
1382 g_free (tip);
1383 g_free (accel);
1384 }
1385
1386 p->documents_list_menu_ui_id = id;
1387 }
1388
1389 /* Returns TRUE if status bar is visible */
1390 static gboolean
set_statusbar_style(XedWindow * window,XedWindow * origin)1391 set_statusbar_style (XedWindow *window,
1392 XedWindow *origin)
1393 {
1394 GtkAction *action;
1395 gboolean visible;
1396
1397 if (origin == NULL)
1398 {
1399 visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_STATUSBAR_VISIBLE);
1400 }
1401 else
1402 {
1403 visible = gtk_widget_get_visible (origin->priv->statusbar);
1404 }
1405
1406 if (visible)
1407 {
1408 gtk_widget_show (window->priv->statusbar);
1409 }
1410 else
1411 {
1412 gtk_widget_hide (window->priv->statusbar);
1413 }
1414
1415 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewStatusbar");
1416
1417 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
1418 {
1419 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
1420 }
1421
1422 return visible;
1423 }
1424
1425 static void
statusbar_visibility_changed(GtkWidget * statusbar,XedWindow * window)1426 statusbar_visibility_changed (GtkWidget *statusbar,
1427 XedWindow *window)
1428 {
1429 gboolean visible;
1430 GtkAction *action;
1431
1432 visible = gtk_widget_get_visible (statusbar);
1433
1434 g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_STATUSBAR_VISIBLE, visible);
1435
1436 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewStatusbar");
1437
1438 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
1439 {
1440 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
1441 }
1442 }
1443
1444 static void
tab_width_button_clicked(GtkMenuItem * item,XedWindow * window)1445 tab_width_button_clicked (GtkMenuItem *item,
1446 XedWindow *window)
1447 {
1448 XedView *view;
1449 guint width_data = 0;
1450
1451 view = xed_window_get_active_view (window);
1452
1453 if (!view)
1454 {
1455 return;
1456 }
1457
1458 width_data = GPOINTER_TO_INT(g_object_get_data (G_OBJECT (item), TAB_WIDTH_DATA));
1459
1460 if (width_data == 0)
1461 {
1462 return;
1463 }
1464
1465 gtk_source_view_set_tab_width (GTK_SOURCE_VIEW(view), width_data);
1466 }
1467
1468 static void
set_tab_spaces_label(XedView * view,XedWindow * window,gboolean use_spaces)1469 set_tab_spaces_label (XedView *view,
1470 XedWindow *window,
1471 gboolean use_spaces)
1472 {
1473 gchar *label;
1474 guint tab_width;
1475
1476 tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (view));
1477
1478 if (use_spaces)
1479 {
1480 label = g_strdup_printf (_("Spaces: %u"), tab_width);
1481 }
1482 else
1483 {
1484 label = g_strdup_printf (_("Tabs: %u"), tab_width);
1485 }
1486
1487 xed_status_menu_button_set_label (XED_STATUS_MENU_BUTTON (window->priv->tab_width_button), label);
1488
1489 g_free (label);
1490 }
1491
1492 static void
use_spaces_toggled(GtkCheckMenuItem * item,XedWindow * window)1493 use_spaces_toggled (GtkCheckMenuItem *item,
1494 XedWindow *window)
1495 {
1496 XedView *view;
1497 gboolean use_spaces;
1498
1499 view = xed_window_get_active_view (window);
1500 use_spaces = gtk_check_menu_item_get_active (item);
1501
1502 set_tab_spaces_label (view, window, use_spaces);
1503
1504 g_signal_handler_block (view, window->priv->spaces_instead_of_tabs_id);
1505 gtk_source_view_set_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (view), use_spaces);
1506 g_signal_handler_unblock (view, window->priv->spaces_instead_of_tabs_id);
1507 }
1508
1509 typedef struct
1510 {
1511 const gchar *label;
1512 guint width;
1513 } TabWidthDefinition;
1514
1515 static void
tab_width_menu_popped_up(GtkMenu * menu,gpointer flipped_rect,gpointer final_rect,gboolean flipped_x,gboolean flipped_y,gpointer user_data)1516 tab_width_menu_popped_up (GtkMenu *menu,
1517 gpointer flipped_rect,
1518 gpointer final_rect,
1519 gboolean flipped_x,
1520 gboolean flipped_y,
1521 gpointer user_data)
1522 {
1523 XedWindow *window = XED_WINDOW (user_data);
1524
1525 gtk_menu_shell_select_item (GTK_MENU_SHELL (window->priv->tab_width_menu), GTK_WIDGET (window->priv->tab_width_item));
1526 }
1527
1528 static void
setup_tab_width_menu(XedWindow * window)1529 setup_tab_width_menu (XedWindow *window)
1530 {
1531 static TabWidthDefinition defs[] = { { "2", 2 }, { "4", 4 }, { "8", 8 }, { "", 0 }, /* custom size */
1532 { NULL, 0 } };
1533
1534 guint i = 0;
1535 GtkWidget *item;
1536
1537 window->priv->tab_width_menu = gtk_menu_new ();
1538
1539 while (defs[i].label != NULL)
1540 {
1541 item = gtk_menu_item_new_with_label (defs[i].label);
1542 g_object_set_data (G_OBJECT(item), TAB_WIDTH_DATA, GINT_TO_POINTER (defs[i].width));
1543
1544 gtk_menu_shell_append (GTK_MENU_SHELL (window->priv->tab_width_menu), item);
1545
1546 g_signal_connect(G_OBJECT (item), "activate",
1547 G_CALLBACK (tab_width_button_clicked), window);
1548
1549 if (defs[i].width != 0)
1550 {
1551 gtk_widget_show (item);
1552 }
1553
1554 ++i;
1555 }
1556
1557 item = gtk_separator_menu_item_new ();
1558 gtk_menu_shell_append (GTK_MENU_SHELL (window->priv->tab_width_menu), item);
1559 gtk_widget_show (item);
1560
1561 item = gtk_check_menu_item_new_with_label (_("Use Spaces"));
1562 gtk_menu_shell_append (GTK_MENU_SHELL (window->priv->tab_width_menu), item);
1563 gtk_widget_show (item);
1564
1565 g_signal_connect (item, "toggled", G_CALLBACK (use_spaces_toggled), window);
1566
1567 g_signal_connect (window->priv->tab_width_menu, "popped-up", G_CALLBACK (tab_width_menu_popped_up), window);
1568 }
1569
1570 static void
on_language_selector_shown(XedHighlightModeSelector * sel,XedWindow * window)1571 on_language_selector_shown (XedHighlightModeSelector *sel,
1572 XedWindow *window)
1573 {
1574 XedDocument *doc;
1575
1576 doc = xed_window_get_active_document (window);
1577 if (doc)
1578 {
1579 xed_highlight_mode_selector_select_language (sel,
1580 xed_document_get_language (doc));
1581 }
1582 }
1583
1584 static void
on_language_selected(XedHighlightModeSelector * sel,GtkSourceLanguage * language,XedWindow * window)1585 on_language_selected (XedHighlightModeSelector *sel,
1586 GtkSourceLanguage *language,
1587 XedWindow *window)
1588 {
1589 XedDocument *doc;
1590
1591 doc = xed_window_get_active_document (window);
1592 if (doc)
1593 {
1594 xed_document_set_language (doc, language);
1595 }
1596
1597 gtk_widget_hide (GTK_WIDGET (window->priv->language_popover));
1598 }
1599
1600 static void
create_statusbar(XedWindow * window,GtkWidget * main_box)1601 create_statusbar (XedWindow *window,
1602 GtkWidget *main_box)
1603 {
1604 GtkWidget *image;
1605 GtkWidget *button_box;
1606 GtkAction *action;
1607 XedHighlightModeSelector *sel;
1608
1609 xed_debug (DEBUG_WINDOW);
1610
1611 window->priv->statusbar = xed_statusbar_new ();
1612 window->priv->searchbar = xed_searchbar_new (GTK_WINDOW (window));
1613
1614 window->priv->generic_message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar),
1615 "generic_message");
1616 window->priv->tip_message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar),
1617 "tip_message");
1618
1619 gtk_box_pack_end (GTK_BOX( main_box), window->priv->statusbar, FALSE, TRUE, 0);
1620
1621 gtk_widget_set_margin_start (GTK_WIDGET (window->priv->statusbar), 0);
1622 gtk_widget_set_margin_end (GTK_WIDGET (window->priv->statusbar), 0);
1623
1624 window->priv->tab_width_button = xed_status_menu_button_new ();
1625 gtk_widget_show (window->priv->tab_width_button);
1626 gtk_box_pack_end (GTK_BOX (window->priv->statusbar), window->priv->tab_width_button, FALSE, FALSE, 0);
1627 gtk_widget_set_margin_bottom (GTK_WIDGET (window->priv->tab_width_button), 2);
1628 gtk_widget_set_margin_top (GTK_WIDGET (window->priv->tab_width_button), 2);
1629
1630 setup_tab_width_menu (window);
1631
1632 gtk_menu_button_set_popup (GTK_MENU_BUTTON (window->priv->tab_width_button),
1633 window->priv->tab_width_menu);
1634
1635 window->priv->language_button = xed_status_menu_button_new ();
1636 gtk_widget_show (window->priv->language_button);
1637 gtk_widget_set_margin_bottom (GTK_WIDGET (window->priv->language_button), 2);
1638 gtk_widget_set_margin_top (GTK_WIDGET (window->priv->language_button), 2);
1639 gtk_box_pack_end (GTK_BOX(window->priv->statusbar), window->priv->language_button, FALSE, FALSE, 0);
1640
1641 window->priv->language_popover = gtk_popover_new (window->priv->language_button);
1642 gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->language_button),
1643 window->priv->language_popover);
1644
1645 sel = xed_highlight_mode_selector_new ();
1646 g_signal_connect (sel,
1647 "show",
1648 G_CALLBACK (on_language_selector_shown),
1649 window);
1650 g_signal_connect (sel,
1651 "language-selected",
1652 G_CALLBACK (on_language_selected),
1653 window);
1654
1655 gtk_container_add (GTK_CONTAINER (window->priv->language_popover), GTK_WIDGET (sel));
1656 gtk_widget_show (GTK_WIDGET (sel));
1657
1658 button_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
1659 gtk_widget_set_margin_top (button_box, 4);
1660 gtk_widget_set_margin_bottom (button_box, 4);
1661 gtk_widget_set_margin_start (button_box, 6);
1662 gtk_box_pack_start (GTK_BOX (window->priv->statusbar), button_box, FALSE, FALSE, 0);
1663
1664 window->priv->show_side_pane_button = gtk_toggle_button_new ();
1665 image = gtk_image_new_from_icon_name ("view-left-pane-symbolic", GTK_ICON_SIZE_INVALID);
1666 gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
1667 gtk_container_add (GTK_CONTAINER (window->priv->show_side_pane_button), image);
1668 gtk_box_pack_start (GTK_BOX (button_box), window->priv->show_side_pane_button, FALSE, FALSE, 0);
1669
1670 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewSidePane");
1671 gtk_activatable_set_related_action (GTK_ACTIVATABLE (window->priv->show_side_pane_button), action);
1672 gtk_widget_set_tooltip_text (window->priv->show_side_pane_button, gtk_action_get_tooltip (action));
1673
1674 window->priv->bottom_pane_button_revealer = gtk_revealer_new ();
1675 gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->bottom_pane_button_revealer),
1676 GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT);
1677 gtk_box_pack_start (GTK_BOX (button_box), window->priv->bottom_pane_button_revealer, FALSE, FALSE, 0);
1678
1679 window->priv->show_bottom_pane_button = gtk_toggle_button_new ();
1680 image = gtk_image_new_from_icon_name ("view-bottom-pane-symbolic", GTK_ICON_SIZE_INVALID);
1681 gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
1682 gtk_container_add (GTK_CONTAINER (window->priv->show_bottom_pane_button), image);
1683 gtk_container_add (GTK_CONTAINER (window->priv->bottom_pane_button_revealer), window->priv->show_bottom_pane_button);
1684
1685 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
1686 gtk_activatable_set_related_action (GTK_ACTIVATABLE (window->priv->show_bottom_pane_button), action);
1687 gtk_widget_set_tooltip_text (window->priv->show_bottom_pane_button, gtk_action_get_tooltip (action));
1688
1689 gtk_widget_show_all (button_box);
1690
1691 g_signal_connect_after(G_OBJECT (window->priv->statusbar), "show",
1692 G_CALLBACK (statusbar_visibility_changed), window);
1693
1694 g_signal_connect_after(G_OBJECT (window->priv->statusbar), "hide",
1695 G_CALLBACK (statusbar_visibility_changed), window);
1696
1697 set_statusbar_style (window, NULL);
1698
1699 gtk_box_pack_end (GTK_BOX (main_box), window->priv->searchbar, FALSE, FALSE, 0);
1700
1701 gtk_box_reorder_child (GTK_BOX (window->priv->statusbar), button_box, 0);
1702 }
1703
1704 static XedWindow *
clone_window(XedWindow * origin)1705 clone_window (XedWindow *origin)
1706 {
1707 XedWindow *window;
1708 GdkScreen *screen;
1709 XedApp *app;
1710 gint panel_page;
1711
1712 xed_debug (DEBUG_WINDOW);
1713
1714 app = XED_APP (g_application_get_default ());
1715
1716 screen = gtk_window_get_screen (GTK_WINDOW (origin));
1717 window = xed_app_create_window (app, screen);
1718
1719 gtk_window_set_default_size (GTK_WINDOW (window), origin->priv->width, origin->priv->height);
1720
1721 if ((origin->priv->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
1722 {
1723 gtk_window_maximize (GTK_WINDOW (window));
1724 }
1725 else
1726 {
1727 gtk_window_unmaximize (GTK_WINDOW (window));
1728 }
1729
1730 if ((origin->priv->window_state & GDK_WINDOW_STATE_STICKY) != 0)
1731 {
1732 gtk_window_stick (GTK_WINDOW(window));
1733 }
1734 else
1735 {
1736 gtk_window_unstick (GTK_WINDOW(window));
1737 }
1738
1739 /* set the panes size, the paned position will be set when
1740 * they are mapped */
1741 window->priv->side_panel_size = origin->priv->side_panel_size;
1742 window->priv->bottom_panel_size = origin->priv->bottom_panel_size;
1743
1744 panel_page = _xed_panel_get_active_item_id (XED_PANEL(origin->priv->side_panel));
1745 _xed_panel_set_active_item_by_id (XED_PANEL(window->priv->side_panel), panel_page);
1746
1747 panel_page = _xed_panel_get_active_item_id (XED_PANEL(origin->priv->bottom_panel));
1748 _xed_panel_set_active_item_by_id (XED_PANEL(window->priv->bottom_panel), panel_page);
1749
1750 if (gtk_widget_get_visible (origin->priv->side_panel))
1751 {
1752 gtk_widget_show (window->priv->side_panel);
1753 }
1754 else
1755 {
1756 gtk_widget_hide (window->priv->side_panel);
1757 }
1758
1759 if (gtk_widget_get_visible (origin->priv->bottom_panel))
1760 {
1761 gtk_widget_show (window->priv->bottom_panel);
1762 }
1763 else
1764 {
1765 gtk_widget_hide (window->priv->bottom_panel);
1766 }
1767
1768 set_menubar_style (window, origin);
1769 set_statusbar_style (window, origin);
1770 set_toolbar_style (window, origin);
1771
1772 return window;
1773 }
1774
1775 static void
update_cursor_position_statusbar(GtkTextBuffer * buffer,XedWindow * window)1776 update_cursor_position_statusbar (GtkTextBuffer *buffer,
1777 XedWindow *window)
1778 {
1779 gint row, col;
1780 GtkTextIter iter;
1781 GtkTextIter start;
1782 guint tab_size;
1783 XedView *view;
1784
1785 xed_debug (DEBUG_WINDOW);
1786
1787 if (buffer != GTK_TEXT_BUFFER(xed_window_get_active_document (window)))
1788 {
1789 return;
1790 }
1791
1792 view = xed_window_get_active_view (window);
1793
1794 gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
1795
1796 row = gtk_text_iter_get_line (&iter);
1797
1798 start = iter;
1799 gtk_text_iter_set_line_offset (&start, 0);
1800 col = 0;
1801
1802 tab_size = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW(view));
1803
1804 while (!gtk_text_iter_equal (&start, &iter))
1805 {
1806 /* FIXME: Are we Unicode compliant here? */
1807 if (gtk_text_iter_get_char (&start) == '\t')
1808 {
1809 col += (tab_size - (col % tab_size));
1810 }
1811 else
1812 {
1813 ++col;
1814 }
1815 gtk_text_iter_forward_char (&start);
1816 }
1817
1818 xed_statusbar_set_cursor_position (XED_STATUSBAR(window->priv->statusbar), row + 1, col + 1);
1819 }
1820
1821 static void
update_overwrite_mode_statusbar(GtkTextView * view,XedWindow * window)1822 update_overwrite_mode_statusbar (GtkTextView *view,
1823 XedWindow *window)
1824 {
1825 if (view != GTK_TEXT_VIEW (xed_window_get_active_view (window)))
1826 {
1827 return;
1828 }
1829
1830 /* Note that we have to use !gtk_text_view_get_overwrite since we
1831 are in the in the signal handler of "toggle overwrite" that is
1832 G_SIGNAL_RUN_LAST
1833 */
1834 xed_statusbar_set_overwrite (XED_STATUSBAR(window->priv->statusbar), !gtk_text_view_get_overwrite (view));
1835 }
1836
1837 #define MAX_TITLE_LENGTH 100
1838
1839 static void
set_title(XedWindow * window)1840 set_title (XedWindow *window)
1841 {
1842 XedDocument *doc = NULL;
1843 gchar *name;
1844 gchar *dirname = NULL;
1845 gchar *title = NULL;
1846 gint len;
1847
1848 if (window->priv->active_tab == NULL)
1849 {
1850 xed_app_set_window_title (XED_APP (g_application_get_default ()), window, "Xed");
1851 return;
1852 }
1853
1854 doc = xed_tab_get_document (window->priv->active_tab);
1855 g_return_if_fail(doc != NULL);
1856
1857 name = xed_document_get_short_name_for_display (doc);
1858
1859 len = g_utf8_strlen (name, -1);
1860
1861 /* if the name is awfully long, truncate it and be done with it,
1862 * otherwise also show the directory (ellipsized if needed)
1863 */
1864 if (len > MAX_TITLE_LENGTH)
1865 {
1866 gchar *tmp;
1867 tmp = xed_utils_str_middle_truncate (name, MAX_TITLE_LENGTH);
1868 g_free (name);
1869 name = tmp;
1870 }
1871 else
1872 {
1873 GtkSourceFile *file = xed_document_get_file (doc);
1874 GFile *location = gtk_source_file_get_location (file);
1875
1876 if (location != NULL)
1877 {
1878 gchar *str = xed_utils_location_get_dirname_for_display (location);
1879
1880 /* use the remaining space for the dir, but use a min of 20 chars
1881 * so that we do not end up with a dirname like "(a...b)".
1882 * This means that in the worst case when the filename is long 99
1883 * we have a title long 99 + 20, but I think it's a rare enough
1884 * case to be acceptable. It's justa darn title afterall :)
1885 */
1886 dirname = xed_utils_str_middle_truncate (str, MAX(20, MAX_TITLE_LENGTH - len));
1887 g_free (str);
1888 }
1889 }
1890
1891 if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER(doc)))
1892 {
1893 gchar *tmp_name;
1894 tmp_name = g_strdup_printf ("*%s", name);
1895 g_free (name);
1896 name = tmp_name;
1897 }
1898
1899 if (xed_document_get_readonly (doc))
1900 {
1901 if (dirname != NULL)
1902 {
1903 title = g_strdup_printf ("%s [%s] (%s)", name, _("Read-Only"), dirname);
1904 }
1905 else
1906 {
1907 title = g_strdup_printf ("%s [%s]", name, _("Read-Only"));
1908 }
1909 }
1910 else
1911 {
1912 if (dirname != NULL)
1913 {
1914 title = g_strdup_printf ("%s (%s)", name, dirname);
1915 }
1916 else
1917 {
1918 title = g_strdup_printf ("%s", name);
1919 }
1920 }
1921
1922 xed_app_set_window_title (XED_APP (g_application_get_default ()), window, title);
1923
1924 g_free (dirname);
1925 g_free (name);
1926 g_free (title);
1927 }
1928
1929 #undef MAX_TITLE_LENGTH
1930
1931 static void
spaces_instead_of_tabs_changed(GObject * object,GParamSpec * pspec,XedWindow * window)1932 spaces_instead_of_tabs_changed (GObject *object,
1933 GParamSpec *pspec,
1934 XedWindow *window)
1935 {
1936 XedView *view = XED_VIEW(object);
1937 gboolean active = gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW(view));
1938 GList *children = gtk_container_get_children (GTK_CONTAINER (window->priv->tab_width_menu));
1939 GtkCheckMenuItem *item;
1940 item = GTK_CHECK_MENU_ITEM(g_list_last (children)->data);
1941 gtk_check_menu_item_set_active (item, active);
1942 g_list_free (children);
1943 }
1944
1945 static void
tab_width_changed(GObject * object,GParamSpec * pspec,XedWindow * window)1946 tab_width_changed (GObject *object,
1947 GParamSpec *pspec,
1948 XedWindow *window)
1949 {
1950 GList *items;
1951 GList *item;
1952 guint new_tab_width;
1953 gboolean use_spaces;
1954 gboolean found = FALSE;
1955
1956 items = gtk_container_get_children (GTK_CONTAINER (window->priv->tab_width_menu));
1957
1958 new_tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (object));
1959 use_spaces = gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (object));
1960
1961 for (item = items; item; item = item->next)
1962 {
1963 guint tab_width = GPOINTER_TO_INT(g_object_get_data (G_OBJECT (item->data), TAB_WIDTH_DATA));
1964
1965 if (tab_width == new_tab_width)
1966 {
1967 window->priv->tab_width_item = item->data;
1968 if (gtk_widget_get_realized (window->priv->tab_width_menu))
1969 {
1970 gtk_menu_shell_select_item (GTK_MENU_SHELL (window->priv->tab_width_menu), GTK_WIDGET (item->data));
1971 }
1972 found = TRUE;
1973 }
1974
1975 if (GTK_IS_SEPARATOR_MENU_ITEM(item->next->data))
1976 {
1977 if (!found)
1978 {
1979 /* Set for the last item the custom thing */
1980 gchar *text;
1981
1982 text = g_strdup_printf ("%u", new_tab_width);
1983 gtk_menu_item_set_label (GTK_MENU_ITEM(item->data), text);
1984
1985 window->priv->tab_width_item = item->data;
1986 if (gtk_widget_get_realized (window->priv->tab_width_menu))
1987 {
1988 gtk_menu_shell_select_item (GTK_MENU_SHELL (window->priv->tab_width_menu), GTK_WIDGET (item->data));
1989 }
1990 gtk_widget_show (GTK_WIDGET(item->data));
1991 }
1992 else
1993 {
1994 gtk_widget_hide (GTK_WIDGET(item->data));
1995 }
1996
1997 break;
1998 }
1999 }
2000
2001 set_tab_spaces_label (XED_VIEW (object), window, use_spaces);
2002
2003 g_list_free (items);
2004 }
2005
2006 static void
language_changed(GObject * object,GParamSpec * pspec,XedWindow * window)2007 language_changed (GObject *object,
2008 GParamSpec *pspec,
2009 XedWindow *window)
2010 {
2011 GtkSourceLanguage *new_language;
2012 const gchar *label;
2013 GtkAction *action;
2014
2015 new_language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (object));
2016
2017 if (new_language)
2018 {
2019 label = gtk_source_language_get_name (new_language);
2020
2021 action = gtk_action_group_get_action (window->priv->action_group, "EditToggleComment");
2022 gtk_action_set_sensitive (action,
2023 gtk_source_language_get_metadata (new_language, "line-comment-start") != NULL);
2024
2025 action = gtk_action_group_get_action (window->priv->action_group, "EditToggleCommentBlock");
2026 gtk_action_set_sensitive (action,
2027 (gtk_source_language_get_metadata (new_language, "block-comment-start") != NULL
2028 && gtk_source_language_get_metadata (new_language, "block-comment-end") != NULL));
2029 }
2030 else
2031 {
2032 label = _("Plain Text");
2033
2034 action = gtk_action_group_get_action (window->priv->action_group, "EditToggleComment");
2035 gtk_action_set_sensitive (action, FALSE);
2036
2037 action = gtk_action_group_get_action (window->priv->action_group, "EditToggleCommentBlock");
2038 gtk_action_set_sensitive (action, FALSE);
2039 }
2040
2041 xed_status_menu_button_set_label (XED_STATUS_MENU_BUTTON (window->priv->language_button), label);
2042 }
2043
2044 static void
word_wrap_changed(GObject * object,GParamSpec * pspec,XedWindow * window)2045 word_wrap_changed (GObject *object,
2046 GParamSpec *pspec,
2047 XedWindow *window)
2048 {
2049 XedView *view;
2050 GtkWrapMode wrap_mode;
2051 GtkAction *action;
2052 gboolean wrap_enabled;
2053
2054 view = XED_VIEW (object);
2055 wrap_mode = gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view));
2056 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewWordWrap");
2057
2058 if (wrap_mode == GTK_WRAP_NONE)
2059 {
2060 wrap_enabled = FALSE;
2061 }
2062 else
2063 {
2064 wrap_enabled = TRUE;
2065 }
2066
2067 g_signal_handlers_block_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_word_wrap), window);
2068 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), wrap_enabled);
2069 g_signal_handlers_unblock_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_word_wrap), window);
2070 }
2071
2072 static void
show_overview_map_changed(GObject * object,GParamSpec * pspec,XedWindow * window)2073 show_overview_map_changed (GObject *object,
2074 GParamSpec *pspec,
2075 XedWindow *window)
2076 {
2077 GtkFrame *map_frame;
2078 GtkAction *action;
2079 gboolean overveiw_map_visible = FALSE;
2080
2081 map_frame = GTK_FRAME (object);
2082 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewOverviewMap");
2083
2084 if (gtk_widget_get_visible (GTK_WIDGET (map_frame)))
2085 {
2086 overveiw_map_visible = TRUE;
2087 }
2088
2089 g_signal_handlers_block_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_overview_map), window);
2090 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), overveiw_map_visible);
2091 g_signal_handlers_unblock_by_func (action, G_CALLBACK (_xed_cmd_view_toggle_overview_map), window);
2092 }
2093
2094 static void
notebook_switch_page(GtkNotebook * book,GtkWidget * pg,gint page_num,XedWindow * window)2095 notebook_switch_page (GtkNotebook *book,
2096 GtkWidget *pg,
2097 gint page_num,
2098 XedWindow *window)
2099 {
2100 XedView *view;
2101 GtkFrame *map_frame;
2102 XedTab *tab;
2103 GtkAction *action;
2104 gchar *action_name;
2105
2106 /* CHECK: I don't know why but it seems notebook_switch_page is called
2107 two times every time the user change the active tab */
2108
2109 tab = XED_TAB (gtk_notebook_get_nth_page (book, page_num));
2110 if (tab == window->priv->active_tab)
2111 {
2112 return;
2113 }
2114
2115 if (window->priv->active_tab)
2116 {
2117 if (window->priv->tab_width_id)
2118 {
2119 g_signal_handler_disconnect (xed_tab_get_view (window->priv->active_tab), window->priv->tab_width_id);
2120 window->priv->tab_width_id = 0;
2121 }
2122
2123 if (window->priv->spaces_instead_of_tabs_id)
2124 {
2125 g_signal_handler_disconnect (xed_tab_get_view (window->priv->active_tab), window->priv->spaces_instead_of_tabs_id);
2126 window->priv->spaces_instead_of_tabs_id = 0;
2127 }
2128
2129 if (window->priv->use_word_wrap_id)
2130 {
2131 g_signal_handler_disconnect (xed_tab_get_view (window->priv->active_tab), window->priv->use_word_wrap_id);
2132 window->priv->use_word_wrap_id = 0;
2133 }
2134
2135 if (window->priv->show_overview_map_id)
2136 {
2137 g_signal_handler_disconnect (xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (window->priv->active_tab))), window->priv->show_overview_map_id);
2138 window->priv->show_overview_map_id = 0;
2139 }
2140 }
2141
2142 /* set the active tab */
2143 window->priv->active_tab = tab;
2144
2145 set_title (window);
2146 set_sensitivity_according_to_tab (window, tab);
2147
2148 /* activate the right item in the documents menu */
2149 action_name = g_strdup_printf ("Tab_%d", page_num);
2150 action = gtk_action_group_get_action (window->priv->documents_list_action_group, action_name);
2151
2152 /* sometimes the action doesn't exist yet, and the proper action
2153 * is set active during the documents list menu creation
2154 * CHECK: would it be nicer if active_tab was a property and we monitored the notify signal?
2155 */
2156 if (action != NULL)
2157 {
2158 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2159 }
2160
2161 g_free (action_name);
2162
2163 view = xed_tab_get_view (tab);
2164 map_frame = xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (tab)));
2165
2166 /* sync the statusbar */
2167 update_cursor_position_statusbar (GTK_TEXT_BUFFER (xed_tab_get_document (tab)), window);
2168 xed_statusbar_set_overwrite (XED_STATUSBAR (window->priv->statusbar),
2169 gtk_text_view_get_overwrite (GTK_TEXT_VIEW(view)));
2170
2171 gtk_widget_show (window->priv->tab_width_button);
2172 gtk_widget_show (window->priv->language_button);
2173
2174 window->priv->tab_width_id = g_signal_connect(view, "notify::tab-width", G_CALLBACK (tab_width_changed), window);
2175
2176 window->priv->spaces_instead_of_tabs_id = g_signal_connect(view, "notify::insert-spaces-instead-of-tabs",
2177 G_CALLBACK (spaces_instead_of_tabs_changed), window);
2178
2179 window->priv->language_changed_id = g_signal_connect(xed_tab_get_document (tab), "notify::language",
2180 G_CALLBACK (language_changed), window);
2181
2182 window->priv->use_word_wrap_id = g_signal_connect (view, "notify::wrap-mode",
2183 G_CALLBACK (word_wrap_changed), window);
2184
2185 window->priv->show_overview_map_id = g_signal_connect (map_frame, "notify::visible",
2186 G_CALLBACK (show_overview_map_changed), window);
2187
2188 /* call it for the first time */
2189 tab_width_changed (G_OBJECT (view), NULL, window);
2190 spaces_instead_of_tabs_changed (G_OBJECT (view), NULL, window);
2191 language_changed (G_OBJECT (xed_tab_get_document (tab)), NULL, window);
2192 word_wrap_changed (G_OBJECT (view), NULL, window);
2193 show_overview_map_changed (G_OBJECT (map_frame), NULL, window);
2194
2195 g_signal_emit (G_OBJECT (window), signals[ACTIVE_TAB_CHANGED], 0, window->priv->active_tab);
2196 }
2197
2198 static void
set_sensitivity_according_to_window_state(XedWindow * window)2199 set_sensitivity_according_to_window_state (XedWindow *window)
2200 {
2201 GtkAction *action;
2202
2203 /* We disable File->Quit/SaveAll/CloseAll while printing to avoid to have two
2204 operations (save and print/print preview) that uses the message area at
2205 the same time (may be we can remove this limitation in the future) */
2206 /* We disable File->Quit/CloseAll if state is saving since saving cannot be
2207 cancelled (may be we can remove this limitation in the future) */
2208 gtk_action_group_set_sensitive (
2209 window->priv->quit_action_group,
2210 !(window->priv->state & XED_WINDOW_STATE_SAVING)
2211 && !(window->priv->state & XED_WINDOW_STATE_PRINTING));
2212
2213 action = gtk_action_group_get_action (window->priv->action_group, "FileCloseAll");
2214 gtk_action_set_sensitive (
2215 action,
2216 !(window->priv->state & XED_WINDOW_STATE_SAVING)
2217 && !(window->priv->state & XED_WINDOW_STATE_PRINTING));
2218
2219 action = gtk_action_group_get_action (window->priv->action_group, "FileSaveAll");
2220 gtk_action_set_sensitive (action, !(window->priv->state & XED_WINDOW_STATE_PRINTING));
2221
2222 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
2223 gtk_action_set_sensitive (action, !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2224
2225 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileOpen");
2226 gtk_action_set_sensitive (action, !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2227
2228 gtk_action_group_set_sensitive (window->priv->recents_action_group,
2229 !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2230
2231 xed_notebook_set_close_buttons_sensitive (XED_NOTEBOOK(window->priv->notebook),
2232 !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2233
2234 xed_notebook_set_tab_drag_and_drop_enabled (XED_NOTEBOOK(window->priv->notebook),
2235 !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
2236
2237 if ((window->priv->state & XED_WINDOW_STATE_SAVING_SESSION) != 0)
2238 {
2239 /* TODO: If we really care, Find could be active
2240 * when in SAVING_SESSION state */
2241 if (gtk_action_group_get_sensitive (window->priv->action_group))
2242 {
2243 gtk_action_group_set_sensitive (window->priv->action_group, FALSE);
2244 }
2245 if (gtk_action_group_get_sensitive (window->priv->quit_action_group))
2246 {
2247 gtk_action_group_set_sensitive (window->priv->quit_action_group, FALSE);
2248 }
2249 if (gtk_action_group_get_sensitive (window->priv->close_action_group))
2250 {
2251 gtk_action_group_set_sensitive (window->priv->close_action_group, FALSE);
2252 }
2253 }
2254 else
2255 {
2256 if (!gtk_action_group_get_sensitive (window->priv->action_group))
2257 {
2258 gtk_action_group_set_sensitive (window->priv->action_group, window->priv->num_tabs > 0);
2259 }
2260 if (!gtk_action_group_get_sensitive (window->priv->quit_action_group))
2261 {
2262 gtk_action_group_set_sensitive (window->priv->quit_action_group, window->priv->num_tabs > 0);
2263 }
2264 if (!gtk_action_group_get_sensitive (window->priv->close_action_group))
2265 {
2266 gtk_action_group_set_sensitive (window->priv->close_action_group, window->priv->num_tabs > 0);
2267 }
2268 }
2269 }
2270
2271 static void
analyze_tab_state(XedTab * tab,XedWindow * window)2272 analyze_tab_state (XedTab *tab,
2273 XedWindow *window)
2274 {
2275 XedTabState ts;
2276
2277 ts = xed_tab_get_state (tab);
2278
2279 switch (ts)
2280 {
2281 case XED_TAB_STATE_LOADING:
2282 case XED_TAB_STATE_REVERTING:
2283 window->priv->state |= XED_WINDOW_STATE_LOADING;
2284 break;
2285 case XED_TAB_STATE_SAVING:
2286 window->priv->state |= XED_WINDOW_STATE_SAVING;
2287 break;
2288 case XED_TAB_STATE_PRINTING:
2289 case XED_TAB_STATE_PRINT_PREVIEWING:
2290 window->priv->state |= XED_WINDOW_STATE_PRINTING;
2291 break;
2292 case XED_TAB_STATE_LOADING_ERROR:
2293 case XED_TAB_STATE_REVERTING_ERROR:
2294 case XED_TAB_STATE_SAVING_ERROR:
2295 case XED_TAB_STATE_GENERIC_ERROR:
2296 window->priv->state |= XED_WINDOW_STATE_ERROR;
2297 ++window->priv->num_tabs_with_error;
2298 break;
2299 default:
2300 /* NOP */
2301 break;
2302 }
2303 }
2304
2305 static void
update_window_state(XedWindow * window)2306 update_window_state (XedWindow *window)
2307 {
2308 XedWindowState old_ws;
2309 gint old_num_of_errors;
2310
2311 xed_debug_message (DEBUG_WINDOW, "Old state: %x", window->priv->state);
2312
2313 old_ws = window->priv->state;
2314 old_num_of_errors = window->priv->num_tabs_with_error;
2315
2316 window->priv->state = old_ws & XED_WINDOW_STATE_SAVING_SESSION;
2317
2318 window->priv->num_tabs_with_error = 0;
2319
2320 gtk_container_foreach (GTK_CONTAINER(window->priv->notebook), (GtkCallback) analyze_tab_state, window);
2321
2322 xed_debug_message (DEBUG_WINDOW, "New state: %x", window->priv->state);
2323
2324 if (old_ws != window->priv->state)
2325 {
2326 set_sensitivity_according_to_window_state (window);
2327 xed_statusbar_set_window_state (XED_STATUSBAR(window->priv->statusbar), window->priv->state,
2328 window->priv->num_tabs_with_error);
2329 g_object_notify (G_OBJECT(window), "state");
2330 }
2331 else if (old_num_of_errors != window->priv->num_tabs_with_error)
2332 {
2333 xed_statusbar_set_window_state (XED_STATUSBAR(window->priv->statusbar), window->priv->state,
2334 window->priv->num_tabs_with_error);
2335 }
2336 }
2337
2338 static void
update_can_close(XedWindow * window)2339 update_can_close (XedWindow *window)
2340 {
2341 XedWindowPrivate *priv = window->priv;
2342 GList *tabs;
2343 GList *l;
2344 gboolean can_close = TRUE;
2345
2346 tabs = xed_notebook_get_all_tabs (XED_NOTEBOOK (priv->notebook));
2347
2348 for (l = tabs; l != NULL; l = g_list_next (l))
2349 {
2350 XedTab *tab = l->data;
2351
2352 if (!_xed_tab_get_can_close (tab))
2353 {
2354 can_close = FALSE;
2355 break;
2356 }
2357 }
2358
2359 if (can_close && (priv->inhibition_cookie != 0))
2360 {
2361 gtk_application_uninhibit (GTK_APPLICATION (g_application_get_default ()), priv->inhibition_cookie);
2362 priv->inhibition_cookie = 0;
2363 }
2364 else if (!can_close && (priv->inhibition_cookie == 0))
2365 {
2366 priv->inhibition_cookie = gtk_application_inhibit (GTK_APPLICATION (g_application_get_default ()),
2367 GTK_WINDOW (window),
2368 GTK_APPLICATION_INHIBIT_LOGOUT,
2369 _("There are unsaved documents"));
2370 }
2371
2372 g_list_free (tabs);
2373 }
2374
2375 static void
sync_state(XedTab * tab,GParamSpec * pspec,XedWindow * window)2376 sync_state (XedTab *tab,
2377 GParamSpec *pspec,
2378 XedWindow *window)
2379 {
2380 xed_debug (DEBUG_WINDOW);
2381 update_window_state (window);
2382 if (tab != window->priv->active_tab)
2383 {
2384 return;
2385 }
2386 set_sensitivity_according_to_tab (window, tab);
2387 g_signal_emit (G_OBJECT(window), signals[ACTIVE_TAB_STATE_CHANGED], 0);
2388 }
2389
2390 static void
sync_name(XedTab * tab,GParamSpec * pspec,XedWindow * window)2391 sync_name (XedTab *tab,
2392 GParamSpec *pspec,
2393 XedWindow *window)
2394 {
2395 GtkAction *action;
2396 gchar *action_name;
2397 gchar *tab_name;
2398 gchar *escaped_name;
2399 gchar *tip;
2400 gint n;
2401 XedDocument *doc;
2402
2403 if (tab == window->priv->active_tab)
2404 {
2405 set_title (window);
2406 doc = xed_tab_get_document (tab);
2407 action = gtk_action_group_get_action (window->priv->action_group, "FileRevert");
2408 gtk_action_set_sensitive (action, !xed_document_is_untitled (doc));
2409 }
2410
2411 /* sync the item in the documents list menu */
2412 n = gtk_notebook_page_num (GTK_NOTEBOOK(window->priv->notebook), GTK_WIDGET(tab));
2413 action_name = g_strdup_printf ("Tab_%d", n);
2414 action = gtk_action_group_get_action (window->priv->documents_list_action_group, action_name);
2415 g_free (action_name);
2416 g_return_if_fail(action != NULL);
2417
2418 tab_name = _xed_tab_get_name (tab);
2419 escaped_name = xed_utils_escape_underscores (tab_name, -1);
2420 tip = get_menu_tip_for_tab (tab);
2421
2422 g_object_set (action, "label", escaped_name, NULL);
2423 g_object_set (action, "tooltip", tip, NULL);
2424
2425 g_free (tab_name);
2426 g_free (escaped_name);
2427 g_free (tip);
2428
2429 peas_extension_set_call (window->priv->extensions, "update_state");
2430 }
2431
2432 static void
sync_can_close(XedTab * tab,GParamSpec * pspec,XedWindow * window)2433 sync_can_close (XedTab *tab,
2434 GParamSpec *pspec,
2435 XedWindow *window)
2436 {
2437 update_can_close (window);
2438 }
2439
2440 static XedWindow *
get_drop_window(GtkWidget * widget)2441 get_drop_window (GtkWidget *widget)
2442 {
2443 GtkWidget *target_window;
2444 target_window = gtk_widget_get_toplevel (widget);
2445 g_return_val_if_fail(XED_IS_WINDOW (target_window), NULL);
2446
2447 if ((XED_WINDOW(target_window)->priv->state & XED_WINDOW_STATE_SAVING_SESSION) != 0)
2448 {
2449 return NULL;
2450 }
2451
2452 return XED_WINDOW(target_window);
2453 }
2454
2455 static void
load_uris_from_drop(XedWindow * window,gchar ** uri_list)2456 load_uris_from_drop (XedWindow *window,
2457 gchar **uri_list)
2458 {
2459 GSList *locations = NULL;
2460 gint i;
2461 GSList *loaded;
2462
2463 if (uri_list == NULL)
2464 {
2465 return;
2466 }
2467
2468 for (i = 0; uri_list[i] != NULL; ++i)
2469 {
2470 locations = g_slist_prepend (locations, g_file_new_for_uri (uri_list[i]));
2471 }
2472
2473 locations = g_slist_reverse (locations);
2474 loaded = xed_commands_load_locations (window, locations, NULL, 0);
2475
2476 g_slist_free (loaded);
2477
2478 g_slist_foreach (locations, (GFunc) g_object_unref, NULL);
2479 g_slist_free (locations);
2480 }
2481
2482 /* Handle drops on the XedWindow */
2483 static void
drag_data_received_cb(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint timestamp,gpointer data)2484 drag_data_received_cb (GtkWidget *widget,
2485 GdkDragContext *context,
2486 gint x,
2487 gint y,
2488 GtkSelectionData *selection_data,
2489 guint info,
2490 guint timestamp,
2491 gpointer data)
2492 {
2493 XedWindow *window;
2494 gchar **uri_list;
2495
2496 window = get_drop_window (widget);
2497 if (window == NULL)
2498 {
2499 return;
2500 }
2501
2502 if (info == TARGET_URI_LIST)
2503 {
2504 uri_list = xed_utils_drop_get_uris (selection_data);
2505 load_uris_from_drop (window, uri_list);
2506 g_strfreev (uri_list);
2507 }
2508 }
2509
2510 /* Handle drops on the XedView */
2511 static void
drop_uris_cb(GtkWidget * widget,gchar ** uri_list)2512 drop_uris_cb (GtkWidget *widget,
2513 gchar **uri_list)
2514 {
2515 XedWindow *window;
2516 window = get_drop_window (widget);
2517 if (window == NULL)
2518 {
2519 return;
2520 }
2521 load_uris_from_drop (window, uri_list);
2522 }
2523
2524 static gboolean
on_fullscreen_controls_enter_notify_event(GtkWidget * widget,GdkEventCrossing * event,XedWindow * window)2525 on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
2526 GdkEventCrossing *event,
2527 XedWindow *window)
2528 {
2529 gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE);
2530
2531 return FALSE;
2532 }
2533
2534 static gboolean
on_fullscreen_controls_leave_notify_event(GtkWidget * widget,GdkEventCrossing * event,XedWindow * window)2535 on_fullscreen_controls_leave_notify_event (GtkWidget *widget,
2536 GdkEventCrossing *event,
2537 XedWindow *window)
2538 {
2539 GdkWindow *gdk_window;
2540 GdkDevice *device;
2541 GdkSeat *seat;
2542 gint x, y;
2543
2544 seat = gdk_display_get_default_seat (gdk_display_get_default ());
2545 device = gdk_seat_get_pointer (seat);
2546 gdk_window = gtk_widget_get_parent_window (widget);
2547
2548 gdk_window_get_device_position (gdk_window, device, &x, &y, NULL);
2549
2550 // sometimes the leave event is erroneously triggered when y = 0
2551 if (y != 0)
2552 {
2553 gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE);
2554 }
2555
2556 return FALSE;
2557 }
2558
2559 static void
fullscreen_controls_build(XedWindow * window)2560 fullscreen_controls_build (XedWindow *window)
2561 {
2562 XedWindowPrivate *priv = window->priv;
2563 GtkAction *action;
2564 GtkWidget *box;
2565 GtkWidget *toolbar;
2566 GtkToolItem *toolitem;
2567 GtkWidget *toolbox;
2568 GtkWidget *fullscreen_btn;
2569 GtkWidget *separator;
2570 GtkWidget *button;
2571
2572 if (priv->fullscreen_controls != NULL)
2573 {
2574 return;
2575 }
2576
2577 priv->fullscreen_controls = gtk_revealer_new ();
2578 gtk_widget_set_valign (priv->fullscreen_controls, GTK_ALIGN_START);
2579 gtk_container_add (GTK_CONTAINER (priv->fullscreen_eventbox), priv->fullscreen_controls);
2580
2581 toolbar = gtk_toolbar_new ();
2582 toolitem = gtk_tool_item_new ();
2583 gtk_tool_item_set_expand (toolitem, TRUE);
2584 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, 0);
2585
2586 toolbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2587 gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), "primary-toolbar");
2588 gtk_container_add (GTK_CONTAINER (toolitem), toolbox);
2589 gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), toolbar);
2590
2591 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2592 gtk_widget_set_vexpand (box, FALSE);
2593 gtk_box_pack_start (GTK_BOX (toolbox), box, FALSE, FALSE, 0);
2594
2595 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
2596 button = create_toolbar_button (action);
2597 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2598
2599 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileOpen");
2600 button = create_toolbar_button (action);
2601 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2602
2603 action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
2604 button = create_toolbar_button (action);
2605 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2606
2607 separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
2608 gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6);
2609
2610 action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
2611 button = create_toolbar_button (action);
2612 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2613
2614 action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
2615 button = create_toolbar_button (action);
2616 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2617
2618 separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
2619 gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6);
2620
2621 action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
2622 button = create_toolbar_button (action);
2623 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2624
2625 action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
2626 button = create_toolbar_button (action);
2627 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2628
2629 action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
2630 button = create_toolbar_button (action);
2631 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2632
2633 separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
2634 gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 6);
2635
2636 action = gtk_action_group_get_action (window->priv->action_group, "SearchFind");
2637 button = create_toolbar_button (action);
2638 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2639
2640 action = gtk_action_group_get_action (window->priv->action_group, "SearchReplace");
2641 button = create_toolbar_button (action);
2642 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
2643
2644 action = gtk_action_group_get_action (priv->always_sensitive_action_group, "LeaveFullscreen");
2645 g_object_set (action, "is-important", TRUE, NULL);
2646 fullscreen_btn = create_toolbar_button (action);
2647 gtk_box_pack_end (GTK_BOX (box), fullscreen_btn, FALSE, FALSE, 0);
2648
2649 gtk_widget_show_all (toolbox);
2650
2651 g_signal_connect (priv->fullscreen_eventbox, "enter-notify-event",
2652 G_CALLBACK (on_fullscreen_controls_enter_notify_event), window);
2653
2654 g_signal_connect (priv->fullscreen_eventbox, "leave-notify-event",
2655 G_CALLBACK (on_fullscreen_controls_leave_notify_event), window);
2656
2657 gtk_widget_set_size_request (priv->fullscreen_eventbox, -1, 1);
2658 }
2659
2660 static void
search_text_notify_cb(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2661 search_text_notify_cb (XedDocument *doc,
2662 GParamSpec *pspec,
2663 XedWindow *window)
2664 {
2665 gboolean sensitive;
2666 GtkAction *action;
2667
2668 if (doc != xed_window_get_active_document (window))
2669 {
2670 return;
2671 }
2672
2673 sensitive = TRUE;
2674
2675 action = gtk_action_group_get_action (window->priv->action_group, "SearchFindNext");
2676 gtk_action_set_sensitive (action, sensitive);
2677
2678 action = gtk_action_group_get_action (window->priv->action_group, "SearchFindPrevious");
2679 gtk_action_set_sensitive (action, sensitive);
2680 }
2681
2682 static void
can_undo(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2683 can_undo (XedDocument *doc,
2684 GParamSpec *pspec,
2685 XedWindow *window)
2686 {
2687 GtkAction *action;
2688 gboolean sensitive;
2689
2690 sensitive = gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER(doc));
2691
2692 if (doc != xed_window_get_active_document (window))
2693 {
2694 return;
2695 }
2696
2697 action = gtk_action_group_get_action (window->priv->action_group, "EditUndo");
2698 gtk_action_set_sensitive (action, sensitive);
2699 }
2700
2701 static void
can_redo(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2702 can_redo (XedDocument *doc,
2703 GParamSpec *pspec,
2704 XedWindow *window)
2705 {
2706 GtkAction *action;
2707 gboolean sensitive;
2708
2709 sensitive = gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER(doc));
2710
2711 if (doc != xed_window_get_active_document (window))
2712 {
2713 return;
2714 }
2715
2716 action = gtk_action_group_get_action (window->priv->action_group, "EditRedo");
2717 gtk_action_set_sensitive (action, sensitive);
2718 }
2719
2720 static void
selection_changed(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2721 selection_changed (XedDocument *doc,
2722 GParamSpec *pspec,
2723 XedWindow *window)
2724 {
2725 XedTab *tab;
2726 XedView *view;
2727 GtkAction *action;
2728 XedTabState state;
2729 gboolean state_normal;
2730 gboolean editable;
2731
2732 xed_debug (DEBUG_WINDOW);
2733
2734 if (doc != xed_window_get_active_document (window))
2735 {
2736 return;
2737 }
2738
2739 tab = xed_tab_get_from_document (doc);
2740 state = xed_tab_get_state (tab);
2741 state_normal = (state == XED_TAB_STATE_NORMAL);
2742
2743 view = xed_tab_get_view (tab);
2744 editable = gtk_text_view_get_editable (GTK_TEXT_VIEW(view));
2745
2746 action = gtk_action_group_get_action (window->priv->action_group, "EditCut");
2747 gtk_action_set_sensitive (action,
2748 state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
2749
2750 action = gtk_action_group_get_action (window->priv->action_group, "EditCopy");
2751 gtk_action_set_sensitive (action,
2752 (state_normal || state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
2753 && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
2754
2755 action = gtk_action_group_get_action (window->priv->action_group, "EditDelete");
2756 gtk_action_set_sensitive (action,
2757 state_normal && editable && gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER(doc)));
2758
2759 peas_extension_set_call (window->priv->extensions, "update_state");
2760 }
2761
2762 static void
sync_languages_menu(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2763 sync_languages_menu (XedDocument *doc,
2764 GParamSpec *pspec,
2765 XedWindow *window)
2766 {
2767 peas_extension_set_call (window->priv->extensions, "update_state");
2768 }
2769
2770 static void
readonly_changed(XedDocument * doc,GParamSpec * pspec,XedWindow * window)2771 readonly_changed (XedDocument *doc,
2772 GParamSpec *pspec,
2773 XedWindow *window)
2774 {
2775 set_sensitivity_according_to_tab (window, window->priv->active_tab);
2776 sync_name (window->priv->active_tab, NULL, window);
2777 peas_extension_set_call (window->priv->extensions, "update_state");
2778 }
2779
2780 static void
editable_changed(XedView * view,GParamSpec * arg1,XedWindow * window)2781 editable_changed (XedView *view,
2782 GParamSpec *arg1,
2783 XedWindow *window)
2784 {
2785 peas_extension_set_call (window->priv->extensions, "update_state");
2786 }
2787
2788 static void
update_sensitivity_according_to_open_tabs(XedWindow * window)2789 update_sensitivity_according_to_open_tabs (XedWindow *window)
2790 {
2791 GtkAction *action;
2792
2793 /* Set sensitivity */
2794 gtk_action_group_set_sensitive (window->priv->action_group, window->priv->num_tabs != 0);
2795
2796 action = gtk_action_group_get_action (window->priv->action_group, "DocumentsMoveToNewWindow");
2797 gtk_action_set_sensitive (action, window->priv->num_tabs > 1);
2798 gtk_action_group_set_sensitive (window->priv->close_action_group, window->priv->num_tabs != 0);
2799 }
2800
2801 static void
notebook_tab_added(XedNotebook * notebook,XedTab * tab,XedWindow * window)2802 notebook_tab_added (XedNotebook *notebook,
2803 XedTab *tab,
2804 XedWindow *window)
2805 {
2806 XedView *view;
2807 XedDocument *doc;
2808
2809 xed_debug (DEBUG_WINDOW);
2810
2811 g_return_if_fail((window->priv->state & XED_WINDOW_STATE_SAVING_SESSION) == 0);
2812
2813 ++window->priv->num_tabs;
2814
2815 update_sensitivity_according_to_open_tabs (window);
2816
2817 view = xed_tab_get_view (tab);
2818 doc = xed_tab_get_document (tab);
2819
2820 /* IMPORTANT: remember to disconnect the signal in notebook_tab_removed
2821 * if a new signal is connected here */
2822
2823 g_signal_connect (tab, "notify::name", G_CALLBACK (sync_name), window);
2824 g_signal_connect (tab, "notify::state", G_CALLBACK (sync_state), window);
2825 g_signal_connect (tab, "notify::can-close", G_CALLBACK (sync_can_close), window);
2826
2827 g_signal_connect (doc, "cursor-moved", G_CALLBACK (update_cursor_position_statusbar), window);
2828 g_signal_connect (doc, "notify::search-text", G_CALLBACK (search_text_notify_cb), window);
2829 g_signal_connect (doc, "notify::can-undo", G_CALLBACK (can_undo), window);
2830 g_signal_connect (doc, "notify::can-redo", G_CALLBACK (can_redo), window);
2831 g_signal_connect (doc, "notify::has-selection", G_CALLBACK (selection_changed), window);
2832 g_signal_connect (doc, "notify::language", G_CALLBACK (sync_languages_menu), window);
2833 g_signal_connect (doc, "notify::read-only", G_CALLBACK (readonly_changed), window);
2834 g_signal_connect (view, "toggle_overwrite", G_CALLBACK (update_overwrite_mode_statusbar), window);
2835 g_signal_connect (view, "notify::editable", G_CALLBACK (editable_changed), window);
2836
2837 update_documents_list_menu (window);
2838
2839 g_signal_connect(view, "drop_uris", G_CALLBACK (drop_uris_cb), NULL);
2840
2841 update_window_state (window);
2842 update_can_close (window);
2843
2844 g_signal_emit (G_OBJECT(window), signals[TAB_ADDED], 0, tab);
2845 }
2846
2847 static void
notebook_tab_removed(XedNotebook * notebook,XedTab * tab,XedWindow * window)2848 notebook_tab_removed (XedNotebook *notebook,
2849 XedTab *tab,
2850 XedWindow *window)
2851 {
2852 XedView *view;
2853 XedViewFrame *frame;
2854 XedDocument *doc;
2855
2856 xed_debug (DEBUG_WINDOW);
2857
2858 g_return_if_fail((window->priv->state & XED_WINDOW_STATE_SAVING_SESSION) == 0);
2859
2860 --window->priv->num_tabs;
2861
2862 view = xed_tab_get_view (tab);
2863 frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab));
2864 doc = xed_tab_get_document (tab);
2865
2866 g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_name), window);
2867 g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_state), window);
2868 g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_can_close), window);
2869 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (update_cursor_position_statusbar), window);
2870 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (search_text_notify_cb), window);
2871 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (can_undo), window);
2872 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (can_redo), window);
2873 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (selection_changed), window);
2874 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (sync_languages_menu), window);
2875 g_signal_handlers_disconnect_by_func (doc, G_CALLBACK (readonly_changed), window);
2876 g_signal_handlers_disconnect_by_func (view, G_CALLBACK (update_overwrite_mode_statusbar), window);
2877 g_signal_handlers_disconnect_by_func (view, G_CALLBACK (editable_changed), window);
2878 g_signal_handlers_disconnect_by_func (view, G_CALLBACK (drop_uris_cb), NULL);
2879
2880 if (window->priv->tab_width_id && tab == xed_window_get_active_tab (window))
2881 {
2882 g_signal_handler_disconnect (view, window->priv->tab_width_id);
2883 window->priv->tab_width_id = 0;
2884 }
2885
2886 if (window->priv->spaces_instead_of_tabs_id && tab == xed_window_get_active_tab (window))
2887 {
2888 g_signal_handler_disconnect (view, window->priv->spaces_instead_of_tabs_id);
2889 window->priv->spaces_instead_of_tabs_id = 0;
2890 }
2891
2892 if (window->priv->language_changed_id && tab == xed_window_get_active_tab (window))
2893 {
2894 g_signal_handler_disconnect (doc, window->priv->language_changed_id);
2895 window->priv->language_changed_id = 0;
2896 }
2897
2898 if (window->priv->use_word_wrap_id && tab == xed_window_get_active_tab (window))
2899 {
2900 g_signal_handler_disconnect (view, window->priv->use_word_wrap_id);
2901 window->priv->use_word_wrap_id = 0;
2902 }
2903
2904 if (window->priv->show_overview_map_id && tab == xed_window_get_active_tab (window))
2905 {
2906 g_signal_handler_disconnect (xed_view_frame_get_map_frame (frame), window->priv->show_overview_map_id);
2907 window->priv->show_overview_map_id = 0;
2908 }
2909
2910 g_return_if_fail(window->priv->num_tabs >= 0);
2911 if (window->priv->num_tabs == 0)
2912 {
2913 window->priv->active_tab = NULL;
2914 set_title (window);
2915
2916 /* Remove line and col info */
2917 xed_statusbar_set_cursor_position (XED_STATUSBAR(window->priv->statusbar), -1, -1);
2918
2919 xed_statusbar_clear_overwrite (XED_STATUSBAR(window->priv->statusbar));
2920
2921 /* hide the combos */
2922 gtk_widget_hide (window->priv->tab_width_button);
2923 gtk_widget_hide (window->priv->language_button);
2924 }
2925
2926 if (!window->priv->removing_tabs || window->priv->num_tabs == 0)
2927 {
2928 update_documents_list_menu (window);
2929 update_next_prev_doc_sensitivity_per_window (window);
2930 }
2931
2932 update_sensitivity_according_to_open_tabs (window);
2933
2934 if (window->priv->num_tabs == 0)
2935 {
2936 peas_extension_set_call (window->priv->extensions, "update_state");
2937 }
2938
2939 update_window_state (window);
2940 update_can_close (window);
2941
2942 g_signal_emit (G_OBJECT(window), signals[TAB_REMOVED], 0, tab);
2943 }
2944
2945 static void
notebook_tabs_reordered(XedNotebook * notebook,XedWindow * window)2946 notebook_tabs_reordered (XedNotebook *notebook,
2947 XedWindow *window)
2948 {
2949 update_documents_list_menu (window);
2950 update_next_prev_doc_sensitivity_per_window (window);
2951 g_signal_emit (G_OBJECT(window), signals[TABS_REORDERED], 0);
2952 }
2953
2954 static void
notebook_tab_detached(XedNotebook * notebook,XedTab * tab,XedWindow * window)2955 notebook_tab_detached (XedNotebook *notebook,
2956 XedTab *tab,
2957 XedWindow *window)
2958 {
2959 XedWindow *new_window;
2960
2961 new_window = clone_window (window);
2962
2963 xed_notebook_move_tab (notebook, XED_NOTEBOOK(_xed_window_get_notebook (new_window)), tab, 0);
2964
2965 gtk_window_set_position (GTK_WINDOW(new_window), GTK_WIN_POS_MOUSE);
2966
2967 gtk_widget_show (GTK_WIDGET(new_window));
2968 }
2969
2970 static void
notebook_tab_close_request(XedNotebook * notebook,XedTab * tab,GtkWindow * window)2971 notebook_tab_close_request (XedNotebook *notebook,
2972 XedTab *tab,
2973 GtkWindow *window)
2974 {
2975 /* Note: we are destroying the tab before the default handler
2976 * seems to be ok, but we need to keep an eye on this. */
2977 _xed_cmd_file_close_tab (tab, XED_WINDOW(window));
2978 }
2979
2980 static gboolean
show_notebook_popup_menu(GtkNotebook * notebook,XedWindow * window,GdkEventButton * event)2981 show_notebook_popup_menu (GtkNotebook *notebook,
2982 XedWindow *window,
2983 GdkEventButton *event)
2984 {
2985 GtkWidget *menu;
2986 // GtkAction *action;
2987
2988 menu = gtk_ui_manager_get_widget (window->priv->manager, "/NotebookPopup");
2989 g_return_val_if_fail(menu != NULL, FALSE);
2990
2991 // CHECK do we need this?
2992 #if 0
2993 /* allow extensions to sync when showing the popup */
2994 action = gtk_action_group_get_action (window->priv->action_group,
2995 "NotebookPopupAction");
2996 g_return_val_if_fail (action != NULL, FALSE);
2997 gtk_action_activate (action);
2998 #endif
2999 if (event != NULL)
3000 {
3001 gtk_menu_popup_at_pointer (GTK_MENU(menu), (GdkEvent *) event);
3002
3003 }
3004 else
3005 {
3006 GtkWidget *tab;
3007 GtkWidget *tab_label;
3008
3009 tab = GTK_WIDGET (xed_window_get_active_tab (window));
3010 g_return_val_if_fail (tab != NULL, FALSE);
3011
3012 tab_label = gtk_notebook_get_tab_label (notebook, tab);
3013
3014 gtk_menu_popup_at_widget (GTK_MENU (menu), tab_label, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL);
3015
3016 gtk_menu_shell_select_first (GTK_MENU_SHELL(menu), FALSE);
3017 }
3018
3019 return TRUE;
3020 }
3021
3022 static gboolean
notebook_button_press_event(GtkNotebook * notebook,GdkEventButton * event,XedWindow * window)3023 notebook_button_press_event (GtkNotebook *notebook,
3024 GdkEventButton *event,
3025 XedWindow *window)
3026 {
3027 if (GDK_BUTTON_PRESS == event->type && 3 == event->button)
3028 {
3029 return show_notebook_popup_menu (notebook, window, event);
3030 }
3031 else if (GDK_BUTTON_PRESS == event->type && 2 == event->button)
3032 {
3033 XedTab *tab;
3034 tab = xed_window_get_active_tab (window);
3035 notebook_tab_close_request (XED_NOTEBOOK(notebook), tab, GTK_WINDOW(window));
3036 return FALSE;
3037 }
3038 return FALSE;
3039 }
3040
3041 static gboolean
notebook_popup_menu(GtkNotebook * notebook,XedWindow * window)3042 notebook_popup_menu (GtkNotebook *notebook,
3043 XedWindow *window)
3044 {
3045 /* Only respond if the notebook is the actual focus */
3046 if (XED_IS_NOTEBOOK(gtk_window_get_focus (GTK_WINDOW (window))))
3047 {
3048 return show_notebook_popup_menu (notebook, window, NULL);
3049 }
3050 return FALSE;
3051 }
3052
3053 static void
side_panel_size_allocate(GtkWidget * widget,GtkAllocation * allocation,XedWindow * window)3054 side_panel_size_allocate (GtkWidget *widget,
3055 GtkAllocation *allocation,
3056 XedWindow *window)
3057 {
3058 if (!xed_paned_get_is_animating (XED_PANED (window->priv->hpaned)))
3059 {
3060 window->priv->side_panel_size = allocation->width;
3061 }
3062 }
3063
3064 static void
bottom_panel_size_allocate(GtkWidget * widget,GtkAllocation * allocation,XedWindow * window)3065 bottom_panel_size_allocate (GtkWidget *widget,
3066 GtkAllocation *allocation,
3067 XedWindow *window)
3068 {
3069 if (!xed_paned_get_is_animating (XED_PANED (window->priv->vpaned)))
3070 {
3071 window->priv->bottom_panel_size = allocation->height;
3072 }
3073 }
3074
3075 static void
hpaned_restore_position(GtkWidget * widget,XedWindow * window)3076 hpaned_restore_position (GtkWidget *widget,
3077 XedWindow *window)
3078 {
3079 gint pos;
3080 xed_debug_message (DEBUG_WINDOW, "Restoring hpaned position: side panel size %d", window->priv->side_panel_size);
3081
3082 pos = MAX(100, window->priv->side_panel_size);
3083 gtk_paned_set_position (GTK_PANED(window->priv->hpaned), pos);
3084
3085 /* start monitoring the size */
3086 g_signal_connect(window->priv->side_panel, "size-allocate", G_CALLBACK (side_panel_size_allocate), window);
3087
3088 /* run this only once */
3089 g_signal_handlers_disconnect_by_func(widget, hpaned_restore_position, window);
3090 }
3091
3092 static void
vpaned_restore_position(GtkWidget * widget,XedWindow * window)3093 vpaned_restore_position (GtkWidget *widget,
3094 XedWindow *window)
3095 {
3096 GtkAllocation allocation;
3097 gint pos;
3098
3099 gtk_widget_get_allocation (widget, &allocation);
3100
3101 xed_debug_message (DEBUG_WINDOW, "Restoring vpaned position: bottom panel size %d",
3102 window->priv->bottom_panel_size);
3103
3104 pos = allocation.height - MAX(50, window->priv->bottom_panel_size);
3105 gtk_paned_set_position (GTK_PANED(window->priv->vpaned), pos);
3106
3107 /* start monitoring the size */
3108 g_signal_connect(window->priv->bottom_panel, "size-allocate", G_CALLBACK (bottom_panel_size_allocate), window);
3109
3110 /* run this only once */
3111 g_signal_handlers_disconnect_by_func(widget, vpaned_restore_position, window);
3112 }
3113
3114 static void
side_panel_visibility_changed(GtkWidget * side_panel,XedWindow * window)3115 side_panel_visibility_changed (GtkWidget *side_panel,
3116 XedWindow *window)
3117 {
3118 gboolean visible;
3119 GtkAction *action;
3120
3121 visible = gtk_widget_get_visible (side_panel);
3122
3123 g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_SIDE_PANEL_VISIBLE, visible);
3124
3125 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewSidePane");
3126
3127 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
3128 {
3129 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
3130 }
3131
3132 /* focus the document */
3133 if (!visible && window->priv->active_tab != NULL)
3134 {
3135 gtk_widget_grab_focus (GTK_WIDGET(xed_tab_get_view (XED_TAB (window->priv->active_tab))));
3136 }
3137 }
3138
3139 static void
create_side_panel(XedWindow * window)3140 create_side_panel (XedWindow *window)
3141 {
3142 GtkWidget *documents_panel;
3143 xed_debug (DEBUG_WINDOW);
3144
3145 window->priv->side_panel = xed_panel_new (GTK_ORIENTATION_VERTICAL);
3146
3147 gtk_paned_pack1 (GTK_PANED (window->priv->hpaned), window->priv->side_panel, FALSE, TRUE);
3148
3149 g_signal_connect_after (window->priv->side_panel, "show", G_CALLBACK (side_panel_visibility_changed), window);
3150 g_signal_connect_after (window->priv->side_panel, "hide", G_CALLBACK (side_panel_visibility_changed), window);
3151
3152 documents_panel = xed_documents_panel_new (window);
3153 xed_panel_add_item (XED_PANEL (window->priv->side_panel), documents_panel, _("Documents"), "text-x-generic");
3154 }
3155
3156 static void
bottom_panel_visibility_changed(XedPanel * bottom_panel,XedWindow * window)3157 bottom_panel_visibility_changed (XedPanel *bottom_panel,
3158 XedWindow *window)
3159 {
3160 gboolean visible;
3161 GtkAction *action;
3162
3163 visible = gtk_widget_get_visible (GTK_WIDGET (bottom_panel));
3164
3165 g_settings_set_boolean (window->priv->ui_settings, XED_SETTINGS_BOTTOM_PANEL_VISIBLE, visible);
3166
3167 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3168
3169 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)) != visible)
3170 {
3171 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), visible);
3172 }
3173
3174 /* focus the document */
3175 if (!visible && window->priv->active_tab != NULL)
3176 {
3177 gtk_widget_grab_focus (GTK_WIDGET(xed_tab_get_view (XED_TAB (window->priv->active_tab))));
3178 }
3179 }
3180
3181 static void
bottom_panel_item_removed(XedPanel * panel,GtkWidget * item,XedWindow * window)3182 bottom_panel_item_removed (XedPanel *panel,
3183 GtkWidget *item,
3184 XedWindow *window)
3185 {
3186 if (xed_panel_get_n_items (panel) == 0)
3187 {
3188 GtkAction *action;
3189
3190 xed_paned_close (XED_PANED (window->priv->vpaned), 2);
3191 gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE);
3192 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3193 gtk_action_set_sensitive (action, FALSE);
3194 }
3195 }
3196
3197 static void
bottom_panel_item_added(XedPanel * panel,GtkWidget * item,XedWindow * window)3198 bottom_panel_item_added (XedPanel *panel,
3199 GtkWidget *item,
3200 XedWindow *window)
3201 {
3202 /* if it's the first item added, set the menu item
3203 * sensitive and if needed show the panel */
3204 if (xed_panel_get_n_items (panel) == 1)
3205 {
3206 GtkAction *action;
3207 gboolean show;
3208
3209 gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), TRUE);
3210
3211 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3212 gtk_action_set_sensitive (action, TRUE);
3213 show = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3214 if (show)
3215 {
3216 gtk_widget_show (GTK_WIDGET(panel));
3217 }
3218 }
3219 }
3220
3221 static void
create_bottom_panel(XedWindow * window)3222 create_bottom_panel (XedWindow *window)
3223 {
3224 xed_debug (DEBUG_WINDOW);
3225 window->priv->bottom_panel = xed_panel_new (GTK_ORIENTATION_HORIZONTAL);
3226 gtk_paned_pack2 (GTK_PANED (window->priv->vpaned), window->priv->bottom_panel, FALSE, TRUE);
3227 g_signal_connect_after(window->priv->bottom_panel, "show", G_CALLBACK (bottom_panel_visibility_changed), window);
3228 g_signal_connect_after(window->priv->bottom_panel, "hide", G_CALLBACK (bottom_panel_visibility_changed), window);
3229 }
3230
3231 static void
init_panels_visibility(XedWindow * window)3232 init_panels_visibility (XedWindow *window)
3233 {
3234 gint active_page;
3235 gboolean side_panel_visible;
3236 gboolean bottom_panel_visible;
3237
3238 xed_debug (DEBUG_WINDOW);
3239
3240 /* side pane */
3241 active_page = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_ACTIVE_PAGE);
3242 _xed_panel_set_active_item_by_id (XED_PANEL (window->priv->side_panel), active_page);
3243
3244 side_panel_visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_SIDE_PANEL_VISIBLE);
3245 bottom_panel_visible = g_settings_get_boolean (window->priv->ui_settings, XED_SETTINGS_BOTTOM_PANEL_VISIBLE);
3246
3247 if (side_panel_visible)
3248 {
3249 gtk_widget_show (window->priv->side_panel);
3250 }
3251
3252 /* bottom pane, it can be empty */
3253 if (xed_panel_get_n_items (XED_PANEL (window->priv->bottom_panel)) > 0)
3254 {
3255 active_page = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE);
3256 _xed_panel_set_active_item_by_id (XED_PANEL(window->priv->bottom_panel), active_page);
3257
3258 if (bottom_panel_visible)
3259 {
3260 gtk_widget_show (window->priv->bottom_panel);
3261 }
3262
3263 gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), TRUE);
3264 }
3265 else
3266 {
3267 GtkAction *action;
3268
3269 action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
3270 gtk_action_set_sensitive (action, FALSE);
3271 gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE);
3272 }
3273
3274 /* start track sensitivity after the initial state is set */
3275 window->priv->bottom_panel_item_removed_handler_id =
3276 g_signal_connect (window->priv->bottom_panel, "item_removed",
3277 G_CALLBACK (bottom_panel_item_removed), window);
3278
3279 g_signal_connect(window->priv->bottom_panel, "item_added", G_CALLBACK (bottom_panel_item_added), window);
3280 }
3281
3282 static void
clipboard_owner_change(GtkClipboard * clipboard,GdkEventOwnerChange * event,XedWindow * window)3283 clipboard_owner_change (GtkClipboard *clipboard,
3284 GdkEventOwnerChange *event,
3285 XedWindow *window)
3286 {
3287 set_paste_sensitivity_according_to_clipboard (window, clipboard);
3288 }
3289
3290 static void
window_realized(GtkWidget * window,gpointer * data)3291 window_realized (GtkWidget *window,
3292 gpointer *data)
3293 {
3294 GtkClipboard *clipboard;
3295 clipboard = gtk_widget_get_clipboard (window, GDK_SELECTION_CLIPBOARD);
3296 g_signal_connect(clipboard, "owner_change", G_CALLBACK (clipboard_owner_change), window);
3297 }
3298
3299 static void
window_unrealized(GtkWidget * window,gpointer * data)3300 window_unrealized (GtkWidget *window,
3301 gpointer *data)
3302 {
3303 GtkClipboard *clipboard;
3304 clipboard = gtk_widget_get_clipboard (window, GDK_SELECTION_CLIPBOARD);
3305 g_signal_handlers_disconnect_by_func(clipboard, G_CALLBACK (clipboard_owner_change), window);
3306 }
3307
3308 static void
check_window_is_active(XedWindow * window,GParamSpec * property,gpointer useless)3309 check_window_is_active (XedWindow *window,
3310 GParamSpec *property,
3311 gpointer useless)
3312 {
3313 if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
3314 {
3315 gtk_widget_set_visible (window->priv->fullscreen_eventbox, gtk_window_is_active (GTK_WINDOW (window)));
3316 }
3317 }
3318
3319 static void
connect_notebook_signals(XedWindow * window,GtkWidget * notebook)3320 connect_notebook_signals (XedWindow *window,
3321 GtkWidget *notebook)
3322 {
3323 g_signal_connect(notebook, "switch-page", G_CALLBACK (notebook_switch_page), window);
3324 g_signal_connect(notebook, "tab-added", G_CALLBACK (notebook_tab_added), window);
3325 g_signal_connect(notebook, "tab-removed", G_CALLBACK (notebook_tab_removed), window);
3326 g_signal_connect(notebook, "tabs-reordered", G_CALLBACK (notebook_tabs_reordered), window);
3327 g_signal_connect(notebook, "tab-detached", G_CALLBACK (notebook_tab_detached), window);
3328 g_signal_connect(notebook, "tab-close-request", G_CALLBACK (notebook_tab_close_request), window);
3329 g_signal_connect(notebook, "button-press-event", G_CALLBACK (notebook_button_press_event), window);
3330 g_signal_connect(notebook, "popup-menu", G_CALLBACK (notebook_popup_menu), window);
3331 }
3332
3333 static void
add_notebook(XedWindow * window,GtkWidget * notebook)3334 add_notebook (XedWindow *window,
3335 GtkWidget *notebook)
3336 {
3337 gtk_paned_pack1 (GTK_PANED(window->priv->vpaned), notebook, TRUE, TRUE);
3338 gtk_widget_show (notebook);
3339
3340 // xed_notebook_set_tab_scrolling_enabled (XED_NOTEBOOK (notebook), xed_prefs_manager_get_enable_tab_scrolling ());
3341
3342 connect_notebook_signals (window, notebook);
3343 }
3344
3345 static void
extension_added(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,XedWindow * window)3346 extension_added (PeasExtensionSet *extensions,
3347 PeasPluginInfo *info,
3348 PeasExtension *exten,
3349 XedWindow *window)
3350 {
3351 peas_extension_call (exten, "activate");
3352 }
3353
3354 static void
extension_removed(PeasExtensionSet * extensions,PeasPluginInfo * info,PeasExtension * exten,XedWindow * window)3355 extension_removed (PeasExtensionSet *extensions,
3356 PeasPluginInfo *info,
3357 PeasExtension *exten,
3358 XedWindow *window)
3359 {
3360 peas_extension_call (exten, "deactivate");
3361
3362 /* Ensure update of the ui manager, because we suspect it does something with expected static strings in the
3363 * type module (when unloaded the strings don't exist anymore, and the ui manager update in a idle func) */
3364 gtk_ui_manager_ensure_update (window->priv->manager);
3365 }
3366
3367 static void
xed_window_init(XedWindow * window)3368 xed_window_init (XedWindow *window)
3369 {
3370 GtkWidget *main_box;
3371 GtkTargetList *tl;
3372
3373 xed_debug (DEBUG_WINDOW);
3374
3375 window->priv = xed_window_get_instance_private (window);
3376 window->priv->active_tab = NULL;
3377 window->priv->num_tabs = 0;
3378 window->priv->removing_tabs = FALSE;
3379 window->priv->state = XED_WINDOW_STATE_NORMAL;
3380 window->priv->inhibition_cookie = 0;
3381 window->priv->dispose_has_run = FALSE;
3382 window->priv->fullscreen_controls = NULL;
3383 window->priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor");
3384 window->priv->ui_settings = g_settings_new ("org.x.editor.preferences.ui");
3385
3386 /* Window settings are applied only once the window is closed. We do not want
3387 to keep writing to disk when the window is dragged around */
3388 window->priv->window_settings = g_settings_new ("org.x.editor.state.window");
3389 g_settings_delay (window->priv->window_settings);
3390
3391 window->priv->message_bus = xed_message_bus_new ();
3392
3393 window->priv->window_group = gtk_window_group_new ();
3394 gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window));
3395
3396 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "xed-window");
3397
3398 main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3399 window->priv->fullscreen_overlay = gtk_overlay_new ();
3400 gtk_container_add (GTK_CONTAINER (window->priv->fullscreen_overlay), main_box);
3401 gtk_container_add (GTK_CONTAINER (window), window->priv->fullscreen_overlay);
3402 gtk_widget_show (window->priv->fullscreen_overlay);
3403 gtk_widget_show (main_box);
3404
3405 window->priv->fullscreen_eventbox = gtk_event_box_new ();
3406 gtk_widget_set_valign (window->priv->fullscreen_eventbox, GTK_ALIGN_START);
3407 gtk_overlay_add_overlay (GTK_OVERLAY (window->priv->fullscreen_overlay), window->priv->fullscreen_eventbox);
3408
3409 /* Add menu bar and toolbar bar */
3410 create_menu_bar_and_toolbar (window, main_box);
3411
3412 /* If we're running as root, add and infobar to warn about elevated privileges */
3413 if (geteuid () == 0)
3414 {
3415 GtkWidget *root_bar = gtk_info_bar_new ();
3416 gtk_info_bar_set_message_type (GTK_INFO_BAR (root_bar), GTK_MESSAGE_ERROR);
3417 GtkWidget *content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (root_bar));
3418 GtkWidget *label = gtk_label_new (_("Elevated Privileges"));
3419 gtk_widget_show (label);
3420 gtk_container_add (GTK_CONTAINER (content_area), label);
3421 gtk_box_pack_start (GTK_BOX (main_box), root_bar, FALSE, FALSE, 0);
3422 gtk_widget_set_visible (root_bar, TRUE);
3423 }
3424
3425 /* Add status bar */
3426 create_statusbar (window, main_box);
3427
3428 /* Add the main area */
3429 xed_debug_message (DEBUG_WINDOW, "Add main area");
3430 window->priv->hpaned = xed_paned_new (GTK_ORIENTATION_HORIZONTAL);
3431 gtk_box_pack_start (GTK_BOX (main_box), window->priv->hpaned, TRUE, TRUE, 0);
3432
3433 window->priv->vpaned = xed_paned_new (GTK_ORIENTATION_VERTICAL);
3434 gtk_paned_pack2 (GTK_PANED (window->priv->hpaned), window->priv->vpaned, TRUE, FALSE);
3435
3436 xed_debug_message (DEBUG_WINDOW, "Create xed notebook");
3437 window->priv->notebook = xed_notebook_new ();
3438 add_notebook (window, window->priv->notebook);
3439
3440 /* side and bottom panels */
3441 create_side_panel (window);
3442 create_bottom_panel (window);
3443
3444 /* panes' state must be restored after panels have been mapped,
3445 * since the bottom pane position depends on the size of the vpaned. */
3446 window->priv->side_panel_size = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_SIDE_PANEL_SIZE);
3447 window->priv->bottom_panel_size = g_settings_get_int (window->priv->window_settings, XED_SETTINGS_BOTTOM_PANEL_SIZE);
3448
3449 g_signal_connect_after(window->priv->hpaned, "map", G_CALLBACK (hpaned_restore_position), window);
3450 g_signal_connect_after(window->priv->vpaned, "map", G_CALLBACK (vpaned_restore_position), window);
3451
3452 gtk_widget_show (window->priv->hpaned);
3453 gtk_widget_show (window->priv->vpaned);
3454
3455 /* Drag and drop support, set targets to NULL because we add the
3456 default uri_targets below */
3457 gtk_drag_dest_set (GTK_WIDGET(window), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
3458 NULL, 0, GDK_ACTION_COPY);
3459
3460 /* Add uri targets */
3461 tl = gtk_drag_dest_get_target_list (GTK_WIDGET (window));
3462
3463 if (tl == NULL)
3464 {
3465 tl = gtk_target_list_new (NULL, 0);
3466 gtk_drag_dest_set_target_list (GTK_WIDGET (window), tl);
3467 gtk_target_list_unref (tl);
3468 }
3469
3470 gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
3471
3472 /* connect instead of override, so that we can share the cb code with the view */
3473 g_signal_connect (window, "drag_data_received", G_CALLBACK (drag_data_received_cb), NULL);
3474
3475 /* we can get the clipboard only after the widget is realized */
3476 g_signal_connect (window, "realize", G_CALLBACK (window_realized), NULL);
3477 g_signal_connect (window, "unrealize", G_CALLBACK (window_unrealized), NULL);
3478
3479 /* Check if the window is active for fullscreen */
3480 g_signal_connect (window, "notify::is-active", G_CALLBACK (check_window_is_active), NULL);
3481
3482 g_signal_connect (GTK_WIDGET (window), "key-press-event", G_CALLBACK (on_key_pressed), window);
3483
3484 xed_debug_message (DEBUG_WINDOW, "Update plugins ui");
3485
3486 window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (xed_plugins_engine_get_default ()),
3487 XED_TYPE_WINDOW_ACTIVATABLE, "window", window, NULL);
3488
3489 g_signal_connect (window->priv->extensions, "extension-added", G_CALLBACK (extension_added), window);
3490 g_signal_connect (window->priv->extensions, "extension-removed", G_CALLBACK (extension_removed), window);
3491
3492 peas_extension_set_call (window->priv->extensions, "activate");
3493
3494 /* set visibility of panes.
3495 * This needs to be done after plugins activatation */
3496 init_panels_visibility (window);
3497
3498 update_sensitivity_according_to_open_tabs (window);
3499
3500 xed_debug_message (DEBUG_WINDOW, "END");
3501 }
3502
3503 /**
3504 * xed_window_get_active_view:
3505 * @window: a #XedWindow
3506 *
3507 * Gets the active #XedView.
3508 *
3509 * Returns: (transfer none): the active #XedView
3510 */
3511 XedView *
xed_window_get_active_view(XedWindow * window)3512 xed_window_get_active_view (XedWindow *window)
3513 {
3514 XedView *view;
3515
3516 if (window == NULL)
3517 {
3518 return NULL;
3519 }
3520
3521 if (window->priv->active_tab == NULL)
3522 {
3523 return NULL;
3524 }
3525
3526 view = xed_tab_get_view (XED_TAB (window->priv->active_tab));
3527
3528 return view;
3529 }
3530
3531 /**
3532 * xed_window_get_active_document:
3533 * @window: a #XedWindow
3534 *
3535 * Gets the active #XedDocument.
3536 *
3537 * Returns: (transfer none): the active #XedDocument
3538 */
3539 XedDocument *
xed_window_get_active_document(XedWindow * window)3540 xed_window_get_active_document (XedWindow *window)
3541 {
3542 XedView *view;
3543
3544 if (window == NULL)
3545 {
3546 return NULL;
3547 }
3548
3549 view = xed_window_get_active_view (window);
3550 if (view == NULL)
3551 {
3552 return NULL;
3553 }
3554
3555 return XED_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
3556 }
3557
3558 GtkWidget *
_xed_window_get_notebook(XedWindow * window)3559 _xed_window_get_notebook (XedWindow *window)
3560 {
3561 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3562
3563 return window->priv->notebook;
3564 }
3565
3566 /**
3567 * xed_window_create_tab:
3568 * @window: a #XedWindow
3569 * @jump_to: %TRUE to set the new #XedTab as active
3570 *
3571 * Creates a new #XedTab and adds the new tab to the #XedNotebook.
3572 * In case @jump_to is %TRUE the #XedNotebook switches to that new #XedTab.
3573 *
3574 * Returns: (transfer none): a new #XedTab
3575 */
3576 XedTab *
xed_window_create_tab(XedWindow * window,gboolean jump_to)3577 xed_window_create_tab (XedWindow *window,
3578 gboolean jump_to)
3579 {
3580 XedTab *tab;
3581
3582 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3583
3584 tab = XED_TAB(_xed_tab_new ());
3585 gtk_widget_show (GTK_WIDGET (tab));
3586
3587 xed_notebook_add_tab (XED_NOTEBOOK (window->priv->notebook), tab, -1, jump_to);
3588
3589 if (!gtk_widget_get_visible (GTK_WIDGET (window)))
3590 {
3591 gtk_window_present (GTK_WINDOW (window));
3592 }
3593
3594 return tab;
3595 }
3596
3597 static XedTab *
process_create_tab(XedWindow * window,XedTab * tab,gboolean jump_to)3598 process_create_tab (XedWindow *window,
3599 XedTab *tab,
3600 gboolean jump_to)
3601 {
3602 if (tab == NULL)
3603 {
3604 return NULL;
3605 }
3606
3607 gtk_widget_show (GTK_WIDGET (tab));
3608
3609 xed_notebook_add_tab (XED_NOTEBOOK (window->priv->notebook), tab, -1, jump_to);
3610
3611 if (!gtk_widget_get_visible (GTK_WIDGET (window)))
3612 {
3613 gtk_window_present (GTK_WINDOW (window));
3614 }
3615
3616 return tab;
3617 }
3618
3619 /**
3620 * xed_window_create_tab_from_location:
3621 * @window: a #XedWindow
3622 * @location: the location of the document
3623 * @encoding: (allow-none): a #GtkSourceEncoding
3624 * @line_pos: the line position to visualize
3625 * @create: %TRUE to create a new document in case @uri does exist
3626 * @jump_to: %TRUE to set the new #XedTab as active
3627 *
3628 * Creates a new #XedTab loading the document specified by @uri.
3629 * In case @jump_to is %TRUE the #XedNotebook swithes to that new #XedTab.
3630 * Whether @create is %TRUE, creates a new empty document if location does
3631 * not refer to an existing file
3632 *
3633 * Returns: (transfer none): a new #XedTab
3634 */
3635 XedTab *
xed_window_create_tab_from_location(XedWindow * window,GFile * location,const GtkSourceEncoding * encoding,gint line_pos,gboolean create,gboolean jump_to)3636 xed_window_create_tab_from_location (XedWindow *window,
3637 GFile *location,
3638 const GtkSourceEncoding *encoding,
3639 gint line_pos,
3640 gboolean create,
3641 gboolean jump_to)
3642 {
3643 GtkWidget *tab;
3644
3645 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3646 g_return_val_if_fail(G_IS_FILE (location), NULL);
3647
3648 tab = _xed_tab_new_from_location (location, encoding, line_pos, create);
3649
3650 return process_create_tab (window, XED_TAB (tab), jump_to);
3651 }
3652
3653 /**
3654 * xed_window_create_tab_from_stream:
3655 * @window: a #XedWindow
3656 * @stream: the #GInputStream
3657 * @encoding: the encoding to use in the stream
3658 * @line_pos: the position
3659 * @jump_to: whether to jump to the new tab
3660 *
3661 * Returns: (transfer none): the active #XedTab in the @window.
3662 */
3663 XedTab *
xed_window_create_tab_from_stream(XedWindow * window,GInputStream * stream,const GtkSourceEncoding * encoding,gint line_pos,gboolean jump_to)3664 xed_window_create_tab_from_stream (XedWindow *window,
3665 GInputStream *stream,
3666 const GtkSourceEncoding *encoding,
3667 gint line_pos,
3668 gboolean jump_to)
3669 {
3670 GtkWidget *tab;
3671
3672 g_return_val_if_fail (XED_IS_WINDOW (window), NULL);
3673 g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
3674
3675 tab = _xed_tab_new_from_stream (stream, encoding, line_pos);
3676
3677 return process_create_tab (window, XED_TAB (tab), jump_to);
3678 }
3679
3680 /**
3681 * xed_window_get_active_tab:
3682 * @window: a XedWindow
3683 *
3684 * Gets the active #XedTab in the @window.
3685 *
3686 * Returns: (transfer none): the active #XedTab in the @window.
3687 */
3688 XedTab *
xed_window_get_active_tab(XedWindow * window)3689 xed_window_get_active_tab (XedWindow *window)
3690 {
3691 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3692
3693 if (window->priv->active_tab == NULL)
3694 {
3695 return NULL;
3696 }
3697 else
3698 {
3699 return XED_TAB(window->priv->active_tab);
3700 }
3701 }
3702
3703 static void
add_document(XedTab * tab,GList ** res)3704 add_document (XedTab *tab,
3705 GList **res)
3706 {
3707 XedDocument *doc;
3708
3709 doc = xed_tab_get_document (tab);
3710
3711 *res = g_list_prepend (*res, doc);
3712 }
3713
3714 /**
3715 * xed_window_get_documents:
3716 * @window: a #XedWindow
3717 *
3718 * Gets a newly allocated list with all the documents in the window.
3719 * This list must be freed.
3720 *
3721 * Returns: (element-type Xed.Document) (transfer container): a newly
3722 * allocated list with all the documents in the window
3723 */
3724 GList *
xed_window_get_documents(XedWindow * window)3725 xed_window_get_documents (XedWindow *window)
3726 {
3727 GList *res = NULL;
3728 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3729 gtk_container_foreach (GTK_CONTAINER(window->priv->notebook), (GtkCallback) add_document, &res);
3730 res = g_list_reverse (res);
3731 return res;
3732 }
3733
3734 static void
add_view(XedTab * tab,GList ** res)3735 add_view (XedTab *tab,
3736 GList **res)
3737 {
3738 XedView *view;
3739 view = xed_tab_get_view (tab);
3740 *res = g_list_prepend (*res, view);
3741 }
3742
3743 /**
3744 * xed_window_get_views:
3745 * @window: a #XedWindow
3746 *
3747 * Gets a list with all the views in the window. This list must be freed.
3748 *
3749 * Returns: (element-type Xed.View) (transfer container): a newly allocated
3750 * list with all the views in the window
3751 */
3752 GList *
xed_window_get_views(XedWindow * window)3753 xed_window_get_views (XedWindow *window)
3754 {
3755 GList *res = NULL;
3756 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3757 gtk_container_foreach (GTK_CONTAINER(window->priv->notebook), (GtkCallback) add_view, &res);
3758 res = g_list_reverse (res);
3759 return res;
3760 }
3761
3762 /**
3763 * xed_window_close_tab:
3764 * @window: a #XedWindow
3765 * @tab: the #XedTab to close
3766 *
3767 * Closes the @tab.
3768 */
3769 void
xed_window_close_tab(XedWindow * window,XedTab * tab)3770 xed_window_close_tab (XedWindow *window,
3771 XedTab *tab)
3772 {
3773 g_return_if_fail (XED_IS_WINDOW (window));
3774 g_return_if_fail (XED_IS_TAB (tab));
3775 g_return_if_fail ((xed_tab_get_state (tab) != XED_TAB_STATE_SAVING)
3776 && (xed_tab_get_state (tab) != XED_TAB_STATE_SHOWING_PRINT_PREVIEW));
3777
3778 xed_notebook_remove_tab (XED_NOTEBOOK (window->priv->notebook), tab);
3779 }
3780
3781 /**
3782 * xed_window_close_all_tabs:
3783 * @window: a #XedWindow
3784 *
3785 * Closes all opened tabs.
3786 */
3787 void
xed_window_close_all_tabs(XedWindow * window)3788 xed_window_close_all_tabs (XedWindow *window)
3789 {
3790 g_return_if_fail(XED_IS_WINDOW (window));
3791 g_return_if_fail(!(window->priv->state & XED_WINDOW_STATE_SAVING)
3792 && !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
3793
3794 window->priv->removing_tabs = TRUE;
3795 xed_notebook_remove_all_tabs (XED_NOTEBOOK(window->priv->notebook));
3796 window->priv->removing_tabs = FALSE;
3797 }
3798
3799 /**
3800 * xed_window_close_tabs:
3801 * @window: a #XedWindow
3802 * @tabs: (element-type Xed.Tab): a list of #XedTab
3803 *
3804 * Closes all tabs specified by @tabs.
3805 */
3806 void
xed_window_close_tabs(XedWindow * window,const GList * tabs)3807 xed_window_close_tabs (XedWindow *window,
3808 const GList *tabs)
3809 {
3810 g_return_if_fail(XED_IS_WINDOW (window));
3811 g_return_if_fail(!(window->priv->state & XED_WINDOW_STATE_SAVING)
3812 && !(window->priv->state & XED_WINDOW_STATE_SAVING_SESSION));
3813
3814 if (tabs == NULL)
3815 {
3816 return;
3817 }
3818
3819 window->priv->removing_tabs = TRUE;
3820
3821 while (tabs != NULL)
3822 {
3823 if (tabs->next == NULL)
3824 {
3825 window->priv->removing_tabs = FALSE;
3826 }
3827
3828 xed_notebook_remove_tab (XED_NOTEBOOK(window->priv->notebook), XED_TAB(tabs->data));
3829 tabs = g_list_next(tabs);
3830 }
3831
3832 g_return_if_fail(window->priv->removing_tabs == FALSE);
3833 }
3834
3835 XedWindow *
_xed_window_move_tab_to_new_window(XedWindow * window,XedTab * tab)3836 _xed_window_move_tab_to_new_window (XedWindow *window,
3837 XedTab *tab)
3838 {
3839 XedWindow *new_window;
3840
3841 g_return_val_if_fail (XED_IS_WINDOW (window), NULL);
3842 g_return_val_if_fail (XED_IS_TAB (tab), NULL);
3843 g_return_val_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) > 1, NULL);
3844
3845 new_window = clone_window (window);
3846 xed_notebook_move_tab (XED_NOTEBOOK (window->priv->notebook), XED_NOTEBOOK (new_window->priv->notebook), tab, -1);
3847 gtk_widget_show (GTK_WIDGET (new_window));
3848
3849 return new_window;
3850 }
3851
3852 /**
3853 * xed_window_set_active_tab:
3854 * @window: a #XedWindow
3855 * @tab: a #XedTab
3856 *
3857 * Switches to the tab that matches with @tab.
3858 */
3859 void
xed_window_set_active_tab(XedWindow * window,XedTab * tab)3860 xed_window_set_active_tab (XedWindow *window,
3861 XedTab *tab)
3862 {
3863 gint page_num;
3864
3865 g_return_if_fail(XED_IS_WINDOW (window));
3866 g_return_if_fail(XED_IS_TAB (tab));
3867
3868 page_num = gtk_notebook_page_num (GTK_NOTEBOOK(window->priv->notebook), GTK_WIDGET(tab));
3869 g_return_if_fail(page_num != -1);
3870 gtk_notebook_set_current_page (GTK_NOTEBOOK(window->priv->notebook), page_num);
3871
3872 /* Make sure to grab focus if the page didn't change */
3873 gtk_widget_grab_focus (GTK_WIDGET (xed_tab_get_view (tab)));
3874 }
3875
3876 /**
3877 * xed_window_get_group:
3878 * @window: a #XedWindow
3879 *
3880 * Gets the #GtkWindowGroup in which @window resides.
3881 *
3882 * Returns: (transfer none): the #GtkWindowGroup
3883 */
3884 GtkWindowGroup *
xed_window_get_group(XedWindow * window)3885 xed_window_get_group (XedWindow *window)
3886 {
3887 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3888 return window->priv->window_group;
3889 }
3890
3891 gboolean
_xed_window_is_removing_tabs(XedWindow * window)3892 _xed_window_is_removing_tabs (XedWindow *window)
3893 {
3894 g_return_val_if_fail(XED_IS_WINDOW (window), FALSE);
3895 return window->priv->removing_tabs;
3896 }
3897
3898 /**
3899 * xed_window_get_ui_manager:
3900 * @window: a #XedWindow
3901 *
3902 * Gets the #GtkUIManager associated with the @window.
3903 *
3904 * Returns: (transfer none): the #GtkUIManager of the @window.
3905 */
3906 GtkUIManager *
xed_window_get_ui_manager(XedWindow * window)3907 xed_window_get_ui_manager (XedWindow *window)
3908 {
3909 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3910 return window->priv->manager;
3911 }
3912
3913 /**
3914 * xed_window_get_side_panel:
3915 * @window: a #XedWindow
3916 *
3917 * Gets the side #XedPanel of the @window.
3918 *
3919 * Returns: (transfer none): the side #XedPanel.
3920 */
3921 XedPanel *
xed_window_get_side_panel(XedWindow * window)3922 xed_window_get_side_panel (XedWindow *window)
3923 {
3924 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3925 return XED_PANEL(window->priv->side_panel);
3926 }
3927
3928 /**
3929 * xed_window_get_bottom_panel:
3930 * @window: a #XedWindow
3931 *
3932 * Gets the bottom #XedPanel of the @window.
3933 *
3934 * Returns: (transfer none): the bottom #XedPanel.
3935 */
3936 XedPanel *
xed_window_get_bottom_panel(XedWindow * window)3937 xed_window_get_bottom_panel (XedWindow *window)
3938 {
3939 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3940 return XED_PANEL(window->priv->bottom_panel);
3941 }
3942
3943 /**
3944 * xed_window_get_statusbar:
3945 * @window: a #XedWindow
3946 *
3947 * Gets the #XedStatusbar of the @window.
3948 *
3949 * Returns: (transfer none): the #XedStatusbar of the @window.
3950 */
3951 GtkWidget *
xed_window_get_statusbar(XedWindow * window)3952 xed_window_get_statusbar (XedWindow *window)
3953 {
3954 g_return_val_if_fail(XED_IS_WINDOW (window), 0);
3955 return window->priv->statusbar;
3956 }
3957
3958 /**
3959 * xed_window_get_searchbar:
3960 * @window: a #XedWindow
3961 *
3962 * Gets the #XedSearchbar of the @window.
3963 *
3964 * Returns: (transfer none): the #XedSearchbar of the @window.
3965 */
3966 GtkWidget *
xed_window_get_searchbar(XedWindow * window)3967 xed_window_get_searchbar (XedWindow *window)
3968 {
3969 g_return_val_if_fail(XED_IS_WINDOW (window), 0);
3970 return window->priv->searchbar;
3971 }
3972
3973 /**
3974 * xed_window_get_state:
3975 * @window: a #XedWindow
3976 *
3977 * Retrieves the state of the @window.
3978 *
3979 * Returns: the current #XedWindowState of the @window.
3980 */
3981 XedWindowState
xed_window_get_state(XedWindow * window)3982 xed_window_get_state (XedWindow *window)
3983 {
3984 g_return_val_if_fail(XED_IS_WINDOW (window), XED_WINDOW_STATE_NORMAL);
3985 return window->priv->state;
3986 }
3987
3988 GFile *
_xed_window_get_default_location(XedWindow * window)3989 _xed_window_get_default_location (XedWindow *window)
3990 {
3991 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
3992 if (window->priv->default_location != NULL)
3993 {
3994 return g_object_ref (window->priv->default_location);
3995 }
3996 else
3997 {
3998 return NULL;
3999 }
4000 }
4001
4002 void
_xed_window_set_default_location(XedWindow * window,GFile * location)4003 _xed_window_set_default_location (XedWindow *window,
4004 GFile *location)
4005 {
4006 GFile *dir;
4007
4008 g_return_if_fail(XED_IS_WINDOW (window));
4009 g_return_if_fail(G_IS_FILE (location));
4010
4011 dir = g_file_get_parent (location);
4012 g_return_if_fail(dir != NULL);
4013
4014 if (window->priv->default_location != NULL)
4015 {
4016 g_object_unref (window->priv->default_location);
4017 }
4018
4019 window->priv->default_location = dir;
4020 }
4021
4022 /**
4023 * xed_window_get_unsaved_documents:
4024 * @window: a #XedWindow
4025 *
4026 * Gets the list of documents that need to be saved before closing the window.
4027 *
4028 * Returns: (element-type Xed.Document) (transfer container): a list of
4029 * #XedDocument that need to be saved before closing the window
4030 */
4031 GList *
xed_window_get_unsaved_documents(XedWindow * window)4032 xed_window_get_unsaved_documents (XedWindow *window)
4033 {
4034 GList *unsaved_docs = NULL;
4035 GList *tabs;
4036 GList *l;
4037
4038 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
4039
4040 tabs = gtk_container_get_children (GTK_CONTAINER(window->priv->notebook));
4041
4042 l = tabs;
4043 while (l != NULL)
4044 {
4045 XedTab *tab;
4046 tab = XED_TAB(l->data);
4047 if (!_xed_tab_get_can_close (tab))
4048 {
4049 XedDocument *doc;
4050 doc = xed_tab_get_document (tab);
4051 unsaved_docs = g_list_prepend (unsaved_docs, doc);
4052 }
4053 l = g_list_next(l);
4054 }
4055
4056 g_list_free (tabs);
4057
4058 return g_list_reverse (unsaved_docs);
4059 }
4060
4061 void
_xed_window_set_saving_session_state(XedWindow * window,gboolean saving_session)4062 _xed_window_set_saving_session_state (XedWindow *window,
4063 gboolean saving_session)
4064 {
4065 XedWindowState old_state;
4066
4067 g_return_if_fail(XED_IS_WINDOW (window));
4068
4069 old_state = window->priv->state;
4070
4071 if (saving_session)
4072 {
4073 window->priv->state |= XED_WINDOW_STATE_SAVING_SESSION;
4074 }
4075 else
4076 {
4077 window->priv->state &= ~XED_WINDOW_STATE_SAVING_SESSION;
4078 }
4079
4080 if (old_state != window->priv->state)
4081 {
4082 set_sensitivity_according_to_window_state (window);
4083 g_object_notify (G_OBJECT(window), "state");
4084 }
4085 }
4086
4087 static void
hide_notebook_tabs_on_fullscreen(GtkNotebook * notebook,GParamSpec * pspec,XedWindow * window)4088 hide_notebook_tabs_on_fullscreen (GtkNotebook *notebook,
4089 GParamSpec *pspec,
4090 XedWindow *window)
4091 {
4092 gtk_notebook_set_show_tabs (notebook, FALSE);
4093 }
4094
4095 void
_xed_window_fullscreen(XedWindow * window)4096 _xed_window_fullscreen (XedWindow *window)
4097 {
4098 g_return_if_fail (XED_IS_WINDOW (window));
4099
4100 if (_xed_window_is_fullscreen (window))
4101 {
4102 return;
4103 }
4104
4105 /* Go to fullscreen mode and hide bars */
4106 gtk_window_fullscreen (GTK_WINDOW (&window->window));
4107
4108 gtk_widget_hide (window->priv->menubar);
4109
4110 g_signal_handlers_block_by_func (window->priv->toolbar, toolbar_visibility_changed, window);
4111 gtk_widget_hide (window->priv->toolbar);
4112
4113 g_signal_handlers_block_by_func (window->priv->statusbar, statusbar_visibility_changed, window);
4114 gtk_widget_hide (window->priv->statusbar);
4115
4116 fullscreen_controls_build (window);
4117
4118 gtk_widget_show_all (window->priv->fullscreen_eventbox);
4119 }
4120
4121 void
_xed_window_unfullscreen(XedWindow * window)4122 _xed_window_unfullscreen (XedWindow *window)
4123 {
4124 gboolean visible;
4125 GtkAction *action;
4126
4127 g_return_if_fail (XED_IS_WINDOW (window));
4128
4129 if (!_xed_window_is_fullscreen (window))
4130 {
4131 return;
4132 }
4133
4134 /* Unfullscreen and show bars */
4135 gtk_window_unfullscreen (GTK_WINDOW (&window->window));
4136 g_signal_handlers_disconnect_by_func (window->priv->notebook, hide_notebook_tabs_on_fullscreen, window);
4137
4138 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewToolbar");
4139 visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4140 if (visible)
4141 {
4142 gtk_widget_show (window->priv->toolbar);
4143 }
4144 g_signal_handlers_unblock_by_func (window->priv->toolbar, toolbar_visibility_changed, window);
4145
4146 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewMenubar");
4147 visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4148 if (visible)
4149 {
4150 gtk_widget_show (window->priv->menubar);
4151 }
4152
4153 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewStatusbar");
4154 visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4155 if (visible)
4156 {
4157 gtk_widget_show (window->priv->statusbar);
4158 }
4159 g_signal_handlers_unblock_by_func (window->priv->statusbar, statusbar_visibility_changed, window);
4160
4161 gtk_widget_hide (window->priv->fullscreen_eventbox);
4162 }
4163
4164 gboolean
_xed_window_is_fullscreen(XedWindow * window)4165 _xed_window_is_fullscreen (XedWindow *window)
4166 {
4167 g_return_val_if_fail(XED_IS_WINDOW (window), FALSE);
4168 return window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN;
4169 }
4170
4171 /**
4172 * xed_window_get_tab_from_location:
4173 * @window: a #XedWindow
4174 * @location: a #GFile
4175 *
4176 * Gets the #XedTab that matches with the given @location.
4177 *
4178 * Returns: (transfer none): the #XedTab that matches with the given @location.
4179 */
4180 XedTab *
xed_window_get_tab_from_location(XedWindow * window,GFile * location)4181 xed_window_get_tab_from_location (XedWindow *window,
4182 GFile *location)
4183 {
4184 GList *tabs;
4185 GList *l;
4186 XedTab *ret = NULL;
4187
4188 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
4189 g_return_val_if_fail(G_IS_FILE (location), NULL);
4190
4191 tabs = gtk_container_get_children (GTK_CONTAINER(window->priv->notebook));
4192
4193 for (l = tabs; l != NULL; l = g_list_next(l))
4194 {
4195 XedDocument *doc;
4196 GtkSourceFile *file;
4197 XedTab *tab;
4198 GFile *cur_location;
4199
4200 tab = XED_TAB (l->data);
4201 doc = xed_tab_get_document (tab);
4202 file = xed_document_get_file (doc);
4203 cur_location = gtk_source_file_get_location (file);
4204
4205 if (cur_location != NULL)
4206 {
4207 gboolean found = g_file_equal (location, cur_location);
4208
4209 if (found)
4210 {
4211 ret = tab;
4212 break;
4213 }
4214 }
4215 }
4216
4217 g_list_free (tabs);
4218
4219 return ret;
4220 }
4221
4222 /**
4223 * xed_window_get_message_bus:
4224 * @window: a #XedWindow
4225 *
4226 * Gets the #XedMessageBus associated with @window. The returned reference
4227 * is owned by the window and should not be unreffed.
4228 *
4229 * Return value: (transfer none): the #XedMessageBus associated with @window
4230 */
4231 XedMessageBus *
xed_window_get_message_bus(XedWindow * window)4232 xed_window_get_message_bus (XedWindow *window)
4233 {
4234 g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
4235 return window->priv->message_bus;
4236 }
4237
4238 void
_xed_window_get_default_size(gint * width,gint * height)4239 _xed_window_get_default_size (gint *width,
4240 gint *height)
4241 {
4242 g_return_if_fail (width != NULL && height != NULL);
4243
4244 *width = XED_WINDOW_DEFAULT_WIDTH;
4245 *height = XED_WINDOW_DEFAULT_HEIGHT;
4246 }
4247
4248 XedPaned *
_xed_window_get_hpaned(XedWindow * window)4249 _xed_window_get_hpaned (XedWindow *window)
4250 {
4251 return XED_PANED (window->priv->hpaned);
4252 }
4253
4254 XedPaned *
_xed_window_get_vpaned(XedWindow * window)4255 _xed_window_get_vpaned (XedWindow *window)
4256 {
4257 return XED_PANED (window->priv->vpaned);
4258 }
4259
4260 gint
_xed_window_get_side_panel_size(XedWindow * window)4261 _xed_window_get_side_panel_size (XedWindow *window)
4262 {
4263 return window->priv->side_panel_size;
4264 }
4265
4266 gint
_xed_window_get_bottom_panel_size(XedWindow * window)4267 _xed_window_get_bottom_panel_size (XedWindow *window)
4268 {
4269 return window->priv->bottom_panel_size;
4270 }
4271