Make colors configurable
This commit is contained in:
parent
429d4a6814
commit
9bf7dd2bbb
2
TODO
2
TODO
@ -25,7 +25,7 @@ IPC, like dwb -x
|
|||||||
Mode handling?
|
Mode handling?
|
||||||
Bookmarks
|
Bookmarks
|
||||||
sensible crash handling (exceptions, segfaults [windows?])
|
sensible crash handling (exceptions, segfaults [windows?])
|
||||||
more configuration (colors, hide completion)
|
more configuration (hide completion)
|
||||||
|
|
||||||
Minor features/bugs
|
Minor features/bugs
|
||||||
===================
|
===================
|
||||||
|
@ -7,9 +7,9 @@ from PyQt5.QtWidgets import QApplication
|
|||||||
from PyQt5.QtCore import QUrl, QTimer
|
from PyQt5.QtCore import QUrl, QTimer
|
||||||
|
|
||||||
import qutebrowser.commands.utils as cmdutils
|
import qutebrowser.commands.utils as cmdutils
|
||||||
|
import qutebrowser.utils.config as config
|
||||||
from qutebrowser.widgets.mainwindow import MainWindow
|
from qutebrowser.widgets.mainwindow import MainWindow
|
||||||
from qutebrowser.commands.keys import KeyParser
|
from qutebrowser.commands.keys import KeyParser
|
||||||
from qutebrowser.utils.config import Config
|
|
||||||
from qutebrowser.utils.appdirs import AppDirs
|
from qutebrowser.utils.appdirs import AppDirs
|
||||||
|
|
||||||
class QuteBrowser(QApplication):
|
class QuteBrowser(QApplication):
|
||||||
@ -35,14 +35,14 @@ class QuteBrowser(QApplication):
|
|||||||
confdir = None
|
confdir = None
|
||||||
else:
|
else:
|
||||||
confdir = self.args.confdir
|
confdir = self.args.confdir
|
||||||
self.config = Config(confdir)
|
config.init(confdir)
|
||||||
|
|
||||||
self.commandparser = cmdutils.CommandParser()
|
self.commandparser = cmdutils.CommandParser()
|
||||||
self.keyparser = KeyParser(self.mainwindow)
|
self.keyparser = KeyParser(self.mainwindow)
|
||||||
self.init_cmds()
|
self.init_cmds()
|
||||||
self.mainwindow = MainWindow()
|
self.mainwindow = MainWindow()
|
||||||
|
|
||||||
self.aboutToQuit.connect(self.config.save)
|
self.aboutToQuit.connect(config.config.save)
|
||||||
self.mainwindow.tabs.keypress.connect(self.keyparser.handle)
|
self.mainwindow.tabs.keypress.connect(self.keyparser.handle)
|
||||||
self.keyparser.set_cmd_text.connect(self.mainwindow.status.cmd.set_cmd)
|
self.keyparser.set_cmd_text.connect(self.mainwindow.status.cmd.set_cmd)
|
||||||
self.mainwindow.status.cmd.got_cmd.connect(self.commandparser.run)
|
self.mainwindow.status.cmd.got_cmd.connect(self.commandparser.run)
|
||||||
@ -104,7 +104,7 @@ class QuteBrowser(QApplication):
|
|||||||
for cmd in cmdutils.cmd_dict.values():
|
for cmd in cmdutils.cmd_dict.values():
|
||||||
cmd.signal.connect(self.cmd_handler)
|
cmd.signal.connect(self.cmd_handler)
|
||||||
try:
|
try:
|
||||||
self.keyparser.from_config_sect(self.config['keybind'])
|
self.keyparser.from_config_sect(config.config['keybind'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ import logging
|
|||||||
|
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
|
config = None
|
||||||
|
colordict = {}
|
||||||
|
|
||||||
default_config = {
|
default_config = {
|
||||||
'keybind': {
|
'keybind': {
|
||||||
'o': 'open',
|
'o': 'open',
|
||||||
@ -21,9 +24,61 @@ default_config = {
|
|||||||
'u': 'undo',
|
'u': 'undo',
|
||||||
'gg': 'scroll_perc_y 0',
|
'gg': 'scroll_perc_y 0',
|
||||||
'G': 'scroll_perc_y',
|
'G': 'scroll_perc_y',
|
||||||
}
|
},
|
||||||
|
'colors': {
|
||||||
|
'completion.fg': '#333333',
|
||||||
|
'completion.item.bg': 'white',
|
||||||
|
'completion.category.bg': 'qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #e4e4e4, stop:1 #dbdbdb)',
|
||||||
|
'completion.category.border.top': '#808080',
|
||||||
|
'completion.category.border.bottom': '#bbbbbb',
|
||||||
|
'completion.item.selected.fg': '#333333',
|
||||||
|
'completion.item.selected.bg': '#ffec8b',
|
||||||
|
'completion.item.selected.border.top': '#f2f2c0',
|
||||||
|
'completion.item.selected.border.bottom': '#e6e680',
|
||||||
|
'completion.match.fg': 'red',
|
||||||
|
'statusbar.progress.bg': 'white',
|
||||||
|
'statusbar.progress.bg.error': 'red',
|
||||||
|
'statusbar.bg': 'black',
|
||||||
|
'statusbar.fg': 'white',
|
||||||
|
'statusbar.bg.error': 'red',
|
||||||
|
'tab.bg': 'grey',
|
||||||
|
'tab.bg.selected': 'black',
|
||||||
|
'tab.fg': 'white',
|
||||||
|
'tab.seperator': 'white',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def init(confdir):
|
||||||
|
global config, colordict
|
||||||
|
config = Config(confdir)
|
||||||
|
try:
|
||||||
|
colordict = ColorDict(config['colors'])
|
||||||
|
except KeyError:
|
||||||
|
colordict = ColorDict()
|
||||||
|
|
||||||
|
def get_stylesheet(template):
|
||||||
|
global colordict
|
||||||
|
return template.strip().format(color=colordict)
|
||||||
|
|
||||||
|
class ColorDict(dict):
|
||||||
|
def __getitem__(self, key):
|
||||||
|
try:
|
||||||
|
val = super().__getitem__(key)
|
||||||
|
except KeyError:
|
||||||
|
return ''
|
||||||
|
if 'fg' in key.split('.'):
|
||||||
|
return 'color: {};'.format(val)
|
||||||
|
elif 'bg' in key.split('.'):
|
||||||
|
return 'background-color: {};'.format(val)
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
|
def getraw(self, key):
|
||||||
|
try:
|
||||||
|
return super().__getitem__(key)
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
class Config(ConfigParser):
|
class Config(ConfigParser):
|
||||||
"""Our own ConfigParser"""
|
"""Our own ConfigParser"""
|
||||||
configdir = None
|
configdir = None
|
||||||
|
@ -8,33 +8,35 @@ from PyQt5.QtCore import (QRectF, QRect, QPoint, pyqtSignal, Qt,
|
|||||||
from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
|
from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
|
||||||
QTextCursor)
|
QTextCursor)
|
||||||
|
|
||||||
|
import qutebrowser.utils.config as config
|
||||||
from qutebrowser.utils.completion import CompletionFilterModel
|
from qutebrowser.utils.completion import CompletionFilterModel
|
||||||
from qutebrowser.commands.utils import CommandCompletionModel
|
from qutebrowser.commands.utils import CommandCompletionModel
|
||||||
|
|
||||||
class CompletionView(QTreeView):
|
class CompletionView(QTreeView):
|
||||||
_stylesheet = """
|
_stylesheet = """
|
||||||
QTreeView {
|
QTreeView {{
|
||||||
font-family: Monospace, Courier;
|
font-family: Monospace, Courier;
|
||||||
color: #333333;
|
{color[completion.fg]}
|
||||||
|
{color[completion.bg]}
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}}
|
||||||
QTreeView::item {
|
QTreeView::item {{
|
||||||
background: white;
|
{color[completion.item.fg]}
|
||||||
}
|
{color[completion.item.bg]}
|
||||||
QTreeView::item:has-children {
|
}}
|
||||||
|
QTreeView::item:has-children {{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
{color[completion.category.fg]}
|
||||||
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #e4e4e4,
|
{color[completion.category.bg]}
|
||||||
stop:1 #dbdbdb);
|
border-top: 1px solid {color[completion.category.border.top]};
|
||||||
border-top: 1px solid #808080;
|
border-bottom: 1px solid {color[completion.category.border.bottom]};
|
||||||
border-bottom: 1px solid #bbbbbb;
|
}}
|
||||||
}
|
QTreeView::item:selected {{
|
||||||
QTreeView::item:selected {
|
border-top: 1px solid {color[completon.item.selected.border.top]};
|
||||||
border-top: 1px solid #f2f2c0;
|
border-bottom: 1px solid {color[completion.item.selected.border.bottom]};
|
||||||
border-bottom: 1px solid #e6e680;
|
background-color: {color[completion.item.selected.bg]};
|
||||||
background-color: #ffec8b;
|
{color[completion.item.selected.fg]}
|
||||||
color: #333333;
|
}}
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
# FIXME because we use :has-children, if a category is empty, it won't look
|
# FIXME because we use :has-children, if a category is empty, it won't look
|
||||||
# like one anymore
|
# like one anymore
|
||||||
@ -53,7 +55,7 @@ class CompletionView(QTreeView):
|
|||||||
self.model.setSourceModel(self.completion_models['command'])
|
self.model.setSourceModel(self.completion_models['command'])
|
||||||
self.model.pattern_changed.connect(self.resort)
|
self.model.pattern_changed.connect(self.resort)
|
||||||
self.setItemDelegate(CompletionItemDelegate())
|
self.setItemDelegate(CompletionItemDelegate())
|
||||||
self.setStyleSheet(self._stylesheet.strip())
|
self.setStyleSheet(config.get_stylesheet(self._stylesheet))
|
||||||
self.expandAll()
|
self.expandAll()
|
||||||
self.setHeaderHidden(True)
|
self.setHeaderHidden(True)
|
||||||
self.setIndentation(0)
|
self.setIndentation(0)
|
||||||
@ -242,11 +244,11 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
doc.setHtml('<b>{}</b>'.format(html.escape(self.opt.text)))
|
doc.setHtml('<b>{}</b>'.format(html.escape(self.opt.text)))
|
||||||
doc.setDefaultFont(self.opt.font)
|
doc.setDefaultFont(self.opt.font)
|
||||||
doc.setDefaultTextOption(text_option)
|
doc.setDefaultTextOption(text_option)
|
||||||
doc.setDefaultStyleSheet("""
|
doc.setDefaultStyleSheet(config.get_stylesheet("""
|
||||||
.highlight {
|
.highlight {{
|
||||||
color: red;
|
{color[completion.match.fg]}
|
||||||
}
|
}}
|
||||||
""")
|
"""))
|
||||||
doc.setDocumentMargin(0)
|
doc.setDocumentMargin(0)
|
||||||
|
|
||||||
if index.column() == 0:
|
if index.column() == 0:
|
||||||
|
@ -3,6 +3,7 @@ import logging
|
|||||||
from PyQt5.QtCore import pyqtSignal
|
from PyQt5.QtCore import pyqtSignal
|
||||||
from PyQt5.QtWidgets import QHBoxLayout, QWidget
|
from PyQt5.QtWidgets import QHBoxLayout, QWidget
|
||||||
|
|
||||||
|
import qutebrowser.utils.config as config
|
||||||
from qutebrowser.widgets.statusbar.command import Command
|
from qutebrowser.widgets.statusbar.command import Command
|
||||||
from qutebrowser.widgets.statusbar.text import Text
|
from qutebrowser.widgets.statusbar.text import Text
|
||||||
from qutebrowser.widgets.statusbar.progress import Progress
|
from qutebrowser.widgets.statusbar.progress import Progress
|
||||||
@ -14,27 +15,33 @@ class StatusBar(QWidget):
|
|||||||
txt = None
|
txt = None
|
||||||
prog = None
|
prog = None
|
||||||
resized = pyqtSignal('QRect')
|
resized = pyqtSignal('QRect')
|
||||||
fgcolor = 'white'
|
fgcolor = None
|
||||||
bgcolor = 'black'
|
bgcolor = None
|
||||||
font = 'Monospace, Courier'
|
|
||||||
_stylesheet = """
|
_stylesheet = """
|
||||||
* {{
|
* {{
|
||||||
background: {self.bgcolor};
|
{color[statusbar.bg.__cur__]}
|
||||||
color: {self.fgcolor};
|
{color[statusbar.fg.__cur__]}
|
||||||
font-family: {self.font};
|
font-family: Monospace, Courier;
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
"""Update the stylesheet if relevant attributes have been changed"""
|
"""Update the stylesheet if relevant attributes have been changed"""
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
if name in ['fgcolor', 'bgcolor', 'font']:
|
if name == 'fgcolor' and value is not None:
|
||||||
self.setStyleSheet(self._stylesheet.strip().format(self=self))
|
config.colordict['statusbar.fg.__cur__'] = value
|
||||||
|
self.setStyleSheet(config.get_stylesheet(self._stylesheet))
|
||||||
|
elif name == 'bgcolor' and value is not None:
|
||||||
|
config.colordict['statusbar.bg.__cur__'] = value
|
||||||
|
self.setStyleSheet(config.get_stylesheet(self._stylesheet))
|
||||||
|
|
||||||
# TODO: the statusbar should be a bit smaller
|
# TODO: the statusbar should be a bit smaller
|
||||||
def __init__(self, mainwindow):
|
def __init__(self, mainwindow):
|
||||||
super().__init__(mainwindow)
|
super().__init__(mainwindow)
|
||||||
self.setStyleSheet(self._stylesheet.strip().format(self=self))
|
self.fgcolor = config.colordict.getraw('statusbar.fg')
|
||||||
|
self.bgcolor = config.colordict.getraw('statusbar.bg')
|
||||||
|
self.setStyleSheet(config.get_stylesheet(self._stylesheet))
|
||||||
|
|
||||||
self.hbox = QHBoxLayout(self)
|
self.hbox = QHBoxLayout(self)
|
||||||
self.hbox.setContentsMargins(0, 0, 0, 0)
|
self.hbox.setContentsMargins(0, 0, 0, 0)
|
||||||
self.hbox.setSpacing(0)
|
self.hbox.setSpacing(0)
|
||||||
@ -50,12 +57,14 @@ class StatusBar(QWidget):
|
|||||||
|
|
||||||
def disp_error(self, text):
|
def disp_error(self, text):
|
||||||
"""Displays an error in the statusbar"""
|
"""Displays an error in the statusbar"""
|
||||||
self.bgcolor = 'red'
|
self.bgcolor = config.colordict.getraw('statusbar.bg.error')
|
||||||
|
self.fgcolor = config.colordict.getraw('statusbar.fg.error')
|
||||||
self.txt.error = text
|
self.txt.error = text
|
||||||
|
|
||||||
def clear_error(self):
|
def clear_error(self):
|
||||||
"""Clears a displayed error from the status bar"""
|
"""Clears a displayed error from the status bar"""
|
||||||
self.bgcolor = 'black'
|
self.bgcolor = config.colordict.getraw('statusbar.bg')
|
||||||
|
self.fgcolor = config.colordict.getraw('statusbar.fg')
|
||||||
self.txt.error = ''
|
self.txt.error = ''
|
||||||
|
|
||||||
def resizeEvent(self, e):
|
def resizeEvent(self, e):
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
import qutebrowser.utils.config as config
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
|
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
|
||||||
from PyQt5.QtCore import QSize
|
from PyQt5.QtCore import QSize
|
||||||
|
|
||||||
class Progress(QProgressBar):
|
class Progress(QProgressBar):
|
||||||
""" The progress bar part of the status bar"""
|
""" The progress bar part of the status bar"""
|
||||||
bar = None
|
bar = None
|
||||||
color = 'white'
|
color = None
|
||||||
_stylesheet = """
|
_stylesheet = """
|
||||||
QProgressBar {{
|
QProgressBar {{
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
@ -13,7 +15,7 @@ class Progress(QProgressBar):
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
QProgressBar::chunk {{
|
QProgressBar::chunk {{
|
||||||
background-color: {self.color};
|
{color[statusbar.progress.bg.__cur__]}
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -23,14 +25,15 @@ class Progress(QProgressBar):
|
|||||||
|
|
||||||
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
||||||
self.setTextVisible(False)
|
self.setTextVisible(False)
|
||||||
self.setStyleSheet(self._stylesheet.strip().format(self=self))
|
self.color = config.colordict.getraw('statusbar.progress.bg')
|
||||||
self.hide()
|
self.hide()
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
"""Update the stylesheet if relevant attributes have been changed"""
|
"""Update the stylesheet if relevant attributes have been changed"""
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
if name == 'color':
|
if name == 'color' and value is not None:
|
||||||
self.setStyleSheet(self._stylesheet.strip().format(self=self))
|
config.colordict['statusbar.progress.bg.__cur__'] = value
|
||||||
|
self.setStyleSheet(config.get_stylesheet(self._stylesheet))
|
||||||
|
|
||||||
def minimumSizeHint(self):
|
def minimumSizeHint(self):
|
||||||
status_size = self.bar.size()
|
status_size = self.bar.size()
|
||||||
@ -45,8 +48,9 @@ class Progress(QProgressBar):
|
|||||||
if prog == 100:
|
if prog == 100:
|
||||||
self.setValue(prog)
|
self.setValue(prog)
|
||||||
else:
|
else:
|
||||||
if self.color != 'white':
|
color = config.colordict.getraw('status.progress.bg')
|
||||||
self.color = 'white'
|
if self.color != color:
|
||||||
|
self.color = color
|
||||||
self.setValue(prog)
|
self.setValue(prog)
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
@ -54,4 +58,5 @@ class Progress(QProgressBar):
|
|||||||
if ok:
|
if ok:
|
||||||
self.hide()
|
self.hide()
|
||||||
else:
|
else:
|
||||||
self.color = 'red'
|
self.color = config.colordict.getraw('statusbar.progress.bg.error')
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from PyQt5.QtWidgets import QTabWidget
|
from PyQt5.QtWidgets import QTabWidget
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
|
import qutebrowser.utils.config as config
|
||||||
|
|
||||||
class TabWidget(QTabWidget):
|
class TabWidget(QTabWidget):
|
||||||
"""The tabwidget used for TabbedBrowser"""
|
"""The tabwidget used for TabbedBrowser"""
|
||||||
|
|
||||||
@ -8,36 +10,36 @@ class TabWidget(QTabWidget):
|
|||||||
# background-color: grey for QTabBar...
|
# background-color: grey for QTabBar...
|
||||||
|
|
||||||
_stylesheet = """
|
_stylesheet = """
|
||||||
QTabWidget::pane {
|
QTabWidget::pane {{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
}
|
}}
|
||||||
|
|
||||||
QTabBar {
|
QTabBar {{
|
||||||
font-family: Monospace, Courier;
|
font-family: Monospace, Courier;
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
}
|
}}
|
||||||
|
|
||||||
QTabBar::tab {
|
QTabBar::tab {{
|
||||||
background-color: grey;
|
{color[tab.bg]}
|
||||||
color: white;
|
{color[tab.fg]}
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
}
|
}}
|
||||||
|
|
||||||
QTabBar::tab:first, QTabBar::tab:middle {
|
QTabBar::tab:first, QTabBar::tab:middle {{
|
||||||
border-right: 1px solid white;
|
border-right: 1px solid {color[tab.seperator]};
|
||||||
}
|
}}
|
||||||
|
|
||||||
QTabBar::tab:selected {
|
QTabBar::tab:selected {{
|
||||||
background-color: black;
|
{color[tab.bg.selected]}
|
||||||
}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setStyleSheet(self._stylesheet.strip())
|
self.setStyleSheet(config.get_stylesheet(self._stylesheet))
|
||||||
self.setDocumentMode(True)
|
self.setDocumentMode(True)
|
||||||
self.setElideMode(Qt.ElideRight)
|
self.setElideMode(Qt.ElideRight)
|
||||||
|
Loading…
Reference in New Issue
Block a user