프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / DTI_PID / DTI_PID / SymbolEditorDialog.py @ 47ce8e9c

이력 | 보기 | 이력해설 | 다운로드 (36 KB)

1
# coding: utf-8
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)  #  Copies the data
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+$"))) # ([0-1]{1}[.])?[0-9]+
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: # conString : x,y
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
                    #directionComboBox.currentIndexChanged.connect(self.onDirectionComboBoxChanged)
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]) # 0 : text / 1 : data(integer)
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
        #symId = self.ui.idLineEdit.text()
318
        name = self.ui.nameLineEdit.text()
319
        type = self.ui.typeComboBox.currentText() #Empty
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) ### update roll back 으로 변경해야함
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
            #directionComboBox.currentIndexChanged.connect(self.onDirectionComboBoxChanged)
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
        #self.ui.connectionPointList.clear()
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
        #idText = self.ui.idLineEdit.text()
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: #default value(None) index
807
            infoTitle = self.ui.baseSymbolLabel.text()
808
            return (False, EXCEPTION_MSG_FORMAT.format(infoTitle))
809

    
810
        #Additional Symbol is Nullable
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)
클립보드 이미지 추가 (최대 크기: 500 MB)