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 #ifndef DIAGRAM_H
19 #define DIAGRAM_H
20 #include <QtWidgets>
21 #include <QtXml>
22 #include <QHash>
23 #include "bordertitleblock.h"
24 #include "conductorproperties.h"
25 #include "exportproperties.h"
26 #include "qgimanager.h"
27 #include "numerotationcontext.h"
28 #include "qetproject.h"
29 #include "properties/xrefproperties.h"
30 #include "elementsmover.h"
31 #include "elementtextsmover.h"
32 
33 class Conductor;
34 class CustomElement;
35 class DiagramContent;
36 class DiagramPosition;
37 class DiagramTextItem;
38 class Element;
39 class ElementsLocation;
40 class QETProject;
41 class Terminal;
42 class DiagramImageItem;
43 class DiagramEventInterface;
44 
45 /**
46 	This class represents an electric diagram. It manages its various child
47 	elements, conductors and texts and handles their graphic rendering.
48 */
49 class Diagram : public QGraphicsScene
50 {
51 	Q_OBJECT
52 
53 		// constructors, destructor
54 	public:
55 		Diagram(QETProject *project);
56 		~Diagram() override;
57 	private:
58 		Diagram(const Diagram &diagram);
59 
60 	// ATTRIBUTES
61 	public:
62 		/**
63 			Represents available options when rendering a particular diagram:
64 			 * EmptyBorder: display border only
65 			 * TitleBlock: display title block
66 			 * Columns: display columns
67 		*/
68 		enum BorderOptions { EmptyBorder, TitleBlock, Columns };
69 		/// Represents available option of Numerotation type.
70 		enum NumerotationType { Conductors };
71 		/// Default properties for new conductors
72 		ConductorProperties defaultConductorProperties;
73 		/// Diagram dimensions and title block
74 		BorderTitleBlock border_and_titleblock;
75 		/// abscissa grid step size
76 		static int xGrid;
77 		/// ordinate grid step size
78 		static int yGrid;
79 		/// Key grid x step size
80 		static int xKeyGrid;
81 		/// Key grid y step size
82 		static int yKeyGrid;
83         /// Key grid fine x step size
84         static int xKeyGridFine;
85         /// Key grid fine y step size
86         static int yKeyGridFine;
87 		/// margin around the diagram
88 		static const qreal margin;
89 		/// background color of diagram
90 
91 		static QColor background_color;
92 		/// Hash containing max values for folio sequential autonums in this diagram
93 		QHash <QString, QStringList> m_elmt_unitfolio_max;
94 		QHash <QString, QStringList> m_elmt_tenfolio_max;
95 		QHash <QString, QStringList> m_elmt_hundredfolio_max;
96 		/// Hash containing max values for folio sequential autonums in this diagram
97 		QHash <QString, QStringList> m_cnd_unitfolio_max;
98 		QHash <QString, QStringList> m_cnd_tenfolio_max;
99 		QHash <QString, QStringList> m_cnd_hundredfolio_max;
100 
101 	private:
102 		QGraphicsLineItem *conductor_setter_;
103 		ElementsMover     m_elements_mover;
104 		ElementTextsMover m_element_texts_mover;
105 		QGIManager        *qgi_manager_;
106 		QETProject        *m_project;
107 
108 		QDomDocument xml_document_;
109 
110 		qreal diagram_qet_version_;
111 
112 		bool draw_grid_;
113 		bool use_border_;
114 		bool draw_terminals_;
115 		bool draw_colored_conductors_;
116 
117 		QString m_conductors_autonum_name;
118 		DiagramEventInterface *m_event_interface;
119 
120 		bool m_freeze_new_elements;
121 		bool m_freeze_new_conductors_;
122 
123 	// METHODS
124 	protected:
125 		void drawBackground(QPainter *, const QRectF &) override;
126 
127 		void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override;
128 		void mousePressEvent       (QGraphicsSceneMouseEvent *event) override;
129 		void mouseMoveEvent        (QGraphicsSceneMouseEvent *event) override;
130 		void mouseReleaseEvent     (QGraphicsSceneMouseEvent *event) override;
131 		void wheelEvent            (QGraphicsSceneWheelEvent *event) override;
132 		void keyPressEvent   (QKeyEvent *event) override;
133 		void keyReleaseEvent (QKeyEvent *) override;
134 
135 	public:
136 		void setEventInterface (DiagramEventInterface *event_interface);
137 		void clearEventInterface();
138 
139 			//methods related to autonum
140 		QString conductorsAutonumName() const;
141 		void setConductorsAutonumName(const QString &name);
142 
143 		static bool clipboardMayContainDiagram();
144 
145 			// methods related to parent project
146 		QETProject *project() const;
147 		void        setProject(QETProject *);
148 		int         folioIndex() const;
149 		qreal       declaredQElectroTechVersion(bool = true) const;
showMe()150 		void        showMe() {emit showDiagram(this);}
151 		bool        isReadOnly() const;
152 
153 			// methods related to conductor creation
154 		void setConductor(bool);
155 		void setConductorStart (QPointF);
156 		void setConductorStop(QPointF);
157 		QList < QSet <Conductor *> > potentials();
158 
159 		// methods related to XML import/export
160 		QDomDocument toXml(bool = true);
161 		bool initFromXml(QDomElement &, QPointF = QPointF(), bool = true, DiagramContent * = nullptr);
162 		bool fromXml(QDomDocument &, QPointF = QPointF(), bool = true, DiagramContent * = nullptr);
163 		bool fromXml(QDomElement &, QPointF = QPointF(), bool = true, DiagramContent * = nullptr);
164 		void folioSequentialsToXml(QHash<QString, QStringList>*, QDomElement *, const QString&, const QString&, QDomDocument *);
165 		void folioSequentialsFromXml(const QDomElement&, QHash<QString, QStringList>*, const QString&, const QString&, const QString&, const QString&);
166 
167 		void refreshContents();
168 
169 			// methods related to graphics items addition/removal on the diagram
170 		virtual void addItem    (QGraphicsItem *item);
171 		virtual void removeItem (QGraphicsItem *item);
172 
173 			// methods related to graphics options
174 		ExportProperties applyProperties(const ExportProperties &);
175 		void setDisplayGrid(bool);
176 		bool displayGrid();
177 		void setUseBorder(bool);
178 		bool useBorder();
179 		void setBorderOptions(BorderOptions);
180 		BorderOptions borderOptions();
181 		DiagramPosition convertPosition(const QPointF &);
182 		static QPointF snapToGrid(const QPointF &p);
183 
184 		bool drawTerminals() const;
185 		void setDrawTerminals(bool);
186 		bool drawColoredConductors() const;
187 		void setDrawColoredConductors(bool);
188 
189 		QString title() const;
190 		bool toPaintDevice(QPaintDevice &, int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio);
191 		QSize imageSize() const;
192 
193 		bool isEmpty() const;
194 
195 		QList<Element *> elements() const;
196 		QList<Conductor *> conductors() const;
197 		QSet<Conductor *> selectedConductors() const;
198 		DiagramContent content() const;
199 		bool canRotateSelection() const;
200 		ElementsMover &elementsMover();
201 		ElementTextsMover &elementTextsMover();
202 		bool usesElement(const ElementsLocation &);
203 		bool usesTitleBlockTemplate(const QString &);
204 
205 		QUndoStack &undoStack();
206 		QGIManager &qgiManager();
207 
208 			//methods related to element label Update Policy
209 		void freezeElements(bool freeze);
210 		void unfreezeElements();
211 		void setFreezeNewElements(bool);
212 		bool freezeNewElements();
213 
214 			//methods related to conductor label Update Policy
215 		void freezeConductors(bool freeze);
216 		void setFreezeNewConductors(bool);
217 		bool freezeNewConductors();
218 
219 			//methods related to insertion and loading of folio sequential
220 		void insertFolioSeqHash (QHash<QString, QStringList> *hash, const QString& title, const QString& seq, NumerotationContext *nc);
221 		void loadFolioSeqHash (QHash<QString, QStringList> *hash, const QString& title, const QString& seq, NumerotationContext *nc);
222 		void changeZValue(QET::DepthOption option);
223 
224 	public slots:
225 		void adjustSceneRect ();
226 		void titleChanged(const QString &);
227 		void titleBlockTemplateChanged(const QString &);
228 		void titleBlockTemplateRemoved(const QString &, const QString & = QString());
229 		void setTitleBlockTemplate(const QString &);
230 		void updateLabels();
231 		void loadElmtFolioSeq();
232 		void loadCndFolioSeq();
233 
234 			// methods related to graphics items selection
235 		void selectAll();
236 		void deselectAll();
237 		void invertSelection();
238 
239 	signals:
240 		void showDiagram (Diagram *);
241 		void usedTitleBlockTemplateChanged(const QString &);
242 		void diagramTitleChanged(Diagram *, const QString &);
243 		void findElementRequired(const ElementsLocation &);		/// Signal emitted when users wish to locate an element from the diagram within elements collection
244 		void editElementRequired(const ElementsLocation &);		/// Signal emitted when users wish to edit an element from the diagram
245 		void diagramActivated();
246 };
Q_DECLARE_METATYPE(Diagram *)247 Q_DECLARE_METATYPE(Diagram *)
248 
249 /**
250 	Display or hide the conductor setter, i.e. a dashed conductor stub which appears when creating a conductor between two terminals.
251 	@param pf true pour ajouter le poseur de conducteur, false pour l'enlever
252 */
253 inline void Diagram::setConductor(bool adding) {
254 	if (adding) {
255 		if (!conductor_setter_ -> scene()) addItem(conductor_setter_);
256 	} else {
257 		if (conductor_setter_ -> scene()) removeItem(conductor_setter_);
258 	}
259 }
260 
261 /**
262 	Set the start point of the conductor setter.
263 	@param start the point (in scene coordinates) which the newly created
264 	conductor should start from.
265 */
setConductorStart(QPointF start)266 inline void Diagram::setConductorStart(QPointF start) {
267 	conductor_setter_ -> setLine(QLineF(start, conductor_setter_ -> line().p2()));
268 }
269 
270 /**
271 	Set the end point of the conductor setter.
272 	@param end the point (in scene coordinates) upon to which the newly created
273 	conductor should be drawn.
274 */
setConductorStop(QPointF end)275 inline void Diagram::setConductorStop(QPointF end) {
276 	conductor_setter_ -> setLine(QLineF(conductor_setter_ -> line().p1(), end));
277 }
278 
279 /**
280 	Set whether the diagram grid should be drawn.
281 	@param dg true to render the grid, false otherwise.
282 */
setDisplayGrid(bool dg)283 inline void Diagram::setDisplayGrid(bool dg) {
284 	draw_grid_ = dg;
285 }
286 
287 /**
288 	@return true if the grid is drawn, false otherwise.
289 */
displayGrid()290 inline bool Diagram::displayGrid() {
291 	return(draw_grid_);
292 }
293 
294 /**
295 	Set whether the diagram border (including rows/colums headers and the title
296 	block) should be rendered along with the diagram. When set to false, the size
297 	of the smallest rectangle containing all items is considered as the diagram
298 	size.
299 	@param ub true to take the border into account, false otherwise
300 */
setUseBorder(bool ub)301 inline void Diagram::setUseBorder(bool ub) {
302 	use_border_ = ub;
303 }
304 
305 /**
306 	@return true if the border is rendered and take into account, false
307 	otherwise.
308 */
useBorder()309 inline bool Diagram::useBorder() {
310 	return(use_border_);
311 }
312 
313 /**
314 	Set the rendering options for the diagram border (including rows/colums
315 	headers and the title block)
316 	@param bo Enabled options ORed together
317 	@see BorderOptions
318 */
setBorderOptions(Diagram::BorderOptions bo)319 inline void Diagram::setBorderOptions(Diagram::BorderOptions bo) {
320 	border_and_titleblock.displayBorder(!(bo & EmptyBorder));
321 	border_and_titleblock.displayColumns(bo & Columns);
322 	border_and_titleblock.displayTitleBlock(bo & TitleBlock);
323 }
324 
325 /**
326 	@return The rendering optios for the diagram border
327 	@see setBorderOptions
328 */
borderOptions()329 inline Diagram::BorderOptions Diagram::borderOptions() {
330 	BorderOptions options = EmptyBorder;
331 	if (border_and_titleblock.titleBlockIsDisplayed()) options = (BorderOptions)(options|TitleBlock);
332 	if (border_and_titleblock.columnsAreDisplayed()) options = (BorderOptions)(options|Columns);
333 	return(options);
334 }
335 
336 /// @return the diagram undo stack
undoStack()337 inline QUndoStack &Diagram::undoStack() {
338 	return *(project()->undoStack());
339 }
340 
341 /// @return the diagram graphics item manager
qgiManager()342 inline QGIManager &Diagram::qgiManager() {
343 	return(*qgi_manager_);
344 }
345 
346 /// @return true if terminals are rendered, false otherwise
drawTerminals()347 inline bool Diagram::drawTerminals() const {
348 	return(draw_terminals_);
349 }
350 
351 /// @return true if conductors colors are rendered, false otherwise.
drawColoredConductors()352 inline bool Diagram::drawColoredConductors() const {
353 	return(draw_colored_conductors_);
354 }
355 
356 #endif
357