프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / SymbolTreeWidget.py @ 8701ed58

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

1
# coding: utf-8
2
""" This is Symbol Tree Widget module """
3

    
4
try:
5
    from PyQt5.QtCore import *
6
    from PyQt5.QtGui import *
7
    from PyQt5.QtWidgets import *
8
except ImportError:
9
    try:
10
        from PyQt4.QtCore import *
11
        from PyQt4.QtGui import *
12
    except ImportError:
13
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
14
from AppDocData import *
15
import os
16
import sys
17
import SymbolBase
18
import symbol
19
import SymbolEditorDialog
20
import QSymbolDisplayDialog
21

    
22

    
23
class QSymbolTreeWidget(QTreeWidget):
24
    # Add signal
25
    singleClicked = pyqtSignal(SymbolBase.SymbolBase)
26
    TREE_DATA_ROLE = Qt.UserRole
27

    
28
    def __init__(self):
29
        QTreeWidget.__init__(self)
30
        self.setIconSize(QSize(32, 32))
31

    
32
        self.setDragEnabled(True)  # enable drag
33
        self.initDirTreeWidget()
34
        self.isDoubleClicked = False
35
        self.itemDoubleClicked.connect(self.itemDoubleClickEvent)
36
        self.setContextMenuPolicy(Qt.CustomContextMenu)
37
        self.customContextMenuRequested.connect(self.openContextMenu)
38
        self.currentItemChanged.connect(self.onCurrentItemChanged)
39

    
40
    '''
41
        @brief      Show Context Menu
42
        @author     Jeongwoo
43
        @date       18.04.??
44
        @history    Jeongwoo 2018.04.23 Symbol object Null Check when show context menu
45
                    humkyung 2018.08.14 add menu for symbol type
46
    '''
47

    
48
    def openContextMenu(self, position):
49
        indexes = self.selectedIndexes()
50
        itemPosition = self.mapTo(self, position)
51
        item = self.itemAt(itemPosition)
52
        data = item.data(0, self.TREE_DATA_ROLE)
53

    
54
        advanced = False
55
        app_doc_data = AppDocData.instance()
56
        configs = app_doc_data.getAppConfigs('app', 'mode')
57
        if configs and 1 == len(configs) and 'advanced' == configs[0].value:
58
            advanced = True
59

    
60
        if data is not None and type(data) is symbol.SymbolBase:
61
            sym = self.getSymbolByItemName(item, 0)
62
            text = item.text(0)
63
            if len(indexes) > 0:
64
                level = 0
65
                index = indexes[0]
66
                while index.parent().isValid():
67
                    index = index.parent()
68
                    level += 1
69
            if sym is not None:
70
                menu = QMenu()
71
                if advanced:
72
                    editSymbolAction = QAction(self.tr("Edit Symbol"))
73
                    editSymbolAction.triggered.connect(lambda: self.editSymbolActionClickEvent(item, 0))
74
                    menu.addAction(editSymbolAction)
75
                    editDisplaySymbolAction = QAction(self.tr("Edit Symbol for Dispay"))
76
                    editDisplaySymbolAction.triggered.connect(lambda: self.editDisplaySymbolActionClickEvent(item, 0))
77
                    menu.addAction(editDisplaySymbolAction)
78
                displaySymbolAction = QAction(self.tr("Display Symbol"))
79
                displaySymbolAction.triggered.connect(lambda: self.displaySymbolActionClickEvent(item, 0))
80
                menu.addAction(displaySymbolAction)
81
                if advanced:
82
                    deleteSymbolAction = QAction(self.tr("Delete Symbol"))
83
                    deleteSymbolAction.triggered.connect(lambda: self.deleteSymbolActionClickEvent(sym.getType(), text))
84
                    menu.addAction(deleteSymbolAction)
85
                menu.exec_(self.viewport().mapToGlobal(position))
86
        else:
87
            if advanced:
88
                menu = QMenu()
89
                editAttrAction = QAction(self.tr("Edit Attribute"))
90
                editAttrAction.triggered.connect(lambda: self.onEditAttrClicked(item, 0))
91
                menu.addAction(editAttrAction)
92
                menu.exec_(self.viewport().mapToGlobal(position))
93

    
94
    def editSymbolActionClickEvent(self, item, columNo):
95
        self.showSymbolEditorDialog(item, columNo)
96

    
97
    def editDisplaySymbolActionClickEvent(self, item, columNo):
98
        self.showSymbolEditorDialog(item, columNo, True)
99

    
100
    '''
101
        @brief      popup attribute editor dialog
102
        @author     humkyung
103
        @date       2018.08.13
104
    '''
105

    
106
    def onEditAttrClicked(self, item, columnNo):
107
        from SymbolAttrEditorDialog import QSymbolAttrEditorDialog
108

    
109
        try:
110
            data = item.data(0, self.TREE_DATA_ROLE)
111

    
112
            dlg = QSymbolAttrEditorDialog(self, data)
113
            dlg.show()
114
            dlg.exec_()
115
        except Exception as ex:
116
            from App import App
117

    
118
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
119
                                                           sys.exc_info()[-1].tb_lineno)
120
            App.mainWnd().addMessage.emit(MessageType.Error, message)
121

    
122
    def displaySymbolActionClickEvent(self, item, columnNo):
123
        # project = AppDocData.instance().getCurrentProject()
124
        # image = QImage(os.path.join(project.getImageFilePath(), itemType, itemName, "PNG")) #itemName includes ".png"
125
        try:
126
            sym = self.getSymbolByItemName(item, columnNo)
127
            if sym is not None:
128
                # origin symbol image
129
                path = sym.getPath()
130
                image = QImage(path, "PNG")
131
                # symbol image for display
132
                path = os.path.splitext(path)
133
                path = path[0] + '_display' + path[1]
134
                image2 = QImage(path, "PNG") if os.path.exists(path) else None
135
                dialog = QSymbolDisplayDialog.QSymbolDisplayDialog(image, image2)
136
                dialog.showDialog()
137
            else:
138
                QMessageBox.about(self, self.tr('Error'), self.tr('Error occurs during loading symbol data.'))
139
        except Exception as ex:
140
            from App import App
141
            from AppDocData import MessageType
142

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

    
147
    def deleteSymbolActionClickEvent(self, itemType, itemName):
148
        msg = QMessageBox()
149
        msg.setIcon(QMessageBox.Critical)
150
        msg.setText(self.tr('Are you sure you want to delete selected symbol?\nData can not be restored!'))
151
        msg.setWindowTitle(self.tr('Delete symbol'))
152
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
153
        result = msg.exec_()
154
        self.handleDeleteSymbolAction(result, itemType, itemName)
155

    
156
    '''
157
        @history    2018.05.03  Jeongwoo    Modify file path with ".png" and ".svg"
158
                                            Use project object when making svgPath
159
    '''
160

    
161
    def handleDeleteSymbolAction(self, result, itemType, itemName):
162
        if result == QMessageBox.Ok:
163
            project = AppDocData.instance().getCurrentProject()
164
            imagePath = os.path.join(project.getImageFilePath(), itemType,
165
                                     itemName + '.png')  # itemName DOESN'T includes ".png"
166
            if os.path.exists(imagePath):
167
                os.remove(imagePath)
168

    
169
            svgPath = os.path.join(project.getSvgFilePath(), itemType, itemName + '.svg')
170
            if os.path.exists(svgPath):
171
                os.remove(svgPath)
172

    
173
            AppDocData.instance().deleteSymbol(itemName)
174
            self.initDirTreeWidget()
175
        else:
176
            pass
177

    
178
    '''
179
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
180
    '''
181

    
182
    def initDirTreeWidget(self):
183
        project = AppDocData.instance().getCurrentProject()
184
        if project is not None:
185
            self.clear()
186
            projectPath = project.getPath().replace("\\", "/")
187
            self.makeChildDir()
188
            self.load_symbol_info()
189
            self.expandAll()
190

    
191
    '''
192
        @brief      Load Symbol Info and add TreeItem with DB
193
        @author     Jeongwoo
194
        @date       18.04.20
195
        @history    Jeongwoo 2018.05.03 Get Svg File Path by SymbolBase.getSvgFileFullPath()
196
                    humkyung 2018.07.30 sort child items
197
    '''
198

    
199
    def load_symbol_info(self):
200
        try:
201
            app_doc_data = AppDocData.instance()
202

    
203
            symbolTypeList = AppDocData.instance().getSymbolTypeList()
204
            for symbolType in symbolTypeList:
205
                if not symbolType[1]: continue  # skip if category is empty
206
                parent = QTreeWidgetItem(self, [symbolType[2]])
207
                parent.setData(0, self.TREE_DATA_ROLE, symbolType)
208
                symbolList = AppDocData.instance().getSymbolListByType('UID', symbolType[0])
209
                for symbol in symbolList:
210
                    symbolItem = QTreeWidgetItem(parent, [symbol.getName()])
211
                    symbolItem.setData(0, self.TREE_DATA_ROLE, symbol)
212

    
213
                    _, svg = app_doc_data.read_symbol_shape(symbol.sName)
214
                    if svg:
215
                        pixmap = QPixmap(QSize(32, 32))
216
                        pixmap.loadFromData(svg if isinstance(svg, bytes) else svg.encode())
217
                        icon = QIcon(pixmap)
218
                        symbolItem.setIcon(0, icon)
219
                        symbolItem.svgFilePath = None   # save svg file path
220
                    else:
221
                        svgPath = symbol.getSvgFileFullPath()
222
                        icon = QIcon(svgPath)
223
                        symbolItem.setIcon(0, icon)
224
                        symbolItem.svgFilePath = svgPath  # save svg file path
225

    
226
                parent.sortChildren(0, Qt.AscendingOrder)
227
        except Exception as ex:
228
            from App import App
229

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

    
234
    '''
235
        @brief      Make Directory
236
        @author     Jeongwoo
237
        @date       18.04.??
238
        @history    18.04.12    Jeongwoo    Add output, temp Directory
239
    '''
240

    
241
    def makeChildDir(self):
242
        project = AppDocData.instance().getCurrentProject()
243
        dbDir = project.getDbFilePath()
244
        if not os.path.exists(dbDir):
245
            os.makedirs(dbDir)
246
        imgDir = project.getImageFilePath()
247
        if not os.path.exists(imgDir):
248
            os.makedirs(imgDir)
249
        svgDir = project.getSvgFilePath()
250
        if not os.path.exists(svgDir):
251
            os.makedirs(svgDir)
252
        outputDir = project.getOutputPath()
253
        if not os.path.exists(outputDir):
254
            os.makedirs(outputDir)
255
        tempDir = project.getTempPath()
256
        if not os.path.exists(tempDir):
257
            os.makedirs(tempDir)
258

    
259
    def showSymbolEditorDialog(self, item, columnNo, display=False):
260
        try:
261
            sym = self.getSymbolByItemName(item, columnNo)
262
            if sym and display:
263
                # for symbol image for display
264
                path = os.path.splitext(sym.getPath())
265
                path = path[0] + '_display' + path[1]
266
                if os.path.exists(path):
267
                    image = QImage(path, "PNG")
268
                else:
269
                    path = sym.getPath()
270
                    image = QImage(path, "PNG")
271
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image,
272
                                                                            AppDocData.instance().getCurrentProject(),
273
                                                                            sym, True)
274
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
275
                self.initDirTreeWidget()
276
            elif sym:
277
                # for symbol data and detection image
278
                path = sym.getPath()
279
                image = QImage(path, "PNG")
280
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image,
281
                                                                            AppDocData.instance().getCurrentProject(),
282
                                                                            sym, False)
283
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
284
                self.initDirTreeWidget()
285
            else:
286
                QMessageBox.about(self, self.tr('Error'), self.tr('Error occurs during loading symbol data.'))
287
        except Exception as ex:
288
            from App import App
289
            from AppDocData import MessageType
290

    
291
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
292
                                                           sys.exc_info()[-1].tb_lineno)
293
            App.mainWnd().addMessage.emit(MessageType.Error, message)
294

    
295
    def itemDoubleClickEvent(self, item, columnNo):
296
        self.isDoubleClicked = True
297
        sym = self.getSymbolByItemName(item, columnNo)
298
        itemName = item.text(columnNo)
299
        if sym is not None:
300
            self.showSymbolEditorDialog(item, columnNo)
301
        self.isDoubleClicked = False
302

    
303
    '''
304
        @brief      Get Symbol data by symbol name
305
        @author     Jeongwoo
306
        @date       18.04.20
307
    '''
308

    
309
    def getSymbolByItemName(self, item, columnNo):
310
        itemName = item.text(columnNo)
311

    
312
        name = itemName
313
        sym = AppDocData.instance().getSymbolByQuery("name", name)
314
        return sym
315

    
316
    '''
317
        @breif      show symbol's property when selection changed
318
        @author     humkyung
319
        @date       2018.07.30
320
    '''
321

    
322
    def onCurrentItemChanged(self, current, previous):
323
        item = self.currentItem()
324
        if item is not None:
325
            data = item.data(0, self.TREE_DATA_ROLE)
326
            if data is not None and type(data) is symbol.SymbolBase:
327
                self.singleClicked.emit(data)
328

    
329
    '''
330
        @brief  start drag
331
        @author humkyung
332
        @date   2018.04.17
333
        @history    18.04.20    Jeongwoo    Change Path in QPixmap
334
                    18.06.21    Jeongwoo    Casting string to float and int
335
    '''
336

    
337
    def startDrag(self, dropAction):
338
        try:
339
            items = self.selectedItems()
340
            if items and hasattr(items[0], 'svgFilePath'):
341
                symData = items[0].data(0, self.TREE_DATA_ROLE)
342
                if items[0].svgFilePath:
343
                    pixmap = QPixmap(items[0].svgFilePath)
344
                else:
345
                    app_doc_data = AppDocData.instance()
346
                    _, svg = app_doc_data.read_symbol_shape(symData.getName())
347
                    if svg:
348
                        pixmap = QPixmap()
349
                        pixmap.loadFromData(svg if isinstance(svg, bytes) else svg.encode())
350

    
351
                mime = QMimeData()
352
                mime.setText(symData.getName())
353

    
354
                drag = QDrag(self)
355
                drag.setMimeData(mime)
356
                originalPoint = symData.getOriginalPoint()
357
                drag.setHotSpot(
358
                    QPoint(int(float(originalPoint.split(",")[0])), int(float(originalPoint.split(",")[1]))))
359
                drag.setPixmap(pixmap)
360
                drag.exec(Qt.CopyAction)
361
        except Exception as ex:
362
            from App import App
363

    
364
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
365
                                                           sys.exc_info()[-1].tb_lineno)
366
            App.mainWnd().addMessage.emit(MessageType.Error, message)
클립보드 이미지 추가 (최대 크기: 500 MB)