# Copyright (C) 2007, Eduardo Silva . # Copyright (C) 2008, One Laptop Per Child # Copyright (C) 2009, Simon Schampijer # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os import sys #import simplejson import pickle import ConfigParser import shutil import gobject from exceptions import * import logging from gettext import gettext as _ import gtk import vte import pango from sugar.graphics.toolbutton import ToolButton from sugar.activity.activity import Activity import sugar.activity.activity as activity from sugar import env from help.help import Help # Attempt to import the new toolbar classes. If the import fails, # fall back to the old toolbar style. try: from sugar.graphics.toolbarbox import ToolbarBox from sugar.graphics.toolbarbox import ToolbarButton from sugar.activity.widgets import ActivityToolbarButton from sugar.activity.widgets import StopButton NEW_TOOLBARS = True except ImportError: from sugar.activity.activity import ActivityToolbox NEW_TOOLBARS = False from terminal import TerminalBase logging.basicConfig() _logger = logging.getLogger('vimtutor') _logger.setLevel(logging.DEBUG) class TerminalActivity(TerminalBase, Activity): def __init__(self, vimtutor, handle): create_jobject = True #not handle.object_id Activity.__init__(self, handle, create_jobject) TerminalBase.__init__(self, vimtutor, handle) self.handle = handle self._vimtutor = vimtutor self.help_x11 = False self.max_participants = 1 self.accelerator = gtk.AccelGroup() self.add_accel_group(self.accelerator) edit_toolbar = self._create_edit_toolbar() edit_toolbar.show() view_toolbar = self._create_view_toolbar() view_toolbar.show() self._delete_tab_toolbar = None self._previous_tab_toolbar = None self._next_tab_toolbar = None tab_toolbar = self._create_tab_toolbar() tab_toolbar.show() help_toolbar = self._create_help_toolbar() help_toolbar.show() self.help = Help(self) # Add a button that will be used to become root easily. root_button = ToolButton('activity-become-root') root_button.set_tooltip(_('Become root')) root_button.connect('clicked', self.__become_root_cb) root_button.show() if NEW_TOOLBARS: toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) #activity_button.page.keep.props.accelerator = 'S' activity_button.show() edit_toolbar_button = ToolbarButton( page=edit_toolbar, icon_name='toolbar-edit') toolbar_box.toolbar.insert(edit_toolbar_button, -1) edit_toolbar_button.show() view_toolbar_button = ToolbarButton( page=view_toolbar, icon_name='toolbar-view') toolbar_box.toolbar.insert(view_toolbar_button, -1) view_toolbar_button.show() tab_toolbar_button = ToolbarButton( page=tab_toolbar, icon_name='toolbar-tab') toolbar_box.toolbar.insert(tab_toolbar_button, -1) tab_toolbar_button.show() toolbar_box.toolbar.insert(root_button, -1) separator = gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) stop_button.add_accelerator('clicked', self.accelerator, ord('Q'), gtk.gdk.SHIFT_MASK, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) #stop_button.props.accelerator = 'Q' toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show() else: toolbox = ActivityToolbox(self) toolbox.add_toolbar(_('Edit'), edit_toolbar) toolbox.add_toolbar(_('View'), view_toolbar) toolbox.add_toolbar(_('Tab'), tab_toolbar) toolbox.add_toolbar(_('Help'), help_toolbar) toolbox.connect_after('current_toolbar_changed', self._toolbar_changed_cb) self.HELP_INDEX = 4 self.set_toolbox(toolbox) toolbox.show() self.set_canvas(self._notebook) def _create_edit_toolbar(self): edit_toolbar = activity.EditToolbar() edit_toolbar.undo.props.visible = False edit_toolbar.redo.props.visible = False edit_toolbar.separator.props.visible = False edit_toolbar.copy.connect('clicked', self.__copy_cb) #edit_toolbar.copy.props.accelerator = 'C' edit_toolbar.copy.add_accelerator('clicked', self.accelerator, ord('C'), gtk.gdk.SHIFT_MASK & gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) edit_toolbar.paste.connect('clicked', self.__paste_cb) #edit_toolbar.paste.props.accelerator = 'V' edit_toolbar.paste.add_accelerator('clicked', self.accelerator, ord('V'), gtk.gdk.SHIFT_MASK & gtk.gdk.CONTROL_MASK , gtk.ACCEL_VISIBLE) return edit_toolbar def __copy_cb(self, button): vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt if vt.get_has_selection(): vt.copy_clipboard() def __paste_cb(self, button): vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt vt.paste_clipboard() def _create_view_toolbar(self): view_toolbar = gtk.Toolbar() fullscreen_button = ToolButton('view-fullscreen') fullscreen_button.set_tooltip(_("Fullscreen")) #fullscreen_button.props.accelerator = 'Return' fullscreen_button.connect('clicked', self.__fullscreen_cb) view_toolbar.insert(fullscreen_button, -1) fullscreen_button.show() return view_toolbar def __fullscreen_cb(self, button): self.fullscreen() def _create_tab_toolbar(self): tab_toolbar = gtk.Toolbar() new_tab_button = ToolButton('tab-add') new_tab_button.set_tooltip(_("Open New Tab")) #new_tab_button.props.accelerator = 'T' #new_tab_button.add_accelerator('clicked', self.accelerator, ord('T'), # gtk.gdk.SHIFT_MASK>k.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) new_tab_button.connect('clicked', self.__open_tab_cb) tab_toolbar.insert(new_tab_button, -1) new_tab_button.show() self._delete_tab_button = ToolButton('tab-remove') self._delete_tab_button.set_tooltip(_("Close Tab")) #self._delete_tab_button.props.accelerator = 'X' self._delete_tab_button.add_accelerator('clicked', self.accelerator, ord('X'), gtk.gdk.SHIFT_MASK>k.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) self._delete_tab_button.props.sensitive = False self._delete_tab_button.connect('clicked', self.__close_tab_cb) tab_toolbar.insert(self._delete_tab_button, -1) self._delete_tab_button.show() self._previous_tab_button = ToolButton('tab-previous') self._previous_tab_button.set_tooltip(_("Previous Tab")) #self._previous_tab_button.props.accelerator = 'Left' self._previous_tab_button.props.sensitive = False #self._previous_tab_button.add_accelerator('clicked', self.accelerator, #gtk.gdk.GDK_left, #gtk.gdk.SHIFT_MASK>k.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) self._previous_tab_button.connect('clicked', self.__prev_tab_cb) tab_toolbar.insert(self._previous_tab_button, -1) self._previous_tab_button.show() self._next_tab_button = ToolButton('tab-next') self._next_tab_button.set_tooltip(_("Next Tab")) #self._next_tab_button.props.accelerator = 'Right' self._next_tab_button.props.sensitive = False self._next_tab_button.connect('clicked', self.__next_tab_cb) tab_toolbar.insert(self._next_tab_button, -1) self._next_tab_button.show() return tab_toolbar def __open_tab_cb(self, btn): index = self._create_tab(None) self._notebook.page = index if self._notebook.get_n_pages() == 2: self._delete_tab_button.props.sensitive = True self._previous_tab_button.props.sensitive = True self._next_tab_button.props.sensitive = True def __close_tab_cb(self, btn): self._close_tab(self._notebook.props.page) if self._notebook.get_n_pages() == 1: self._delete_tab_button.props.sensitive = False self._previous_tab_button.props.sensitive = False self._next_tab_button.props.sensitive = False def __prev_tab_cb(self, btn): if self._notebook.props.page == 0: self._notebook.props.page = self._notebook.get_n_pages() - 1 else: self._notebook.props.page = self._notebook.props.page - 1 vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt vt.grab_focus() def __next_tab_cb(self, btn): if self._notebook.props.page == self._notebook.get_n_pages() - 1: self._notebook.props.page = 0 else: self._notebook.props.page = self._notebook.props.page + 1 vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt vt.grab_focus() def _close_tab(self, index): self._notebook.remove_page(index) if self._notebook.get_n_pages() == 0: self.close() def tab_child_exited_cb(self, vt): for i in range(self._notebook.get_n_pages()): if self._notebook.get_nth_page(i).vt == vt: self._close_tab(i) return def tab_title_changed_cb(self, vt): for i in range(self._notebook.get_n_pages()): if self._notebook.get_nth_page(i).vt == vt: label = self._notebook.get_nth_page(i).label label.set_text(vt.get_window_title()) return def drag_data_received_cb(self, widget, context, x, y, selection, target, time): widget.feed_child(selection.data) context.finish(True, False, time) return True def __become_root_cb(self, button): vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt vt.feed('\r\n') vt.fork_command("/bin/su", ('/bin/su', '-')) ################ Help routines ################ def _create_help_toolbar(self): help_toolbar = gtk.Toolbar() return help_toolbar def _toolbar_changed_cb(self, widget, tab_no): """top level menu clicked, check for help""" if tab_no == self.HELP_INDEX: self.help_selected() gobject.idle_add(self.grab_vt_focus) def set_toolbar(self,tab): self.toolbox.set_current_toolbar(tab) def grab_vt_focus(self): vt = self._notebook.get_nth_page(self._notebook.get_current_page()).vt vt.grab_focus() def help_selected(self): """ if help is not created in a gtk.mainwindow then create it else just switch to that window """ if not self.help_x11: screen = gtk.gdk.screen_get_default() self.pdb_window = screen.get_root_window() _logger.debug('xid for pydebug:%s'%self.pdb_window.xid) self.help_x11 = self.help.realize_help() else: self.help.activate_help()