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 "conductorcreator.h"
19 #include "diagram.h"
20 #include "qgraphicsitem.h"
21 #include "terminal.h"
22 #include "conductor.h"
23 #include "potentialselectordialog.h"
24 #include "diagramcommands.h"
25 #include "conductorautonumerotation.h"
26 #include "element.h"
27 
28 #include <QPolygonF>
29 
30 /**
31  * @brief ConductorCreator::ConductorCreator
32  * Create an electrical potential between all terminals of @terminals_list.
33  * the terminals of the list must be in the same diagram.
34  * @param terminals_list
35  */
ConductorCreator(Diagram * d,QList<Terminal * > terminals_list)36 ConductorCreator::ConductorCreator(Diagram *d, QList<Terminal *> terminals_list) :
37 	m_terminals_list(terminals_list)
38 {
39 	if (m_terminals_list.size() <= 1) {
40 		return;
41 	}
42 	m_properties = m_terminals_list.first()->diagram()->defaultConductorProperties;
43 
44 	setUpPropertieToUse();
45 	Terminal *hub_terminal = hubTerminal();
46 
47 	d->undoStack().beginMacro(QObject::tr("Création de conducteurs"));
48 
49 	QList<Conductor *> c_list;
50 	for (Terminal *t : m_terminals_list)
51 	{
52 		if (t == hub_terminal) {
53 			continue;
54 		}
55 
56 		Conductor *cond = new Conductor(hub_terminal, t);
57 		cond->setProperties(m_properties);
58 		cond->setSequenceNum(m_sequential_number);
59 		d->undoStack().push(new AddItemCommand<Conductor *>(cond, d));
60 
61 		c_list.append(cond);
62 	}
63 	d->undoStack().endMacro();
64 
65 	for(Conductor *c : c_list) {
66 		c->refreshText();
67 	}
68 }
69 
70 /**
71  * @brief ConductorCreator::create
72  * Create an electrical potential between the terminals of the diagram d, contained in the polygon
73  * @param d
74  * @param polygon : polygon in diagram coordinate
75  */
create(Diagram * d,const QPolygonF & polygon)76 void ConductorCreator::create(Diagram *d, const QPolygonF &polygon)
77 {
78 	QList<Terminal *> t_list;
79 
80 	for (QGraphicsItem *item : d->items(polygon))
81 	{
82 		if (item->type() == Terminal::Type) {
83 			t_list.append(qgraphicsitem_cast<Terminal *>(item));
84 		}
85 	}
86 
87 	if (t_list.size() <= 1) {
88 		return;
89 	} else {
90 		ConductorCreator cc(d, t_list);
91 	}
92 }
93 
94 /**
95  * @brief ConductorCreator::propertieToUse
96  * @return the conductor properties to use for the new conductors.
97  */
setUpPropertieToUse()98 void ConductorCreator::setUpPropertieToUse()
99 {
100 	QList<Conductor *> potentials = existingPotential();
101 
102 		//There is an existing potential
103 		//we get one of them
104 	if (!potentials.isEmpty())
105 	{
106 		if (potentials.size() >= 2)
107 		{
108 			QList <ConductorProperties> cp_list;
109 			for(Conductor *c : potentials) {
110 				cp_list.append(c->properties());
111 			}
112 
113 			m_properties = PotentialSelectorDialog::chosenProperties(cp_list);
114 			for (Conductor *c : potentials) {
115 				if (c->properties() == m_properties) {
116 					m_sequential_number = c->sequenceNum();
117 				}
118 			}
119 		}
120 		else if (potentials.size() == 1)
121 		{
122 			m_properties = potentials.first()->properties();
123 			m_sequential_number = potentials.first()->sequenceNum();
124 		}
125 		return;
126 	}
127 
128 		//get a new properties
129 	ConductorAutoNumerotation::newProperties(m_terminals_list.first()->diagram(), m_properties, m_sequential_number);
130 }
131 
132 /**
133  * @brief ConductorCreator::existingPotential
134  * Return the list of existing potential of
135  * the terminal list
136  * @return
137  */
existingPotential()138 QList<Conductor *> ConductorCreator::existingPotential()
139 {
140 	QList<Conductor *> c_list;
141 	QList<Terminal *> t_exclude;
142 
143 	for (Terminal *t : m_terminals_list)
144 	{
145 		if (t_exclude.contains(t)) {
146 			continue;
147 		}
148 
149 		if (!t->conductors().isEmpty())
150 		{
151 			c_list.append(t->conductors().first());
152 
153 				//We must to check m_terminals_list contain a terminal
154 				//in the same potential of c, and if true, exclude this terminal from the search.
155 			for (Conductor *c : t->conductors().first()->relatedPotentialConductors(false))
156 			{
157 				if (m_terminals_list.contains(c->terminal1)) {
158 					t_exclude.append(c->terminal1);
159 				} else if (m_terminals_list.contains(c->terminal2)) {
160 					t_exclude.append(c->terminal2);
161 				}
162 			}
163 		}
164 		else if (t->parentElement()->linkType() & Element::AllReport && !t->parentElement()->isFree())
165 		{
166 			Element *linked_report = t->parentElement()->linkedElements().first();
167 			if (!linked_report->conductors().isEmpty()) {
168 				c_list.append(linked_report->conductors().first());
169 			}
170 		}
171 	}
172 
173 	return c_list;
174 }
175 
176 /**
177  * @brief ConductorCreator::hubTerminal
178  * @return
179  */
hubTerminal()180 Terminal *ConductorCreator::hubTerminal()
181 {
182 	Terminal *hub_terminal = m_terminals_list.first();
183 
184 	for (Terminal *tt : m_terminals_list)
185 	{
186 		if (tt->scenePos().x() < hub_terminal->scenePos().x()) {
187 			hub_terminal = tt;
188 		} else if (tt->scenePos().x() == hub_terminal->scenePos().x()) {
189 			if (tt->scenePos().y() < hub_terminal->scenePos().y()) {
190 				hub_terminal = tt;
191 			}
192 		}
193 	}
194 
195 	return  hub_terminal;
196 }
197