shinestacker 0.4.0__py3-none-any.whl → 1.0.0__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.
- shinestacker/_version.py +1 -1
- shinestacker/algorithms/align.py +4 -12
- shinestacker/algorithms/balance.py +11 -9
- shinestacker/algorithms/depth_map.py +0 -30
- shinestacker/algorithms/utils.py +10 -0
- shinestacker/algorithms/vignetting.py +116 -70
- shinestacker/app/about_dialog.py +101 -12
- shinestacker/app/gui_utils.py +1 -1
- shinestacker/app/help_menu.py +1 -1
- shinestacker/app/main.py +2 -2
- shinestacker/app/project.py +2 -2
- shinestacker/config/constants.py +4 -1
- shinestacker/config/gui_constants.py +10 -9
- shinestacker/gui/action_config.py +5 -561
- shinestacker/gui/action_config_dialog.py +567 -0
- shinestacker/gui/base_form_dialog.py +18 -0
- shinestacker/gui/colors.py +5 -6
- shinestacker/gui/gui_logging.py +0 -1
- shinestacker/gui/gui_run.py +54 -106
- shinestacker/gui/ico/shinestacker.icns +0 -0
- shinestacker/gui/ico/shinestacker.ico +0 -0
- shinestacker/gui/ico/shinestacker.png +0 -0
- shinestacker/gui/ico/shinestacker.svg +60 -0
- shinestacker/gui/main_window.py +276 -367
- shinestacker/gui/menu_manager.py +236 -0
- shinestacker/gui/new_project.py +75 -20
- shinestacker/gui/project_converter.py +6 -6
- shinestacker/gui/project_editor.py +248 -165
- shinestacker/gui/project_model.py +2 -7
- shinestacker/gui/tab_widget.py +81 -0
- shinestacker/gui/time_progress_bar.py +95 -0
- shinestacker/retouch/base_filter.py +173 -40
- shinestacker/retouch/brush_preview.py +0 -10
- shinestacker/retouch/brush_tool.py +25 -11
- shinestacker/retouch/denoise_filter.py +5 -44
- shinestacker/retouch/display_manager.py +57 -20
- shinestacker/retouch/exif_data.py +10 -13
- shinestacker/retouch/file_loader.py +1 -1
- shinestacker/retouch/filter_manager.py +1 -4
- shinestacker/retouch/image_editor_ui.py +365 -49
- shinestacker/retouch/image_viewer.py +34 -11
- shinestacker/retouch/io_gui_handler.py +96 -43
- shinestacker/retouch/io_manager.py +23 -7
- shinestacker/retouch/layer_collection.py +2 -0
- shinestacker/retouch/shortcuts_help.py +12 -0
- shinestacker/retouch/unsharp_mask_filter.py +10 -10
- shinestacker/retouch/vignetting_filter.py +69 -0
- shinestacker/retouch/white_balance_filter.py +46 -14
- {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/METADATA +14 -2
- shinestacker-1.0.0.dist-info/RECORD +90 -0
- shinestacker/app/app_config.py +0 -22
- shinestacker/gui/actions_window.py +0 -258
- shinestacker/retouch/image_editor.py +0 -201
- shinestacker/retouch/image_filters.py +0 -69
- shinestacker-0.4.0.dist-info/RECORD +0 -87
- {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/WHEEL +0 -0
- {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/entry_points.txt +0 -0
- {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/top_level.txt +0 -0
shinestacker/gui/main_window.py
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
# pylint: disable=C0114, C0115, C0116, E0611, R0902, R0915, R0904, R0914
|
|
1
|
+
# pylint: disable=C0114, C0115, C0116, E0611, R0902, R0915, R0904, R0914
|
|
2
|
+
# pylint: disable=R0912, E1101, W0201, E1121, R0913, R0917
|
|
2
3
|
import os
|
|
3
4
|
import subprocess
|
|
4
|
-
from PySide6.
|
|
5
|
-
|
|
6
|
-
from PySide6.
|
|
7
|
-
|
|
5
|
+
from PySide6.QtCore import Qt
|
|
6
|
+
from PySide6.QtGui import QGuiApplication, QAction, QIcon
|
|
7
|
+
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox,
|
|
8
|
+
QSplitter, QToolBar, QMenu, QMainWindow)
|
|
8
9
|
from .. config.constants import constants
|
|
9
|
-
from .. core.core_utils import running_under_windows, running_under_macos
|
|
10
|
+
from .. core.core_utils import running_under_windows, running_under_macos
|
|
10
11
|
from .colors import ColorPalette
|
|
11
12
|
from .project_model import Project
|
|
12
|
-
from .actions_window import ActionsWindow
|
|
13
13
|
from .gui_logging import LogManager
|
|
14
14
|
from .gui_run import RunWindow, RunWorker
|
|
15
15
|
from .project_converter import ProjectConverter
|
|
16
16
|
from .project_model import get_action_working_path, get_action_input_path, get_action_output_path
|
|
17
|
+
from .menu_manager import MenuManager
|
|
18
|
+
from .project_controller import ProjectController
|
|
19
|
+
from .tab_widget import TabWidgetWithPlaceholder
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
class JobLogWorker(RunWorker):
|
|
@@ -45,105 +48,50 @@ LIST_STYLE_SHEET = f"""
|
|
|
45
48
|
"""
|
|
46
49
|
|
|
47
50
|
|
|
48
|
-
class
|
|
49
|
-
# Segnali aggiuntivi per mantenere la compatibilità
|
|
50
|
-
currentChanged = Signal(int)
|
|
51
|
-
tabCloseRequested = Signal(int)
|
|
52
|
-
|
|
53
|
-
def __init__(self, parent=None):
|
|
54
|
-
super().__init__(parent)
|
|
55
|
-
self.layout = QVBoxLayout(self)
|
|
56
|
-
self.layout.setContentsMargins(0, 0, 0, 0)
|
|
57
|
-
self.stacked_widget = QStackedWidget()
|
|
58
|
-
self.layout.addWidget(self.stacked_widget)
|
|
59
|
-
self.tab_widget = QTabWidget()
|
|
60
|
-
self.stacked_widget.addWidget(self.tab_widget)
|
|
61
|
-
self.placeholder = QLabel()
|
|
62
|
-
self.placeholder.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
63
|
-
rel_path = 'ico/focus_stack_bkg.png'
|
|
64
|
-
icon_path = f'{get_app_base_path()}/{rel_path}'
|
|
65
|
-
if not os.path.exists(icon_path):
|
|
66
|
-
icon_path = f'{get_app_base_path()}/../{rel_path}'
|
|
67
|
-
if os.path.exists(icon_path):
|
|
68
|
-
pixmap = QPixmap(icon_path)
|
|
69
|
-
# Ridimensiona mantenendo le proporzioni (es. max 400x400)
|
|
70
|
-
pixmap = pixmap.scaled(250, 250, Qt.AspectRatioMode.KeepAspectRatio,
|
|
71
|
-
Qt.TransformationMode.SmoothTransformation)
|
|
72
|
-
self.placeholder.setPixmap(pixmap)
|
|
73
|
-
else:
|
|
74
|
-
self.placeholder.setText("Run logs will appear here.")
|
|
75
|
-
self.stacked_widget.addWidget(self.placeholder)
|
|
76
|
-
self.tab_widget.currentChanged.connect(self._on_current_changed)
|
|
77
|
-
self.tab_widget.tabCloseRequested.connect(self._on_tab_close_requested)
|
|
78
|
-
self.update_placeholder_visibility()
|
|
79
|
-
|
|
80
|
-
def _on_current_changed(self, index):
|
|
81
|
-
self.currentChanged.emit(index)
|
|
82
|
-
self.update_placeholder_visibility()
|
|
83
|
-
|
|
84
|
-
def _on_tab_close_requested(self, index):
|
|
85
|
-
self.tabCloseRequested.emit(index)
|
|
86
|
-
self.update_placeholder_visibility()
|
|
87
|
-
|
|
88
|
-
def update_placeholder_visibility(self):
|
|
89
|
-
if self.tab_widget.count() == 0:
|
|
90
|
-
self.stacked_widget.setCurrentIndex(1)
|
|
91
|
-
else:
|
|
92
|
-
self.stacked_widget.setCurrentIndex(0)
|
|
93
|
-
|
|
94
|
-
# pylint: disable=C0103
|
|
95
|
-
def addTab(self, widget, label):
|
|
96
|
-
result = self.tab_widget.addTab(widget, label)
|
|
97
|
-
self.update_placeholder_visibility()
|
|
98
|
-
return result
|
|
99
|
-
|
|
100
|
-
def removeTab(self, index):
|
|
101
|
-
result = self.tab_widget.removeTab(index)
|
|
102
|
-
self.update_placeholder_visibility()
|
|
103
|
-
return result
|
|
104
|
-
|
|
105
|
-
def count(self):
|
|
106
|
-
return self.tab_widget.count()
|
|
107
|
-
|
|
108
|
-
def setCurrentIndex(self, index):
|
|
109
|
-
return self.tab_widget.setCurrentIndex(index)
|
|
110
|
-
|
|
111
|
-
def currentIndex(self):
|
|
112
|
-
return self.tab_widget.currentIndex()
|
|
113
|
-
|
|
114
|
-
def currentWidget(self):
|
|
115
|
-
return self.tab_widget.currentWidget()
|
|
116
|
-
|
|
117
|
-
def widget(self, index):
|
|
118
|
-
return self.tab_widget.widget(index)
|
|
119
|
-
|
|
120
|
-
def indexOf(self, widget):
|
|
121
|
-
return self.tab_widget.indexOf(widget)
|
|
122
|
-
# pylint: enable=C0103
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
class MainWindow(ActionsWindow, LogManager):
|
|
51
|
+
class MainWindow(QMainWindow, LogManager):
|
|
126
52
|
def __init__(self):
|
|
127
|
-
|
|
53
|
+
QMainWindow.__init__(self)
|
|
128
54
|
LogManager.__init__(self)
|
|
55
|
+
self.project_controller = ProjectController(self)
|
|
56
|
+
self.project_editor = self.project_controller.project_editor
|
|
57
|
+
actions = {
|
|
58
|
+
"&New...": self.project_controller.new_project,
|
|
59
|
+
"&Open...": self.project_controller.open_project,
|
|
60
|
+
"&Close": self.project_controller.close_project,
|
|
61
|
+
"&Save": self.project_controller.save_project,
|
|
62
|
+
"Save &As...": self.project_controller.save_project_as,
|
|
63
|
+
"&Undo": self.project_editor.undo,
|
|
64
|
+
"&Cut": self.project_editor.cut_element,
|
|
65
|
+
"Cop&y": self.project_editor.copy_element,
|
|
66
|
+
"&Paste": self.project_editor.paste_element,
|
|
67
|
+
"Duplicate": self.project_editor.clone_element,
|
|
68
|
+
"Delete": self.delete_element,
|
|
69
|
+
"Move &Up": self.project_editor.move_element_up,
|
|
70
|
+
"Move &Down": self.project_editor.move_element_down,
|
|
71
|
+
"E&nable": self.project_editor.enable,
|
|
72
|
+
"Di&sable": self.project_editor.disable,
|
|
73
|
+
"Enable All": self.project_editor.enable_all,
|
|
74
|
+
"Disable All": self.project_editor.disable_all,
|
|
75
|
+
"Expert Options": self.toggle_expert_options,
|
|
76
|
+
"Add Job": self.project_editor.add_job,
|
|
77
|
+
"Run Job": self.run_job,
|
|
78
|
+
"Run All Jobs": self.run_all_jobs,
|
|
79
|
+
}
|
|
80
|
+
self.menu_manager = MenuManager(self.menuBar(), actions, self.project_editor, self)
|
|
81
|
+
self.script_dir = os.path.dirname(__file__)
|
|
129
82
|
self._windows = []
|
|
130
83
|
self._workers = []
|
|
131
84
|
self.retouch_callback = None
|
|
132
|
-
self.
|
|
133
|
-
self.
|
|
134
|
-
|
|
135
|
-
self.
|
|
136
|
-
self.add_edit_menu(menubar)
|
|
137
|
-
self.add_view_menu(menubar)
|
|
138
|
-
self.add_job_menu(menubar)
|
|
139
|
-
self.add_actions_menu(menubar)
|
|
140
|
-
self.add_help_menu(menubar)
|
|
85
|
+
self.expert_options = False
|
|
86
|
+
self.job_list().setStyleSheet(LIST_STYLE_SHEET)
|
|
87
|
+
self.action_list().setStyleSheet(LIST_STYLE_SHEET)
|
|
88
|
+
self.menu_manager.add_menus()
|
|
141
89
|
toolbar = QToolBar(self)
|
|
142
90
|
self.addToolBar(Qt.TopToolBarArea, toolbar)
|
|
143
|
-
self.fill_toolbar(toolbar)
|
|
91
|
+
self.menu_manager.fill_toolbar(toolbar)
|
|
144
92
|
self.resize(1200, 800)
|
|
145
|
-
|
|
146
|
-
|
|
93
|
+
self.move(QGuiApplication.primaryScreen().geometry().center() -
|
|
94
|
+
self.rect().center())
|
|
147
95
|
self.set_project(Project())
|
|
148
96
|
self.central_widget = QWidget()
|
|
149
97
|
self.setCentralWidget(self.central_widget)
|
|
@@ -158,243 +106,181 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
158
106
|
self.tab_widget = TabWidgetWithPlaceholder()
|
|
159
107
|
self.tab_widget.resize(1000, 500)
|
|
160
108
|
h_splitter.addWidget(self.tab_widget)
|
|
161
|
-
self.job_list.currentRowChanged.connect(self.on_job_selected)
|
|
162
|
-
self.job_list.itemDoubleClicked.connect(self.on_job_edit)
|
|
163
|
-
self.action_list.itemDoubleClicked.connect(self.on_action_edit)
|
|
109
|
+
self.job_list().currentRowChanged.connect(self.project_editor.on_job_selected)
|
|
110
|
+
self.job_list().itemDoubleClicked.connect(self.on_job_edit)
|
|
111
|
+
self.action_list().itemDoubleClicked.connect(self.on_action_edit)
|
|
164
112
|
vbox_left = QVBoxLayout()
|
|
165
113
|
vbox_left.setSpacing(4)
|
|
166
114
|
vbox_left.addWidget(QLabel("Job"))
|
|
167
|
-
vbox_left.addWidget(self.job_list)
|
|
115
|
+
vbox_left.addWidget(self.job_list())
|
|
168
116
|
vbox_right = QVBoxLayout()
|
|
169
117
|
vbox_right.setSpacing(4)
|
|
170
118
|
vbox_right.addWidget(QLabel("Action"))
|
|
171
|
-
vbox_right.addWidget(self.action_list)
|
|
172
|
-
self.job_list.itemSelectionChanged.connect(self.update_delete_action_state)
|
|
173
|
-
self.action_list.itemSelectionChanged.connect(self.update_delete_action_state)
|
|
119
|
+
vbox_right.addWidget(self.action_list())
|
|
120
|
+
self.job_list().itemSelectionChanged.connect(self.update_delete_action_state)
|
|
121
|
+
self.action_list().itemSelectionChanged.connect(self.update_delete_action_state)
|
|
174
122
|
h_layout.addLayout(vbox_left)
|
|
175
123
|
h_layout.addLayout(vbox_right)
|
|
176
124
|
layout.addWidget(h_splitter)
|
|
177
125
|
self.central_widget.setLayout(layout)
|
|
126
|
+
self.update_title()
|
|
127
|
+
|
|
128
|
+
def handle_modified(modified):
|
|
129
|
+
self.save_actions_set_enabled(modified)
|
|
130
|
+
self.update_title()
|
|
131
|
+
|
|
132
|
+
self.project_editor.modified_signal.connect(handle_modified)
|
|
133
|
+
self.project_editor.select_signal.connect(self.update_delete_action_state)
|
|
134
|
+
self.project_editor.refresh_ui_signal.connect(self.refresh_ui)
|
|
135
|
+
self.project_editor.enable_delete_action_signal.connect(
|
|
136
|
+
self.menu_manager.delete_element_action.setEnabled)
|
|
137
|
+
self.project_controller.update_title_requested.connect(self.update_title)
|
|
138
|
+
self.project_controller.refresh_ui_requested.connect(self.refresh_ui)
|
|
139
|
+
self.project_controller.activate_window_requested.connect(self.activateWindow)
|
|
140
|
+
self.project_controller.enable_save_actions_requested.connect(
|
|
141
|
+
self.menu_manager.save_actions_set_enabled)
|
|
142
|
+
|
|
143
|
+
def modified(self):
|
|
144
|
+
return self.project_editor.modified()
|
|
145
|
+
|
|
146
|
+
def mark_as_modified(self, modified=True):
|
|
147
|
+
self.project_editor.mark_as_modified(modified)
|
|
148
|
+
|
|
149
|
+
def set_project(self, project):
|
|
150
|
+
self.project_editor.set_project(project)
|
|
151
|
+
|
|
152
|
+
def project(self):
|
|
153
|
+
return self.project_editor.project()
|
|
154
|
+
|
|
155
|
+
def project_jobs(self):
|
|
156
|
+
return self.project_editor.project_jobs()
|
|
157
|
+
|
|
158
|
+
def project_job(self, i):
|
|
159
|
+
return self.project_editor.project_job(i)
|
|
160
|
+
|
|
161
|
+
def add_job_to_project(self, job):
|
|
162
|
+
self.project_editor.add_job_to_project(job)
|
|
163
|
+
|
|
164
|
+
def num_project_jobs(self):
|
|
165
|
+
return self.project_editor.num_project_jobs()
|
|
166
|
+
|
|
167
|
+
def current_file_path(self):
|
|
168
|
+
return self.project_editor.current_file_path()
|
|
169
|
+
|
|
170
|
+
def current_file_directory(self):
|
|
171
|
+
return self.project_editor.current_file_directory()
|
|
172
|
+
|
|
173
|
+
def current_file_name(self):
|
|
174
|
+
return self.project_editor.current_file_name()
|
|
175
|
+
|
|
176
|
+
def set_current_file_path(self, path):
|
|
177
|
+
self.project_editor.set_current_file_path(path)
|
|
178
|
+
|
|
179
|
+
def job_list(self):
|
|
180
|
+
return self.project_editor.job_list()
|
|
181
|
+
|
|
182
|
+
def action_list(self):
|
|
183
|
+
return self.project_editor.action_list()
|
|
184
|
+
|
|
185
|
+
def current_job_index(self):
|
|
186
|
+
return self.project_editor.current_job_index()
|
|
187
|
+
|
|
188
|
+
def current_action_index(self):
|
|
189
|
+
return self.project_editor.current_action_index()
|
|
190
|
+
|
|
191
|
+
def set_current_job(self, index):
|
|
192
|
+
return self.project_editor.set_current_job(index)
|
|
193
|
+
|
|
194
|
+
def set_current_action(self, index):
|
|
195
|
+
return self.project_editor.set_current_action(index)
|
|
196
|
+
|
|
197
|
+
def job_list_count(self):
|
|
198
|
+
return self.project_editor.job_list_count()
|
|
199
|
+
|
|
200
|
+
def action_list_count(self):
|
|
201
|
+
return self.project_editor.action_list_count()
|
|
202
|
+
|
|
203
|
+
def job_list_item(self, index):
|
|
204
|
+
return self.project_editor.job_list_item(index)
|
|
205
|
+
|
|
206
|
+
def action_list_item(self, index):
|
|
207
|
+
return self.project_editor.action_list_item(index)
|
|
208
|
+
|
|
209
|
+
def job_list_has_focus(self):
|
|
210
|
+
return self.project_editor.job_list_has_focus()
|
|
211
|
+
|
|
212
|
+
def action_list_has_focus(self):
|
|
213
|
+
return self.project_editor.action_list_has_focus()
|
|
214
|
+
|
|
215
|
+
def clear_job_list(self):
|
|
216
|
+
self.project_editor.clear_job_list()
|
|
217
|
+
|
|
218
|
+
def clear_action_list(self):
|
|
219
|
+
self.project_editor.clear_action_list()
|
|
220
|
+
|
|
221
|
+
def num_selected_jobs(self):
|
|
222
|
+
return self.project_editor.num_selected_jobs()
|
|
223
|
+
|
|
224
|
+
def num_selected_actions(self):
|
|
225
|
+
return self.project_editor.num_selected_actions()
|
|
226
|
+
|
|
227
|
+
def get_current_action_at(self, job, action_index):
|
|
228
|
+
return self.project_editor.get_current_action_at(job, action_index)
|
|
229
|
+
|
|
230
|
+
def action_config_dialog(self, action):
|
|
231
|
+
return self.project_editor.action_config_dialog(action)
|
|
232
|
+
|
|
233
|
+
def action_text(self, action, is_sub_action=False, indent=True, long_name=False, html=False):
|
|
234
|
+
return self.project_editor.action_text(action, is_sub_action, indent, long_name, html)
|
|
235
|
+
|
|
236
|
+
def job_text(self, job, long_name=False, html=False):
|
|
237
|
+
return self.project_editor.job_text(job, long_name, html)
|
|
238
|
+
|
|
239
|
+
def on_job_selected(self, index):
|
|
240
|
+
return self.project_editor.on_job_selected(index)
|
|
241
|
+
|
|
242
|
+
def get_action_at(self, action_row):
|
|
243
|
+
return self.project_editor.get_action_at(action_row)
|
|
244
|
+
|
|
245
|
+
def on_job_edit(self, item):
|
|
246
|
+
self.project_controller.on_job_edit(item)
|
|
247
|
+
|
|
248
|
+
def on_action_edit(self, item):
|
|
249
|
+
self.project_controller.on_action_edit(item)
|
|
250
|
+
|
|
251
|
+
def edit_current_action(self):
|
|
252
|
+
self.project_controller.edit_current_action()
|
|
253
|
+
|
|
254
|
+
def edit_action(self, action):
|
|
255
|
+
self.project_controller.edit_action(action)
|
|
178
256
|
|
|
179
257
|
def set_retouch_callback(self, callback):
|
|
180
258
|
self.retouch_callback = callback
|
|
181
259
|
|
|
182
|
-
def
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
save_action.setShortcut("Ctrl+S")
|
|
194
|
-
save_action.triggered.connect(self.save_project)
|
|
195
|
-
menu.addAction(save_action)
|
|
196
|
-
save_as_action = QAction("Save &As...", self)
|
|
197
|
-
save_as_action.setShortcut("Ctrl+Shift+S")
|
|
198
|
-
save_as_action.triggered.connect(self.save_project_as)
|
|
199
|
-
menu.addAction(save_as_action)
|
|
200
|
-
close_action = QAction("&Close", self)
|
|
201
|
-
close_action.setShortcut("Ctrl+W")
|
|
202
|
-
close_action.triggered.connect(self.close_project)
|
|
203
|
-
menu.addAction(close_action)
|
|
204
|
-
|
|
205
|
-
def add_edit_menu(self, menubar):
|
|
206
|
-
menu = menubar.addMenu("&Edit")
|
|
207
|
-
undo_action = QAction("&Undo", self)
|
|
208
|
-
undo_action.setShortcut("Ctrl+Z")
|
|
209
|
-
undo_action.triggered.connect(self.undo)
|
|
210
|
-
menu.addAction(undo_action)
|
|
211
|
-
menu.addSeparator()
|
|
212
|
-
cut_action = QAction("&Cut", self)
|
|
213
|
-
cut_action.setShortcut("Ctrl+X")
|
|
214
|
-
cut_action.triggered.connect(self.cut_element)
|
|
215
|
-
menu.addAction(cut_action)
|
|
216
|
-
copy_action = QAction("Cop&y", self)
|
|
217
|
-
copy_action.setShortcut("Ctrl+C")
|
|
218
|
-
copy_action.triggered.connect(self.copy_element)
|
|
219
|
-
menu.addAction(copy_action)
|
|
220
|
-
paste_action = QAction("&Paste", self)
|
|
221
|
-
paste_action.setShortcut("Ctrl+V")
|
|
222
|
-
paste_action.triggered.connect(self.paste_element)
|
|
223
|
-
menu.addAction(paste_action)
|
|
224
|
-
clone_action = QAction("Duplicate", self)
|
|
225
|
-
clone_action.setShortcut("Ctrl+D")
|
|
226
|
-
clone_action.triggered.connect(self.clone_element)
|
|
227
|
-
menu.addAction(clone_action)
|
|
228
|
-
self.delete_element_action = QAction("Delete", self)
|
|
229
|
-
self.delete_element_action.setShortcut("Del") # Qt.Key_Backspace
|
|
230
|
-
self.delete_element_action.setIcon(self.get_icon("close-round-line-icon"))
|
|
231
|
-
self.delete_element_action.setToolTip("delete")
|
|
232
|
-
self.delete_element_action.triggered.connect(self.delete_element)
|
|
233
|
-
self.delete_element_action.setEnabled(False)
|
|
234
|
-
menu.addAction(self.delete_element_action)
|
|
235
|
-
menu.addSeparator()
|
|
236
|
-
up_action = QAction("Move &Up", self)
|
|
237
|
-
up_action.setShortcut("Ctrl+Up")
|
|
238
|
-
up_action.triggered.connect(self.move_element_up)
|
|
239
|
-
menu.addAction(up_action)
|
|
240
|
-
down_action = QAction("Move &Down", self)
|
|
241
|
-
down_action.setShortcut("Ctrl+Down")
|
|
242
|
-
down_action.triggered.connect(self.move_element_down)
|
|
243
|
-
menu.addAction(down_action)
|
|
244
|
-
menu.addSeparator()
|
|
245
|
-
self.enable_action = QAction("E&nable", self)
|
|
246
|
-
self.enable_action.setShortcut("Ctrl+E")
|
|
247
|
-
self.enable_action.triggered.connect(self.enable)
|
|
248
|
-
menu.addAction(self.enable_action)
|
|
249
|
-
self.disable_action = QAction("Di&sable", self)
|
|
250
|
-
self.disable_action.setShortcut("Ctrl+B")
|
|
251
|
-
self.disable_action.triggered.connect(self.disable)
|
|
252
|
-
menu.addAction(self.disable_action)
|
|
253
|
-
enable_all_action = QAction("Enable All", self)
|
|
254
|
-
enable_all_action.setShortcut("Ctrl+Shift+E")
|
|
255
|
-
enable_all_action.triggered.connect(self.enable_all)
|
|
256
|
-
menu.addAction(enable_all_action)
|
|
257
|
-
disable_all_action = QAction("Disable All", self)
|
|
258
|
-
disable_all_action.setShortcut("Ctrl+Shift+B")
|
|
259
|
-
disable_all_action.triggered.connect(self.disable_all)
|
|
260
|
-
menu.addAction(disable_all_action)
|
|
261
|
-
|
|
262
|
-
def add_view_menu(self, menubar):
|
|
263
|
-
menu = menubar.addMenu("&View")
|
|
264
|
-
self.expert_options_action = QAction("Expert Options", self)
|
|
265
|
-
self.expert_options_action.setShortcut("Ctrl+Shift+X")
|
|
266
|
-
self.expert_options_action.triggered.connect(self.toggle_expert_options)
|
|
267
|
-
self.expert_options_action.setCheckable(True)
|
|
268
|
-
self.expert_options_action.setChecked(self.expert_options)
|
|
269
|
-
menu.addAction(self.expert_options_action)
|
|
270
|
-
|
|
271
|
-
def add_job_menu(self, menubar):
|
|
272
|
-
menu = menubar.addMenu("&Jobs")
|
|
273
|
-
self.add_job_action = QAction("Add Job", self)
|
|
274
|
-
self.add_job_action.setShortcut("Ctrl+P")
|
|
275
|
-
self.add_job_action.setIcon(self.get_icon("plus-round-line-icon"))
|
|
276
|
-
self.add_job_action.setToolTip("Add job")
|
|
277
|
-
self.add_job_action.triggered.connect(self.add_job)
|
|
278
|
-
menu.addAction(self.add_job_action)
|
|
279
|
-
menu.addSeparator()
|
|
280
|
-
self.run_job_action = QAction("Run Job", self)
|
|
281
|
-
self.run_job_action.setShortcut("Ctrl+J")
|
|
282
|
-
self.run_job_action.setIcon(self.get_icon("play-button-round-icon"))
|
|
283
|
-
self.run_job_action.setToolTip("Run job")
|
|
284
|
-
self.run_job_action.setEnabled(False)
|
|
285
|
-
self.run_job_action.triggered.connect(self.run_job)
|
|
286
|
-
menu.addAction(self.run_job_action)
|
|
287
|
-
self.run_all_jobs_action = QAction("Run All Jobs", self)
|
|
288
|
-
self.run_all_jobs_action.setShortcut("Ctrl+Shift+J")
|
|
289
|
-
self.run_all_jobs_action.setIcon(self.get_icon("forward-button-icon"))
|
|
290
|
-
self.run_all_jobs_action.setToolTip("Run all jobs")
|
|
291
|
-
self.run_all_jobs_action.setEnabled(False)
|
|
292
|
-
self.run_all_jobs_action.triggered.connect(self.run_all_jobs)
|
|
293
|
-
menu.addAction(self.run_all_jobs_action)
|
|
294
|
-
|
|
295
|
-
def add_action_combined_actions(self):
|
|
296
|
-
self.add_action(constants.ACTION_COMBO)
|
|
297
|
-
|
|
298
|
-
def add_action_noise_detection(self):
|
|
299
|
-
self.add_action(constants.ACTION_NOISEDETECTION)
|
|
300
|
-
|
|
301
|
-
def add_action_focus_stack(self):
|
|
302
|
-
self.add_action(constants.ACTION_FOCUSSTACK)
|
|
303
|
-
|
|
304
|
-
def add_action_focus_stack_bunch(self):
|
|
305
|
-
self.add_action(constants.ACTION_FOCUSSTACKBUNCH)
|
|
306
|
-
|
|
307
|
-
def add_action_multilayer(self):
|
|
308
|
-
self.add_action(constants.ACTION_MULTILAYER)
|
|
309
|
-
|
|
310
|
-
def add_sub_action_make_noise(self):
|
|
311
|
-
self.add_sub_action(constants.ACTION_MASKNOISE)
|
|
312
|
-
|
|
313
|
-
def add_sub_action_vignetting(self):
|
|
314
|
-
self.add_sub_action(constants.ACTION_VIGNETTING)
|
|
315
|
-
|
|
316
|
-
def add_sub_action_align_frames(self):
|
|
317
|
-
self.add_sub_action(constants.ACTION_ALIGNFRAMES)
|
|
318
|
-
|
|
319
|
-
def add_sub_action_balance_frames(self):
|
|
320
|
-
self.add_sub_action(constants.ACTION_BALANCEFRAMES)
|
|
321
|
-
|
|
322
|
-
def add_actions_menu(self, menubar):
|
|
323
|
-
menu = menubar.addMenu("&Actions")
|
|
324
|
-
add_action_menu = QMenu("Add Action", self)
|
|
325
|
-
for action in constants.ACTION_TYPES:
|
|
326
|
-
entry_action = QAction(action, self)
|
|
327
|
-
entry_action.triggered.connect({
|
|
328
|
-
constants.ACTION_COMBO: self.add_action_combined_actions,
|
|
329
|
-
constants.ACTION_NOISEDETECTION: self.add_action_noise_detection,
|
|
330
|
-
constants.ACTION_FOCUSSTACK: self.add_action_focus_stack,
|
|
331
|
-
constants.ACTION_FOCUSSTACKBUNCH: self.add_action_focus_stack_bunch,
|
|
332
|
-
constants.ACTION_MULTILAYER: self.add_action_multilayer
|
|
333
|
-
}[action])
|
|
334
|
-
add_action_menu.addAction(entry_action)
|
|
335
|
-
menu.addMenu(add_action_menu)
|
|
336
|
-
add_sub_action_menu = QMenu("Add Sub Action", self)
|
|
337
|
-
self.sub_action_menu_entries = []
|
|
338
|
-
for action in constants.SUB_ACTION_TYPES:
|
|
339
|
-
entry_action = QAction(action, self)
|
|
340
|
-
entry_action.triggered.connect({
|
|
341
|
-
constants.ACTION_MASKNOISE: self.add_sub_action_make_noise,
|
|
342
|
-
constants.ACTION_VIGNETTING: self.add_sub_action_vignetting,
|
|
343
|
-
constants.ACTION_ALIGNFRAMES: self.add_sub_action_align_frames,
|
|
344
|
-
constants.ACTION_BALANCEFRAMES: self.add_sub_action_balance_frames
|
|
345
|
-
}[action])
|
|
346
|
-
entry_action.setEnabled(False)
|
|
347
|
-
self.sub_action_menu_entries.append(entry_action)
|
|
348
|
-
add_sub_action_menu.addAction(entry_action)
|
|
349
|
-
menu.addMenu(add_sub_action_menu)
|
|
350
|
-
|
|
351
|
-
def add_help_menu(self, menubar):
|
|
352
|
-
menu = menubar.addMenu("&Help")
|
|
353
|
-
menu.setObjectName("Help")
|
|
354
|
-
|
|
355
|
-
def fill_toolbar(self, toolbar):
|
|
356
|
-
toolbar.addAction(self.add_job_action)
|
|
357
|
-
toolbar.addSeparator()
|
|
358
|
-
self.action_selector = QComboBox()
|
|
359
|
-
self.action_selector.addItems(constants.ACTION_TYPES)
|
|
360
|
-
self.action_selector.setEnabled(False)
|
|
361
|
-
toolbar.addWidget(self.action_selector)
|
|
362
|
-
self.add_action_entry_action = QAction("Add Action", self)
|
|
363
|
-
self.add_action_entry_action.setIcon(
|
|
364
|
-
QIcon(os.path.join(self.script_dir, "img/plus-round-line-icon.png")))
|
|
365
|
-
self.add_action_entry_action.setToolTip("Add action")
|
|
366
|
-
self.add_action_entry_action.triggered.connect(self.add_action)
|
|
367
|
-
self.add_action_entry_action.setEnabled(False)
|
|
368
|
-
toolbar.addAction(self.add_action_entry_action)
|
|
369
|
-
self.sub_action_selector = QComboBox()
|
|
370
|
-
self.sub_action_selector.addItems(constants.SUB_ACTION_TYPES)
|
|
371
|
-
self.sub_action_selector.setEnabled(False)
|
|
372
|
-
toolbar.addWidget(self.sub_action_selector)
|
|
373
|
-
self.add_sub_action_entry_action = QAction("Add Sub Action", self)
|
|
374
|
-
self.add_sub_action_entry_action.setIcon(
|
|
375
|
-
QIcon(os.path.join(self.script_dir, "img/plus-round-line-icon.png")))
|
|
376
|
-
self.add_sub_action_entry_action.setToolTip("Add sub action")
|
|
377
|
-
self.add_sub_action_entry_action.triggered.connect(self.add_sub_action)
|
|
378
|
-
self.add_sub_action_entry_action.setEnabled(False)
|
|
379
|
-
toolbar.addAction(self.add_sub_action_entry_action)
|
|
380
|
-
toolbar.addSeparator()
|
|
381
|
-
toolbar.addAction(self.delete_element_action)
|
|
382
|
-
toolbar.addSeparator()
|
|
383
|
-
toolbar.addAction(self.run_job_action)
|
|
384
|
-
toolbar.addAction(self.run_all_jobs_action)
|
|
260
|
+
def save_actions_set_enabled(self, enabled):
|
|
261
|
+
self.menu_manager.save_actions_set_enabled(enabled)
|
|
262
|
+
|
|
263
|
+
def update_title(self):
|
|
264
|
+
title = constants.APP_TITLE
|
|
265
|
+
file_name = self.current_file_name()
|
|
266
|
+
if file_name:
|
|
267
|
+
title += f" - {file_name}"
|
|
268
|
+
if self.modified():
|
|
269
|
+
title += " *"
|
|
270
|
+
self.window().setWindowTitle(title)
|
|
385
271
|
|
|
386
272
|
# pylint: disable=C0103
|
|
387
273
|
def contextMenuEvent(self, event):
|
|
388
|
-
item = self.job_list.itemAt(self.job_list.viewport().mapFrom(self, event.pos()))
|
|
274
|
+
item = self.job_list().itemAt(self.job_list().viewport().mapFrom(self, event.pos()))
|
|
389
275
|
current_action = None
|
|
390
276
|
if item:
|
|
391
|
-
index = self.job_list.row(item)
|
|
277
|
+
index = self.job_list().row(item)
|
|
392
278
|
current_action = self.get_job_at(index)
|
|
393
|
-
self.
|
|
394
|
-
item = self.action_list.itemAt(self.action_list.viewport().mapFrom(self, event.pos()))
|
|
279
|
+
self.set_current_job(index)
|
|
280
|
+
item = self.action_list().itemAt(self.action_list().viewport().mapFrom(self, event.pos()))
|
|
395
281
|
if item:
|
|
396
|
-
index = self.action_list.row(item)
|
|
397
|
-
self.
|
|
282
|
+
index = self.action_list().row(item)
|
|
283
|
+
self.set_current_action(index)
|
|
398
284
|
_job_row, _action_row, pos = self.get_action_at(index)
|
|
399
285
|
current_action = pos.action if not pos.is_sub_action else pos.sub_action
|
|
400
286
|
if current_action:
|
|
@@ -412,7 +298,7 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
412
298
|
os.path.exists(self.current_action_working_path):
|
|
413
299
|
action_name = "Browse Working Path" + (f" > {name}" if name != '' else '')
|
|
414
300
|
self.browse_working_path_action = QAction(action_name)
|
|
415
|
-
self.browse_working_path_action.triggered.connect(self.
|
|
301
|
+
self.browse_working_path_action.triggered.connect(self.browse_working_path)
|
|
416
302
|
menu.addAction(self.browse_working_path_action)
|
|
417
303
|
ip, name = get_action_input_path(current_action)
|
|
418
304
|
if ip != '':
|
|
@@ -426,16 +312,24 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
426
312
|
break
|
|
427
313
|
if p_exists:
|
|
428
314
|
action_name = "Browse Input Path" + (f" > {name}" if name != '' else '')
|
|
315
|
+
n_files = [f"{len(next(os.walk(p))[2])}"
|
|
316
|
+
for p in
|
|
317
|
+
self.current_action_input_path.split(constants.PATH_SEPARATOR)]
|
|
318
|
+
s = "" if len(n_files) == 1 and n_files[0] == 1 else "s"
|
|
319
|
+
action_name += " (" + ", ".join(n_files) + f" file{s})"
|
|
429
320
|
self.browse_input_path_action = QAction(action_name)
|
|
430
|
-
self.browse_input_path_action.triggered.connect(self.
|
|
321
|
+
self.browse_input_path_action.triggered.connect(self.browse_input_path)
|
|
431
322
|
menu.addAction(self.browse_input_path_action)
|
|
432
323
|
op, name = get_action_output_path(current_action)
|
|
433
324
|
if op != '':
|
|
434
325
|
self.current_action_output_path = f"{self.current_action_working_path}/{op}"
|
|
435
326
|
if os.path.exists(self.current_action_output_path):
|
|
436
327
|
action_name = "Browse Output Path" + (f" > {name}" if name != '' else '')
|
|
328
|
+
n_files = len(next(os.walk(op))[2])
|
|
329
|
+
s = "" if n_files == 1 else "s"
|
|
330
|
+
action_name += f" ({n_files} file{s})"
|
|
437
331
|
self.browse_output_path_action = QAction(action_name)
|
|
438
|
-
self.browse_output_path_action.triggered.connect(self.
|
|
332
|
+
self.browse_output_path_action.triggered.connect(self.browse_output_path)
|
|
439
333
|
menu.addAction(self.browse_output_path_action)
|
|
440
334
|
menu.addSeparator()
|
|
441
335
|
menu.addAction(self.run_job_action)
|
|
@@ -483,58 +377,57 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
483
377
|
if os.path.exists(p):
|
|
484
378
|
if running_under_windows():
|
|
485
379
|
os.startfile(os.path.normpath(p))
|
|
486
|
-
elif running_under_macos():
|
|
487
|
-
subprocess.run(['open', p], check=True)
|
|
488
380
|
else:
|
|
489
|
-
|
|
381
|
+
cmd = 'open' if running_under_macos() else 'xdg-open'
|
|
382
|
+
subprocess.run([cmd, p], check=True)
|
|
490
383
|
|
|
491
|
-
def
|
|
384
|
+
def browse_working_path(self):
|
|
492
385
|
self.browse_path(self.current_action_working_path)
|
|
493
386
|
|
|
494
|
-
def
|
|
387
|
+
def browse_input_path(self):
|
|
495
388
|
self.browse_path(self.current_action_input_path)
|
|
496
389
|
|
|
497
|
-
def
|
|
390
|
+
def browse_output_path(self):
|
|
498
391
|
self.browse_path(self.current_action_output_path)
|
|
499
392
|
|
|
500
393
|
def refresh_ui(self, job_row=-1, action_row=-1):
|
|
501
|
-
self.
|
|
502
|
-
for job in self.
|
|
503
|
-
self.add_list_item(self.job_list, job, False)
|
|
504
|
-
if self.
|
|
505
|
-
self.
|
|
394
|
+
self.clear_job_list()
|
|
395
|
+
for job in self.project_jobs():
|
|
396
|
+
self.project_editor.add_list_item(self.job_list(), job, False)
|
|
397
|
+
if self.project_jobs():
|
|
398
|
+
self.set_current_job(0)
|
|
506
399
|
if job_row >= 0:
|
|
507
|
-
self.
|
|
400
|
+
self.set_current_job(job_row)
|
|
508
401
|
if action_row >= 0:
|
|
509
|
-
self.
|
|
510
|
-
if self.
|
|
511
|
-
self.add_action_entry_action.setEnabled(False)
|
|
512
|
-
self.action_selector.setEnabled(False)
|
|
402
|
+
self.set_current_action(action_row)
|
|
403
|
+
if self.job_list_count() == 0:
|
|
404
|
+
self.menu_manager.add_action_entry_action.setEnabled(False)
|
|
405
|
+
self.menu_manager.action_selector.setEnabled(False)
|
|
513
406
|
self.run_job_action.setEnabled(False)
|
|
514
407
|
self.run_all_jobs_action.setEnabled(False)
|
|
515
408
|
else:
|
|
516
|
-
self.add_action_entry_action.setEnabled(True)
|
|
517
|
-
self.action_selector.setEnabled(True)
|
|
518
|
-
self.delete_element_action.setEnabled(True)
|
|
519
|
-
self.run_job_action.setEnabled(True)
|
|
520
|
-
self.run_all_jobs_action.setEnabled(True)
|
|
409
|
+
self.menu_manager.add_action_entry_action.setEnabled(True)
|
|
410
|
+
self.menu_manager.action_selector.setEnabled(True)
|
|
411
|
+
self.menu_manager.delete_element_action.setEnabled(True)
|
|
412
|
+
self.menu_manager.run_job_action.setEnabled(True)
|
|
413
|
+
self.menu_manager.run_all_jobs_action.setEnabled(True)
|
|
521
414
|
|
|
522
415
|
def quit(self):
|
|
523
|
-
if self.
|
|
416
|
+
if self.project_controller.check_unsaved_changes():
|
|
524
417
|
for worker in self._workers:
|
|
525
418
|
worker.stop()
|
|
526
419
|
self.close()
|
|
527
420
|
|
|
528
421
|
def toggle_expert_options(self):
|
|
529
|
-
self.expert_options = self.expert_options_action.isChecked()
|
|
422
|
+
self.expert_options = self.menu_manager.expert_options_action.isChecked()
|
|
530
423
|
|
|
531
424
|
def set_expert_options(self):
|
|
532
425
|
self.expert_options_action.setChecked(True)
|
|
533
426
|
self.expert_options = True
|
|
534
427
|
|
|
535
428
|
def before_thread_begins(self):
|
|
536
|
-
self.run_job_action.setEnabled(False)
|
|
537
|
-
self.run_all_jobs_action.setEnabled(False)
|
|
429
|
+
self.menu_manager.run_job_action.setEnabled(False)
|
|
430
|
+
self.menu_manager.run_all_jobs_action.setEnabled(False)
|
|
538
431
|
|
|
539
432
|
def get_tab_and_position(self, id_str):
|
|
540
433
|
for i in range(self.tab_widget.count()):
|
|
@@ -552,8 +445,8 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
552
445
|
return i
|
|
553
446
|
|
|
554
447
|
def do_handle_end_message(self, status, id_str, message):
|
|
555
|
-
self.run_job_action.setEnabled(True)
|
|
556
|
-
self.run_all_jobs_action.setEnabled(True)
|
|
448
|
+
self.menu_manager.run_job_action.setEnabled(True)
|
|
449
|
+
self.menu_manager.run_all_jobs_action.setEnabled(True)
|
|
557
450
|
tab = self.get_tab_at_position(id_str)
|
|
558
451
|
tab.close_button.setEnabled(True)
|
|
559
452
|
tab.stop_button.setEnabled(False)
|
|
@@ -564,8 +457,7 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
564
457
|
new_window = RunWindow(labels,
|
|
565
458
|
lambda id_str: self.stop_worker(self.get_tab_position(id_str)),
|
|
566
459
|
lambda id_str: self.close_window(self.get_tab_position(id_str)),
|
|
567
|
-
retouch_paths,
|
|
568
|
-
self)
|
|
460
|
+
retouch_paths, self)
|
|
569
461
|
self.tab_widget.addTab(new_window, title)
|
|
570
462
|
self.tab_widget.setCurrentIndex(self.tab_widget.count() - 1)
|
|
571
463
|
if title is not None:
|
|
@@ -584,7 +476,7 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
584
476
|
worker = self._workers[tab_position]
|
|
585
477
|
worker.stop()
|
|
586
478
|
|
|
587
|
-
def
|
|
479
|
+
def connect_worker_signals(self, worker, window):
|
|
588
480
|
worker.before_action_signal.connect(window.handle_before_action)
|
|
589
481
|
worker.after_action_signal.connect(window.handle_after_action)
|
|
590
482
|
worker.step_counts_signal.connect(window.handle_step_counts)
|
|
@@ -593,23 +485,18 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
593
485
|
worker.after_step_signal.connect(window.handle_after_step)
|
|
594
486
|
worker.save_plot_signal.connect(window.handle_save_plot)
|
|
595
487
|
worker.open_app_signal.connect(window.handle_open_app)
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
self.sub_action_selector.setEnabled(enabled)
|
|
600
|
-
for a in self.sub_action_menu_entries:
|
|
601
|
-
a.setEnabled(enabled)
|
|
488
|
+
worker.run_completed_signal.connect(window.handle_run_completed)
|
|
489
|
+
worker.run_stopped_signal.connect(window.handle_run_stopped)
|
|
490
|
+
worker.run_failed_signal.connect(window.handle_run_failed)
|
|
602
491
|
|
|
603
492
|
def run_job(self):
|
|
604
|
-
current_index = self.
|
|
493
|
+
current_index = self.current_job_index()
|
|
605
494
|
if current_index < 0:
|
|
606
|
-
if
|
|
607
|
-
|
|
608
|
-
else:
|
|
609
|
-
QMessageBox.warning(self, "No Job Added", "Please add a job first.")
|
|
495
|
+
msg = "No Job Selected" if self.num_project_jobs() > 0 else "No Job Added"
|
|
496
|
+
QMessageBox.warning(self, msg, "Please select a job first.")
|
|
610
497
|
return
|
|
611
498
|
if current_index >= 0:
|
|
612
|
-
job = self.
|
|
499
|
+
job = self.project_job(current_index)
|
|
613
500
|
if job.enabled():
|
|
614
501
|
job_name = job.params["name"]
|
|
615
502
|
labels = [[(self.action_text(a), a.enabled()) for a in job.sub_actions]]
|
|
@@ -618,29 +505,51 @@ class MainWindow(ActionsWindow, LogManager):
|
|
|
618
505
|
new_window, id_str = self.create_new_window(f"{job_name} [⚙️ Job]",
|
|
619
506
|
labels, retouch_paths)
|
|
620
507
|
worker = JobLogWorker(job, id_str)
|
|
621
|
-
self.
|
|
508
|
+
self.connect_worker_signals(worker, new_window)
|
|
622
509
|
self.start_thread(worker)
|
|
623
510
|
self._workers.append(worker)
|
|
624
511
|
else:
|
|
625
|
-
QMessageBox.warning(
|
|
626
|
-
|
|
627
|
-
"Job " + job.params["name"] + " is disabled.")
|
|
512
|
+
QMessageBox.warning(self, "Can't run Job",
|
|
513
|
+
"Job " + job.params["name"] + " is disabled.")
|
|
628
514
|
return
|
|
629
515
|
|
|
630
516
|
def run_all_jobs(self):
|
|
631
517
|
labels = [[(self.action_text(a), a.enabled() and
|
|
632
|
-
job.enabled()) for a in job.sub_actions] for job in self.
|
|
518
|
+
job.enabled()) for a in job.sub_actions] for job in self.project_jobs()]
|
|
633
519
|
project_name = ".".join(self.current_file_name().split(".")[:-1])
|
|
634
520
|
if project_name == '':
|
|
635
521
|
project_name = '[new]'
|
|
636
522
|
retouch_paths = []
|
|
637
|
-
for job in self.
|
|
523
|
+
for job in self.project_jobs():
|
|
638
524
|
r = self.get_retouch_path(job)
|
|
639
525
|
if len(r) > 0:
|
|
640
526
|
retouch_paths.append((job.params["name"], r))
|
|
641
527
|
new_window, id_str = self.create_new_window(f"{project_name} [Project 📚]",
|
|
642
528
|
labels, retouch_paths)
|
|
643
|
-
worker = ProjectLogWorker(self.project, id_str)
|
|
644
|
-
self.
|
|
529
|
+
worker = ProjectLogWorker(self.project(), id_str)
|
|
530
|
+
self.connect_worker_signals(worker, new_window)
|
|
645
531
|
self.start_thread(worker)
|
|
646
532
|
self._workers.append(worker)
|
|
533
|
+
|
|
534
|
+
def delete_element(self):
|
|
535
|
+
self.project_editor.delete_element()
|
|
536
|
+
if self.job_list_count() > 0:
|
|
537
|
+
self.menu_manager.delete_element_action.setEnabled(True)
|
|
538
|
+
|
|
539
|
+
def update_delete_action_state(self):
|
|
540
|
+
has_job_selected = self.num_selected_jobs() > 0
|
|
541
|
+
has_action_selected = self.num_selected_actions() > 0
|
|
542
|
+
self.menu_manager.delete_element_action.setEnabled(
|
|
543
|
+
has_job_selected or has_action_selected)
|
|
544
|
+
if has_action_selected and has_job_selected:
|
|
545
|
+
job_index = min(self.current_job_index(), self.num_project_jobs() - 1)
|
|
546
|
+
action_index = self.current_action_index()
|
|
547
|
+
if job_index >= 0:
|
|
548
|
+
job = self.project_job(job_index)
|
|
549
|
+
current_action, is_sub_action = \
|
|
550
|
+
self.get_current_action_at(job, action_index)
|
|
551
|
+
enable_sub_actions = current_action is not None and \
|
|
552
|
+
not is_sub_action and current_action.type_name == constants.ACTION_COMBO
|
|
553
|
+
self.menu_manager.set_enabled_sub_actions_gui(enable_sub_actions)
|
|
554
|
+
else:
|
|
555
|
+
self.menu_manager.set_enabled_sub_actions_gui(False)
|