Merge branch 'ninja'
This commit is contained in:
commit
d059c468af
3
.gitignore
vendored
3
.gitignore
vendored
@ -13,4 +13,5 @@ __pycache__
|
|||||||
.ropeproject
|
.ropeproject
|
||||||
# We can probably remove these later
|
# We can probably remove these later
|
||||||
*.asciidoc
|
*.asciidoc
|
||||||
*.html
|
/doc/*.html
|
||||||
|
/README.html
|
||||||
|
@ -74,6 +74,7 @@ The following software and libraries are required to run qutebrowser:
|
|||||||
(5.3.1 recommended) for Python 3
|
(5.3.1 recommended) for Python 3
|
||||||
* https://pypi.python.org/pypi/setuptools/[pkg_resources/setuptools]
|
* https://pypi.python.org/pypi/setuptools/[pkg_resources/setuptools]
|
||||||
* http://fdik.org/pyPEG/[pyPEG2]
|
* http://fdik.org/pyPEG/[pyPEG2]
|
||||||
|
* http://jinja.pocoo.org/[jinja2]
|
||||||
|
|
||||||
The following libraries are optional and provide colored logging in the
|
The following libraries are optional and provide colored logging in the
|
||||||
console:
|
console:
|
||||||
@ -85,7 +86,8 @@ On Debian
|
|||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
----
|
----
|
||||||
# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python3-pkg-resources python3-pip
|
# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python3-pkg-resources
|
||||||
|
python3-pip python3-jinja2
|
||||||
# pip3 install pypeg2 --allow-external pypeg2 --allow-unverified pypeg2
|
# pip3 install pypeg2 --allow-external pypeg2 --allow-unverified pypeg2
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -129,6 +131,7 @@ to get Qt and PyQt5.
|
|||||||
* Get pip as described http://stackoverflow.com/a/12476379[on Stack Overflow].
|
* Get pip as described http://stackoverflow.com/a/12476379[on Stack Overflow].
|
||||||
* Run +pip install --allow-external pypeg2 --allow-unverified pypeg2 pypeg2+ to
|
* Run +pip install --allow-external pypeg2 --allow-unverified pypeg2 pypeg2+ to
|
||||||
install pypeg2.
|
install pypeg2.
|
||||||
|
* Run +pip install jinja2+ to install jinja2.
|
||||||
|
|
||||||
As soon as v0.1 is out, a standalone .exe (built with
|
As soon as v0.1 is out, a standalone .exe (built with
|
||||||
http://cx-freeze.sourceforge.net/[cx_Freeze]) will be provided. In the
|
http://cx-freeze.sourceforge.net/[cx_Freeze]) will be provided. In the
|
||||||
|
@ -9,7 +9,7 @@ arch=(any)
|
|||||||
url="http://www.qutebrowser.org/"
|
url="http://www.qutebrowser.org/"
|
||||||
license=('GPL')
|
license=('GPL')
|
||||||
depends=('python>=3.4' 'python-setuptools' 'python-pyqt5>=5.2' 'qt5-base>=5.2'
|
depends=('python>=3.4' 'python-setuptools' 'python-pyqt5>=5.2' 'qt5-base>=5.2'
|
||||||
'qt5-webkit>=5.2' 'libxkbcommon-x11' 'python-pypeg2')
|
'qt5-webkit>=5.2' 'libxkbcommon-x11' 'python-pypeg2' 'python-jinja')
|
||||||
makedepends=('python' 'python-setuptools')
|
makedepends=('python' 'python-setuptools')
|
||||||
optdepends=('python-colorlog: colored logging output')
|
optdepends=('python-colorlog: colored logging output')
|
||||||
options=(!emptydirs)
|
options=(!emptydirs)
|
||||||
|
@ -394,7 +394,7 @@ class Application(QApplication):
|
|||||||
status.prompt.prompter.ask_question, Qt.DirectConnection)
|
status.prompt.prompter.ask_question, Qt.DirectConnection)
|
||||||
|
|
||||||
# config
|
# config
|
||||||
self.config.style_changed.connect(style.invalidate_caches)
|
self.config.style_changed.connect(style.get_stylesheet.cache_clear)
|
||||||
for obj in (tabs, completion, self.mainwindow, self.cmd_history,
|
for obj in (tabs, completion, self.mainwindow, self.cmd_history,
|
||||||
websettings, kp[utypes.KeyMode.normal], self.modeman,
|
websettings, kp[utypes.KeyMode.normal], self.modeman,
|
||||||
status, status.txt):
|
status, status.txt):
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
"""The main browser widgets."""
|
"""The main browser widgets."""
|
||||||
|
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
import sip
|
import sip
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt, QTimer
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, PYQT_VERSION, Qt
|
||||||
from PyQt5.QtNetwork import QNetworkReply
|
from PyQt5.QtNetwork import QNetworkReply
|
||||||
from PyQt5.QtWidgets import QFileDialog
|
from PyQt5.QtWidgets import QFileDialog
|
||||||
from PyQt5.QtPrintSupport import QPrintDialog
|
from PyQt5.QtPrintSupport import QPrintDialog
|
||||||
@ -30,7 +30,7 @@ from PyQt5.QtWebKitWidgets import QWebPage
|
|||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.network import networkmanager
|
from qutebrowser.network import networkmanager
|
||||||
from qutebrowser.utils import message, usertypes, log, http, utils, qtutils
|
from qutebrowser.utils import message, usertypes, log, http, jinja, qtutils
|
||||||
|
|
||||||
|
|
||||||
class BrowserPage(QWebPage):
|
class BrowserPage(QWebPage):
|
||||||
@ -118,7 +118,8 @@ class BrowserPage(QWebPage):
|
|||||||
log.webview.debug("Error domain: {}, error code: {}".format(
|
log.webview.debug("Error domain: {}, error code: {}".format(
|
||||||
info.domain, info.error))
|
info.domain, info.error))
|
||||||
title = "Error loading page: {}".format(urlstr)
|
title = "Error loading page: {}".format(urlstr)
|
||||||
errpage.content = utils.read_file('html/error.html').format(
|
template = jinja.env.get_template('error.html')
|
||||||
|
errpage.content = template.render( # pylint: disable=maybe-no-member
|
||||||
title=title, url=urlstr, error=info.errorString, icon='')
|
title=title, url=urlstr, error=info.errorString, icon='')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -197,8 +198,8 @@ class BrowserPage(QWebPage):
|
|||||||
if reply.isFinished():
|
if reply.isFinished():
|
||||||
self.display_content(reply, 'image/jpeg')
|
self.display_content(reply, 'image/jpeg')
|
||||||
else:
|
else:
|
||||||
reply.finished.connect(
|
reply.finished.connect(functools.partial(
|
||||||
partial(self.display_content, reply, 'image/jpeg'))
|
self.display_content, reply, 'image/jpeg'))
|
||||||
else:
|
else:
|
||||||
# Unknown mimetype, so download anyways.
|
# Unknown mimetype, so download anyways.
|
||||||
self.start_download.emit(reply)
|
self.start_download.emit(reply)
|
||||||
@ -240,19 +241,16 @@ class BrowserPage(QWebPage):
|
|||||||
log.webview.warning("Extension {} not supported!".format(ext))
|
log.webview.warning("Extension {} not supported!".format(ext))
|
||||||
return super().extension(ext, opt, out)
|
return super().extension(ext, opt, out)
|
||||||
return handler(opt, out)
|
return handler(opt, out)
|
||||||
except BaseException as e:
|
except: # pylint: disable=bare-except
|
||||||
# Due to a bug in PyQt, exceptions inside extension() get swallowed
|
# Due to a bug in PyQt, exceptions inside extension() get swallowed
|
||||||
# for some reason. Here we set up a single-shot QTimer to re-raise
|
# for some reason.
|
||||||
# them when we're back in the mainloop.
|
|
||||||
# http://www.riverbankcomputing.com/pipermail/pyqt/2014-August/034722.html
|
# http://www.riverbankcomputing.com/pipermail/pyqt/2014-August/034722.html
|
||||||
#
|
#
|
||||||
# Note we somehow can't re-raise with the correct traceback here.
|
# We used to re-raise the exception with a single-shot QTimer here,
|
||||||
# Using "raise from" or ".with_traceback()" just ignores the
|
# but that lead to a strange proble with a KeyError with some
|
||||||
# exception again.
|
# random jinja template stuff as content. For now, we only log it,
|
||||||
exc = e # needed for the closure
|
# so it doesn't pass 100% silently.
|
||||||
def raise_():
|
log.webview.exception("Error inside WebPage::extension")
|
||||||
raise exc
|
|
||||||
QTimer.singleShot(0, raise_)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def javaScriptAlert(self, _frame, msg):
|
def javaScriptAlert(self, _frame, msg):
|
||||||
|
@ -17,40 +17,31 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""Utilities related to the look&feel of qutebrowser.
|
"""Utilities related to the look&feel of qutebrowser."""
|
||||||
|
|
||||||
Module attributes:
|
|
||||||
_colordict: The global cached ColorDict.
|
|
||||||
_fontdict: The global cached FontDict.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
|
import jinja2
|
||||||
from PyQt5.QtGui import QColor
|
from PyQt5.QtGui import QColor
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils import log, utils
|
from qutebrowser.utils import log, utils
|
||||||
|
|
||||||
|
|
||||||
_colordict = None
|
@functools.lru_cache(maxsize=16)
|
||||||
_fontdict = None
|
def get_stylesheet(template_str):
|
||||||
|
|
||||||
|
|
||||||
def get_stylesheet(template):
|
|
||||||
"""Format a stylesheet based on a template.
|
"""Format a stylesheet based on a template.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
template: The stylesheet template as string.
|
template_str: The stylesheet template as string.
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
The formatted template as string.
|
The formatted template as string.
|
||||||
"""
|
"""
|
||||||
global _colordict, _fontdict
|
colordict = ColorDict(config.section('colors'))
|
||||||
if _colordict is None:
|
fontdict = FontDict(config.section('fonts'))
|
||||||
_colordict = ColorDict(config.section('colors'))
|
template = jinja2.Template(template_str)
|
||||||
if _fontdict is None:
|
return template.render(color=colordict, font=fontdict,
|
||||||
_fontdict = FontDict(config.section('fonts'))
|
|
||||||
return template.strip().format(color=_colordict, font=_fontdict,
|
|
||||||
config=config.instance())
|
config=config.instance())
|
||||||
|
|
||||||
|
|
||||||
@ -78,15 +69,6 @@ def _update_stylesheet(obj, _section, _option):
|
|||||||
obj.setStyleSheet(get_stylesheet(obj.STYLESHEET))
|
obj.setStyleSheet(get_stylesheet(obj.STYLESHEET))
|
||||||
|
|
||||||
|
|
||||||
def invalidate_caches(section, _option):
|
|
||||||
"""Invalidate cached dicts."""
|
|
||||||
global _colordict, _fontdict
|
|
||||||
if section == 'colors':
|
|
||||||
_colordict = None
|
|
||||||
elif section == 'fonts':
|
|
||||||
_fontdict = None
|
|
||||||
|
|
||||||
|
|
||||||
class ColorDict(dict):
|
class ColorDict(dict):
|
||||||
|
|
||||||
"""A dict aimed at Qt stylesheet colors."""
|
"""A dict aimed at Qt stylesheet colors."""
|
||||||
@ -123,20 +105,6 @@ class ColorDict(dict):
|
|||||||
else:
|
else:
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def getraw(self, key):
|
|
||||||
"""Get a value without the transformations done in __getitem__.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key: The key to get from the dict.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
A value, or None if the value wasn't found.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return super().__getitem__(key)
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class FontDict(dict):
|
class FontDict(dict):
|
||||||
|
|
||||||
@ -160,17 +128,3 @@ class FontDict(dict):
|
|||||||
return ''
|
return ''
|
||||||
else:
|
else:
|
||||||
return 'font: {};'.format(val)
|
return 'font: {};'.format(val)
|
||||||
|
|
||||||
def getraw(self, key):
|
|
||||||
"""Get a value without the transformations done in __getitem__.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key: The key to get from the dict.
|
|
||||||
|
|
||||||
Return:
|
|
||||||
A value, or None if the value wasn't found.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return super().__getitem__(key)
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
31
qutebrowser/html/base.html
Normal file
31
qutebrowser/html/base.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
vim: ft=html fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
{% if icon %}
|
||||||
|
<link rel='icon' type='image/png' href="{{ icon }}">
|
||||||
|
{% endif %}
|
||||||
|
<style type="text/css">
|
||||||
|
{% block style %}
|
||||||
|
body {
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
{% endblock %}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
{% block script %}
|
||||||
|
{% endblock %}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,22 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<!--
|
{% block style %}
|
||||||
vim: ft=html fileencoding=utf-8 sts=4 sw=4 et:
|
{{ super() }}
|
||||||
Based on html/error.html from dwb
|
#errorContainer {
|
||||||
-->
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>{title}</title>
|
|
||||||
<!--<link rel='icon' type='image/png' href="{icon}">-->
|
|
||||||
<style type="text/css">
|
|
||||||
body {{
|
|
||||||
background-color: #fff;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}}
|
|
||||||
|
|
||||||
#errorContainer {{
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
min-width: 35em;
|
min-width: 35em;
|
||||||
max-width: 35em;
|
max-width: 35em;
|
||||||
@ -26,35 +11,37 @@ Based on html/error.html from dwb
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 2px solid #eee;
|
border: 2px solid #eee;
|
||||||
-webkit-border-radius: 5px;
|
-webkit-border-radius: 5px;
|
||||||
}}
|
}
|
||||||
|
|
||||||
#errorTitleText {{
|
#errorTitleText {
|
||||||
font-size: 118%;
|
font-size: 118%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}}
|
}
|
||||||
|
|
||||||
#errorMessageText {{
|
#errorMessageText {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}}
|
}
|
||||||
</style>
|
{% endblock %}
|
||||||
<script type="text/javascript">
|
|
||||||
|
{% block script %}
|
||||||
|
{{ super() }}
|
||||||
function tryagain()
|
function tryagain()
|
||||||
{{
|
{
|
||||||
location.reload();
|
location.reload();
|
||||||
}}
|
}
|
||||||
function searchFor(uri) {{
|
function searchFor(uri) {
|
||||||
location.href = uri;
|
location.href = uri;
|
||||||
}}
|
}
|
||||||
</script>
|
{% endblock %}
|
||||||
</head>
|
|
||||||
<body>
|
{% block content %}
|
||||||
<div id="errorContainer">
|
<div id="errorContainer">
|
||||||
<div id="errorTitle">
|
<div id="errorTitle">
|
||||||
<p id="errorTitleText">Unable to load page</p>
|
<p id="errorTitleText">Unable to load page</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="errorMessage">
|
<div id="errorMessage">
|
||||||
<p>Problem occurred while loading the URL {url}</p>
|
<p>Problem occurred while loading the URL {{ url }}</p>
|
||||||
<p id="errorMessageText">{error}</p>
|
<p id="errorMessageText">{{ error }}</p>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -63,5 +50,4 @@ Based on html/error.html from dwb
|
|||||||
<!--<input type="button" value="Search" style="visibility:%s" onclick="javascript:searchFor('%s')" />-->
|
<!--<input type="button" value="Search" style="visibility:%s" onclick="javascript:searchFor('%s')" />-->
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
{% endblock %}
|
||||||
</html>
|
|
||||||
|
35
qutebrowser/html/log.html
Normal file
35
qutebrowser/html/log.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block style %}
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px solid grey;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid grey;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{{ super() }}
|
||||||
|
{% if content %}
|
||||||
|
<table>
|
||||||
|
{{ content | safe() }}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<p>Log output was disabled.</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
7
qutebrowser/html/pre.html
Normal file
7
qutebrowser/html/pre.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{{ super() }}
|
||||||
|
<pre>
|
||||||
|
{{ content }}
|
||||||
|
</pre>
|
||||||
|
{% endblock %}
|
26
qutebrowser/html/version.html
Normal file
26
qutebrowser/html/version.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{{ super() }}
|
||||||
|
<h1>Version info</h1>
|
||||||
|
<pre>{{ version }}</pre>
|
||||||
|
|
||||||
|
<h1>Copyright info</h1>
|
||||||
|
<p>{{ copyright }}</p>
|
||||||
|
<p>
|
||||||
|
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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <a href="http://www.gnu.org/licenses/">
|
||||||
|
http://www.gnu.org/licenses/</a> or open <a href="qute:gpl">qute:gpl</a>.
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
@ -16,60 +16,28 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# pylint complains when using .render() on jinja templates, so we make it shut
|
||||||
|
# up for this whole module.
|
||||||
|
# pylint: disable=maybe-no-member
|
||||||
|
|
||||||
"""Handler functions for different qute:... pages.
|
"""Handler functions for different qute:... pages.
|
||||||
|
|
||||||
Module attributes:
|
Module attributes:
|
||||||
_HTML_TEMPLATE: The HTML boilerplate used to convert text into html.
|
|
||||||
pyeval_output: The output of the last :pyeval command.
|
pyeval_output: The output of the last :pyeval command.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import html as pyhtml
|
|
||||||
|
|
||||||
from PyQt5.QtNetwork import QNetworkReply
|
from PyQt5.QtNetwork import QNetworkReply
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
from qutebrowser.network import schemehandler
|
from qutebrowser.network import schemehandler
|
||||||
from qutebrowser.utils import version, utils
|
from qutebrowser.utils import version, utils, jinja
|
||||||
from qutebrowser.utils import log as logutils
|
from qutebrowser.utils import log as logutils
|
||||||
|
|
||||||
|
|
||||||
_HTML_TEMPLATE = """
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>{title}</title>
|
|
||||||
{head}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{body}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
pyeval_output = ":pyeval was never called"
|
pyeval_output = ":pyeval was never called"
|
||||||
|
|
||||||
|
|
||||||
def _get_html(title, snippet, head=None):
|
|
||||||
"""Add HTML boilerplate to a html snippet.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
title: The title the page should have.
|
|
||||||
snippet: The html snippet.
|
|
||||||
head: Additional stuff to put in <head>
|
|
||||||
|
|
||||||
Return:
|
|
||||||
HTML content as bytes.
|
|
||||||
"""
|
|
||||||
if head is None:
|
|
||||||
head = ""
|
|
||||||
html = _HTML_TEMPLATE.format(title=title, body=snippet, head=head).encode(
|
|
||||||
'UTF-8', errors='xmlcharrefreplace')
|
|
||||||
return html
|
|
||||||
|
|
||||||
|
|
||||||
class QuteSchemeHandler(schemehandler.SchemeHandler):
|
class QuteSchemeHandler(schemehandler.SchemeHandler):
|
||||||
|
|
||||||
"""Scheme handler for qute: URLs."""
|
"""Scheme handler for qute: URLs."""
|
||||||
@ -110,61 +78,39 @@ class QuteHandlers:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def pyeval(cls):
|
def pyeval(cls):
|
||||||
"""Handler for qute:pyeval. Return HTML content as bytes."""
|
"""Handler for qute:pyeval. Return HTML content as bytes."""
|
||||||
text = pyhtml.escape(pyeval_output)
|
html = jinja.env.get_template('pre.html').render(
|
||||||
return _get_html('pyeval', '<pre>{}</pre>'.format(text))
|
title='pyeval', content=pyeval_output)
|
||||||
|
return html.encode('UTF-8', errors='xmlcharrefreplace')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def version(cls):
|
def version(cls):
|
||||||
"""Handler for qute:version. Return HTML content as bytes."""
|
"""Handler for qute:version. Return HTML content as bytes."""
|
||||||
text = pyhtml.escape(version.version())
|
html = jinja.env.get_template('version.html').render(
|
||||||
html = '<h1>Version info</h1>'
|
title='Version info', version=version.version(),
|
||||||
html += '<p>{}</p>'.format(text.replace('\n', '<br/>'))
|
copyright=qutebrowser.__copyright__)
|
||||||
html += '<h1>Copyright info</h1>'
|
return html.encode('UTF-8', errors='xmlcharrefreplace')
|
||||||
html += '<p>{}</p>'.format(qutebrowser.__copyright__)
|
|
||||||
html += version.GPL_BOILERPLATE_HTML
|
|
||||||
return _get_html('Version', html)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def plainlog(cls):
|
def plainlog(cls):
|
||||||
"""Handler for qute:log. Return HTML content as bytes."""
|
"""Handler for qute:plainlog. Return HTML content as bytes."""
|
||||||
if logutils.ram_handler is None:
|
if logutils.ram_handler is None:
|
||||||
text = "Log output was disabled."
|
text = "Log output was disabled."
|
||||||
else:
|
else:
|
||||||
text = pyhtml.escape(logutils.ram_handler.dump_log())
|
text = logutils.ram_handler.dump_log()
|
||||||
return _get_html('log', '<pre>{}</pre>'.format(text))
|
html = jinja.env.get_template('pre.html').render(
|
||||||
|
title='log', content=text)
|
||||||
|
return html.encode('UTF-8', errors='xmlcharrefreplace')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def log(cls):
|
def log(cls):
|
||||||
"""Handler for qute:log. Return HTML content as bytes."""
|
"""Handler for qute:log. Return HTML content as bytes."""
|
||||||
style = """
|
|
||||||
<style type="text/css">
|
|
||||||
body {
|
|
||||||
background-color: black;
|
|
||||||
color: white;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
border: 1px solid grey;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
th, td {
|
|
||||||
border: 1px solid grey;
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
"""
|
|
||||||
if logutils.ram_handler is None:
|
if logutils.ram_handler is None:
|
||||||
html = "<p>Log output was disabled.</p>"
|
html_log = None
|
||||||
else:
|
else:
|
||||||
html = logutils.ram_handler.dump_log(html=True)
|
html_log = logutils.ram_handler.dump_log(html=True)
|
||||||
return _get_html('log', html, head=style)
|
html = jinja.env.get_template('log.html').render(
|
||||||
|
title='log', content=html_log)
|
||||||
|
return html.encode('UTF-8', errors='xmlcharrefreplace')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def gpl(cls):
|
def gpl(cls):
|
||||||
|
@ -112,6 +112,7 @@ def main():
|
|||||||
earlyinit.check_pyqt_webkit()
|
earlyinit.check_pyqt_webkit()
|
||||||
earlyinit.check_pkg_resources()
|
earlyinit.check_pkg_resources()
|
||||||
earlyinit.check_pypeg2()
|
earlyinit.check_pypeg2()
|
||||||
|
earlyinit.check_jinja2()
|
||||||
# We do this import late as we need to fix harfbuzz first.
|
# We do this import late as we need to fix harfbuzz first.
|
||||||
from qutebrowser import app
|
from qutebrowser import app
|
||||||
from qutebrowser.utils import debug
|
from qutebrowser.utils import debug
|
||||||
|
@ -29,7 +29,7 @@ from PyQt5.QtCore import pyqtRemoveInputHook, QEvent, QCoreApplication
|
|||||||
|
|
||||||
from qutebrowser.utils import log, utils
|
from qutebrowser.utils import log, utils
|
||||||
from qutebrowser.commands import cmdutils
|
from qutebrowser.commands import cmdutils
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config, style
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register(debug=True, name='debug-set-trace')
|
@cmdutils.register(debug=True, name='debug-set-trace')
|
||||||
@ -87,9 +87,11 @@ def debug_all_objects():
|
|||||||
|
|
||||||
@cmdutils.register(debug=True)
|
@cmdutils.register(debug=True)
|
||||||
def debug_cache_stats():
|
def debug_cache_stats():
|
||||||
"""Print config LRU cache stats."""
|
"""Print LRU cache stats."""
|
||||||
info = config.instance().get.cache_info()
|
config_info = config.instance().get.cache_info()
|
||||||
log.misc.debug(info)
|
style_info = style.get_stylesheet.cache_info()
|
||||||
|
log.misc.debug('config: {}'.format(config_info))
|
||||||
|
log.misc.debug('style: {}'.format(style_info))
|
||||||
|
|
||||||
|
|
||||||
def log_events(klass):
|
def log_events(klass):
|
||||||
|
@ -248,3 +248,17 @@ def check_pypeg2():
|
|||||||
pip="pypeg2 --allow-external pypeg2 "
|
pip="pypeg2 --allow-external pypeg2 "
|
||||||
"--allow-unverified pypeg2")
|
"--allow-unverified pypeg2")
|
||||||
_die(text)
|
_die(text)
|
||||||
|
|
||||||
|
|
||||||
|
def check_jinja2():
|
||||||
|
"""Check if jinja2 is installed."""
|
||||||
|
try:
|
||||||
|
import jinja2 # pylint: disable=unused-variable
|
||||||
|
except ImportError:
|
||||||
|
text = _missing_str("jinja2",
|
||||||
|
debian="apt-get install python3-jinja2",
|
||||||
|
arch="Install python-jinja from the AUR",
|
||||||
|
windows="Install from http://www.lfd.uci.edu/"
|
||||||
|
"~gohlke/pythonlibs/#jinja2 or via pip.",
|
||||||
|
pip="jinja2")
|
||||||
|
_die(text)
|
||||||
|
58
qutebrowser/utils/jinja.py
Normal file
58
qutebrowser/utils/jinja.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
|
||||||
|
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
"""Utilities related to jinja2. """
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
import jinja2
|
||||||
|
|
||||||
|
from qutebrowser.utils import utils
|
||||||
|
|
||||||
|
|
||||||
|
class Loader(jinja2.BaseLoader):
|
||||||
|
|
||||||
|
"""Jinja loader which uses utils.read_file to load templates."""
|
||||||
|
|
||||||
|
def __init__(self, subdir):
|
||||||
|
self.subdir = subdir
|
||||||
|
|
||||||
|
def get_source(self, _env, template):
|
||||||
|
path = os.path.join(self.subdir, template)
|
||||||
|
try:
|
||||||
|
source = utils.read_file(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise jinja2.TemplateNotFound(template)
|
||||||
|
# Currently we don't implement auto-reloading, so we always return True
|
||||||
|
# for up-to-date.
|
||||||
|
return source, path, lambda: True
|
||||||
|
|
||||||
|
|
||||||
|
def _guess_autoescape(template_name):
|
||||||
|
"""Turns autoescape on/off based on the filetype.
|
||||||
|
|
||||||
|
Based on http://jinja.pocoo.org/docs/dev/api/#autoescaping
|
||||||
|
"""
|
||||||
|
if template_name is None or '.' not in template_name:
|
||||||
|
return False
|
||||||
|
ext = template_name.rsplit('.', 1)[1]
|
||||||
|
return ext in ('html', 'htm', 'xml')
|
||||||
|
|
||||||
|
|
||||||
|
env = jinja2.Environment(loader=Loader('html'), autoescape=_guess_autoescape)
|
@ -341,13 +341,12 @@ class RAMHandler(logging.Handler):
|
|||||||
self.data.append(record)
|
self.data.append(record)
|
||||||
|
|
||||||
def dump_log(self, html=False):
|
def dump_log(self, html=False):
|
||||||
"""Dump the complete formatted log data as as string."""
|
"""Dump the complete formatted log data as as string.
|
||||||
if html:
|
|
||||||
fmt = self.html_formatter.format
|
FIXME: We should do all the HTML formatter via jinja2.
|
||||||
lines = ['<table>']
|
"""
|
||||||
else:
|
|
||||||
fmt = self.format
|
|
||||||
lines = []
|
lines = []
|
||||||
|
fmt = self.html_formatter.format if html else self.format
|
||||||
self.acquire()
|
self.acquire()
|
||||||
try:
|
try:
|
||||||
records = list(self.data)
|
records = list(self.data)
|
||||||
@ -355,8 +354,6 @@ class RAMHandler(logging.Handler):
|
|||||||
self.release()
|
self.release()
|
||||||
for record in records:
|
for record in records:
|
||||||
lines.append(fmt(record))
|
lines.append(fmt(record))
|
||||||
if html:
|
|
||||||
lines.append('</table>')
|
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,25 +48,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/> or use
|
|||||||
:open qute:gpl.
|
:open qute:gpl.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
GPL_BOILERPLATE_HTML = """
|
|
||||||
<p>
|
|
||||||
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 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <a href="http://www.gnu.org/licenses/">
|
|
||||||
http://www.gnu.org/licenses/</a> or open <a href="qute:gpl">qute:gpl</a>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def _git_str():
|
def _git_str():
|
||||||
"""Try to find out git version.
|
"""Try to find out git version.
|
||||||
@ -179,6 +160,13 @@ def _module_versions():
|
|||||||
else:
|
else:
|
||||||
ver = getattr(pypeg2, '__version__', 'yes')
|
ver = getattr(pypeg2, '__version__', 'yes')
|
||||||
lines.append('pypeg2: {}'.format(ver))
|
lines.append('pypeg2: {}'.format(ver))
|
||||||
|
try:
|
||||||
|
import jinja2
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
ver = getattr(jinja2, '__version__', 'yes')
|
||||||
|
lines.append('jinja2: {}'.format(ver))
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ class CompletionView(QTreeView):
|
|||||||
Highlights completions based on marks in the Role.marks data.
|
Highlights completions based on marks in the Role.marks data.
|
||||||
|
|
||||||
Class attributes:
|
Class attributes:
|
||||||
STYLESHEET: The stylesheet template for the CompletionView.
|
|
||||||
COLUMN_WIDTHS: A list of column widths, in percent.
|
COLUMN_WIDTHS: A list of column widths, in percent.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
@ -59,29 +58,31 @@ class CompletionView(QTreeView):
|
|||||||
# Drawing the item foreground will be done by CompletionItemDelegate, so we
|
# Drawing the item foreground will be done by CompletionItemDelegate, so we
|
||||||
# don't define that in this stylesheet.
|
# don't define that in this stylesheet.
|
||||||
STYLESHEET = """
|
STYLESHEET = """
|
||||||
QTreeView {{
|
QTreeView {
|
||||||
{font[completion]}
|
{{ font['completion'] }}
|
||||||
{color[completion.bg]}
|
{{ color['completion.bg'] }}
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}}
|
}
|
||||||
|
|
||||||
QTreeView::item:disabled {{
|
QTreeView::item:disabled {
|
||||||
{color[completion.category.bg]}
|
{{ color['completion.category.bg'] }}
|
||||||
border-top: 1px solid {color[completion.category.border.top]};
|
border-top: 1px solid
|
||||||
|
{{ color['completion.category.border.top'] }};
|
||||||
border-bottom: 1px solid
|
border-bottom: 1px solid
|
||||||
{color[completion.category.border.bottom]};
|
{{ color['completion.category.border.bottom'] }};
|
||||||
}}
|
}
|
||||||
|
|
||||||
QTreeView::item:selected, QTreeView::item:selected:hover {{
|
QTreeView::item:selected, QTreeView::item:selected:hover {
|
||||||
border-top: 1px solid {color[completion.item.selected.border.top]};
|
border-top: 1px solid
|
||||||
|
{{ color['completion.item.selected.border.top'] }};
|
||||||
border-bottom: 1px solid
|
border-bottom: 1px solid
|
||||||
{color[completion.item.selected.border.bottom]};
|
{{ color['completion.item.selected.border.bottom'] }};
|
||||||
{color[completion.item.selected.bg]}
|
{{ color['completion.item.selected.bg'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QTreeView:item::hover {{
|
QTreeView:item::hover {
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}}
|
}
|
||||||
"""
|
"""
|
||||||
COLUMN_WIDTHS = (20, 70, 10)
|
COLUMN_WIDTHS = (20, 70, 10)
|
||||||
|
|
||||||
|
@ -189,9 +189,9 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
self._doc.setDefaultFont(self._opt.font)
|
self._doc.setDefaultFont(self._opt.font)
|
||||||
self._doc.setDefaultTextOption(text_option)
|
self._doc.setDefaultTextOption(text_option)
|
||||||
self._doc.setDefaultStyleSheet(style.get_stylesheet("""
|
self._doc.setDefaultStyleSheet(style.get_stylesheet("""
|
||||||
.highlight {{
|
.highlight {
|
||||||
{color[completion.match.fg]}
|
{{ color['completion.match.fg'] }}
|
||||||
}}
|
}
|
||||||
"""))
|
"""))
|
||||||
self._doc.setDocumentMargin(2)
|
self._doc.setDocumentMargin(2)
|
||||||
|
|
||||||
|
@ -37,14 +37,14 @@ class DownloadView(QListView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
STYLESHEET = """
|
STYLESHEET = """
|
||||||
QListView {{
|
QListView {
|
||||||
{color[downloads.bg.bar]}
|
{{ color['downloads.bg.bar'] }}
|
||||||
{font[downloads]}
|
{{ font['downloads'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QListView::item {{
|
QListView::item {
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
}}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@ -40,9 +40,6 @@ class StatusBar(QWidget):
|
|||||||
|
|
||||||
"""The statusbar at the bottom of the mainwindow.
|
"""The statusbar at the bottom of the mainwindow.
|
||||||
|
|
||||||
Class attributes:
|
|
||||||
STYLESHEET: The stylesheet template.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
cmd: The Command widget in the statusbar.
|
cmd: The Command widget in the statusbar.
|
||||||
txt: The Text widget in the statusbar.
|
txt: The Text widget in the statusbar.
|
||||||
@ -96,26 +93,26 @@ class StatusBar(QWidget):
|
|||||||
_insert_active = False
|
_insert_active = False
|
||||||
|
|
||||||
STYLESHEET = """
|
STYLESHEET = """
|
||||||
QWidget#StatusBar {{
|
QWidget#StatusBar {
|
||||||
{color[statusbar.bg]}
|
{{ color['statusbar.bg'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QWidget#StatusBar[insert_active="true"] {{
|
QWidget#StatusBar[insert_active="true"] {
|
||||||
{color[statusbar.bg.insert]}
|
{{ color['statusbar.bg.insert'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QWidget#StatusBar[prompt_active="true"] {{
|
QWidget#StatusBar[prompt_active="true"] {
|
||||||
{color[statusbar.bg.prompt]}
|
{{ color['statusbar.bg.prompt'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QWidget#StatusBar[error="true"] {{
|
QWidget#StatusBar[error="true"] {
|
||||||
{color[statusbar.bg.error]}
|
{{ color['statusbar.bg.error'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QWidget {{
|
QWidget {
|
||||||
{color[statusbar.fg]}
|
{{ color['statusbar.fg'] }}
|
||||||
{font[statusbar]}
|
{{ font['statusbar'] }}
|
||||||
}}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@ -28,24 +28,20 @@ from qutebrowser.config import style
|
|||||||
|
|
||||||
class Progress(QProgressBar):
|
class Progress(QProgressBar):
|
||||||
|
|
||||||
"""The progress bar part of the status bar.
|
"""The progress bar part of the status bar."""
|
||||||
|
|
||||||
Class attributes:
|
|
||||||
STYLESHEET: The stylesheet template.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# FIXME for some reason, margin-left is not shown
|
# FIXME for some reason, margin-left is not shown
|
||||||
STYLESHEET = """
|
STYLESHEET = """
|
||||||
QProgressBar {{
|
QProgressBar {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}}
|
}
|
||||||
|
|
||||||
QProgressBar::chunk {{
|
QProgressBar::chunk {
|
||||||
{color[statusbar.progress.bg]}
|
{{ color['statusbar.progress.bg'] }}
|
||||||
}}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@ -36,9 +36,6 @@ class UrlText(textbase.TextBase):
|
|||||||
|
|
||||||
"""URL displayed in the statusbar.
|
"""URL displayed in the statusbar.
|
||||||
|
|
||||||
Class attributes:
|
|
||||||
STYLESHEET: The stylesheet template.
|
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
normal_url: The normal URL to be displayed as a UrlType instance.
|
normal_url: The normal URL to be displayed as a UrlType instance.
|
||||||
normal_url_type: The type of the normal URL as a UrlType instance.
|
normal_url_type: The type of the normal URL as a UrlType instance.
|
||||||
@ -56,25 +53,25 @@ class UrlText(textbase.TextBase):
|
|||||||
_urltype = None
|
_urltype = None
|
||||||
|
|
||||||
STYLESHEET = """
|
STYLESHEET = """
|
||||||
QLabel#UrlText[urltype="normal"] {{
|
QLabel#UrlText[urltype="normal"] {
|
||||||
{color[statusbar.url.fg]}
|
{{ color['statusbar.url.fg'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QLabel#UrlText[urltype="success"] {{
|
QLabel#UrlText[urltype="success"] {
|
||||||
{color[statusbar.url.fg.success]}
|
{{ color['statusbar.url.fg.success'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QLabel#UrlText[urltype="error"] {{
|
QLabel#UrlText[urltype="error"] {
|
||||||
{color[statusbar.url.fg.error]}
|
{{ color['statusbar.url.fg.error'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QLabel#UrlText[urltype="warn"] {{
|
QLabel#UrlText[urltype="warn"] {
|
||||||
{color[statusbar.url.fg.warn]}
|
{{ color['statusbar.url.fg.warn'] }}
|
||||||
}}
|
}
|
||||||
|
|
||||||
QLabel#UrlText[urltype="hover"] {{
|
QLabel#UrlText[urltype="hover"] {
|
||||||
{color[statusbar.url.fg.hover]}
|
{{ color['statusbar.url.fg.hover'] }}
|
||||||
}}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@ -98,7 +98,7 @@ setupdata = {
|
|||||||
'description': _get_constant('description'),
|
'description': _get_constant('description'),
|
||||||
'long_description': read_file('README.asciidoc'),
|
'long_description': read_file('README.asciidoc'),
|
||||||
'url': 'http://www.qutebrowser.org/',
|
'url': 'http://www.qutebrowser.org/',
|
||||||
'requires': ['pypeg2'],
|
'requires': ['pypeg2', 'jinja2'],
|
||||||
'author': _get_constant('author'),
|
'author': _get_constant('author'),
|
||||||
'author_email': _get_constant('email'),
|
'author_email': _get_constant('email'),
|
||||||
'license': _get_constant('license'),
|
'license': _get_constant('license'),
|
||||||
|
2
setup.py
2
setup.py
@ -47,7 +47,7 @@ try:
|
|||||||
['qutebrowser = qutebrowser.qutebrowser:main']},
|
['qutebrowser = qutebrowser.qutebrowser:main']},
|
||||||
test_suite='qutebrowser.test',
|
test_suite='qutebrowser.test',
|
||||||
zip_safe=True,
|
zip_safe=True,
|
||||||
install_requires=['pypeg2'],
|
install_requires=['pypeg2', 'jinja2'],
|
||||||
extras_require={'nice-debugging': ['colorlog', 'colorama'],
|
extras_require={'nice-debugging': ['colorlog', 'colorama'],
|
||||||
'checks': ['flake8', 'pylint', 'check-manifest',
|
'checks': ['flake8', 'pylint', 'check-manifest',
|
||||||
'pyroma']},
|
'pyroma']},
|
||||||
|
Loading…
Reference in New Issue
Block a user