Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/browser.py
diff options
context:
space:
mode:
authorManuel QuiƱones <manuq@laptop.org>2011-09-09 02:42:35 (GMT)
committer Simon Schampijer <simon@schampijer.de>2011-09-10 06:45:49 (GMT)
commit959f86e0406914267047dc10302f98a059b6ba21 (patch)
treed5a5582f52e5af4b3bd2b95beeff604492049eff /browser.py
parent370dfc1c167934eb4784b0444b28a493c4cc6cec (diff)
Browse: tabs usability improved
The Add Tab button has been relocated next to the tab labels, allowing more space for the URL entry. Tabs are always shown. There is at least one tab. In that case, it cannot be closed. We prevent the closing by hiding the 'X' button. Also, the close image was sugarized. There is now a fixed width for tabs. The label text does ellipsize. The width depends on the amount of tabs. There is a maximum size that is used when there is extra space. There is a minimum size to prevent hiding the information. When a new tab is opened, it now shows an empty page, not the default page. In the future, we will add a hint in this empty page, similar to what we have for an empty Journal. Added the option to "follow link in new tab" in the link's palette. Added an icon for this item, and also the icon for "follow link" is also updated. When a new tab is opened via the '+' button, the focus goes to the URL entry in the toolbar. Signed-off-by: Manuel QuiƱones <manuq@laptop.org> Acked-by: Simon Schampijer <simon@laptop.org>
Diffstat (limited to 'browser.py')
-rw-r--r--browser.py157
1 files changed, 137 insertions, 20 deletions
diff --git a/browser.py b/browser.py
index 96e6fb1..47318bb 100644
--- a/browser.py
+++ b/browser.py
@@ -18,9 +18,11 @@
import os
import time
+from gettext import gettext as _
import gobject
import gtk
+import pango
import hulahop
import xpcom
from xpcom.nsError import *
@@ -31,13 +33,16 @@ from hulahop.webview import WebView
from sugar import env
from sugar.activity import activity
from sugar.graphics import style
+from sugar.graphics.icon import Icon
import sessionstore
from palettes import ContentInvoker
from sessionhistory import HistoryListener
from progresslistener import ProgressListener
+from widgets import BrowserNotebook
_ZOOM_AMOUNT = 0.1
+_LIBRARY_PATH = '/usr/share/library-common/index.html'
class SaveListener(object):
@@ -93,9 +98,15 @@ class CommandListener(object):
cert_exception.showDialog(self._window)
-class TabbedView(gtk.Notebook):
+class TabbedView(BrowserNotebook):
__gtype_name__ = 'TabbedView'
+ __gsignals__ = {
+ 'focus-url-entry': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ ([])),
+ }
+
_com_interfaces_ = interfaces.nsIWindowCreator
AGENT_SHEET = os.path.join(activity.get_bundle_path(),
@@ -104,7 +115,7 @@ class TabbedView(gtk.Notebook):
'user-stylesheet.css')
def __init__(self):
- gobject.GObject.__init__(self)
+ BrowserNotebook.__init__(self)
self.props.show_border = False
self.props.scrollable = True
@@ -140,8 +151,13 @@ class TabbedView(gtk.Notebook):
interfaces.nsIWindowCreator)
window_watcher.setWindowCreator(window_creator)
- browser = Browser()
- self._append_tab(browser)
+ self.connect('size-allocate', self.__size_allocate_cb)
+ self.connect('page-added', self.__page_added_cb)
+ self.connect('page-removed', self.__page_removed_cb)
+
+ self.add_tab()
+ self._update_closing_buttons()
+ self._update_tab_sizes()
def createChromeWindow(self, parent, flags):
if flags & interfaces.nsIWebBrowserChrome.CHROME_OPENAS_CHROME:
@@ -160,25 +176,104 @@ class TabbedView(gtk.Notebook):
return browser.containerWindow
else:
- browser = Browser()
+ browser = Browser(self)
self._append_tab(browser)
return browser.browser.containerWindow
+ def __size_allocate_cb(self, widget, allocation):
+ self._update_tab_sizes()
+
+ def __page_added_cb(self, notebook, child, pagenum):
+ self._update_closing_buttons()
+ self._update_tab_sizes()
+
+ def __page_removed_cb(self, notebook, child, pagenum):
+ self._update_closing_buttons()
+ self._update_tab_sizes()
+
+ def add_tab(self, next_to_current=False):
+ browser = Browser(self)
+
+ label = TabLabel(browser)
+ label.connect('tab-close', self.__tab_close_cb)
+
+ if next_to_current:
+ self._insert_tab_next(browser)
+ else:
+ self._append_tab(browser)
+ self.emit('focus-url-entry')
+ browser.load_uri('about:blank')
+ return browser
+
+ def _insert_tab_next(self, browser):
+ label = TabLabel(browser)
+ label.connect('tab-close', self.__tab_close_cb)
+
+ next_index = self.get_current_page() + 1
+ self.insert_page(browser, label, next_index)
+ browser.show()
+ self.set_current_page(next_index)
+
def _append_tab(self, browser):
label = TabLabel(browser)
label.connect('tab-close', self.__tab_close_cb)
self.append_page(browser, label)
browser.show()
-
self.set_current_page(-1)
- self.props.show_tabs = self.get_n_pages() > 1
+
+ def on_add_tab(self, gobject):
+ self.add_tab()
def __tab_close_cb(self, label, browser):
self.remove_page(self.page_num(browser))
browser.destroy()
- self.props.show_tabs = self.get_n_pages() > 1
+
+ def _update_tab_sizes(self):
+ """Update ta widths based in the amount of tabs."""
+
+ n_pages = self.get_n_pages()
+ canvas_size = self.get_allocation()
+ overlap_size = self.style_get_property('tab-overlap') * n_pages - 1
+ allowed_size = canvas_size.width - overlap_size
+
+ tab_new_size = int(allowed_size * 1.0 / (n_pages + 1))
+ # Four tabs ensured:
+ tab_max_size = int(allowed_size * 1.0 / (5))
+ # Eight tabs ensured:
+ tab_min_size = int(allowed_size * 1.0 / (9))
+
+ if tab_new_size < tab_min_size:
+ tab_new_size = tab_min_size
+ elif tab_new_size > tab_max_size:
+ tab_new_size = tab_max_size
+
+ 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)
+
+ def _update_closing_buttons(self):
+ """Prevent closing the last tab."""
+ first_page = self.get_nth_page(0)
+ first_label = self.get_tab_label(first_page)
+ if self.get_n_pages() == 0:
+ return
+ elif self.get_n_pages() == 1:
+ first_label.hide_close_button()
+ else:
+ first_label.show_close_button()
+
+ def load_homepage(self):
+ browser = self.current_browser
+
+ if os.path.isfile(_LIBRARY_PATH):
+ browser.load_uri('file://' + _LIBRARY_PATH)
+ else:
+ default_page = os.path.join(activity.get_bundle_path(),
+ "data/index.html")
+ browser.load_uri(default_page)
def _get_current_browser(self):
return self.get_nth_page(self.get_current_page())
@@ -202,7 +297,7 @@ class TabbedView(gtk.Notebook):
self.remove_page(self.get_n_pages() - 1)
for tab_session in tab_sessions:
- browser = Browser()
+ browser = Browser(self)
self._append_tab(browser)
sessionstore.set_session(browser, tab_session)
@@ -230,22 +325,35 @@ class TabLabel(gtk.HBox):
self._browser = browser
self._browser.connect('is-setup', self.__browser_is_setup_cb)
- self._label = gtk.Label('')
+ self._label = gtk.Label(_('Untitled'))
+ self._label.set_ellipsize(pango.ELLIPSIZE_END)
+ self._label.set_alignment(0, 0.5)
self.pack_start(self._label)
self._label.show()
+ close_tab_icon = Icon(icon_name='browse-close-tab')
button = gtk.Button()
- button.connect('clicked', self.__button_clicked_cb)
- button.set_name('browse-tab-close')
button.props.relief = gtk.RELIEF_NONE
button.props.focus_on_click = False
- self.pack_start(button)
+ 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, expand=False)
+ close_tab_icon.show()
+ icon_box.show()
button.show()
+ self._close_button = button
+
+ def update_size(self, size):
+ self.set_size_request(size, -1)
+
+ def hide_close_button(self):
+ self._close_button.hide()
- close_image = gtk.image_new_from_stock(gtk.STOCK_CLOSE,
- gtk.ICON_SIZE_MENU)
- button.add(close_image)
- close_image.show()
+ def show_close_button(self):
+ self._close_button.show()
def __button_clicked_cb(self, button):
self.emit('tab-close', self._browser)
@@ -257,10 +365,16 @@ class TabLabel(gtk.HBox):
def __location_changed_cb(self, progress_listener, pspec):
url = self._browser.get_url_from_nsiuri(progress_listener.location)
- self._label.set_text(url)
+ if url == 'about:blank':
+ self._label.set_text(_('Loading...'))
+ else:
+ self._label.set_text(url)
def __title_changed_cb(self, browser, pspec):
- self._label.set_text(browser.props.title)
+ if browser.props.title == "":
+ self._label.set_text(_('Untitled'))
+ else:
+ self._label.set_text(browser.props.title)
class Browser(WebView):
@@ -272,9 +386,10 @@ class Browser(WebView):
([])),
}
- def __init__(self):
+ def __init__(self, tabbed_view):
WebView.__init__(self)
+ self.tabbed_view = tabbed_view
self.history = HistoryListener()
self.progress = ProgressListener()
@@ -356,6 +471,8 @@ class Browser(WebView):
return self.web_navigation.sessionHistory.index
def set_history_index(self, index):
+ if index == -1:
+ return
self.web_navigation.gotoIndex(index)