프로젝트

일반

사용자정보

통계
| 개정판:

hytos / HYTOS / HYTOS / Shapes / EngineeringDimensionItem.py @ 759bdc98

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

1
# coding: utf-8
2
import os.path
3
import copy
4
import sys
5

    
6
try:
7
    from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QObject, QT_VERSION_STR, QRect
8
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QTransform, QFont, QColor, QFontMetricsF
9
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, \
10
        QGraphicsPathItem
11
except ImportError:
12
    try:
13
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QRect, QObject, QT_VERSION_STR
14
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont, \
15
            QColor, QFontMetricsF
16
    except ImportError:
17
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
18

    
19
from AppDocData import *
20
from EngineeringAbstractItem import QEngineeringAbstractItem
21

    
22

    
23
class QEngineeringDimensionItem(QGraphicsPathItem, QEngineeringAbstractItem):
24
    selected_change = pyqtSignal(QGraphicsItem)
25

    
26
    ARROW_SIZE = 10
27
    DIMENSION_DEPTH = 30
28
    HIGHLIGHT = '#BC4438'
29
    ZVALUE = 210
30

    
31
    def __init__(self, uid=None, pts=None):
32
        import uuid
33

    
34
        QGraphicsPathItem.__init__(self, None)
35
        QEngineeringAbstractItem.__init__(self)
36

    
37
        self.uid = uuid.uuid4() if uid is None else uuid.UUID(uid, version=4)
38
        self.type = 'Dimension'
39
        self.loc = None
40
        self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)
41
        self.setAcceptHoverEvents(True)
42
        self.setAcceptTouchEvents(True)
43

    
44
        self._selected_idx = None
45
        self.setPath(self.create_path(pts))
46
        self.setBrush(Qt.black)
47

    
48
        self.transfer = Transfer()
49
        self.setZValue(QEngineeringDimensionItem.ZVALUE)
50

    
51
    def __str__(self):
52
        """ return string represent uuid """
53
        return str(self.uid)
54

    
55
    @property
56
    def pos(self):
57
        """return dimension position"""
58
        path = self.mapToScene(self.path())
59
        return [QPointF(path.elementAt(0).x, path.elementAt(0).y), QPointF(path.elementAt(1).x, path.elementAt(1).y)]
60

    
61
    def set_pos(self, pts):
62
        """set dimension positions"""
63

    
64
        if pts and 2 == len(pts):
65
            self.setPath(self.create_path(pts))
66

    
67
    def create_path(self, pts):
68
        """create a path"""
69
        import math
70
        from EngineeringConnectorItem import QEngineeringConnectorItem
71

    
72
        #self.resetTransform()
73
        path = QPainterPath()
74
        if pts:
75
            if 1 == len(pts):
76
                pts.append(QPointF(pts[0].x() + 10, pts[0].y() + 10))
77

    
78
            path.moveTo(pts[0])
79
            path.lineTo(pts[1])
80

    
81
            dx = pts[1].x() - pts[0].x()
82
            dy = pts[1].y() - pts[0].y()
83
            length = math.sqrt(dx*dx + dy*dy)
84
            if length:
85
                _dir = [dx / length, dy / length]
86

    
87
                arrow_size = QEngineeringDimensionItem.ARROW_SIZE * 0.25
88

    
89
                perpendicular = (-_dir[1], _dir[0])
90
                polygon = QPolygonF()
91
                polygon.append(QPointF(
92
                    pts[1].x() - _dir[0] * QEngineeringDimensionItem.ARROW_SIZE + perpendicular[0] * arrow_size,
93
                    pts[1].y() - _dir[1] * QEngineeringDimensionItem.ARROW_SIZE + perpendicular[1] * arrow_size))
94
                polygon.append(QPointF(
95
                    pts[1].x() - _dir[0] * QEngineeringDimensionItem.ARROW_SIZE - perpendicular[0] * arrow_size,
96
                    pts[1].y() - _dir[1] * QEngineeringDimensionItem.ARROW_SIZE - perpendicular[1] * arrow_size))
97
                polygon.append(pts[1])
98
                polygon.append(polygon[0])
99

    
100
                path.addPolygon(polygon)
101

    
102
                polygon = QPolygonF()
103
                polygon.append(QPointF(
104
                    pts[0].x() + _dir[0] * QEngineeringDimensionItem.ARROW_SIZE + perpendicular[0] * arrow_size,
105
                    pts[0].y() + _dir[1] * QEngineeringDimensionItem.ARROW_SIZE + perpendicular[1] * arrow_size))
106
                polygon.append(QPointF(
107
                    pts[0].x() + _dir[0] * QEngineeringDimensionItem.ARROW_SIZE - perpendicular[0] * arrow_size,
108
                    pts[0].y() + _dir[1] * QEngineeringDimensionItem.ARROW_SIZE - perpendicular[1] * arrow_size))
109
                polygon.append(pts[0])
110
                polygon.append(polygon[0])
111

    
112
                path.moveTo(pts[0].x() - perpendicular[0]*5, pts[0].y() - perpendicular[1]*5)
113
                path.lineTo(pts[0].x() + perpendicular[0]*QEngineeringDimensionItem.DIMENSION_DEPTH,
114
                            pts[0].y() + perpendicular[1]*QEngineeringDimensionItem.DIMENSION_DEPTH)
115

    
116
                path.moveTo(pts[1].x() - perpendicular[0]*5, pts[1].y() - perpendicular[1]*5)
117
                path.lineTo(pts[1].x() + perpendicular[0] * QEngineeringDimensionItem.DIMENSION_DEPTH,
118
                            pts[1].y() + perpendicular[1] * QEngineeringDimensionItem.DIMENSION_DEPTH)
119

    
120
                path.addPolygon(polygon)
121

    
122
                path.addEllipse(pts[0], 4, 4)
123
                path.addEllipse(pts[1], 4, 4)
124

    
125
                """
126
                if not self.connectors:
127
                    conn = QEngineeringConnectorItem(uid=None, parent=self, index=0)
128
                    conn.setFlags(
129
                        QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)
130
                    conn.transfer.onPosChanged.connect(self.on_connector_pos_changed)
131
                    self.connectors.append(conn)
132
                    conn = QEngineeringConnectorItem(uid=None, parent=self, index=1)
133
                    conn.setFlags(
134
                        QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable)
135
                    conn.transfer.onPosChanged.connect(self.on_connector_pos_changed)
136
                    self.connectors.append(conn)
137

138
                self.connectors[0].setPos((self._pts[0].x(), self._pts[0].y()))
139
                self.connectors[1].setPos((self._pts[1].x(), self._pts[1].y()))
140
                """
141

    
142
        return path
143

    
144
    """
145
    def on_connector_pos_changed(self, conn):
146
        #rebuild stream line
147
        self._pts[conn._conn_index] = QPointF(conn.center()[0], conn.center()[1])
148
        self.setPath(self.create_path())
149
    """
150

    
151
    '''
152
        @brief      hover event
153
        @authro     humkyung
154
        @date       
155
    '''
156

    
157
    def hoverEnterEvent(self, event):
158
        self.highlight(True)
159

    
160
    def hoverLeaveEvent(self, event):
161
        self.highlight(False)
162

    
163
    def highlight(self, flag):
164
        """highlight dimension"""
165
        if flag:
166
            _pen = self.pen()
167
            _pen.setColor(QColor(QEngineeringAbstractItem.HOVER_COLOR))
168
        else:
169
            _pen = self.pen()
170
            _pen.setColor(Qt.black)
171

    
172
        self.setPen(_pen)
173
        self.update()
174

    
175
    def hoverMoveEvent(self, event):
176
        pass
177

    
178
    def mousePressEvent(self, event):
179
        import math
180

    
181
        if event.buttons() == Qt.LeftButton:
182
            toler = 5
183

    
184
            pos = event.scenePos()
185

    
186
            path = self.mapToScene(self.path())
187
            pts = [QPointF(path.elementAt(0).x, path.elementAt(0).y), QPointF(path.elementAt(1).x, path.elementAt(1).y)]
188

    
189
            dx = pts[0].x() - pos.x()
190
            dy = pts[0].y() - pos.y()
191
            if math.sqrt(dx * dx + dy * dy) < toler:
192
                self._selected_idx = 0
193
                return
194

    
195
            dx = pts[1].x() - pos.x()
196
            dy = pts[1].y() - pos.y()
197
            if math.sqrt(dx * dx + dy * dy) < toler:
198
                self._selected_idx = 1
199
                return
200

    
201
        super(QEngineeringDimensionItem, self).mousePressEvent(event)
202

    
203
    def mouseMoveEvent(self, event):
204
        """reshape dimension"""
205

    
206
        if event.buttons() == Qt.LeftButton and (self._selected_idx == 0 or self._selected_idx == 1):
207
            path = self.mapToScene(self.path())
208
            pts = [QPointF(path.elementAt(0).x, path.elementAt(0).y), QPointF(path.elementAt(1).x, path.elementAt(1).y)]
209
            pts[self._selected_idx] = event.scenePos()
210
            self.setPath(self.create_path(pts))
211
            return
212

    
213
        super(QEngineeringDimensionItem, self).mouseMoveEvent(event)
214

    
215
    def mouseReleaseEvent(self, event: 'QGraphicsSceneMouseEvent') -> None:
216
        self._selected_idx = None
217
        super(QEngineeringDimensionItem, self).mouseReleaseEvent(event)
218

    
219
    def itemChange(self, change, value):
220
        if change == QGraphicsItem.ItemSelectedChange:
221
            pass
222
        return value
223

    
224
    def setColor(self, color):
225
        pass
226

    
227
    @staticmethod
228
    def fromDatabase(componentInfos):
229
        """ create a callout from database """
230
        from PlaceDimensionCommand import PlaceDimensionCommand
231

    
232
        item = None
233

    
234
        try:
235
            uid = componentInfos[0]['Comp_UID']  # uid@Components
236
            tag_no = componentInfos[0]['Name']  # name@Components
237
            index = componentInfos[0]['Comp_Index']
238
            dbUid = componentInfos[0]['Symbols_UID']  # Symbol_UID@Components
239
            category = componentInfos[0]['Category']  # Category@SymbolType
240
            _type = componentInfos[0]['Type']  # Type@SymbolType
241
            name = componentInfos[0]['Symbol_Name']  # Name@Symbols
242
            originalPoint = componentInfos[0]['OriginalPoint']  # OriginalPoint@Symbols
243
            x = componentInfos[0]['Comp_X']  # X@Components
244
            y = componentInfos[0]['Comp_Y']  # Y@Components
245
            angle = componentInfos[0]['Rotation']  # Rotation@Components
246
            scale = componentInfos[0]['Scale']  # Scale@Components
247

    
248
            pt = QPointF(float(x), float(y))
249
            item = PlaceDimensionCommand.create_item(pt)
250
        except Exception as ex:
251
            from App import App
252
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
253
                                                           sys.exc_info()[-1].tb_lineno)
254
            App.mainWnd().addMessage.emit(MessageType.Error, message)
255

    
256
        return item
257

    
258
    def toSql(self):
259
        """convert callout data to sql query"""
260
        from AppDocData import AppDocData
261

    
262
        """ generate sql string to save label to database """
263
        res = []
264

    
265
        try:
266
            cols = ['UID', 'Symbols_UID', 'Name', 'X', 'Y']
267
            values = ['?', "(select uid from Symbols where Name='Callout')", '?', '?', '?']
268

    
269
            param = [str(self.uid), self.toHtml(), self.pos().x(), self.pos().y()]
270
            sql = f"insert or replace into Components({','.join(cols)}) values({','.join(values)})"
271
            res.append((sql, tuple(param)))
272

    
273
            cols, values = ['UID', 'Components_UID', '[Index]', 'X', 'Y'], ['?', '?', '?', '?', '?']
274
            param = [str(self.uid), str(self.uid), 0, self.pos().x(), self.pos().y()]
275
            sql = 'insert or replace into Points({}) values({})'.format(','.join(cols), ','.join(values))
276
            res.append((sql, tuple(param)))
277

    
278
        except Exception as ex:
279
            from App import App
280
            from AppDocData import MessageType
281

    
282
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
283
                                                           sys.exc_info()[-1].tb_lineno)
284
            App.mainWnd().addMessage.emit(MessageType.Error, message)
285

    
286
        return res
287

    
288
'''
289
    @brief      The class transfer pyqtSignal Event. Cause Subclass of QGraphicsRectItem can't use pyqtSignal
290
    @author     Jeongwoo
291
    @date       2018.06.18
292
'''
293

    
294

    
295
class Transfer(QObject):
296
    onRemoved = pyqtSignal(QGraphicsItem)
297

    
298
    def __init__(self, parent=None):
299
        QObject.__init__(self, parent)
클립보드 이미지 추가 (최대 크기: 500 MB)