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: 6904 $:
22 $Author: irascibl@gmail.com $:
23 $Date: 2013-02-26 16:26:03 +0100 (Di, 26. Feb 2013) $
24 
25 ********************************************************************/
26 
27 #include <QHBoxLayout>
28 #include <QVBoxLayout>
29 #include <QFormLayout>
30 #include <QLineEdit>
31 #include <QRadioButton>
32 #include <QMessageBox>
33 #include <QMutexLocker>
34 #include <QApplication>
35 
36 #include "peconnectorsview.h"
37 #include "peutils.h"
38 #include "hashpopulatewidget.h"
39 #include "../debugdialog.h"
40 
41 //////////////////////////////////////
42 
PEConnectorsView(QWidget * parent)43 PEConnectorsView::PEConnectorsView(QWidget * parent) : QFrame(parent)
44 {
45 	m_connectorCount = 0;
46 
47     this -> setObjectName("peConnectors");
48     /*
49     QFile styleSheet(":/resources/styles/newpartseditor.qss");
50     if (!styleSheet.open(QIODevice::ReadOnly)) {
51         DebugDialog::debug("Unable to open :/resources/styles/newpartseditor.qss");
52     } else {
53     	this->setStyleSheet(styleSheet.readAll());
54     }
55 */
56 	QVBoxLayout *mainLayout = new QVBoxLayout();
57     mainLayout->setSizeConstraint( QLayout::SetMinAndMaxSize );
58 
59     QLabel *explanation = new QLabel(tr("This is where you edit the connector metadata for the part"));
60     mainLayout->addWidget(explanation);
61 
62     QFrame * numberFrame = new QFrame();
63     QHBoxLayout * numberLayout = new QHBoxLayout();
64 
65     QLabel * label = new QLabel(tr("number of connectors:"));
66     numberLayout->addWidget(label);
67 
68     m_numberEdit = new QLineEdit();
69     QValidator *validator = new QIntValidator(1, 999, this);
70     m_numberEdit->setValidator(validator);
71     numberLayout->addWidget(m_numberEdit);
72     connect(m_numberEdit, SIGNAL(editingFinished()), this, SLOT(connectorCountEntry()));
73 
74     numberLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding));
75     numberFrame->setLayout(numberLayout);
76     mainLayout->addWidget(numberFrame);
77 
78     QFrame * typeFrame = new QFrame();
79     QHBoxLayout * typeLayout = new QHBoxLayout();
80 
81     label = new QLabel(QObject::tr("Set all to:"));
82 	label->setObjectName("NewPartsEditorLabel");
83     typeLayout->addWidget(label);
84 
85 	m_radios.clear();
86     QRadioButton * radioButton = new QRadioButton(MaleSymbolString);
87 	QObject::connect(radioButton, SIGNAL(clicked()), this, SLOT(allTypeEntry()));
88     radioButton->setObjectName("NewPartsEditorRadio");
89     radioButton->setProperty("value", Connector::Male);
90     typeLayout->addWidget(radioButton);
91 	m_radios.append(radioButton);
92 
93     radioButton = new QRadioButton(FemaleSymbolString);
94 	QObject::connect(radioButton, SIGNAL(clicked()), this, SLOT(allTypeEntry()));
95     radioButton->setObjectName("NewPartsEditorRadio");
96     radioButton->setProperty("value", Connector::Female);
97     typeLayout->addWidget(radioButton);
98 	m_radios.append(radioButton);
99 
100     radioButton = new QRadioButton(QObject::tr("Pad"));
101 	QObject::connect(radioButton, SIGNAL(clicked()), this, SLOT(allTypeEntry()));
102     radioButton->setObjectName("NewPartsEditorRadio");
103     radioButton->setProperty("value", Connector::Pad);
104     typeLayout->addWidget(radioButton);
105 	m_radios.append(radioButton);
106 
107 	typeLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding));
108 	typeFrame->setLayout(typeLayout);
109 	mainLayout->addWidget(typeFrame);
110 
111     QFrame * smdFrame = new QFrame();
112     QHBoxLayout * smdLayout = new QHBoxLayout();
113 
114     m_tht = new QRadioButton(tr("Through-hole"));
115 	QObject::connect(m_tht, SIGNAL(clicked()), this, SLOT(smdEntry()));
116     m_tht->setObjectName("NewPartsEditorRadio");
117     smdLayout->addWidget(m_tht);
118 
119     m_smd = new QRadioButton(tr("SMD"));
120 	QObject::connect(m_smd, SIGNAL(clicked()), this, SLOT(smdEntry()));
121     m_smd->setObjectName("NewPartsEditorRadio");
122     smdLayout->addWidget(m_smd);
123 
124 	smdLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding));
125 	smdFrame->setLayout(smdLayout);
126 	mainLayout->addWidget(smdFrame);
127 
128 	m_scrollArea = new QScrollArea;
129 	m_scrollArea->setWidgetResizable(true);
130 	m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
131 
132 	m_scrollFrame = new QFrame;
133 	m_scrollArea->setWidget(m_scrollFrame);
134 
135 	mainLayout->addWidget(m_scrollArea);
136 	this->setLayout(mainLayout);
137 
138 }
139 
~PEConnectorsView()140 PEConnectorsView::~PEConnectorsView() {
141 
142 }
143 
initConnectors(QList<QDomElement> * connectorList)144 void PEConnectorsView::initConnectors(QList<QDomElement> * connectorList)
145 {
146     QWidget * widget = QApplication::focusWidget();
147     if (widget) {
148         QList<QWidget *> children = m_scrollFrame->findChildren<QWidget *>();
149         if (children.contains(widget)) {
150             widget->blockSignals(true);
151         }
152     }
153 
154     if (m_scrollFrame) {
155         m_scrollArea->setWidget(NULL);
156         delete m_scrollFrame;
157         m_scrollFrame = NULL;
158     }
159 
160     m_connectorCount = connectorList->size();
161     m_numberEdit->setText(QString::number(m_connectorCount));
162 
163 	m_scrollFrame = new QFrame(this);
164 	m_scrollFrame->setObjectName("NewPartsEditorConnectors");
165 	QVBoxLayout *scrollLayout = new QVBoxLayout();
166 
167     int ix = 0;
168     foreach (QDomElement connector, *connectorList) {
169         QWidget * widget = PEUtils::makeConnectorForm(connector, ix++, this, true);
170         scrollLayout->addWidget(widget);
171     }
172 
173     scrollLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding));
174     m_scrollFrame->setLayout(scrollLayout);
175 
176     m_scrollArea->setWidget(m_scrollFrame);
177 }
178 
nameEntry()179 void PEConnectorsView::nameEntry() {
180 	QLineEdit * lineEdit = qobject_cast<QLineEdit *>(sender());
181 	if (lineEdit != NULL && lineEdit->isModified()) {
182 		changeConnector();
183         lineEdit->setModified(false);
184 	}
185 }
186 
typeEntry()187 void PEConnectorsView::typeEntry() {
188     changeConnector();
189 }
190 
descriptionEntry()191 void PEConnectorsView::descriptionEntry() {
192 	QLineEdit * lineEdit = qobject_cast<QLineEdit *>(sender());
193 	if (lineEdit != NULL && lineEdit->isModified()) {
194 		changeConnector();
195         lineEdit->setModified(false);
196 	}
197 }
198 
connectorCountEntry()199 void PEConnectorsView::connectorCountEntry() {
200     if (!m_mutex.tryLock(1)) return;            // need the mutex because multiple editingFinished() signals can be triggered more-or-less at once
201 
202     QLineEdit * lineEdit = qobject_cast<QLineEdit *>(sender());
203     if (lineEdit != NULL && lineEdit->isModified()) {
204         int newCount = lineEdit->text().toInt();
205         if (newCount != m_connectorCount) {
206             m_connectorCount = newCount;
207             emit connectorCountChanged(newCount);
208             lineEdit->setModified(false);
209         }
210     }
211 
212     m_mutex.unlock();
213 }
214 
removeConnector()215 void PEConnectorsView::removeConnector() {
216     bool ok;
217     int senderIndex = sender()->property("index").toInt(&ok);
218     if (!ok) return;
219 
220     ConnectorMetadata cmd;
221     if (!PEUtils::fillInMetadata(senderIndex, m_scrollFrame, cmd)) return;
222 
223     QList<ConnectorMetadata *> cmdList;
224     cmdList.append(&cmd);
225     emit removedConnectors(cmdList);
226 }
227 
changeConnector()228 void PEConnectorsView::changeConnector() {
229     bool ok;
230     int senderIndex = sender()->property("index").toInt(&ok);
231     if (!ok) return;
232 
233     ConnectorMetadata cmd;
234     if (!PEUtils::fillInMetadata(senderIndex, m_scrollFrame, cmd)) return;
235 
236     emit connectorMetadataChanged(&cmd);
237 }
238 
allTypeEntry()239 void PEConnectorsView::allTypeEntry() {
240 	QRadioButton * radio = qobject_cast<QRadioButton *>(sender());
241 	if (radio == NULL) return;
242 
243 	bool ok;
244 	Connector::ConnectorType ct = (Connector::ConnectorType) radio->property("value").toInt(&ok);
245 	if (!ok) return;
246 
247 	emit connectorsTypeChanged(ct);
248 
249 	QTimer::singleShot(10, this, SLOT(uncheckRadios()));
250 }
251 
smdEntry()252 void PEConnectorsView::smdEntry()
253 {
254 	QRadioButton * radio = qobject_cast<QRadioButton *>(sender());
255 	if (radio == NULL) return;
256 
257 	emit smdChanged(radio == m_smd ? "smd" : "tht");
258 }
259 
uncheckRadios()260 void PEConnectorsView::uncheckRadios() {
261 	// this doesn't work because the buttons are "autoexclusive"
262 	foreach (QRadioButton * radio, m_radios) {
263 		radio->setChecked(false);
264 	}
265 }
266 
setSMD(bool smd)267 void PEConnectorsView::setSMD(bool smd)
268 {
269 	if (smd) m_smd->setChecked(true);
270 	else m_tht->setChecked(true);
271 }
272