hytos / DTI_PID / DTI_PID / QResultTreeWidget.py @ ef580b4f
이력 | 보기 | 이력해설 | 다운로드 (16.8 KB)
1 |
try:
|
---|---|
2 |
from PyQt5.QtCore import * |
3 |
from PyQt5.QtGui import * |
4 |
from PyQt5.QtWidgets import * |
5 |
except ImportError: |
6 |
try:
|
7 |
from PyQt4.QtCore import * |
8 |
from PyQt4.QtGui import * |
9 |
except ImportError: |
10 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
11 |
from SymbolSvgItem import SymbolSvgItem |
12 |
from QEngineeringTextItem import QEngineeringTextItem |
13 |
from QEngineeringNoteItem import QEngineeringNoteItem |
14 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
15 |
from AppDocData import AppDocData |
16 |
import os |
17 |
import re |
18 |
|
19 |
class QResultTreeWidget(QTreeWidget): |
20 |
TREE_DATA_ROLE = Qt.ToolTipRole |
21 |
|
22 |
#Add Signal
|
23 |
singleClicked = pyqtSignal(SymbolSvgItem) |
24 |
noteNoSingleClicked = pyqtSignal(str, list) |
25 |
lineNoSingleClicked = pyqtSignal(QEngineeringLineNoTextItem) |
26 |
|
27 |
'''
|
28 |
@history 2018.05.11 Jeongwoo Add Context Menu settings
|
29 |
'''
|
30 |
def __init__(self, imageViewer): |
31 |
QTreeWidget.__init__(self)
|
32 |
self.itemClicked.connect(self.itemClickEvent) |
33 |
self.imageViewer = imageViewer
|
34 |
self.scene = imageViewer.scene
|
35 |
self.root = None |
36 |
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
37 |
self.customContextMenuRequested.connect(self.openContextMenu) |
38 |
|
39 |
'''
|
40 |
@brief Show Context Menu
|
41 |
@author Jeongwoo
|
42 |
@date 18.05.11
|
43 |
'''
|
44 |
def openContextMenu(self, position): |
45 |
indexes = self.selectedIndexes()
|
46 |
itemPosition = self.mapTo(self, position) |
47 |
item = self.itemAt(itemPosition)
|
48 |
data = item.data(0, self.TREE_DATA_ROLE) |
49 |
if len(indexes) > 0 and data is not None and type(data) is QEngineeringLineNoTextItem: |
50 |
index = indexes[0]
|
51 |
menu = QMenu() |
52 |
pickColorAction = QAction(self.tr("색상 설정")) |
53 |
pickColorAction.triggered.connect(lambda : self.pickColorClickEvent(item)) |
54 |
menu.addAction(pickColorAction) |
55 |
menu.exec_(self.viewport().mapToGlobal(position))
|
56 |
|
57 |
'''
|
58 |
@brief Pick Color for Line No
|
59 |
@author Jeongwoo
|
60 |
@date 18.05.11
|
61 |
@history 18.05.14 Jeongwoo Change method to change color by changeTreeWidgetItemColorRecursively()
|
62 |
'''
|
63 |
def pickColorClickEvent(self, lineNoTreeWidgetItem): |
64 |
''''''
|
65 |
color = QColorDialog.getColor() # Dialog returns QColor
|
66 |
|
67 |
if color is not None: |
68 |
lineNoTreeWidgetItem.setForeground(0, QBrush(color))
|
69 |
lineNoTreeWidgetItem.setFont(0, lineNoTreeWidgetItem.font(0)) |
70 |
lineNoItem = lineNoTreeWidgetItem.data(0, self.TREE_DATA_ROLE) |
71 |
lineNoItem.setColor(color.name()) |
72 |
connectedItems = lineNoItem.getConnectedItems() |
73 |
if connectedItems is not None: |
74 |
for connectedItem in connectedItems: |
75 |
connectedItem.setColor(color.name()) |
76 |
self.changeTreeWidgetItemColorRecursively(lineNoTreeWidgetItem, color)
|
77 |
|
78 |
'''
|
79 |
@brief Change Color recursively
|
80 |
@author Jeongwoo
|
81 |
@date 18.05.14
|
82 |
'''
|
83 |
def changeTreeWidgetItemColorRecursively(self, item, color): |
84 |
for index in range(item.childCount()): |
85 |
child = item.child(index) |
86 |
child.setForeground(0, QBrush(color))
|
87 |
child.setFont(0, child.font(0)) |
88 |
self.changeTreeWidgetItemColorRecursively(child, color)
|
89 |
|
90 |
'''
|
91 |
@brief Clear TreeWidget and Set Current PID
|
92 |
@author Jeongwoo
|
93 |
@date 18.04.11
|
94 |
@history 2018.04.26 Jeongwoo Add Child [SYMBOLS, NOTES] into root item
|
95 |
2018.05.09 Jeongwoo Change method to add default tree items
|
96 |
'''
|
97 |
def setCurrentPID(self, baseName): |
98 |
self.clear()
|
99 |
self.root = QTreeWidgetItem(self, [os.path.splitext(baseName)[0]]) |
100 |
self.root.addChild(QTreeWidgetItem(['EQUIPMENTS'])) |
101 |
self.root.addChild(QTreeWidgetItem(['SYMBOLS'])) |
102 |
self.root.addChild(QTreeWidgetItem(['NOTES'])) |
103 |
|
104 |
'''
|
105 |
@brief create tree item for pipe run if need
|
106 |
@author humkyung
|
107 |
@date 2018.05.15
|
108 |
'''
|
109 |
def addPipeRunTreeItemIfNeed(self, lineNoTreeItem, pipeRun): |
110 |
for index in range(lineNoTreeItem.childCount()): |
111 |
treeItem = lineNoTreeItem.child(index) |
112 |
itemData = treeItem.data(0, self.TREE_DATA_ROLE) |
113 |
if itemData is not None and itemData == pipeRun.uid: |
114 |
return treeItem
|
115 |
|
116 |
runItem = QTreeWidgetItem(['RUNS {}'.format(lineNoTreeItem.childCount()+1)]) |
117 |
runItem.setData(0, self.TREE_DATA_ROLE, pipeRun.uid) |
118 |
lineNoTreeItem.addChild(runItem) |
119 |
|
120 |
return runItem
|
121 |
|
122 |
'''
|
123 |
@brief add a tree item
|
124 |
@author humkyung
|
125 |
@date 2018.04.17
|
126 |
@history humkyung 2018.04.19 treat a case parent is changed
|
127 |
Jeongwoo 2018.04.26 QEngineeringTextItem → QEngineeringLineNoTextItem
|
128 |
Insert if-statement for QEngineeringNoteItem
|
129 |
Add if-statement for QEngineeringLineNoTextItem
|
130 |
Jeongwoo 2018.05.11 Set color when SymbolSvgItem moved into new parent(Line No)
|
131 |
'''
|
132 |
def addTreeItem(self, parent, child): |
133 |
item = None
|
134 |
if (not hasattr(child, 'treeItem')) or (child.treeItem is None): |
135 |
if issubclass(type(child), SymbolSvgItem): |
136 |
if AppDocData.instance().isEquipmentByType(child.type):
|
137 |
symbolsRootItem = self.findItems('EQUIPMENTS', Qt.MatchExactly|Qt.MatchRecursive, 0) |
138 |
symbolsRootItem = symbolsRootItem[0]
|
139 |
item = QTreeWidgetItem(symbolsRootItem, [child.name]) |
140 |
else:
|
141 |
symbolsRootItem = self.findItems('SYMBOLS', Qt.MatchExactly|Qt.MatchRecursive, 0) |
142 |
symbolsRootItem = symbolsRootItem[0]
|
143 |
item = QTreeWidgetItem(symbolsRootItem, [child.name]) |
144 |
iconPath = os.path.join(AppDocData.instance().getCurrentProject().getSvgFilePath(), child.type , child.name + ".svg")
|
145 |
item.setIcon(0, QIcon(iconPath))
|
146 |
item.setData(0, self.TREE_DATA_ROLE, child) |
147 |
child.treeItem = item |
148 |
symbolsRootItem.addChild(item) |
149 |
elif type(child) is QEngineeringLineNoTextItem: |
150 |
item = QTreeWidgetItem([child.text()]) |
151 |
item.setFlags(item.flags() | Qt.ItemIsUserCheckable) |
152 |
item.setData(0, self.TREE_DATA_ROLE, child) |
153 |
item.setCheckState(0, Qt.Unchecked)
|
154 |
child.treeItem = item |
155 |
self.root.insertChild(0, item) |
156 |
elif (type(child) is QEngineeringNoteItem): |
157 |
item = QTreeWidgetItem([child.text()]) |
158 |
item.setData(0, self.TREE_DATA_ROLE, child) |
159 |
child.treeItem = item |
160 |
if parent is not None: |
161 |
parent.addChild(item) |
162 |
elif issubclass(type(child), SymbolSvgItem): # change item's parent |
163 |
foundItems = self.findItems(child.name, Qt.MatchExactly|Qt.MatchRecursive, 0) |
164 |
if foundItems is not None: |
165 |
for item in foundItems: |
166 |
data = item.data(0, self.TREE_DATA_ROLE) |
167 |
if data is not None and (data == child) and (parent is not item.parent()): |
168 |
parentData = parent.data(0, self.TREE_DATA_ROLE) |
169 |
if type(parentData) is QEngineeringLineNoTextItem: |
170 |
for index in range(len(parentData.runs)): |
171 |
runGroup = parentData.runs[index] |
172 |
if data in runGroup.items: |
173 |
item.parent().removeChild(item) # remove item from original parent
|
174 |
runItem = self.addPipeRunTreeItemIfNeed(parent, runGroup) #parent.child(index) |
175 |
brush = parent.foreground(0)
|
176 |
item.setForeground(0, brush)
|
177 |
item.data(0, self.TREE_DATA_ROLE).setColor(brush.color().name()) |
178 |
item.setFont(0, item.font(0)) |
179 |
runItem.addChild(item) |
180 |
else:
|
181 |
print(item.text(0) + " Not Found on " + parent.text(0)) |
182 |
#brush = parent.foreground(0)
|
183 |
#item.setForeground(0, brush)
|
184 |
#item.data(0, self.TREE_DATA_ROLE).setColor(brush.color().name())
|
185 |
#item.setFont(0, item.font(0))
|
186 |
#parent.addChild(item)
|
187 |
break
|
188 |
elif type(child) is QEngineeringLineNoTextItem: |
189 |
foundItems = self.findItems(child.text(), Qt.MatchExactly|Qt.MatchRecursive, 0) |
190 |
if foundItems is not None: |
191 |
for item in foundItems: |
192 |
data = item.data(0, self.TREE_DATA_ROLE) |
193 |
if data is not None and (data == child): |
194 |
#for index in range(len(data.runs)):
|
195 |
# item.addChild(QTreeWidgetItem(['RUNS' + str(index+1)]))
|
196 |
return item
|
197 |
|
198 |
return item
|
199 |
|
200 |
'''
|
201 |
@brief Scene Changed Listener
|
202 |
@author Jeongwoo
|
203 |
@date 18.04.11
|
204 |
@history Jeongwoo 2018.04.25 Add QEngineeringNoteItem to list for loop / NOT QEngineeringTextItem
|
205 |
Jeongwoo 2018.04.26 Change changedSceneItems conditions in loop (QEngineeringTextItem → QEngineeringLineNoTextItem)
|
206 |
'''
|
207 |
lastSceneItems = None
|
208 |
def sceneChanged(self, sceneItems): |
209 |
changedSceneItems = [item for item in sceneItems if ((issubclass(type(item), SymbolSvgItem)) or (type(item) is QEngineeringNoteItem) or (type(item) is QEngineeringLineNoTextItem)) |
210 |
and (not hasattr(item, 'treeItem') or item.treeItem is None)] # Sublist includes SymbolSvgItem |
211 |
self.initResultTreeWidget(changedSceneItems)
|
212 |
|
213 |
'''
|
214 |
@brief Initialize TreeWidget
|
215 |
Tree Item Clear and Add Item
|
216 |
@author Jeongwoo
|
217 |
@date 2018.04.11
|
218 |
@history 2018.04.12 Jeongwoo Declare self.TREE_DATA_ROLE for QTreeWidgetItem.data(column, role)
|
219 |
@history 2018.04.17 humkyung NOT remove child of root
|
220 |
2018.04.25 Jeongwoo Add QEngineeringNoteItem Child
|
221 |
2018.04.26 Jeongwoo Change method to insert child
|
222 |
'''
|
223 |
def initResultTreeWidget(self, items): |
224 |
for item in items: |
225 |
if (type(item) is QEngineeringNoteItem): |
226 |
notesRootItem = self.findItems('NOTES', Qt.MatchExactly|Qt.MatchRecursive, 0) |
227 |
notesRootItem = notesRootItem[0]
|
228 |
|
229 |
self.addTreeItem(notesRootItem, item)
|
230 |
else:
|
231 |
self.addTreeItem(self.root, item) |
232 |
|
233 |
notesRootItem = self.findItems('NOTES', Qt.MatchExactly|Qt.MatchRecursive, 0) |
234 |
if notesRootItem is not None and len(notesRootItem) > 0: |
235 |
notesRootItem[0].sortChildren(0, Qt.AscendingOrder) |
236 |
self.expandAll()
|
237 |
|
238 |
'''
|
239 |
@brief TreeWidget Item click listener
|
240 |
@author Jeongwoo
|
241 |
@date 18.04.11
|
242 |
@history 18.04.12 Jeongwoo Declare self.TREE_DATA_ROLE for QTreeWidgetItem.data(column, role)
|
243 |
18.04.13 Jeongwoo Signal 'singleClicked' emit SymbolSvgItem
|
244 |
CenterOn() with Symbol's center
|
245 |
18.04.25 Jeongwoo Add QEngineeringNoteItem Click event
|
246 |
18.04.26 Jeongwoo QEngineeringTextItem → QEngineeringLineNoTextItem
|
247 |
18.04.27 Jeongwoo Find NOTE Contents when NOTE No. Clicked
|
248 |
Move singClicked to if-statement type(itemData) is SymbolSvgItem:
|
249 |
18.05.10 Jeongwoo Add lineNoSingleClicked emit
|
250 |
'''
|
251 |
lastClickedItem = None
|
252 |
def itemClickEvent(self, item, columnNo, isSvgClick = False): |
253 |
print("Item " + item.text(0) + " clicked") |
254 |
itemData = item.data(0, self.TREE_DATA_ROLE) |
255 |
|
256 |
if self.lastClickedItem is not None: |
257 |
self.scene.removeItem(self.lastClickedItem) |
258 |
|
259 |
if itemData is not None: ## Not PID Name |
260 |
if issubclass(type(itemData), SymbolSvgItem): |
261 |
## Draw rectangle on selected symbol
|
262 |
rect = itemData.sceneBoundingRect() |
263 |
graphicItem = self.scene.addRect(rect.left(), rect.top(), rect.width(), rect.height(), QPen(QColor(255,255,0,100)), QBrush(QColor(255,255,0,100))) |
264 |
if isSvgClick == False: |
265 |
self.imageViewer.centerOn(rect.center())
|
266 |
## Send new event to imageViewer's zoomImage Method
|
267 |
self.imageViewer.zoomImage(True, QMouseEvent(QEvent.MouseButtonPress, self.imageViewer.mapFromScene(QPointF(rect.left(), rect.top())), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier), 3) |
268 |
self.lastClickedItem = graphicItem
|
269 |
|
270 |
self.singleClicked.emit(itemData)
|
271 |
elif type(itemData) is QEngineeringLineNoTextItem: |
272 |
rect = itemData.sceneBoundingRect() |
273 |
graphicItem = self.scene.addRect(rect.left(), rect.top(), rect.width(), rect.height(), QPen(QColor(255,255,0,100)), QBrush(QColor(255,255,0,100))) |
274 |
if isSvgClick == False: |
275 |
self.imageViewer.centerOn(rect.center())
|
276 |
## Send new event to imageViewer's zoomImage Method
|
277 |
self.imageViewer.zoomImage(True, QMouseEvent(QEvent.MouseButtonPress, self.imageViewer.mapFromScene(QPointF(rect.left(), rect.top())), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier), 3) |
278 |
self.lastClickedItem = graphicItem
|
279 |
|
280 |
self.lineNoSingleClicked.emit(itemData)
|
281 |
elif type(itemData) is QEngineeringNoteItem: |
282 |
rect = itemData.sceneBoundingRect() |
283 |
graphicItem = self.scene.addRect(rect.left(), rect.top(), rect.width(), rect.height(), QPen(QColor(255,255,0,100)), QBrush(QColor(255,255,0,100))) |
284 |
if isSvgClick == False: |
285 |
self.imageViewer.centerOn(rect.center())
|
286 |
## Send new event to imageViewer's zoomImage Method
|
287 |
self.imageViewer.zoomImage(True, QMouseEvent(QEvent.MouseButtonPress, self.imageViewer.mapFromScene(QPointF(rect.left(), rect.top())), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier), 3) |
288 |
self.lastClickedItem = graphicItem
|
289 |
#noteContentsList = self.findNoteContents(itemData.text())
|
290 |
noteContentsList = itemData.findNoteContents(itemData.text()) |
291 |
|
292 |
self.noteNoSingleClicked.emit(itemData.text(), noteContentsList)
|
293 |
|
294 |
|
295 |
'''
|
296 |
@brief find item which has data is given item
|
297 |
@author humkyung
|
298 |
@date 2018.04.23
|
299 |
'''
|
300 |
def findItemByData(self, item): |
301 |
if issubclass(type(item), SymbolSvgItem): |
302 |
foundItems = self.findItems(item.name, Qt.MatchExactly|Qt.MatchRecursive, 0) |
303 |
for foundItem in foundItems: |
304 |
data = foundItem.data(0, self.TREE_DATA_ROLE) |
305 |
if data is not None and data is item: |
306 |
return foundItem
|
307 |
elif type(item) is QEngineeringLineNoTextItem: |
308 |
foundItems = self.findItems(item.text() , Qt.MatchExactly|Qt.MatchRecursive, 0) |
309 |
for foundItem in foundItems: |
310 |
data = foundItem.data(0, self.TREE_DATA_ROLE) |
311 |
if data is not None and data is item: |
312 |
return foundItem
|
313 |
|
314 |
return None |
315 |
|
316 |
'''
|
317 |
@brief Find QTreeWidgetItem by SymbolSvgItem object
|
318 |
@author Jeongwoo
|
319 |
@date 18.04.11
|
320 |
@history 18.04.12 Jeongwoo Change Flags (Qt.MatchExactly → Qt.MatchExactly|Qt.MatchRecursive)
|
321 |
Declare self.TREE_DATA_ROLE for QTreeWidgetItem.data(column, role)
|
322 |
'''
|
323 |
@pyqtSlot(SymbolSvgItem)
|
324 |
def findItem(self, item): |
325 |
if issubclass(type(item), SymbolSvgItem): |
326 |
foundItems = self.findItems(item.name, Qt.MatchExactly|Qt.MatchRecursive, 0) |
327 |
if foundItems is not None: |
328 |
for fItem in foundItems: |
329 |
data = fItem.data(0, self.TREE_DATA_ROLE) |
330 |
if data is not None and data == item: |
331 |
self.setCurrentItem(fItem)
|
332 |
self.itemClickEvent(fItem, 0, True) |
333 |
return
|
334 |
## Not found
|
335 |
msg = QMessageBox() |
336 |
msg.setIcon(QMessageBox.Warning) |
337 |
msg.setText('선택하신 심볼의 데이터를 찾을 수 없습니다.')
|
338 |
|
339 |
'''
|
340 |
@brief remove given item
|
341 |
@author humkyung
|
342 |
@date 2018.04.23
|
343 |
'''
|
344 |
@pyqtSlot(QGraphicsItem)
|
345 |
def itemRemoved(self, item): |
346 |
foundItem = self.findItemByData(item)
|
347 |
if foundItem is not None: |
348 |
foundItem.parent().removeChild(foundItem) |