프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / Shapes / EngineeringTextItem.py @ 19d19912

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

1 3ba37adf humkyung
# coding: utf-8
2
import os.path
3
import copy
4 24015dc6 humkyung
import sys
5 3ba37adf humkyung
try:
6 d7080855 humkyung
    from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QObject, QT_VERSION_STR, QRect
7 acf92f86 humkyung
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QTransform, QFont, QColor, QFontMetrics
8 3ba37adf humkyung
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, QGraphicsTextItem
9
except ImportError:
10
    try:
11 d7080855 humkyung
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QRect, QObject, QT_VERSION_STR
12 acf92f86 humkyung
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont, QColor, QFontMetrics
13 3ba37adf humkyung
    except ImportError:
14
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
15
16 66e4d816 humkyung
from EngineeringPolylineItem import QEngineeringPolylineItem
17 8fd1d96f humkyung
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
18 6e4b95fc humkyung
from AppDocData import *
19 3d6ff047 humkyung
from EngineeringAbstractItem import QEngineeringAbstractItem
20 3ba37adf humkyung
21 ce9281d7 humkyung
class QEngineeringTextItem(QGraphicsTextItem, QEngineeringAbstractItem):
22 c80d49e6 humkyung
    HIGHLIGHT = '#BC4438'
23
24 5b782afc 김정우
    '''
25
        @history    2018.05.17  Jeongwoo    Add self._owner variable
26
    '''
27 d7080855 humkyung
    def __init__(self, uid=None, parent=None):
28 6fb1a52e humkyung
        import uuid
29
30 3ba37adf humkyung
        QGraphicsTextItem.__init__(self, parent)
31 ce9281d7 humkyung
        QEngineeringAbstractItem.__init__(self)
32 3ba37adf humkyung
33 d7080855 humkyung
        self.uid = uuid.uuid4() if uid is None else uid
34 8c5431cc humkyung
        self.loc = None
35
        self.size = None
36 68ce37ea humkyung
        self.angle = 0  # angle in radian
37 8c5431cc humkyung
        self.conns = []
38 5b782afc 김정우
        self._owner = None
39 9f8c177d 김정우
        self.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable)
40 3ba37adf humkyung
        self.setAcceptHoverEvents(True)
41 9f8c177d 김정우
        self.setAcceptTouchEvents(True)
42 3ba37adf humkyung
43 ce9281d7 humkyung
        self.setColor(self._color)
44 19d19912 humkyung
        self._savedColor = None        
45
46 ccb8b051 gaqhf
        self.delimiter = '"'
47 2885ca96 gaqhf
48
        self.attribute = ''
49 d7080855 humkyung
50
        self.transfer = Transfer()
51 2029fb03 humkyung
        
52 5b782afc 김정우
    '''
53
        @brief      Get owner
54
        @author     Jeongwoo
55
        @date       2018.05.17
56
    '''
57
    @property
58
    def owner(self):
59
        return self._owner
60
61
    '''
62
        @brief      Set owner
63
        @author     Jeongwoo
64
        @date       2018.05.17
65
        @history    2018.05.17  Jeongwoo    Add Calling setColor if self._owner is None or not
66
    '''
67
    @owner.setter
68
    def owner(self, value):
69
        self._owner = value
70
71
        if self._owner is None:
72
            self._color = self.DEFAULT_COLOR
73
        self.setColor(self._color)
74 ce9281d7 humkyung
75 8c5431cc humkyung
    '''
76
        @brief  return text string
77
        @author humkyung
78
        @date   2018.04.16
79
    '''
80
    def text(self):
81
        return self.toPlainText()
82
    
83
    '''
84
        @brief  return center position of text
85
        @author humkyung
86
        @date   2018.04.16
87
    '''
88
    def center(self):
89 3a4cc147 humkyung
        return self.sceneBoundingRect().center()
90 8c5431cc humkyung
91 c80d49e6 humkyung
    '''
92
        @brief      hover event
93
        @authro     humkyung
94
        @date       
95
    '''
96 3ba37adf humkyung
    def hoverEnterEvent(self, event):
97 4efdc42f gaqhf
        self.setHightlight()
98
99
    def hoverLeaveEvent(self, event):
100
        self.unsetHightlight()
101
102
    '''
103
        @brief      set highlight
104
        @author     kyouho
105
        @date       2018.08.27
106
    '''
107
    def setHightlight(self):
108 19d19912 humkyung
        if self._savedColor is None:
109
            self._savedColor = self.getColor()
110 c80d49e6 humkyung
        self.setColor(QEngineeringTextItem.HIGHLIGHT)
111 19d19912 humkyung
112 c80d49e6 humkyung
        self.update()
113 3ba37adf humkyung
114 4efdc42f gaqhf
    '''
115
        @brief      unset highlight
116
        @author     kyouho
117
        @date       2018.08.27
118
    '''
119
    def unsetHightlight(self):
120 c80d49e6 humkyung
        self.setColor(self._savedColor)
121
        self.update()
122 3ba37adf humkyung
123
    def hoverMoveEvent(self, event):
124 7b2a4455 김정우
        pass
125
126 9f8c177d 김정우
    '''
127 6e4b95fc humkyung
        @brief      remove item when user press delete key
128
        @author     humkyung
129
        @date       2018.04.23
130 a3a805a0 김정우
        @history    2018.05.25  Jeongwoo    Seperate delete item method
131 6e4b95fc humkyung
                    humkyung 2018.08.18 rotate text when user press 'R'
132 9f8c177d 김정우
    '''
133
    def keyPressEvent(self, event): 
134
        if event.key() == Qt.Key_Delete:
135 a3a805a0 김정우
            self.deleteTextItemFromScene()
136 6e4b95fc humkyung
        elif event.key() == Qt.Key_R:
137
            #degree 0
138
            if 0 == self.angle:
139
                self.angle = 1.57
140
            #degree 90
141
            elif (1.57 == self.angle):
142
                self.angle = 3.14
143
            #degree 180
144
            elif 3.14 == self.angle:
145
                self.angle = 4.71
146
            #degree 270
147
            elif 4.71 == self.angle :
148
                self.angle = 0
149
150
            width = self.size[0]
151
            height = self.size[1]
152
            self.size = (height, width)
153
154
            self.rotate()
155
156
        QGraphicsTextItem.keyPressEvent(self, event)
157 a3a805a0 김정우
158
    '''
159 6d6ad72f humkyung
        @brief  draw rect when item is selected
160
        @author humkyung
161
        @date   2018.07.08
162
    '''
163
    def drawFocusRect(self, painter):
164
        self.focuspen = QPen(Qt.DotLine)
165
        self.focuspen.setColor(Qt.black)
166
        self.focuspen.setWidthF(1.5)
167
        hilightColor = QColor(255, 0, 0, 127)
168
        painter.setBrush(QBrush(hilightColor))
169
        painter.setPen(self.focuspen)
170
        painter.drawRect(self.boundingRect())
171
172
    '''
173
        @brief  override paint(draw connection points)
174
        @author humkyung
175
        @date   2018.07.08
176
    '''
177
    def paint(self, painter, options=None, widget=None):
178
        QGraphicsTextItem.paint(self, painter, options, widget)
179
        if self.isSelected():
180
            self.drawFocusRect(painter)
181
182
    '''
183 a3a805a0 김정우
        @brief      Delete text item
184
        @author     Jeongwoo
185
        @date       2018.05.25
186
    '''
187
    def deleteTextItemFromScene(self):
188 d7080855 humkyung
        self.transfer.onRemoved.emit(self)
189 a3a805a0 김정우
        self.scene().removeItem(self)
190
191
    '''
192
        @brief      Return real item position
193
        @author     Jeongwoo
194
        @date       2018.05.25
195
    '''
196
    def boundingRectOnScene(self):
197
        rect = self.boundingRect()
198
        rect.moveTo(self.loc[0], self.loc[1])
199
        return rect
200 9f8c177d 김정우
201 7b2a4455 김정우
    '''
202
        @brief      Double click event, Show QOcrResultDialog
203
        @author     Jeongwoo
204
        @date       18.04.23
205 24adc995 김정우
        @history    18.06.20    Jeongwoo    Resize QRect added 1
206 7b2a4455 김정우
    '''
207
    def mouseDoubleClickEvent(self, event):
208 0ed45c45 김정우
        if event.buttons() == Qt.LeftButton:
209 01ca0061 gaqhf
            from OcrResultDialog import QOcrResultDialog
210 d6d16d45 humkyung
            dialog = QOcrResultDialog(None, AppDocData.instance().getCurrentPidSource().getQImageOnRect(QRect(self.loc[0], self.loc[1], self.size[0]+1, self.size[1]))
211 24adc995 김정우
                                                       , QRect(self.loc[0], self.loc[1], self.size[0]+1, self.size[1]), True, self.text())
212 0ed45c45 김정우
            (isAccept, textInfoList) = dialog.showDialog()
213 7b2a4455 김정우
214 0ed45c45 김정우
            if isAccept:
215
                scene = self.scene()
216
                scene.removeItem(self)
217
                text = textInfoList[0].getText()
218
                self.setPlainText(text)
219
                self.setDefaultTextColor(Qt.blue)
220
                self.addTextItemToScene(scene)
221 7b2a4455 김정우
222
    '''
223 6e4b95fc humkyung
        @brief      rotate text
224
        @author     humkyung
225
        @date       2018.08.18
226
    '''
227
    def rotate(self):
228
        sx = 1
229
        sy = 1
230
        width = self.size[0]
231
        height = self.size[1]
232
        x = self.loc[0]
233
        y = self.loc[1]
234
235
        transform = QTransform()
236
        if (1.57 == self.angle) or (4.71 == self.angle):
237
            rect = self.boundingRect()
238
            sx = width/rect.height()
239
            sy = height/rect.width()
240
                                        
241
            transform.translate(x, y)
242
            transform.translate(width*0.5, height*0.5)
243
            transform.scale(1, sy)
244
            transform.rotateRadians(-self.angle)
245
            transform.translate(-rect.width()*0.5, -rect.height()*0.5)
246
        elif 3.14 == self.angle:
247
            rect = self.boundingRect()
248
            sx = width/rect.width()
249
            sy = height/rect.height()
250
251
            transform.translate(x, y - round((rect.height()-height)*0.5))
252
            transform.scale(sx, 1)
253
            transform.rotateRadians(-self.angle)
254
            transform.translate(-width*0.5, -height*0.5)
255
        else:
256
            rect = self.boundingRect()
257
            sx = width/rect.width()
258
            sy = height/rect.height()
259
260
            #if '\n' not in text:
261
            transform.translate(x, y - round((rect.height()-height)*0.5))
262
            transform.scale(sx, 1)
263
264
        self.setTransform(transform)
265
        self.update()
266
267
    '''
268 7b2a4455 김정우
        @brief      Put text on scene
269
        @author     Jeongwoo
270
        @date       18.04.23
271 a3b64994 humkyung
        @history    humkyung 2018.06.30 apply font configuration
272 7b2a4455 김정우
    '''
273
    def addTextItemToScene(self, scene):
274 a3b64994 humkyung
        try:
275
            docData = AppDocData.instance()
276
            configs = docData.getConfigs('Text Style', 'Font Name')
277
            fontName = configs[0].value if configs else 'Arial'
278
            configs = docData.getConfigs('Text Style', 'Font Size')
279
            fontSize = int(configs[0].value) if configs else -1
280
281
            sx = 1
282
            sy = 1
283
            width = self.size[0]
284
            height = self.size[1]
285
            x = self.loc[0]
286
            y = self.loc[1]
287
            rect = None
288
            transform = QTransform()
289
            if (1.57 == self.angle) or (4.71 == self.angle):
290
                font = QFont(fontName, width*1.2 if fontSize == -1 else fontSize)
291 acf92f86 humkyung
                
292
                x_factor = width / QFontMetrics(font).height()
293
                y_factor = height / QFontMetrics(font).width(self.text())
294
                factor = min(x_factor, y_factor)
295
                font.setPointSizeF(font.pointSizeF()*factor)
296
297 a3b64994 humkyung
                self.setFont(font)
298
                rect = self.boundingRect()
299
                sx = width/rect.height()
300
                sy = height/rect.width()
301
                                            
302
                transform.translate(x, y)
303
                transform.translate(width*0.5, height*0.5)
304
                transform.scale(1, sy)
305
                transform.rotateRadians(-self.angle)
306
                transform.translate(-rect.width()*0.5, -rect.height()*0.5)
307
            elif 3.14 == self.angle:
308
                font = QFont(fontName, height*1.2 if fontSize == -1 else fontSize)
309 acf92f86 humkyung
310
                x_factor = width / QFontMetrics(font).width(self.text())
311
                y_factor = height / QFontMetrics(font).height()
312
                factor = min(x_factor, y_factor)
313
                font.setPointSizeF(font.pointSizeF()*factor)
314
315 a3b64994 humkyung
                self.setFont(font)
316
                rect = self.boundingRect()
317
                sx = width/rect.width()
318
                sy = height/rect.height()
319
320
                transform.translate(x, y - round((rect.height()-height)*0.5))
321
                transform.scale(sx, 1)
322
                transform.rotateRadians(-self.angle)
323
                transform.translate(-width*0.5, -height*0.5)
324
            else:
325
                font = QFont(fontName, height*1.2 if fontSize == -1 else fontSize)
326 acf92f86 humkyung
327
                x_factor = width / QFontMetrics(font).width(self.text())
328
                y_factor = height / QFontMetrics(font).height()
329
                factor = min(x_factor, y_factor)
330
                font.setPointSizeF(font.pointSizeF()*factor)
331
332 a3b64994 humkyung
                self.setFont(font)
333
                rect = self.boundingRect()
334
                sx = width/rect.width()
335
                sy = height/rect.height()
336
337
                #if '\n' not in text:
338
                transform.translate(x, y - round((rect.height()-height)*0.5))
339
                transform.scale(sx, 1)
340
341
            self.setTransform(transform)
342
                    
343
            scene.addItem(self)
344
        except Exception as ex:
345
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
346
347 68ce37ea humkyung
    '''
348
        @brief  get connected items
349
        @author humkyung
350
        @date   2018.04.23
351
    '''
352
    def getConnectedItems(self):
353
        visited = []
354
355 ce9281d7 humkyung
        try:
356
            if 1 == len(self.conns):
357
                # iterate connected items
358
                pool = []
359
                visited = []
360
                pool.append(self.conns[0])
361
                while len(pool) > 0:
362
                    it = pool.pop()
363
                    visited.append(it)
364
                    for conn in it.conns:
365
                        if (conn is not None) and (conn not in visited): pool.append(conn)
366
                # up to here
367
        except Exception as ex:
368
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
369 68ce37ea humkyung
370
        return visited
371 22fdbd0b humkyung
    
372 f5943099 humkyung
    '''
373 baf331db humkyung
        @brief      parse xml code
374
        @author     humkyung
375
        @date       2018.09.15
376
    '''
377
    @staticmethod 
378
    def fromXml(node):
379
        from TextItemFactory import TextItemFactory
380
        from AppDocData import AppDocData
381 abf4f001 gaqhf
        from QEngineeringNoteItem import QEngineeringNoteItem
382 baf331db humkyung
383
        item = None
384
385
        try:
386
            location = node.find('LOCATION').text if node.find('LOCATION') is not None else '0,0'
387
            x = float(location.split(',')[0])
388
            y = float(location.split(',')[1])
389
            width = float(node.find('WIDTH').text) if node.find('WIDTH') is not None else 0
390
            height = float(node.find('HEIGHT').text) if node.find('HEIGHT') is not None else 0
391
            angle = float(node.find('ANGLE').text) if node.find('ANGLE') is not None else 0
392
            value = node.find('VALUE').text
393
            uid = node.find('UID')
394
            attributeValue = node.find('ATTRIBUTEVALUE')
395
            name = node.find('NAME').text
396
            if name == 'TEXT':
397
                item = TextItemFactory.instance().createTextItem(value)
398
                if item is not None:
399
                    item.loc = (x, y)
400
                    item.size = (width, height)
401
                    item.angle = angle
402
                    item.setPlainText(value)
403
            elif name == 'NOTE':
404 abf4f001 gaqhf
                item = QEngineeringNoteItem()
405 baf331db humkyung
                if item is not None:
406
                    item.loc = (x, y)
407
                    item.size = (width, height)
408
                    item.angle = angle
409
                    item.setPlainText(value)
410
411
            ## assign area
412
            if item is not None:
413
                if node.find('AREA') is None:
414
                    appDocData = AppDocData.instance()
415
                    for area in appDocData.getAreaList():
416
                        if area.contains([x, y]):
417
                            item.area = area.name
418
                            break
419
                else:
420 abf4f001 gaqhf
                    item.area = node.find('AREA').text  
421 baf331db humkyung
            ## up to here
422
        except Exception as ex:
423
            from App import App
424
            from AppDocData import MessageType
425
426
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
427
            App.mainWnd().addMessage.emit(MessageType.Error, message)
428
429
        return item
430
431
    '''
432 18f54b2f humkyung
        @brief      generate xml code
433
        @author     humkyung
434
        @date       2018.04.23
435
        @history    humkyung 2018.04.27 move to QEngineeringLineNoTextItem
436 24015dc6 humkyung
                    humkyung 2018.05.02 add name as parameter
437 f09eb8ff 김정우
                    Jeongwoo 2018.05.30 Change variable [owner] is nullable and Add/Modify attributes
438 68ce37ea humkyung
    '''
439 f09eb8ff 김정우
    def toXml(self, owner = None, name='TEXT'):
440 24015dc6 humkyung
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree
441 d7080855 humkyung
        from EngineeringLineItem import QEngineeringLineItem
442 24015dc6 humkyung
        from SymbolSvgItem import SymbolSvgItem
443
444
        try:
445
            node = Element('ATTRIBUTE')
446 16ca5a01 gaqhf
            #if owner is not None:
447
            uidNode = Element('UID')
448
            uidNode.text = str(self.uid)
449
            node.append(uidNode)
450
451
            attributeValueNode = Element('ATTRIBUTEVALUE')
452
            attributeValueNode.text = self.attribute
453
            node.append(attributeValueNode)
454 24015dc6 humkyung
455
            nameNode = Element('NAME')
456
            nameNode.text = name
457
            node.append(nameNode)
458 f09eb8ff 김정우
            
459
            locNode = Element('LOCATION')
460
            locNode.text = '{},{}'.format(self.loc[0], self.loc[1])
461
            node.append(locNode)
462 24015dc6 humkyung
463
            valueNode = Element('VALUE')
464
            valueNode.text = self.text()
465
            node.append(valueNode)
466
467
            angleNode = Element('ANGLE')
468
            angleNode.text = str(self.angle)
469
            node.append(angleNode)
470
471
            widthNode = Element('WIDTH')
472 f09eb8ff 김정우
            widthNode.text = str(self.size[0])
473 24015dc6 humkyung
            node.append(widthNode)
474
475
            heightNode = Element('HEIGHT')
476 f09eb8ff 김정우
            heightNode.text = str(self.size[1])
477 24015dc6 humkyung
            node.append(heightNode)
478 baf331db humkyung
479
            areaNode = Element('AREA')
480
            areaNode.text = self.area
481
            node.append(areaNode)
482 24015dc6 humkyung
        except Exception as ex:
483
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
484 baf331db humkyung
            return str(self.uid)
485 24015dc6 humkyung
486 d1576bff 김정우
        return node 
487
    
488
    '''
489
        @brief      Set Color. Override QEngineeringAbstractItem's
490
        @author     Jeongwoo
491
        @date       2018.05.11
492 ce9281d7 humkyung
        @history    humkyung 2018.05.13 update after change color
493 d1576bff 김정우
    '''
494
    def setColor(self, color):
495 ce9281d7 humkyung
        self._color = color
496 d1576bff 김정우
        c = QColor()
497
        c.setNamedColor(color)
498
        self.setDefaultTextColor(c)
499 5b782afc 김정우
        self.update()
500
501
    def getColor(self):
502 59384c70 김정우
        return self._color
503 d7080855 humkyung
504
'''
505
    @brief      The class transfer pyqtSignal Event. Cause Subclass of QGraphicsRectItem can't use pyqtSignal
506
    @author     Jeongwoo
507
    @date       2018.06.18
508
'''
509
class Transfer(QObject):
510
    onRemoved = pyqtSignal(QGraphicsItem)
511
512
    def __init__(self, parent = None):
513
        QObject.__init__(self, parent)
클립보드 이미지 추가 (최대 크기: 500 MB)