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

Contents of /branches/qtcharts/mainwindow.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 220 - (show annotations)
Sun Mar 18 21:16:30 2018 UTC (3 years, 6 months ago) by ben
File size: 33981 byte(s)
added bandpass aligment chooser dialog
1 #include <QtCore>
2 #include <QDebug>
3 #include <QMessageBox>
4 #include <QPrintDialog>
5 #include <QPrinter>
6 #include <QPainter>
7 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
8 #include <QStandardPaths>
9 #endif
10 #include <QDesktopServices>
11
12 #include "mainwindow.h"
13 #include "ui_mainwindow.h"
14
15 #include "speakerdb.h"
16 #include "importexport.h"
17 #include "plot.h"
18 #include "searchdialog.h"
19 #include "listdialog.h"
20 #include "system.h"
21 #include "optimizer.h"
22
23 MainWindow::MainWindow(QWidget *parent) :
24 QMainWindow(parent),
25 ui(new Ui::MainWindow),
26 projectSaved(false),
27 isModifying(false),
28 spkDialog(NULL),
29 fileDialog(NULL),
30 searchDialog(NULL),
31 listDialog(NULL),
32 bandpassDialog(NULL),
33 currentSpeakerNumber(0),
34 currentTabIndex(-1),
35 sealedPlot(NULL),
36 portedPlot(NULL),
37 bandpassPlot(NULL),
38 notInDbSpeaker(NULL)
39 {
40 ui->setupUi(this);
41
42 /* insert QChartView plotters in ui */
43
44 QHBoxLayout *ly1 = new QHBoxLayout(ui->sealedVolumePlotWidget);
45 sealedPlot = new Plot(tr("Sealed volume frequency response"), ui->sealedVolumePlotWidget);
46 sealedPlot->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
47 ly1->insertWidget(0, sealedPlot);
48
49 QHBoxLayout *ly2 = new QHBoxLayout(ui->portedPlotWidget);
50 portedPlot = new Plot(tr("Ported volume frequency response"), ui->portedPlotWidget);
51 portedPlot->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
52 ly2->insertWidget(0, portedPlot);
53
54 QHBoxLayout *ly3 = new QHBoxLayout(ui->bandpassPlotWidget);
55 bandpassPlot = new Plot(tr("Bandpass volumes frequency response"), ui->bandpassPlotWidget);
56 bandpassPlot->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored);
57 ly3->insertWidget(0, bandpassPlot);
58
59 /* test db */
60 if (!SpeakerDb::exists() || (SpeakerDb::lastModified() < SpeakerDb::pkgInstalled())) {
61 QFile pkg_db(SpeakerDb::pkgPath());
62 if (SpeakerDb::merge(pkg_db)) qDebug() << "merged db";
63 }
64
65 /* fill speaker combos */
66 ui->vendorComboBox->addItems(SpeakerDb::getVendors());
67 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(ui->vendorComboBox->currentText()));
68
69 /* restore last saved project... */
70 ImportExport::restoreProject(currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, &currentSpeakerNumber, &currentTabIndex);
71 projectSaved = true;
72
73 /* on first run, no speaker. reset to the speaker of the combos if needed */
74 if (!currentSpeaker.isValid()) {
75 currentSpeaker = SpeakerDb::getByVendorAndModel(ui->vendorComboBox->currentText(), ui->modelComboBox->currentText());
76 }
77
78 /* display sibling number */
79 ui->numberSpinBox->setValue(currentSpeakerNumber);
80
81 /* select restored tab */
82 ui->tabWidget->setCurrentIndex(currentTabIndex);
83
84 /* tab index change is not connected yet, do menu modifications manually */
85 if (currentTabIndex != 1) {
86 /* index != 1 needs to deactivate the ported alignments menu */
87 setActivateActions(ui->menuPorted_alignments->actions(), false);
88 }
89
90 syncUiFromCurrentSpeaker(currentSpeaker);
91 syncUiFromCurrentSealedBox(currentSealedBox);
92 syncUiFromCurrentPortedBox(currentPortedBox);
93 syncUiFromCurrentBandPassBox(currentBandPassBox);
94
95 /* display speaker's values */
96 ui->fsValueLabel->setNum(currentSpeaker.getFs());
97 ui->qtsValueLabel->setNum(currentSpeaker.getQts());
98 ui->vasValueLabel->setNum(currentSpeaker.getVas());
99 ui->sdValueLabel->setNum(currentSpeaker.getSd());
100 ui->reValueLabel->setNum(currentSpeaker.getRe());
101
102 /*
103 * connections
104 */
105
106 /* drivers number spin action */
107 connect(ui->numberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onNumberSpinChanged(int)));
108
109 /* combos action */
110 connect(ui->vendorComboBox, SIGNAL(activated(QString)), this, SLOT(onVendorChanged(QString)));
111 connect(ui->modelComboBox, SIGNAL(activated(QString)), this, SLOT(onModelChanged(QString)));
112
113 /* menu actions */
114 connect(ui->actionProjectSave, SIGNAL(triggered()), this, SLOT(onProjectSave()));
115 connect(ui->actionProjectQuit, SIGNAL(triggered()), this, SLOT(onProjectQuit()));
116 connect(ui->actionSpeakerNew, SIGNAL(triggered()), this, SLOT(onSpeakerNew()));
117 connect(ui->actionSpeakerModify, SIGNAL(triggered()), this, SLOT(onSpeakerModify()));
118 connect(ui->actionSpeakerRemove, SIGNAL(triggered()), this, SLOT(onSpeakerRemove()));
119 connect(ui->actionProjectExport, SIGNAL(triggered()), this, SLOT(onProjectExport()));
120 connect(ui->actionProjectImport, SIGNAL(triggered()), this, SLOT(onProjectImport()));
121 connect(ui->actionEditOptimize, SIGNAL(triggered()), this, SLOT(onEditOptimize()));
122 connect(ui->actionSpeakerSearch, SIGNAL(triggered()), this, SLOT(onSpeakerSearch()));
123 connect(ui->actionProjectPrint, SIGNAL(triggered()), this, SLOT(onProjectPrint()));
124 connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAboutAbout()));
125
126 /* ported alignments sub-menu */
127 connect(ui->actionModerate_Inf, SIGNAL(triggered()), this, SLOT(onAlignModerate_Inf()));
128 connect(ui->actionLegendre, SIGNAL(triggered()), this, SLOT(onAlignLegendre()));
129 connect(ui->actionBessel, SIGNAL(triggered()), this, SLOT(onAlignBessel()));
130 connect(ui->actionBullock, SIGNAL(triggered()), this, SLOT(onAlignBullock()));
131 connect(ui->actionKeele_Hoge, SIGNAL(triggered()), this, SLOT(onAlignKeele_Hoge()));
132
133 /* bandpass alignment */
134 connect(ui->actionBandpass_alignement, SIGNAL(triggered(bool)), this, SLOT(onBandpassAlignment()));
135
136 /* tabs actions */
137 connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(onCurrentTabChanged(int)));
138
139 connect(ui->sealedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onSealedVolumeDoubleSpinChanged(double)));
140
141 connect(ui->portedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedVolumeDoubleSpinChanged(double)));
142 connect(ui->portedResonancedoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedResonanceDoubleSpinChanged(double)));
143 connect(ui->portedPortsNumberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onPortedPortsNumberSpinChanged(int)));
144 connect(ui->portedPortDiameterDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedPortDiameterDoubleSpinChanged(double)));
145 connect(ui->portedPortSlotWidthDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onPortedSlotWidthDoubleSpinChanged(double)));
146
147 connect(ui->bandPassSealedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassSealedVolumeDoubleSpinChanged(double)));
148 connect(ui->bandPassPortedVolumeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortedVolumeDoubleSpinChanged(double)));
149 connect(ui->bandPassPortedResonanceDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortedResonanceDoubleSpinChanged(double)));
150 connect(ui->bandPassPortsNumberSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onBandPassPortNumSpinChanged(int)));
151 connect(ui->bandPassPortDiameterDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onBandPassPortDiameterDoubleSpinChanged(double)));
152
153 /* app state */
154 connect(this, SIGNAL(currentSpeakerChanged(Speaker)), this, SLOT(onCurrentSpeakerChanged(const Speaker&)));
155 connect(this, SIGNAL(currentSealedBoxChanged(SealedBox)), this, SLOT(onCurrentSealedBoxChanged(const SealedBox&)));
156 connect(this, SIGNAL(currentPortedBoxChanged(PortedBox)), this, SLOT(onCurrentPortedBoxChanged(const PortedBox&)));
157 connect(this, SIGNAL(currentBandPassBoxChanged(BandPassBox)), this, SLOT(onCurrentBandPassBoxChanged(const BandPassBox&)));
158
159 }
160
161 MainWindow::~MainWindow()
162 {
163 delete ui;
164 }
165
166 void MainWindow::onProjectSave()
167 {
168 projectSaved = true;
169
170 ImportExport::saveProject(currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, currentSpeakerNumber, currentTabIndex);
171 }
172
173 void MainWindow::onProjectExport()
174 {
175 QString home = MainWindow::getHome();
176 QString fileName = QFileDialog::getSaveFileName(this, tr("Export File"), home + tr("/untitled.qsp"), tr("QSpeakers project (*.qsp)"));
177
178 QFile file(fileName);
179 ImportExport::exportProject(file, currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, currentSpeakerNumber, currentTabIndex);
180 }
181
182 void MainWindow::onProjectImport()
183 {
184 if (!projectSaved) {
185 QMessageBox::StandardButton pressed =
186 QMessageBox::question(this, tr("Project not saved"),
187 tr("The current project has not been saved. Continue anyway?"),
188 QMessageBox::Yes|QMessageBox::No);
189 if (pressed == QMessageBox::No)
190 return;
191 }
192
193 QString home = MainWindow::getHome();
194 QString fileName = QFileDialog::getOpenFileName(this, tr("Import File"), home, tr("QSpeakers project (*.qsp)"));
195
196 /* user cancelled */
197 if (fileName.isEmpty())
198 return;
199
200 QFile file(fileName);
201 ImportExport::importProject(currentSpeaker, currentSealedBox, currentPortedBox, currentBandPassBox, &currentSpeakerNumber, &currentTabIndex, file);
202 ImportExport::setSavePath(fileName);
203 setWindowFilePath(ImportExport::getSavePath());
204
205 ui->numberSpinBox->setValue(currentSpeakerNumber);
206 ui->tabWidget->setCurrentIndex(currentTabIndex);
207
208 syncUiFromCurrentSpeaker(currentSpeaker);
209 syncUiFromCurrentSealedBox(currentSealedBox);
210 syncUiFromCurrentPortedBox(currentPortedBox);
211 syncUiFromCurrentBandPassBox(currentBandPassBox);
212 emit currentSpeakerChanged(currentSpeaker);
213 emit currentSealedBoxChanged(currentSealedBox);
214 emit currentPortedBoxChanged(currentPortedBox);
215 emit currentBandPassBoxChanged(currentBandPassBox);
216 }
217
218 void MainWindow::onProjectQuit()
219 {
220 if (projectSaved) {
221 this->close();
222 return;
223 }
224
225 if (!currentSpeaker.isValid()) {
226 this->close();
227 return;
228 }
229
230 QMessageBox::StandardButton pressed =
231 QMessageBox::question(this, tr("Project not saved"),
232 tr("The current project has not been saved. Exit anyway?"),
233 QMessageBox::Yes|QMessageBox::No);
234 if (pressed == QMessageBox::Yes)
235 this->close();
236 }
237
238 void MainWindow::syncUiFromCurrentSpeaker(const Speaker& spk)
239 {
240 if (!spk.isValid())
241 return;
242
243 /* look if vendor is in the db */
244 QList<Speaker> speakers = SpeakerDb::getByVendor(spk.getVendor());
245
246 if (speakers.count() == 0) {
247 /* if this is an unknown vendor, insert in combo */
248 ui->vendorComboBox->insertItem(0, spk.getVendor());
249 ui->vendorComboBox->setCurrentIndex(0);
250 ui->modelComboBox->clear();
251 /* this means also a new model */
252 ui->modelComboBox->insertItem(0, spk.getModel());
253 ui->modelComboBox->setCurrentIndex(0);
254 notInDbSpeaker = &spk;
255 } else {
256 /* select correct vendor */
257 ui->vendorComboBox->setCurrentIndex(ui->vendorComboBox->findText(spk.getVendor()));
258 /* fill speakers of this vendor */
259 ui->modelComboBox->clear();
260 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(spk.getVendor()));
261
262 for (int i = 0; i < speakers.count(); i++) {
263 Speaker speaker = speakers[i];
264 if (speaker.getModel() == spk.getModel()) {
265 if (speaker != spk) {
266 /* speaker conflict, renaming */
267 currentSpeaker.setModel(speaker.getModel() + "*");
268 ui->modelComboBox->addItem(spk.getModel());
269 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(spk.getModel()));
270 notInDbSpeaker = &spk;
271 } else {
272 /* okay, select correct combo */
273 ui->modelComboBox->setCurrentIndex(ui->modelComboBox->findText(spk.getModel()));
274 notInDbSpeaker = NULL;
275 }
276 }
277 }
278 }
279 }
280
281 void MainWindow::syncUiFromCurrentSealedBox(const SealedBox& box)
282 {
283 ui->sealedVolumeDoubleSpinBox->setValue(box.getVolume());
284
285 System s(currentSpeaker, &box, currentSpeakerNumber);
286 sealedPlot->clear();
287 for (double f = sealedPlot->getXmin(); f < portedPlot->getXmax(); f *= pow(10, 1.0/100.0)) {
288 double db = s.response(f);
289 sealedPlot->appendPointF(QPointF(f, db));
290 }
291 sealedPlot->draw3dbVLine();
292 }
293
294 void MainWindow::syncUiFromCurrentPortedBox(const PortedBox& box)
295 {
296 ui->portedVolumeDoubleSpinBox->setValue(box.getBoxVolume());
297 ui->portedResonancedoubleSpinBox->setValue(box.getResFreq());
298 ui->portedPortsNumberSpinBox->setValue(box.getPortNum());
299 ui->portedPortDiameterDoubleSpinBox->setValue(box.getPortDiam());
300 ui->portedPortSlotWidthDoubleSpinBox->setValue(box.getSlotWidth());
301 ui->portedPortSlotHeightLineEdit->setText(QString::number(box.getSlotHeight(), 'f', 2));
302 ui->portedPortLengthLineEdit->setText(QString::number(box.getPortLen(), 'f', 2));
303
304 System s(currentSpeaker, &box, currentSpeakerNumber);
305 portedPlot->clear();
306 for (double f = portedPlot->getXmin(); f < portedPlot->getXmax(); f *= pow(10, 1.0/100.0)) {
307 double db = s.response(f);
308 portedPlot->appendPointF(QPointF(f, db));
309 }
310 portedPlot->draw3dbVLine();
311 }
312
313 void MainWindow::syncUiFromCurrentBandPassBox(const BandPassBox& box)
314 {
315 ui->bandPassSealedVolumeDoubleSpinBox->setValue(box.getSealedBoxVolume());
316 ui->bandPassPortedVolumeDoubleSpinBox->setValue(box.getPortedBoxVolume());
317 ui->bandPassPortedResonanceDoubleSpinBox->setValue(box.getPortedBoxResFreq());
318 ui->bandPassPortsNumberSpinBox->setValue(box.getPortedBoxPortNum());
319 ui->bandPassPortDiameterDoubleSpinBox->setValue(box.getPortedBoxPortDiam());
320 ui->bandPassPortLengthLineEdit->setText(QString::number(box.getPortedBoxPortLen(), 'f', 2));
321
322 System s(currentSpeaker, &box, currentSpeakerNumber);
323 bandpassPlot->clear();
324 for (double f = bandpassPlot->getXmin(); f < bandpassPlot->getXmax(); f *= pow(10, 1.0/100.0)) {
325 double db = s.response(f);
326 bandpassPlot->appendPointF(QPointF(f, db));
327 }
328 bandpassPlot->draw3dbVLine();
329 }
330
331 void MainWindow::setCurrentSpeaker(const Speaker &spk)
332 {
333 if ((currentSpeaker.getVendor() == spk.getVendor()) &&
334 (currentSpeaker.getModel() == spk.getModel()))
335 return;
336
337 currentSpeaker = spk;
338 emit currentSpeakerChanged(spk);
339 }
340
341 bool MainWindow::print(QPrinter *printer)
342 {
343 QPainter painter;
344 if (!painter.begin(printer))
345 return false;
346
347 QRect page = printer->pageRect();
348
349 qreal step = page.height() / 8;
350
351 currentSpeaker.render(&painter, QRectF(page.left(), page.top(), page.width(), step));
352
353 if (ui->tabWidget->currentWidget() == ui->sealedTab) {
354 System s(currentSpeaker, &currentSealedBox, currentSpeakerNumber);
355 s.render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() / 16));
356 step += page.height() / 16;
357 currentSealedBox.render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() / 16));
358 step += page.height() / 16;
359 sealedPlot->setUseOpenGL(false);
360 sealedPlot->render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() - step));
361 sealedPlot->setUseOpenGL(true);
362 } else if (ui->tabWidget->currentWidget() == ui->portedTab) {
363 System s(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
364 s.render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() / 16));
365 step += page.height() / 16;
366 currentPortedBox.render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() / 16));
367 step += page.height() / 16;
368 portedPlot->setUseOpenGL(false);
369 portedPlot->render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() - step));
370 portedPlot->setUseOpenGL(true);
371 } else {
372 System s(currentSpeaker, &currentBandPassBox, currentSpeakerNumber);
373 s.render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height()/ 16));
374 step += page.height() / 16;
375 currentBandPassBox.render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() / 16));
376 step += page.height() / 16;
377 bandpassPlot->setUseOpenGL(false);
378 bandpassPlot->render(&painter, QRectF(page.left(), page.top() + step, page.width(), page.height() - step));
379 bandpassPlot->setUseOpenGL(true);
380 }
381
382 painter.end();
383 return true;
384 }
385
386 QString MainWindow::getHome()
387 {
388 QString home;
389 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
390 home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
391 #else
392 home = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
393 #endif
394 return home;
395 }
396
397 void MainWindow::onBandpassAlignment()
398 {
399 bandpassDialog = new BandpassDialog(this);
400 connect(bandpassDialog, SIGNAL(optimizeRequested(double, double)), this, SLOT(onBandpassOptimizeRequested(double, double)));
401 connect(bandpassDialog, SIGNAL(optimizeCancelled()), this, SLOT(onBandpassOptimizeCancelled()));
402 bandpassDialog->show();
403 }
404
405 void MainWindow::onBandpassOptimizeRequested(double s, double pa)
406 {
407 if (ui->tabWidget->currentWidget() == ui->bandpassTab) {
408 Optimizer optimizer(currentSpeaker, &currentBandPassBox, currentSpeakerNumber);
409 optimizer.bandpassAlignS_Pa(s, pa);
410 emit currentBandPassBoxChanged(currentBandPassBox);
411 }
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 delete bandpassDialog;
417 bandpassDialog = NULL;
418 }
419
420 void MainWindow::onBandpassOptimizeCancelled()
421 {
422 disconnect(bandpassDialog, SIGNAL(optimizeRequested(double,double)), this, SLOT(onBandpassOptimizeRequested(double,double)));
423 disconnect(bandpassDialog, SIGNAL(optimizeCancelled()), this, SLOT(onBandpassOptimizeCancelled()));
424 bandpassDialog->close();
425 delete bandpassDialog;
426 bandpassDialog = NULL;
427 }
428
429 void MainWindow::onSpeakerNew()
430 {
431 isModifying = false;
432 spkDialog = new SpeakerDialog(this);
433 connect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
434 connect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
435 spkDialog->show();
436 }
437
438 void MainWindow::onSpeakerRemove()
439 {
440
441 QMessageBox::StandardButton pressed =
442 QMessageBox::question(this,
443 tr("Removal confirmation"),
444 tr("Do you really want to remove this loudspeaker from the database?"),
445 QMessageBox::Yes|QMessageBox::No);
446
447 if (pressed == QMessageBox::No)
448 return;
449
450 QString vendor = currentSpeaker.getVendor();
451 QString model = currentSpeaker.getModel();
452
453 int num = SpeakerDb::getModelsByVendor(currentSpeaker.getVendor()).size();
454 ui->modelComboBox->removeItem(ui->modelComboBox->currentIndex());
455 if (num == 1) {
456 ui->vendorComboBox->removeItem(ui->vendorComboBox->currentIndex());
457 }
458
459 SpeakerDb::removeByVendorAndModel(vendor, model);
460 }
461
462 void MainWindow::onSpeakerModify()
463 {
464 isModifying = true;
465 spkDialog = new SpeakerDialog(currentSpeaker, this);
466 connect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
467 connect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
468 spkDialog->show();
469 }
470
471 void MainWindow::onSpeakerInserted(Speaker spk)
472 {
473 if (isModifying) {
474 int idx;
475 idx = ui->vendorComboBox->currentIndex();
476 ui->vendorComboBox->setItemText(idx, spk.getVendor());
477 idx = ui->modelComboBox->currentIndex();
478 ui->modelComboBox->setItemText(idx, spk.getModel());
479
480 currentSpeaker = spk;
481 emit currentSpeakerChanged(currentSpeaker);
482 } else {
483 int idx = ui->vendorComboBox->findText(spk.getVendor());
484 if (idx == -1)
485 ui->vendorComboBox->addItem(spk.getVendor());
486 else if (idx == ui->vendorComboBox->currentIndex())
487 ui->modelComboBox->addItem(spk.getModel());
488 }
489
490 disconnect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
491 disconnect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
492 spkDialog->close();
493 delete spkDialog;
494 spkDialog = NULL;
495 }
496
497 void MainWindow::onSpeakerCancelled()
498 {
499 disconnect(spkDialog, SIGNAL(speakerInserted(Speaker)), this, SLOT(onSpeakerInserted(Speaker)));
500 disconnect(spkDialog, SIGNAL(speakerCancelled()), this, SLOT(onSpeakerCancelled()));
501 spkDialog->close();
502 delete spkDialog;
503 spkDialog = NULL;
504 }
505
506 void MainWindow::onEditOptimize()
507 {
508 if (ui->tabWidget->currentWidget() == ui->sealedTab) {
509 Optimizer optimizer(currentSpeaker, &currentSealedBox, currentSpeakerNumber);
510 optimizer.genericOptimizeBox();
511 emit currentSealedBoxChanged(currentSealedBox);
512 } else if (ui->tabWidget->currentWidget() == ui->portedTab) {
513 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
514 optimizer.genericOptimizeBox();
515 emit currentPortedBoxChanged(currentPortedBox);
516 } else {
517 Optimizer optimizer(currentSpeaker, &currentBandPassBox, currentSpeakerNumber);
518 optimizer.genericOptimizeBox();
519 emit currentBandPassBoxChanged(currentBandPassBox);
520 }
521 }
522
523 void MainWindow::onAlignModerate_Inf()
524 {
525 if (ui->tabWidget->currentWidget() == ui->portedTab) {
526 Optimizer optimzer(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
527 optimzer.portedAlignModerate_Inf();
528 emit currentPortedBoxChanged(currentPortedBox);
529 }
530 }
531
532 void MainWindow::onAlignLegendre()
533 {
534 if (ui->tabWidget->currentWidget() == ui->portedTab) {
535 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
536 optimizer.portedAlignLegendre();
537 emit currentPortedBoxChanged(currentPortedBox);
538 }
539 }
540
541 void MainWindow::onAlignBessel()
542 {
543 if (ui->tabWidget->currentWidget() == ui->portedTab) {
544 Optimizer optimzer(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
545 optimzer.portedAlignBessel();
546 emit currentPortedBoxChanged(currentPortedBox);
547 }
548 }
549
550 void MainWindow::onAlignKeele_Hoge()
551 {
552 /* BB4 */
553 if (ui->tabWidget->currentWidget() == ui->portedTab) {
554 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
555 optimizer.portedAlignKeele_Hoge();
556 emit currentPortedBoxChanged(currentPortedBox);
557 }
558 }
559
560 void MainWindow::onAlignBullock()
561 {
562 /* SBB4 */
563 if (ui->tabWidget->currentWidget() == ui->portedTab) {
564 Optimizer optimizer(currentSpeaker, &currentPortedBox, currentSpeakerNumber);
565 optimizer.portedAlignBullock();
566 emit currentPortedBoxChanged(currentPortedBox);
567 }
568 }
569
570 void MainWindow::onSpeakerSearch()
571 {
572 searchDialog = new SearchDialog(this);
573 connect(searchDialog, SIGNAL(searchRequested(const QString&, double, double)), this, SLOT(onSearchRequested(const QString&, double, double)));
574 connect(searchDialog, SIGNAL(searchCancelled()), this, SLOT(onSearchCancelled()));
575 searchDialog->show();
576 }
577
578 void MainWindow::onProjectPrint()
579 {
580 QPrinter printer;
581 printer.setCreator("QSpeakers");
582 printer.setOrientation(QPrinter::Landscape);
583 QPrintDialog dialog(&printer, this);
584 if (dialog.exec() == QDialog::Accepted) {
585 print(&printer);
586 }
587 }
588
589 void MainWindow::onAboutAbout()
590 {
591 QMessageBox::about(this, tr("About QSpeakers"),
592 tr("QSpeakers version " VERSION "\n\n"
593 "This program simulates common acoustical enclosures behaviour to help designing loudspeaker systems.\n\n"
594 "This program is free software, copyright (C) 2014 Benoit Rouits <brouits@free.fr> and released under the GNU General Public Lisence "
595 "version 3. It is delivered as is in the hope it can be useful, but with no warranty of correctness."));
596 }
597
598 void MainWindow::onSearchRequested(const QString& param, double min, double max)
599 {
600 disconnect(searchDialog, SIGNAL(searchRequested(const QString&, double, double)), this, SLOT(onSearchRequested(const QString&, double, double)));
601 disconnect(searchDialog, SIGNAL(searchCancelled()), this, SLOT(onSearchCancelled()));
602 searchDialog->close();
603 delete searchDialog;
604 searchDialog = NULL;
605
606 QList<Speaker> speakers = SpeakerDb::getByValue(param, min, max);
607
608 listDialog = new ListDialog(speakers, this);
609 connect(listDialog, SIGNAL(speakerItemSelected(QString, const Speaker&)), this, SLOT(onSpeakerItemSelected(QString, const Speaker&)));
610 connect(listDialog, SIGNAL(speakerItemCancelled()), this, SLOT(onSpeakerItemCancelled()));
611 listDialog->show();
612 }
613
614 void MainWindow::onSearchCancelled()
615 {
616 disconnect(searchDialog, SIGNAL(searchRequested(const QString&, double, double)), this, SLOT(onSearchRequested(const QString&, double, double)));
617 disconnect(searchDialog, SIGNAL(searchCancelled()), this, SLOT(onSearchCancelled()));
618 searchDialog->close();
619 delete searchDialog;
620 searchDialog = NULL;
621 }
622
623 void MainWindow::onSpeakerItemSelected(QString title, const Speaker& speaker)
624 {
625 qDebug() << title;
626 if (speaker.isValid()) {
627 setCurrentSpeaker(speaker);
628 syncUiFromCurrentSpeaker(speaker);
629 }
630
631 disconnect(listDialog, SIGNAL(speakerItemSelected(QString, const Speaker&)), this, SLOT(onSpeakerItemSelected(QString, const Speaker&)));
632 disconnect(listDialog, SIGNAL(speakerItemCancelled()), this, SLOT(onSpeakerItemCancelled()));
633 listDialog->close();
634 delete listDialog;
635 listDialog = NULL;
636 }
637
638 void MainWindow::onSpeakerItemCancelled()
639 {
640 disconnect(listDialog, SIGNAL(speakerItemSelected(QString,const Speaker&)), this, SLOT(onSpeakerItemSelected(QString,const Speaker&)));
641 disconnect(listDialog, SIGNAL(speakerItemCancelled()), this, SLOT(onSpeakerItemCancelled()));
642 listDialog->close();
643 delete listDialog;
644 listDialog = NULL;
645 }
646
647 void MainWindow::setActivateActions(QList<QAction*> actions, bool enable)
648 {
649 for (int i = 0; i < actions.count(); i++) {
650 actions[i]->setEnabled(enable);
651 }
652 }
653
654 void MainWindow::onCurrentTabChanged(int tab)
655 {
656 if (tab == currentTabIndex)
657 return;
658
659 QList<QAction*> alignments = ui->menuPorted_alignments->actions();
660 currentTabIndex = tab;
661
662 switch (tab) {
663 case 0:
664 {
665 setActivateActions(alignments, false);
666 syncUiFromCurrentSealedBox(currentSealedBox);
667 break;
668 }
669 case 1:
670 {
671 setActivateActions(alignments, true);
672 syncUiFromCurrentPortedBox(currentPortedBox);
673 break;
674 }
675 case 2:
676 {
677 setActivateActions(alignments, false);
678 syncUiFromCurrentBandPassBox(currentBandPassBox);
679 break;
680 }
681 default:
682 break;
683 }
684 }
685
686 void MainWindow::onNumberSpinChanged(int number) {
687 if (currentSpeakerNumber == number)
688 return;
689
690 currentSpeakerNumber = number;
691
692 /* the user may have used the "?" fake speaker */
693 if (!currentSpeaker.isValid()) {
694 qDebug() << "invalid speaker, not computing.";
695 return;
696 }
697
698 projectSaved = false;
699 if (ui->tabWidget->currentWidget() == ui->sealedTab)
700 syncUiFromCurrentSealedBox(currentSealedBox);
701 else if (ui->tabWidget->currentWidget() == ui->portedTab)
702 syncUiFromCurrentPortedBox(currentPortedBox);
703 else
704 syncUiFromCurrentBandPassBox(currentBandPassBox);
705 }
706
707 void MainWindow::onVendorChanged(QString vendor)
708 {
709
710 if (notInDbSpeaker) {
711 QMessageBox::StandardButton pressed =
712 QMessageBox::question(this, tr("Unsaved speaker"),
713 tr("This speaker is not present in the database. Would you like to insert it before to continue?"),
714 QMessageBox::Yes|QMessageBox::No);
715 if (pressed == QMessageBox::Yes) {
716 SpeakerDb::insertOrReplace(notInDbSpeaker->getVendor(), notInDbSpeaker->getModel(), *notInDbSpeaker);
717 notInDbSpeaker = NULL;
718 }
719 }
720
721 /* fill speakers of this vendor */
722 ui->modelComboBox->clear();
723 ui->modelComboBox->addItems(SpeakerDb::getModelsByVendor(vendor));
724 /* insert a fake speaker to let the choice to the user */
725 ui->modelComboBox->insertItem(0, "?");
726 ui->modelComboBox->setCurrentIndex(0);
727 setCurrentSpeaker(Speaker());
728 }
729
730 void MainWindow::onModelChanged(QString model)
731 {
732 if (model.isNull() || model.isEmpty())
733 return;
734
735 if (notInDbSpeaker) {
736 QMessageBox::StandardButton pressed =
737 QMessageBox::question(this, tr("Unsaved speaker"),
738 tr("This speaker is not present in the database. Would you like to insert it before to continue?"),
739 QMessageBox::Yes|QMessageBox::No);
740 if (pressed == QMessageBox::Yes) {
741 SpeakerDb::insertOrReplace(notInDbSpeaker->getVendor(), notInDbSpeaker->getModel(), *notInDbSpeaker);
742 notInDbSpeaker = NULL;
743 }
744 }
745
746 if ((ui->modelComboBox->findText("?") == 0) && (ui->modelComboBox->currentIndex() != 0)) {
747 /* user choose a speaker; safely remove fake speaker */
748 ui->modelComboBox->removeItem(0);
749 }
750
751 QString vendor = ui->vendorComboBox->currentText();
752 setCurrentSpeaker(SpeakerDb::getByVendorAndModel(vendor, model));
753 }
754
755 void MainWindow::onCurrentSpeakerChanged(const Speaker &spk)
756 {
757 ui->fsValueLabel->setNum(spk.getFs());
758 ui->qtsValueLabel->setNum(spk.getQts());
759 ui->vasValueLabel->setNum(spk.getVas());
760 ui->sdValueLabel->setNum(spk.getSd());
761 ui->reValueLabel->setNum(spk.getRe());
762
763 /* the user may have activated the "?" fake speaker */
764 if (!spk.isValid()) {
765 qDebug() << "invalid speaker, not computing.";
766 return;
767 }
768
769 projectSaved = false;
770 if (ui->tabWidget->currentWidget() == ui->sealedTab)
771 syncUiFromCurrentSealedBox(currentSealedBox);
772 else if (ui->tabWidget->currentWidget() == ui->portedTab)
773 syncUiFromCurrentPortedBox(currentPortedBox);
774 else
775 syncUiFromCurrentBandPassBox(currentBandPassBox);
776 }
777
778 void MainWindow::onCurrentSealedBoxChanged(const SealedBox &box)
779 {
780 if (!currentSpeaker.isValid())
781 return;
782
783 projectSaved = false;
784 if (ui->tabWidget->currentWidget() == ui->sealedTab)
785 syncUiFromCurrentSealedBox(box);
786 }
787
788 void MainWindow::onCurrentPortedBoxChanged(const PortedBox &box)
789 {
790 if (!currentSpeaker.isValid())
791 return;
792
793 projectSaved = false;
794 if (ui->tabWidget->currentWidget() == ui->portedTab)
795 syncUiFromCurrentPortedBox(box);
796 }
797
798 void MainWindow::onCurrentBandPassBoxChanged(const BandPassBox &box)
799 {
800 if (!currentSpeaker.isValid())
801 return;
802
803 projectSaved = false;
804 if (ui->tabWidget->currentWidget() == ui->bandpassTab)
805 syncUiFromCurrentBandPassBox(box);
806 }
807
808 void MainWindow::onSealedVolumeDoubleSpinChanged(double val)
809 {
810 currentSealedBox.setVolume(val);
811 emit currentSealedBoxChanged(currentSealedBox);
812 }
813
814 void MainWindow::onPortedVolumeDoubleSpinChanged(double val)
815 {
816 currentPortedBox.setBoxVolume(val);
817 currentPortedBox.updatePorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
818 emit currentPortedBoxChanged(currentPortedBox);
819 }
820
821 void MainWindow::onPortedResonanceDoubleSpinChanged(double val)
822 {
823 currentPortedBox.setResFreq(val);
824 currentPortedBox.updatePorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
825 emit currentPortedBoxChanged(currentPortedBox);
826 }
827
828 void MainWindow::onPortedPortsNumberSpinChanged(int val)
829 {
830 currentPortedBox.setPortNum(val);
831 currentPortedBox.updatePorts(currentSpeaker.getSd()* currentSpeakerNumber, currentSpeaker.getXmax());
832 emit currentPortedBoxChanged(currentPortedBox);
833 }
834
835 void MainWindow::onPortedPortDiameterDoubleSpinChanged(double val)
836 {
837 /* allow manual decrease/increase of port diameter */
838 currentPortedBox.setPortDiam(val);
839 currentPortedBox.updateSlots();
840 currentPortedBox.updatePortsLength();
841 emit currentPortedBoxChanged(currentPortedBox);
842 }
843
844 void MainWindow::onPortedSlotWidthDoubleSpinChanged(double val)
845 {
846 currentPortedBox.setSlotWidth(val);
847 emit currentPortedBoxChanged(currentPortedBox);
848 }
849
850 void MainWindow::onBandPassSealedVolumeDoubleSpinChanged(double val)
851 {
852 currentBandPassBox.setSealedBoxVolume(val);
853 emit currentBandPassBoxChanged(currentBandPassBox);
854 }
855
856 void MainWindow::onBandPassPortedVolumeDoubleSpinChanged(double val)
857 {
858 currentBandPassBox.setPortedBoxVolume(val);
859 currentBandPassBox.updatePortedBoxPorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
860 emit currentBandPassBoxChanged(currentBandPassBox);
861 }
862
863 void MainWindow::onBandPassPortedResonanceDoubleSpinChanged(double val)
864 {
865 currentBandPassBox.setPortedBoxResFreq(val);
866 currentBandPassBox.updatePortedBoxPorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
867 emit currentBandPassBoxChanged(currentBandPassBox);
868 }
869
870 void MainWindow::onBandPassPortNumSpinChanged(int val)
871 {
872 currentBandPassBox.setPortedBoxPortNum(val);
873 currentBandPassBox.updatePortedBoxPorts(currentSpeaker.getSd() * currentSpeakerNumber, currentSpeaker.getXmax());
874 emit currentBandPassBoxChanged(currentBandPassBox);
875 }
876 void MainWindow::onBandPassPortDiameterDoubleSpinChanged(double val)
877 {
878 currentBandPassBox.setPortedBoxPortDiam(val);
879 currentBandPassBox.updatePortedBoxPortsLength();
880 emit currentBandPassBoxChanged(currentBandPassBox);
881 }

  ViewVC Help
Powered by ViewVC 1.1.26