Skip to content

Commit 68835b7

Browse files
committed
rework custom stylesheet loading
Previously, the stylesheet was copied to the user's .config dir, and this was then loaded as a style (with priority "application"). The user could alter this stylesheet directly. This stylesheet was called "safeeyes_styles.css". Now, we split the stylesheets into two: - The system stylesheet, which is directly loaded with priority "application". - The user's stylesheet, if it exists, which is loaded from the .config dir with priority "user", overriding both the system stylesheet and any themes the user might have. This is now called "safeeyes_custom_styles.css". This means in the future, we can simply add new default styles to the system stylesheet without breaking the user. Additionally, any styles loaded with a higher priority than "application" (eg. certain GTK themes, see slgobinath#687), can now be overridden by the user's stylesheet. We also check if the old path ("safeeyes_styles.css") contains an old default stylesheet. If it does, we delete it. If it (likely) contains a customized stylesheet, don't delete it, but warn the user that they should use "safeeyes_custom_styles.css" instead now.
1 parent b379523 commit 68835b7

File tree

4 files changed

+50
-23
lines changed

4 files changed

+50
-23
lines changed

safeeyes/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def main():
130130
utility.initialize_logging(args.debug)
131131
utility.initialize_platform()
132132
config = Config()
133-
utility.create_user_stylesheet_if_missing()
133+
utility.cleanup_old_user_stylesheet()
134134

135135
if __running():
136136
logging.info("Safe Eyes is already running")

safeeyes/model.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,6 @@ def __init__(self, init=True):
327327
self.__user_config, self.__system_config
328328
)
329329
self.__user_config = self.__system_config
330-
# Update the style sheet
331-
utility.replace_style_sheet()
332330

333331
utility.merge_plugins(self.__user_config)
334332
self.save()

safeeyes/safeeyes.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ def do_activate(self):
167167

168168
def _initialize_styles(self):
169169
utility.load_css_file(
170-
utility.STYLE_SHEET_PATH, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
170+
utility.SYSTEM_STYLE_SHEET_PATH, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
171+
)
172+
utility.load_css_file(
173+
utility.CUSTOM_STYLE_SHEET_PATH, Gtk.STYLE_PROVIDER_PRIORITY_USER
171174
)
172175

173176
def _retry_errored_plugins(self):

safeeyes/utility.py

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"""This module contains utility functions for Safe Eyes and its plugins."""
2020

2121
import errno
22+
import hashlib
2223
import inspect
2324
import importlib
2425
import json
@@ -56,7 +57,10 @@
5657
CONFIG_FILE_PATH = os.path.join(CONFIG_DIRECTORY, "safeeyes.json")
5758
CONFIG_RESOURCE = os.path.join(CONFIG_DIRECTORY, "resource")
5859
SESSION_FILE_PATH = os.path.join(CONFIG_DIRECTORY, "session.json")
59-
STYLE_SHEET_PATH = os.path.join(STYLE_SHEET_DIRECTORY, "safeeyes_style.css")
60+
OLD_STYLE_SHEET_PATH = os.path.join(STYLE_SHEET_DIRECTORY, "safeeyes_style.css")
61+
CUSTOM_STYLE_SHEET_PATH = os.path.join(
62+
STYLE_SHEET_DIRECTORY, "safeeyes_custom_style.css"
63+
)
6064
SYSTEM_CONFIG_FILE_PATH = os.path.join(BIN_DIRECTORY, "config/safeeyes.json")
6165
SYSTEM_STYLE_SHEET_PATH = os.path.join(BIN_DIRECTORY, "config/style/safeeyes_style.css")
6266
LOG_FILE_PATH = os.path.join(HOME_DIRECTORY, "safeeyes.log")
@@ -373,6 +377,17 @@ def merge_configs(new_config, old_config):
373377
return new_config
374378

375379

380+
def sha256sum(filename):
381+
"""Get the sha256 hash of the given file."""
382+
h = hashlib.sha256()
383+
b = bytearray(128 * 1024)
384+
mv = memoryview(b)
385+
with open(filename, "rb", buffering=0) as f:
386+
for n in iter(lambda: f.readinto(mv), 0):
387+
h.update(mv[:n])
388+
return h.hexdigest()
389+
390+
376391
def load_css_file(style_sheet_path, priority):
377392
css_provider = Gtk.CssProvider()
378393
css_provider.load_from_path(style_sheet_path)
@@ -382,7 +397,7 @@ def load_css_file(style_sheet_path, priority):
382397

383398

384399
def initialize_safeeyes():
385-
"""Create the config file and style sheet in XDG_CONFIG_HOME(or
400+
"""Create the config file in XDG_CONFIG_HOME(or
386401
~/.config)/safeeyes directory.
387402
"""
388403
logging.info("Copy the config files to XDG_CONFIG_HOME(or ~/.config)/safeeyes")
@@ -397,24 +412,45 @@ def initialize_safeeyes():
397412
shutil.copy2(SYSTEM_CONFIG_FILE_PATH, CONFIG_FILE_PATH)
398413
os.chmod(CONFIG_FILE_PATH, 0o666)
399414

400-
create_user_stylesheet_if_missing()
401-
402415
# initialize_safeeyes gets called when the configuration file is not present, which
403416
# happens just after installation or manual deletion of
404417
# .config/safeeyes/safeeyes.json file. In these cases, we want to force the creation
405418
# of a startup entry
406419
create_startup_entry(force=True)
407420

408421

409-
def create_user_stylesheet_if_missing():
422+
def cleanup_old_user_stylesheet():
410423
# Create the XDG_CONFIG_HOME(or ~/.config)/safeeyes/style directory
411424
if not os.path.isdir(STYLE_SHEET_DIRECTORY):
412425
mkdir(STYLE_SHEET_DIRECTORY)
413426

414-
# Copy the new style sheet
415-
if not os.path.isfile(STYLE_SHEET_PATH):
416-
shutil.copy2(SYSTEM_STYLE_SHEET_PATH, STYLE_SHEET_PATH)
417-
os.chmod(STYLE_SHEET_PATH, 0o666)
427+
# Delete the old stylesheet, unless it has customizations
428+
if os.path.isfile(OLD_STYLE_SHEET_PATH):
429+
hash = sha256sum(OLD_STYLE_SHEET_PATH)
430+
old_default_versions = [
431+
# 2.2.3
432+
"fdc2a305613ae4eeb269650452789d35df3df5bdf1c56eb576cd5ebac70a6f09",
433+
# 2.1.0 - 2.2.2
434+
"fbde048fc234db757461971a7542df43a467869035ca3d05ff9b236ca250e4c5",
435+
# 2.0.9
436+
"70ca55c12d83ad7a6a4e1c5e7758a38617a43f5d32f28709ede75426d3186713",
437+
# 2.0.7 - 2.0.8
438+
"7a15f985e0da6d92c8a62d49ce151781e6d423f87e66d205cc1dc4536e369e19",
439+
# 2.0.6 and earlier
440+
"f26621a883e323ca7685a4adba25027e70daa471e0db4a21c261e6c15caaa5ee",
441+
]
442+
if hash in old_default_versions:
443+
logging.info("Deleting old stylesheet containing default content")
444+
delete(OLD_STYLE_SHEET_PATH)
445+
else:
446+
# Stylesheet was likely customized, don't delete but warn
447+
logging.warning(
448+
_(
449+
"Old stylesheet found at '%(old)s', ignoring. For custom styles, "
450+
"create a new stylesheet in '%(new)s' instead.",
451+
)
452+
% {"old": OLD_STYLE_SHEET_PATH, "new": CUSTOM_STYLE_SHEET_PATH}
453+
)
418454

419455

420456
def create_startup_entry(force=False):
@@ -526,26 +562,16 @@ def initialize_platform():
526562
def reset_config():
527563
# Remove the ~/.config/safeeyes/safeeyes.json and safeeyes_style.css
528564
delete(CONFIG_FILE_PATH)
529-
delete(STYLE_SHEET_PATH)
530565

531566
# Copy the safeeyes.json and safeeyes_style.css
532567
shutil.copy2(SYSTEM_CONFIG_FILE_PATH, CONFIG_FILE_PATH)
533-
shutil.copy2(SYSTEM_STYLE_SHEET_PATH, STYLE_SHEET_PATH)
534568

535569
# Add write permission (e.g. if original file was stored in /nix/store)
536570
os.chmod(CONFIG_FILE_PATH, 0o666)
537-
os.chmod(STYLE_SHEET_PATH, 0o666)
538571

539572
create_startup_entry()
540573

541574

542-
def replace_style_sheet():
543-
"""Replace the user style sheet by system style sheet."""
544-
delete(STYLE_SHEET_PATH)
545-
shutil.copy2(SYSTEM_STYLE_SHEET_PATH, STYLE_SHEET_PATH)
546-
os.chmod(STYLE_SHEET_PATH, 0o666)
547-
548-
549575
def initialize_logging(debug):
550576
"""Initialize the logging framework using the Safe Eyes specific
551577
configurations.

0 commit comments

Comments
 (0)