Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--browser.py55
-rw-r--r--icons/save-to-journal.svg109
-rw-r--r--pdfviewer.py420
-rw-r--r--viewtoolbar.py23
-rw-r--r--webtoolbar.py12
5 files changed, 613 insertions, 6 deletions
diff --git a/browser.py b/browser.py
index 0886580..dd95746 100644
--- a/browser.py
+++ b/browser.py
@@ -36,6 +36,7 @@ from sugar3.graphics.icon import Icon
from widgets import BrowserNotebook
import globalhistory
import downloadmanager
+from pdfviewer import PDFTabPage
_ZOOM_AMOUNT = 0.1
_LIBRARY_PATH = '/usr/share/library-common/index.html'
@@ -164,9 +165,25 @@ class TabbedView(BrowserNotebook):
new_browser.load_uri(url)
new_browser.grab_focus()
+ def __open_pdf_in_new_tab_cb(self, browser, url):
+ tab_page = PDFTabPage()
+ tab_page.browser.connect('new-tab', self.__new_tab_cb)
+ tab_page.browser.connect('tab-close', self.__tab_close_cb)
+
+ label = TabLabel(tab_page.browser)
+ label.connect('tab-close', self.__tab_close_cb, tab_page)
+
+ next_index = self.get_current_page() + 1
+ self.insert_page(tab_page, label, next_index)
+ tab_page.show()
+ label.show()
+ self.set_current_page(next_index)
+ tab_page.setup(url)
+
def add_tab(self, next_to_current=False):
browser = Browser()
browser.connect('new-tab', self.__new_tab_cb)
+ browser.connect('open-pdf', self.__open_pdf_in_new_tab_cb)
if next_to_current:
self._insert_tab_next(browser)
@@ -271,11 +288,31 @@ class TabbedView(BrowserNotebook):
while self.get_n_pages():
self.remove_page(self.get_n_pages() - 1)
+ def is_pdf_history(tab_history):
+ return (len(tab_history) == 1 and
+ tab_history[0]['url'].lower().endswith('pdf'))
+
for tab_history in tab_histories:
- browser = Browser()
- browser.connect('new-tab', self.__new_tab_cb)
- self._append_tab(browser)
- browser.set_history(tab_history)
+ if is_pdf_history(tab_history):
+ url = tab_history[0]['url']
+ tab_page = PDFTabPage()
+ tab_page.browser.connect('new-tab', self.__new_tab_cb)
+ tab_page.browser.connect('tab-close', self.__tab_close_cb)
+
+ label = TabLabel(tab_page.browser)
+ label.connect('tab-close', self.__tab_close_cb, tab_page)
+
+ self.append_page(tab_page, label)
+ tab_page.show()
+ label.show()
+ tab_page.setup(url, title=tab_history[0]['title'])
+
+ else:
+ browser = Browser()
+ browser.connect('new-tab', self.__new_tab_cb)
+ browser.connect('open-pdf', self.__open_pdf_in_new_tab_cb)
+ self._append_tab(browser)
+ browser.set_history(tab_history)
Gtk.rc_parse_string('''
@@ -418,6 +455,9 @@ class Browser(WebKit.WebView):
'new-tab': (GObject.SignalFlags.RUN_FIRST,
None,
([str])),
+ 'open-pdf': (GObject.SignalFlags.RUN_FIRST,
+ None,
+ ([str])),
}
CURRENT_SUGAR_VERSION = '0.96'
@@ -529,7 +569,12 @@ class Browser(WebKit.WebView):
def __mime_type_policy_cb(self, webview, frame, request, mimetype,
policy_decision):
- if not self.can_show_mime_type(mimetype):
+ if mimetype == 'application/pdf':
+ self.emit('open-pdf', request.get_uri())
+ return False
+ elif self.can_show_mime_type(mimetype):
+ return True
+ else:
policy_decision.download()
return True
diff --git a/icons/save-to-journal.svg b/icons/save-to-journal.svg
new file mode 100644
index 0000000..a42436c
--- /dev/null
+++ b/icons/save-to-journal.svg
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata25"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs33">
+</defs><g
+ transform="matrix(0.75578519,0,0,0.75578519,-4.9396196,-1.2911009)"
+ id="clipping-text"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1;display:block">
+ <g
+ id="g3152"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1;display:inline">
+ <g
+ id="g3154"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1">
+ <polygon
+ points="31.874,6.088 43.818,18.027 43.818,48.914 10.932,48.914 10.932,6.088 "
+ id="polygon3156"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1" />
+ <polyline
+ id="polyline3158"
+ points="43.818,18.027 31.874,18.027 31.874,6.088 "
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1" />
+ </g>
+ </g>
+ <line
+ id="line3160"
+ y2="26.25"
+ y1="26.25"
+ x2="36.875"
+ x1="17.875"
+ display="inline"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1;display:inline" />
+ <line
+ id="line3162"
+ y2="33.25"
+ y1="33.25"
+ x2="36.875"
+ x1="17.875"
+ display="inline"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1;display:inline" />
+ <line
+ id="line3164"
+ y2="40.25"
+ y1="40.25"
+ x2="36.875"
+ x1="17.875"
+ display="inline"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1;display:inline" />
+</g><g
+ id="g3830"><g
+ transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)"
+ id="g4382"><g
+ transform="translate(-80.093659,12.220029)"
+ id="g4308"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1"><g
+ id="g4310"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1"><path
+ d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389"
+ id="path4312"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><g
+ transform="translate(-80.093659,12.220029)"
+ id="g4314"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1"><g
+ id="g4316"
+ style="fill:none;stroke:#ffffff;stroke-opacity:1"><path
+ d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z"
+ id="path4318"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><path
+ d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543"
+ id="path4320"
+ style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path
+ d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543"
+ id="path4322"
+ style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path
+ d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544"
+ id="path4324"
+ style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line
+ id="line4326"
+ y2="23.725029"
+ y1="58.753029"
+ x2="-66.884659"
+ x1="-66.884659"
+ style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g
+ transform="matrix(1,0,0,-1,-30.386573,49.171266)"
+ id="g4770"><g
+ transform="translate(34.0803,-1006.42)"
+ id="g4772"><polyline
+ id="polyline4774"
+ points="51.562,15.306 41.17,16.188 42.053,5.794"
+ style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round"
+ transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path
+ d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067"
+ id="path4776"
+ style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
diff --git a/pdfviewer.py b/pdfviewer.py
new file mode 100644
index 0000000..c7e2452
--- /dev/null
+++ b/pdfviewer.py
@@ -0,0 +1,420 @@
+# Copyright (C) 2012, One Laptop Per Child
+#
+# 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
+
+import os
+import logging
+import tempfile
+import threading
+from gettext import gettext as _
+
+from gi.repository import GObject
+from gi.repository import Gtk
+from gi.repository import GLib
+from gi.repository import EvinceDocument
+from gi.repository import EvinceView
+from gi.repository import WebKit
+
+from sugar3.graphics.toolbarbox import ToolbarBox
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.datastore import datastore
+from sugar3.activity import activity
+
+
+class EvinceViewer(Gtk.Overlay):
+ """PDF viewer with a toolbar overlay for basic navigation and an
+ option to save to Journal.
+
+ """
+ __gsignals__ = {
+ 'save-to-journal': (GObject.SignalFlags.RUN_FIRST,
+ None,
+ ([])),
+ 'open-link': (GObject.SignalFlags.RUN_FIRST,
+ None,
+ ([str])),
+ }
+
+ def __init__(self, uri):
+ GObject.GObject.__init__(self)
+
+ self._uri = uri
+
+ # Create Evince objects to handle the PDF in the URI:
+ EvinceDocument.init()
+ self._doc = EvinceDocument.Document.factory_get_document(uri)
+ self._view = EvinceView.View()
+ self._model = EvinceView.DocumentModel()
+ self._model.set_document(self._doc)
+ self._view.set_model(self._model)
+
+ self._view.connect('external-link', self.__handle_link_cb)
+ self._model.connect('page-changed', self.__page_changed_cb)
+
+ self._back_page_button = None
+ self._forward_page_button = None
+ self._toolbar_box = self._create_toolbar()
+ self._update_nav_buttons()
+
+ self._toolbar_box.set_halign(Gtk.Align.FILL)
+ self._toolbar_box.set_valign(Gtk.Align.END)
+ self.add_overlay(self._toolbar_box)
+ self._toolbar_box.show()
+
+ scrolled_window = Gtk.ScrolledWindow()
+ self.add(scrolled_window)
+ scrolled_window.show()
+
+ scrolled_window.add(self._view)
+ self._view.show()
+
+ def _create_toolbar(self):
+ toolbar_box = ToolbarBox()
+
+ zoom_out_button = ToolButton('zoom-out')
+ zoom_out_button.set_tooltip(_('Zoom out'))
+ zoom_out_button.connect('clicked', self.__zoom_out_cb)
+ toolbar_box.toolbar.insert(zoom_out_button, -1)
+ zoom_out_button.show()
+
+ zoom_in_button = ToolButton('zoom-in')
+ zoom_in_button.set_tooltip(_('Zoom in'))
+ zoom_in_button.connect('clicked', self.__zoom_in_cb)
+ toolbar_box.toolbar.insert(zoom_in_button, -1)
+ zoom_in_button.show()
+
+ separator = Gtk.SeparatorToolItem()
+ separator.props.draw = True
+ toolbar_box.toolbar.insert(separator, -1)
+ separator.show()
+
+ self._back_page_button = ToolButton('go-previous-paired')
+ self._back_page_button.set_tooltip(_('Previous page'))
+ self._back_page_button.props.sensitive = False
+ self._back_page_button.connect('clicked', self.__go_back_page_cb)
+ toolbar_box.toolbar.insert(self._back_page_button, -1)
+ self._back_page_button.show()
+
+ self._forward_page_button = ToolButton('go-next-paired')
+ self._forward_page_button.set_tooltip(_('Next page'))
+ self._forward_page_button.props.sensitive = False
+ self._forward_page_button.connect('clicked', self.__go_forward_page_cb)
+ toolbar_box.toolbar.insert(self._forward_page_button, -1)
+ self._forward_page_button.show()
+
+ separator = Gtk.SeparatorToolItem()
+ separator.props.draw = True
+ toolbar_box.toolbar.insert(separator, -1)
+ separator.show()
+
+ self._save_to_journal_button = ToolButton('save-to-journal')
+ self._save_to_journal_button.set_tooltip(_('Save PDF to Journal'))
+ self._save_to_journal_button.connect('clicked',
+ self.__save_to_journal_button_cb)
+ toolbar_box.toolbar.insert(self._save_to_journal_button, -1)
+ self._save_to_journal_button.show()
+
+ return toolbar_box
+
+ def disable_journal_button(self):
+ self._save_to_journal_button.props.sensitive = False
+
+ def __handle_link_cb(self, widget, url):
+ self.emit('open-link', url.get_uri())
+
+ def __page_changed_cb(self, model, page_from, page_to):
+ self._update_nav_buttons()
+
+ def __zoom_out_cb(self, widget):
+ self.zoom_out()
+
+ def __zoom_in_cb(self, widget):
+ self.zoom_in()
+
+ def __go_back_page_cb(self, widget):
+ self._view.previous_page()
+
+ def __go_forward_page_cb(self, widget):
+ self._view.next_page()
+
+ def __save_to_journal_button_cb(self, widget):
+ self.emit('save-to-journal')
+ self._save_to_journal_button.props.sensitive = False
+
+ def _update_nav_buttons(self):
+ current_page = self._model.props.page
+ self._back_page_button.props.sensitive = current_page > 0
+ self._forward_page_button.props.sensitive = \
+ current_page < self._doc.get_n_pages() - 1
+
+ def zoom_in(self):
+ self._model.props.sizing_mode = EvinceView.SizingMode.FREE
+ self._view.zoom_in()
+
+ def zoom_out(self):
+ self._model.props.sizing_mode = EvinceView.SizingMode.FREE
+ self._view.zoom_out()
+
+ def get_pdf_title(self):
+ return self._doc.get_title()
+
+
+class DummyBrowser(GObject.GObject):
+ """Has the same interface as browser.Browser ."""
+ __gsignals__ = {
+ 'new-tab': (GObject.SignalFlags.RUN_FIRST, None, ([str])),
+ 'tab-close': (GObject.SignalFlags.RUN_FIRST, None, ([object])),
+ 'selection-changed': (GObject.SignalFlags.RUN_FIRST, None, ([])),
+ }
+
+ __gproperties__ = {
+ "title": (object, "title", "Title", GObject.PARAM_READWRITE),
+ "uri": (object, "uri", "URI", GObject.PARAM_READWRITE),
+ "progress": (object, "progress", "Progress", GObject.PARAM_READWRITE),
+ "load-status": (object, "load status", "a WebKit LoadStatus",
+ GObject.PARAM_READWRITE),
+ }
+
+ def __init__(self, tab):
+ GObject.GObject.__init__(self)
+ self._tab = tab
+ self._title = ""
+ self._uri = ""
+ self._progress = 0.0
+ self._load_status = WebKit.LoadStatus.PROVISIONAL
+
+ def do_get_property(self, prop):
+ if prop.name == 'title':
+ return self._title
+ elif prop.name == 'uri':
+ return self._uri
+ elif prop.name == 'progress':
+ return self._progress
+ elif prop.name == 'load-status':
+ return self._load_status
+ else:
+ raise AttributeError, 'Unknown property %s' % prop.name
+
+ def do_set_property(self, prop, value):
+ if prop.name == 'title':
+ self._title = value
+ elif prop.name == 'uri':
+ self._uri = value
+ elif prop.name == 'progress':
+ self._progress = value
+ elif prop.name == 'load-status':
+ self._load_status = value
+ else:
+ raise AttributeError, 'Unknown property %s' % prop.name
+
+ def get_title(self):
+ return self._title
+
+ def get_uri(self):
+ return self._uri
+
+ def get_progress(self):
+ return self._progress
+
+ def get_load_status(self):
+ return self._load_status
+
+ def emit_new_tab(self, uri):
+ self.emit('new-tab', uri)
+
+ def emit_close_tab(self):
+ self.emit('tab-close', self._tab)
+
+ def get_history(self):
+ return [{'url': self.props.uri, 'title': self.props.title}]
+
+ def can_undo(self):
+ return False
+
+ def can_redo(self):
+ return False
+
+ def can_go_back(self):
+ return False
+
+ def can_go_forward(self):
+ return False
+
+ def can_copy_clipboard(self):
+ return False
+
+ def can_paste_clipboard(self):
+ return False
+
+ def set_history_index(self, index):
+ pass
+
+ def get_history_index(self):
+ return 0
+
+ def stop_loading(self):
+ self._tab.cancel_download()
+
+ def reload(self):
+ pass
+
+
+class PDFTabPage(Gtk.HBox):
+ """Shows a basic PDF viewer, download the file first if the PDF is
+ in a remote location.
+
+ """
+ def __init__(self):
+ GObject.GObject.__init__(self)
+ self._browser = DummyBrowser(self)
+ self._evince_viewer = None
+ self._pdf_uri = None
+ self._requested_uri = None
+
+ def setup(self, requested_uri, title=None):
+ self._requested_uri = requested_uri
+
+ # The title may be given from the Journal:
+ if title is not None:
+ self._browser.props.title = title
+ else:
+ self._browser.props.title = os.path.basename(requested_uri)
+
+ self._browser.props.uri = requested_uri
+ self._browser.props.load_status = WebKit.LoadStatus.PROVISIONAL
+
+ # show PDF directly if the file is local (from the system tree
+ # or from the journal)
+
+ if requested_uri.startswith('file://'):
+ self._pdf_uri = requested_uri
+ self._show_pdf()
+
+ elif requested_uri.startswith('journal://'):
+ self._pdf_uri = self._get_path_from_journal(requested_uri)
+ self._show_pdf(from_journal=True)
+
+ # download first if file is remote
+
+ elif requested_uri.startswith('http://'):
+ self._download_from_http(requested_uri)
+
+ def _get_browser(self):
+ return self._browser
+
+ browser = GObject.property(type=object, getter=_get_browser)
+
+ def _show_pdf(self, from_journal=False):
+ self._evince_viewer = EvinceViewer(self._pdf_uri)
+ self._evince_viewer.connect('save-to-journal',
+ self.__save_to_journal_cb)
+ self._evince_viewer.connect('open-link',
+ self.__open_link_cb)
+
+ # disable save to journal if the PDF is already loaded from
+ # the journal:
+ if from_journal:
+ self._evince_viewer.disable_journal_button()
+
+ self._evince_viewer.show()
+ self.pack_start(self._evince_viewer, True, True, 0)
+
+ # if the PDF has a title, show it instead of the URI:
+ pdf_title = self._evince_viewer.get_pdf_title()
+ if pdf_title is not None:
+ self._browser.props.title = pdf_title
+
+ def _get_path_from_journal(self, journal_uri):
+ """Get the system tree URI of the file for the Journal object."""
+ journal_id = self.__journal_id_from_uri(journal_uri)
+ jobject = datastore.get(journal_id)
+ return 'file://' + jobject.file_path
+
+ def _download_from_http(self, remote_uri):
+ """Download the PDF from a remote location to a temporal file."""
+
+ # Figure out download URI
+ temp_path = os.path.join(activity.get_activity_root(), 'instance')
+ if not os.path.exists(temp_path):
+ os.makedirs(temp_path)
+
+ fd, dest_path = tempfile.mkstemp(dir=temp_path)
+
+ self._pdf_uri = 'file://' + dest_path
+
+ network_request = WebKit.NetworkRequest.new(remote_uri)
+ self._download = WebKit.Download.new(network_request)
+ self._download.set_destination_uri('file://' + dest_path)
+
+ self._download.connect('notify::progress', self.__download_progress_cb)
+ self._download.connect('notify::status', self.__download_status_cb)
+ self._download.connect('error', self.__download_error_cb)
+
+ self._download.start()
+
+ def __download_progress_cb(self, download, data):
+ progress = download.get_progress()
+ self._browser.props.load_status = WebKit.LoadStatus.PROVISIONAL
+ self._browser.props.progress = progress
+
+ def __download_status_cb(self, download, data):
+ status = download.get_status()
+ if status == WebKit.DownloadStatus.STARTED:
+ self._browser.props.load_status = WebKit.LoadStatus.PROVISIONAL
+ elif status == WebKit.DownloadStatus.FINISHED:
+ self._browser.props.load_status = WebKit.LoadStatus.FINISHED
+ self._show_pdf()
+ elif status == WebKit.DownloadStatus.CANCELLED:
+ logging.debug('Download PDF canceled')
+
+ def __download_error_cb(self, download, err_code, err_detail, reason):
+ logging.debug('Download error! code %s, detail %s: %s' % \
+ (err_code, err_detail, reason))
+
+ def cancel_download(self):
+ self._download.cancel()
+ self._browser.emit_close_tab()
+
+ def __journal_id_to_uri(self, journal_id):
+ """Return an URI for a Journal object ID."""
+ return "journal://" + journal_id + ".pdf"
+
+ def __journal_id_from_uri(self, journal_uri):
+ """Return a Journal object ID from an URI."""
+ return journal_uri[len("journal://"):-len(".pdf")]
+
+ def __save_to_journal_cb(self, widget):
+ """Save the PDF in the Journal.
+
+ Put the PDF title as the title, or if the PDF doesn't have
+ one, use the filename instead. Put the requested uri as the
+ description.
+
+ """
+ jobject = datastore.create()
+
+ jobject.metadata['title'] = self._browser.props.title
+ jobject.metadata['description'] = _('From: %s') % self._requested_uri
+
+ jobject.metadata['mime_type'] = "application/pdf"
+ jobject.file_path = self._pdf_uri[len("file://"):]
+ datastore.write(jobject)
+
+ # display the new URI:
+ self._browser.props.uri = self.__journal_id_to_uri(jobject.object_id)
+
+ def __open_link_cb(self, widget, uri):
+ """Open the external link of a PDF in a new tab."""
+ self._browser.emit_new_tab(uri)
diff --git a/viewtoolbar.py b/viewtoolbar.py
index 7daadc9..0226df8 100644
--- a/viewtoolbar.py
+++ b/viewtoolbar.py
@@ -22,11 +22,15 @@ from gi.repository import GObject
from sugar3.graphics.toolbutton import ToolButton
+from browser import Browser
+
class ViewToolbar(Gtk.Toolbar):
def __init__(self, activity):
GObject.GObject.__init__(self)
+ self._browser = None
+
self._activity = activity
self._activity.tray.connect('unmap', self.__unmap_cb)
self._activity.tray.connect('map', self.__map_cb)
@@ -60,6 +64,25 @@ class ViewToolbar(Gtk.Toolbar):
self.insert(self.traybutton, -1)
self.traybutton.show()
+ tabbed_view = self._activity.get_canvas()
+
+ if tabbed_view.get_n_pages():
+ self._connect_to_browser(tabbed_view.props.current_browser)
+
+ tabbed_view.connect_after('switch-page', self.__switch_page_cb)
+
+ def __switch_page_cb(self, tabbed_view, page, page_num):
+ self._connect_to_browser(tabbed_view.props.current_browser)
+
+ def _connect_to_browser(self, browser):
+ self._browser = browser
+ self._update_zoom_buttons()
+
+ def _update_zoom_buttons(self):
+ is_webkit_browser = isinstance(self._browser, Browser)
+ self.zoomin.set_sensitive(is_webkit_browser)
+ self.zoomout.set_sensitive(is_webkit_browser)
+
def __zoomin_clicked_cb(self, button):
tabbed_view = self._activity.get_canvas()
tabbed_view.props.current_browser.zoom_in()
diff --git a/webtoolbar.py b/webtoolbar.py
index 098f832..7525053 100644
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -34,6 +34,7 @@ from sugar3.activity.widgets import StopButton
# import filepicker
import places
from sugarmenuitem import SugarMenuItem
+from browser import Browser
_MAX_HISTORY_ENTRIES = 15
@@ -331,6 +332,11 @@ class PrimaryToolbar(ToolbarBase):
self._set_title(_('Untitled'))
self._set_address(self._browser.props.uri)
+ if isinstance(self._browser, Browser):
+ self.entry.props.editable = True
+ else:
+ self.entry.props.editable = False
+
self._title_changed_hid = self._browser.connect(
'notify::title', self._title_changed_cb)
self._uri_changed_hid = self._browser.connect(
@@ -379,7 +385,11 @@ class PrimaryToolbar(ToolbarBase):
can_go_forward = self._browser.can_go_forward()
self._forward.props.sensitive = can_go_forward
- self._reload_session_history()
+ is_webkit_browser = isinstance(self._browser, Browser)
+ self._link_add.props.sensitive = is_webkit_browser
+ self._go_home.props.sensitive = is_webkit_browser
+ if is_webkit_browser:
+ self._reload_session_history()
def _entry_activate_cb(self, entry):
url = entry.props.text