shinestacker 1.5.3__py3-none-any.whl → 1.6.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.

Files changed (38) hide show
  1. shinestacker/_version.py +1 -1
  2. shinestacker/algorithms/multilayer.py +1 -1
  3. shinestacker/algorithms/stack.py +17 -9
  4. shinestacker/app/args_parser_opts.py +4 -0
  5. shinestacker/app/gui_utils.py +10 -2
  6. shinestacker/app/main.py +5 -2
  7. shinestacker/app/project.py +4 -2
  8. shinestacker/app/retouch.py +3 -1
  9. shinestacker/app/settings_dialog.py +171 -0
  10. shinestacker/config/app_config.py +30 -0
  11. shinestacker/config/constants.py +3 -0
  12. shinestacker/config/gui_constants.py +4 -2
  13. shinestacker/config/settings.py +110 -0
  14. shinestacker/gui/action_config.py +6 -5
  15. shinestacker/gui/action_config_dialog.py +17 -74
  16. shinestacker/gui/config_dialog.py +78 -0
  17. shinestacker/gui/main_window.py +16 -6
  18. shinestacker/gui/menu_manager.py +16 -10
  19. shinestacker/gui/new_project.py +2 -1
  20. shinestacker/gui/project_controller.py +11 -6
  21. shinestacker/gui/project_model.py +16 -1
  22. shinestacker/gui/recent_file_manager.py +3 -21
  23. shinestacker/retouch/display_manager.py +47 -5
  24. shinestacker/retouch/image_editor_ui.py +59 -15
  25. shinestacker/retouch/image_view_status.py +4 -1
  26. shinestacker/retouch/io_gui_handler.py +3 -0
  27. shinestacker/retouch/overlaid_view.py +6 -43
  28. shinestacker/retouch/sidebyside_view.py +45 -41
  29. shinestacker/retouch/transformation_manager.py +0 -1
  30. shinestacker/retouch/undo_manager.py +1 -1
  31. shinestacker/retouch/view_strategy.py +125 -61
  32. shinestacker/retouch/white_balance_filter.py +5 -6
  33. {shinestacker-1.5.3.dist-info → shinestacker-1.6.0.dist-info}/METADATA +1 -1
  34. {shinestacker-1.5.3.dist-info → shinestacker-1.6.0.dist-info}/RECORD +38 -34
  35. {shinestacker-1.5.3.dist-info → shinestacker-1.6.0.dist-info}/WHEEL +0 -0
  36. {shinestacker-1.5.3.dist-info → shinestacker-1.6.0.dist-info}/entry_points.txt +0 -0
  37. {shinestacker-1.5.3.dist-info → shinestacker-1.6.0.dist-info}/licenses/LICENSE +0 -0
  38. {shinestacker-1.5.3.dist-info → shinestacker-1.6.0.dist-info}/top_level.txt +0 -0
@@ -9,6 +9,7 @@ from PySide6.QtWidgets import (
9
9
  QGraphicsEllipseItem, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem,
10
10
  QGraphicsItemGroup, QGraphicsPathItem)
11
11
  from .. config.gui_constants import gui_constants
12
+ from .. config.app_config import AppConfig
12
13
  from .layer_collection import LayerCollectionHandler
13
14
  from .brush_gradient import create_default_brush_gradient
14
15
  from .brush_preview import BrushPreviewItem
@@ -68,6 +69,7 @@ class BrushCursor(QGraphicsItemGroup):
68
69
 
69
70
  def setRect(self, x, y, w, h):
70
71
  self._rect = QRectF(x, y, w, h)
72
+ self._radius = min(w, h) / 2
71
73
  self._create_arcs()
72
74
 
73
75
  def rect(self):
@@ -96,6 +98,8 @@ class ImageGraphicsViewBase(QGraphicsView):
96
98
  self.setRenderHint(QPainter.Antialiasing)
97
99
  self.setRenderHint(QPainter.SmoothPixmapTransform)
98
100
  self.setCursor(Qt.BlankCursor)
101
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
102
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
99
103
 
100
104
 
101
105
  class ViewStrategy(LayerCollectionHandler):
@@ -118,6 +122,7 @@ class ViewStrategy(LayerCollectionHandler):
118
122
  self.last_mouse_pos = None
119
123
  self.last_update_time = QTime.currentTime()
120
124
  self.last_color_update_time = 0
125
+ self.last_cursor_update_time = 0
121
126
 
122
127
  @abstractmethod
123
128
  def create_pixmaps(self):
@@ -187,6 +192,10 @@ class ViewStrategy(LayerCollectionHandler):
187
192
  def set_mouse_callbacks(self, callbacks):
188
193
  pass
189
194
 
195
+ @abstractmethod
196
+ def get_view_with_mouse(self, event=None):
197
+ pass
198
+
190
199
  def hide_brush_cursor(self):
191
200
  if self.brush_cursor:
192
201
  self.brush_cursor.hide()
@@ -238,6 +247,8 @@ class ViewStrategy(LayerCollectionHandler):
238
247
 
239
248
  def set_cursor_style(self, style):
240
249
  self.cursor_style = style
250
+ if style != 'simple' and self.brush_cursor:
251
+ self.brush_cursor.setBrush(Qt.NoBrush)
241
252
  if style == 'preview':
242
253
  self.show_brush_preview()
243
254
  self.update_brush_cursor()
@@ -276,7 +287,7 @@ class ViewStrategy(LayerCollectionHandler):
276
287
  self.update_view_display(
277
288
  self.current_layer(),
278
289
  self.get_current_pixmap(),
279
- self.get_current_view(),
290
+ self.get_current_scene(),
280
291
  self.get_current_view())
281
292
 
282
293
  def update_cursor_pen_width(self):
@@ -319,6 +330,17 @@ class ViewStrategy(LayerCollectionHandler):
319
330
  return QImage(memoryview(array), width, height, 3 * width, QImage.Format_RGB888)
320
331
  return QImage()
321
332
 
333
+ def setup_view_image(self, view, pixmap):
334
+ img_width, img_height = pixmap.width(), pixmap.height()
335
+ self.set_max_min_scales(img_width, img_height)
336
+ view_rect = view.viewport().rect()
337
+ scale_x = view_rect.width() / img_width
338
+ scale_y = view_rect.height() / img_height
339
+ scale_factor = min(scale_x, scale_y)
340
+ scale_factor = max(self.min_scale(), min(scale_factor, self.max_scale()))
341
+ self.set_zoom_factor(scale_factor)
342
+ return img_width, img_height, scale_factor
343
+
322
344
  def create_scene(self, view):
323
345
  scene = QGraphicsScene()
324
346
  view.setScene(scene)
@@ -340,21 +362,6 @@ class ViewStrategy(LayerCollectionHandler):
340
362
  gui_constants.MIN_ZOOMED_IMG_HEIGHT / img_height))
341
363
  self.set_max_scale(gui_constants.MAX_ZOOMED_IMG_PX_SIZE)
342
364
 
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
365
  def apply_zoom(self):
359
366
  if self.empty():
360
367
  return
@@ -363,20 +370,98 @@ class ViewStrategy(LayerCollectionHandler):
363
370
  scale_factor = self.zoom_factor() / current_scale
364
371
  view.scale(scale_factor, scale_factor)
365
372
 
366
- def zoom_out(self):
373
+ def center_image(self, view):
374
+ view.horizontalScrollBar().setValue(self.status.h_scroll)
375
+ view.verticalScrollBar().setValue(self.status.v_scroll)
376
+
377
+ def set_scroll_and_center(self, view, delta):
378
+ self.status.set_scroll(
379
+ view.horizontalScrollBar().value() + int(delta.x() * self.zoom_factor()),
380
+ view.verticalScrollBar().value() + int(delta.y() * self.zoom_factor()))
381
+ self.center_image(view)
382
+
383
+ def apply_zoom_and_center(self, view, new_scale, ref_pos, old_center):
384
+ self.set_zoom_factor(new_scale)
385
+ self.apply_zoom()
386
+ new_center = view.mapToScene(ref_pos)
387
+ delta = old_center - new_center
388
+ self.set_scroll_and_center(view, delta)
389
+
390
+ def handle_pinch_gesture(self, pinch):
391
+ master_view = self.get_master_view()
392
+ if pinch.state() == Qt.GestureStarted:
393
+ self.pinch_start_scale = self.zoom_factor()
394
+ self.pinch_center_view = pinch.centerPoint()
395
+ self.pinch_center_scene = master_view.mapToScene(self.pinch_center_view.toPoint())
396
+ self.gesture_active = True
397
+ elif pinch.state() == Qt.GestureUpdated:
398
+ new_scale = self.pinch_start_scale * pinch.totalScaleFactor()
399
+ new_scale = max(self.min_scale(), min(new_scale, self.max_scale()))
400
+ if abs(new_scale - self.zoom_factor()) > 0.01:
401
+ old_center = self.pinch_center_scene
402
+ ref_pos = self.pinch_center_view.toPoint()
403
+ self.apply_zoom_and_center(master_view, new_scale, ref_pos, old_center)
404
+ elif pinch.state() in (Qt.GestureFinished, Qt.GestureCanceled):
405
+ self.gesture_active = False
406
+ self.update_cursor_pen_width()
407
+
408
+ def do_zoom(self, new_scale, view):
367
409
  if self.empty():
368
410
  return
369
- master_view = self.get_master_view()
370
- old_center = master_view.mapToScene(master_view.viewport().rect().center())
371
- current_scale = self.get_current_scale()
372
- new_scale = current_scale * gui_constants.ZOOM_OUT_FACTOR
373
- if new_scale >= self.min_scale():
374
- for view in self.get_views():
375
- view.scale(gui_constants.ZOOM_OUT_FACTOR, gui_constants.ZOOM_OUT_FACTOR)
376
- self.set_zoom_factor(new_scale)
377
- master_view.centerOn(old_center)
411
+ if not self.min_scale() <= new_scale <= self.max_scale():
412
+ return
413
+ if view is None:
414
+ view = self.get_master_view()
415
+ global_pos = QCursor.pos()
416
+ ref_pos = view.mapFromGlobal(global_pos)
417
+ old_center = view.mapToScene(ref_pos)
418
+ self.apply_zoom_and_center(view, new_scale, ref_pos, old_center)
419
+ self.update_cursor_pen_width()
420
+
421
+ def handle_wheel_event(self, event):
422
+ if self.empty() or self.gesture_active:
423
+ return
424
+ if event.source() == Qt.MouseEventNotSynthesized: # Physical mouse
425
+ if self.control_pressed:
426
+ self.brush_size_change_requested.emit(1 if event.angleDelta().y() > 0 else -1)
427
+ else:
428
+ self.handle_zoom_wheel(self.get_view_with_mouse(event), event)
378
429
  self.update_brush_cursor()
379
- self.update_cursor_pen_width()
430
+ else:
431
+ self.handle_wheel_touchpad_event(event)
432
+
433
+ def handle_wheel_touchpad_event(self, event):
434
+ if not self.control_pressed:
435
+ delta = event.pixelDelta() or event.angleDelta() / 8
436
+ if delta:
437
+ self.scroll_view(self.get_view_with_mouse(event), delta.x(), delta.y())
438
+ else:
439
+ zoom_in = event.angleDelta().y() > 0
440
+ if zoom_in:
441
+ self.zoom_in()
442
+ else:
443
+ self.zoom_out()
444
+
445
+ def handle_zoom_wheel(self, view, event):
446
+ if view is None:
447
+ return
448
+ current_scale = self.get_current_scale()
449
+ if event.angleDelta().y() > 0:
450
+ new_scale = current_scale * gui_constants.ZOOM_IN_FACTOR
451
+ else:
452
+ new_scale = current_scale * gui_constants.ZOOM_OUT_FACTOR
453
+ new_scale = max(self.min_scale(), min(new_scale, self.max_scale()))
454
+ self.do_zoom(new_scale, view)
455
+
456
+ def zoom_in(self):
457
+ self.do_zoom(
458
+ self.get_current_scale() * gui_constants.ZOOM_IN_FACTOR,
459
+ self.get_view_with_mouse())
460
+
461
+ def zoom_out(self):
462
+ self.do_zoom(
463
+ self.get_current_scale() * gui_constants.ZOOM_OUT_FACTOR,
464
+ self.get_view_with_mouse())
380
465
 
381
466
  def reset_zoom(self):
382
467
  if self.empty():
@@ -479,7 +564,8 @@ class ViewStrategy(LayerCollectionHandler):
479
564
  self.update_master_cursor_color()
480
565
  if self.cursor_style == 'brush':
481
566
  self.setup_simple_brush_style(scene_pos.x(), scene_pos.y(), radius)
482
- self.show_brush_cursor()
567
+ if not self.scrolling:
568
+ self.show_brush_cursor()
483
569
 
484
570
  def update_color_time(self):
485
571
  current_time = time.time()
@@ -612,22 +698,24 @@ class ViewStrategy(LayerCollectionHandler):
612
698
  self.status.set_scroll(view.horizontalScrollBar().value(),
613
699
  view.verticalScrollBar().value())
614
700
 
615
- def center_image(self, view):
616
- view.horizontalScrollBar().setValue(self.status.h_scroll)
617
- view.verticalScrollBar().setValue(self.status.v_scroll)
618
-
619
701
  def mouse_move_event(self, event):
620
702
  if self.empty():
621
703
  return
704
+ current_time = time.time() * 1000 # ms
705
+ cursor_update_interval = AppConfig.get('cursor_update_time')
706
+ if current_time - self.last_cursor_update_time < cursor_update_interval:
707
+ return
708
+ self.last_cursor_update_time = current_time
622
709
  position = event.position()
623
710
  brush_size = self.brush.size
624
711
  if not self.space_pressed:
625
712
  self.update_brush_cursor()
626
713
  if self.dragging and event.buttons() & Qt.LeftButton:
627
714
  current_time = QTime.currentTime()
628
- if self.last_update_time.msecsTo(current_time) >= gui_constants.PAINT_REFRESH_TIMER:
629
- min_step = brush_size * \
630
- gui_constants.MIN_MOUSE_STEP_BRUSH_FRACTION * self.zoom_factor()
715
+ paint_refresh_time = AppConfig.get('paint_refresh_time')
716
+ if self.last_update_time.msecsTo(current_time) >= paint_refresh_time:
717
+ min_step = AppConfig.get('min_mouse_step_brush_fraction')
718
+ min_step = brush_size * min_step * self.zoom_factor()
631
719
  x, y = position.x(), position.y()
632
720
  xp, yp = self.last_brush_pos.x(), self.last_brush_pos.y()
633
721
  distance = math.sqrt((x - xp)**2 + (y - yp)**2)
@@ -662,7 +750,8 @@ class ViewStrategy(LayerCollectionHandler):
662
750
  self.last_brush_pos = event.position()
663
751
  self.brush_operation_started.emit(event.position().toPoint())
664
752
  self.dragging = True
665
- self.show_brush_cursor()
753
+ if not self.scrolling:
754
+ self.show_brush_cursor()
666
755
 
667
756
  def mouse_release_event(self, event):
668
757
  if self.empty():
@@ -681,28 +770,3 @@ class ViewStrategy(LayerCollectionHandler):
681
770
  elif self.dragging:
682
771
  self.dragging = False
683
772
  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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shinestacker
3
- Version: 1.5.3
3
+ Version: 1.6.0
4
4
  Summary: ShineStacker
5
5
  Author-email: Luca Lista <luka.lista@gmail.com>
6
6
  License-Expression: LGPL-3.0
@@ -1,5 +1,5 @@
1
1
  shinestacker/__init__.py,sha256=uq2fjAw2z_6TpH3mOcWFZ98GoEPRsNhTAK8N0MMm_e8,448
2
- shinestacker/_version.py,sha256=zG2cd7WLo5fIizFwE9xNzjpfZPff6uzTZIgsxS6ri_g,21
2
+ shinestacker/_version.py,sha256=aWnRnF5TUBHC_2RdGczq36VyxBiPAviva2RjtMVjCFg,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
@@ -9,30 +9,33 @@ shinestacker/algorithms/base_stack_algo.py,sha256=RzxvLDHqxqhnAl83u2onjvfsRea1qG
9
9
  shinestacker/algorithms/denoise.py,sha256=GL3Z4_6MHxSa7Wo4ZzQECZS87tHBFqO0sIVF_jPuYQU,426
10
10
  shinestacker/algorithms/depth_map.py,sha256=nRBrZQWbdUqFOtYMEQx9UNdnybrBTeAOr1eV91FlN8U,5611
11
11
  shinestacker/algorithms/exif.py,sha256=SM4ZDDe8hCJ3xY6053FNndOiwzEStzdp0WrXurlcHVc,9429
12
- shinestacker/algorithms/multilayer.py,sha256=WlB4L5oY9qra3w7Qahg-tqO6S_s3pMB_LmGR8PPR_7w,9904
12
+ shinestacker/algorithms/multilayer.py,sha256=EEMDr2NlCU9DCFO5ykbBrY-2q9oBUD0-ctm7x0IXU5U,9911
13
13
  shinestacker/algorithms/noise_detection.py,sha256=myUiLKYC3Ph62j28upUd_7rZum_JpqyxiN33nZN35zE,9346
14
14
  shinestacker/algorithms/pyramid.py,sha256=Z7tlp8Hh3ploAXJCr0VNe33d8H9GNrlqHXq_LapgRwo,8205
15
15
  shinestacker/algorithms/pyramid_auto.py,sha256=fl_jXNYLWsBiX0M0UghzCLqai0SGXlmKYHU7Z9SUYSo,6173
16
16
  shinestacker/algorithms/pyramid_tiles.py,sha256=ZBWIeifkDOIVFF4SCyspRZHSj6K_1P3dk4WLmuo53RU,12213
17
17
  shinestacker/algorithms/sharpen.py,sha256=h7PMJBYxucg194Usp_6pvItPUMFYbT-ebAc_-7XBFUw,949
18
- shinestacker/algorithms/stack.py,sha256=V9YX0CbNWrgAo7_uti64rmmuwU6RsRcjDoBpsES4aSE,5137
18
+ shinestacker/algorithms/stack.py,sha256=p9bLCbMjDMm7rX_FRfgXRTEJAj3GhNPOCvwePE9hVmc,5549
19
19
  shinestacker/algorithms/stack_framework.py,sha256=OMrjD5dKquHQXhM7TfLRExDsqN1n938WWhGAfkPYLZM,13883
20
20
  shinestacker/algorithms/utils.py,sha256=l6GJpEXpzDr_ml9Not03a1_F7wYvPwn8JkEWDuNwL9o,12116
21
21
  shinestacker/algorithms/vignetting.py,sha256=gJOv-FN3GnTgaVn70W_6d-qbw3WmqinDiO9oL053cus,10351
22
22
  shinestacker/algorithms/white_balance.py,sha256=PMKsBtxOSn5aRr_Gkx1StHS4eN6kBN2EhNnhg4UG24g,501
23
23
  shinestacker/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  shinestacker/app/about_dialog.py,sha256=pkH7nnxUP8yc0D3vRGd1jRb5cwi1nDVbQRk_OC9yLk8,4144
25
- shinestacker/app/args_parser_opts.py,sha256=TlfMR5GBd6Zz9wZNrN7CGJ1_hm1FnLZn5EoP5mkRHrk,776
26
- shinestacker/app/gui_utils.py,sha256=fSpkwPXTON_l676UHdAnJNrGq7BPbSlPOiHpOF_LZaI,2519
25
+ shinestacker/app/args_parser_opts.py,sha256=c6IUXOI0SJIFckPWPXYnwmBmdNnOcrtvU5S8hUDU_AQ,979
26
+ shinestacker/app/gui_utils.py,sha256=EGZejp0XZXRLVa_Wd_2VYAwK3oe9hMSoZzNgT7NUNRw,2986
27
27
  shinestacker/app/help_menu.py,sha256=g8lKG_xZmXtNQaC3SIRzyROKVWva_PLEgZsQWh6zUcQ,499
28
- shinestacker/app/main.py,sha256=UkWz4jvaBPH4Fs-arHe8H0NqKVTA4B_1e9BRn9S5oFo,10963
28
+ shinestacker/app/main.py,sha256=l9O9J7nICTi3wnW2uJpKfLV7HWDEi-r_xoOrbywJv_s,11129
29
29
  shinestacker/app/open_frames.py,sha256=bsu32iJSYJQLe_tQQbvAU5DuMDVX6MRuNdE7B5lojZc,1488
30
- shinestacker/app/project.py,sha256=_kopeyb8e5JAA3XjNXoCshlYBfT5Avw-kTqiJN4GVlo,2805
31
- shinestacker/app/retouch.py,sha256=On2oV2QonfMziQAvRkO6qw-h6E6wWQE0svKzZQKHeyg,2687
30
+ shinestacker/app/project.py,sha256=8hjKkZqBsumS7McHXRZdGvyHgopPHeHznrnIdXajp_w,2916
31
+ shinestacker/app/retouch.py,sha256=pks7aoXmYyRoeTzOA-D2Uy5f4RKoEDh25OQtkcOE_9c,2778
32
+ shinestacker/app/settings_dialog.py,sha256=0P3nqqZEiTIFgidW1_e3Q_zE7NbAouNsuj-yNsU41vk,8192
32
33
  shinestacker/config/__init__.py,sha256=aXxi-LmAvXd0daIFrVnTHE5OCaYeK1uf1BKMr7oaXQs,197
34
+ shinestacker/config/app_config.py,sha256=rM1Rndk1GDa5c0AhcVNEN9zSAzxPZixzQYfjODbJUwE,771
33
35
  shinestacker/config/config.py,sha256=eBko2D3ADhLTIm9X6hB_a_WsIjwgfE-qmBVkhP1XSvc,1636
34
- shinestacker/config/constants.py,sha256=EEdr7pZg4JpbIjUWaP7kJQfTuBB85FN739myDNAfn8A,8301
35
- shinestacker/config/gui_constants.py,sha256=55Qr0KzrTx8eQHCkT-EVabSiD59VvLZIh5o2cA9028s,2791
36
+ shinestacker/config/constants.py,sha256=Z7QjaklrYYsPjTX68Tjyh_wCOuYyQPBR8dnYrZfNwA8,8376
37
+ shinestacker/config/gui_constants.py,sha256=PNxzwmVEppJ2mV_vwp68NhWzJOEitVy1Pk9SwSmRsho,2882
38
+ shinestacker/config/settings.py,sha256=4p4r6wKOCbttzfH9tyHQSTd-iv-GfgCd1LxI3C7WIjU,3861
36
39
  shinestacker/core/__init__.py,sha256=IUEIx6SQ3DygDEHN3_E6uKpHjHtUa4a_U_1dLd_8yEU,484
37
40
  shinestacker/core/colors.py,sha256=kr_tJA1iRsdck2JaYDb2lS-codZ4Ty9gdu3kHfiWvuM,1340
38
41
  shinestacker/core/core_utils.py,sha256=1LYj19Dfc9jZN9-4dlf1paximDH5WZYa7DXvKr7R7QY,1719
@@ -40,23 +43,24 @@ shinestacker/core/exceptions.py,sha256=2-noG-ORAGdvDhL8jBQFs0xxZS4fI6UIkMqrWekgk
40
43
  shinestacker/core/framework.py,sha256=QaTfnzEUHwzlbyFG7KzeyteckTSWHWEEJE4d5Tc8H18,11015
41
44
  shinestacker/core/logging.py,sha256=9SuSSy9Usbh7zqmLYMqkmy-VBkOJW000lwqAR0XQs30,3067
42
45
  shinestacker/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- shinestacker/gui/action_config.py,sha256=HeDbRy3YSl9IldLZBCdXj7eWIfTTHmUqC_AW9LJU2Pk,25859
44
- shinestacker/gui/action_config_dialog.py,sha256=Jp0LVhE0gdz70ve47LCL5N2sSLuj8_arZb4xL50_pkk,41101
46
+ shinestacker/gui/action_config.py,sha256=Xv7SGbhPl1F_dUnU04VBt_E-wIItnN_q6QuhU_d9GfI,25929
47
+ shinestacker/gui/action_config_dialog.py,sha256=QN95FiVPYL6uin2sYO5F7tq6G5rBWh9yRkeTVvwKrwU,38341
45
48
  shinestacker/gui/base_form_dialog.py,sha256=KAUQNtmJazttmOIe4E4pFifbtvcByTAhtCmcIYeA4UE,766
46
49
  shinestacker/gui/colors.py,sha256=-HaFprDuzRSKjXoZfX1rdOuvawQAkazqdgLBEiZcFII,1476
50
+ shinestacker/gui/config_dialog.py,sha256=yt3nvh0HPHQuCn3AFlzlIHUJnnxcz-Rrw3W3jS9ZYiE,3447
47
51
  shinestacker/gui/flow_layout.py,sha256=3yBU_z7VtvHKpx1H97CHVd81eq9pe1Dcja2EZBGGKcI,3791
48
52
  shinestacker/gui/folder_file_selection.py,sha256=IYWfZQFkoD5iO7zJ7BxVVDP9F3Dc0EXLILAhL4q-Cb8,4117
49
53
  shinestacker/gui/gui_images.py,sha256=k39DpdsxcmYoRdHNNZj6OpFAas0GOHS4JSG542wfheg,5728
50
54
  shinestacker/gui/gui_logging.py,sha256=kiZcrC2AFYCWgPZo0O5SKw-E5cFrezwf4anS3HjPuNw,8168
51
55
  shinestacker/gui/gui_run.py,sha256=zr7x4BVmM0n_ZRsSEaJVVKvHSWHuwhftgkUvgeg90gU,15767
52
- shinestacker/gui/main_window.py,sha256=5k_9TiZT9idKCmovUFYpUTSEQQj-DMQrlyq9dAgY1MU,24800
53
- shinestacker/gui/menu_manager.py,sha256=b5Cxh6uddOlio8i7fRISbGDJI-oe0ds6LIF5dWM7leI,11263
54
- shinestacker/gui/new_project.py,sha256=z8e3EhRMB-KtoPwYQSiKLSOQ2dS0-Okm7zVw21B7zy8,16391
55
- shinestacker/gui/project_controller.py,sha256=W4sbBGEPVtfF9F1rC-6Y0oKLq_y94HuFBvZRj87xNKQ,16272
56
+ shinestacker/gui/main_window.py,sha256=0G-ZjSVKY_rCK_DmstRn3wxOdvS5i3Ba3FBR2ijxpe0,25220
57
+ shinestacker/gui/menu_manager.py,sha256=q4m3cBSxUR68gexpwfIROVRKJ86zp-XPZVrohh1PfQU,11786
58
+ shinestacker/gui/new_project.py,sha256=XMv1ttYrkuqaN9629anXtVSn1bxosgyJpxSFPjlVryU,16437
59
+ shinestacker/gui/project_controller.py,sha256=MYv8QJNXUdc7r1K5D6LnBbds9YalCKSAo_CaO6b0TO8,16636
56
60
  shinestacker/gui/project_converter.py,sha256=Gmna0HwbvACcXiX74TaQYumif8ZV8sZ2APLTMM-L1mU,7436
57
61
  shinestacker/gui/project_editor.py,sha256=lSgQ42IoaobHs-NQQWT88Qhg5l7nu5ejxAO5VgIupr8,25498
58
- shinestacker/gui/project_model.py,sha256=eRUmH3QmRzDtPtZoxgT6amKzN8_5XzwjHgEJeL-_JOE,4263
59
- shinestacker/gui/recent_file_manager.py,sha256=FtatDGUqwmXXchepZdA0YRNzqCRS9Qp4EL9R9Wsg5qE,3731
62
+ shinestacker/gui/project_model.py,sha256=9dId8N-np4YHDpz_wO20Mvd06np3YKlej-0TMWaA_WE,4833
63
+ shinestacker/gui/recent_file_manager.py,sha256=010bciuirKLiVCfOAKs0uFlB3iUjHNBlPX_9K2vH5j0,2916
60
64
  shinestacker/gui/select_path_widget.py,sha256=HSwgSr702w5Et4c-6nkRXnIpm1KFqKJetAF5xQNa5zI,1017
61
65
  shinestacker/gui/sys_mon.py,sha256=zU41YYVeqQ1-v6oGIh2_BFzQWq87keN-398Wdm59-Nk,3526
62
66
  shinestacker/gui/tab_widget.py,sha256=VgRmuktWXCgbXbV7c1Tho0--W5_EmmzXPfzRZgwhGfg,2965
@@ -77,29 +81,29 @@ shinestacker/retouch/brush_gradient.py,sha256=F5SFhyzl8YTMqjJU3jK8BrIlLCYLUvITd5
77
81
  shinestacker/retouch/brush_preview.py,sha256=cOFVMCbEsgR_alzmr_-LLghtGU_unrE-hAjLHcvrZAY,5484
78
82
  shinestacker/retouch/brush_tool.py,sha256=8uVncTA375uC3Nhp2YM0eZjpOR-nN47i2eGjN8tJzOU,8714
79
83
  shinestacker/retouch/denoise_filter.py,sha256=UpNKbFs7uArdglEej8AUHan7oCVYV5E7HNzkovj7XMQ,571
80
- shinestacker/retouch/display_manager.py,sha256=vRmaSfHP47rYQrqvJ3flx_GgMJnMZDfQO4PXTfKcpqE,8505
84
+ shinestacker/retouch/display_manager.py,sha256=iRPcXWb3h3OVJy-S4xny--SB-rUfU4Qc4YSVu3XstWE,10236
81
85
  shinestacker/retouch/exif_data.py,sha256=LF-fRXW-reMq-xJ_QRE5j8DC2LVGKIlC6MR3QbC1cdg,1896
82
86
  shinestacker/retouch/file_loader.py,sha256=z02-A8_uDZxayI1NFTxT2GVUvEBWStchX9hlN1o5-0U,4784
83
87
  shinestacker/retouch/filter_manager.py,sha256=tOGIWj5HjViL1-iXHkd91X-sZ1c1G531pDmLO0x6zx0,866
84
88
  shinestacker/retouch/icon_container.py,sha256=6gw1HO1bC2FrdB4dc_iH81DQuLjzuvRGksZ2hKLT9yA,585
85
- shinestacker/retouch/image_editor_ui.py,sha256=wvsYmS7cXt61KJlv7b3X9EbymMLgdUfeEOzi8jEuR3g,31662
86
- shinestacker/retouch/image_view_status.py,sha256=bdIhsXiYXm7eyjkTGWkw5PRShzaF_by-g7daqgmhwjM,1858
89
+ shinestacker/retouch/image_editor_ui.py,sha256=vPfLuHdRZTGNbmX3ZXYoJ9Q2_dCDbFJHUxB41hrOD6k,34117
90
+ shinestacker/retouch/image_view_status.py,sha256=2rWi2ugdyjMhWCtRJkwOnb7-tCtVfnGfCY_54qpZhwM,1970
87
91
  shinestacker/retouch/image_viewer.py,sha256=H8w-ORug1aKf7X3FeSX4lQV-a0IewZ9OVG1-50BK4cE,4452
88
- shinestacker/retouch/io_gui_handler.py,sha256=BRQ5eSt1tCMDYtOqxfdYGhx2BLCrncfNrNLGuWIy5Rk,11873
92
+ shinestacker/retouch/io_gui_handler.py,sha256=UOnrFT00s0075Ng_yJACJX9TP8UT9mQOWXwQwNAfpMw,12079
89
93
  shinestacker/retouch/io_manager.py,sha256=JUAA--AK0mVa1PTErJTnBFjaXIle5Qs7Ow0Wkd8at0o,2437
90
94
  shinestacker/retouch/layer_collection.py,sha256=fZlGrkm9-Ycc7AOzFSpImhafiTieBeCZRk-UlvlFHbo,5819
91
- shinestacker/retouch/overlaid_view.py,sha256=uIMolD1984uQPWXpd27tMvGBTcSrYT-4vxO0pWVlEO4,8686
95
+ shinestacker/retouch/overlaid_view.py,sha256=KBwuzC2OQsK7rdtFAKrSvXrHrEV1SiOoZhxPCQLGkvg,6734
92
96
  shinestacker/retouch/shortcuts_help.py,sha256=BFWTT5QvodqMhqa_9LI25hZqjICfckgyWG4fGrGzvnM,4283
93
- shinestacker/retouch/sidebyside_view.py,sha256=2BrIrr38FxYJ522GLpHomScwbJgAczO9LiPwTAIlPUE,18647
94
- shinestacker/retouch/transformation_manager.py,sha256=NSHGUF-JFv4Y81gSvizjQCTp49TLo1so7c0WoUElO08,1812
95
- shinestacker/retouch/undo_manager.py,sha256=cKUkqnJtnJ-Hq-LQs5Bv49FC6qkG6XSw9oCVySJ8jS0,4312
97
+ shinestacker/retouch/sidebyside_view.py,sha256=iwnIENV_YrR2fogXqKNdCcAQBROWkQxOnh8G4tU5bqA,18829
98
+ shinestacker/retouch/transformation_manager.py,sha256=T2ewDsEKn1FBxapQ1kR7KqFwrF7spUu-KZ43bKpfBo8,1761
99
+ shinestacker/retouch/undo_manager.py,sha256=_qTpwjGsznc-Sz-sfWEDv3IxJNmrYU0qi7yJelg58DU,4319
96
100
  shinestacker/retouch/unsharp_mask_filter.py,sha256=Iapc8UmSVpj3V0LcJq_38P5qerRqTevMynbbk5Rk6iE,3634
97
- shinestacker/retouch/view_strategy.py,sha256=Di0iaYwTMI58pheF51d9MBJ0eLDvJog1DnmBLNMMMRs,26100
101
+ shinestacker/retouch/view_strategy.py,sha256=l_Fuh6vmTLv7S400XAP1fDO61Dv7U8GaOrNTvjKKjvc,28521
98
102
  shinestacker/retouch/vignetting_filter.py,sha256=JhFr6OVIripQzSJrZEG4lxq7wBsmpofLqJQ-aP2bKw8,3789
99
- shinestacker/retouch/white_balance_filter.py,sha256=QlMnzWmBYqUQqckY8XTH3dWPdqo7mz4gTwTZafxldPw,8237
100
- shinestacker-1.5.3.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
101
- shinestacker-1.5.3.dist-info/METADATA,sha256=8-9HAKfGrk6TEYj1rr_O6habe-0YlUGpHrrlhmQvRwY,6978
102
- shinestacker-1.5.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
103
- shinestacker-1.5.3.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
104
- shinestacker-1.5.3.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
105
- shinestacker-1.5.3.dist-info/RECORD,,
103
+ shinestacker/retouch/white_balance_filter.py,sha256=UaH4yxG3fU4vPutBAkV5oTXIQyUTN09x0uTywAzv3sY,8286
104
+ shinestacker-1.6.0.dist-info/licenses/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
105
+ shinestacker-1.6.0.dist-info/METADATA,sha256=0sCC4ubrLH2wabRFJaCx9_Kaj3K4HDIdM6vULEj2iJA,6978
106
+ shinestacker-1.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
107
+ shinestacker-1.6.0.dist-info/entry_points.txt,sha256=SY6g1LqtMmp23q1DGwLUDT_dhLX9iss8DvWkiWLyo_4,166
108
+ shinestacker-1.6.0.dist-info/top_level.txt,sha256=MhijwnBVX5psfsyX8JZjqp3SYiWPsKe69f3Gnyze4Fw,13
109
+ shinestacker-1.6.0.dist-info/RECORD,,