1 /*
2 Copyright 2006-2019 The QElectroTech Team
3 This file is part of QElectroTech.
4
5 QElectroTech is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
9
10 QElectroTech is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "partterminal.h"
19 #include "terminal.h"
20
21 /**
22 Constructeur
23 @param editor L'editeur d'element concerne
24 @param parent Le QGraphicsItem parent de cette borne
25 @param scene La scene sur laquelle figure cette borne
26 */
PartTerminal(QETElementEditor * editor,QGraphicsItem * parent)27 PartTerminal::PartTerminal(QETElementEditor *editor, QGraphicsItem *parent) :
28 CustomElementGraphicPart(editor, parent),
29 m_orientation(Qet::North)
30 {
31 updateSecondPoint();
32 setZValue(100000);
33 }
34
35 /// Destructeur
~PartTerminal()36 PartTerminal::~PartTerminal() {
37 }
38
39 /**
40 Importe les proprietes d'une borne depuis un element XML
41 @param xml_elmt Element XML a lire
42 */
fromXml(const QDomElement & xml_elmt)43 void PartTerminal::fromXml(const QDomElement &xml_elmt) {
44 // lit la position de la borne
45 qreal term_x = 0.0, term_y = 0.0;
46 QET::attributeIsAReal(xml_elmt, "x", &term_x);
47 QET::attributeIsAReal(xml_elmt, "y", &term_y);
48 setPos(QPointF(term_x, term_y));
49
50 // lit l'orientation de la borne
51 m_orientation = Qet::orientationFromString(xml_elmt.attribute("orientation"));
52
53 updateSecondPoint();
54 }
55
56 /**
57 Exporte la borne en XML
58 @param xml_document Document XML a utiliser pour creer l'element XML
59 @return un element XML decrivant la borne
60 */
toXml(QDomDocument & xml_document) const61 const QDomElement PartTerminal::toXml(QDomDocument &xml_document) const {
62 QDomElement xml_element = xml_document.createElement("terminal");
63
64 // ecrit la position de la borne
65 xml_element.setAttribute("x", QString("%1").arg(scenePos().x()));
66 xml_element.setAttribute("y", QString("%1").arg(scenePos().y()));
67
68
69 // ecrit l'orientation de la borne
70 xml_element.setAttribute("orientation", Qet::orientationToString(m_orientation));
71 // Write name and number to XML
72
73 return(xml_element);
74 }
75
76 /**
77 Dessine la borne
78 @param p QPainter a utiliser pour rendre le dessin
79 @param options Options pour affiner le rendu
80 @param widget Widget sur lequel le rendu est effectue
81 */
paint(QPainter * p,const QStyleOptionGraphicsItem * options,QWidget * widget)82 void PartTerminal::paint(QPainter *p, const QStyleOptionGraphicsItem *options, QWidget *widget) {
83 Q_UNUSED(widget);
84 p -> save();
85
86 // annulation des renderhints
87 p -> setRenderHint(QPainter::Antialiasing, false);
88 p -> setRenderHint(QPainter::TextAntialiasing, false);
89 p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
90
91 QPen t;
92 t.setWidthF(1.0);
93 t.setCosmetic(options && options -> levelOfDetail < 1.0);
94
95 // dessin de la borne en rouge
96 t.setColor(isSelected() ? Terminal::neutralColor : Qt::red);
97 p -> setPen(t);
98 p -> drawLine(QPointF(0.0, 0.0), second_point);
99
100 // dessin du point d'amarrage au conducteur en bleu
101 t.setColor(isSelected() ? Qt::red : Terminal::neutralColor);
102 p -> setPen(t);
103 p -> setBrush(Terminal::neutralColor);
104 p -> drawPoint(QPointF(0.0, 0.0));
105 p -> restore();
106
107 if (m_hovered)
108 drawShadowShape(p);
109 }
110
111 /**
112 * @brief PartTerminal::shape
113 * @return the shape of this item
114 */
shape() const115 QPainterPath PartTerminal::shape() const
116 {
117 QPainterPath shape;
118 shape.lineTo(second_point);
119
120 QPainterPathStroker pps;
121 pps.setWidth(1);
122
123 return (pps.createStroke(shape));
124 }
125
126 /**
127 * @brief PartTerminal::boundingRect
128 * @return the bounding rect of this item
129 */
boundingRect() const130 QRectF PartTerminal::boundingRect() const
131 {
132 QRectF br(QPointF(0, 0), second_point);
133 br = br.normalized();
134
135 qreal adjust = (SHADOWS_HEIGHT + 1) / 2;
136 br.adjust(-adjust, -adjust, adjust, adjust);
137 return(br);
138 }
139
140 /**
141 Definit l'orientation de la borne
142 @param ori la nouvelle orientation de la borne
143 */
setOrientation(Qet::Orientation ori)144 void PartTerminal::setOrientation(Qet::Orientation ori)
145 {
146 if (m_orientation == ori) return;
147 prepareGeometryChange();
148 m_orientation = ori;
149 updateSecondPoint();
150 emit orientationChanged();
151 }
152
153 /**
154 Met a jour la position du second point en fonction de la position et de
155 l'orientation de la borne.
156 */
updateSecondPoint()157 void PartTerminal::updateSecondPoint() {
158 qreal ts = 4.0; // terminal size
159 switch(m_orientation) {
160 case Qet::North: second_point = QPointF(0.0, ts); break;
161 case Qet::East : second_point = QPointF(-ts, 0.0); break;
162 case Qet::South: second_point = QPointF(0.0, -ts); break;
163 case Qet::West : second_point = QPointF(ts, 0.0); break;
164 }
165 }
166
167 /**
168 @return true si cette partie n'est pas pertinente et ne merite pas d'etre
169 conservee / enregistree.
170 Une borne est toujours pertinente ; cette fonction renvoie donc
171 toujours false
172 */
isUseless() const173 bool PartTerminal::isUseless() const {
174 return(false);
175 }
176
177 /**
178 @return the minimum, margin-less rectangle this part can fit into, in scene
179 coordinates. It is different from boundingRect() because it is not supposed
180 to imply any margin, and it is different from shape because it is a regular
181 rectangle, not a complex shape.
182 */
sceneGeometricRect() const183 QRectF PartTerminal::sceneGeometricRect() const {
184 return(sceneBoundingRect());
185 }
186
187 /**
188 Start the user-induced transformation, provided this primitive is contained
189 within the \a initial_selection_rect bounding rectangle.
190 */
startUserTransformation(const QRectF & initial_selection_rect)191 void PartTerminal::startUserTransformation(const QRectF &initial_selection_rect) {
192 Q_UNUSED(initial_selection_rect)
193 saved_position_ = scenePos();
194 }
195
196 /**
197 Handle the user-induced transformation from \a initial_selection_rect to \a new_selection_rect
198 */
handleUserTransformation(const QRectF & initial_selection_rect,const QRectF & new_selection_rect)199 void PartTerminal::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) {
200 QPointF mapped_point = mapPoints(initial_selection_rect, new_selection_rect, QList<QPointF>() << saved_position_).first();
201 setPos(mapped_point);
202 }
203