batoolset 0.1.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 (162) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/list_gui.py +513 -0
  3. batoolset/GUI/multi_image_display.py +989 -0
  4. batoolset/GUI/open.py +325 -0
  5. batoolset/GUI/overlay_hints.py +45 -0
  6. batoolset/GUI/paint2.py +1345 -0
  7. batoolset/GUI/scrollablepaint.py +1152 -0
  8. batoolset/IJ_ROIs/__init__.py +0 -0
  9. batoolset/IJ_ROIs/tools.py +40 -0
  10. batoolset/PATH/__init__.py +0 -0
  11. batoolset/PATH/tools.py +79 -0
  12. batoolset/SQLite_tools/__init__.py +0 -0
  13. batoolset/SQLite_tools/tools.py +840 -0
  14. batoolset/__init__.py +0 -0
  15. batoolset/binary/__init__.py +0 -0
  16. batoolset/binary/tools.py +123 -0
  17. batoolset/binarytools/__init__.py +0 -0
  18. batoolset/binarytools/cell_center_detector.py +290 -0
  19. batoolset/clipboard_tools/__init__.py +0 -0
  20. batoolset/clipboard_tools/tools.py +7 -0
  21. batoolset/colors/__init__.py +0 -0
  22. batoolset/colors/colorgen.py +193 -0
  23. batoolset/colors/tools.py +22 -0
  24. batoolset/command_line/__init__.py +0 -0
  25. batoolset/command_line/tools.py +18 -0
  26. batoolset/dialogs/__init__.py +0 -0
  27. batoolset/dialogs/opensave.py +228 -0
  28. batoolset/dicts/__init__.py +0 -0
  29. batoolset/dicts/tools.py +299 -0
  30. batoolset/dims/__init__.py +0 -0
  31. batoolset/dims/tools.py +83 -0
  32. batoolset/draw/__init__.py +0 -0
  33. batoolset/draw/shapes/Position.py +183 -0
  34. batoolset/draw/shapes/__init__.py +0 -0
  35. batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
  36. batoolset/draw/shapes/circle2d.py +99 -0
  37. batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
  38. batoolset/draw/shapes/ellipse2d.py +336 -0
  39. batoolset/draw/shapes/freehand2d.py +235 -0
  40. batoolset/draw/shapes/group.py +1830 -0
  41. batoolset/draw/shapes/image2d.py +2469 -0
  42. batoolset/draw/shapes/line2d.py +575 -0
  43. batoolset/draw/shapes/point2d.py +257 -0
  44. batoolset/draw/shapes/polygon2d.py +357 -0
  45. batoolset/draw/shapes/polyline2d.py +235 -0
  46. batoolset/draw/shapes/rect2d.py +388 -0
  47. batoolset/draw/shapes/rectangle2d.py +601 -0
  48. batoolset/draw/shapes/scalebar.py +304 -0
  49. batoolset/draw/shapes/serializablefont.py +126 -0
  50. batoolset/draw/shapes/serializableguiparams.py +10 -0
  51. batoolset/draw/shapes/square2d.py +103 -0
  52. batoolset/draw/shapes/textorientation.py +45 -0
  53. batoolset/draw/shapes/tools.py +467 -0
  54. batoolset/draw/shapes/transform2D.py +350 -0
  55. batoolset/draw/shapes/txt2d.py +550 -0
  56. batoolset/draw/widgets/__init__.py +0 -0
  57. batoolset/draw/widgets/col.py +343 -0
  58. batoolset/draw/widgets/image_group.py +248 -0
  59. batoolset/draw/widgets/image_organizer.py +96 -0
  60. batoolset/draw/widgets/paint.py +184 -0
  61. batoolset/draw/widgets/vectorial.py +257 -0
  62. batoolset/figure/__init__.py +0 -0
  63. batoolset/figure/alignment.py +814 -0
  64. batoolset/figure/column.py +1117 -0
  65. batoolset/figure/fig_tools.py +285 -0
  66. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  67. batoolset/figure/panel.py +697 -0
  68. batoolset/figure/row.py +852 -0
  69. batoolset/figure/user_selection.py +287 -0
  70. batoolset/files/__init__.py +0 -0
  71. batoolset/files/tools.py +1321 -0
  72. batoolset/images/__init__.py +0 -0
  73. batoolset/images/tools.py +81 -0
  74. batoolset/img.py +5216 -0
  75. batoolset/linux/__init__.py +0 -0
  76. batoolset/linux/tools.py +72 -0
  77. batoolset/lists/__init__.py +0 -0
  78. batoolset/lists/tools.py +436 -0
  79. batoolset/luts/__init__.py +0 -0
  80. batoolset/luts/lut_minimal_test.py +1207 -0
  81. batoolset/matplolib/__init__.py +0 -0
  82. batoolset/matplolib/tools.py +44 -0
  83. batoolset/np_tools/__init__.py +0 -0
  84. batoolset/np_tools/tools.py +252 -0
  85. batoolset/np_tools/trash.py +15 -0
  86. batoolset/pandas_tools/__init__.py +0 -0
  87. batoolset/pandas_tools/tools.py +880 -0
  88. batoolset/partials/__init__.py +0 -0
  89. batoolset/partials/tools.py +83 -0
  90. batoolset/plot_tools/__init__.py +0 -0
  91. batoolset/plot_tools/tools.py +70 -0
  92. batoolset/pyqt/__init__.py +0 -0
  93. batoolset/pyqt/tools.py +691 -0
  94. batoolset/re_tools/__init__.py +0 -0
  95. batoolset/re_tools/tools.py +35 -0
  96. batoolset/serialization/__init__.py +0 -0
  97. batoolset/serialization/tools.py +1192 -0
  98. batoolset/sets/__init__.py +0 -0
  99. batoolset/sets/tools.py +109 -0
  100. batoolset/settings/__init__.py +0 -0
  101. batoolset/settings/global_settings.py +134 -0
  102. batoolset/strings/__init__.py +0 -0
  103. batoolset/strings/tools.py +225 -0
  104. batoolset/ta/__init__.py +0 -0
  105. batoolset/ta/database/__init__.py +0 -0
  106. batoolset/ta/database/advanced_sql_plotter.py +1170 -0
  107. batoolset/ta/database/my_qt_table.py +79 -0
  108. batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
  109. batoolset/ta/database/sql.py +2141 -0
  110. batoolset/ta/database/sql_column_name_dialog.py +122 -0
  111. batoolset/ta/measurements/TAmeasures.py +2226 -0
  112. batoolset/ta/measurements/__init__.py +0 -0
  113. batoolset/ta/measurements/measurements3D/__init__.py +0 -0
  114. batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
  115. batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
  116. batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
  117. batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
  118. batoolset/ta/measurements/nematic.py +562 -0
  119. batoolset/ta/measurements/nematic_measurements.py +107 -0
  120. batoolset/ta/segmentation/__init__.py +0 -0
  121. batoolset/ta/segmentation/neo_wshed.py +314 -0
  122. batoolset/ta/selections/__init__.py +0 -0
  123. batoolset/ta/selections/selection.py +329 -0
  124. batoolset/ta/tracking/__init__.py +0 -0
  125. batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
  126. batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
  127. batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
  128. batoolset/ta/tracking/registration.py +108 -0
  129. batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
  130. batoolset/ta/tracking/track_correction.py +238 -0
  131. batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
  132. batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
  133. batoolset/ta/utils/TA_tools.py +43 -0
  134. batoolset/ta/utils/__init__.py +0 -0
  135. batoolset/ta/utils/rps_tools.py +1783 -0
  136. batoolset/tests/__init__.py +0 -0
  137. batoolset/tests/rps_tools.py +51 -0
  138. batoolset/tests/tools.py +10 -0
  139. batoolset/tools/__init__.py +0 -0
  140. batoolset/tools/early_stopper_class.py +9 -0
  141. batoolset/tools/guided_data_recoverer.py +110 -0
  142. batoolset/tools/logger.py +100 -0
  143. batoolset/tools/mytimer.py +31 -0
  144. batoolset/tools/prompt_color.py +160 -0
  145. batoolset/tools/qthandler.py +118 -0
  146. batoolset/uitools/__init__.py +0 -0
  147. batoolset/uitools/blinker.py +56 -0
  148. batoolset/unsafe/__init__.py +0 -0
  149. batoolset/unsafe/tools.py +115 -0
  150. batoolset/utils/__init__.py +0 -0
  151. batoolset/utils/commontools.py +158 -0
  152. batoolset/utils/loadlist.py +728 -0
  153. batoolset/version.py +10 -0
  154. batoolset/xml/__init__.py +0 -0
  155. batoolset/xml/tools.py +65 -0
  156. batoolset/zip_tools/__init__.py +0 -0
  157. batoolset/zip_tools/tools.py +76 -0
  158. batoolset-0.1.0.dist-info/LICENSE +24 -0
  159. batoolset-0.1.0.dist-info/METADATA +45 -0
  160. batoolset-0.1.0.dist-info/RECORD +162 -0
  161. batoolset-0.1.0.dist-info/WHEEL +5 -0
  162. batoolset-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,184 @@
1
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
2
+ set_UI()
3
+ import sys
4
+ from qtpy.QtCore import QRect, QTimer
5
+ from qtpy.QtGui import QPixmap
6
+ from qtpy.QtWidgets import QWidget
7
+
8
+ from batoolset.draw.widgets.vectorial import VectorialDrawPane
9
+ from qtpy.QtWidgets import QMenu, QApplication
10
+ from qtpy import QtCore, QtGui
11
+
12
+ from batoolset.img import toQimage
13
+ from batoolset.tools.logger import TA_logger # logging
14
+
15
+ logger = TA_logger()
16
+
17
+ class Createpaintwidget(QWidget):
18
+
19
+ def __init__(self):
20
+ super().__init__()
21
+ self.vdp = VectorialDrawPane(active=False) #, demo=True
22
+ self.image = None
23
+ self.imageDraw = None
24
+ self.cursor = None
25
+ self.maskVisible = True
26
+ self.scale = 1.0
27
+ self.drawing = False
28
+ self.brushSize = 3
29
+ self._clear_size = 30
30
+ self.drawColor = QtGui.QColor(QtCore.Qt.red) # blue green cyan
31
+ self.eraseColor = QtGui.QColor(QtCore.Qt.black)
32
+ self.cursorColor = QtGui.QColor(QtCore.Qt.green)
33
+ self.lastPoint = QtCore.QPointF()
34
+ self.change = False
35
+ # KEEP IMPORTANT required to track mouse even when not clicked
36
+ self.setMouseTracking(True) # KEEP IMPORTANT
37
+ self.scrollArea = None
38
+ self.statusBar = None
39
+
40
+ def setImage(self, img):
41
+ if img is None:
42
+ self.image = None
43
+ self.imageDraw = None
44
+ self.update()
45
+ return
46
+ else:
47
+ self.image = toQimage(img) #.getQimage() # bug is here
48
+
49
+ # self.image = QPixmap(100,200).toImage()
50
+ width = self.image.size().width()
51
+ height = self.image.size().height()
52
+ top = self.geometry().x()
53
+ left = self.geometry().y()
54
+ self.setGeometry(top, left, int(width*self.scale), int(height*self.scale))
55
+ self.imageDraw = QtGui.QImage(self.image.size(), QtGui.QImage.Format_ARGB32)
56
+ self.imageDraw.fill(QtCore.Qt.transparent)
57
+ self.cursor = QtGui.QImage(self.image.size(), QtGui.QImage.Format_ARGB32)
58
+ self.cursor.fill(QtCore.Qt.transparent)
59
+ self.update()
60
+
61
+ def mousePressEvent(self, event):
62
+ if not self.hasMouseTracking():
63
+ return
64
+ self.clickCount = 1
65
+ if self.vdp.active:
66
+ self.vdp.mousePressEvent(event)
67
+ self.update()
68
+ return
69
+
70
+ if event.buttons() == QtCore.Qt.LeftButton or event.buttons() == QtCore.Qt.RightButton:
71
+ self.drawing = True
72
+ zoom_corrected_pos = event.position() / self.scale
73
+ self.lastPoint = zoom_corrected_pos
74
+ self.drawOnImage(event)
75
+
76
+ def mouseMoveEvent(self, event):
77
+ if not self.hasMouseTracking():
78
+ return
79
+ # print('in mouse move', self.hasMouseTracking(), self.drawing, self.vdp.active)
80
+ if self.statusBar:
81
+ zoom_corrected_pos = event.position() / self.scale
82
+ self.statusBar.showMessage('x=' + str(zoom_corrected_pos.x()) + ' y=' + str(
83
+ zoom_corrected_pos.y()))
84
+ if self.vdp.active:
85
+ self.vdp.mouseMoveEvent(event)
86
+ region = self.scrollArea.widget().visibleRegion()
87
+ self.update(region)
88
+ return
89
+ self.drawOnImage(event)
90
+
91
+ def drawOnImage(self, event):
92
+ zoom_corrected_pos = event.position() / self.scale
93
+ if self.drawing and (event.buttons() == QtCore.Qt.LeftButton or event.buttons() == QtCore.Qt.RightButton):
94
+ # now drawing or erasing over the image
95
+ painter = QtGui.QPainter(self.imageDraw)
96
+ if event.buttons() == QtCore.Qt.LeftButton:
97
+ painter.setPen(QtGui.QPen(self.drawColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
98
+ QtCore.Qt.RoundJoin))
99
+ else:
100
+ painter.setPen(QtGui.QPen(self.eraseColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
101
+ QtCore.Qt.RoundJoin))
102
+ if self.lastPoint != zoom_corrected_pos:
103
+ painter.drawLine(self.lastPoint, zoom_corrected_pos)
104
+ else:
105
+ # if zero length line then draw point instead
106
+ painter.drawPoint(zoom_corrected_pos)
107
+ painter.end()
108
+
109
+ # Drawing the cursor TODO add boolean to ask if drawing cursor should be shown
110
+ painter = QtGui.QPainter(self.cursor)
111
+ # We erase previous pointer
112
+ r = QtCore.QRect(QtCore.QPoint(), self._clear_size * QtCore.QSize() * self.brushSize)
113
+ painter.save()
114
+ r.moveCenter(self.lastPoint.toPoint())
115
+ painter.setCompositionMode(QtGui.QPainter.CompositionMode_Clear)
116
+ painter.eraseRect(r)
117
+ painter.restore()
118
+ # draw the new one
119
+ painter.setPen(QtGui.QPen(self.cursorColor, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
120
+ QtCore.Qt.RoundJoin))
121
+ painter.drawEllipse(zoom_corrected_pos, int(self.brushSize / 2.),
122
+ int(self.brushSize / 2.))
123
+ painter.end()
124
+ region = self.scrollArea.widget().visibleRegion()
125
+ self.update(region)
126
+
127
+ # required to erase mouse pointer
128
+ self.lastPoint = zoom_corrected_pos
129
+
130
+ def mouseReleaseEvent(self, event):
131
+ if not self.hasMouseTracking():
132
+ return
133
+ if self.vdp.active:
134
+ self.vdp.mouseReleaseEvent(event)
135
+ self.update() # required to update drawing
136
+ return
137
+ if event.button == QtCore.Qt.LeftButton:
138
+ self.drawing = False
139
+ if self.clickCount == 1:
140
+ QTimer.singleShot(QApplication.instance().doubleClickInterval(),
141
+ self.updateButtonCount)
142
+
143
+ # adds context/right click menu but only in vectorial mode
144
+ def contextMenuEvent(self, event):
145
+ if not self.vdp.active:
146
+ return
147
+ cmenu = QMenu(self)
148
+ newAct = cmenu.addAction("New")
149
+ opnAct = cmenu.addAction("Open")
150
+ quitAct = cmenu.addAction("Quit")
151
+ action = cmenu.exec_(self.mapToGlobal(event.position()))
152
+ if action == quitAct:
153
+ sys.exit(0)
154
+
155
+ def updateButtonCount(self):
156
+ self.clickCount = 1
157
+
158
+ def mouseDoubleClickEvent(self, event):
159
+ self.clickCount = 2
160
+ self.vdp.mouseDoubleClickEvent(event)
161
+
162
+ def paintEvent(self, event):
163
+ canvasPainter = QtGui.QPainter(self)
164
+ # the scrollpane visible region
165
+ visibleRegion = self.scrollArea.widget().visibleRegion()
166
+ # the corresponding rect
167
+ visibleRect = visibleRegion.boundingRect()
168
+ # the visibleRect taking zoom into account
169
+ scaledVisibleRect = QRect(int(visibleRect.x() / self.scale), int(visibleRect.y() / self.scale),
170
+ int(visibleRect.width() / self.scale), int(visibleRect.height() / self.scale))
171
+ if self.image is None:
172
+ canvasPainter.eraseRect(visibleRect)
173
+ canvasPainter.end()
174
+ return
175
+
176
+ canvasPainter.drawImage(visibleRect, self.image, scaledVisibleRect)
177
+ if not self.vdp.active and self.maskVisible:
178
+ canvasPainter.drawImage(visibleRect, self.imageDraw, scaledVisibleRect)
179
+ # should draw the cursor
180
+ canvasPainter.drawImage(visibleRect, self.cursor, scaledVisibleRect)
181
+
182
+ if self.vdp.active:
183
+ self.vdp.paintEvent(canvasPainter, scaledVisibleRect)
184
+ canvasPainter.end()
@@ -0,0 +1,257 @@
1
+ # TODO -−> add the small displacement filtering there!!! --> jut copy it from the other code -−> should be easy and maybe it would be useful to have a list of shapes so that one can delete them -−> see if I add that as separate stuff!!!
2
+ # I could also save the polygonF maybe
3
+
4
+
5
+ import os
6
+
7
+ from batoolset.draw.shapes.txt2d import TAText2D
8
+ from batoolset.pyqt.tools import getCtrlModifier
9
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
10
+ set_UI()
11
+ from qtpy import QtCore
12
+ from batoolset.draw.shapes.polygon2d import Polygon2D
13
+ from batoolset.draw.shapes.line2d import Line2D
14
+ from batoolset.draw.shapes.rect2d import Rect2D
15
+ from batoolset.draw.shapes.square2d import Square2D
16
+ from batoolset.draw.shapes.ellipse2d import Ellipse2D
17
+ from batoolset.draw.shapes.circle2d import Circle2D
18
+ from batoolset.draw.shapes.freehand2d import Freehand2D
19
+ from batoolset.draw.shapes.point2d import Point2D
20
+ from batoolset.draw.shapes.polyline2d import PolyLine2D
21
+ from batoolset.draw.shapes.image2d import Image2D
22
+ from qtpy.QtCore import QPointF, QRectF
23
+ from batoolset.tools.logger import TA_logger # logging
24
+ logger = TA_logger()
25
+
26
+ class VectorialDrawPane:
27
+
28
+ def __init__(self, active=False, demo=False, scale=1.0, drawing_mode=False, extra_size_for_sel=0, filter_out_unwanted_shapes_based_on_distance=True):
29
+ self.shapes = []
30
+ self.currently_drawn_shape = None
31
+ self.shape_to_draw = None
32
+ self.selected_shape = []
33
+ self.active = active
34
+ self.scale = scale
35
+ self.drawing_mode = drawing_mode
36
+ self.extra_size_for_sel = extra_size_for_sel # can be used to add an extra size around very small shapes --> TODO
37
+ self.filter_out_unwanted_shapes_based_on_distance = filter_out_unwanted_shapes_based_on_distance # if set to True the tool will attempt to filter accidental drawings by the user (based on distance between draw points)
38
+ if demo:
39
+ self.shapes.append(Polygon2D(0, 0, 10, 0, 10, 20, 0, 20, 0, 0, color=0x00FF00))
40
+ self.shapes.append(
41
+ Polygon2D(100, 100, 110, 100, 110, 120, 10, 120, 100, 100, color=0x0000FF, fill_color=0x00FFFF,
42
+ stroke=2))
43
+ self.shapes.append(Line2D(0, 0, 110, 100, color=0xFF0000, stroke=3))
44
+ self.shapes.append(Rect2D(200, 150, 250, 100, stroke=10))
45
+ self.shapes.append(Square2D(300, 260, 250, stroke=3))
46
+ self.shapes.append(Ellipse2D(0, 50, 600, 200, stroke=3))
47
+ self.shapes.append(Circle2D(150, 300, 30, color=0xFF0000))
48
+ self.shapes.append(PolyLine2D(10, 10, 20, 10, 20, 30, 40, 30, color=0xFF0000, stroke=2))
49
+ self.shapes.append(PolyLine2D(10, 10, 20, 10, 20, 30, 40, 30, color=0xFF0000, stroke=2))
50
+ self.shapes.append(Point2D(128, 128, color=0xFF0000, stroke=6))
51
+ self.shapes.append(Point2D(128, 128, color=0x00FF00, stroke=1))
52
+ self.shapes.append(Point2D(10, 10, color=0x000000, stroke=6))
53
+ img0 = Image2D('/E/Sample_images/counter/00.png')
54
+ img1 = Image2D('/E/Sample_images/counter/01.png')
55
+ img2 = Image2D('/E/Sample_images/counter/02.png')
56
+ img3 = Image2D('/E/Sample_images/counter/03.png')
57
+ img4 = Image2D('/E/Sample_images/counter/04.png')
58
+ img5 = Image2D('/E/Sample_images/counter/05.png')
59
+ img6 = Image2D('/E/Sample_images/counter/06.png')
60
+ img7 = Image2D('/E/Sample_images/counter/07.png')
61
+ img8 = Image2D('/E/Sample_images/counter/08.png')
62
+ img9 = Image2D('/E/Sample_images/counter/09.png')
63
+ img10 = Image2D('/E/Sample_images/counter/10.png')
64
+
65
+ row = img1 + img2 + img10
66
+
67
+ self.shapes.append(row)
68
+
69
+ row2 = img4 + img5
70
+ fig = row / row2
71
+ # fig = Column(row, row2)
72
+ #self.shapes.append(fig)
73
+ self.drawing_mode = True
74
+ # self.shape_to_draw = Line2D
75
+ # self.shape_to_draw = Rect2D
76
+ # self.shape_to_draw = Square2D
77
+ # self.shape_to_draw = Ellipse2D
78
+ # self.shape_to_draw = Circle2D
79
+ # self.shape_to_draw = Point2D # ok maybe small centering issue
80
+ # self.shape_to_draw = Freehand2D
81
+ # self.shape_to_draw = PolyLine2D
82
+ # self.shape_to_draw = Polygon2D
83
+ import random
84
+ drawing_methods = [Line2D, Rect2D, Square2D, Ellipse2D, Circle2D, Point2D, Freehand2D, PolyLine2D, Polygon2D]
85
+ self.shape_to_draw = random.choice(drawing_methods)
86
+
87
+ # TODO freehand drawing
88
+ # TODO broken line --> need double click for end
89
+
90
+ def paintEvent(self, *args):
91
+ painter = args[0]
92
+ visibleRect = None
93
+ if len(args) >= 2:
94
+ visibleRect = args[1]
95
+
96
+ painter.save()
97
+ if self.scale != 1.0:
98
+ painter.scale(self.scale, self.scale)
99
+
100
+ for shape in self.shapes:
101
+ # only draw shapes if they are visible --> requires a visiblerect to be passed
102
+ if visibleRect is not None:
103
+ # only draws if in visible rect
104
+ if shape.boundingRect().intersects(QRectF(visibleRect)):
105
+ shape.draw(painter)
106
+ else:
107
+ shape.draw(painter)
108
+
109
+ if self.currently_drawn_shape is not None:
110
+ if self.currently_drawn_shape.isSet:
111
+ self.currently_drawn_shape.draw(painter)
112
+
113
+ sel = self.create_master_rect()
114
+ if sel is not None:
115
+ painter.drawRect(sel)
116
+ painter.restore()
117
+ # painter.end() # probably a good idea ????
118
+
119
+ def group_contains(self, x, y):
120
+ # checks if master rect for group contains click
121
+ # get bounds and create union and compare
122
+ master_rect = self.create_master_rect()
123
+ if master_rect is None:
124
+ return False
125
+ return master_rect.contains(QPointF(x, y))
126
+
127
+ def create_master_rect(self):
128
+ master_rect = None
129
+ if self.selected_shape:
130
+ for shape in self.selected_shape:
131
+ if master_rect is None:
132
+ master_rect = shape.boundingRect()
133
+ else:
134
+ master_rect = master_rect.united(shape.boundingRect())
135
+ return master_rect
136
+
137
+ def removeCurShape(self):
138
+ if self.selected_shape:
139
+ self.shapes = [e for e in self.shapes if e not in self.selected_shape]
140
+ self.selected_shape = []
141
+
142
+ def mousePressEvent(self, event):
143
+ if event.button() == QtCore.Qt.LeftButton:
144
+ self.drawing = True
145
+ self.lastPoint = event.position() / self.scale
146
+ self.firstPoint = event.position() / self.scale
147
+
148
+ shapeFound = False
149
+ if self.currently_drawn_shape is None:
150
+ for shape in reversed(self.shapes):
151
+ if shape.contains(self.lastPoint, extra=self.extra_size_for_sel) and not shape in self.selected_shape:
152
+ logger.debug('you clicked shape:' + str(shape))
153
+ if event.modifiers() == getCtrlModifier():
154
+ if shape not in self.selected_shape: # avoid doublons
155
+ self.selected_shape.append(shape) # add shape to group
156
+ logger.debug('adding shape to group')
157
+ # shapeFound = True
158
+ else:
159
+ if not self.group_contains(self.lastPoint.x(), self.lastPoint.y()):
160
+ self.selected_shape = [shape]
161
+ logger.debug('only one element is selected')
162
+ # shapeFound = True
163
+ return
164
+
165
+ if not shapeFound and event.modifiers() == getCtrlModifier():
166
+ for shape in reversed(self.shapes):
167
+ if shape.contains(self.lastPoint, extra=self.extra_size_for_sel):
168
+ if shape in self.selected_shape: # avoid doublons
169
+ logger.debug('you clicked again shape:' + str(shape))
170
+ self.selected_shape.remove(shape) # add shape to group
171
+ logger.debug('removing a shape from group')
172
+ shapeFound = True
173
+ # no shape found --> reset sel
174
+ if not shapeFound and not self.group_contains(self.lastPoint.x(), self.lastPoint.y()):
175
+ logger.debug('resetting sel')
176
+ self.selected_shape = []
177
+
178
+ # check if a shape is selected and only move that
179
+ if self.drawing_mode and not self.selected_shape and self.currently_drawn_shape is None:
180
+ # do not reset shape if not done drawing...
181
+ if self.shape_to_draw is not None:
182
+ self.currently_drawn_shape = self.shape_to_draw()
183
+ else:
184
+ self.currently_drawn_shape = None
185
+ if self.drawing_mode and not self.selected_shape:
186
+ if self.currently_drawn_shape is not None:
187
+ self.currently_drawn_shape.setTopLeft(QPointF(self.lastPoint.x(), self.lastPoint.y()))
188
+
189
+ def mouseMoveEvent(self, event):
190
+ if event.buttons() and QtCore.Qt.LeftButton:
191
+ if self.selected_shape and self.currently_drawn_shape is None:
192
+ logger.debug('moving' + str(self.selected_shape))
193
+ for shape in self.selected_shape:
194
+ shape.translate(event.position() / self.scale - self.lastPoint)
195
+
196
+ if self.currently_drawn_shape is not None:
197
+ self.currently_drawn_shape.add(self.firstPoint, self.lastPoint)
198
+
199
+ self.lastPoint = event.position() / self.scale
200
+
201
+ def mouseReleaseEvent(self, event):
202
+ if event.button() == QtCore.Qt.LeftButton:
203
+ self.lastPoint = event.position() / self.scale
204
+ self.drawing = False
205
+ if self.drawing_mode and self.currently_drawn_shape is not None:
206
+ self.currently_drawn_shape.add(self.firstPoint, self.lastPoint)
207
+ if isinstance(self.currently_drawn_shape, Freehand2D):
208
+ # this closes the freehand shape
209
+ self.currently_drawn_shape.add(self.lastPoint, self.firstPoint)
210
+ # should not erase the shape if it's a polyline or a polygon by the way
211
+ if isinstance(self.currently_drawn_shape, Freehand2D) or (not isinstance(self.currently_drawn_shape, PolyLine2D) and not isinstance(self.currently_drawn_shape, Polygon2D)):
212
+ if self.check_shape_size_before_adding_it():
213
+ self.shapes.append(self.currently_drawn_shape)
214
+ self.selected_shape = [self.currently_drawn_shape]
215
+ self.currently_drawn_shape = None
216
+ else:
217
+ self.currently_drawn_shape = None
218
+ self.selected_shape = []
219
+
220
+ else:
221
+ self.currently_drawn_shape=None
222
+ self.selected_shape = []
223
+
224
+ def mouseDoubleClickEvent(self, event):
225
+ if isinstance(self.currently_drawn_shape, PolyLine2D) or isinstance(self.currently_drawn_shape, Polygon2D):
226
+ self.shapes.append(self.currently_drawn_shape)
227
+ self.currently_drawn_shape = None
228
+
229
+ def check_shape_size_before_adding_it(self):
230
+ if self.filter_out_unwanted_shapes_based_on_distance: # TODO maybe allow arrowheads to be drawn and stay small, allow lines only if they are in arrwohed only mode (if so do not allow the body of the li,ne to be drawn)
231
+ # if the movement is too small and the object is not a point then the shape drawing is probably undesised!!!
232
+ # print(self.firstPoint , self.lastPoint)
233
+ # print('distance', self.distance(self.firstPoint, self.lastPoint))
234
+ # print('scaled distance', self.distance(self.firstPoint, self.lastPoint)*self.scale)
235
+ # if self.distance(self.firstPoint, self.lastPoint) < 20:
236
+ # best is to look
237
+ # print(self.currently_drawn_shape.getRect())
238
+ rect = self.currently_drawn_shape.getRect()
239
+
240
+ print(rect, self.scale)
241
+
242
+
243
+ print('area to check',rect.width()* rect.height()*self.scale)
244
+ if not isinstance(self.currently_drawn_shape,(Point2D, TAText2D, Line2D)) and rect.width()* rect.height()*self.scale<200:
245
+
246
+
247
+ # if not isinstance(self.currently_drawn_shape,(Point2D)) and self.distance(self.firstPoint,self.lastPoint) * self.scale < 40: # , Polygon2D, PolyLine2D, Freehand2D)
248
+ logger.warning(str(self.currently_drawn_shape) + '-->' +
249
+ 'area of object is too small, drawing is ignored, the software assumes unintended drawing, zoom more (Ctrl/Cmd +) and redraw the shape if wanted')
250
+ self.currently_drawn_shape = None
251
+ # self.update()
252
+ # print(distance )
253
+ return False
254
+ return True
255
+
256
+ if __name__ == '__main__':
257
+ VectorialDrawPane()
File without changes