개정판 24015dc6
Implementing issue #487: 속성 연계
DTI_PID/DTI_PID/Configuration_UI.py | ||
---|---|---|
42 | 42 |
self.spinBoxMaxArea = QtWidgets.QSpinBox(self.groupBox) |
43 | 43 |
self.spinBoxMaxArea.setObjectName("spinBoxMaxArea") |
44 | 44 |
self.horizontalLayout_6.addWidget(self.spinBoxMaxArea) |
45 |
self.gridLayout_5.addLayout(self.horizontalLayout_6, 0, 0, 1, 1)
|
|
45 |
self.gridLayout_5.addLayout(self.horizontalLayout_6, 2, 0, 1, 1)
|
|
46 | 46 |
self.horizontalLayout = QtWidgets.QHBoxLayout() |
47 | 47 |
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint) |
48 | 48 |
self.horizontalLayout.setObjectName("horizontalLayout") |
... | ... | |
56 | 56 |
self.spinBoxHeight = QtWidgets.QSpinBox(self.groupBox) |
57 | 57 |
self.spinBoxHeight.setObjectName("spinBoxHeight") |
58 | 58 |
self.horizontalLayout.addWidget(self.spinBoxHeight) |
59 |
self.gridLayout_5.addLayout(self.horizontalLayout, 1, 0, 1, 1)
|
|
60 |
self.gridLayout_2.addWidget(self.groupBox, 0, 1, 1, 1)
|
|
59 |
self.gridLayout_5.addLayout(self.horizontalLayout, 3, 0, 1, 1)
|
|
60 |
self.gridLayout_2.addWidget(self.groupBox, 1, 1, 1, 1)
|
|
61 | 61 |
self.groupBoxLineNo = QtWidgets.QGroupBox(self.Recognition) |
62 | 62 |
self.groupBoxLineNo.setObjectName("groupBoxLineNo") |
63 | 63 |
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBoxLineNo) |
... | ... | |
105 | 105 |
self.horizontalLayout_3.setObjectName("horizontalLayout_3") |
106 | 106 |
self.verticalLayout_2.addLayout(self.horizontalLayout_3) |
107 | 107 |
self.gridLayout_3.addLayout(self.verticalLayout_2, 6, 0, 1, 1) |
108 |
self.gridLayout_2.addWidget(self.groupBoxLineNo, 1, 1, 1, 1) |
|
108 |
self.gridLayout_2.addWidget(self.groupBoxLineNo, 2, 1, 1, 1) |
|
109 |
self.groupBoxAttribute = QtWidgets.QGroupBox(self.Recognition) |
|
110 |
self.groupBoxAttribute.setObjectName("groupBoxAttribute") |
|
111 |
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupBoxAttribute) |
|
112 |
self.gridLayout_6.setObjectName("gridLayout_6") |
|
113 |
self.verticalLayout_3 = QtWidgets.QVBoxLayout() |
|
114 |
self.verticalLayout_3.setObjectName("verticalLayout_3") |
|
115 |
self.horizontalLayout_8 = QtWidgets.QHBoxLayout() |
|
116 |
self.horizontalLayout_8.setObjectName("horizontalLayout_8") |
|
117 |
self.label_6 = QtWidgets.QLabel(self.groupBoxAttribute) |
|
118 |
self.label_6.setObjectName("label_6") |
|
119 |
self.horizontalLayout_8.addWidget(self.label_6, 0, QtCore.Qt.AlignVCenter) |
|
120 |
self.lineEditSizeDelimiter = QtWidgets.QLineEdit(self.groupBoxAttribute) |
|
121 |
self.lineEditSizeDelimiter.setObjectName("lineEditSizeDelimiter") |
|
122 |
self.horizontalLayout_8.addWidget(self.lineEditSizeDelimiter, 0, QtCore.Qt.AlignVCenter) |
|
123 |
self.verticalLayout_3.addLayout(self.horizontalLayout_8) |
|
124 |
self.gridLayout_6.addLayout(self.verticalLayout_3, 0, 0, 1, 1) |
|
125 |
self.gridLayout_2.addWidget(self.groupBoxAttribute, 0, 1, 1, 1) |
|
109 | 126 |
self.tabWidget.addTab(self.Recognition, "") |
110 | 127 |
self.tabNominalPipeSize = QtWidgets.QWidget() |
111 | 128 |
self.tabNominalPipeSize.setObjectName("tabNominalPipeSize") |
... | ... | |
147 | 164 |
self.radioButtonInch.setText(_translate("ConfigurationDialog", "Inch")) |
148 | 165 |
self.label_2.setText(_translate("ConfigurationDialog", "Delimiter : ")) |
149 | 166 |
self.pushButtonAddProperty.setText(_translate("ConfigurationDialog", "추가")) |
167 |
self.groupBoxAttribute.setTitle(_translate("ConfigurationDialog", "속성 검출")) |
|
168 |
self.label_6.setText(_translate("ConfigurationDialog", "Size Delimiter : ")) |
|
150 | 169 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Recognition), _translate("ConfigurationDialog", "인식")) |
151 | 170 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabNominalPipeSize), _translate("ConfigurationDialog", "Nominal Pipe Size")) |
152 | 171 |
DTI_PID/DTI_PID/LineNoTracer.py | ||
---|---|---|
73 | 73 |
obj = pool.pop() |
74 | 74 |
if type(obj) is QEngineeringLineItem: |
75 | 75 |
matches = [x for x in self.symbols if len(obj.connectIfPossible(x, toler)) > 0] |
76 |
elif type(obj) is SymbolSvgItem:
|
|
76 |
elif issubclass(type(obj), SymbolSvgItem):
|
|
77 | 77 |
matches = [x for x in self.lines if len(obj.connectIfPossible(x, toler)) > 0] |
78 | 78 | |
79 | 79 |
for match in matches: pool.append(match) |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
28 | 28 |
from QEngineeringTextItem import QEngineeringTextItem |
29 | 29 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
30 | 30 |
from QEngineeringNoteItem import QEngineeringNoteItem |
31 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
|
31 | 32 |
from AppDocData import AppDocData |
32 | 33 |
import QDirTreeWidget, QPropertyTableWidget |
33 | 34 |
import QSymbolEditorDialog |
... | ... | |
399 | 400 | |
400 | 401 |
symbols = [] |
401 | 402 |
for item in self.graphicsView.scene.items(): |
402 |
if (type(item) is SymbolSvgItem):
|
|
403 |
if issubclass(type(item), SymbolSvgItem):
|
|
403 | 404 |
symbols.append(item) |
404 | 405 |
res = detector.detectConnectedLine(item, round(area.x), round(area.y)) |
405 | 406 |
if res is not None: |
406 | 407 |
for line in res: connectedLines.append(line) |
407 | 408 | |
408 |
lineNos = [] |
|
409 |
for item in self.graphicsView.scene.items(): |
|
410 |
if (type(item) is QEngineeringLineNoTextItem): lineNos.append(item) |
|
409 |
texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)] |
|
410 |
for symbol in symbols: |
|
411 |
symbol.connectAttribute(texts) |
|
412 | ||
413 |
lineNos = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineNoTextItem] |
|
411 | 414 | |
412 | 415 |
if len(connectedLines) > 1: |
413 | 416 |
detector.mergeLines(connectedLines, toler=20) |
... | ... | |
452 | 455 |
item = self.resultTreeWidget.addTreeItem(self.resultTreeWidget.root, text) |
453 | 456 |
connectedItems = text.getConnectedItems() |
454 | 457 |
for connectedItem in connectedItems: |
455 |
if type(connectedItem) is SymbolSvgItem: self.resultTreeWidget.addTreeItem(item, connectedItem)
|
|
458 |
if issubclass(type(connectedItem), SymbolSvgItem): self.resultTreeWidget.addTreeItem(item, connectedItem)
|
|
456 | 459 |
# up to here |
457 | 460 |
except Exception as ex: |
458 | 461 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
... | ... | |
487 | 490 |
if symbol.find('CONNECTIONPOINT').text is not None: |
488 | 491 |
connPts = [(float(x.split(',')[0]), float(x.split(',')[1])) for x in symbol.find('CONNECTIONPOINT').text.split('/')] |
489 | 492 |
|
490 |
svgFilePath = project.getSvgFilePath() + '/' + type + '/' + name + '.svg'
|
|
493 |
svgFilePath = os.path.join(project.getSvgFilePath(), type, name + '.svg')
|
|
491 | 494 |
if os.path.isfile(svgFilePath): |
492 |
svg = SymbolSvgItem(svgFilePath)
|
|
495 |
svg = SymbolSvgItem.createItem(type, svgFilePath)
|
|
493 | 496 |
svg.buildItem(name, type, angle, pt, size, origin, connPts) |
494 | 497 | |
495 | 498 |
#### lambda param=svg : bind 'svg' object to lambda('param') |
DTI_PID/DTI_PID/QConfigurationDialog.py | ||
---|---|---|
52 | 52 |
self.itemModel = QStandardItemModel() |
53 | 53 | |
54 | 54 |
docData = AppDocData.instance() |
55 |
configs = docData.getConfigs('Size', 'Delimiter') |
|
56 |
self.ui.lineEditSizeDelimiter.setText(configs[0].value if 1 == len(configs) else 'X') |
|
57 | ||
55 | 58 |
# set min,max area for small object |
56 | 59 |
configs = docData.getConfigs('Small Object Size', 'Min Area') |
57 | 60 |
self.ui.spinBoxMinArea.setValue(int(configs[0].value)) if 1 == len(configs) else self.ui.spinBoxMinArea.setValue(20) |
... | ... | |
117 | 120 |
@date 2018.??.?? |
118 | 121 |
@history humkyung 2018.04.24 save size unit of line no |
119 | 122 |
humkyung 2018.04.26 save min,max area for small object |
123 |
humkyung 2018.05.02 save size delimiter |
|
120 | 124 |
''' |
121 | 125 |
def accept(self): |
122 | 126 |
try: |
123 | 127 |
self.isAccepted = True |
124 | 128 | |
125 | 129 |
configs = [] |
130 |
configs.append(Config('Size', 'Delimiter', self.ui.lineEditSizeDelimiter.text())) |
|
126 | 131 |
configs.append(Config('Small Object Size', 'Min Area', self.ui.spinBoxMinArea.value())) |
127 | 132 |
configs.append(Config('Small Object Size', 'Max Area', self.ui.spinBoxMaxArea.value())) |
128 | 133 |
configs.append(Config('Sliding Window', 'Width', self.ui.spinBoxWidth.value())) |
DTI_PID/DTI_PID/QResultTreeWidget.py | ||
---|---|---|
54 | 54 |
def addTreeItem(self, parent, child): |
55 | 55 |
item = None |
56 | 56 |
if (not hasattr(child, 'treeItem')) or (child.treeItem is None): |
57 |
if type(child) is SymbolSvgItem:
|
|
57 |
if issubclass(type(child), SymbolSvgItem):
|
|
58 | 58 |
symbolsRootItem = self.findItems('SYMBOLS', Qt.MatchExactly|Qt.MatchRecursive, 0) |
59 | 59 |
symbolsRootItem = symbolsRootItem[0] |
60 | 60 |
item = QTreeWidgetItem(symbolsRootItem, [child.name]) |
... | ... | |
76 | 76 |
child.treeItem = item |
77 | 77 |
if parent is not None: |
78 | 78 |
parent.addChild(item) |
79 |
elif type(child) is SymbolSvgItem: # change item's parent
|
|
79 |
elif issubclass(type(child), SymbolSvgItem): # change item's parent
|
|
80 | 80 |
foundItems = self.findItems(child.name, Qt.MatchExactly|Qt.MatchRecursive, 0) |
81 | 81 |
if foundItems is not None: |
82 | 82 |
for item in foundItems: |
... | ... | |
104 | 104 |
''' |
105 | 105 |
lastSceneItems = None |
106 | 106 |
def sceneChanged(self, sceneItems): |
107 |
changedSceneItems = [item for item in sceneItems if ((type(item) is SymbolSvgItem) or (type(item) is QEngineeringNoteItem) or (type(item) is QEngineeringLineNoTextItem))
|
|
107 |
changedSceneItems = [item for item in sceneItems if ((issubclass(type(item), SymbolSvgItem)) or (type(item) is QEngineeringNoteItem) or (type(item) is QEngineeringLineNoTextItem))
|
|
108 | 108 |
and (not hasattr(item, 'treeItem') or item.treeItem is None)] # Sublist includes SymbolSvgItem |
109 | 109 |
self.initResultTreeWidget(changedSceneItems) |
110 | 110 |
|
... | ... | |
154 | 154 |
self.scene.removeItem(self.lastClickedItem) |
155 | 155 | |
156 | 156 |
if itemData is not None: ## Not PID Name |
157 |
if type(itemData) is SymbolSvgItem:
|
|
157 |
if issubclass(type(itemData), SymbolSvgItem):
|
|
158 | 158 |
## Draw rectangle on selected symbol |
159 | 159 |
rect = itemData.sceneBoundingRect() |
160 | 160 |
graphicItem = self.scene.addRect(rect.left(), rect.top(), rect.width(), rect.height(), QPen(QColor(255,255,0,100)), QBrush(QColor(255,255,0,100))) |
... | ... | |
193 | 193 |
@date 2018.04.23 |
194 | 194 |
''' |
195 | 195 |
def findItemByData(self, item): |
196 |
if type(item) is SymbolSvgItem:
|
|
196 |
if issubclass(type(item), SymbolSvgItem):
|
|
197 | 197 |
foundItems = self.findItems(item.name, Qt.MatchExactly|Qt.MatchRecursive, 0) |
198 | 198 |
for foundItem in foundItems: |
199 | 199 |
data = foundItem.data(0, self.TREE_DATA_ROLE) |
... | ... | |
217 | 217 |
''' |
218 | 218 |
@pyqtSlot(SymbolSvgItem) |
219 | 219 |
def findItem(self, item): |
220 |
if type(item) is SymbolSvgItem:
|
|
220 |
if issubclass(type(item), SymbolSvgItem):
|
|
221 | 221 |
foundItems = self.findItems(item.name, Qt.MatchExactly|Qt.MatchRecursive, 0) |
222 | 222 |
if foundItems is not None: |
223 | 223 |
for fItem in foundItems: |
... | ... | |
227 | 227 |
self.itemClickEvent(fItem, 0, True) |
228 | 228 |
return |
229 | 229 |
## Not found |
230 |
QMessageBox.about(self.ui.buttonBox, "알림", "선택하신 심볼의 데이터를 찾을 수 없습니다.") |
|
230 |
msg = QMessageBox() |
|
231 |
msg.setIcon(QMessageBox.Warning) |
|
232 |
msg.setText('선택하신 심볼의 데이터를 찾을 수 없습니다.') |
|
231 | 233 |
|
232 | 234 |
''' |
233 | 235 |
@brief remove given item |
DTI_PID/DTI_PID/QtImageViewer.py | ||
---|---|---|
405 | 405 |
svgFileName = event.mimeData().text() |
406 | 406 |
symbol = AppDocData.instance().getSymbolByQuery('name', svgFileName) |
407 | 407 |
svgFilePath = os.path.join(AppDocData.instance().getCurrentProject().getSvgFilePath(), symbol.getType(), svgFileName+'.svg') |
408 |
svg = SymbolSvgItem(svgFilePath)
|
|
408 |
svg = SymbolSvgItem.createItem(symbol.getType(), svgFilePath)
|
|
409 | 409 |
connPts = None |
410 | 410 |
strConnPts = symbol.getConnectionPoint() |
411 | 411 |
if strConnPts is not None: |
DTI_PID/DTI_PID/Shapes/QEngineeringLineNoTextItem.py | ||
---|---|---|
45 | 45 |
return res |
46 | 46 |
|
47 | 47 |
''' |
48 |
@brief generate xml code |
|
49 |
@author humkyung |
|
50 |
@date 2018.04.23 |
|
48 |
@brief generate xml code |
|
49 |
@author humkyung |
|
50 |
@date 2018.04.23 |
|
51 |
@history humkyung 2018.05.02 write symbol's attribute |
|
51 | 52 |
''' |
52 | 53 |
def toXml(self): |
53 | 54 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree |
... | ... | |
114 | 115 |
#for item in connectedLines: |
115 | 116 |
# node.append(item.toXml()) |
116 | 117 | |
117 |
connectedSymbols = [item for item in connectedItems if type(item) is SymbolSvgItem]
|
|
118 |
connectedSymbols = [item for item in connectedItems if issubclass(type(item), SymbolSvgItem)]
|
|
118 | 119 |
for item in connectedSymbols: |
119 | 120 |
node.append(item.toXml()) |
120 | 121 | |
... | ... | |
135 | 136 |
attrNode.append(valueNode) |
136 | 137 | |
137 | 138 |
node.append(attrNode) |
139 | ||
140 |
for item in connectedSymbols: |
|
141 |
item.toXmlAsAttribute(node) |
|
138 | 142 |
except Exception as ex: |
139 | 143 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
140 | 144 |
DTI_PID/DTI_PID/Shapes/QEngineeringOPCItem.py | ||
---|---|---|
1 |
#!/usr/bin/env/python3 |
|
2 |
# coding: utf-8 |
|
3 | ||
4 |
import sys |
|
5 |
import os |
|
6 |
import math |
|
7 |
from PyQt5.QtGui import * |
|
8 |
from PyQt5.QtCore import * |
|
9 |
from PyQt5.QtSvg import * |
|
10 |
from PyQt5.QtWidgets import (QApplication, QGraphicsItem) |
|
11 | ||
12 |
from SymbolSvgItem import SymbolSvgItem |
|
13 |
from QConnectorItem import QConnectorItem |
|
14 | ||
15 |
class QEngineeringOPCItem(SymbolSvgItem): |
|
16 |
clicked = pyqtSignal(QGraphicsSvgItem) |
|
17 |
removed = pyqtSignal(QGraphicsItem) |
|
18 | ||
19 |
''' |
|
20 |
''' |
|
21 |
def __init__(self, path): |
|
22 |
import uuid |
|
23 | ||
24 |
SymbolSvgItem.__init__(self, path) |
|
25 | ||
26 |
''' |
|
27 |
@brief connect attribute |
|
28 |
@author humkyung |
|
29 |
@date 2018.05.02 |
|
30 |
''' |
|
31 |
def connectAttribute(self, attributes): |
|
32 |
self.attrs.clear() |
|
33 | ||
34 |
rect = self.sceneBoundingRect() |
|
35 |
for attr in attributes: |
|
36 |
if rect.contains(attr.center()): |
|
37 |
self.attrs.append(attr) |
|
38 | ||
39 |
''' |
|
40 |
@brief generate xml code for attribute |
|
41 |
@author humkyung |
|
42 |
@date 2018.05.02 |
|
43 |
''' |
|
44 |
def toXmlAsAttribute(self, parent): |
|
45 |
for attr in self.attrs: |
|
46 |
text = attr.text() |
|
47 |
if QRegExpValidator(QRegExp("^[0-9]+$")).validate(text, 0)[0] != QValidator.Invalid: |
|
48 |
parent.append(attr.toXml(self, 'OPC Tag')) |
|
49 |
else: |
|
50 |
parent.append(attr.toXml(self, 'Description')) |
DTI_PID/DTI_PID/Shapes/QEngineeringSizeTextItem.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
import os.path |
|
3 |
import sys |
|
4 |
import copy |
|
5 |
try: |
|
6 |
from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
|
7 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QTransform, QFont |
|
8 |
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, QGraphicsTextItem |
|
9 |
except ImportError: |
|
10 |
try: |
|
11 |
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
|
12 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont |
|
13 |
except ImportError: |
|
14 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
|
15 | ||
16 |
from QGraphicsPolylineItem import QGraphicsPolylineItem |
|
17 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
|
18 |
import QOcrResultDialog |
|
19 |
from AppDocData import AppDocData |
|
20 |
from QEngineeringTextItem import QEngineeringTextItem |
|
21 | ||
22 |
class QEngineeringSizeTextItem(QEngineeringTextItem): |
|
23 |
#removed = pyqtSignal(QGraphicsItem) |
|
24 | ||
25 |
def __init__(self, parent=None): |
|
26 |
import uuid |
|
27 | ||
28 |
QEngineeringTextItem.__init__(self, parent) |
|
29 | ||
30 |
''' |
|
31 |
@brief generate xml code |
|
32 |
@author humkyung |
|
33 |
@date 2018.05.02 |
|
34 |
''' |
|
35 |
def toXml(self, owner, name='SIZE'): |
|
36 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree |
|
37 |
from QEngineeringLineItem import QEngineeringLineItem |
|
38 |
from SymbolSvgItem import SymbolSvgItem |
|
39 | ||
40 |
try: |
|
41 |
node = Element('ATTRIBUTE') |
|
42 |
uidNode = Element('UID') |
|
43 |
uidNode.text = str(owner.uid) |
|
44 |
node.append(uidNode) |
|
45 | ||
46 |
textNode = Element('NAME') |
|
47 |
textNode.text = 'SIZE' |
|
48 |
node.append(textNode) |
|
49 | ||
50 |
valueNode = Element('VALUE') |
|
51 |
valueNode.text = self.text() |
|
52 |
node.append(valueNode) |
|
53 | ||
54 |
angleNode = Element('ANGLE') |
|
55 |
angleNode.text = str(self.angle) |
|
56 |
node.append(angleNode) |
|
57 | ||
58 |
rect = self.sceneBoundingRect() |
|
59 |
widthNode = Element('WIDTH') |
|
60 |
widthNode.text = str(rect.width()) |
|
61 |
node.append(widthNode) |
|
62 | ||
63 |
heightNode = Element('HEIGHT') |
|
64 |
heightNode.text = str(rect.height()) |
|
65 |
node.append(heightNode) |
|
66 |
except Exception as ex: |
|
67 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
68 | ||
69 |
return node |
|
70 | ||
71 |
def hoverEnterEvent(self, event): |
|
72 |
pass |
|
73 | ||
74 |
def hoverLeaveEvent(self, event): |
|
75 |
pass |
|
76 | ||
77 |
def hoverMoveEvent(self, event): |
|
78 |
pass |
DTI_PID/DTI_PID/Shapes/QEngineeringTextItem.py | ||
---|---|---|
1 | 1 |
# coding: utf-8 |
2 | 2 |
import os.path |
3 | 3 |
import copy |
4 |
import sys |
|
4 | 5 |
try: |
5 | 6 |
from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
6 | 7 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QTransform, QFont |
... | ... | |
239 | 240 |
@author humkyung |
240 | 241 |
@date 2018.04.23 |
241 | 242 |
@history humkyung 2018.04.27 move to QEngineeringLineNoTextItem |
243 |
humkyung 2018.05.02 add name as parameter |
|
242 | 244 |
''' |
243 |
def toXml(self): |
|
244 |
pass |
|
245 |
def toXml(self, owner, name='TEXT'): |
|
246 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree |
|
247 |
from QEngineeringLineItem import QEngineeringLineItem |
|
248 |
from SymbolSvgItem import SymbolSvgItem |
|
249 | ||
250 |
try: |
|
251 |
node = Element('ATTRIBUTE') |
|
252 |
uidNode = Element('UID') |
|
253 |
uidNode.text = str(owner.uid) |
|
254 |
node.append(uidNode) |
|
255 | ||
256 |
nameNode = Element('NAME') |
|
257 |
nameNode.text = name |
|
258 |
node.append(nameNode) |
|
259 | ||
260 |
valueNode = Element('VALUE') |
|
261 |
valueNode.text = self.text() |
|
262 |
node.append(valueNode) |
|
263 | ||
264 |
angleNode = Element('ANGLE') |
|
265 |
angleNode.text = str(self.angle) |
|
266 |
node.append(angleNode) |
|
267 | ||
268 |
rect = self.sceneBoundingRect() |
|
269 |
widthNode = Element('WIDTH') |
|
270 |
widthNode.text = str(rect.width()) |
|
271 |
node.append(widthNode) |
|
272 | ||
273 |
heightNode = Element('HEIGHT') |
|
274 |
heightNode.text = str(rect.height()) |
|
275 |
node.append(heightNode) |
|
276 |
except Exception as ex: |
|
277 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
278 | ||
279 |
return node |
DTI_PID/DTI_PID/Shapes/SymbolSvgItem.py | ||
---|---|---|
35 | 35 |
self.size = None |
36 | 36 |
self.conns = [] |
37 | 37 |
self.connectors = [] |
38 |
self.attrs = [] # attributes |
|
38 | 39 | |
39 | 40 |
self.setAcceptHoverEvents(True) |
40 | 41 |
self.setAcceptedMouseButtons(Qt.LeftButton) |
... | ... | |
133 | 134 |
def center(self): |
134 | 135 |
return self.sceneBoundingRect().center() |
135 | 136 |
|
137 |
''' |
|
138 |
@brief highlight connector and attribute |
|
139 |
@authro humkyung |
|
140 |
@date 2018.05.02 |
|
141 |
''' |
|
136 | 142 |
def hoverEnterEvent(self, event): |
137 | 143 |
cursor = QCursor(Qt.OpenHandCursor) |
138 | 144 |
QApplication.instance().setOverrideCursor(cursor) |
... | ... | |
142 | 148 |
connector.setVisible(True) |
143 | 149 |
connector.update() |
144 | 150 | |
151 |
for attr in self.attrs: |
|
152 |
attr.setDefaultTextColor(Qt.red) |
|
153 |
attr.update() |
|
154 | ||
155 |
''' |
|
156 |
@brief unhighlight connector and attribute |
|
157 |
@author humkyung |
|
158 |
@date 2018.05.02 |
|
159 |
''' |
|
145 | 160 |
def hoverLeaveEvent(self, event): |
146 | 161 |
QApplication.instance().restoreOverrideCursor() |
147 | 162 |
self.update() |
... | ... | |
150 | 165 |
connector.setVisible(False) |
151 | 166 |
connector.update() |
152 | 167 | |
168 |
for attr in self.attrs: |
|
169 |
attr.setDefaultTextColor(Qt.blue) |
|
170 |
attr.update() |
|
171 | ||
153 | 172 |
''' |
154 | 173 |
@brief change cursor to CrossCursor if mouse point is close to connection point |
155 | 174 |
@author humkyung |
... | ... | |
192 | 211 |
self.scene().removeItem(self) |
193 | 212 | |
194 | 213 |
''' |
214 |
@brief connect attribute |
|
215 |
@author humkyung |
|
216 |
@date 2018.05.02 |
|
217 |
''' |
|
218 |
def connectAttribute(self, attributes): |
|
219 |
import math |
|
220 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
|
221 | ||
222 |
self.attrs.clear() |
|
223 | ||
224 |
dist = max(self.sceneBoundingRect().height(), self.sceneBoundingRect().width()) |
|
225 |
center = self.sceneBoundingRect().center() |
|
226 |
for attr in attributes: |
|
227 |
if type(attr) is QEngineeringSizeTextItem: |
|
228 |
dx = attr.center().x() - center.x() |
|
229 |
dy = attr.center().y() - center.y() |
|
230 |
if math.sqrt(dx*dx + dy*dy) < dist*2: |
|
231 |
self.attrs.append(attr) |
|
232 | ||
233 |
''' |
|
195 | 234 |
@brief generate xml code |
196 | 235 |
@author humkyung |
197 | 236 |
@date 2018.04.23 |
198 | 237 |
@history humkyung 2018.04.25 add angle xml node |
199 | 238 |
humkyung 2018.04.27 add originalpoint xml node |
239 |
humkyung 2018.05.02 add attribute of symbol |
|
200 | 240 |
''' |
201 | 241 |
def toXml(self): |
202 | 242 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree |
... | ... | |
233 | 273 |
return node |
234 | 274 | |
235 | 275 |
''' |
276 |
@brief generate xml code for attribute |
|
277 |
@author humkyung |
|
278 |
@date 2018.05.02 |
|
279 |
''' |
|
280 |
def toXmlAsAttribute(self, parent): |
|
281 |
for attr in self.attrs: |
|
282 |
parent.append(attr.toXml(self)) |
|
283 | ||
284 |
''' |
|
285 |
@brief create item corresponding to given type |
|
286 |
@author humkyung |
|
287 |
@date 2018.05.02 |
|
288 |
''' |
|
289 |
@staticmethod |
|
290 |
def createItem(type, path): |
|
291 |
from QEngineeringOPCItem import QEngineeringOPCItem |
|
292 | ||
293 |
item = None |
|
294 |
if type == "Piping OPC''s": |
|
295 |
item = QEngineeringOPCItem(path) |
|
296 |
else: |
|
297 |
item = SymbolSvgItem(path) |
|
298 |
|
|
299 |
return item |
|
300 |
|
|
301 |
''' |
|
236 | 302 |
@brief override paint(draw connection points) |
237 | 303 |
@author humkyung |
238 | 304 |
@date 2018.04.21 |
DTI_PID/DTI_PID/TextItemFactory.py | ||
---|---|---|
15 | 15 |
from QEngineeringTextItem import QEngineeringTextItem |
16 | 16 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
17 | 17 |
from QEngineeringNoteItem import QEngineeringNoteItem |
18 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
|
18 | 19 | |
19 | 20 |
class TextItemFactory(SingletonInstane): |
20 | 21 |
def __init__(self): |
... | ... | |
23 | 24 | |
24 | 25 |
''' |
25 | 26 |
@history 2018.04.27 Jeongwoo Add condition on elif-statement (delimiter != '' and lineNoConfig != '') |
27 |
humkyung 2018.05.02 create engineering size text item if condition matches |
|
26 | 28 |
''' |
27 | 29 |
def createTextItem(self, text, delimiter = '', lineNoConfig = ''): |
28 | 30 |
item = None |
29 | 31 | |
30 | 32 |
try: |
33 |
docData = AppDocData.instance() |
|
34 |
configs = docData.getConfigs('Size', 'Delimiter') |
|
35 |
sizeDelimiter = configs[0].value.upper() if 1 == len(configs) else None |
|
36 | ||
31 | 37 |
if self.isNoteNoText(text): |
32 | 38 |
item = QEngineeringNoteItem() |
33 | 39 |
elif (delimiter != '' and lineNoConfig != '') and self.isLineNo(text, delimiter, lineNoConfig): |
34 | 40 |
item = QEngineeringLineNoTextItem() |
41 |
elif self.isSizeText(text, sizeDelimiter): |
|
42 |
item = QEngineeringSizeTextItem() |
|
35 | 43 |
else: |
36 | 44 |
item = QEngineeringTextItem() |
37 | 45 |
except Exception as ex: |
... | ... | |
82 | 90 |
if QRegExpValidator(QRegExp("NOTE\s\d+")).validate(text, 0)[0] != QValidator.Invalid: |
83 | 91 |
return True |
84 | 92 |
else: |
85 |
return False |
|
93 |
return False |
|
94 | ||
95 |
''' |
|
96 |
@brief check if given text is size text |
|
97 |
@author humkyung |
|
98 |
@date 2018.05.02 |
|
99 |
''' |
|
100 |
def isSizeText(self, text, delimiter=None): |
|
101 |
docData = AppDocData.instance() |
|
102 |
sizeDataList = docData.getNomialPipeSizeData() |
|
103 | ||
104 |
tokens = text.upper().split(delimiter) if delimiter is not None else [text] |
|
105 |
for token in tokens: |
|
106 |
matches = [sizeData for sizeData in sizeDataList if sizeData.sizeValue() == token] |
|
107 |
if not matches: return False |
|
108 |
|
|
109 |
return True |
DTI_PID/DTI_PID/UI/Configuration.ui | ||
---|---|---|
32 | 32 |
<string>인식</string> |
33 | 33 |
</attribute> |
34 | 34 |
<layout class="QGridLayout" name="gridLayout_2"> |
35 |
<item row="0" column="1">
|
|
35 |
<item row="1" column="1">
|
|
36 | 36 |
<widget class="QGroupBox" name="groupBox"> |
37 | 37 |
<property name="title"> |
38 | 38 |
<string>라인 검출</string> |
39 | 39 |
</property> |
40 | 40 |
<layout class="QGridLayout" name="gridLayout_5"> |
41 |
<item row="0" column="0">
|
|
41 |
<item row="2" column="0">
|
|
42 | 42 |
<layout class="QHBoxLayout" name="horizontalLayout_6"> |
43 | 43 |
<item> |
44 | 44 |
<widget class="QLabel" name="label_4"> |
... | ... | |
62 | 62 |
</item> |
63 | 63 |
</layout> |
64 | 64 |
</item> |
65 |
<item row="1" column="0">
|
|
65 |
<item row="3" column="0">
|
|
66 | 66 |
<layout class="QHBoxLayout" name="horizontalLayout"> |
67 | 67 |
<property name="sizeConstraint"> |
68 | 68 |
<enum>QLayout::SetNoConstraint</enum> |
... | ... | |
88 | 88 |
</layout> |
89 | 89 |
</widget> |
90 | 90 |
</item> |
91 |
<item row="1" column="1">
|
|
91 |
<item row="2" column="1">
|
|
92 | 92 |
<widget class="QGroupBox" name="groupBoxLineNo"> |
93 | 93 |
<property name="title"> |
94 | 94 |
<string>Line No</string> |
... | ... | |
178 | 178 |
</layout> |
179 | 179 |
</widget> |
180 | 180 |
</item> |
181 |
<item row="0" column="1"> |
|
182 |
<widget class="QGroupBox" name="groupBoxAttribute"> |
|
183 |
<property name="title"> |
|
184 |
<string>속성 검출</string> |
|
185 |
</property> |
|
186 |
<layout class="QGridLayout" name="gridLayout_6"> |
|
187 |
<item row="0" column="0"> |
|
188 |
<layout class="QVBoxLayout" name="verticalLayout_3"> |
|
189 |
<item> |
|
190 |
<layout class="QHBoxLayout" name="horizontalLayout_8"> |
|
191 |
<item alignment="Qt::AlignVCenter"> |
|
192 |
<widget class="QLabel" name="label_6"> |
|
193 |
<property name="text"> |
|
194 |
<string>Size Delimiter : </string> |
|
195 |
</property> |
|
196 |
</widget> |
|
197 |
</item> |
|
198 |
<item alignment="Qt::AlignVCenter"> |
|
199 |
<widget class="QLineEdit" name="lineEditSizeDelimiter"/> |
|
200 |
</item> |
|
201 |
</layout> |
|
202 |
</item> |
|
203 |
</layout> |
|
204 |
</item> |
|
205 |
</layout> |
|
206 |
</widget> |
|
207 |
</item> |
|
181 | 208 |
</layout> |
182 | 209 |
</widget> |
183 | 210 |
<widget class="QWidget" name="tabNominalPipeSize"> |
내보내기 Unified diff