1
|
|
2
|
|
3
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
4
|
from PyQt5.QtCore import pyqtSlot, QRectF
|
5
|
from PyQt5.QtWidgets import *
|
6
|
from PyQt5.QtGui import *
|
7
|
from QtImageViewer import QtImageViewer
|
8
|
import os
|
9
|
import sqlite3
|
10
|
import sys
|
11
|
import symbol, SymbolBase
|
12
|
import potrace
|
13
|
import numpy as np
|
14
|
import cv2
|
15
|
|
16
|
import SymbolEditor_UI
|
17
|
from AppDocData import *
|
18
|
|
19
|
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands')
|
20
|
import CropCommand, HandCommand, ZoomCommand, PenCommand, EraserCommand, AreaEraserCommand, OriginalPointCommand, ConnectionPointCommand, AreaZoomCommand, FitImageCommand, RemoveTextCommand, RotateImageCommand, FlipImageCommand
|
21
|
|
22
|
|
23
|
class QSymbolEditorDialog(QDialog):
|
24
|
FILE_NUMBER = 0
|
25
|
|
26
|
'''
|
27
|
@history 2018.05.02 Jeongwoo Add variables (self.offsetX, self.offsetY, self.newSym)
|
28
|
2018.05.03 Jeongwoo Remove parameter in SG_DbHelper()
|
29
|
Remove self.dbHelper variable
|
30
|
2018.07.03 Yecheol Rename File, Is Instrument Label added
|
31
|
'''
|
32
|
def __init__(self, parent, image, project, selectedSymbol = None):
|
33
|
QDialog.__init__(self, parent)
|
34
|
|
35
|
try:
|
36
|
self.image = image
|
37
|
self.selectedSymbol = selectedSymbol
|
38
|
self.project = project
|
39
|
self.ui = SymbolEditor_UI.Ui_Dialog()
|
40
|
self.ui.setupUi(self)
|
41
|
self.ui.tableWidgetConnList.setColumnCount(2)
|
42
|
self.ui.tableWidgetConnList.setHorizontalHeaderLabels(['위치', '방향'])
|
43
|
self.ui.tableWidgetConnList.horizontalHeaderItem(0).setSizeHint(QSize(25, 25))
|
44
|
self.ui.tableWidgetConnList.itemPressed.connect(self.onConnPtPressed)
|
45
|
|
46
|
self.setupImageViewer()
|
47
|
self.setupTools()
|
48
|
self.initForms()
|
49
|
self.initContents()
|
50
|
self.isAccepted = False
|
51
|
self.offsetX = 0
|
52
|
self.offsetY = 0
|
53
|
self.newSym = None
|
54
|
|
55
|
self.setWindowTitle('심볼 편집기')
|
56
|
except Exception as ex:
|
57
|
from App import App
|
58
|
|
59
|
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
|
60
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
61
|
|
62
|
'''
|
63
|
@brief hilight pressed connector item
|
64
|
@author humkyung
|
65
|
@date 2018.08.31
|
66
|
'''
|
67
|
def onConnPtPressed(self, item):
|
68
|
data = item.data(Qt.UserRole)
|
69
|
if data is not None:
|
70
|
for row in range(self.ui.tableWidgetConnList.rowCount()):
|
71
|
item = self.ui.tableWidgetConnList.item(row, 0)
|
72
|
item.data(Qt.UserRole).hoverLeaveEvent(None)
|
73
|
|
74
|
data.hoverEnterEvent(None)
|
75
|
|
76
|
def convertQImageToMat(self, incomingImage):
|
77
|
''' Converts a QImage into an opencv MAT format '''
|
78
|
|
79
|
try:
|
80
|
incomingImage = incomingImage.convertToFormat(QImage.Format_RGBA8888)
|
81
|
|
82
|
width = incomingImage.width()
|
83
|
height = incomingImage.height()
|
84
|
|
85
|
ptr = incomingImage.bits()
|
86
|
ptr.setsize(incomingImage.byteCount())
|
87
|
arr = np.array(ptr).reshape(height, width, 4)
|
88
|
return arr
|
89
|
except Exception as ex:
|
90
|
from App import App
|
91
|
|
92
|
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
|
93
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
94
|
|
95
|
'''
|
96
|
@brief Set up QtImageViewer and QImage
|
97
|
@history 2018.05.02 Jeongwoo Connect imageviewer and QSymbolEditorDialog
|
98
|
'''
|
99
|
def setupImageViewer(self):
|
100
|
from MainWindow import MainWindow
|
101
|
|
102
|
x = self.ui.imageViewContainer.x()
|
103
|
y = self.ui.imageViewContainer.y()
|
104
|
width = self.ui.imageViewContainer.frameGeometry().width()
|
105
|
height = self.ui.imageViewContainer.frameGeometry().height()
|
106
|
self.ui.imageView = QtImageViewer(MainWindow.instance())
|
107
|
self.ui.imageView.guidesEnabled = True
|
108
|
self.ui.imageView.setGeometry(QtCore.QRect(0, y, height, height))
|
109
|
self.ui.imageView.aspectRatioMode = QtCore.Qt.KeepAspectRatio
|
110
|
self.ui.imageView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
|
111
|
self.ui.imageView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
|
112
|
self.ui.imageView.canZoom = True
|
113
|
self.ui.imageView.canPan = True
|
114
|
image = self.image.copy()
|
115
|
self.imgW = image.width()
|
116
|
self.imgH = image.height()
|
117
|
image = image.scaled(self.imgW, self.imgH)
|
118
|
self.ui.imageView.setImage(image)
|
119
|
self.ui.imageViewerContainerLayout.addWidget(self.ui.imageView)
|
120
|
self.ui.imageView.startPointChanged.connect(self.offsetChanged)
|
121
|
|
122
|
'''
|
123
|
@brief Set up Hand, Crop, ETC Tools
|
124
|
@history 2018.05.03 Jeongwoo Add connection for removeTextButton
|
125
|
2018.06.11 Jeongwoo Add connection for rotation and flip
|
126
|
'''
|
127
|
def setupTools(self):
|
128
|
self.ui.handButton.clicked.connect(self.handToolClickEvent)
|
129
|
self.ui.cropButton.clicked.connect(self.cropToolClickEvent)
|
130
|
self.ui.penButton.clicked.connect(self.penToolClickEvent)
|
131
|
self.ui.penWidthSpinBox.valueChanged.connect(self.penWidthChangedEvent)
|
132
|
self.ui.eraserButton.clicked.connect(self.eraserToolClickEvent)
|
133
|
self.ui.eraserSpinBox.valueChanged.connect(self.eraserWidthChangedEvent)
|
134
|
self.ui.areaEraserButton.clicked.connect(self.areaEraserToolClickEvent)
|
135
|
self.ui.fitImageButton.clicked.connect(self.fitImageToolClickEvent)
|
136
|
self.ui.zoomButton.clicked.connect(self.zoomToolClickEvent)
|
137
|
self.ui.areaZoomButton.clicked.connect(self.areaZoomToolClickEvent)
|
138
|
self.ui.initZoomButton.clicked.connect(self.zoomInitToolClickEvent)
|
139
|
self.ui.guidelineCheckbox.stateChanged.connect(self.guidelineStateChangedEvent)
|
140
|
self.ui.removeTextButton.clicked.connect(self.removeTextClickEvent)
|
141
|
self.ui.rotateLeftButton.clicked.connect(self.rotateLeftClickEvent)
|
142
|
self.ui.rotateRightButton.clicked.connect(self.rotateRightClickEvent)
|
143
|
self.ui.flipHorizontalButton.clicked.connect(self.flipHorizontalClickEvent)
|
144
|
self.ui.flipVerticalButton.clicked.connect(self.flipVerticalClickEvent)
|
145
|
self.ui.pushButtonDelConnPt.clicked.connect(self.onDeleteConnPt)
|
146
|
|
147
|
'''
|
148
|
@brief Init Forms with type and default values
|
149
|
'''
|
150
|
def initForms(self):
|
151
|
self.ui.thresholdLineEdit.setValidator(QRegExpValidator(QtCore.QRegExp("^[0-9]\d+$")))
|
152
|
self.ui.minMatchPointLineEdit.setValidator(QRegExpValidator(QtCore.QRegExp("^[0-9]\d+$")))
|
153
|
self.initDefaultSymbolDirectionComboBoxItems()
|
154
|
self.ui.addAdditionalSymbolButton.clicked.connect(self.addAdditionalSymbolEvent)
|
155
|
self.ui.addOriginalPointButton.clicked.connect(self.addOriginalPoint)
|
156
|
self.ui.addConnectionPointButton.clicked.connect(self.addConnectionPoint)
|
157
|
self.initSymbolTypeComboBoxItems()
|
158
|
self.initBaseSymbolComboBoxItems(None)
|
159
|
self.initAdditionalSymbolComboBoxItems()
|
160
|
|
161
|
'''
|
162
|
@brief Init Symbol Type ComboBox Items
|
163
|
@author Jeongwoo
|
164
|
@date 2018.04.06
|
165
|
'''
|
166
|
def initSymbolTypeComboBoxItems(self):
|
167
|
for item in AppDocData.instance().getSymbolTypeComboBoxItems():
|
168
|
self.ui.typeComboBox.addItem(item[2])
|
169
|
self.ui.typeComboBox.currentTextChanged.connect(self.symbolTypeTextChagedEvent)
|
170
|
|
171
|
def symbolTypeTextChagedEvent(self, value):
|
172
|
self.initBaseSymbolComboBoxItems(value)
|
173
|
|
174
|
'''
|
175
|
@brief Set data on forms, For modifying symbol
|
176
|
@history 2018.05.02 Jeongwoo When modifying symbol, Make immediateInsertCheckBox disable
|
177
|
2018.07.04 Yecheol Remove is Symbol ID(idLineEdit)
|
178
|
'''
|
179
|
def initContents(self):
|
180
|
if self.selectedSymbol is not None:
|
181
|
self.ui.immediateInsertCheckBox.setDisabled(True)
|
182
|
|
183
|
self.ui.nameLineEdit.setText(self.selectedSymbol.getName())
|
184
|
self.ui.thresholdLineEdit.setText(str(int(self.selectedSymbol.getThreshold() * 100)))
|
185
|
self.ui.minMatchPointLineEdit.setText(str(self.selectedSymbol.getMinMatchCount()))
|
186
|
self.ui.rotationCountSpinBox.setValue(self.selectedSymbol.getRotationCount())
|
187
|
self.ui.isContainChildCheckBox.setChecked(True if self.selectedSymbol.getIsContainChild() else False)
|
188
|
self.ui.typeComboBox.setCurrentIndex(self.ui.typeComboBox.findText(self.selectedSymbol.getType()))
|
189
|
self.ui.baseSymbolComboBox.setCurrentIndex(self.ui.baseSymbolComboBox.findText(self.selectedSymbol.getBaseSymbol()))
|
190
|
self.ui.isExceptDetectCheckBox.setChecked(True if self.selectedSymbol.getIsExceptDetect() else False)
|
191
|
|
192
|
self.ui.hasInstrumentLabelCheckBox.setChecked(True if self.selectedSymbol.getHasInstrumentLabel() else False)
|
193
|
|
194
|
additionalSymbol = self.selectedSymbol.getAdditionalSymbol()
|
195
|
if additionalSymbol is not None and len(additionalSymbol) > 0:
|
196
|
splitAdditionalSymbolList = additionalSymbol.split("/")
|
197
|
for symString in splitAdditionalSymbolList:
|
198
|
splitSymString = symString.split(",")
|
199
|
self.addAdditionalSymbol(splitSymString[0], splitSymString[1])
|
200
|
|
201
|
originalPoint = self.selectedSymbol.getOriginalPoint()
|
202
|
self.ui.originalPointLineEdit.setText(originalPoint)
|
203
|
OriginalPointCommand.OriginalPointCommand.drawCircle(self.ui.imageView, originalPoint.split(",")[0], originalPoint.split(",")[1])
|
204
|
self.ui.imageView.isOriginalPointSelected = True
|
205
|
|
206
|
connectionPoint = self.selectedSymbol.getConnectionPoint()
|
207
|
if connectionPoint is not None and len(connectionPoint) > 0:
|
208
|
splitConnectionPointList = connectionPoint.split("/")
|
209
|
|
210
|
self.ui.tableWidgetConnList.setRowCount(len(splitConnectionPointList))
|
211
|
row = 0
|
212
|
for conString in splitConnectionPointList:
|
213
|
direction = 'AUTO'
|
214
|
tokens = conString.split(',')
|
215
|
if len(tokens) == 3:
|
216
|
direction = tokens[0]
|
217
|
x = tokens[1]
|
218
|
y = tokens[2]
|
219
|
elif len(tokens) == 2:
|
220
|
x = tokens[0]
|
221
|
y = tokens[1]
|
222
|
|
223
|
conn = ConnectionPointCommand.ConnectionPointCommand.drawCircle(self.ui.imageView, x, y)
|
224
|
|
225
|
item = QTableWidgetItem('{},{}'.format(x, y))
|
226
|
item.setFlags(Qt.ItemIsEnabled)
|
227
|
item.setData(Qt.UserRole, conn)
|
228
|
self.ui.tableWidgetConnList.setItem(row, 0, item)
|
229
|
|
230
|
directionComboBox = QComboBox(self.ui.tableWidgetConnList)
|
231
|
directionComboBox.addItems(['AUTO', 'LEFT', 'RIGHT', 'UP', 'DOWN'])
|
232
|
directionComboBox.setCurrentText(direction)
|
233
|
|
234
|
self.ui.tableWidgetConnList.setCellWidget(row, 1, directionComboBox)
|
235
|
|
236
|
row = row + 1
|
237
|
|
238
|
'''
|
239
|
@brief Init ComboBox Items For Direction of DB Field [additionalSymbol]
|
240
|
'''
|
241
|
def initDefaultSymbolDirectionComboBoxItems(self):
|
242
|
for item in AppDocData.instance().getDefaultSymbolDirectionComboBoxItems():
|
243
|
self.ui.defaultSymbolDirectionComboBox.addItem(item[0], item[1])
|
244
|
|
245
|
'''
|
246
|
@brief Init ComboBox Items For DB Field [baseSymbol]
|
247
|
'''
|
248
|
def initBaseSymbolComboBoxItems(self, type):
|
249
|
self.ui.baseSymbolComboBox.clear()
|
250
|
for item in AppDocData.instance().getBaseSymbolComboBoxItems(type):
|
251
|
self.ui.baseSymbolComboBox.addItem(item)
|
252
|
|
253
|
'''
|
254
|
@brief Init ComboBox Items For symbolName of DB Field [additionalSymbol]
|
255
|
'''
|
256
|
def initAdditionalSymbolComboBoxItems(self):
|
257
|
for name in AppDocData.instance().getAdditionalSymbolComboBoxItems():
|
258
|
self.ui.additionalSymbolComboBox.addItem(name)
|
259
|
|
260
|
'''
|
261
|
@brief remove ConnectionPoint Circles (Using for loop)
|
262
|
'''
|
263
|
def removeConnectionPointCircles(self, circlePointList):
|
264
|
for circlePoint in circlePointList:
|
265
|
self.removeConnectionPointCircle(circlePoint)
|
266
|
|
267
|
'''
|
268
|
@brief remove each ConnectionPoint Circle
|
269
|
@history 2018.06.12 Jeongwoo Add conditions for selecting ellipse item
|
270
|
'''
|
271
|
def removeConnectionPointCircle(self, circlePoint):
|
272
|
from EngineeringConnectorItem import QEngineeringConnectorItem
|
273
|
|
274
|
imageWidth = self.ui.imageView.image().width()
|
275
|
imageHeight = self.ui.imageView.image().height()
|
276
|
items = [item for item in self.ui.imageView.scene.items(QRectF(float(circlePoint.x())-0.5, float(circlePoint.y())-0.5, 1, 1)) \
|
277
|
if type(item) is QEngineeringConnectorItem]
|
278
|
for item in items:
|
279
|
self.ui.imageView.scene.removeItem(item)
|
280
|
|
281
|
'''^
|
282
|
@brief Display this QDialog
|
283
|
@history 2018.05.02 Jeongwoo Change return value (Single variable → Tuple)
|
284
|
'''
|
285
|
def showDialog(self):
|
286
|
self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint)
|
287
|
self.exec_()
|
288
|
return (self.isAccepted, self.ui.immediateInsertCheckBox.isChecked(), self.offsetX, self.offsetY, self.newSym)
|
289
|
|
290
|
'''
|
291
|
@brief Using input [Name], make file name
|
292
|
If the [Name] exists, add number like [FILE_NAME(1), FILE_NAME(2), ...]
|
293
|
Recursive function
|
294
|
@history 2018.05.02 Jeongwoo Change isExistFileName's parameter (Dir → newName)
|
295
|
2018.05.03 Jeongwoo Change self.dbHelper to AppDocData
|
296
|
'''
|
297
|
def makeFileName(self, type, originName, newName):
|
298
|
imageFolderDir = self.project.getImageFilePath()
|
299
|
imageDir = os.path.join(imageFolderDir, type, newName + '.png')
|
300
|
svgFolderDir = self.project.getSvgFilePath()
|
301
|
svgDir = os.path.join(svgFolderDir, type, newName + '.svg')
|
302
|
if (os.path.exists(imageDir)) or (AppDocData.instance().isExistFileName(newName) or (os.path.exists(svgDir))):
|
303
|
self.FILE_NUMBER = self.FILE_NUMBER + 1
|
304
|
imgName = originName + "({})".format(self.FILE_NUMBER)
|
305
|
return self.makeFileName(type, originName, imgName)
|
306
|
else:
|
307
|
return newName
|
308
|
|
309
|
'''
|
310
|
@brief Make symbol object for saving on DB
|
311
|
@history 2018.05.02 Jeongwoo newSym object changed self.newSym
|
312
|
'''
|
313
|
def makeSymbolData(self, width, height):
|
314
|
uid = -1
|
315
|
if self.selectedSymbol is not None:
|
316
|
uid = self.selectedSymbol.getUid()
|
317
|
|
318
|
name = self.ui.nameLineEdit.text()
|
319
|
type = self.ui.typeComboBox.currentText()
|
320
|
self.FILE_NUMBER = 0
|
321
|
lastName = ""
|
322
|
if self.selectedSymbol is not None:
|
323
|
lastName = self.selectedSymbol.getName()
|
324
|
fileName = ""
|
325
|
if name == lastName:
|
326
|
fileName = name
|
327
|
else:
|
328
|
fileName = self.makeFileName(type, name, name)
|
329
|
threshold = self.ui.thresholdLineEdit.text()
|
330
|
minMatchPoint = self.ui.minMatchPointLineEdit.text()
|
331
|
rotationCount = self.ui.rotationCountSpinBox.value()
|
332
|
ocrOption = 0
|
333
|
isContainChild = 1 if self.ui.isContainChildCheckBox.isChecked() else 0
|
334
|
originalPoint = self.ui.originalPointLineEdit.text()
|
335
|
connectionPoint = self.makeConnectionPointListString()
|
336
|
baseSymbol = self.ui.baseSymbolComboBox.currentText()
|
337
|
additionalSymbol = self.makeAdditionalSymbolListString()
|
338
|
isExceptDetect = 1 if self.ui.isExceptDetectCheckBox.isChecked() else 0
|
339
|
|
340
|
hasInstrumentLabel = 1 if self.ui.hasInstrumentLabelCheckBox.isChecked() else 0
|
341
|
|
342
|
convertedThreshold = int(threshold) / 100.0
|
343
|
|
344
|
imageWidth = width
|
345
|
iamgeHeight = height
|
346
|
|
347
|
self.newSym = symbol.SymbolBase(fileName, type, convertedThreshold, int(minMatchPoint), True,
|
348
|
rotationCount, ocrOption, isContainChild, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, hasInstrumentLabel, uid, imageWidth, iamgeHeight)
|
349
|
|
350
|
return self.newSym
|
351
|
|
352
|
'''
|
353
|
@brief Make AdditionalSymbol String
|
354
|
[AdditionalSymbolString = DIRECTION,SYMBOL_NAME/DIRECTION,SYMBOL_NAME/...]
|
355
|
'''
|
356
|
def makeAdditionalSymbolListString(self):
|
357
|
ret = ""
|
358
|
listItems = []
|
359
|
for index in range(self.ui.additionalSymbolListWidget.count()):
|
360
|
listItems.append(self.ui.additionalSymbolListWidget.item(index))
|
361
|
if listItems is not None:
|
362
|
for index in range(len(listItems)):
|
363
|
item = listItems[index]
|
364
|
text = item.text()
|
365
|
if index != 0:
|
366
|
ret = ret + "/"
|
367
|
ret = ret + text
|
368
|
return ret
|
369
|
|
370
|
'''
|
371
|
@brief Make ConnectionPoint String
|
372
|
[ConnectionPointString = U,x1,y1/D,x2,y2/...]
|
373
|
'''
|
374
|
def makeConnectionPointListString(self):
|
375
|
res = ""
|
376
|
|
377
|
connPtStringList = []
|
378
|
for row in range(self.ui.tableWidgetConnList.rowCount()):
|
379
|
direction = self.ui.tableWidgetConnList.cellWidget(row, 1).currentText()
|
380
|
|
381
|
connPtString = '{},{}'.format(direction, self.ui.tableWidgetConnList.item(row, 0).text())
|
382
|
connPtStringList.append(connPtString)
|
383
|
|
384
|
res = '/'.join(connPtStringList)
|
385
|
|
386
|
return res
|
387
|
|
388
|
'''
|
389
|
@brief Called when Save Button Clicked
|
390
|
Validation Check → Make Symbol Data → Insert Symbol Data into DB → Save png and svg files
|
391
|
@history 2018.05.03 Jeongwoo Change parameters on method 'deleteImageAndSvg'
|
392
|
Change self.dbHelper to AppDocData
|
393
|
'''
|
394
|
def accept(self):
|
395
|
isValid, exceptionMsg = self.isValidSymbolInfo()
|
396
|
if isValid:
|
397
|
if self.selectedSymbol is None:
|
398
|
isSuccess, fileType, fileName, imagePath = AppDocData.instance().insertSymbol(self.makeSymbolData(self.ui.imageView.image().width(), self.ui.imageView.image().height()))
|
399
|
else:
|
400
|
isSuccess, fileType, fileName, imagePath = AppDocData.instance().updateSymbol(self.makeSymbolData(self.ui.imageView.image().width(), self.ui.imageView.image().height()))
|
401
|
|
402
|
if isSuccess:
|
403
|
try:
|
404
|
image = self.ui.imageView.image()
|
405
|
if image is not None:
|
406
|
if self.selectedSymbol is not None:
|
407
|
self.deleteImageAndSvg(self.selectedSymbol.getImageFileFullPath(), self.selectedSymbol.getSvgFileFullPath())
|
408
|
imageLocation = os.path.join(self.project.getImageFilePath(), fileType)
|
409
|
if not os.path.exists(imageLocation):
|
410
|
os.makedirs(imageLocation)
|
411
|
|
412
|
image.save(imagePath, 'PNG')
|
413
|
|
414
|
svgLocation = os.path.join(self.project.getSvgFilePath(), fileType)
|
415
|
if not os.path.exists(svgLocation):
|
416
|
os.makedirs(svgLocation)
|
417
|
potrace.convertImageToSvg(imagePath, svgLocation + "/" + fileName + ".svg")
|
418
|
self.isAccepted = True
|
419
|
QDialog.accept(self)
|
420
|
except:
|
421
|
if self.selectedSymbol is None:
|
422
|
self.resetInsertSymbol(imagePath, fileName)
|
423
|
else:
|
424
|
self.resetUpdateSymbol(imagePath, fileName)
|
425
|
self.isAccepted = False
|
426
|
QMessageBox.about(self.ui.buttonBox, "알림", "심볼 저장 과정 중 문제가 발생했습니다.")
|
427
|
else:
|
428
|
QMessageBox.about(self.ui.buttonBox, "알림", "심볼 저장 과정 중 문제가 발생했습니다.")
|
429
|
else:
|
430
|
print("invalid symbol info")
|
431
|
QMessageBox.about(self.ui.buttonBox, "알림", exceptionMsg)
|
432
|
|
433
|
'''
|
434
|
@brief Called When Close Button Clicked
|
435
|
'''
|
436
|
def reject(self):
|
437
|
self.isAccepted = False
|
438
|
QDialog.reject(self)
|
439
|
|
440
|
'''
|
441
|
@history 2018.05.03 Jeongwoo Change Parameters (imagePath, type, name → imagePath, svgPath)
|
442
|
'''
|
443
|
def deleteImageAndSvg(self, imagePath, svgPath):
|
444
|
if os.path.exists(imagePath):
|
445
|
os.remove(imagePath)
|
446
|
|
447
|
if os.path.exists(svgPath):
|
448
|
os.remove(svgPath)
|
449
|
|
450
|
'''
|
451
|
@brief Called When error occured while saving png and svg files
|
452
|
Delete png, svg files and record from DB
|
453
|
@history 2018.05.03 Jeongwoo Change Parameters and fileName variable
|
454
|
'''
|
455
|
def resetInsertSymbol(self, imagePath, svgPath):
|
456
|
self.deleteImageAndSvg(imagePath, svgPath)
|
457
|
|
458
|
fileName = os.path.basename(imagePath.replace('.png', ''))
|
459
|
AppDocData.instance().deleteSymbol(fileName)
|
460
|
|
461
|
'''
|
462
|
@history 2018.05.03 Jeongwoo Change Parameters
|
463
|
Change self.dbHelper to AppDocData
|
464
|
'''
|
465
|
def resetUpdateSymbol(self, imagePath, svgPath):
|
466
|
self.deleteImageAndSvg(imagePath, svgPath)
|
467
|
|
468
|
AppDocData.instance().updateSymbol(self.selectedSymbol)
|
469
|
|
470
|
'''
|
471
|
@history 2018.06.12 Jeongwoo coords type changed (int → float)
|
472
|
'''
|
473
|
def keyPressEvent(self, event):
|
474
|
if event.key() == QtCore.Qt.Key_Delete:
|
475
|
if self.ui.tableWidgetConnList.hasFocus():
|
476
|
model = self.ui.tableWidgetConnList.model()
|
477
|
|
478
|
item = self.ui.tableWidgetConnList.currentItem()
|
479
|
if item is not None:
|
480
|
item = self.ui.tableWidgetConnList.item(item.row(), 0)
|
481
|
data = item.data(Qt.UserRole)
|
482
|
if data is not None:
|
483
|
self.ui.imageView.scene.removeItem(data)
|
484
|
model.removeRow(item.row())
|
485
|
elif self.ui.additionalSymbolListWidget.hasFocus():
|
486
|
selectedItems = self.ui.additionalSymbolListWidget.selectedItems()
|
487
|
if selectedItems is not None:
|
488
|
for item in selectedItems:
|
489
|
self.ui.additionalSymbolListWidget.takeItem(self.ui.additionalSymbolListWidget.row(item))
|
490
|
|
491
|
'''
|
492
|
@brief Hand Tool Button Clicked
|
493
|
'''
|
494
|
def handToolClickEvent(self, event):
|
495
|
self.ui.imageView.command = HandCommand.HandCommand(self.ui.imageView)
|
496
|
|
497
|
'''
|
498
|
@brief Crop Tool Button Clicked
|
499
|
@history 2018.06.11 Jeongwoo init original/connection points and guide line refresh
|
500
|
'''
|
501
|
def cropToolClickEvent(self, event):
|
502
|
self.initOriginalAndConnectionPoint()
|
503
|
self.ui.imageView.command = CropCommand.CropCommand(self.ui.imageView)
|
504
|
self.guidelineStateChangedEvent(None)
|
505
|
|
506
|
'''
|
507
|
@brief Zoom Init Tool Button Clicked
|
508
|
'''
|
509
|
def zoomInitToolClickEvent(self, event):
|
510
|
self.ui.imageView.command = None
|
511
|
self.ui.imageView.zoomImageInit()
|
512
|
|
513
|
'''
|
514
|
@brief Area Zoom Tool Button Clicked
|
515
|
'''
|
516
|
def areaZoomToolClickEvent(self, event):
|
517
|
self.ui.imageView.command = AreaZoomCommand.AreaZoomCommand(self.ui.imageView)
|
518
|
|
519
|
'''
|
520
|
@brief Zoom Tool Button Clicked
|
521
|
'''
|
522
|
def zoomToolClickEvent(self, event):
|
523
|
self.ui.imageView.command = ZoomCommand.ZoomCommand(self.ui.imageView)
|
524
|
|
525
|
'''
|
526
|
@brief Pen Tool Button Clicked
|
527
|
'''
|
528
|
def penToolClickEvent(self, event):
|
529
|
width = self.ui.toolWidget.findChild(QSpinBox, 'penWidthSpinBox').value()
|
530
|
self.ui.imageView.command = PenCommand.PenCommand(self.ui.imageView)
|
531
|
self.ui.imageView.command.width = width
|
532
|
|
533
|
'''
|
534
|
@brief Pen Width Value Changed
|
535
|
'''
|
536
|
def penWidthChangedEvent(self, value):
|
537
|
if self.ui.imageView.command is not None and type(self.ui.imageView.command) is PenCommand.PenCommand:
|
538
|
self.ui.imageView.command.width = value
|
539
|
|
540
|
'''
|
541
|
@brief Eraser Tool Button Clicked
|
542
|
'''
|
543
|
def eraserToolClickEvent(self, event):
|
544
|
width = self.ui.toolWidget.findChild(QSpinBox, 'eraserSpinBox').value()
|
545
|
self.ui.imageView.command = EraserCommand.EraserCommand(self.ui.imageView)
|
546
|
self.ui.imageView.command.width = width
|
547
|
|
548
|
'''
|
549
|
@brief Eraser Width Value Changed
|
550
|
'''
|
551
|
def eraserWidthChangedEvent(self, value):
|
552
|
if self.ui.imageView.command is not None and type(self.ui.imageView.command) is EraserCommand.EraserCommand:
|
553
|
self.ui.imageView.command.width = value
|
554
|
|
555
|
'''
|
556
|
@brief Area Eraser Tool Button Clicked
|
557
|
'''
|
558
|
def areaEraserToolClickEvent(self, event):
|
559
|
self.ui.imageView.command = AreaEraserCommand.AreaEraserCommand(self.ui.imageView)
|
560
|
|
561
|
'''
|
562
|
@brief Fit Image Tool Button Clicked
|
563
|
@history 2018.05.02 Jeongwoo Method name changed(getAdjust → getOffset)
|
564
|
Emit offsets to startPointChanged
|
565
|
2018.06.11 Jeongwoo init original/connection points
|
566
|
'''
|
567
|
def fitImageToolClickEvent(self, event):
|
568
|
self.initOriginalAndConnectionPoint()
|
569
|
self.ui.imageView.command = FitImageCommand.FitImageCommand(self.ui.imageView)
|
570
|
adjustX, adjustY = self.ui.imageView.command.getOffset()
|
571
|
self.ui.imageView.startPointChanged.emit(adjustX, adjustY)
|
572
|
|
573
|
'''
|
574
|
@brief Guideline Check State Changed
|
575
|
'''
|
576
|
def guidelineStateChangedEvent(self, value):
|
577
|
if self.ui.guidelineCheckbox.isChecked():
|
578
|
self.ui.imageView.showGuideline(None, True)
|
579
|
else:
|
580
|
self.ui.imageView.showGuideline(None, False)
|
581
|
|
582
|
'''
|
583
|
@brief Add AdditionalSymbol String on ListWidget Listener
|
584
|
'''
|
585
|
def addAdditionalSymbolEvent(self, event):
|
586
|
additionalSymbolIndex = self.ui.additionalSymbolComboBox.currentIndex()
|
587
|
if additionalSymbolIndex != 0:
|
588
|
direction = self.ui.defaultSymbolDirectionComboBox.currentText()
|
589
|
symbolName = self.ui.additionalSymbolComboBox.currentText()
|
590
|
self.addAdditionalSymbol(direction, symbolName)
|
591
|
|
592
|
'''
|
593
|
@brief Add AdditionalSymbol String on ListWidget
|
594
|
'''
|
595
|
def addAdditionalSymbol(self, direction, symbolName):
|
596
|
text = "{},{}".format(direction, symbolName)
|
597
|
|
598
|
if self.isAlreadyAdded(text):
|
599
|
QMessageBox.about(self.ui.buttonBox, "알림", "이미 추가된 아이템입니다.")
|
600
|
else:
|
601
|
self.ui.additionalSymbolListWidget.addItem(text)
|
602
|
|
603
|
'''
|
604
|
@brief Check the text is already added
|
605
|
'''
|
606
|
def isAlreadyAdded(self, text):
|
607
|
for index in range(self.ui.additionalSymbolListWidget.count()):
|
608
|
item = self.ui.additionalSymbolListWidget.item(index)
|
609
|
if item.text() == text:
|
610
|
return True
|
611
|
return False
|
612
|
|
613
|
'''
|
614
|
@brief update scene when command is success
|
615
|
@author humkyung
|
616
|
@date 2018.08.28
|
617
|
'''
|
618
|
def onCommandSuccess(self, pt):
|
619
|
from EngineeringConnectorItem import QEngineeringConnectorItem
|
620
|
|
621
|
self.ui.imageView.scene.invalidate()
|
622
|
if type(pt) is QEngineeringConnectorItem:
|
623
|
rows = self.ui.tableWidgetConnList.rowCount()
|
624
|
self.ui.tableWidgetConnList.setRowCount(rows + 1)
|
625
|
|
626
|
item = QTableWidgetItem('{},{}'.format(pt.center()[0], pt.center()[1]))
|
627
|
item.setData(Qt.UserRole, pt)
|
628
|
item.setFlags(Qt.ItemIsEnabled)
|
629
|
self.ui.tableWidgetConnList.setItem(rows, 0, item)
|
630
|
|
631
|
directionComboBox = QComboBox(self.ui.tableWidgetConnList)
|
632
|
directionComboBox.addItems(['AUTO', 'LEFT', 'RIGHT', 'UP', 'DOWN'])
|
633
|
directionComboBox.setCurrentText('AUTO')
|
634
|
|
635
|
self.ui.tableWidgetConnList.setCellWidget(rows, 1, directionComboBox)
|
636
|
|
637
|
'''
|
638
|
@brief Original Point Tool Button Clicked
|
639
|
'''
|
640
|
def addOriginalPoint(self, event):
|
641
|
cmd = OriginalPointCommand.OriginalPointCommand(self.ui.imageView, self.ui.originalPointLineEdit)
|
642
|
cmd.onSuccess.connect(self.onCommandSuccess)
|
643
|
self.ui.imageView.command = cmd
|
644
|
|
645
|
'''
|
646
|
@brief Connection Point Tool Button Clicked
|
647
|
'''
|
648
|
def addConnectionPoint(self, event):
|
649
|
cmd = ConnectionPointCommand.ConnectionPointCommand(self.ui.imageView, self.ui.connectionPointLineEdit)
|
650
|
cmd.onSuccess.connect(self.onCommandSuccess)
|
651
|
self.ui.imageView.command = cmd
|
652
|
|
653
|
'''
|
654
|
@brief delete current item from tableWidgetConnList
|
655
|
@author humkyung
|
656
|
@date 2018.08.31
|
657
|
'''
|
658
|
def onDeleteConnPt(self):
|
659
|
try:
|
660
|
model = self.ui.tableWidgetConnList.model()
|
661
|
|
662
|
item = self.ui.tableWidgetConnList.currentItem()
|
663
|
if item is not None:
|
664
|
item = self.ui.tableWidgetConnList.item(item.row(), 0)
|
665
|
data = item.data(Qt.UserRole)
|
666
|
if data is not None:
|
667
|
self.ui.imageView.scene.removeItem(data)
|
668
|
model.removeRow(item.row())
|
669
|
except Exception as ex:
|
670
|
from App import App
|
671
|
from AppDocData import MessageType
|
672
|
|
673
|
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
|
674
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
675
|
|
676
|
'''
|
677
|
@brief Remove Text Tool Button Clicked
|
678
|
@author Jeongwoo
|
679
|
@date 2018.05.03
|
680
|
@history 2018.05.09 Jeongwoo Remove comment and activate RemoveTextCommand
|
681
|
'''
|
682
|
def removeTextClickEvent(self, event):
|
683
|
self.ui.imageView.command = RemoveTextCommand.RemoveTextCommand(self.ui.imageView)
|
684
|
|
685
|
'''
|
686
|
@brief Init Original/Connection points
|
687
|
@author Jeongwoo
|
688
|
@date 2018.06.11
|
689
|
'''
|
690
|
def initOriginalAndConnectionPoint(self):
|
691
|
self.ui.originalPointLineEdit.setText('')
|
692
|
self.ui.tableWidgetConnList.setRowCount(0)
|
693
|
|
694
|
|
695
|
'''
|
696
|
@brief Rotate image clockwise
|
697
|
@author Jeongwoo
|
698
|
@date 2018.06.11
|
699
|
'''
|
700
|
def rotateLeftClickEvent(self, event):
|
701
|
self.initOriginalAndConnectionPoint()
|
702
|
self.ui.imageView.command = RotateImageCommand.RotateImageCommand(self.ui.imageView, True)
|
703
|
self.guidelineStateChangedEvent(None)
|
704
|
|
705
|
'''
|
706
|
@brief Rotate image counter-clockwise
|
707
|
@author Jeongwoo
|
708
|
@date 2018.06.11
|
709
|
'''
|
710
|
def rotateRightClickEvent(self, event):
|
711
|
self.initOriginalAndConnectionPoint()
|
712
|
self.ui.imageView.command = RotateImageCommand.RotateImageCommand(self.ui.imageView)
|
713
|
self.guidelineStateChangedEvent(None)
|
714
|
|
715
|
'''
|
716
|
@brief Flip image left and right
|
717
|
@author Jeongwoo
|
718
|
@date 2018.06.11
|
719
|
'''
|
720
|
def flipHorizontalClickEvent(self, event):
|
721
|
self.initOriginalAndConnectionPoint()
|
722
|
self.ui.imageView.command = FlipImageCommand.FlipImageCommand(self.ui.imageView, horizontal = True, vertical = False)
|
723
|
self.guidelineStateChangedEvent(None)
|
724
|
|
725
|
'''
|
726
|
@brief Flip image up and down
|
727
|
@author Jeongwoo
|
728
|
@date 2018.06.11
|
729
|
'''
|
730
|
def flipVerticalClickEvent(self, event):
|
731
|
self.initOriginalAndConnectionPoint()
|
732
|
self.ui.imageView.command = FlipImageCommand.FlipImageCommand(self.ui.imageView, horizontal = False, vertical = True)
|
733
|
self.guidelineStateChangedEvent(None)
|
734
|
|
735
|
def adjustOriginalPoint(self, adjustX, adjustY):
|
736
|
originalPoint = self.ui.originalPointLineEdit.text()
|
737
|
if originalPoint and self.ui.imageView.isOriginalPointSelected:
|
738
|
x = float(originalPoint.split(",")[0])
|
739
|
y = float(originalPoint.split(",")[1])
|
740
|
OriginalPointCommand.OriginalPointCommand.removeCircle(self.ui.imageView, x, y)
|
741
|
x = x - adjustX
|
742
|
y = y - adjustY
|
743
|
self.ui.originalPointLineEdit.setText(str(x)+","+str(y))
|
744
|
OriginalPointCommand.OriginalPointCommand.drawCircle(self.ui.imageView, x, y)
|
745
|
|
746
|
def adjustConnectionPoint(self, adjustX, adjustY):
|
747
|
itemCount = self.ui.connectionPointList.count()
|
748
|
for index in range(itemCount):
|
749
|
item = self.ui.connectionPointList.item(index)
|
750
|
text = item.text()
|
751
|
x = float(text.split(",")[0])
|
752
|
y = float(text.split(",")[1])
|
753
|
self.removeConnectionPointCircle(QtCore.QPointF(x, y))
|
754
|
x = x - adjustX
|
755
|
y = y - adjustY
|
756
|
item.setText(str(x)+","+str(y))
|
757
|
ConnectionPointCommand.ConnectionPointCommand.drawCircle(self.ui.imageView, x, y)
|
758
|
|
759
|
'''
|
760
|
@brief Validation Check
|
761
|
@return (isValid, errorMsg)
|
762
|
@history 2018.05.03 Jeongwoo Change self.dbHelper to AppDocData
|
763
|
'''
|
764
|
def isValidSymbolInfo(self):
|
765
|
EXCEPTION_MSG_FORMAT = "{} 입력을 확인해주세요."
|
766
|
EXCEPTION_MSG_DUPLICATED_FORMAT = "이미 저장된 {} 값입니다."
|
767
|
infoTitle = ""
|
768
|
|
769
|
|
770
|
'''
|
771
|
id = int(idText) if idText else -1
|
772
|
if (id == -1 or id < 100):
|
773
|
infoTitle = self.ui.idLabel.text()
|
774
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
775
|
'''
|
776
|
|
777
|
'''
|
778
|
lastId = -1
|
779
|
if self.selectedSymbol is not None:
|
780
|
lastId = self.selectedSymbol.getId()
|
781
|
if lastId != id and AppDocData.instance().isExistData('symId', id):
|
782
|
infoTitle = self.ui.idLabel.text()
|
783
|
return (False, EXCEPTION_MSG_DUPLICATED_FORMAT.format(infoTitle))
|
784
|
'''
|
785
|
|
786
|
if not self.ui.nameLineEdit.text():
|
787
|
infoTitle = self.ui.nameLabel.text()
|
788
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
789
|
|
790
|
thresholdText = self.ui.thresholdLineEdit.text()
|
791
|
threshold = float(thresholdText) if thresholdText else -1
|
792
|
if not(threshold >= 0 and threshold <= 100):
|
793
|
infoTitle = self.ui.thresholdLabel.text()
|
794
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
795
|
|
796
|
minMatchPointText = self.ui.minMatchPointLineEdit.text()
|
797
|
minMatchPoint = float(minMatchPointText) if minMatchPointText else -1
|
798
|
if not(minMatchPoint >= 0):
|
799
|
infoTitle = self.ui.minMatchPointLabel.text()
|
800
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
801
|
|
802
|
if self.ui.typeComboBox.currentIndex() == 0:
|
803
|
infoTitle = self.ui.typeLabel.text()
|
804
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
805
|
|
806
|
if self.ui.baseSymbolComboBox.currentIndex() == 0:
|
807
|
infoTitle = self.ui.baseSymbolLabel.text()
|
808
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
809
|
|
810
|
|
811
|
|
812
|
if not self.ui.originalPointLineEdit.text() or self.ui.imageView.isOriginalPointSelected == False:
|
813
|
infoTitle = self.ui.originalPointLabel.text()
|
814
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
815
|
|
816
|
if not (self.ui.tableWidgetConnList.rowCount() > 0):
|
817
|
infoTitle = self.ui.connectionPointLabel.text()
|
818
|
return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
|
819
|
|
820
|
return True, None
|
821
|
|
822
|
'''
|
823
|
@brief Slot for change offsets
|
824
|
@author Jeongwoo
|
825
|
@date 2018.05.02
|
826
|
@history 2018.06.11 Jeongwoo Add refresh guideline
|
827
|
'''
|
828
|
@pyqtSlot(float, float)
|
829
|
def offsetChanged(self, oX, oY):
|
830
|
print('offsetX : ' + str(self.offsetX) + '->' + str(self.offsetX+oX))
|
831
|
print('offsetY : ' + str(self.offsetY) + '->' + str(self.offsetY+oY))
|
832
|
self.offsetX = self.offsetX + oX
|
833
|
self.offsetY = self.offsetY + oY
|
834
|
self.guidelineStateChangedEvent(None)
|