[Sugar-devel] [PATCH Terminal 2/2] The same tabs as the Browse Activity
Agustin Zubiaga
aguz at sugarlabs.org
Mon May 14 15:32:05 EDT 2012
Signed-off-by: Agustin Zubiaga <aguz at sugarlabs.org>
Signed-off-by: Daniel Francis <francis at sugarlabs.org>
---
icons/close-tab.svg | 27 ++++++++++
terminal.py | 42 +++++++++++-----
widgets.py | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 197 insertions(+), 12 deletions(-)
create mode 100644 icons/close-tab.svg
create mode 100644 widgets.py
diff --git a/icons/close-tab.svg b/icons/close-tab.svg
new file mode 100644
index 0000000..782ad24
--- /dev/null
+++ b/icons/close-tab.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY fill_color "#FFFFFF">
+ <!ENTITY stroke_color "#010101">
+]>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="22.16"
+ height="22.16"
+ viewBox="0 0 22.16 22.16"
+ id="browse-close-tab"
+ xml:space="preserve">
+ <g
+ transform="matrix(1.3,0,0,1.3,-3.2682282,-3.3351543)"
+ id="browse-dialog-cancel"
+ style="stroke:&fill_color;;stroke-width:2.69230771;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ d="M 14.798121,7.2131543 6.9900671,15.021208"
+ id="path2986"
+ style="fill:none;stroke:&fill_color;;stroke-width:2.69230771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="M 6.9900671,7.2131543 14.798121,15.021208"
+ id="path3756"
+ style="fill:none;stroke:&fill_color;;stroke-width:2.69230771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+</svg>
diff --git a/terminal.py b/terminal.py
index 160b35d..59b4940 100644
--- a/terminal.py
+++ b/terminal.py
@@ -31,7 +31,6 @@ from gi.repository import Pango
from sugar3.graphics.toolbutton import ToolButton
from sugar3.graphics.toolbarbox import ToolbarBox
from sugar3.graphics.toolbarbox import ToolbarButton
-from sugar3.graphics.notebook import Notebook
from sugar3.activity.widgets import EditToolbar
from sugar3.activity.widgets import ActivityToolbarButton
@@ -39,6 +38,8 @@ from sugar3.activity.widgets import StopButton
from sugar3.activity import activity
from sugar3 import env
+from widgets import BrowserNotebook, TabLabel
+
MASKED_ENVIRONMENT = [
'DBUS_SESSION_BUS_ADDRESS',
'PPID']
@@ -117,7 +118,8 @@ class TerminalActivity(activity.Activity):
toolbar_box.show()
self._update_accelerators(toolbar_box)
- self._notebook = Notebook()
+ self._notebook = BrowserNotebook()
+ self._notebook.connect("tab-added", self.__open_tab_cb)
self._notebook.set_property("tab-pos", Gtk.PositionType.TOP)
self._notebook.set_scrollable(True)
self._notebook.show()
@@ -254,10 +256,13 @@ class TerminalActivity(activity.Activity):
def __close_tab_cb(self, btn):
self._close_tab(self._notebook.props.page)
if self._notebook.get_n_pages() == 1:
+ self._notebook.get_tab_label(0).button.hide_all()
self._delete_tab_button.props.sensitive = False
self._previous_tab_button.props.sensitive = False
self._next_tab_button.props.sensitive = False
+ self._notebook.update_tab_sizes()
+
def __prev_tab_cb(self, btn):
if self._notebook.props.page == 0:
self._notebook.props.page = self._notebook.get_n_pages() - 1
@@ -304,7 +309,7 @@ class TerminalActivity(activity.Activity):
vt.connect("window-title-changed", self.__tab_title_changed_cb)
# FIXME have to resend motion events to parent, see #1402
- vt.connect('motion-notify-event', self.__motion_notify_cb)
+ #vt.connect('motion-notify-event', self.__motion_notify_cb)
#vt.drag_dest_set(Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP,
# [('text/plain', 0, 0), ('STRING', 0, 1)],
@@ -316,19 +321,24 @@ class TerminalActivity(activity.Activity):
vt.show()
- label = Gtk.Label()
-
scrollbar = Gtk.VScrollbar(vt.get_vadjustment())
- scrollbar.show()
box = Gtk.HBox()
+
box.pack_start(vt, True, True, 0)
box.pack_start(scrollbar, True, True, 0)
box.vt = vt
- box.label = label
+ box.show()
+
+ tablabel = TabLabel()
+ tablabel.connect('tab-close', self.__close_tab_cb)
+ box.label = tablabel
+
+ index = self._notebook.append_page(box, tablabel)
+ tablabel.show_all()
- index = self._notebook.append_page(box, label)
+ self._notebook.update_tab_sizes()
self._notebook.show_all()
# Uncomment this to only show the tab bar when there is at least
@@ -366,20 +376,28 @@ class TerminalActivity(activity.Activity):
for l in tab_state['scrollback']:
vt.feed(l + '\r\n')
- box.pid = vt.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ["HOME"], ["/bin/bash"], [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
+ box.pid = vt.fork_command_full(Vte.PtyFlags.DEFAULT,
+ os.environ["HOME"],
+ ["/bin/bash"], [],
+ GLib.SpawnFlags.DO_NOT_REAP_CHILD,
+ None, None)
self._notebook.props.page = index
vt.grab_focus()
return index
- def __motion_notify_cb(self, widget, event):
- self.emit('motion-notify-event', event)
+# def __motion_notify_cb(self, widget, event):
+# self.emit('motion-notify-event', event)
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_full(Vte.PtyFlags.DEFAULT, os.environ["HOME"], ["/bin/su"], [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
+ vt.fork_command_full(Vte.PtyFlags.DEFAULT,
+ os.environ["HOME"],
+ ["/bin/su"], [],
+ GLib.SpawnFlags.DO_NOT_REAP_CHILD,
+ None, None)
def __key_press_cb(self, window, event):
"""Route some keypresses directly to the vte and then drop them.
diff --git a/widgets.py b/widgets.py
new file mode 100644
index 0000000..93d7dc0
--- /dev/null
+++ b/widgets.py
@@ -0,0 +1,140 @@
+# Copyright (C) 2006, Red Hat, Inc.
+# Copyright (C) 2011, One Laptop Per Child
+# Copyright (C) 2009, Tomeu Vizoso, 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
+
+from gi.repository import GObject
+from gi.repository import Gtk
+from gi.repository import Pango
+
+from sugar3.graphics.icon import Icon
+
+
+class TabAdd(Gtk.Button):
+ __gtype_name__ = 'BrowseTabAdd'
+
+ __gsignals__ = {
+ 'tab-added': (GObject.SignalFlags.RUN_FIRST,
+ None,
+ ([])),
+ }
+
+ def __init__(self):
+ GObject.GObject.__init__(self)
+
+ add_tab_icon = Icon(icon_name='add')
+ self.props.relief = Gtk.ReliefStyle.NONE
+ self.props.focus_on_click = False
+ icon_box = Gtk.HBox()
+ icon_box.pack_start(add_tab_icon, True, False, 0)
+ self.add(icon_box)
+ self.connect('clicked', self.__button_clicked_cb)
+ self.set_name('browse-tab-add')
+ add_tab_icon.show()
+ icon_box.show()
+ self.show()
+
+ def __button_clicked_cb(self, button):
+ self.emit('tab-added')
+
+
+class BrowserNotebook(Gtk.Notebook):
+ __gtype_name__ = 'BrowseNotebook'
+
+ __gsignals__ = {
+ 'tab-added': (GObject.SignalFlags.RUN_FIRST,
+ None,
+ ([])),
+ }
+
+ """Handle an extra tab at the end with an Add Tab button."""
+
+ def __init__(self):
+ GObject.GObject.__init__(self)
+
+ self._tab_add = TabAdd()
+ self._tab_add.connect('tab-added', self.on_add_tab)
+ self.set_action_widget(self._tab_add, Gtk.PackType.END)
+ self._tab_add.show()
+
+ def on_add_tab(self, obj):
+ self.emit('tab-added')
+
+ def update_tab_sizes(self):
+ n_pages = self.get_n_pages()
+ canvas_size = self.get_allocation()
+
+ # FIXME
+ # overlap_size = self.style_get_property('tab-overlap') * n_pages - 1
+ overlap_size = 0
+ allowed_size = canvas_size.width - overlap_size
+
+ tab_new_size = int(float(allowed_size) / (n_pages) -\
+ self._tab_add.get_allocation().width - 5)
+
+ for page_idx in range(n_pages):
+ page = self.get_nth_page(page_idx)
+ label = self.get_tab_label(page)
+ label.update_size(tab_new_size)
+
+
+class TabLabel(Gtk.HBox):
+ __gtype_name__ = 'BrowseTabLabel'
+
+ __gsignals__ = {
+ 'tab-close': (GObject.SignalFlags.RUN_FIRST,
+ None,
+ ([])),
+ }
+
+ def __init__(self):
+ GObject.GObject.__init__(self)
+
+ self._label = Gtk.Label(label="")
+ self._label.set_ellipsize(Pango.EllipsizeMode.END)
+ self._label.set_alignment(0, 0.5)
+ self.pack_start(self._label, True, True, 0)
+ self._label.show()
+
+ close_tab_icon = Icon(icon_name='close-tab')
+ button = Gtk.Button()
+ button.props.relief = Gtk.ReliefStyle.NONE
+ button.props.focus_on_click = False
+ icon_box = Gtk.HBox()
+ icon_box.pack_start(close_tab_icon, True, False, 0)
+ button.add(icon_box)
+ button.connect('clicked', self.__button_clicked_cb)
+ button.set_name('browse-tab-close')
+ self.pack_start(button, False, True, 0)
+ close_tab_icon.show()
+ icon_box.show()
+ button.show()
+ self._close_button = button
+
+ def set_text(self, title):
+ self._label.set_text(title)
+
+ def update_size(self, size):
+ self.set_size_request(size, -1)
+
+ def hide_close_button(self):
+ self._close_button.hide()
+
+ def show_close_button(self):
+ self._close_button.show()
+
+ def __button_clicked_cb(self, button):
+ self.emit('tab-close')
--
1.7.9.5
More information about the Sugar-devel
mailing list