Add config option for custom app icon. Takes an absolute path to an image file. Falls back to default icons when custom icon cannot be loaded.

This resolves the following issues:
https://github.com/qutebrowser/qutebrowser/issues/7714
https://github.com/qutebrowser/qutebrowser/issues/4009

It can be used by adding this line to the config.py:
`c.app.icon = '/Users/luke/Pictures/browser.png'`
This commit is contained in:
Luke 2025-02-05 22:19:16 +01:00
parent 60f526d81f
commit cad3646b49
5 changed files with 72 additions and 9 deletions

2
.gitignore vendored
View File

@ -55,3 +55,5 @@ TODO
/misc/nsis/include
/misc/nsis/plugins
/wheels
/wheels
.DS_Store

View File

@ -168,15 +168,36 @@ def init(*, args: argparse.Namespace) -> None:
def _init_icon():
"""Initialize the icon of qutebrowser."""
fallback_icon = QIcon()
for size in [16, 24, 32, 48, 64, 96, 128, 256, 512]:
filename = 'icons/qutebrowser-{size}x{size}.png'.format(size=size)
def load_default_icons():
for size in [16, 24, 32, 48, 64, 96, 128, 256, 512]:
filename = 'icons/qutebrowser-{size}x{size}.png'.format(size=size)
pixmap = QPixmap()
pixmap.loadFromData(resources.read_file_binary(filename))
if pixmap.isNull():
log.init.warning("Failed to load: {}".format(filename))
else:
fallback_icon.addPixmap(pixmap)
icon_custom = config.val.app.icon
if icon_custom != None:
# Use the custom icon if possible
pixmap = QPixmap()
pixmap.loadFromData(resources.read_file_binary(filename))
if pixmap.isNull():
log.init.warning("Failed to load {}".format(filename))
else:
fallback_icon.addPixmap(pixmap)
try:
pixmap.loadFromData(resources.read_absolute_file_binary(icon_custom))
if pixmap.isNull():
log.init.warning("Failed to load custom icon: {}. Falling back to default".format(icon_custom))
load_default_icons()
else:
fallback_icon.addPixmap(pixmap)
except FileNotFoundError:
log.init.warning("Custom icon not found: {}. Falling back to default".format(icon_custom))
load_default_icons()
else:
load_default_icons()
icon = QIcon.fromTheme('qutebrowser', fallback_icon)
if icon.isNull():
log.init.warning("Failed to load icon")

View File

@ -970,8 +970,21 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
hints["x-kde-origin-name"] = origin_url_str
if icon.isNull():
filename = 'icons/qutebrowser-64x64.png'
icon = QImage.fromData(resources.read_file_binary(filename))
icon_custom = config.val.app.icon
icon_default = 'icons/qutebrowser-64x64.png'
def get_icon_data():
if icon_custom == None:
return resources.read_file_binary(icon_default)
try:
return resources.read_absolute_file_binary(icon_custom)
except FileNotFoundError:
log.init.warning("Custom icon not found: {}. Falling back to default".format(icon_custom))
return resources.read_file_binary(icon_default)
icon = QImage.fromData(get_icon_data())
key = self._quirks.icon_key or "image-data"
data = self._convert_image(icon)

View File

@ -4094,3 +4094,15 @@ logging.level.console:
desc: >-
Level for console (stdout/stderr) logs.
Ignored if the `--loglevel` or `--debug` CLI flags are used.
## app
app.icon:
type:
name: String
none_ok: true
default: null
restart: true
desc: >-
The absolute path to a custom icon for the qutebrowser app.
Note that this only sets the icon for the app while it is running.

View File

@ -121,3 +121,18 @@ def read_file_binary(filename: str) -> bytes:
path = _path(filename)
with _keyerror_workaround():
return path.read_bytes()
def read_absolute_file_binary(filepath: str) -> bytes:
"""Get the contents of an binary file at an absolute path.
This file may exist outside of qutebrowser-owned directories.
Args:
filepath: The absolute filepath to open as string.
Return:
The file contents as a bytes object.
"""
path = pathlib.Path(filepath)
with _keyerror_workaround():
return path.read_bytes()