batoolset-gui 0.2.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.
Files changed (74) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/customdialog.py +136 -0
  3. batoolset/GUI/exception_handler.py +74 -0
  4. batoolset/GUI/list_gui.py +514 -0
  5. batoolset/GUI/multi_image_display.py +1038 -0
  6. batoolset/GUI/open.py +325 -0
  7. batoolset/GUI/overlay_hints.py +45 -0
  8. batoolset/GUI/paint2.py +1369 -0
  9. batoolset/GUI/scrollablepaint.py +1165 -0
  10. batoolset/dialogs/__init__.py +0 -0
  11. batoolset/dialogs/opensave.py +228 -0
  12. batoolset/drawings/__init__.py +0 -0
  13. batoolset/drawings/math_text.py +294 -0
  14. batoolset/drawings/pdf_svg_renderer.py +376 -0
  15. batoolset/drawings/shapes/Position.py +183 -0
  16. batoolset/drawings/shapes/__init__.py +0 -0
  17. batoolset/drawings/shapes/automated_alignment_drawing_refactored.py +346 -0
  18. batoolset/drawings/shapes/circle2d.py +99 -0
  19. batoolset/drawings/shapes/compute_optimal_size_all_merged.py +328 -0
  20. batoolset/drawings/shapes/ellipse2d.py +336 -0
  21. batoolset/drawings/shapes/freehand2d.py +235 -0
  22. batoolset/drawings/shapes/group.py +1985 -0
  23. batoolset/drawings/shapes/image2d.py +3157 -0
  24. batoolset/drawings/shapes/line2d.py +579 -0
  25. batoolset/drawings/shapes/point2d.py +257 -0
  26. batoolset/drawings/shapes/polygon2d.py +357 -0
  27. batoolset/drawings/shapes/polyline2d.py +235 -0
  28. batoolset/drawings/shapes/rect2d.py +388 -0
  29. batoolset/drawings/shapes/rectangle2d.py +601 -0
  30. batoolset/drawings/shapes/scalebar.py +310 -0
  31. batoolset/drawings/shapes/serializablefont.py +133 -0
  32. batoolset/drawings/shapes/serializableguiparams.py +14 -0
  33. batoolset/drawings/shapes/square2d.py +102 -0
  34. batoolset/drawings/shapes/test_publication_style.py +220 -0
  35. batoolset/drawings/shapes/textorientation.py +45 -0
  36. batoolset/drawings/shapes/tools.py +467 -0
  37. batoolset/drawings/shapes/transform2D.py +350 -0
  38. batoolset/drawings/shapes/txt2d.py +615 -0
  39. batoolset/drawings/svg_clip_renderer.py +247 -0
  40. batoolset/drawings/svg_embed.py +165 -0
  41. batoolset/drawings/svg_text_renderer.py +183 -0
  42. batoolset/drawings/widgets/__init__.py +0 -0
  43. batoolset/drawings/widgets/col.py +343 -0
  44. batoolset/drawings/widgets/image_group.py +248 -0
  45. batoolset/drawings/widgets/image_organizer.py +96 -0
  46. batoolset/drawings/widgets/paint.py +184 -0
  47. batoolset/drawings/widgets/vectorial.py +256 -0
  48. batoolset/figure/__init__.py +0 -0
  49. batoolset/figure/alignment.py +822 -0
  50. batoolset/figure/column.py +1117 -0
  51. batoolset/figure/fig_tools.py +285 -0
  52. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  53. batoolset/figure/panel.py +697 -0
  54. batoolset/figure/row.py +852 -0
  55. batoolset/figure/user_selection.py +287 -0
  56. batoolset/icons/__init__.py +0 -0
  57. batoolset/icons/tools.py +248 -0
  58. batoolset/luts/__init__.py +0 -0
  59. batoolset/luts/lut_minimal_test.py +1308 -0
  60. batoolset/luts/lutcreatorfromformula.py +209 -0
  61. batoolset/luts/luteditor.py +243 -0
  62. batoolset/pyqts/__init__.py +0 -0
  63. batoolset/pyqts/pleasewaitdialog.py +14 -0
  64. batoolset/pyqts/tools.py +760 -0
  65. batoolset/serializations/__init__.py +0 -0
  66. batoolset/serializations/tools.py +1338 -0
  67. batoolset/theme.py +647 -0
  68. batoolset/uis/__init__.py +0 -0
  69. batoolset/uis/blinker.py +56 -0
  70. batoolset_gui-0.2.0.dist-info/METADATA +54 -0
  71. batoolset_gui-0.2.0.dist-info/RECORD +74 -0
  72. batoolset_gui-0.2.0.dist-info/WHEEL +5 -0
  73. batoolset_gui-0.2.0.dist-info/licenses/LICENSE +24 -0
  74. batoolset_gui-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,310 @@
1
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
2
+ set_UI()
3
+ from qtpy.QtGui import QTransform,QPen, QColor
4
+ from qtpy.QtCore import QPointF
5
+ from batoolset.figure.alignment import pack2, align2, align_positions
6
+ from batoolset.drawings.shapes.rectangle2d import Rectangle2D
7
+ from batoolset.drawings.shapes.txt2d import TAText2D
8
+ from batoolset.drawings.shapes.Position import Position
9
+ # logger
10
+ from batoolset.tools.logger import TA_logger
11
+
12
+ logger = TA_logger()
13
+
14
+ class ScaleBar(Rectangle2D):
15
+
16
+ # TODO need a scaling factor for the bar if image is itself scaled or ??? --> most likely yes need think about it
17
+ # TODO handle bar color
18
+ def __init__(self, bar_width_in_units=0, legend="", unit_to_pixel_conversion_factor=1, bar_height_in_px=3, placement=Position('bottom-right'), bar_color=None, __version__=1.0,**kwargs):
19
+ super(ScaleBar, self).__init__()
20
+ # print('unsupported inputs scale',kwargs)
21
+ self.scale = 1
22
+ # colour of the bar itself (0xRRGGBB); None = white. A dedicated field:
23
+ # the inherited `color` was never used for drawing, and old files hold
24
+ # stale values there (e.g. yellow) that must not suddenly show up.
25
+ self.bar_color = bar_color
26
+ self.bar = Rectangle2D(color=None, fill_color=0xFFFFFF if bar_color is None else bar_color, stroke=0)
27
+ self.extra_space = 3
28
+ # print('bar_width_in_units',bar_width_in_units, 'unit_to_pixel_conversion_factor',unit_to_pixel_conversion_factor)
29
+
30
+ self.bar_height_in_px = bar_height_in_px
31
+ self.bar.setWidth(bar_width_in_units / (unit_to_pixel_conversion_factor if unit_to_pixel_conversion_factor else 1))
32
+ self.bar.setHeight(self.bar_height_in_px)
33
+ self.legend = None
34
+ self.setLegend(legend)
35
+
36
+ # print('self.legend inside',self.legend)
37
+
38
+ self.bar_width_in_units = bar_width_in_units
39
+ self.unit_to_pixel_conversion_factor = unit_to_pixel_conversion_factor
40
+ if not isinstance(placement, Position):
41
+ placement = Position(placement)
42
+ self.placement = placement
43
+ self.line_style = None # useless but require for compat with other shapes
44
+ self.__version__ = __version__
45
+
46
+ def setLegend(self, legend):
47
+ if isinstance(legend, str):
48
+ self.legend = TAText2D(legend)
49
+ elif isinstance(legend, TAText2D):
50
+ self.legend = legend
51
+ else:
52
+ self.legend = None
53
+
54
+ def setBarWidth(self, bar_width_in_units):
55
+ self.bar_width_in_units = bar_width_in_units
56
+ self.bar.setWidth(bar_width_in_units / (self.unit_to_pixel_conversion_factor if self.unit_to_pixel_conversion_factor else 1)) # this is ok but this is unscaled!!!
57
+ self.updateBoudingRect()
58
+
59
+ def update_bar_at_scale(self,scale):
60
+ # pass
61
+ # print('bar_width_in_units', self.bar_width_in_units, self.unit_to_pixel_conversion_factor, scale, self.bar.width(), self.width())
62
+ #
63
+ # self.bar.setWidth((self.bar_width_in_units * self.unit_to_pixel_conversion_factor) /scale)
64
+ #
65
+ # print('after', self.bar.width(), self.width()) # --> bar width is computed correctly so why isn't the size ok !!!
66
+
67
+ self.scale = scale
68
+
69
+ self.bar.setWidth((self.bar_width_in_units / (self.unit_to_pixel_conversion_factor if self.unit_to_pixel_conversion_factor else 1.)) / self.scale)
70
+
71
+ # self.packY() # it is the packing that fucks it all
72
+ # print('after2a', self.bar.width(),self.width()) # --> bar width is computed correctly so why isn't the size ok !!!
73
+ self.updateBoudingRect()
74
+ # print('after2b', self.bar.width(),self.width()) # --> bar width is computed correctly so why isn't the size ok !!!
75
+
76
+ # weird bug is here --> it resets the scale --> not what I want
77
+
78
+ # print('after2', self.bar.width(), self.width()) # --> bar width is computed correctly so why isn't the size ok !!!
79
+
80
+
81
+
82
+ def width(self, *args, **kwargs):
83
+ return super().width() # mandatory for proper scaling KEEP
84
+
85
+ def height(self, *args, **kwargs):
86
+ return super().height() # mandatory for proper scaling KEEP
87
+
88
+ def setConversionFactor(self, unit_to_pixel_conversion_factor):
89
+ self.unit_to_pixel_conversion_factor = unit_to_pixel_conversion_factor
90
+
91
+ def draw(self, painter, draw=True, parent=None):
92
+
93
+ # shall I reset scale from painter --> maybe
94
+ # painter.setWorldTransform(QTransform())
95
+ # I need reset scale from painter as it is handled directly in the object
96
+ # then position is not ok but why
97
+
98
+ painter.save()
99
+
100
+
101
+
102
+ # we dynamically place the bar with respect to the bounding rect
103
+ self.bar.moveCenter(self.center())
104
+ self.bar.moveBottom(self.bottom() - self.extra_space)
105
+ bar_color = getattr(self, 'bar_color', None)
106
+ self.bar.fill_color = 0xFFFFFF if bar_color is None else bar_color
107
+ self.bar.draw(painter=painter)
108
+ if self.legend is not None:
109
+ # we dynamically place the legend above the bar, inside the bounding rect
110
+ self.legend.moveCenter(self.center())
111
+ self.legend.moveTop(self.top() + self.extra_space / 2.)
112
+ self.legend.draw(painter=painter)
113
+ # self.drawAndFill(painter=painter)
114
+
115
+ # the bar should be centered on
116
+
117
+
118
+ if False: # just for debug !!!
119
+ painter.setPen(QPen(QColor("Green"),3))
120
+ painter.drawRect(self) # --> definitely the rect is incorrect -−> the error is in the placement of the rect
121
+
122
+ painter.restore()
123
+ def updateBoudingRect(self):
124
+ """
125
+ updates the image bounding rect depending on content
126
+ :return:
127
+ """
128
+
129
+ # contient deux objects et est donc la somme des deux
130
+ # --> facile en theorie faire que du packing et de l'alignement à gauche droite ou ailleurs
131
+ # pack in y direction the text and the bar
132
+ extra_space_below = 3 # TODO see how to make it not stuck to the bottom of the image --> it needs be a specificity of the bar and text but not for images --> TODO -> see how to do that
133
+ x = self.x()
134
+ y = self.y()
135
+ # x2 = None
136
+ # y2 = None
137
+ w=None
138
+ h=None
139
+ # the pb is that the shapes are not properly placed with respect to that
140
+ # and if the rect position is properly placed it is reset by wro,g placement of inner objects
141
+
142
+ # x=self.topLeft().x()
143
+ # y=self.topLeft().y()
144
+
145
+ to_pack = [self.bar, self.legend]
146
+ for img in to_pack:
147
+ if img is None:
148
+ continue
149
+ if not w:
150
+ w = img.width()
151
+ if not h:
152
+ h = img.height()
153
+
154
+ try:
155
+ w = max(w, img.width())
156
+ except Exception:
157
+ pass
158
+ # h = max(h, img.height())
159
+
160
+ # try:
161
+ # topLeft = img.topLeft()
162
+ # if x is None:
163
+ # x = topLeft.x()
164
+ # if y is None:
165
+ # y = topLeft.y()
166
+ # x = min(topLeft.x(), x)
167
+ # y = min(topLeft.y(), y)
168
+ #
169
+ # # print(img, img.boundingRect(), type(img))
170
+ # # print(img, img.boundingRect(), type(img), img.boundingRect().height())
171
+ #
172
+ # if x2 is None:
173
+ # x2 = topLeft.x() + img.boundingRect().width()
174
+ # if y2 is None:
175
+ # y2 = topLeft.y() + img.boundingRect().height()
176
+ # x2 = max(topLeft.x() + img.boundingRect().width(), x2)
177
+ # y2 = max(topLeft.y() + img.boundingRect().height(), y2)
178
+ # except:
179
+ # pass
180
+
181
+ h = self.bar.height()
182
+ if self.legend and not isinstance(self.legend, str):
183
+ h += self.legend.height() # stack bar and legend vertically
184
+
185
+ # shall I translate the stuff at the same time ??? -−> maybe
186
+
187
+
188
+
189
+ if False:
190
+ self.setX(x-self.extra_space)
191
+ self.setY(y-self.extra_space)
192
+ self.setWidth(x2 - x)
193
+ # if not self.legend or self.width()<=self.bar.width():
194
+ self.setWidth(self.width()+self.extra_space*2) # maybe
195
+ self.setHeight(y2 - y)
196
+ # self.setHeight(self.height()+3) # add extra
197
+ self.setHeight(self.height()+self.extra_space*2)
198
+
199
+ self.setWidth(w+2*self.extra_space)
200
+ self.setHeight(h+2*self.extra_space)
201
+
202
+ # MEGA TOOD -> maybe I should only add space or not depending on placement -> check that !!!
203
+
204
+
205
+
206
+ def packY(self, space=3):
207
+ # center in vertical axis then pack
208
+ #
209
+ # last_x = 0
210
+ # last_y = 0
211
+ #
212
+ # to_pack = [self.bar, self.legend]
213
+ # for i in range(len(to_pack)):
214
+ # img = self.images[i]
215
+ # if i != 0:
216
+ # last_y += space
217
+ # img.setTopLeft(img.topLeft().x(), last_y)
218
+ # # get all the bounding boxes and pack them with desired space in between
219
+ # # get first point and last point in x
220
+ # x = img.boundingRect().x()
221
+ # y = img.boundingRect().y()
222
+ # last_x = img.boundingRect().x() + img.boundingRect().width()
223
+ # last_y = img.boundingRect().y() + img.boundingRect().height()
224
+ if self.legend is not None and not isinstance(self.legend, str):
225
+ self.bar.setWidth((self.bar_width_in_units / self.unit_to_pixel_conversion_factor)/self.scale)
226
+ # alignCenterH(self.legend, self.bar)
227
+ align2(align_positions[-1], self.legend, self.bar)
228
+ # align_positions = ['Top', 'Bottom', 'Left', 'Right', 'CenterV', 'CenterH']
229
+ # packY(12, self.legend, self.bar)
230
+ pack2(3, ('-' if self.placement.check_position('top') else '') + 'Y', False, *[self.legend, self.bar])
231
+
232
+
233
+
234
+ self.updateBoudingRect()
235
+
236
+
237
+
238
+
239
+
240
+ # finally just need align right
241
+
242
+ # def setTopLeft(self, *args):
243
+ def setTopLeft(self, *args):
244
+ curP1 = self.topLeft()
245
+ if args:
246
+ if len(args) == 1:
247
+ # assume a QpointF
248
+ super().moveTopLeft(args[0])
249
+ elif len(args) == 2:
250
+ super().moveTopLeft(QPointF(args[0], args[1]))
251
+ else:
252
+ logger.error('invalid args for top left')
253
+
254
+ newP1 = self.topLeft()
255
+ # if
256
+ # # self.setTopLeft(*args)
257
+ # current_pos = self.boundingRect().topLeft()
258
+ # self.translate(point.x() - current_pos.x(), point.y() - current_pos.y())
259
+
260
+
261
+ if False:
262
+ # TODO check this code as most of this si probably totally useless
263
+ # curP1 = self.topLeft()
264
+ self.packY()
265
+ # Rectangle2D.setTopLeft(self, *args)
266
+ # Rectangle2D.setTopLeft(self, *args)
267
+ # newP1 = self.topLeft()
268
+
269
+ to_pack = [self.bar, self.legend]
270
+ for img in to_pack:
271
+ if img is not None:
272
+ img.translate(newP1.x() - curP1.x(), newP1.y() - curP1.y())
273
+ # img.translate(self.center().x()-img.center().x(),0)
274
+
275
+ # print('before aazezae', self.getRect())
276
+
277
+
278
+ self.updateBoudingRect()
279
+ # print('after qsdqsdqd', self.getRect())
280
+
281
+ # def set_to_scale(self, scale):
282
+ # self.scale = scale
283
+
284
+ # def setcolor
285
+
286
+ # get the bounds of the bar with the associated text
287
+ # center text on bar see how I do in EZF
288
+
289
+ def __repr__(self):
290
+ class_name = type(self).__name__
291
+ memory_address = hex(id(self))
292
+ return f"{class_name}-{memory_address}"
293
+
294
+
295
+ # def to_dict(self):
296
+ # x = self.x()
297
+ # y = self.y()
298
+ # width = self.width()
299
+ # height = self.height()
300
+ #
301
+ # # Create a dictionary representation of the values of the super object
302
+ # output_dict = {
303
+ # 'x': x,
304
+ # 'y': y,
305
+ # 'width': width,
306
+ # 'height': height,
307
+ # }
308
+ # # Update the dictionary with the __dict__ of Rectangle2D
309
+ # output_dict.update(self.__dict__)
310
+ # return output_dict
@@ -0,0 +1,133 @@
1
+ from batoolset.drawings.shapes.Position import Position
2
+ from batoolset.drawings.shapes.txt2d import TAText2D
3
+ from batoolset.pyqts.tools import get_html_text_with_font
4
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
5
+ set_UI()
6
+ from qtpy.QtGui import QFont
7
+ from qtpy.QtWidgets import QApplication
8
+ # from qtpy.QtCore import Qt
9
+ import sys
10
+
11
+ class SerializableQFont(QFont):
12
+
13
+ def __init__(self, *args, **kwargs):
14
+ # print('kwargs of qfont', kwargs)
15
+ # print('args of qfont', args)
16
+
17
+ self.foreground = 0x000000
18
+ if 'foreground' in kwargs:
19
+ self.foreground = kwargs['foreground']
20
+ del kwargs['foreground']
21
+
22
+ self.background = 0xFFFFFF
23
+ if 'background' in kwargs:
24
+ self.background = kwargs['background']
25
+ del kwargs['background']
26
+ self.placement = Position('top-left')
27
+ if 'placement' in kwargs:
28
+ if isinstance(kwargs['placement'], Position):
29
+ self.placement = kwargs['placement']
30
+ else:
31
+ self.placement = Position(kwargs['placement'])
32
+ del kwargs['placement']
33
+
34
+
35
+ super().__init__(*args, **kwargs)
36
+
37
+
38
+ # print('kwargs of qfont', kwargs)
39
+ # print('args of qfont', args)
40
+
41
+ # tmp_font = None
42
+ # if args:
43
+ # if isinstance(args[0], SerializableQFont):
44
+ # print('BINGO', args[0].foreground, args[0].background)
45
+ # else:
46
+ # print('PAS BINGO', type(args[0]))
47
+
48
+
49
+
50
+
51
+ def to_dict(self):
52
+ """Convert the SerializableQFont object to a dictionary."""
53
+ return {
54
+ 'family': self.family(),
55
+ 'size': max(self.pointSize(),1), # just in case pointsize is 0
56
+ 'style': self.weight(), # if self.weight() == QFont.Normal else 'Bold'
57
+ 'italic': self.italic(),
58
+ 'background': self.background,
59
+ 'foreground': self.foreground,
60
+ 'placement':self.placement.position_to_string(),
61
+ }
62
+
63
+ @staticmethod
64
+ def from_dict(font_dict):
65
+ """Create a SerializableQFont object from a dictionary."""
66
+ font = SerializableQFont(font_dict.get('family', 'Arial'), pointSize=font_dict.get('size', 12), weight=font_dict.get('style', QFont.Normal), italic=font_dict.get('italic', False), background = font_dict.get('background', None),foreground = font_dict.get('foreground', None), placement=Position(font_dict.get('placement', 'top-left')))
67
+ return font
68
+
69
+ def format_text_with_font(self, text):
70
+ return get_html_text_with_font(text, self)
71
+
72
+
73
+ # self.foreground
74
+ def get_letter_html(self, text, foreground=None):
75
+ """*foreground* (0xRRGGBB int) overrides the font colour for this letter,
76
+ e.g. dark letters on a white chart panel when the figure uses white."""
77
+ fg = self.foreground if foreground is None else foreground
78
+ if fg is not None:
79
+ text = f'<font color=#{fg:06x}>{text}</font>'
80
+ return self.format_text_with_font(text)
81
+
82
+ def get_TaText2D_with_font(self, text, foreground=None):
83
+ return TAText2D(self.get_letter_html(text, foreground=foreground), placement=self.placement,
84
+ fill_color=self.background, is_letter=True)
85
+
86
+ def __copy__(self):
87
+ return self
88
+
89
+ def __deepcopy__(self, memo):
90
+ return self
91
+
92
+ # be careful with that because this is what is compared when using == !!! so if poorly implemented this can have dramatic effects
93
+
94
+ def __str__(self):
95
+ # return f"{ self.__class__.__name__} {self.ID}"
96
+ return self.__repr__()
97
+ #
98
+ # def __repr__(self):
99
+ # return self.__str__()
100
+
101
+ def __repr__(self):
102
+ class_name = type(self).__name__
103
+ memory_address = hex(id(self))
104
+ return f"{class_name}-{memory_address}"
105
+
106
+ def main():
107
+ # Create a SerializableQFont object
108
+ font = SerializableQFont()
109
+ font.setFamily('Arial')
110
+ font.setFamily('Comic Sans MS')
111
+ font.setPointSize(12)
112
+ font.setWeight(QFont.Normal)
113
+ font.setItalic(True)
114
+ font.background = 0xFF0000
115
+ font.foreground = 0x0000FF
116
+
117
+ # Convert the SerializableQFont object to a dictionary
118
+ font_dict = font.to_dict()
119
+ print(font_dict)
120
+
121
+ # Convert the SerializableQFont object to a JSON string
122
+ # Create a SerializableQFont object from a dictionary
123
+ font2 = SerializableQFont.from_dict(font_dict)
124
+ print(font2.family(), font2.pointSize(), font2.weight(), font2.italic())
125
+
126
+ # Exit the QApplication
127
+
128
+
129
+ if __name__ == '__main__':
130
+ # Initialize the QApplication
131
+ app = QApplication(sys.argv)
132
+ main()
133
+ # sys.exit(app.exec_())
@@ -0,0 +1,14 @@
1
+ # Here I will store all the GUI parameters (such as Y spacing) so that I can restore them too
2
+
3
+
4
+ class SerializableGUIparameters():
5
+ # min = None, max = None,
6
+ def __init__(self, space=3, background=None, first_letter=None, auto_lettering=None, **kwargs):
7
+ self.space = space
8
+ # figure-wide background colour (0xRRGGBB) behind panels and gaps; None = none
9
+ self.background = background
10
+ # panel lettering: the first letter ('A' or 'a'...) and whether panels are
11
+ # lettered at all; None in files saved before they were stored
12
+ self.first_letter = first_letter
13
+ self.auto_lettering = auto_lettering
14
+ # see what are the other things I can store
@@ -0,0 +1,102 @@
1
+ import os
2
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
3
+ set_UI()
4
+ from batoolset.drawings.shapes.rectangle2d import Rectangle2D
5
+ from qtpy.QtCore import QPointF
6
+
7
+ from batoolset.drawings.shapes.rect2d import Rect2D
8
+
9
+ from batoolset.tools.logger import TA_logger
10
+
11
+ logger = TA_logger()
12
+
13
+ # Do I need square if I have already the rect2D
14
+ # make it that the code is just a series of instructions so that it is rebuilt on the fly and always works -−> no serialization --> no pb
15
+
16
+
17
+
18
+ class Square2D(Rectangle2D):
19
+
20
+ def __init__(self, *args, x=0, y=0, width=0, color=0xFFFFFF, fill_color=None, opacity=1., stroke=0.65, line_style=None, theta=0, __version__=1.0,**kwargs):
21
+ if len(args) == 3:
22
+ super(Square2D, self).__init__(*args, args[-1])
23
+ elif len(args) == 4:
24
+ logger.error("too many values, square only has, x,y and width")
25
+ else:
26
+ if args:
27
+ super(Square2D, self).__init__(*args) # create empty circle
28
+ else:
29
+ super(Square2D, self).__init__(x, y, width, width) # create empty circle
30
+ self.color = color
31
+ self.fill_color = fill_color
32
+ self.stroke = stroke
33
+ self.opacity = opacity
34
+ self.line_style = line_style
35
+ # rotation
36
+ self.theta = theta
37
+ self.__version__ = __version__
38
+
39
+ def add(self, *args):
40
+ p1 = args[0]
41
+ p2 = args[1]
42
+
43
+ x = p2.x()
44
+ y = p2.y()
45
+ x2 = p1.x()
46
+ y2 = p1.y()
47
+ if p1.x() < p2.x():
48
+ x = p1.x()
49
+ x2 = p2.x()
50
+ if p1.y() < p2.y():
51
+ y = p1.y()
52
+ y2 = p2.y()
53
+ w = abs(x - x2)
54
+ h = abs(y - y2)
55
+ self.setX(x)
56
+ self.setY(y)
57
+ if w < h:
58
+ self.setWidth(h)
59
+ self.setHeight(h)
60
+ else:
61
+ self.setWidth(w)
62
+ self.setHeight(w)
63
+ # self.isSet = True
64
+
65
+ def __repr__(self):
66
+ class_name = type(self).__name__
67
+ memory_address = hex(id(self))
68
+ return f"{class_name}-{memory_address}"
69
+
70
+ if __name__ == '__main__':
71
+ # ça marche --> voici deux examples de shapes
72
+ test = Square2D(0, 0, 200)
73
+ print(test.x(), test.y(), test.width(), test.height())
74
+ print(test.contains(QPointF(50, 50)))
75
+ print(test.contains(QPointF(-1, -1)))
76
+ print(test.contains(QPointF(0, 0)))
77
+ print(test.contains(QPointF(100, 100)))
78
+ print(test.contains(QPointF(100, 100.1)))
79
+
80
+ # p1 = test.p1()
81
+ # print(p1.x(), p1.y())
82
+ # p2 = test.p2()
83
+ # print(p2.x(), p2.y())
84
+ # print(test.arrow)
85
+ # print(test.length()) # sqrt 2 --> 141
86
+ # # if it's an arrow I can add easily all the stuff I need
87
+ #
88
+ # test = Rect2D(0, 0, 1, 1)
89
+ # p1 = test.p1()
90
+ # print(p1.x(), p1.y())
91
+ # p2 = test.p2()
92
+ # print(p2.x(), p2.y())
93
+ # print(test.arrow)
94
+ # import math
95
+ # print(test.length() == math.sqrt(2)) # sqrt 2
96
+ #
97
+ # test2 = Rect2D()
98
+ # p1 = test2.p1()
99
+ # print(p1.x(), p1.y())
100
+ # p2 = test2.p2()
101
+ # print(p2.x(), p2.y())
102
+ # print(test2.arrow)