Initial attempt at getting PDF.js to work with separate downloads
This commit is contained in:
parent
8f1690eff7
commit
df67c254f8
@ -32,10 +32,11 @@ import enum
|
|||||||
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QObject, QModelIndex,
|
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QObject, QModelIndex,
|
||||||
QTimer, QAbstractListModel, QUrl)
|
QTimer, QAbstractListModel, QUrl)
|
||||||
|
|
||||||
|
from qutebrowser.browser import pdfjs
|
||||||
from qutebrowser.commands import cmdexc, cmdutils
|
from qutebrowser.commands import cmdexc, cmdutils
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils import (usertypes, standarddir, utils, message, log,
|
from qutebrowser.utils import (usertypes, standarddir, utils, message, log,
|
||||||
qtutils)
|
qtutils, objreg)
|
||||||
from qutebrowser.qt import sip
|
from qutebrowser.qt import sip
|
||||||
|
|
||||||
|
|
||||||
@ -224,9 +225,6 @@ class _DownloadTarget:
|
|||||||
|
|
||||||
"""Abstract base class for different download targets."""
|
"""Abstract base class for different download targets."""
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def suggested_filename(self):
|
def suggested_filename(self):
|
||||||
"""Get the suggested filename for this download target."""
|
"""Get the suggested filename for this download target."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -300,6 +298,17 @@ class OpenFileDownloadTarget(_DownloadTarget):
|
|||||||
return 'temporary file'
|
return 'temporary file'
|
||||||
|
|
||||||
|
|
||||||
|
class PDFJSDownloadTarget(_DownloadTarget):
|
||||||
|
|
||||||
|
"""Open the download via PDF.js."""
|
||||||
|
|
||||||
|
def suggested_filename(self):
|
||||||
|
raise NoFilenameError
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'temporary PDF.js file'
|
||||||
|
|
||||||
|
|
||||||
class DownloadItemStats(QObject):
|
class DownloadItemStats(QObject):
|
||||||
|
|
||||||
"""Statistics (bytes done, total bytes, time, etc.) about a download.
|
"""Statistics (bytes done, total bytes, time, etc.) about a download.
|
||||||
@ -405,6 +414,8 @@ class AbstractDownloadItem(QObject):
|
|||||||
arg: The error message as string.
|
arg: The error message as string.
|
||||||
remove_requested: Emitted when the removal of this download was
|
remove_requested: Emitted when the removal of this download was
|
||||||
requested.
|
requested.
|
||||||
|
pdfjs_requested: Emitted when PDF.js should be opened with the given
|
||||||
|
filename.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data_changed = pyqtSignal()
|
data_changed = pyqtSignal()
|
||||||
@ -412,6 +423,7 @@ class AbstractDownloadItem(QObject):
|
|||||||
error = pyqtSignal(str)
|
error = pyqtSignal(str)
|
||||||
cancelled = pyqtSignal()
|
cancelled = pyqtSignal()
|
||||||
remove_requested = pyqtSignal()
|
remove_requested = pyqtSignal()
|
||||||
|
pdfjs_requested = pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -730,6 +742,19 @@ class AbstractDownloadItem(QObject):
|
|||||||
return
|
return
|
||||||
self.open_file(cmdline)
|
self.open_file(cmdline)
|
||||||
|
|
||||||
|
def _pdfjs_if_successful(self):
|
||||||
|
"""Open the file via PDF.js if downloading was successful."""
|
||||||
|
if not self.successful:
|
||||||
|
log.downloads.debug("{} finished but not successful, not opening!"
|
||||||
|
.format(self))
|
||||||
|
return
|
||||||
|
|
||||||
|
filename = self._get_open_filename()
|
||||||
|
if filename is None: # pragma: no cover
|
||||||
|
log.downloads.error("No filename to open the download!")
|
||||||
|
return
|
||||||
|
self.pdfjs_requested.emit(filename)
|
||||||
|
|
||||||
def set_target(self, target):
|
def set_target(self, target):
|
||||||
"""Set the target for a given download.
|
"""Set the target for a given download.
|
||||||
|
|
||||||
@ -741,7 +766,7 @@ class AbstractDownloadItem(QObject):
|
|||||||
elif isinstance(target, FileDownloadTarget):
|
elif isinstance(target, FileDownloadTarget):
|
||||||
self._set_filename(
|
self._set_filename(
|
||||||
target.filename, force_overwrite=target.force_overwrite)
|
target.filename, force_overwrite=target.force_overwrite)
|
||||||
elif isinstance(target, OpenFileDownloadTarget):
|
elif isinstance(target, (OpenFileDownloadTarget, PDFJSDownloadTarget)):
|
||||||
try:
|
try:
|
||||||
fobj = temp_download_manager.get_tmpfile(self.basename)
|
fobj = temp_download_manager.get_tmpfile(self.basename)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
@ -749,8 +774,15 @@ class AbstractDownloadItem(QObject):
|
|||||||
message.error(msg)
|
message.error(msg)
|
||||||
self.cancel()
|
self.cancel()
|
||||||
return
|
return
|
||||||
self.finished.connect(
|
|
||||||
functools.partial(self._open_if_successful, target.cmdline))
|
if isinstance(target, OpenFileDownloadTarget):
|
||||||
|
self.finished.connect(
|
||||||
|
functools.partial(self._open_if_successful, target.cmdline))
|
||||||
|
elif isinstance(target, PDFJSDownloadTarget):
|
||||||
|
self.finished.connect(self._pdfjs_if_successful)
|
||||||
|
else:
|
||||||
|
assert False, target
|
||||||
|
|
||||||
self._set_tempfile(fobj)
|
self._set_tempfile(fobj)
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
raise ValueError("Unsupported download target: {}".format(target))
|
raise ValueError("Unsupported download target: {}".format(target))
|
||||||
@ -797,6 +829,13 @@ class AbstractDownloadManager(QObject):
|
|||||||
dl.stats.update_speed()
|
dl.stats.update_speed()
|
||||||
self.data_changed.emit(-1)
|
self.data_changed.emit(-1)
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def _on_pdfjs_requested(self, filename):
|
||||||
|
"""Open PDF.js when a download requests it."""
|
||||||
|
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||||
|
window='last-focused')
|
||||||
|
tabbed_browser.tabopen(pdfjs.get_main_url(filename))
|
||||||
|
|
||||||
def _init_item(self, download, auto_remove, suggested_filename):
|
def _init_item(self, download, auto_remove, suggested_filename):
|
||||||
"""Initialize a newly created DownloadItem."""
|
"""Initialize a newly created DownloadItem."""
|
||||||
download.cancelled.connect(download.remove)
|
download.cancelled.connect(download.remove)
|
||||||
@ -813,6 +852,8 @@ class AbstractDownloadManager(QObject):
|
|||||||
download.data_changed.connect(
|
download.data_changed.connect(
|
||||||
functools.partial(self._on_data_changed, download))
|
functools.partial(self._on_data_changed, download))
|
||||||
download.error.connect(self._on_error)
|
download.error.connect(self._on_error)
|
||||||
|
download.pdfjs_requested.connect(self._on_pdfjs_requested)
|
||||||
|
|
||||||
download.basename = suggested_filename
|
download.basename = suggested_filename
|
||||||
idx = len(self.downloads)
|
idx = len(self.downloads)
|
||||||
download.index = idx + 1 # "Human readable" index
|
download.index = idx + 1 # "Human readable" index
|
||||||
|
@ -22,9 +22,10 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl, QUrlQuery
|
||||||
|
|
||||||
from qutebrowser.utils import utils, javascript, jinja
|
from qutebrowser.utils import utils, javascript, jinja
|
||||||
|
from qutebrowser.config import config
|
||||||
|
|
||||||
|
|
||||||
class PDFJSNotFound(Exception):
|
class PDFJSNotFound(Exception):
|
||||||
@ -210,3 +211,17 @@ def is_available():
|
|||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def should_use_pdfjs(mimetype):
|
||||||
|
return (mimetype in ['application/pdf', 'application/x-pdf'] and
|
||||||
|
config.val.content.pdfjs)
|
||||||
|
|
||||||
|
|
||||||
|
def get_main_url(filename):
|
||||||
|
"""Get the URL to be opened to view a local PDF."""
|
||||||
|
url = QUrl('qute://pdfjs')
|
||||||
|
query = QUrlQuery()
|
||||||
|
query.addQueryItem('file', QUrl.fromLocalFile(filename).toString())
|
||||||
|
url.setQuery(query)
|
||||||
|
return url
|
||||||
|
@ -523,6 +523,11 @@ def qute_pastebin_version(_url):
|
|||||||
@add_handler('pdfjs')
|
@add_handler('pdfjs')
|
||||||
def qute_pdfjs(url):
|
def qute_pdfjs(url):
|
||||||
"""Handler for qute://pdfjs. Return the pdf.js viewer."""
|
"""Handler for qute://pdfjs. Return the pdf.js viewer."""
|
||||||
|
if url.path() == '/':
|
||||||
|
filepath = QUrlQuery(url).queryItemValue("file")
|
||||||
|
data = pdfjs.generate_pdfjs_page(QUrl.fromLocalFile(filepath))
|
||||||
|
return 'text/html', data
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = pdfjs.get_pdfjs_res(url.path())
|
data = pdfjs.get_pdfjs_res(url.path())
|
||||||
except pdfjs.PDFJSNotFound as e:
|
except pdfjs.PDFJSNotFound as e:
|
||||||
@ -534,5 +539,6 @@ def qute_pdfjs(url):
|
|||||||
raise NotFoundError("Can't find pdfjs resource '{}'".format(e.path))
|
raise NotFoundError("Can't find pdfjs resource '{}'".format(e.path))
|
||||||
else:
|
else:
|
||||||
mimetype, _encoding = mimetypes.guess_type(url.fileName())
|
mimetype, _encoding = mimetypes.guess_type(url.fileName())
|
||||||
assert mimetype is not None, url
|
if mimetype is None:
|
||||||
|
mimetype = 'application/octet-stream'
|
||||||
return mimetype, data
|
return mimetype, data
|
||||||
|
@ -30,7 +30,7 @@ from PyQt5.QtPrintSupport import QPrintDialog
|
|||||||
from PyQt5.QtWebKitWidgets import QWebPage, QWebFrame
|
from PyQt5.QtWebKitWidgets import QWebPage, QWebFrame
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.browser import pdfjs, shared
|
from qutebrowser.browser import pdfjs, shared, downloads
|
||||||
from qutebrowser.browser.webkit import http
|
from qutebrowser.browser.webkit import http
|
||||||
from qutebrowser.browser.webkit.network import networkmanager
|
from qutebrowser.browser.webkit.network import networkmanager
|
||||||
from qutebrowser.utils import message, usertypes, log, jinja, objreg
|
from qutebrowser.utils import message, usertypes, log, jinja, objreg
|
||||||
@ -275,10 +275,9 @@ class BrowserPage(QWebPage):
|
|||||||
else:
|
else:
|
||||||
reply.finished.connect(functools.partial(
|
reply.finished.connect(functools.partial(
|
||||||
self.display_content, reply, 'image/jpeg'))
|
self.display_content, reply, 'image/jpeg'))
|
||||||
elif (mimetype in ['application/pdf', 'application/x-pdf'] and
|
elif pdfjs.should_use_pdfjs(mimetype):
|
||||||
config.val.content.pdfjs):
|
download_manager.fetch(reply,
|
||||||
# Use pdf.js to display the page
|
target=downloads.PDFJSDownloadTarget())
|
||||||
self._show_pdfjs(reply)
|
|
||||||
else:
|
else:
|
||||||
# Unknown mimetype, so download anyways.
|
# Unknown mimetype, so download anyways.
|
||||||
download_manager.fetch(reply,
|
download_manager.fetch(reply,
|
||||||
|
Loading…
Reference in New Issue
Block a user