1
|
|
2
|
import os.path
|
3
|
import copy
|
4
|
import sys
|
5
|
|
6
|
try:
|
7
|
from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QObject, QT_VERSION_STR, QRect
|
8
|
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QTransform, QFont, QColor, QFontMetricsF
|
9
|
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, \
|
10
|
QGraphicsTextItem
|
11
|
except ImportError:
|
12
|
try:
|
13
|
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QRect, QObject, QT_VERSION_STR
|
14
|
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont, \
|
15
|
QColor, QFontMetricsF
|
16
|
except ImportError:
|
17
|
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
|
18
|
|
19
|
from EngineeringPolylineItem import QEngineeringPolylineItem
|
20
|
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
|
21
|
from AppDocData import *
|
22
|
from EngineeringAbstractItem import QEngineeringAbstractItem
|
23
|
from TextInfo import TextInfo
|
24
|
from SymbolSvgItem import SymbolSvgItem
|
25
|
|
26
|
|
27
|
class QEngineeringTextItem(QGraphicsTextItem, QEngineeringAbstractItem):
|
28
|
HIGHLIGHT = '#BC4438'
|
29
|
ZVALUE = 210
|
30
|
|
31
|
'''
|
32
|
@history 2018.05.17 Jeongwoo Add self._owner variable
|
33
|
'''
|
34
|
|
35
|
def __init__(self, uid=None, parent=None):
|
36
|
import uuid
|
37
|
|
38
|
QGraphicsTextItem.__init__(self, parent)
|
39
|
QEngineeringAbstractItem.__init__(self)
|
40
|
|
41
|
self.uid = uuid.uuid4() if uid is None else uuid.UUID(uid)
|
42
|
self.type = 'TEXT'
|
43
|
self.loc = None
|
44
|
self.size = None
|
45
|
self.angle = 0
|
46
|
self._owner = None
|
47
|
self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
|
48
|
self.setAcceptHoverEvents(True)
|
49
|
self.setAcceptTouchEvents(True)
|
50
|
|
51
|
self.setColor(self._color)
|
52
|
self._savedColor = None
|
53
|
|
54
|
self.delimiter = '"'
|
55
|
self.lineNoDelimiter = '!-!'
|
56
|
|
57
|
self.attribute = ''
|
58
|
self._properties = {}
|
59
|
|
60
|
self.transfer = Transfer()
|
61
|
self.setZValue(QEngineeringTextItem.ZVALUE)
|
62
|
|
63
|
def __str__(self):
|
64
|
""" return string represent uuid """
|
65
|
return str(self.uid)
|
66
|
|
67
|
'''
|
68
|
@brief Get owner
|
69
|
@author Jeongwoo
|
70
|
@date 2018.05.17
|
71
|
'''
|
72
|
|
73
|
@property
|
74
|
def owner(self):
|
75
|
import uuid
|
76
|
|
77
|
|
78
|
if self.scene() and self._owner is not None and type(self._owner) is uuid.UUID:
|
79
|
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(self._owner)]
|
80
|
if matches: self._owner = matches[0]
|
81
|
return matches[0] if matches else None
|
82
|
|
83
|
|
84
|
if type(self._owner) is not uuid.UUID and type(self._owner) is not str:
|
85
|
return self._owner
|
86
|
else:
|
87
|
self._owner = None
|
88
|
return None
|
89
|
|
90
|
'''
|
91
|
@brief Set owner
|
92
|
@author Jeongwoo
|
93
|
@date 2018.05.17
|
94
|
@history 2018.05.17 Jeongwoo Add Calling setColor if self._owner is None or not
|
95
|
'''
|
96
|
|
97
|
@owner.setter
|
98
|
def owner(self, value):
|
99
|
self._owner = value
|
100
|
|
101
|
if self._owner is None:
|
102
|
self._color = self.DEFAULT_COLOR
|
103
|
self.setColor(self._color)
|
104
|
|
105
|
'''
|
106
|
@brief return text string
|
107
|
@author humkyung
|
108
|
@date 2018.04.16
|
109
|
'''
|
110
|
|
111
|
def text(self):
|
112
|
return self.toPlainText()
|
113
|
|
114
|
'''
|
115
|
@brief return center position of text
|
116
|
@author humkyung
|
117
|
@date 2018.04.16
|
118
|
'''
|
119
|
|
120
|
def center(self):
|
121
|
return self.sceneBoundingRect().center()
|
122
|
|
123
|
def boundingRect(self):
|
124
|
if self.angle == 1.57 or self.angle == 4.71:
|
125
|
return QRectF(0, 0, self.size[1], self.size[0])
|
126
|
else:
|
127
|
return QRectF(0, 0, self.size[0], self.size[1])
|
128
|
|
129
|
'''
|
130
|
@brief hover event
|
131
|
@authro humkyung
|
132
|
@date
|
133
|
'''
|
134
|
|
135
|
def hoverEnterEvent(self, event):
|
136
|
self.highlight(True)
|
137
|
|
138
|
def hoverLeaveEvent(self, event):
|
139
|
self.highlight(False)
|
140
|
|
141
|
'''
|
142
|
@brief set highlight
|
143
|
@author kyouho
|
144
|
@date 2018.08.27
|
145
|
'''
|
146
|
|
147
|
def highlight(self, flag):
|
148
|
self.hover = flag
|
149
|
if flag:
|
150
|
if self._savedColor is None:
|
151
|
self._savedColor = self.getColor()
|
152
|
self.setColor(QEngineeringTextItem.HIGHLIGHT)
|
153
|
elif hasattr(self, '_savedColor'):
|
154
|
self.setColor(self._savedColor)
|
155
|
|
156
|
self.update()
|
157
|
|
158
|
def hoverMoveEvent(self, event):
|
159
|
pass
|
160
|
|
161
|
'''
|
162
|
@brief remove item when user press delete key
|
163
|
@author humkyung
|
164
|
@date 2018.04.23
|
165
|
@history 2018.05.25 Jeongwoo Seperate delete item method
|
166
|
humkyung 2018.08.18 rotate text when user press 'R'
|
167
|
'''
|
168
|
|
169
|
def keyPressEvent(self, event):
|
170
|
if Qt.Key_Return == event.key():
|
171
|
self.edit_text()
|
172
|
elif event.key() == Qt.Key_R:
|
173
|
|
174
|
if 0 == self.angle:
|
175
|
self.angle = 1.57
|
176
|
|
177
|
elif 1.57 == self.angle:
|
178
|
self.angle = 3.14
|
179
|
|
180
|
elif 3.14 == self.angle:
|
181
|
self.angle = 4.71
|
182
|
|
183
|
elif 4.71 == self.angle:
|
184
|
self.angle = 0
|
185
|
|
186
|
width = self.size[0]
|
187
|
height = self.size[1]
|
188
|
self.size = [height, width]
|
189
|
|
190
|
self.rotate()
|
191
|
elif event.key() == Qt.Key_Up:
|
192
|
self.loc[1] = self.loc[1] - 1
|
193
|
self.rotate()
|
194
|
elif event.key() == Qt.Key_Down:
|
195
|
self.loc[1] = self.loc[1] + 1
|
196
|
self.rotate()
|
197
|
elif event.key() == Qt.Key_Left:
|
198
|
self.loc[0] = self.loc[0] - 1
|
199
|
self.rotate()
|
200
|
elif event.key() == Qt.Key_Right:
|
201
|
self.loc[0] = self.loc[0] + 1
|
202
|
self.rotate()
|
203
|
|
204
|
|
205
|
|
206
|
'''
|
207
|
@brief draw rect when item is selected
|
208
|
@author humkyung
|
209
|
@date 2018.07.08
|
210
|
'''
|
211
|
|
212
|
def drawFocusRect(self, painter):
|
213
|
self.focuspen = QPen(Qt.DotLine)
|
214
|
self.focuspen.setColor(Qt.black)
|
215
|
self.focuspen.setWidthF(1.5)
|
216
|
hilightColor = QColor(255, 0, 0, 127)
|
217
|
painter.setBrush(QBrush(hilightColor))
|
218
|
painter.setPen(self.focuspen)
|
219
|
painter.drawRect(self.boundingRect())
|
220
|
|
221
|
'''
|
222
|
@brief override paint(draw connection points)
|
223
|
@author humkyung
|
224
|
@date 2018.07.08
|
225
|
'''
|
226
|
|
227
|
def paint(self, painter, options=None, widget=None):
|
228
|
self.setColor(self.getColor())
|
229
|
|
230
|
if self.angle == 1.57 or self.angle == 4.71:
|
231
|
rect = QRectF(0, 0, self.size[1], self.size[0])
|
232
|
else:
|
233
|
rect = QRectF(0, 0, self.size[0], self.size[1])
|
234
|
|
235
|
painter.setFont(self.font())
|
236
|
color = self.defaultTextColor()
|
237
|
|
238
|
|
239
|
if self.hover:
|
240
|
configs = AppDocData.instance().getConfigs('Text', 'Background')
|
241
|
if not configs or not int(configs[0].value) != 1:
|
242
|
painter.setPen(Qt.NoPen)
|
243
|
painter.setBrush(Qt.white)
|
244
|
painter.drawRect(self.boundingRect())
|
245
|
|
246
|
|
247
|
painter.setPen(QPen(color))
|
248
|
painter.drawText(rect, Qt.AlignCenter, self.text())
|
249
|
|
250
|
if self.isSelected():
|
251
|
self.drawFocusRect(painter)
|
252
|
|
253
|
'''
|
254
|
@brief Delete text item
|
255
|
@author Jeongwoo
|
256
|
@date 2018.05.25
|
257
|
'''
|
258
|
|
259
|
def deleteTextItemFromScene(self):
|
260
|
''' not used '''
|
261
|
|
262
|
self.scene().removeItem(self)
|
263
|
|
264
|
'''
|
265
|
@brief Return real item position
|
266
|
@author Jeongwoo
|
267
|
@date 2018.05.25
|
268
|
'''
|
269
|
|
270
|
def boundingRectOnScene(self):
|
271
|
rect = self.boundingRect()
|
272
|
rect.moveTo(self.loc[0], self.loc[1])
|
273
|
return rect
|
274
|
|
275
|
def edit_text(self):
|
276
|
"""edit text by using ocr dialog"""
|
277
|
from TextItemFactory import TextItemFactory
|
278
|
from OcrResultDialog import QOcrResultDialog
|
279
|
|
280
|
item = None
|
281
|
try:
|
282
|
dialog = QOcrResultDialog(None, self.scene().parent().image().copy(self.loc[0] - 3, self.loc[1] - 3,
|
283
|
self.size[0] + 6, self.size[1] + 6),
|
284
|
QRect(self.loc[0], self.loc[1], self.size[0], self.size[1]), True, self.text())
|
285
|
(isAccept, textInfoList) = dialog.showDialog()
|
286
|
|
287
|
if isAccept:
|
288
|
scene = self.scene()
|
289
|
|
290
|
textInfo = textInfoList[0]
|
291
|
x = textInfo.getX()
|
292
|
y = textInfo.getY()
|
293
|
angle = textInfo.getAngle()
|
294
|
text = textInfo.getText()
|
295
|
width = textInfo.getW()
|
296
|
height = textInfo.getH()
|
297
|
item = TextItemFactory.instance().createTextItem(textInfo)
|
298
|
if item is not None:
|
299
|
item.loc = [x, y]
|
300
|
item.size = (width, height)
|
301
|
item.angle = angle
|
302
|
item.area = self.area
|
303
|
item.addTextItemToScene(scene)
|
304
|
item.transfer.onRemoved.connect(scene.parent().parent().parent().itemRemoved)
|
305
|
|
306
|
self.transfer.onRemoved.emit(self)
|
307
|
except Exception as ex:
|
308
|
message = 'error occurred({}) in {}:{}'.format(self.tr('Fail to create text'),
|
309
|
sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
310
|
sys.exc_info()[-1].tb_lineno)
|
311
|
self.addMessage.emit(MessageType.Normal, message)
|
312
|
|
313
|
return item
|
314
|
|
315
|
'''
|
316
|
@brief Double click event, Show QOcrResultDialog
|
317
|
@author Jeongwoo
|
318
|
@date 18.04.23
|
319
|
@history 18.06.20 Jeongwoo Resize QRect added 1
|
320
|
'''
|
321
|
|
322
|
def mouseDoubleClickEvent(self, event):
|
323
|
if event.buttons() == Qt.LeftButton:
|
324
|
self.edit_text()
|
325
|
|
326
|
'''
|
327
|
@brief rotate text
|
328
|
@author humkyung
|
329
|
@date 2018.08.18
|
330
|
'''
|
331
|
|
332
|
def rotate(self):
|
333
|
sx = 1
|
334
|
sy = 1
|
335
|
width = self.size[0]
|
336
|
height = self.size[1]
|
337
|
x = self.loc[0]
|
338
|
y = self.loc[1]
|
339
|
|
340
|
transform = QTransform()
|
341
|
if (1.57 == self.angle) or (4.71 == self.angle):
|
342
|
rect = self.boundingRect()
|
343
|
sx = width / rect.height()
|
344
|
sy = height / rect.width()
|
345
|
|
346
|
transform.translate(x, y)
|
347
|
transform.translate(width * 0.5, height * 0.5)
|
348
|
transform.scale(1, sy)
|
349
|
transform.rotateRadians(-self.angle)
|
350
|
transform.translate(-rect.width() * 0.5, -rect.height() * 0.5)
|
351
|
elif 3.14 == self.angle:
|
352
|
rect = self.boundingRect()
|
353
|
sx = width / rect.width()
|
354
|
sy = height / rect.height()
|
355
|
|
356
|
transform.translate(x, y - round((rect.height() - height) * 0.5))
|
357
|
transform.scale(sx, 1)
|
358
|
transform.rotateRadians(-self.angle)
|
359
|
transform.translate(-width * 0.5, -height * 0.5)
|
360
|
else:
|
361
|
rect = self.boundingRect()
|
362
|
sx = width / rect.width()
|
363
|
sy = height / rect.height()
|
364
|
|
365
|
|
366
|
transform.translate(x, y - round((rect.height() - height) * 0.5))
|
367
|
transform.scale(sx, 1)
|
368
|
|
369
|
self.setTransform(transform)
|
370
|
self.update()
|
371
|
|
372
|
'''
|
373
|
@brief Put text on scene
|
374
|
@author Jeongwoo
|
375
|
@date 18.04.23
|
376
|
@history humkyung 2018.06.30 apply font configuration
|
377
|
'''
|
378
|
def addTextItemToScene(self, scene):
|
379
|
try:
|
380
|
docData = AppDocData.instance()
|
381
|
configs = docData.getConfigs('Text Style', 'Font Name')
|
382
|
fontName = configs[0].value if configs else 'Arial'
|
383
|
configs = docData.getConfigs('Text Style', 'Font Size')
|
384
|
fontSize = int(configs[0].value) if configs else -1
|
385
|
|
386
|
sx = 1
|
387
|
sy = 1
|
388
|
width = self.size[0]
|
389
|
height = self.size[1]
|
390
|
x = self.loc[0]
|
391
|
y = self.loc[1]
|
392
|
rect = None
|
393
|
lineCount = self.text().count('\n') if self.text().count('\n') is not 0 else 1
|
394
|
transform = QTransform()
|
395
|
|
396
|
allowed_error = 0.001
|
397
|
if abs(self.angle - 1.57) < allowed_error:
|
398
|
self.angle = 1.57
|
399
|
elif abs(self.angle - 4.71) < allowed_error:
|
400
|
self.angle = 4.71
|
401
|
elif abs(self.angle - 3.14) < allowed_error:
|
402
|
self.angle = 3.14
|
403
|
else:
|
404
|
self.angle = 0
|
405
|
|
406
|
if abs(self.angle - 1.57) < allowed_error or abs(self.angle - 4.71) < allowed_error:
|
407
|
font = QFont(fontName, width if fontSize == -1 else fontSize)
|
408
|
|
409
|
x_factor = width / QFontMetricsF(font).height()
|
410
|
y_factor = height / (QFontMetricsF(font).width(self.text()) / lineCount)
|
411
|
factor = min(x_factor, y_factor)
|
412
|
font.setPointSizeF(font.pointSizeF() * factor)
|
413
|
|
414
|
self.setFont(font)
|
415
|
rect = self.boundingRect()
|
416
|
sx = width / rect.height()
|
417
|
sy = height / rect.width()
|
418
|
|
419
|
transform.translate(x, y)
|
420
|
transform.translate(width * 0.5, height * 0.5)
|
421
|
transform.scale(1, sy)
|
422
|
transform.rotateRadians(-self.angle)
|
423
|
transform.translate(-rect.width() * 0.5, -rect.height() * 0.5)
|
424
|
elif abs(self.angle - 3.14) < allowed_error:
|
425
|
font = QFont(fontName, height if fontSize == -1 else fontSize)
|
426
|
|
427
|
x_factor = width / (QFontMetricsF(font).width(self.text()) / lineCount)
|
428
|
y_factor = height / QFontMetricsF(font).height()
|
429
|
factor = min(x_factor, y_factor)
|
430
|
font.setPointSizeF(font.pointSizeF() * factor)
|
431
|
|
432
|
self.setFont(font)
|
433
|
rect = self.boundingRect()
|
434
|
sx = width / rect.width()
|
435
|
sy = height / rect.height()
|
436
|
|
437
|
transform.translate(x, y - round((rect.height() - height) * 0.5))
|
438
|
transform.scale(sx, 1)
|
439
|
transform.rotateRadians(-self.angle)
|
440
|
transform.translate(-width * 0.5, -height * 0.5)
|
441
|
else:
|
442
|
font = QFont(fontName, height if fontSize == -1 else fontSize)
|
443
|
|
444
|
x_factor = width / (QFontMetricsF(font).width(self.text()) / lineCount)
|
445
|
y_factor = height / QFontMetricsF(font).height()
|
446
|
factor = min(x_factor, y_factor)
|
447
|
font.setPointSizeF(font.pointSizeF() * factor)
|
448
|
|
449
|
self.setFont(font)
|
450
|
rect = self.boundingRect()
|
451
|
|
452
|
"""
|
453
|
doc = self.document()
|
454
|
doc.setDocumentMargin(0)
|
455
|
doc.adjustSize()
|
456
|
doc_size = doc.size()
|
457
|
|
458
|
sx = rect.width() / doc_size.width()
|
459
|
sy = rect.height() / doc_size.height()
|
460
|
"""
|
461
|
|
462
|
sx = width / rect.width()
|
463
|
sy = height / rect.height()
|
464
|
|
465
|
|
466
|
transform.translate(x, y)
|
467
|
|
468
|
|
469
|
self.setTransform(transform)
|
470
|
|
471
|
scene.addItem(self)
|
472
|
except Exception as ex:
|
473
|
from App import App
|
474
|
from AppDocData import MessageType
|
475
|
|
476
|
message = 'error occurred({}-{}) in {}:{}'.format(ex, self.text(),
|
477
|
sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
478
|
sys.exc_info()[-1].tb_lineno)
|
479
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
480
|
|
481
|
'''
|
482
|
@brief get connected items
|
483
|
@author humkyung
|
484
|
@date 2018.04.23
|
485
|
@history 2018.11.22 euisung fix note road
|
486
|
'''
|
487
|
|
488
|
def getConnectedItems(self):
|
489
|
visited = []
|
490
|
|
491
|
try:
|
492
|
if 1 == len(self.conns):
|
493
|
|
494
|
pool = []
|
495
|
visited = []
|
496
|
pool.append(self.conns[0])
|
497
|
while len(pool) > 0:
|
498
|
it = pool.pop()
|
499
|
visited.append(it)
|
500
|
for conn in it.conns:
|
501
|
if (conn is not None) and (conn not in visited): pool.append(conn)
|
502
|
|
503
|
except Exception as ex:
|
504
|
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
505
|
sys.exc_info()[-1].tb_lineno))
|
506
|
|
507
|
return visited
|
508
|
|
509
|
@staticmethod
|
510
|
def from_database(component):
|
511
|
""" get text item from database """
|
512
|
import uuid
|
513
|
from AppDocData import AppDocData
|
514
|
from TextItemFactory import TextItemFactory
|
515
|
from SymbolAttr import SymbolAttr
|
516
|
|
517
|
item = None
|
518
|
|
519
|
try:
|
520
|
x = float(component['X'])
|
521
|
y = float(component['Y'])
|
522
|
width = float(component['Width']) if component['Width'] is not None else 0
|
523
|
height = float(component['Height']) if component['Height'] is not None else 0
|
524
|
angle = float(component['Rotation']) if component['Rotation'] is not None else 0
|
525
|
text = component['Value']
|
526
|
textInfo = TextInfo(text, x, y, width, height, angle)
|
527
|
connline = component['Connected'] if component['Connected'] is not None else None
|
528
|
|
529
|
item = TextItemFactory.instance().createTextItem(textInfo)
|
530
|
if item is not None:
|
531
|
item.setVisible(False)
|
532
|
item.uid = uuid.UUID(component['UID'])
|
533
|
item.loc = [x, y]
|
534
|
item.size = [width, height]
|
535
|
item.angle = angle
|
536
|
item.setToolTip('<b>{}</b><br>LINE NO={}'.format(str(item.uid), text))
|
537
|
|
538
|
if component['Owner'] and component['Owner'] != 'None':
|
539
|
item._owner = uuid.UUID(component['Owner'])
|
540
|
|
541
|
|
542
|
if not component['Area']:
|
543
|
app_doc_data = AppDocData.instance()
|
544
|
for area in app_doc_data.getAreaList():
|
545
|
if area.contains([x, y]):
|
546
|
item.area = area.name
|
547
|
break
|
548
|
else:
|
549
|
item.area = component['Area']
|
550
|
|
551
|
|
552
|
""" apply freeze value """
|
553
|
|
554
|
|
555
|
if connline is not None:
|
556
|
item.conns.append(connline)
|
557
|
except Exception as ex:
|
558
|
from App import App
|
559
|
from AppDocData import MessageType
|
560
|
|
561
|
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
562
|
sys.exc_info()[-1].tb_lineno)
|
563
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
564
|
return None
|
565
|
|
566
|
return item
|
567
|
|
568
|
'''
|
569
|
@brief parse xml code
|
570
|
@author humkyung
|
571
|
@date 2018.09.15
|
572
|
'''
|
573
|
|
574
|
@staticmethod
|
575
|
def fromXml(node):
|
576
|
import uuid
|
577
|
from TextItemFactory import TextItemFactory
|
578
|
from AppDocData import AppDocData
|
579
|
from EngineeringNoteItem import QEngineeringNoteItem
|
580
|
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
|
581
|
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
|
582
|
|
583
|
item = None
|
584
|
|
585
|
try:
|
586
|
location = node.find('LOCATION').text if node.find('LOCATION') is not None else '0,0'
|
587
|
x = float(location.split(',')[0])
|
588
|
y = float(location.split(',')[1])
|
589
|
width = float(node.find('WIDTH').text) if node.find('WIDTH') is not None else 0
|
590
|
height = float(node.find('HEIGHT').text) if node.find('HEIGHT') is not None else 0
|
591
|
angle = float(node.find('ANGLE').text) if node.find('ANGLE') is not None else 0
|
592
|
value = node.find('VALUE').text
|
593
|
if len(value.replace('\n', '').replace(' ', '')) == 0:
|
594
|
return None
|
595
|
|
596
|
name = node.find('NAME').text
|
597
|
textInfo = TextInfo(value, x, y, width, height, angle)
|
598
|
|
599
|
item = TextItemFactory.instance().createTextItem(textInfo)
|
600
|
if item is not None:
|
601
|
item.loc = [x, y]
|
602
|
item.size = [width, height]
|
603
|
item.angle = angle
|
604
|
|
605
|
|
606
|
if item is not None:
|
607
|
item.uid = uuid.UUID(node.find('UID').text)
|
608
|
item.setVisible(False)
|
609
|
|
610
|
if node.find('OWNER') is not None and node.find('OWNER').text != 'None':
|
611
|
item._owner = uuid.UUID(node.find('OWNER').text)
|
612
|
|
613
|
|
614
|
if item is not None:
|
615
|
if node.find('AREA') is None:
|
616
|
appDocData = AppDocData.instance()
|
617
|
for area in appDocData.getAreaList():
|
618
|
if area.contains([x, y]):
|
619
|
item.area = area.name
|
620
|
break
|
621
|
else:
|
622
|
item.area = node.find('AREA').text
|
623
|
|
624
|
except Exception as ex:
|
625
|
from App import App
|
626
|
from AppDocData import MessageType
|
627
|
|
628
|
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
629
|
sys.exc_info()[-1].tb_lineno)
|
630
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
631
|
|
632
|
return item
|
633
|
|
634
|
'''
|
635
|
@brief generate xml code
|
636
|
@author humkyung
|
637
|
@date 2018.04.23
|
638
|
@history humkyung 2018.04.27 move to QEngineeringLineNoTextItem
|
639
|
humkyung 2018.05.02 add name as parameter
|
640
|
Jeongwoo 2018.05.30 Change variable [owner] is nullable and Add/Modify attributes
|
641
|
'''
|
642
|
|
643
|
def toXml(self, owner=None):
|
644
|
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree
|
645
|
from EngineeringLineItem import QEngineeringLineItem
|
646
|
from SymbolSvgItem import SymbolSvgItem
|
647
|
|
648
|
try:
|
649
|
node = Element('ATTRIBUTE')
|
650
|
uidNode = Element('UID')
|
651
|
uidNode.text = str(self.uid)
|
652
|
node.append(uidNode)
|
653
|
|
654
|
|
655
|
ownerNode = Element('OWNER')
|
656
|
if self.owner is not None:
|
657
|
ownerNode.text = str(self.owner)
|
658
|
else:
|
659
|
ownerNode.text = 'None'
|
660
|
node.append(ownerNode)
|
661
|
|
662
|
|
663
|
attributeValueNode = Element('ATTRIBUTEVALUE')
|
664
|
attributeValueNode.text = self.attribute
|
665
|
node.append(attributeValueNode)
|
666
|
|
667
|
nameNode = Element('NAME')
|
668
|
nameNode.text = self.type
|
669
|
node.append(nameNode)
|
670
|
|
671
|
locNode = Element('LOCATION')
|
672
|
locNode.text = '{},{}'.format(self.loc[0], self.loc[1])
|
673
|
node.append(locNode)
|
674
|
|
675
|
valueNode = Element('VALUE')
|
676
|
valueNode.text = self.text()
|
677
|
node.append(valueNode)
|
678
|
|
679
|
angleNode = Element('ANGLE')
|
680
|
angleNode.text = str(self.angle)
|
681
|
node.append(angleNode)
|
682
|
|
683
|
widthNode = Element('WIDTH')
|
684
|
widthNode.text = str(self.size[0])
|
685
|
node.append(widthNode)
|
686
|
|
687
|
heightNode = Element('HEIGHT')
|
688
|
heightNode.text = str(self.size[1])
|
689
|
node.append(heightNode)
|
690
|
|
691
|
areaNode = Element('AREA')
|
692
|
areaNode.text = self.area
|
693
|
node.append(areaNode)
|
694
|
|
695
|
sceneNode = Element('SCENE')
|
696
|
rect = self.sceneBoundingRect()
|
697
|
sceneNode.text = '{},{},{},{}'.format(rect.x(), rect.y(), rect.width(), rect.height())
|
698
|
node.append(sceneNode)
|
699
|
|
700
|
except Exception as ex:
|
701
|
from App import App
|
702
|
from AppDocData import MessageType
|
703
|
|
704
|
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
705
|
sys.exc_info()[-1].tb_lineno)
|
706
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
707
|
|
708
|
return None
|
709
|
|
710
|
return node
|
711
|
|
712
|
def findOwner(self, symbols):
|
713
|
import math
|
714
|
|
715
|
try:
|
716
|
minDist = None
|
717
|
selected = None
|
718
|
|
719
|
configs = AppDocData.instance().getConfigs('Range', 'Detection Ratio')
|
720
|
ratio = float(configs[0].value) if 1 == len(configs) else 1.5
|
721
|
|
722
|
dist = (self.sceneBoundingRect().height() + self.sceneBoundingRect().width()) * ratio / 2
|
723
|
center = self.sceneBoundingRect().center()
|
724
|
|
725
|
target_symbols = []
|
726
|
for symbol in symbols:
|
727
|
attrs = symbol.getAttributes()
|
728
|
|
729
|
freeze = False
|
730
|
for attr in attrs:
|
731
|
if attr.Freeze:
|
732
|
freeze = True
|
733
|
break
|
734
|
if freeze: continue
|
735
|
for attr in attrs:
|
736
|
ret = attr.Codes.find_match_exactly(self.text())
|
737
|
if ret:
|
738
|
target_symbols.append(symbol)
|
739
|
break
|
740
|
|
741
|
for symbol in target_symbols:
|
742
|
if issubclass(type(symbol), SymbolSvgItem):
|
743
|
dx = symbol.origin[0] - center.x()
|
744
|
dy = symbol.origin[1] - center.y()
|
745
|
|
746
|
|
747
|
length = math.sqrt(dx * dx + dy * dy)
|
748
|
|
749
|
if (length < dist) and (minDist is None or length < minDist):
|
750
|
minDist = length
|
751
|
selected = symbol
|
752
|
|
753
|
if selected is not None:
|
754
|
attrs = selected.getAttributes()
|
755
|
target_attr = None
|
756
|
for attr in attrs:
|
757
|
ret = attr.Codes.find_match_exactly(self.text())
|
758
|
if ret:
|
759
|
target_attr = attr
|
760
|
break
|
761
|
if target_attr.AssocItem is None and selected.add_assoc_item(self, at=int(target_attr.AttrAt)):
|
762
|
target_attr.AssocItem = self
|
763
|
self.owner = selected
|
764
|
return ret
|
765
|
else:
|
766
|
return False
|
767
|
except Exception as ex:
|
768
|
from App import App
|
769
|
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
770
|
sys.exc_info()[-1].tb_lineno)
|
771
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
772
|
|
773
|
'''
|
774
|
@brief Set Color. Override QEngineeringAbstractItem's
|
775
|
@author Jeongwoo
|
776
|
@date 2018.05.11
|
777
|
@history humkyung 2018.05.13 update after change color
|
778
|
'''
|
779
|
|
780
|
def setColor(self, color):
|
781
|
if QColor.isValidColor(color):
|
782
|
c = QColor()
|
783
|
c.setNamedColor(color)
|
784
|
self.setDefaultTextColor(c)
|
785
|
self.update()
|
786
|
|
787
|
def toSql(self):
|
788
|
""" convert text data to sql query for components and title block """
|
789
|
from AppDocData import AppDocData
|
790
|
|
791
|
res = []
|
792
|
|
793
|
appDocData = AppDocData.instance()
|
794
|
cols = ['UID', 'Drawings_UID', 'Symbol_UID', 'X', 'Y', 'Width', 'Height', 'Rotation', 'Area', 'Value', 'Owner',
|
795
|
'Connected', 'SpecialItemTypes_UID']
|
796
|
values = ['?', '?', "(select UID from Symbol where Name='Text' and SymbolType_UID=-1)", '?', '?', '?', '?', '?',
|
797
|
'?', '?', '?', '?', '?']
|
798
|
|
799
|
param = [
|
800
|
(str(self.uid), str(appDocData.activeDrawing.UID), self.loc[0], self.loc[1], self.size[0], self.size[1],
|
801
|
str(self.angle),
|
802
|
self.area, self.text(), \
|
803
|
str(self.owner) if self.owner else None, \
|
804
|
str(self.conns[0]) if self.conns else None, \
|
805
|
str(self.special_item_type) if self.special_item_type else None)]
|
806
|
sql = 'insert into Components({}) values({})'.format(','.join(cols), ','.join(values))
|
807
|
res.append((sql, tuple(param)))
|
808
|
|
809
|
titleBlockProps = appDocData.getTitleBlockProperties()
|
810
|
if titleBlockProps:
|
811
|
cols = ['UID', 'Drawings_UID', 'TitleBlockProperties_UID', 'VALUE']
|
812
|
values = ['?', '?', '?', '?']
|
813
|
params = []
|
814
|
for titleBlockProp in titleBlockProps:
|
815
|
if self.area == titleBlockProp[0]:
|
816
|
params.append((str(self.uid), appDocData.activeDrawing.UID, self.area, self.text()))
|
817
|
|
818
|
sql = 'insert into TitleBlockValues({}) values({})'.format(','.join(cols), ','.join(values))
|
819
|
if params: res.append((sql, tuple(params)))
|
820
|
|
821
|
return res
|
822
|
|
823
|
|
824
|
'''
|
825
|
@brief The class transfer pyqtSignal Event. Cause Subclass of QGraphicsRectItem can't use pyqtSignal
|
826
|
@author Jeongwoo
|
827
|
@date 2018.06.18
|
828
|
'''
|
829
|
|
830
|
|
831
|
class Transfer(QObject):
|
832
|
onRemoved = pyqtSignal(QGraphicsItem)
|
833
|
|
834
|
def __init__(self, parent=None):
|
835
|
QObject.__init__(self, parent)
|