프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / SymbolTreeWidget.py @ db2dcb47

이력 | 보기 | 이력해설 | 다운로드 (14.9 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 Display"))
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 = app_doc_data.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 = app_doc_data.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
                        symbol.pixmap = QPixmap()
216
                        symbol.pixmap.loadFromData(svg if isinstance(svg, bytes) else svg.encode())
217
                        icon = QIcon(symbol.pixmap)
218
                        symbolItem.setIcon(0, icon)
219
                        symbolItem.svgFilePath = None   # save svg file path
220
                    else:
221
                        svgPath = symbol.getSvgFileFullPath()
222
                        symbol.pixmap = QPixmap(svgPath)
223
                        icon = QIcon(symbol.pixmap)
224
                        symbolItem.setIcon(0, icon)
225
                        symbolItem.svgFilePath = svgPath  # save svg file path
226

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

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

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

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

    
260
    def showSymbolEditorDialog(self, item, columnNo, display=False):
261
        """pop up symbol editor dialog"""
262

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

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

    
298
    def select_symbol(self, symbol):
299
        """select a tree with given symbol"""
300

    
301
        founds = self.findItems(symbol.name, Qt.MatchExactly | Qt.MatchRecursive, 0)
302
        if founds:
303
            self.setCurrentItem(founds[0])
304

    
305
    def itemDoubleClickEvent(self, item, columnNo):
306
        self.isDoubleClicked = True
307
        sym = self.getSymbolByItemName(item, columnNo)
308
        itemName = item.text(columnNo)
309
        if sym is not None:
310
            self.showSymbolEditorDialog(item, columnNo)
311
        self.isDoubleClicked = False
312

    
313
    '''
314
        @brief      Get Symbol data by symbol name
315
        @author     Jeongwoo
316
        @date       18.04.20
317
    '''
318

    
319
    def getSymbolByItemName(self, item, columnNo):
320
        itemName = item.text(columnNo)
321

    
322
        name = itemName
323
        sym = AppDocData.instance().getSymbolByQuery("name", name)
324
        return sym
325

    
326
    '''
327
        @breif      show symbol's property when selection changed
328
        @author     humkyung
329
        @date       2018.07.30
330
    '''
331

    
332
    def onCurrentItemChanged(self, current, previous):
333
        item = self.currentItem()
334
        if item is not None:
335
            data = item.data(0, self.TREE_DATA_ROLE)
336
            if data is not None and type(data) is symbol.SymbolBase:
337
                self.singleClicked.emit(data)
338

    
339
    def startDrag(self, dropAction):
340
        """start drag"""
341
        try:
342
            items = self.selectedItems()
343
            if items and hasattr(items[0], 'svgFilePath'):
344
                symData = items[0].data(0, self.TREE_DATA_ROLE)
345

    
346
                mime = QMimeData()
347
                mime.setText(symData.getName())
348
                mime.tag = symData
349

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

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