hytos / DTI_PID / DTI_PID / ItemPropertyTableWidget.py @ ef4aed65
이력 | 보기 | 이력해설 | 다운로드 (41.5 KB)
1 |
# coding: utf-8
|
---|---|
2 |
""" This is ItemPropertyTableWidget 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 | |
15 |
import os |
16 |
import sys |
17 |
import math |
18 |
import re |
19 |
import SelectAttributeCommand |
20 | |
21 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
22 |
from SymbolSvgItem import SymbolSvgItem |
23 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
24 |
from EngineeringLineItem import QEngineeringLineItem |
25 |
from EngineeringNoteItem import QEngineeringNoteItem |
26 |
from EngineeringTextItem import QEngineeringTextItem |
27 |
from UserInputAttribute import UserInputAttribute |
28 |
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem |
29 |
from EngineeringErrorItem import QEngineeringErrorItem |
30 |
from EngineeringVendorItem import QEngineeringVendorItem |
31 |
from SymbolAttr import SymbolAttr |
32 |
from AppDocData import * |
33 |
from Drawing import Drawing |
34 |
from enum import Enum |
35 | |
36 |
'''
|
37 |
@brief ItemType
|
38 |
@author Jeongwoo
|
39 |
@date 2018.04.27
|
40 |
@history 2018.05.10 Jeongwoo Add LINE_NO
|
41 |
'''
|
42 |
class ItemType(Enum): |
43 |
SYMBOL = 1
|
44 |
NOTE = 2
|
45 |
LINE_NO = 3
|
46 | |
47 |
class QCustomCheckBox(QCheckBox): |
48 |
def __init__(self, table, row, col): |
49 |
QCheckBox.__init__(self)
|
50 |
self.table = table
|
51 |
self.row = row
|
52 |
self.col = col
|
53 | |
54 |
def state_changed(self, state): |
55 |
""" check box state is changed """
|
56 |
if self.col == 0: |
57 |
'''
|
58 |
for index in range(self.table.rowCount()):
|
59 |
data = self.table.item(index, 1).data(Qt.UserRole) if self.table.item(index, 1) is not None else None
|
60 |
if data and type(data) is SymbolAttr:
|
61 |
widget = self.table.cellWidget(index, 3)
|
62 |
if widget:
|
63 |
widget.setEnabled(False) if state else widget.setEnabled(True)
|
64 |
data.Freeze = self.isChecked()
|
65 |
|
66 |
item = self.table.item(index, 3)
|
67 |
if item:
|
68 |
item.setFlags(Qt.ItemIsEnabled) if state else item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsEditable|Qt.ItemIsSelectable)
|
69 |
item.setBackground(Qt.lightGray) if state else item.setBackground(Qt.white)
|
70 |
'''
|
71 | |
72 |
widget = self.table.cellWidget(self.row, 3) |
73 |
if widget:
|
74 |
widget.setEnabled(False) if state else widget.setEnabled(True) |
75 | |
76 |
data = self.table.item(self.row, 1).data(Qt.UserRole) |
77 |
if data: data.Freeze = self.isChecked() |
78 | |
79 |
item = self.table.item(self.row, 3) |
80 |
if item:
|
81 |
item.setFlags(Qt.ItemIsEnabled) if state else item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsEditable|Qt.ItemIsSelectable) |
82 |
#item.setBackground(Qt.lightGray) if state else item.setBackground(Qt.white)
|
83 |
elif self.col == 3: |
84 |
cell = self.table.item(self.row, 1) |
85 |
if cell:
|
86 |
data = cell.data(Qt.UserRole) |
87 |
if data is not None: |
88 |
if self.table._item: self.table._item.set_property(data.Attribute, self.isChecked()) |
89 | |
90 |
class QItemPropertyTableWidget(QTableWidget): |
91 |
def __init__(self, mainWindow): |
92 |
QTableWidget.__init__(self)
|
93 |
self._item = None |
94 |
self.initResultPropertyTableWidget()
|
95 |
self.mainWindow = mainWindow
|
96 | |
97 |
self.cellChanged.connect(self.cellChangedEvent) |
98 |
self.cellDoubleClicked.connect(self.cellDoubleClickedEvent) |
99 | |
100 |
'''
|
101 |
@brief show item's property
|
102 |
@author humkyung
|
103 |
@date 2018.07.03
|
104 |
@history euisung 2019.01.15 add icon image to line item
|
105 |
'''
|
106 |
def show_item_property(self, item): |
107 |
try:
|
108 |
from PyQt5 import QtGui |
109 |
from SymbolAttr import SymbolAttr |
110 | |
111 |
self._item = item
|
112 | |
113 |
self.blockSignals(True) |
114 | |
115 |
if type(item) is QEngineeringLineItem: |
116 |
self.initTitleCell(item)
|
117 |
self.initContentsCell()
|
118 |
elif issubclass(type(item), SymbolSvgItem): |
119 |
self.onSymbolClicked(item)
|
120 |
elif type(item) is QEngineeringLineNoTextItem: |
121 |
self.onLineNoClicked(item)
|
122 |
elif type(item) is QEngineeringNoteItem: |
123 |
noteContentsList = item.findNoteContents(item.text()) |
124 |
self.onNoteClicked(item.text(), noteContentsList)
|
125 |
elif issubclass(type(item), QEngineeringTextItem): |
126 |
self.onTextClicked(item)
|
127 |
elif type(item) is QEngineeringVendorItem: |
128 |
self.onVendorClicked(item)
|
129 |
elif item is None: |
130 |
self.setRowCount(0) |
131 |
except Exception as ex: |
132 |
from App import App |
133 | |
134 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
135 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
136 |
finally:
|
137 |
self.blockSignals(False) |
138 | |
139 |
'''
|
140 |
@brief Initialize TableWidget
|
141 |
@author Jeongwoo
|
142 |
@date 18.04.13
|
143 |
@history humkyung 2018.07.08 show column header
|
144 |
'''
|
145 |
def initResultPropertyTableWidget(self): |
146 |
self.setColumnCount(4) |
147 |
self.setHorizontalHeaderLabels(['', self.tr('Name'), '', self.tr('Value')]) |
148 |
self.setColumnWidth(0, 10) |
149 |
self.setColumnWidth(1, 20) |
150 |
self.setColumnWidth(2, 10) |
151 |
self.setRowCount(13) |
152 |
self.verticalHeader().hide()
|
153 |
self.horizontalHeader().setStretchLastSection(True) |
154 |
|
155 |
'''
|
156 |
@brief Slot to accept item click event
|
157 |
@author Jeongwoo
|
158 |
@date 18.04.13
|
159 |
@history humkyung 2018.04.17 check if given symbol type is SymbolSvgItem
|
160 |
'''
|
161 |
@pyqtSlot(SymbolSvgItem)
|
162 |
def onSymbolClicked(self, symbol): |
163 |
try:
|
164 |
self.blockSignals(True) |
165 |
if issubclass(type(symbol), SymbolSvgItem): |
166 |
self._item = symbol
|
167 |
self.symbolChanged(symbol)
|
168 |
elif type(symbol) is QEngineeringLineNoTextItem: |
169 |
self.lineNoChanged(symbol)
|
170 |
finally:
|
171 |
self.blockSignals(True) |
172 | |
173 |
'''
|
174 |
@brief show drawing' attributes
|
175 |
@author humkyung
|
176 |
@date 2018.07.07
|
177 |
'''
|
178 |
@pyqtSlot(Drawing)
|
179 |
def onDrawingClicked(self, drawing): |
180 |
try:
|
181 |
self.blockSignals(True) |
182 |
self.setRowCount(len(drawing.attrs)) |
183 | |
184 |
row = 0
|
185 |
for attr in drawing.attrs: |
186 |
name = attr[0]
|
187 |
item = QTableWidgetItem(name) |
188 |
item.setFlags(Qt.ItemIsEnabled) |
189 |
#item.setBackground(Qt.lightGray)
|
190 |
self.setItem(row, 0, item) |
191 | |
192 |
value = attr[1]
|
193 |
item = QTableWidgetItem(value) |
194 |
item.setFlags(Qt.ItemIsEnabled) |
195 |
self.setItem(row, 1, item) |
196 | |
197 |
row = row + 1
|
198 |
finally:
|
199 |
self.blockSignals(False) |
200 | |
201 |
def onVendorClicked(self, item): |
202 |
from SymbolAttr import SymbolAttr |
203 | |
204 |
try:
|
205 |
self.blockSignals(True) |
206 |
self.initTitleCell(item)
|
207 | |
208 |
self.setItem(0, 3, QTableWidgetItem(str(self._item.uid))) |
209 | |
210 |
self.show_item_properties(item)
|
211 |
self.show_item_attributes(item)
|
212 |
finally:
|
213 |
self.blockSignals(False) |
214 | |
215 |
def onTextClicked(self, item): |
216 |
from SymbolAttr import SymbolAttr |
217 | |
218 |
try:
|
219 |
self.blockSignals(True) |
220 |
self.initTitleCell(item)
|
221 | |
222 |
self.setItem(0, 3, QTableWidgetItem(str(self._item.uid))) |
223 | |
224 |
owner_item = QTableWidgetItem('{}'.format('None' if self._item.owner is None else str(self._item.owner))) |
225 |
owner_item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) |
226 |
self.setItem(1, 3, owner_item) |
227 | |
228 |
""" show icon item """
|
229 |
attr = SymbolAttr() |
230 |
attr.AttributeType = "OWNER"
|
231 |
self.show_icon_item(1, 2, attr) |
232 |
self.item(1, 1).setData(Qt.UserRole, attr) |
233 | |
234 |
self.setItem(2, 3, QTableWidgetItem(self._item.type)) |
235 |
self.setItem(3, 3, QTableWidgetItem(self._item.text())) |
236 |
finally:
|
237 |
self.blockSignals(False) |
238 | |
239 |
'''
|
240 |
@brief Slot to accept Note item click event
|
241 |
@author Jeongwoo
|
242 |
@date 18.04.27
|
243 |
@history humkyung 2018.07.08 change method name to onNoteClicked
|
244 |
'''
|
245 |
@pyqtSlot(str, dict) |
246 |
def onNoteClicked(self, noteNoStr, noteContentsList): |
247 |
try:
|
248 |
self.blockSignals(True) |
249 |
self.noteChanged(noteNoStr, noteContentsList)
|
250 |
finally:
|
251 |
self.blockSignals(False) |
252 | |
253 |
'''
|
254 |
@brief Slot to accept Line No Item Click event
|
255 |
@author Jeongwoo
|
256 |
@date 18.05.10
|
257 |
@hisotry humkyung 2018.07.08 change method name to onLineNoClicked
|
258 |
'''
|
259 |
@pyqtSlot(QEngineeringAbstractItem)
|
260 |
def onLineNoClicked(self, item): |
261 |
try:
|
262 |
self.blockSignals(True) |
263 |
self.lineNoChanged(item)
|
264 |
finally:
|
265 |
self.blockSignals(False) |
266 |
|
267 |
'''
|
268 |
@brief Reset table with new SymbolSvgItem
|
269 |
@author Jeongwoo
|
270 |
@date 18.04.13
|
271 |
@history .
|
272 |
'''
|
273 |
def symbolChanged(self, item): |
274 |
self.initTitleCell(item)
|
275 |
self.initContentsCell()
|
276 | |
277 |
'''
|
278 |
@brief Reset table with note info
|
279 |
@author Jeongwoo
|
280 |
@date 18.04.27
|
281 |
'''
|
282 |
def noteChanged(self, noteNoStr, noteContentsList): |
283 |
self.initNoteCell(noteNoStr, noteContentsList)
|
284 | |
285 |
'''
|
286 |
@brief Reset table with line no item
|
287 |
@author Jeongwoo
|
288 |
@date 18.05.10
|
289 |
'''
|
290 |
def lineNoChanged(self, item): |
291 |
from EngineeringRunItem import QEngineeringRunItem |
292 | |
293 |
if type(item) is QEngineeringLineNoTextItem: |
294 |
self.initTitleCell(item)
|
295 |
self.initLineNoCell(item)
|
296 |
elif type(item) is QEngineeringRunItem: |
297 |
self.initLineRunCell(item)
|
298 | |
299 |
""" show tooltip """
|
300 |
for index in range(self.rowCount()): |
301 |
item = self.item(index, 1) |
302 |
if item is not None: |
303 |
item.setToolTip(item.text()) |
304 | |
305 |
'''
|
306 |
@brief Initialize Title Cell
|
307 |
@author Jeongwoos
|
308 |
@date 18.04.13
|
309 |
@history Jeongwoo 2018.04.27 Add if-statement by ItemType
|
310 |
Jeongwoo 2018.05.10 Add if-statement LINE_NO ItemType
|
311 |
humkyung 2018.08.15 add combobox for line type
|
312 |
'''
|
313 |
def initTitleCell(self, item): |
314 |
from LineTypeConditions import LineTypeConditions |
315 | |
316 |
try:
|
317 |
self.clear()
|
318 |
self.setHorizontalHeaderLabels(['', self.tr('Name'), '', self.tr('Value')]) |
319 |
self.setColumnWidth(0, 20) |
320 |
self.setColumnWidth(1, 80) |
321 |
self.setColumnWidth(2, 20) |
322 |
if type(item) is QEngineeringSpecBreakItem: |
323 |
self.setRowCount(7) |
324 |
self.setItem(0, 1, QTableWidgetItem(self.tr("UID"))) |
325 |
self.setItem(1, 1, QTableWidgetItem(self.tr("Name"))) |
326 |
self.setItem(2, 1, QTableWidgetItem(self.tr("Type"))) |
327 |
self.setItem(3, 1, QTableWidgetItem(self.tr("Angle"))) |
328 |
self.setItem(4, 1, QTableWidgetItem(self.tr("Origin"))) |
329 |
self.setItem(5, 1, QTableWidgetItem(self.tr("OWNER"))) |
330 |
self.setItem(6, 1, QTableWidgetItem(self.tr("Set Specs"))) |
331 |
elif type(item) is QEngineeringErrorItem: |
332 |
self.setRowCount(7) |
333 |
self.setItem(0, 1, QTableWidgetItem(self.tr("UID"))) |
334 |
self.setItem(1, 1, QTableWidgetItem(self.tr("Name"))) |
335 |
self.setItem(2, 1, QTableWidgetItem(self.tr("Type"))) |
336 |
self.setItem(3, 1, QTableWidgetItem(self.tr("Angle"))) |
337 |
self.setItem(4, 1, QTableWidgetItem(self.tr("Origin"))) |
338 |
self.setItem(5, 1, QTableWidgetItem(self.tr("OWNER"))) |
339 |
self.setItem(6, 1, QTableWidgetItem(self.tr("Message"))) |
340 |
elif issubclass(type(item), SymbolSvgItem): |
341 |
self.setRowCount(6) |
342 |
self.setItem(0, 1, QTableWidgetItem(self.tr("UID"))) |
343 |
self.setItem(1, 1, QTableWidgetItem(self.tr("Name"))) |
344 |
self.setItem(2, 1, QTableWidgetItem(self.tr("Type"))) |
345 |
self.setItem(3, 1, QTableWidgetItem(self.tr("Angle"))) |
346 |
self.setItem(4, 1, QTableWidgetItem(self.tr("Origin"))) |
347 |
self.setItem(5, 1, QTableWidgetItem(self.tr("OWNER"))) |
348 |
elif type(item) is QEngineeringNoteItem: |
349 |
self.setRowCount(2) |
350 |
self.setItem(0, 1, QTableWidgetItem(self.tr("Note No"))) |
351 |
self.setItem(1, 1, QTableWidgetItem(self.tr("Desc."))) |
352 |
elif type(item) is QEngineeringLineNoTextItem: |
353 |
self.setRowCount(1) |
354 |
self.setItem(0, 1, QTableWidgetItem(self.tr("UID"))) |
355 |
elif type(item) is QEngineeringLineItem: |
356 |
self.setRowCount(5) |
357 |
self.setItem(0, 1, QTableWidgetItem(self.tr('UID'))) |
358 |
self.setItem(1, 1, QTableWidgetItem(self.tr('OWNER'))) |
359 |
widgetItem = QTableWidgetItem(self.tr("Type")) |
360 |
widgetItem.setData(Qt.UserRole, item) |
361 |
self.setItem(2, 1, widgetItem) |
362 |
self._lineTypeComboBox = QComboBox(self) |
363 |
self._lineTypeComboBox.tag = widgetItem
|
364 |
for lineType in LineTypeConditions.items(): |
365 |
self._lineTypeComboBox.addItem(lineType.name)
|
366 |
self.setCellWidget(2, 3, self._lineTypeComboBox) |
367 |
self._lineTypeComboBox.setCurrentText(item.lineType)
|
368 |
self._lineTypeComboBox.currentIndexChanged.connect(self.onLineTypeChanged) |
369 |
elif type(item) is QEngineeringVendorItem: |
370 |
self.setRowCount(1) |
371 |
self.setItem(0, 1, QTableWidgetItem(self.tr("UID"))) |
372 |
else:
|
373 |
self.setRowCount(4) |
374 |
self.setItem(0, 1, QTableWidgetItem(self.tr("UID"))) |
375 |
self.setItem(1, 1, QTableWidgetItem(self.tr("OWNER"))) |
376 |
self.setItem(2, 1, QTableWidgetItem(self.tr("Type"))) |
377 |
self.setItem(3, 1, QTableWidgetItem(self.tr("Text"))) |
378 | |
379 |
for index in range(self.rowCount()): |
380 |
item = self.item(index, 1) |
381 |
if item is not None: |
382 |
item.setFlags(Qt.ItemIsEnabled) |
383 |
#item.setBackground(Qt.lightGray)
|
384 |
except Exception as ex: |
385 |
from App import App |
386 | |
387 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
388 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
389 | |
390 |
'''
|
391 |
@brief change selected lines' type by selected line type
|
392 |
@author humkyung
|
393 |
@date 2018.08.15
|
394 |
'''
|
395 |
def onLineTypeChanged(self, param): |
396 |
lineType = self._lineTypeComboBox.itemText(param)
|
397 |
data = self._lineTypeComboBox.tag.data(Qt.UserRole)
|
398 |
if type(data) is QEngineeringLineItem: |
399 |
self.changeConnectedLineType(data, lineType)
|
400 | |
401 |
def changeConnectedLineType(self, line, lineType): |
402 |
line.lineType = lineType |
403 |
if type(line.connectors[0].connectedItem) is QEngineeringLineItem and \ |
404 |
(line.connectors[0].connectedItem.connectors[0].connectedItem is line or line.connectors[0].connectedItem.connectors[1].connectedItem is line) and \ |
405 |
line.connectors[0].connectedItem.lineType is not lineType: |
406 |
self.changeConnectedLineType(line.connectors[0].connectedItem, lineType) |
407 |
if type(line.connectors[1].connectedItem) is QEngineeringLineItem and \ |
408 |
(line.connectors[1].connectedItem.connectors[0].connectedItem is line or line.connectors[1].connectedItem.connectors[1].connectedItem is line) and \ |
409 |
line.connectors[1].connectedItem.lineType is not lineType: |
410 |
self.changeConnectedLineType(line.connectors[1].connectedItem, lineType) |
411 | |
412 |
def show_icon_item(self, row, col, prop): |
413 |
""" show icon item on grid """
|
414 |
from PyQt5 import QtGui |
415 | |
416 |
if prop.is_selectable or prop.AttributeType == 'OWNER' or prop.AttributeType == 'CONN': |
417 |
icon = QtGui.QIcon() |
418 |
icon.addPixmap(QtGui.QPixmap(":/newPrefix/doubleclick.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
419 |
icon_item = QTableWidgetItem('')
|
420 |
icon_item.setFlags(Qt.ItemIsEnabled) |
421 |
icon_item.setIcon(icon) |
422 |
self.setItem(row, col, icon_item)
|
423 |
elif prop.AttributeType == "String": |
424 |
icon = QtGui.QIcon() |
425 |
icon.addPixmap(QtGui.QPixmap(":/newPrefix/type.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
426 |
icon_item = QTableWidgetItem() |
427 |
icon_item.setIcon(icon) |
428 |
self.setItem(row, col, icon_item)
|
429 |
else:
|
430 |
item = QTableWidgetItem() |
431 |
item.setFlags(Qt.ItemIsEditable) |
432 |
self.setItem(row, col, item)
|
433 | |
434 |
def show_item_properties(self, item): |
435 |
""" show item properties on grid """
|
436 |
from PyQt5 import QtGui |
437 | |
438 |
row = self.rowCount()
|
439 |
if hasattr(item, '_properties'): |
440 |
self.setRowCount(row + len(item.properties)) |
441 | |
442 |
for prop,value in item.properties.items(): |
443 |
try:
|
444 |
""" show freeze state """
|
445 |
checkbox = QCustomCheckBox(self, row, 0) |
446 |
checkbox.setChecked(prop.Freeze) |
447 |
checkbox.stateChanged.connect(checkbox.state_changed) |
448 |
self.setCellWidget(row, 0, checkbox) |
449 | |
450 |
""" show property name """
|
451 |
key_item = QTableWidgetItem(prop.DisplayAttribute if prop.DisplayAttribute else prop.Attribute) |
452 |
key_item.setFlags(Qt.ItemIsEnabled) |
453 |
#key_item.setBackground(Qt.lightGray)
|
454 |
key_item.setData(Qt.UserRole, prop) |
455 |
self.setItem(row, 1, key_item) |
456 | |
457 |
""" show icon item """
|
458 |
self.show_icon_item(row, 2, prop) |
459 | |
460 |
""" show property value """
|
461 |
if prop.is_selectable:
|
462 |
value_item = QTableWidgetItem(str(value.uid) if hasattr(value, 'uid') else value) |
463 |
value_item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) |
464 |
self.setItem(row, 3, value_item) |
465 |
else:
|
466 |
if prop.AttributeType == 'Boolean': |
467 |
self.checkbox_cell = QCustomCheckBox(self, row, 3) |
468 |
self.checkbox_cell.setChecked(True if value and str(value) == 'True' else False) |
469 |
self.checkbox_cell.stateChanged.connect(self.checkbox_cell.state_changed) |
470 |
#if prop.Attribute == 'Freeze': self.checkbox_cell.stateChanged.connect(item.freeze_item.update_freeze)
|
471 |
self.setCellWidget(row, 3, self.checkbox_cell) |
472 |
else:
|
473 |
value_item = QTableWidgetItem(value if value else '') |
474 |
value_item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable|Qt.ItemIsEditable) |
475 |
self.setItem(row, 3, value_item) |
476 | |
477 |
checkbox.state_changed(checkbox.isChecked()) |
478 |
|
479 |
row = row + 1
|
480 |
except Exception as ex: |
481 |
from App import App |
482 | |
483 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
484 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
485 | |
486 |
def show_item_attributes(self, item): |
487 |
""" show item's attributes on grid """
|
488 |
from PyQt5 import QtGui |
489 | |
490 |
row = self.rowCount()
|
491 |
attrs = item.getAttributes() |
492 | |
493 |
# display attributes of symbol
|
494 |
if attrs is not None: |
495 |
self.setRowCount(row + len(attrs)) |
496 | |
497 |
for key,value in attrs.items(): |
498 |
try:
|
499 |
""" show freeze state """
|
500 |
checkbox = QCustomCheckBox(self, row, 0) |
501 |
checkbox.setChecked(key.Freeze) |
502 |
checkbox.stateChanged.connect(checkbox.state_changed) |
503 |
self.setCellWidget(row, 0, checkbox) |
504 | |
505 |
""" show property name """
|
506 |
key_item = QTableWidgetItem(key.DisplayAttribute if key.DisplayAttribute else key.Attribute) |
507 |
#key_item.setBackground(Qt.lightGray)
|
508 |
key_item.setData(Qt.UserRole, key) |
509 |
self.setItem(row, 1, key_item) |
510 | |
511 |
""" show icon item """
|
512 |
self.show_icon_item(row, 2, key) |
513 | |
514 |
value_item = QTableWidgetItem(str(value))
|
515 |
value_item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable|Qt.ItemIsEditable) |
516 | |
517 |
if type(item) is QEngineeringSpecBreakItem: |
518 |
if key.Attribute == 'UpStream' or key.Attribute == 'DownStream': |
519 |
UpDownItem = QTableWidgetItem('{}'.format('None' if value is None else value)) |
520 |
self.setItem(row, 3, UpDownItem) |
521 |
else: # elif key.AttributeType == 'Spec': |
522 |
self.setItem(row, 3, QTableWidgetItem(str(value)[1:-1])) |
523 |
else:
|
524 |
self.setItem(row, 3, value_item) |
525 | |
526 |
checkbox.state_changed(checkbox.isChecked()) |
527 | |
528 |
row = row + 1
|
529 |
except Exception as ex: |
530 |
from App import App |
531 | |
532 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
533 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
534 | |
535 |
def show_item_connectors(self, item): |
536 |
""" show items' connectors on grid """
|
537 |
from PyQt5 import QtGui |
538 |
from SymbolAttr import SymbolAttr |
539 | |
540 |
row = self.rowCount()
|
541 |
self.setRowCount(row + len(item.connectors)) |
542 | |
543 |
count = 1
|
544 |
for connector in item.connectors: |
545 |
connector_item = QTableWidgetItem('CONN{}'.format(count))
|
546 |
connector_item.setFlags(Qt.ItemIsEnabled) |
547 |
#connector_item.setBackground(Qt.lightGray)
|
548 |
self.setItem(row, 1, connector_item) |
549 | |
550 |
attr = SymbolAttr() |
551 |
attr.AttributeType = "CONN"
|
552 |
attr.AttrAt = count |
553 |
connector_item.setData(Qt.UserRole, attr) |
554 | |
555 |
""" show icon item """
|
556 |
self.show_icon_item(row, 2, attr) |
557 | |
558 |
connector_item = QTableWidgetItem('{}'.format('None' if connector.connectedItem is None else str(connector.connectedItem))) |
559 |
connector_item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) |
560 |
self.setItem(row, 3, connector_item) |
561 |
|
562 |
row = row + 1
|
563 |
count = count + 1
|
564 | |
565 |
'''
|
566 |
@brief Initialize Contents Cell
|
567 |
@author Jeongwoo
|
568 |
@date 18.04.13
|
569 |
@history humkyung 2018.06.14 display symbol attributes
|
570 |
humkyung 2018.07.05 display connectivity
|
571 |
euisung 2019.01.15 edit specbreak
|
572 |
'''
|
573 |
def initContentsCell(self): |
574 |
from PyQt5 import QtGui |
575 |
from SymbolAttr import SymbolAttr |
576 | |
577 |
try:
|
578 |
if self._item is not None and issubclass(type(self._item), SymbolSvgItem): |
579 |
docData = AppDocData.instance() |
580 | |
581 |
self.setItem(0, 3, QTableWidgetItem(str(self._item.uid))) |
582 |
self.setItem(1, 3, QTableWidgetItem(self._item.name)) |
583 |
self.setItem(2, 3, QTableWidgetItem(self._item.type)) |
584 |
self.setItem(3, 3, QTableWidgetItem(str(round(math.degrees(self._item.angle))))) |
585 |
self.setItem(4, 3, QTableWidgetItem(str(self._item.origin))) |
586 |
owner_item = QTableWidgetItem('{}'.format('None' if self._item.owner is None else str(self._item.owner))) |
587 |
self.setItem(5, 3, owner_item) |
588 | |
589 |
for index in range(self.rowCount()): |
590 |
item = self.item(index, 3) |
591 |
if item is not None: |
592 |
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) |
593 | |
594 |
""" show icon item """
|
595 |
attr = SymbolAttr() |
596 |
attr.AttributeType = "OWNER"
|
597 |
self.show_icon_item(5, 2, attr) |
598 |
self.item(5, 1).setData(Qt.UserRole, attr) |
599 | |
600 |
if type(self._item) is not QEngineeringSpecBreakItem and type(self._item) is not QEngineeringErrorItem: |
601 |
self.show_item_properties(self._item) |
602 | |
603 |
if type(self._item) is QEngineeringSpecBreakItem: |
604 |
row = self.rowCount()
|
605 |
setSpecsItem = QTableWidgetItem('')
|
606 |
icon = QtGui.QIcon() |
607 |
icon.addPixmap(QtGui.QPixmap(":/newPrefix/doubleclick.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
608 |
setSpecsItem.setIcon(icon) |
609 |
self.setItem(row - 1, 2, setSpecsItem) |
610 |
self.setItem(row - 1, 3, QTableWidgetItem('Open')) |
611 | |
612 |
if type(self._item) is QEngineeringErrorItem: |
613 |
errType = 'None'
|
614 |
if type(self._item.parent) is QEngineeringLineItem: |
615 |
errType = 'line'
|
616 |
elif issubclass(type(self._item.parent), SymbolSvgItem): |
617 |
errType = 'symbol'
|
618 |
self.setItem(2, 3, QTableWidgetItem(errType)) |
619 |
self.setItem(5, 3, QTableWidgetItem(str(self._item.parent.uid))) |
620 |
self.setItem(6, 3, QTableWidgetItem(self._item.msg)) |
621 | |
622 |
self.show_item_attributes(self._item) |
623 |
self.show_item_connectors(self._item) |
624 |
|
625 |
for index in range(self.rowCount()): |
626 |
item = self.item(index, 3) |
627 |
if item is not None: item.setToolTip(item.text()) |
628 |
elif self._item is not None and type(self._item) is QEngineeringLineItem: |
629 |
self.setItem(0, 3, QTableWidgetItem(str(self._item.uid))) |
630 | |
631 |
""" show icon item """
|
632 |
attr = SymbolAttr() |
633 |
attr.AttributeType = "OWNER"
|
634 |
self.show_icon_item(1, 2, attr) |
635 |
self.item(1, 1).setData(Qt.UserRole, attr) |
636 | |
637 |
owner_item = QTableWidgetItem('{}'.format('None' if self._item.owner is None else str(self._item.owner))) |
638 |
self.setItem(1, 3, owner_item) |
639 | |
640 |
self.show_item_properties(self._item) |
641 | |
642 |
pt = self._item.startPoint()
|
643 |
key_item = QTableWidgetItem(self.tr("Start")) |
644 |
key_item.setFlags(Qt.ItemIsEnabled) |
645 |
#key_item.setBackground(Qt.lightGray)
|
646 |
self.setItem(3, 1, key_item) |
647 |
self.setItem(3, 3, QTableWidgetItem('({},{})'.format(pt[0], pt[1]))) |
648 |
pt = self._item.endPoint()
|
649 |
key_item = QTableWidgetItem(self.tr("End")) |
650 |
key_item.setFlags(Qt.ItemIsEnabled) |
651 |
#key_item.setBackground(Qt.lightGray)
|
652 |
self.setItem(4, 1, key_item) |
653 |
self.setItem(4, 3, QTableWidgetItem('({},{})'.format(pt[0], pt[1]))) |
654 | |
655 |
self.show_item_attributes(self._item) |
656 |
self.show_item_connectors(self._item) |
657 |
else:
|
658 |
self.setRowCount(0) |
659 |
|
660 |
except Exception as ex: |
661 |
from App import App |
662 | |
663 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
664 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
665 | |
666 |
'''
|
667 |
@brief combobox change event
|
668 |
@author kyouho
|
669 |
@date 2018.08.28
|
670 |
'''
|
671 |
def upStreamChanged(self, text): |
672 |
if self._item is not None: |
673 |
find = False
|
674 |
for index in range(len(self._item.attrs)): |
675 |
if type(self._item.attrs[index]) is tuple and self._item.attrs[index][0] == 'Up Stream': |
676 |
self._item.attrs[index] = (self._item.attrs[index][0], text) |
677 |
find = True
|
678 |
break
|
679 |
|
680 |
if not find: |
681 |
self._item.attrs.append(('Up Stream', text)) |
682 | |
683 |
'''
|
684 |
@brief combobox change event
|
685 |
@author kyouho
|
686 |
@date 2018.08.28
|
687 |
'''
|
688 |
def downStreamChanged(self, text): |
689 |
if self._item is not None: |
690 |
find = False
|
691 |
for index in range(len(self._item.attrs)): |
692 |
if type(self._item.attrs[index]) is tuple and self._item.attrs[index][0] == 'Down Stream': |
693 |
self._item.attrs[index] = (self._item.attrs[index][0], text) |
694 |
find = True
|
695 |
break
|
696 |
|
697 |
if not find: |
698 |
self._item.attrs.append(('Down Stream', text)) |
699 | |
700 |
'''
|
701 |
@brief Initialize Note Contents Cell
|
702 |
@author Jeongwoo
|
703 |
@date 18.04.27
|
704 |
'''
|
705 |
def initNoteCell(self, noteNoStr, noteContentsList): |
706 |
self.setRowCount(0) |
707 | |
708 |
for key in noteContentsList: |
709 |
row = self.rowCount()
|
710 |
self.setRowCount(row + len(noteContentsList[key])) |
711 |
item = QTableWidgetItem(key) |
712 |
self.setItem(row, 1, item) |
713 | |
714 |
for index in range(len(noteContentsList[key])): |
715 |
self.setItem(row, 3, QTableWidgetItem(noteContentsList[key][index])) |
716 |
row = row + 1
|
717 | |
718 |
for index in range(self.rowCount()): |
719 |
item = self.item(index, 1) |
720 |
if item is not None: |
721 |
item.setFlags(Qt.ItemIsEnabled) |
722 |
#item.setBackground(Qt.lightGray)
|
723 | |
724 |
'''
|
725 |
@brief Initialize Line No Contents Cell
|
726 |
@author Jeongwoo
|
727 |
@date 18.05.10
|
728 |
@history humkyung 2018.07.20 display combobox when key is 'Stream No'
|
729 |
'''
|
730 |
def initLineNoCell(self, lineNoItem): |
731 |
appDocData = AppDocData.instance() |
732 |
configs = appDocData.getConfigs('Line No', 'Configuration') |
733 |
configs = configs[0].value.split('"-"') |
734 | |
735 |
item = QTableWidgetItem(str(lineNoItem.uid))
|
736 |
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) |
737 |
self.setItem(0, 3, item) |
738 | |
739 |
self.show_item_properties(lineNoItem)
|
740 |
|
741 |
row = self.rowCount()
|
742 |
attrs = lineNoItem.getAttributes() |
743 |
self.setRowCount(row + len(attrs)) |
744 |
if attrs is not None: |
745 |
for key in attrs.keys(): |
746 |
item = QTableWidgetItem(key.DisplayAttribute if key.DisplayAttribute else key.Attribute) |
747 |
item.setFlags(Qt.ItemIsEnabled) |
748 |
#item.setBackground(Qt.lightGray)
|
749 |
item.tag = key |
750 |
self.setItem(row, 1, item) |
751 | |
752 |
""" show icon item """
|
753 |
self.show_icon_item(row, 2, key) |
754 | |
755 |
# value cell
|
756 |
value = attrs[key] |
757 |
valueCell = QTableWidgetItem(value) |
758 | |
759 |
# UID로 확인
|
760 |
keyStr = appDocData.getLinePropertiesByUID(key.UID) |
761 |
if keyStr:
|
762 |
# editable value cell
|
763 |
if keyStr[0].AttributeType == 'String': |
764 |
pass
|
765 |
#self.attrValueList.append((valueCell, key.Attribute))
|
766 |
#self.stringCell.append(valueCell)
|
767 |
if keyStr[0].UID in configs: valueCell.setFlags(Qt.ItemIsEnabled) |
768 |
else:
|
769 |
valueCell.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable) |
770 |
|
771 |
if key.Attribute.upper() == 'STREAM_NO': |
772 |
self.streamNoComboBox = QComboBox()
|
773 |
self.streamNoComboBox.tag = key
|
774 |
self.streamNoComboBox.currentIndexChanged.connect(self.onStreamNoChanged) |
775 |
|
776 |
streamNos = sorted(list(appDocData.hmbTable.streamNos())) |
777 |
for streamNo in streamNos: |
778 |
self.streamNoComboBox.addItem(streamNo)
|
779 |
self.setCellWidget(row, 3, self.streamNoComboBox) |
780 |
self.streamNoComboBox.setCurrentText(value)
|
781 |
|
782 |
self.setItem(row, 3, valueCell) |
783 | |
784 |
row = row + 1
|
785 | |
786 |
'''
|
787 |
@brief change selected lines' stream no by selected stream no
|
788 |
@author humkyung
|
789 |
@date 2018.07.20
|
790 |
'''
|
791 |
def onStreamNoChanged(self, param): |
792 |
items = self.mainWindow.graphicsView.scene.selectedItems()
|
793 |
if items is not None and len(items) == 1: |
794 |
if type(items[0]) is QEngineeringLineNoTextItem: |
795 |
stream_no = self.streamNoComboBox.itemText(param)
|
796 |
items[0].set_attrib(self.streamNoComboBox.tag, stream_no) |
797 |
return
|
798 | |
799 |
'''
|
800 |
@brief Initialize Run Contents Cell
|
801 |
@author humkyung
|
802 |
@date 2018.05.27
|
803 |
'''
|
804 |
def initLineRunCell(self, item): |
805 |
self.setRowCount(1) |
806 | |
807 |
lineTypeItem = QTableWidgetItem(self.tr("Line Type")) |
808 |
#lineTypeItem.setBackground(Qt.lightGray)
|
809 |
lineTypeItem.setFlags(Qt.ItemIsEnabled) |
810 |
self.setItem(0, 1, lineTypeItem) |
811 | |
812 |
'''
|
813 |
@brief Key Press Event
|
814 |
@author kyouho
|
815 |
@date 2018.07.19
|
816 |
'''
|
817 |
def keyPressEvent(self, event): |
818 |
from SymbolAttr import SymbolAttr |
819 | |
820 |
if event.key() == Qt.Key_Delete:
|
821 |
items = self.mainWindow.graphicsView.scene.selectedItems()
|
822 |
selectedIndexes = self.selectedIndexes()
|
823 |
if selectedIndexes and selectedIndexes[0].column() == 3 and self.item(selectedIndexes[0].row(), 1).text() == 'OWNER': |
824 |
items[0].owner = None |
825 |
self.show_item_property(items[0]) |
826 |
elif len(items) == 1 and len(selectedIndexes) == 1 and (type(items[0]) is QEngineeringLineItem or issubclass(type(items[0]), SymbolSvgItem)): |
827 |
key_cell = self.item(selectedIndexes[0].row(), 1) |
828 |
data = key_cell.data(Qt.UserRole) |
829 |
if selectedIndexes[0].column() == 3 and key_cell.text().find('CONN') is 0: |
830 |
selectedUID = self.item(selectedIndexes[0].row(), 1).text() |
831 |
connNum = int(key_cell.text().replace('CONN', '')) |
832 |
items[0].connectors[connNum - 1].connectedItem = None |
833 |
self.show_item_property(items[0]) |
834 | |
835 |
for sceneItem in self.mainWindow.graphicsView.scene.items(): |
836 |
if hasattr(sceneItem, 'uid') and str(sceneItem.uid) == selectedUID and hasattr(sceneItem, 'connectors'): |
837 |
for sceneConnector in sceneItem.connectors: |
838 |
if sceneConnector.connectedItem is not None and items[0].uid == sceneConnector.connectedItem.uid: |
839 |
sceneConnector.connectedItem = None
|
840 |
elif selectedIndexes[0].column() == 3 and data and type(data) is SymbolAttr: |
841 |
assocItem = None
|
842 |
for _attr,_value in items[0].attrs.items(): |
843 |
if str(_attr.UID) == str(data.UID): |
844 |
assocItem = _attr.AssocItem |
845 |
items[0].remove_assoc_item(_attr.AssocItem)
|
846 |
if issubclass(type(_attr.AssocItem), QEngineeringTextItem): |
847 |
_attr.AssocItem.owner = None
|
848 |
_attr.AssocItem = None
|
849 |
items[0].attrs[_attr] = '' |
850 |
break
|
851 |
for _attr,_value in items[0].attrs.items(): |
852 |
if _attr.AssocItem is assocItem: |
853 |
_attr.AssocItem = None
|
854 |
items[0].attrs[_attr] = '' |
855 |
self.show_item_property(items[0]) |
856 |
elif len(items) == 1 and len(selectedIndexes) == 1 and type(items[0]) is QEngineeringSpecBreakItem: |
857 |
keyCell = self.item(selectedIndexes[0].row(), 1) |
858 |
if selectedIndexes[0].column() == 3 and (keyCell.text() == 'UpStream' or keyCell.text() == 'DownStream'): |
859 |
for attr in items[0].attrs.keys(): |
860 |
if attr.Attribute == keyCell.text():
|
861 |
items[0].attrs[attr] = None |
862 |
self.show_item_property(items[0]) |
863 |
elif (event.key() == Qt.Key_C) and (event.modifiers() & Qt.ControlModifier): |
864 |
self.copy_cells_to_clipboard()
|
865 |
event.accept() |
866 | |
867 |
def copy_cells_to_clipboard(self): |
868 |
""" copy selected text to clipboard """
|
869 | |
870 |
selection = self.selectedIndexes()
|
871 |
if selection:
|
872 |
rows = sorted(index.row() for index in selection) |
873 |
columns = sorted(index.column() for index in selection) |
874 |
text = self.item(rows[-1], columns[-1]).text() |
875 |
QApplication.clipboard().setText(text) |
876 | |
877 |
'''
|
878 |
@brief int cell check
|
879 |
@author kyouho
|
880 |
@date 2018.08.20
|
881 |
'''
|
882 |
def cellChangedEvent(self, row, column): |
883 |
from SymbolAttr import SymbolProp |
884 |
from SymbolAttr import SymbolAttr |
885 | |
886 |
try:
|
887 |
if column == 3: |
888 |
item = self.item(row, 1) |
889 |
data = item.data(Qt.UserRole) if item is not None else None |
890 |
if data is not None: |
891 |
if self._item: |
892 |
if type(data) is SymbolProp: |
893 |
if data.AttributeType != 'Boolean': |
894 |
self._item.set_property(data.Attribute, self.item(row, column).text()) |
895 |
else:
|
896 |
self._item.set_property(data.Attribute, self.cellWidget(row, column).isChecked()) |
897 |
elif type(data) is SymbolAttr: |
898 |
if data.AttributeType != 'Boolean': |
899 |
self._item.set_attrib(data, self.item(row, column).text()) |
900 |
else:
|
901 |
self._item.set_attrib(data, self.cellWidget(row, column).isChecked()) |
902 |
except Exception as ex: |
903 |
from App import App |
904 |
from AppDocData import MessageType |
905 | |
906 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
907 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
908 | |
909 |
'''
|
910 |
@brief resultPropertyTableWidget Cell Double Click Event
|
911 |
@author kyouho
|
912 |
@date 2018.07.19
|
913 |
@history euisung 2019.01.15 edit specbreak
|
914 |
'''
|
915 |
def cellDoubleClickedEvent(self, row, column): |
916 |
from SymbolAttr import SymbolProp |
917 | |
918 |
if column == 2: |
919 |
items = self.mainWindow.graphicsView.scene.selectedItems()
|
920 |
keyCell = self.item(row, 1) |
921 |
attr = keyCell.data(Qt.UserRole) |
922 |
if hasattr(keyCell, 'tag') and type(items[0]) is not QEngineeringSpecBreakItem: |
923 |
attr = keyCell.tag |
924 |
if attr.is_selectable:
|
925 |
cmd = SelectAttributeCommand.SelectAttributeCommand(items[0], attr, self.mainWindow.graphicsView) |
926 |
cmd.onSuccess.connect(self.onSuccessSelectAttribute)
|
927 |
self.mainWindow.graphicsView.command = cmd
|
928 |
elif self.item(row, column).flags() != Qt.ItemIsEnabled: |
929 |
self.editItem(self.item(row, column)) |
930 |
elif keyCell.text() == 'CONN' and type(items[0]) is QEngineeringLineNoTextItem: |
931 |
# unused code
|
932 |
from SymbolAttr import SymbolAttr |
933 |
attr = SymbolAttr() |
934 |
attr.AttributeType = "Line Item"
|
935 |
cmd = SelectAttributeCommand.SelectAttributeCommand(items[0], attr, self.mainWindow.graphicsView) |
936 |
cmd.onSuccess.connect(self.onSuccessSelectAttribute)
|
937 |
self.mainWindow.graphicsView.command = cmd
|
938 |
elif keyCell.text() == 'OWNER' and ((type(items[0]) is QEngineeringLineItem) or (issubclass(type(items[0]), SymbolSvgItem)) or (issubclass(type(items[0]), QEngineeringTextItem))): |
939 |
attr = keyCell.data(Qt.UserRole) |
940 |
cmd = SelectAttributeCommand.SelectAttributeCommand(items[0], attr, self.mainWindow.graphicsView) |
941 |
cmd.onSuccess.connect(self.onSuccessSelectAttribute)
|
942 |
self.mainWindow.graphicsView.command = cmd
|
943 |
elif type(items[0]) is QEngineeringSpecBreakItem: |
944 |
if keyCell.text() == 'UpStream' or keyCell.text() == 'DownStream': |
945 |
attr = keyCell.data(Qt.UserRole) |
946 |
cmd = SelectAttributeCommand.SelectAttributeCommand(items[0], attr, self.mainWindow.graphicsView) |
947 |
cmd.onSuccess.connect(self.onSuccessSelectAttribute)
|
948 |
self.mainWindow.graphicsView.command = cmd
|
949 | |
950 |
elif keyCell.text() == 'Set Specs': |
951 |
from SpecBreakDialog import QSpecBreakDialog |
952 | |
953 |
try:
|
954 |
dialog = QSpecBreakDialog(self, items[0]) |
955 |
dialog.exec_() |
956 |
self.show_item_property(items[0]) |
957 |
except Exception as ex: |
958 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
959 |
elif issubclass(type(attr), SymbolProp): |
960 |
attr = keyCell.data(Qt.UserRole) |
961 |
cmd = SelectAttributeCommand.SelectAttributeCommand(items[0], attr, self.mainWindow.graphicsView) |
962 |
cmd.onSuccess.connect(self.onSuccessSelectAttribute)
|
963 |
self.mainWindow.graphicsView.command = cmd
|
964 | |
965 |
'''
|
966 |
@brief success select attribute
|
967 |
@author kyouho
|
968 |
@date 2018.10.23
|
969 |
'''
|
970 |
def onSuccessSelectAttribute(self, connItem = None): |
971 |
""" update item's properties after selecting """
|
972 |
self.show_item_property(self._item) |