/[qspeakers]/mainwindow.cpp
ViewVC logotype

Contents of /mainwindow.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26