/[qspeakers]/branches/qtcharts/mainwindow.cpp
ViewVC logotype

Contents of /branches/qtcharts/mainwindow.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 285 - (show annotations)
Sat Nov 7 16:27:00 2020 UTC (11 months, 2 weeks ago) by ben
File size: 46265 byte(s)
Adjust combobox size
1 #include <iostream>
2 #include <QtCore>
3 #include <QDebug>
4 #include <QMessageBox>
5 #include <QPrintDialog>
6 #include <QPrinter>
7 #include <QPrinterInfo>
8 #include <QPainter>
9 #include <QUndoStack>
10 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
11 #include <QStandardPaths>
12 #endif
13 #include <QDesktopServices>
14
15 #include "mainwindow.h"
16 #include "ui_mainwindow.h"
17
18 #include "speaker.h"
19 #include "speakerdb.h"
20 #include "importexport.h"
21 #include "plot.h"
22 #include "searchdialog.h"
23 #include "listdialog.h"
24 #include "system.h"
25 #include "optimizer.h"
26 #include "undocommands.h"
27
28 MainWindow::MainWindow(QWidget *parent) :
29 QMainWindow(parent),
30 ui(new Ui::MainWindow),
31 projectSaved(false),
32 isModifying(false),
33 spkDialog(nullptr),
34 fileDialog(nullptr),
35 searchDialog(nullptr),
36 listDialog(nullptr),
37 bandpassDialog(nullptr),
38 currentSpeakerNumber(0),
39 currentTabIndex(-1),
40 sealedPlot(nullptr),
41 portedPlot(nullptr),
42 bandpassPlot(nullptr),
43 notInDbSpeaker(nullptr),
44 commandStack(new QUndoStack(this))
45 {
46 ui->setupUi(this);
47
48 /* insert QChartView plotters in ui */
49
50 QHBoxLayout *ly1 = new QHBoxLayout(ui->sealedVolumePlotWidget);
51 sealedPlot = new Plot(tr("Sealed volume frequency response"), ui->sealedVolumePlotWidget);
52 sealedPlot->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
53 ly1->insertWidget(0, sealedPlot);
54
55 QHBoxLayout *ly2 = new QHBoxLayout(ui->portedPlotWidget);
56 portedPlot = new Plot(tr("Ported volume frequency response"), ui->portedPlotWidget);
57 portedPlot->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
58 ly2->insertWidget(0, portedPlot);
59
60 QHBoxLayout *ly3 = new QHBoxLayout(ui->bandpassPlotWidget);
61 bandpassPlot = new Plot(tr("Bandpass volumes frequency response"), ui->bandpassPlotWidget);
62 bandpassPlot->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
63 ly3->insertWidget(0, bandpassPlot);
64
65 /* test db */
66 if (!SpeakerDb::exists() || (SpeakerDb::lastModified() <= SpeakerDb::pkgInstalled())) {
67 QFile pkg_db(SpeakerDb::pkgPath());
68 if (SpeakerDb::merge(pkg_db)) qDebug() << "merged db";
69 }
70
71 /* fill speaker combos */
72 ui->vendorComboBox->addItems(SpeakerDb::getVendors());
73 ui->vendorComboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents);
74 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(ui->vendorComboBox->currentText()));
75 ui->modelComboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents);
76
77 /* undo history is empty */
78 this->ui->actionUndo->setEnabled(false);
79 this->ui->actionRedo->setEnabled(false);
80
81 /* restore last saved project... */
82 ImportExport::restoreProject(currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, &currentSpeakerNumber, &currentTabIndex);
83 projectSaved = true;
84
85 /* on first run, no speaker. reset to the speaker of the combos if needed */
86 if (!currentSpeaker.isValid()) {
87 currentSpeaker = SpeakerDb::getByVendorAndModel(ui->vendorComboBox->currentText(), ui->modelComboBox->currentText());
88 }
89
90 /* display sibling number */
91 ui->numberSpinBox->setValue(currentSpeakerNumber);
92
93 /* select restored tab */
94 ui->tabWidget->setCurrentIndex(currentTabIndex);
95
96 /* tab index change is not connected yet, do menu modifications manually */
97 if (currentTabIndex != 1) {
98 /* index != 1 needs to deactivate the ported alignments menu */
99 setActivateActions(ui->menuPorted_alignments->actions(), false);
100 }
101 if (currentTabIndex != 2) {
102 /* index != 2 needs to deactivate the bandpass alignment menu */
103 ui->actionBandpass_alignment->setEnabled(false);
104 }
105
106 syncUiFromCurrentSpeaker(currentSpeaker);
107 syncUiFromCurrentSealedBox(currentSealedBox);
108 syncUiFromCurrentPortedBox(currentPortedBox);
109 syncUiFromCurrentBandPassBox(currentBandPassBox);
110
111 /*
112 * connections
113 */
114
115 /* menu actions */
116 linkMenus();
117
118 /* tabs actions */
119 linkTabs();
120
121 /* non-graphic */
122 linkInternals();
123 }
124
125 MainWindow::~MainWindow()
126 {
127 delete ui;
128 }
129
130 void MainWindow::onProjectSave()
131 {
132 projectSaved = true;
133
134 ImportExport::saveProject(currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, currentSpeakerNumber, currentTabIndex);
135 }
136
137 void MainWindow::onProjectExport()
138 {
139 QString home = MainWindow::getHome();
140 QString fileName = QFileDialog::getSaveFileName(this, tr("Export File"), home + tr("/untitled.qsp"), tr("QSpeakers project (*.qsp)"));
141
142 QFile file(fileName);
143 ImportExport::exportProject(file, currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, currentSpeakerNumber, currentTabIndex);
144 }
145
146 void MainWindow::onProjectImport()
147 {
148 if (!projectSaved) {
149 QMessageBox::StandardButton pressed =
150 QMessageBox::question(this, tr("Project not saved"),
151 tr("The current project has not been saved. Continue anyway?"),
152 QMessageBox::Yes|QMessageBox::No);
153 if (pressed == QMessageBox::No)
154 return;
155 }
156
157 QString home = MainWindow::getHome();
158 QString fileName = QFileDialog::getOpenFileName(this, tr("Import File"), home, tr("QSpeakers project (*.qsp)"));
159
160 /* user cancelled */
161 if (fileName.isEmpty())
162 return;
163
164 /* clear undo history */
165 this->commandStack->clear();
166
167 unlinkInternals();
168 unlinkTabs();
169
170 QFile file(fileName);
171 ImportExport::importProject(currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, &currentSpeakerNumber, &currentTabIndex, file);
172 ImportExport::setSavePath(fileName);
173 setWindowFilePath(ImportExport::getSavePath());
174
175 ui->tabWidget->setCurrentIndex(currentTabIndex);
176
177 syncUiFromCurrentSpeaker(currentSpeaker);
178 syncUiFromCurrentSealedBox(currentSealedBox);
179 syncUiFromCurrentPortedBox(currentPortedBox);
180 syncUiFromCurrentBandPassBox(currentBandPassBox);
181
182 linkInternals();
183 linkTabs();
184
185 if (notInDbSpeaker)
186 onSpeakerModify();
187 }
188
189 void MainWindow::onProjectQuit()
190 {
191 if (projectSaved) {
192 this->close();
193 return;
194 }
195
196 if (!currentSpeaker.isValid()) {
197 this->close();
198 return;
199 }
200
201 QMessageBox::StandardButton pressed =
202 QMessageBox::question(this, tr("Project not saved"),
203 tr("The current project has not been saved. Exit anyway?"),
204 QMessageBox::Yes|QMessageBox::No);
205 if (pressed == QMessageBox::Yes)
206 this->close();
207 }
208
209 void MainWindow::syncUiFromCurrentSpeaker(const Speaker& spk)
210 {
211 if (!spk.isValid())
212 return;
213
214 /* look if vendor is in the db */
215 QList<Speaker> speakers = SpeakerDb::getByVendor(spk.getVendor());
216
217 unlinkTabs();
218 if (speakers.count() == 0) {
219 /* if this is an unknown vendor, insert in combo */
220 ui->vendorComboBox->insertItem(0, spk.getVendor());
221 ui->vendorComboBox->setCurrentIndex(0);
222 ui->modelComboBox->clear();
223 /* this means also a new model */
224 ui->modelComboBox->insertItem(0, spk.getModel());
225 ui->modelComboBox->setCurrentIndex(0);
226 notInDbSpeaker = &spk;
227 } else {
228 /* select correct vendor */
229 ui->vendorComboBox->setCurrentIndex(ui->vendorComboBox->findText(spk.getVendor()));
230 /* fill speakers of this vendor */
231 ui->modelComboBox->clear();
232 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(spk.getVendor()));
233
234 int i = 0;
235 for (i = 0; i < speakers.count(); i++) {
236 Speaker speaker = speakers[i];
237 if (speaker.getModel() == spk.getModel()) {
238 if (speaker != spk) {
239 /* speaker conflict, renaming */
240 currentSpeaker.setModel(speaker.getModel() + "*");
241 ui->modelComboBox->addItem(spk.getModel());
242 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(spk.getModel()));
243 notInDbSpeaker = &spk;
244 } else {
245 /* okay, select correct combo */
246 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(spk.getModel()));
247 notInDbSpeaker = nullptr;
248 }
249
250 break;
251 }
252 }
253
254 if (i == speakers.count()) {
255 /* vendor was ok but model was not in DB */
256 ui->modelComboBox->addItem(spk.getModel());
257 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(spk.getModel()));
258 notInDbSpeaker = &spk;
259 }
260 }
261
262 ui->numberSpinBox->setValue(currentSpeakerNumber);
263
264 /* display speaker's values */
265 ui->fsValueLabel->setNum(currentSpeaker.getFs());
266 ui->qtsValueLabel->setNum(currentSpeaker.getQts());
267 ui->vasValueLabel->setNum(currentSpeaker.getVas());
268 ui->diaValueLabel->setNum(currentSpeaker.getDia());
269 ui->zValueLabel->setNum(currentSpeaker.getZ());
270 ui->vcValueLabel->setNum(currentSpeaker.getVc());
271
272 linkTabs();
273 }
274
275 void MainWindow::syncUiFromCurrentSealedBox(const SealedBox& box)
276 {
277 unlinkTabs();
278 ui->sealedVolumeDoubleSpinBox->setValue(box.getVolume());
279
280 System s(currentSpeaker, &box, currentSpeakerNumber);
281 sealedPlot->clear();
282 for (double f = sealedPlot->getXmin(); f < portedPlot->getXmax(); f *= pow(10, 1.0/100.0)) {
283 double db = s.response(f);
284 sealedPlot->appendPointF(QPointF(f, db));
285 }
286 sealedPlot->draw3dbVLine();
287 linkTabs();
288 }
289
290 void MainWindow::syncUiFromCurrentPortedBox(const PortedBox& box)
291 {
292 unlinkTabs();
293 ui->portedVolumeDoubleSpinBox->setValue(box.getBoxVolume());
294 ui->portedResonancedoubleSpinBox->setValue(box.getResFreq());
295 ui->portedPortsNumberSpinBox->setValue(box.getPortNum());
296 ui->portedPortDiameterDoubleSpinBox->setValue(box.getPortDiam());
297 ui->portedPortSlotWidthButton->setChecked(box.getSlotPortActivated());
298 ui->portedPortSlotWidthButton->clicked(box.getSlotPortActivated());
299 ui->portedPortSlotWidthDoubleSpinBox->setValue(box.getSlotWidth());
300 ui->portedPortSlotHeightLineEdit->setText(QString::number(box.getSlotHeight(), 'f', 2));
301 ui->portedPortLengthLineEdit->setText(QString::number(box.getPortLen(), 'f', 2));
302
303 System s(currentSpeaker, &box, currentSpeakerNumber);
304 portedPlot->clear();
305 for (double f = portedPlot->getXmin(); f < portedPlot->getXmax(); f *= pow(10, 1.0/100.0)) {
306 double db = s.response(f);
307 portedPlot->appendPointF(QPointF(f, db));
308 }
309 portedPlot->draw3dbVLine();
310 linkTabs();
311 }
312
313 void MainWindow::syncUiFromCurrentBandPassBox(const BandPassBox& box)
314 {
315 unlinkTabs();
316 ui->bandPassSealedVolumeDoubleSpinBox->setValue(box.getSealedBoxVolume());
317 ui->bandPassPortedVolumeDoubleSpinBox->setValue(box.getPortedBoxVolume());
318 ui->bandPassPortedResonanceDoubleSpinBox->setValue(box.getPortedBoxResFreq());
319 ui->bandPassPortsNumberSpinBox->setValue(box.getPortedBoxPortNum());
320 ui->bandPassPortDiameterDoubleSpinBox->setValue(box.getPortedBoxPortDiam());
321 ui->bandPassPortLengthLineEdit->setText(QString::number(box.getPortedBoxPortLen(), 'f', 2));
322
323 System s(currentSpeaker, &box, currentSpeakerNumber);
324 bandpassPlot->clear();
325 for (double f = bandpassPlot->getXmin(); f < bandpassPlot->getXmax(); f *= pow(10, 1.0/100.0)) {
326 double db = s.response(f);
327 bandpassPlot->appendPointF(QPointF(f, db));
328 }
329 bandpassPlot->draw3dbVLine();
330 linkTabs();
331 }
332
333 void MainWindow::setCurrentSpeaker(const Speaker &spk)
334 {
335 if ((currentSpeaker.getVendor() == spk.getVendor()) &&
336 (currentSpeaker.getModel() == spk.getModel()))
337 return;
338
339 currentSpeaker = spk;
340 emit currentSpeakerChanged(spk);
341 }
342
343 bool MainWindow::print(QPrinter *printer)
344 {
345 QPainter painter;
346 if (!painter.begin(printer))
347 return false;
348
349 QRect page = printer->pageRect();
350
351 qreal step = page.height() / 4.0;
352
353 if (ui->tabWidget->currentWidget() == ui->sealedTab) {
354 System s(currentSpeaker, &currentSealedBox, currentSpeakerNumber);
355 s.render(&painter, QRectF(page.left(), page.top(), page.width(), step));
356 //sealedPlot->setUseOpenGL(false);
357 sealedPlot->render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() - step));
358 //sealedPlot->setUseOpenGL(true);
359 } else if (ui->tabWidget->currentWidget() == ui->portedTab) {
360 System s(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
361 s.render(&painter, QRectF(page.left(), page.top(), page.width(), step));
362 //portedPlot->setUseOpenGL(false);
363 portedPlot->render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() - step));
364 //portedPlot->setUseOpenGL(true);
365 } else {
366 System s(currentSpeaker, &currentBandPassBox, currentSpeakerNumber);
367 s.render(&painter, QRectF(page.left(), page.top(), page.width(), step));
368 //bandpassPlot->setUseOpenGL(false);
369 bandpassPlot->render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() - step));
370 //bandpassPlot->setUseOpenGL(true);
371 }
372
373 painter.end();
374 return true;
375 }
376
377 QString MainWindow::getHome()
378 {
379 QString home;
380 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
381 home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
382 #else
383 home = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
384 #endif
385 return home;
386 }
387
388 void MainWindow::onBandpassAlignment()
389 {
390 bandpassDialog = new BandpassDialog(this);
391 connect(bandpassDialog, SIGNAL(optimizeRequested(double, double)), this, SLOT(onBandpassOptimizeRequested(double, double)));
392 connect(bandpassDialog, SIGNAL(optimizeCancelled()), this, SLOT(onBandpassOptimizeCancelled()));
393 bandpassDialog->show();
394 }
395
396 void MainWindow::onBandpassOptimizeRequested(double s, double pa)
397 {
398 if (ui->tabWidget->currentWidget() == ui->bandpassTab) {
399 Optimizer optimizer(currentSpeaker, &currentBandPassBox, currentSpeakerNumber, this);
400 optimizer.bandpassAlignS_Pa(s, pa);
401 emit currentBandPassBoxChanged(currentBandPassBox);
402 }
403
404 disconnect(bandpassDialog, SIGNAL(optimizeRequested(double,double)), this, SLOT(onBandpassOptimizeRequested(double,double)));
405 disconnect(bandpassDialog, SIGNAL(optimizeCancelled()), this, SLOT(onBandpassOptimizeCancelled()));
406 bandpassDialog->close();
407 bandpassDialog->deleteLater();
408 bandpassDialog = nullptr;
409 }
410
411 void MainWindow::onBandpassOptimizeCancelled()
412 {
413 disconnect(bandpassDialog, SIGNAL(optimizeRequested(double,double)), this, SLOT(onBandpassOptimizeRequested(double,double)));
414 disconnect(bandpassDialog, SIGNAL(optimizeCancelled()), this, SLOT(onBandpassOptimizeCancelled()));
415 bandpassDialog->close();
416 bandpassDialog->deleteLater();
417 bandpassDialog = nullptr;
418 }
419
420 void MainWindow::linkMenus()
421 {
422 connect(ui->actionProjectSave, SIGNAL(triggered()), this, SLOT(onProjectSave()));
423 connect(ui->actionProjectQuit, SIGNAL(triggered()), this, SLOT(onProjectQuit()));
424 connect(ui->actionSpeakerNew, SIGNAL(triggered()), this, SLOT(onSpeakerNew()));
425 connect(ui->actionSpeakerModify, SIGNAL(triggered()), this, SLOT(onSpeakerModify()));
426 connect(ui->actionSpeakerRemove, SIGNAL(triggered()), this, SLOT(onSpeakerRemove()));
427 connect(ui->actionProjectExport, SIGNAL(triggered()), this, SLOT(onProjectExport()));
428 connect(ui->actionProjectImport, SIGNAL(triggered()), this, SLOT(onProjectImport()));
429 connect(ui->actionEditOptimize, SIGNAL(triggered()), this, SLOT(onEditOptimize()));
430 connect(ui->actionSpeakerSearch, SIGNAL(triggered()), this, SLOT(onSpeakerSearch()));
431 connect(ui->actionProjectPrint, SIGNAL(triggered()), this, SLOT(onProjectPrint()));
432 connect(ui->actionUndo, SIGNAL(triggered()), this, SLOT(onUndo()));
433 connect(ui->actionRedo, SIGNAL(triggered()), this, SLOT(onRedo()));
434 connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAboutAbout()));
435
436 /* ported alignments sub-menu */
437 connect(ui->actionModerate_Inf, SIGNAL(triggered()), this, SLOT(onAlignModerate_Inf()));
438 connect(ui->actionLegendre, SIGNAL(triggered()), this, SLOT(onAlignLegendre()));
439 connect(ui->actionBessel, SIGNAL(triggered()), this, SLOT(onAlignBessel()));
440 connect(ui->actionBullock, SIGNAL(triggered()), this, SLOT(onAlignBullock()));
441 connect(ui->actionKeele_Hoge, SIGNAL(triggered()), this, SLOT(onAlignKeele_Hoge()));
442
443 /* bandpass alignment */
444 connect(ui->actionBandpass_alignment, SIGNAL(triggered(bool)), this, SLOT(onBandpassAlignment()));
445 }
446
447 void MainWindow::linkTabs()
448 {
449 connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(onCurrentTabChanged(int)));
450
451 /* spk combos action */
452 connect(ui->vendorComboBox, SIGNAL(activated(QString)), this, SLOT(onVendorChanged(QString)));
453 connect(ui->modelComboBox, SIGNAL(activated(QString)), this, SLOT(onModelChanged(QString)));
454
455 /* drivers number spin action */
456 connect(ui->numberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onNumberSpinChanged(int)));
457
458 connect(ui->sealedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onSealedVolumeDoubleSpinChanged(double)));
459
460 connect(ui->portedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedVolumeDoubleSpinChanged(double)));
461 connect(ui->portedResonancedoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedResonanceDoubleSpinChanged(double)));
462 connect(ui->portedPortsNumberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onPortedPortsNumberSpinChanged(int)));
463 connect(ui->portedPortDiameterDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedPortDiameterDoubleSpinChanged(double)));
464 connect(ui->portedPortSlotWidthButton, SIGNAL(clicked(bool)), this, SLOT(onPortedSlotPortActivated(bool)));
465 connect(ui->portedPortSlotWidthDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedSlotWidthDoubleSpinChanged(double)));
466
467 connect(ui->bandPassSealedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassSealedVolumeDoubleSpinChanged(double)));
468 connect(ui->bandPassPortedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortedVolumeDoubleSpinChanged(double)));
469 connect(ui->bandPassPortedResonanceDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortedResonanceDoubleSpinChanged(double)));
470 connect(ui->bandPassPortsNumberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onBandPassPortNumSpinChanged(int)));
471 connect(ui->bandPassPortDiameterDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortDiameterDoubleSpinChanged(double)));
472 }
473
474 void MainWindow::linkInternals()
475 {
476 connect(this, SIGNAL(currentSpeakerChanged(Speaker)), this, SLOT(onCurrentSpeakerChanged(const Speaker&)));
477 connect(this, SIGNAL(currentSealedBoxChanged(SealedBox)), this, SLOT(onCurrentSealedBoxChanged(const SealedBox&)));
478 connect(this, SIGNAL(currentPortedBoxChanged(PortedBox)), this, SLOT(onCurrentPortedBoxChanged(const PortedBox&)));
479 connect(this, SIGNAL(currentBandPassBoxChanged(BandPassBox)), this, SLOT(onCurrentBandPassBoxChanged(const BandPassBox&)));
480
481 connect(this->commandStack, SIGNAL(canUndoChanged(bool)), ui->actionUndo, SLOT(setEnabled(bool)));
482 connect(this->commandStack, SIGNAL(canRedoChanged(bool)), ui->actionRedo, SLOT(setEnabled(bool)));
483 }
484
485 void MainWindow::unlinkMenus()
486 {
487 disconnect(ui->actionProjectSave, SIGNAL(triggered()), this, SLOT(onProjectSave()));
488 disconnect(ui->actionProjectQuit, SIGNAL(triggered()), this, SLOT(onProjectQuit()));
489 disconnect(ui->actionSpeakerNew, SIGNAL(triggered()), this, SLOT(onSpeakerNew()));
490 disconnect(ui->actionSpeakerModify, SIGNAL(triggered()), this, SLOT(onSpeakerModify()));
491 disconnect(ui->actionSpeakerRemove, SIGNAL(triggered()), this, SLOT(onSpeakerRemove()));
492 disconnect(ui->actionProjectExport, SIGNAL(triggered()), this, SLOT(onProjectExport()));
493 disconnect(ui->actionProjectImport, SIGNAL(triggered()), this, SLOT(onProjectImport()));
494 disconnect(ui->actionEditOptimize, SIGNAL(triggered()), this, SLOT(onEditOptimize()));
495 disconnect(ui->actionSpeakerSearch, SIGNAL(triggered()), this, SLOT(onSpeakerSearch()));
496 disconnect(ui->actionProjectPrint, SIGNAL(triggered()), this, SLOT(onProjectPrint()));
497 disconnect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAboutAbout()));
498
499 /* ported alignments sub-menu */
500 disconnect(ui->actionModerate_Inf, SIGNAL(triggered()), this, SLOT(onAlignModerate_Inf()));
501 disconnect(ui->actionLegendre, SIGNAL(triggered()), this, SLOT(onAlignLegendre()));
502 disconnect(ui->actionBessel, SIGNAL(triggered()), this, SLOT(onAlignBessel()));
503 disconnect(ui->actionBullock, SIGNAL(triggered()), this, SLOT(onAlignBullock()));
504 disconnect(ui->actionKeele_Hoge, SIGNAL(triggered()), this, SLOT(onAlignKeele_Hoge()));
505
506 /* bandpass alignment */
507 disconnect(ui->actionBandpass_alignment, SIGNAL(triggered(bool)), this, SLOT(onBandpassAlignment()));
508 }
509
510 void MainWindow::unlinkTabs()
511 {
512 disconnect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(onCurrentTabChanged(int)));
513
514 /* spk combos action */
515 disconnect(ui->vendorComboBox, SIGNAL(activated(QString)), this, SLOT(onVendorChanged(QString)));
516 disconnect(ui->modelComboBox, SIGNAL(activated(QString)), this, SLOT(onModelChanged(QString)));
517
518 disconnect(ui->numberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onNumberSpinChanged(int)));
519
520 disconnect(ui->sealedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onSealedVolumeDoubleSpinChanged(double)));
521
522 disconnect(ui->portedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedVolumeDoubleSpinChanged(double)));
523 disconnect(ui->portedResonancedoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedResonanceDoubleSpinChanged(double)));
524 disconnect(ui->portedPortsNumberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onPortedPortsNumberSpinChanged(int)));
525 disconnect(ui->portedPortDiameterDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedPortDiameterDoubleSpinChanged(double)));
526 disconnect(ui->portedPortSlotWidthButton, SIGNAL(clicked(bool)), this, SLOT(onPortedSlotPortActivated(bool)));
527 disconnect(ui->portedPortSlotWidthDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedSlotWidthDoubleSpinChanged(double)));
528
529 disconnect(ui->bandPassSealedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassSealedVolumeDoubleSpinChanged(double)));
530 disconnect(ui->bandPassPortedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortedVolumeDoubleSpinChanged(double)));
531 disconnect(ui->bandPassPortedResonanceDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortedResonanceDoubleSpinChanged(double)));
532 disconnect(ui->bandPassPortsNumberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onBandPassPortNumSpinChanged(int)));
533 disconnect(ui->bandPassPortDiameterDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortDiameterDoubleSpinChanged(double)));
534 }
535
536 void MainWindow::unlinkInternals()
537 {
538 disconnect(this, SIGNAL(currentSpeakerChanged(Speaker)), this, SLOT(onCurrentSpeakerChanged(const Speaker&)));
539 disconnect(this, SIGNAL(currentSealedBoxChanged(SealedBox)), this, SLOT(onCurrentSealedBoxChanged(const SealedBox&)));
540 disconnect(this, SIGNAL(currentPortedBoxChanged(PortedBox)), this, SLOT(onCurrentPortedBoxChanged(const PortedBox&)));
541 disconnect(this, SIGNAL(currentBandPassBoxChanged(BandPassBox)), this, SLOT(onCurrentBandPassBoxChanged(const BandPassBox&)));
542 }
543
544 void MainWindow::onSpeakerNew()
545 {
546 isModifying = false;
547 spkDialog = new SpeakerDialog(this);
548 connect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
549 connect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
550 spkDialog->show();
551 }
552
553 void MainWindow::onSpeakerRemove()
554 {
555
556 QMessageBox::StandardButton pressed =
557 QMessageBox::question(this,
558 tr("Removal confirmation"),
559 tr("Do you really want to remove this loudspeaker from the database?"),
560 QMessageBox::Yes|QMessageBox::No);
561
562 if (pressed == QMessageBox::No)
563 return;
564
565 QString vendor = currentSpeaker.getVendor();
566 QString model = currentSpeaker.getModel();
567
568 int num = SpeakerDb::getModelsByVendor(currentSpeaker.getVendor()).size();
569 ui->modelComboBox->removeItem(ui->modelComboBox->currentIndex());
570 if (num == 1) {
571 ui->vendorComboBox->removeItem(ui->vendorComboBox->currentIndex());
572 }
573
574 SpeakerDb::removeByVendorAndModel(vendor, model);
575
576 /* fill speakers of automatically reselected vendor */
577 QString v = ui->vendorComboBox->currentText();
578 ui->modelComboBox->clear();
579 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(v));
580 /* insert a fake speaker to let the choice to the user */
581 ui->modelComboBox->insertItem(0, "?");
582 ui->modelComboBox->setCurrentIndex(0);
583 setCurrentSpeaker(Speaker());
584 }
585
586 void MainWindow::onSpeakerModify()
587 {
588 isModifying = true;
589 spkDialog = new SpeakerDialog(currentSpeaker, this);
590 connect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
591 connect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
592 spkDialog->show();
593 }
594
595 void MainWindow::onSpeakerInserted(Speaker spk)
596 {
597 if (isModifying) {
598 int idx;
599 idx = ui->vendorComboBox->currentIndex();
600 ui->vendorComboBox->setItemText(idx, spk.getVendor());
601 idx = ui->modelComboBox->currentIndex();
602 ui->modelComboBox->setItemText(idx, spk.getModel());
603
604 currentSpeaker = spk;
605 emit currentSpeakerChanged(currentSpeaker);
606 } else {
607 int idx = ui->vendorComboBox->findText(spk.getVendor());
608 if (idx == -1)
609 ui->vendorComboBox->addItem(spk.getVendor());
610 else if (idx == ui->vendorComboBox->currentIndex())
611 ui->modelComboBox->addItem(spk.getModel());
612 }
613
614 /* spk has been inserted or modified: remove anyway notInDbSpeaker */
615 notInDbSpeaker = nullptr;
616
617 disconnect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
618 disconnect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
619 spkDialog->close();
620 spkDialog->deleteLater();
621 spkDialog = nullptr;
622 }
623
624 void MainWindow::onSpeakerCancelled()
625 {
626 disconnect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
627 disconnect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
628 spkDialog->close();
629 spkDialog->deleteLater();
630 spkDialog = nullptr;
631 }
632
633 void MainWindow::onEditOptimize()
634 {
635 if (ui->tabWidget->currentWidget() == ui->sealedTab) {
636 Optimizer optimizer(currentSpeaker, &currentSealedBox, currentSpeakerNumber, this);
637 optimizer.genericOptimizeBox();
638 emit currentSealedBoxChanged(currentSealedBox);
639 } else if (ui->tabWidget->currentWidget() == ui->portedTab) {
640 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber, this);
641 optimizer.genericOptimizeBox();
642 emit currentPortedBoxChanged(currentPortedBox);
643 } else {
644 Optimizer optimizer(currentSpeaker, &currentBandPassBox, currentSpeakerNumber, this);
645 optimizer.genericOptimizeBox();
646 emit currentBandPassBoxChanged(currentBandPassBox);
647 }
648 }
649
650 void MainWindow::onAlignModerate_Inf()
651 {
652 if (ui->tabWidget->currentWidget() == ui->portedTab) {
653 Optimizer optimzer(currentSpeaker, &currentPortedBox, currentSpeakerNumber, this);
654 optimzer.portedAlignModerate_Inf();
655 emit currentPortedBoxChanged(currentPortedBox);
656 }
657 }
658
659 void MainWindow::onAlignLegendre()
660 {
661 if (ui->tabWidget->currentWidget() == ui->portedTab) {
662 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber, this);
663 optimizer.portedAlignLegendre();
664 emit currentPortedBoxChanged(currentPortedBox);
665 }
666 }
667
668 void MainWindow::onAlignBessel()
669 {
670 if (ui->tabWidget->currentWidget() == ui->portedTab) {
671 Optimizer optimzer(currentSpeaker, &currentPortedBox, currentSpeakerNumber, this);
672 optimzer.portedAlignBessel();
673 emit currentPortedBoxChanged(currentPortedBox);
674 }
675 }
676
677 void MainWindow::onAlignKeele_Hoge()
678 {
679 /* BB4 */
680 if (ui->tabWidget->currentWidget() == ui->portedTab) {
681 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber, this);
682 optimizer.portedAlignKeele_Hoge();
683 emit currentPortedBoxChanged(currentPortedBox);
684 }
685 }
686
687 void MainWindow::onAlignBullock()
688 {
689 /* SBB4 */
690 if (ui->tabWidget->currentWidget() == ui->portedTab) {
691 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber, this);
692 optimizer.portedAlignBullock();
693 emit currentPortedBoxChanged(currentPortedBox);
694 }
695 }
696
697 void MainWindow::onSpeakerSearch()
698 {
699 searchDialog = new SearchDialog(this);
700 connect(searchDialog, SIGNAL(searchRequested(const QString&, double, double)), this, SLOT(onSearchRequested(const QString&, double, double)));
701 connect(searchDialog, SIGNAL(searchCancelled()), this, SLOT(onSearchCancelled()));
702 searchDialog->show();
703 }
704
705 void MainWindow::onProjectPrint()
706 {
707 QPrinter printer;
708 printer.setCreator("QSpeakers");
709 printer.setDocName("qspeakers_project");
710 printer.setOrientation(QPrinter::Landscape);
711 QPrintDialog dialog(&printer, this);
712 if (dialog.exec() == QDialog::Accepted) {
713 if (printer.isValid()) {
714 if (!print(&printer)) {
715 QPrinterInfo info(printer);
716 qWarning() << "printerinfo definition null:" << info.isNull();
717 qWarning() << "printerinfo state error:" << (info.state() == QPrinter::Error);
718 }
719 } else {
720 qWarning() << "invalid printer object";
721 }
722 }
723 }
724
725 void MainWindow::onUndo()
726 {
727 if (this->commandStack->canUndo())
728 this->commandStack->undo();
729 }
730
731 void MainWindow::onRedo()
732 {
733 if (this->commandStack->canRedo())
734 this->commandStack->redo();
735 }
736
737 void MainWindow::onAboutAbout()
738 {
739 QMessageBox::about(this, tr("About QSpeakers"),
740 tr("QSpeakers version " VERSION "\n\n"
741 "This program simulates common acoustical enclosures behaviour to help designing loudspeaker systems.\n\n"
742 "This program is free software, copyright (C) 2014 Benoit Rouits <brouits@free.fr> and released under the GNU General Public Lisence "
743 "version 3. It is delivered as is in the hope it can be useful, but with no warranty of correctness."));
744 }
745
746 void MainWindow::onSearchRequested(const QString& param, double min, double max)
747 {
748 disconnect(searchDialog, SIGNAL(searchRequested(const QString&, double, double)), this, SLOT(onSearchRequested(const QString&, double, double)));
749 disconnect(searchDialog, SIGNAL(searchCancelled()), this, SLOT(onSearchCancelled()));
750 searchDialog->close();
751 searchDialog->deleteLater();
752 searchDialog = nullptr;
753
754 QList<Speaker> speakers = SpeakerDb::getByValue(param, min, max);
755 listDialog = new ListDialog(speakers, this);
756 connect(listDialog, SIGNAL(speakerItemSelected(QString, const Speaker&)), this, SLOT(onSpeakerItemSelected(QString, const Speaker&)));
757 connect(listDialog, SIGNAL(speakerItemCancelled()), this, SLOT(onSpeakerItemCancelled()));
758 listDialog->show();
759 }
760
761 void MainWindow::onSearchCancelled()
762 {
763 disconnect(searchDialog, SIGNAL(searchRequested(const QString&, double, double)), this, SLOT(onSearchRequested(const QString&, double, double)));
764 disconnect(searchDialog, SIGNAL(searchCancelled()), this, SLOT(onSearchCancelled()));
765 searchDialog->close();
766 searchDialog->deleteLater();
767 searchDialog = nullptr;
768 }
769
770 void MainWindow::onSpeakerItemSelected(QString title, const Speaker& speaker)
771 {
772 qDebug() << title;
773 if (speaker.isValid()) {
774 setCurrentSpeaker(speaker);
775 syncUiFromCurrentSpeaker(speaker);
776 }
777
778 disconnect(listDialog, SIGNAL(speakerItemSelected(QString, const Speaker&)), this, SLOT(onSpeakerItemSelected(QString, const Speaker&)));
779 disconnect(listDialog, SIGNAL(speakerItemCancelled()), this, SLOT(onSpeakerItemCancelled()));
780 listDialog->close();
781 listDialog->deleteLater();
782 listDialog = nullptr;
783 }
784
785 void MainWindow::onSpeakerItemCancelled()
786 {
787 disconnect(listDialog, SIGNAL(speakerItemSelected(QString,const Speaker&)), this, SLOT(onSpeakerItemSelected(QString,const Speaker&)));
788 disconnect(listDialog, SIGNAL(speakerItemCancelled()), this, SLOT(onSpeakerItemCancelled()));
789 listDialog->close();
790 listDialog->deleteLater();
791 listDialog = nullptr;
792 }
793
794 void MainWindow::setActivateActions(QList<QAction*> actions, bool enable)
795 {
796 for (int i = 0; i < actions.count(); i++) {
797 actions[i]->setEnabled(enable);
798 }
799 }
800
801 void MainWindow::onCurrentTabChanged(int tab)
802 {
803 if (tab == currentTabIndex)
804 return;
805
806 this->commandStack->clear();
807
808 QList<QAction*> alignments = ui->menuPorted_alignments->actions();
809 currentTabIndex = tab;
810
811 switch (tab) {
812 case 0:
813 {
814 setActivateActions(alignments, false);
815 ui->actionBandpass_alignment->setEnabled(false);
816
817 syncUiFromCurrentSealedBox(currentSealedBox);
818 break;
819 }
820 case 1:
821 {
822 setActivateActions(alignments, true);
823 ui->actionBandpass_alignment->setEnabled(false);
824
825 syncUiFromCurrentPortedBox(currentPortedBox);
826 break;
827 }
828 case 2:
829 {
830 setActivateActions(alignments, false);
831 ui->actionBandpass_alignment->setEnabled(true);
832
833 syncUiFromCurrentBandPassBox(currentBandPassBox);
834 break;
835 }
836 default:
837 break;
838 }
839 }
840
841 void MainWindow::onNumberSpinChanged(int number) {
842 if (currentSpeakerNumber == number)
843 return;
844
845 NumberCommand* com = new NumberCommand (currentSpeakerNumber, number, this);
846 this->commandStack->push(com);
847 }
848
849 void MainWindow::changeSpeakerNumber(int number) {
850 /* order is very important to avoid crash loop */
851 currentSpeakerNumber = number;
852 ui->numberSpinBox->setValue(number);
853
854 /* the user may have used the "?" fake speaker */
855 if (!currentSpeaker.isValid()) {
856 qDebug() << "invalid speaker, not computing.";
857 return;
858 }
859
860 projectSaved = false;
861 syncUiFromCurrentSealedBox(currentSealedBox);
862 syncUiFromCurrentPortedBox(currentPortedBox);
863 syncUiFromCurrentBandPassBox(currentBandPassBox);
864 }
865
866 void MainWindow::onVendorChanged(QString vendor)
867 {
868 if (currentSpeaker.getVendor() == vendor)
869 return;
870
871 if (notInDbSpeaker) {
872 if (vendor == notInDbSpeaker->getVendor())
873 return;
874
875 QMessageBox::StandardButton pressed =
876 QMessageBox::question(this, tr("Unsaved speaker"),
877 tr("This speaker is not present in the database. Would you like to insert it before to continue?"),
878 QMessageBox::Yes|QMessageBox::No);
879 if (pressed == QMessageBox::Yes) {
880 SpeakerDb::insertOrReplace(notInDbSpeaker->getVendor(), notInDbSpeaker->getModel(), *notInDbSpeaker);
881 notInDbSpeaker = nullptr;
882 } else /* no insert wanted */ {
883 if (0 == SpeakerDb::getByVendor(notInDbSpeaker->getVendor()).count()) {
884 /* forget entries */
885 ui->vendorComboBox->removeItem(ui->vendorComboBox->findText(notInDbSpeaker->getVendor()));
886 ui->modelComboBox->removeItem(ui->modelComboBox->findText(notInDbSpeaker->getModel()));
887 } else {
888 /* forget model */
889 ui->modelComboBox->removeItem(ui->modelComboBox->findText(notInDbSpeaker->getModel()));
890 }
891 notInDbSpeaker = nullptr;
892 }
893 }
894
895 this->commandStack->beginMacro("changing loudspeaker");
896 VendorCommand* com = new VendorCommand (currentSpeaker.getVendor(), vendor, currentSpeaker, this);
897 this->commandStack->push(com);
898 }
899
900 void MainWindow::changeVendor(const QString& vendor, const Speaker& oldspeaker)
901 {
902 ui->vendorComboBox->setCurrentIndex(ui->vendorComboBox->findText(vendor));
903
904 /* fill speakers of this vendor */
905 ui->modelComboBox->clear();
906 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(vendor));
907
908 /* if we come back to a previous vendor, set last vendor's selected speaker */
909 if (oldspeaker.getVendor() == vendor) {
910 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(oldspeaker.getModel()));
911 setCurrentSpeaker(SpeakerDb::getByVendorAndModel(vendor, oldspeaker.getModel()));
912 } else {
913 /* insert a fake speaker to let the choice to the user */
914 ui->modelComboBox->insertItem(0, "?");
915 ui->modelComboBox->setCurrentIndex(0);
916 setCurrentSpeaker(Speaker());
917 }
918 }
919
920 void MainWindow::onModelChanged(QString model)
921 {
922 if (model.isNull() || model.isEmpty())
923 return;
924
925 if (currentSpeaker.getModel() == model)
926 return;
927
928 if (notInDbSpeaker) {
929 if (model == notInDbSpeaker->getModel())
930 return;
931
932 QMessageBox::StandardButton pressed =
933 QMessageBox::question(this, tr("Unsaved speaker"),
934 tr("This speaker is not present in the database. Would you like to insert it before to continue?"),
935 QMessageBox::Yes|QMessageBox::No);
936 if (pressed == QMessageBox::Yes) {
937 SpeakerDb::insertOrReplace(notInDbSpeaker->getVendor(), notInDbSpeaker->getModel(), *notInDbSpeaker);
938 notInDbSpeaker = nullptr;
939 } else /* no insert wanted */ {
940 if (0 == SpeakerDb::getByVendor(notInDbSpeaker->getVendor()).count()) {
941 /* forget entries */
942 ui->vendorComboBox->removeItem(ui->vendorComboBox->findText(notInDbSpeaker->getVendor()));
943 ui->modelComboBox->removeItem(ui->modelComboBox->findText(notInDbSpeaker->getModel()));
944 } else {
945 /* forget model */
946 ui->modelComboBox->removeItem(ui->modelComboBox->findText(notInDbSpeaker->getModel()));
947 }
948 notInDbSpeaker = nullptr;
949 }
950 }
951
952 oldSpeaker = currentSpeaker;
953
954 ModelCommand* com = new ModelCommand (currentSpeaker.getModel(), model, this);
955 this->commandStack->push(com);
956
957 if (oldSpeaker.getVendor() != currentSpeaker.getVendor()) {
958 oldSpeaker = currentSpeaker;
959 this->commandStack->endMacro();
960 }
961 }
962
963 void MainWindow::changeModel(const QString& model)
964 {
965 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(model));
966
967 /* change model */
968 if ((ui->modelComboBox->findText("?") == 0) && (ui->modelComboBox->currentIndex() != 0)) {
969 /* user choose a speaker; safely remove fake speaker */
970 ui->modelComboBox->removeItem(0);
971 }
972
973 QString vendor = ui->vendorComboBox->currentText();
974 setCurrentSpeaker(SpeakerDb::getByVendorAndModel(vendor, model));
975 }
976
977 void MainWindow::onCurrentSpeakerChanged(const Speaker &spk)
978 {
979 ui->fsValueLabel->setNum(spk.getFs());
980 ui->qtsValueLabel->setNum(spk.getQts());
981 ui->vasValueLabel->setNum(spk.getVas());
982 ui->diaValueLabel->setNum(spk.getDia());
983 ui->zValueLabel->setNum(spk.getZ());
984 ui->vcValueLabel->setNum(spk.getVc());
985
986 /* the user may have activated the "?" fake speaker */
987 if (!spk.isValid()) {
988 qDebug() << "invalid speaker, not computing.";
989 return;
990 }
991
992 projectSaved = false;
993 syncUiFromCurrentSealedBox(currentSealedBox);
994 syncUiFromCurrentPortedBox(currentPortedBox);
995 syncUiFromCurrentBandPassBox(currentBandPassBox);
996 }
997
998 void MainWindow::onSealedVolumeDoubleSpinChanged(double val)
999 {
1000 SealedVolumeCommand* com = new SealedVolumeCommand (currentSealedBox.getVolume(), val, this);
1001 this->commandStack->push(com);
1002 }
1003
1004 void MainWindow::changeSealedVolume(double val)
1005 {
1006 currentSealedBox.setVolume(val);
1007 syncUiFromCurrentSealedBox(currentSealedBox);
1008 }
1009
1010 void MainWindow::onCurrentSealedBoxChanged(const SealedBox &box)
1011 {
1012 if (!currentSpeaker.isValid())
1013 return;
1014
1015 projectSaved = false;
1016 syncUiFromCurrentSealedBox(box);
1017 }
1018
1019 void MainWindow::onPortedVolumeDoubleSpinChanged(double val)
1020 {
1021 PortedVolumeCommand* com = new PortedVolumeCommand (currentPortedBox.getBoxVolume(), val, this);
1022 this->commandStack->push(com);
1023 }
1024
1025 void MainWindow::changePortedVolume(double val)
1026 {
1027 currentPortedBox.setBoxVolume(val);
1028 currentPortedBox.updatePorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
1029 syncUiFromCurrentPortedBox(currentPortedBox);
1030 }
1031
1032 void MainWindow::onPortedResonanceDoubleSpinChanged(double val)
1033 {
1034 PortedResFreqCommand* com = new PortedResFreqCommand (currentPortedBox.getResFreq(), val, this);
1035 this->commandStack->push(com);
1036 }
1037
1038 void MainWindow::changePortedResFreq(double val)
1039 {
1040 currentPortedBox.setResFreq(val);
1041 currentPortedBox.updatePorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
1042 syncUiFromCurrentPortedBox(currentPortedBox);
1043 }
1044
1045 void MainWindow::onPortedPortsNumberSpinChanged(int val)
1046 {
1047 PortedPortNumberCommand* com = new PortedPortNumberCommand (currentPortedBox.getPortNum(), val, this);
1048 this->commandStack->push(com);
1049 }
1050
1051 void MainWindow::changePortedPortNumber(unsigned int val)
1052 {
1053 currentPortedBox.setPortNum(val);
1054 currentPortedBox.updatePorts(currentSpeaker.getSd()* currentSpeakerNumber, currentSpeaker.getXmax());
1055 syncUiFromCurrentPortedBox(currentPortedBox);
1056 }
1057
1058 void MainWindow::onPortedPortDiameterDoubleSpinChanged(double val)
1059 {
1060 /* allow manual decrease/increase of port diameter */
1061 PortedPortDiamCommand* com = new PortedPortDiamCommand (currentPortedBox.getPortDiam(), val, this);
1062 this->commandStack->push(com);
1063 }
1064
1065 void MainWindow::changePortedPortDiam(double val)
1066 {
1067 currentPortedBox.setPortDiam(val);
1068 currentPortedBox.updateSlots();
1069 currentPortedBox.updatePortsLength();
1070 syncUiFromCurrentPortedBox(currentPortedBox);
1071 }
1072
1073 void MainWindow::onPortedSlotPortActivated(bool checked)
1074 {
1075 PortedSlotPortCommand* com = new PortedSlotPortCommand (this->currentPortedBox.getSlotPortActivated(), checked, this);
1076 this->commandStack->push(com);
1077 }
1078
1079 void MainWindow::changePortedSlotPortActivation(bool checked)
1080 {
1081 currentPortedBox.setSlotPortActivated(checked);
1082
1083 ui->portedPortSlotWidthDoubleSpinBox->setEnabled(checked);
1084 ui->portedPortSlotHeightLineEdit->setEnabled(checked);
1085
1086 syncUiFromCurrentPortedBox(currentPortedBox);
1087 }
1088
1089 void MainWindow::onPortedSlotWidthDoubleSpinChanged(double val)
1090 {
1091 PortedSlotWidthCommand* com = new PortedSlotWidthCommand (currentPortedBox.getSlotWidth(), val, this);
1092 this->commandStack->push(com);
1093 }
1094
1095 void MainWindow::changePortedSlotWidth(double val)
1096 {
1097 currentPortedBox.setSlotWidth(val);
1098 syncUiFromCurrentPortedBox(currentPortedBox);
1099 }
1100
1101 void MainWindow::onCurrentPortedBoxChanged(const PortedBox &box)
1102 {
1103 if (!currentSpeaker.isValid())
1104 return;
1105
1106 projectSaved = false;
1107 syncUiFromCurrentPortedBox(box);
1108 }
1109
1110 void MainWindow::onBandPassSealedVolumeDoubleSpinChanged(double val)
1111 {
1112 BPSealedVolumeCommand* com = new BPSealedVolumeCommand (currentBandPassBox.getSealedBoxVolume(), val, this);
1113 this->commandStack->push(com);
1114 }
1115
1116 void MainWindow::changeBPSealedVolume(double val)
1117 {
1118 currentBandPassBox.setSealedBoxVolume(val);
1119 syncUiFromCurrentBandPassBox(currentBandPassBox);
1120 }
1121
1122 void MainWindow::onBandPassPortedVolumeDoubleSpinChanged(double val)
1123 {
1124 BPPortedVolumeCommand* com = new BPPortedVolumeCommand (currentBandPassBox.getPortedBoxVolume(), val, this);
1125 this->commandStack->push(com);
1126 }
1127
1128 void MainWindow::changeBPPortedVolume(double val)
1129 {
1130 currentBandPassBox.setPortedBoxVolume(val);
1131 currentBandPassBox.updatePortedBoxPorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
1132 syncUiFromCurrentBandPassBox(currentBandPassBox);
1133 }
1134
1135 void MainWindow::onBandPassPortedResonanceDoubleSpinChanged(double val)
1136 {
1137 BPPortedResFreqCommand* com = new BPPortedResFreqCommand (currentBandPassBox.getPortedBoxResFreq(), val, this);
1138 this->commandStack->push(com);
1139 }
1140
1141 void MainWindow::changeBPPortedResFreq(double val)
1142 {
1143 currentBandPassBox.setPortedBoxResFreq(val);
1144 currentBandPassBox.updatePortedBoxPorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
1145 syncUiFromCurrentBandPassBox(currentBandPassBox);
1146 }
1147
1148 void MainWindow::onBandPassPortNumSpinChanged(int val)
1149 {
1150 BPPortedPortNumberCommand* com = new BPPortedPortNumberCommand (currentBandPassBox.getPortedBoxPortNum(), val, this);
1151 this->commandStack->push(com);
1152 }
1153
1154 void MainWindow::changeBPPortedPortNumber(double val)
1155 {
1156 currentBandPassBox.setPortedBoxPortNum(val);
1157 currentBandPassBox.updatePortedBoxPorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
1158 syncUiFromCurrentBandPassBox(currentBandPassBox);
1159 }
1160
1161 void MainWindow::onBandPassPortDiameterDoubleSpinChanged(double val)
1162 {
1163 /* allow manual decrease/increase of port diameter */
1164 BPPortedPortDiamCommand* com = new BPPortedPortDiamCommand (currentBandPassBox.getPortedBoxPortDiam(), val, this);
1165 this->commandStack->push(com);
1166 }
1167
1168 void MainWindow::changeBPPortedPortDiam(double val)
1169 {
1170 currentBandPassBox.setPortedBoxPortDiam(val);
1171 currentBandPassBox.updatePortedBoxPortsLength();
1172 syncUiFromCurrentBandPassBox(currentBandPassBox);
1173 }
1174
1175 void MainWindow::onCurrentBandPassBoxChanged(const BandPassBox &box)
1176 {
1177 if (!currentSpeaker.isValid())
1178 return;
1179
1180 projectSaved = false;
1181 syncUiFromCurrentBandPassBox(box);
1182 }

  ViewVC Help
Powered by ViewVC 1.1.26