molde 0.1.13__tar.gz → 0.1.15__tar.gz

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.
Files changed (68) hide show
  1. {molde-0.1.13 → molde-0.1.15}/PKG-INFO +1 -1
  2. {molde-0.1.13 → molde-0.1.15}/molde/colors/color.py +94 -42
  3. {molde-0.1.13 → molde-0.1.15}/pyproject.toml +1 -1
  4. {molde-0.1.13 → molde-0.1.15}/README.md +0 -0
  5. {molde-0.1.13 → molde-0.1.15}/molde/__init__.py +0 -0
  6. {molde-0.1.13 → molde-0.1.15}/molde/__main__.py +0 -0
  7. {molde-0.1.13 → molde-0.1.15}/molde/actors/__init__.py +0 -0
  8. {molde-0.1.13 → molde-0.1.15}/molde/actors/common_symbols_actor.py +0 -0
  9. {molde-0.1.13 → molde-0.1.15}/molde/actors/ghost_actor.py +0 -0
  10. {molde-0.1.13 → molde-0.1.15}/molde/actors/lines_actor.py +0 -0
  11. {molde-0.1.13 → molde-0.1.15}/molde/actors/round_points_actor.py +0 -0
  12. {molde-0.1.13 → molde-0.1.15}/molde/actors/square_points_actor.py +0 -0
  13. {molde-0.1.13 → molde-0.1.15}/molde/colors/__init__.py +0 -0
  14. {molde-0.1.13 → molde-0.1.15}/molde/colors/color_names.py +0 -0
  15. {molde-0.1.13 → molde-0.1.15}/molde/fonts/IBMPlexMono-Bold.ttf +0 -0
  16. {molde-0.1.13 → molde-0.1.15}/molde/fonts/IBMPlexMono-Regular.ttf +0 -0
  17. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_down_dark_theme.svg +0 -0
  18. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_down_disabled_dark_theme.svg +0 -0
  19. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_down_disabled_light_theme.svg +0 -0
  20. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_down_light_theme.svg +0 -0
  21. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_left_dark_theme.svg +0 -0
  22. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_left_light_theme.svg +0 -0
  23. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_right_dark_theme.svg +0 -0
  24. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_right_light_theme.svg +0 -0
  25. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_up_dark_theme.svg +0 -0
  26. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_up_disabled_dark_theme.svg +0 -0
  27. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_up_disabled_light_theme.svg +0 -0
  28. {molde-0.1.13 → molde-0.1.15}/molde/icons/arrow_up_light_theme.svg +0 -0
  29. {molde-0.1.13 → molde-0.1.15}/molde/icons/check_box_image.svg +0 -0
  30. {molde-0.1.13 → molde-0.1.15}/molde/interactor_styles/__init__.py +0 -0
  31. {molde-0.1.13 → molde-0.1.15}/molde/interactor_styles/arcball_camera_style.py +0 -0
  32. {molde-0.1.13 → molde-0.1.15}/molde/interactor_styles/box_selection_style.py +0 -0
  33. {molde-0.1.13 → molde-0.1.15}/molde/main_window.ui +0 -0
  34. {molde-0.1.13 → molde-0.1.15}/molde/pickers/__init__.py +0 -0
  35. {molde-0.1.13 → molde-0.1.15}/molde/pickers/cell_area_picker.py +0 -0
  36. {molde-0.1.13 → molde-0.1.15}/molde/pickers/cell_property_area_picker.py +0 -0
  37. {molde-0.1.13 → molde-0.1.15}/molde/poly_data/__init__.py +0 -0
  38. {molde-0.1.13 → molde-0.1.15}/molde/poly_data/arrows.py +0 -0
  39. {molde-0.1.13 → molde-0.1.15}/molde/poly_data/lines_data.py +0 -0
  40. {molde-0.1.13 → molde-0.1.15}/molde/poly_data/simple_shapes.py +0 -0
  41. {molde-0.1.13 → molde-0.1.15}/molde/poly_data/vertices_data.py +0 -0
  42. {molde-0.1.13 → molde-0.1.15}/molde/render_widgets/__init__.py +0 -0
  43. {molde-0.1.13 → molde-0.1.15}/molde/render_widgets/animated_render_widget.py +0 -0
  44. {molde-0.1.13 → molde-0.1.15}/molde/render_widgets/common_render_widget.py +0 -0
  45. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/__init__.py +0 -0
  46. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/common.qss +0 -0
  47. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/create_color_page.py +0 -0
  48. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/mainwindow.ui +0 -0
  49. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qcheckbox.qss +0 -0
  50. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qinputs.qss +0 -0
  51. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qlayouts.qss +0 -0
  52. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qmenubar.qss +0 -0
  53. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qprogressbar.qss +0 -0
  54. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qpushbutton.qss +0 -0
  55. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qradiobutton.qss +0 -0
  56. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qscrollbar.qss +0 -0
  57. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qslider.qss +0 -0
  58. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qtablewidget.qss +0 -0
  59. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qtabwidget.qss +0 -0
  60. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qtoolbar.qss +0 -0
  61. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qtoolbuttons.qss +0 -0
  62. {molde-0.1.13 → molde-0.1.15}/molde/stylesheets/qtreewidget.qss +0 -0
  63. {molde-0.1.13 → molde-0.1.15}/molde/ui_files/messages/new_loading_window.ui +0 -0
  64. {molde-0.1.13 → molde-0.1.15}/molde/utils/__init__.py +0 -0
  65. {molde-0.1.13 → molde-0.1.15}/molde/utils/format_sequences.py +0 -0
  66. {molde-0.1.13 → molde-0.1.15}/molde/utils/poly_data_utils.py +0 -0
  67. {molde-0.1.13 → molde-0.1.15}/molde/utils/tree_info.py +0 -0
  68. {molde-0.1.13 → molde-0.1.15}/molde/windows/loading_window.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: molde
3
- Version: 0.1.13
3
+ Version: 0.1.15
4
4
  Summary:
5
5
  Author: André Fernandes
6
6
  Author-email: fpf.andre@gmail.com
@@ -1,8 +1,10 @@
1
1
  import typing
2
2
  from qtpy.QtGui import QColor
3
3
  import numpy as np
4
+ from dataclasses import dataclass
4
5
 
5
6
 
7
+ @dataclass(frozen=True, init=False)
6
8
  class Color:
7
9
  r: int
8
10
  g: int
@@ -10,19 +12,19 @@ class Color:
10
12
  a: int
11
13
 
12
14
  @typing.overload
13
- def __init__(self, r: int, g: int, b: int, a: int = 255):
15
+ def __new__(self, r: int, g: int, b: int, a: int = 255):
14
16
  """
15
17
  Initialize Colors with RGB or RGBA integer values ranging from 0 to 255.
16
18
  """
17
19
 
18
20
  @typing.overload
19
- def __init__(self, r: float, g: float, b: float, a: float = 1.0):
21
+ def __new__(self, r: float, g: float, b: float, a: float = 1.0):
20
22
  """
21
23
  Initialize Colors with RGB or RGBA floating values ranging from 0.0 to 1.0.
22
24
  """
23
25
 
24
26
  @typing.overload
25
- def __init__(self, hexa: str):
27
+ def __new__(self, hexa: str):
26
28
  """
27
29
  Initialize colors from hex values.
28
30
  The valid formats incluce RGB (#FF0000 for example)
@@ -30,61 +32,79 @@ class Color:
30
32
  """
31
33
 
32
34
  @typing.overload
33
- def __init__(self, qcolor: QColor):
35
+ def __new__(self, qcolor: QColor):
34
36
  """
35
37
  Initialize the color class with an instance of QColor
36
38
  """
37
39
 
38
40
  @typing.overload
39
- def __init__(self, color: "Color"):
41
+ def __new__(self, color: "Color"):
40
42
  """
41
43
  Initialize the color class with an instance it's own class
42
44
  """
43
45
 
44
46
  @typing.overload
45
- def __init__(self):
47
+ def __new__(self):
46
48
  """
47
49
  Initialize an empty black color
48
50
  """
49
51
 
50
- def __init__(self, *args):
52
+ def __new__(cls, *args):
53
+ """
54
+ Calls the appropriate constructor for the class according to the
55
+ number of arguments and their types.
56
+ """
57
+
51
58
  all_int = all([isinstance(i, int) for i in args])
52
59
  all_float = all([isinstance(i, float) for i in args])
53
60
 
54
61
  if len(args) == 0:
55
- self.from_rgba(0, 0, 0, 255)
62
+ return cls.from_rgba(0, 0, 0, 255)
56
63
 
57
64
  elif len(args) == 1 and isinstance(args[0], str):
58
- self.from_hex(*args)
65
+ return cls.from_hex(*args)
59
66
 
60
67
  elif len(args) == 1 and isinstance(args[0], QColor):
61
- self.from_qcolor(*args)
68
+ return cls.from_qcolor(*args)
62
69
 
63
70
  elif len(args) == 1 and isinstance(args[0], Color):
64
- self.from_color(*args)
71
+ return cls.from_color(*args)
65
72
 
66
73
  elif len(args) in [3, 4] and all_int:
67
- self.from_rgba(*args)
74
+ return cls.from_rgba(*args)
68
75
 
69
76
  elif len(args) in [3, 4] and all_float:
70
- self.from_rgba_f(*args)
77
+ return cls.from_rgba_f(*args)
71
78
 
72
79
  else:
73
80
  raise ValueError("Invalid input values")
74
81
 
82
+ @classmethod
83
+ def from_rgba(cls, r: int, g: int, b: int, a: int = 255) -> "Color":
84
+ """
85
+ This is the default constructor for the class.
86
+ All other constructors call this one.
87
+
88
+ Since "Color" should be imutable, we use "object.__setattr__" to bypass
89
+ the imutability just in the constructor.
90
+ """
91
+
92
+ obj = super().__new__(cls)
93
+ object.__setattr__(obj, "r", round(np.clip(r, 0, 255)))
94
+ object.__setattr__(obj, "g", round(np.clip(g, 0, 255)))
95
+ object.__setattr__(obj, "b", round(np.clip(b, 0, 255)))
96
+ object.__setattr__(obj, "a", round(np.clip(a, 0, 255)))
97
+ return obj
98
+
99
+ @classmethod
75
100
  def from_rgb(self, r: int, g: int, b: int) -> "Color":
76
101
  return self.from_rgba(r, g, b)
77
102
 
78
- def from_rgba(self, r: int, g: int, b: int, a: int = 255) -> "Color":
79
- self.r = round(np.clip(r, 0, 255))
80
- self.g = round(np.clip(g, 0, 255))
81
- self.b = round(np.clip(b, 0, 255))
82
- self.a = round(np.clip(a, 0, 255))
83
- return self
84
-
103
+ @classmethod
85
104
  def from_rgb_f(self, r: float, g: float, b: float) -> "Color":
86
105
  return self.from_rgba_f(r, g, b)
87
106
 
107
+ @classmethod
88
108
  def from_rgba_f(self, r: float, g: float, b: float, a: float = 1) -> "Color":
89
109
  return self.from_rgba(
90
110
  round(r * 255),
@@ -93,6 +113,7 @@ class Color:
93
113
  round(a * 255),
94
114
  )
95
115
 
116
+ @classmethod
96
117
  def from_hex(self, color: str) -> "Color":
97
118
  color = color.lstrip("#")
98
119
  if len(color) == 6:
@@ -103,6 +124,7 @@ class Color:
103
124
  return self.from_rgba(r, g, b, a)
104
125
  raise ValueError("Invalid hex color format")
105
126
 
127
+ @classmethod
106
128
  def from_hsv(self, hue: float, saturation: float, value: float):
107
129
  v = value / 100
108
130
  s = saturation / 100
@@ -111,17 +133,17 @@ class Color:
111
133
  h = hue / 60
112
134
  x = c * (1 - abs(h % 2 - 1))
113
135
 
114
- if 0 < h < 1:
136
+ if 0 <= h < 1:
115
137
  r, g, b = c, x, 0
116
- elif 1 < h < 2:
138
+ elif 1 <= h < 2:
117
139
  r, g, b = x, c, 0
118
- elif 2 < h < 3:
140
+ elif 2 <= h < 3:
119
141
  r, g, b = 0, c, x
120
- elif 3 < h < 4:
142
+ elif 3 <= h < 4:
121
143
  r, g, b = 0, x, c
122
- elif 4 < h < 5:
144
+ elif 4 <= h < 5:
123
145
  r, g, b = x, 0, c
124
- elif 5 < h < 6:
146
+ elif 5 <= h < 6:
125
147
  r, g, b = c, 0, x
126
148
  else:
127
149
  r, g, b = 0, 0, 0
@@ -132,9 +154,11 @@ class Color:
132
154
  (b + v - c),
133
155
  )
134
156
 
157
+ @classmethod
135
158
  def from_qcolor(self, color: QColor) -> "Color":
136
159
  return self.from_rgba(color.red(), color.green(), color.blue(), color.alpha())
137
160
 
161
+ @classmethod
138
162
  def from_color(self, color: "Color"):
139
163
  self.r = color.r
140
164
  self.g = color.g
@@ -165,7 +189,9 @@ class Color:
165
189
  min_, mid_, max_ = sorted((r, g, b))
166
190
  delta = max_ - min_
167
191
 
168
- if max_ == r:
192
+ if delta == 0:
193
+ hue = 0
194
+ elif max_ == r:
169
195
  hue = (g - b) / delta
170
196
  elif max_ == g:
171
197
  hue = (b - r) / delta + 2
@@ -191,23 +217,49 @@ class Color:
191
217
  return Color(self.r, self.g, self.b, self.a)
192
218
 
193
219
  def apply_factor(self, factor: float | int) -> "Color":
194
- new_color = self.copy()
195
- new_color.r = round(np.clip(self.r * factor, 0, 255))
196
- new_color.g = round(np.clip(self.g * factor, 0, 255))
197
- new_color.b = round(np.clip(self.b * factor, 0, 255))
198
-
199
- return new_color
220
+ r = round(np.clip(self.r * factor, 0, 255))
221
+ g = round(np.clip(self.g * factor, 0, 255))
222
+ b = round(np.clip(self.b * factor, 0, 255))
223
+ return Color.from_rgba(r, g, b, self.a)
200
224
 
201
- def set_brightness(self, brightness: int) -> "Color":
225
+ def with_brightness(self, brightness: int) -> "Color":
226
+ """
227
+ Percentage of brightness of the new color.
228
+ """
202
229
  h, s, _ = self.to_hsv()
203
- return self.to_hsv(h, s, brightness)
230
+ return self.from_hsv(h, s, brightness)
204
231
 
205
- def set_saturation(self, saturation: int) -> "Color":
232
+ def with_saturation(self, saturation: int) -> "Color":
233
+ """
234
+ Percentage of brightness of the new color.
235
+ """
206
236
  h, _, v = self.to_hsv()
207
- return self.to_hsv(h, saturation, v)
208
-
209
- def __repr__(self):
210
- return f"Color(r={self.r}, g={self.g}, b={self.b}, a={self.a})"
237
+ return self.from_hsv(h, saturation, v)
238
+
239
+ def with_rgba(
240
+ self,
241
+ r: int | None = None,
242
+ g: int | None = None,
243
+ b: int | None = None,
244
+ a: int | None = None,
245
+ ) -> "Color":
246
+ return self.from_rgba(
247
+ r if (r is not None) else self.r,
248
+ g if (g is not None) else self.g,
249
+ b if (b is not None) else self.b,
250
+ a if (a is not None) else self.a,
251
+ )
211
252
 
212
- def __eq__(self, other: "Color"):
213
- return self.r == other.r and self.g == other.g and self.b == other.b and self.a == other.a
253
+ def with_rgba_f(
254
+ self,
255
+ r: int | None = None,
256
+ g: int | None = None,
257
+ b: int | None = None,
258
+ a: int | None = None,
259
+ ) -> "Color":
260
+ return self.from_rgba_f(
261
+ r if (r is not None) else self.r,
262
+ g if (g is not None) else self.g,
263
+ b if (b is not None) else self.b,
264
+ a if (a is not None) else self.a,
265
+ )
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "molde"
3
- version = "0.1.13"
3
+ version = "0.1.15"
4
4
  description = ""
5
5
  authors = ["André Fernandes <fpf.andre@gmail.com>"]
6
6
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes