프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / SymbolTreeWidget.py @ db2dcb47

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

1 d0db0878 humkyung
# coding: utf-8
2
""" This is Symbol Tree Widget module """
3
4 d52b3462 김정우
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 6a2a7457 humkyung
from AppDocData import *
15 d52b3462 김정우
import os
16 4f0ae2af humkyung
import sys
17 936111d1 김정우
import SymbolBase
18
import symbol
19 dc05dcb9 humkyung
import SymbolEditorDialog
20 8df40630 김정우
import QSymbolDisplayDialog
21 d52b3462 김정우
22 b1a510c6 humkyung
23 b929957d humkyung
class QSymbolTreeWidget(QTreeWidget):
24 b1a510c6 humkyung
    # Add signal
25 936111d1 김정우
    singleClicked = pyqtSignal(SymbolBase.SymbolBase)
26 b929957d humkyung
    TREE_DATA_ROLE = Qt.UserRole
27 936111d1 김정우
28 d52b3462 김정우
    def __init__(self):
29
        QTreeWidget.__init__(self)
30 b1a510c6 humkyung
        self.setIconSize(QSize(32, 32))
31
32
        self.setDragEnabled(True)  # enable drag
33 d52b3462 김정우
        self.initDirTreeWidget()
34 936111d1 김정우
        self.isDoubleClicked = False
35 d52b3462 김정우
        self.itemDoubleClicked.connect(self.itemDoubleClickEvent)
36 e85bb909 김정우
        self.setContextMenuPolicy(Qt.CustomContextMenu)
37
        self.customContextMenuRequested.connect(self.openContextMenu)
38 b929957d humkyung
        self.currentItemChanged.connect(self.onCurrentItemChanged)
39 b1a510c6 humkyung
40 2894ed79 김정우
    '''
41
        @brief      Show Context Menu
42
        @author     Jeongwoo
43
        @date       18.04.??
44 6a2a7457 humkyung
        @history    Jeongwoo 2018.04.23 Symbol object Null Check when show context menu
45
                    humkyung 2018.08.14 add menu for symbol type
46 2894ed79 김정우
    '''
47 b1a510c6 humkyung
48 e85bb909 김정우
    def openContextMenu(self, position):
49
        indexes = self.selectedIndexes()
50
        itemPosition = self.mapTo(self, position)
51
        item = self.itemAt(itemPosition)
52 6a2a7457 humkyung
        data = item.data(0, self.TREE_DATA_ROLE)
53 8701ed58 esham21
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 b0034990 humkyung
        if data is not None and type(data) is symbol.SymbolBase:
61 6a2a7457 humkyung
            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 8701ed58 esham21
                if advanced:
72
                    editSymbolAction = QAction(self.tr("Edit Symbol"))
73
                    editSymbolAction.triggered.connect(lambda: self.editSymbolActionClickEvent(item, 0))
74
                    menu.addAction(editSymbolAction)
75 02519509 humkyung
                    editDisplaySymbolAction = QAction(self.tr("Edit Symbol for Display"))
76 8701ed58 esham21
                    editDisplaySymbolAction.triggered.connect(lambda: self.editDisplaySymbolActionClickEvent(item, 0))
77
                    menu.addAction(editDisplaySymbolAction)
78 6a2a7457 humkyung
                displaySymbolAction = QAction(self.tr("Display Symbol"))
79 61a7cd2d esham21
                displaySymbolAction.triggered.connect(lambda: self.displaySymbolActionClickEvent(item, 0))
80 6a2a7457 humkyung
                menu.addAction(displaySymbolAction)
81 8701ed58 esham21
                if advanced:
82
                    deleteSymbolAction = QAction(self.tr("Delete Symbol"))
83
                    deleteSymbolAction.triggered.connect(lambda: self.deleteSymbolActionClickEvent(sym.getType(), text))
84
                    menu.addAction(deleteSymbolAction)
85 6a2a7457 humkyung
                menu.exec_(self.viewport().mapToGlobal(position))
86
        else:
87 8701ed58 esham21
            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 e85bb909 김정우
94
    def editSymbolActionClickEvent(self, item, columNo):
95
        self.showSymbolEditorDialog(item, columNo)
96
97 61a7cd2d esham21
    def editDisplaySymbolActionClickEvent(self, item, columNo):
98
        self.showSymbolEditorDialog(item, columNo, True)
99
100 6a2a7457 humkyung
    '''
101
        @brief      popup attribute editor dialog
102
        @author     humkyung
103
        @date       2018.08.13
104
    '''
105 b1a510c6 humkyung
106 6a2a7457 humkyung
    def onEditAttrClicked(self, item, columnNo):
107 b0034990 humkyung
        from SymbolAttrEditorDialog import QSymbolAttrEditorDialog
108 6a2a7457 humkyung
109
        try:
110 b1a510c6 humkyung
            data = item.data(0, self.TREE_DATA_ROLE)
111 b0034990 humkyung
112 b1a510c6 humkyung
            dlg = QSymbolAttrEditorDialog(self, data)
113 e89f871b esham21
            dlg.show()
114 b1a510c6 humkyung
            dlg.exec_()
115 6a2a7457 humkyung
        except Exception as ex:
116
            from App import App
117
118 b1a510c6 humkyung
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
119
                                                           sys.exc_info()[-1].tb_lineno)
120 6a2a7457 humkyung
            App.mainWnd().addMessage.emit(MessageType.Error, message)
121
122 61a7cd2d esham21
    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 bceea84f esham21
                # origin symbol image
129 61a7cd2d esham21
                path = sym.getPath()
130
                image = QImage(path, "PNG")
131 bceea84f esham21
                # 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 61a7cd2d esham21
                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 b1a510c6 humkyung
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
144
                                                           sys.exc_info()[-1].tb_lineno)
145 61a7cd2d esham21
            App.mainWnd().addMessage.emit(MessageType.Error, message)
146 e85bb909 김정우
147 cb51acb2 김정우
    def deleteSymbolActionClickEvent(self, itemType, itemName):
148 100ba941 김정우
        msg = QMessageBox()
149
        msg.setIcon(QMessageBox.Critical)
150 d88d6f39 esham21
        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 b1a510c6 humkyung
        msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
153 100ba941 김정우
        result = msg.exec_()
154 cb51acb2 김정우
        self.handleDeleteSymbolAction(result, itemType, itemName)
155 100ba941 김정우
156 d9cbc4d3 김정우
    '''
157
        @history    2018.05.03  Jeongwoo    Modify file path with ".png" and ".svg"
158
                                            Use project object when making svgPath
159
    '''
160 b1a510c6 humkyung
161 cb51acb2 김정우
    def handleDeleteSymbolAction(self, result, itemType, itemName):
162 100ba941 김정우
        if result == QMessageBox.Ok:
163
            project = AppDocData.instance().getCurrentProject()
164 b1a510c6 humkyung
            imagePath = os.path.join(project.getImageFilePath(), itemType,
165
                                     itemName + '.png')  # itemName DOESN'T includes ".png"
166 100ba941 김정우
            if os.path.exists(imagePath):
167
                os.remove(imagePath)
168
169 25e0cacb Gyusu
            svgPath = os.path.join(project.getSvgFilePath(), itemType, itemName + '.svg')
170 100ba941 김정우
            if os.path.exists(svgPath):
171
                os.remove(svgPath)
172
173 d9cbc4d3 김정우
            AppDocData.instance().deleteSymbol(itemName)
174 bcdd2a76 김정우
            self.initDirTreeWidget()
175 100ba941 김정우
        else:
176
            pass
177 000faa4d 김정우
178 3828d206 김정우
    '''
179
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
180
    '''
181 b1a510c6 humkyung
182 000faa4d 김정우
    def initDirTreeWidget(self):
183
        project = AppDocData.instance().getCurrentProject()
184
        if project is not None:
185 d52b3462 김정우
            self.clear()
186 000faa4d 김정우
            projectPath = project.getPath().replace("\\", "/")
187 cb51acb2 김정우
            self.makeChildDir()
188 b1a510c6 humkyung
            self.load_symbol_info()
189 cb51acb2 김정우
            self.expandAll()
190 d52b3462 김정우
191 ed2b4ab0 김정우
    '''
192
        @brief      Load Symbol Info and add TreeItem with DB
193
        @author     Jeongwoo
194
        @date       18.04.20
195 65f1308c humkyung
        @history    Jeongwoo 2018.05.03 Get Svg File Path by SymbolBase.getSvgFileFullPath()
196
                    humkyung 2018.07.30 sort child items
197 ed2b4ab0 김정우
    '''
198 b1a510c6 humkyung
199
    def load_symbol_info(self):
200 b0034990 humkyung
        try:
201 b1a510c6 humkyung
            app_doc_data = AppDocData.instance()
202
203 02519509 humkyung
            symbolTypeList = app_doc_data.getSymbolTypeList()
204 b0034990 humkyung
            for symbolType in symbolTypeList:
205 d0db0878 humkyung
                if not symbolType[1]: continue  # skip if category is empty
206 b0034990 humkyung
                parent = QTreeWidgetItem(self, [symbolType[2]])
207
                parent.setData(0, self.TREE_DATA_ROLE, symbolType)
208 02519509 humkyung
                symbolList = app_doc_data.getSymbolListByType('UID', symbolType[0])
209 b0034990 humkyung
                for symbol in symbolList:
210
                    symbolItem = QTreeWidgetItem(parent, [symbol.getName()])
211
                    symbolItem.setData(0, self.TREE_DATA_ROLE, symbol)
212 b1a510c6 humkyung
213
                    _, svg = app_doc_data.read_symbol_shape(symbol.sName)
214
                    if svg:
215 db2dcb47 humkyung
                        symbol.pixmap = QPixmap()
216 a1723c66 humkyung
                        symbol.pixmap.loadFromData(svg if isinstance(svg, bytes) else svg.encode())
217
                        icon = QIcon(symbol.pixmap)
218 b1a510c6 humkyung
                        symbolItem.setIcon(0, icon)
219
                        symbolItem.svgFilePath = None   # save svg file path
220
                    else:
221
                        svgPath = symbol.getSvgFileFullPath()
222 db2dcb47 humkyung
                        symbol.pixmap = QPixmap(svgPath)
223
                        icon = QIcon(symbol.pixmap)
224 b1a510c6 humkyung
                        symbolItem.setIcon(0, icon)
225
                        symbolItem.svgFilePath = svgPath  # save svg file path
226 ed2b4ab0 김정우
227 b0034990 humkyung
                parent.sortChildren(0, Qt.AscendingOrder)
228
        except Exception as ex:
229
            from App import App
230
231 b1a510c6 humkyung
            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 b0034990 humkyung
            App.mainWnd().addMessage.emit(MessageType.Error, message)
234 cdbc7e7f 김정우
235 9b09db27 김정우
    '''
236
        @brief      Make Directory
237
        @author     Jeongwoo
238
        @date       18.04.??
239
        @history    18.04.12    Jeongwoo    Add output, temp Directory
240
    '''
241 b1a510c6 humkyung
242 cb51acb2 김정우
    def makeChildDir(self):
243
        project = AppDocData.instance().getCurrentProject()
244
        dbDir = project.getDbFilePath()
245 d52b3462 김정우
        if not os.path.exists(dbDir):
246
            os.makedirs(dbDir)
247 cb51acb2 김정우
        imgDir = project.getImageFilePath()
248 d52b3462 김정우
        if not os.path.exists(imgDir):
249
            os.makedirs(imgDir)
250 cb51acb2 김정우
        svgDir = project.getSvgFilePath()
251 d52b3462 김정우
        if not os.path.exists(svgDir):
252
            os.makedirs(svgDir)
253 9b09db27 김정우
        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 d52b3462 김정우
260 b1a510c6 humkyung
    def showSymbolEditorDialog(self, item, columnNo, display=False):
261 e2ae85c2 humkyung
        """pop up symbol editor dialog"""
262
263 4f0ae2af humkyung
        try:
264
            sym = self.getSymbolByItemName(item, columnNo)
265 61a7cd2d esham21
            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 b1a510c6 humkyung
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image,
275
                                                                            AppDocData.instance().getCurrentProject(),
276
                                                                            sym, True)
277 61a7cd2d esham21
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
278
                self.initDirTreeWidget()
279
            elif sym:
280
                # for symbol data and detection image
281 4f0ae2af humkyung
                path = sym.getPath()
282
                image = QImage(path, "PNG")
283 b1a510c6 humkyung
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image,
284
                                                                            AppDocData.instance().getCurrentProject(),
285
                                                                            sym, False)
286 3828d206 김정우
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
287 4f0ae2af humkyung
                self.initDirTreeWidget()
288
            else:
289 d88d6f39 esham21
                QMessageBox.about(self, self.tr('Error'), self.tr('Error occurs during loading symbol data.'))
290 4f0ae2af humkyung
        except Exception as ex:
291 b0034990 humkyung
            from App import App
292 61a7cd2d esham21
            from AppDocData import MessageType
293 3926c898 김정우
294 b1a510c6 humkyung
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
295
                                                           sys.exc_info()[-1].tb_lineno)
296 b0034990 humkyung
            App.mainWnd().addMessage.emit(MessageType.Error, message)
297 e85bb909 김정우
298 e2ae85c2 humkyung
    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 e85bb909 김정우
    def itemDoubleClickEvent(self, item, columnNo):
306
        self.isDoubleClicked = True
307 2894ed79 김정우
        sym = self.getSymbolByItemName(item, columnNo)
308 e85bb909 김정우
        itemName = item.text(columnNo)
309 2894ed79 김정우
        if sym is not None:
310
            self.showSymbolEditorDialog(item, columnNo)
311 936111d1 김정우
        self.isDoubleClicked = False
312 d52b3462 김정우
313 b580f6e4 김정우
    '''
314 ed2b4ab0 김정우
        @brief      Get Symbol data by symbol name
315
        @author     Jeongwoo
316
        @date       18.04.20
317
    '''
318 b1a510c6 humkyung
319 936111d1 김정우
    def getSymbolByItemName(self, item, columnNo):
320 d52b3462 김정우
        itemName = item.text(columnNo)
321 65f1308c humkyung
322 ed2b4ab0 김정우
        name = itemName
323
        sym = AppDocData.instance().getSymbolByQuery("name", name)
324
        return sym
325 b192a44e humkyung
326
    '''
327 b929957d humkyung
        @breif      show symbol's property when selection changed
328
        @author     humkyung
329
        @date       2018.07.30
330
    '''
331 b1a510c6 humkyung
332 b929957d humkyung
    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 b0034990 humkyung
            if data is not None and type(data) is symbol.SymbolBase:
337 b929957d humkyung
                self.singleClicked.emit(data)
338
339 b192a44e humkyung
    def startDrag(self, dropAction):
340 db2dcb47 humkyung
        """start drag"""
341 4f0ae2af humkyung
        try:
342
            items = self.selectedItems()
343 47a4970e esham21
            if items and hasattr(items[0], 'svgFilePath'):
344 4f0ae2af humkyung
                symData = items[0].data(0, self.TREE_DATA_ROLE)
345
346
                mime = QMimeData()
347 3a4cc147 humkyung
                mime.setText(symData.getName())
348 a1723c66 humkyung
                mime.tag = symData
349 4f0ae2af humkyung
350
                drag = QDrag(self)
351 b1a510c6 humkyung
                drag.setMimeData(mime)
352 4f0ae2af humkyung
                originalPoint = symData.getOriginalPoint()
353 b1a510c6 humkyung
                drag.setHotSpot(
354
                    QPoint(int(float(originalPoint.split(",")[0])), int(float(originalPoint.split(",")[1]))))
355 db2dcb47 humkyung
                drag.setPixmap(symData.pixmap)
356 4f0ae2af humkyung
                drag.exec(Qt.CopyAction)
357
        except Exception as ex:
358 b0034990 humkyung
            from App import App
359
360 b1a510c6 humkyung
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
361
                                                           sys.exc_info()[-1].tb_lineno)
362 b0034990 humkyung
            App.mainWnd().addMessage.emit(MessageType.Error, message)
클립보드 이미지 추가 (최대 크기: 500 MB)