개정판 e6b6b13d
Add progress dialog for connecting attributes
DTI_PID/DTI_PID/ConnectAttr_UI.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
|
|
3 |
# Form implementation generated from reading ui file 'ui/dlgConnectAttr.ui' |
|
4 |
# |
|
5 |
# Created by: PyQt5 UI code generator 5.10.1 |
|
6 |
# |
|
7 |
# WARNING! All changes made in this file will be lost! |
|
8 |
|
|
9 |
from PyQt5 import QtCore, QtGui, QtWidgets |
|
10 |
|
|
11 |
class Ui_ConnectAttr(object): |
|
12 |
def setupUi(self, ConnectAttr): |
|
13 |
ConnectAttr.setObjectName("ConnectAttr") |
|
14 |
ConnectAttr.setWindowModality(QtCore.Qt.WindowModal) |
|
15 |
ConnectAttr.resize(845, 453) |
|
16 |
font = QtGui.QFont() |
|
17 |
font.setFamily("맑은 고딕") |
|
18 |
ConnectAttr.setFont(font) |
|
19 |
self.gridLayout = QtWidgets.QGridLayout(ConnectAttr) |
|
20 |
self.gridLayout.setObjectName("gridLayout") |
|
21 |
self.horizontalLayout = QtWidgets.QHBoxLayout() |
|
22 |
self.horizontalLayout.setObjectName("horizontalLayout") |
|
23 |
self.progressBar = QtWidgets.QProgressBar(ConnectAttr) |
|
24 |
self.progressBar.setProperty("value", 0) |
|
25 |
self.progressBar.setObjectName("progressBar") |
|
26 |
self.horizontalLayout.addWidget(self.progressBar) |
|
27 |
self.buttonBox = QtWidgets.QDialogButtonBox(ConnectAttr) |
|
28 |
self.buttonBox.setEnabled(False) |
|
29 |
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) |
|
30 |
sizePolicy.setHorizontalStretch(0) |
|
31 |
sizePolicy.setVerticalStretch(0) |
|
32 |
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth()) |
|
33 |
self.buttonBox.setSizePolicy(sizePolicy) |
|
34 |
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) |
|
35 |
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close) |
|
36 |
self.buttonBox.setObjectName("buttonBox") |
|
37 |
self.horizontalLayout.addWidget(self.buttonBox, 0, QtCore.Qt.AlignRight) |
|
38 |
self.gridLayout.addLayout(self.horizontalLayout, 3, 0, 1, 1) |
|
39 |
self.listWidget = QtWidgets.QListWidget(ConnectAttr) |
|
40 |
self.listWidget.setObjectName("listWidget") |
|
41 |
self.gridLayout.addWidget(self.listWidget, 0, 0, 1, 1) |
|
42 |
|
|
43 |
self.retranslateUi(ConnectAttr) |
|
44 |
self.buttonBox.clicked['QAbstractButton*'].connect(ConnectAttr.accept) |
|
45 |
QtCore.QMetaObject.connectSlotsByName(ConnectAttr) |
|
46 |
|
|
47 |
def retranslateUi(self, ConnectAttr): |
|
48 |
_translate = QtCore.QCoreApplication.translate |
|
49 |
ConnectAttr.setWindowTitle(_translate("ConnectAttr", "속성 연계")) |
|
50 |
|
|
51 |
|
|
52 |
if __name__ == "__main__": |
|
53 |
import sys |
|
54 |
app = QtWidgets.QApplication(sys.argv) |
|
55 |
ConnectAttr = QtWidgets.QDialog() |
|
56 |
ui = Ui_ConnectAttr() |
|
57 |
ui.setupUi(ConnectAttr) |
|
58 |
ConnectAttr.show() |
|
59 |
sys.exit(app.exec_()) |
|
60 |
|
DTI_PID/DTI_PID/DTI_PID.py | ||
---|---|---|
61 | 61 |
|
62 | 62 |
MIN_TEXT_SIZE = 10 |
63 | 63 |
|
64 |
THREAD_MAX_WORKER = 4
|
|
64 |
THREAD_MAX_WORKER = os.cpu_count()
|
|
65 | 65 |
threadLock = threading.Lock() |
66 | 66 |
|
67 | 67 |
ACCEPT_OVERLAY_AREA = 10 |
... | ... | |
720 | 720 |
return targetSymbolList |
721 | 721 |
|
722 | 722 |
''' |
723 |
@brief detect text areas |
|
724 |
@author humkyung |
|
725 |
@date 2018.06.16 |
|
726 |
''' |
|
727 |
def detectTextAreas(filePath): |
|
728 |
global srcGray |
|
729 |
|
|
730 |
tInfoList = [] |
|
731 |
try: |
|
732 |
if os.path.isfile(filePath): |
|
733 |
area = AppDocData.instance().getArea('Drawing') |
|
734 |
configs = AppDocData.instance().getConfigs('Text Area', 'Text Area') |
|
735 |
type = int(configs[0].value) if 1 == len(configs) else 0 |
|
736 |
|
|
737 |
if type == 0: |
|
738 |
(_tempOcrSrc, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
739 |
else: |
|
740 |
tInfoList = getTextAreaInfo(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
741 |
except Exception as ex: |
|
742 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
743 |
|
|
744 |
return tInfoList |
|
745 |
|
|
746 |
''' |
|
723 | 747 |
@brief read image drawing and then remove text |
724 | 748 |
@author jwkim |
725 | 749 |
@date |
... | ... | |
728 | 752 |
Jeongwoo 2018.05.25 Add condition on if-statement |
729 | 753 |
Jeongwoo 2018.06.05 Get text area data list by config.type |
730 | 754 |
Jeongwoo 2018.06.08 Add angle Parameter on TOCR.getTextInfo |
755 |
humkyung 2018.06.16 update proessbar while recognizing text |
|
731 | 756 |
''' |
732 |
def initMainSrc(mainRes): |
|
757 |
def initMainSrc(mainRes, tInfoList, updateProgressSignal):
|
|
733 | 758 |
global srcGray |
734 | 759 |
global ocrCompletedSrc |
735 | 760 |
global textInfoList |
736 | 761 |
global noteTextInfoList |
762 |
global maxProgressValue |
|
737 | 763 |
|
738 | 764 |
try: |
739 | 765 |
if os.path.isfile(mainRes): |
740 | 766 |
ocrCompletedSrc = srcGray.copy() |
741 | 767 |
|
742 |
area = AppDocData.instance().getArea('Drawing') |
|
743 |
configs = AppDocData.instance().getConfigs('Text Area', 'Text Area') |
|
744 |
type = int(configs[0].value) if 1 == len(configs) else 0 |
|
745 |
#(_tempOcrSrc, textInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
746 |
tInfoList = [] |
|
747 |
if type == 0: |
|
748 |
(_tempOcrSrc, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
749 |
else: |
|
750 |
tInfoList = getTextAreaInfo(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
751 |
|
|
752 | 768 |
global MIN_TEXT_SIZE |
753 | 769 |
for tInfo in tInfoList: |
754 | 770 |
if tInfo.getW() >= MIN_TEXT_SIZE or tInfo.getH() >= MIN_TEXT_SIZE: |
... | ... | |
758 | 774 |
ocrCompletedSrc = removeText(ocrCompletedSrc, resultTextInfo[0].getText(), resultTextInfo[0].getX(), resultTextInfo[0].getY(), resultTextInfo[0].getW(), resultTextInfo[0].getH()) |
759 | 775 |
else: |
760 | 776 |
print(tInfo.getText()) |
761 |
#global MIN_TEXT_SIZE |
|
762 |
#for textInfo in textInfoList: |
|
763 |
# if textInfo.getW() >= MIN_TEXT_SIZE or textInfo.getH() >= MIN_TEXT_SIZE: |
|
764 |
# ocrCompletedSrc = removeText(ocrCompletedSrc, textInfo.getText(), textInfo.getX(), textInfo.getY(), textInfo.getW(), textInfo.getH()) |
|
777 |
updateProgressSignal.emit(maxProgressValue) |
|
765 | 778 |
|
766 | 779 |
noteArea = AppDocData.instance().getArea('Note') |
767 | 780 |
if noteArea is not None: |
768 | 781 |
noteArea.img = srcGray[round(noteArea.y-1):round(noteArea.y+noteArea.height-1), round(noteArea.x-1):round(noteArea.x+noteArea.width-1)] |
769 |
#(_tempNoteOcrSrc, noteTextInfoList) = OCR.removeTextFromNpArray(noteArea.img, noteArea.x, noteArea.y) |
|
770 | 782 |
noteTextInfoList = TOCR.getTextInfo(noteArea.img, (noteArea.x, noteArea.y)) |
783 |
updateProgressSignal.emit(maxProgressValue) |
|
771 | 784 |
except Exception as ex: |
772 | 785 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
773 | 786 |
|
... | ... | |
962 | 975 |
listWidget.addItem("Start recognition : " + mainRes) |
963 | 976 |
|
964 | 977 |
if isSymbolTextChecked: |
965 |
initMainSrc(mainRes) |
|
966 |
|
|
967 | 978 |
threadLock.acquire() |
979 |
textAreas = detectTextAreas(mainRes) |
|
968 | 980 |
### calculate total count of symbol |
969 |
maxProgressValue = 0
|
|
981 |
maxProgressValue = len(textAreas) + 1
|
|
970 | 982 |
for targetItem in targetSymbolList: |
971 | 983 |
if type(targetItem) is list: |
972 | 984 |
maxProgressValue += len(targetItem) |
... | ... | |
975 | 987 |
print('totalCount = {}'.format(maxProgressValue)) |
976 | 988 |
### up to here |
977 | 989 |
threadLock.release() |
978 |
|
|
990 |
|
|
991 |
initMainSrc(mainRes, textAreas, updateProgressSignal) |
|
992 |
|
|
979 | 993 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
980 | 994 |
for targetItem in targetSymbolList: |
981 | 995 |
if type(targetItem) is list: |
DTI_PID/DTI_PID/LineNoTracer.py | ||
---|---|---|
5 | 5 |
import cv2 |
6 | 6 |
import numpy as np |
7 | 7 |
import math |
8 |
from PyQt5.QtCore import * |
|
9 |
from PyQt5.QtGui import * |
|
10 |
from PyQt5.QtWidgets import * |
|
11 |
from PyQt5.QtSvg import * |
|
8 | 12 |
import shapely |
9 | 13 |
from AppDocData import AppDocData |
14 |
from QEngineeringLineItem import QEngineeringLineItem |
|
15 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
|
16 |
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem |
|
17 |
from SymbolSvgItem import SymbolSvgItem |
|
18 |
from QEngineeringTextItem import QEngineeringTextItem |
|
10 | 19 |
|
11 | 20 |
class LineNoTracer: |
12 | 21 |
''' |
... | ... | |
39 | 48 |
pipeRun.items = connectedItems |
40 | 49 |
lineno.runs.append(pipeRun) |
41 | 50 |
|
42 |
connectedLines = [item for item in connectedItems if type(item) is QEngineeringLineItem] |
|
43 |
|
|
44 |
maxLength = None |
|
45 |
maxLengthItem = None |
|
46 |
for line in connectedLines: |
|
47 |
length = line.length() |
|
48 |
if maxLength is None or maxLength < length: |
|
49 |
maxLength = length |
|
50 |
maxLengthItem = line |
|
51 |
|
|
52 |
if maxLengthItem is not None: maxLengthItem.addFlowArrow() # TODO: check error scene() returns None |
|
53 |
|
|
54 | 51 |
return connectedItems |
55 | 52 |
|
56 | 53 |
''' |
... | ... | |
78 | 75 |
pipeRun.items = connectedItems |
79 | 76 |
if pipeRun.items is not None and len(pipeRun.items) > 0: |
80 | 77 |
matches[0].owner.runs.append(pipeRun) |
81 |
|
|
82 |
connectedLines = [item for item in connectedItems if type(item) is QEngineeringLineItem] |
|
83 |
|
|
84 |
maxLength = None |
|
85 |
maxLengthItem = None |
|
86 |
for line in connectedLines: |
|
87 |
length = line.length() |
|
88 |
if maxLength is None or maxLength < length: |
|
89 |
maxLength = length |
|
90 |
maxLengthItem = line |
|
91 |
|
|
92 |
if maxLengthItem is not None: maxLengthItem.addFlowArrow() # TODO: check error scene() returns None |
|
93 | 78 |
else: |
94 | 79 |
notMatches.append(line) |
95 | 80 |
lines = notMatches |
... | ... | |
106 | 91 |
Modify find secondary lines with 'while' used sublist for unconnected line |
107 | 92 |
humkyung 2018.05.18 set start line's owner before tracing |
108 | 93 |
''' |
109 |
def execute(self, toler=50): |
|
94 |
def execute(self, displayMessage, updateProgress, toler=50):
|
|
110 | 95 |
from QEngineeringLineItem import QEngineeringLineItem |
111 | 96 |
from SymbolSvgItem import SymbolSvgItem |
112 | 97 |
from QEngineeringRunItem import QEngineeringRunItem |
... | ... | |
137 | 122 |
# set start line's owner |
138 | 123 |
for lineno in docData.lineNos: |
139 | 124 |
if lineno.conns: lineno.conns[0].owner = lineno |
140 |
|
|
125 |
|
|
126 |
maxValue = len(self._lineNos) + 3 ## line no's count + secondary line + trim line + flowmark |
|
127 |
|
|
141 | 128 |
# find primary lines |
142 | 129 |
for lineno in docData.lineNos: |
130 |
displayMessage.emit('{} 토폴로지 구성'.format(lineno.text())) |
|
143 | 131 |
self.findPrimaryLines(lineno) |
132 |
updateProgress.emit(maxValue) |
|
144 | 133 |
|
145 | 134 |
# find secondary lines |
146 | 135 |
lines = self._lines |
147 | 136 |
self.findSecondaryLines(lines) |
137 |
updateProgress.emit(maxValue) |
|
148 | 138 |
|
149 | 139 |
### make trim lines |
140 |
displayMessage.emit('TrimLine 토폴로지 구성') |
|
150 | 141 |
orphanLines = [line for line in self._lines if line.owner is None] |
151 | 142 |
if orphanLines: |
152 | 143 |
orphanLines = sorted(orphanLines, key=lambda param:param.length(), reverse=True) |
... | ... | |
163 | 154 |
if item.owner is not None: orphanLines.remove(item) |
164 | 155 |
|
165 | 156 |
docData.lineNos.append(trimLineNo) |
166 |
|
|
157 |
|
|
158 |
updateProgress.emit(maxValue) |
|
167 | 159 |
except Exception as ex: |
168 | 160 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
169 | 161 |
|
... | ... | |
201 | 193 |
visited.append(match) |
202 | 194 |
|
203 | 195 |
return visited |
196 |
|
|
197 |
''' |
|
198 |
@brief connect attributes |
|
199 |
@author humkyung |
|
200 |
@date 2018.06.17 |
|
201 |
''' |
|
202 |
def connectAttrImpl(worker): |
|
203 |
from LineNoTracer import LineNoTracer |
|
204 |
from AppDocData import AppDocData |
|
205 |
|
|
206 |
try: |
|
207 |
symbols = [] |
|
208 |
lines = [] |
|
209 |
lineNos = [] |
|
210 |
for item in worker.graphicsView.scene.items(): |
|
211 |
if issubclass(type(item), SymbolSvgItem): |
|
212 |
symbols.append(item) |
|
213 |
elif type(item) is QEngineeringLineNoTextItem: |
|
214 |
lineNos.append(item) |
|
215 |
elif type(item) is QEngineeringLineItem: |
|
216 |
lines.append(item) |
|
217 |
|
|
218 |
# trace line no |
|
219 |
tracer = LineNoTracer(symbols, lines, lineNos) |
|
220 |
tracer.execute(worker.displayMessage, worker.updateProgress) |
|
221 |
# up to here |
|
222 |
except Exception as ex: |
|
223 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
224 |
finally: |
|
225 |
worker.finished.emit() |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
512 | 512 |
humkyung 2018.04.26 remove small objects before recognizing line |
513 | 513 |
Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image |
514 | 514 |
Jeongwoo 2018.05.25 Move codes about LineDetector |
515 |
humkyung 2018.06.17 show progress dialog |
|
515 | 516 |
''' |
516 | 517 |
def recognizeLine(self, MainWindow): |
517 | 518 |
from LineNoTracer import LineNoTracer |
519 |
from QConnectAttrDialog import QConnectAttrDialog |
|
518 | 520 |
|
519 | 521 |
if not self.graphicsView.hasImage(): |
520 | 522 |
self.showImageSelectionMessageBox() |
521 | 523 |
return |
522 | 524 |
|
523 | 525 |
try: |
524 |
symbols = [] |
|
525 |
lines = [] |
|
526 |
lineNos = [] |
|
527 |
for item in self.graphicsView.scene.items(): |
|
528 |
if issubclass(type(item), SymbolSvgItem): |
|
529 |
symbols.append(item) |
|
530 |
elif type(item) is QEngineeringLineNoTextItem: |
|
531 |
lineNos.append(item) |
|
532 |
elif type(item) is QEngineeringLineItem: |
|
533 |
lines.append(item) |
|
534 |
|
|
535 |
# trace line no |
|
536 |
tracer = LineNoTracer(symbols, lines, lineNos) |
|
537 |
tracer.execute() |
|
538 |
# up to here |
|
526 |
self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView) |
|
527 |
self.dlgConnectAttr.exec_() |
|
539 | 528 |
|
540 | 529 |
# construct line no item |
541 | 530 |
docData = AppDocData.instance() |
DTI_PID/DTI_PID/QConnectAttrDialog.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
from PyQt5.QtCore import * |
|
3 |
from PyQt5.QtGui import * |
|
4 |
from PyQt5.QtWidgets import * |
|
5 |
import ConnectAttr_UI |
|
6 |
import sys |
|
7 |
import os |
|
8 |
import cv2 |
|
9 |
from AppDocData import AppDocData |
|
10 |
from LineDetector import LineDetector |
|
11 |
from QEngineeringLineItem import QEngineeringLineItem |
|
12 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
|
13 |
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem |
|
14 |
from SymbolSvgItem import SymbolSvgItem |
|
15 |
from QEngineeringTextItem import QEngineeringTextItem |
|
16 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
|
17 |
|
|
18 |
''' |
|
19 |
''' |
|
20 |
class Worker(QObject): |
|
21 |
from PyQt5.QtCore import QThread |
|
22 |
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QListWidget |
|
23 |
from QtImageViewer import QtImageViewer |
|
24 |
import sys |
|
25 |
|
|
26 |
''' |
|
27 |
''' |
|
28 |
finished = pyqtSignal() |
|
29 |
intReady = pyqtSignal(int) |
|
30 |
displayMessage = pyqtSignal(str) |
|
31 |
updateProgress = pyqtSignal(int) |
|
32 |
|
|
33 |
''' |
|
34 |
@brief execute connecting attributes |
|
35 |
@author humkyung |
|
36 |
@date 2018.06.17 |
|
37 |
''' |
|
38 |
#pyqtSlot() |
|
39 |
def procCounter(self): # A slot takes no params |
|
40 |
from LineNoTracer import connectAttrImpl |
|
41 |
|
|
42 |
try: |
|
43 |
connectAttrImpl(self) |
|
44 |
except Exception as ex: |
|
45 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
46 |
|
|
47 |
''' |
|
48 |
''' |
|
49 |
class QConnectAttrDialog(QDialog): |
|
50 |
''' |
|
51 |
''' |
|
52 |
def __init__(self, parent, graphicsView): #Parent is MainWindow |
|
53 |
import ConnectAttr_UI |
|
54 |
|
|
55 |
QDialog.__init__(self, parent) |
|
56 |
|
|
57 |
self.parent = parent |
|
58 |
self.graphicsView = graphicsView |
|
59 |
self.ui = ConnectAttr_UI.Ui_ConnectAttr() |
|
60 |
self.ui.setupUi(self) |
|
61 |
self.ui.buttonBox.setEnabled(True) |
|
62 |
self.ui.listWidget.model().rowsInserted.connect(self.rowInserted) ## connect to func rowInserted(self, item) |
|
63 |
self.isAccepted = False |
|
64 |
|
|
65 |
self.ui.buttonBox.setEnabled(False) |
|
66 |
self.ui.progressBar.setValue(0) |
|
67 |
self.startThread() |
|
68 |
|
|
69 |
''' |
|
70 |
@brief QListWidget Row Inserted Listener |
|
71 |
Whenever row inserted, scroll to bottom |
|
72 |
@author Jeongwoo |
|
73 |
@date 18.04.12 |
|
74 |
''' |
|
75 |
def rowInserted(self, item): |
|
76 |
self.ui.listWidget.scrollToBottom() |
|
77 |
|
|
78 |
''' |
|
79 |
@brief add item to list widget |
|
80 |
@author humkyung |
|
81 |
@date 2018.06.17 |
|
82 |
''' |
|
83 |
def addListItem(self, msg): |
|
84 |
self.ui.listWidget.addItem(msg) |
|
85 |
|
|
86 |
def accept(self): |
|
87 |
self.isAccepted = True |
|
88 |
QDialog.accept(self) |
|
89 |
|
|
90 |
''' |
|
91 |
@brief update progressbar with given value |
|
92 |
@author humkyung |
|
93 |
@date 2018.06.17 |
|
94 |
''' |
|
95 |
def updateProgress(self, maxValue): |
|
96 |
self.ui.progressBar.setMaximum(maxValue) |
|
97 |
self.ui.progressBar.setValue(self.ui.progressBar.value() + 1) |
|
98 |
|
|
99 |
''' |
|
100 |
@brief start thread |
|
101 |
@author humkyung |
|
102 |
@date 2018.06.17 |
|
103 |
''' |
|
104 |
def startThread(self): |
|
105 |
import timeit |
|
106 |
from LineNoTracer import connectAttrImpl |
|
107 |
|
|
108 |
self.ui.buttonBox.setDisabled(True) |
|
109 |
|
|
110 |
# 1 - create Worker and Thread inside the Form |
|
111 |
self.obj = Worker() # no parent! |
|
112 |
self.obj.graphicsView = self.graphicsView |
|
113 |
self.thread = QThread() # no parent! |
|
114 |
|
|
115 |
# 2 - Move the Worker object to the Thread object |
|
116 |
self.obj.moveToThread(self.thread) |
|
117 |
|
|
118 |
# 3 - Connect Worker Signals to the Thread slots |
|
119 |
self.obj.finished.connect(self.thread.quit) |
|
120 |
self.obj.displayMessage.connect(self.addListItem) |
|
121 |
self.obj.updateProgress.connect(self.updateProgress) |
|
122 |
|
|
123 |
# 4 - Connect Thread started signal to Worker operational slot method |
|
124 |
self.thread.started.connect(self.obj.procCounter) |
|
125 |
|
|
126 |
# 5 - Thread finished signal will close the app if you want! |
|
127 |
self.thread.finished.connect(self.dlgExit) |
|
128 |
|
|
129 |
# 6 - Start the thread |
|
130 |
self.thread.start() |
|
131 |
|
|
132 |
self.tmStart = timeit.default_timer() |
|
133 |
|
|
134 |
''' |
|
135 |
@brief set buttonbox's enabled flag |
|
136 |
@author humkyung |
|
137 |
@date 2018.06.17 |
|
138 |
@history humkyung 2018.06.17 add flow mark for pipe run |
|
139 |
''' |
|
140 |
def dlgExit(self): |
|
141 |
import timeit |
|
142 |
|
|
143 |
try: |
|
144 |
# add flow mark |
|
145 |
self.ui.listWidget.addItem("FlowMark 생성") |
|
146 |
docData = AppDocData.instance() |
|
147 |
for lineno in docData.lineNos: |
|
148 |
for run in lineno.runs: |
|
149 |
run.addFlowMark() |
|
150 |
# up to here |
|
151 |
|
|
152 |
self.ui.progressBar.setValue(self.ui.progressBar.maximum()) |
|
153 |
self.ui.buttonBox.setEnabled(True) |
|
154 |
except Exception as ex: |
|
155 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
156 |
finally: |
|
157 |
self.tmStop = timeit.default_timer() |
|
158 |
seconds = self.tmStop - self.tmStart |
|
159 |
self.ui.listWidget.addItem("\nRunning Time : {} min".format(str(round(seconds/60, 1))) + "\n") |
DTI_PID/DTI_PID/QRecognitionDialog.py | ||
---|---|---|
23 | 23 |
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QListWidget |
24 | 24 |
from QtImageViewer import QtImageViewer |
25 | 25 |
import sys |
26 |
import timeit |
|
27 | 26 |
|
28 | 27 |
''' |
29 | 28 |
@history 2018.05.30 Jeongwoo Remove parameter on recognizeLine signal / Change signal name (drawDetectedItems) |
... | ... | |
44 | 43 |
#pyqtSlot() |
45 | 44 |
def procCounter(self): # A slot takes no params |
46 | 45 |
from DTI_PID import executeRecognition |
47 |
import timeit |
|
48 | 46 |
|
49 | 47 |
try: |
50 |
start = timeit.default_timer() |
|
51 | 48 |
executeRecognition(self.drawDetectedItems, self.updateProgress, self.path, self.listWidget, self.isSymbolTextChecked) |
52 | 49 |
if self.isLineChecked: |
53 | 50 |
self.recognizeLine.emit(self.path, self.listWidget, self.graphicsView) |
54 | 51 |
self.finished.emit() |
55 | 52 |
except Exception as ex: |
56 | 53 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
57 |
finally: |
|
58 |
stop = timeit.default_timer() |
|
59 |
seconds = stop - start |
|
60 |
self.listWidget.addItem("\nRunning Time : {} min".format(str(round(seconds/60, 1))) + "\n") |
|
61 | 54 |
|
62 | 55 |
''' |
63 | 56 |
@history 2018.05.25 Jeongwoo Add pyqtSignal(svgItemClicked, itemRemoved) |
... | ... | |
127 | 120 |
humkyung 2018.06.08 connect signal to self.updateProgress |
128 | 121 |
''' |
129 | 122 |
def startThread(self): |
123 |
import timeit |
|
130 | 124 |
from DTI_PID import recognizeLine |
131 | 125 |
|
132 | 126 |
self.ui.buttonBox.setDisabled(True) |
... | ... | |
158 | 152 |
# 6 - Start the thread |
159 | 153 |
self.thread.start() |
160 | 154 |
|
155 |
self.tmStart = timeit.default_timer() |
|
156 |
|
|
161 | 157 |
''' |
162 | 158 |
@brief set buttonbox's enabled flag |
163 | 159 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
... | ... | |
165 | 161 |
2018.06.14 Jeongwoo Change sentence order |
166 | 162 |
''' |
167 | 163 |
def dlgExit(self): |
164 |
import timeit |
|
168 | 165 |
import XmlGenerator as xg |
166 |
|
|
169 | 167 |
try: |
170 | 168 |
self.ui.buttonBox.setEnabled(True) |
171 | 169 |
docData = AppDocData.instance() |
... | ... | |
175 | 173 |
xg.writeXmlOnScene(docData.imgName, docData.imgWidth, docData.imgHeight, self.graphicsView.scene) |
176 | 174 |
except Exception as ex: |
177 | 175 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
176 |
finally: |
|
177 |
self.tmStop = timeit.default_timer() |
|
178 |
seconds = self.tmStop - self.tmStart |
|
179 |
self.ui.listWidget.addItem("\nRunning Time : {} min".format(str(round(seconds/60, 1))) + "\n") |
|
178 | 180 |
|
179 | 181 |
''' |
180 | 182 |
@history 2018.05.29 Jeongwoo Call parent's method |
DTI_PID/DTI_PID/QtImageViewer.py | ||
---|---|---|
226 | 226 |
scenePos1 = self.mapToScene(clickPos.x() - HALF_SIZE//adjust, clickPos.y() - HALF_SIZE//adjust) |
227 | 227 |
scenePos2 = self.mapToScene(clickPos.x() + HALF_SIZE//adjust, clickPos.y() + HALF_SIZE//adjust) |
228 | 228 |
if isZoomIn: |
229 |
print("zoom in") |
|
230 | 229 |
zoomArea = QRectF(QPointF(scenePos1.x() if scenePos1.x() > 0 else 0, scenePos1.y() if scenePos1.y() > 0 else 0), QPointF(scenePos2.x(), scenePos2.y())) |
231 | 230 |
#self.fitInView(zoomArea, Qt.KeepAspectRatioByExpanding) |
232 | 231 |
viewBBox = self.zoomStack[-1] if len(self.zoomStack) else self.sceneRect() |
... | ... | |
237 | 236 |
self.zoomStack.append(selectionBBox) |
238 | 237 |
self.updateViewer() |
239 | 238 |
else: |
240 |
print("zoom out") |
|
241 | 239 |
self.scene.setSelectionArea(QPainterPath()) # Clear current selection area. |
242 | 240 |
if len(self.zoomStack): |
243 | 241 |
self.zoomStack.pop() |
... | ... | |
248 | 246 |
""" |
249 | 247 |
self.updateViewer() |
250 | 248 |
|
251 |
#''' |
|
252 |
# @brief draw something event |
|
253 |
#''' |
|
254 |
#def paintEvent(self, event): |
|
255 |
# if self.command is not None: |
|
256 |
# scenePos = self.mapToScene(event.pos()) |
|
257 |
# self.command.execute(['paintEvent', event, scenePos]) |
|
258 |
# if self.command.isTreated == True: return |
|
259 |
|
|
260 | 249 |
''' |
261 | 250 |
@brief mouse move event |
262 | 251 |
''' |
DTI_PID/DTI_PID/Shapes/QEngineeringRunItem.py | ||
---|---|---|
63 | 63 |
return res |
64 | 64 |
|
65 | 65 |
''' |
66 |
@brief add flow mark |
|
67 |
@author humkyung |
|
68 |
@date 2018.06.17 |
|
69 |
''' |
|
70 |
def addFlowMark(self): |
|
71 |
from QEngineeringLineItem import QEngineeringLineItem |
|
72 |
|
|
73 |
try: |
|
74 |
connectedLines = [item for item in self.items if type(item) is QEngineeringLineItem] |
|
75 |
|
|
76 |
maxLength = None |
|
77 |
maxLengthItem = None |
|
78 |
for line in connectedLines: |
|
79 |
length = line.length() |
|
80 |
if maxLength is None or maxLength < length: |
|
81 |
maxLength = length |
|
82 |
maxLengthItem = line |
|
83 |
|
|
84 |
if maxLengthItem is not None: maxLengthItem.addFlowArrow() |
|
85 |
except Exception as ex: |
|
86 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
87 |
|
|
88 |
''' |
|
66 | 89 |
@brief write to xml |
67 | 90 |
@author humkyung |
68 | 91 |
@date 2018.05.16 |
DTI_PID/DTI_PID/UI/dlgConnectAttr.ui | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
<ui version="4.0"> |
|
3 |
<class>ConnectAttr</class> |
|
4 |
<widget class="QDialog" name="ConnectAttr"> |
|
5 |
<property name="windowModality"> |
|
6 |
<enum>Qt::WindowModal</enum> |
|
7 |
</property> |
|
8 |
<property name="geometry"> |
|
9 |
<rect> |
|
10 |
<x>0</x> |
|
11 |
<y>0</y> |
|
12 |
<width>845</width> |
|
13 |
<height>453</height> |
|
14 |
</rect> |
|
15 |
</property> |
|
16 |
<property name="font"> |
|
17 |
<font> |
|
18 |
<family>맑은 고딕</family> |
|
19 |
</font> |
|
20 |
</property> |
|
21 |
<property name="windowTitle"> |
|
22 |
<string>속성 연계</string> |
|
23 |
</property> |
|
24 |
<layout class="QGridLayout" name="gridLayout"> |
|
25 |
<item row="3" column="0"> |
|
26 |
<layout class="QHBoxLayout" name="horizontalLayout"> |
|
27 |
<item> |
|
28 |
<widget class="QProgressBar" name="progressBar"> |
|
29 |
<property name="value"> |
|
30 |
<number>0</number> |
|
31 |
</property> |
|
32 |
</widget> |
|
33 |
</item> |
|
34 |
<item alignment="Qt::AlignRight"> |
|
35 |
<widget class="QDialogButtonBox" name="buttonBox"> |
|
36 |
<property name="enabled"> |
|
37 |
<bool>false</bool> |
|
38 |
</property> |
|
39 |
<property name="sizePolicy"> |
|
40 |
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
|
41 |
<horstretch>0</horstretch> |
|
42 |
<verstretch>0</verstretch> |
|
43 |
</sizepolicy> |
|
44 |
</property> |
|
45 |
<property name="orientation"> |
|
46 |
<enum>Qt::Horizontal</enum> |
|
47 |
</property> |
|
48 |
<property name="standardButtons"> |
|
49 |
<set>QDialogButtonBox::Close</set> |
|
50 |
</property> |
|
51 |
</widget> |
|
52 |
</item> |
|
53 |
</layout> |
|
54 |
</item> |
|
55 |
<item row="0" column="0"> |
|
56 |
<widget class="QListWidget" name="listWidget"/> |
|
57 |
</item> |
|
58 |
</layout> |
|
59 |
</widget> |
|
60 |
<resources/> |
|
61 |
<connections> |
|
62 |
<connection> |
|
63 |
<sender>buttonBox</sender> |
|
64 |
<signal>clicked(QAbstractButton*)</signal> |
|
65 |
<receiver>ConnectAttr</receiver> |
|
66 |
<slot>accept()</slot> |
|
67 |
<hints> |
|
68 |
<hint type="sourcelabel"> |
|
69 |
<x>248</x> |
|
70 |
<y>254</y> |
|
71 |
</hint> |
|
72 |
<hint type="destinationlabel"> |
|
73 |
<x>157</x> |
|
74 |
<y>274</y> |
|
75 |
</hint> |
|
76 |
</hints> |
|
77 |
</connection> |
|
78 |
</connections> |
|
79 |
</ui> |
내보내기 Unified diff