shinestacker 1.5.3__py3-none-any.whl → 1.5.4__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/gui/main_window.py +10 -0
- shinestacker/gui/menu_manager.py +14 -10
- shinestacker/gui/project_controller.py +3 -0
- shinestacker/retouch/image_editor_ui.py +45 -14
- shinestacker/retouch/io_gui_handler.py +3 -0
- shinestacker/retouch/overlaid_view.py +6 -43
- shinestacker/retouch/sidebyside_view.py +17 -29
- shinestacker/retouch/view_strategy.py +111 -57
- shinestacker/retouch/white_balance_filter.py +5 -6
- {shinestacker-1.5.3.dist-info → shinestacker-1.5.4.dist-info}/METADATA +1 -1
- {shinestacker-1.5.3.dist-info → shinestacker-1.5.4.dist-info}/RECORD +16 -16
- {shinestacker-1.5.3.dist-info → shinestacker-1.5.4.dist-info}/WHEEL +0 -0
- {shinestacker-1.5.3.dist-info → shinestacker-1.5.4.dist-info}/entry_points.txt +0 -0
- {shinestacker-1.5.3.dist-info → shinestacker-1.5.4.dist-info}/licenses/LICENSE +0 -0
- {shinestacker-1.5.3.dist-info → shinestacker-1.5.4.dist-info}/top_level.txt +0 -0
shinestacker/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '1.5.
|
|
1
|
+
__version__ = '1.5.4'
|
shinestacker/gui/main_window.py
CHANGED
|
@@ -154,9 +154,14 @@ class MainWindow(QMainWindow, LogManager):
|
|
|
154
154
|
self.menu_manager.set_enabled_sub_actions_gui)
|
|
155
155
|
self.project_controller.add_recent_file_requested.connect(
|
|
156
156
|
self.menu_manager.add_recent_file)
|
|
157
|
+
self.project_controller.set_enabled_file_open_close_actions_requested.connect(
|
|
158
|
+
self.set_enabled_file_open_close_actions)
|
|
159
|
+
|
|
157
160
|
self.menu_manager.open_file_requested.connect(
|
|
158
161
|
self.project_controller.open_project)
|
|
159
162
|
|
|
163
|
+
self.set_enabled_file_open_close_actions(False)
|
|
164
|
+
|
|
160
165
|
def modified(self):
|
|
161
166
|
return self.project_editor.modified()
|
|
162
167
|
|
|
@@ -571,3 +576,8 @@ class MainWindow(QMainWindow, LogManager):
|
|
|
571
576
|
self.menu_manager.set_enabled_sub_actions_gui(enable_sub_actions)
|
|
572
577
|
else:
|
|
573
578
|
self.menu_manager.set_enabled_sub_actions_gui(False)
|
|
579
|
+
|
|
580
|
+
def set_enabled_file_open_close_actions(self, enabled):
|
|
581
|
+
for action in self.findChildren(QAction):
|
|
582
|
+
if action.property("requires_file"):
|
|
583
|
+
action.setEnabled(enabled)
|
shinestacker/gui/menu_manager.py
CHANGED
|
@@ -60,8 +60,10 @@ class MenuManager(QObject):
|
|
|
60
60
|
def get_icon(self, icon):
|
|
61
61
|
return QIcon(os.path.join(self.script_dir, f"img/{icon}.png"))
|
|
62
62
|
|
|
63
|
-
def action(self, name):
|
|
63
|
+
def action(self, name, requires_file=False):
|
|
64
64
|
action = QAction(name, self.parent)
|
|
65
|
+
if requires_file:
|
|
66
|
+
action.setProperty("requires_file", True)
|
|
65
67
|
shortcut = self.shortcuts.get(name, '')
|
|
66
68
|
if shortcut:
|
|
67
69
|
action.setShortcut(shortcut)
|
|
@@ -110,20 +112,20 @@ class MenuManager(QObject):
|
|
|
110
112
|
self.undo_action.setEnabled(False)
|
|
111
113
|
menu.addAction(self.undo_action)
|
|
112
114
|
for name in ["&Cut", "Cop&y", "&Paste", "Duplicate"]:
|
|
113
|
-
menu.addAction(self.action(name))
|
|
114
|
-
self.delete_element_action = self.action("Delete")
|
|
115
|
+
menu.addAction(self.action(name, requires_file=True))
|
|
116
|
+
self.delete_element_action = self.action("Delete", requires_file=True)
|
|
115
117
|
self.delete_element_action.setEnabled(False)
|
|
116
118
|
menu.addAction(self.delete_element_action)
|
|
117
119
|
menu.addSeparator()
|
|
118
120
|
for name in ["Move &Up", "Move &Down"]:
|
|
119
|
-
menu.addAction(self.action(name))
|
|
121
|
+
menu.addAction(self.action(name, requires_file=True))
|
|
120
122
|
menu.addSeparator()
|
|
121
|
-
self.enable_action = self.action("E&nable")
|
|
123
|
+
self.enable_action = self.action("E&nable", requires_file=True)
|
|
122
124
|
menu.addAction(self.enable_action)
|
|
123
|
-
self.disable_action = self.action("Di&sable")
|
|
125
|
+
self.disable_action = self.action("Di&sable", requires_file=True)
|
|
124
126
|
menu.addAction(self.disable_action)
|
|
125
127
|
for name in ["Enable All", "Disable All"]:
|
|
126
|
-
menu.addAction(self.action(name))
|
|
128
|
+
menu.addAction(self.action(name, requires_file=True))
|
|
127
129
|
|
|
128
130
|
def add_view_menu(self):
|
|
129
131
|
menu = self.menubar.addMenu("&View")
|
|
@@ -133,13 +135,13 @@ class MenuManager(QObject):
|
|
|
133
135
|
|
|
134
136
|
def add_job_menu(self):
|
|
135
137
|
menu = self.menubar.addMenu("&Jobs")
|
|
136
|
-
self.add_job_action = self.action("Add Job")
|
|
138
|
+
self.add_job_action = self.action("Add Job", requires_file=True)
|
|
137
139
|
menu.addAction(self.add_job_action)
|
|
138
140
|
menu.addSeparator()
|
|
139
|
-
self.run_job_action = self.action("Run Job")
|
|
141
|
+
self.run_job_action = self.action("Run Job", requires_file=True)
|
|
140
142
|
self.run_job_action.setEnabled(False)
|
|
141
143
|
menu.addAction(self.run_job_action)
|
|
142
|
-
self.run_all_jobs_action = self.action("Run All Jobs")
|
|
144
|
+
self.run_all_jobs_action = self.action("Run All Jobs", requires_file=True)
|
|
143
145
|
self.set_enabled_run_all_jobs(False)
|
|
144
146
|
menu.addAction(self.run_all_jobs_action)
|
|
145
147
|
|
|
@@ -148,6 +150,7 @@ class MenuManager(QObject):
|
|
|
148
150
|
add_action_menu = QMenu("Add Action", self.parent)
|
|
149
151
|
for action in constants.ACTION_TYPES:
|
|
150
152
|
entry_action = QAction(action, self.parent)
|
|
153
|
+
entry_action.setProperty("requires_file", True)
|
|
151
154
|
entry_action.triggered.connect({
|
|
152
155
|
constants.ACTION_COMBO: self.add_action_combined_actions,
|
|
153
156
|
constants.ACTION_NOISEDETECTION: self.add_action_noise_detection,
|
|
@@ -161,6 +164,7 @@ class MenuManager(QObject):
|
|
|
161
164
|
self.sub_action_menu_entries = []
|
|
162
165
|
for action in constants.SUB_ACTION_TYPES:
|
|
163
166
|
entry_action = QAction(action, self.parent)
|
|
167
|
+
entry_action.setProperty("requires_file", True)
|
|
164
168
|
entry_action.triggered.connect({
|
|
165
169
|
constants.ACTION_MASKNOISE: self.add_sub_action_make_noise,
|
|
166
170
|
constants.ACTION_VIGNETTING: self.add_sub_action_vignetting,
|
|
@@ -21,6 +21,7 @@ class ProjectController(QObject):
|
|
|
21
21
|
enable_save_actions_requested = Signal(bool)
|
|
22
22
|
enable_sub_actions_requested = Signal(bool)
|
|
23
23
|
add_recent_file_requested = Signal(str)
|
|
24
|
+
set_enabled_file_open_close_actions_requested = Signal(bool)
|
|
24
25
|
|
|
25
26
|
def __init__(self, parent):
|
|
26
27
|
super().__init__(parent)
|
|
@@ -138,6 +139,7 @@ class ProjectController(QObject):
|
|
|
138
139
|
self.clear_action_list()
|
|
139
140
|
self.mark_as_modified(False)
|
|
140
141
|
self.project_editor.reset_undo()
|
|
142
|
+
self.set_enabled_file_open_close_actions_requested.emit(False)
|
|
141
143
|
|
|
142
144
|
def new_project(self):
|
|
143
145
|
if not self.check_unsaved_changes():
|
|
@@ -250,6 +252,7 @@ class ProjectController(QObject):
|
|
|
250
252
|
project = Project.from_dict(json_obj['project'])
|
|
251
253
|
if project is None:
|
|
252
254
|
raise RuntimeError(f"Project from file {file_path} produced a null project.")
|
|
255
|
+
self.set_enabled_file_open_close_actions_requested.emit(True)
|
|
253
256
|
self.set_project(project)
|
|
254
257
|
self.mark_as_modified(False)
|
|
255
258
|
self.add_recent_file_requested.emit(abs_file_path)
|
|
@@ -229,6 +229,8 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
229
229
|
self.io_gui_handler.mark_as_modified_requested.connect(self.mark_as_modified)
|
|
230
230
|
self.io_gui_handler.change_layer_requested.connect(self.change_layer)
|
|
231
231
|
self.io_gui_handler.add_recent_file_requested.connect(self.add_recent_file)
|
|
232
|
+
self.io_gui_handler.set_enabled_file_open_close_actions_requested.connect(
|
|
233
|
+
self.set_enabled_file_open_close_actions)
|
|
232
234
|
self.brush_tool.setup_ui(self.brush, self.brush_preview_widget, self.image_viewer,
|
|
233
235
|
self.brush_size_slider, self.hardness_slider, self.opacity_slider,
|
|
234
236
|
self.flow_slider)
|
|
@@ -277,22 +279,26 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
277
279
|
|
|
278
280
|
transf_menu = QMenu("&Transform")
|
|
279
281
|
rotate_90_cw_action = QAction(gui_constants.ROTATE_90_CW_LABEL, self)
|
|
280
|
-
|
|
282
|
+
rotate_90_cw_action.setProperty("requires_file", True)
|
|
281
283
|
rotate_90_cw_action.triggered.connect(lambda: self.transformation_manager.rotate_90_cw())
|
|
284
|
+
transf_menu.addAction(rotate_90_cw_action)
|
|
282
285
|
rotate_90_ccw_action = QAction(gui_constants.ROTATE_90_CCW_LABEL, self)
|
|
283
|
-
|
|
286
|
+
rotate_90_ccw_action.setProperty("requires_file", True)
|
|
284
287
|
rotate_90_ccw_action.triggered.connect(lambda: self.transformation_manager.rotate_90_ccw())
|
|
288
|
+
transf_menu.addAction(rotate_90_ccw_action)
|
|
285
289
|
rotate_180_action = QAction(gui_constants.ROTATE_180_LABEL, self)
|
|
286
290
|
rotate_180_action.triggered.connect(lambda: self.transformation_manager.rotate_180())
|
|
291
|
+
rotate_180_action.setProperty("requires_file", True)
|
|
287
292
|
transf_menu.addAction(rotate_180_action)
|
|
288
293
|
edit_menu.addMenu(transf_menu)
|
|
289
294
|
|
|
290
295
|
edit_menu.addSeparator()
|
|
291
296
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
297
|
+
copy_current_to_master_action = QAction("Copy Current Layer to Master", self)
|
|
298
|
+
copy_current_to_master_action.setShortcut("Ctrl+M")
|
|
299
|
+
copy_current_to_master_action.setProperty("requires_file", True)
|
|
300
|
+
copy_current_to_master_action.triggered.connect(self.copy_layer_to_master)
|
|
301
|
+
edit_menu.addAction(copy_current_to_master_action)
|
|
296
302
|
|
|
297
303
|
view_menu = menubar.addMenu("&View")
|
|
298
304
|
|
|
@@ -351,15 +357,18 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
351
357
|
}
|
|
352
358
|
brush_action = self.cursor_style_actions['brush']
|
|
353
359
|
brush_action.setCheckable(True)
|
|
360
|
+
brush_action.setProperty("requires_file", True)
|
|
354
361
|
brush_action.triggered.connect(lambda: set_cursor_style('brush'))
|
|
355
362
|
cursor_menu.addAction(brush_action)
|
|
356
363
|
|
|
357
364
|
preview_action = self.cursor_style_actions['preview']
|
|
365
|
+
preview_action.setProperty("requires_file", True)
|
|
358
366
|
preview_action.setCheckable(True)
|
|
359
367
|
preview_action.triggered.connect(lambda: set_cursor_style('preview'))
|
|
360
368
|
cursor_menu.addAction(preview_action)
|
|
361
369
|
|
|
362
370
|
outline_action = self.cursor_style_actions['outline']
|
|
371
|
+
outline_action.setProperty("requires_file", True)
|
|
363
372
|
outline_action.setCheckable(True)
|
|
364
373
|
outline_action.triggered.connect(lambda: set_cursor_style('outline'))
|
|
365
374
|
cursor_menu.addAction(outline_action)
|
|
@@ -382,37 +391,44 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
382
391
|
|
|
383
392
|
zoom_in_action = QAction("Zoom In", self)
|
|
384
393
|
zoom_in_action.setShortcut("Ctrl++")
|
|
394
|
+
zoom_in_action.setProperty("requires_file", True)
|
|
385
395
|
zoom_in_action.triggered.connect(self.image_viewer.zoom_in)
|
|
386
396
|
view_menu.addAction(zoom_in_action)
|
|
387
397
|
|
|
388
398
|
zoom_out_action = QAction("Zoom Out", self)
|
|
389
399
|
zoom_out_action.setShortcut("Ctrl+-")
|
|
400
|
+
zoom_out_action.setProperty("requires_file", True)
|
|
390
401
|
zoom_out_action.triggered.connect(self.image_viewer.zoom_out)
|
|
391
402
|
view_menu.addAction(zoom_out_action)
|
|
392
403
|
|
|
393
404
|
adapt_action = QAction("Adapt to Screen", self)
|
|
394
405
|
adapt_action.setShortcut("Ctrl+0")
|
|
406
|
+
adapt_action.setProperty("requires_file", True)
|
|
395
407
|
adapt_action.triggered.connect(self.image_viewer.reset_zoom)
|
|
396
408
|
view_menu.addAction(adapt_action)
|
|
397
409
|
|
|
398
410
|
actual_size_action = QAction("Actual Size", self)
|
|
399
411
|
actual_size_action.setShortcut("Ctrl+R")
|
|
412
|
+
actual_size_action.setProperty("requires_file", True)
|
|
400
413
|
actual_size_action.triggered.connect(self.image_viewer.actual_size)
|
|
401
414
|
view_menu.addAction(actual_size_action)
|
|
402
415
|
view_menu.addSeparator()
|
|
403
416
|
|
|
404
417
|
self.view_master_action = QAction("View Master", self)
|
|
405
418
|
self.view_master_action.setShortcut("M")
|
|
419
|
+
self.view_master_action.setProperty("requires_file", True)
|
|
406
420
|
self.view_master_action.triggered.connect(self.set_view_master)
|
|
407
421
|
view_menu.addAction(self.view_master_action)
|
|
408
422
|
|
|
409
423
|
self.view_individual_action = QAction("View Individual", self)
|
|
410
424
|
self.view_individual_action.setShortcut("L")
|
|
425
|
+
self.view_individual_action.setProperty("requires_file", True)
|
|
411
426
|
self.view_individual_action.triggered.connect(self.set_view_individual)
|
|
412
427
|
view_menu.addAction(self.view_individual_action)
|
|
413
428
|
|
|
414
429
|
self.toggle_view_master_individual_action = QAction("Toggle Master/Individual", self)
|
|
415
430
|
self.toggle_view_master_individual_action.setShortcut("T")
|
|
431
|
+
self.toggle_view_master_individual_action.setProperty("requires_file", True)
|
|
416
432
|
self.toggle_view_master_individual_action.triggered.connect(
|
|
417
433
|
self.toggle_view_master_individual)
|
|
418
434
|
view_menu.addAction(self.toggle_view_master_individual_action)
|
|
@@ -421,11 +437,13 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
421
437
|
self.set_strategy('overlaid')
|
|
422
438
|
|
|
423
439
|
sort_asc_action = QAction("Sort Layers A-Z", self)
|
|
424
|
-
sort_asc_action.
|
|
440
|
+
sort_asc_action.setProperty("requires_file", True)
|
|
441
|
+
sort_asc_action.triggered.connect(lambda: self.sort_layers_ui('asc'))
|
|
425
442
|
view_menu.addAction(sort_asc_action)
|
|
426
443
|
|
|
427
444
|
sort_desc_action = QAction("Sort Layers Z-A", self)
|
|
428
|
-
sort_desc_action.
|
|
445
|
+
sort_desc_action.setProperty("requires_file", True)
|
|
446
|
+
sort_desc_action.triggered.connect(lambda: self.sort_layers_ui('desc'))
|
|
429
447
|
view_menu.addAction(sort_desc_action)
|
|
430
448
|
|
|
431
449
|
view_menu.addSeparator()
|
|
@@ -433,15 +451,19 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
433
451
|
filter_menu = menubar.addMenu("&Filter")
|
|
434
452
|
filter_menu.setObjectName("Filter")
|
|
435
453
|
denoise_action = QAction("Denoise", self)
|
|
454
|
+
denoise_action.setProperty("requires_file", True)
|
|
436
455
|
denoise_action.triggered.connect(self.denoise_filter)
|
|
437
456
|
filter_menu.addAction(denoise_action)
|
|
438
457
|
unsharp_mask_action = QAction("Unsharp Mask", self)
|
|
458
|
+
unsharp_mask_action.setProperty("requires_file", True)
|
|
439
459
|
unsharp_mask_action.triggered.connect(self.unsharp_mask)
|
|
440
460
|
filter_menu.addAction(unsharp_mask_action)
|
|
441
461
|
white_balance_action = QAction("White Balance", self)
|
|
462
|
+
white_balance_action.setProperty("requires_file", True)
|
|
442
463
|
white_balance_action.triggered.connect(self.white_balance)
|
|
443
464
|
filter_menu.addAction(white_balance_action)
|
|
444
465
|
vignetting_action = QAction("Vignetting Correction", self)
|
|
466
|
+
vignetting_action.setProperty("requires_file", True)
|
|
445
467
|
vignetting_action.triggered.connect(self.vignetting_correction)
|
|
446
468
|
filter_menu.addAction(vignetting_action)
|
|
447
469
|
|
|
@@ -462,20 +484,29 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
462
484
|
prev_layer.activated.connect(self.prev_layer)
|
|
463
485
|
next_layer = QShortcut(QKeySequence(Qt.Key_Down), self, context=Qt.ApplicationShortcut)
|
|
464
486
|
next_layer.activated.connect(self.next_layer)
|
|
487
|
+
|
|
488
|
+
self.set_enabled_file_open_close_actions(False)
|
|
465
489
|
self.installEventFilter(self)
|
|
466
490
|
|
|
491
|
+
def set_enabled_view_toggles(self, enabled):
|
|
492
|
+
self.view_master_action.setEnabled(enabled)
|
|
493
|
+
self.view_individual_action.setEnabled(enabled)
|
|
494
|
+
self.toggle_view_master_individual_action.setEnabled(enabled)
|
|
495
|
+
|
|
467
496
|
def set_strategy(self, strategy):
|
|
468
497
|
self.image_viewer.set_strategy(strategy)
|
|
469
|
-
enable_shortcuts = strategy == 'overlaid'
|
|
470
498
|
self.display_manager.view_mode = 'master'
|
|
471
499
|
self.highlight_master_thumbnail(gui_constants.THUMB_MASTER_HI_COLOR)
|
|
472
|
-
self.
|
|
473
|
-
self.view_individual_action.setEnabled(enable_shortcuts)
|
|
474
|
-
self.toggle_view_master_individual_action.setEnabled(enable_shortcuts)
|
|
500
|
+
self.set_enabled_view_toggles(strategy == 'overlaid')
|
|
475
501
|
for label, mode in self.view_mode_actions.items():
|
|
476
502
|
mode.setEnabled(label != strategy)
|
|
477
503
|
mode.setChecked(label == strategy)
|
|
478
504
|
|
|
505
|
+
def set_enabled_file_open_close_actions(self, enabled):
|
|
506
|
+
for action in self.findChildren(QAction):
|
|
507
|
+
if action.property("requires_file"):
|
|
508
|
+
action.setEnabled(enabled)
|
|
509
|
+
|
|
479
510
|
def update_title(self):
|
|
480
511
|
title = constants.APP_TITLE
|
|
481
512
|
if self.io_gui_handler is not None:
|
|
@@ -544,10 +575,10 @@ class ImageEditorUI(QMainWindow, LayerCollectionHandler):
|
|
|
544
575
|
def save_master_only(self, _checked):
|
|
545
576
|
self.update_title()
|
|
546
577
|
|
|
547
|
-
def
|
|
578
|
+
def sort_layers_ui(self, order):
|
|
548
579
|
self.sort_layers(order)
|
|
549
580
|
self.display_manager.update_thumbnails()
|
|
550
|
-
self.change_layer(self.
|
|
581
|
+
self.change_layer(self.current_layer_idx())
|
|
551
582
|
|
|
552
583
|
def change_layer(self, layer_idx):
|
|
553
584
|
if 0 <= layer_idx < self.number_of_layers():
|
|
@@ -17,6 +17,7 @@ class IOGuiHandler(QObject, LayerCollectionHandler):
|
|
|
17
17
|
mark_as_modified_requested = Signal(bool)
|
|
18
18
|
change_layer_requested = Signal(int)
|
|
19
19
|
add_recent_file_requested = Signal(str)
|
|
20
|
+
set_enabled_file_open_close_actions_requested = Signal(bool)
|
|
20
21
|
|
|
21
22
|
def __init__(self, layer_collection, undo_manager, parent):
|
|
22
23
|
QObject.__init__(self, parent)
|
|
@@ -165,6 +166,7 @@ class IOGuiHandler(QObject, LayerCollectionHandler):
|
|
|
165
166
|
self.change_layer_requested.emit(0)
|
|
166
167
|
self.status_message_requested.emit(message)
|
|
167
168
|
self.update_title_requested.emit()
|
|
169
|
+
self.set_enabled_file_open_close_actions_requested.emit(True)
|
|
168
170
|
self.add_recent_file_requested.emit(self.current_file_path_master)
|
|
169
171
|
|
|
170
172
|
def save_file(self):
|
|
@@ -277,4 +279,5 @@ class IOGuiHandler(QObject, LayerCollectionHandler):
|
|
|
277
279
|
self.display_manager.thumbnail_list.clear()
|
|
278
280
|
self.display_manager.update_thumbnails()
|
|
279
281
|
self.update_title_requested.emit()
|
|
282
|
+
self.set_enabled_file_open_close_actions_requested.emit(False)
|
|
280
283
|
self.status_message_requested.emit("File closed")
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# pylint: disable=C0114, C0115, C0116, E0611, E1101, R0904, R0912, R0914, R0902, E0202
|
|
2
2
|
from PySide6.QtCore import Qt, QPointF, QEvent, QRectF
|
|
3
|
-
from .. config.gui_constants import gui_constants
|
|
4
3
|
from .view_strategy import ViewStrategy, ImageGraphicsViewBase, ViewSignals
|
|
5
4
|
|
|
6
5
|
|
|
@@ -61,41 +60,9 @@ class OverlaidView(ViewStrategy, ImageGraphicsViewBase, ViewSignals):
|
|
|
61
60
|
self.mouse_release_event(event)
|
|
62
61
|
super().mouseReleaseEvent(event)
|
|
63
62
|
|
|
64
|
-
# pylint: enable=R0801
|
|
65
63
|
def wheelEvent(self, event):
|
|
66
|
-
|
|
67
|
-
return
|
|
68
|
-
if event.source() == Qt.MouseEventNotSynthesized: # Physical mouse
|
|
69
|
-
if self.control_pressed:
|
|
70
|
-
self.brush_size_change_requested.emit(1 if event.angleDelta().y() > 0 else -1)
|
|
71
|
-
else:
|
|
72
|
-
zoom_in_factor = gui_constants.ZOOM_IN_FACTOR
|
|
73
|
-
zoom_out_factor = gui_constants.ZOOM_OUT_FACTOR
|
|
74
|
-
current_scale = self.get_current_scale()
|
|
75
|
-
if event.angleDelta().y() > 0: # Zoom in
|
|
76
|
-
new_scale = current_scale * zoom_in_factor
|
|
77
|
-
if new_scale <= self.max_scale():
|
|
78
|
-
self.scale(zoom_in_factor, zoom_in_factor)
|
|
79
|
-
self.set_zoom_factor(new_scale)
|
|
80
|
-
else: # Zoom out
|
|
81
|
-
new_scale = current_scale * zoom_out_factor
|
|
82
|
-
if new_scale >= self.min_scale():
|
|
83
|
-
self.scale(zoom_out_factor, zoom_out_factor)
|
|
84
|
-
self.set_zoom_factor(new_scale)
|
|
85
|
-
self.update_brush_cursor()
|
|
86
|
-
else: # Touchpad event - fallback for systems without gesture recognition
|
|
87
|
-
if not self.control_pressed:
|
|
88
|
-
delta = event.pixelDelta() or event.angleDelta() / 8
|
|
89
|
-
if delta:
|
|
90
|
-
self.scroll_view(self, delta.x(), delta.y())
|
|
91
|
-
else: # Control + touchpad scroll for zoom
|
|
92
|
-
zoom_in = event.angleDelta().y() > 0
|
|
93
|
-
if zoom_in:
|
|
94
|
-
self.zoom_in()
|
|
95
|
-
else:
|
|
96
|
-
self.zoom_out()
|
|
64
|
+
self.handle_wheel_event(event)
|
|
97
65
|
event.accept()
|
|
98
|
-
# pylint: disable=R0801
|
|
99
66
|
|
|
100
67
|
def enterEvent(self, event):
|
|
101
68
|
self.activateWindow()
|
|
@@ -114,10 +81,13 @@ class OverlaidView(ViewStrategy, ImageGraphicsViewBase, ViewSignals):
|
|
|
114
81
|
def set_mouse_callbacks(self, callbacks):
|
|
115
82
|
self.mousePressEvent = callbacks
|
|
116
83
|
|
|
84
|
+
def get_view_with_mouse(self, event=None):
|
|
85
|
+
return self
|
|
86
|
+
|
|
87
|
+
# pylint: enable=C0103
|
|
117
88
|
def show(self):
|
|
118
89
|
self.show_master()
|
|
119
90
|
super().show()
|
|
120
|
-
# pylint: enable=C0103
|
|
121
91
|
|
|
122
92
|
def event(self, event):
|
|
123
93
|
if event.type() == QEvent.Gesture:
|
|
@@ -126,14 +96,7 @@ class OverlaidView(ViewStrategy, ImageGraphicsViewBase, ViewSignals):
|
|
|
126
96
|
|
|
127
97
|
def setup_scene_image(self, pixmap, pixmap_item):
|
|
128
98
|
self.setSceneRect(QRectF(pixmap.rect()))
|
|
129
|
-
|
|
130
|
-
self.set_max_min_scales(img_width, img_height)
|
|
131
|
-
view_rect = self.viewport().rect()
|
|
132
|
-
scale_x = view_rect.width() / img_width
|
|
133
|
-
scale_y = view_rect.height() / img_height
|
|
134
|
-
scale_factor = min(scale_x, scale_y)
|
|
135
|
-
scale_factor = max(self.min_scale(), min(scale_factor, self.max_scale()))
|
|
136
|
-
self.set_zoom_factor(scale_factor)
|
|
99
|
+
_img_width, _img_height, scale_factor = self.setup_view_image(self, pixmap)
|
|
137
100
|
self.resetTransform()
|
|
138
101
|
self.scale(scale_factor, scale_factor)
|
|
139
102
|
self.centerOn(pixmap_item)
|
|
@@ -3,6 +3,7 @@ import time
|
|
|
3
3
|
from PySide6.QtCore import Qt, Signal, QEvent, QRectF
|
|
4
4
|
from PySide6.QtGui import QCursor
|
|
5
5
|
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QFrame
|
|
6
|
+
|
|
6
7
|
from .view_strategy import ViewStrategy, ImageGraphicsViewBase, ViewSignals
|
|
7
8
|
|
|
8
9
|
|
|
@@ -229,25 +230,20 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
|
|
|
229
230
|
self.current_view.mousePressEvent = callbacks
|
|
230
231
|
# pylint: enable=C0103
|
|
231
232
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
delta = event.pixelDelta() or event.angleDelta() / 8
|
|
247
|
-
if delta:
|
|
248
|
-
self.scroll_view(self.master_view, delta.x(), delta.y())
|
|
249
|
-
self.scroll_view(self.current_view, delta.x(), delta.y())
|
|
250
|
-
# pylint: disable=R0801
|
|
233
|
+
def get_view_with_mouse(self, event=None):
|
|
234
|
+
if event is None:
|
|
235
|
+
mouse_pos_global = QCursor.pos()
|
|
236
|
+
else:
|
|
237
|
+
mouse_pos_global = event.globalPosition().toPoint()
|
|
238
|
+
mouse_pos_current = self.current_view.mapFromGlobal(mouse_pos_global)
|
|
239
|
+
mouse_pos_master = self.master_view.mapFromGlobal(mouse_pos_global)
|
|
240
|
+
current_has_mouse = self.current_view.rect().contains(mouse_pos_current)
|
|
241
|
+
master_has_mouse = self.master_view.rect().contains(mouse_pos_master)
|
|
242
|
+
if master_has_mouse:
|
|
243
|
+
return self.master_view
|
|
244
|
+
if current_has_mouse:
|
|
245
|
+
return self.current_view
|
|
246
|
+
return None
|
|
251
247
|
|
|
252
248
|
def _apply_zoom_to_view(self, view, factor):
|
|
253
249
|
view.scale(factor, factor)
|
|
@@ -383,14 +379,7 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
|
|
|
383
379
|
pixmap = self.status.pixmap_master
|
|
384
380
|
self.master_view.setSceneRect(QRectF(pixmap.rect()))
|
|
385
381
|
self.pixmap_item_master.setPixmap(pixmap)
|
|
386
|
-
img_width, img_height =
|
|
387
|
-
self.set_max_min_scales(img_width, img_height)
|
|
388
|
-
view_rect = self.master_view.viewport().rect()
|
|
389
|
-
scale_x = view_rect.width() / img_width
|
|
390
|
-
scale_y = view_rect.height() / img_height
|
|
391
|
-
scale_factor = min(scale_x, scale_y)
|
|
392
|
-
scale_factor = max(self.min_scale(), min(scale_factor, self.max_scale()))
|
|
393
|
-
self.set_zoom_factor(scale_factor)
|
|
382
|
+
img_width, img_height, scale_factor = self.setup_view_image(self.master_view, pixmap)
|
|
394
383
|
self.master_view.resetTransform()
|
|
395
384
|
self.master_view.scale(scale_factor, scale_factor)
|
|
396
385
|
self.master_view.centerOn(self.pixmap_item_master)
|
|
@@ -439,8 +428,7 @@ class DoubleViewBase(ViewStrategy, QWidget, ViewSignals):
|
|
|
439
428
|
size = self.brush.size
|
|
440
429
|
radius = size / 2
|
|
441
430
|
self.current_brush_cursor.setRect(
|
|
442
|
-
scene_pos.x() - radius, scene_pos.y() - radius,
|
|
443
|
-
size, size)
|
|
431
|
+
scene_pos.x() - radius, scene_pos.y() - radius, size, size)
|
|
444
432
|
if self.brush_cursor.isVisible():
|
|
445
433
|
self.update_current_cursor_color()
|
|
446
434
|
self.current_brush_cursor.show()
|
|
@@ -68,6 +68,7 @@ class BrushCursor(QGraphicsItemGroup):
|
|
|
68
68
|
|
|
69
69
|
def setRect(self, x, y, w, h):
|
|
70
70
|
self._rect = QRectF(x, y, w, h)
|
|
71
|
+
self._radius = min(w, h) / 2
|
|
71
72
|
self._create_arcs()
|
|
72
73
|
|
|
73
74
|
def rect(self):
|
|
@@ -96,6 +97,8 @@ class ImageGraphicsViewBase(QGraphicsView):
|
|
|
96
97
|
self.setRenderHint(QPainter.Antialiasing)
|
|
97
98
|
self.setRenderHint(QPainter.SmoothPixmapTransform)
|
|
98
99
|
self.setCursor(Qt.BlankCursor)
|
|
100
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
|
101
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
|
99
102
|
|
|
100
103
|
|
|
101
104
|
class ViewStrategy(LayerCollectionHandler):
|
|
@@ -187,6 +190,10 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
187
190
|
def set_mouse_callbacks(self, callbacks):
|
|
188
191
|
pass
|
|
189
192
|
|
|
193
|
+
@abstractmethod
|
|
194
|
+
def get_view_with_mouse(self, event=None):
|
|
195
|
+
pass
|
|
196
|
+
|
|
190
197
|
def hide_brush_cursor(self):
|
|
191
198
|
if self.brush_cursor:
|
|
192
199
|
self.brush_cursor.hide()
|
|
@@ -319,6 +326,17 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
319
326
|
return QImage(memoryview(array), width, height, 3 * width, QImage.Format_RGB888)
|
|
320
327
|
return QImage()
|
|
321
328
|
|
|
329
|
+
def setup_view_image(self, view, pixmap):
|
|
330
|
+
img_width, img_height = pixmap.width(), pixmap.height()
|
|
331
|
+
self.set_max_min_scales(img_width, img_height)
|
|
332
|
+
view_rect = view.viewport().rect()
|
|
333
|
+
scale_x = view_rect.width() / img_width
|
|
334
|
+
scale_y = view_rect.height() / img_height
|
|
335
|
+
scale_factor = min(scale_x, scale_y)
|
|
336
|
+
scale_factor = max(self.min_scale(), min(scale_factor, self.max_scale()))
|
|
337
|
+
self.set_zoom_factor(scale_factor)
|
|
338
|
+
return img_width, img_height, scale_factor
|
|
339
|
+
|
|
322
340
|
def create_scene(self, view):
|
|
323
341
|
scene = QGraphicsScene()
|
|
324
342
|
view.setScene(scene)
|
|
@@ -340,21 +358,6 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
340
358
|
gui_constants.MIN_ZOOMED_IMG_HEIGHT / img_height))
|
|
341
359
|
self.set_max_scale(gui_constants.MAX_ZOOMED_IMG_PX_SIZE)
|
|
342
360
|
|
|
343
|
-
def zoom_in(self):
|
|
344
|
-
if self.empty():
|
|
345
|
-
return
|
|
346
|
-
master_view = self.get_master_view()
|
|
347
|
-
old_center = master_view.mapToScene(master_view.viewport().rect().center())
|
|
348
|
-
current_scale = self.get_current_scale()
|
|
349
|
-
new_scale = current_scale * gui_constants.ZOOM_IN_FACTOR
|
|
350
|
-
if new_scale <= self.max_scale():
|
|
351
|
-
for view in self.get_views():
|
|
352
|
-
view.scale(gui_constants.ZOOM_IN_FACTOR, gui_constants.ZOOM_IN_FACTOR)
|
|
353
|
-
self.set_zoom_factor(new_scale)
|
|
354
|
-
master_view.centerOn(old_center)
|
|
355
|
-
self.update_brush_cursor()
|
|
356
|
-
self.update_cursor_pen_width()
|
|
357
|
-
|
|
358
361
|
def apply_zoom(self):
|
|
359
362
|
if self.empty():
|
|
360
363
|
return
|
|
@@ -363,20 +366,98 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
363
366
|
scale_factor = self.zoom_factor() / current_scale
|
|
364
367
|
view.scale(scale_factor, scale_factor)
|
|
365
368
|
|
|
366
|
-
def
|
|
369
|
+
def center_image(self, view):
|
|
370
|
+
view.horizontalScrollBar().setValue(self.status.h_scroll)
|
|
371
|
+
view.verticalScrollBar().setValue(self.status.v_scroll)
|
|
372
|
+
|
|
373
|
+
def set_scroll_and_center(self, view, delta):
|
|
374
|
+
self.status.set_scroll(
|
|
375
|
+
view.horizontalScrollBar().value() + int(delta.x() * self.zoom_factor()),
|
|
376
|
+
view.verticalScrollBar().value() + int(delta.y() * self.zoom_factor()))
|
|
377
|
+
self.center_image(view)
|
|
378
|
+
|
|
379
|
+
def apply_zoom_and_center(self, view, new_scale, ref_pos, old_center):
|
|
380
|
+
self.set_zoom_factor(new_scale)
|
|
381
|
+
self.apply_zoom()
|
|
382
|
+
new_center = view.mapToScene(ref_pos)
|
|
383
|
+
delta = old_center - new_center
|
|
384
|
+
self.set_scroll_and_center(view, delta)
|
|
385
|
+
|
|
386
|
+
def handle_pinch_gesture(self, pinch):
|
|
387
|
+
master_view = self.get_master_view()
|
|
388
|
+
if pinch.state() == Qt.GestureStarted:
|
|
389
|
+
self.pinch_start_scale = self.zoom_factor()
|
|
390
|
+
self.pinch_center_view = pinch.centerPoint()
|
|
391
|
+
self.pinch_center_scene = master_view.mapToScene(self.pinch_center_view.toPoint())
|
|
392
|
+
self.gesture_active = True
|
|
393
|
+
elif pinch.state() == Qt.GestureUpdated:
|
|
394
|
+
new_scale = self.pinch_start_scale * pinch.totalScaleFactor()
|
|
395
|
+
new_scale = max(self.min_scale(), min(new_scale, self.max_scale()))
|
|
396
|
+
if abs(new_scale - self.zoom_factor()) > 0.01:
|
|
397
|
+
old_center = self.pinch_center_scene
|
|
398
|
+
ref_pos = self.pinch_center_view.toPoint()
|
|
399
|
+
self.apply_zoom_and_center(master_view, new_scale, ref_pos, old_center)
|
|
400
|
+
elif pinch.state() in (Qt.GestureFinished, Qt.GestureCanceled):
|
|
401
|
+
self.gesture_active = False
|
|
402
|
+
self.update_cursor_pen_width()
|
|
403
|
+
|
|
404
|
+
def do_zoom(self, new_scale, view):
|
|
367
405
|
if self.empty():
|
|
368
406
|
return
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
407
|
+
if not self.min_scale() <= new_scale <= self.max_scale():
|
|
408
|
+
return
|
|
409
|
+
if view is None:
|
|
410
|
+
view = self.get_master_view()
|
|
411
|
+
global_pos = QCursor.pos()
|
|
412
|
+
ref_pos = view.mapFromGlobal(global_pos)
|
|
413
|
+
old_center = view.mapToScene(ref_pos)
|
|
414
|
+
self.apply_zoom_and_center(view, new_scale, ref_pos, old_center)
|
|
415
|
+
self.update_cursor_pen_width()
|
|
416
|
+
|
|
417
|
+
def handle_wheel_event(self, event):
|
|
418
|
+
if self.empty() or self.gesture_active:
|
|
419
|
+
return
|
|
420
|
+
if event.source() == Qt.MouseEventNotSynthesized: # Physical mouse
|
|
421
|
+
if self.control_pressed:
|
|
422
|
+
self.brush_size_change_requested.emit(1 if event.angleDelta().y() > 0 else -1)
|
|
423
|
+
else:
|
|
424
|
+
self.handle_zoom_wheel(self.get_view_with_mouse(event), event)
|
|
378
425
|
self.update_brush_cursor()
|
|
379
|
-
|
|
426
|
+
else:
|
|
427
|
+
self.handle_wheel_touchpad_event(event)
|
|
428
|
+
|
|
429
|
+
def handle_wheel_touchpad_event(self, event):
|
|
430
|
+
if not self.control_pressed:
|
|
431
|
+
delta = event.pixelDelta() or event.angleDelta() / 8
|
|
432
|
+
if delta:
|
|
433
|
+
self.scroll_view(self.get_view_with_mouse(event), delta.x(), delta.y())
|
|
434
|
+
else:
|
|
435
|
+
zoom_in = event.angleDelta().y() > 0
|
|
436
|
+
if zoom_in:
|
|
437
|
+
self.zoom_in()
|
|
438
|
+
else:
|
|
439
|
+
self.zoom_out()
|
|
440
|
+
|
|
441
|
+
def handle_zoom_wheel(self, view, event):
|
|
442
|
+
if view is None:
|
|
443
|
+
return
|
|
444
|
+
current_scale = self.get_current_scale()
|
|
445
|
+
if event.angleDelta().y() > 0:
|
|
446
|
+
new_scale = current_scale * gui_constants.ZOOM_IN_FACTOR
|
|
447
|
+
else:
|
|
448
|
+
new_scale = current_scale * gui_constants.ZOOM_OUT_FACTOR
|
|
449
|
+
new_scale = max(self.min_scale(), min(new_scale, self.max_scale()))
|
|
450
|
+
self.do_zoom(new_scale, view)
|
|
451
|
+
|
|
452
|
+
def zoom_in(self):
|
|
453
|
+
self.do_zoom(
|
|
454
|
+
self.get_current_scale() * gui_constants.ZOOM_IN_FACTOR,
|
|
455
|
+
self.get_view_with_mouse())
|
|
456
|
+
|
|
457
|
+
def zoom_out(self):
|
|
458
|
+
self.do_zoom(
|
|
459
|
+
self.get_current_scale() * gui_constants.ZOOM_OUT_FACTOR,
|
|
460
|
+
self.get_view_with_mouse())
|
|
380
461
|
|
|
381
462
|
def reset_zoom(self):
|
|
382
463
|
if self.empty():
|
|
@@ -479,7 +560,8 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
479
560
|
self.update_master_cursor_color()
|
|
480
561
|
if self.cursor_style == 'brush':
|
|
481
562
|
self.setup_simple_brush_style(scene_pos.x(), scene_pos.y(), radius)
|
|
482
|
-
self.
|
|
563
|
+
if not self.scrolling:
|
|
564
|
+
self.show_brush_cursor()
|
|
483
565
|
|
|
484
566
|
def update_color_time(self):
|
|
485
567
|
current_time = time.time()
|
|
@@ -612,10 +694,6 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
612
694
|
self.status.set_scroll(view.horizontalScrollBar().value(),
|
|
613
695
|
view.verticalScrollBar().value())
|
|
614
696
|
|
|
615
|
-
def center_image(self, view):
|
|
616
|
-
view.horizontalScrollBar().setValue(self.status.h_scroll)
|
|
617
|
-
view.verticalScrollBar().setValue(self.status.v_scroll)
|
|
618
|
-
|
|
619
697
|
def mouse_move_event(self, event):
|
|
620
698
|
if self.empty():
|
|
621
699
|
return
|
|
@@ -662,7 +740,8 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
662
740
|
self.last_brush_pos = event.position()
|
|
663
741
|
self.brush_operation_started.emit(event.position().toPoint())
|
|
664
742
|
self.dragging = True
|
|
665
|
-
self.
|
|
743
|
+
if not self.scrolling:
|
|
744
|
+
self.show_brush_cursor()
|
|
666
745
|
|
|
667
746
|
def mouse_release_event(self, event):
|
|
668
747
|
if self.empty():
|
|
@@ -681,28 +760,3 @@ class ViewStrategy(LayerCollectionHandler):
|
|
|
681
760
|
elif self.dragging:
|
|
682
761
|
self.dragging = False
|
|
683
762
|
self.brush_operation_ended.emit()
|
|
684
|
-
|
|
685
|
-
def handle_pinch_gesture(self, pinch):
|
|
686
|
-
master_view = self.get_master_view()
|
|
687
|
-
if pinch.state() == Qt.GestureStarted:
|
|
688
|
-
self.pinch_start_scale = self.zoom_factor()
|
|
689
|
-
self.pinch_center_view = pinch.centerPoint()
|
|
690
|
-
self.pinch_center_scene = master_view.mapToScene(self.pinch_center_view.toPoint())
|
|
691
|
-
self.gesture_active = True
|
|
692
|
-
elif pinch.state() == Qt.GestureUpdated:
|
|
693
|
-
new_scale = self.pinch_start_scale * pinch.totalScaleFactor()
|
|
694
|
-
new_scale = max(self.min_scale(), min(new_scale, self.max_scale()))
|
|
695
|
-
if abs(new_scale - self.zoom_factor()) > 0.01:
|
|
696
|
-
self.set_zoom_factor(new_scale)
|
|
697
|
-
self.apply_zoom()
|
|
698
|
-
new_center = master_view.mapToScene(self.pinch_center_view.toPoint())
|
|
699
|
-
delta = self.pinch_center_scene - new_center
|
|
700
|
-
h_scroll = master_view.horizontalScrollBar().value() + \
|
|
701
|
-
int(delta.x() * self.zoom_factor())
|
|
702
|
-
v_scroll = master_view.verticalScrollBar().value() + \
|
|
703
|
-
int(delta.y() * self.zoom_factor())
|
|
704
|
-
self.status.set_scroll(h_scroll, v_scroll)
|
|
705
|
-
self.center_image(master_view)
|
|
706
|
-
elif pinch.state() in (Qt.GestureFinished, Qt.GestureCanceled):
|
|
707
|
-
self.gesture_active = False
|
|
708
|
-
self.update_cursor_pen_width()
|
|
@@ -49,7 +49,6 @@ class WhiteBalanceFilter(BaseFilter):
|
|
|
49
49
|
self.value_labels[name] = val_label
|
|
50
50
|
row_layout.addLayout(sliders_layout)
|
|
51
51
|
layout.addLayout(row_layout)
|
|
52
|
-
|
|
53
52
|
rbg_layout = QHBoxLayout()
|
|
54
53
|
rbg_layout.addWidget(QLabel("RBG hex:"))
|
|
55
54
|
self.rgb_hex = QLineEdit(self.hex_color(self.initial_val))
|
|
@@ -58,7 +57,6 @@ class WhiteBalanceFilter(BaseFilter):
|
|
|
58
57
|
rbg_layout.addWidget(self.rgb_hex)
|
|
59
58
|
rbg_layout.addStretch(1)
|
|
60
59
|
layout.addLayout(rbg_layout)
|
|
61
|
-
|
|
62
60
|
pick_button = QPushButton("Pick Color")
|
|
63
61
|
layout.addWidget(pick_button)
|
|
64
62
|
self.create_base_widgets(
|
|
@@ -126,17 +124,18 @@ class WhiteBalanceFilter(BaseFilter):
|
|
|
126
124
|
bgr = self.get_pixel_color_at(
|
|
127
125
|
pos, radius=int(self.image_viewer.get_brush().size))
|
|
128
126
|
rgb = (bgr[2], bgr[1], bgr[0])
|
|
127
|
+
QApplication.restoreOverrideCursor()
|
|
128
|
+
self.image_viewer.unsetCursor()
|
|
129
|
+
self.image_viewer.strategy.set_mouse_callbacks(self.original_mouse_press)
|
|
130
|
+
self.filter_gui_set_enabled_requested.emit(True)
|
|
131
|
+
self.image_viewer.hide_brush_preview()
|
|
129
132
|
new_filter = WhiteBalanceFilter(
|
|
130
133
|
self.name, self.parent(), self.image_viewer, self.layer_collection,
|
|
131
134
|
self.undo_manager)
|
|
132
135
|
new_filter.run_with_preview(init_val=rgb)
|
|
133
|
-
QApplication.restoreOverrideCursor()
|
|
134
|
-
self.image_viewer.unsetCursor()
|
|
135
|
-
self.image_viewer.strategy.set_mouse_callbacks(self.original_mouse_press)
|
|
136
136
|
self.image_viewer.set_cursor_style(self.original_cursor_style)
|
|
137
137
|
self.image_viewer.show_brush_cursor()
|
|
138
138
|
self.image_viewer.show_brush_preview()
|
|
139
|
-
self.filter_gui_set_enabled_requested.emit(True)
|
|
140
139
|
|
|
141
140
|
def reset_rgb(self):
|
|
142
141
|
for name, slider in self.sliders.items():
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
shinestacker/__init__.py,sha256=uq2fjAw2z_6TpH3mOcWFZ98GoEPRsNhTAK8N0MMm_e8,448
|
|
2
|
-
shinestacker/_version.py,sha256=
|
|
2
|
+
shinestacker/_version.py,sha256=HfPNw49U2WWQOQlRuPSUUE8x8nkPx62dtjaGJfbhyTk,21
|
|
3
3
|
shinestacker/algorithms/__init__.py,sha256=1FwVJ3w9GGbFFkjYJRUedTvcdE4j0ieSgaH9RC9iCY4,877
|
|
4
4
|
shinestacker/algorithms/align.py,sha256=mb44u-YxZI1TTSHz81nRpX_2c8awlOhnGrK0LyfTQeQ,33543
|
|
5
5
|
shinestacker/algorithms/align_auto.py,sha256=pJetw6zZEWQLouzcelkI8gD4cPiOp887ePXzVbm0E6Q,3800
|
|
@@ -49,10 +49,10 @@ shinestacker/gui/folder_file_selection.py,sha256=IYWfZQFkoD5iO7zJ7BxVVDP9F3Dc0EX
|
|
|
49
49
|
shinestacker/gui/gui_images.py,sha256=k39DpdsxcmYoRdHNNZj6OpFAas0GOHS4JSG542wfheg,5728
|
|
50
50
|
shinestacker/gui/gui_logging.py,sha256=kiZcrC2AFYCWgPZo0O5SKw-E5cFrezwf4anS3HjPuNw,8168
|
|
51
51
|
shinestacker/gui/gui_run.py,sha256=zr7x4BVmM0n_ZRsSEaJVVKvHSWHuwhftgkUvgeg90gU,15767
|
|
52
|
-
shinestacker/gui/main_window.py,sha256=
|
|
53
|
-
shinestacker/gui/menu_manager.py,sha256=
|
|
52
|
+
shinestacker/gui/main_window.py,sha256=zOxIRn6urmnmfDOR1JJ3n6xsT1qryOt1s7kZxwh-qYI,25202
|
|
53
|
+
shinestacker/gui/menu_manager.py,sha256=legmYEpQxuzEQoDhxMUWiwCcYTXwd-uRfAju-Nymy8g,11664
|
|
54
54
|
shinestacker/gui/new_project.py,sha256=z8e3EhRMB-KtoPwYQSiKLSOQ2dS0-Okm7zVw21B7zy8,16391
|
|
55
|
-
shinestacker/gui/project_controller.py,sha256=
|
|
55
|
+
shinestacker/gui/project_controller.py,sha256=7vSyoxepplJrf0VsbPrZkMqtHW6rtPgEOZgdPsOPVoQ,16490
|
|
56
56
|
shinestacker/gui/project_converter.py,sha256=Gmna0HwbvACcXiX74TaQYumif8ZV8sZ2APLTMM-L1mU,7436
|
|
57
57
|
shinestacker/gui/project_editor.py,sha256=lSgQ42IoaobHs-NQQWT88Qhg5l7nu5ejxAO5VgIupr8,25498
|
|
58
58
|
shinestacker/gui/project_model.py,sha256=eRUmH3QmRzDtPtZoxgT6amKzN8_5XzwjHgEJeL-_JOE,4263
|
|
@@ -82,24 +82,24 @@ shinestacker/retouch/exif_data.py,sha256=LF-fRXW-reMq-xJ_QRE5j8DC2LVGKIlC6MR3QbC
|
|
|
82
82
|
shinestacker/retouch/file_loader.py,sha256=z02-A8_uDZxayI1NFTxT2GVUvEBWStchX9hlN1o5-0U,4784
|
|
83
83
|
shinestacker/retouch/filter_manager.py,sha256=tOGIWj5HjViL1-iXHkd91X-sZ1c1G531pDmLO0x6zx0,866
|
|
84
84
|
shinestacker/retouch/icon_container.py,sha256=6gw1HO1bC2FrdB4dc_iH81DQuLjzuvRGksZ2hKLT9yA,585
|
|
85
|
-
shinestacker/retouch/image_editor_ui.py,sha256
|
|
85
|
+
shinestacker/retouch/image_editor_ui.py,sha256=-UVWeFSnXyHOG7XEIl9wNhiCjH5R0UFeM2VOg5R6ozs,33435
|
|
86
86
|
shinestacker/retouch/image_view_status.py,sha256=bdIhsXiYXm7eyjkTGWkw5PRShzaF_by-g7daqgmhwjM,1858
|
|
87
87
|
shinestacker/retouch/image_viewer.py,sha256=H8w-ORug1aKf7X3FeSX4lQV-a0IewZ9OVG1-50BK4cE,4452
|
|
88
|
-
shinestacker/retouch/io_gui_handler.py,sha256=
|
|
88
|
+
shinestacker/retouch/io_gui_handler.py,sha256=UOnrFT00s0075Ng_yJACJX9TP8UT9mQOWXwQwNAfpMw,12079
|
|
89
89
|
shinestacker/retouch/io_manager.py,sha256=JUAA--AK0mVa1PTErJTnBFjaXIle5Qs7Ow0Wkd8at0o,2437
|
|
90
90
|
shinestacker/retouch/layer_collection.py,sha256=fZlGrkm9-Ycc7AOzFSpImhafiTieBeCZRk-UlvlFHbo,5819
|
|
91
|
-
shinestacker/retouch/overlaid_view.py,sha256=
|
|
91
|
+
shinestacker/retouch/overlaid_view.py,sha256=KBwuzC2OQsK7rdtFAKrSvXrHrEV1SiOoZhxPCQLGkvg,6734
|
|
92
92
|
shinestacker/retouch/shortcuts_help.py,sha256=BFWTT5QvodqMhqa_9LI25hZqjICfckgyWG4fGrGzvnM,4283
|
|
93
|
-
shinestacker/retouch/sidebyside_view.py,sha256=
|
|
93
|
+
shinestacker/retouch/sidebyside_view.py,sha256=Ipx5ckaAuEv6fnxg4RpENj00ew6-M2jLsnTKUcYKcAk,18055
|
|
94
94
|
shinestacker/retouch/transformation_manager.py,sha256=NSHGUF-JFv4Y81gSvizjQCTp49TLo1so7c0WoUElO08,1812
|
|
95
95
|
shinestacker/retouch/undo_manager.py,sha256=cKUkqnJtnJ-Hq-LQs5Bv49FC6qkG6XSw9oCVySJ8jS0,4312
|
|
96
96
|
shinestacker/retouch/unsharp_mask_filter.py,sha256=Iapc8UmSVpj3V0LcJq_38P5qerRqTevMynbbk5Rk6iE,3634
|
|
97
|
-
shinestacker/retouch/view_strategy.py,sha256=
|
|
97
|
+
shinestacker/retouch/view_strategy.py,sha256=u9oOB-fxap_ijNJ3O3Ev5OMLH-bDZNGj4hyBkJUDeeo,27993
|
|
98
98
|
shinestacker/retouch/vignetting_filter.py,sha256=JhFr6OVIripQzSJrZEG4lxq7wBsmpofLqJQ-aP2bKw8,3789
|
|
99
|
-
shinestacker/retouch/white_balance_filter.py,sha256=
|
|
100
|
-
shinestacker-1.5.
|
|
101
|
-
shinestacker-1.5.
|
|
102
|
-
shinestacker-1.5.
|
|
103
|
-
shinestacker-1.5.
|
|
104
|
-
shinestacker-1.5.
|
|
105
|
-
shinestacker-1.5.
|
|
99
|
+
shinestacker/retouch/white_balance_filter.py,sha256=UaH4yxG3fU4vPutBAkV5oTXIQyUTN09x0uTywAzv3sY,8286
|
|
100
|
+
shinestacker-1.5.4.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
|
|
101
|
+
shinestacker-1.5.4.dist-info/METADATA,sha256=1cFUICQsSTKF1T8L7sNiT7XQ_UkwXlIMRr64bym9TvA,6978
|
|
102
|
+
shinestacker-1.5.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
103
|
+
shinestacker-1.5.4.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
|
|
104
|
+
shinestacker-1.5.4.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
|
|
105
|
+
shinestacker-1.5.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|