Entropy Piano Tuner  1.1.3 (documentation not yet complete)
An open-source experimental software for piano tuning by entropy minimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mainwindow.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright 2015 Haye Hinrichsen, Christoph Wick
3  *
4  * This file is part of Entropy Piano Tuner.
5  *
6  * Entropy Piano Tuner is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * Entropy Piano Tuner is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * Entropy Piano Tuner. If not, see http://www.gnu.org/licenses/.
18  *****************************************************************************/
19 
20 #include "mainwindow.h"
21 #include "ui_mainwindow.h"
22 #include "../core/messages/message.h"
23 #include "../core/messages/messagehandler.h"
24 #include "../core/messages/messagemodechanged.h"
25 #include "../core/messages/messageprojectfile.h"
26 #include "../core/messages/messagekeyselectionchanged.h"
27 #include "../core/messages/messagerecorderenergychanged.h"
28 #include "../core/messages/messagefinalkey.h"
29 #include "../core/messages/messagecaluclationprogress.h"
30 #include "../core/messages/messagenewfftcalculated.h"
31 #include "../core/system/version.h"
32 #include "../core/system/serverinfo.h"
33 #include <QDebug>
34 #include <QCloseEvent>
35 #include <QProcess>
36 #include <QMessageBox>
37 #include <QFileDialog>
38 #include <QToolButton>
39 #include <QStatusBar>
40 #include <QButtonGroup>
41 #include <QWhatsThis>
42 #include <QShortcut>
43 #include <QGuiApplication>
44 #include <QScreen>
45 #include <QCheckBox>
46 #include <QDateTime>
47 #include <QDesktopServices>
48 #include <QUrl>
49 #include <QTextEdit>
50 #include <QTextBrowser>
51 #include <QResource>
52 #include <QDialogButtonBox>
53 #include <QScroller>
54 #include "qtconfig.h"
55 #include "logforqt.h"
56 #include "editpianosheetdialog.h"
57 #include "logviewer.h"
58 #include "settingsforqt.h"
59 #include "options/optionsdialog.h"
61 #include "autoclosingmessagebox.h"
62 #include "aboutdialog.h"
63 #include "displaysize.h"
65 
66 MainWindow::MainWindow(QWidget *parent) :
67  QMainWindow(parent),
68  mIconPostfix((QApplication::primaryScreen()->devicePixelRatio() > 1.5) ? "@2x" : ""),
69  mCore(nullptr),
70  ui(new Ui::MainWindow)
71 {
72  ui->setupUi(this);
73  ui->graphSplitter->setSizes(QList<int>() << 200 << 200);
74 
75  // this is in mm
76  qreal maxDisplaySize = std::max(QGuiApplication::primaryScreen()->physicalSize().width(),
77  QGuiApplication::primaryScreen()->physicalSize().height());
78  new DisplaySizeDefines(maxDisplaySize * 0.0393701, ui->modeToolBar->fontMetrics().height()); // convert mm to inch
79  // switch for testing a display size
80  // new DisplaySizeDefines(DS_XSMALL);
81 
83  ui->controlLayout->addWidget(mVolumeControlGroup, 1);
84  QObject::connect(this, SIGNAL(modeChanged(OperationMode)), mVolumeControlGroup, SLOT(onModeChanged(OperationMode)));
85  QObject::connect(mVolumeControlGroup, SIGNAL(refreshInputLevels()), this, SLOT(onResetNoiseLevel()));
86  QObject::connect(mVolumeControlGroup, SIGNAL(muteMicroToggled(bool)), this, SLOT(onToggleMicroMute(bool)));
87  QObject::connect(mVolumeControlGroup, SIGNAL(muteSpeakerToggled(bool)), this, SLOT(onToggleSpeakerMute(bool)));
88 
90  ui->controlLayout->addWidget(mSignalAnalyzerGroup, 0);
91  QObject::connect(this, SIGNAL(modeChanged(OperationMode)), mSignalAnalyzerGroup, SLOT(onModeChanged(OperationMode)));
92 
94  ui->controlLayout->addWidget(mTuningIndicatorGroup, 1);
95  QObject::connect(this, SIGNAL(modeChanged(OperationMode)), mTuningIndicatorGroup, SLOT(onModeChanged(OperationMode)));
96 
98  qobject_cast<QBoxLayout*>(ui->centralWidget->layout())->addWidget(mKeyboardGraphicsView);
99 
100 
101  // Tool bars
102  int iconSize = ui->modeToolBar->fontMetrics().height();
103  QSize modeIconSize = QSize(iconSize, iconSize) * 2;
104  ui->modeToolBar->setObjectName("modeToolBar");
105  ui->modeToolBar->setIconSize(QSize(iconSize, iconSize) * 2);
106 
107 
108  QScrollArea *modeScrollArea = new QScrollArea;
109  ui->modeToolBar->addWidget(modeScrollArea);
110  modeScrollArea->setWidgetResizable(true);
111  modeScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
112  modeScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
113  modeScrollArea->setStyleSheet("\
114  QScrollArea { background: transparent; } \
115  QScrollArea > QWidget > QWidget { background: transparent; } \
116  ");
117  modeScrollArea->setFrameShape(QFrame::NoFrame);
118  QScroller::grabGesture(modeScrollArea->viewport(), QScroller::LeftMouseButtonGesture);
119  QWidget *modeScrollContents = new QWidget;
120  modeScrollArea->setWidget(modeScrollContents);
121  modeScrollContents->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
122  QVBoxLayout *modeScrollLayout = new QVBoxLayout;
123  modeScrollLayout->setMargin(0);
124  modeScrollLayout->setSpacing(0);
125  modeScrollContents->setLayout(modeScrollLayout);
126 
127  QButtonGroup *group = new QButtonGroup(this);
128 
129  auto createModeToolButton = [this, modeIconSize, group, modeScrollLayout]() {
130  QToolButton *b = new QToolButton(this);
131  group->addButton(b);
132  b->setAutoRaise(true);
133  b->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
134  b->setCheckable(true);
135  b->setIconSize(modeIconSize);
136  b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
137 
138  modeScrollLayout->addWidget(b);
139  return b;
140  };
141 
142  QToolButton *idleButton = createModeToolButton();
143  idleButton->setText(tr("Idle"));
144  idleButton->setIcon(QIcon(":/media/icons/system-idle.png"));
145  idleButton->setWhatsThis(tr("Press this button to switch to the idle mode."));
146  connect(idleButton, SIGNAL(toggled(bool)), this, SLOT(onModeIdle(bool)));
147 
148  QToolButton *recordingButton = createModeToolButton();
149  recordingButton->setText(tr("Record"));
150  recordingButton->setIcon(QIcon::fromTheme("audio-input-microphone", QIcon(":/media/icons/audio-input-microphone.png")));
151  recordingButton->setWhatsThis(tr("Press this button to switch to the recording mode."));
152  connect(recordingButton, SIGNAL(toggled(bool)), this, SLOT(onModeRecord(bool)));
153 
154  QToolButton *calculatingButton = createModeToolButton();
155  calculatingButton->setText(tr("Calculate"));
156  calculatingButton->setIcon(QIcon(":/media/icons/note.png"));
157  calculatingButton->setWhatsThis(tr("Press this button to switch to the calculation mode."));
158  connect(calculatingButton, SIGNAL(toggled(bool)), this, SLOT(onModeCalculate(bool)));
159 
160  QToolButton *tuningButton = createModeToolButton();
161  tuningButton->setText(tr("Tune"));
162  tuningButton->setIcon(QIcon(":/media/icons/wrest.png"));
163  tuningButton->setWhatsThis(tr("Press this button to switch to the tuning mode."));
164  connect(tuningButton, SIGNAL(toggled(bool)), this, SLOT(onModeTune(bool)));
165 
166  idleButton->setChecked(true);
167 
168  modeScrollLayout->addStretch();
169 
170  mModeToolButtons[MODE_IDLE] = idleButton;
171  mModeToolButtons[MODE_RECORDING] = recordingButton;
172  mModeToolButtons[MODE_CALCULATION] = calculatingButton;
173  mModeToolButtons[MODE_TUNING] = tuningButton;
174 
175  // helper function to get default icon from system or from local icon theme
176  auto iconFromTheme = [](const QString &s) {return QIcon::fromTheme(s, QIcon(":/media/icons/" + s + ".png"));};
177 
178  // file tool bar, containing most relevant buttons
179  mFileToolBar = new QToolBar(tr("Documents and tools"));
180  mFileToolBar->setObjectName("fileToolBar");
181  addToolBar(Qt::TopToolBarArea, mFileToolBar);
182  mFileToolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::LeftToolBarArea);
183  mFileToolBar->setMovable(false);
184  mFileToolBar->setIconSize(QSize(iconSize, iconSize) * 1.5);
185  mFileToolBar->addAction(iconFromTheme("document-new"), tr("New"), this, SLOT(onFileNew()));
186  mFileToolBar->addAction(iconFromTheme("document-open"), tr("Open"), this, SLOT(onFileOpen()));
187  mFileToolBar->addAction(iconFromTheme("document-save"), tr("Save"), this, SLOT(onFileSave()));
188  mFileToolBar->addAction(iconFromTheme("document-save-as"), tr("Save as"), this, SLOT(onFileSaveAs()));
189  mFileToolBar->addAction(iconFromTheme("accessories-text-editor"), tr("Edit piano data sheet"), this, SLOT(onEditPianoDataSheet()));
190  mFileToolBar->addAction(iconFromTheme("edit-clear"), tr("Clear pitch markers"), this, SLOT(onResetRecording()));
191  mFileToolBar->addSeparator();
192  mFileToolBar->addAction(iconFromTheme("preferences-system"), tr("Options"), this, SLOT(onOptions()));
193  mFileToolBar->addAction(QIcon(":/media/icons/mathematical_plot.png"), tr("Graphs"), this, SLOT(onOpenPlots()));
194 
195  QToolBar *helpToolBar = new QToolBar(tr("Help"));
196  helpToolBar->setObjectName("helpToolBar");
197  addToolBar(Qt::TopToolBarArea, helpToolBar);
198  helpToolBar->setMovable(false);
199  helpToolBar->setFloatable(false);
200  helpToolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::LeftToolBarArea);
201  helpToolBar->setIconSize(mFileToolBar->iconSize());
202 
203  QWidget *tbStretch = new QWidget;
204  helpToolBar->addWidget(tbStretch);
205  tbStretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
206  tbStretch->setVisible(true);
207 
208  helpToolBar->addAction(iconFromTheme("help-contents"), tr("Tutorial"), this, SLOT(onTutorial()));
209  //helpToolBar->addAction(iconFromTheme("accessories-text-editor"), tr("Log"), this, SLOT(onViewLog()));
210  helpToolBar->addAction(iconFromTheme("help-about"), tr("About"), this, SLOT(onAbout()));
211 
212 
213  // main menu icons
214 #if CONFIG_MENU_ICONS
215  ui->action_New->setIcon(iconFromTheme("document-new"));
216  ui->actionOpen->setIcon(iconFromTheme("document-open"));
217  ui->actionSave->setIcon(iconFromTheme("document-save"));
218  ui->actionSave_As->setIcon(iconFromTheme("document-save-as"));
219  ui->actionExit->setIcon(iconFromTheme("application-exit"));
220  ui->actionEdit_piano_data_sheet->setIcon(iconFromTheme("accessories-text-editor"));
221  ui->actionClear_pitches->setIcon(iconFromTheme("edit-clear"));
222  ui->actionOptions->setIcon(iconFromTheme("preferences-system"));
223  ui->actionTutorial->setIcon(iconFromTheme("help-contents"));
224  ui->actionView_log->setIcon(iconFromTheme("accessories-text-editor"));
225  ui->actionAbout->setIcon(iconFromTheme("help-about"));
226 #endif
227 
228 #ifdef Q_OS_DESKTOP
229  // enable export button
230  QAction *exportAction = new QAction(tr("Export"), ui->menuFile);
231  QObject::connect(exportAction, SIGNAL(triggered(bool)), this, SLOT(onExport()));
232  ui->menuFile->insertAction(ui->actionShare, exportAction);
233  ui->menuFile->insertSeparator(exportAction);
234 #endif
235 
236 #if __APPLE__
237 # if defined(TARGET_IPHONE_SIMULATOR) || defined(TARGET_OS_IPHONE)
238  ui->menuBar->setVisible(false);
239 # endif
240 #endif
241 
242 #ifdef __ANDROID__
243  // show share button on android
244  ui->actionShare->setVisible(true);
245 #endif // __ANDROID__
246 
247 #if EPT_WHATS_THIS_ENABLED
248  QAction *whatsThisAction = QWhatsThis::createAction(this);
249  whatsThisAction->setIcon(QIcon(":/media/icons/help-context.png"));
250  whatsThisAction->setCheckable(true);
251  ui->menuHelp->addAction(whatsThisAction);
252  helpToolBar->addAction(whatsThisAction);
253 #endif // EPT_WHATS_THIS_ENABLED
254 
255  // create shortcuts
256  new QShortcut(QKeySequence(Qt::Key_Tab), this, SLOT(onSelectNextMode()));
257  new QShortcut(QKeySequence(Qt::SHIFT | Qt::Key_Tab), this, SLOT(onSelectPreviousMode()));
258  new QShortcut(QKeySequence(Qt::Key_F11), this, SLOT(onToggleFullscreen()));
259  new QShortcut(QKeySequence(Qt::Key_F), this, SLOT(onToggleFullscreen()));
260  new QShortcut(QKeySequence::FullScreen, this, SLOT(onToggleFullscreen()));
261  new QShortcut(QKeySequence(Qt::Key_Space), this, SLOT(onToggleTuningIndictator()));
262 
263  ui->action_New->setShortcut(QKeySequence::New);
264  ui->actionOpen->setShortcut(QKeySequence::Open);
265  ui->actionSave->setShortcut(QKeySequence::Save);
266  ui->actionSave_As->setShortcut(QKeySequence::SaveAs);
267  ui->actionExit->setShortcut(QKeySequence::Quit);
268  ui->actionOptions->setShortcut(QKeySequence::Preferences);
269  ui->actionTutorial->setShortcut(QKeySequence::HelpContents);
270  ui->actionEdit_piano_data_sheet->setShortcut(QKeySequence(Qt::Key_F9));
271 
272  ui->fourierSpectrumGraphics->setKeyboard(mKeyboardGraphicsView);
273  ui->tuningCurveGraphicsView->setKeyboard(mKeyboardGraphicsView);
274 
275 
276  QBoxLayout *mainLayout = qobject_cast<QBoxLayout*>(centralWidget()->layout());
277  mainLayout->setStretch(0, 0);
278  mainLayout->setStretch(1, 1);
279  mainLayout->setStretch(3, 1);
280 
281 #if CONFIG_DIALOG_SIZE == 1
282  // reset old settings (windows size/position and splitter)
283  QSettings settings;
284  restoreGeometry(settings.value("geometry/mainwindow").toByteArray());
285  restoreState(settings.value("windowState/mainwindow").toByteArray());
286  QList<int> sizes;
287  for (QVariant v : settings.value("splitterSizes/graphSplitter").toList()) {
288  sizes.push_back(v.toInt());
289  }
290  if (sizes.size() > 0) {
291  ui->graphSplitter->setSizes(sizes);
292  }
293  show();
294 #else
295  SHOW_DIALOG(this);
296 #endif // CONFIG_DIALOG_SIZE
297 }
298 
300 {
301  delete ui;
302 }
303 
304 void MainWindow::init(Core *core) {
305  EptAssert(core, "Core is required");
306  mCore = core;
307 
308 
309  qDebug() << "Display size: " << QGuiApplication::primaryScreen()->physicalSize();
310 
312 
313  // hide some elements
314  if (DisplaySizeDefines::getSingleton()->getGraphDisplayMode() == GDM_ONE_VISIBLE) {
315  ui->fourierSpectrumGraphics->setVisible(false); // only visible during recording
316 
317  // hide status bar
318  statusBar()->setHidden(true);
319  }
320 
321  ui->controlLayout->addWidget(mCalculationProgressGroup = new CalculationProgressGroup(mCore, this));
322 }
323 
325  updateVolumeBar();
326 
327  // init the project manager (load startup file)
329 
331 
332  // check for updates
333  VersionCheck *versionChecker = new VersionCheck(this);
334  QObject::connect(versionChecker, SIGNAL(updateAvailable(VersionInformation)), this, SLOT(onVersionUpdate(VersionInformation)));
335 }
336 
337 void MainWindow::closeEvent(QCloseEvent *event)
338 {
339  if (mCore->getProjectManager()->onQuit()) {
340 #if CONFIG_DIALOG_SIZE == 1
341  QSettings settings;
342  settings.setValue("geometry/mainwindow", saveGeometry());
343  settings.setValue("windowState/mainwindow", saveState());
344  QVariantList sizes;
345  for (int s : ui->graphSplitter->sizes()) {
346  sizes.push_back(QVariant(s));
347  }
348  settings.setValue("splitterSizes/graphSplitter", sizes);
349 #endif
350 
351  event->accept();
352  QMainWindow::closeEvent(event);
353  } else {
354  event->ignore();
355  }
356 }
357 
359  switch (m->getType()) {
361  auto mpf(std::static_pointer_cast<MessageProjectFile>(m));
362  switch (mpf->getFileMessageType()) {
364  statusBar()->showMessage(tr("File created"));
365  break;
367  statusBar()->showMessage(tr("File edited"));
368  break;
370  statusBar()->showMessage(tr("File opened"));
371  break;
373  statusBar()->showMessage(tr("File saved"));
374  break;
375  default:
376  LogW("MessagePojectFile::Type Not implemented");
377  break;
378  }
379 
380  break;
381  }
383  auto mmc(std::static_pointer_cast<MessageModeChanged>(m));
384 
385  // check the correct tool button
386  mModeToolButtons[mmc->getMode()]->setChecked(true);
387 
388  emit modeChanged(mmc->getMode());
389 
390  // hide all groups first and enable if required
391  mCalculationProgressGroup->setVisible(false);
392 
393  if (mmc->getMode() == MODE_CALCULATION) {
394  // hide first for correct sizing
395  mCalculationProgressGroup->setVisible(true);
396  if (DisplaySizeDefines::getSingleton()->getGraphDisplayMode() == GDM_ONE_VISIBLE) {
397  ui->fourierSpectrumGraphics->setVisible(false);
398  }
399  } else {
400  // hide first for correct sizing
401  if (DisplaySizeDefines::getSingleton()->getGraphDisplayMode() != GDM_ONE_VISIBLE) {
402  ui->fourierSpectrumGraphics->setVisible(true);
403  }
404  }
405 
406  if (mmc->getMode() == MODE_TUNING) {
407 
408  // perform a small check if tuning is possible
409  int missingKeyRecordings = 0;
410  int missingComputedFrequencies = 0;
411 
412  for (const Key &key : mCore->getPianoManager()->getPiano().getKeyboard().getKeys()) {
413  if (!key.isRecorded()) {
414  missingKeyRecordings++;
415  }
416  if (key.getComputedFrequency() <= 0) {
417  missingComputedFrequencies++;
418  }
419  }
420 
421  // print the result of the check
423  // manually check if reshow, that we reach other else and if's
424  // we do not want to show more than one box at a time
426  }
427  else if (missingComputedFrequencies == mCore->getPianoManager()->getPiano().getKeyboard().getNumberOfKeys()) {
429  } else if (missingComputedFrequencies > 0) {
431  }
432  } else {
433  }
434 
436  break;
437  }
439  statusBar()->showMessage(tr("Recording keystroke"));
440  if (DisplaySizeDefines::getSingleton()->getGraphDisplayMode() == GDM_ONE_VISIBLE) {
441  ui->tuningCurveGraphicsView->setVisible(false);
442  ui->fourierSpectrumGraphics->setVisible(true);
443  }
445  break;
447  statusBar()->showMessage(tr("Signal analysis started"));
448  break;
450  statusBar()->showMessage(tr("Signal analysis ended"));
451  if (DisplaySizeDefines::getSingleton()->getGraphDisplayMode() == GDM_ONE_VISIBLE) {
452  ui->fourierSpectrumGraphics->setVisible(false);
453  ui->tuningCurveGraphicsView->setVisible(true);
454  }
455  break;
457  auto mksc(std::static_pointer_cast<MessageKeySelectionChanged>(m));
458  updateNoteName(mksc->getKeyNumber());
459  updateFrequency(mksc->getKey());
460  break;}
462  auto mrec(std::static_pointer_cast<MessageRecorderEnergyChanged>(m));
463  if (mrec->getLevelType() == MessageRecorderEnergyChanged::LevelType::LEVEL_OFF) {
464  // off level changed, adjust the volume bar indicator positions
465  updateVolumeBar();
466  }
467  break;
468  }
469  case Message::MSG_FINAL_KEY: {
470  auto message(std::static_pointer_cast<MessageFinalKey>(m));
471  auto keyptr = message->getFinalKey(); // get shared pointer to the new key
472  updateFrequency(keyptr.get());
473  break;
474  }
476  auto mcp(std::static_pointer_cast<MessageCaluclationProgress>(m));
477  switch (mcp->getCalculationType()) {
479  statusBar()->showMessage(tr("Calculation failed"));
480  break;
482  statusBar()->showMessage(tr("Calculation ended"));
483  break;
485  statusBar()->showMessage(tr("Calculation started"));
486  break;
487  default:
488  break;
489  }
490  break;
491  }
492  default:
493  break;
494  }
495 }
496 
499 }
500 
502  QString text(QString::fromStdString(mCore->getPianoManager()->getPiano().getKeyboard().getNoteName(key)));
503  // add super script to #
504  text.replace("#", "<sup>#</sup>");
505  //text.replace(QRegExp("([0-9])"), "<sub>\\1</sub>");
507 }
508 
510  if (!key) {
511  mSignalAnalyzerGroup->setFrequency(QString("-"));
512  } else {
513  double frequency = key->getRecordedFrequency();
514  if (mCurrentMode == MODE_TUNING) {
515  frequency = key->getTunedFrequency();
516  }
517  mSignalAnalyzerGroup->setFrequency(QString("%1").arg(frequency, 0, 'f', 1));
518  }
519 }
520 
522  setWindowTitle(tr("Entropy piano tuner") + " - " + QString::fromStdString(mCore->getPianoManager()->getPiano().getName()) + (mCore->getProjectManager()->hasChangesInFile() ? "*" : ""));
523 }
524 
527 }
528 
530  QList<QPair<QString, QStringList> > programNames;
531 #ifdef __linux__
532  programNames.append(qMakePair(QString("pavucontrol"), QStringList()));
533  programNames.append(qMakePair(QString("gnome-control-center"), QStringList() << "sound"));
534 #elif __APPLE__
535  // not supported yet
536  programNames.append(qMakePair(QString("open"), QStringList() << "/System/Library/PreferencePanes/Sound.prefPane/"));
537 #elif _WIN32
538  // untested, see http://support.microsoft.com/kb/192806/de
539  programNames.append(qMakePair(QString("control"), QStringList() << "mmsys.cpl" << "sounds"));
540 #endif
541 
542 #ifdef QT_NO_PROCESS
543  // no processes allowed on the platform (e.g. windows RT)
544 #else
545  QProcess *process = new QProcess(this);
546  for (auto &program : programNames) {
547  process->start(program.first, program.second);
548  if (process->waitForStarted()) {
549  LogI("Sound control program '%s' started", program.first.toStdString().c_str());
550  return;
551  }
552  }
553 
554  // no program could be started
555  QMessageBox::warning(this, tr("Warning"), tr("Unable to find a supported sound control."));
556 #endif
557 }
558 
560 #ifdef __ANDROID__
561  return false;
562 #elif __APPLE__
563 # if TARGET_IPHONE_SIMULATOR
564  return false;
565 # elif TARGET_OS_IPHONE
566  return false;
567 # endif
568 #endif
569 
570  return true;
571 }
572 
575 }
576 
577 void MainWindow::onToggleMicroMute(bool checked) {
578  mCore->getAudioRecorder()->setMuted(checked);
579 }
580 
582  mCore->getAudioPlayer()->setMuted(checked);
583 }
584 
587 }
588 
591 }
592 
595 }
596 
599 }
600 
603  QMessageBox::information(this, tr("Canceled"), tr("You need to save the file before you can share it."));
604  }
605 }
606 
609 }
610 
612  if (DoNotShowAgainMessageBox::show(DoNotShowAgainMessageBox::RESET_PITCHES, this) == QMessageBox::Accepted) {
614  }
615 }
616 
619  options.exec();
620 }
621 
623  PlotsDialog pd(mCore->getPianoManager()->getPiano(), this);
624  pd.exec();
625 }
626 
628  QDialog helpDialog(this, Qt::Window);
629 
630  // if in non maximized mode, the dialog has a size of half the main window
631  QRect mwRect(this->geometry());
632  helpDialog.setGeometry(mwRect.x() + mwRect.width() / 4, mwRect.y() + mwRect.height() / 4,
633  mwRect.width() / 2, mwRect.height() / 2);
634 
635  // create elements
636  QVBoxLayout *mainLayout = new QVBoxLayout;
637  helpDialog.setLayout(mainLayout);
638  QTextBrowser *edit = new QTextBrowser;
639  mainLayout->addWidget(edit);
640  edit->setOpenExternalLinks(true);
641  edit->setReadOnly(true);
642  QString languageStr(QLocale().name());
643  languageStr = languageStr.left(languageStr.indexOf("_"));
644  QFile manual(":/tutorial/tutorial_" + languageStr + ".html");
645 
646  // function to read all text from the given file
647  auto readAllFromFile = [](QFile &f) {
648  QTextStream in(&f);
649  return in.readAll();
650  };
651 
652  // load manual logic (use english if language not found)
653  QString text;
654  if (!manual.open(QFile::ReadOnly | QFile::Text)) {
655  LogW("Manual not found for language %s. Using english as fallback.",
656  languageStr.toStdString().c_str());
657 
658  // use english as fallback
659  QFile enManual(":/tutorial/tutorial_en.html");
660  if (!enManual.open(QFile::ReadOnly | QFile::Text)) {
661  LogE("Engish manual not found. Maybe the location of the manual changed?");
662  text = "No manual found. Please use the online manual instead.";
663  } else {
664  text = readAllFromFile(enManual);
665  }
666  } else {
667  text = readAllFromFile(manual);
668  }
669 
670  // replace media content
671  text.replace(QRegExp("SRC=\"([^\"]*)\""), "SRC=\":/tutorial/\\1\"");
672  edit->setText(text);
673  edit->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
674 
675  QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Close);
676  mainLayout->addWidget(buttons);
677 
678  QObject::connect(buttons, SIGNAL(rejected()), &helpDialog, SLOT(reject()));
679 
680  QScroller::grabGesture(edit);
681 
682  // show maximized as default
683  helpDialog.showMaximized();
684  helpDialog.exec();
685 }
686 
688  QDesktopServices::openUrl(QUrl(serverinfo::getManualFileAddress(SettingsForQt::getSingleton().getUserLanguageId()).c_str()));
689 }
690 
692  AboutDialog d(this, mIconPostfix);
693  d.exec();
694 }
695 
696 
698  LogViewer logViewer(this);
699  logViewer.exec();
700 }
701 
702 void MainWindow::onModeIdle(bool checked) {
703  if (checked) {
705  }
706 }
707 
708 void MainWindow::onModeRecord(bool checked) {
709  if (checked) {
711  }
712 }
713 
714 void MainWindow::onModeCalculate(bool checked) {
715  if (checked) {
717  }
718 }
719 
720 void MainWindow::onModeTune(bool checked) {
721  if (checked) {
723  }
724 }
725 
727  OperationMode mode = static_cast<OperationMode>((mCurrentMode + 1) % MODE_COUNT);
728  mModeToolButtons[mode]->setChecked(true);
729 }
730 
732  OperationMode mode = static_cast<OperationMode>((mCurrentMode - 1 + MODE_COUNT) % MODE_COUNT);
733  mModeToolButtons[mode]->setChecked(true);
734 }
735 
737  if (this->windowState() & Qt::WindowFullScreen) {
738  showNormal();
739  } else {
740  showFullScreen();
741  }
742 }
743 
744 
746 {
749 }
750 
751 
754 }
755 
757  QMessageBox mb;
758  mb.setText(tr("A new update is available!"));
759  mb.setInformativeText(tr("The online app version is %1. Do you want to install this update?").arg(information.mAppVersion));
760  mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
761  if (mb.exec() == QMessageBox::Yes) {
762 #ifdef Q_OS_MACX
763  // download new dmg file
764  if (!QDesktopServices::openUrl(QUrl::fromUserInput(serverinfo::getDownloadsFileAddress(serverinfo::MAC_X86_64_DMG).c_str()))) {
765  LogW("Online installer file for mac could not be found.");
766  QDesktopServices::openUrl(QUrl::fromUserInput(serverinfo::SERVER_ADDRESS.c_str()));
767  } else {
768  this->close();
769  }
770 #else
771 # ifdef QT_NO_PROCESS
772  // no processes allowed on this device, usually mobile devices (e.g. WinRT/WinPhone)
773 # else
774  // run maintenace tool in updater mode
775  if (QProcess::startDetached("maintenancetool", QStringList() << "--updater") == false) {
776  LogW("Maintenace tool could not be started.");
777  QMessageBox::warning(this, tr("Warning"), tr("The maintenance tool could not be started automatically. To update the program you have to start the maintenance tool manually."));
778  } else {
779  // close the program for the installer
780  this->close();
781  }
782 # endif // QT_NO_PROCESS
783 
784 #endif // Q_OS_MACX
785  }
786 }
double getRecordedFrequency() const
Get recorded frequency.
Definition: key.cpp:119
void setMuted(bool muted)
Mute the audio player.
PianoManager * getPianoManager()
Definition: core.h:67
std::shared_ptr< Message > MessagePtr
Global type of a shared message pointer.
Definition: message.h:98
void changesInFileUpdated(bool b) overridefinal
Called if changed in file are made to update the window title.
Definition: mainwindow.cpp:497
void updateVolumeBar()
This will update the positions of the labels in the volume bar.
Definition: mainwindow.cpp:525
const Key * getSelectedKey() const
void updateWindowTitle()
Update the window title.
Definition: mainwindow.cpp:521
TuningIndicatorView * getTunincIndicatorView()
QToolBar * mFileToolBar
Definition: mainwindow.h:168
void onOptions()
Slot to open the options.
Definition: mainwindow.cpp:617
OperationMode
Operation mode of the tuner.
Definition: prerequisites.h:66
void setCallback(FileChangesCallback *cb)
Set a callback function for file changes.
void toggleSpectralAndStroboscopeMode()
Toggle between spectral and stroboscopic operation mode.
void setMuted(bool muted)
Set and reset the muting flag.
void updateFrequency(const Key *key)
Update the frequency label.
Definition: mainwindow.cpp:509
void onOpenPlots()
Slot to open the mathematical plots dialog.
Definition: mainwindow.cpp:622
void onOpenSoundControl()
Slot to open the sound control.
Definition: mainwindow.cpp:529
void onFileSaveAs()
Slot to save the current file as a new file.
Definition: mainwindow.cpp:593
static const double LEVEL_TRIGGER
Level above which the recorder starts to operate.
void onResetRecording()
Slot to reset the recording.
Definition: mainwindow.cpp:611
#define LogW(...)
Definition: log.h:56
virtual ~MainWindow()
Destructor.
Definition: mainwindow.cpp:299
OperationMode mCurrentMode
void onSelectNextMode()
Slot to select the next mode.
Definition: mainwindow.cpp:726
void onManual()
Slot to open the manual.
Definition: mainwindow.cpp:687
Message that a change was made with the current project file.
Definition: message.h:68
Class describing a single piano key.
Definition: key.h:45
void onViewLog()
Slot to open the log viewer.
Definition: mainwindow.cpp:697
std::string getManualFileAddress(const std::string &langCode)
Definition: serverinfo.cpp:32
#define SHOW_DIALOG(d)
Definition: qtconfig.h:41
CalculationProgressGroup * mCalculationProgressGroup
Pointer to the CalculationProgressGroup.
Definition: mainwindow.h:155
Message that the operation mode has changed.
Definition: message.h:65
void onModeTune(bool)
Slot to switch to tuning mode.
Definition: mainwindow.cpp:720
void onAbout()
Slot to open the about dialog.
Definition: mainwindow.cpp:691
void updateNoteName(int key)
Update the note name.
Definition: mainwindow.cpp:501
Piano & getPiano()
Definition: pianomanager.h:45
std::string getDownloadsFileAddress(const std::string &filename)
Definition: serverinfo.cpp:24
void resetPitches()
Reset all recorded keys and send a message to redraw all elements.
void onFileSave()
Slot to save the current file.
Definition: mainwindow.cpp:589
QToolButton * mModeToolButtons[OperationMode::MODE_COUNT]
Tool buttons for all modes.
Definition: mainwindow.h:171
Mode where the entropy optimization is carried out.
Definition: prerequisites.h:70
Mode for recording the piano keys.
Definition: prerequisites.h:69
Message that a key has been selected.
Definition: message.h:63
The count of modes.
Definition: prerequisites.h:73
AudioPlayerAdapter * getAudioPlayer()
Definition: core.h:66
void onExport()
Slot to open the export dialog.
Definition: mainwindow.cpp:752
void onSelectPreviousMode()
Slot to select the previous mode.
Definition: mainwindow.cpp:731
Visible QGroupBox to handle the calculation.
Keys & getKeys()
Definition: keyboard.h:69
const Keyboard & getKeyboard() const
Definition: piano.h:83
recording input level has changed
Definition: message.h:69
void start()
Starts the main window.
Definition: mainwindow.cpp:324
analysis of the signal started
Definition: message.h:53
std::string getNoteName(int keynumber) const
Get the name of the key as a string.
Definition: keyboard.cpp:135
Ui::MainWindow * ui
Ui of the Mainwindow.
Definition: mainwindow.h:152
double getStopLevel() const
Results onNewFile()
New-file menu response.
ProjectManagerAdapter * getProjectManager()
Definition: core.h:64
#define LogI(...)
Definition: log.h:50
void init(Core *core)
Initialize the project management adapter.
Core * mCore
Pointer to the Core.
Definition: mainwindow.h:149
void onTutorial()
Definition: mainwindow.cpp:627
void resetInputLevelControl()
Reset input level control.
MainWindow(QWidget *parent=nullptr)
Constructor.
Definition: mainwindow.cpp:66
#define LogE(...)
Definition: log.h:62
Message that progress of any kind was made by the calculator.
Definition: message.h:59
void modeChanged(OperationMode mode)
void updateLevels(double stopLevel, double onLevel)
Mode for manually tuning the piano.
Definition: prerequisites.h:71
void setMode(OperationMode m)
Set operation mode.
KeyboardGraphicsView * mKeyboardGraphicsView
Definition: mainwindow.h:166
const QString mIconPostfix
Definition: mainwindow.h:146
void onToggleFullscreen()
Slot to toggle full screen of the MainWindow.
Definition: mainwindow.cpp:736
void onFileShare()
Slot to store the current file.
Definition: mainwindow.cpp:601
final key information after recording
Definition: message.h:55
void onModeCalculate(bool)
Slot to switch to calculation mode.
Definition: mainwindow.cpp:714
CORE : Class managing the core.
Definition: core.h:45
void onFileOpen()
Slot to open a new file.
Definition: mainwindow.cpp:597
void onToggleSpeakerMute(bool checked)
Toggle the mute button.
Definition: mainwindow.cpp:581
static int show(Type type, const QString text, QWidget *parent=nullptr)
Show a message box if the user didnt check the QCheckBox.
bool isSoundControlSupported()
Definition: mainwindow.cpp:559
VolumeControlGroupBox * mVolumeControlGroup
Pointer to the VolumeControlGroupBox.
Definition: mainwindow.h:164
void onToggleTuningIndictator()
Slot to toggle between the two tuning indicator modes.
Definition: mainwindow.cpp:745
#define EptAssert(a, b)
Definition: eptexception.h:47
void onVersionUpdate(VersionInformation information)
Definition: mainwindow.cpp:756
Viewer for the keyboard.
static bool doNotShowAgain(Type type)
void onToggleMicroMute(bool checked)
Toggle the mute button.
Definition: mainwindow.cpp:577
void onModeIdle(bool)
Slot to switch to idle mode.
Definition: mainwindow.cpp:702
SignalAnalyzerGroupBox * mSignalAnalyzerGroup
Pointer to the SignalAnalyzerGroupBox.
Definition: mainwindow.h:158
void init(Core *core)
Initialised the window using the given Core.
Definition: mainwindow.cpp:304
void onFileNew()
Slot called for creating a new file.
Definition: mainwindow.cpp:585
static const std::string SERVER_ADDRESS
Definition: serverinfo.h:29
void onEditPianoDataSheet()
Slot to edit the current piano data sheet.
Definition: mainwindow.cpp:607
static const std::unique_ptr< DisplaySizeDefines > & getSingleton()
Definition: displaysize.cpp:29
Do nothing.
Definition: prerequisites.h:68
void onModeRecord(bool)
Slot to switch to recording mode.
Definition: mainwindow.cpp:708
The main window.
Definition: mainwindow.h:49
int getNumberOfKeys() const
Definition: keyboard.h:72
const std::string & getName() const
Definition: piano.h:57
double getTunedFrequency() const
Get tuned frequency.
Definition: key.cpp:193
analysis of the signal ended
Definition: message.h:54
static SettingsForQt & getSingleton()
Getter function for the singleton.
TuningIndicatorGroupBox * mTuningIndicatorGroup
Pointer to the TuningIndicatorGroupBox.
Definition: mainwindow.h:161
void handleMessage(MessagePtr m) override
Message handling.
Definition: mainwindow.cpp:358
void onResetNoiseLevel()
Slot to reset the noise level.
Definition: mainwindow.cpp:573
keystroke recognized and recording started
Definition: message.h:51
void closeEvent(QCloseEvent *event) override
Reimplementation of the close event.
Definition: mainwindow.cpp:337
static const std::string MAC_X86_64_DMG
Definition: serverinfo.h:36
AudioRecorderAdapter * getAudioRecorder()
Definition: core.h:65