1 /*******************************************************************
2 
3 Part of the Fritzing project - http://fritzing.org
4 Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de
5 
6 Fritzing is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 Fritzing is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with Fritzing.  If not, see <http://www.gnu.org/licenses/>.
18 
19 ********************************************************************
20 
21 $Revision: 6954 $:
22 $Author: irascibl@gmail.com $:
23 $Date: 2013-04-05 10:22:00 +0200 (Fr, 05. Apr 2013) $
24 
25 ********************************************************************/
26 
27 #include "connector.h"
28 #include "connectorshared.h"
29 #include "connectoritem.h"
30 #include "../debugdialog.h"
31 #include "../model/modelpart.h"
32 #include "bus.h"
33 #include "../fsvgrenderer.h"
34 #include "ercdata.h"
35 
36 QHash <Connector::ConnectorType, QString > Connector::Names;
37 static const QList<SvgIdLayer *> EmptySvgIdLayerList;
38 
QuickHash(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)39 static inline int QuickHash(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
40 	return (1000 * viewID) + viewLayerID;
41 }
42 
Connector(ConnectorShared * connectorShared,ModelPart * modelPart)43 Connector::Connector( ConnectorShared * connectorShared, ModelPart * modelPart)
44 {
45 	m_modelPart = modelPart;
46 	m_connectorShared = connectorShared;
47 	m_bus = NULL;
48 }
49 
~Connector()50 Connector::~Connector() {
51 	//DebugDialog::debug(QString("deleting connector %1 %2").arg((long) this, 0, 16).arg(connectorSharedID()));
52 	foreach (ConnectorItem * connectorItem, m_connectorItems.values()) {
53 		connectorItem->clearConnector();
54 	}
55 }
56 
initNames()57 void Connector::initNames() {
58 	if (Names.count() == 0) {
59 		Names.insert(Connector::Male, "male");
60 		Names.insert(Connector::Female, "female");
61 		Names.insert(Connector::Wire, "wire");
62 		Names.insert(Connector::Pad, "pad");
63 	}
64 
65 }
66 
connectorTypeFromName(const QString & name)67 Connector::ConnectorType Connector::connectorTypeFromName(const QString & name) {
68 	QHashIterator<ConnectorType, QString> i(Names);
69     while (i.hasNext()) {
70         i.next();
71 		if (name.compare(i.value(), Qt::CaseInsensitive ) == 0) {
72 			return i.key();
73 		}
74     }
75 
76 	return Connector::Unknown;
77 }
78 
connectorNameFromType(ConnectorType type)79 const QString & Connector::connectorNameFromType(ConnectorType type) {
80 	return Names[type];
81 }
82 
connectorType() const83 Connector::ConnectorType Connector::connectorType() const {
84 	if (m_connectorShared != NULL) {
85 		return m_connectorShared->connectorType();
86 	}
87 
88 	return Connector::Unknown;
89 }
90 
connectorShared()91 ConnectorShared * Connector::connectorShared() {
92 	return m_connectorShared;
93 }
94 
addViewItem(ConnectorItem * item)95 void Connector::addViewItem(ConnectorItem * item) {
96 	//item->debugInfo(QString("add view item c:%1 ci:%2 b:%3").arg((long) this, 0, 16).arg((long) item, 0, 16).arg((long) m_bus.data(), 0, 16));
97 	m_connectorItems.insert(QuickHash(item->attachedToViewID(), item->attachedToViewLayerID()), item);
98 }
99 
removeViewItem(ConnectorItem * item)100 void Connector::removeViewItem(ConnectorItem * item) {
101 	//DebugDialog::debug(QString("remove view item c:%1 ci:%2 b:%3").arg((long) this, 0, 16).arg((long) item, 0, 16).arg((long) m_bus.data(), 0, 16));
102 	m_connectorItems.remove(QuickHash(item->attachedToViewID(), item->attachedToViewLayerID()));
103 }
104 
connectTo(Connector * connector)105 void Connector::connectTo(Connector * connector) {
106 
107 	if (this->modelPart() == NULL) {
108 		DebugDialog::debug("connecting bus connector 1");
109 	}
110 	else if (connector->modelPart() == NULL) {
111 		DebugDialog::debug("connecting bus connector 2");
112 	}
113 
114 	if (!m_toConnectors.contains(connector)) {
115 		m_toConnectors.append(connector);
116 	}
117 	if (!connector->m_toConnectors.contains(this)) {
118 		connector->m_toConnectors.append(this);
119 	}
120 }
121 
disconnectFrom(Connector * connector)122 void Connector::disconnectFrom(Connector * connector) {
123 	m_toConnectors.removeOne(connector);
124 	connector->m_toConnectors.removeOne(this);
125 }
126 
saveAsPart(QXmlStreamWriter & writer)127 void Connector::saveAsPart(QXmlStreamWriter & writer) {
128 	writer.writeStartElement("connector");
129 	writer.writeAttribute("id", connectorShared()->id());
130 	writer.writeAttribute("type", connectorShared()->connectorTypeString());
131 	writer.writeAttribute("name", connectorShared()->sharedName());
132 	writer.writeTextElement("description", connectorShared()->description());
133 	writer.writeTextElement("replacedby", connectorShared()->replacedby());
134 	writer.writeStartElement("views");
135 	QMultiHash<ViewLayer::ViewID,SvgIdLayer *> pins = m_connectorShared->pins();
136 	foreach (ViewLayer::ViewID currView, pins.uniqueKeys()) {
137 		writer.writeStartElement(ViewLayer::viewIDXmlName(currView));
138 		foreach (SvgIdLayer * svgIdLayer, pins.values(currView)) {
139 			writer.writeStartElement("p");
140 			writeLayerAttr(writer, svgIdLayer->m_svgViewLayerID);
141 			writeSvgIdAttr(writer, currView, svgIdLayer->m_svgId);
142 			writeTerminalIdAttr(writer, currView, svgIdLayer->m_terminalId);
143 			writer.writeEndElement();
144 		}
145 		writer.writeEndElement();
146 	}
147 	writer.writeEndElement();
148 	writer.writeEndElement();
149 }
150 
writeLayerAttr(QXmlStreamWriter & writer,ViewLayer::ViewLayerID viewLayerID)151 void Connector::writeLayerAttr(QXmlStreamWriter &writer, ViewLayer::ViewLayerID viewLayerID) {
152 	writer.writeAttribute("layer",ViewLayer::viewLayerXmlNameFromID(viewLayerID));
153 }
154 
writeSvgIdAttr(QXmlStreamWriter & writer,ViewLayer::ViewID view,QString connId)155 void Connector::writeSvgIdAttr(QXmlStreamWriter &writer, ViewLayer::ViewID view, QString connId) {
156 	Q_UNUSED(view);
157 	writer.writeAttribute("svgId",connId);
158 }
159 
writeTerminalIdAttr(QXmlStreamWriter & writer,ViewLayer::ViewID view,QString terminalId)160 void Connector::writeTerminalIdAttr(QXmlStreamWriter &writer, ViewLayer::ViewID view, QString terminalId) {
161         if((view == ViewLayer::BreadboardView || view == ViewLayer::SchematicView)
162             &&
163            (!terminalId.isNull() && !terminalId.isEmpty()) ) {
164 		writer.writeAttribute("terminalId",terminalId);
165 	} else {
166 		return;
167 	}
168 }
169 
toConnectors()170 const QList<Connector *> & Connector::toConnectors() {
171 	return m_toConnectors;
172 }
173 
connectorItemByViewLayerID(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)174 ConnectorItem * Connector::connectorItemByViewLayerID(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
175 	return m_connectorItems.value(QuickHash(viewID, viewLayerID), NULL);
176 }
177 
connectorItem(ViewLayer::ViewID viewID)178 ConnectorItem * Connector::connectorItem(ViewLayer::ViewID viewID) {
179 	foreach (ConnectorItem * connectorItem, m_connectorItems.values()) {
180         if (connectorItem->attachedToViewID() == viewID) return connectorItem;
181     }
182 
183     return NULL;
184 }
185 
connectionIsAllowed(Connector * that)186 bool Connector::connectionIsAllowed(Connector* that)
187 {
188 	Connector::ConnectorType thisConnectorType = connectorType();
189 	Connector::ConnectorType thatConnectorType = that->connectorType();
190 	if (thisConnectorType == Connector::Unknown) return false;
191 	if (thatConnectorType == Connector::Unknown) return false;		// unknowns are celebate
192 
193 	if (thisConnectorType == Connector::Wire) return true;
194 	if (thatConnectorType == Connector::Wire) return true;		// wires are bisexual
195 
196 	return (thisConnectorType != thatConnectorType);		// otherwise heterosexual
197 }
198 
connectorSharedID() const199 const QString & Connector::connectorSharedID() const {
200 	if (m_connectorShared == NULL) return ___emptyString___;
201 
202 	return m_connectorShared->id();
203 }
204 
connectorSharedName() const205 const QString & Connector::connectorSharedName() const {
206 	if (m_connectorShared == NULL) return ___emptyString___;
207 
208 	if (!m_connectorLocalName.isEmpty()) {
209 		return m_connectorLocalName;
210 	}
211 
212 	return m_connectorShared->sharedName();
213 }
214 
connectorSharedDescription() const215 const QString & Connector::connectorSharedDescription() const {
216 	if (m_connectorShared == NULL) return ___emptyString___;
217 
218 	return m_connectorShared->description();
219 }
220 
connectorSharedReplacedby() const221 const QString & Connector::connectorSharedReplacedby() const {
222 	if (m_connectorShared == NULL) return ___emptyString___;
223 
224 	return m_connectorShared->replacedby();
225 }
226 
connectorSharedErcData()227 ErcData * Connector::connectorSharedErcData() {
228 	if (m_connectorShared == NULL) return NULL;
229 
230 	return m_connectorShared->ercData();
231 }
232 
busID()233 const QString & Connector::busID() {
234 	if (m_bus == NULL) return ___emptyString___;
235 
236 	return m_bus->id();
237 }
238 
bus()239 Bus * Connector::bus() {
240 	return m_bus;
241 }
242 
setBus(Bus * bus)243 void Connector::setBus(Bus * bus) {
244 	m_bus = bus;
245 }
246 
unprocess(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)247 void Connector::unprocess(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
248 	SvgIdLayer * svgIdLayer = m_connectorShared->fullPinInfo(viewID, viewLayerID);
249 	if (svgIdLayer != NULL) {
250 		svgIdLayer->unprocess();
251 	}
252 }
253 
fullPinInfo(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)254 SvgIdLayer * Connector::fullPinInfo(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
255 	if (m_connectorShared == NULL) return NULL;
256 
257 	return m_connectorShared->fullPinInfo(viewID, viewLayerID);
258 }
259 
modelIndex()260 long Connector::modelIndex() {
261 	if (m_modelPart != NULL) return m_modelPart->modelIndex();
262 
263 	DebugDialog::debug(QString("saving bus connector item: how is this supposed to work?"));
264 	return 0;
265 }
266 
267 
modelPart()268 ModelPart * Connector::modelPart() {
269 	return m_modelPart;
270 }
271 
connectorItemCount()272 int Connector::connectorItemCount() {
273 	return m_connectorItems.count();
274 }
275 
viewItems()276 QList< QPointer<ConnectorItem> > Connector::viewItems() {
277 	return m_connectorItems.values();
278 }
279 
legID(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)280 const QString & Connector::legID(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
281 	if (m_connectorShared) return m_connectorShared->legID(viewID, viewLayerID);
282 
283 	return ___emptyString___;
284 }
285 
setConnectorLocalName(const QString & name)286 void Connector::setConnectorLocalName(const QString & name) {
287 	if (m_connectorShared != NULL && name.compare(m_connectorShared->sharedName()) == 0) {
288 		m_connectorLocalName.clear();
289 		return;
290 	}
291 
292 	m_connectorLocalName = name;
293 }
294 
connectorLocalName()295 const QString & Connector::connectorLocalName() {
296 	return m_connectorLocalName;
297 }
298 
svgIdLayers() const299 const QList<SvgIdLayer *> Connector::svgIdLayers() const {
300     if (m_connectorShared) return m_connectorShared->svgIdLayers();
301 
302     return EmptySvgIdLayerList;
303 }
304 
addPin(ViewLayer::ViewID viewID,const QString & svgId,ViewLayer::ViewLayerID viewLayerId,const QString & terminalId,const QString & legId,bool hybrid)305 void Connector::addPin(ViewLayer::ViewID viewID, const QString & svgId, ViewLayer::ViewLayerID viewLayerId, const QString & terminalId, const QString & legId, bool hybrid)
306 {
307     if (m_connectorShared) m_connectorShared->addPin(viewID, svgId, viewLayerId, terminalId, legId, hybrid);
308 }
309