개정판 3828d206
QSymbolEditorDialog 에 즉시 삽입 옵션 추가 / 즉시 삽입 옵션 추가와 관련 부분 수정 / InsertSymbol 내에 함수 표기가 잘못되어 저장되지 않는 문제 수정
DTI_PID/DTI_PID/Commands/CropCommand.py | ||
---|---|---|
14 | 14 |
class CropCommand(AbstractCommand.AbstractCommand): |
15 | 15 |
def __init__(self, imageViewer): |
16 | 16 |
super(CropCommand, self).__init__(imageViewer) |
17 |
self.name = 'Crop' |
|
17 |
self.name = 'Crop' |
|
18 |
self.offsetX = 0 |
|
19 |
self.offsetY = 0 |
|
18 | 20 |
self.imageViewer.setCursor(QCursor(Qt.CrossCursor)) |
19 | 21 |
|
20 | 22 |
''' |
21 | 23 |
@brief crop image by rectangle selected by user |
24 |
@history 2018.05.02 Jeongwoo Init self.offsetX and self.offsetY |
|
25 |
Add QtImageViewer.startPointChanged.emit |
|
22 | 26 |
''' |
23 | 27 |
def execute(self, param): |
24 | 28 |
event = param[1] |
... | ... | |
34 | 38 |
selectionBBox = self.imageViewer.scene.selectionArea().boundingRect().intersected(viewBBox) |
35 | 39 |
if selectionBBox.isValid(): |
36 | 40 |
croppedImage = self.imageViewer.image().copy(selectionBBox.toAlignedRect()) |
41 |
self.offsetX = selectionBBox.x() |
|
42 |
self.offsetY = selectionBBox.y() |
|
37 | 43 |
self.imageViewer.setImage(croppedImage) |
38 | 44 |
finally: |
39 | 45 |
self.imageViewer.setDragMode(QGraphicsView.NoDrag) |
40 | 46 |
self.imageViewer.leftMouseButtonReleased.emit(scenePos.x(), scenePos.y()) |
47 |
self.imageViewer.startPointChanged.emit(self.offsetX, self.offsetY) |
|
41 | 48 |
pass |
42 | 49 |
self.isTreated = False |
43 | 50 |
DTI_PID/DTI_PID/Commands/FitImageCommand.py | ||
---|---|---|
16 | 16 |
WHITE_PIXEL = (255, 255, 255, 255) |
17 | 17 |
BLACK_PIXEL = (0, 0, 0, 255) |
18 | 18 | |
19 |
''' |
|
20 |
@history 2018.05.02 Jeongwoo Change variable name (adjustX, adjustY → offsetX, offsetY) |
|
21 |
''' |
|
19 | 22 |
def __init__(self, imageViewer): |
20 | 23 |
super(FitImageCommand, self).__init__(imageViewer) |
21 | 24 |
self.name = 'FitImage' |
... | ... | |
24 | 27 |
boundingBox = self.getImageBoundingBox() |
25 | 28 |
croppedImage = self.imageViewer.image().copy(boundingBox) |
26 | 29 |
self.imageViewer.setImage(croppedImage) |
27 |
self.adjustX = boundingBox.left()
|
|
28 |
self.adjustY = boundingBox.top()
|
|
30 |
self.offsetX = boundingBox.left()
|
|
31 |
self.offsetY = boundingBox.top()
|
|
29 | 32 | |
30 |
def getAdjust(self): |
|
31 |
return (self.adjustX, self.adjustY) |
|
33 |
''' |
|
34 |
@history 2018.05.02 Jeongwoo Change method name (getAdjust → getOffset) |
|
35 |
''' |
|
36 |
def getOffset(self): |
|
37 |
return (self.offsetX, self.offsetY) |
|
32 | 38 | |
33 | 39 |
def getImageBoundingBox(self): |
34 | 40 |
image = self.imageViewer.image() |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
287 | 287 | |
288 | 288 |
''' |
289 | 289 |
@brief create a symbol |
290 |
@history 2018.05.02 Jeongwoo Change return value of QSymbolEditorDialog (Single variable → Tuple) |
|
291 |
Add SymbolSvgItem |
|
290 | 292 |
''' |
291 | 293 |
def createSymbol(self): |
292 | 294 |
image = self.graphicsView.image() |
293 | 295 |
if image is not None: |
294 | 296 |
symbolEditorDialog = QSymbolEditorDialog.QSymbolEditorDialog(self, image, AppDocData.instance().getCurrentProject()) |
295 |
_ret = symbolEditorDialog.showDialog()
|
|
297 |
(isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
|
|
296 | 298 |
self.dirTreeWidget.initDirTreeWidget() |
299 |
if isAccepted: |
|
300 |
if isImmediateInsert: |
|
301 |
'''''' |
|
302 |
svgPath = AppDocData.instance().getCurrentProject().getSvgFilePath() + "/" + newSym.getType() + "/" + newSym.getName() + ".svg" |
|
303 |
img = cv2.imread(AppDocData.instance().getCurrentProject().getImageFilePath() + "/" + newSym.getType() + "/" + newSym.getName() + ".png", 1) |
|
304 |
w, h = (0, 0) |
|
305 |
if len(img.shape[::-1]) == 2: |
|
306 |
w, h = img.shape[::-1] |
|
307 |
else: |
|
308 |
_chan, w, h = img.shape[::-1] |
|
309 |
svg = SymbolSvgItem(svgPath) |
|
310 |
svg.buildItem(newSym.getName(), newSym.getType(), 0, [offsetX, offsetY], [w, h], [float(x) for x in newSym.getOriginalPoint().split(',')], [(float(x.split(',')[0]), float(x.split(',')[1])) for x in newSym.getConnectionPoint().split('/')]) |
|
311 | ||
312 |
#### lambda param=svg : bind 'svg' object to lambda('param') |
|
313 |
#### If case of 'lambda svg=svg:', function uses the 'svg' value bound to lambda |
|
314 |
svg.clicked.connect(lambda param=svg: self.resultTreeWidget.findItem(param)) |
|
315 |
svg.removed.connect(self.resultTreeWidget.itemRemoved) |
|
316 | ||
317 |
transform = QTransform() |
|
318 |
transform.translate(offsetX, offsetY) |
|
319 |
svg.setTransform(transform) |
|
320 |
self.graphicsView.scene.addItem(svg) |
|
321 |
for connector in svg.connectors: |
|
322 |
self.graphicsView.scene.addItem(connector) |
|
297 | 323 | |
298 | 324 |
''' |
299 | 325 |
@brief connect equipment and nozzle |
DTI_PID/DTI_PID/QDirTreeWidget.py | ||
---|---|---|
98 | 98 |
else: |
99 | 99 |
pass |
100 | 100 | |
101 |
''' |
|
102 |
@history 2018.05.02 Jeongwoo Change return value of QSymbolEditorDialog (Single variable → Tuple) |
|
103 |
''' |
|
101 | 104 |
def initDirTreeWidget(self): |
102 | 105 |
project = AppDocData.instance().getCurrentProject() |
103 | 106 |
if project is not None: |
... | ... | |
174 | 177 |
image = QImage(path, "PNG") |
175 | 178 |
print("after image") |
176 | 179 |
symbolEditorDialog = QSymbolEditorDialog.QSymbolEditorDialog(self, image, AppDocData.instance().getCurrentProject(), sym) |
177 |
_ret = symbolEditorDialog.showDialog()
|
|
180 |
(isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
|
|
178 | 181 |
self.initDirTreeWidget() |
179 | 182 |
else: |
180 | 183 |
QMessageBox.about(self, "알림", "심볼 데이터를 불러오는 중 에러가 발생했습니다.") |
DTI_PID/DTI_PID/QSymbolEditorDialog.py | ||
---|---|---|
1 | 1 |
# coding: utf-8 |
2 | 2 |
from PyQt5 import QtCore, QtGui, QtWidgets |
3 |
from PyQt5.QtCore import pyqtSlot |
|
3 | 4 |
from PyQt5.QtWidgets import * |
4 | 5 |
from PyQt5.QtGui import * |
5 | 6 |
from QtImageViewer import QtImageViewer |
... | ... | |
21 | 22 |
class QSymbolEditorDialog(QDialog): |
22 | 23 |
FILE_NUMBER = 0 |
23 | 24 | |
25 |
''' |
|
26 |
@history 2018.05.02 Jeongwoo Add variables (self.offsetX, self.offsetY, self.newSym) |
|
27 |
''' |
|
24 | 28 |
def __init__(self, parent, image, project, selectedSymbol = None): |
25 | 29 |
QDialog.__init__(self, parent) |
26 | 30 |
self.image = image |
... | ... | |
33 | 37 |
self.initForms() |
34 | 38 |
self.initContents() |
35 | 39 |
self.isAccepted = False |
40 |
self.offsetX = 0 |
|
41 |
self.offsetY = 0 |
|
42 |
self.newSym = None |
|
36 | 43 |
self.dbHelper = SG_DbHelper.SG_DbHelper(self.project.getPath()) |
37 | 44 | |
38 | 45 |
''' |
39 | 46 |
@brief Set up QtImageViewer and QImage |
47 |
@history 2018.05.02 Jeongwoo Connect imageviewer and QSymbolEditorDialog |
|
40 | 48 |
''' |
41 | 49 |
def setupImageViewer(self): |
42 | 50 |
x = self.ui.imageViewContainer.x() |
... | ... | |
56 | 64 |
image = image.scaled(self.imgW, self.imgH) |
57 | 65 |
self.ui.imageView.setImage(image) |
58 | 66 |
self.ui.imageViewerContainerLayout.addWidget(self.ui.imageView) |
67 |
self.ui.imageView.startPointChanged.connect(self.offsetChanged) |
|
59 | 68 | |
60 | 69 |
''' |
61 | 70 |
@brief Set up Hand, Crop, ETC Tools |
... | ... | |
109 | 118 |
|
110 | 119 |
''' |
111 | 120 |
@brief Set data on forms, For modifying symbol |
121 |
@history 2018.05.02 Jeongwoo When modifying symbol, Make immediateInsertCheckBox disable |
|
112 | 122 |
''' |
113 | 123 |
def initContents(self): |
114 | 124 |
self.ui.targetDBLineEdit.setText(self.project.getPath()+'/db/ITI_PID.db') |
115 | 125 |
if self.selectedSymbol is not None: |
126 |
self.ui.immediateInsertCheckBox.setDisabled(True) |
|
127 | ||
116 | 128 |
self.ui.idLineEdit.setText(str(self.selectedSymbol.getId())) |
117 | 129 |
self.ui.nameLineEdit.setText(self.selectedSymbol.getName()) |
118 | 130 |
self.ui.thresholdLineEdit.setText(str(int(self.selectedSymbol.getThreshold() * 100))) |
... | ... | |
194 | 206 |
|
195 | 207 |
''' |
196 | 208 |
@brief Display this QDialog |
209 |
@history 2018.05.02 Jeongwoo Change return value (Single variable → Tuple) |
|
197 | 210 |
''' |
198 | 211 |
def showDialog(self): |
199 | 212 |
self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) |
200 | 213 |
#self.show() |
201 | 214 |
self.exec_() |
202 |
return self.isAccepted
|
|
215 |
return (self.isAccepted, self.ui.immediateInsertCheckBox.isChecked(), self.offsetX, self.offsetY, self.newSym)
|
|
203 | 216 |
|
204 | 217 |
''' |
205 | 218 |
@brief Using input [Name], make file name |
206 | 219 |
If the [Name] exists, add number like [FILE_NAME(1), FILE_NAME(2), ...] |
207 | 220 |
Recursive function |
221 |
@history 2018.05.02 Jeongwoo Change isExistFileName's parameter (Dir → newName) |
|
208 | 222 |
''' |
209 | 223 |
def makeFileName(self, type, originName, newName): |
210 | 224 |
imageFolderDir = self.project.getImageFilePath() |
211 | 225 |
imageDir = imageFolderDir + "/" + type + "/" + newName + ".png" |
212 | 226 |
svgFolderDir = self.project.getSvgFilePath() |
213 | 227 |
svgDir = svgFolderDir + "/" + type + "/" + newName + ".svg" |
214 |
if (os.path.exists(imageDir)) or (self.dbHelper.isExistFileName(imageDir) or (os.path.exists(svgDir))):
|
|
228 |
if (os.path.exists(imageDir)) or (self.dbHelper.isExistFileName(newName) or (os.path.exists(svgDir))):
|
|
215 | 229 |
self.FILE_NUMBER = self.FILE_NUMBER + 1 |
216 | 230 |
imgName = originName + "({})".format(self.FILE_NUMBER) |
217 | 231 |
return self.makeFileName(originName, imgName) |
... | ... | |
220 | 234 |
|
221 | 235 |
''' |
222 | 236 |
@brief Make symbol object for saving on DB |
237 |
@history 2018.05.02 Jeongwoo newSym object changed self.newSym |
|
223 | 238 |
''' |
224 | 239 |
def makeSymbolData(self): |
225 | 240 |
uid = -1 |
... | ... | |
252 | 267 | |
253 | 268 |
convertedThreshold = int(threshold) / 100.0 |
254 | 269 | |
255 |
newSym = symbol.SymbolBase(int(symId), fileName, type, convertedThreshold, int(minMatchPoint), isDetectOnOrigin |
|
270 |
self.newSym = symbol.SymbolBase(int(symId), fileName, type, convertedThreshold, int(minMatchPoint), isDetectOnOrigin
|
|
256 | 271 |
, rotationCount, ocrOption, isContainChild, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, uid) |
257 | 272 | |
258 |
return newSym |
|
273 |
return self.newSym
|
|
259 | 274 |
|
260 | 275 |
''' |
261 | 276 |
@brief Make AdditionalSymbol String |
... | ... | |
464 | 479 |
|
465 | 480 |
''' |
466 | 481 |
@brief Fit Image Tool Button Clicked |
482 |
@history 2018.05.02 Jeongwoo Method name changed(getAdjust → getOffset) |
|
483 |
Emit offsets to startPointChanged |
|
467 | 484 |
''' |
468 | 485 |
def fitImageToolClickEvent(self, event): |
469 | 486 |
print("Fit Image") |
470 | 487 |
self.ui.imageView.command = FitImageCommand.FitImageCommand(self.ui.imageView) |
471 |
adjustX, adjustY = self.ui.imageView.command.getAdjust()
|
|
488 |
adjustX, adjustY = self.ui.imageView.command.getOffset()
|
|
472 | 489 |
self.adjustOriginalPoint(adjustX, adjustY) |
473 | 490 |
self.adjustConnectionPoint(adjustX, adjustY) |
491 |
self.ui.imageView.startPointChanged.emit(adjustX, adjustY) |
|
474 | 492 |
|
475 | 493 |
''' |
476 | 494 |
@brief Guideline Check State Changed |
... | ... | |
609 | 627 |
infoTitle = self.ui.connectionPointLabel.text() |
610 | 628 |
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle)) |
611 | 629 |
|
612 |
return True, None |
|
630 |
return True, None |
|
631 | ||
632 |
''' |
|
633 |
@brief Slot for change offsets |
|
634 |
@author Jeongwoo |
|
635 |
@date 2018.05.02 |
|
636 |
''' |
|
637 |
@pyqtSlot(float, float) |
|
638 |
def offsetChanged(self, oX, oY): |
|
639 |
print('offsetX : ' + str(self.offsetX) + '->' + str(self.offsetX+oX)) |
|
640 |
print('offsetY : ' + str(self.offsetY) + '->' + str(self.offsetY+oY)) |
|
641 |
self.offsetX = self.offsetX + oX |
|
642 |
self.offsetY = self.offsetY + oY |
DTI_PID/DTI_PID/QtImageViewer.py | ||
---|---|---|
47 | 47 |
leftMouseButtonDoubleClicked = pyqtSignal(float, float) |
48 | 48 |
rightMouseButtonDoubleClicked = pyqtSignal(float, float) |
49 | 49 |
itemRemoved = pyqtSignal(SymbolSvgItem) |
50 |
startPointChanged = pyqtSignal(float, float) |
|
50 | 51 | |
51 | 52 |
def __init__(self): |
52 | 53 |
QGraphicsView.__init__(self) |
DTI_PID/DTI_PID/SG_DbHelper.py | ||
---|---|---|
129 | 129 |
else: |
130 | 130 |
return False |
131 | 131 | |
132 |
def isExistFileName(self, imageDir): |
|
132 |
''' |
|
133 |
@history 2018.05.02 Jeongwoo Parameter and WHERE changed (path → name) |
|
134 |
''' |
|
135 |
def isExistFileName(self, name): |
|
133 | 136 |
rows = None |
134 | 137 |
try: |
135 | 138 |
conn = sqlite3.connect(self.dbFullPath) |
136 | 139 |
cursor = conn.cursor() |
137 |
sql = "SELECT * FROM Symbol WHERE path = '"+ imageDir +"'"
|
|
140 |
sql = "SELECT * FROM Symbol WHERE name = '"+ name +"'"
|
|
138 | 141 |
cursor.execute(sql) |
139 | 142 |
rows = cursor.fetchall() |
140 | 143 |
except Error as e: |
... | ... | |
146 | 149 |
else: |
147 | 150 |
return False |
148 | 151 | |
152 |
''' |
|
153 |
@history 2018.05.02 Jeongwoo Fix bug : symbol.getIsExceptDetect → symbol.getIsExceptDetect() |
|
154 |
''' |
|
149 | 155 |
def insertSymbol(self, symbol): |
150 | 156 |
isAdded = False |
151 | 157 |
try: |
... | ... | |
156 | 162 |
, symbol.getMinMatchCount(), symbol.getIsDetectOnOrigin(), symbol.getRotationCount() |
157 | 163 |
, symbol.getOcrOption(), symbol.getIsContainChild() |
158 | 164 |
, symbol.getOriginalPoint(), symbol.getConnectionPoint() |
159 |
, symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect) |
|
165 |
, symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getIsExceptDetect())
|
|
160 | 166 |
cursor.execute(self.INSERT_SYMBOL_SQL, query) |
161 | 167 |
conn.commit() |
162 | 168 |
isAdded = True |
DTI_PID/DTI_PID/SymbolGenerator.py | ||
---|---|---|
276 | 276 |
print("area zoom tool clicked") |
277 | 277 |
self.imageView.command = AreaZoomCommand.AreaZoomCommand(self.imageView) |
278 | 278 | |
279 |
''' |
|
280 |
@history 2018.05.02 Jeongwoo Return value changed (Single variable → Tuple) |
|
281 |
''' |
|
279 | 282 |
def nextStepToolClickEvent(self, event): |
280 | 283 |
print("next step tool clicked") |
281 | 284 |
if self.imageView.hasImage(): |
282 | 285 |
self.symbolEditorDialog = QSymbolEditorDialog.QSymbolEditorDialog(self.imageView, self.imageView.image(), self.project) |
283 |
isSymbolAdded = self.symbolEditorDialog.showDialog()
|
|
286 |
(isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = self.symbolEditorDialog.showDialog()
|
|
284 | 287 |
|
285 |
if isSymbolAdded:
|
|
288 |
if isAccepted:
|
|
286 | 289 |
self.initTreeWidget(self.project) |
287 | 290 |
else: |
288 | 291 |
QMessageBox.about(self.topWidget, "알림", "이미지를 선택한 후 다시 시도해주세요.") |
DTI_PID/DTI_PID/UI/SymbolEditor.ui | ||
---|---|---|
599 | 599 |
</property> |
600 | 600 |
</widget> |
601 | 601 |
</item> |
602 |
<item row="19" column="0"> |
|
603 |
<widget class="QLabel" name="immediateInsertLabel"> |
|
604 |
<property name="font"> |
|
605 |
<font> |
|
606 |
<weight>75</weight> |
|
607 |
<bold>true</bold> |
|
608 |
</font> |
|
609 |
</property> |
|
610 |
<property name="text"> |
|
611 |
<string>즉시 삽입 여부 |
|
612 |
(심볼 생성 시)</string> |
|
613 |
</property> |
|
614 |
</widget> |
|
615 |
</item> |
|
616 |
<item row="19" column="1"> |
|
617 |
<widget class="QCheckBox" name="immediateInsertCheckBox"> |
|
618 |
<property name="text"> |
|
619 |
<string/> |
|
620 |
</property> |
|
621 |
</widget> |
|
622 |
</item> |
|
602 | 623 |
</layout> |
603 | 624 |
</item> |
604 | 625 |
</layout> |
DTI_PID/DTI_PID/UI_SymbolEditor.py | ||
---|---|---|
315 | 315 |
self.isExceptDetectCheckBox.setText("") |
316 | 316 |
self.isExceptDetectCheckBox.setObjectName("isExceptDetectCheckBox") |
317 | 317 |
self.formLayout.setWidget(18, QtWidgets.QFormLayout.FieldRole, self.isExceptDetectCheckBox) |
318 |
self.immediateInsertLabel = QtWidgets.QLabel(self.scrollAreaWidgetContents) |
|
319 |
font = QtGui.QFont() |
|
320 |
font.setBold(True) |
|
321 |
font.setWeight(75) |
|
322 |
self.immediateInsertLabel.setFont(font) |
|
323 |
self.immediateInsertLabel.setObjectName("immediateInsertLabel") |
|
324 |
self.formLayout.setWidget(19, QtWidgets.QFormLayout.LabelRole, self.immediateInsertLabel) |
|
325 |
self.immediateInsertCheckBox = QtWidgets.QCheckBox(self.scrollAreaWidgetContents) |
|
326 |
self.immediateInsertCheckBox.setText("") |
|
327 |
self.immediateInsertCheckBox.setObjectName("immediateInsertCheckBox") |
|
328 |
self.formLayout.setWidget(19, QtWidgets.QFormLayout.FieldRole, self.immediateInsertCheckBox) |
|
318 | 329 |
self.gridLayout_4.addLayout(self.formLayout, 0, 0, 1, 1) |
319 | 330 |
self.scrollArea.setWidget(self.scrollAreaWidgetContents) |
320 | 331 |
self.verticalLayout.addWidget(self.scrollArea) |
... | ... | |
361 | 372 |
self.addConnectionPointButton.setText(_translate("Dialog", "추가")) |
362 | 373 |
self.typeLabel.setText(_translate("Dialog", "심볼 타입")) |
363 | 374 |
self.isExceptDetectLabel.setText(_translate("Dialog", "검출 미포함 여부")) |
375 |
self.immediateInsertLabel.setText(_translate("Dialog", "즉시 삽입 여부\n" |
|
376 |
"(심볼 생성 시)")) |
|
364 | 377 | |
365 | 378 | |
366 | 379 |
if __name__ == "__main__": |
내보내기 Unified diff