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