Skip to content

Commit

Permalink
Merge pull request #113 from Alexhuszagh/compress
Browse files Browse the repository at this point in the history
Add support for compressed resource files by default. This uses per-resource compression and not per-file compression, first compiling all resources without compression, then compressions the entire resource bundle. This can be disabled using --use-default-compression in configure.py.

This has space savings of ~4.4MB (PyQt5) or 1.9M (everything else) to ~200KB, or ~90% to 95% space savings. Due to the time at startup for the UI initialization, the extra overhead is unlikely to be noticeable.

Closes #110.
  • Loading branch information
Alexhuszagh authored Sep 8, 2024
2 parents 207e1b6 + 27e341a commit b47b503
Show file tree
Hide file tree
Showing 80 changed files with 6,055 additions and 44,525 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# NOTE: this file is auto-generated via `vcs.py`
# DO NOT MANUALLY EDIT THIS FILE.
TODO.md
dist/
resources/

# Byte-compiled / optimized / DLL files
__pycache__/
Expand All @@ -14,7 +16,6 @@ __pycache__/
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning].
- Documented support for CMake builds (from [ruilvo]).
- Add additional alternate themes for common styles (from [Inverted-E]).
- Add additional a red theme (from [Inverted-E]).
- Compress resource files by default.

### Changed

Expand Down
61 changes: 60 additions & 1 deletion configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
__version__ = '0.2.0'

import argparse
import ast
import binascii
import glob
import json
import lzma
import os
import re
import shutil
Expand Down Expand Up @@ -80,6 +83,11 @@ def parse_args(argv=None):
'--compiled-resource',
help='output compiled python resource file.',
)
parser.add_argument(
'--use-default-compression',
help='use the default Qt compression rather than the more efficient custom compression.',
action='store_true',
)
args = parser.parse_args(argv)
parse_styles(args)
parse_extensions(args)
Expand Down Expand Up @@ -364,6 +372,8 @@ def compile_resource(args):
compiled_resource_path = f'{resources_dir}/{compiled_resource_path}'

command = [rcc, resource_path, '-o', compiled_resource_path]
if not args.use_default_compression:
command.append('-no-compress')
try:
subprocess.check_output(
command,
Expand Down Expand Up @@ -396,6 +406,55 @@ def compile_resource(args):
if args.qt_framework == 'pyqt6':
fix_qt6_import(compiled_resource_path)

if not args.use_default_compression:
compress_resource(compiled_resource_path)


def compress(data):
'''Compress an array to a smaller amount, and then split it along lines.'''
raise NotImplementedError('TODO')


def compress_and_replace(module, prefix):
'''Extract data from a resource module, then replace the data with compress values.'''

# first, get and compress our data
# this pattern is always safe since there will never be any internal `"`
# characters due to how compilation/quoting is done, even escaped ones.
pattern = fr'(?P<prefix>{prefix}\s*=\s*)(?P<data>b".*?")'
match = re.search(pattern, module, flags=re.DOTALL)
if match is None and prefix == 'qt_resource_struct':
# NOTE: some older versions use v1/v2 structs
v1 = compress_and_replace(module, 'qt_resource_struct_v1')
v2 = compress_and_replace(v1, 'qt_resource_struct_v2')
return v2
decompressed = ast.literal_eval(match.group('data'))
compressed = lzma.compress(decompressed)

# NOTE: to avoid any issues with `"` or `'` characters, we always escape it
hexlified = binascii.hexlify(compressed).decode('ascii').upper()
escaped = ''.join([f'\\x{hexlified[i:i+2]}' for i in range(0, len(hexlified), 2)])
lzma_replace = f'{prefix} = lzma.decompress(_{prefix})'
replacement = f'_{prefix} = b"{escaped}"\n{lzma_replace}\n'

return module[: match.start()] + replacement + module[match.end() + 1 :]


def compress_resource(path):
'''Compress the data within a Qt resource module.'''

# want to minimize the file size, let's use custom gzip compression
with open(path, encoding='utf-8') as file:
module = file.read()
module = module.replace('import QtCore', 'import QtCore\nimport lzma', 1)
# NOTE: these should never be none or we have an error
module = compress_and_replace(module, 'qt_resource_data')
module = compress_and_replace(module, 'qt_resource_name')
module = compress_and_replace(module, 'qt_resource_struct')

with open(path, 'w', encoding='utf-8') as file:
file.write(module)


def configure(args):
'''Configure all styles and write the files to a QRC file.'''
Expand Down Expand Up @@ -436,7 +495,7 @@ def fix_qt6_import(compiled_file):

with open(compiled_file, 'r', encoding='utf-8') as file:
text = file.read()
text = text.replace('PySide6', 'PyQt6')
text = text.replace('PySide6', 'PyQt6', 1)
with open(compiled_file, 'w', encoding='utf-8') as file:
file.write(text)

Expand Down
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_close_hover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_close_pressed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_detach.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_detach_hover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_detach_hover_pressed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_maximize.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_maximize_hover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_maximize_pressed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_menu_button.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_menu_button_hover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions dist/dark-blue/ads_menu_button_pressed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions dist/dark-blue/browser_refresh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions dist/dark-blue/browser_refresh_stop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions dist/dark-blue/dialog_apply.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions dist/dark-blue/dialog_ignore.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions dist/dark-blue/dialog_retry.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions dist/dark-blue/dialog_save_all.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions dist/dark-blue/dialog_yes_to_all.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions dist/dark-blue/folder_open_link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions dist/dark-blue/horizontal_extension.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions dist/dark-blue/pause.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions dist/dark-blue/play.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions dist/dark-blue/restore_defaults.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions dist/dark-blue/seek_backward.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions dist/dark-blue/seek_forward.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/skip_backward.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/skip_forward.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/stop.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/tab_close.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/vertical_extension.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/vista_shield.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/volume.svg
3 changes: 3 additions & 0 deletions dist/dark-blue/volume_muted.svg
Loading

0 comments on commit b47b503

Please sign in to comment.