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: 6984 $:
22 $Author: irascibl@gmail.com $:
23 $Date: 2013-04-22 23:44:56 +0200 (Mo, 22. Apr 2013) $
24 
25 ********************************************************************/
26 
27 #include "tracewire.h"
28 #include "../sketch/infographicsview.h"
29 #include "../connectors/connectoritem.h"
30 #include "../utils/focusoutcombobox.h"
31 
32 
33 #include <QComboBox>
34 
35 const int TraceWire::MinTraceWidthMils = 8;
36 const int TraceWire::MaxTraceWidthMils = 128;
37 
38 /////////////////////////////////////////////////////////
39 
TraceWire(ModelPart * modelPart,ViewLayer::ViewID viewID,const ViewGeometry & viewGeometry,long id,QMenu * itemMenu)40 TraceWire::TraceWire( ModelPart * modelPart, ViewLayer::ViewID viewID,  const ViewGeometry & viewGeometry, long id, QMenu * itemMenu  )
41 	: ClipableWire(modelPart, viewID,  viewGeometry,  id, itemMenu, true)
42 {
43 	m_canChainMultiple = true;
44 	m_wireDirection = TraceWire::NoDirection;
45 }
46 
47 
~TraceWire()48 TraceWire::~TraceWire()
49 {
50 }
51 
createWidthComboBox(double m,QWidget * parent)52 QComboBox * TraceWire::createWidthComboBox(double m, QWidget * parent)
53 {
54 	QComboBox * comboBox = new FocusOutComboBox(parent);  // new QComboBox(parent);
55 	comboBox->setEditable(true);
56 	QIntValidator * intValidator = new QIntValidator(comboBox);
57 	intValidator->setRange(MinTraceWidthMils, MaxTraceWidthMils);
58 	comboBox->setValidator(intValidator);
59     comboBox->setToolTip(tr("Select from the dropdown, or type in any value from %1 to %2").arg(MinTraceWidthMils).arg(MaxTraceWidthMils));
60 
61 	int ix = 0;
62 	if (!Wire::widths.contains(m)) {
63 		Wire::widths.append(m);
64 		qSort(Wire::widths.begin(), Wire::widths.end());
65 	}
66 	foreach(long widthValue, Wire::widths) {
67 		QString widthName = Wire::widthTrans.value(widthValue, "");
68 		QVariant val((int) widthValue);
69 		comboBox->addItem(widthName.isEmpty() ? QString::number(widthValue) : widthName, val);
70 		if (qAbs(m - widthValue) < .01) {
71 			comboBox->setCurrentIndex(ix);
72 		}
73 		ix++;
74 	}
75 
76 	return comboBox;
77 
78 }
79 
80 
collectExtraInfo(QWidget * parent,const QString & family,const QString & prop,const QString & value,bool swappingEnabled,QString & returnProp,QString & returnValue,QWidget * & returnWidget,bool & hide)81 bool TraceWire::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide)
82 {
83 	if (prop.compare("width", Qt::CaseInsensitive) == 0) {
84         if (viewID() != ViewLayer::PCBView) {
85             // only in pcb view for now
86             hide = true;
87             return false;
88         }
89 
90 		returnProp = tr("width");
91 		QComboBox * comboBox = createWidthComboBox(mils(), parent);
92 		comboBox->setEnabled(swappingEnabled);
93 		comboBox->setObjectName("infoViewComboBox");
94 
95 		connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(widthEntry(const QString &)));
96 		returnWidget = comboBox;
97 		returnValue = comboBox->currentText();
98 
99 		return true;
100 	}
101 
102 	bool result =  ClipableWire::collectExtraInfo(parent, family, prop, value, swappingEnabled, returnProp, returnValue, returnWidget, hide);
103     if (prop.compare("layer") == 0 && returnWidget != NULL) {
104         bool disabled = !canSwitchLayers();
105         if (!disabled) {
106             InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
107             if (infoGraphicsView == NULL || infoGraphicsView->boardLayers() == 1) disabled = true;
108         }
109         returnWidget->setDisabled(disabled);
110     }
111 
112     return result;
113 
114 
115     return result;
116 }
117 
118 
widthEntry(const QString & text)119 void TraceWire::widthEntry(const QString & text) {
120 
121 	int w = widthEntry(text, sender());
122 	if (w == 0) return;
123 
124 	InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
125 	if (infoGraphicsView != NULL) {
126 		infoGraphicsView->changeWireWidthMils(QString::number(w));
127 	}
128 }
129 
widthEntry(const QString & text,QObject * sender)130 int TraceWire::widthEntry(const QString & text, QObject * sender) {
131 
132 	QComboBox * comboBox = qobject_cast<QComboBox *>(sender);
133 	if (comboBox == NULL) return 0;
134 
135 	int w = comboBox->itemData(comboBox->currentIndex()).toInt();
136 	if (w == 0) {
137 		// user typed in a number
138 		w = text.toInt();
139 	}
140 	if (!Wire::widths.contains(w)) {
141 		Wire::widths.append(w);
142 		qSort(Wire::widths.begin(), Wire::widths.end());
143 	}
144 
145 	return w;
146 }
147 
setColorFromElement(QDomElement & element)148 void TraceWire::setColorFromElement(QDomElement & element) {
149 	switch (m_viewLayerID) {
150 		case ViewLayer::Copper0Trace:
151 			element.setAttribute("color", ViewLayer::Copper0WireColor);
152 			break;
153 		case ViewLayer::Copper1Trace:
154 			element.setAttribute("color", ViewLayer::Copper1WireColor);
155 			break;
156 		case ViewLayer::SchematicTrace:
157 			//element.setAttribute("color", "#000000");
158 		default:
159 			break;
160 	}
161 
162 	Wire::setColorFromElement(element);
163 }
164 
canSwitchLayers()165 bool TraceWire::canSwitchLayers() {
166 	QList<Wire *> wires;
167 	QList<ConnectorItem *> ends;
168 	collectChained(wires, ends);
169 
170 	foreach (ConnectorItem * end, ends) {
171 		if (end->getCrossLayerConnectorItem() == NULL) return false;
172 	}
173 
174 	return true;
175 }
176 
setWireDirection(TraceWire::WireDirection wireDirection)177 void TraceWire::setWireDirection(TraceWire::WireDirection wireDirection) {
178 	m_wireDirection = wireDirection;
179 }
180 
wireDirection()181 TraceWire::WireDirection TraceWire::wireDirection() {
182 	return m_wireDirection;
183 }
184 
getTrace(ConnectorItem * connectorItem)185 TraceWire * TraceWire::getTrace(ConnectorItem * connectorItem)
186 {
187 	return qobject_cast<TraceWire *>(connectorItem->attachedTo());
188 }
189 
setSchematic(bool schematic)190 void TraceWire::setSchematic(bool schematic) {
191 	m_viewGeometry.setSchematicTrace(schematic);
192 }
193 
prepareProps(ModelPart * modelPart,bool wantDebug,QStringList & keys)194 QHash<QString, QString> TraceWire::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys)
195 {
196     QHash<QString, QString> props = ClipableWire::prepareProps(modelPart, wantDebug, keys);
197 
198     if (m_viewID != ViewLayer::PCBView) return props;
199     if (!m_viewGeometry.getPCBTrace()) return props;
200 
201     keys.append("layer");
202     props.insert("layer", ViewLayer::topLayers().contains(m_viewLayerID) ? "top" : "bottom");
203     return props;
204 }
205 
collectValues(const QString & family,const QString & prop,QString & value)206 QStringList TraceWire::collectValues(const QString & family, const QString & prop, QString & value) {
207     if (prop.compare("layer") == 0) {
208         QStringList values = ClipableWire::collectValues(family, prop, value);
209         if (values.count() == 0) {
210             values << TranslatedPropertyNames.value("bottom") << TranslatedPropertyNames.value("top");
211             if (ViewLayer::bottomLayers().contains(m_viewLayerID)) {
212                 value = values.at(0);
213             }
214             else {
215                 value = values.at(1);
216             }
217         }
218         return values;
219     }
220 
221     return ClipableWire::collectValues(family, prop, value);
222 }
223