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.

Files changed (59) hide show
  1. shinestacker/_version.py +1 -1
  2. shinestacker/algorithms/align.py +4 -12
  3. shinestacker/algorithms/balance.py +11 -9
  4. shinestacker/algorithms/depth_map.py +0 -30
  5. shinestacker/algorithms/utils.py +10 -0
  6. shinestacker/algorithms/vignetting.py +116 -70
  7. shinestacker/app/about_dialog.py +101 -12
  8. shinestacker/app/gui_utils.py +1 -1
  9. shinestacker/app/help_menu.py +1 -1
  10. shinestacker/app/main.py +2 -2
  11. shinestacker/app/project.py +2 -2
  12. shinestacker/config/constants.py +4 -1
  13. shinestacker/config/gui_constants.py +10 -9
  14. shinestacker/gui/action_config.py +5 -561
  15. shinestacker/gui/action_config_dialog.py +567 -0
  16. shinestacker/gui/base_form_dialog.py +18 -0
  17. shinestacker/gui/colors.py +5 -6
  18. shinestacker/gui/gui_logging.py +0 -1
  19. shinestacker/gui/gui_run.py +54 -106
  20. shinestacker/gui/ico/shinestacker.icns +0 -0
  21. shinestacker/gui/ico/shinestacker.ico +0 -0
  22. shinestacker/gui/ico/shinestacker.png +0 -0
  23. shinestacker/gui/ico/shinestacker.svg +60 -0
  24. shinestacker/gui/main_window.py +276 -367
  25. shinestacker/gui/menu_manager.py +236 -0
  26. shinestacker/gui/new_project.py +75 -20
  27. shinestacker/gui/project_converter.py +6 -6
  28. shinestacker/gui/project_editor.py +248 -165
  29. shinestacker/gui/project_model.py +2 -7
  30. shinestacker/gui/tab_widget.py +81 -0
  31. shinestacker/gui/time_progress_bar.py +95 -0
  32. shinestacker/retouch/base_filter.py +173 -40
  33. shinestacker/retouch/brush_preview.py +0 -10
  34. shinestacker/retouch/brush_tool.py +25 -11
  35. shinestacker/retouch/denoise_filter.py +5 -44
  36. shinestacker/retouch/display_manager.py +57 -20
  37. shinestacker/retouch/exif_data.py +10 -13
  38. shinestacker/retouch/file_loader.py +1 -1
  39. shinestacker/retouch/filter_manager.py +1 -4
  40. shinestacker/retouch/image_editor_ui.py +365 -49
  41. shinestacker/retouch/image_viewer.py +34 -11
  42. shinestacker/retouch/io_gui_handler.py +96 -43
  43. shinestacker/retouch/io_manager.py +23 -7
  44. shinestacker/retouch/layer_collection.py +2 -0
  45. shinestacker/retouch/shortcuts_help.py +12 -0
  46. shinestacker/retouch/unsharp_mask_filter.py +10 -10
  47. shinestacker/retouch/vignetting_filter.py +69 -0
  48. shinestacker/retouch/white_balance_filter.py +46 -14
  49. {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/METADATA +14 -2
  50. shinestacker-1.0.0.dist-info/RECORD +90 -0
  51. shinestacker/app/app_config.py +0 -22
  52. shinestacker/gui/actions_window.py +0 -258
  53. shinestacker/retouch/image_editor.py +0 -201
  54. shinestacker/retouch/image_filters.py +0 -69
  55. shinestacker-0.4.0.dist-info/RECORD +0 -87
  56. {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/WHEEL +0 -0
  57. {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/entry_points.txt +0 -0
  58. {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/licenses/LICENSE +0 -0
  59. {shinestacker-0.4.0.dist-info → shinestacker-1.0.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,5 @@
1
1
  # pylint: disable=C0114, C0115, C0116, E0611, R0903, R0915, R0914, R0917, R0913, R0902
2
- import time
3
- from PySide6.QtWidgets import (QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QProgressBar,
2
+ from PySide6.QtWidgets import (QWidget, QPushButton, QVBoxLayout, QHBoxLayout,
4
3
  QMessageBox, QScrollArea, QSizePolicy, QFrame, QLabel, QComboBox)
5
4
  from PySide6.QtGui import QColor
6
5
  from PySide6.QtCore import Qt, QTimer
@@ -10,11 +9,11 @@ from .. config.gui_constants import gui_constants
10
9
  from .colors import RED_BUTTON_STYLE, BLUE_BUTTON_STYLE, BLUE_COMBO_STYLE
11
10
  from .gui_logging import LogWorker, QTextEditLogger
12
11
  from .gui_images import GuiPdfView, GuiImageView, GuiOpenApp
13
- from .colors import ColorPalette
14
-
15
-
16
- ACTION_RUNNING_COLOR = ColorPalette.MEDIUM_BLUE
17
- ACTION_DONE_COLOR = ColorPalette.MEDIUM_GREEN
12
+ from .colors import (
13
+ ColorPalette,
14
+ ACTION_RUNNING_COLOR, ACTION_COMPLETED_COLOR,
15
+ ACTION_STOPPED_COLOR, ACTION_FAILED_COLOR)
16
+ from .time_progress_bar import TimerProgressBar
18
17
 
19
18
 
20
19
  class ColorButton(QPushButton):
@@ -40,95 +39,6 @@ class ColorButton(QPushButton):
40
39
  """)
41
40
 
42
41
 
43
- class TimerProgressBar(QProgressBar):
44
- light_background_color = ColorPalette.LIGHT_BLUE
45
- border_color = ColorPalette.DARK_BLUE
46
- text_color = ColorPalette.DARK_BLUE
47
-
48
- def __init__(self):
49
- super().__init__()
50
- super().setRange(0, 10)
51
- super().setValue(0)
52
- self.set_running_style()
53
- self._start_time = -1
54
- self._current_time = -1
55
-
56
- def set_style(self, bar_color=None):
57
- if bar_color is None:
58
- bar_color = ColorPalette.MEDIUM_BLUE
59
- self.setStyleSheet(f"""
60
- QProgressBar {{
61
- border: 2px solid #{self.border_color.hex()};
62
- border-radius: 8px;
63
- text-align: center;
64
- font-weight: bold;
65
- font-size: 12px;
66
- background-color: #{self.light_background_color.hex()};
67
- color: #{self.text_color.hex()};
68
- min-height: 1px;
69
- }}
70
- QProgressBar::chunk {{
71
- border-radius: 6px;
72
- background-color: #{bar_color.hex()};
73
- }}
74
- """)
75
-
76
- def time_str(self, secs):
77
- ss = int(secs)
78
- h = ss // 3600
79
- m = (ss % 3600) // 60
80
- s = (ss % 3600) % 60
81
- x = secs - ss
82
- t_str = f"{s:02d}" + f"{x:.1f}s".lstrip('0')
83
- if m > 0:
84
- t_str = f"{m:02d}:{t_str}"
85
- if h > 0:
86
- t_str = f"{h:02d}:{t_str}"
87
- if m > 0 or h > 0:
88
- t_str = t_str.lstrip('0')
89
- elif 0 < s < 10:
90
- t_str = t_str.lstrip('0')
91
- elif s == 0:
92
- t_str = t_str[1:]
93
- return t_str
94
-
95
- def check_time(self, val):
96
- if self._start_time < 0:
97
- raise RuntimeError("TimeProgressbar: start and must be called before setValue and stop")
98
- self._current_time = time.time()
99
- elapsed_time = self._current_time - self._start_time
100
- elapsed_str = self.time_str(elapsed_time)
101
- fmt = f"Progress: %p% - %v of %m - elapsed: {elapsed_str}"
102
- if 0 < val < self.maximum():
103
- time_per_iter = elapsed_time / val
104
- estimated_time = time_per_iter * self.maximum()
105
- remaining_time = max(0, estimated_time - elapsed_time)
106
- remaining_str = self.time_str(remaining_time)
107
- fmt += f", {remaining_str} remaining"
108
- self.setFormat(fmt)
109
-
110
- def start(self, steps):
111
- super().setMaximum(steps)
112
- self._start_time = time.time()
113
- self.setValue(0)
114
-
115
- def stop(self):
116
- self.check_time(self.maximum())
117
- self.setValue(self.maximum())
118
-
119
- # pylint: disable=C0103
120
- def setValue(self, val):
121
- self.check_time(val)
122
- super().setValue(val)
123
- # pylint: enable=C0103
124
-
125
- def set_running_style(self):
126
- self.set_style(ACTION_RUNNING_COLOR)
127
-
128
- def set_done_style(self):
129
- self.set_style(ACTION_DONE_COLOR)
130
-
131
-
132
42
  class RunWindow(QTextEditLogger):
133
43
  def __init__(self, labels, stop_worker_callback, close_window_callback, retouch_paths, parent):
134
44
  QTextEditLogger.__init__(self, parent)
@@ -245,17 +155,26 @@ class RunWindow(QTextEditLogger):
245
155
 
246
156
  @Slot(int, str)
247
157
  def handle_before_action(self, run_id, _name):
248
- if 0 <= run_id < len(self.color_widgets[self.row_widget_id]):
249
- self.color_widgets[self.row_widget_id][run_id].set_color(*ACTION_RUNNING_COLOR.tuple())
250
- self.progress_bar.start(1)
158
+ if self.row_widget_id < len(self.color_widgets):
159
+ widgets = self.color_widgets[self.row_widget_id]
160
+ if 0 <= run_id < len(widgets):
161
+ widget = widgets[run_id]
162
+ widget.set_color(*ACTION_RUNNING_COLOR.tuple())
163
+ widget.setText(widget.text() + " - running")
164
+ self.progress_bar.start(1)
251
165
  if run_id == -1:
252
166
  self.progress_bar.set_running_style()
253
167
 
254
168
  @Slot(int, str)
255
169
  def handle_after_action(self, run_id, _name):
256
- if 0 <= run_id < len(self.color_widgets[self.row_widget_id]):
257
- self.color_widgets[self.row_widget_id][run_id].set_color(*ACTION_DONE_COLOR.tuple())
258
- self.progress_bar.stop()
170
+ if self.row_widget_id < len(self.color_widgets):
171
+ widgets = self.color_widgets[self.row_widget_id]
172
+ if 0 <= run_id < len(widgets):
173
+ widget = widgets[run_id]
174
+ widget.set_color(*ACTION_COMPLETED_COLOR.tuple())
175
+ postfix = f" - completed in {self.progress_bar.elapsed_str}"
176
+ widget.setText(widget.text().replace(" - running", "") + postfix)
177
+ self.progress_bar.stop()
259
178
  if run_id == -1:
260
179
  self.row_widget_id += 1
261
180
  self.progress_bar.set_done_style()
@@ -318,6 +237,28 @@ class RunWindow(QTextEditLogger):
318
237
  0, lambda: self.right_area.verticalScrollBar().setValue(
319
238
  self.right_area.verticalScrollBar().maximum()))
320
239
 
240
+ @Slot(int)
241
+ def handle_run_completed(self, _run_id):
242
+ self.progress_bar.setFormat(self.progress_bar.format() + " - completed")
243
+
244
+ def handle_run_interrupt(self, run_id, color, postfix):
245
+ if self.row_widget_id < len(self.color_widgets):
246
+ widgets = self.color_widgets[self.row_widget_id]
247
+ if 0 <= run_id < len(widgets):
248
+ widget = widgets[run_id]
249
+ widget.set_color(*color)
250
+ widget.setText(widget.text().replace(" - running", "") + postfix)
251
+
252
+ @Slot(int)
253
+ def handle_run_stopped(self, run_id):
254
+ postfix = f" - stopped after {self.progress_bar.elapsed_str}"
255
+ self.handle_run_interrupt(run_id, ACTION_STOPPED_COLOR.tuple(), postfix)
256
+
257
+ @Slot(int)
258
+ def handle_run_failed(self, run_id):
259
+ postfix = f" - failed after {self.progress_bar.elapsed_str}"
260
+ self.handle_run_interrupt(run_id, ACTION_FAILED_COLOR.tuple(), postfix)
261
+
321
262
 
322
263
  class RunWorker(LogWorker):
323
264
  before_action_signal = Signal(int, str)
@@ -328,6 +269,9 @@ class RunWorker(LogWorker):
328
269
  after_step_signal = Signal(int, str, int)
329
270
  save_plot_signal = Signal(int, str, str)
330
271
  open_app_signal = Signal(int, str, str, str)
272
+ run_completed_signal = Signal(int)
273
+ run_stopped_signal = Signal(int)
274
+ run_failed_signal = Signal(int)
331
275
 
332
276
  def __init__(self, id_str):
333
277
  LogWorker.__init__(self)
@@ -382,15 +326,19 @@ class RunWorker(LogWorker):
382
326
  </div>
383
327
  ''') # noqa
384
328
  status, error_message = self.do_run()
385
- if status == constants.RUN_FAILED:
386
- message = f"{self.tag} failed"
387
- color = "#" + ColorPalette.DARK_RED.hex()
388
- elif status == constants.RUN_COMPLETED:
329
+ run_id = int(self.id_str.split('_')[-1])
330
+ if status == constants.RUN_COMPLETED:
389
331
  message = f"{self.tag} ended successfully"
332
+ self.run_completed_signal.emit(run_id)
390
333
  color = "#" + ColorPalette.DARK_BLUE.hex()
391
334
  elif status == constants.RUN_STOPPED:
392
335
  message = f"{self.tag} stopped"
393
336
  color = "#" + ColorPalette.DARK_RED.hex()
337
+ self.run_stopped_signal.emit(run_id)
338
+ elif status == constants.RUN_FAILED:
339
+ message = f"{self.tag} failed"
340
+ color = "#" + ColorPalette.DARK_RED.hex()
341
+ self.run_failed_signal.emit(run_id)
394
342
  else:
395
343
  message = ''
396
344
  color = "#000000"
Binary file
Binary file
Binary file
@@ -0,0 +1,60 @@
1
+ <svg id="Livello_1" data-name="Livello 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
2
+ <defs>
3
+ <style>
4
+ .cls-1 {
5
+ fill: #fff;
6
+ }
7
+
8
+ .cls-2 {
9
+ fill: #216ea1;
10
+ }
11
+
12
+ .cls-3 {
13
+ opacity: 0.8;
14
+ }
15
+
16
+ .cls-4 {
17
+ opacity: 0.6;
18
+ }
19
+
20
+ .cls-5 {
21
+ opacity: 0.4;
22
+ }
23
+ </style>
24
+ </defs>
25
+ <title>shinestacker_1</title>
26
+ <rect class="cls-1" x="238.36" y="238.36" width="523.29" height="523.29" rx="100" transform="translate(1000 1000) rotate(-180)"/>
27
+ <rect class="cls-2" x="312.66" y="487.43" width="311.99" height="35.36" rx="7.87"/>
28
+ <g class="cls-3">
29
+ <rect class="cls-2" x="374.9" y="535.13" width="311.99" height="35.36" rx="7.87"/>
30
+ </g>
31
+ <g class="cls-4">
32
+ <rect class="cls-2" x="312.66" y="582.82" width="311.99" height="35.36" rx="7.87"/>
33
+ </g>
34
+ <g class="cls-5">
35
+ <rect class="cls-2" x="268.51" y="630.51" width="311.99" height="35.36" rx="7.87"/>
36
+ </g>
37
+ <g>
38
+ <g>
39
+ <g>
40
+ <g>
41
+ <path class="cls-2" d="M493.18,405.7c13.36,10,26.59,18.35,39.15,10.5,10.79-6.75,16.24-40.11,23.51-50.42,7.95-11.29,47.4-9.52,62.4-5,13.25,4,21.24,9.35,29.9,20.64,7.63,9.94,5.49,19.28,11.61,24.94,7.36,6.79,13.12,1.52,13.4-4,.19-3.83-1.25-9.55-4.08-14.29-9.43-15.79-30.85-29.24-48.48-35.39-20.12-7-59.42-4.39-71-1.18-9,2.51-33.85-3.58-58.11,9.29C461.05,376.94,475.15,392.16,493.18,405.7Zm27.87-39.55a12.47,12.47,0,0,1,3.9-5.76c3.34-2.9,8-4.45,12.27-3.3a10.12,10.12,0,0,1,5.3,3.41c4.08,5,3.31,13.64-2.15,17.95-5,4-12.21,2.42-16.42-1.89A11,11,0,0,1,521.05,366.15Z"/>
42
+ <path class="cls-2" d="M493,405.94c-10.09-7.58-20.3-16.62-19.55-26.19.53-6.83,6.4-13.12,17.94-19.24,16.86-8.95,33.66-8.78,45.92-8.65,5.32.05,9.52.1,12.25-.66,11.17-3.12,50.63-6,71.13,1.18,17.24,6,39,19.33,48.64,35.52,2.67,4.47,4.32,10.28,4.11,14.45a8,8,0,0,1-4.57,7.07c-2.8,1.14-6.11.13-9.32-2.84s-4.09-6.51-5.27-10.78-2.53-9.18-6.37-14.19c-8.52-11.11-16.31-16.48-29.75-20.54-14.43-4.35-54.16-6.37-62.08,4.88-2.88,4.1-5.5,11.93-8.28,20.23-4.1,12.26-8.75,26.17-15.31,30.27a19.88,19.88,0,0,1-10.19,3.13C512.56,419.82,502.57,413.13,493,405.94ZM618.33,360.5c13.58,4.1,21.44,9.53,30,20.75,3.91,5.1,5.27,10,6.48,14.39,1.15,4.18,2.14,7.79,5.09,10.51s6.12,3.76,8.69,2.72a7.41,7.41,0,0,0,4.21-6.54c.2-4.07-1.42-9.75-4-14.13-9.6-16.06-31.19-29.28-48.33-35.26-20.38-7.11-59.65-4.27-70.77-1.17-2.81.78-7.05.74-12.42.68-12.2-.12-28.9-.29-45.63,8.58-11.34,6-17.11,12.16-17.63,18.77-.73,9.28,9.36,18.18,19.32,25.66,12.78,9.6,26.3,18.31,38.81,10.48,6.38-4,11-17.78,15.07-29.95,2.79-8.34,5.42-16.22,8.36-20.39,4.79-6.8,20.09-8.27,28.79-8.55l.77,0C597,356.74,610.51,358.14,618.33,360.5Zm-94.59,16.26h0a11.22,11.22,0,0,1-3-10.69,12.57,12.57,0,0,1,4-5.9c3.66-3.19,8.46-4.47,12.54-3.37a10.47,10.47,0,0,1,5.45,3.51,12.77,12.77,0,0,1,2.57,9.45,13.21,13.21,0,0,1-4.77,8.93A10.84,10.84,0,0,1,534,381,14.21,14.21,0,0,1,523.74,376.76Zm1.41-16.15a12,12,0,0,0-3.81,5.62,10.62,10.62,0,0,0,2.82,10.12h0c3.94,4,11,5.83,16,1.87a12.61,12.61,0,0,0,4.55-8.52,12.2,12.2,0,0,0-2.44-9,9.81,9.81,0,0,0-5.14-3.3A10.71,10.71,0,0,0,534,357,14.28,14.28,0,0,0,525.15,360.61Z"/>
43
+ </g>
44
+ <path class="cls-2" d="M464.67,376.8c-10-8.15-40.07-.55-51.41,4.72a101.42,101.42,0,0,0-38.2,30.84c-7.44,10-14.3,23.13-12.26,36,.84,5.33,3.55,9.79,8.48,12.22a33,33,0,0,0,9.59,2.65c21.74,3.38,43.54.18,64.87-4.24,13.95-2.88,28.27-6.23,41.11-12.57,8.38-4.14,18.66-11.43,15.55-22.2-1.85-6.38-15.55-14.82-24.76-24.91C469.06,389.9,468.22,379.69,464.67,376.8Z"/>
45
+ <path class="cls-2" d="M539.06,363.49a6.24,6.24,0,0,0-3.34-2.1,9,9,0,0,0-7.84,2.21,8.22,8.22,0,0,0-2.55,3.68,6.75,6.75,0,0,0,1.75,6.55c2.63,2.68,7.18,3.6,10.43,1C541,372.08,541.61,366.62,539.06,363.49Z"/>
46
+ </g>
47
+ <path class="cls-2" d="M688.89,361a74.58,74.58,0,0,0-14.25-3.37c-2.4-.28-4.79-.52-7.18-.58-1.2,0-2.4-.06-3.59,0s-2.39.09-3.58.19a54.34,54.34,0,0,0-26.46,9.52,60.68,60.68,0,0,0-18.49,21.15,75.05,75.05,0,0,0-8.06,27.78l7.14-.3a46.86,46.86,0,0,1,2.88-26.54,48.34,48.34,0,0,1,17.21-21.09c1-.61,1.93-1.26,2.93-1.85l3-1.62a53.91,53.91,0,0,1,6.43-2.47,44.83,44.83,0,0,1,13.49-2.11,51.67,51.67,0,0,1,13.47,1.77,53.55,53.55,0,0,1,6.4,2.18,39.53,39.53,0,0,1,5.92,3Z"/>
48
+ </g>
49
+ <path class="cls-2" d="M530,426.52h0a4.22,4.22,0,0,0,.84,6.29l20.36,13.57a4.22,4.22,0,0,0,6.36-2.22l1.73-5.39a4.23,4.23,0,0,0-2.56-5.25l-22.09-8.18A4.21,4.21,0,0,0,530,426.52Z"/>
50
+ <path class="cls-2" d="M350.43,434.83h0a5.23,5.23,0,0,0,2.43,7.49l27.91,12.07a5.25,5.25,0,0,0,7.28-4.13l.91-7a5.24,5.24,0,0,0-4.29-5.84l-28.82-5.09A5.25,5.25,0,0,0,350.43,434.83Z"/>
51
+ <path class="cls-2" d="M559.79,442.49h0a2.84,2.84,0,0,1,4.54,1l11.88,27.94a2.83,2.83,0,0,1-2.06,3.87l-2.11.43a2.84,2.84,0,0,1-3.25-1.85L559,445.48A2.8,2.8,0,0,1,559.79,442.49Z"/>
52
+ <path class="cls-2" d="M573.56,477.22l5.57,3.81a.9.9,0,0,1,0,1.39,1.06,1.06,0,0,1-.61.14,3.53,3.53,0,0,0-.86.08,1.54,1.54,0,0,0-.49.13.26.26,0,0,0-.09.37,1.37,1.37,0,0,0,.38.38c.35.28.65.59,1,.9l1.64,1.56h0c.44.42.25,1.44-.26,1.44h-8.05c-.25,0-.47-.3-.5-.69l-.66-9a.83.83,0,0,1,.36-.83A2.46,2.46,0,0,1,573.56,477.22Z"/>
53
+ <path class="cls-2" d="M349.61,441.27h0a3,3,0,0,0-4.71,1l-12.3,28.94a2.93,2.93,0,0,0,2.13,4l2.19.44a2.93,2.93,0,0,0,3.37-1.91l10.11-29.38A2.9,2.9,0,0,0,349.61,441.27Z"/>
54
+ <path class="cls-2" d="M333.55,477.22,328,481a.9.9,0,0,0,0,1.39,1.08,1.08,0,0,0,.61.14,3.62,3.62,0,0,1,.87.08,1.69,1.69,0,0,1,.49.13.25.25,0,0,1,.08.37,1.49,1.49,0,0,1-.37.38c-.35.28-.66.59-1,.9L327,486h0c-.43.42-.24,1.44.27,1.44h8c.26,0,.47-.3.5-.69l.67-9a.86.86,0,0,0-.36-.83A2.48,2.48,0,0,0,333.55,477.22Z"/>
55
+ <path class="cls-2" d="M413.88,438.35h0a3.19,3.19,0,0,0-5.1,1.1l-13.33,31.36a3.17,3.17,0,0,0,2.3,4.35l2.37.48a3.18,3.18,0,0,0,3.65-2.08l11-31.85A3.16,3.16,0,0,0,413.88,438.35Z"/>
56
+ <path class="cls-2" d="M397,477.22,391.43,481a.9.9,0,0,0,0,1.39,1.09,1.09,0,0,0,.62.14,3.58,3.58,0,0,1,.86.08,1.69,1.69,0,0,1,.49.13.26.26,0,0,1,.09.37,1.37,1.37,0,0,1-.38.38c-.35.28-.66.59-1,.9L390.48,486h0c-.43.42-.24,1.44.27,1.44h8c.26,0,.48-.3.51-.69l.66-9a.83.83,0,0,0-.36-.83A2.48,2.48,0,0,0,397,477.22Z"/>
57
+ <path class="cls-2" d="M449.93,482l2.5-4.58a1.44,1.44,0,0,1,1.62-.72h0a1.45,1.45,0,0,1,.89.66l2.84,4.7a.71.71,0,0,1-.67,1.07h0a.71.71,0,0,0-.61,1.15l1.63,2a.71.71,0,0,1-.55,1.15h-7.36a.7.7,0,0,1-.55-1.14l1.65-2.11a.7.7,0,0,0-.61-1.14h-.11A.7.7,0,0,1,449.93,482Z"/>
58
+ <path class="cls-2" d="M452.52,475.76h2a2.94,2.94,0,0,0,2.94-3l-1.16-34.88a2.94,2.94,0,0,0-2.9-2.84h0a3,3,0,0,0-3,2.87l-.83,34.87A2.94,2.94,0,0,0,452.52,475.76Z"/>
59
+ </g>
60
+ </svg>