1 /*
2 	VeroRoute - Qt based Veroboard/Perfboard/PCB layout & routing application.
3 
4 	Copyright (C) 2017  Alex Lawrow    ( dralx@users.sourceforge.net )
5 
6 	This program 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 	This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "controldialog.h"
21 #include "ui_controldialog.h"
22 #include "mainwindow.h"
23 
ControlDialog(QWidget * parent)24 ControlDialog::ControlDialog(QWidget* parent)
25 : QWidget(parent)
26 , ui(new Ui_ControlDialog)
27 , m_pMainWindow(nullptr)
28 {
29 	ui->setupUi( reinterpret_cast<QDialog*>(this) );
30 
31 	QFont font = ui->rotateCCW->font();
32 	font.setFamily(QString("Arial Unicode MS"));
33 	font.setPointSize(12);
34 	ui->rotateCCW->setFont(font);
35 	ui->rotateCW->setFont(font);
36 	ui->textL->setFont(font);
37 	ui->textR->setFont(font);
38 	ui->textT->setFont(font);
39 	ui->textB->setFont(font);
40 
41 	// Unicode arrowed circles...
42 	ui->rotateCCW->setText(QChar(0x21ba));
43 	ui->rotateCW->setText(QChar(0x21bb));
44 
45 	// Unicode triangles ...
46 	ui->textL->setText(QChar(0x25c0));
47 	ui->textR->setText(QChar(0x25b6));
48 	ui->textT->setText(QChar(0x25b2));
49 	ui->textB->setText(QChar(0x25bc));
50 }
51 
SetMainWindow(MainWindow * p)52 void ControlDialog::SetMainWindow(MainWindow* p)
53 {
54 	m_pMainWindow = p;
55 
56 	QObject::connect(ui->trackSlider,		SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(TrackSliderChanged(int)));
57 	QObject::connect(ui->saturationSlider,	SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(SaturationSliderChanged(int)));
58 	QObject::connect(ui->compSlider,		SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(CompSliderChanged(int)));
59 	QObject::connect(ui->fillSlider,		SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(FillSliderChanged(int)));
60 	QObject::connect(ui->crop,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(Crop()));
61 	QObject::connect(ui->margin,			SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(MarginChanged(int)));
62 
63 	QObject::connect(ui->nameEdit,			SIGNAL(textChanged(QString)),			m_pMainWindow, SLOT(SetCompName(QString)));
64 	QObject::connect(ui->valueEdit,			SIGNAL(textChanged(QString)),			m_pMainWindow, SLOT(SetCompValue(QString)));
65 	QObject::connect(ui->typeComboBox,		SIGNAL(currentTextChanged(QString)),	m_pMainWindow, SLOT(SetCompType(QString)));
66 	QObject::connect(ui->rotateCCW,			SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompRotateCCW()));
67 	QObject::connect(ui->rotateCW,			SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompRotateCW()));
68 	QObject::connect(ui->grow,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompGrow()));
69 	QObject::connect(ui->shrink,			SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompShrink()));
70 	QObject::connect(ui->grow_2,			SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompGrow2()));
71 	QObject::connect(ui->shrink_2,			SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompShrink2()));
72 	QObject::connect(ui->textC,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompTextCentre()));
73 	QObject::connect(ui->textL,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompTextL()));
74 	QObject::connect(ui->textR,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompTextR()));
75 	QObject::connect(ui->textT,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompTextT()));
76 	QObject::connect(ui->textB,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(CompTextB()));
77 
78 	QObject::connect(ui->custom,			SIGNAL(toggled(bool)),		m_pMainWindow,	SLOT(SetCompCustomFlag(bool)));
79 	QObject::connect(ui->padWidth,			SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(SetCompPadWidth(int)));
80 	QObject::connect(ui->holeWidth,			SIGNAL(valueChanged(int)),	m_pMainWindow,	SLOT(SetCompHoleWidth(int)));
81 	QObject::connect(ui->brokenList,		SIGNAL(itemClicked(QListWidgetItem*)),	m_pMainWindow, SLOT(SetNodeId(QListWidgetItem*)));
82 
83 	QObject::connect(ui->autoRoute,			SIGNAL(toggled(bool)),		m_pMainWindow,	SLOT(EnableRouting(bool)));
84 	QObject::connect(ui->autoRoute,			SIGNAL(toggled(bool)),		ui->paste,		SLOT(setEnabled(bool)));
85 	QObject::connect(ui->fast,				SIGNAL(toggled(bool)),		m_pMainWindow,	SLOT(EnableFastRouting(bool)));
86 	QObject::connect(ui->paste,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(Paste()));
87 	QObject::connect(ui->tidy,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(Tidy()));
88 	QObject::connect(ui->wipe,				SIGNAL(clicked()),			m_pMainWindow,	SLOT(WipeTracks()));
89 
90 	QObject::connect(ui->autoColor,			SIGNAL(toggled(bool)),		m_pMainWindow,	SLOT(AutoColor(bool)));
91 	QObject::connect(ui->setColor,			SIGNAL(clicked()),			m_pMainWindow,	SLOT(SelectNodeColor()));
92 }
93 
~ControlDialog()94 ControlDialog::~ControlDialog()
95 {
96 	delete ui;
97 }
98 
ClearList()99 void ControlDialog::ClearList()
100 {
101 	auto* pList = ui->brokenList;
102 	for (int i = 0; i < pList->count(); i++)
103 	{
104 		QListWidgetItem* p = pList->takeItem(i);
105 		if ( p ) delete p;
106 	}
107 	pList->clear();
108 }
109 
SetListItem(const int nodeId)110 void ControlDialog::SetListItem(const int nodeId)
111 {
112 	auto* pList = ui->brokenList;
113 	bool bFound(false);
114 	for (int i = 0; i < pList->count() && !bFound; i++)
115 	{
116 		const QString& str = pList->item(i)->text();
117 		bFound = ( str.leftRef(str.size() - 11).toInt() == nodeId );	// 11 because of " (Floating)" suffix below
118 		if ( bFound ) pList->setCurrentRow(i);
119 	}
120 	if ( !bFound && pList->count() > 0 ) pList->setCurrentRow(0, QItemSelectionModel::Clear);
121 
122 	ui->tidy->setEnabled( !ui->autoRoute->isChecked() && pList->count() == 0 );
123 }
124 
AddListItem(const int nodeId,bool bFloating)125 void ControlDialog::AddListItem(const int nodeId, bool bFloating)
126 {
127 	const std::string str = std::to_string(nodeId) + ( bFloating ? " (Floating)" : "           " );
128 	ui->brokenList->addItem( str.c_str() );
129 }
130 
UpdateCompControls()131 void ControlDialog::UpdateCompControls()	// Component controls
132 {
133 	Board& board = m_pMainWindow->m_board;
134 
135 	std::string nameStr(""), valueStr(""), typeStr("");
136 	bool bCustom(false);
137 	int iPadWidth(0), iHoleWidth(0);
138 
139 	if ( board.GetGroupMgr().GetNumUserComps() == 1 )
140 	{
141 		const Component& comp = board.GetUserComponent();
142 		nameStr			= comp.GetNameStr();
143 		valueStr		= comp.GetValueStr();
144 		typeStr			= comp.GetTypeStr();
145 		bCustom			= comp.GetCustomPads();
146 		iPadWidth		= comp.GetPadWidth();
147 		iHoleWidth		= comp.GetHoleWidth();
148 
149 		int currentIndex = ui->typeComboBox->findText( QString::fromStdString( typeStr ));
150 		if ( currentIndex != -1 )
151 			ui->typeComboBox->setCurrentIndex(currentIndex);
152 		else
153 		{
154 			currentIndex = 0;
155 
156 			// Wipe the Type combobox and repopulate it
157 			ui->typeComboBox->blockSignals(true);	// Block signals while populating box
158 			ui->typeComboBox->clear();
159 			if ( board.GetDisableChangeType() )
160 				ui->typeComboBox->addItem(QString::fromStdString(typeStr));	// Single item
161 			else
162 			{
163 				int index(0);
164 				for (const auto& compType : CompTypes::GetListCompTypes())
165 				{
166 					if ( CompTypes::AllowTypeChange(comp.GetType(), compType) )	// Only put allowed types in combo
167 					{
168 						ui->typeComboBox->addItem(QString::fromStdString( CompTypes::GetDefaultTypeStr(compType) ));
169 						if ( compType == comp.GetType() ) currentIndex = index;
170 						index++;
171 					}
172 				}
173 			}
174 			ui->typeComboBox->blockSignals(false);	// We're done populating, so unblock signals
175 			ui->typeComboBox->setCurrentIndex(currentIndex);
176 		}
177 	}
178 	else
179 		ui->typeComboBox->clear();
180 
181 	ui->nameEdit->setText(nameStr.c_str());
182 	ui->valueEdit->setText(valueStr.c_str());
183 	ui->nameEdit->show();
184 	ui->valueEdit->show();
185 
186 	if ( ui->custom->isChecked() != bCustom ) ui->custom->setChecked(bCustom);
187 	if ( bCustom )
188 	{
189 		if ( ui->padWidth->value()  != iPadWidth  ) ui->padWidth->setValue(iPadWidth);
190 		if ( ui->holeWidth->value() != iHoleWidth ) ui->holeWidth->setValue(iHoleWidth);
191 		ui->padWidth->show();
192 		ui->holeWidth->show();
193 		ui->label_pad->show();
194 		ui->label_hole->show();
195 	}
196 	else
197 	{
198 		ui->padWidth->hide();
199 		ui->holeWidth->hide();
200 		ui->label_pad->hide();
201 		ui->label_hole->hide();
202 	}
203 
204 	const bool bCompEdit		= board.GetCompEdit();
205 	const bool bNoTrackOptions	= board.GetTrackMode() == TRACKMODE::OFF;
206 	const bool bVero			= board.GetVeroTracks();
207 	const bool bNoText			= bCompEdit || board.GetDisableCompText();
208 	const bool bNoRotate		= bCompEdit || board.GetDisableRotate();
209 
210 	// Disable controls	...
211 	ui->nameEdit->setDisabled(		bNoText );
212 	ui->valueEdit->setDisabled(		bNoText );
213 	ui->textC->setDisabled(			bNoText );
214 	ui->textL->setDisabled(			bNoText );
215 	ui->textR->setDisabled(			bNoText );
216 	ui->textT->setDisabled(			bNoText );
217 	ui->textB->setDisabled(			bNoText );
218 	ui->rotateCCW->setDisabled(		bNoRotate );
219 	ui->rotateCW->setDisabled(		bNoRotate );
220 	ui->shrink->setDisabled(		bCompEdit || board.GetDisableStretch(false) );
221 	ui->grow->setDisabled(			bCompEdit || board.GetDisableStretch(true) );
222 	ui->shrink_2->setDisabled(		bCompEdit || board.GetDisableStretchWidth(false) );
223 	ui->grow_2->setDisabled(		bCompEdit || board.GetDisableStretchWidth(true) );
224 	ui->typeComboBox->setDisabled(	bCompEdit || board.GetDisableChangeType() );
225 	ui->custom->setDisabled(		bCompEdit || bNoTrackOptions || bVero || board.GetDisableChangeCustom() );
226 	ui->padWidth->setDisabled(		bCompEdit || bNoTrackOptions || bVero || board.GetDisableChangeCustom() || !ui->custom->isChecked() );
227 	ui->holeWidth->setDisabled(		bCompEdit || bNoTrackOptions || bVero || board.GetDisableChangeCustom() || !ui->custom->isChecked() );
228 
229 	// ... and the corresponding labels
230 	ui->label_name->setDisabled(	bNoText );
231 	ui->label_value->setDisabled(	bNoText );
232 	ui->label_label->setDisabled(	bNoText );
233 	ui->label_rotate->setDisabled(	bNoRotate );
234 	ui->label_length->setDisabled(	bCompEdit || (board.GetDisableStretch(false)      && board.GetDisableStretch(true)) );
235 	ui->label_width->setDisabled(	bCompEdit || (board.GetDisableStretchWidth(false) && board.GetDisableStretchWidth(true)) );
236 	ui->label_type->setDisabled(	bCompEdit || board.GetDisableChangeType() );
237 	ui->label_pad->setDisabled(		bCompEdit || bNoTrackOptions || bVero || board.GetDisableChangeCustom() );
238 	ui->label_hole->setDisabled(	bCompEdit || bNoTrackOptions || bVero || board.GetDisableChangeCustom() );
239 }
240 
UpdateControls()241 void ControlDialog::UpdateControls()	// Non-component controls
242 {
243 	Board& board = m_pMainWindow->m_board;
244 
245 	const bool bCompEdit	= board.GetCompEdit();
246 	const bool bNoTracks	= board.GetTrackMode() == TRACKMODE::OFF;
247 	const bool bColor		= board.GetTrackMode() == TRACKMODE::COLOR;
248 	const bool bComps		= board.GetCompMode()  != COMPSMODE::OFF;
249 
250 	ui->crop->setDisabled( bCompEdit );
251 	ui->margin->setDisabled( bCompEdit );
252 	ui->margin->setValue( board.GetCropMargin() );
253 
254 	ui->label_saturation->setEnabled( !bCompEdit && bColor );
255 	ui->label_fill->setEnabled( !bCompEdit && bComps && ( bColor || bNoTracks) );
256 
257 	ui->autoRoute->setChecked( board.GetRoutingEnabled() );
258 	ui->autoRoute->setDisabled( bCompEdit );
259 	ui->fast->setChecked( board.GetRoutingMethod() == 0 );
260 	ui->fast->setDisabled( bCompEdit );
261 	ui->wipe->setDisabled( bCompEdit || board.GetDisableWipe() );
262 
263 	// Do sliders last (they can trigger a redraw)
264 	ui->trackSlider->setEnabled( !bCompEdit );
265 	ui->saturationSlider->setEnabled( !bCompEdit && bColor );
266 	ui->compSlider->setEnabled( !bCompEdit );
267 	ui->fillSlider->setEnabled( !bCompEdit && bComps && ( bColor || bNoTracks) );
268 	ui->trackSlider->setValue( board.GetTrackSliderValue() );
269 	ui->saturationSlider->setValue( board.GetSaturation() );
270 	ui->compSlider->setValue( board.GetCompSliderValue() );
271 	ui->fillSlider->setValue( board.GetFillSaturation() );
272 
273 	const bool bNodeIdOK = board.GetCurrentNodeId() != BAD_NODEID;
274 	ui->autoColor->setEnabled( bColor && bNodeIdOK );
275 	ui->setColor->setEnabled( bColor && bNodeIdOK );
276 	ui->autoColor->setChecked( bNodeIdOK && !board.GetColorMgr().GetIsFixed( board.GetCurrentNodeId() ) );
277 
278 	QColor color = bColor ? board.GetColorMgr().GetColorFromNodeId( board.GetCurrentNodeId(), false ) : Qt::black;
279 	ui->setColor->setStyleSheet("border:2px solid " + color.name());
280 }
281 
wheelEvent(QWheelEvent * event)282 void ControlDialog::wheelEvent(QWheelEvent* event)
283 {
284 	QWidget::wheelEvent(event);
285 	event->accept();
286 }
287 
mousePressEvent(QMouseEvent * event)288 void ControlDialog::mousePressEvent(QMouseEvent* event)
289 {
290 	QWidget::mousePressEvent(event);
291 	event->accept();
292 }
293 
mouseDoubleClickEvent(QMouseEvent * event)294 void ControlDialog::mouseDoubleClickEvent(QMouseEvent* event)
295 {
296 	QWidget::mouseDoubleClickEvent(event);
297 	event->accept();
298 }
299 
mouseMoveEvent(QMouseEvent * event)300 void ControlDialog::mouseMoveEvent(QMouseEvent* event)
301 {
302 	QWidget::mouseMoveEvent(event);
303 	event->accept();
304 }
305 
mouseReleaseEvent(QMouseEvent * event)306 void ControlDialog::mouseReleaseEvent(QMouseEvent* event)
307 {
308 	QWidget::mouseReleaseEvent(event);
309 	event->accept();
310 }
311 
keyPressEvent(QKeyEvent * event)312 void ControlDialog::keyPressEvent(QKeyEvent* event)
313 {
314 	m_pMainWindow->specialKeyPressEvent(event);
315 	QWidget::keyPressEvent(event);
316 	event->accept();
317 }
318 
keyReleaseEvent(QKeyEvent * event)319 void ControlDialog::keyReleaseEvent(QKeyEvent* event)
320 {
321 	m_pMainWindow->commonKeyReleaseEvent(event);
322 	QWidget::keyReleaseEvent(event);
323 	event->accept();
324 }
325