1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2000 Naba Kumar
5 Copyright (C) 2014 Tristian Celestin
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <libanjuta/anjuta-shell.h>
27 #include <libanjuta/anjuta-debug.h>
29 #include <libanjuta/interfaces/ianjuta-terminal.h>
30 #include <libanjuta/interfaces/ianjuta-preferences.h>
31 #include <libanjuta/interfaces/ianjuta-project-manager.h>
32 #include <sys/types.h>
36 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-terminal-plugin.xml"
37 #define PREFS_BUILDER PACKAGE_DATA_DIR"/glade/anjuta-terminal-plugin.ui"
38 #define ICON_FILE "anjuta-terminal-plugin-48.png"
40 /* Gnome-Terminal GSettings Schemas and Keys */
41 #define TERM_PROFILE_LIST_SCHEMA "org.gnome.Terminal.ProfilesList"
42 #define TERM_LEGACY_SCHEMA "org.gnome.Terminal.Legacy.Settings"
43 #define TERM_PROFILE_DEFAULT "default"
45 /* Gnome Desktop GSettings Schemas and Keys */
46 #define GNOME_DESKTOP_INTERFACE_SCHEMA "org.gnome.desktop.interface"
47 #define GNOME_MONOSPACE_FONT "monospace-font-name"
49 /* Anjuta Terminal Plugin Schema and Keys */
50 #define PREF_SCHEMA "org.gnome.anjuta.terminal"
51 #define PREFS_TERMINAL_PROFILE_USE_DEFAULT "use-default-profile"
52 #define PREFS_TERMINAL_PROFILE "terminal-profile"
54 /* Columns in model for combo box */
56 TERM_STORE_UUID_COLUMN
,
57 TERM_STORE_NAME_COLUMN
63 #include <libanjuta/anjuta-plugin.h>
64 #include "terminal-schemas.h"
66 extern GType
terminal_plugin_get_type (GTypeModule
*module
);
67 #define ANJUTA_PLUGIN_TERMINAL_TYPE (terminal_plugin_get_type (NULL))
68 #define ANJUTA_PLUGIN_TERMINAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_PLUGIN_TERMINAL_TYPE, TerminalPlugin))
69 #define ANJUTA_PLUGIN_TERMINAL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_PLUGIN_TERMINAL_CLASS, TerminalPluginClass))
70 #define ANJUTA_IS_PLUGIN_TERMINAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_PLUGIN_TERMINAL_TYPE))
71 #define ANJUTA_IS_PLUGIN_TERMINAL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_PLUGIN_TERMINAL_TYPE))
72 #define ANJUTA_PLUGIN_TERMINAL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_PLUGIN_TERMINAL_TYPE, TerminalPluginClass))
74 typedef struct _TerminalPlugin TerminalPlugin
;
75 typedef struct _TerminalPluginClass TerminalPluginClass
;
77 struct _TerminalPlugin
{
81 GtkActionGroup
*action_group
;
84 GtkWidget
*shell
, *term
;
85 GtkWidget
*shell_box
, *term_box
;
87 GtkWidget
*pref_profile_combo
;
88 GtkWidget
*pref_default_button
;
89 gboolean widget_added_to_shell
;
94 gboolean first_time_realization
;
98 struct _TerminalPluginClass
{
99 AnjutaPluginClass parent_class
;
102 static gpointer parent_class
;
106 get_profile_key (const gchar
*profile
, const gchar
*key
)
108 /* A reasonably safe buffer */
109 static gchar buffer
[1024];
111 g_return_val_if_fail (profile
!= NULL
&& key
!= NULL
, NULL
);
113 snprintf (buffer
, 1024, "%s/%s/%s", GCONF_PROFILE_PREFIX
, profile
, key
);
119 strv_to_rgbav (const gchar
**specs
, gsize
*size
, GdkRGBA
**colors
)
126 var
= g_variant_new_strv (specs
, -1);
127 g_variant_iter_init (&iter
, var
);
128 *size
= g_variant_iter_n_children (&iter
);
129 *colors
= g_new (GdkRGBA
, *size
);
131 while (g_variant_iter_next (&iter
, "&s", &str
)) {
132 if (!gdk_rgba_parse (&(*colors
)[i
++], str
)) {
134 g_variant_unref (var
);
138 g_variant_unref (var
);
143 terminal_set_preferences (VteTerminal
*term
, GSettings
* settings
, TerminalPlugin
*term_plugin
)
145 GSettingsSchemaSource
*source
;
146 GSettingsSchema
*schema
;
149 GSettings
*profiles_list
;
150 GSettings
*profile_settings
;
151 GSettings
*interface_settings
;
162 g_return_if_fail (settings
!= NULL
);
164 /* Always autohide mouse */
165 vte_terminal_set_mouse_autohide (term
, TRUE
);
167 /* Check that terminal schemas really exist. They could be missing if gnome
168 * terminal is not installed or there is an old version */
169 source
= g_settings_schema_source_get_default ();
170 schema
= g_settings_schema_source_lookup (source
, TERMINAL_PROFILES_LIST_SCHEMA
, TRUE
);
171 if (schema
== NULL
) return;
173 profiles_list
= g_settings_new_full (schema
, NULL
, NULL
);
174 g_settings_schema_unref (schema
);
176 /* Get selected profile */
177 bool_val
= g_settings_get_boolean (settings
, PREFS_TERMINAL_PROFILE_USE_DEFAULT
);
179 uuid
= g_settings_get_string (profiles_list
, TERMINAL_SETTINGS_LIST_DEFAULT_KEY
);
181 uuid
= g_settings_get_string (settings
, PREFS_TERMINAL_PROFILE
);
182 path
= g_strdup_printf ("%s:%s/", TERMINAL_PROFILES_PATH_PREFIX
, uuid
);
183 profile_settings
= g_settings_new_with_path (TERMINAL_PROFILE_SCHEMA
, path
);
187 /* Set terminal font */
188 bool_val
= g_settings_get_boolean (profile_settings
, TERMINAL_PROFILE_USE_SYSTEM_FONT_KEY
);
191 interface_settings
= g_settings_new (GNOME_DESKTOP_INTERFACE_SCHEMA
);
192 str_val
= g_settings_get_string (interface_settings
, GNOME_MONOSPACE_FONT
);
193 g_object_unref (interface_settings
);
196 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_FONT_KEY
);
199 vte_terminal_set_font_from_string (term
, str_val
);
201 /* Set cursor blink */
202 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_CURSOR_BLINK_MODE_KEY
);
203 if (g_strcmp0 (str_val
, "system") == 0)
204 vte_terminal_set_cursor_blink_mode (term
, VTE_CURSOR_BLINK_SYSTEM
);
205 else if (g_strcmp0 (str_val
, "on") == 0)
206 vte_terminal_set_cursor_blink_mode (term
, VTE_CURSOR_BLINK_ON
);
207 else if (g_strcmp0 (str_val
, "off") == 0)
208 vte_terminal_set_cursor_blink_mode (term
, VTE_CURSOR_BLINK_OFF
);
211 /* Set audible bell */
212 bool_val
= g_settings_get_boolean (profile_settings
, TERMINAL_PROFILE_AUDIBLE_BELL_KEY
);
213 vte_terminal_set_audible_bell (term
, bool_val
);
216 int_val
= g_settings_get_int (profile_settings
, TERMINAL_PROFILE_SCROLLBACK_LINES_KEY
);
217 vte_terminal_set_scrollback_lines (term
, (int_val
== 0) ? 500 : int_val
);
219 /* Set scroll on keystroke */
220 bool_val
= g_settings_get_boolean (profile_settings
, TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE_KEY
);
221 vte_terminal_set_scroll_on_keystroke (term
, bool_val
);
223 /* Scroll on output */
224 bool_val
= g_settings_get_boolean (profile_settings
, TERMINAL_PROFILE_SCROLL_ON_OUTPUT_KEY
);
225 vte_terminal_set_scroll_on_output (term
, bool_val
);
227 /* Set word characters */
228 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_WORD_CHARS_KEY
);
230 vte_terminal_set_word_chars (term
, str_val
);
233 /* Set backspace key */
234 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_BACKSPACE_BINDING_KEY
);
237 if (g_strcmp0 (str_val
, "ascii-del") == 0)
238 vte_terminal_set_backspace_binding (term
, VTE_ERASE_ASCII_DELETE
);
239 else if (g_strcmp0 (str_val
, "escape-sequence") == 0)
240 vte_terminal_set_backspace_binding (term
, VTE_ERASE_DELETE_SEQUENCE
);
241 else if (g_strcmp0 (str_val
, "control-h") == 0)
242 vte_terminal_set_backspace_binding (term
, VTE_ERASE_ASCII_BACKSPACE
);
244 vte_terminal_set_backspace_binding (term
, VTE_ERASE_AUTO
);
249 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_DELETE_BINDING_KEY
);
252 if (g_strcmp0 (str_val
, "ascii-del") == 0)
253 vte_terminal_set_delete_binding (term
, VTE_ERASE_ASCII_DELETE
);
254 else if (g_strcmp0 (str_val
, "escape-sequence") == 0)
255 vte_terminal_set_delete_binding (term
, VTE_ERASE_DELETE_SEQUENCE
);
256 else if (g_strcmp0 (str_val
, "control-h") == 0)
257 vte_terminal_set_delete_binding (term
, VTE_ERASE_ASCII_BACKSPACE
);
259 vte_terminal_set_delete_binding (term
, VTE_ERASE_AUTO
);
263 /* Set colors (foreground, background, and palette) */
264 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_BACKGROUND_COLOR_KEY
);
266 bool_val
= gdk_rgba_parse (&color
[0], str_val
);
267 background
= bool_val
? &color
[0] : NULL
;
270 str_val
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_FOREGROUND_COLOR_KEY
);
272 bool_val
= gdk_rgba_parse (&color
[1], str_val
);
273 foreground
= bool_val
? &color
[1] : NULL
;
276 str_vals
= g_settings_get_strv(profile_settings
, TERMINAL_PROFILE_PALETTE_KEY
);
277 strv_to_rgbav (str_vals
, &size
, &palette
);
280 /* vte_terminal_set_colors() works even if the terminal widget is not realized,
281 * which is not the case with vte_terminal_set_color_foreground() and
282 * vte_terminal_set_color_background()
284 vte_terminal_set_colors_rgba (term
, foreground
, background
, palette
, size
);
287 g_object_unref (profiles_list
);
288 g_object_unref (profile_settings
);
292 preferences_changed (GSettings
* settings
, TerminalPlugin
*term
)
294 terminal_set_preferences (VTE_TERMINAL (term
->shell
), settings
, term
);
295 terminal_set_preferences (VTE_TERMINAL (term
->term
), settings
, term
);
299 on_notify_prefs_profile(GSettings
* settings
,
303 TerminalPlugin
*tp
= ANJUTA_PLUGIN_TERMINAL (user_data
);
304 preferences_changed (settings
, tp
);
308 on_notify_prefs_default (GSettings
* settings
,
312 TerminalPlugin
*tp
= ANJUTA_PLUGIN_TERMINAL (user_data
);
313 preferences_changed (settings
, tp
);
317 prefs_init (TerminalPlugin
*tp
)
319 g_signal_connect (tp
->settings
, "changed::" PREFS_TERMINAL_PROFILE
,
320 G_CALLBACK (on_notify_prefs_profile
), tp
);
321 g_signal_connect (tp
->settings
, "changed::" PREFS_TERMINAL_PROFILE_USE_DEFAULT
,
322 G_CALLBACK (on_notify_prefs_default
), tp
);
326 use_default_profile_cb (GtkToggleButton
*button
,
327 TerminalPlugin
*term
)
329 if (gtk_toggle_button_get_active (button
))
330 gtk_widget_set_sensitive (term
->pref_profile_combo
, FALSE
);
332 gtk_widget_set_sensitive (term
->pref_profile_combo
, TRUE
);
336 terminal_child_exited_cb (VteTerminal
*term
, gpointer user_data
)
338 TerminalPlugin
*term_plugin
= ANJUTA_PLUGIN_TERMINAL (user_data
);
339 GPid pid
= term_plugin
->child_pid
;
342 if (term_plugin
->child_pid
)
346 focus
= gtk_widget_is_focus (term_plugin
->term
);
348 gtk_container_remove (GTK_CONTAINER (term_plugin
->frame
), term_plugin
->term_box
);
349 gtk_container_add (GTK_CONTAINER (term_plugin
->frame
), term_plugin
->shell_box
);
350 gtk_widget_show_all (term_plugin
->shell_box
);
352 gtk_widget_grab_focus (term_plugin
->shell
);
353 term_plugin
->child_pid
= 0;
356 status
= vte_terminal_get_child_exit_status (term
);
357 g_signal_emit_by_name(term_plugin
, "child-exited", pid
, status
);
361 terminal_execute (TerminalPlugin
*term_plugin
, const gchar
*directory
,
362 const gchar
*command
, gchar
**environment
)
364 char **args
, **args_ptr
;
365 GList
*args_list
, *args_list_ptr
;
370 g_return_val_if_fail (command
!= NULL
, 0);
372 /* Prepare command args */
373 args_list
= anjuta_util_parse_args_from_string (command
);
374 args
= g_new (char*, g_list_length (args_list
) + 1);
375 args_list_ptr
= args_list
;
377 while (args_list_ptr
)
379 *args_ptr
= (char*) args_list_ptr
->data
;
380 args_list_ptr
= g_list_next (args_list_ptr
);
385 if (directory
== NULL
)
386 dir
= g_path_get_dirname (args
[0]);
388 dir
= g_strdup (directory
);
390 term
= VTE_TERMINAL (term_plugin
->term
);
393 vte_terminal_reset (term, TRUE, TRUE);
396 if (vte_terminal_fork_command_full (term
, term_plugin
->pty_flags
,
397 dir
, args
, environment
,
398 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
, NULL
, NULL
,
403 term_plugin
->child_pid
= pid
;
405 /* Display terminal widget */
406 focus
= gtk_widget_is_focus (term_plugin
->shell
);
407 gtk_container_remove (GTK_CONTAINER (term_plugin
->frame
), term_plugin
->shell_box
);
408 gtk_container_add (GTK_CONTAINER (term_plugin
->frame
), term_plugin
->term_box
);
409 gtk_widget_show_all (term_plugin
->term_box
);
411 gtk_widget_grab_focus (term_plugin
->term
);
413 if (term_plugin
->widget_added_to_shell
)
414 anjuta_shell_present_widget (ANJUTA_PLUGIN (term_plugin
)->shell
,
415 term_plugin
->frame
, NULL
);
420 g_list_foreach (args_list
, (GFunc
)g_free
, NULL
);
421 g_list_free (args_list
);
427 init_shell (TerminalPlugin
*term_plugin
, const char *path
)
429 gchar
*shell
[2] = {0, 0};
430 static gboolean first_time
= TRUE
;
431 VteTerminal
*term
= VTE_TERMINAL (term_plugin
->shell
);
433 shell
[0] = vte_get_user_shell ();
434 if (shell
[0] == NULL
) shell
[0] = g_strdup("/bin/sh");
437 vte_terminal_reset (term
, FALSE
, TRUE
);
441 vte_terminal_fork_command_full (term
, term_plugin
->pty_flags
,
449 terminal_focus_cb (GtkWidget
*widget
, GdkEvent
*event
,
450 TerminalPlugin
*term
)
452 gtk_widget_grab_focus (widget
);
457 terminal_keypress_cb (GtkWidget
*widget
, GdkEventKey
*event
,
458 TerminalPlugin
*terminal_plugin
)
460 if (event
->type
!= GDK_KEY_PRESS
)
464 if ((event
->keyval
== GDK_KEY_d
|| event
->keyval
== GDK_KEY_D
) &&
465 (event
->state
& GDK_CONTROL_MASK
))
467 if (terminal_plugin
->child_pid
)
469 kill (terminal_plugin
->child_pid
, SIGINT
);
470 terminal_plugin
->child_pid
= 0;
478 terminal_click_cb (GtkWidget
*widget
, GdkEventButton
*event
,
479 TerminalPlugin
*term
)
481 if (event
->button
== 3)
487 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN(term
)->shell
, NULL
);
488 popup
= GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
), "/PopupTerminal"));
489 action
= gtk_action_group_get_action (term
->action_group
, "ActionCopyFromTerminal");
490 gtk_action_set_sensitive (action
,vte_terminal_get_has_selection(VTE_TERMINAL(widget
)));
492 gtk_menu_popup (popup
, NULL
, NULL
, NULL
, NULL
,
493 event
->button
, event
->time
);
500 /* VTE has a terrible bug where it could crash when container is changed.
501 * The problem has been traced in vte where its style-set handler does not
502 * adequately check if the widget is realized, resulting in a crash when
503 * style-set occurs in an unrealized vte widget.
505 * This work around blocks all style-set signal emissions when the vte
506 * widget is unrealized. -Naba
509 terminal_realize_cb (GtkWidget
*term
, TerminalPlugin
*plugin
)
513 if (plugin
->first_time_realization
)
515 /* First time realize does not have the signals blocked */
516 plugin
->first_time_realization
= FALSE
;
519 count
= g_signal_handlers_unblock_matched (term
,
522 g_quark_from_string ("style-set"),
526 DEBUG_PRINT ("Unlocked %d terminal signal", count
);
530 terminal_unrealize_cb (GtkWidget
*term
, TerminalPlugin
*plugin
)
533 count
= g_signal_handlers_block_matched (term
,
536 g_quark_from_string ("style-set"),
540 DEBUG_PRINT ("Blocked %d terminal signal", count
);
545 on_terminal_copy_cb (GtkAction
* action
, TerminalPlugin
*term_plugin
)
549 if (term_plugin
->child_pid
)
550 term
= VTE_TERMINAL (term_plugin
->term
);
552 term
= VTE_TERMINAL (term_plugin
->shell
);
554 if (vte_terminal_get_has_selection(term
))
555 vte_terminal_copy_clipboard(term
);
559 on_terminal_paste_cb (GtkAction
* action
, TerminalPlugin
*term_plugin
)
563 if (term_plugin
->child_pid
)
564 term
= VTE_TERMINAL (term_plugin
->term
);
566 term
= VTE_TERMINAL (term_plugin
->shell
);
568 vte_terminal_paste_clipboard(term
);
572 on_terminal_command_cb (GtkAction
* action
, TerminalPlugin
*term_plugin
)
577 if (term_plugin
->child_pid
)
578 term
= VTE_TERMINAL (term_plugin
->term
);
580 term
= VTE_TERMINAL (term_plugin
->shell
);
582 /* this only works for control + letter */
583 c
= gtk_action_get_name (action
) [strlen (gtk_action_get_name (action
)) - 1] - 64;
585 vte_terminal_feed_child (term
, &c
, 1);
588 static GtkActionEntry actions_terminal
[] = {
590 "ActionCopyFromTerminal", /* Action name */
591 GTK_STOCK_COPY
, /* Stock icon, if any */
592 N_("_Copy"), /* Display label */
593 NULL
, /* short-cut */
595 G_CALLBACK (on_terminal_copy_cb
) /* action callback */
598 "ActionPasteInTerminal",
603 G_CALLBACK (on_terminal_paste_cb
)
605 /* Add other control + letter commands here ending in -CTRL and then letter e.g. -CTRLT */
607 "ActionCommandToTerminal-CTRLC",
612 G_CALLBACK (on_terminal_command_cb
)
615 "ActionCommandToTerminal-CTRLX",
620 G_CALLBACK (on_terminal_command_cb
)
623 "ActionCommandToTerminal-CTRLZ",
628 G_CALLBACK (on_terminal_command_cb
)
633 on_project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
634 const GValue
*value
, gpointer user_data
)
636 TerminalPlugin
*term_plugin
;
637 const gchar
*root_uri
;
639 term_plugin
= (TerminalPlugin
*)plugin
;
641 root_uri
= g_value_get_string (value
);
647 file
= g_file_new_for_uri (root_uri
);
648 path
= g_file_get_path (file
);
650 init_shell (term_plugin
, path
);
652 g_object_unref (file
);
658 create_terminal (TerminalPlugin
*term_plugin
)
662 /* Create new terminal. */
663 term
= vte_terminal_new ();
664 gtk_widget_set_size_request (GTK_WIDGET (term
), 10, 10);
665 vte_terminal_set_size (VTE_TERMINAL (term
), 50, 1);
667 g_signal_connect (G_OBJECT (term
), "focus-in-event",
668 G_CALLBACK (terminal_focus_cb
), term_plugin
);
670 g_signal_connect (G_OBJECT (term
), "button-press-event",
671 G_CALLBACK (terminal_click_cb
), term_plugin
);
673 g_signal_connect (G_OBJECT (term
), "child-exited",
674 G_CALLBACK (terminal_child_exited_cb
), term_plugin
);
677 g_signal_connect (G_OBJECT (term
), "realize",
678 G_CALLBACK (terminal_realize_cb
), term_plugin
);
679 g_signal_connect (G_OBJECT (term
), "unrealize",
680 G_CALLBACK (terminal_unrealize_cb
), term_plugin
);
687 create_box (GtkWidget
*term
)
689 GtkWidget
*sb
, *hbox
;
691 sb
= gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL
, GTK_ADJUSTMENT (vte_terminal_get_adjustment (VTE_TERMINAL (term
))));
692 gtk_widget_set_can_focus (sb
, FALSE
);
694 hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 0);
695 gtk_box_pack_start (GTK_BOX (hbox
), term
, TRUE
, TRUE
, 0);
696 gtk_box_pack_start (GTK_BOX (hbox
), sb
, FALSE
, TRUE
, 0);
698 g_object_ref_sink (hbox
);
704 terminal_create (TerminalPlugin
*term_plugin
)
708 g_return_if_fail(term_plugin
!= NULL
);
710 term_plugin
->child_pid
= 0;
712 /* Create the terminals. */
713 term_plugin
->shell
= create_terminal (term_plugin
);
714 term_plugin
->shell_box
= create_box (term_plugin
->shell
);
716 term_plugin
->term
= create_terminal (term_plugin
);
717 term_plugin
->term_box
= create_box (term_plugin
->term
);
719 /* key-press handler for ctrl-d "kill" */
720 g_signal_connect (G_OBJECT (term_plugin
->term
), "key-press-event",
721 G_CALLBACK (terminal_keypress_cb
), term_plugin
);
723 frame
= gtk_frame_new (NULL
);
724 gtk_widget_show (frame
);
725 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_IN
);
727 gtk_container_add (GTK_CONTAINER (frame
), term_plugin
->shell_box
);
728 gtk_widget_show_all (frame
);
730 term_plugin
->frame
= frame
;
732 init_shell (term_plugin
, NULL
);
736 register_stock_icons (AnjutaPlugin
*plugin
)
738 static gboolean registered
= FALSE
;
744 BEGIN_REGISTER_ICON (plugin
);
745 REGISTER_ICON (ICON_FILE
, "terminal-plugin-icon");
750 activate_plugin (AnjutaPlugin
*plugin
)
752 TerminalPlugin
*term_plugin
;
753 static gboolean initialized
= FALSE
;
756 DEBUG_PRINT ("%s", "TerminalPlugin: Activating Terminal plugin ...");
758 term_plugin
= ANJUTA_PLUGIN_TERMINAL (plugin
);
759 term_plugin
->widget_added_to_shell
= FALSE
;
760 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
761 term_plugin
->action_group
= anjuta_ui_add_action_group_entries (ui
,
762 "ActionGroupTerminal",
763 _("terminal operations"),
765 G_N_ELEMENTS (actions_terminal
),
766 GETTEXT_PACKAGE
, TRUE
, term_plugin
);
767 term_plugin
->uiid
= anjuta_ui_merge (ui
, UI_FILE
);
769 terminal_create (term_plugin
);
773 register_stock_icons (plugin
);
776 /* Setup prefs callbacks */
777 prefs_init (term_plugin
);
779 /* Added widget in shell */
780 anjuta_shell_add_widget (plugin
->shell
, term_plugin
->frame
,
781 "AnjutaTerminal", _("Terminal"),
782 "terminal-plugin-icon",
783 ANJUTA_SHELL_PLACEMENT_BOTTOM
, NULL
);
784 /* terminal_focus_cb (term_plugin->term, NULL, term_plugin); */
785 term_plugin
->widget_added_to_shell
= TRUE
;
788 /* Set all terminal preferences, at that time the terminal widget is
789 * not realized, a few vte functions are not working. Another
790 * possibility could be to call this when the widget is realized */
791 preferences_changed (term_plugin
->settings
, term_plugin
);
793 /* set up project directory watch */
794 term_plugin
->root_watch_id
= anjuta_plugin_add_watch (plugin
,
795 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
796 on_project_root_added
,
803 deactivate_plugin (AnjutaPlugin
*plugin
)
805 TerminalPlugin
*term_plugin
;
808 term_plugin
= ANJUTA_PLUGIN_TERMINAL (plugin
);
810 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
811 anjuta_ui_unmerge (ui
, term_plugin
->uiid
);
812 if (term_plugin
->action_group
)
814 anjuta_ui_remove_action_group (ui
, term_plugin
->action_group
);
815 term_plugin
->action_group
= NULL
;
818 /* terminal plugin widgets are destroyed as soon as it is removed */
819 anjuta_shell_remove_widget (plugin
->shell
, term_plugin
->frame
, NULL
);
821 g_object_unref (term_plugin
->shell_box
);
822 g_object_unref (term_plugin
->term_box
);
825 anjuta_plugin_remove_watch (plugin
, term_plugin
->root_watch_id
, FALSE
);
827 term_plugin
->child_pid
= 0;
830 g_signal_handlers_disconnect_by_func (G_OBJECT (term_plugin
->term
),
831 G_CALLBACK (terminal_unrealize_cb
), term_plugin
);
833 term_plugin
->first_time_realization
= TRUE
;
840 terminal_plugin_dispose (GObject
*obj
)
842 TerminalPlugin
*term_plugin
= ANJUTA_PLUGIN_TERMINAL (obj
);
844 g_object_unref (term_plugin
->settings
);
846 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
850 terminal_plugin_finalize (GObject
*obj
)
852 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
856 terminal_plugin_instance_init (GObject
*obj
)
858 TerminalPlugin
*term_plugin
= ANJUTA_PLUGIN_TERMINAL (obj
);
860 term_plugin
->settings
= g_settings_new (PREF_SCHEMA
);
861 term_plugin
->child_pid
= 0;
862 term_plugin
->pref_profile_combo
= NULL
;
863 term_plugin
->uiid
= 0;
864 term_plugin
->action_group
= NULL
;
865 term_plugin
->pty_flags
= VTE_PTY_DEFAULT
;
867 plugin
->first_time_realization
= TRUE
;
872 terminal_plugin_class_init (GObjectClass
*klass
)
874 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
876 parent_class
= g_type_class_peek_parent (klass
);
878 plugin_class
->activate
= activate_plugin
;
879 plugin_class
->deactivate
= deactivate_plugin
;
880 klass
->dispose
= terminal_plugin_dispose
;
881 klass
->finalize
= terminal_plugin_finalize
;
885 iterminal_execute_command (IAnjutaTerminal
*terminal
,
886 const gchar
*directory
,
887 const gchar
*command
,
888 gchar
**environment
, GError
**error
)
890 TerminalPlugin
*plugin
;
893 plugin
= ANJUTA_PLUGIN_TERMINAL (terminal
);
895 pid
= terminal_execute (plugin
, directory
, command
, environment
);
898 g_set_error (error
, G_SPAWN_ERROR
, G_SPAWN_ERROR_FAILED
, _("Unable to execute command"));
905 iterminal_iface_init(IAnjutaTerminalIface
*iface
)
907 iface
->execute_command
= iterminal_execute_command
;
911 add_data_to_store (gchar
*uuid
, gchar
*name
, GtkListStore
*model
)
915 gtk_list_store_append (model
, &iter
);
916 gtk_list_store_set (model
, &iter
, TERM_STORE_UUID_COLUMN
, uuid
, TERM_STORE_NAME_COLUMN
, name
, -1);
920 on_pref_profile_changed (GtkComboBox
* combo
, TerminalPlugin
* term_plugin
)
922 GtkTreeModel
*model
= gtk_combo_box_get_model (combo
);
926 gtk_combo_box_get_active_iter (combo
, &iter
);
927 gtk_tree_model_get (model
, &iter
, TERM_STORE_UUID_COLUMN
, &uuid
, -1);
928 g_settings_set_string (term_plugin
->settings
, PREFS_TERMINAL_PROFILE
, uuid
);
933 ipreferences_merge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
935 GSettingsSchemaSource
*source
;
936 GSettingsSchema
*schema
;
937 GSettings
*terminal_settings
;
938 GSettings
*profile_settings
;
941 gchar
*default_uuid
= NULL
;
949 GError
*error
= NULL
;
950 GtkCellRenderer
*name_renderer
;
951 GtkCellRenderer
*uuid_renderer
;
953 /* Create the terminal preferences page */
954 TerminalPlugin
*term_plugin
= ANJUTA_PLUGIN_TERMINAL (ipref
);
955 GtkBuilder
*bxml
= gtk_builder_new ();
957 if (!gtk_builder_add_from_file (bxml
, PREFS_BUILDER
, &error
))
959 g_warning ("Couldn't load builder file: %s", error
->message
);
960 g_error_free (error
);
964 anjuta_preferences_add_from_builder (prefs
, bxml
,
965 term_plugin
->settings
,
966 "Terminal", _("Terminal"), ICON_FILE
);
968 term_plugin
->pref_profile_combo
= GTK_WIDGET (gtk_builder_get_object (bxml
, "profile_list_combo"));
969 term_plugin
->pref_default_button
= GTK_WIDGET (gtk_builder_get_object (bxml
, "preferences_toggle:bool:1:0:use-default-profile"));
971 /* Add profile-name and profile-uuid renderers to combo box */
972 name_renderer
= gtk_cell_renderer_text_new ();
973 uuid_renderer
= gtk_cell_renderer_text_new ();
974 gtk_cell_layout_clear (GTK_CELL_LAYOUT(term_plugin
->pref_profile_combo
));
975 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(term_plugin
->pref_profile_combo
), name_renderer
, TRUE
);
976 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(term_plugin
->pref_profile_combo
), uuid_renderer
, FALSE
);
977 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(term_plugin
->pref_profile_combo
), name_renderer
, "text", TERM_STORE_NAME_COLUMN
);
978 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(term_plugin
->pref_profile_combo
), uuid_renderer
, "text", TERM_STORE_UUID_COLUMN
);
979 g_object_set (uuid_renderer
, "style", PANGO_STYLE_ITALIC
, NULL
);
981 /* If at least a default profile exists ... */
982 source
= g_settings_schema_source_get_default ();
983 schema
= g_settings_schema_source_lookup (source
, TERMINAL_PROFILES_LIST_SCHEMA
, TRUE
);
986 terminal_settings
= g_settings_new_full (schema
, NULL
, NULL
);
987 default_uuid
= g_settings_get_string (terminal_settings
, "default");
988 g_settings_schema_unref (schema
);
991 if (default_uuid
!= NULL
) {
993 /* Populate profiles store */
994 profiles
= g_settings_get_strv (terminal_settings
, "list");
995 store
= GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (term_plugin
->pref_profile_combo
)));
996 gtk_list_store_clear (store
);
997 for (i
= 0; profiles
[i
] != NULL
; i
++) {
998 path
= g_strdup_printf ("%s:%s/", TERMINAL_PROFILES_PATH_PREFIX
, profiles
[i
]);
999 profile_settings
= g_settings_new_with_path (TERMINAL_PROFILE_SCHEMA
, path
);
1000 temp
= g_settings_get_string (profile_settings
, TERMINAL_PROFILE_VISIBLE_NAME_KEY
);
1001 add_data_to_store (profiles
[i
], temp
, store
);
1004 /* Display saved profile in combo box */
1005 saved_uuid
= g_settings_get_string (term_plugin
->settings
, PREFS_TERMINAL_PROFILE
);
1006 if (saved_uuid
!= NULL
)
1009 iter_valid
= gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store
), &iter
);
1010 while (iter_valid
&& !found
)
1012 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
, TERM_STORE_UUID_COLUMN
, &temp
, -1);
1013 if (g_strcmp0 (saved_uuid
, temp
) == 0)
1015 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (term_plugin
->pref_profile_combo
), &iter
);
1018 iter_valid
= gtk_tree_model_iter_next (GTK_TREE_MODEL (store
), &iter
);
1021 g_free (saved_uuid
);
1024 /* Save profile selection if changed */
1025 g_signal_connect (term_plugin
->pref_profile_combo
, "changed",
1026 G_CALLBACK (on_pref_profile_changed
), term_plugin
);
1028 /* Deactivate profile selection if not using default profile */
1029 use_default_profile_cb (GTK_TOGGLE_BUTTON (term_plugin
->pref_default_button
), term_plugin
);
1030 g_signal_connect (G_OBJECT(term_plugin
->pref_default_button
), "toggled",
1031 G_CALLBACK (use_default_profile_cb
), term_plugin
);
1033 g_object_unref(terminal_settings
);
1037 /* No profile, perhaps GNOME Terminal is not installed,
1038 * Remove selection */
1039 gtk_widget_set_sensitive (term_plugin
->pref_profile_combo
, FALSE
);
1040 gtk_widget_set_sensitive (term_plugin
->pref_default_button
, FALSE
);
1043 g_object_unref (bxml
);
1047 ipreferences_unmerge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
1049 TerminalPlugin
* term_plugin
= ANJUTA_PLUGIN_TERMINAL (ipref
);
1050 g_signal_handlers_disconnect_by_func(G_OBJECT(term_plugin
->pref_default_button
),
1051 G_CALLBACK (use_default_profile_cb
), term_plugin
);
1052 anjuta_preferences_remove_page(prefs
, _("Terminal"));
1053 term_plugin
->pref_profile_combo
= NULL
;
1057 ipreferences_iface_init(IAnjutaPreferencesIface
* iface
)
1059 iface
->merge
= ipreferences_merge
;
1060 iface
->unmerge
= ipreferences_unmerge
;
1063 ANJUTA_PLUGIN_BEGIN (TerminalPlugin
, terminal_plugin
);
1064 ANJUTA_PLUGIN_ADD_INTERFACE (iterminal
, IANJUTA_TYPE_TERMINAL
);
1065 ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences
, IANJUTA_TYPE_PREFERENCES
);
1068 ANJUTA_SIMPLE_PLUGIN (TerminalPlugin
, terminal_plugin
);