First attempt at proper AboutSchemeHandler
This commit is contained in:
parent
ec1951c56c
commit
38ef8fe8c7
@ -17,8 +17,10 @@
|
|||||||
|
|
||||||
"""Handler functions for different about:... pages."""
|
"""Handler functions for different about:... pages."""
|
||||||
|
|
||||||
|
from qutebrowser.network.schemehandler import (SchemeHandler,
|
||||||
|
SpecialNetworkReply)
|
||||||
from qutebrowser.utils.version import version
|
from qutebrowser.utils.version import version
|
||||||
from qutebrowser.utils.url import is_about_url
|
from qutebrowser.utils.url import is_about_url, urlstring
|
||||||
|
|
||||||
|
|
||||||
_HTML_TEMPLATE = """
|
_HTML_TEMPLATE = """
|
||||||
@ -84,6 +86,30 @@ def _get_html(title, snippet):
|
|||||||
return _HTML_TEMPLATE.format(title=title, body=snippet).encode('UTF-8')
|
return _HTML_TEMPLATE.format(title=title, body=snippet).encode('UTF-8')
|
||||||
|
|
||||||
|
|
||||||
|
class AboutSchemeHandler(SchemeHandler):
|
||||||
|
|
||||||
|
"""Scheme handler for about: URLs."""
|
||||||
|
|
||||||
|
def createRequest(self, op, request, outgoingData=None):
|
||||||
|
"""Create a new request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
op: Operation op
|
||||||
|
req: const QNetworkRequest & req
|
||||||
|
outgoing_data: QIODevice * outgoingData
|
||||||
|
|
||||||
|
Return:
|
||||||
|
A QNetworkReply.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# FIXME handle unknown pages
|
||||||
|
# FIXME adjust URLutils based on handlers
|
||||||
|
|
||||||
|
data = handle(urlstring(request.url()))
|
||||||
|
return SpecialNetworkReply(request, data, "text/html", self.parent())
|
||||||
|
|
||||||
|
|
||||||
class AboutHandlers:
|
class AboutHandlers:
|
||||||
|
|
||||||
"""Handlers for about:... pages."""
|
"""Handlers for about:... pages."""
|
||||||
|
@ -17,20 +17,30 @@
|
|||||||
|
|
||||||
"""Our own QNetworkAccessManager."""
|
"""Our own QNetworkAccessManager."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||||
|
|
||||||
|
from qutebrowser.network.about import AboutSchemeHandler
|
||||||
|
|
||||||
|
|
||||||
class NetworkManager(QNetworkAccessManager):
|
class NetworkManager(QNetworkAccessManager):
|
||||||
|
|
||||||
"""Our own QNetworkAccessManager.
|
"""Our own QNetworkAccessManager.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
_requests: Pending requests.
|
_requests: Pending requests.
|
||||||
|
_scheme_handlers: A dictionary (scheme -> handler) of supported custom
|
||||||
|
schemes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
self._requests = {}
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
self._requests = {}
|
||||||
|
self._scheme_handlers = {
|
||||||
|
'about': AboutSchemeHandler,
|
||||||
|
}
|
||||||
|
|
||||||
def abort_requests(self):
|
def abort_requests(self):
|
||||||
"""Abort all running requests."""
|
"""Abort all running requests."""
|
||||||
@ -41,7 +51,7 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
"""Return a new QNetworkReply object.
|
"""Return a new QNetworkReply object.
|
||||||
|
|
||||||
Extend QNetworkAccessManager::createRequest to save requests in
|
Extend QNetworkAccessManager::createRequest to save requests in
|
||||||
self._requests.
|
self._requests and handle custom schemes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
op: Operation op
|
op: Operation op
|
||||||
@ -52,6 +62,13 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
A QNetworkReply.
|
A QNetworkReply.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
scheme = req.url().scheme()
|
||||||
|
logging.debug("new req, scheme {}, handlers {}".format(scheme,
|
||||||
|
self._scheme_handlers))
|
||||||
|
if scheme in self._scheme_handlers:
|
||||||
|
reply = self._scheme_handlers[scheme].createRequest(
|
||||||
|
op, req, outgoing_data)
|
||||||
|
return reply
|
||||||
reply = super().createRequest(op, req, outgoing_data)
|
reply = super().createRequest(op, req, outgoing_data)
|
||||||
self._requests[id(reply)] = reply
|
self._requests[id(reply)] = reply
|
||||||
reply.destroyed.connect(lambda obj: self._requests.pop(id(obj)))
|
reply.destroyed.connect(lambda obj: self._requests.pop(id(obj)))
|
||||||
|
118
qutebrowser/network/schemehandler.py
Normal file
118
qutebrowser/network/schemehandler.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||||
|
#
|
||||||
|
# Based on the Eric5 helpviewer,
|
||||||
|
# Copyright (c) 2009 - 2014 Detlev Offenbach <detlev@die-offenbachs.de>
|
||||||
|
#
|
||||||
|
# This file is part of qutebrowser.
|
||||||
|
#
|
||||||
|
# qutebrowser 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 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# qutebrowser 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 qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""Base class for custom scheme handlers."""
|
||||||
|
|
||||||
|
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
|
||||||
|
from PyQt5.QtCore import pyqtSlot, QObject, QIODevice, QByteArray
|
||||||
|
|
||||||
|
class SchemeHandler(QObject):
|
||||||
|
|
||||||
|
"""Abstract base class for custom scheme handlers."""
|
||||||
|
|
||||||
|
def createRequest(self, op, request, outgoingData=None):
|
||||||
|
"""Create a new request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
op: Operation op
|
||||||
|
req: const QNetworkRequest & req
|
||||||
|
outgoing_data: QIODevice * outgoingData
|
||||||
|
|
||||||
|
Return:
|
||||||
|
A QNetworkReply.
|
||||||
|
|
||||||
|
Raise:
|
||||||
|
NotImplementedError because this needs to be overwritten by
|
||||||
|
subclasses.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SpecialNetworkReply(QNetworkReply):
|
||||||
|
|
||||||
|
"""QNetworkReply subclass for special data."""
|
||||||
|
|
||||||
|
def __init__(self, request, fileData, mimeType, parent=None):
|
||||||
|
"""Constructor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request: reference to the request object (QNetworkRequest)
|
||||||
|
fileData: reference to the data buffer (QByteArray)
|
||||||
|
mimeType: for the reply (string)
|
||||||
|
parent: reference to the parent object (QObject)
|
||||||
|
|
||||||
|
Emit:
|
||||||
|
metaDataChanged and readyRead after initializing.
|
||||||
|
|
||||||
|
"""
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self._data = fileData
|
||||||
|
|
||||||
|
self.setRequest(request)
|
||||||
|
self.setOpenMode(QIODevice.ReadOnly)
|
||||||
|
|
||||||
|
self.setHeader(QNetworkRequest.ContentTypeHeader, mimeType)
|
||||||
|
self.setHeader(QNetworkRequest.ContentLengthHeader,
|
||||||
|
QByteArray.number(fileData.length()))
|
||||||
|
self.setAttribute(QNetworkRequest.HttpStatusCodeAttribute, 200)
|
||||||
|
self.setAttribute(QNetworkRequest.HttpReasonPhraseAttribute, "OK")
|
||||||
|
self.metaDataChanged.emit()
|
||||||
|
self.readyRead.emit()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def abort(self):
|
||||||
|
"""Abort the operation."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def bytesAvailable(self):
|
||||||
|
"""Determine the bytes available for being read.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
bytes available (int)
|
||||||
|
|
||||||
|
Emit:
|
||||||
|
finished: if the data length is 0
|
||||||
|
|
||||||
|
"""
|
||||||
|
if self._data.length() == 0:
|
||||||
|
self.finished.emit()
|
||||||
|
return self._data.length() + super().bytesAvailable()
|
||||||
|
|
||||||
|
def readData(self, maxlen):
|
||||||
|
"""Retrieve data from the reply object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
maxlen maximum number of bytes to read (int)
|
||||||
|
|
||||||
|
Return:
|
||||||
|
bytestring containing the data
|
||||||
|
|
||||||
|
Emit:
|
||||||
|
finished: if all data was read
|
||||||
|
|
||||||
|
"""
|
||||||
|
len_ = min(maxlen, self._data.length())
|
||||||
|
buf = bytes(self._data[:len_])
|
||||||
|
self._data.remove(0, len_)
|
||||||
|
if self._data.length() == 0:
|
||||||
|
self.finished.emit()
|
||||||
|
return buf
|
@ -36,7 +36,6 @@ from PyQt5.QtWebKitWidgets import QWebView, QWebPage
|
|||||||
|
|
||||||
import qutebrowser.utils.url as urlutils
|
import qutebrowser.utils.url as urlutils
|
||||||
import qutebrowser.utils.config as config
|
import qutebrowser.utils.config as config
|
||||||
import qutebrowser.network.about as about
|
|
||||||
from qutebrowser.widgets.tabbar import TabWidget
|
from qutebrowser.widgets.tabbar import TabWidget
|
||||||
from qutebrowser.network.networkmanager import NetworkManager
|
from qutebrowser.network.networkmanager import NetworkManager
|
||||||
from qutebrowser.utils.signals import SignalCache, dbg_signal
|
from qutebrowser.utils.signals import SignalCache, dbg_signal
|
||||||
@ -719,15 +718,6 @@ class BrowserTab(QWebView):
|
|||||||
logging.debug('New title: {}'.format(urlutils.urlstring(u)))
|
logging.debug('New title: {}'.format(urlutils.urlstring(u)))
|
||||||
self.titleChanged.emit(urlutils.urlstring(u))
|
self.titleChanged.emit(urlutils.urlstring(u))
|
||||||
self.urlChanged.emit(urlutils.qurl(u))
|
self.urlChanged.emit(urlutils.qurl(u))
|
||||||
if urlutils.is_about_url(u):
|
|
||||||
try:
|
|
||||||
content = about.handle(urlutils.urlstring(u))
|
|
||||||
except AttributeError:
|
|
||||||
return self.load(u)
|
|
||||||
else:
|
|
||||||
self.setUrl(u)
|
|
||||||
self.setContent(content, 'text/html')
|
|
||||||
else:
|
|
||||||
return self.load(u)
|
return self.load(u)
|
||||||
|
|
||||||
def zoom(self, offset):
|
def zoom(self, offset):
|
||||||
|
Loading…
Reference in New Issue
Block a user