Updated Spanish translation
[anjuta-git-plugin.git] / plugins / terminal / terminal.c
blob45e030a16291a6b1b0f4244e7b5a8e9d8470822e
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 plugin.c
4 Copyright (C) 2000 Naba Kumar
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
23 #include <signal.h>
25 #include <libanjuta/anjuta-shell.h>
26 #include <libanjuta/anjuta-debug.h>
28 #include <libanjuta/interfaces/ianjuta-terminal.h>
29 #include <libanjuta/interfaces/ianjuta-preferences.h>
31 #include <signal.h>
33 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-terminal-plugin.ui"
34 #define PREFS_GLADE PACKAGE_DATA_DIR"/glade/anjuta-terminal-plugin.glade"
35 #define ICON_FILE "anjuta-terminal-plugin-48.png"
37 /* Some desktop/gnome-terminal gconf keys. */
38 #define GCONF_MONOSPACE_FONT "/desktop/gnome/interface/monospace_font_name"
39 #define GCONF_DEFAULT_PROFILE "/apps/gnome-terminal/global/default_profile"
40 #define GCONF_PROFILE_LIST "/apps/gnome-terminal/global/profile_list"
42 #define GCONF_PROFILE_PREFIX "/apps/gnome-terminal/profiles"
43 #define GCONF_BACKGROUND_COLOR "background_color"
44 #define GCONF_BACKSPACE_BINDING "backspace_binding"
45 #define GCONF_CURSOR_BLINK "cursor_blink"
46 #define GCONF_DELETE_BINDING "delete_binding"
47 #define GCONF_EXIT_ACTION "exit_action"
48 #define GCONF_VTE_TERMINAL_FONT "font"
49 #define GCONF_FOREGROUND_COLOR "foreground_color"
50 #define GCONF_SCROLLBACK_LINES "scrollback_lines"
51 #define GCONF_SCROLL_ON_KEYSTROKE "scroll_on_keystroke"
52 #define GCONF_SCROLL_ON_OUTPUT "scroll_on_output"
53 #define GCONF_SILENT_BELL "silent_bell"
54 #define GCONF_USE_SYSTEM_FONT "use_system_font"
55 #define GCONF_WORD_CHARS "word_chars"
57 #define PREFS_TERMINAL_PROFILE_USE_DEFAULT "terminal.default.profile"
58 #define PREFS_TERMINAL_PROFILE "terminal.profile"
60 #include <gconf/gconf-client.h>
61 #include <vte/vte.h>
62 #include <vte/reaper.h>
63 #include <pwd.h>
64 #include <gtk/gtk.h>
65 #include <libanjuta/anjuta-plugin.h>
67 extern GType terminal_plugin_get_type (GTypeModule *module);
68 #define ANJUTA_PLUGIN_TERMINAL_TYPE (terminal_plugin_get_type (NULL))
69 #define ANJUTA_PLUGIN_TERMINAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_PLUGIN_TERMINAL_TYPE, TerminalPlugin))
70 #define ANJUTA_PLUGIN_TERMINAL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_PLUGIN_TERMINAL_CLASS, TerminalPluginClass))
71 #define ANJUTA_IS_PLUGIN_TERMINAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_PLUGIN_TERMINAL_TYPE))
72 #define ANJUTA_IS_PLUGIN_TERMINAL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_PLUGIN_TERMINAL_TYPE))
73 #define ANJUTA_PLUGIN_TERMINAL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_PLUGIN_TERMINAL_TYPE, TerminalPluginClass))
75 typedef struct _TerminalPlugin TerminalPlugin;
76 typedef struct _TerminalPluginClass TerminalPluginClass;
78 struct _TerminalPlugin{
79 AnjutaPlugin parent;
81 gint uiid;
82 GtkActionGroup *action_group;
84 AnjutaPreferences *prefs;
85 pid_t child_pid;
86 GtkWidget *term;
87 GtkWidget *hbox;
88 GtkWidget *frame;
89 GtkWidget *scrollbar;
90 GtkWidget *pref_profile_combo;
91 GtkWidget *pref_default_button;
92 gboolean widget_added_to_shell;
93 GList *gconf_notify_ids;
94 #if OLD_VTE == 1
95 gboolean first_time_realization;
96 #endif
99 struct _TerminalPluginClass{
100 AnjutaPluginClass parent_class;
103 static gpointer parent_class;
105 static const gchar*
106 get_profile_key (const gchar *profile, const gchar *key)
108 /* A resonably 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);
114 return buffer;
117 #define GET_PROFILE_BOOL(key) \
118 gconf_client_get_bool (client, \
119 get_profile_key (profile, key), \
120 NULL);
121 #define GET_PROFILE_INT(key) \
122 gconf_client_get_int (client, \
123 get_profile_key (profile, key), \
124 NULL);
125 #define GET_PROFILE_STRING(key) \
126 gconf_client_get_string (client, \
127 get_profile_key (profile, key), \
128 NULL);
130 static void
131 preferences_changed (AnjutaPreferences *prefs, TerminalPlugin *term)
133 GConfClient *client;
134 char *text;
135 int value;
136 gboolean setting;
137 GdkColor color[2];
138 GdkColor* foreground;
139 GdkColor* background;
140 GtkWidget *vte;
141 gchar *profile;
142 AnjutaPreferences *pref;
144 pref = term->prefs;
145 vte = term->term;
146 client = gconf_client_get_default ();
148 g_return_if_fail (client != NULL);
150 /* Update the currently available list of terminal profiles */
151 setting = anjuta_preferences_get_int (pref,
152 PREFS_TERMINAL_PROFILE_USE_DEFAULT);
153 if (setting)
155 /* Use the currently selected profile in gnome-terminal */
156 text = gconf_client_get_string (client, GCONF_DEFAULT_PROFILE, NULL);
158 else
160 /* Otherwise use the user selected profile */
161 text = anjuta_preferences_get (pref, PREFS_TERMINAL_PROFILE);
163 if (!text || (*text == '\0'))
164 text = g_strdup ("Default");
165 profile = text;
167 vte_terminal_set_mouse_autohide (VTE_TERMINAL (vte), TRUE);
169 /* Set terminal font either using the desktop wide font or g-t one. */
170 setting = GET_PROFILE_BOOL (GCONF_USE_SYSTEM_FONT);
171 if (setting) {
172 text = gconf_client_get_string (client, GCONF_MONOSPACE_FONT, NULL);
173 if (!text)
174 text = GET_PROFILE_STRING (GCONF_VTE_TERMINAL_FONT);
175 } else {
176 text = GET_PROFILE_STRING (GCONF_VTE_TERMINAL_FONT);
178 vte_terminal_set_font_from_string (VTE_TERMINAL (vte), text);
179 g_free (text);
181 setting = GET_PROFILE_BOOL (GCONF_CURSOR_BLINK);
182 vte_terminal_set_cursor_blinks (VTE_TERMINAL (vte), setting);
183 setting = GET_PROFILE_BOOL (GCONF_SILENT_BELL);
184 vte_terminal_set_audible_bell (VTE_TERMINAL (vte), !setting);
185 value = GET_PROFILE_INT (GCONF_SCROLLBACK_LINES);
186 vte_terminal_set_scrollback_lines (VTE_TERMINAL (vte), value);
187 setting = GET_PROFILE_BOOL (GCONF_SCROLL_ON_KEYSTROKE);
188 vte_terminal_set_scroll_on_keystroke (VTE_TERMINAL (vte), setting);
189 setting = GET_PROFILE_BOOL (GCONF_SCROLL_ON_OUTPUT);
190 vte_terminal_set_scroll_on_output (VTE_TERMINAL (vte), TRUE);
191 text = GET_PROFILE_STRING (GCONF_WORD_CHARS);
192 if (text)
193 vte_terminal_set_word_chars (VTE_TERMINAL (vte), text);
194 g_free (text);
196 text = GET_PROFILE_STRING (GCONF_BACKSPACE_BINDING);
197 if (text)
199 if (!strcmp (text, "ascii-del"))
200 vte_terminal_set_backspace_binding (VTE_TERMINAL (vte),
201 VTE_ERASE_ASCII_DELETE);
202 else if (!strcmp (text, "escape-sequence"))
203 vte_terminal_set_backspace_binding (VTE_TERMINAL (vte),
204 VTE_ERASE_DELETE_SEQUENCE);
205 else if (!strcmp (text, "control-h"))
206 vte_terminal_set_backspace_binding (VTE_TERMINAL (vte),
207 VTE_ERASE_ASCII_BACKSPACE);
208 else
209 vte_terminal_set_backspace_binding (VTE_TERMINAL (vte),
210 VTE_ERASE_AUTO);
211 g_free (text);
213 text = GET_PROFILE_STRING (GCONF_DELETE_BINDING);
214 if (text)
216 if (!strcmp (text, "ascii-del"))
217 vte_terminal_set_delete_binding (VTE_TERMINAL (vte),
218 VTE_ERASE_ASCII_DELETE);
219 else if (!strcmp (text, "escape-sequence"))
220 vte_terminal_set_delete_binding (VTE_TERMINAL (vte),
221 VTE_ERASE_DELETE_SEQUENCE);
222 else if (!strcmp (text, "control-h"))
223 vte_terminal_set_delete_binding (VTE_TERMINAL (vte),
224 VTE_ERASE_ASCII_BACKSPACE);
225 else
226 vte_terminal_set_delete_binding (VTE_TERMINAL (vte),
227 VTE_ERASE_AUTO);
228 g_free (text);
230 /* Set fore- and background colors. */
231 text = GET_PROFILE_STRING (GCONF_BACKGROUND_COLOR);
232 if (text)
234 gdk_color_parse (text, &color[0]);
235 g_free (text);
237 background = text ? &color[0] : NULL;
238 text = GET_PROFILE_STRING (GCONF_FOREGROUND_COLOR);
239 if (text)
241 gdk_color_parse (text, &color[1]);
242 g_free (text);
244 foreground = text ? &color[1] : NULL;
245 /* vte_terminal_set_colors works even if the terminal widget is not realized
246 * which is not the case with vte_terminal_set_color_foreground and
247 * vte_terminal_set_color_background */
248 vte_terminal_set_colors (VTE_TERMINAL (vte), foreground, background, NULL, 0);
249 g_free (profile);
250 g_object_unref (client);
253 static void
254 on_gconf_notify_prefs (GConfClient *gclient, guint cnxn_id,
255 GConfEntry *entry, gpointer user_data)
257 TerminalPlugin *tp = ANJUTA_PLUGIN_TERMINAL (user_data);
258 preferences_changed (tp->prefs, tp);
261 #define REGISTER_NOTIFY(key, func) \
262 notify_id = anjuta_preferences_notify_add (tp->prefs, \
263 key, func, tp, NULL); \
264 tp->gconf_notify_ids = g_list_prepend (tp->gconf_notify_ids, \
265 GUINT_TO_POINTER (notify_id));
266 static void
267 prefs_init (TerminalPlugin *tp)
269 guint notify_id;
270 REGISTER_NOTIFY (PREFS_TERMINAL_PROFILE, on_gconf_notify_prefs);
271 REGISTER_NOTIFY (PREFS_TERMINAL_PROFILE_USE_DEFAULT, on_gconf_notify_prefs);
274 static void
275 prefs_finalize (TerminalPlugin *tp)
277 GList *node;
278 node = tp->gconf_notify_ids;
279 while (node)
281 anjuta_preferences_notify_remove (tp->prefs,
282 GPOINTER_TO_UINT (node->data));
283 node = g_list_next (node);
285 g_list_free (tp->gconf_notify_ids);
286 tp->gconf_notify_ids = NULL;
289 static void
290 use_default_profile_cb (GtkToggleButton *button,
291 TerminalPlugin *term)
293 if (gtk_toggle_button_get_active (button))
294 gtk_widget_set_sensitive (term->pref_profile_combo, FALSE);
295 else
296 gtk_widget_set_sensitive (term->pref_profile_combo, TRUE);
299 static void
300 terminal_child_exited_cb (VteReaper *vtereaper, gint pid, gint status, TerminalPlugin *term_plugin)
302 g_signal_emit_by_name(term_plugin, "child-exited", pid, status);
305 static pid_t
306 terminal_execute (TerminalPlugin *term_plugin, const gchar *directory,
307 const gchar *command, gchar **environment)
309 char **args, **args_ptr;
310 GList *args_list, *args_list_ptr;
311 gchar *dir;
312 VteTerminal *term;
314 g_return_val_if_fail (command != NULL, 0);
316 /* Prepare command args */
317 args_list = anjuta_util_parse_args_from_string (command);
318 args = g_new (char*, g_list_length (args_list) + 1);
319 args_list_ptr = args_list;
320 args_ptr = args;
321 while (args_list_ptr)
323 *args_ptr = (char*) args_list_ptr->data;
324 args_list_ptr = g_list_next (args_list_ptr);
325 args_ptr++;
327 *args_ptr = NULL;
329 if (directory == NULL)
330 dir = g_path_get_dirname (args[0]);
331 else
332 dir = g_strdup (directory);
334 term = VTE_TERMINAL (term_plugin->term);
336 vte_terminal_reset (term, TRUE, TRUE);
338 term_plugin->child_pid = vte_terminal_fork_command (term, args[0], args,
339 environment, dir, 0, 0, 0);
340 vte_reaper_add_child (term_plugin->child_pid);
342 g_free (dir);
343 g_free (args);
344 g_list_foreach (args_list, (GFunc)g_free, NULL);
345 g_list_free (args_list);
347 if (term_plugin->widget_added_to_shell)
348 anjuta_shell_present_widget (ANJUTA_PLUGIN (term_plugin)->shell,
349 term_plugin->frame, NULL);
351 return term_plugin->child_pid;
354 static void
355 terminal_init_cb (GtkWidget *widget, TerminalPlugin *term_plugin)
357 struct passwd *pw;
358 const char *shell;
359 const char *dir;
361 pw = getpwuid (getuid ());
362 if (pw) {
363 shell = pw->pw_shell;
364 dir = pw->pw_dir;
365 } else {
366 shell = "/bin/sh";
367 dir = "/";
369 terminal_execute (term_plugin, dir, shell, NULL);
372 static gboolean
373 terminal_focus_cb (GtkWidget *widget, GdkEvent *event,
374 TerminalPlugin *term)
376 if (term->child_pid == 0)
378 terminal_init_cb (widget, term);
380 gtk_widget_grab_focus (widget);
381 return FALSE;
384 static gboolean
385 terminal_keypress_cb (GtkWidget *widget, GdkEventKey *event,
386 TerminalPlugin *term)
388 /* Fixme: GDK_KEY_PRESS doesn't seem to be called for our keys */
389 if (event->type != GDK_KEY_RELEASE)
390 return FALSE;
392 /* ctrl-d */
393 if (event->keyval == GDK_d ||
394 event->keyval == GDK_D)
396 /* Ctrl pressed */
397 if (event->state & GDK_CONTROL_MASK)
399 kill (term->child_pid, SIGINT);
400 term->child_pid = 0;
401 terminal_init_cb (GTK_WIDGET (term->term), term);
402 return TRUE;
405 /* Shift-Insert */
406 if ((event->keyval == GDK_Insert || event->keyval == GDK_KP_Insert) &&
407 event->state & GDK_SHIFT_MASK)
409 vte_terminal_paste_clipboard(VTE_TERMINAL(term->term));
410 return TRUE;
412 return FALSE;
415 static gboolean
416 terminal_click_cb (GtkWidget *widget, GdkEventButton *event,
417 TerminalPlugin *term)
419 if (event->button == 3)
421 AnjutaUI *ui;
422 GtkMenu *popup;
423 GtkAction *action;
425 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(term)->shell, NULL);
426 popup = GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupTerminal"));
427 action = gtk_action_group_get_action (term->action_group, "ActionCopyFromTerminal");
428 gtk_action_set_sensitive (action,vte_terminal_get_has_selection(VTE_TERMINAL(term->term)));
430 gtk_menu_popup (popup, NULL, NULL, NULL, NULL,
431 event->button, event->time);
434 return FALSE;
437 #if OLD_VTE == 1
438 /* VTE has a terrible bug where it could crash when container is changed.
439 * The problem has been traced in vte where its style-set handler does not
440 * adequately check if the widget is realized, resulting in a crash when
441 * style-set occurs in an unrealized vte widget.
443 * This work around blocks all style-set signal emissions when the vte
444 * widget is unrealized. -Naba
446 static void
447 terminal_realize_cb (GtkWidget *term, TerminalPlugin *plugin)
449 gint count;
451 if (plugin->first_time_realization)
453 /* First time realize does not have the signals blocked */
454 plugin->first_time_realization = FALSE;
455 return;
457 count = g_signal_handlers_unblock_matched (term,
458 G_SIGNAL_MATCH_DATA,
460 g_quark_from_string ("style-set"),
461 NULL,
462 NULL,
463 NULL);
464 DEBUG_PRINT ("Unlocked %d terminal signal", count);
467 static void
468 terminal_unrealize_cb (GtkWidget *term, TerminalPlugin *plugin)
470 gint count;
471 count = g_signal_handlers_block_matched (term,
472 G_SIGNAL_MATCH_DATA,
474 g_quark_from_string ("style-set"),
475 NULL,
476 NULL,
477 NULL);
478 DEBUG_PRINT ("Blocked %d terminal signal", count);
480 #endif
482 static void
483 terminal_destroy_cb (GtkWidget *widget, TerminalPlugin *term)
485 g_signal_handlers_disconnect_by_func (G_OBJECT (widget),
486 G_CALLBACK (terminal_init_cb), term);
489 static void
490 on_terminal_copy_cb (GtkAction * action, TerminalPlugin *term)
492 if (vte_terminal_get_has_selection(VTE_TERMINAL(term->term)))
493 vte_terminal_copy_clipboard(VTE_TERMINAL(term->term));
496 static void
497 on_terminal_paste_cb (GtkAction * action, TerminalPlugin *term)
499 vte_terminal_paste_clipboard(VTE_TERMINAL(term->term));
502 static GtkActionEntry actions_terminal[] = {
504 "ActionCopyFromTerminal", /* Action name */
505 GTK_STOCK_COPY, /* Stock icon, if any */
506 N_("_Copy"), /* Display label */
507 NULL, /* short-cut */
508 NULL, /* Tooltip */
509 G_CALLBACK (on_terminal_copy_cb) /* action callback */
512 "ActionPasteInTerminal",
513 GTK_STOCK_PASTE,
514 N_("_Paste"),
515 NULL,
516 NULL,
517 G_CALLBACK (on_terminal_paste_cb)
521 static void
522 terminal_create (TerminalPlugin *term_plugin)
524 GtkWidget *sb, *frame, *hbox;
526 g_return_if_fail(term_plugin != NULL);
528 term_plugin->child_pid = 0;
530 /* Create new terminal. */
531 term_plugin->term = vte_terminal_new ();
532 gtk_widget_set_size_request (GTK_WIDGET (term_plugin->term), 10, 10);
533 vte_terminal_set_size (VTE_TERMINAL (term_plugin->term), 50, 1);
535 g_signal_connect (G_OBJECT (term_plugin->term), "focus_in_event",
536 G_CALLBACK (terminal_focus_cb), term_plugin);
537 g_signal_connect (G_OBJECT (term_plugin->term), "child-exited",
538 G_CALLBACK (terminal_init_cb), term_plugin);
539 g_signal_connect (G_OBJECT (term_plugin->term), "destroy",
540 G_CALLBACK (terminal_destroy_cb), term_plugin);
541 g_signal_connect (G_OBJECT (term_plugin->term), "key-press-event",
542 G_CALLBACK (terminal_keypress_cb), term_plugin);
543 g_signal_connect (G_OBJECT (term_plugin->term), "button-press-event",
544 G_CALLBACK (terminal_click_cb), term_plugin);
545 #if OLD_VTE == 1
546 g_signal_connect (G_OBJECT (term_plugin->term), "realize",
547 G_CALLBACK (terminal_realize_cb), term_plugin);
548 g_signal_connect (G_OBJECT (term_plugin->term), "unrealize",
549 G_CALLBACK (terminal_unrealize_cb), term_plugin);
550 #endif
551 g_signal_connect (vte_reaper_get(), "child-exited",
552 G_CALLBACK (terminal_child_exited_cb), term_plugin);
554 sb = gtk_vscrollbar_new (GTK_ADJUSTMENT (VTE_TERMINAL (term_plugin->term)->adjustment));
555 GTK_WIDGET_UNSET_FLAGS (sb, GTK_CAN_FOCUS);
557 frame = gtk_frame_new (NULL);
558 gtk_widget_show (frame);
559 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
561 hbox = gtk_hbox_new (FALSE, 0);
562 gtk_container_add (GTK_CONTAINER (frame), hbox);
563 gtk_box_pack_start (GTK_BOX (hbox), term_plugin->term, TRUE, TRUE, 0);
564 gtk_box_pack_start (GTK_BOX (hbox), sb, FALSE, TRUE, 0);
565 gtk_widget_show_all (frame);
567 term_plugin->scrollbar = sb;
568 term_plugin->frame = frame;
569 term_plugin->hbox = hbox;
571 terminal_init_cb (GTK_WIDGET (term_plugin->term), term_plugin);
574 static void
575 register_stock_icons (AnjutaPlugin *plugin)
577 static gboolean registered = FALSE;
579 if (registered)
580 return;
581 registered = TRUE;
583 BEGIN_REGISTER_ICON (plugin);
584 REGISTER_ICON (ICON_FILE, "terminal-plugin-icon");
585 END_REGISTER_ICON;
588 static gboolean
589 activate_plugin (AnjutaPlugin *plugin)
591 TerminalPlugin *term_plugin;
592 static gboolean initialized = FALSE;
593 AnjutaUI *ui;
595 DEBUG_PRINT ("TerminalPlugin: Activating Terminal plugin ...");
597 term_plugin = ANJUTA_PLUGIN_TERMINAL (plugin);
598 term_plugin->prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
599 term_plugin->widget_added_to_shell = FALSE;
600 ui = anjuta_shell_get_ui (plugin->shell, NULL);
601 term_plugin->action_group = anjuta_ui_add_action_group_entries (ui,
602 "ActionGroupTerminal",
603 _("terminal operations"),
604 actions_terminal,
605 G_N_ELEMENTS (actions_terminal),
606 GETTEXT_PACKAGE, TRUE, term_plugin);
607 term_plugin->uiid = anjuta_ui_merge (ui, UI_FILE);
609 terminal_create (term_plugin);
611 if (!initialized)
613 register_stock_icons (plugin);
616 /* Setup prefs callbacks */
617 prefs_init (term_plugin);
619 /* Added widget in shell */
620 anjuta_shell_add_widget (plugin->shell, term_plugin->frame,
621 "AnjutaTerminal", _("Terminal"),
622 "terminal-plugin-icon",
623 ANJUTA_SHELL_PLACEMENT_BOTTOM, NULL);
624 /* terminal_focus_cb (term_plugin->term, NULL, term_plugin); */
625 term_plugin->widget_added_to_shell = TRUE;
626 initialized = TRUE;
628 /* Set all terminal preferences, at that time the terminal widget is
629 * not realized, a few vte functions are not working. Another
630 * possibility could be to call this when the widget is realized */
631 preferences_changed (term_plugin->prefs, term_plugin);
633 return TRUE;
636 static gboolean
637 deactivate_plugin (AnjutaPlugin *plugin)
639 TerminalPlugin *term_plugin;
640 AnjutaUI *ui;
642 term_plugin = ANJUTA_PLUGIN_TERMINAL (plugin);
644 ui = anjuta_shell_get_ui (plugin->shell, NULL);
645 anjuta_ui_unmerge (ui, term_plugin->uiid);
646 if (term_plugin->action_group)
648 anjuta_ui_remove_action_group (ui, term_plugin->action_group);
649 term_plugin->action_group = NULL;
652 prefs_finalize (term_plugin);
654 #if OLD_VTE == 1
655 g_signal_handlers_disconnect_by_func (G_OBJECT (term_plugin->term),
656 G_CALLBACK (terminal_unrealize_cb), term_plugin);
657 #endif
659 /* terminal plugin widgets are destroyed as soon as it is removed */
660 anjuta_shell_remove_widget (plugin->shell, term_plugin->frame, NULL);
663 g_signal_handlers_disconnect_by_func (G_OBJECT (term_plugin->pref_default_button),
664 G_CALLBACK (use_default_profile_cb),
665 term_plugin);
667 term_plugin->frame = NULL;
668 term_plugin->term = NULL;
669 term_plugin->scrollbar = NULL;
670 term_plugin->hbox = NULL;
671 term_plugin->child_pid = 0;
672 #if OLD_VTE == 1
673 term_plugin->first_time_realization = TRUE;
674 #endif
676 // terminal_finalize (term_plugin);
677 return TRUE;
680 static void
681 terminal_plugin_dispose (GObject *obj)
683 G_OBJECT_CLASS (parent_class)->dispose (obj);
686 static void
687 terminal_plugin_finalize (GObject *obj)
689 G_OBJECT_CLASS (parent_class)->finalize (obj);
692 static void
693 terminal_plugin_instance_init (GObject *obj)
695 TerminalPlugin *plugin = ANJUTA_PLUGIN_TERMINAL (obj);
696 plugin->gconf_notify_ids = NULL;
697 plugin->child_pid = 0;
698 plugin->pref_profile_combo = NULL;
699 plugin->uiid = 0;
700 plugin->action_group = NULL;
701 #if OLD_VTE == 1
702 plugin->first_time_realization = TRUE;
703 #endif
706 static void
707 terminal_plugin_class_init (GObjectClass *klass)
709 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
711 parent_class = g_type_class_peek_parent (klass);
713 plugin_class->activate = activate_plugin;
714 plugin_class->deactivate = deactivate_plugin;
715 klass->dispose = terminal_plugin_dispose;
716 klass->finalize = terminal_plugin_finalize;
719 static pid_t
720 iterminal_execute_command (IAnjutaTerminal *terminal,
721 const gchar *directory,
722 const gchar *command,
723 gchar **environment, GError **err)
725 TerminalPlugin *plugin;
726 const gchar *dir;
728 plugin = ANJUTA_PLUGIN_TERMINAL (terminal);
730 if (directory == NULL || strlen (directory) <= 0)
731 dir = NULL;
732 else
733 dir = directory;
735 return terminal_execute (plugin, directory, command, environment);
738 static void
739 iterminal_iface_init(IAnjutaTerminalIface *iface)
741 iface->execute_command = iterminal_execute_command;
744 static void
745 on_add_string_in_store (gpointer data, gpointer user_data)
747 GtkListStore* model = (GtkListStore *)user_data;
748 GtkTreeIter iter;
750 gtk_list_store_append (model, &iter);
751 gtk_list_store_set (model, &iter, 0, (const gchar *)data, -1);
754 static void
755 on_concat_string (gpointer data, gpointer user_data)
757 GString* str = (GString *)user_data;
759 if (str->len != 0)
760 g_string_append_c (str, ',');
761 g_string_append (str, data);
764 static void
765 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
767 GSList *profiles;
768 GConfClient *client;
770 /* Create the terminal preferences page */
771 TerminalPlugin* term_plugin = ANJUTA_PLUGIN_TERMINAL (ipref);
772 GladeXML *gxml = glade_xml_new (PREFS_GLADE, "preferences_dialog_terminal", NULL);
773 anjuta_preferences_add_page (term_plugin->prefs, gxml,
774 "Terminal", _("Terminal"), ICON_FILE);
776 term_plugin->pref_profile_combo = glade_xml_get_widget (gxml, "profile_list_combo");
777 term_plugin->pref_default_button = glade_xml_get_widget (gxml, "preferences_toggle:bool:1:0:terminal.default.profile");
779 /* Update the currently available list of terminal profiles */
780 client = gconf_client_get_default ();
781 profiles = gconf_client_get_list (client, GCONF_PROFILE_LIST,
782 GCONF_VALUE_STRING, NULL);
783 if (profiles)
785 GtkListStore *store;
786 GString *default_value;
788 default_value = g_string_new (NULL);
789 store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (term_plugin->pref_profile_combo)));
791 gtk_list_store_clear (store);
792 g_slist_foreach (profiles, on_add_string_in_store, store);
793 g_slist_foreach (profiles, on_concat_string, default_value);
794 g_slist_foreach (profiles, (GFunc)g_free, NULL);
795 g_slist_free (profiles);
797 anjuta_preferences_register_property_raw (term_plugin->prefs,
798 term_plugin->pref_profile_combo,
799 PREFS_TERMINAL_PROFILE,
800 default_value->str,
802 ANJUTA_PROPERTY_OBJECT_TYPE_COMBO,
803 ANJUTA_PROPERTY_DATA_TYPE_TEXT);
804 g_string_free (default_value, TRUE);
806 use_default_profile_cb (GTK_TOGGLE_BUTTON (term_plugin->pref_default_button), term_plugin);
807 g_signal_connect (G_OBJECT(term_plugin->pref_default_button), "toggled",
808 G_CALLBACK (use_default_profile_cb), term_plugin);
810 else
812 /* No profile, perhaps GNOME Terminal is not installed,
813 * Remove selection */
814 gtk_widget_set_sensitive (term_plugin->pref_profile_combo, FALSE);
815 gtk_widget_set_sensitive (term_plugin->pref_default_button, FALSE);
818 g_object_unref (gxml);
821 static void
822 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
824 TerminalPlugin* term_plugin = ANJUTA_PLUGIN_TERMINAL (ipref);
825 g_signal_handlers_disconnect_by_func(G_OBJECT(term_plugin->pref_default_button),
826 G_CALLBACK (use_default_profile_cb), term_plugin);
827 anjuta_preferences_remove_page(prefs, _("Terminal"));
828 term_plugin->pref_profile_combo = NULL;
831 static void
832 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
834 iface->merge = ipreferences_merge;
835 iface->unmerge = ipreferences_unmerge;
838 ANJUTA_PLUGIN_BEGIN (TerminalPlugin, terminal_plugin);
839 ANJUTA_PLUGIN_ADD_INTERFACE (iterminal, IANJUTA_TYPE_TERMINAL);
840 ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences, IANJUTA_TYPE_PREFERENCES);
841 ANJUTA_PLUGIN_END;
843 ANJUTA_SIMPLE_PLUGIN (TerminalPlugin, terminal_plugin);