2014-01-20 15:58:49 +01:00
|
|
|
import logging
|
|
|
|
|
|
|
|
from PyQt5.QtCore import QUrl, pyqtSignal, Qt, QPoint
|
2014-01-17 21:50:43 +01:00
|
|
|
from PyQt5.QtPrintSupport import QPrintPreviewDialog
|
2013-12-15 21:40:15 +01:00
|
|
|
from PyQt5.QtWebKitWidgets import QWebView
|
2014-01-20 15:58:49 +01:00
|
|
|
|
2013-12-15 21:40:15 +01:00
|
|
|
from qutebrowser.widgets.tabbar import TabWidget
|
|
|
|
|
|
|
|
class TabbedBrowser(TabWidget):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""A TabWidget with QWebViews inside"""
|
|
|
|
|
|
|
|
cur_progress = pyqtSignal(int) # Progress of the current tab changed
|
|
|
|
cur_load_finished = pyqtSignal(bool) # Current tab finished loading
|
2014-01-19 19:41:34 +01:00
|
|
|
keypress = pyqtSignal('QKeyEvent')
|
2014-01-20 15:58:49 +01:00
|
|
|
_url_stack = [] # Stack of URLs of closed tabs
|
2013-12-15 21:40:15 +01:00
|
|
|
|
|
|
|
def __init__(self, parent):
|
|
|
|
super().__init__(parent)
|
2014-01-20 15:58:49 +01:00
|
|
|
self.currentChanged.connect(self._currentChanged_handler)
|
2013-12-15 21:40:15 +01:00
|
|
|
self.tabopen("http://ddg.gg/")
|
|
|
|
|
|
|
|
def tabopen(self, url):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""Opens a new tab with a given url"""
|
2013-12-15 21:40:15 +01:00
|
|
|
tab = BrowserTab(self)
|
|
|
|
tab.openurl(url)
|
|
|
|
self.addTab(tab, url)
|
2013-12-16 22:07:11 +01:00
|
|
|
self.setCurrentWidget(tab)
|
2014-01-20 15:58:49 +01:00
|
|
|
self.cur_progress.emit(tab.progress)
|
|
|
|
tab.loadProgress.connect(
|
|
|
|
lambda *args: self._filter_signals(self.cur_progress, *args))
|
|
|
|
tab.loadFinished.connect(
|
|
|
|
lambda *args: self._filter_signals(self.cur_load_finished, *args))
|
2014-01-20 08:57:11 +01:00
|
|
|
# FIXME should we really bind this to loadStarted? Sometimes the URL
|
|
|
|
# isn't set correctly at this point, e.g. when doing
|
|
|
|
# setContent(..., baseUrl=QUrl('foo'))
|
2014-01-20 15:58:49 +01:00
|
|
|
tab.loadStarted.connect(self._loadStarted_handler)
|
|
|
|
tab.titleChanged.connect(self._titleChanged_handler)
|
2013-12-15 21:40:15 +01:00
|
|
|
|
2013-12-16 22:01:06 +01:00
|
|
|
def openurl(self, url):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""Opens an url in the current tab"""
|
2014-01-17 23:22:49 +01:00
|
|
|
tab = self.currentWidget()
|
2013-12-16 22:01:06 +01:00
|
|
|
tab.openurl(url)
|
|
|
|
|
2014-01-17 23:17:24 +01:00
|
|
|
def undo_close(self):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""Undos closing a tab"""
|
|
|
|
if self._url_stack:
|
|
|
|
self.tabopen(self._url_stack.pop())
|
2014-01-17 23:17:24 +01:00
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def cur_close(self):
|
|
|
|
"""Closes the current tab"""
|
2014-01-17 23:22:49 +01:00
|
|
|
if self.count() > 1:
|
2014-01-17 08:28:04 +01:00
|
|
|
idx = self.currentIndex()
|
2014-01-17 23:22:49 +01:00
|
|
|
tab = self.currentWidget()
|
2014-01-17 23:17:24 +01:00
|
|
|
# FIXME maybe we should add the QUrl object here and deal with QUrls everywhere
|
|
|
|
# FIXME maybe we actually should store the webview objects here
|
2014-01-20 15:58:49 +01:00
|
|
|
self._url_stack.append(tab.url().url())
|
2014-01-17 08:28:04 +01:00
|
|
|
self.removeTab(idx)
|
|
|
|
else:
|
|
|
|
# FIXME
|
|
|
|
pass
|
2014-01-17 08:03:42 +01:00
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def cur_reload(self):
|
|
|
|
"""Reloads the current tab"""
|
2014-01-17 21:50:43 +01:00
|
|
|
self.currentWidget().reload()
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def cur_stop(self):
|
|
|
|
"""Stops loading in the current tab"""
|
2014-01-17 21:50:43 +01:00
|
|
|
self.currentWidget().stop()
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def cur_print(self):
|
|
|
|
"""Prints the current tab"""
|
2014-01-17 21:50:43 +01:00
|
|
|
# FIXME that does not what I expect
|
|
|
|
preview = QPrintPreviewDialog()
|
|
|
|
preview.paintRequested.connect(self.currentWidget().print)
|
|
|
|
preview.exec_()
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def cur_back(self):
|
|
|
|
"""Goes back in the history of the current tab"""
|
2014-01-17 21:50:43 +01:00
|
|
|
# FIXME display warning if beginning of history
|
|
|
|
self.currentWidget().back()
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def cur_forward(self):
|
|
|
|
"""Goes forward in the history of the current tab"""
|
2014-01-17 21:50:43 +01:00
|
|
|
# FIXME display warning if end of history
|
|
|
|
self.currentWidget().forward()
|
|
|
|
|
2014-01-20 17:01:52 +01:00
|
|
|
def cur_scroll(self, dx, dy, count=None):
|
|
|
|
"""Scrolls the current tab by count * dx/dy"""
|
2014-01-19 22:55:00 +01:00
|
|
|
if count is None:
|
2014-01-20 17:01:52 +01:00
|
|
|
count = 1
|
|
|
|
dx = int(count) * int(dx)
|
|
|
|
dy = int(count) * int(dy)
|
|
|
|
self.currentWidget().page().mainFrame().scroll(dx, dy)
|
2014-01-19 17:45:03 +01:00
|
|
|
|
2014-01-20 17:59:01 +01:00
|
|
|
def cur_scroll_percent_x(self, perc=None, count=None):
|
|
|
|
"""Scrolls the current tab to a specific percent of the page.
|
|
|
|
Accepts percentage either as argument, or as count.
|
|
|
|
"""
|
|
|
|
if perc is None and count is None:
|
|
|
|
perc = 0
|
|
|
|
elif perc is None:
|
|
|
|
perc = count
|
2014-01-19 18:43:47 +01:00
|
|
|
frame = self.currentWidget().page().mainFrame()
|
|
|
|
cur_pos = frame.scrollPosition()
|
2014-01-20 17:59:01 +01:00
|
|
|
size = frame.contentsSize()
|
|
|
|
x = size.width() / 100 * int(perc)
|
|
|
|
frame.setScrollPosition(QPoint(x, cur_pos.y()))
|
|
|
|
|
|
|
|
def cur_scroll_percent_y(self, perc=None, count=None):
|
|
|
|
"""Scrolls the current tab to a specific percent of the page
|
|
|
|
Accepts percentage either as argument, or as count.
|
|
|
|
"""
|
|
|
|
if perc is None and count is None:
|
|
|
|
perc = 100
|
|
|
|
elif perc is None:
|
|
|
|
perc = count
|
2014-01-19 18:43:47 +01:00
|
|
|
frame = self.currentWidget().page().mainFrame()
|
|
|
|
cur_pos = frame.scrollPosition()
|
|
|
|
size = frame.contentsSize()
|
2014-01-20 17:59:01 +01:00
|
|
|
y = size.height() / 100 * int(perc)
|
|
|
|
frame.setScrollPosition(QPoint(cur_pos.x(), y))
|
2014-01-19 18:43:47 +01:00
|
|
|
|
2014-01-17 08:39:14 +01:00
|
|
|
def switch_prev(self):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""Switches to the previous tab"""
|
2014-01-17 08:39:14 +01:00
|
|
|
idx = self.currentIndex()
|
|
|
|
if idx > 0:
|
|
|
|
self.setCurrentIndex(idx - 1)
|
|
|
|
else:
|
|
|
|
# FIXME
|
|
|
|
pass
|
|
|
|
|
|
|
|
def switch_next(self):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""Switches to the next tab"""
|
2014-01-17 08:39:14 +01:00
|
|
|
idx = self.currentIndex()
|
|
|
|
if idx < self.count() - 1:
|
|
|
|
self.setCurrentIndex(idx + 1)
|
|
|
|
else:
|
|
|
|
# FIXME
|
|
|
|
pass
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def keyPressEvent(self, e):
|
|
|
|
self.keypress.emit(e)
|
|
|
|
super().keyPressEvent(e)
|
2014-01-19 16:56:19 +01:00
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def _titleChanged_handler(self, text):
|
2014-01-17 22:50:27 +01:00
|
|
|
if text:
|
|
|
|
self.setTabText(self.indexOf(self.sender()), text)
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def _loadStarted_handler(self):
|
2014-01-20 08:57:11 +01:00
|
|
|
s = self.sender()
|
|
|
|
self.setTabText(self.indexOf(s), s.url().toString())
|
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def _filter_signals(self, signal, *args):
|
|
|
|
"""Filters signals, and triggers TabbedBrowser signals if the signal
|
|
|
|
was sent from the _current_ tab and not from any other one.
|
|
|
|
"""
|
2014-01-17 21:29:43 +01:00
|
|
|
dbgstr = "{} ({})".format(
|
|
|
|
signal.signal, ','.join([str(e) for e in args]))
|
2014-01-17 13:08:44 +01:00
|
|
|
if self.currentWidget() == self.sender():
|
2014-01-17 21:29:43 +01:00
|
|
|
logging.debug('{} - emitting'.format(dbgstr))
|
|
|
|
signal.emit(*args)
|
2014-01-17 20:29:20 +01:00
|
|
|
else:
|
2014-01-17 21:29:43 +01:00
|
|
|
logging.debug('{} - ignoring'.format(dbgstr))
|
2014-01-17 08:39:14 +01:00
|
|
|
|
2014-01-20 15:58:49 +01:00
|
|
|
def _currentChanged_handler(self, idx):
|
2014-01-17 13:16:13 +01:00
|
|
|
tab = self.widget(idx)
|
|
|
|
self.cur_progress.emit(tab.progress)
|
|
|
|
|
2013-12-15 21:40:15 +01:00
|
|
|
class BrowserTab(QWebView):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""One browser tab in TabbedBrowser"""
|
2014-01-17 13:16:13 +01:00
|
|
|
progress = 0
|
2014-01-17 12:24:38 +01:00
|
|
|
|
2013-12-15 21:40:15 +01:00
|
|
|
def __init__(self, parent):
|
|
|
|
super().__init__(parent)
|
2014-01-19 17:39:06 +01:00
|
|
|
frame = self.page().mainFrame()
|
|
|
|
frame.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
|
|
|
|
frame.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
|
2014-01-17 13:16:13 +01:00
|
|
|
self.loadProgress.connect(self.set_progress)
|
2013-12-15 21:40:15 +01:00
|
|
|
self.show()
|
|
|
|
|
|
|
|
def openurl(self, url):
|
2014-01-20 15:58:49 +01:00
|
|
|
"""Opens an URL in the browser"""
|
2013-12-15 21:40:15 +01:00
|
|
|
if not url.startswith('http://'):
|
|
|
|
url = 'http://' + url
|
2014-01-20 15:58:49 +01:00
|
|
|
self.load(QUrl(url))
|
2014-01-17 13:16:13 +01:00
|
|
|
|
|
|
|
def set_progress(self, prog):
|
|
|
|
self.progress = prog
|