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