Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/webtoolbar.py
diff options
context:
space:
mode:
Diffstat (limited to 'webtoolbar.py')
-rwxr-xr-xwebtoolbar.py162
1 files changed, 161 insertions, 1 deletions
diff --git a/webtoolbar.py b/webtoolbar.py
index 3d1877c..f3f8ccb 100755
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -19,6 +19,7 @@ from gettext import gettext as _
import gobject
import gtk
+import pango
from xpcom.components import interfaces
from xpcom import components
@@ -29,9 +30,168 @@ from sugar._sugarext import AddressEntry
import sessionhistory
import progresslistener
import filepicker
+import places
_MAX_HISTORY_ENTRIES = 15
+class WebEntry(AddressEntry):
+ _COL_ADDRESS = 0
+ _COL_TITLE = 1
+
+ def __init__(self):
+ gobject.GObject.__init__(self)
+
+ self._address = None
+ self._title = None
+ self._search_view = self._search_create_view()
+
+ self._search_window = gtk.Window(gtk.WINDOW_POPUP)
+ self._search_window.add(self._search_view)
+ self._search_view.show()
+
+ self.connect('focus-in-event', self.__focus_in_event_cb)
+ self.connect('populate-popup', self.__populate_popup_cb)
+ self.connect('key-press-event', self.__key_press_event_cb)
+ self._focus_out_hid = self.connect(
+ 'focus-out-event', self.__focus_out_event_cb)
+ self._change_hid = self.connect('changed', self.__changed_cb)
+
+ def _set_text(self, text):
+ """Set the text but block changes notification, so that we can
+ recognize changes caused directly by user actions"""
+ self.handler_block(self._change_hid)
+ try:
+ self.props.text = text
+ finally:
+ self.handler_unblock(self._change_hid)
+
+ def activate(self, uri):
+ self._set_text(uri)
+ self._search_popdown()
+ self.emit('activate')
+
+ def _set_address(self, address):
+ self._address = address
+
+ address = gobject.property(type=str, setter=_set_address)
+
+ def _set_title(self, title):
+ self._title = title
+
+ title = gobject.property(type=str, setter=_set_title)
+
+ def _search_create_view(self):
+ view = gtk.TreeView()
+ view.props.headers_visible = False
+
+ view.connect('button-press-event', self.__view_button_press_event_cb)
+
+ column = gtk.TreeViewColumn()
+ view.append_column(column)
+
+ cell = gtk.CellRendererText()
+ cell.props.ellipsize = pango.ELLIPSIZE_END
+ cell.props.ellipsize_set = True
+ column.pack_start(cell, True)
+
+ column.set_attributes(cell, text=self._COL_ADDRESS)
+
+ cell = gtk.CellRendererText()
+ cell.props.ellipsize = pango.ELLIPSIZE_END
+ cell.props.ellipsize_set = True
+ cell.props.alignment = pango.ALIGN_LEFT
+ cell.props.font = 'Bold'
+ column.pack_start(cell)
+
+ column.set_attributes(cell, text=self._COL_TITLE)
+
+ return view
+
+ def _search_update(self):
+ list_store = gtk.ListStore(str, str)
+
+ for place in places.get_store().search(self.props.text):
+ list_store.append([place.uri, place.title])
+
+ self._search_view.set_model(list_store)
+
+ return len(list_store) > 0
+
+ def _search_popup(self):
+ entry_x, entry_y = self.window.get_origin()
+ entry_w, entry_h = self.size_request()
+
+ x = entry_x
+ y = entry_y + entry_h
+ width = self.allocation.width
+ height = gtk.gdk.screen_height() / 3
+
+ i = self._search_view.get_model().get_iter_first()
+ self._search_view.get_selection().select_iter(i)
+
+ self._search_window.move(x, y)
+ self._search_window.resize(width, height)
+ self._search_window.show()
+
+ def _search_popdown(self):
+ self._search_window.hide()
+
+ def __focus_in_event_cb(self, entry, event):
+ self._set_text(self._address)
+ self._search_popdown()
+
+ def __focus_out_event_cb(self, entry, event):
+ self._set_text(self._title)
+ self._search_popdown()
+
+ def __view_button_press_event_cb(self, view, event):
+ model = view.get_model()
+
+ path, col_, x_, y_ = view.get_path_at_pos(event.x, event.y)
+ if path:
+ uri = model[path][self._COL_ADDRESS]
+ self.activate(uri)
+
+ def __key_press_event_cb(self, entry, event):
+ keyname = gtk.gdk.keyval_name(event.keyval)
+
+ selection = self._search_view.get_selection()
+ model, selected = selection.get_selected()
+ if selected == None:
+ return False
+
+ if keyname == 'Up':
+ index = model.get_path(selected)[0]
+ if index > 0:
+ selection.select_path(index - 1)
+ return True
+ elif keyname == 'Down':
+ next = model.iter_next(selected)
+ if next:
+ selection.select_iter(next)
+ return True
+ elif keyname == 'Return':
+ uri = model[model.get_path(selected)][self._COL_ADDRESS]
+ self.activate(uri)
+ return True
+
+ return False
+
+ def __popup_unmap_cb(self, entry):
+ self.handler_unblock(self._focus_out_hid)
+
+ def __populate_popup_cb(self, entry, menu):
+ self.handler_block(self._focus_out_hid)
+ menu.connect('unmap', self.__popup_unmap_cb)
+
+ def __changed_cb(self, entry):
+ self._address = self.props.text
+
+ if not self.props.text or not self._search_update():
+ self._search_popdown()
+ else:
+ self._search_popup()
+
class WebToolbar(gtk.Toolbar):
__gtype_name__ = 'WebToolbar'
@@ -67,7 +227,7 @@ class WebToolbar(gtk.Toolbar):
self.insert(self._stop_and_reload, -1)
self._stop_and_reload.show()
- self.entry = AddressEntry()
+ self.entry = WebEntry()
self.entry.connect('activate', self._entry_activate_cb)
entry_item = gtk.ToolItem()