hytos / DTI_PID / DTI_PID / QtImageViewerScene.py @ ebf14a7c
이력 | 보기 | 이력해설 | 다운로드 (14.3 KB)
1 |
# coding: utf-8
|
---|---|
2 |
""" This is image viewer scene module """
|
3 |
|
4 |
import sys |
5 |
import os.path |
6 |
from SingletonInstance import SingletonInstance |
7 |
|
8 |
try:
|
9 |
from PyQt5.QtCore import * |
10 |
from PyQt5.QtGui import * |
11 |
from PyQt5.QtWidgets import * |
12 |
except ImportError: |
13 |
try:
|
14 |
from PyQt4.QtCore import * |
15 |
from PyQt4.QtGui import * |
16 |
except ImportError: |
17 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
18 |
|
19 |
__author__ = "humkyung <humkyung.doftech.co.kr>"
|
20 |
__version__ = '1.0.0'
|
21 |
|
22 |
|
23 |
class QtImageViewerScene(QGraphicsScene): |
24 |
""" This is image viewer scene class """
|
25 |
contents_changed = pyqtSignal() |
26 |
|
27 |
def __init__(self, parent): |
28 |
QGraphicsScene.__init__(self, parent)
|
29 |
|
30 |
self._undo_stack = QUndoStack(self) |
31 |
self._delta = QPointF()
|
32 |
self._pressed_keys = set() |
33 |
|
34 |
self.contours = []
|
35 |
self.contour_color = None |
36 |
self.circles = None |
37 |
|
38 |
self.guidesEnabled = False |
39 |
self._guidePen = QPen()
|
40 |
self._guidePen.setColor(QColor(180, 180, 180)) |
41 |
self._guidePen.setStyle(Qt.DashLine)
|
42 |
self._guidePen.setWidthF(0.3) |
43 |
|
44 |
self._pressed_position = None |
45 |
|
46 |
@property
|
47 |
def undo_stack(self): |
48 |
return self._undo_stack |
49 |
|
50 |
def addItem(self, item): |
51 |
"""add given item to scene"""
|
52 |
|
53 |
if hasattr(item, 'transfer'): |
54 |
item.transfer.onRemoved.connect(self.parent().itemRemoved)
|
55 |
|
56 |
QGraphicsScene.addItem(self, item)
|
57 |
self.contents_changed.emit()
|
58 |
|
59 |
def removeItem(self, item): |
60 |
"""remove given item from scene"""
|
61 |
|
62 |
if hasattr(item, 'transfer') and item.transfer.receivers(item.transfer.onRemoved) > 0: |
63 |
item.transfer.onRemoved.disconnect(self.parent().itemRemoved)
|
64 |
|
65 |
QGraphicsScene.removeItem(self, item)
|
66 |
self.contents_changed.emit()
|
67 |
|
68 |
def keyPressEvent(self, event: QKeyEvent): |
69 |
from SymbolSvgItem import SymbolSvgItem |
70 |
from EngineeringTextItem import QEngineeringTextItem |
71 |
from EngineeringLineItem import QEngineeringLineItem |
72 |
from QEngineeringTrimLineNoTextItem import QEngineeringLineNoTextItem |
73 |
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem |
74 |
from EngineeringVendorItem import QEngineeringVendorItem |
75 |
from DeleteCommand import DeleteCommand |
76 |
from RotateCommand import RotateCommand |
77 |
from FlipCommand import FlipCommand |
78 |
from AppDocData import AppDocData |
79 |
|
80 |
try:
|
81 |
#print('scene : ' + str(event.key()))
|
82 |
if event.key() == Qt.Key_Delete or event.key() == Qt.Key_E: |
83 |
cmd = DeleteCommand(self, [item for item in self.selectedItems() if hasattr(item, 'transfer')]) |
84 |
self._undo_stack.push(cmd)
|
85 |
elif event.key() in [Qt.Key_S, Qt.Key_D, Qt.Key_H]: |
86 |
if self.selectedItems(): |
87 |
items = [text for text in self.selectedItems() if type(text) is QEngineeringLineNoTextItem] |
88 |
#self._pressed_keys.add(event.key())
|
89 |
if items:
|
90 |
for item in items: |
91 |
item.keyPressEvent(event) |
92 |
|
93 |
event.accept() |
94 |
return
|
95 |
elif event.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right, Qt.Key_Return]: |
96 |
|
97 |
items = [text for text in self.selectedItems() if |
98 |
issubclass(type(text), QEngineeringTextItem) or issubclass(type(text), SymbolSvgItem) or type(text) == QEngineeringLineItem] |
99 |
self._pressed_keys.add(event.key())
|
100 |
if items:
|
101 |
for item in items: |
102 |
item.keyPressEvent(event) |
103 |
|
104 |
modifiers = QApplication.keyboardModifiers() |
105 |
delta = 10 if modifiers == Qt.ControlModifier else 1 |
106 |
if event.key() == Qt.Key_Up:
|
107 |
self._delta.setY(self._delta.y() - delta) |
108 |
elif event.key() == Qt.Key_Down:
|
109 |
self._delta.setY(self._delta.y() + delta) |
110 |
elif event.key() == Qt.Key_Left:
|
111 |
self._delta.setX(self._delta.x() - delta) |
112 |
elif event.key() == Qt.Key_Right:
|
113 |
self._delta.setX(self._delta.x() + delta) |
114 |
|
115 |
event.accept() |
116 |
return
|
117 |
elif event.key() == Qt.Key_C and event.modifiers() & Qt.ControlModifier: |
118 |
from xml.etree import ElementTree |
119 |
import XmlGenerator as xg |
120 |
|
121 |
app_doc_data = AppDocData.instance() |
122 |
xml, result = xg.write_to_xml(app_doc_data.activeDrawing.file_path, app_doc_data.activeDrawing.width, |
123 |
app_doc_data.activeDrawing.height, self.selectedItems(), [])
|
124 |
if xml:
|
125 |
QApplication.clipboard().setText(ElementTree.tostring(xml, encoding='unicode'))
|
126 |
elif event.key() == Qt.Key_V and event.modifiers() & Qt.ControlModifier: |
127 |
from App import App |
128 |
import uuid |
129 |
from QtImageViewer import QtImageViewer |
130 |
from TextInfo import TextInfo |
131 |
|
132 |
app_doc_data = AppDocData.instance() |
133 |
clipboard = QApplication.clipboard() |
134 |
mime_data = clipboard.mimeData() |
135 |
if mime_data.hasText():
|
136 |
text = mime_data.text() |
137 |
if text.find('<DWG>') != -1 and text.find('</DWG>') != -1: |
138 |
from xml.etree import ElementTree |
139 |
|
140 |
origin = self.views()[0].mapFromGlobal(QCursor.pos()) |
141 |
origin = self.views()[0].mapToScene(origin) |
142 |
|
143 |
delta = None
|
144 |
root = ElementTree.fromstring(text) |
145 |
for symbol in root.find('SYMBOLS').iter('SYMBOL'): |
146 |
item = SymbolSvgItem.fromXml(symbol) |
147 |
svg = QtImageViewer.createSymbolObject(item.name) |
148 |
if not delta: |
149 |
delta = origin - QPointF(item.origin[0], item.origin[1]) |
150 |
|
151 |
if type(svg) is QEngineeringSpecBreakItem: |
152 |
specBreakAttrsFull = [attr for attr in app_doc_data.getSymbolAttribute('Segment Breaks') if attr.AttributeType == 'Spec' or attr.AttributeType == 'String'] |
153 |
|
154 |
from_attrs = item.attrs |
155 |
to_attrs = svg.getAttributes() |
156 |
|
157 |
for key in from_attrs.keys(): |
158 |
if key.Attribute == 'UpStream' or key.Attribute == 'DownStream': |
159 |
continue
|
160 |
for full in specBreakAttrsFull: |
161 |
if full.Attribute == key.Attribute:
|
162 |
to_attrs[full] = from_attrs[key].copy() |
163 |
|
164 |
if item.prop('Freeze'): |
165 |
svg.set_property('Freeze', True) |
166 |
if item.prop('Show'): |
167 |
svg.set_property('Show', True) |
168 |
|
169 |
QtImageViewer.matchSymbolToLine(self, svg, QPointF(item.origin[0], item.origin[1]) + delta, item.angle) |
170 |
'''
|
171 |
# uid 새로 할당
|
172 |
item.uid = uuid.uuid4()
|
173 |
for connector in item.connectors:
|
174 |
connector.connectedItem = None
|
175 |
item.origin[0], item.origin[1] = origin.x(), origin.y()
|
176 |
item.transfer.onRemoved.connect(App.mainWnd().itemRemoved)
|
177 |
item.addSvgItemToScene(self, True)
|
178 |
item.setVisible(True)
|
179 |
'''
|
180 |
for text in root.find('TEXTINFOS').iter('ATTRIBUTE'): |
181 |
width = float(text.find('WIDTH').text) |
182 |
height = float(text.find('HEIGHT').text) |
183 |
angle = float(text.find('ANGLE').text) |
184 |
tokens = text.find('LOCATION').text.split(',') |
185 |
loc = QPointF(float(tokens[0]), float(tokens[1])) |
186 |
if not delta: |
187 |
delta = origin - loc |
188 |
pos = loc + delta |
189 |
textInfo = TextInfo(text.find('VALUE').text, pos.x(), pos.y(), width, height, angle)
|
190 |
item = QEngineeringTextItem.create_text_with(self, textInfo)
|
191 |
item.transfer.onRemoved.connect(App.mainWnd().itemRemoved) |
192 |
|
193 |
for node in root.find('LINEINFOS').iter('LINE'): |
194 |
startPoint = [float(x) for x in node.find('STARTPOINT').text.split(',')] |
195 |
endPoint = [float(x) for x in node.find('ENDPOINT').text.split(',')] |
196 |
loc = QPointF(startPoint[0], startPoint[1]) |
197 |
if not delta: |
198 |
delta = origin - loc |
199 |
line = QEngineeringLineItem(vertices=[[startPoint[0] + delta.x(), startPoint[1] + delta.y()], |
200 |
[endPoint[0] + delta.x(), endPoint[1] + delta.y()]]) #.fromXml(node) |
201 |
if line:
|
202 |
'''lineF = line.line()
|
203 |
loc = QPointF(lineF.x1(), lineF.y1())
|
204 |
if not anchor:
|
205 |
anchor = loc
|
206 |
delta = origin - loc - anchor
|
207 |
lineF.translate(delta)
|
208 |
line.setLine(lineF)
|
209 |
line.setVisible(True)'''
|
210 |
self.addItem(line)
|
211 |
|
212 |
for vendor in root.find('VENDORS').iter('VENDOR'): |
213 |
_type = vendor.attrib['Type'] if 'Type' in vendor.attrib else 'Vendor Package' |
214 |
pointNode = vendor.find('POINT')
|
215 |
strPoints = pointNode.text |
216 |
points = [] |
217 |
for strPoint in strPoints.split(QEngineeringVendorItem.DELIMITER): |
218 |
point = strPoint.split(',')
|
219 |
points.append(QPoint(float(point[0]), float(point[1]))) |
220 |
polygon = QPolygonF(points) |
221 |
item = QEngineeringVendorItem(polygon, pack_type=_type) |
222 |
item.area = vendor.find('AREA').text
|
223 |
|
224 |
self.addItem(item)
|
225 |
|
226 |
elif event.key() == Qt.Key_Z and event.modifiers() & Qt.ControlModifier: |
227 |
#self._undo_stack.undo()
|
228 |
pass
|
229 |
elif event.key() == Qt.Key_Y and event.modifiers() & Qt.ControlModifier: |
230 |
#self._undo_stack.redo()
|
231 |
pass
|
232 |
elif self.selectedItems() and event.key() == Qt.Key_R and not(event.modifiers() & Qt.ControlModifier): |
233 |
self._undo_stack.push(RotateCommand(self, self.selectedItems())) |
234 |
elif self.selectedItems() and event.key() == Qt.Key_F and not(event.modifiers() & Qt.ControlModifier): |
235 |
self._undo_stack.push(FlipCommand(self, self.selectedItems())) |
236 |
|
237 |
super(QtImageViewerScene, self).keyPressEvent(event) |
238 |
except Exception as ex: |
239 |
from App import App |
240 |
from AppDocData import MessageType |
241 |
|
242 |
message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
|
243 |
f"{sys.exc_info()[-1].tb_lineno}"
|
244 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
245 |
|
246 |
def keyReleaseEvent(self, event: QKeyEvent): |
247 |
from MoveCommand import MoveCommand |
248 |
|
249 |
if event.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right] and not event.isAutoRepeat(): |
250 |
if self.selectedItems() and not self._delta.isNull(): |
251 |
self._undo_stack.push(MoveCommand(self, QPointF(self._delta))) |
252 |
self._delta.setX(0) |
253 |
self._delta.setY(0) |
254 |
|
255 |
super(QtImageViewerScene, self).keyReleaseEvent(event) |
256 |
|
257 |
def mousePressEvent(self, event: 'QGraphicsSceneMouseEvent') -> None: |
258 |
if self.selectedItems(): |
259 |
self._pressed_position = event.scenePos()
|
260 |
elif not self.selectedItems() and self.items(event.scenePos()): |
261 |
self._pressed_position = event.scenePos()
|
262 |
|
263 |
super(QtImageViewerScene, self).mousePressEvent(event) |
264 |
|
265 |
def mouseReleaseEvent(self, event: 'QGraphicsSceneMouseEvent') -> None: |
266 |
from MoveCommand import MoveCommand |
267 |
|
268 |
if self._pressed_position and self._pressed_position != event.scenePos() and self.selectedItems(): |
269 |
self._undo_stack.push(MoveCommand(self, event.scenePos() - self._pressed_position)) |
270 |
|
271 |
self._pressed_position = None |
272 |
super(QtImageViewerScene, self).mouseReleaseEvent(event) |
273 |
|
274 |
def clear(self): |
275 |
"""clear undo stack"""
|
276 |
self._undo_stack.clear()
|
277 |
super(QtImageViewerScene, self).clear() |
278 |
|
279 |
def drawForeground(self, painter: QPainter, rect: QRectF) -> None: |
280 |
"""draw foreground"""
|
281 |
if self.contours: |
282 |
pen = QPen(Qt.DotLine) |
283 |
pen.setColor(Qt.red) |
284 |
pen.setWidthF(2)
|
285 |
painter.setPen(pen) |
286 |
for contour in self.contours: |
287 |
path = QPainterPath() |
288 |
poly = QPolygonF() |
289 |
for pt in contour: |
290 |
poly.append(QPointF(pt[0], pt[1])) |
291 |
poly.append(poly[0])
|
292 |
path.addPolygon(poly) |
293 |
painter.fillPath(path, QBrush(Qt.darkRed if self.contour_color is None else self.contour_color, |
294 |
Qt.SolidPattern)) |
295 |
|
296 |
if self.circles: |
297 |
for circle in self.circles: |
298 |
painter.drawEllipse(circle[0], circle[1], circle[2], circle[2]) |
299 |
pass
|
300 |
|
301 |
"""draw guid line"""
|
302 |
if hasattr(self, 'coords') and self.guidesEnabled: |
303 |
painter.setClipRect(rect) |
304 |
painter.setPen(self._guidePen)
|
305 |
painter.drawLine(round(self.coords.x()), round(rect.top()), round(self.coords.x()), round(rect.bottom())) |
306 |
painter.drawLine(round(rect.left()), round(self.coords.y()), round(rect.right()), round(self.coords.y())) |