Add colors to DownloadView
This commit is contained in:
parent
3c2c08f73a
commit
2ffc9bb00a
@ -26,6 +26,7 @@ import qutebrowser.config.config as config
|
||||
import qutebrowser.utils.message as message
|
||||
from qutebrowser.utils.log import downloads as logger
|
||||
from qutebrowser.utils.usertypes import PromptMode
|
||||
from qutebrowser.utils.misc import interpolate_color
|
||||
|
||||
|
||||
class DownloadItem(QObject):
|
||||
@ -111,6 +112,16 @@ class DownloadItem(QObject):
|
||||
else:
|
||||
return 100 * self.bytes_done / self.bytes_total
|
||||
|
||||
def bg_color(self):
|
||||
"""Background color to be shown."""
|
||||
start = config.get('colors', 'download.bg.start')
|
||||
stop = config.get('colors', 'download.bg.stop')
|
||||
system = config.get('colors', 'download.bg.system')
|
||||
if self.percentage is None:
|
||||
return start
|
||||
else:
|
||||
return interpolate_color(start, stop, self.percentage, system)
|
||||
|
||||
def cancel(self):
|
||||
"""Cancel the download."""
|
||||
logger.debug("cancelled")
|
||||
|
@ -894,6 +894,22 @@ DATA = OrderedDict([
|
||||
'left bottom, color-stop(0%,#FFF785), '
|
||||
'color-stop(100%,#FFC542))'),
|
||||
"Background color for hints."),
|
||||
|
||||
('download.fg',
|
||||
SettingValue(types.QtColor(), '#ffffff'),
|
||||
"Foreground color for downloads."),
|
||||
|
||||
('download.bg.start',
|
||||
SettingValue(types.QtColor(), '#0000aa'),
|
||||
"Color gradient start for downloads."),
|
||||
|
||||
('download.bg.stop',
|
||||
SettingValue(types.QtColor(), '#00aa00'),
|
||||
"Color gradient end for downloads."),
|
||||
|
||||
('download.bg.system',
|
||||
SettingValue(types.ColorSystem(), 'rgb'),
|
||||
"Color gradient interpolation system for downloads."),
|
||||
)),
|
||||
|
||||
('fonts', sect.KeyValue(
|
||||
|
@ -434,6 +434,42 @@ class Command(BaseType):
|
||||
return out
|
||||
|
||||
|
||||
class ColorSystem(BaseType):
|
||||
|
||||
"""Color systems for interpolation."""
|
||||
|
||||
valid_values = ValidValues(('rgb', "Interpolate in the RGB color system."),
|
||||
('hsv', "Interpolate in the HSV color system."),
|
||||
('hsl', "Interpolate in the HSV color system."))
|
||||
|
||||
def validate(self, value):
|
||||
super().validate(value.lower())
|
||||
|
||||
def transform(self, value):
|
||||
mapping = {
|
||||
'rgb': QColor.Rgb,
|
||||
'hsv': QColor.Hsv,
|
||||
'hsl': QColor.Hsl,
|
||||
}
|
||||
return mapping[value.lower()]
|
||||
|
||||
|
||||
class QtColor(BaseType):
|
||||
|
||||
"""Base class for QColor."""
|
||||
|
||||
typestr = 'qcolor'
|
||||
|
||||
def validate(self, value):
|
||||
if QColor.isValidColor(value):
|
||||
pass
|
||||
else:
|
||||
raise ValidationError(value, "must be a valid color")
|
||||
|
||||
def transform(self, value):
|
||||
return QColor(value)
|
||||
|
||||
|
||||
class CssColor(BaseType):
|
||||
|
||||
"""Base class for a CSS color value."""
|
||||
|
@ -21,6 +21,8 @@ from PyQt5.QtCore import (pyqtSlot, Qt, QVariant, QAbstractListModel,
|
||||
QModelIndex)
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
import qutebrowser.config.config as config
|
||||
|
||||
|
||||
class DownloadModel(QAbstractListModel):
|
||||
|
||||
@ -59,19 +61,26 @@ class DownloadModel(QAbstractListModel):
|
||||
"""Download data from DownloadManager."""
|
||||
if not index.isValid():
|
||||
return QVariant()
|
||||
elif role != Qt.DisplayRole:
|
||||
return QVariant()
|
||||
elif index.parent().isValid() or index.column() != 0:
|
||||
return QVariant()
|
||||
|
||||
try:
|
||||
item = self.downloadmanager.downloads[index.row()]
|
||||
except IndexError:
|
||||
return QVariant()
|
||||
if role == Qt.DisplayRole:
|
||||
perc = item.percentage
|
||||
if perc is None:
|
||||
return QVariant()
|
||||
data = QVariant()
|
||||
else:
|
||||
return str(round(perc)) # FIXME
|
||||
data = str(round(perc)) # FIXME
|
||||
elif role == Qt.ForegroundRole:
|
||||
data = config.get('colors', 'download.fg')
|
||||
elif role == Qt.BackgroundRole:
|
||||
data = item.bg_color()
|
||||
else:
|
||||
data = QVariant()
|
||||
return data
|
||||
|
||||
def rowCount(self, parent):
|
||||
"""Get count of active downloads."""
|
||||
|
@ -30,6 +30,7 @@ from tempfile import mkdtemp
|
||||
from unittest import TestCase
|
||||
|
||||
from PyQt5.QtCore import QStandardPaths, QCoreApplication
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
import qutebrowser.utils.misc as utils
|
||||
from qutebrowser.test.helpers import environ_set_temp
|
||||
@ -436,5 +437,93 @@ class GetQtArgsTests(TestCase):
|
||||
self.assertEqual(utils.get_qt_args(ns), [sys.argv[0]])
|
||||
|
||||
|
||||
class InterpolateColorTests(TestCase):
|
||||
|
||||
"""Tests for interpolate_color.
|
||||
|
||||
Attributes:
|
||||
white: The QColor white as a valid QColor for tests.
|
||||
white: The QColor black as a valid QColor for tests.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.white = QColor('white')
|
||||
self.black = QColor('black')
|
||||
|
||||
def test_invalid_start(self):
|
||||
"""Test an invalid start color."""
|
||||
with self.assertRaises(ValueError):
|
||||
utils.interpolate_color(QColor(), self.white, 0)
|
||||
|
||||
def test_invalid_end(self):
|
||||
"""Test an invalid end color."""
|
||||
with self.assertRaises(ValueError):
|
||||
utils.interpolate_color(self.white, QColor(), 0)
|
||||
|
||||
def test_invalid_percentage(self):
|
||||
"""Test an invalid percentage."""
|
||||
with self.assertRaises(ValueError):
|
||||
utils.interpolate_color(self.white, self.white, -1)
|
||||
with self.assertRaises(ValueError):
|
||||
utils.interpolate_color(self.white, self.white, 101)
|
||||
|
||||
def test_invalid_colorspace(self):
|
||||
"""Test an invalid colorspace."""
|
||||
with self.assertRaises(ValueError):
|
||||
utils.interpolate_color(self.white, self.black, 10, QColor.Cmyk)
|
||||
|
||||
def test_valid_percentages_rgb(self):
|
||||
"""Test 0% and 100% in the RGB colorspace."""
|
||||
white = utils.interpolate_color(self.white, self.black, 0, QColor.Rgb)
|
||||
black = utils.interpolate_color(self.white, self.black, 100,
|
||||
QColor.Rgb)
|
||||
self.assertEqual(white, self.white)
|
||||
self.assertEqual(black, self.black)
|
||||
|
||||
def test_valid_percentages_hsv(self):
|
||||
"""Test 0% and 100% in the HSV colorspace."""
|
||||
white = utils.interpolate_color(self.white, self.black, 0, QColor.Hsv)
|
||||
black = utils.interpolate_color(self.white, self.black, 100,
|
||||
QColor.Hsv)
|
||||
self.assertEqual(white, self.white)
|
||||
self.assertEqual(black, self.black)
|
||||
|
||||
def test_valid_percentages_hsl(self):
|
||||
"""Test 0% and 100% in the HSL colorspace."""
|
||||
white = utils.interpolate_color(self.white, self.black, 0, QColor.Hsl)
|
||||
black = utils.interpolate_color(self.white, self.black, 100,
|
||||
QColor.Hsl)
|
||||
self.assertEqual(white, self.white)
|
||||
self.assertEqual(black, self.black)
|
||||
|
||||
def test_interpolation_rgb(self):
|
||||
"""Test an interpolation in the RGB colorspace."""
|
||||
color = utils.interpolate_color(QColor(0, 40, 100), QColor(0, 20, 200),
|
||||
50, QColor.Rgb)
|
||||
self.assertEqual(color, QColor(0, 30, 150))
|
||||
|
||||
def test_interpolation_hsv(self):
|
||||
"""Test an interpolation in the HSV colorspace."""
|
||||
start = QColor()
|
||||
stop = QColor()
|
||||
start.setHsv(0, 40, 100)
|
||||
stop.setHsv(0, 20, 200)
|
||||
color = utils.interpolate_color(start, stop, 50, QColor.Hsv)
|
||||
expected = QColor()
|
||||
expected.setHsv(0, 30, 150)
|
||||
self.assertEqual(color, expected)
|
||||
|
||||
def test_interpolation_hsl(self):
|
||||
"""Test an interpolation in the HSL colorspace."""
|
||||
start = QColor()
|
||||
stop = QColor()
|
||||
start.setHsl(0, 40, 100)
|
||||
stop.setHsl(0, 20, 200)
|
||||
color = utils.interpolate_color(start, stop, 50, QColor.Hsl)
|
||||
expected = QColor()
|
||||
expected.setHsl(0, 30, 150)
|
||||
self.assertEqual(color, expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -33,6 +33,7 @@ from functools import reduce
|
||||
from distutils.version import StrictVersion as Version
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication, QStandardPaths, qVersion
|
||||
from PyQt5.QtGui import QColor
|
||||
from pkg_resources import resource_string
|
||||
|
||||
import qutebrowser
|
||||
@ -285,3 +286,71 @@ def get_qt_args(namespace):
|
||||
argv.append('-' + argname)
|
||||
argv.append(val[0])
|
||||
return argv
|
||||
|
||||
|
||||
def _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3, percent):
|
||||
"""Get a color which is percent% interpolated between start and end.
|
||||
|
||||
Args:
|
||||
a_c1, a_c2, a_c3: Start color components (R, G, B / H, S, V / H, S, L)
|
||||
b_c1, b_c2, b_c3: End color components (R, G, B / H, S, V / H, S, L)
|
||||
percent: Percentage to interpolate, 0-100.
|
||||
0: Start color will be returned.
|
||||
100: End color will be returned.
|
||||
|
||||
Return:
|
||||
A (c1, c2, c3) tuple with the interpolated color components.
|
||||
|
||||
Raise:
|
||||
ValueError if the percentage was invalid.
|
||||
"""
|
||||
if not 0 <= percent <= 100:
|
||||
raise ValueError("percent needs to be between 0 and 100!")
|
||||
out_c1 = round(a_c1 + (b_c1 - a_c1) * percent / 100)
|
||||
out_c2 = round(a_c2 + (b_c2 - a_c2) * percent / 100)
|
||||
out_c3 = round(a_c3 + (b_c3 - a_c3) * percent / 100)
|
||||
return (out_c1, out_c2, out_c3)
|
||||
|
||||
|
||||
def interpolate_color(start, end, percent, colorspace=QColor.Rgb):
|
||||
"""Get an interpolated color value.
|
||||
|
||||
Args:
|
||||
start: The start color.
|
||||
end: The end color.
|
||||
percent: Which value to get (0 - 100)
|
||||
colorspace: The desired interpolation colorsystem,
|
||||
QColor::{Rgb,Hsv,Hsl} (from QColor::Spec enum)
|
||||
|
||||
Return:
|
||||
The interpolated QColor, with the same spec as the given start color.
|
||||
|
||||
Raise:
|
||||
ValueError if invalid parameters are passed.
|
||||
"""
|
||||
if not start.isValid():
|
||||
raise ValueError("Invalid start color")
|
||||
if not end.isValid():
|
||||
raise ValueError("Invalid end color")
|
||||
out = QColor()
|
||||
if colorspace == QColor.Rgb:
|
||||
a_c1, a_c2, a_c3, _alpha = start.getRgb()
|
||||
b_c1, b_c2, b_c3, _alpha = end.getRgb()
|
||||
components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
|
||||
percent)
|
||||
out.setRgb(*components)
|
||||
elif colorspace == QColor.Hsv:
|
||||
a_c1, a_c2, a_c3, _alpha = start.getHsv()
|
||||
b_c1, b_c2, b_c3, _alpha = end.getHsv()
|
||||
components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
|
||||
percent)
|
||||
out.setHsv(*components)
|
||||
elif colorspace == QColor.Hsl:
|
||||
a_c1, a_c2, a_c3, _alpha = start.getHsl()
|
||||
b_c1, b_c2, b_c3, _alpha = end.getHsl()
|
||||
components = _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3,
|
||||
percent)
|
||||
out.setHsl(*components)
|
||||
else:
|
||||
raise ValueError("Invalid colorspace!")
|
||||
return out.convertTo(start.spec())
|
||||
|
Loading…
Reference in New Issue
Block a user