shinestacker 1.6.0__tar.gz → 1.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of shinestacker might be problematic. Click here for more details.
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.github/workflows/release.yml +21 -2
- {shinestacker-1.6.0 → shinestacker-1.7.0}/CHANGELOG.md +31 -1
- {shinestacker-1.6.0/src/shinestacker.egg-info → shinestacker-1.7.0}/PKG-INFO +2 -2
- {shinestacker-1.6.0 → shinestacker-1.7.0}/README.md +1 -1
- shinestacker-1.7.0/scripts/build_release.py +215 -0
- shinestacker-1.7.0/scripts/create_macos_icon.py +58 -0
- shinestacker-1.7.0/scripts/hooks/hook-IPython.py +10 -0
- shinestacker-1.7.0/scripts/hooks/hook-PySide6.py +53 -0
- shinestacker-1.7.0/scripts/hooks/hook-opencv.py +24 -0
- shinestacker-1.7.0/scripts/hooks/hook-tests.py +7 -0
- shinestacker-1.7.0/scripts/scan_imports.py +47 -0
- shinestacker-1.7.0/scripts/shinestacker-inno-setup.iss +72 -0
- shinestacker-1.7.0/shinestacker-inno-setup.iss +68 -0
- shinestacker-1.7.0/src/shinestacker/_version.py +1 -0
- shinestacker-1.7.0/src/shinestacker/algorithms/corrections.py +26 -0
- shinestacker-1.7.0/src/shinestacker/app/args_parser_opts.py +66 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/gui_utils.py +19 -2
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/main.py +16 -25
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/project.py +12 -21
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/retouch.py +12 -20
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/core/core_utils.py +2 -12
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/core/logging.py +4 -3
- shinestacker-1.7.0/src/shinestacker/gui/ico/shinestacker.icns +0 -0
- shinestacker-1.7.0/src/shinestacker/gui/ico/shinestacker_bkg.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/tab_widget.py +1 -5
- shinestacker-1.7.0/src/shinestacker/retouch/adjustments.py +93 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/base_filter.py +63 -8
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/denoise_filter.py +1 -1
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/display_manager.py +1 -2
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/image_editor_ui.py +39 -39
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/image_viewer.py +17 -9
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/io_gui_handler.py +96 -44
- shinestacker-1.7.0/src/shinestacker/retouch/io_threads.py +78 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/layer_collection.py +12 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/overlaid_view.py +13 -5
- shinestacker-1.7.0/src/shinestacker/retouch/paint_area_manager.py +30 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/sidebyside_view.py +3 -3
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/transformation_manager.py +1 -2
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/undo_manager.py +15 -13
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/unsharp_mask_filter.py +13 -28
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/view_strategy.py +65 -22
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/vignetting_filter.py +1 -1
- {shinestacker-1.6.0 → shinestacker-1.7.0/src/shinestacker.egg-info}/PKG-INFO +2 -2
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker.egg-info/SOURCES.txt +13 -2
- shinestacker-1.6.0/scripts/build_release.py +0 -54
- shinestacker-1.6.0/src/shinestacker/_version.py +0 -1
- shinestacker-1.6.0/src/shinestacker/app/args_parser_opts.py +0 -27
- shinestacker-1.6.0/src/shinestacker/gui/ico/focus_stack_bkg.png +0 -0
- shinestacker-1.6.0/src/shinestacker/gui/ico/shinestacker.icns +0 -0
- shinestacker-1.6.0/src/shinestacker/retouch/io_manager.py +0 -69
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.coveragerc +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.flake8 +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.github/workflows/ci-multiplatform.yml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.github/workflows/pylint.yml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.github/workflows/pypi-publish.yml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.gitignore +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.pylintrc +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/.readthedocs.yaml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/LICENSE +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/MANIFEST.in +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/THIRD_PARTY_LICENSES.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/alignment.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/api.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/balancing.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/conf.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/focus_stacking.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/gui.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/index.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/job.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/main.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/multilayer.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/noise.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/requirements.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/docs/vignetting.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/coffee.gif +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/coffee_stack.jpg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/extreme-vignetting.jpg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/flies.gif +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/flies_stack.jpg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/flow-diagram.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/gui-finder.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/gui-project-new.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/gui-project-run.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/img/gui-retouch.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/index.html +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/pyproject.toml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/requirements.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/scripts/git-rev-list.sh +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/scripts/validate-tomli.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/setup.cfg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/align.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/align_auto.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/align_parallel.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/balance.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/base_stack_algo.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/denoise.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/depth_map.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/exif.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/multilayer.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/noise_detection.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/pyramid.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/pyramid_auto.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/pyramid_tiles.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/sharpen.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/stack.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/stack_framework.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/utils.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/vignetting.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/algorithms/white_balance.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/about_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/help_menu.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/open_frames.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/app/settings_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/config/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/config/app_config.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/config/config.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/config/constants.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/config/gui_constants.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/config/settings.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/core/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/core/colors.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/core/exceptions.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/core/framework.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/action_config.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/action_config_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/base_form_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/colors.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/config_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/flow_layout.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/folder_file_selection.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/gui_images.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/gui_logging.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/gui_run.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/ico/shinestacker.ico +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/ico/shinestacker.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/ico/shinestacker.svg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/img/close-round-line-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/img/forward-button-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/img/play-button-round-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/img/plus-round-line-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/main_window.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/menu_manager.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/new_project.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/project_controller.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/project_converter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/project_editor.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/project_model.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/recent_file_manager.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/select_path_widget.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/sys_mon.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/gui/time_progress_bar.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/brush.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/brush_gradient.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/brush_preview.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/brush_tool.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/exif_data.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/file_loader.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/filter_manager.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/icon_container.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/image_view_status.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/shortcuts_help.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker/retouch/white_balance_filter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker.egg-info/dependency_links.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker.egg-info/entry_points.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker.egg-info/requires.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.7.0}/src/shinestacker.egg-info/top_level.txt +0 -0
|
@@ -29,6 +29,10 @@ jobs:
|
|
|
29
29
|
with:
|
|
30
30
|
python-version: "3.12"
|
|
31
31
|
|
|
32
|
+
- name: Install Inno Setup
|
|
33
|
+
if: runner.os == 'Windows'
|
|
34
|
+
run: choco install innosetup -y --no-progress --accept-license
|
|
35
|
+
|
|
32
36
|
- name: Install dependencies
|
|
33
37
|
run: |
|
|
34
38
|
python -m pip install --upgrade pip
|
|
@@ -40,12 +44,18 @@ jobs:
|
|
|
40
44
|
run: |
|
|
41
45
|
python build_release.py
|
|
42
46
|
|
|
43
|
-
- name: Upload
|
|
47
|
+
- name: Upload artifacts
|
|
44
48
|
uses: actions/upload-artifact@v4
|
|
45
49
|
with:
|
|
46
50
|
name: shinestacker-${{ matrix.os }}
|
|
47
51
|
path: |
|
|
48
|
-
${{ matrix.os == 'windows-latest' && 'dist/shinestacker-release.zip' || '
|
|
52
|
+
${{ matrix.os == 'windows-latest' && 'dist/shinestacker-release.zip' || '' }}
|
|
53
|
+
${{ matrix.os == 'windows-latest' && 'dist/*.exe' || '' }}
|
|
54
|
+
${{ matrix.os == 'ubuntu-latest' && 'dist/shinestacker-release.tar.gz' || '' }}
|
|
55
|
+
${{ matrix.os == 'macos-latest' && 'dist/shinestacker-release.tar.gz' || '' }}
|
|
56
|
+
${{ matrix.os == 'macos-latest' && 'dist/shinestacker-release.dmg' || '' }}
|
|
57
|
+
if-no-files-found: ignore
|
|
58
|
+
|
|
49
59
|
create-release:
|
|
50
60
|
needs: publish-release
|
|
51
61
|
runs-on: ubuntu-latest
|
|
@@ -58,9 +68,16 @@ jobs:
|
|
|
58
68
|
- name: Prepare release assets
|
|
59
69
|
run: |
|
|
60
70
|
mkdir -p release_assets
|
|
71
|
+
# Linux
|
|
61
72
|
cp artifacts/shinestacker-ubuntu-latest/shinestacker-release.tar.gz release_assets/shinestacker-ubuntu.tar.gz
|
|
73
|
+
# macOS - include both formats
|
|
62
74
|
cp artifacts/shinestacker-macos-latest/shinestacker-release.tar.gz release_assets/shinestacker-macos.tar.gz
|
|
75
|
+
cp artifacts/shinestacker-macos-latest/shinestacker-release.dmg release_assets/shinestacker-macos.dmg
|
|
76
|
+
# Windows
|
|
63
77
|
cp artifacts/shinestacker-windows-latest/shinestacker-release.zip release_assets/shinestacker-windows.zip
|
|
78
|
+
if ls artifacts/shinestacker-windows-latest/shinestacker-setup.exe 1> /dev/null 2>&1; then
|
|
79
|
+
cp artifacts/shinestacker-windows-latest/shinestacker-setup.exe release_assets/
|
|
80
|
+
fi
|
|
64
81
|
ls -la release_assets/
|
|
65
82
|
|
|
66
83
|
- name: Create release
|
|
@@ -70,4 +87,6 @@ jobs:
|
|
|
70
87
|
files: |
|
|
71
88
|
release_assets/shinestacker-ubuntu.tar.gz
|
|
72
89
|
release_assets/shinestacker-macos.tar.gz
|
|
90
|
+
release_assets/shinestacker-macos.dmg
|
|
73
91
|
release_assets/shinestacker-windows.zip
|
|
92
|
+
release_assets/shinestacker-setup.exe
|
|
@@ -2,7 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
This page reports the main releases only and the main changes therein.
|
|
4
4
|
|
|
5
|
-
## [v1.
|
|
5
|
+
## [v1.7.0] - 2025-10-04
|
|
6
|
+
** New image adjustment actions and macOS dmg installer **
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- luminosity and contrast adjustment action
|
|
10
|
+
- saturation and vibrance adjustment action
|
|
11
|
+
- macOS dmg installer
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- improved windows installer
|
|
15
|
+
- white balance moved from filters to edit > adjust menu
|
|
16
|
+
- minor GUI cosmetic improvements
|
|
17
|
+
- code refactoring
|
|
18
|
+
|
|
19
|
+
-----
|
|
20
|
+
|
|
21
|
+
## [v1.6.1] - 2025-10-01
|
|
22
|
+
** Performance improvements **
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- windows installer
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- improved display update performance by refreshing only the painted area
|
|
29
|
+
- multiple frame import now runs in a separate thread, avoiding UI freezes
|
|
30
|
+
- reduced dependencies and code refactored for more robust architecture
|
|
31
|
+
- dropped examples and test images to reduce distribution file size
|
|
32
|
+
|
|
33
|
+
-----
|
|
34
|
+
|
|
35
|
+
## [v1.6.0] - 2025-09-27
|
|
6
36
|
**Few more features and several fixes**
|
|
7
37
|
|
|
8
38
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: shinestacker
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: ShineStacker
|
|
5
5
|
Author-email: Luca Lista <luka.lista@gmail.com>
|
|
6
6
|
License-Expression: LGPL-3.0
|
|
@@ -85,7 +85,7 @@ In order to prevent this, follow the instructions below:
|
|
|
85
85
|
1. Download the compressed archive ```shinestacker-macos.tar.gz``` in your ```Download``` folder.
|
|
86
86
|
2. Double-click the archive to uncompress it. You will find a new folder ```shinestacker```.
|
|
87
87
|
3. Open a terminal (*Applications > Utilities > Terminal*)
|
|
88
|
-
4. Type the folliwng command on the terminal:
|
|
88
|
+
4. Type the folliwng command on the terminal (assuming you have expanded the ```tar.gz``` under ```Downloads```):
|
|
89
89
|
```bash
|
|
90
90
|
xattr -cr ~/Downloads/shinestacker/shinestacker.app
|
|
91
91
|
```
|
|
@@ -53,7 +53,7 @@ In order to prevent this, follow the instructions below:
|
|
|
53
53
|
1. Download the compressed archive ```shinestacker-macos.tar.gz``` in your ```Download``` folder.
|
|
54
54
|
2. Double-click the archive to uncompress it. You will find a new folder ```shinestacker```.
|
|
55
55
|
3. Open a terminal (*Applications > Utilities > Terminal*)
|
|
56
|
-
4. Type the folliwng command on the terminal:
|
|
56
|
+
4. Type the folliwng command on the terminal (assuming you have expanded the ```tar.gz``` under ```Downloads```):
|
|
57
57
|
```bash
|
|
58
58
|
xattr -cr ~/Downloads/shinestacker/shinestacker.app
|
|
59
59
|
```
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import tarfile
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import platform
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def setup_environment():
|
|
10
|
+
os.chdir("../")
|
|
11
|
+
project_root = Path(__file__).resolve().parent.parent
|
|
12
|
+
dist_dir = project_root / "dist"
|
|
13
|
+
project_name = "shinestacker"
|
|
14
|
+
app_name = "shinestacker"
|
|
15
|
+
hooks_dir = "scripts/hooks"
|
|
16
|
+
hook_files = list(Path(hooks_dir).glob("hook-*.py"))
|
|
17
|
+
for hook in hook_files:
|
|
18
|
+
print(f" - {hook.name}")
|
|
19
|
+
return project_root, dist_dir, project_name, app_name
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def build_pyinstaller_command(sys_name, dist_dir, project_name, app_name, hooks_dir):
|
|
23
|
+
if sys_name == 'darwin':
|
|
24
|
+
return [
|
|
25
|
+
"pyinstaller", "--windowed",
|
|
26
|
+
f"--name={app_name}",
|
|
27
|
+
f"--distpath={dist_dir}",
|
|
28
|
+
"--paths=src",
|
|
29
|
+
"--icon=src/shinestacker/gui/ico/shinestacker.icns",
|
|
30
|
+
"--argv-emulation",
|
|
31
|
+
f"--additional-hooks-dir={hooks_dir}",
|
|
32
|
+
f"--collect-all={project_name}",
|
|
33
|
+
"--collect-data=imagecodecs",
|
|
34
|
+
"--collect-submodules=imagecodecs",
|
|
35
|
+
"--copy-metadata=imagecodecs",
|
|
36
|
+
"src/shinestacker/app/main.py"
|
|
37
|
+
]
|
|
38
|
+
elif sys_name == 'windows':
|
|
39
|
+
return [
|
|
40
|
+
"pyinstaller", "--onedir", "--windowed",
|
|
41
|
+
f"--name={app_name}",
|
|
42
|
+
f"--distpath={dist_dir}",
|
|
43
|
+
"--paths=src",
|
|
44
|
+
"--icon=src/shinestacker/gui/ico/shinestacker.ico",
|
|
45
|
+
f"--collect-all={project_name}",
|
|
46
|
+
"--collect-data=imagecodecs", "--collect-submodules=imagecodecs",
|
|
47
|
+
"--copy-metadata=imagecodecs", f"--additional-hooks-dir={hooks_dir}",
|
|
48
|
+
"src/shinestacker/app/main.py"
|
|
49
|
+
]
|
|
50
|
+
else:
|
|
51
|
+
return [
|
|
52
|
+
"pyinstaller", "--onedir",
|
|
53
|
+
f"--name={app_name}",
|
|
54
|
+
f"--distpath={dist_dir}",
|
|
55
|
+
"--paths=src",
|
|
56
|
+
f"--collect-all={project_name}",
|
|
57
|
+
"--collect-data=imagecodecs", "--collect-submodules=imagecodecs",
|
|
58
|
+
"--copy-metadata=imagecodecs", f"--additional-hooks-dir={hooks_dir}",
|
|
59
|
+
"src/shinestacker/app/main.py"
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def package_windows(dist_dir, app_name):
|
|
64
|
+
shutil.make_archive(
|
|
65
|
+
base_name=str(dist_dir / "shinestacker-release"),
|
|
66
|
+
format="zip",
|
|
67
|
+
root_dir=dist_dir,
|
|
68
|
+
base_dir=app_name
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def package_macos(dist_dir, app_name, project_root):
|
|
73
|
+
app_bundle = dist_dir / f"{app_name}.app"
|
|
74
|
+
if not app_bundle.exists():
|
|
75
|
+
print(f"ERROR: .app bundle not found at {app_bundle}")
|
|
76
|
+
return
|
|
77
|
+
version = get_version(project_root)
|
|
78
|
+
build_number = version.replace('.', '') + '0' # Convert x.y.z -> xyz0
|
|
79
|
+
info_plist_template = project_root / "scripts" / "Info.plist"
|
|
80
|
+
info_plist_target = app_bundle / "Contents" / "Info.plist"
|
|
81
|
+
if info_plist_template.exists():
|
|
82
|
+
print("Processing Info.plist...")
|
|
83
|
+
with open(info_plist_template, 'r') as f:
|
|
84
|
+
plist_content = f.read()
|
|
85
|
+
plist_content = plist_content.replace('{{VERSION}}', version)
|
|
86
|
+
plist_content = plist_content.replace('{{BUILD_NUMBER}}', build_number)
|
|
87
|
+
info_plist_target.parent.mkdir(parents=True, exist_ok=True)
|
|
88
|
+
with open(info_plist_target, 'w') as f:
|
|
89
|
+
f.write(plist_content)
|
|
90
|
+
print(f"Info.plist created at: {info_plist_target}")
|
|
91
|
+
else:
|
|
92
|
+
print(f"WARNING: Info.plist template not found at {info_plist_template}")
|
|
93
|
+
icon_source = project_root / "src" / "shinestacker" / "gui" / "ico" / "shinestacker.icns"
|
|
94
|
+
dmg_temp_dir = dist_dir / "dmg_temp"
|
|
95
|
+
if dmg_temp_dir.exists():
|
|
96
|
+
shutil.rmtree(dmg_temp_dir)
|
|
97
|
+
shutil.copytree(app_bundle, dmg_temp_dir / app_bundle.name, symlinks=True)
|
|
98
|
+
os.symlink("/Applications", dmg_temp_dir / "Applications")
|
|
99
|
+
dmg_path = dist_dir / f"{app_name}-release.dmg"
|
|
100
|
+
dmg_cmd = [
|
|
101
|
+
"hdiutil", "create",
|
|
102
|
+
"-volname", app_name,
|
|
103
|
+
"-srcfolder", str(dmg_temp_dir),
|
|
104
|
+
"-ov", str(dmg_path),
|
|
105
|
+
"-format", "UDBZ",
|
|
106
|
+
"-fs", "HFS+"
|
|
107
|
+
]
|
|
108
|
+
subprocess.run(dmg_cmd, check=True)
|
|
109
|
+
print(f"Created DMG: {dmg_path.name}")
|
|
110
|
+
if icon_source.exists():
|
|
111
|
+
print("Setting custom icon...")
|
|
112
|
+
try:
|
|
113
|
+
subprocess.run(["sips", "-i", str(icon_source)], check=True)
|
|
114
|
+
subprocess.run(["DeRez", "-only", "icns", str(icon_source)],
|
|
115
|
+
stdout=open("/tmp/icon.r", "w"), check=True)
|
|
116
|
+
subprocess.run(["Rez", "-append", "/tmp/icon.r", "-o", str(dmg_path)], check=True)
|
|
117
|
+
subprocess.run(["SetFile", "-a", "C", str(dmg_path)], check=True)
|
|
118
|
+
print("Custom icon set successfully!")
|
|
119
|
+
except subprocess.CalledProcessError as e:
|
|
120
|
+
print(f"Could not set custom icon: {e}")
|
|
121
|
+
shutil.rmtree(dmg_temp_dir)
|
|
122
|
+
archive_path = dist_dir / "shinestacker-release.tar.gz"
|
|
123
|
+
with tarfile.open(archive_path, "w:gz") as tar:
|
|
124
|
+
tar.add(app_bundle, arcname=app_bundle.name, recursive=True)
|
|
125
|
+
print(f"Created tar.gz: {archive_path.name}")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def package_linux(dist_dir, app_name):
|
|
129
|
+
archive_path = dist_dir / "shinestacker-release.tar.gz"
|
|
130
|
+
linux_app_dir = dist_dir / app_name
|
|
131
|
+
if linux_app_dir.exists():
|
|
132
|
+
with tarfile.open(archive_path, "w:gz") as tar:
|
|
133
|
+
tar.add(linux_app_dir, arcname=app_name, recursive=True)
|
|
134
|
+
print(f"Packaged Linux application: {app_name}")
|
|
135
|
+
else:
|
|
136
|
+
print(f"ERROR: Linux app directory not found at {linux_app_dir}")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def get_version(project_root):
|
|
140
|
+
version_file = project_root / "src" / "shinestacker" / "_version.py"
|
|
141
|
+
version = "0.0.0"
|
|
142
|
+
if version_file.exists():
|
|
143
|
+
with open(version_file, 'r') as f:
|
|
144
|
+
content = f.read()
|
|
145
|
+
import re
|
|
146
|
+
match = re.search(r"__version__\s*=\s*['\"]([^'\"]+)['\"]", content)
|
|
147
|
+
if match:
|
|
148
|
+
version = match.group(1)
|
|
149
|
+
return version
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def create_windows_installer(project_root, dist_dir):
|
|
153
|
+
inno_paths = [
|
|
154
|
+
r"C:\Program Files (x86)\Inno Setup 6\ISCC.exe",
|
|
155
|
+
r"C:\Program Files (x86)\Inno Setup 5\ISCC.exe",
|
|
156
|
+
r"C:\Program Files\Inno Setup 6\ISCC.exe",
|
|
157
|
+
r"C:\Program Files\Inno Setup 5\ISCC.exe"
|
|
158
|
+
]
|
|
159
|
+
iscc_exe = None
|
|
160
|
+
for path in inno_paths:
|
|
161
|
+
if os.path.exists(path):
|
|
162
|
+
iscc_exe = path
|
|
163
|
+
break
|
|
164
|
+
if not iscc_exe:
|
|
165
|
+
try:
|
|
166
|
+
subprocess.run(["choco", "--version"], check=True, capture_output=True)
|
|
167
|
+
subprocess.run(["choco", "install", "innosetup", "-y",
|
|
168
|
+
"--no-progress", "--accept-license"], check=True)
|
|
169
|
+
for path in inno_paths:
|
|
170
|
+
if os.path.exists(path):
|
|
171
|
+
iscc_exe = path
|
|
172
|
+
break
|
|
173
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
174
|
+
pass
|
|
175
|
+
if iscc_exe:
|
|
176
|
+
iss_script_source = project_root / "scripts" / "shinestacker-inno-setup.iss"
|
|
177
|
+
iss_script_temp = project_root / "shinestacker-inno-setup.iss"
|
|
178
|
+
if iss_script_source.exists():
|
|
179
|
+
version = get_version(project_root)
|
|
180
|
+
with open(iss_script_source, 'r') as f:
|
|
181
|
+
iss_content = f.read()
|
|
182
|
+
old_version_line = f'#define MyAppVersion "{"x.x.x"}"'
|
|
183
|
+
new_version_line = f'#define MyAppVersion "{version}"'
|
|
184
|
+
iss_content = iss_content.replace(old_version_line, new_version_line)
|
|
185
|
+
with open(iss_script_temp, 'w') as f:
|
|
186
|
+
f.write(iss_content)
|
|
187
|
+
subprocess.run([iscc_exe, str(iss_script_temp)], check=True)
|
|
188
|
+
iss_script_temp.unlink()
|
|
189
|
+
if dist_dir.exists():
|
|
190
|
+
installer_files = list(dist_dir.glob("*.exe"))
|
|
191
|
+
if installer_files:
|
|
192
|
+
print(f"Installer created: {installer_files[0].name}")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def main():
|
|
196
|
+
project_root, dist_dir, project_name, app_name = setup_environment()
|
|
197
|
+
sys_name = platform.system().lower()
|
|
198
|
+
hooks_dir = "scripts/hooks"
|
|
199
|
+
pyinstaller_cmd = build_pyinstaller_command(
|
|
200
|
+
sys_name, dist_dir, project_name, app_name, hooks_dir)
|
|
201
|
+
print(" ".join(pyinstaller_cmd))
|
|
202
|
+
subprocess.run(pyinstaller_cmd, check=True)
|
|
203
|
+
if sys_name == 'windows':
|
|
204
|
+
package_windows(dist_dir, app_name)
|
|
205
|
+
elif sys_name == 'darwin':
|
|
206
|
+
package_macos(dist_dir, app_name, project_root)
|
|
207
|
+
else:
|
|
208
|
+
package_linux(dist_dir, app_name)
|
|
209
|
+
if sys_name == 'windows':
|
|
210
|
+
print("=== CREATING WINDOWS INSTALLER ===")
|
|
211
|
+
create_windows_installer(project_root, dist_dir)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
if __name__ == "__main__":
|
|
215
|
+
main()
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
def create_macos_icon():
|
|
7
|
+
script_dir = Path(__file__).parent
|
|
8
|
+
project_root = script_dir.parent
|
|
9
|
+
png_source = project_root / "src" / "shinestacker" / "gui" / "ico" / "shinestacker.png"
|
|
10
|
+
icns_output = project_root / "src" / "shinestacker" / "gui" / "ico" / "shinestacker.icns"
|
|
11
|
+
|
|
12
|
+
if not png_source.exists():
|
|
13
|
+
print(f"ERROR: Source PNG not found at {png_source}")
|
|
14
|
+
return False
|
|
15
|
+
|
|
16
|
+
print(f"Creating macOS icon from {png_source}")
|
|
17
|
+
|
|
18
|
+
iconset_dir = project_root / "src" / "shinestacker" / "gui" / "ico" / "shinestacker.iconset"
|
|
19
|
+
if iconset_dir.exists():
|
|
20
|
+
shutil.rmtree(iconset_dir)
|
|
21
|
+
iconset_dir.mkdir()
|
|
22
|
+
|
|
23
|
+
sizes = [
|
|
24
|
+
("16x16", 16),
|
|
25
|
+
("16x16@2x", 32),
|
|
26
|
+
("32x32", 32),
|
|
27
|
+
("32x32@2x", 64),
|
|
28
|
+
("128x128", 128),
|
|
29
|
+
("128x128@2x", 256),
|
|
30
|
+
("256x256", 256),
|
|
31
|
+
("256x256@2x", 512),
|
|
32
|
+
("512x512", 512),
|
|
33
|
+
("512x512@2x", 1024)
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
for name, size in sizes:
|
|
37
|
+
output_file = iconset_dir / f"icon_{name}.png"
|
|
38
|
+
print(f" Creating {name}...")
|
|
39
|
+
subprocess.run([
|
|
40
|
+
"sips", "-z", str(size), str(size),
|
|
41
|
+
str(png_source),
|
|
42
|
+
"--out", str(output_file)
|
|
43
|
+
], check=True)
|
|
44
|
+
|
|
45
|
+
print("Converting to .icns format...")
|
|
46
|
+
subprocess.run([
|
|
47
|
+
"iconutil", "-c", "icns",
|
|
48
|
+
str(iconset_dir),
|
|
49
|
+
"-o", str(icns_output)
|
|
50
|
+
], check=True)
|
|
51
|
+
|
|
52
|
+
shutil.rmtree(iconset_dir)
|
|
53
|
+
print(f"SUCCESS: Created {icns_output}")
|
|
54
|
+
return True
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
create_macos_icon()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
excludedimports = [
|
|
2
|
+
# Keep only these 5 modules actually used:
|
|
3
|
+
# PySide6.QtCore
|
|
4
|
+
# PySide6.QtGui
|
|
5
|
+
# PySide6.QtPdf
|
|
6
|
+
# PySide6.QtPdfWidgets
|
|
7
|
+
# PySide6.QtWidgets
|
|
8
|
+
|
|
9
|
+
# Exclude everything else:
|
|
10
|
+
'PySide6.Qt3DAnimation',
|
|
11
|
+
'PySide6.Qt3DCore',
|
|
12
|
+
'PySide6.Qt3DExtras',
|
|
13
|
+
'PySide6.Qt3DInput',
|
|
14
|
+
'PySide6.Qt3DLogic',
|
|
15
|
+
'PySide6.Qt3DRender',
|
|
16
|
+
'PySide6.QtBluetooth',
|
|
17
|
+
'PySide6.QtCharts',
|
|
18
|
+
'PySide6.QtConcurrent',
|
|
19
|
+
'PySide6.QtDataVisualization',
|
|
20
|
+
'PySide6.QtDBus',
|
|
21
|
+
'PySide6.QtDesigner',
|
|
22
|
+
'PySide6.QtGamepad',
|
|
23
|
+
'PySide6.QtHelp',
|
|
24
|
+
'PySide6.QtLocation',
|
|
25
|
+
'PySide6.QtMultimedia',
|
|
26
|
+
'PySide6.QtMultimediaWidgets',
|
|
27
|
+
'PySide6.QtNetwork',
|
|
28
|
+
'PySide6.QtNfc',
|
|
29
|
+
'PySide6.QtOpenGL',
|
|
30
|
+
'PySide6.QtOpenGLWidgets',
|
|
31
|
+
'PySide6.QtPositioning',
|
|
32
|
+
'PySide6.QtPrintSupport',
|
|
33
|
+
'PySide6.QtQml',
|
|
34
|
+
'PySide6.QtQuick',
|
|
35
|
+
'PySide6.QtQuick3D',
|
|
36
|
+
'PySide6.QtQuickWidgets',
|
|
37
|
+
'PySide6.QtRemoteObjects',
|
|
38
|
+
'PySide6.QtScxml',
|
|
39
|
+
'PySide6.QtSensors',
|
|
40
|
+
'PySide6.QtSerialPort',
|
|
41
|
+
'PySide6.QtSql',
|
|
42
|
+
'PySide6.QtSvg',
|
|
43
|
+
'PySide6.QtTest',
|
|
44
|
+
'PySide6.QtTextToSpeech',
|
|
45
|
+
'PySide6.QtUiTools',
|
|
46
|
+
'PySide6.QtWebChannel',
|
|
47
|
+
'PySide6.QtWebEngine',
|
|
48
|
+
'PySide6.QtWebEngineCore',
|
|
49
|
+
'PySide6.QtWebEngineWidgets',
|
|
50
|
+
'PySide6.QtWebSockets',
|
|
51
|
+
'PySide6.QtXml',
|
|
52
|
+
'PySide6.QtXmlPatterns',
|
|
53
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
excludedimports = [
|
|
2
|
+
'cv2.videoio',
|
|
3
|
+
'cv2.videostab',
|
|
4
|
+
'cv2.face',
|
|
5
|
+
'cv2.bgsegm',
|
|
6
|
+
'cv2.optflow',
|
|
7
|
+
'cv2.saliency',
|
|
8
|
+
'cv2.text',
|
|
9
|
+
'cv2.tracking',
|
|
10
|
+
'cv2.mcc',
|
|
11
|
+
'cv2.rapid',
|
|
12
|
+
'cv2.stereo',
|
|
13
|
+
'cv2.dnn',
|
|
14
|
+
'cv2.freetype',
|
|
15
|
+
'cv2.hdf',
|
|
16
|
+
'cv2.img_hash',
|
|
17
|
+
'cv2.line_descriptor',
|
|
18
|
+
'cv2.reg',
|
|
19
|
+
'cv2.rgbd',
|
|
20
|
+
'cv2.surface_matching',
|
|
21
|
+
'cv2.xfeatures2d',
|
|
22
|
+
'cv2.ximgproc',
|
|
23
|
+
'cv2.xphoto',
|
|
24
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
def scan_imports():
|
|
5
|
+
project_root = Path("../src/shinestacker")
|
|
6
|
+
imports = {
|
|
7
|
+
'PySide6': set(),
|
|
8
|
+
'scipy': set(),
|
|
9
|
+
'matplotlib': set(),
|
|
10
|
+
'cv2': set(),
|
|
11
|
+
'numpy': set(),
|
|
12
|
+
'PIL': set()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
for py_file in project_root.rglob("*.py"):
|
|
16
|
+
with open(py_file, 'r', encoding='utf-8') as f:
|
|
17
|
+
try:
|
|
18
|
+
tree = ast.parse(f.read())
|
|
19
|
+
except:
|
|
20
|
+
continue
|
|
21
|
+
|
|
22
|
+
for node in ast.walk(tree):
|
|
23
|
+
if isinstance(node, ast.Import):
|
|
24
|
+
for alias in node.names:
|
|
25
|
+
for lib in imports.keys():
|
|
26
|
+
if lib in alias.name:
|
|
27
|
+
imports[lib].add(alias.name)
|
|
28
|
+
elif isinstance(node, ast.ImportFrom):
|
|
29
|
+
if node.module:
|
|
30
|
+
for lib in imports.keys():
|
|
31
|
+
if lib in node.module:
|
|
32
|
+
imports[lib].add(node.module)
|
|
33
|
+
if node.names:
|
|
34
|
+
for alias in node.names:
|
|
35
|
+
imports[lib].add(f"{node.module}.{alias.name}")
|
|
36
|
+
return imports
|
|
37
|
+
|
|
38
|
+
def print_imports(imports):
|
|
39
|
+
for lib, modules in imports.items():
|
|
40
|
+
if modules:
|
|
41
|
+
print(f"\n=== {lib.upper()} IMPORTS ===")
|
|
42
|
+
for imp in sorted(modules):
|
|
43
|
+
print(f" {imp}")
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
found_imports = scan_imports()
|
|
47
|
+
print_imports(found_imports)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#define MyAppName "ShineStacker"
|
|
2
|
+
#define MyAppVersion "x.x.x"
|
|
3
|
+
#define MyAppPublisher "Luca Lista"
|
|
4
|
+
#define MyAppURL "https://shinestacker.wordpress.com/"
|
|
5
|
+
#define MyAppExeName "shinestacker.exe"
|
|
6
|
+
#define MyAppAssocName MyAppName + " focus stacking project"
|
|
7
|
+
#define MyAppAssocExt ".fsp"
|
|
8
|
+
#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt
|
|
9
|
+
|
|
10
|
+
[Setup]
|
|
11
|
+
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
|
12
|
+
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
|
13
|
+
AppId={{A2B55EAF-932F-4D5A-8D80-B7DF79D5AE7B}
|
|
14
|
+
AppName={#MyAppName}
|
|
15
|
+
AppVersion={#MyAppVersion}
|
|
16
|
+
;AppVerName={#MyAppName} {#MyAppVersion}
|
|
17
|
+
AppPublisher={#MyAppPublisher}
|
|
18
|
+
AppPublisherURL={#MyAppURL}
|
|
19
|
+
AppSupportURL={#MyAppURL}
|
|
20
|
+
AppUpdatesURL={#MyAppURL}
|
|
21
|
+
DefaultDirName={autopf}\{#MyAppName}
|
|
22
|
+
UninstallDisplayIcon={app}\{#MyAppExeName}
|
|
23
|
+
; "ArchitecturesAllowed=x64compatible" specifies that Setup cannot run
|
|
24
|
+
; on anything but x64 and Windows 11 on Arm.
|
|
25
|
+
ArchitecturesAllowed=x64compatible
|
|
26
|
+
; "ArchitecturesInstallIn64BitMode=x64compatible" requests that the
|
|
27
|
+
; install be done in "64-bit mode" on x64 or Windows 11 on Arm,
|
|
28
|
+
; meaning it should use the native 64-bit Program Files directory and
|
|
29
|
+
; the 64-bit view of the registry.
|
|
30
|
+
ArchitecturesInstallIn64BitMode=x64compatible
|
|
31
|
+
ChangesAssociations=yes
|
|
32
|
+
DisableProgramGroupPage=yes
|
|
33
|
+
LicenseFile=.\LICENSE
|
|
34
|
+
; Uncomment the following line to run in non administrative install mode (install for current user only).
|
|
35
|
+
;PrivilegesRequired=lowest
|
|
36
|
+
OutputBaseFilename=shinestacker-setup
|
|
37
|
+
OutputDir=dist
|
|
38
|
+
VersionInfoVersion={#MyAppVersion}
|
|
39
|
+
VersionInfoCompany={#MyAppPublisher}
|
|
40
|
+
SetupIconFile=src\shinestacker\gui\ico\shinestacker.ico
|
|
41
|
+
SolidCompression=yes
|
|
42
|
+
WizardStyle=modern
|
|
43
|
+
|
|
44
|
+
[Languages]
|
|
45
|
+
Name: "english"; MessagesFile: "compiler:Default.isl"
|
|
46
|
+
|
|
47
|
+
[Messages]
|
|
48
|
+
WelcomeLabel1=Welcome to the {#MyAppName} Setup Wizard
|
|
49
|
+
WelcomeLabel2=This wizard will install {#MyAppName} {#MyAppVersion}, an open-source focus stacking application developed by Luca Lista.%n%nThe source code is available on GitHub.
|
|
50
|
+
FinishedLabel=Setup has finished installing {#MyAppName} on your computer. The application may be launched by selecting the installed shortcuts.%n%nClick Finish to exit Setup.
|
|
51
|
+
|
|
52
|
+
[Tasks]
|
|
53
|
+
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
|
54
|
+
|
|
55
|
+
[Files]
|
|
56
|
+
; Copy the entire shinestacker folder structure that contains both the exe and _internal
|
|
57
|
+
Source: "dist\shinestacker\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
|
58
|
+
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
|
59
|
+
|
|
60
|
+
[Registry]
|
|
61
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
|
|
62
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
|
|
63
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
|
|
64
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" -f ""%1"""
|
|
65
|
+
|
|
66
|
+
[Icons]
|
|
67
|
+
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
|
68
|
+
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
|
69
|
+
|
|
70
|
+
[Run]
|
|
71
|
+
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
|
72
|
+
|