개정판 2140125c
issue #1061: enable to resize symbol
Change-Id: I0b249a124f238b89d2bbfb51c457384a4c4ef557
HYTOS/HYTOS/Shapes/EngineeringStreamNoTextItem.py | ||
---|---|---|
7 | 7 |
|
8 | 8 |
try: |
9 | 9 |
from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
10 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QPainter, QPolygonF, QBrush, QPen, QTransform, QFont, QColor |
|
10 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QPainter, QPolygonF, QBrush, QPen, QTransform, QFont, QColor, \ |
|
11 |
QTextOption |
|
11 | 12 |
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, \ |
12 |
QGraphicsTextItem |
|
13 |
QGraphicsTextItem, QGraphicsPathItem
|
|
13 | 14 |
except ImportError: |
14 | 15 |
try: |
15 | 16 |
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
... | ... | |
21 | 22 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
22 | 23 |
|
23 | 24 |
|
25 |
class QEngineeringStreamNoBorderItem(QGraphicsPathItem): |
|
26 |
selected_change = pyqtSignal(QGraphicsItem) |
|
27 |
HIGHLIGHT = '#BC4438' |
|
28 |
|
|
29 |
def __init__(self, parent): |
|
30 |
QGraphicsPathItem.__init__(self, parent=parent) |
|
31 |
|
|
32 |
self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable | |
|
33 |
QGraphicsItem.ItemSendsGeometryChanges | QGraphicsItem.ItemClipsToShape) |
|
34 |
self.setAcceptHoverEvents(True) |
|
35 |
self.setAcceptTouchEvents(True) |
|
36 |
|
|
37 |
def update_border(self): |
|
38 |
"""create a border""" |
|
39 |
import math |
|
40 |
|
|
41 |
path = QPainterPath() |
|
42 |
|
|
43 |
rect = self.parentItem().boundingRect() |
|
44 |
n, r, s = 4, rect.width() * 0.5 if rect.width() > rect.height() else rect.height() * 0.5, 0 |
|
45 |
|
|
46 |
polygon = QPolygonF() |
|
47 |
w = 360 / n # angle per step |
|
48 |
for i in range(n): # add the points of polygon |
|
49 |
t = w * i + s |
|
50 |
x = r * math.cos(math.radians(t)) |
|
51 |
y = r * math.sin(math.radians(t)) |
|
52 |
polygon.append(QPointF(rect.width() * 0.5 + x, rect.height() * 0.5 + y)) |
|
53 |
polygon.append(polygon[0]) |
|
54 |
path.addPolygon(polygon) |
|
55 |
|
|
56 |
self.setPath(path) |
|
57 |
|
|
58 |
def mouseDoubleClickEvent(self, event): |
|
59 |
"""call parent's mouseDoubleClickEvent""" |
|
60 |
self.parentItem().mouseDoubleClickEvent(event) |
|
61 |
|
|
62 |
|
|
24 | 63 |
class QEngineeringStreamNoTextItem(QGraphicsTextItem): |
25 | 64 |
""" This is engineering stream no text item class """ |
26 | 65 |
|
27 | 66 |
def __init__(self, text, parent=None): |
28 |
import uuid |
|
29 |
|
|
30 | 67 |
QGraphicsTextItem.__init__(self, text, parent) |
31 | 68 |
doc = self.document() |
32 | 69 |
option = doc.defaultTextOption() |
33 | 70 |
option.setAlignment(Qt.AlignCenter) |
71 |
option.setWrapMode(QTextOption.WordWrap) |
|
34 | 72 |
doc.setDefaultTextOption(option) |
73 |
doc.contentsChanged.connect(self.update_border) |
|
35 | 74 |
self.type = 'STREAM NO' |
36 | 75 |
|
37 | 76 |
font = QFont('Arial', 15) |
38 | 77 |
font.setPointSizeF(4) |
39 | 78 |
self.setFont(font) |
40 | 79 |
|
80 |
self.borders = [] |
|
81 |
|
|
82 |
@property |
|
83 |
def border_item(self): |
|
84 |
if self.toPlainText() and not self.borders: |
|
85 |
self.borders.append(QEngineeringStreamNoBorderItem(self)) |
|
86 |
|
|
87 |
return self.borders[0] if self.borders else None |
|
88 |
|
|
41 | 89 |
def highlight(self, flag): |
42 | 90 |
if flag: |
43 | 91 |
self.setDefaultTextColor(QColor(QEngineeringAbstractItem.HOVER_COLOR)) |
... | ... | |
46 | 94 |
|
47 | 95 |
self.update() |
48 | 96 |
|
97 |
""" |
|
49 | 98 |
def paint(self, painter, option, widget): |
50 |
""" override paint method """
|
|
99 |
#override paint method
|
|
51 | 100 |
|
52 | 101 |
rect = self.boundingRect() |
53 | 102 |
r = rect.width()*0.5 if rect.width() > rect.height() else rect.height()*0.5 |
... | ... | |
68 | 117 |
polygon.append(QPointF(rect.width() * 0.5 + x, rect.height() * 0.5 + y)) |
69 | 118 |
|
70 | 119 |
return polygon |
120 |
""" |
|
71 | 121 |
|
72 | 122 |
def set_font_size(self, size): |
73 | 123 |
"""set font size""" |
... | ... | |
76 | 126 |
_font.setPointSizeF(float(size)) |
77 | 127 |
self.setFont(_font) |
78 | 128 |
|
129 |
self.update_border() |
|
130 |
|
|
131 |
def update_border(self): |
|
132 |
"""update border""" |
|
133 |
if self.border_item: |
|
134 |
self.border_item.update_border() |
|
135 |
|
|
79 | 136 |
def mouseDoubleClickEvent(self, event): |
80 | 137 |
"""call parent's mouseDoubleClickEvent""" |
81 | 138 |
self.parentItem().mouseDoubleClickEvent(event) |
HYTOS/HYTOS/Shapes/Resizer.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
""" This is MainWindow module """ |
|
3 |
|
|
4 |
import sys |
|
5 |
import os |
|
6 |
import math |
|
7 |
from PyQt5.QtGui import * |
|
8 |
from PyQt5.QtCore import * |
|
9 |
from PyQt5.QtSvg import * |
|
10 |
from PyQt5.QtWidgets import (QApplication, QGraphicsItem, QGraphicsObject) |
|
11 |
|
|
12 |
from SingletonInstance import SingletonInstane |
|
13 |
|
|
14 |
|
|
15 |
class Resizer(QGraphicsObject): |
|
16 |
resize_signal = pyqtSignal(QRectF) |
|
17 |
|
|
18 |
def __init__(self, parent=None): |
|
19 |
super().__init__(parent) |
|
20 |
self.setFlags( |
|
21 |
QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemSendsGeometryChanges) |
|
22 |
self.setAcceptHoverEvents(True) |
|
23 |
self.setCursor(Qt.SizeFDiagCursor) |
|
24 |
self.rect = QRectF(0, 0, 10, 10) |
|
25 |
self.setZValue(200) |
|
26 |
|
|
27 |
def boundingRect(self): |
|
28 |
return self.rect |
|
29 |
|
|
30 |
def paint(self, painter, option, widget=None): |
|
31 |
if self.isSelected(): |
|
32 |
pen = QPen() |
|
33 |
pen.setStyle(Qt.DotLine) |
|
34 |
pen.setWidthF(3) |
|
35 |
painter.setPen(pen) |
|
36 |
painter.setRenderHint(QPainter.Antialiasing) |
|
37 |
painter.drawEllipse(self.rect) |
|
38 |
self.update() |
|
39 |
|
|
40 |
def hoverEnterEvent(self, event): |
|
41 |
self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) |
|
42 |
|
|
43 |
def hoverLeaveEvent(self, event): |
|
44 |
self.setFlag(QGraphicsItem.ItemIgnoresTransformations, False) |
|
45 |
self.setSelected(False) |
|
46 |
#self.setPos(self._connected.sceneBoundingRect().bottomRight()) |
|
47 |
#self.hide() |
|
48 |
|
|
49 |
def itemChange(self, change, value): |
|
50 |
#self.prepareGeometryChange() |
|
51 |
if change == QGraphicsItem.ItemPositionHasChanged: |
|
52 |
if self.isSelected(): |
|
53 |
pt = self.parentItem().boundingRect().topLeft() |
|
54 |
_value = self.pos() |
|
55 |
x, y = min(_value.x(), pt.x()), min(_value.y(), pt.y()) |
|
56 |
dx, dy = abs(_value.x() - pt.x()), abs(_value.y() - pt.y()) |
|
57 |
self.resize_signal.emit(QRectF(x, y, dx, dy)) |
|
58 |
|
|
59 |
return super(Resizer, self).itemChange(change, value) |
HYTOS/HYTOS/Shapes/SymbolSvgItem.py | ||
---|---|---|
187 | 187 |
try: |
188 | 188 |
rect = self.boundingRect() |
189 | 189 |
if rect.isValid(): |
190 |
self.resetTransform() |
|
191 |
self.setPos(change.topLeft()) |
|
192 |
scale = min([change.width() / rect.width(), change.height() / rect.height()])
|
|
190 |
#self.resetTransform()
|
|
191 |
#self.setPos(change.topLeft())
|
|
192 |
scale = max(min([change.width() / rect.width(), change.height() / rect.height()]), 1)
|
|
193 | 193 |
# scale the item |
194 | 194 |
self.setScale(scale) |
195 | 195 |
|
... | ... | |
220 | 220 |
values = ['?', '?', '?', '?', '?', '?', '?', '?'] |
221 | 221 |
param = [str(self.uid), str(self.dbUid), str(self.tag_no) if self.tag_no is not None else self.tag_no, |
222 | 222 |
self.index, rect.left(), rect.top(), |
223 |
str(self.angle), self.transform().m11()]
|
|
223 |
str(self.angle), self.scale()]
|
|
224 | 224 |
sql = 'insert or replace into Components({}) values({})'.format(','.join(cols), ','.join(values)) |
225 | 225 |
res.append((sql, tuple(param))) |
226 | 226 |
|
... | ... | |
268 | 268 |
self._scale = scale |
269 | 269 |
self.loc = loc |
270 | 270 |
|
271 |
docData = AppDocData.instance()
|
|
271 |
app_doc_data = AppDocData.instance()
|
|
272 | 272 |
if dbUid is None: |
273 |
symbolInfo = docData.getSymbolByQuery('name', name)
|
|
273 |
symbolInfo = app_doc_data.getSymbolByQuery('name', name)
|
|
274 | 274 |
else: |
275 |
symbolInfo = docData.getSymbolByQuery('UID', dbUid)
|
|
275 |
symbolInfo = app_doc_data.getSymbolByQuery('UID', dbUid)
|
|
276 | 276 |
|
277 | 277 |
self.dbUid = symbolInfo.uid |
278 | 278 |
self.category = symbolInfo.sCategory |
... | ... | |
1346 | 1346 |
|
1347 | 1347 |
def itemChange(self, change, value): |
1348 | 1348 |
""" call signals when item's position is changed """ |
1349 |
if change == QGraphicsItem.ItemPositionHasChanged: |
|
1349 |
if change == QGraphicsItem.ItemPositionHasChanged or change == QGraphicsItem.ItemScaleHasChanged:
|
|
1350 | 1350 |
self.transfer.on_pos_changed.emit(self) |
1351 |
""" |
|
1352 |
for conn in self.connectors: |
|
1353 |
if conn.conectedItem: |
|
1354 |
line = conn.connectedItem.parentItem() |
|
1355 |
start = line.connectors[-1].connectedItem.center() |
|
1356 |
end = line.connectors[-2].connectedItem.center() |
|
1357 |
dx, dy = end[-1] - start[0], end[1] - start[1] |
|
1358 |
""" |
|
1359 |
|
|
1360 | 1351 |
self.scene().contents_changed.emit() |
1361 | 1352 |
return value |
1362 | 1353 |
|
1363 | 1354 |
return super().itemChange(change, value) |
1364 | 1355 |
|
1365 | 1356 |
''' |
1366 |
@brief Check Overlap |
|
1367 |
@author kyouho |
|
1368 |
@date 18.07.17 |
|
1369 |
''' |
|
1370 |
|
|
1371 |
def isOverlapItemAndPoint(self, item, point): |
|
1372 |
x = point.x() |
|
1373 |
y = point.y() |
|
1374 |
loc = item.loc |
|
1375 |
size = item.size |
|
1376 |
|
|
1377 |
if loc[0] <= x and loc[0] + size[0] >= x and loc[1] <= y and loc[1] + size[1] >= y: |
|
1378 |
return True |
|
1379 |
else: |
|
1380 |
return False |
|
1381 |
|
|
1382 |
''' |
|
1383 | 1357 |
@brief remove item when user press delete key |
1384 | 1358 |
@author humkyung |
1385 | 1359 |
@date 2018.04.23 |
... | ... | |
1396 | 1370 |
self.mouseDoubleClickEvent(event) |
1397 | 1371 |
|
1398 | 1372 |
''' |
1399 |
@brief connect attribute |
|
1400 |
@author humkyung |
|
1401 |
@date 2018.05.02 |
|
1402 |
@history humkyung 2018.05.09 append only nearest size attribute |
|
1403 |
''' |
|
1404 |
|
|
1405 |
def connectAttribute(self, attributes, clear=True): |
|
1406 |
import math |
|
1407 |
|
|
1408 |
try: |
|
1409 |
if clear: |
|
1410 |
self.clear_attr_and_assoc_item() |
|
1411 |
|
|
1412 |
configs = AppDocData.instance().getConfigs('Range', 'Detection Ratio') |
|
1413 |
ratio = float(configs[0].value) if 1 == len(configs) else 1.5 |
|
1414 |
|
|
1415 |
dist = max(self.sceneBoundingRect().height(), self.sceneBoundingRect().width()) * ratio |
|
1416 |
center = self.sceneBoundingRect().center() |
|
1417 |
|
|
1418 |
minDist = None |
|
1419 |
selected = None |
|
1420 |
for attr in attributes: |
|
1421 |
# size text and operation code text will find onwer themselves in findowner method |
|
1422 |
if False: # type(attr) is QEngineeringSizeTextItem or type(attr) is QEngineeringValveOperCodeTextItem: |
|
1423 |
dx = attr.center().x() - center.x() |
|
1424 |
dy = attr.center().y() - center.y() |
|
1425 |
length = math.sqrt(dx * dx + dy * dy) |
|
1426 |
if (length < dist) and (minDist is None or length < minDist): |
|
1427 |
minDist = length |
|
1428 |
selected = attr |
|
1429 |
elif type(attr) is QEngineeringInstrumentItem: |
|
1430 |
if not attr.is_connected: |
|
1431 |
dx = attr.center().x() - center.x() |
|
1432 |
dy = attr.center().y() - center.y() |
|
1433 |
if math.sqrt(dx * dx + dy * dy) < dist: |
|
1434 |
if self.add_assoc_item(attr): |
|
1435 |
attr.owner = self |
|
1436 |
|
|
1437 |
if selected is not None: |
|
1438 |
if self.add_assoc_item(selected): |
|
1439 |
selected.owner = self |
|
1440 |
|
|
1441 |
except Exception as ex: |
|
1442 |
from App import App |
|
1443 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
1444 |
sys.exc_info()[-1].tb_lineno) |
|
1445 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
1446 |
|
|
1447 |
''' |
|
1448 | 1373 |
@brief Double click event, Show rotate symbol dialog |
1449 | 1374 |
@author euisung |
1450 | 1375 |
@date 2019.04.16 |
... | ... | |
2030 | 1955 |
|
2031 | 1956 |
def addSvgItemToScene(self, scene): |
2032 | 1957 |
"""add svg item to scene""" |
2033 |
transform = QTransform() |
|
1958 |
self.setScale(self._scale) |
|
1959 |
# scale down for label |
|
1960 |
for conn, label in self.desc_labels.items(): |
|
1961 |
label.setScale(1 / self._scale) |
|
1962 |
# up to here |
|
2034 | 1963 |
|
1964 |
transform = QTransform() |
|
2035 | 1965 |
transform.translate(self.loc[0] + self.symbolOrigin[0], self.loc[1] + self.symbolOrigin[1]) |
2036 | 1966 |
transform.rotateRadians(-self.angle) |
2037 | 1967 |
transform.translate(-self.symbolOrigin[0], -self.symbolOrigin[1]) |
2038 |
transform.scale(self._scale, self._scale) |
|
2039 |
|
|
2040 | 1968 |
self.setTransform(transform) |
2041 | 1969 |
scene.addItem(self) |
2042 | 1970 |
|
내보내기 Unified diff