hytos / DTI_PID / DTI_PID / Shapes / EngineeringLineNoTextItem.py @ 40606a5d
이력 | 보기 | 이력해설 | 다운로드 (61.8 KB)
1 |
# coding: utf-8
|
---|---|
2 |
""" This is engineering line no text item module """
|
3 |
|
4 |
import os.path |
5 |
import sys |
6 |
import copy |
7 |
|
8 |
from EngineeringFromMarkItem import EngineeringFromMarkItem |
9 |
from EngineeringToMarkItem import EngineeringToMarkItem |
10 |
|
11 |
try:
|
12 |
from PyQt5.QtCore import * |
13 |
from PyQt5.QtGui import * |
14 |
from PyQt5.QtWidgets import * |
15 |
except ImportError: |
16 |
try:
|
17 |
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
18 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont |
19 |
except ImportError: |
20 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
21 |
|
22 |
#from UserInputAttribute import UserInputAttribute
|
23 |
from OcrResultDialog import QOcrResultDialog |
24 |
from AppDocData import AppDocData |
25 |
from EngineeringTextItem import QEngineeringTextItem |
26 |
from TextInfo import TextInfo |
27 |
|
28 |
lineColumnList = ['UID', 'LINE_SIZE', 'LINE_SYMBOL', 'LINE_NO', 'LINE_CLASS', 'LINE_ROUTING_FROM', 'LINE_ROUTING_TO', |
29 |
'SERVICE_FLUID', 'SERVICE_DENSITY', 'SERVICE_STATE', 'OPERATION_CONDITION_TEMP', |
30 |
'OPERATION_CONDITION_PRESS', 'DESIGN_CONDITION_TEMP', 'DESIGN_CONDITION_PRESS', 'TEST_CONDITION_TEMP', |
31 |
'TEST_CONDITION_PRESS', 'INSUL_CODE', 'PAINT_CODE', 'NDE_CODE', 'PWHT', 'PNID_NO'] |
32 |
|
33 |
|
34 |
class QEngineeringLineNoTextItem(QEngineeringTextItem): |
35 |
'''
|
36 |
@history 18.05.14 Jeongwoo Add variable self.runs
|
37 |
humkyung 2018.07.09 add stream no
|
38 |
'''
|
39 |
|
40 |
def __init__(self, uid=None, parent=None): |
41 |
from SymbolAttr import SymbolProp |
42 |
from EngineeringFreezeItem import QEngineeringFreezeItem |
43 |
|
44 |
QEngineeringTextItem.__init__(self, uid, parent)
|
45 |
|
46 |
self._properties = { SymbolProp(None, 'From', 'Comp Item'): None, \ |
47 |
SymbolProp(None, 'To', 'Comp Item'): None, \ |
48 |
SymbolProp(None, 'Config', 'String'): None } # , SymbolProp(None, 'Freeze', 'Boolean'):False} |
49 |
self._runs = []
|
50 |
|
51 |
self.lineNoFromToIndicator = []
|
52 |
self.lineNoFromToIndicatorShowFlag = False |
53 |
|
54 |
""" create freeze control """
|
55 |
# self.freeze_item = QEngineeringFreezeItem(-QEngineeringFreezeItem.FREEZE_SIZE*0.5, -QEngineeringFreezeItem.FREEZE_SIZE*0.5, QEngineeringFreezeItem.FREEZE_SIZE, QEngineeringFreezeItem.FREEZE_SIZE)
|
56 |
# self.freeze_item.setParentItem(self)
|
57 |
# self.freeze_item.setZValue(self.zValue() + 1)
|
58 |
# self.freeze_item.setPen(Qt.black)
|
59 |
|
60 |
@property
|
61 |
def Size(self): |
62 |
""" return line no's size """
|
63 |
attrs = self.getAttributes()
|
64 |
matches = [value for attr, value in attrs.items() if attr.Attribute.upper() == 'NOMINALDIAMETER'] |
65 |
return matches[0] if matches else '' |
66 |
|
67 |
def empty(self): |
68 |
""" return True if run is empty else return False """
|
69 |
return False if self._runs else True |
70 |
|
71 |
#def setVisible(self, visible):
|
72 |
# """ override visible value """
|
73 |
# super(QEngineeringTextItem, self).setVisible(visible)
|
74 |
# for run in self.runs:
|
75 |
# run.visible = visible
|
76 |
|
77 |
@property
|
78 |
def connected_line(self): |
79 |
"""return connected line"""
|
80 |
if self.conns: |
81 |
if type(self.conns[0]) is str: |
82 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(self.conns[0])] |
83 |
if matches:
|
84 |
self.conns[0] = matches[0] |
85 |
|
86 |
return self.conns[0] |
87 |
|
88 |
return None |
89 |
|
90 |
'''
|
91 |
@brief getter of runs
|
92 |
@author humkyung
|
93 |
@date 2018.05.11
|
94 |
'''
|
95 |
|
96 |
@property
|
97 |
def runs(self): |
98 |
return self._runs |
99 |
|
100 |
'''
|
101 |
@brief setter of runs
|
102 |
@author humkyung
|
103 |
@date 2018.05.11
|
104 |
'''
|
105 |
|
106 |
@runs.setter
|
107 |
def runs(self, value): |
108 |
self._runs = value
|
109 |
|
110 |
def hoverEnterEvent(self, event): |
111 |
""" highlight line no text and run's item """
|
112 |
from App import App |
113 |
|
114 |
try:
|
115 |
self.hover = True |
116 |
self.update()
|
117 |
|
118 |
for run in self.runs: |
119 |
for item in run.items: |
120 |
item.hoverEnterEvent(event, True)
|
121 |
|
122 |
# display from / to indicator
|
123 |
if not self.lineNoFromToIndicatorShowFlag: |
124 |
if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2: |
125 |
if run is self.runs[0] and (item is run.items[0] or item is run.items[-1]): |
126 |
_label = EngineeringFromMarkItem(10, color=self._color) \ |
127 |
if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color) |
128 |
_label.setZValue(500)
|
129 |
self.scene().addItem(_label)
|
130 |
#_label.setParentItem(self)
|
131 |
_label.setPos(QPointF(item.origin[0], item.origin[1])) |
132 |
self.lineNoFromToIndicator.append(_label)
|
133 |
elif self.lineNoFromToIndicator: |
134 |
if run is self.runs[0] and (item is run.items[0]): |
135 |
self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1])) |
136 |
self.lineNoFromToIndicator[0].setVisible(True) |
137 |
elif run is self.runs[0] and (item is run.items[-1]): |
138 |
self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1])) |
139 |
self.lineNoFromToIndicator[1].setVisible(True) |
140 |
|
141 |
if not self.runs: |
142 |
_from = self.prop('From') |
143 |
_to = self.prop('To') |
144 |
if _from and _to: |
145 |
for item in [_from, _to]: |
146 |
# display from / to indicator
|
147 |
if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2: |
148 |
_label = EngineeringFromMarkItem(10, color=self._color) \ |
149 |
if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color) |
150 |
_label.setZValue(500)
|
151 |
self.scene().addItem(_label)
|
152 |
_label.setPos(QPointF(item.origin[0], item.origin[1])) |
153 |
self.lineNoFromToIndicator.append(_label)
|
154 |
elif self.lineNoFromToIndicator: |
155 |
if item is _from: |
156 |
self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1])) |
157 |
self.lineNoFromToIndicator[0].setVisible(True) |
158 |
elif item is _to: |
159 |
self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1])) |
160 |
self.lineNoFromToIndicator[1].setVisible(True) |
161 |
|
162 |
except Exception as ex: |
163 |
from App import App |
164 |
from AppDocData import MessageType |
165 |
|
166 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
167 |
sys.exc_info()[-1].tb_lineno)
|
168 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
169 |
|
170 |
def contextMenuEvent(self, event): |
171 |
items = self.scene().selectedItems()
|
172 |
menu = QMenu() |
173 |
if len(items) == 1 and self in items: |
174 |
'''
|
175 |
explodeAction = QAction('Explode', None)
|
176 |
explodeAction.triggered.connect(self.contextExplode)
|
177 |
menu.addAction(explodeAction)
|
178 |
|
179 |
explodeKeepAction = QAction('Explode(keep from, to)', None)
|
180 |
explodeKeepAction.triggered.connect(self.contextExplodeKeep)
|
181 |
menu.addAction(explodeKeepAction)
|
182 |
'''
|
183 |
|
184 |
explodeAction = QAction('Explode', None) |
185 |
explodeAction.triggered.connect(self.contextExplode)
|
186 |
menu.addAction(explodeAction) |
187 |
|
188 |
explodeKeepAction = QAction('Explode(keep from, to)', None) |
189 |
explodeKeepAction.triggered.connect(self.contextExplodeKeep)
|
190 |
menu.addAction(explodeKeepAction) |
191 |
|
192 |
fromAction = QAction('Set From(S)', None) |
193 |
fromAction.triggered.connect(self.contextFrom)
|
194 |
menu.addAction(fromAction) |
195 |
|
196 |
toAction = QAction('Set To(D)', None) |
197 |
toAction.triggered.connect(self.contextTo)
|
198 |
menu.addAction(toAction) |
199 |
|
200 |
showAction = QAction('Show From, To(H)', None) if not self.lineNoFromToIndicatorShowFlag else QAction('Hide From, To(H)', None) |
201 |
showAction.triggered.connect(self.contextShow)
|
202 |
menu.addAction(showAction) |
203 |
|
204 |
allAction = QAction('Select All in View(A)', None) |
205 |
allAction.triggered.connect(self.contextSelectAll)
|
206 |
menu.addAction(allAction) |
207 |
|
208 |
searchAction = QAction('Search All Duplicate Line No', None) |
209 |
searchAction.triggered.connect(self.contextSearch)
|
210 |
menu.addAction(searchAction) |
211 |
|
212 |
highlightAction = QAction('Highlight', None) |
213 |
highlightAction.triggered.connect(lambda: self.contextHighlight(self)) |
214 |
menu.addAction(highlightAction) |
215 |
|
216 |
actions = [] |
217 |
for index in range(len(self.runs)): |
218 |
actions.append(QAction('Highlight Run ' + str(index + 1), None)) |
219 |
|
220 |
binding = [lambda index=index: actions[index].triggered.connect(lambda: self.contextHighlight(self.runs[index])) for index in range(len(self.runs))] |
221 |
|
222 |
for index in range(len(actions)): |
223 |
binding[index]() |
224 |
menu.addAction(actions[index]) |
225 |
|
226 |
editAction = QAction('Edit(Return)', None) |
227 |
editAction.triggered.connect(self.contextEdit)
|
228 |
menu.addAction(editAction) |
229 |
|
230 |
rotateAction = QAction('Rotate(R)', None) |
231 |
rotateAction.triggered.connect(self.contextRotate)
|
232 |
menu.addAction(rotateAction) |
233 |
|
234 |
deleteAction = QAction('Delete(E)', None) |
235 |
deleteAction.triggered.connect(self.contextDelete)
|
236 |
menu.addAction(deleteAction) |
237 |
else:
|
238 |
alignAction = QAction('Resize Selected Texts with This ', None) |
239 |
alignAction.triggered.connect(self.contextResizeText)
|
240 |
menu.addAction(alignAction) |
241 |
|
242 |
menu.exec_(event.screenPos()) |
243 |
|
244 |
def contextResizeText(self): |
245 |
textItems = [item for item in self.scene().selectedItems() if item is not self and type(item) is QEngineeringLineNoTextItem] |
246 |
allowed_error = 0.01
|
247 |
|
248 |
for text in textItems: |
249 |
if abs(self.angle - text.angle) < allowed_error: |
250 |
dx = round(self.size[0] - text.size[0]) |
251 |
dy = round(self.size[1] - text.size[1]) |
252 |
else:
|
253 |
dx = round(self.size[1] - text.size[0]) |
254 |
dy = round(self.size[0] - text.size[1]) |
255 |
|
256 |
text.size[1] = text.size[1] + dy |
257 |
if abs(text.angle - 1.57) < allowed_error or abs(text.angle - 3.14) < allowed_error: |
258 |
text.loc[1] = text.loc[1] - dy |
259 |
|
260 |
text.size[0] = text.size[0] + dx |
261 |
if abs(text.angle - 4.71) < allowed_error or abs(text.angle - 4.71) < allowed_error or abs(text.angle - 3.14) < allowed_error: |
262 |
text.loc[0] = text.loc[0] - dx |
263 |
|
264 |
text.update_font() |
265 |
text.update() |
266 |
|
267 |
def contextSearch(self): |
268 |
from App import App |
269 |
from TextItemEditDialog import QTextItemEditDialog |
270 |
|
271 |
dlgTextItemEdit = QTextItemEditDialog(App.mainWnd(), 'Line No')
|
272 |
dlgTextItemEdit.show() |
273 |
dlgTextItemEdit.exec_() |
274 |
|
275 |
def contextSelectAll(self): |
276 |
from App import App |
277 |
|
278 |
rect = App.mainWnd().graphicsView.viewport().rect() |
279 |
view_rect = App.mainWnd().graphicsView.mapToScene(rect).boundingRect() |
280 |
lineNos = [item for item in self.scene().items() if type(item) is QEngineeringLineNoTextItem and view_rect.contains(item.sceneBoundingRect().center())] |
281 |
for lineNo in lineNos: |
282 |
lineNo.setSelected(True)
|
283 |
|
284 |
def contextShow(self): |
285 |
self.lineNoFromToIndicatorShowFlag = not self.lineNoFromToIndicatorShowFlag |
286 |
if self.lineNoFromToIndicatorShowFlag: |
287 |
if self.runs and self.runs[0].items: |
288 |
for item in [self.runs[0].items[0], self.runs[0].items[-1]]: |
289 |
# display from / to indicator
|
290 |
if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2: |
291 |
_label = EngineeringFromMarkItem(10, color=self._color) \ |
292 |
if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color) |
293 |
_label.setZValue(500)
|
294 |
self.scene().addItem(_label)
|
295 |
_label.setPos(QPointF(item.origin[0], item.origin[1])) |
296 |
self.lineNoFromToIndicator.append(_label)
|
297 |
elif self.lineNoFromToIndicator: |
298 |
if item is self.runs[0].items[0]: |
299 |
self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1])) |
300 |
self.lineNoFromToIndicator[0].setVisible(True) |
301 |
elif item is self.runs[0].items[-1]: |
302 |
self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1])) |
303 |
self.lineNoFromToIndicator[1].setVisible(True) |
304 |
elif not self.runs: |
305 |
_from = self.prop('From') |
306 |
_to = self.prop('To') |
307 |
if _from and _to: |
308 |
for item in [_from, _to]: |
309 |
# display from / to indicator
|
310 |
if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2: |
311 |
_label = EngineeringFromMarkItem(10, color=self._color) \ |
312 |
if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color) |
313 |
_label.setZValue(500)
|
314 |
self.scene().addItem(_label)
|
315 |
_label.setPos(QPointF(item.origin[0], item.origin[1])) |
316 |
self.lineNoFromToIndicator.append(_label)
|
317 |
elif self.lineNoFromToIndicator: |
318 |
if item is _from: |
319 |
self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1])) |
320 |
self.lineNoFromToIndicator[0].setVisible(True) |
321 |
elif item is _to: |
322 |
self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1])) |
323 |
self.lineNoFromToIndicator[1].setVisible(True) |
324 |
else:
|
325 |
if self.lineNoFromToIndicator: |
326 |
for _label in self.lineNoFromToIndicator: |
327 |
_label.setVisible(False)
|
328 |
|
329 |
def contextFrom(self): |
330 |
from App import App |
331 |
import SelectAttributeCommand |
332 |
_from = None
|
333 |
for prop, value in self.properties.items(): |
334 |
if prop.Attribute == 'From': |
335 |
_from = prop |
336 |
break
|
337 |
cmd = SelectAttributeCommand.SelectAttributeCommand(self, _from, App.mainWnd().graphicsView)
|
338 |
cmd.onSuccess.connect(App.mainWnd().resultPropertyTableWidget.onSuccessSelectAttribute) |
339 |
App.mainWnd().graphicsView.command = cmd |
340 |
|
341 |
def contextTo(self): |
342 |
from App import App |
343 |
import SelectAttributeCommand |
344 |
_to = None
|
345 |
for prop, value in self.properties.items(): |
346 |
if prop.Attribute == 'To': |
347 |
_to = prop |
348 |
break
|
349 |
cmd = SelectAttributeCommand.SelectAttributeCommand(self, _to, App.mainWnd().graphicsView)
|
350 |
cmd.onSuccess.connect(App.mainWnd().resultPropertyTableWidget.onSuccessSelectAttribute) |
351 |
App.mainWnd().graphicsView.command = cmd |
352 |
|
353 |
def contextHighlight(self, item): |
354 |
from App import App |
355 |
from HighlightCommand import HighlightCommand |
356 |
HighlightCommand(App.mainWnd().graphicsView).execute(item) |
357 |
|
358 |
def contextExplode(self): |
359 |
from App import App |
360 |
App.mainWnd().itemTreeWidget.explode_line_no_from_context(self)
|
361 |
|
362 |
def contextExplodeKeep(self): |
363 |
from App import App |
364 |
App.mainWnd().itemTreeWidget.explode_line_no_from_context(self, True) |
365 |
|
366 |
def contextReverse(self): |
367 |
self.reverse()
|
368 |
|
369 |
def contextDelete(self): |
370 |
event = QKeyEvent(QEvent.KeyPress, Qt.Key_Delete, Qt.NoModifier) |
371 |
self.scene().keyPressEvent(event)
|
372 |
|
373 |
def contextEdit(self): |
374 |
event = QKeyEvent(QEvent.KeyPress, Qt.Key_Return, Qt.NoModifier) |
375 |
self.keyPressEvent(event)
|
376 |
|
377 |
def contextRotate(self): |
378 |
event = QKeyEvent(QEvent.KeyPress, Qt.Key_R, Qt.NoModifier) |
379 |
self.keyPressEvent(event)
|
380 |
|
381 |
def hoverLeaveEvent(self, event): |
382 |
""" unhighlight line no text and run's item """
|
383 |
try:
|
384 |
self.hover = False |
385 |
self.update()
|
386 |
|
387 |
for run in self.runs: |
388 |
for item in run.items: |
389 |
item.hoverLeaveEvent(event, True)
|
390 |
|
391 |
if not self.lineNoFromToIndicatorShowFlag: |
392 |
if self.lineNoFromToIndicator: |
393 |
for _label in self.lineNoFromToIndicator: |
394 |
_label.setVisible(False)
|
395 |
except Exception as ex: |
396 |
from App import App |
397 |
from AppDocData import MessageType |
398 |
|
399 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
400 |
sys.exc_info()[-1].tb_lineno)
|
401 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
402 |
|
403 |
|
404 |
def keyPressEvent(self, event): |
405 |
""" reverse line routine when user press 'C' key """
|
406 |
if event.key() == Qt.Key_C:
|
407 |
self.reverse()
|
408 |
elif event.key() == Qt.Key_S:
|
409 |
self.contextFrom()
|
410 |
elif event.key() == Qt.Key_D:
|
411 |
self.contextTo()
|
412 |
elif event.key() == Qt.Key_H:
|
413 |
self.contextShow()
|
414 |
elif event.key() == Qt.Key_A:
|
415 |
self.contextSelectAll()
|
416 |
|
417 |
QEngineeringTextItem.keyPressEvent(self, event)
|
418 |
|
419 |
def update_flow_mark(self, position, minLength): |
420 |
""" update line flow mark """
|
421 |
import math |
422 |
from EngineeringLineItem import QEngineeringLineItem |
423 |
|
424 |
allowed_error_radian = 0.09
|
425 |
|
426 |
try:
|
427 |
for run in self.runs: |
428 |
pre = None
|
429 |
preRadian = None
|
430 |
for item in run.items: |
431 |
if pre is None and type(item) is QEngineeringLineItem and item.is_piping(True) and item.length() > minLength: |
432 |
pre = item |
433 |
start = item.line().p1() |
434 |
end = item.line().p2() |
435 |
_dir = [(end.x() - start.x()) / item.length(), (end.y() - start.y()) / item.length()] |
436 |
radian = math.atan2(_dir[1], _dir[0]) - math.pi / 2 |
437 |
preRadian = radian if radian >= 0 else radian + 2 * math.pi |
438 |
preRadian = abs(preRadian - math.pi)
|
439 |
|
440 |
elif pre and type(pre) is QEngineeringLineItem and type(item) is QEngineeringLineItem and item.is_piping(True): |
441 |
start = item.line().p1() |
442 |
end = item.line().p2() |
443 |
_dir = [(end.x() - start.x()) / item.length(), (end.y() - start.y()) / item.length()] |
444 |
radian = math.atan2(_dir[1], _dir[0]) - math.pi / 2 |
445 |
currRadian = radian if radian >= 0 else radian + 2 * math.pi |
446 |
currRadian = abs(currRadian - math.pi)
|
447 |
if abs(currRadian - preRadian) > allowed_error_radian: |
448 |
# insert flow mark at pre line
|
449 |
if pre.length() > minLength:
|
450 |
# if str(pre.uid) == '62edfbe5-29fd-49af-840b-6dce051e04d1':
|
451 |
# print(math.atan2(preDir[0], preDir[1]) - math.pi / 2)
|
452 |
# print(currRadian)
|
453 |
# print(preRadian)
|
454 |
pre.flowMark = position |
455 |
pre.update_arrow() |
456 |
|
457 |
pre = item |
458 |
preRadian = currRadian |
459 |
|
460 |
if pre and type(item) is QEngineeringLineItem and item.is_piping(True) and item.length() > minLength: |
461 |
pre.flowMark = position |
462 |
pre.update_arrow() |
463 |
|
464 |
except Exception as ex: |
465 |
from App import App |
466 |
from AppDocData import MessageType |
467 |
|
468 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
469 |
sys.exc_info()[-1].tb_lineno)
|
470 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
471 |
|
472 |
"""
|
473 |
def paint(self, painter, options=None, widget=None):
|
474 |
QEngineeringTextItem.paint(self, painter, options, widget)
|
475 |
if self.freeze_item is None:
|
476 |
from EngineeringFreezeItem import QEngineeringFreezeItem
|
477 |
|
478 |
self.freeze_item = QEngineeringFreezeItem(0, 0, QEngineeringFreezeItem.FREEZE_SIZE, QEngineeringFreezeItem.FREEZE_SIZE)
|
479 |
self.freeze_item.setParentItem(self)
|
480 |
self.freeze_item.setZValue(self.zValue() + 1)
|
481 |
self.freeze_item.setPen(Qt.black)
|
482 |
"""
|
483 |
|
484 |
def reverse(self): |
485 |
""" reverse line routine """
|
486 |
|
487 |
if self.runs: |
488 |
self.runs[0].reverse() |
489 |
_from = self.prop('From') |
490 |
_to = self.prop('To') |
491 |
self.set_property('From', _to) |
492 |
self.set_property('To', _from) |
493 |
|
494 |
def getLongestTwoPoints(self, pts): |
495 |
import math |
496 |
res = [None, None] |
497 |
|
498 |
maxDistance = None
|
499 |
for i in range(len(pts)): |
500 |
for j in range(i + 1, len(pts)): |
501 |
dx = pts[i][0] - pts[j][0] |
502 |
dy = pts[i][1] - pts[j][1] |
503 |
dist = math.sqrt(dx * dx + dy * dy) |
504 |
if (maxDistance is None) or (maxDistance < dist): |
505 |
maxDistance = dist |
506 |
res[0] = pts[i]
|
507 |
res[1] = pts[j]
|
508 |
|
509 |
return res
|
510 |
|
511 |
'''
|
512 |
@brief set attribute
|
513 |
@author humkyung
|
514 |
@date 2018.07.20
|
515 |
'''
|
516 |
|
517 |
def set_attrib(self, attrib, value): |
518 |
matches = [attr for attr in self.attrs if attr.UID == attrib.UID] |
519 |
if len(matches) == 1: |
520 |
self.attrs[matches[0]] = value |
521 |
else:
|
522 |
self.attrs[attrib] = value
|
523 |
|
524 |
def removeSelfAttr(self, attributeName): |
525 |
pass
|
526 |
|
527 |
'''
|
528 |
@brief get attribute
|
529 |
@author kyouho
|
530 |
@date 2018.09.06
|
531 |
'''
|
532 |
def getLineNoAttributes(self, _attrs=None): |
533 |
from SymbolAttr import SymbolAttr |
534 |
from Configs import LineNoConfig |
535 |
import csv |
536 |
|
537 |
if _attrs is None: |
538 |
_attrs = {} |
539 |
|
540 |
try:
|
541 |
docData = AppDocData.instance() |
542 |
|
543 |
line_no_configs = LineNoConfig.instance() |
544 |
config = None
|
545 |
if line_no_configs:
|
546 |
for line_no_config in line_no_configs: |
547 |
item = line_no_config.parse(self.text())
|
548 |
if item[0]: |
549 |
config = line_no_config |
550 |
break
|
551 |
else:
|
552 |
item = (False,)
|
553 |
|
554 |
if item[0]: |
555 |
# Line No 부분
|
556 |
attr = SymbolAttr() |
557 |
attr.Attribute = 'LINE NO'
|
558 |
attr.DisplayAttribute = 'Line No'
|
559 |
attr.AttributeType = 'String'
|
560 |
attr.IsProp = 5
|
561 |
attr.Index = -1
|
562 |
_attrs[attr] = self.text()
|
563 |
|
564 |
result = item[1]
|
565 |
configs = list(csv.reader([config.value], delimiter=self.delimiter, escapechar='^'))[0] |
566 |
props = docData.getLineProperties() |
567 |
for prop in props: |
568 |
if prop.UID in configs: |
569 |
for i in range(len(configs)): |
570 |
if prop.UID == configs[i]:
|
571 |
_attrs[prop] = result[i] |
572 |
break
|
573 |
else:
|
574 |
matches = [attr for attr in self.attrs if attr.UID == prop.UID] |
575 |
if len(matches) == 1: |
576 |
_attrs[matches[0]] = self.attrs[matches[0]] |
577 |
# else:
|
578 |
# _attrs[prop] = ''
|
579 |
except Exception as ex: |
580 |
from App import App |
581 |
from AppDocData import MessageType |
582 |
|
583 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
584 |
sys.exc_info()[-1].tb_lineno)
|
585 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
586 |
|
587 |
return _attrs
|
588 |
|
589 |
@staticmethod
|
590 |
def from_database(component): |
591 |
""" get line no item from database """
|
592 |
import uuid |
593 |
from AppDocData import AppDocData |
594 |
from TextItemFactory import TextItemFactory |
595 |
from SymbolAttr import SymbolAttr |
596 |
|
597 |
item = None
|
598 |
|
599 |
try:
|
600 |
x = float(component['X']) |
601 |
y = float(component['Y']) |
602 |
width = float(component['Width']) if component['Width'] is not None else 0 |
603 |
height = float(component['Height']) if component['Height'] is not None else 0 |
604 |
angle = float(component['Rotation']) if component['Rotation'] is not None else 0 |
605 |
text = component['Value']
|
606 |
|
607 |
configs = AppDocData.instance().getConfigs('Data', 'Grid') |
608 |
grid = int(configs[0].value) if 1 == len(configs) else -1 |
609 |
if grid == 1: |
610 |
x = round(x)
|
611 |
y = round(y)
|
612 |
width = round(width)
|
613 |
height = round(height)
|
614 |
|
615 |
textInfo = TextInfo(text, x, y, width, height, angle) |
616 |
connline = component['Connected'] if component['Connected'] is not None else None |
617 |
|
618 |
item = TextItemFactory.instance().createTextItem(textInfo) |
619 |
if item is not None: |
620 |
item.setVisible(False)
|
621 |
for key in item._properties.keys(): |
622 |
if key.Attribute != 'Config': |
623 |
item._properties[key] = key.parse_value(component[key.Attribute]) |
624 |
|
625 |
app_doc_data = AppDocData.instance() |
626 |
|
627 |
# get associations
|
628 |
associations = app_doc_data.get_component_associations(component['UID'])
|
629 |
if associations:
|
630 |
for assoc in associations: |
631 |
_attrType = assoc['Type']
|
632 |
if not _attrType in item._associations: |
633 |
item._associations[_attrType] = [] |
634 |
item._associations[_attrType].append( |
635 |
uuid.UUID(assoc['Association']) if assoc['Association'] != 'None' else None) |
636 |
# up to here
|
637 |
|
638 |
'''
|
639 |
# get associations
|
640 |
associations = app_doc_data.get_component_associations(component['UID'])
|
641 |
if associations:
|
642 |
for assoc in associations:
|
643 |
_attrType = assoc['Type']
|
644 |
if not _attrType in item._associations:
|
645 |
item._associations[_attrType] = []
|
646 |
item._associations[_attrType].append(
|
647 |
uuid.UUID(assoc['Association']) if assoc['Association'] != 'None' else None)
|
648 |
# up to here
|
649 |
'''
|
650 |
|
651 |
attrs = app_doc_data.get_component_attributes(component['UID'])
|
652 |
for _attr in attrs: |
653 |
attr = SymbolAttr.from_record(_attr) |
654 |
item.attrs[attr] = _attr['Value']
|
655 |
|
656 |
item.uid = uuid.UUID(component['UID'])
|
657 |
item.loc = [x, y] |
658 |
item.size = [width, height] |
659 |
item.angle = angle |
660 |
item.setToolTip('<b>{}</b><br>LINE NO={}'.format(str(item.uid), text)) |
661 |
|
662 |
""" apply freeze value """
|
663 |
# item.freeze_item.update_freeze(item.prop('Freeze'))
|
664 |
|
665 |
if connline is not None: |
666 |
item.conns.append(connline) |
667 |
except Exception as ex: |
668 |
from App import App |
669 |
from AppDocData import MessageType |
670 |
|
671 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
672 |
sys.exc_info()[-1].tb_lineno)
|
673 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
674 |
return None |
675 |
|
676 |
return item
|
677 |
|
678 |
@staticmethod
|
679 |
def fromXml(node): |
680 |
""" generate EngineeringLineNoTextItem from xml node """
|
681 |
import uuid |
682 |
from TextItemFactory import TextItemFactory |
683 |
from SymbolAttr import SymbolAttr |
684 |
|
685 |
item = None
|
686 |
|
687 |
try:
|
688 |
location = node.find('LOCATION').text if node.find('LOCATION') is not None else '0,0' |
689 |
x = float(location.split(',')[0]) |
690 |
y = float(location.split(',')[1]) |
691 |
width = float(node.find('WIDTH').text) if node.find('WIDTH') is not None else 0 |
692 |
height = float(node.find('HEIGHT').text) if node.find('HEIGHT') is not None else 0 |
693 |
angle = float(node.find('ANGLE').text) if node.find('ANGLE') is not None else 0 |
694 |
text = node.find('TEXT').text
|
695 |
|
696 |
configs = AppDocData.instance().getConfigs('Data', 'Grid') |
697 |
grid = int(configs[0].value) if 1 == len(configs) else -1 |
698 |
if grid == 1: |
699 |
x = round(x)
|
700 |
y = round(y)
|
701 |
width = round(width)
|
702 |
height = round(height)
|
703 |
|
704 |
textInfo = TextInfo(text, x, y, width, height, angle) |
705 |
connline = node.find('CONNLINE').text if node.find('CONNLINE') is not None else None |
706 |
|
707 |
configs = AppDocData.instance().getConfigs('Data', 'Grid') |
708 |
grid = int(configs[0].value) if 1 == len(configs) else -1 |
709 |
if grid == 1: |
710 |
x = round(x)
|
711 |
y = round(y)
|
712 |
width = round(width)
|
713 |
height = round(height)
|
714 |
|
715 |
matches = [prop_node for prop_node in node.iter('PROPERTY') if prop_node.attrib['Attribute'] == 'Config'] |
716 |
if matches:
|
717 |
item = TextItemFactory.instance().createTextItem(textInfo, matches[0].text)
|
718 |
else:
|
719 |
item = TextItemFactory.instance().createTextItem(textInfo) |
720 |
|
721 |
if item is not None: |
722 |
item.setVisible(False)
|
723 |
for prop_node in node.iter('PROPERTY'): |
724 |
matches = [prop for prop in item._properties.keys() if |
725 |
prop.Attribute == prop_node.attrib['Attribute'] and prop.Attribute != 'Config'] |
726 |
if matches:
|
727 |
item._properties[matches[0]] = matches[0].parse_value(prop_node.text) |
728 |
|
729 |
for attr_node in node.iterfind('ATTRIBUTE'): |
730 |
attr = SymbolAttr.fromXml(attr_node) |
731 |
item.attrs[attr] = attr_node.text |
732 |
|
733 |
item.uid = uuid.UUID(node.find('UID').text)
|
734 |
item.loc = [x, y] |
735 |
item.size = [width, height] |
736 |
item.angle = angle |
737 |
item.setToolTip('<b>{}</b><br>LINE NO={}'.format(str(item.uid), text)) |
738 |
|
739 |
# get associations
|
740 |
attributeValue = node.find('ASSOCIATIONS')
|
741 |
if attributeValue is not None: |
742 |
for assoc in attributeValue.iter('ASSOCIATION'): |
743 |
_attrType = assoc.attrib['TYPE']
|
744 |
if not _attrType in item._associations: |
745 |
item._associations[_attrType] = [] |
746 |
item._associations[_attrType].append(uuid.UUID(assoc.text) if assoc.text != 'None' else None) |
747 |
# up to here
|
748 |
|
749 |
""" apply freeze value """
|
750 |
# item.freeze_item.update_freeze(item.prop('Freeze'))
|
751 |
|
752 |
if connline is not None: |
753 |
item.conns.append(connline) |
754 |
except Exception as ex: |
755 |
from App import App |
756 |
from AppDocData import MessageType |
757 |
|
758 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
759 |
sys.exc_info()[-1].tb_lineno)
|
760 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
761 |
return None |
762 |
|
763 |
return item
|
764 |
|
765 |
'''
|
766 |
@brief generate xml code
|
767 |
@author humkyung
|
768 |
@date 2018.04.23
|
769 |
@history humkyung 2018.05.02 write symbol's attribute
|
770 |
humkyung 2018.05.16 write run information to xml
|
771 |
'''
|
772 |
|
773 |
def toXml(self): |
774 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree |
775 |
from EngineeringLineItem import QEngineeringLineItem |
776 |
from SymbolSvgItem import SymbolSvgItem |
777 |
|
778 |
try:
|
779 |
#docData = AppDocData.instance()
|
780 |
#configs = docData.getConfigs('Line No', 'Delimiter')
|
781 |
#delimiter = configs[0].value if 1 == len(configs) else '-'
|
782 |
#lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
|
783 |
|
784 |
node = Element('LINE_NO')
|
785 |
uidNode = Element('UID')
|
786 |
uidNode.text = str(self.uid) |
787 |
node.append(uidNode) |
788 |
|
789 |
textNode = Element('TEXT')
|
790 |
textNode.text = self.text()
|
791 |
node.append(textNode) |
792 |
|
793 |
locNode = Element('LOCATION')
|
794 |
locNode.text = '{},{}'.format(self.loc[0], self.loc[1]) |
795 |
node.append(locNode) |
796 |
|
797 |
widthNode = Element('WIDTH')
|
798 |
widthNode.text = str(self.size[0]) |
799 |
node.append(widthNode) |
800 |
|
801 |
heightNode = Element('HEIGHT')
|
802 |
heightNode.text = str(self.size[1]) |
803 |
node.append(heightNode) |
804 |
|
805 |
angleNode = Element('ANGLE')
|
806 |
angleNode.text = str(self.angle) |
807 |
node.append(angleNode) |
808 |
|
809 |
areaNode = Element('AREA')
|
810 |
areaNode.text = self.area
|
811 |
node.append(areaNode) |
812 |
|
813 |
for run in self.runs: |
814 |
if run and run.items: |
815 |
node.append(run.toXml()) |
816 |
|
817 |
attributeValueNode = Element('ASSOCIATIONS')
|
818 |
for key, value in self._associations.items(): |
819 |
for assoc in value: |
820 |
assoc_node = Element('ASSOCIATION')
|
821 |
assoc_node.attrib['TYPE'] = str(key) |
822 |
assoc_node.text = str(assoc)
|
823 |
attributeValueNode.append(assoc_node) |
824 |
node.append(attributeValueNode) |
825 |
|
826 |
properties_node = Element('PROPERTIES')
|
827 |
for prop, value in self.properties.items(): |
828 |
prop_node = prop.toXml() |
829 |
prop_node.text = str(value) if value else '' |
830 |
properties_node.append(prop_node) |
831 |
node.append(properties_node) |
832 |
|
833 |
_attrs = self.getAttributes()
|
834 |
for key in _attrs.keys(): |
835 |
if key.UID is not None: |
836 |
attrNode = key.toXml() |
837 |
attrNode.text = str(_attrs[key])
|
838 |
node.append(attrNode) |
839 |
|
840 |
if self.conns: |
841 |
connNode = Element('CONNLINE')
|
842 |
connNode.text = str(self.conns[0].uid) if hasattr(self.conns[0], 'uid') else str(self.conns[0]) |
843 |
node.append(connNode) |
844 |
|
845 |
sceneNode = Element('SCENE')
|
846 |
sceneNode.text = str(self.sceneBoundingRect()).replace('PyQt5.QtCore.QRectF(', '').replace(' ', '').replace( |
847 |
')', '') if self.scene() else '{},{},{},{}'.format(self.loc[0], self.loc[1], self.size[0], self.size[1]) |
848 |
node.append(sceneNode) |
849 |
|
850 |
except Exception as ex: |
851 |
from App import App |
852 |
from AppDocData import MessageType |
853 |
|
854 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
855 |
sys.exc_info()[-1].tb_lineno)
|
856 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
857 |
|
858 |
return None |
859 |
|
860 |
return node
|
861 |
|
862 |
def to_svg(self, parent) -> list: |
863 |
"""convert line no item to svg"""
|
864 |
import re |
865 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree |
866 |
from App import App |
867 |
|
868 |
res = [] |
869 |
try:
|
870 |
app_doc_data = AppDocData.instance() |
871 |
prj = app_doc_data.getCurrentProject() |
872 |
|
873 |
node = Element('g')
|
874 |
node.attrib['id'] = str(self.uid) |
875 |
node.attrib['class'] = 'Pipe' |
876 |
node.attrib['data-tag-name'] = self.toPlainText() |
877 |
node.attrib['font-family'] = self.font().family() |
878 |
node.attrib['font-size'] = str(self.boundingRect().height()) # str(self.font().pointSizeF()) |
879 |
node.attrib['font-weight'] = str(self.font().weight()) |
880 |
|
881 |
except_pattern = re.compile('[^a-zA-Z0-9-_]')
|
882 |
for attr, value in self.getAttributes().items(): |
883 |
node.attrib[re.sub(except_pattern, '_', attr.Attribute)] = value if value else '' |
884 |
trans = self.sceneTransform()
|
885 |
node.attrib['transform'] = f"matrix(" \ |
886 |
f"{trans.m11()},{trans.m12()}," \
|
887 |
f"{trans.m21()},{trans.m22()}," \
|
888 |
f"{trans.m31()},{trans.m32()}" \
|
889 |
f")"
|
890 |
|
891 |
text = Element('text')
|
892 |
text.text = self.toPlainText()
|
893 |
text.attrib['textLength'] = str(self.boundingRect().width()) |
894 |
text.attrib['lengthAdjust'] = 'spacingAndGlyphs' |
895 |
text.attrib['alignment-baseline'] = 'hanging' # align left-top corner |
896 |
node.append(text) |
897 |
|
898 |
connected_line = self.connected_line
|
899 |
if connected_line:
|
900 |
conn_node = connected_line.to_svg(self)
|
901 |
if conn_node:
|
902 |
node.extend(conn_node) |
903 |
|
904 |
res.append(node) |
905 |
except Exception as ex: |
906 |
from App import App |
907 |
from AppDocData import MessageType |
908 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
909 |
sys.exc_info()[-1].tb_lineno)
|
910 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
911 |
|
912 |
return res
|
913 |
|
914 |
def end_break(self): |
915 |
'''
|
916 |
@brief end break check
|
917 |
@author euisung
|
918 |
@date 2019.05.07
|
919 |
@history 2019.05.19 euisung can cover at both end that contact other line's middle
|
920 |
2019.05.19 euisung no more used integrated with linetracer
|
921 |
'''
|
922 |
from EngineeringLineItem import QEngineeringLineItem |
923 |
from SymbolSvgItem import SymbolSvgItem |
924 |
from AppDocData import AppDocData |
925 |
end_breaks = [] |
926 |
|
927 |
try:
|
928 |
docdata = AppDocData.instance() |
929 |
|
930 |
line_from = self.prop('From') |
931 |
line_to = self.prop('To') |
932 |
|
933 |
end_break_names = docdata.getSymbolListByType('type', 'End Break') |
934 |
if len(end_break_names) is 0: |
935 |
return end_breaks
|
936 |
|
937 |
svgFileName = end_break_names[0].sName
|
938 |
symbol = AppDocData.instance().getSymbolByQuery('name', svgFileName)
|
939 |
svgFilePath = os.path.join(AppDocData.instance().getCurrentProject().getSvgFilePath(), symbol.getType(), |
940 |
svgFileName + '.svg')
|
941 |
|
942 |
for line_end in [line_from, line_to]: |
943 |
for connector in line_end.connectors: |
944 |
if connector.connectedItem is not None and connector.connectedItem.owner is not self: |
945 |
end_break = SymbolSvgItem.createItem(symbol.getType(), None, svgFilePath)
|
946 |
pt = [connector.center()[0] - float(symbol.getOriginalPoint().split(',')[0]), |
947 |
connector.center()[1] - float(symbol.getOriginalPoint().split(',')[1])] |
948 |
origin = [0, 0] |
949 |
if 2 == len(symbol.getOriginalPoint().split(',')): |
950 |
tokens = symbol.getOriginalPoint().split(',')
|
951 |
origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])] |
952 |
end_break.buildItem(svgFileName, symbol.getType(), 5.7, pt,
|
953 |
[end_break.boundingRect().width(), end_break.boundingRect().height()], |
954 |
origin, [], symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), |
955 |
symbol.getHasInstrumentLabel()) |
956 |
|
957 |
end_break.set_property('Connected Item', connector.connectedItem)
|
958 |
end_break.setToolTip('owner : ' + str(line_end)) |
959 |
end_break.area = 'Drawing'
|
960 |
end_break.owner = line_end |
961 |
end_breaks.append(end_break) |
962 |
except Exception as ex: |
963 |
from App import App |
964 |
from AppDocData import MessageType |
965 |
|
966 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
967 |
sys.exc_info()[-1].tb_lineno)
|
968 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
969 |
|
970 |
return end_breaks
|
971 |
|
972 |
'''
|
973 |
@Override (QEngineeringTextItem)
|
974 |
@brief get connected items
|
975 |
@author Jeongwoo
|
976 |
@date 2018.05.15
|
977 |
'''
|
978 |
|
979 |
def getConnectedItems(self): |
980 |
visited = [] |
981 |
|
982 |
try:
|
983 |
for run in self.runs: |
984 |
visited.extend(run.items) |
985 |
except Exception as ex: |
986 |
from App import App |
987 |
from AppDocData import MessageType |
988 |
|
989 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
990 |
sys.exc_info()[-1].tb_lineno)
|
991 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
992 |
|
993 |
return visited
|
994 |
|
995 |
def explode(self, remainFromTo=False): |
996 |
""" explode line no """
|
997 |
|
998 |
# if False == self.prop('Freeze'):
|
999 |
try:
|
1000 |
for index in reversed(range(len(self.runs))): |
1001 |
self.runs[index].explode()
|
1002 |
except Exception as ex: |
1003 |
from App import App |
1004 |
from AppDocData import MessageType |
1005 |
|
1006 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1007 |
sys.exc_info()[-1].tb_lineno) + ' Item UID : ' + str(self.uid) |
1008 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
1009 |
finally:
|
1010 |
self.runs.clear()
|
1011 |
if not remainFromTo: |
1012 |
self.set_property('From', None) |
1013 |
self.set_property('To', None) |
1014 |
|
1015 |
if hasattr(self, 'lineNoFromToIndicator') and self.lineNoFromToIndicator: |
1016 |
self.lineNoFromToIndicatorShowFlag = False |
1017 |
if self.scene(): |
1018 |
self.lineNoFromToIndicator[0].setVisible(False) |
1019 |
if len(self.lineNoFromToIndicator) == 2: |
1020 |
self.lineNoFromToIndicator[1].setVisible(False) |
1021 |
|
1022 |
'''
|
1023 |
@brief generate sql phrase to save to database(Notice: Line No's symbol is is 1)
|
1024 |
@author humkyung
|
1025 |
@date 2018.08.14
|
1026 |
'''
|
1027 |
def toSql_return_separately(self): |
1028 |
import uuid |
1029 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
1030 |
|
1031 |
res = [] |
1032 |
resLater = [] |
1033 |
|
1034 |
app_doc_data = AppDocData.instance() |
1035 |
cols = ['UID', 'Drawings_UID', 'Symbol_UID', 'X', 'Y', 'Width', 'Height', 'Rotation', 'Value', 'Connected', |
1036 |
'[From]', '[To]'] |
1037 |
if type(self) is QEngineeringLineNoTextItem: |
1038 |
values = ['?', '?', "(select UID from Symbol where Name='Line NO' and SymbolType_UID=-1)", '?', '?', '?', |
1039 |
'?', '?', '?', '?', '?', '?'] |
1040 |
else:
|
1041 |
values = ['?', '?', "(select UID from Symbol where Name='Trim Line NO' and SymbolType_UID=-1)", '?', '?', |
1042 |
'?', '?', '?', '?', '?', '?', '?'] |
1043 |
_from = self.prop('From') |
1044 |
if not _from: |
1045 |
_from = ''
|
1046 |
_to = self.prop('To') |
1047 |
if not _to: |
1048 |
_to = ''
|
1049 |
params = [(str(self.uid), str(app_doc_data.activeDrawing.UID), self.loc[0], self.loc[1], self.size[0], |
1050 |
self.size[1], str(self.angle), \ |
1051 |
self.text(), str(self.conns[0]) if self.conns else None, str(_from), str(_to))] |
1052 |
sql = 'insert into Components({}) values({})'.format(','.join(cols), ','.join(values)) |
1053 |
res.append((sql, tuple(params)))
|
1054 |
|
1055 |
cols = ['UID', 'Components_UID', 'LineProperties_UID', 'Value'] |
1056 |
values = ['?', '?', '?', '?'] |
1057 |
params = [] |
1058 |
attrs = self.getAttributes()
|
1059 |
for key, value in attrs.items(): |
1060 |
if key.Attribute == 'LINE NO': # or key.IsProp != 5: |
1061 |
continue
|
1062 |
params.append((str(uuid.uuid4()), str(self.uid), str(key.UID), str(value))) |
1063 |
sql = 'insert into LineNoAttributes({}) values({})'.format(','.join(cols), ','.join(values)) |
1064 |
resLater.append((sql, tuple(params)))
|
1065 |
|
1066 |
if self.associations(): |
1067 |
cols = ['UID', '[Type]', 'Components_UID', 'Association'] |
1068 |
values = ['?', '?', '?', '?'] |
1069 |
params = [] |
1070 |
for assoc in self.associations(): |
1071 |
params.append( |
1072 |
(str(uuid.uuid4()), QEngineeringAbstractItem.assoc_type(assoc), str(self.uid), str(assoc.uid))) |
1073 |
sql = 'insert into Associations({}) values({})'.format(','.join(cols), ','.join(values)) |
1074 |
resLater.append((sql, tuple(params)))
|
1075 |
|
1076 |
# insert line no's Attributes
|
1077 |
cols = ['UID', 'Components_UID', 'SymbolAttribute_UID', 'Value', 'Association_UID', 'Freeze'] |
1078 |
values = ['?', '?', '?', '?', '?', '?'] |
1079 |
params = [] |
1080 |
for key in attrs.keys(): |
1081 |
if key.IsProp != 5: |
1082 |
params.append((str(uuid.uuid4()), str(self.uid), str(key.UID), str(attrs[key]), str(key.AssocItem), |
1083 |
str(key.Freeze)))
|
1084 |
sql = 'insert into Attributes({}) values({})'.format(','.join(cols), ','.join(values)) |
1085 |
res.append((sql, tuple(params)))
|
1086 |
|
1087 |
if self.associations(): |
1088 |
cols = ['UID', '[Type]', 'Components_UID', 'Association'] |
1089 |
values = ['?', '?', '?', '?'] |
1090 |
params = [] |
1091 |
for assoc in self.associations(): |
1092 |
params.append( |
1093 |
(str(uuid.uuid4()), QEngineeringAbstractItem.assoc_type(assoc), str(self.uid), str(assoc.uid))) |
1094 |
sql = 'insert into Associations({}) values({})'.format(','.join(cols), ','.join(values)) |
1095 |
resLater.append((sql, tuple(params)))
|
1096 |
|
1097 |
_index = 0
|
1098 |
for run in self.runs: |
1099 |
if run and run.items: |
1100 |
resLater.extend(run.to_sql(_index, self))
|
1101 |
_index += 1
|
1102 |
|
1103 |
return res, resLater
|
1104 |
|
1105 |
'''
|
1106 |
@brief return Line Data List
|
1107 |
@author kyouho
|
1108 |
@date 2018.08.14
|
1109 |
@ no more used
|
1110 |
'''
|
1111 |
def getLineDataList(self): |
1112 |
dataList = [] |
1113 |
'''
|
1114 |
try:
|
1115 |
import uuid
|
1116 |
global lineColumnList
|
1117 |
|
1118 |
docData = AppDocData.instance()
|
1119 |
attrs = self.getAttributes()
|
1120 |
for index in range(len(lineColumnList)):
|
1121 |
dataList.append('')
|
1122 |
|
1123 |
dataList[20] = docData.imgName
|
1124 |
|
1125 |
for key in attrs.keys():
|
1126 |
if type(key) is not UserInputAttribute:
|
1127 |
lineProp = docData.getLinePropertiesByUID(key.UID)
|
1128 |
if lineProp:
|
1129 |
attrName = lineProp[0].Attribute.upper().replace(' ', '')
|
1130 |
else:
|
1131 |
attrName = key.Attribute.upper().replace(' ', '')
|
1132 |
|
1133 |
data = attrs[key]
|
1134 |
if attrName == 'NOMINALDIAMETER':
|
1135 |
dataList[1] = data
|
1136 |
elif attrName == 'FLUIDCODE':
|
1137 |
dataList[2] = data
|
1138 |
dataList[7] = data
|
1139 |
elif attrName == 'TAGSEQNO':
|
1140 |
pass
|
1141 |
elif attrName == 'INSULATIONPURPOSE':
|
1142 |
dataList[16] = data
|
1143 |
elif attrName == 'STREAMNO':
|
1144 |
pass
|
1145 |
elif attrName == 'LINENO' or attrName == 'LINE NO':
|
1146 |
dataList[3] = data
|
1147 |
elif attrName == 'PNIDNUMBER':
|
1148 |
pass
|
1149 |
elif attrName == 'PIPINGMATERIALSCLASS':
|
1150 |
dataList[4] = data
|
1151 |
elif attrName == '':
|
1152 |
pass
|
1153 |
else:
|
1154 |
typeUID = key.Attribute
|
1155 |
value = key.text
|
1156 |
lineAttr = docData.getLinePropertiesByUID(key.UD)
|
1157 |
|
1158 |
for index in range(len(lineColumnList)):
|
1159 |
if lineColumnList[index] == lineAttr[0].Attribute:
|
1160 |
dataList[index] = value
|
1161 |
except Exception as ex:
|
1162 |
from App import App
|
1163 |
from AppDocData import MessageType
|
1164 |
|
1165 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
1166 |
sys.exc_info()[-1].tb_lineno)
|
1167 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
1168 |
|
1169 |
if dataList[0] == '':
|
1170 |
dataList[0] = str(uuid.uuid4())
|
1171 |
'''
|
1172 |
|
1173 |
return dataList
|
1174 |
|
1175 |
def EvaluatedEQ(self): |
1176 |
''' evaluate line no's From / To equipment '''
|
1177 |
|
1178 |
from EngineeringNozzleItem import QEngineeringNozzleItem |
1179 |
from EngineeringVendorItem import QEngineeringVendorItem |
1180 |
from EngineeringEquipmentItem import QEngineeringEquipmentItem |
1181 |
from EngineeringLineItem import QEngineeringLineItem |
1182 |
|
1183 |
pool = [] |
1184 |
visited = [] |
1185 |
if self.runs and self.runs[0]: |
1186 |
pool.append(self)
|
1187 |
_attrs = self.getAttributes()
|
1188 |
|
1189 |
from_found = False
|
1190 |
to_found = False
|
1191 |
|
1192 |
|
1193 |
try:
|
1194 |
while pool:
|
1195 |
lineNo = pool.pop() |
1196 |
if lineNo not in visited: |
1197 |
visited.append(lineNo) |
1198 |
else:
|
1199 |
continue
|
1200 |
|
1201 |
if lineNo.runs and lineNo.runs[0]: |
1202 |
items = lineNo.runs[0].items
|
1203 |
if len(items) > 2: |
1204 |
if type(items[0]) is QEngineeringNozzleItem and not from_found: |
1205 |
for connector in items[0].connectors: |
1206 |
# From
|
1207 |
if (type(connector.connectedItem) is QEngineeringVendorItem or type( |
1208 |
connector.connectedItem) is QEngineeringEquipmentItem) and \ |
1209 |
connector.connectedItem not in items: |
1210 |
for _attr in _attrs: |
1211 |
if _attr.Attribute == 'From_eq' and self.add_assoc_item(connector.connectedItem, |
1212 |
at=_attr.AttrAt): |
1213 |
_attr.AssocItem = connector.connectedItem |
1214 |
from_found = True
|
1215 |
break
|
1216 |
break
|
1217 |
elif not from_found: |
1218 |
if type(items[0]) is QEngineeringLineItem and items[0].connectors[0].connectedItem and items[0].connectors[0].connectedItem.owner: |
1219 |
pool.append(items[0].connectors[0].connectedItem.owner) |
1220 |
else:
|
1221 |
next_items = [connector.connectedItem for connector in items[0].connectors if connector.connectedItem and \ |
1222 |
connector.connectedItem is not items[1] and items[0].next_connected(items[1], connector.connectedItem)] |
1223 |
if next_items and next_items[0].owner: |
1224 |
pool.append(next_items[0].owner)
|
1225 |
|
1226 |
if type(items[-1]) is QEngineeringNozzleItem and not to_found: |
1227 |
for connector in items[-1].connectors: |
1228 |
# To
|
1229 |
if (type(connector.connectedItem) is QEngineeringVendorItem or type( |
1230 |
connector.connectedItem) is QEngineeringEquipmentItem) and \ |
1231 |
connector.connectedItem not in items: |
1232 |
for _attr in _attrs: |
1233 |
if _attr.Attribute == 'To_eq' and self.add_assoc_item(connector.connectedItem, |
1234 |
at=_attr.AttrAt): |
1235 |
_attr.AssocItem = connector.connectedItem |
1236 |
to_found = True
|
1237 |
break
|
1238 |
break
|
1239 |
elif not to_found: |
1240 |
if type(items[-1]) is QEngineeringLineItem and items[-1].connectors[1].connectedItem and items[-1].connectors[1].connectedItem.owner: |
1241 |
pool.append(items[-1].connectors[1].connectedItem.owner) |
1242 |
else:
|
1243 |
next_items = [connector.connectedItem for connector in items[-1].connectors if connector.connectedItem and \ |
1244 |
connector.connectedItem is not items[-2] and items[-1].next_connected(items[-2], connector.connectedItem)] |
1245 |
if next_items and next_items[0].owner: |
1246 |
pool.append(next_items[0].owner)
|
1247 |
except Exception as ex: |
1248 |
from App import App |
1249 |
from AppDocData import MessageType |
1250 |
|
1251 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1252 |
sys.exc_info()[-1].tb_lineno)
|
1253 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
1254 |
|
1255 |
def sort_order_text(self): |
1256 |
""" return true if line no same"""
|
1257 |
|
1258 |
app_doc_data = AppDocData.instance() |
1259 |
|
1260 |
configs = app_doc_data.getConfigs('Sort', 'LineNoKeys') |
1261 |
targets = configs[0].value.split(',') if configs else [] |
1262 |
|
1263 |
if targets:
|
1264 |
attrs = self.getAttributes(True) |
1265 |
matches = [] |
1266 |
|
1267 |
for key in targets: |
1268 |
_matches = [_key for _key in list(attrs.keys()) if str(_key.UID) == key] |
1269 |
if _matches:
|
1270 |
matches.append(attrs[_matches[0]])
|
1271 |
else:
|
1272 |
matches = [self.text()]
|
1273 |
|
1274 |
return '_'.join(matches) |
1275 |
|
1276 |
def validate(self): |
1277 |
""" validation check """
|
1278 |
|
1279 |
from SymbolSvgItem import SymbolSvgItem |
1280 |
from AppDocData import AppDocData |
1281 |
from EngineeringReducerItem import QEngineeringReducerItem |
1282 |
from EngineeringLineItem import QEngineeringLineItem |
1283 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
1284 |
|
1285 |
errors = [] |
1286 |
|
1287 |
try:
|
1288 |
_translate = QCoreApplication.translate |
1289 |
|
1290 |
docdata = AppDocData.instance() |
1291 |
dataPath = docdata.getErrorItemSvgPath() |
1292 |
|
1293 |
lineNoError = False
|
1294 |
|
1295 |
_error = super().validate()
|
1296 |
errors.extend(_error) |
1297 |
|
1298 |
_from = self.prop('From') |
1299 |
_to = self.prop('To') |
1300 |
|
1301 |
if not _from or not _to: |
1302 |
lineNoError = True
|
1303 |
elif self.runs: |
1304 |
if self.runs[0].items[0] is not _from: |
1305 |
lineNoError = True
|
1306 |
elif self.runs[0].items[-1] is not _to: |
1307 |
lineNoError = True
|
1308 |
else:
|
1309 |
return errors
|
1310 |
|
1311 |
size_errors = [] |
1312 |
branch_errors = [] |
1313 |
for run in self.runs: |
1314 |
sizes = [] |
1315 |
for item in run.items: |
1316 |
item_size = None
|
1317 |
attrs = item.getAttributes() |
1318 |
for prop, value in attrs.items(): |
1319 |
if prop.Attribute.upper() == 'Size'.upper() or prop.Attribute.upper() == 'NominalDiameter'.upper(): |
1320 |
if value and value != 'None': |
1321 |
item_size = value |
1322 |
if type(item) is QEngineeringReducerItem or (issubclass(type(item), SymbolSvgItem) and item.iType == 22): # Relief Valve |
1323 |
sizes.append([item, item.mainSubSize[0], item.mainSubSize[1]]) |
1324 |
break
|
1325 |
else:
|
1326 |
sizes.append([item, value, value]) |
1327 |
break
|
1328 |
|
1329 |
if item_size and type(item) is QEngineeringLineItem: |
1330 |
for conn in item.connectors: |
1331 |
if conn.connectedItem and type(conn.connectedItem) is QEngineeringLineItem and \ |
1332 |
conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_BODY: |
1333 |
_item_size = None
|
1334 |
attrs = conn.connectedItem.getAttributes() |
1335 |
for prop, value in attrs.items(): |
1336 |
if prop.Attribute.upper() == 'Size'.upper() or prop.Attribute.upper() == 'NominalDiameter'.upper(): |
1337 |
if value and value != 'None': |
1338 |
_item_size = value |
1339 |
break
|
1340 |
|
1341 |
if _item_size and self.inch_to_number(item_size) > self.inch_to_number(_item_size): |
1342 |
branch_errors.append(item) |
1343 |
branch_errors.append(conn.connectedItem) |
1344 |
|
1345 |
if len(sizes) > 1: |
1346 |
for index in range(len(sizes) - 1): |
1347 |
if sizes[index][2] != sizes[index + 1][1] and \ |
1348 |
type(sizes[index][0]) is not QEngineeringReducerItem and type(sizes[index + 1][0]) is not QEngineeringReducerItem \ |
1349 |
and (hasattr(sizes[index][0], 'iType') and sizes[index][0].iType != 22) and \ |
1350 |
(hasattr(sizes[index + 1][0], 'iType') and sizes[index + 1][0].iType != 22): |
1351 |
size_errors.append(sizes[index][0])
|
1352 |
size_errors.append(sizes[index + 1][0]) |
1353 |
elif sizes[index][1] not in sizes[index + 1] and sizes[index][2] not in sizes[index + 1]: |
1354 |
size_errors.append(sizes[index][0])
|
1355 |
size_errors.append(sizes[index + 1][0]) |
1356 |
|
1357 |
for size in size_errors: |
1358 |
error = SymbolSvgItem.createItem('Error', None, dataPath) |
1359 |
error.setPosition([size.sceneBoundingRect().center().x(), size.sceneBoundingRect().center().y()]) |
1360 |
error.parent = size |
1361 |
error.msg = _translate('Size change error', 'Size change error') |
1362 |
error.setToolTip(error.msg) |
1363 |
error.area = 'Drawing'
|
1364 |
error.name = 'Error'
|
1365 |
errors.append(error) |
1366 |
|
1367 |
for size in branch_errors: |
1368 |
error = SymbolSvgItem.createItem('Error', None, dataPath) |
1369 |
error.setPosition([size.sceneBoundingRect().center().x(), size.sceneBoundingRect().center().y()]) |
1370 |
error.parent = size |
1371 |
error.msg = _translate('Branch Size error', 'Branch Size error') |
1372 |
error.setToolTip(error.msg) |
1373 |
error.area = 'Drawing'
|
1374 |
error.name = 'Error'
|
1375 |
errors.append(error) |
1376 |
|
1377 |
if self.runs and self.runs[0].items: |
1378 |
_size = self.Size
|
1379 |
found = False
|
1380 |
if _size:
|
1381 |
for item in self.runs[0].items: |
1382 |
if type(item) is QEngineeringReducerItem or (issubclass(type(item), SymbolSvgItem) and item.iType == 22): |
1383 |
continue
|
1384 |
_size2 = item.EvaluatedSize |
1385 |
if _size2 and _size2 != 'None' and _size2 == _size: |
1386 |
found = True
|
1387 |
break
|
1388 |
|
1389 |
#attrs = item.getAttributes()
|
1390 |
#for prop, value in attrs.items():
|
1391 |
# if prop.Attribute.upper() == 'Size'.upper() or prop.Attribute.upper() == 'NominalDiameter'.upper():
|
1392 |
# if value and value != 'None' and _size != value:
|
1393 |
# found = True
|
1394 |
# break
|
1395 |
|
1396 |
if found:
|
1397 |
break
|
1398 |
|
1399 |
if not found: |
1400 |
error = SymbolSvgItem.createItem('Error', None, dataPath) |
1401 |
error.setPosition([self.sceneBoundingRect().center().x(), self.sceneBoundingRect().center().y()]) |
1402 |
error.parent = self
|
1403 |
error.msg = _translate('Main run size warning', 'Main run size warning') |
1404 |
error.setToolTip(error.msg) |
1405 |
error.area = 'Drawing'
|
1406 |
error.name = 'Warning'
|
1407 |
errors.append(error) |
1408 |
|
1409 |
if lineNoError:
|
1410 |
error = SymbolSvgItem.createItem('Error', None, dataPath) |
1411 |
error.setPosition([self.sceneBoundingRect().center().x(), self.sceneBoundingRect().center().y()]) |
1412 |
error.parent = self
|
1413 |
error.msg = _translate('From/ To error', 'From/ To error') |
1414 |
error.setToolTip(error.msg) |
1415 |
error.area = 'Drawing'
|
1416 |
error.name = 'Error'
|
1417 |
errors.append(error) |
1418 |
|
1419 |
except Exception as ex: |
1420 |
from App import App |
1421 |
from AppDocData import MessageType |
1422 |
|
1423 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1424 |
sys.exc_info()[-1].tb_lineno)
|
1425 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
1426 |
|
1427 |
return errors
|