def __init__(self, directory=None, command=None): super(XfConTerminal, self).__init__() self.term_settings = XfTermSettings() self.settings = XfConSettings.Instance() self.match_valid = False self.match_pair = None self.terminal = vte.Terminal() self.terminal.show() self.pack_start(self.terminal) adj = self.terminal.get_adjustment() self.scrollbar = gtk.VScrollbar(adj) self.scrollbar.set_no_show_all(True) self.pack_start(self.scrollbar, False, False) self.__configure_terminal() self.__bind_signals() self.__bind_config() params = {} params["directory"] = directory params["command"] = command self.shell_params = self.__get_fork_params(params) self.pid = self.terminal.fork_command(**self.shell_params) self.show()
class XfConTerminal(gtk.HBox, XfConObject): __gsignals__ = XfConObject.XfConSignals() # Remember the location of most recent directory. class_last_path = "~" def __init__(self, directory=None, command=None): super(XfConTerminal, self).__init__() self.term_settings = XfTermSettings() self.settings = XfConSettings.Instance() self.match_valid = False self.match_pair = None self.terminal = vte.Terminal() self.terminal.show() self.pack_start(self.terminal) adj = self.terminal.get_adjustment() self.scrollbar = gtk.VScrollbar(adj) self.scrollbar.set_no_show_all(True) self.pack_start(self.scrollbar, False, False) self.__configure_terminal() self.__bind_signals() self.__bind_config() params = {} params["directory"] = directory params["command"] = command self.shell_params = self.__get_fork_params(params) self.pid = self.terminal.fork_command(**self.shell_params) self.show() def __bind_config(self): self.term_settings.connect("notify::term-scroll-on-output", self.__config_set_scroll) self.term_settings.connect("notify::term-scroll-on-keypress", self.__config_set_scroll) self.term_settings.connect("notify::term-scroll-history-size", self.__config_set_scroll) self.term_settings.connect("notify::term-scroll-visible", self.__config_set_scroll) self.term_settings.connect("notify::term-emulator-font", self.__config_set_font_style) self.term_settings.connect("notify::term-emulator-opacity", self.__config_set_background_transparency) def __bind_signals(self): self.terminal.connect("button-press-event", self.__on_button_press) self.terminal.connect("expose-event", self.__apply_config) self.terminal.connect("child-exited", self.__on_child_exited) self.terminal.connect("focus-in-event", self.__on_focus_in) self.terminal.connect("focus-out-event", self.__on_focus_out) def __on_focus_in(self, source, event): self.emit("focus-in-event", event) XfConKeyBinder.register( self, [ (self.settings.get_property("key-clipboard-copy"), self.__on_menu_copy), (self.settings.get_property("key-clipboard-paste"), self.__on_menu_paste), (self.settings.get_property("key-view-split-horizontal"), self.__on_split_horizontal), (self.settings.get_property("key-view-split-vertical"), self.__on_split_vertical), (self.settings.get_property("key-view-activate-next"), self.__on_activate_next), (self.settings.get_property("key-view-activate-previous"), self.__on_activate_previous), ], ) def __on_focus_out(self, source, event): XfConKeyBinder.unregister(self) self.emit("focus-out-event", event) def __apply_config(self, *ignore): # there seem to be certain misfeatures in the vte terminal implementation # these cause the terminal to ignore initial configuration, # if applied before the box is shown self.terminal.disconnect_by_func(self.__apply_config) self.__config_set_background_transparency() self.__config_set_font_style() self.__config_set_scroll() self.__config_set_keybindings() def __config_set_font_style(self, *ignore): font = FontDescription(self.term_settings.get_property("term-emulator-font")) self.terminal.set_font(font) def __config_set_background_transparency(self, *ignore): transparency = self.term_settings.get_property("term-emulator-opacity") self.terminal.set_opacity(int(transparency * 65535)) def __config_set_scroll(self, *ignore): self.terminal.set_scroll_on_output(self.term_settings.get_property("term-scroll-on-output")) self.terminal.set_scroll_on_keystroke(self.term_settings.get_property("term-scroll-on-keypress")) self.terminal.set_scrollback_lines(self.term_settings.get_property("term-scroll-history-size")) self.scrollbar.set_visible(self.term_settings.get_property("term-scroll-visible")) def __config_set_keybindings(self, *ignore): self.terminal.set_backspace_binding(vte.ERASE_AUTO) self.terminal.set_delete_binding(vte.ERASE_AUTO) def __on_button_press(self, terminal, event): self.match_pair = self.terminal.match_check( int(event.x / self.terminal.get_char_width()), int(event.y / self.terminal.get_char_height()) ) self.match_valid = self.match_pair != None if event.button == 3: menu = self.__build_menu() self.emit_menu_show() menu.popup(None, None, None, event.button, event.get_time()) def __on_menu_copy(self, *ignore): if self.terminal.get_has_selection(): self.terminal.copy_clipboard() elif self.match_valid: gtk.clipboard_get().set_text(self.match_pair[0]) return True def __on_menu_paste(self, *ignore): self.terminal.paste_clipboard() return True def __on_split_horizontal(self, *ignore): self.emit_view_split_horizontal(XfConTerminal()) def __on_split_vertical(self, *ignore): self.emit_view_split_vertical(XfConTerminal()) def __on_activate_next(self, *ignore): self.emit_view_activate_next() def __on_activate_previous(self, *ignore): self.emit_view_activate_previous() def __on_menu_close(self, menu): menu.destroy() self.emit_menu_hide() def __on_child_exited(self, *ignore): self.emit_view_terminate() def __build_menu(self): menu = gtk.Menu() menu.connect("selection-done", self.__on_menu_close) menu.show() item = gtk.ImageMenuItem(gtk.STOCK_COPY) item.set_label(_("Copy")) item.set_sensitive(self.terminal.get_has_selection() | self.match_valid) item.show() item.connect("activate", self.__on_menu_copy) menu.add(item) item = gtk.ImageMenuItem(gtk.STOCK_PASTE) item.set_label(_("Paste")) item.show() item.connect("activate", self.__on_menu_paste) menu.add(item) separator = gtk.SeparatorMenuItem() separator.show() menu.add(separator) item = gtk.ImageMenuItem(gtk.STOCK_ORIENTATION_LANDSCAPE) item.set_label(_("Split Horizontal")) item.show() item.connect("activate", self.__on_split_horizontal) menu.add(item) item = gtk.ImageMenuItem(gtk.STOCK_ORIENTATION_PORTRAIT) item.set_label(_("Split Vertical")) item.show() item.connect("activate", self.__on_split_vertical) menu.add(item) self.emit_menu_build(menu) return menu def destroy(self): start_new_thread(self.__delete_shell, (self.pid,)) XfConKeyBinder.unregister(self) XfConTerminal.class_last_path = "~" super(self.__class__, self).destroy() def grab_focus(self): self.terminal.grab_focus() def __get_fork_params(self, params=None): if params["command"] is None: params["command"] = os.environ["SHELL"] if self.term_settings.get_property("term-shell-login"): params["loglastlog"] = True params["argv"] = ["-xv"] if params["directory"] is None: if self.term_settings.get_property("term-share-cwd"): params["directory"] = XfConTerminal.class_last_path else: params["directory"] = "~" params["directory"] = os.path.expanduser(params["directory"]) params["command"] = os.path.realpath(params["command"]) return params def __delete_shell(self, pid): try: os.kill(pid, signal.SIGTERM) sleep(3) os.kill(pid, signal.SIGKILL) except (OSError): # most likely process died already pass def __configure_terminal(self): self.terminal.set_word_chars(self.term_settings.get_property("term-emulator-word-chars")) self.terminal.set_audible_bell(self.term_settings.get_property("term-emulator-bell-audible")) self.terminal.set_visible_bell(self.term_settings.get_property("term-emulator-bell-visual")) self.terminal.set_sensitive(True) self.terminal.set_flags(gtk.CAN_DEFAULT) self.terminal.set_flags(gtk.CAN_FOCUS) def get_name(self): return _("Terminal #{num_pages}") def get_icon(self): return None