Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--globalhistory.py81
-rw-r--r--places.py72
-rwxr-xr-xwebactivity.py2
-rwxr-xr-xwebtoolbar.py119
4 files changed, 273 insertions, 1 deletions
diff --git a/globalhistory.py b/globalhistory.py
new file mode 100644
index 0000000..635deca
--- /dev/null
+++ b/globalhistory.py
@@ -0,0 +1,81 @@
+# Copyright (C) 2008, Red Hat, Inc.
+#
+# 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 xpcom import components
+from xpcom.components import interfaces
+from xpcom.server.factory import Factory
+
+import places
+
+_global_history = None
+
+class GlobalHistory:
+ _com_interfaces_ = interfaces.nsIGlobalHistory, \
+ interfaces.nsIGlobalHistory2, \
+ interfaces.nsIGlobalHistory3
+
+ cid = '{2a53cf28-c48e-4a01-ba18-3d3fef3e2985}'
+ description = 'Sugar Global History'
+
+ def __init__(self):
+ self._store = places.get_store()
+
+ def addPage(self, url):
+ self.addURI(url, False, True, None)
+
+ def isVisited(self, uri):
+ place = self._store.lookup_place(uri.spec)
+ return place != None
+
+ def addURI(self, uri, redirect, toplevel, referrer):
+ place = places.Place(uri.spec)
+
+ place.redirect = redirect
+ place.toplevel = toplevel
+ place.referrer = referrer
+
+ self._store.add_place(place)
+
+ def setPageTitle(self, uri, title):
+ place = self._store.lookup_place(uri.spec)
+ if place:
+ place.title = title
+ self._store.update_place(place)
+
+ def addDocumentRedirect(self, old_channel, new_channel, flags, toplevel):
+ pass
+
+ def getURIGeckoFlags(self, uri):
+ place = self._store.lookup_place(uri.spec)
+ if place:
+ return place.gecko_flags
+ else:
+ return 0
+
+ def setURIGeckoFlags(self, uri, flags):
+ place = self._store.lookup_place(uri.spec)
+ if place:
+ place.gecko_flags = flags
+ self._store.update_place(place)
+
+def init():
+ global _global_history
+ _global_history = GlobalHistory()
+
+components.registrar.registerFactory(GlobalHistory.cid,
+ GlobalHistory.description,
+ '@mozilla.org/browser/global-history;2',
+ Factory(GlobalHistory))
diff --git a/places.py b/places.py
new file mode 100644
index 0000000..481c16b
--- /dev/null
+++ b/places.py
@@ -0,0 +1,72 @@
+# Copyright (C) 2008, Red Hat, Inc.
+#
+# 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
+
+_store = None
+
+class Place(object):
+ def __init__(self, uri):
+ self.uri = uri
+ self.redirect = False
+ self.toplevel = True
+ self.referrer = None
+ self.title = None
+ self.gecko_flags = 0
+ self.visits = 0
+
+class MemoryStore(object):
+ def __init__(self):
+ self._places = {}
+
+ def search(self, text):
+ result = []
+ for place in self._places.values():
+ if text in place.uri or text in place.title:
+ result.append(place)
+ return result
+
+ def add_place(self, place):
+ self._places[place.uri] = place
+
+ def lookup_place(self, uri):
+ try:
+ return self._places[uri]
+ except KeyError:
+ return None
+
+ def update_place(self, place):
+ self._places[place.uri] = place
+
+class SQliteStore(object):
+ def __init__(self):
+ pass
+
+ def search(self, text):
+ pass
+
+ def add_place(self, place):
+ pass
+
+ def lookup_place(self, uri):
+ pass
+
+ def update_place(self, place):
+ pass
+
+def get_store():
+ global _store
+ if _store == None:
+ _store = MemoryStore()
+ return _store
diff --git a/webactivity.py b/webactivity.py
index 4b4544a..4bf55bd 100755
--- a/webactivity.py
+++ b/webactivity.py
@@ -71,6 +71,7 @@ import downloadmanager
import sessionhistory
import progresslistener
import filepicker
+import globalhistory
_LIBRARY_PATH = '/usr/share/library-common/index.html'
@@ -100,6 +101,7 @@ class WebActivity(activity.Activity):
sessionhistory.init(self._browser)
progresslistener.init(self._browser)
filepicker.init(self)
+ globalhistory.init()
toolbox = activity.ActivityToolbox(self)
diff --git a/webtoolbar.py b/webtoolbar.py
index 8987a37..a3c59ba 100755
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -16,9 +16,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from gettext import gettext as _
+import logging
import gobject
import gtk
+import pango
from xpcom.components import interfaces
from xpcom import components
@@ -29,9 +31,124 @@ 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._popup_hid = 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._focus_out_hid = self.connect(
+ 'focus-out-event', self.__focus_out_event_cb)
+ self._change_hid = self.connect('changed', self.__changed_cb)
+
+ def _set_address(self, address):
+ self.handler_block(self._change_hid)
+ self._address = address
+ self.handler_unblock(self._change_hid)
+
+ address = gobject.property(type=str, setter=_set_address)
+
+ def _set_title(self, title):
+ self.handler_block(self._change_hid)
+ self._title = title
+ self.handler_unblock(self._change_hid)
+
+ title = gobject.property(type=str, setter=_set_title)
+
+ def _search_create_view(self):
+ view = gtk.TreeView()
+ view.props.headers_visible=False
+
+ 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
+
+ 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.handler_block(self._change_hid)
+ self.props.text = self._address
+ self.handler_unblock(self._change_hid)
+
+ self._search_popdown()
+
+ def __focus_out_event_cb(self, entry, event):
+ self.handler_block(self._change_hid)
+ self.props.text = self._title
+ self.handler_unblock(self._change_hid)
+
+ self._search_popdown()
+
+ 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)
+ self.__popup_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 +184,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()