shinestacker 1.6.0__tar.gz → 1.6.1__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.6.1}/.github/workflows/release.yml +11 -1
- {shinestacker-1.6.0 → shinestacker-1.6.1}/CHANGELOG.md +13 -1
- {shinestacker-1.6.0/src/shinestacker.egg-info → shinestacker-1.6.1}/PKG-INFO +1 -1
- shinestacker-1.6.1/scripts/build_release.py +112 -0
- shinestacker-1.6.1/scripts/hooks/hook-IPython.py +10 -0
- shinestacker-1.6.1/scripts/hooks/hook-PySide6.py +53 -0
- shinestacker-1.6.1/scripts/hooks/hook-opencv.py +24 -0
- shinestacker-1.6.1/scripts/hooks/hook-tests.py +7 -0
- shinestacker-1.6.1/scripts/scan_imports.py +47 -0
- shinestacker-1.6.1/scripts/shinestacker-inno-setup.iss +68 -0
- shinestacker-1.6.1/shinestacker-inno-setup.iss +68 -0
- shinestacker-1.6.1/src/shinestacker/_version.py +1 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/main.py +3 -1
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/project.py +3 -1
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/retouch.py +5 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/core/core_utils.py +3 -12
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/core/logging.py +3 -2
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/base_filter.py +1 -1
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/display_manager.py +1 -2
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/image_editor_ui.py +13 -35
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/image_viewer.py +17 -9
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/io_gui_handler.py +96 -44
- shinestacker-1.6.1/src/shinestacker/retouch/io_threads.py +78 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/layer_collection.py +12 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/overlaid_view.py +13 -5
- shinestacker-1.6.1/src/shinestacker/retouch/paint_area_manager.py +30 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/sidebyside_view.py +3 -3
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/transformation_manager.py +1 -2
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/undo_manager.py +15 -13
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/view_strategy.py +65 -22
- {shinestacker-1.6.0 → shinestacker-1.6.1/src/shinestacker.egg-info}/PKG-INFO +1 -1
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker.egg-info/SOURCES.txt +9 -1
- 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/retouch/io_manager.py +0 -69
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.coveragerc +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.flake8 +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.github/workflows/ci-multiplatform.yml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.github/workflows/pylint.yml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.github/workflows/pypi-publish.yml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.gitignore +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.pylintrc +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/.readthedocs.yaml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/LICENSE +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/MANIFEST.in +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/README.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/THIRD_PARTY_LICENSES.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/alignment.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/api.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/balancing.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/conf.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/focus_stacking.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/gui.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/index.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/job.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/main.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/multilayer.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/noise.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/requirements.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/docs/vignetting.md +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/coffee.gif +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/coffee_stack.jpg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/extreme-vignetting.jpg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/flies.gif +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/flies_stack.jpg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/flow-diagram.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/gui-finder.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/gui-project-new.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/gui-project-run.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/img/gui-retouch.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/index.html +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/pyproject.toml +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/requirements.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/scripts/git-rev-list.sh +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/scripts/validate-tomli.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/setup.cfg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/align.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/align_auto.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/align_parallel.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/balance.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/base_stack_algo.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/denoise.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/depth_map.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/exif.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/multilayer.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/noise_detection.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/pyramid.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/pyramid_auto.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/pyramid_tiles.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/sharpen.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/stack.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/stack_framework.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/utils.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/vignetting.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/algorithms/white_balance.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/about_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/args_parser_opts.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/gui_utils.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/help_menu.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/open_frames.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/app/settings_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/config/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/config/app_config.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/config/config.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/config/constants.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/config/gui_constants.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/config/settings.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/core/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/core/colors.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/core/exceptions.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/core/framework.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/action_config.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/action_config_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/base_form_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/colors.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/config_dialog.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/flow_layout.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/folder_file_selection.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/gui_images.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/gui_logging.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/gui_run.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/ico/focus_stack_bkg.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/ico/shinestacker.icns +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/ico/shinestacker.ico +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/ico/shinestacker.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/ico/shinestacker.svg +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/img/close-round-line-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/img/forward-button-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/img/play-button-round-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/img/plus-round-line-icon.png +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/main_window.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/menu_manager.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/new_project.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/project_controller.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/project_converter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/project_editor.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/project_model.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/recent_file_manager.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/select_path_widget.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/sys_mon.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/tab_widget.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/gui/time_progress_bar.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/__init__.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/brush.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/brush_gradient.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/brush_preview.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/brush_tool.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/denoise_filter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/exif_data.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/file_loader.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/filter_manager.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/icon_container.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/image_view_status.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/shortcuts_help.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/unsharp_mask_filter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/vignetting_filter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker/retouch/white_balance_filter.py +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker.egg-info/dependency_links.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker.egg-info/entry_points.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/src/shinestacker.egg-info/requires.txt +0 -0
- {shinestacker-1.6.0 → shinestacker-1.6.1}/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,14 @@ 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
52
|
${{ matrix.os == 'windows-latest' && 'dist/shinestacker-release.zip' || 'dist/shinestacker-release.tar.gz' }}
|
|
53
|
+
${{ matrix.os == 'windows-latest' && 'dist/*.exe' || '' }}
|
|
54
|
+
if-no-files-found: ignore
|
|
49
55
|
create-release:
|
|
50
56
|
needs: publish-release
|
|
51
57
|
runs-on: ubuntu-latest
|
|
@@ -61,6 +67,9 @@ jobs:
|
|
|
61
67
|
cp artifacts/shinestacker-ubuntu-latest/shinestacker-release.tar.gz release_assets/shinestacker-ubuntu.tar.gz
|
|
62
68
|
cp artifacts/shinestacker-macos-latest/shinestacker-release.tar.gz release_assets/shinestacker-macos.tar.gz
|
|
63
69
|
cp artifacts/shinestacker-windows-latest/shinestacker-release.zip release_assets/shinestacker-windows.zip
|
|
70
|
+
if ls artifacts/shinestacker-windows-latest/shinestacker-setup.exe 1> /dev/null 2>&1; then
|
|
71
|
+
cp artifacts/shinestacker-windows-latest/shinestacker-setup.exe release_assets/
|
|
72
|
+
fi
|
|
64
73
|
ls -la release_assets/
|
|
65
74
|
|
|
66
75
|
- name: Create release
|
|
@@ -71,3 +80,4 @@ jobs:
|
|
|
71
80
|
release_assets/shinestacker-ubuntu.tar.gz
|
|
72
81
|
release_assets/shinestacker-macos.tar.gz
|
|
73
82
|
release_assets/shinestacker-windows.zip
|
|
83
|
+
release_assets/shinestacker-setup.exe
|
|
@@ -2,7 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
This page reports the main releases only and the main changes therein.
|
|
4
4
|
|
|
5
|
-
## [v1.6.
|
|
5
|
+
## [v1.6.1] - 2025-10-01
|
|
6
|
+
** Unreleased updates **
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- improved display update performance by refreshing only the painted area
|
|
10
|
+
- multiple frame import now runs in a separate thread, avoiding UI freezes
|
|
11
|
+
- reduced dependencies and code refactored for more robust architecture
|
|
12
|
+
- added windows installer
|
|
13
|
+
- dropped examples and test images reduces distribution file size
|
|
14
|
+
|
|
15
|
+
-----
|
|
16
|
+
|
|
17
|
+
## [v1.6.0] - 2025-09-27
|
|
6
18
|
**Few more features and several fixes**
|
|
7
19
|
|
|
8
20
|
### Added
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import tarfile
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import platform
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# assume the scripts runs under its directory, "scripts", as defined in release.yml
|
|
10
|
+
#
|
|
11
|
+
os.chdir("../")
|
|
12
|
+
project_root = Path(__file__).resolve().parent.parent
|
|
13
|
+
dist_dir = project_root / "dist"
|
|
14
|
+
project_name = "shinestacker"
|
|
15
|
+
app_name = "shinestacker"
|
|
16
|
+
package_dir = "shinestacker"
|
|
17
|
+
|
|
18
|
+
sys_name = platform.system().lower()
|
|
19
|
+
|
|
20
|
+
hooks_dir = "scripts/hooks"
|
|
21
|
+
|
|
22
|
+
print("=== USING HOOKS ===")
|
|
23
|
+
hook_files = list(Path(hooks_dir).glob("hook-*.py"))
|
|
24
|
+
for hook in hook_files:
|
|
25
|
+
print(f" - {hook.name}")
|
|
26
|
+
|
|
27
|
+
pyinstaller_cmd = [
|
|
28
|
+
"pyinstaller", "--onedir", f"--name={app_name}", "--paths=src",
|
|
29
|
+
f"--distpath=dist/{package_dir}", f"--collect-all={project_name}",
|
|
30
|
+
"--collect-data=imagecodecs", "--collect-submodules=imagecodecs",
|
|
31
|
+
"--copy-metadata=imagecodecs", f"--additional-hooks-dir={hooks_dir}"
|
|
32
|
+
]
|
|
33
|
+
if sys_name == 'darwin':
|
|
34
|
+
pyinstaller_cmd += ["--windowed", "--icon=src/shinestacker/gui/ico/shinestacker.icns"]
|
|
35
|
+
elif sys_name == 'windows':
|
|
36
|
+
pyinstaller_cmd += ["--windowed", "--icon=src/shinestacker/gui/ico/shinestacker.ico"]
|
|
37
|
+
pyinstaller_cmd += ["src/shinestacker/app/main.py"]
|
|
38
|
+
|
|
39
|
+
print(" ".join(pyinstaller_cmd))
|
|
40
|
+
subprocess.run(pyinstaller_cmd, check=True)
|
|
41
|
+
|
|
42
|
+
# examples_dir = project_root / "examples"
|
|
43
|
+
# target_examples = dist_dir / package_dir / "examples"
|
|
44
|
+
# target_examples.mkdir(exist_ok=True)
|
|
45
|
+
# for project_file in ["complete-project.fsp", "stack-from-frames.fsp"]:
|
|
46
|
+
# shutil.copy(examples_dir / project_file, target_examples)
|
|
47
|
+
# shutil.copytree(examples_dir / 'input', target_examples / 'input', dirs_exist_ok=True)
|
|
48
|
+
|
|
49
|
+
if sys_name == 'windows':
|
|
50
|
+
shutil.make_archive(
|
|
51
|
+
base_name=str(dist_dir / "shinestacker-release"),
|
|
52
|
+
format="zip",
|
|
53
|
+
root_dir=dist_dir,
|
|
54
|
+
base_dir=package_dir
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
archive_path = dist_dir / "shinestacker-release.tar.gz"
|
|
58
|
+
with tarfile.open(archive_path, "w:gz") as tar:
|
|
59
|
+
tar.add(
|
|
60
|
+
dist_dir / package_dir,
|
|
61
|
+
arcname=package_dir,
|
|
62
|
+
recursive=True,
|
|
63
|
+
filter=lambda info: info
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if sys_name == 'windows':
|
|
67
|
+
print("=== CREATING WINDOWS INSTALLER ===")
|
|
68
|
+
inno_paths = [
|
|
69
|
+
r"C:\Program Files (x86)\Inno Setup 6\ISCC.exe",
|
|
70
|
+
r"C:\Program Files (x86)\Inno Setup 5\ISCC.exe",
|
|
71
|
+
r"C:\Program Files\Inno Setup 6\ISCC.exe",
|
|
72
|
+
r"C:\Program Files\Inno Setup 5\ISCC.exe"
|
|
73
|
+
]
|
|
74
|
+
iscc_exe = None
|
|
75
|
+
for path in inno_paths:
|
|
76
|
+
if os.path.exists(path):
|
|
77
|
+
iscc_exe = path
|
|
78
|
+
print(f"Found Inno Setup at: {path}")
|
|
79
|
+
break
|
|
80
|
+
if not iscc_exe:
|
|
81
|
+
print("Inno Setup not found in standard locations. Checking for Chocolatey...")
|
|
82
|
+
try:
|
|
83
|
+
subprocess.run(["choco", "--version"], check=True, capture_output=True)
|
|
84
|
+
print("Installing Inno Setup via Chocolatey...")
|
|
85
|
+
subprocess.run(["choco", "install", "innosetup", "-y", "--no-progress", "--accept-license"], check=True)
|
|
86
|
+
for path in inno_paths:
|
|
87
|
+
if os.path.exists(path):
|
|
88
|
+
iscc_exe = path
|
|
89
|
+
print(f"Found Inno Setup at: {path}")
|
|
90
|
+
break
|
|
91
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
92
|
+
print("Chocolatey not available or installation failed.")
|
|
93
|
+
if iscc_exe:
|
|
94
|
+
iss_script_source = project_root / "scripts" / "shinestacker-inno-setup.iss"
|
|
95
|
+
iss_script_temp = project_root / "shinestacker-inno-setup.iss"
|
|
96
|
+
if iss_script_source.exists():
|
|
97
|
+
print(f"Copying ISS script to project root: {iss_script_temp}")
|
|
98
|
+
shutil.copy2(iss_script_source, iss_script_temp)
|
|
99
|
+
print(f"Compiling installer with: {iscc_exe}")
|
|
100
|
+
subprocess.run([iscc_exe, str(iss_script_temp)], check=True)
|
|
101
|
+
print("Removing temporary ISS script")
|
|
102
|
+
iss_script_temp.unlink()
|
|
103
|
+
if dist_dir.exists():
|
|
104
|
+
installer_files = list(dist_dir.glob("*.exe"))
|
|
105
|
+
if installer_files:
|
|
106
|
+
print(f"Installer created: {installer_files[0].name}")
|
|
107
|
+
else:
|
|
108
|
+
print(f"ISS script not found at: {iss_script_source}")
|
|
109
|
+
else:
|
|
110
|
+
print("WARNING: Could not find or install Inno Setup. Skipping installer creation.")
|
|
111
|
+
print("You can manually install Inno Setup from: https://jrsoftware.org/isdl.php")
|
|
112
|
+
print("Or install Chocolatey and run: choco install innosetup -y")
|
|
@@ -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,68 @@
|
|
|
1
|
+
#define MyAppName "ShineStacker"
|
|
2
|
+
#define MyAppVersion "1.6.1"
|
|
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
|
+
[Tasks]
|
|
48
|
+
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
|
49
|
+
|
|
50
|
+
[Files]
|
|
51
|
+
; Copy the entire shinestacker folder structure that contains both the exe and _internal
|
|
52
|
+
Source: ".\dist\shinestacker\shinestacker\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
|
53
|
+
Source: ".\examples\*"; DestDir: "{app}\examples"; Flags: ignoreversion recursesubdirs
|
|
54
|
+
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
|
55
|
+
|
|
56
|
+
[Registry]
|
|
57
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
|
|
58
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
|
|
59
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
|
|
60
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
|
|
61
|
+
|
|
62
|
+
[Icons]
|
|
63
|
+
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
|
64
|
+
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
|
65
|
+
|
|
66
|
+
[Run]
|
|
67
|
+
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
|
68
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#define MyAppName "ShineStacker"
|
|
2
|
+
#define MyAppVersion "1.6.1"
|
|
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
|
+
[Tasks]
|
|
48
|
+
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
|
49
|
+
|
|
50
|
+
[Files]
|
|
51
|
+
; Copy the entire shinestacker folder structure that contains both the exe and _internal
|
|
52
|
+
Source: ".\dist\shinestacker\shinestacker\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
|
53
|
+
Source: ".\examples\*"; DestDir: "{app}\examples"; Flags: ignoreversion recursesubdirs
|
|
54
|
+
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
|
55
|
+
|
|
56
|
+
[Registry]
|
|
57
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
|
|
58
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
|
|
59
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
|
|
60
|
+
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
|
|
61
|
+
|
|
62
|
+
[Icons]
|
|
63
|
+
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
|
64
|
+
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
|
65
|
+
|
|
66
|
+
[Run]
|
|
67
|
+
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
|
68
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '1.6.1'
|
|
@@ -13,6 +13,7 @@ from PySide6.QtCore import Qt, QEvent, QTimer, Signal
|
|
|
13
13
|
from shinestacker.config.config import config
|
|
14
14
|
config.init(DISABLE_TQDM=True, COMBINED_APP=True, DONT_USE_NATIVE_MENU=True)
|
|
15
15
|
from shinestacker.config.constants import constants
|
|
16
|
+
from shinestacker.config.settings import StdPathFile
|
|
16
17
|
from shinestacker.core.logging import setup_logging
|
|
17
18
|
from shinestacker.gui.main_window import MainWindow
|
|
18
19
|
from shinestacker.retouch.image_editor_ui import ImageEditorUI
|
|
@@ -229,7 +230,8 @@ open retouch window at startup instead of project windows.
|
|
|
229
230
|
if filename and path:
|
|
230
231
|
print("can't specify both arguments --filename and --path", file=sys.stderr)
|
|
231
232
|
sys.exit(1)
|
|
232
|
-
setup_logging(console_level=logging.DEBUG, file_level=logging.DEBUG, disable_console=True
|
|
233
|
+
setup_logging(console_level=logging.DEBUG, file_level=logging.DEBUG, disable_console=True,
|
|
234
|
+
log_file=StdPathFile('shinestacker.log').get_file_path())
|
|
233
235
|
app = Application(sys.argv)
|
|
234
236
|
if config.DONT_USE_NATIVE_MENU:
|
|
235
237
|
app.setAttribute(Qt.AA_DontUseNativeMenuBar)
|
|
@@ -12,6 +12,7 @@ from PySide6.QtCore import Qt, QTimer, QEvent
|
|
|
12
12
|
from shinestacker.config.config import config
|
|
13
13
|
config.init(DISABLE_TQDM=True, DONT_USE_NATIVE_MENU=True)
|
|
14
14
|
from shinestacker.config.constants import constants
|
|
15
|
+
from shinestacker.config.settings import StdPathFile
|
|
15
16
|
from shinestacker.core.logging import setup_logging
|
|
16
17
|
from shinestacker.gui.main_window import MainWindow
|
|
17
18
|
from shinestacker.app.gui_utils import (
|
|
@@ -57,7 +58,8 @@ project filename.
|
|
|
57
58
|
''')
|
|
58
59
|
add_project_arguments(parser)
|
|
59
60
|
args = vars(parser.parse_args(sys.argv[1:]))
|
|
60
|
-
setup_logging(console_level=logging.DEBUG, file_level=logging.DEBUG, disable_console=True
|
|
61
|
+
setup_logging(console_level=logging.DEBUG, file_level=logging.DEBUG, disable_console=True,
|
|
62
|
+
log_file=StdPathFile('shinestacker.log').get_file_path())
|
|
61
63
|
app = Application(sys.argv)
|
|
62
64
|
if config.DONT_USE_NATIVE_MENU:
|
|
63
65
|
app.setAttribute(Qt.AA_DontUseNativeMenuBar)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pylint: disable=C0114, C0115, C0116, C0413, E0611, R0903, E1121, W0201
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
|
+
import logging
|
|
4
5
|
import argparse
|
|
5
6
|
from PySide6.QtWidgets import QApplication, QMenu
|
|
6
7
|
from PySide6.QtGui import QIcon
|
|
@@ -8,6 +9,8 @@ from PySide6.QtCore import Qt, QEvent
|
|
|
8
9
|
from shinestacker.config.config import config
|
|
9
10
|
config.init(DISABLE_TQDM=True, DONT_USE_NATIVE_MENU=True)
|
|
10
11
|
from shinestacker.config.constants import constants
|
|
12
|
+
from shinestacker.config.settings import StdPathFile
|
|
13
|
+
from shinestacker.core.logging import setup_logging
|
|
11
14
|
from shinestacker.retouch.image_editor_ui import ImageEditorUI
|
|
12
15
|
from shinestacker.app.gui_utils import (
|
|
13
16
|
disable_macos_special_menu_items, fill_app_menu, set_css_style)
|
|
@@ -54,6 +57,8 @@ Multiple files can be specified separated by ';'.
|
|
|
54
57
|
if filename and path:
|
|
55
58
|
print("can't specify both arguments --filename and --path", file=sys.stderr)
|
|
56
59
|
sys.exit(1)
|
|
60
|
+
setup_logging(console_level=logging.DEBUG, file_level=logging.DEBUG, disable_console=True,
|
|
61
|
+
log_file=StdPathFile('shinestacker.log').get_file_path())
|
|
57
62
|
app = Application(sys.argv)
|
|
58
63
|
if config.DONT_USE_NATIVE_MENU:
|
|
59
64
|
app.setAttribute(Qt.AA_DontUseNativeMenuBar)
|
|
@@ -26,19 +26,10 @@ def make_tqdm_bar(name, size, ncols=80):
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def get_app_base_path():
|
|
29
|
-
sep = '\\' if (platform.system() == 'Windows') else '/'
|
|
30
29
|
if getattr(sys, 'frozen', False):
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
for i in range(len(dirs) - 1, -1, -1):
|
|
35
|
-
if dirs[i] == 'shinestacker':
|
|
36
|
-
last = i
|
|
37
|
-
break
|
|
38
|
-
path = sep.join(dirs if last == 1 else dirs[:last + 1])
|
|
39
|
-
elif __file__:
|
|
40
|
-
path = sep.join(os.path.dirname(os.path.abspath(__file__)).split(sep)[:-3])
|
|
41
|
-
return path
|
|
30
|
+
return os.path.dirname(os.path.abspath(sys.executable))
|
|
31
|
+
else:
|
|
32
|
+
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
42
33
|
|
|
43
34
|
|
|
44
35
|
def running_under_windows() -> bool:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# pylint: disable=C0114, C0115, C0116
|
|
2
|
+
import os
|
|
2
3
|
import logging
|
|
3
4
|
import sys
|
|
4
5
|
from pathlib import Path
|
|
@@ -64,8 +65,8 @@ def setup_logging(console_level=logging.INFO, file_level=logging.DEBUG, log_file
|
|
|
64
65
|
if log_file == '':
|
|
65
66
|
today = datetime.date.today().strftime("%Y-%m-%d")
|
|
66
67
|
log_file = f"logs/{constants.APP_STRING.lower()}-{today}.log"
|
|
67
|
-
if log_file
|
|
68
|
-
log_file =
|
|
68
|
+
if not os.path.isabs(log_file):
|
|
69
|
+
log_file = os.path.join(get_app_base_path(), {log_file})
|
|
69
70
|
Path(log_file).parent.mkdir(parents=True, exist_ok=True)
|
|
70
71
|
file_handler = logging.FileHandler(log_file)
|
|
71
72
|
file_handler.setLevel(file_level)
|
|
@@ -157,7 +157,7 @@ class BaseFilter(QObject, LayerCollectionHandler):
|
|
|
157
157
|
except Exception:
|
|
158
158
|
h, w = self.master_layer_copy().shape[:2]
|
|
159
159
|
try:
|
|
160
|
-
self.undo_manager.
|
|
160
|
+
self.undo_manager.set_paint_area(0, 0, w, h)
|
|
161
161
|
self.undo_manager.save_undo_state(
|
|
162
162
|
self.master_layer_copy(),
|
|
163
163
|
self.name
|
|
@@ -215,7 +215,7 @@ class DisplayManager(QObject, LayerCollectionHandler):
|
|
|
215
215
|
def refresh_master_view(self):
|
|
216
216
|
if self.has_no_master_layer():
|
|
217
217
|
return
|
|
218
|
-
self.image_viewer.
|
|
218
|
+
self.image_viewer.update_master_display_area()
|
|
219
219
|
self.update_master_thumbnail()
|
|
220
220
|
|
|
221
221
|
def refresh_current_view(self):
|
|
@@ -229,7 +229,6 @@ class DisplayManager(QObject, LayerCollectionHandler):
|
|
|
229
229
|
self.status_message_requested.emit("Temporary view: Individual layer.")
|
|
230
230
|
else:
|
|
231
231
|
self._master_refresh_and_thumb()
|
|
232
|
-
self.image_viewer.strategy.brush_preview.hide()
|
|
233
232
|
self.status_message_requested.emit("Temporary view: Master.")
|
|
234
233
|
|
|
235
234
|
def end_temp_view(self):
|