프로젝트

일반

사용자정보

통계
| 개정판:

hytos / HYTOS / HYTOS / Shapes / SymbolSvgItem.py @ 62fd5ea0

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

1
#!/usr/bin/env/python3
2
# coding: utf-8
3

    
4
import sys
5
import os
6
import math
7
from PyQt5.QtGui import *
8
from PyQt5.QtCore import *
9
from PyQt5.QtSvg import *
10
from PyQt5.QtWidgets import (QApplication, QGraphicsItem)
11
from PyQt5.QtXml import *
12
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QMessageBox
13

    
14
from AppDocData import *
15
from EngineeringConnectorItem import QEngineeringConnectorItem
16
from EngineeringAbstractItem import QEngineeringAbstractItem
17
from EngineeringConnectorItem import QEngineeringConnectorItem
18
from UserInputAttribute import UserInputAttribute
19
from Resizer import Resizer
20

    
21
class SymbolSvgItem(QGraphicsSvgItem, QEngineeringAbstractItem):
22
    """ This is symbolsvgitem class """
23

    
24
    clicked = pyqtSignal(QGraphicsSvgItem)
25
    ZVALUE = 50
26
    HOVER_COLOR = 'url(#hover)'
27

    
28
    '''
29
        @history    18.04.11    Jeongwoo    Add Variable (Name, Type)
30
                    18.05.11    Jeongwoo    Declare variable self.color
31
                    18.05.25    Jeongwoo    Call setColor() method
32
                    18.05.30    Jeongwoo    Add self variables (parentSymbol, childSymbol)
33
    '''
34
    def __init__(self, path, uid=None, flip=0):
35
        import uuid
36
        from SymbolAttr import SymbolProp
37

    
38
        QGraphicsSvgItem.__init__(self)
39
        QEngineeringAbstractItem.__init__(self)
40

    
41
        self.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable|QGraphicsItem.ItemIsMovable|QGraphicsItem.ItemSendsGeometryChanges)
42

    
43
        self.dbUid = None
44
        self.uid = uuid.uuid4() if uid is None else uuid.UUID(uid, version=4)
45
        self.name = ''
46
        self.category = ''
47
        self.type = ''
48
        self.angle = 0
49
        self._scale = 1
50
        self.origin = None
51
        self.loc = None
52
        self.size = None
53
        self._owner = None
54
        self.parentSymbol = ''
55
        self.childSymbol = '' 
56
        self.hasInstrumentLabel = 0
57
        self.flip = flip
58
        # attributeType uid
59
        self.attribute = ''
60
        self._properties = {SymbolProp(None, 'Supplied By', 'String'):None}
61

    
62
        self.setAcceptDrops(True)
63
        self.setAcceptHoverEvents(True)
64
        self.setAcceptedMouseButtons(Qt.LeftButton)
65
        self.setAcceptTouchEvents(True)
66
        
67
        self.currentCursor = 0
68
        self.transfer = Transfer()
69

    
70
        try:
71
            f = QFile(path)
72
            f.open(QIODevice.ReadOnly)
73
            array = f.readAll()
74
            self._document = QDomDocument()
75
            self._document.setContent(array)
76
            self._renderer = QSvgRenderer(self._document.toByteArray())
77
            self.setSharedRenderer(self._renderer)
78

    
79
            self._color = self.get_attribute('fill')
80
        except Exception as ex:
81
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
82
        finally:
83
            f.close()
84

    
85
        self.setZValue(SymbolSvgItem.ZVALUE)
86

    
87
    def __str__(self):
88
        """ return string represent uuid """
89
        return str(self.uid)
90

    
91
    '''
92
        @breif  getter owner
93
        @author humkyung
94
        @date   2018.05.10
95
    '''
96
    @property
97
    def owner(self):
98
        import uuid
99

    
100
        if self._owner and type(self._owner) is uuid.UUID:
101
            matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(self._owner)]
102
            if matches: self._owner = matches[0]
103

    
104
        if type(self._owner) is not uuid.UUID and type(self._owner) is not str:
105
            return self._owner
106
        else:
107
            self._owner = None
108
            return None
109

    
110
    '''
111
        @brief  setter owner
112
        @author humkyung
113
        @date   2018.05.10
114
        @history    2018.05.17  Jeongwoo    Add Calling setColor if self._owner is None or not
115
    '''
116
    @owner.setter
117
    def owner(self, value):
118
        self._owner = value
119

    
120
        if self._owner is None:
121
            self._color = self.DEFAULT_COLOR
122
        self.setColor(self._color)
123

    
124
    @property
125
    def properties(self):
126
        """ getter of properties """
127
        import uuid
128

    
129
        for prop,value in self._properties.items():
130
            try:
131
                if prop.is_selectable and type(value) is uuid.UUID and self.scene():
132
                    matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)]
133
                    if matches: self._properties[prop] = matches[0]
134
                
135
                if prop.Expression:
136
                    item = self._properties[prop]   # assign item
137
                    self._properties[prop] = eval(prop.Expression)
138
            except Exception as ex:
139
                from App import App 
140

    
141
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
142
                App.mainWnd().addMessage.emit(MessageType.Error, message)           
143

    
144
        return self._properties
145

    
146
    @properties.setter
147
    def properties(self, value):
148
        """ setter of properties """
149
        self._properties = value
150

    
151
    def set_property(self, property, value):
152
        """ set property with given value """
153
        if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0)
154
        matches = [prop for prop,_ in self._properties.items() if prop.Attribute == property]
155
        if matches: self._properties[matches[0]] = value
156

    
157
    def prop(self, name):
158
        """ return the value of given property with name """
159
        matches = [(prop,value) for prop,value in self.properties.items() if prop.Attribute == name]
160
        if matches: return matches[0][1]
161

    
162
        return None
163

    
164
    @property
165
    def Size(self):
166
        """ return valve's size """
167
        from QEngineeringSizeTextItem import QEngineeringSizeTextItem
168

    
169
        matches = [assoc for assoc in self.associations() if type(assoc) is QEngineeringSizeTextItem]
170
        if matches:
171
            return matches[0].text()
172
        else:
173
            return None
174
    
175
    def includes(self, pt, margin=0):
176
        """ return True if symbol contains given point else return False """
177
        rect = self.sceneBoundingRect()
178
        allowed_error = 0.1
179

    
180
        if abs(rect.x() - 0) <= allowed_error and abs(rect.y() - 0) <= allowed_error:
181
            # when first recognition step, symbols are not in scene(not yet added) therefore cannot use scenebounding rect
182
            minX = self.loc[0] - margin
183
            minY = self.loc[1] - margin
184
            maxX = minX + self.size[0] + margin
185
            maxY = minY + self.size[1] + margin
186
        else:
187
            minX = rect.x() - margin
188
            minY = rect.y() - margin
189
            maxX = minX + rect.width() + margin
190
            maxY = minY + rect.height() + margin
191

    
192
        #print([minX, minY, maxX, maxY])
193

    
194
        return True if (pt[0] >= minX and pt[0] <= maxX and pt[1] >= minY and pt[1] <= maxY) else False
195

    
196
    def toSql(self):
197
        """ convert valve data to sql query """
198
        import uuid
199
        from AppDocData import AppDocData
200

    
201
        res = []
202
        appDocData = AppDocData.instance()
203
        
204
        rect = self.sceneBoundingRect()
205

    
206
        cols = ['UID', 'Drawings_UID', 'Symbols_UID', 'X', 'Y', 'Rotation', 'Scale']
207
        values = ['?','?','?', '?', '?', '?', '?']
208
        param = [str(self.uid), str(appDocData.activeDrawing.UID), str(self.dbUid), rect.left(), rect.top(), str(self.angle), self.transform().m11()]
209
        sql = 'insert or replace into Components({}) values({})'.format(','.join(cols), ','.join(values))
210
        res.append((sql, tuple(param)))
211
        
212
        # save connectors to database
213
        index = 1
214
        for connector in self.connectors:
215
            res.extend(connector.toSql(index))
216
            index += 1
217
        # up to here
218

    
219
        return res
220

    
221
    '''
222
        @brief  build symbol item
223
        @author humkyung
224
        @date   2018.05.02
225
        @history    2018.05.09  Jeongwoo    Clear self.connectors
226
                    2018.05.30  Jeongwoo    Add parameters (parentSymbol, childSymbol)
227
    '''
228
    def buildItem(self, name, _type, angle, scale, loc, origin, connPts, dbUid=None, pointsUids=None):
229
        try:
230
            self.name = name
231
            self.type = _type     
232
            self.angle = angle     
233
            self._scale = scale
234
            self.loc = loc  
235

    
236
            docData = AppDocData.instance()
237
            if dbUid is None:
238
                symbolInfo = docData.getSymbolByQuery('name', name)
239
            else:
240
                symbolInfo = docData.getSymbolByQuery('UID', dbUid)
241
            
242
            self.dbUid = symbolInfo.uid
243
            self.category = symbolInfo.sCategory
244
            originalPoint = symbolInfo.getOriginalPoint().split(',')
245
            self.symbolOrigin = [float(originalPoint[0]), float(originalPoint[1])]
246
            
247
            # setting connectors
248
            connectionPoints = symbolInfo.getConnectionPoint().split('/')
249
            for index in range(len(connectionPoints)):
250
                if connectionPoints[index] == '':
251
                    break
252
                tokens = connectionPoints[index].split(',')
253

    
254
                direction = 'AUTO'                
255
                symbol_idx = '0'
256

    
257
                if len(tokens) == 2:
258
                    x = float(tokens[0])
259
                    y = float(tokens[1])
260
                elif len(tokens) == 3:
261
                    direction = tokens[0]
262
                    x = float(tokens[1])
263
                    y = float(tokens[2])
264
                elif len(tokens) == 4:
265
                    direction = tokens[0]
266
                    x = float(tokens[1])
267
                    y = float(tokens[2])
268
                    symbol_idx = tokens[3]
269

    
270
                if pointsUids:
271
                    self.setConnector(pointsUids[index], index+1)    
272
                else:
273
                    self.setConnector(None, index+1)
274
                
275
                self.connectors[index].direction = direction
276
                self.connectors[index].symbol_idx = symbol_idx
277
                self.connectors[index].setPos((x, y))
278
                self.connectors[index].connectPoint = (x, y)
279
            
280

    
281
            tooltip = '<b>{}</b><br>{}={}'.format(str(self.uid), self.type, self.name)
282
            self.setToolTip(tooltip)
283
        except Exception as ex:
284
            from App import App 
285

    
286
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
287
            App.mainWnd().addMessage.emit(MessageType.Error, message)
288

    
289
    '''
290
        @brief  return bounding box of symbol
291
        @author humkyung
292
        @date   2018.04.08
293
    '''
294
    def rect(self):
295
        return self.sceneBoundingRect()
296
        
297
    '''
298
        @brief  return true if line is able to connect symbol
299
        @author humkyung
300
        @date   2018.04.13
301
    '''
302
    def is_connectable(self, item, toler=10):
303
        #from EngineeringLineItem import QEngineeringLineItem
304

    
305
        '''
306
        if False:#type(item) is QEngineeringLineItem:
307
            line = item
308
            start_pt = line.startPoint()
309
            end_pt = line.endPoint()
310
            for connector in self.connectors:
311
                dx = connector.sceneConnectPoint[0] - (start_pt[0])
312
                dy = connector.sceneConnectPoint[1] - (start_pt[1])
313
                if (math.sqrt(dx*dx + dy*dy) < toler): return True
314
                dx = connector.sceneConnectPoint[0] - (end_pt[0])
315
                dy = connector.sceneConnectPoint[1] - (end_pt[1])
316
                if (math.sqrt(dx*dx + dy*dy) < toler): return True
317
        elif True:#issubclass(type(item), SymbolSvgItem):
318
        '''
319
        for connector in self.connectors:
320
            for iConnector in item.connectors:
321
                dx = connector.sceneConnectPoint[0] - iConnector.sceneConnectPoint[0]
322
                dy = connector.sceneConnectPoint[1] - iConnector.sceneConnectPoint[1]
323
                if (math.sqrt(dx*dx + dy*dy) < toler): return True
324

    
325
        return False
326
 
327
    '''
328
        @author     humkyung
329
        @date       2018.07.03
330
    '''
331
    def is_connected(self, item, at=QEngineeringAbstractItem.CONNECTED_AT_PT):
332
        """ check if given item is connected to self """
333

    
334
        _connectors = [connector for connector in self.connectors if (connector.connectedItem == item and (connector._connected_at == at if at else True))]
335
        return len(_connectors) > 0
336

    
337
    def next_connected(self, lhs, rhs):
338
        """ check given two item's are next connected(ex: 0-1, 2-3) """
339

    
340
        lhs_matches = [at for at in range(len(self.connectors)) if self.connectors[at].connectedItem == lhs]
341
        rhs_matches = [at for at in range(len(self.connectors)) if self.connectors[at].connectedItem == rhs]
342
        if lhs_matches and rhs_matches:
343
            return (lhs_matches[0] in [0,1] and rhs_matches[0] in [0,1]) or (lhs_matches[0] in [2,3] and rhs_matches[0] in [2,3])
344

    
345
        return False
346

    
347
    '''
348
        @brief      connect line and symbol is able to be connected and return line
349
        @author     humkyung
350
        @date       2018.04.16
351
        @history    humkyung 2018.05.08 check if symbol is possible to be connected
352
                    Jeongwoo 2018.05.15 Connect each symbol and line
353
    '''
354
    def connect_if_possible(self, obj, toler=10):
355
        from shapely.geometry import Point
356
        from EngineeringLineItem import QEngineeringLineItem
357

    
358
        res = []
359
        try:
360
            if type(obj) is QEngineeringLineItem:
361
                startPt = obj.startPoint()
362
                endPt = obj.endPoint()
363
                for i in range(len(self.connectors)):
364
                    if (Point(startPt[0], startPt[1]).distance(Point(self.connectors[i].sceneConnectPoint[0], self.connectors[i].sceneConnectPoint[1])) < toler):
365
                        if self.connectors[i].connectedItem is None:
366
                            self.connectors[i].connect(obj)
367
                        if obj.connectors[0].connectedItem is None:
368
                            obj.connectors[0].connect(self)
369
                        
370
                        res.append(obj)
371
                    if (Point(endPt[0], endPt[1]).distance(Point(self.connectors[i].sceneConnectPoint[0], self.connectors[i].sceneConnectPoint[1])) < toler):
372
                        if self.connectors[i].connectedItem is None:
373
                            self.connectors[i].connect(obj)
374
                        if obj.connectors[1].connectedItem is None:
375
                            obj.connectors[1].connect(self)
376
                        
377
                        res.append(obj)
378
            elif issubclass(type(obj), SymbolSvgItem):
379
                for i in range(len(self.connectors)):
380
                    for j in range(len(obj.connectors)):
381
                        _pt = Point(obj.connectors[j].sceneConnectPoint[0], obj.connectors[j].sceneConnectPoint[1])
382
                        if (_pt.distance(Point(self.connectors[i].sceneConnectPoint[0], self.connectors[i].sceneConnectPoint[1])) < toler):
383
                            if self.connectors[i].connectedItem is None:
384
                                self.connectors[i].connect(obj)
385
                            if obj.connectors[j].connectedItem is None:
386
                                obj.connectors[j].connect(self)
387

    
388
                            res.append(obj)
389
        except Exception as ex:
390
            from App import App 
391
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
392
            App.mainWnd().addMessage.emit(MessageType.Error, message)
393

    
394
        return res
395

    
396
    '''
397
        @brief      disconnect connector item
398
        @author     kyouho
399
        @date       2018.08.30
400
    '''
401
    def disconnectedItemAtConnector(self, connector):
402
        for conn in self.connectors:
403
            if conn.isOverlapConnector(connector):
404
                conn.connectedItem = None
405

    
406
    '''
407
        @brief  get connection point close to given point in tolerance
408
        @author humkyung
409
        @dat
410
    '''
411
    def getConnectionPointCloseTo(self, pt, toler=10):
412
        import math
413

    
414
        for connector in self.connectors:
415
            dx = connector.sceneConnectPoint[0] - pt[0]
416
            dy = connector.sceneConnectPoint[1] - pt[1]
417
            if math.sqrt(dx*dx + dy*dy) < toler: return connPt
418
            
419
        return None
420

    
421
    '''
422
        @brief  return center of symbol
423
        @author humkyung
424
        @date   2018.04.08
425
    '''
426
    def center(self):
427
        return self.sceneBoundingRect().center()
428
        
429
    '''
430
        @brief      highlight connector and attribute
431
        @authro     humkyung
432
        @date       2018.05.02
433
    '''
434
    def hoverEnterEvent(self, event):
435
        from Resizer import Resizer
436

    
437
        self.highlight(True)
438

    
439
        """ create a resizer """
440
        resizer = Resizer.instance()
441
        resizer.connected = self
442
        resizerWidth = resizer.rect.width() / 2
443
        rect = self.sceneBoundingRect()
444
        resizerOffset = QPointF(resizerWidth, resizerWidth)
445
        resizer.setPos(rect.bottomRight() - resizerOffset)
446
        if resizer.receivers(resizer.resizeSignal) > 0: resizer.resizeSignal.disconnect()
447
        resizer.resizeSignal.connect(self.resize)
448
        try:
449
            self.transfer.on_pos_changed.disconnect(resizer.on_symbol_pos_changed)
450
        except Exception as ex:
451
            pass
452
        self.transfer.on_pos_changed.connect(resizer.on_symbol_pos_changed)
453
        resizer.setVisible(True)
454
        if not resizer.scene(): self.scene().addItem(resizer)
455

    
456
    '''
457
        @brief      unhighlight connector and attribute
458
        @author     humkyung
459
        @date       2018.05.02
460
        @history    kyouho 2018.07.18 edit ArrowCursor
461
    '''
462
    def hoverLeaveEvent(self, event):
463
        self.highlight(False)
464

    
465
    def highlight(self, flag):
466
        """ highlight/unhighlight the symbol """
467

    
468
        try:
469
            self.hover = flag 
470
            self.setZValue(QEngineeringAbstractItem.HOVER_ZVALUE) if flag else self.setZValue(SymbolSvgItem.ZVALUE)
471
            self.update()
472

    
473
            #for assoc in self.associations():
474
            #    assoc.highlight(flag)
475
        except Exception as ex: 
476
            from App import App 
477
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
478
            App.mainWnd().addMessage.emit(MessageType.Error, message)
479

    
480
    '''
481
        @brief      set highlight
482
        @author     kyouho
483
        @date       2018.08.27
484
    '''
485
    def setHightlight(self):
486
        self.setColor('url(#hover)')
487
        self.update()
488

    
489
    '''
490
        @brief      unset highlight
491
        @author     kyouho
492
        @date       2018.08.27
493
    '''
494
    def unsetHightlight(self):
495
        self.setColor('url(#normal)')
496
        self.update()
497

    
498
    '''
499
        @brief  change cursor to CrossCursor if mouse point is close to connection point
500
        @author humkyung
501
        @date   2018.04.28
502
    '''
503
    def hoverMoveEvent(self, event):
504
        pass
505

    
506
    '''
507
        @brief      Mouse Press Event
508
        @author     Jeongwoo
509
        @date       18.04.11
510
        @history    kyouho 2018.07.18 add isClick logic
511
    '''
512
    def mousePressEvent(self, event):
513
        if event.buttons() == Qt.LeftButton:
514
            self.clicked.emit(self)
515

    
516
    '''
517
        @brief      call on_pos_changed signal
518
        @author     humkyung
519
        @date       19.07.17
520
    '''
521
    def mouseReleaseEvent(self, event):
522
        super().mouseReleaseEvent(event)
523

    
524
    def itemChange(self, change, value):
525
        """ call signals when item's position is changed """
526
        if change == QGraphicsItem.ItemPositionHasChanged:
527
            self.transfer.on_pos_changed.emit(self)
528
            return value
529
        
530
        return super().itemChange(change, value)
531

    
532
    def removeSelfAttr(self, attributeName):
533
        target = None
534
        for attr in self.attrs:
535
            if attr.Attribute == attributeName:
536
                target = attr
537
                break
538
                
539
        if target:
540
            del self.attrs[attr]
541

    
542
    '''
543
        @brief      Check Overlap
544
        @author     kyouho
545
        @date       18.07.17
546
    '''
547
    def isOverlapItemAndPoint(self, item, point):
548
        x = point.x()
549
        y = point.y()
550
        loc = item.loc
551
        size = item.size
552

    
553
        if loc[0] <= x and loc[0] + size[0] >= x and loc[1] <= y and loc[1] + size[1] >= y:
554
            return True
555
        else:
556
            return False
557

    
558
    '''
559
        @brief  remove item when user press delete key
560
        @author humkyung
561
        @date   2018.04.23
562
        @history    2018.05.17  Jeongwoo    Add if-statement and move 'break'
563
                    2018.05.25  Jeongwoo    Seperate delete item method
564
    '''
565
    def keyPressEvent(self, event):
566
        if not self.isSelected(): return
567

    
568
        if event.key() == Qt.Key_Delete:
569
            self.deleteSvgItemFromScene()
570
        elif event.key() == Qt.Key_QuoteLeft:
571
            self.mouseDoubleClickEvent(event)
572
        
573
           
574
    '''
575
        @brief      connect attribute
576
        @author     humkyung
577
        @date       2018.05.02
578
        @history    humkyung 2018.05.09 append only nearest size attribute
579
    '''
580
    def connectAttribute(self, attributes, clear=True):
581
        import math
582
        from EngineeringTextItem import QEngineeringTextItem
583
        from QEngineeringSizeTextItem import QEngineeringSizeTextItem
584
        from EngineeringInstrumentItem import QEngineeringInstrumentItem
585
        from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
586

    
587
        try:
588
            if clear:
589
                self.clear_attr_and_assoc_item()
590

    
591
            configs = AppDocData.instance().getConfigs('Range', 'Detection Ratio')
592
            ratio = float(configs[0].value) if 1 == len(configs) else 1.5
593
            
594
            dist = max(self.sceneBoundingRect().height(), self.sceneBoundingRect().width()) * ratio
595
            center = self.sceneBoundingRect().center()
596

    
597
            minDist = None
598
            selected = None
599
            for attr in attributes:
600
                # size text and operation code text will find onwer themselves in findowner method
601
                if False:# type(attr) is QEngineeringSizeTextItem or type(attr) is QEngineeringValveOperCodeTextItem:
602
                    dx = attr.center().x() - center.x()
603
                    dy = attr.center().y() - center.y()
604
                    length = math.sqrt(dx*dx + dy*dy)
605
                    if (length < dist) and (minDist is None or length < minDist):
606
                        minDist = length
607
                        selected = attr
608
                elif type(attr) is QEngineeringInstrumentItem:
609
                    if not attr.is_connected:
610
                        dx = attr.center().x() - center.x()
611
                        dy = attr.center().y() - center.y()
612
                        if math.sqrt(dx*dx + dy*dy) < dist:
613
                            if self.add_assoc_item(attr):
614
                                attr.owner = self
615

    
616
            if selected is not None:
617
                if self.add_assoc_item(selected):
618
                    selected.owner = self
619

    
620
        except Exception as ex:
621
            from App import App 
622
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
623
            App.mainWnd().addMessage.emit(MessageType.Error, message)
624

    
625
    '''
626
        @brief      Double click event, Show rotate symbol dialog
627
        @author     euisung
628
        @date       2019.04.16
629
    '''
630
    def mouseDoubleClickEvent(self, event):
631
        func_map = [
632
            (('Equipment - [ Pressure Drop ]', 'Air Fin Cooler', 'Air Fin Cooler'), self.show_AirFinCooler),
633
            (('Equipment - [ Pressure Drop ]', 'Filter', ('Horizontal','Vertical')), self.show_Filter),
634
            (('Equipment - [ Pressure Drop ]', 'Heat Exchanger', ('Double Pipe','Horizontal','Vertical','Kettle')), self.show_ShlTubHeatExchanger),
635
            (('Equipment - [ Pressure Drop ]', 'Heat Exchanger', ('Plate')), self.show_PlateHeatExchanger),
636
            (('Equipment - [ Pressure Drop ]', 'Miscellaneous', ('Coil')), self.show_Coil),
637
            (('Equipment - [ Pressure Drop ]', 'Miscellaneous', ('Equipment')), self.show_DP_Equipment),
638
            (('Equipment - [ Pressure Drop ]', 'Miscellaneous', ('Reactor')), self.show_Reactor),
639
            (('Equipment - [ Pressure Drop ]', 'Strainer', ('Horizontal T','Vertical T')), self.show_Strainer_T),
640
            (('Equipment - [ Pressure Drop ]', 'Strainer', ('Horizontal Y','Vertical Y')), self.show_Strainer_Y),
641
            (('Equipment - [ Pressurized ]', 'Battery Limit', None), self.show_BatteryLimit),
642
            (('Equipment - [ Pressurized ]', 'Column', ('Tray')), self.show_Tray),
643
            (('Equipment - [ Pressurized ]', 'Column', ('Single Packed')), self.show_SinglePacked),
644
            (('Equipment - [ Pressurized ]', 'Column', ('Dual Packed')), self.show_DualPacked),
645
            (('Equipment - [ Pressurized ]', 'Drum', ('Horizontal')), self.show_Drum_Horizontal),
646
            (('Equipment - [ Pressurized ]', 'Drum', ('Vertical')), self.show_Drum_Vertical),
647
            (('Equipment - [ Pressurized ]', 'Miscellaneous', ('Equipment')), self.show_Equipment),
648
            (('Equipment - [ Pressurized ]', 'Tank', ('Ball')), self.show_Ball),
649
            (('Equipment - [ Pressurized ]', 'Tank', ('Cone Roof')), self.show_ConeRoof),
650
            (('Equipment - [ Rotating ]', 'Compressor', ('Left','Right')), self.show_Compressor),
651
            (('Equipment - [ Rotating ]', 'Pump', ('Horizontal Left','Horizontal Right','Vertical')), self.show_Pump),
652
            (('Instrument', 'Valve', ('Horizontal Control','Vertical Control')), self.show_ValveControl),
653
            (('Instrument', 'Valve', ('Horizontal Manual','Vertical Manual')), self.show_ValveManual),
654
            (('Instrument', 'Line Splitter', ('Line Splitter')), self.show_LineSplitter),
655
            (('Instrument', 'Flowmeter', ('Horizontal Orifice','Horizontal Others','Horizontal Venturi','Vertical Orifice','Vertical Others','Vertical Venturi')), self.show_Flowmeter),
656
            (('Instrument', 'Reducer', ('Down','Left','Right','Up')), self.show_Reducer)
657
            ]
658

    
659
        connectedItems = [connector for connector in self.connectors if connector.connectedItem is not None]
660
        if len(connectedItems) < 1:     
661

    
662
            msg = QMessageBox()
663
            msg.setIcon(QMessageBox.Information)
664
            msg.setText(self.tr('Connect Line before Data input'))
665
            msg.setWindowTitle(self.tr("Notice"))
666
            msg.setStandardButtons(QMessageBox.Ok)
667
            msg.exec_()       
668
            return
669

    
670
        matches = [func for func in func_map if func[0][0] == self.category and func[0][1] == self.type and (func[0][2] is None or self.name in func[0][2])]
671
        if matches: matches[0][1]()
672

    
673
    def show_AirFinCooler(self):
674
        from AirFinCooler import QAirFinCooler
675

    
676
        dialog = QAirFinCooler()
677
        dialog.showDialog(self)
678

    
679
    def show_Filter(self):
680
        from Filter import QFilter
681
    
682
        dialog = QFilter()
683
        dialog.showDialog(self)
684

    
685
    def show_Coil(self):
686
        from Coil import QCoil
687
    
688
        dialog = QCoil()
689
        dialog.showDialog(self)
690

    
691
    def show_DP_Equipment(self):
692
        from DP_Equipment import QDP_Equipment
693
                                 
694
        dialog = QDP_Equipment()
695
        dialog.showDialog(self)
696

    
697
    def show_Reactor(self):
698
        from Reactor import QReactor
699
                                 
700
        dialog = QReactor()
701
        dialog.showDialog(self)
702

    
703
    def show_Strainer_T(self):
704
        from Strainer_T import QStrainer_T
705
    
706
        dialog = QStrainer_T()
707
        dialog.showDialog(self)
708

    
709
    def show_Strainer_Y(self):
710
        from Strainer_Y import QStrainer_Y
711
        
712
        dialog = QStrainer_Y()
713
        dialog.showDialog(self)
714

    
715
    def show_BatteryLimit(self):
716
        from BatteryLimit import QBatteryLimit
717
        
718
        dialog = QBatteryLimit()
719
        dialog.showDialog(self)
720
    
721
    def show_Tray(self):
722
        from Tray import QTray
723
        
724
        dialog = QTray()
725
        dialog.showDialog(self)
726

    
727
    def show_SinglePacked(self):
728
        from SinglePacked import QSinglePacked
729
        
730
        dialog = QSinglePacked()
731
        dialog.showDialog(self)
732

    
733
    def show_DualPacked(self):
734
        from DualPacked import QDualPacked
735
        
736
        dialog = QDualPacked()
737
        dialog.showDialog(self)
738

    
739
    def show_Drum_Horizontal(self):
740
        from Drum_Horizontal import QDrum_Horizontal
741
        
742
        dialog = QDrum_Horizontal()
743
        dialog.showDialog(self)
744

    
745
    def show_Drum_Vertical(self):
746
        from Drum_Vertical import QDrum_Vertical
747
        
748
        dialog = QDrum_Vertical()
749
        dialog.showDialog(self)
750

    
751
    def show_PlateHeatExchanger(self):
752
        from PlateHeatExchanger import QPlateHeatExchanger
753
        
754
        dialog = QPlateHeatExchanger()
755
        dialog.showDialog(self)
756

    
757
    def show_Equipment(self):
758
        from Equipment import QEquipment
759
        
760
        dialog = QEquipment()
761
        dialog.showDialog(self)
762

    
763
    def show_Ball(self):
764
        from Ball import QBall
765
        
766
        dialog = QBall()
767
        dialog.showDialog(self)
768

    
769
    def show_ShlTubHeatExchanger(self):
770
        from ShlTubHeatExchanger import QShlTubHeatExchanger
771
        
772
        dialog = QShlTubHeatExchanger()
773
        dialog.showDialog(self)
774

    
775
    def show_ConeRoof(self):
776
        from ConeRoof import QConeRoof
777
        
778
        dialog = QConeRoof()
779
        dialog.showDialog(self)
780
    
781
    def show_DomeRoof(self):
782
        from DomeRoof import QDomeRoof
783
            
784
        dialog = QDomeRoof()
785
        dialog.showDialog(self)
786

    
787
    def show_Compressor(self):
788
        from Compressor import QCompressor
789
            
790
        dialog = QCompressor()
791
        dialog.showDialog(self)
792

    
793
    def show_Pump(self):
794
        from Pump import QPump
795
            
796
        dialog = QPump()
797
        dialog.showDialog(self)
798

    
799
    def show_ValveControl(self):
800
        from Valve_Control import QValve_Control
801
            
802
        dialog = QValve_Control()
803
        dialog.showDialog(self)
804

    
805
    def show_ValveManual(self):
806
        from Valve_Manual import QValve_Manual
807
            
808
        dialog = QValve_Manual()
809
        dialog.showDialog(self)
810

    
811
    def show_LineSplitter(self):
812
        from LineSplitter import QLineSplitter
813
            
814
        dialog = QLineSplitter()
815
        dialog.showDialog(self)
816

    
817
    def show_Flowmeter(self):
818
        from Flowmeter import QFlowmeter
819
            
820
        dialog = QFlowmeter()
821
        dialog.showDialog(self)
822

    
823
    def show_Reducer(self):
824
        from Reducer import QReducer
825
            
826
        dialog = QReducer()
827
        dialog.showDialog(self)
828

    
829
    @staticmethod 
830
    def fromDatabase(componentInfos):
831
        """ create a componenet from database """
832
        item = None
833

    
834
        try:
835
            uid = componentInfos[0][0]              # uid@Components
836
            dbUid = componentInfos[0][2]            # Symbol_UID@Components
837
            category = componentInfos[0][3]         # Category@SymbolType
838
            _type = componentInfos[0][4]            # Type@SymbolType
839
            name = componentInfos[0][5]             # Name@Symbols
840
            originalPoint = componentInfos[0][6]    # OriginalPoint@Symbols
841
            x = componentInfos[0][7]                # X@Components
842
            y = componentInfos[0][8]                # Y@Components
843
            angle = componentInfos[0][9]            # Rotation@Components        
844
            scale = componentInfos[0][10]           # Scale@Components        
845

    
846
            pt = []
847
            pt.append(float(x))
848
            pt.append(float(y))
849

    
850
            origin = [float(x) for x in str(originalPoint).split(',')]
851

    
852
            connPts = []
853

    
854
            pointsUids = []
855
            for componentInfo in componentInfos:
856
                pointsUid = componentInfo[11]       # uid@Points
857
                pointsUids.append(pointsUid)
858

    
859
            appDocData = AppDocData.instance()
860
            project = appDocData.getCurrentProject()
861
            svgFilePath = os.path.join(project.getSvgFilePath(), category, _type, name + '.svg')
862
            if os.path.isfile(svgFilePath):
863
                item = SymbolSvgItem.createItem(_type, svgFilePath, uid)
864
                item.setVisible(False)
865
                item.buildItem(name, _type, float(angle), float(scale), pt, origin, connPts, dbUid, pointsUids)
866

    
867
                for area in appDocData.getAreaList():
868
                    if area.contains(pt):
869
                        item.area = area.name
870
                        break
871
                
872
        except Exception as ex:
873
            from App import App 
874
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
875
            App.mainWnd().addMessage.emit(MessageType.Error, message)
876

    
877
        return item
878

    
879
    '''
880
        @brief      create item corresponding to given type
881
        @author     humkyung
882
        @date       2018.05.02
883
        @history    2018.05.08  Jeongwoo    Change type name (Piping OPC''S → Piping OPC's)
884
                    humkyung 2018.05.10 change symbol's color to blue
885
                    humkyung 2018.07.19 create nozzle instance if type is 'Nozzles'
886
    '''
887
    @staticmethod
888
    def createItem(type, path, uid=None, owner=None, flip=0):
889
        from QEngineeringOPCItem import QEngineeringOPCItem
890
        from EngineeringEquipmentItem import QEngineeringEquipmentItem
891
        from EngineeringInstrumentItem import QEngineeringInstrumentItem
892
        from EngineeringNozzleItem import QEngineeringNozzleItem
893
        from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
894
        from EngineeringReducerItem import QEngineeringReducerItem
895
        from EngineeringErrorItem import QEngineeringErrorItem
896
        from EngineeringEndBreakItem import QEngineeringEndBreakItem
897
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
898
        from AppDocData import AppDocData
899
        import uuid
900

    
901
        docData = AppDocData.instance()
902

    
903
        item = None
904
        cateogry = docData.getSymbolCategoryByType(type)
905
        if type == "Piping OPC's":
906
            item = QEngineeringOPCItem(path, uid, flip=flip)
907
        elif cateogry == 'Equipment':
908
            item = QEngineeringEquipmentItem(path, uid, flip=flip)
909
        elif cateogry == 'Instrumentation':
910
            item = QEngineeringInstrumentItem(path, uid, flip=flip)
911
        #elif type == 'Nozzles':
912
        #    item = QEngineeringNozzleItem(path, uid, flip=flip)
913
        elif type == 'Segment Breaks':
914
            item = QEngineeringSpecBreakItem(path, uid, flip=flip)
915
        elif type == 'Reducers':
916
            item = QEngineeringReducerItem(path, uid, flip=flip)
917
        elif type == 'Error':
918
            item = QEngineeringErrorItem(path, uid, flip=flip)
919
        elif type == 'End Break':
920
            item = QEngineeringEndBreakItem(path, uid, flip=flip)
921
        elif type == 'Line':
922
            item = QEngineeringFlowMarkItem(path, uid, flip=flip)
923
        elif type == 'Steam Line':
924
            item = QEngineeringStreamlineItem(uid)
925
        else:
926
            item = SymbolSvgItem(path, uid, flip=flip)
927

    
928
        if owner is not None:
929
            item.owner = uuid.UUID(owner, version=4)
930

    
931
        return item
932

    
933
    '''
934
        @brief      change svg's color
935
        @author     humkyung
936
        @date       2018.05.10
937
        @history    2018.05.11  Jeongwoo    Override QEngineeringAbstractItem's
938
                    humkyung 2018.05.13 update after change color
939
    '''
940
    def setColor(self, color):
941
        self.changeAttributes('fill', color)
942
        self.changeAttributes('stroke', color)
943
        self.renderer().load(self._document.toByteArray())
944
        self.update()
945

    
946
    def getColor(self):
947
        """ return hover color if mouse is over otherwise reutrn owner's color if owner exist else this color """
948
        return SymbolSvgItem.HOVER_COLOR if self.hover else (self.owner._color if self.owner and hasattr(self.owner, '_color') else self._color)
949

    
950
    '''
951
        @brief  get attributes from svg file
952
        @author humkyung
953
        @date   2019.03.08
954
    '''
955
    def get_attribute(self, attName):
956
        root = self._document.documentElement()
957
        node = root.firstChild()
958
        while not node.isNull():
959
            if node.isElement():
960
                element = node.toElement()
961
                if element.hasAttribute(attName):
962
                    return element.attribute(attName)
963

    
964
                if element.hasChildNodes():
965
                    att_val = self.recursive_get_attribute(element.firstChild(), attName)
966
                    if att_val is not None: return att_val
967

    
968
            node = node.nextSibling()
969

    
970
        return None
971

    
972
    '''
973
        @brief  get recursively attribute
974
        @author humkyung
975
        @date   2019.03.08
976
    '''
977
    def recursive_get_attribute(self, node, attName):
978
        while not node.isNull():
979
            if node.isElement():
980
                element = node.toElement()
981
                if element.hasAttribute(attName):
982
                    return element.attribute(attName)
983

    
984
                if node.hasChildNodes():
985
                    att_val = self.recursive_get_attribute(node.firstChild(), attName)
986
                    if att_val is not None: return att_val
987
            
988
            node = node.nextSibling()
989

    
990
        return None
991

    
992
    '''
993
        @brief  change attributes
994
        @author humkyung
995
        @date   2018.05.10
996
    '''
997
    def changeAttributes(self, attName, attValue):
998
        root = self._document.documentElement()
999
        node = root.firstChild()
1000
        while not node.isNull():
1001
            if node.isElement():
1002
                element = node.toElement()
1003
                if element.hasAttribute(attName):
1004
                    element.setAttribute(attName, attValue)
1005

    
1006
                if element.hasChildNodes():
1007
                    recursiveChangeAttributes(element.firstChild(), attName, attValue)
1008

    
1009
            node = node.nextSibling()
1010

    
1011
    '''
1012
        @brief  change attribute
1013
        @author humkyung
1014
        @date   2018.05.10
1015
    '''
1016
    def recursiveChangeAttributes(self, node, attName, attValue):
1017
        while not node.isNull():
1018
            if node.isElement():
1019
                element = node.toElement()
1020
                if element.hasAttribute(attName):
1021
                    element.setAttribute(attName, attValue)
1022

    
1023
                if node.hasChildNodes():
1024
                    recursiveChangeAttributes(node.firstChild(), attName, attValue)
1025
            
1026
            node = node.nextSibling()
1027

    
1028
    '''
1029
        @brief  draw rect when item is selected
1030
        @author humkyung
1031
        @date   2018.07.07
1032
    '''
1033
    def drawFocusRect(self, painter):
1034
        self.focuspen = QPen(Qt.DotLine)
1035
        self.focuspen.setColor(Qt.black)
1036
        self.focuspen.setWidthF(1.5)
1037
        hilightColor = QColor(255, 0, 0, 127)
1038
        painter.setBrush(QBrush(hilightColor))
1039
        painter.setPen(self.focuspen)
1040
        painter.drawRect(self.boundingRect())
1041

    
1042
    '''
1043
        @brief  override paint(draw connection points)
1044
        @author humkyung
1045
        @date   2018.04.21
1046
    '''
1047
    def paint(self, painter, options=None, widget=None):
1048
        from EngineeringAbstractItem import QEngineeringAbstractItem
1049
        from EngineeringTextItem import QEngineeringTextItem
1050

    
1051
        self.setColor(self.getColor())
1052

    
1053
        painter.setClipRect(options.exposedRect)
1054
        QGraphicsSvgItem.paint(self, painter, options, widget)
1055
        for attr in self.attrs:
1056
            if issubclass(type(attr), QEngineeringTextItem):
1057
                color = QEngineeringAbstractItem.HOVER_COLOR if self.hover else (self._owner._color if self._owner else QEngineeringAbstractItem.DEFAULT_COLOR)
1058
                attr.setColor(color)
1059
            elif issubclass(type(attr), SymbolSvgItem):
1060
                attr.setColor(self.getColor())
1061
                attr.update()
1062

    
1063
        if self.isSelected():
1064
            self.drawFocusRect(painter)
1065

    
1066
    '''
1067
        @brief      Add Svg Item into ImageViewer's Scene
1068
        @author     Jeongwoo
1069
        @date       2018.05.03
1070
        @history    add connectors which's parent is symbol
1071
                    kyouho  2018.07.30  remove connectors logic
1072
    '''
1073
    def addSvgItemToScene(self, scene):
1074
        transform = QTransform()
1075

    
1076
        transform.translate(self.loc[0] + self.symbolOrigin[0], self.loc[1] + self.symbolOrigin[1])
1077
        transform.rotateRadians(-self.angle)
1078
        transform.translate(-self.symbolOrigin[0], -self.symbolOrigin[1])
1079
        transform.scale(self._scale, self._scale)
1080

    
1081
        self.setTransform(transform)
1082
        scene.addItem(self)
1083

    
1084
    '''
1085
        @brief      
1086
        @author     humkyung
1087
        @date       2018.07.27
1088
    '''
1089
    def onConnectorPosChaned(self, connector):
1090
        pass
1091

    
1092
    '''
1093
        @brief      set connector
1094
        @author     kyouho
1095
        @date       2018.07.26
1096
    '''
1097
    def setConnector(self, uid, index=None):
1098
        from AppDocData import AppDocData
1099

    
1100
        app_doc_data = AppDocData.instance()
1101
        connector = QEngineeringConnectorItem(uid, parent=self, index=index)
1102
        connector.nozzle_data = app_doc_data.get_nozzle_data(uid)
1103
        connector.setParentItem(self)
1104
        self.connectors.append(connector)
1105

    
1106
    '''
1107
    '''
1108
    def refreshConnector(self):
1109
        for connector in self.connectors:
1110
            connector.buildItem()
1111

    
1112
    def deleteSvgItemFromScene(self):
1113
        """ remove self from scene """
1114
        try:
1115
            for conn in self.connectors:
1116
                if conn.connectedItem is not None:
1117
                    conn.connectedItem.connect(None)
1118
        except Exception as ex:
1119
            from App import App
1120
            from AppDocData import MessageType
1121

    
1122
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1123
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1124

    
1125
        self.transfer.onRemoved.emit(self)
1126
        
1127
    '''
1128
        @brief      Return real item position
1129
        @author     Jeongwoo
1130
        @date       2018.05.25
1131
    '''
1132
    def boundingRectOnScene(self):
1133
        rect = self.boundingRect()
1134
        rect.moveTo(self.loc[0], self.loc[1])
1135
        return rect
1136

    
1137
    def flipSymbol(self):
1138
        '''
1139
            @brief  remove item when user press delete key
1140
            @author humkyung
1141
            @date   2018.04.23
1142
        '''
1143
        if self.flip is 0:
1144
            self.flip = 1
1145
        else:
1146
            self.flip = 0
1147

    
1148
        currentPoint = self.getCurrentPoint()
1149
        self.reSettingSymbol(currentPoint, self.angle)
1150

    
1151
    '''
1152
        @brief      rotate Symbol
1153
        @author     kyouho
1154
        @date       2018.07.24
1155
    '''
1156
    def rotateSymbol(self, angle=None):
1157
        if angle is None:
1158
            #degree 0
1159
            if 0 == self.angle:
1160
                self.angle = 1.57
1161
            #degree 90
1162
            elif (1.57 == self.angle):
1163
                self.angle = 3.14
1164
            #degree 180
1165
            elif 3.14 == self.angle:
1166
                self.angle = 4.71
1167
            #degree 270
1168
            elif 4.71 == self.angle :
1169
                self.angle = 0
1170
            else:
1171
                self.angle = 0
1172
                
1173
            self.size[0], self.size[1] = self.size[1], self.size[0]
1174
        else:
1175
            self.angle = angle
1176
        
1177
        #scene = self.scene()
1178
        #self.scene().removeItem(self)
1179
        #self.addSvgItemToScene(scene)
1180
        currentPoint = self.getCurrentPoint()
1181
        self.reSettingSymbol(currentPoint, self.angle)
1182

    
1183
    '''
1184
        @brief      resetting rotate Symbol
1185
        @author     kyouho
1186
        @date       2018.07.24
1187
    '''
1188
    def reSettingSymbol(self, standardPoint, angle):
1189
        transform = QTransform()
1190
        
1191
        transform.translate(self.loc[0] + self.symbolOrigin[0], self.loc[1] + self.symbolOrigin[1])
1192
        transform.rotateRadians(-angle)
1193
        transform.translate(-standardPoint[0], -standardPoint[1])
1194

    
1195
        if self.flip is 1:
1196
            transform.scale(-1.0, 1.0)
1197
            transform.translate(-self.size[0], 0)
1198

    
1199
        self.setTransform(transform)
1200
        self.reSettingConnetors()
1201

    
1202
    def reSettingConnetors(self):
1203
        for conn in self.connectors:
1204
            conn.sceneConnectPoint = (conn.sceneBoundingRect().center().x(), conn.sceneBoundingRect().center().y())
1205

    
1206
        from EngineeringLineItem import QEngineeringLineItem
1207
        for connector in self.connectors:
1208
            if connector.connectedItem is not None and type(connector.connectedItem) == QEngineeringLineItem:
1209
                line = connector.connectedItem
1210
                line.reDrawLine(self, connector.center())
1211
                line.update_arrow()
1212

    
1213
    '''
1214
        @brief      change Conn point 
1215
        @author     kyouho
1216
        @date       2018.07.25
1217
    '''
1218
    def changeConnPoint(self):
1219
        if len(self.connectors) == 2:
1220

    
1221
            conn1Item = self.connectors[0].connectedItem
1222
            conn2Item = self.connectors[1].connectedItem
1223
            self.connectors[0].connectedItem = conn2Item
1224
            self.connectors[1].connectedItem = conn1Item
1225

    
1226
            currentPoint = self.getCurrentPoint()
1227
            self.reSettingSymbol(currentPoint, self.angle)
1228

    
1229
    '''
1230
        @brief      change standard point
1231
        @author     kyouho
1232
        @date       2018.07.24
1233
    '''
1234
    def changeStandardPoint(self):
1235
        connPtsCount = len(self.connectors)
1236
        
1237
        if self.currentPointModeIndex < connPtsCount:
1238
            self.currentPointModeIndex += 1
1239
        else:
1240
            self.currentPointModeIndex = 0
1241

    
1242
        currentPoint = self.getCurrentPoint()
1243
        self.reSettingSymbol(currentPoint, self.angle)
1244
    
1245
    '''
1246
        @brief      get standard point
1247
        @author     kyouho
1248
        @date       2018.07.25
1249
    '''
1250
    def getCurrentPoint(self):
1251
        #from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
1252

    
1253
        pointList = []
1254
        pointList.append(self.symbolOrigin)
1255
        for connector in self.connectors:
1256
            pointList.append(connector.connectPoint)
1257

    
1258
        #if type(self) is QEngineeringSpecBreakItem:
1259
        #    self.currentPointModeIndex = 1
1260

    
1261
        return pointList[self.currentPointModeIndex]
1262

    
1263
    '''
1264
        @brief      심볼 회전 시 서로 다른 기준점으로 회전하기 때문에 기준점을 이후 개발한 SymbolSvgItem 기준의 회전좌표로 이동하기 위해서 만듬 (loc 기준으로 회전해야함)
1265
        @author     kyouho
1266
        @date       18.08.06
1267
    '''
1268
    def reCalculationRotatedItem(self):
1269

    
1270
        transform = QTransform()
1271
        transform.translate(self.loc[0] + self.symbolOrigin[0], self.loc[1] + self.symbolOrigin[1])
1272
        transform.rotateRadians(-self.angle)
1273
        currentPoint = self.getCurrentPoint()
1274
        transform.translate(-currentPoint[0], -currentPoint[1])
1275
        # 시작점을 구하기 위해서
1276
        goPoint = transform.map(QPoint(self.symbolOrigin[0], self.symbolOrigin[1]))
1277
        
1278
        self.loc = [self.loc[0] + self.origin[0] - goPoint.x(), self.loc[1] + self.origin[1] - goPoint.y()]
1279

    
1280
    def resize(self, change):
1281
        """ resize item """
1282
        # Get the smaller side of the rect
1283
        rect = self.sceneBoundingRect()
1284
        loc = QPointF(rect.x(), rect.y())
1285
        self.resetTransform()
1286
        #self.setScale(1)
1287
        rect = self.sceneBoundingRect()
1288
        scale = [(change.width() - loc.x())/rect.width(), (change.height() - loc.y())/rect.height()]
1289
        #scale the item
1290
        if scale[0] > 0 and scale[1] > 0:
1291
            self.setPos(loc)
1292
            #self.setScale(scale[0] if scale[0] < scale[1] else scale[1])
1293
            trans = QTransform()
1294
            trans.scale(scale[0] if scale[0] < scale[1] else scale[1],scale[0] if scale[0] < scale[1] else scale[1])
1295
            self.setTransform(trans)
1296
            self.prepareGeometryChange()
1297
            self.update()
1298

    
1299
            self.transfer.on_size_changed.emit(self)
1300

    
1301
    def moveto(self, to, timeLine = 5000, rotation = 0):
1302
        """Move the item from one position to one other."""
1303

    
1304
        anim = QPropertyAnimation(self, b'pos')
1305
        rect = self.sceneBoundingRect()
1306
        anim.setStartValue(QPointF(0, 0))
1307
        anim.setEndValue(QPointF(100,10))
1308
        anim.setDuration(10000)
1309
        anim.start()
1310

    
1311
def recursiveChangeAttributes(node, attName, attValue):
1312
    while not node.isNull():
1313
        if node.isElement():
1314
            element = node.toElement()
1315
            if element.hasAttribute(attName):
1316
                element.setAttribute(attName, attValue)
1317

    
1318
            if node.hasChildNodes():
1319
                recursiveChangeAttributes(node.firstChild(), attName, attValue)
1320
        
1321
        node = node.nextSibling()
1322

    
1323
'''
1324
    @brief      The class transfer pyqtSignal Event. Cause Subclass of QGraphicsRectItem can't use pyqtSignal
1325
    @author     Jeongwoo
1326
    @date       2018.06.18
1327
'''
1328
class Transfer(QObject):
1329
    on_pos_changed = pyqtSignal(QGraphicsItem)
1330
    on_size_changed = pyqtSignal(QGraphicsItem)
1331
    onRemoved = pyqtSignal(QGraphicsItem)
1332

    
1333
    def __init__(self, parent = None):
1334
        QObject.__init__(self, parent)
1335

    
1336

    
1337
if __name__ == '__main__':
1338
    f = QFile('d:/Projects/DTIPID/DTI_PID/DTI_PID/SG_TEST/svg/ANGLE VALVE.svg')
1339
    f.open(QIODevice.ReadOnly)
1340
    array = f.readAll()
1341
    document = QDomDocument()
1342
    document.setContent(array)
1343

    
1344
    root = document.documentElement()
1345
    node = root.firstChild()
1346
    while not node.isNull():
1347
        if node.isElement():
1348
            element = node.toElement()
1349
            if element.hasAttribute('fill'):
1350
                element.setAttribute('fill', '#FFFFF')
1351

    
1352
            if element.hasChildNodes():
1353
                recursiveChangeAttributes(element.firstChild(), 'fill', '#FFFFF')
1354

    
1355
        node = node.nextSibling()
클립보드 이미지 추가 (최대 크기: 500 MB)