shinestacker 1.2.1__py3-none-any.whl → 1.3.1__py3-none-any.whl

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.

Files changed (46) hide show
  1. shinestacker/_version.py +1 -1
  2. shinestacker/algorithms/align.py +152 -112
  3. shinestacker/algorithms/align_auto.py +76 -0
  4. shinestacker/algorithms/align_parallel.py +336 -0
  5. shinestacker/algorithms/balance.py +3 -1
  6. shinestacker/algorithms/base_stack_algo.py +25 -22
  7. shinestacker/algorithms/depth_map.py +9 -14
  8. shinestacker/algorithms/multilayer.py +8 -8
  9. shinestacker/algorithms/noise_detection.py +10 -10
  10. shinestacker/algorithms/pyramid.py +10 -24
  11. shinestacker/algorithms/pyramid_auto.py +21 -24
  12. shinestacker/algorithms/pyramid_tiles.py +31 -25
  13. shinestacker/algorithms/stack.py +21 -17
  14. shinestacker/algorithms/stack_framework.py +98 -47
  15. shinestacker/algorithms/utils.py +16 -0
  16. shinestacker/algorithms/vignetting.py +13 -10
  17. shinestacker/app/gui_utils.py +10 -0
  18. shinestacker/app/main.py +10 -4
  19. shinestacker/app/project.py +3 -1
  20. shinestacker/app/retouch.py +3 -1
  21. shinestacker/config/constants.py +60 -25
  22. shinestacker/config/gui_constants.py +1 -1
  23. shinestacker/core/core_utils.py +4 -0
  24. shinestacker/core/framework.py +104 -23
  25. shinestacker/gui/action_config.py +4 -5
  26. shinestacker/gui/action_config_dialog.py +409 -239
  27. shinestacker/gui/base_form_dialog.py +2 -2
  28. shinestacker/gui/colors.py +1 -0
  29. shinestacker/gui/folder_file_selection.py +106 -0
  30. shinestacker/gui/gui_run.py +12 -10
  31. shinestacker/gui/main_window.py +10 -5
  32. shinestacker/gui/new_project.py +171 -73
  33. shinestacker/gui/project_controller.py +10 -6
  34. shinestacker/gui/project_converter.py +4 -2
  35. shinestacker/gui/project_editor.py +40 -28
  36. shinestacker/gui/select_path_widget.py +1 -1
  37. shinestacker/gui/sys_mon.py +97 -0
  38. shinestacker/gui/time_progress_bar.py +4 -3
  39. shinestacker/retouch/exif_data.py +1 -1
  40. shinestacker/retouch/image_editor_ui.py +2 -0
  41. {shinestacker-1.2.1.dist-info → shinestacker-1.3.1.dist-info}/METADATA +6 -6
  42. {shinestacker-1.2.1.dist-info → shinestacker-1.3.1.dist-info}/RECORD +46 -42
  43. {shinestacker-1.2.1.dist-info → shinestacker-1.3.1.dist-info}/WHEEL +0 -0
  44. {shinestacker-1.2.1.dist-info → shinestacker-1.3.1.dist-info}/entry_points.txt +0 -0
  45. {shinestacker-1.2.1.dist-info → shinestacker-1.3.1.dist-info}/licenses/LICENSE +0 -0
  46. {shinestacker-1.2.1.dist-info → shinestacker-1.3.1.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,8 @@
1
- # pylint: disable=C0114, C0115, C0116, R0904, R1702, R0917, R0913, R0902, E0611, E1131, E1121
1
+ # pylint: disable=C0114, C0115, C0116, R0903, R0904, R1702, R0917, R0913, R0902, E0611, E1131, E1121
2
2
  import os
3
3
  from dataclasses import dataclass
4
- from PySide6.QtWidgets import (QListWidget, QMessageBox,
5
- QDialog, QListWidgetItem, QLabel)
6
- from PySide6.QtCore import Qt, QObject, Signal
4
+ from PySide6.QtWidgets import QListWidget, QMessageBox, QDialog, QListWidgetItem, QLabel
5
+ from PySide6.QtCore import Qt, QObject, Signal, QEvent
7
6
  from .. config.constants import constants
8
7
  from .colors import ColorPalette
9
8
  from .action_config_dialog import ActionConfigDialog
@@ -101,6 +100,25 @@ class ProjectUndoManager(QObject):
101
100
  self.set_enabled_undo_action_requested.emit(False, '')
102
101
 
103
102
 
103
+ class HandCursorListWidget(QListWidget):
104
+ def __init__(self, parent=None):
105
+ super().__init__(parent)
106
+ self.setMouseTracking(True)
107
+ self.viewport().setMouseTracking(True)
108
+
109
+ def event(self, event):
110
+ if event.type() == QEvent.HoverMove:
111
+ pos = event.position().toPoint()
112
+ item = self.itemAt(pos)
113
+ if item:
114
+ self.viewport().setCursor(Qt.PointingHandCursor)
115
+ else:
116
+ self.viewport().setCursor(Qt.ArrowCursor)
117
+ elif event.type() == QEvent.Leave:
118
+ self.viewport().setCursor(Qt.ArrowCursor)
119
+ return super().event(event)
120
+
121
+
104
122
  class ProjectEditor(QObject):
105
123
  INDENT_SPACE = "   ↪   "
106
124
  CLONE_POSTFIX = " (clone)"
@@ -117,8 +135,8 @@ class ProjectEditor(QObject):
117
135
  self._project = None
118
136
  self._copy_buffer = None
119
137
  self._current_file_path = ''
120
- self._job_list = QListWidget()
121
- self._action_list = QListWidget()
138
+ self._job_list = HandCursorListWidget()
139
+ self._action_list = HandCursorListWidget()
122
140
  self.dialog = None
123
141
 
124
142
  def reset_undo(self):
@@ -246,38 +264,30 @@ class ProjectEditor(QObject):
246
264
  txt = f"{job.params.get('name', '(job)')}"
247
265
  if html:
248
266
  txt = f"<b>{txt}</b>"
249
- in_path = get_action_input_path(job)
250
- return txt + (f" [⚙️ Job: 📁 {in_path[0]} → 📂 ...]" if long_name else "")
267
+ in_path = get_action_input_path(job)[0]
268
+ if os.path.isabs(in_path):
269
+ in_path = ".../" + os.path.basename(in_path)
270
+ ico = constants.ACTION_ICONS[constants.ACTION_JOB]
271
+ return txt + (f" [{ico}Job] - 📁 {in_path} → 📂 ..." if long_name else "")
251
272
 
252
273
  def action_text(self, action, is_sub_action=False, indent=True, long_name=False, html=False):
253
- icon_map = {
254
- constants.ACTION_COMBO: '⚡',
255
- constants.ACTION_NOISEDETECTION: '🌫',
256
- constants.ACTION_FOCUSSTACK: '🎯',
257
- constants.ACTION_FOCUSSTACKBUNCH: '🖇',
258
- constants.ACTION_MULTILAYER: '🎞️',
259
- constants.ACTION_MASKNOISE: '🎭',
260
- constants.ACTION_VIGNETTING: '⭕️',
261
- constants.ACTION_ALIGNFRAMES: '📐',
262
- constants.ACTION_BALANCEFRAMES: '🌈'
263
- }
264
- ico = icon_map.get(action.type_name, '')
274
+ ico = constants.ACTION_ICONS.get(action.type_name, '')
265
275
  if is_sub_action and indent:
266
276
  txt = self.INDENT_SPACE
267
- if ico == '':
268
- ico = '🟣'
269
277
  else:
270
278
  txt = ''
271
- if ico == '':
272
- ico = '🔵'
273
279
  if action.params.get('name', '') != '':
274
280
  txt += f"{action.params['name']}"
275
281
  if html:
276
282
  txt = f"<b>{txt}</b>"
277
- in_path, out_path = get_action_input_path(action), get_action_output_path(action)
278
- return f"{txt} [{ico} {action.type_name}" + \
279
- (f": 📁 <i>{in_path[0]}</i> → 📂 <i>{out_path[0]}</i>]"
280
- if long_name and not is_sub_action else "]")
283
+ in_path, out_path = get_action_input_path(action)[0], get_action_output_path(action)[0]
284
+ if os.path.isabs(in_path):
285
+ in_path = ".../" + os.path.basename(in_path)
286
+ if os.path.isabs(out_path):
287
+ out_path = ".../" + os.path.basename(out_path)
288
+ return f"{txt} [{ico}{action.type_name}]" + \
289
+ (f" - 📁 <i>{in_path}</i> → 📂 <i>{out_path}</i>"
290
+ if long_name and not is_sub_action else "")
281
291
 
282
292
  def get_job_at(self, index):
283
293
  return None if index < 0 else self.project_job(index)
@@ -485,6 +495,8 @@ class ProjectEditor(QObject):
485
495
  text = self.action_text(action, long_name=True, html=True, is_sub_action=is_sub_action)
486
496
  item = QListWidgetItem()
487
497
  item.setText('')
498
+ item.setToolTip("<b>Double-click:</b> configure parameters<br>"
499
+ "<b>Right-click:</b> show menu")
488
500
  item.setData(Qt.ItemDataRole.UserRole, True)
489
501
  widget_list.addItem(item)
490
502
  html_text = f"✅ <span style='color:#{ColorPalette.DARK_BLUE.hex()};'>{text}</span>" \
@@ -29,4 +29,4 @@ def create_select_file_paths_widget(value, placeholder, tag):
29
29
  if path:
30
30
  edit.setText(path)
31
31
 
32
- return edit, create_layout_widget_and_connect(button, edit, browse)
32
+ return create_layout_widget_and_connect(button, edit, browse)
@@ -0,0 +1,97 @@
1
+ # pylint: disable=C0114, C0115, C0116, E0611
2
+ import psutil
3
+ from PySide6.QtWidgets import QWidget, QHBoxLayout, QLabel, QProgressBar, QSizePolicy
4
+ from PySide6.QtCore import QTimer, Qt
5
+ from .colors import ColorPalette
6
+
7
+
8
+ class StatusBarSystemMonitor(QWidget):
9
+ def __init__(self, parent=None):
10
+ super().__init__(parent)
11
+ self.setup_ui()
12
+ self.setup_timer()
13
+ self.setFixedHeight(28)
14
+
15
+ def setup_ui(self):
16
+ bar_width = 100
17
+ bar_height = 22
18
+ layout = QHBoxLayout()
19
+ layout.setSpacing(10)
20
+ layout.setContentsMargins(0, 2, 0, 0)
21
+ layout.setAlignment(Qt.AlignLeft)
22
+ layout.setAlignment(Qt.AlignCenter)
23
+ cpu_widget = QWidget()
24
+ cpu_widget.setFixedSize(bar_width, bar_height)
25
+ self.cpu_bar = QProgressBar(cpu_widget)
26
+ self.cpu_bar.setRange(0, 100)
27
+ self.cpu_bar.setTextVisible(False)
28
+ self.cpu_bar.setGeometry(0, 0, bar_width, bar_height)
29
+ self.cpu_bar.setStyleSheet(f"""
30
+ QProgressBar {{
31
+ border: 1px solid #cccccc;
32
+ border-radius: 5px;
33
+ background: #F0F0F0;
34
+ }}
35
+ QProgressBar::chunk {{
36
+ background-color: #{ColorPalette.LIGHT_BLUE.hex()};
37
+ border-radius: 5px;
38
+ }}
39
+ """)
40
+ self.cpu_label = QLabel("CPU: --%", cpu_widget)
41
+ self.cpu_label.setAlignment(Qt.AlignCenter)
42
+ self.cpu_label.setGeometry(0, 0, bar_width, bar_height)
43
+ self.cpu_label.setStyleSheet(f"""
44
+ QLabel {{
45
+ color: #{ColorPalette.DARK_BLUE.hex()};
46
+ font-weight: bold;
47
+ background: transparent;
48
+ font-size: 12px;
49
+ }}
50
+ """)
51
+ mem_widget = QWidget()
52
+ mem_widget.setFixedSize(bar_width, bar_height)
53
+ self.mem_bar = QProgressBar(mem_widget)
54
+ self.mem_bar.setRange(0, 100)
55
+ self.mem_bar.setTextVisible(False)
56
+ self.mem_bar.setGeometry(0, 0, bar_width, bar_height)
57
+ self.mem_bar.setStyleSheet(f"""
58
+ QProgressBar {{
59
+ border: 1px solid #CCCCCC;
60
+ border-radius: 5px;
61
+ background: #f0f0f0;
62
+ }}
63
+ QProgressBar::chunk {{
64
+ background-color: #{ColorPalette.LIGHT_GREEN.hex()};
65
+ border-radius: 5px;
66
+ }}
67
+ """)
68
+ self.mem_label = QLabel("MEM: --%", mem_widget)
69
+ self.mem_label.setAlignment(Qt.AlignCenter)
70
+ self.mem_label.setGeometry(0, 0, bar_width, bar_height)
71
+ self.mem_label.setStyleSheet(f"""
72
+ QLabel {{
73
+ color: #{ColorPalette.DARK_BLUE.hex()};
74
+ font-weight: bold;
75
+ background: transparent;
76
+ font-size: 12px;
77
+ }}
78
+ """)
79
+ layout.addWidget(cpu_widget)
80
+ layout.addWidget(mem_widget)
81
+ layout.addStretch()
82
+ self.setLayout(layout)
83
+ self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
84
+
85
+ def setup_timer(self):
86
+ self.timer = QTimer()
87
+ self.timer.timeout.connect(self.update_stats)
88
+ self.timer.start(1000)
89
+
90
+ def update_stats(self):
91
+ cpu_percent = psutil.cpu_percent()
92
+ memory = psutil.virtual_memory()
93
+ mem_percent = memory.percent
94
+ self.cpu_bar.setValue(int(cpu_percent))
95
+ self.cpu_label.setText(f"CPU: {cpu_percent:.1f}%")
96
+ self.mem_bar.setValue(int(mem_percent))
97
+ self.mem_label.setText(f"MEM: {mem_percent:.1f}%")
@@ -39,13 +39,14 @@ class TimerProgressBar(QProgressBar):
39
39
  """)
40
40
 
41
41
  def time_str(self, secs):
42
- x = secs % 1
43
- ss = int(secs // 1)
42
+ xsecs = int(secs * 10)
43
+ x = xsecs % 10
44
+ ss = xsecs // 10
44
45
  s = ss % 60
45
46
  mm = ss // 60
46
47
  m = mm % 60
47
48
  h = mm // 60
48
- t_str = f"{s:02d}" + f"{x:.1f}s".lstrip('0')
49
+ t_str = f"{s:02d}.{x:1d}s"
49
50
  if m > 0:
50
51
  t_str = f"{m:02d}:{t_str}"
51
52
  if h > 0:
@@ -9,7 +9,7 @@ from .. gui.base_form_dialog import BaseFormDialog
9
9
 
10
10
  class ExifData(BaseFormDialog):
11
11
  def __init__(self, exif, parent=None):
12
- super().__init__("EXIF data", parent)
12
+ super().__init__("EXIF data", parent=parent)
13
13
  self.exif = exif
14
14
  self.create_form()
15
15
  button_container = QWidget()
@@ -658,6 +658,8 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
658
658
  def quit(self):
659
659
  if self.check_unsaved_changes():
660
660
  self.close()
661
+ return True
662
+ return False
661
663
 
662
664
  def undo(self):
663
665
  if self.undo_manager.undo(self.master_layer()):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shinestacker
3
- Version: 1.2.1
3
+ Version: 1.3.1
4
4
  Summary: ShineStacker
5
5
  Author-email: Luca Lista <luka.lista@gmail.com>
6
6
  License-Expression: LGPL-3.0
@@ -20,6 +20,7 @@ Requires-Dist: numpy
20
20
  Requires-Dist: opencv_python
21
21
  Requires-Dist: pillow
22
22
  Requires-Dist: psdtags
23
+ Requires-Dist: psutil
23
24
  Requires-Dist: PySide6
24
25
  Requires-Dist: scipy
25
26
  Requires-Dist: tifffile
@@ -69,6 +70,10 @@ The GUI has two main working areas:
69
70
 
70
71
  <img src='https://raw.githubusercontent.com/lucalista/shinestacker/main/img/gui-retouch.png' width="600" referrerpolicy="no-referrer">
71
72
 
73
+ # Resources
74
+
75
+ 🌍 [Website on WordPress](https://shinestacker.wordpress.com) • 📖 [Main documentation](https://shinestacker.readthedocs.io) • 📝 [Changelog](https://github.com/lucalista/shinestacker/blob/main/CHANGELOG.md)
76
+
72
77
  # Note for macOS users
73
78
 
74
79
  **The following note is only relevant if you download the application as compressed archive from the [release page](https://github.com/lucalista/shinestacker/releases).**
@@ -88,11 +93,6 @@ xattr -cr ~/Downloads/shinestacker/shinestacker.app
88
93
 
89
94
  macOS adds a quarantine flag to all files downloaded from the internet. The above command removes that flag while preserving all other application functionality.
90
95
 
91
- # Resources
92
-
93
- 🌍 [Website on WordPress](https://shinestacker.wordpress.com) • 📖 [Main documentation](https://shinestacker.readthedocs.io) • 📝 [Changelog](https://github.com/lucalista/shinestacker/blob/main/CHANGELOG.md)
94
-
95
-
96
96
  # Credits
97
97
 
98
98
  The first version of the core focus stack algorithm was initially inspired by the [Laplacian pyramids method](https://github.com/sjawhar/focus-stacking) implementation by Sami Jawhar that was used under permission of the author. The implementation in the latest releases was rewritten from the original code.
@@ -1,60 +1,64 @@
1
1
  shinestacker/__init__.py,sha256=uq2fjAw2z_6TpH3mOcWFZ98GoEPRsNhTAK8N0MMm_e8,448
2
- shinestacker/_version.py,sha256=VvDq5py76uDFeq6tv3EFMgTHX4rtDyt6nw0tPm3Wrkk,21
2
+ shinestacker/_version.py,sha256=U9SSjW6vREFTPVkV-L7VR9upz56SvAyLuYgaMCMvw0E,21
3
3
  shinestacker/algorithms/__init__.py,sha256=1FwVJ3w9GGbFFkjYJRUedTvcdE4j0ieSgaH9RC9iCY4,877
4
- shinestacker/algorithms/align.py,sha256=PvjxHgP4Q19jmt6LS3nGcimCOywHglmxXMlfxo7dCjc,22641
5
- shinestacker/algorithms/balance.py,sha256=Rj4dPvEiXBb0VNJPJd60wYYgevlO7xmg7H9Onxmabbs,23508
6
- shinestacker/algorithms/base_stack_algo.py,sha256=W-VSrCF0-lE_OOsxsnZvJ3BI0NqRKIRMciQV-ui5t_g,2515
4
+ shinestacker/algorithms/align.py,sha256=V6JUTk9zTntnlSbltJnlli32Yl7n3ozWg4PBJQOx190,23735
5
+ shinestacker/algorithms/align_auto.py,sha256=pJetw6zZEWQLouzcelkI8gD4cPiOp887ePXzVbm0E6Q,3800
6
+ shinestacker/algorithms/align_parallel.py,sha256=s4BlLRLDcIFOzZIQEM49rhilyu_Uy15-IeyN0nDbdno,16985
7
+ shinestacker/algorithms/balance.py,sha256=KJ8eXWYyqRVQa7_iZWQhZZ9BfO4wNve5nhZxunK7B5k,23583
8
+ shinestacker/algorithms/base_stack_algo.py,sha256=RzxvLDHqxqhnAl83u2onjvfsRea1qGK_blbh2Vo0kxA,2670
7
9
  shinestacker/algorithms/denoise.py,sha256=GL3Z4_6MHxSa7Wo4ZzQECZS87tHBFqO0sIVF_jPuYQU,426
8
- shinestacker/algorithms/depth_map.py,sha256=m0_Qm8FLDeSWyQEMNx29PzXp_VFGar7gY3jWxq_10t8,5713
10
+ shinestacker/algorithms/depth_map.py,sha256=nRBrZQWbdUqFOtYMEQx9UNdnybrBTeAOr1eV91FlN8U,5611
9
11
  shinestacker/algorithms/exif.py,sha256=SM4ZDDe8hCJ3xY6053FNndOiwzEStzdp0WrXurlcHVc,9429
10
- shinestacker/algorithms/multilayer.py,sha256=SfF51orenT3k15St_EUJcwnfOZ8Y5X5ZhStOWygjn1g,9838
11
- shinestacker/algorithms/noise_detection.py,sha256=Ku0xgc_FFHzycSObDNXAux5scP3PVBeffGoYVdNJci0,9180
12
- shinestacker/algorithms/pyramid.py,sha256=lmd-lw4bzrpcfBaLnBXHuOJ9J7-5sWq4dC9p_EejqXA,8881
13
- shinestacker/algorithms/pyramid_auto.py,sha256=ByDH7Xblqj4YfNwsCWwN3wv2xL6gYp2lFnvpNPSEawM,6161
14
- shinestacker/algorithms/pyramid_tiles.py,sha256=SzjTSheme8MP8nQXfOu8QHbzrtpuQX2aIsBVr5aM4Mc,12165
12
+ shinestacker/algorithms/multilayer.py,sha256=WlB4L5oY9qra3w7Qahg-tqO6S_s3pMB_LmGR8PPR_7w,9904
13
+ shinestacker/algorithms/noise_detection.py,sha256=KSdMDER5GNOCTD6DIAbjJvRDFvrVorul3xr5maXtCh8,9298
14
+ shinestacker/algorithms/pyramid.py,sha256=Z7tlp8Hh3ploAXJCr0VNe33d8H9GNrlqHXq_LapgRwo,8205
15
+ shinestacker/algorithms/pyramid_auto.py,sha256=fl_jXNYLWsBiX0M0UghzCLqai0SGXlmKYHU7Z9SUYSo,6173
16
+ shinestacker/algorithms/pyramid_tiles.py,sha256=ZBWIeifkDOIVFF4SCyspRZHSj6K_1P3dk4WLmuo53RU,12213
15
17
  shinestacker/algorithms/sharpen.py,sha256=h7PMJBYxucg194Usp_6pvItPUMFYbT-ebAc_-7XBFUw,949
16
- shinestacker/algorithms/stack.py,sha256=UN2XHb-x-qXtescUCsOLK8GKSYx26AFpKa2xCMJKhVo,4997
17
- shinestacker/algorithms/stack_framework.py,sha256=Y1uuXYbpCFuPYWumMhx040Q4FkylPwKkz6iXz8ay2aY,11831
18
- shinestacker/algorithms/utils.py,sha256=jImR2XF73gsLRZMic0kv8cyCuO2Zq21tX4kUhaTcfzI,11301
19
- shinestacker/algorithms/vignetting.py,sha256=3E-ulzw8dggAefyJwzQI056J5IGlV_vV2zPrO0DGVGk,10208
18
+ shinestacker/algorithms/stack.py,sha256=V9YX0CbNWrgAo7_uti64rmmuwU6RsRcjDoBpsES4aSE,5137
19
+ shinestacker/algorithms/stack_framework.py,sha256=OMrjD5dKquHQXhM7TfLRExDsqN1n938WWhGAfkPYLZM,13883
20
+ shinestacker/algorithms/utils.py,sha256=oyt2sQQsgcTyemlVcU2hJRSza6ntsXQbG7WhHJTP7a0,11808
21
+ shinestacker/algorithms/vignetting.py,sha256=MwhsTqmNMc6GdQl_Bbuyo8IUQPn1OoeGcWj1L6Jjybc,10274
20
22
  shinestacker/algorithms/white_balance.py,sha256=PMKsBtxOSn5aRr_Gkx1StHS4eN6kBN2EhNnhg4UG24g,501
21
23
  shinestacker/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
24
  shinestacker/app/about_dialog.py,sha256=pkH7nnxUP8yc0D3vRGd1jRb5cwi1nDVbQRk_OC9yLk8,4144
23
- shinestacker/app/gui_utils.py,sha256=08TrCj2gFGsNsF6hG7ySO2y7wcQakM5PzERkeplqNFs,2344
25
+ shinestacker/app/gui_utils.py,sha256=fSpkwPXTON_l676UHdAnJNrGq7BPbSlPOiHpOF_LZaI,2519
24
26
  shinestacker/app/help_menu.py,sha256=g8lKG_xZmXtNQaC3SIRzyROKVWva_PLEgZsQWh6zUcQ,499
25
- shinestacker/app/main.py,sha256=rcXlzsPErIN9ItbucsB6nz103vwNvsff6wSADOwFt6I,10301
27
+ shinestacker/app/main.py,sha256=XdWYUm1ed1q7aPghxgaFwWJVNijCvZZ_WG0fux8Nisc,10459
26
28
  shinestacker/app/open_frames.py,sha256=bsu32iJSYJQLe_tQQbvAU5DuMDVX6MRuNdE7B5lojZc,1488
27
- shinestacker/app/project.py,sha256=W0u715LZne_PNJvg9msSy27ybIjgDXiEAQdJ7_6BjYI,2774
28
- shinestacker/app/retouch.py,sha256=ZQ-nRKnHo6xurcP34RNqaAWkmuGBjJ5jE05hTQ_ycis,2482
29
+ shinestacker/app/project.py,sha256=oopOiqU6bOK1cQdpot88z49KbKrlB-LAz_q4-8Iui0U,2819
30
+ shinestacker/app/retouch.py,sha256=dpSozNWSxL6wIO0SMjoviDbXZbbfRN_rVLjeL324c54,2527
29
31
  shinestacker/config/__init__.py,sha256=aXxi-LmAvXd0daIFrVnTHE5OCaYeK1uf1BKMr7oaXQs,197
30
32
  shinestacker/config/config.py,sha256=eBko2D3ADhLTIm9X6hB_a_WsIjwgfE-qmBVkhP1XSvc,1636
31
- shinestacker/config/constants.py,sha256=M8sKfZdGBhWY_wuJ40F_CEPtspPoYhrva4WFHX5bD6s,7145
32
- shinestacker/config/gui_constants.py,sha256=5DR-ET1oeMMD7lIsjvAwSuln89A7I9wy9VuAeRo2G64,2575
33
+ shinestacker/config/constants.py,sha256=EEdr7pZg4JpbIjUWaP7kJQfTuBB85FN739myDNAfn8A,8301
34
+ shinestacker/config/gui_constants.py,sha256=i2dHeGRnY-Wc3dVjpIEKNNxEQYhfn18IEUcvl96r89I,2575
33
35
  shinestacker/core/__init__.py,sha256=IUEIx6SQ3DygDEHN3_E6uKpHjHtUa4a_U_1dLd_8yEU,484
34
36
  shinestacker/core/colors.py,sha256=kr_tJA1iRsdck2JaYDb2lS-codZ4Ty9gdu3kHfiWvuM,1340
35
- shinestacker/core/core_utils.py,sha256=ulJhzen5McAb5n6wWNA_KB4U_PdTEr-H2TCQkVKUaOw,1421
37
+ shinestacker/core/core_utils.py,sha256=BlHbvQmDQXSONNkDx0zq_xiDTsfrS0N7r1DBTUPm8CE,1523
36
38
  shinestacker/core/exceptions.py,sha256=2-noG-ORAGdvDhL8jBQFs0xxZS4fI6UIkMqrWekgk2c,1618
37
- shinestacker/core/framework.py,sha256=9uAvITAmzWnKFApLNtPf6Ah7nGJAxQ3I5nw_b2sVGQA,7628
39
+ shinestacker/core/framework.py,sha256=QaTfnzEUHwzlbyFG7KzeyteckTSWHWEEJE4d5Tc8H18,11015
38
40
  shinestacker/core/logging.py,sha256=9SuSSy9Usbh7zqmLYMqkmy-VBkOJW000lwqAR0XQs30,3067
39
41
  shinestacker/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- shinestacker/gui/action_config.py,sha256=xwJfNJwYbccL9M74NObjUc4_-EBVoHN5qDdToE19rMs,19075
41
- shinestacker/gui/action_config_dialog.py,sha256=0j6oJfNGdZ9b9-ns0k7fM_iiD9jlMmVeCEEfzO3drpw,35134
42
- shinestacker/gui/base_form_dialog.py,sha256=M_BvjpqUWe9YuecKg0pF3vUJ-1mqF24HjKujst2j3BA,753
43
- shinestacker/gui/colors.py,sha256=m0pQQ-uvtIN1xmb_-N06BvC7pZYZZnq59ZSEJwutHuk,1432
42
+ shinestacker/gui/action_config.py,sha256=BhKssL0xHPdNkE5hDkBy7Uw5rZOLZ8PU8hz-Nt_CdwA,19038
43
+ shinestacker/gui/action_config_dialog.py,sha256=IRK0RkGEBjGY351xalRc87cZb1HyWZdufnLa__vYCO0,43787
44
+ shinestacker/gui/base_form_dialog.py,sha256=KAUQNtmJazttmOIe4E4pFifbtvcByTAhtCmcIYeA4UE,766
45
+ shinestacker/gui/colors.py,sha256=-HaFprDuzRSKjXoZfX1rdOuvawQAkazqdgLBEiZcFII,1476
44
46
  shinestacker/gui/flow_layout.py,sha256=3yBU_z7VtvHKpx1H97CHVd81eq9pe1Dcja2EZBGGKcI,3791
47
+ shinestacker/gui/folder_file_selection.py,sha256=IYWfZQFkoD5iO7zJ7BxVVDP9F3Dc0EXLILAhL4q-Cb8,4117
45
48
  shinestacker/gui/gui_images.py,sha256=k39DpdsxcmYoRdHNNZj6OpFAas0GOHS4JSG542wfheg,5728
46
49
  shinestacker/gui/gui_logging.py,sha256=kiZcrC2AFYCWgPZo0O5SKw-E5cFrezwf4anS3HjPuNw,8168
47
- shinestacker/gui/gui_run.py,sha256=KZakfz8AkdagObB-0fLy9JUNau0hIreBHrjdf4ZRXYs,15440
48
- shinestacker/gui/main_window.py,sha256=7zO1U_wGXsg7Owlre21PWwG9CMP5OcEey-aLtH4na0M,24404
50
+ shinestacker/gui/gui_run.py,sha256=MQPE7muBPw3KTrGDsg-MBcC6nNFYuvvojfXfq84kR8o,15759
51
+ shinestacker/gui/main_window.py,sha256=BbGj6JeIpDNICTktYG6F___NXKtMHgVcHsSiqemtw8w,24516
49
52
  shinestacker/gui/menu_manager.py,sha256=ZsND0e-vM263-6unwKUtYAtLbb4YgvIQabh5lCiT2ow,10179
50
- shinestacker/gui/new_project.py,sha256=rlEaMTaxZ9eo5sZP5_zJx-vxPk9t8-I6X_aoYyVT2uQ,11171
51
- shinestacker/gui/project_controller.py,sha256=9uNlt8fghS6QYyUpPyEw54Ia5RxwXLp1FaOtKxKArb8,15905
52
- shinestacker/gui/project_converter.py,sha256=bNyC1_D_MjcTOCPlQln6CIIlX818-sw_j2omrfQIGQs,7279
53
- shinestacker/gui/project_editor.py,sha256=mv_gJHhllAqjttueLKFnJotrtshDpCwh0TYfG6EGBnA,24965
53
+ shinestacker/gui/new_project.py,sha256=VSUaq1xm9CR0gimKHRKfCdQOQ-ErE1sxGmu6x14nlAQ,16113
54
+ shinestacker/gui/project_controller.py,sha256=hvSNGrQM-yDHH3e132oouxBtgRv7mUG7lrigUl21BsA,16043
55
+ shinestacker/gui/project_converter.py,sha256=Gmna0HwbvACcXiX74TaQYumif8ZV8sZ2APLTMM-L1mU,7436
56
+ shinestacker/gui/project_editor.py,sha256=lSgQ42IoaobHs-NQQWT88Qhg5l7nu5ejxAO5VgIupr8,25498
54
57
  shinestacker/gui/project_model.py,sha256=eRUmH3QmRzDtPtZoxgT6amKzN8_5XzwjHgEJeL-_JOE,4263
55
- shinestacker/gui/select_path_widget.py,sha256=OfQImOmkzbvl5BBshmb7ePWrSGDJQ8VvyaAOypHAGd4,1023
58
+ shinestacker/gui/select_path_widget.py,sha256=HSwgSr702w5Et4c-6nkRXnIpm1KFqKJetAF5xQNa5zI,1017
59
+ shinestacker/gui/sys_mon.py,sha256=zU41YYVeqQ1-v6oGIh2_BFzQWq87keN-398Wdm59-Nk,3526
56
60
  shinestacker/gui/tab_widget.py,sha256=VgRmuktWXCgbXbV7c1Tho0--W5_EmmzXPfzRZgwhGfg,2965
57
- shinestacker/gui/time_progress_bar.py,sha256=4_5DT_EzFdVJi5bgd9TEpoTJXeU3M08CF91cZLi75Wc,3016
61
+ shinestacker/gui/time_progress_bar.py,sha256=7_sllrQgayjRh__mwJ0-4lghXIakuRAx8wWucJ6olYs,3028
58
62
  shinestacker/gui/ico/focus_stack_bkg.png,sha256=Q86TgqvKEi_IzKI8m6aZB2a3T40UkDtexf2PdeBM9XE,163151
59
63
  shinestacker/gui/ico/shinestacker.icns,sha256=3IshIOv0uFexYsAEPkE9xiyuw8mB5X5gffekOUhFlt0,45278
60
64
  shinestacker/gui/ico/shinestacker.ico,sha256=8IMRk-toObWUz8iDXA-zHBWQ8Ps3vXN5u5ZEyw7sP3c,109613
@@ -72,11 +76,11 @@ shinestacker/retouch/brush_preview.py,sha256=QKD3pL7n7YJbIibinUFYKv7lkyq_AWLpt6o
72
76
  shinestacker/retouch/brush_tool.py,sha256=nxnEuvTioPNw1WeWsT20X1zl-LNZ8i-1ExOcihikEjk,8618
73
77
  shinestacker/retouch/denoise_filter.py,sha256=TDUHzhRKlKvCa3D5SCYCZKTpjcl81kGwmONsgSDtO1k,440
74
78
  shinestacker/retouch/display_manager.py,sha256=XPbOBmoYc_jNA791WkWkOSaFHb0ztCZechl2p2KSlwQ,9597
75
- shinestacker/retouch/exif_data.py,sha256=WF40bTh0bwIqSQLMkGMCycEED06_q35-TqrBNAyaB-k,1889
79
+ shinestacker/retouch/exif_data.py,sha256=LF-fRXW-reMq-xJ_QRE5j8DC2LVGKIlC6MR3QbC1cdg,1896
76
80
  shinestacker/retouch/file_loader.py,sha256=z02-A8_uDZxayI1NFTxT2GVUvEBWStchX9hlN1o5-0U,4784
77
81
  shinestacker/retouch/filter_manager.py,sha256=SdYIZkZBUvuB6wDG0moGWav5sfEvIcB9ioUJR5wJFts,388
78
82
  shinestacker/retouch/icon_container.py,sha256=6gw1HO1bC2FrdB4dc_iH81DQuLjzuvRGksZ2hKLT9yA,585
79
- shinestacker/retouch/image_editor_ui.py,sha256=cMGiqyPGqJmBaXMAc0WImDPf_hmxO4KiJtaaSpiW9EU,29869
83
+ shinestacker/retouch/image_editor_ui.py,sha256=eYOHR_ihekQ7bWZUk7jXqNDpi5WYOAyTgvi3_QxnmTE,29914
80
84
  shinestacker/retouch/image_viewer.py,sha256=3ebrLHTDtGd_EbIT2nNFRUjH836rblmmK7jZ62YcJ2U,19564
81
85
  shinestacker/retouch/io_gui_handler.py,sha256=pT-49uP0GROMOjZ70LoMLgXHnqSDq8ieAlAKGw0t1TM,11418
82
86
  shinestacker/retouch/io_manager.py,sha256=JUAA--AK0mVa1PTErJTnBFjaXIle5Qs7Ow0Wkd8at0o,2437
@@ -86,9 +90,9 @@ shinestacker/retouch/undo_manager.py,sha256=_ekbcOLcPbQLY7t-o8wf-b1uA6OPY9rRyLM-
86
90
  shinestacker/retouch/unsharp_mask_filter.py,sha256=uFnth8fpZFGhdIgJCnS8x5v6lBQgJ3hX0CBke9pFXeM,3510
87
91
  shinestacker/retouch/vignetting_filter.py,sha256=MA97rQkSL0D-Nh-n2L4AiPR064RoTROkvza4tw84g9U,3658
88
92
  shinestacker/retouch/white_balance_filter.py,sha256=glMBYlmrF-i_OrB3sGUpjZE6X4FQdyLC4GBy2bWtaFc,6056
89
- shinestacker-1.2.1.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
90
- shinestacker-1.2.1.dist-info/METADATA,sha256=6Cdeb52FCCmc0H48Ru2ydN6McvhemfdzB9Ye2bdCMhw,6951
91
- shinestacker-1.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
92
- shinestacker-1.2.1.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
93
- shinestacker-1.2.1.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
94
- shinestacker-1.2.1.dist-info/RECORD,,
93
+ shinestacker-1.3.1.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
94
+ shinestacker-1.3.1.dist-info/METADATA,sha256=uKow_yD_ono611Nztz8cszW4tVsMaGieF2Qfongsds0,6972
95
+ shinestacker-1.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
96
+ shinestacker-1.3.1.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
97
+ shinestacker-1.3.1.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
98
+ shinestacker-1.3.1.dist-info/RECORD,,