Mercurial > hg > sonic-visualiser
comparison main/MainWindow.cpp @ 1523:f73a4e8c7040
Merge from branch 3.0-integration
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2017 16:21:32 +0000 |
parents | f016667b4adb |
children | 44e09e1996a3 |
comparison
equal
deleted
inserted
replaced
1522:a0a37ed3c07a | 1523:f73a4e8c7040 |
---|---|
40 #include "layer/Colour3DPlotLayer.h" | 40 #include "layer/Colour3DPlotLayer.h" |
41 #include "layer/SliceLayer.h" | 41 #include "layer/SliceLayer.h" |
42 #include "layer/SliceableLayer.h" | 42 #include "layer/SliceableLayer.h" |
43 #include "layer/ImageLayer.h" | 43 #include "layer/ImageLayer.h" |
44 #include "layer/RegionLayer.h" | 44 #include "layer/RegionLayer.h" |
45 #include "widgets/Fader.h" | |
46 #include "view/Overview.h" | 45 #include "view/Overview.h" |
47 #include "widgets/PropertyBox.h" | 46 #include "widgets/PropertyBox.h" |
48 #include "widgets/PropertyStack.h" | 47 #include "widgets/PropertyStack.h" |
49 #include "widgets/AudioDial.h" | 48 #include "widgets/AudioDial.h" |
49 #include "widgets/LevelPanWidget.h" | |
50 #include "widgets/LevelPanToolButton.h" | |
50 #include "widgets/IconLoader.h" | 51 #include "widgets/IconLoader.h" |
51 #include "widgets/LayerTreeDialog.h" | 52 #include "widgets/LayerTreeDialog.h" |
52 #include "widgets/ListInputDialog.h" | 53 #include "widgets/ListInputDialog.h" |
53 #include "widgets/SubdividingMenu.h" | 54 #include "widgets/SubdividingMenu.h" |
54 #include "widgets/NotifyingPushButton.h" | 55 #include "widgets/NotifyingPushButton.h" |
55 #include "widgets/KeyReference.h" | 56 #include "widgets/KeyReference.h" |
56 #include "widgets/TransformFinder.h" | 57 #include "widgets/TransformFinder.h" |
57 #include "widgets/LabelCounterInputDialog.h" | 58 #include "widgets/LabelCounterInputDialog.h" |
58 #include "widgets/ActivityLog.h" | 59 #include "widgets/ActivityLog.h" |
59 #include "widgets/UnitConverter.h" | 60 #include "widgets/UnitConverter.h" |
60 #include "audioio/AudioCallbackPlaySource.h" | 61 #include "audio/AudioCallbackPlaySource.h" |
61 #include "audioio/AudioCallbackPlayTarget.h" | 62 #include "audio/AudioCallbackRecordTarget.h" |
62 #include "audioio/AudioTargetFactory.h" | 63 #include "audio/PlaySpeedRangeMapper.h" |
63 #include "audioio/PlaySpeedRangeMapper.h" | |
64 #include "data/fileio/DataFileReaderFactory.h" | 64 #include "data/fileio/DataFileReaderFactory.h" |
65 #include "data/fileio/PlaylistFileReader.h" | 65 #include "data/fileio/PlaylistFileReader.h" |
66 #include "data/fileio/WavFileWriter.h" | 66 #include "data/fileio/WavFileWriter.h" |
67 #include "data/fileio/CSVFileWriter.h" | 67 #include "data/fileio/CSVFileWriter.h" |
68 #include "data/fileio/MIDIFileWriter.h" | 68 #include "data/fileio/MIDIFileWriter.h" |
69 #include "data/fileio/BZipFileDevice.h" | 69 #include "data/fileio/BZipFileDevice.h" |
70 #include "data/fileio/FileSource.h" | 70 #include "data/fileio/FileSource.h" |
71 #include "data/fft/FFTDataServer.h" | |
72 #include "data/midi/MIDIInput.h" | 71 #include "data/midi/MIDIInput.h" |
73 #include "base/RecentFiles.h" | 72 #include "base/RecentFiles.h" |
73 #include "plugin/PluginScan.h" | |
74 #include "transform/TransformFactory.h" | 74 #include "transform/TransformFactory.h" |
75 #include "transform/ModelTransformerFactory.h" | 75 #include "transform/ModelTransformerFactory.h" |
76 #include "base/PlayParameterRepository.h" | 76 #include "base/PlayParameterRepository.h" |
77 #include "base/XmlExportable.h" | 77 #include "base/XmlExportable.h" |
78 #include "widgets/CommandHistory.h" | 78 #include "widgets/CommandHistory.h" |
91 // For version information | 91 // For version information |
92 #include <vamp/vamp.h> | 92 #include <vamp/vamp.h> |
93 #include <vamp-hostsdk/PluginBase.h> | 93 #include <vamp-hostsdk/PluginBase.h> |
94 #include "plugin/api/ladspa.h" | 94 #include "plugin/api/ladspa.h" |
95 #include "plugin/api/dssi.h" | 95 #include "plugin/api/dssi.h" |
96 | |
97 #include <bqaudioio/SystemPlaybackTarget.h> | |
98 #include <bqaudioio/SystemAudioIO.h> | |
96 | 99 |
97 #include <QApplication> | 100 #include <QApplication> |
98 #include <QMessageBox> | 101 #include <QMessageBox> |
99 #include <QGridLayout> | 102 #include <QGridLayout> |
100 #include <QLabel> | 103 #include <QLabel> |
115 #include <QDateTime> | 118 #include <QDateTime> |
116 #include <QProcess> | 119 #include <QProcess> |
117 #include <QCheckBox> | 120 #include <QCheckBox> |
118 #include <QRegExp> | 121 #include <QRegExp> |
119 #include <QScrollArea> | 122 #include <QScrollArea> |
123 #include <QCloseEvent> | |
120 #include <QDesktopServices> | 124 #include <QDesktopServices> |
121 #include <QDialogButtonBox> | 125 #include <QDialogButtonBox> |
122 #include <QFileSystemWatcher> | 126 #include <QFileSystemWatcher> |
127 #include <QTextEdit> | |
123 | 128 |
124 #include <iostream> | 129 #include <iostream> |
125 #include <cstdio> | 130 #include <cstdio> |
126 #include <errno.h> | 131 #include <errno.h> |
127 | 132 |
128 using std::vector; | 133 using std::vector; |
129 using std::map; | 134 using std::map; |
130 using std::set; | 135 using std::set; |
131 | 136 |
132 | 137 |
133 MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : | 138 MainWindow::MainWindow(SoundOptions options, bool withOSCSupport) : |
134 MainWindowBase(withAudioOutput, true), | 139 MainWindowBase(options), |
135 m_overview(0), | 140 m_overview(0), |
136 m_mainMenusCreated(false), | 141 m_mainMenusCreated(false), |
137 m_paneMenu(0), | 142 m_paneMenu(0), |
138 m_layerMenu(0), | 143 m_layerMenu(0), |
139 m_transformsMenu(0), | 144 m_transformsMenu(0), |
153 m_rwdAction(0), | 158 m_rwdAction(0), |
154 m_ffwdAction(0), | 159 m_ffwdAction(0), |
155 m_ffwdSimilarAction(0), | 160 m_ffwdSimilarAction(0), |
156 m_ffwdEndAction(0), | 161 m_ffwdEndAction(0), |
157 m_playAction(0), | 162 m_playAction(0), |
163 m_recordAction(0), | |
158 m_playSelectionAction(0), | 164 m_playSelectionAction(0), |
159 m_playLoopAction(0), | 165 m_playLoopAction(0), |
160 m_soloModified(false), | 166 m_soloModified(false), |
161 m_prevSolo(false), | 167 m_prevSolo(false), |
162 m_playControlsSpacer(0), | 168 m_playControlsSpacer(0), |
205 | 211 |
206 m_mainScroll->setWidget(m_paneStack); | 212 m_mainScroll->setWidget(m_paneStack); |
207 | 213 |
208 m_overview = new Overview(frame); | 214 m_overview = new Overview(frame); |
209 m_overview->setViewManager(m_viewManager); | 215 m_overview->setViewManager(m_viewManager); |
210 m_overview->setFixedHeight(40); | 216 int overviewHeight = m_viewManager->scalePixelSize(35); |
217 if (overviewHeight < 40) overviewHeight = 40; | |
218 m_overview->setFixedHeight(overviewHeight); | |
211 #ifndef _WIN32 | 219 #ifndef _WIN32 |
212 // For some reason, the contents of the overview never appear if we | 220 // For some reason, the contents of the overview never appear if we |
213 // make this setting on Windows. I have no inclination at the moment | 221 // make this setting on Windows. I have no inclination at the moment |
214 // to track down the reason why. | 222 // to track down the reason why. |
215 m_overview->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); | 223 m_overview->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); |
220 m_panLayer = new WaveformLayer; | 228 m_panLayer = new WaveformLayer; |
221 m_panLayer->setChannelMode(WaveformLayer::MergeChannels); | 229 m_panLayer->setChannelMode(WaveformLayer::MergeChannels); |
222 m_panLayer->setAggressiveCacheing(true); | 230 m_panLayer->setAggressiveCacheing(true); |
223 m_overview->addLayer(m_panLayer); | 231 m_overview->addLayer(m_panLayer); |
224 | 232 |
225 if (m_viewManager->getGlobalDarkBackground()) { | 233 coloursChanged(); // sets pan layer colour from preferences |
226 m_panLayer->setBaseColour | |
227 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green"))); | |
228 } else { | |
229 m_panLayer->setBaseColour | |
230 (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); | |
231 } | |
232 | |
233 m_fader = new Fader(frame, false); | |
234 connect(m_fader, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); | |
235 connect(m_fader, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); | |
236 | 234 |
237 m_playSpeed = new AudioDial(frame); | 235 m_playSpeed = new AudioDial(frame); |
238 m_playSpeed->setMinimum(0); | 236 m_playSpeed->setMinimum(0); |
239 m_playSpeed->setMaximum(120); | 237 m_playSpeed->setMaximum(120); |
240 m_playSpeed->setValue(60); | 238 m_playSpeed->setValue(60); |
241 m_playSpeed->setFixedWidth(32); | 239 m_playSpeed->setFixedWidth(overviewHeight); |
242 m_playSpeed->setFixedHeight(32); | 240 m_playSpeed->setFixedHeight(overviewHeight); |
243 m_playSpeed->setNotchesVisible(true); | 241 m_playSpeed->setNotchesVisible(true); |
244 m_playSpeed->setPageStep(10); | 242 m_playSpeed->setPageStep(10); |
245 m_playSpeed->setObjectName(tr("Playback Speed")); | 243 m_playSpeed->setObjectName(tr("Playback Speed")); |
246 m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper); | 244 m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper); |
247 m_playSpeed->setDefaultValue(60); | 245 m_playSpeed->setDefaultValue(60); |
249 connect(m_playSpeed, SIGNAL(valueChanged(int)), | 247 connect(m_playSpeed, SIGNAL(valueChanged(int)), |
250 this, SLOT(playSpeedChanged(int))); | 248 this, SLOT(playSpeedChanged(int))); |
251 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); | 249 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); |
252 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); | 250 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); |
253 | 251 |
254 IconLoader il; | 252 m_mainLevelPan = new LevelPanToolButton(frame); |
253 connect(m_mainLevelPan, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); | |
254 connect(m_mainLevelPan, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); | |
255 m_mainLevelPan->setFixedHeight(overviewHeight); | |
256 m_mainLevelPan->setFixedWidth(overviewHeight); | |
257 m_mainLevelPan->setImageSize((overviewHeight * 3) / 4); | |
258 m_mainLevelPan->setBigImageSize(overviewHeight * 3); | |
255 | 259 |
256 m_playControlsSpacer = new QFrame; | 260 m_playControlsSpacer = new QFrame; |
257 | 261 |
258 layout->setSpacing(4); | 262 layout->setSpacing(m_viewManager->scalePixelSize(4)); |
259 layout->addWidget(m_mainScroll, 0, 0, 1, 5); | 263 layout->addWidget(m_mainScroll, 0, 0, 1, 4); |
260 layout->addWidget(m_overview, 1, 1); | 264 layout->addWidget(m_overview, 1, 0); |
265 layout->addWidget(m_playSpeed, 1, 1); | |
261 layout->addWidget(m_playControlsSpacer, 1, 2); | 266 layout->addWidget(m_playControlsSpacer, 1, 2); |
262 layout->addWidget(m_playSpeed, 1, 3); | 267 layout->addWidget(m_mainLevelPan, 1, 3); |
263 layout->addWidget(m_fader, 1, 4); | |
264 | 268 |
265 m_playControlsWidth = | 269 m_playControlsWidth = |
266 m_fader->width() + m_playSpeed->width() + layout->spacing() * 2; | 270 m_mainLevelPan->width() + m_playSpeed->width() + layout->spacing() * 2; |
267 | |
268 layout->setColumnMinimumWidth(0, 14); | |
269 layout->setColumnStretch(0, 0); | |
270 | 271 |
271 m_paneStack->setPropertyStackMinWidth(m_playControlsWidth | 272 m_paneStack->setPropertyStackMinWidth(m_playControlsWidth |
272 + 2 + layout->spacing()); | 273 + 2 + layout->spacing()); |
273 m_playControlsSpacer->setFixedSize(QSize(2, 2)); | 274 m_playControlsSpacer->setFixedSize(QSize(2, 2)); |
274 | 275 |
275 layout->setColumnStretch(1, 10); | 276 layout->setColumnStretch(0, 10); |
276 | 277 |
277 connect(m_paneStack, SIGNAL(propertyStacksResized(int)), | 278 connect(m_paneStack, SIGNAL(propertyStacksResized(int)), |
278 this, SLOT(propertyStacksResized(int))); | 279 this, SLOT(propertyStacksResized(int))); |
279 | 280 |
280 frame->setLayout(layout); | 281 frame->setLayout(layout); |
282 | |
283 #ifdef Q_OS_MAC | |
284 // Mac doesn't align menu labels when icons are shown: result is messy | |
285 QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); | |
286 setIconsVisibleInMenus(false); | |
287 #endif | |
281 | 288 |
282 setupMenus(); | 289 setupMenus(); |
283 setupToolbars(); | 290 setupToolbars(); |
284 setupHelpMenu(); | 291 setupHelpMenu(); |
285 | 292 |
296 connect(CommandHistory::getInstance(), SIGNAL(activity(QString)), | 303 connect(CommandHistory::getInstance(), SIGNAL(activity(QString)), |
297 m_activityLog, SLOT(activityHappened(QString))); | 304 m_activityLog, SLOT(activityHappened(QString))); |
298 connect(this, SIGNAL(activity(QString)), | 305 connect(this, SIGNAL(activity(QString)), |
299 m_activityLog, SLOT(activityHappened(QString))); | 306 m_activityLog, SLOT(activityHappened(QString))); |
300 connect(this, SIGNAL(replacedDocument()), this, SLOT(documentReplaced())); | 307 connect(this, SIGNAL(replacedDocument()), this, SLOT(documentReplaced())); |
308 | |
301 m_activityLog->hide(); | 309 m_activityLog->hide(); |
302 | 310 |
303 m_unitConverter->hide(); | 311 m_unitConverter->hide(); |
312 | |
313 setAudioRecordMode(RecordCreateAdditionalModel); | |
304 | 314 |
305 newSession(); | 315 newSession(); |
306 | 316 |
307 connect(m_midiInput, SIGNAL(eventsAvailable()), | 317 connect(m_midiInput, SIGNAL(eventsAvailable()), |
308 this, SLOT(midiEventsAvailable())); | 318 this, SLOT(midiEventsAvailable())); |
322 this, SLOT(newerVersionAvailable(QString))); | 332 this, SLOT(newerVersionAvailable(QString))); |
323 } else { | 333 } else { |
324 m_surveyer = 0; | 334 m_surveyer = 0; |
325 m_versionTester = 0; | 335 m_versionTester = 0; |
326 } | 336 } |
337 | |
338 QTimer::singleShot(500, this, SLOT(betaReleaseWarning())); | |
339 | |
340 QString warning = PluginScan::getInstance()->getStartupFailureReport(); | |
341 if (warning != "") { | |
342 QTimer::singleShot(500, this, SLOT(pluginPopulationWarning())); | |
343 } | |
327 } | 344 } |
328 | 345 |
329 MainWindow::~MainWindow() | 346 MainWindow::~MainWindow() |
330 { | 347 { |
331 // SVDEBUG << "MainWindow::~MainWindow" << endl; | 348 // SVDEBUG << "MainWindow::~MainWindow" << endl; |
352 // workaround, to remove the appmenu-qt5 package, but that is | 369 // workaround, to remove the appmenu-qt5 package, but that is |
353 // awkward and the problem is so severe that it merits disabling | 370 // awkward and the problem is so severe that it merits disabling |
354 // the system menubar integration altogether. Like this: | 371 // the system menubar integration altogether. Like this: |
355 menuBar()->setNativeMenuBar(false); // fix #1039 | 372 menuBar()->setNativeMenuBar(false); // fix #1039 |
356 #endif | 373 #endif |
357 | 374 |
358 m_rightButtonMenu = new QMenu(); | 375 m_rightButtonMenu = new QMenu(); |
359 | 376 |
360 // No -- we don't want tear-off enabled on the right-button | 377 // We don't want tear-off enabled on the right-button menu. |
361 // menu. If it is enabled, then simply right-clicking and | 378 // If it is enabled, then simply right-clicking and releasing |
362 // releasing will pop up the menu, activate the tear-off, and | 379 // will pop up the menu, activate the tear-off, and leave the |
363 // leave the torn-off menu window in front of the main window. | 380 // torn-off menu window in front of the main window. That |
364 // That isn't desirable. I'm not sure it ever would be, in a | 381 // isn't desirable. |
365 // context menu -- perhaps technically a Qt bug? | 382 m_rightButtonMenu->setTearOffEnabled(false); |
366 // m_rightButtonMenu->setTearOffEnabled(true); | |
367 } | 383 } |
368 | 384 |
369 if (m_rightButtonTransformsMenu) { | 385 if (m_rightButtonTransformsMenu) { |
370 m_rightButtonTransformsMenu->clear(); | 386 m_rightButtonTransformsMenu->clear(); |
371 } else { | 387 } else { |
457 m_keyReference->setCategory(tr("File and Session Management")); | 473 m_keyReference->setCategory(tr("File and Session Management")); |
458 | 474 |
459 IconLoader il; | 475 IconLoader il; |
460 | 476 |
461 QIcon icon = il.load("filenew"); | 477 QIcon icon = il.load("filenew"); |
462 icon.addPixmap(il.loadPixmap("filenew-22")); | |
463 QAction *action = new QAction(icon, tr("&New Session"), this); | 478 QAction *action = new QAction(icon, tr("&New Session"), this); |
464 action->setShortcut(tr("Ctrl+N")); | 479 action->setShortcut(tr("Ctrl+N")); |
465 action->setStatusTip(tr("Abandon the current %1 session and start a new one").arg(QApplication::applicationName())); | 480 action->setStatusTip(tr("Abandon the current %1 session and start a new one").arg(QApplication::applicationName())); |
466 connect(action, SIGNAL(triggered()), this, SLOT(newSession())); | 481 connect(action, SIGNAL(triggered()), this, SLOT(newSession())); |
467 m_keyReference->registerShortcut(action); | 482 m_keyReference->registerShortcut(action); |
468 menu->addAction(action); | 483 menu->addAction(action); |
469 toolbar->addAction(action); | 484 toolbar->addAction(action); |
470 | 485 |
471 icon = il.load("fileopen"); | 486 icon = il.load("fileopen"); |
472 icon.addPixmap(il.loadPixmap("fileopen-22")); | |
473 action = new QAction(icon, tr("&Open..."), this); | 487 action = new QAction(icon, tr("&Open..."), this); |
474 action->setShortcut(tr("Ctrl+O")); | 488 action->setShortcut(tr("Ctrl+O")); |
475 action->setStatusTip(tr("Open a session file, audio file, or layer")); | 489 action->setStatusTip(tr("Open a session file, audio file, or layer")); |
476 connect(action, SIGNAL(triggered()), this, SLOT(openSomething())); | 490 connect(action, SIGNAL(triggered()), this, SLOT(openSomething())); |
477 m_keyReference->registerShortcut(action); | 491 m_keyReference->registerShortcut(action); |
508 this, SLOT(setupRecentFilesMenu())); | 522 this, SLOT(setupRecentFilesMenu())); |
509 | 523 |
510 menu->addSeparator(); | 524 menu->addSeparator(); |
511 | 525 |
512 icon = il.load("filesave"); | 526 icon = il.load("filesave"); |
513 icon.addPixmap(il.loadPixmap("filesave-22")); | |
514 action = new QAction(icon, tr("&Save Session"), this); | 527 action = new QAction(icon, tr("&Save Session"), this); |
515 action->setShortcut(tr("Ctrl+S")); | 528 action->setShortcut(tr("Ctrl+S")); |
516 action->setStatusTip(tr("Save the current session into a %1 session file").arg(QApplication::applicationName())); | 529 action->setStatusTip(tr("Save the current session into a %1 session file").arg(QApplication::applicationName())); |
517 connect(action, SIGNAL(triggered()), this, SLOT(saveSession())); | 530 connect(action, SIGNAL(triggered()), this, SLOT(saveSession())); |
518 connect(this, SIGNAL(canSave(bool)), action, SLOT(setEnabled(bool))); | 531 connect(this, SIGNAL(canSave(bool)), action, SLOT(setEnabled(bool))); |
519 m_keyReference->registerShortcut(action); | 532 m_keyReference->registerShortcut(action); |
520 menu->addAction(action); | 533 menu->addAction(action); |
521 toolbar->addAction(action); | 534 toolbar->addAction(action); |
522 | 535 |
523 icon = il.load("filesaveas"); | 536 icon = il.load("filesaveas"); |
524 icon.addPixmap(il.loadPixmap("filesaveas-22")); | |
525 action = new QAction(icon, tr("Save Session &As..."), this); | 537 action = new QAction(icon, tr("Save Session &As..."), this); |
526 action->setShortcut(tr("Ctrl+Shift+S")); | 538 action->setShortcut(tr("Ctrl+Shift+S")); |
527 action->setStatusTip(tr("Save the current session into a new %1 session file").arg(QApplication::applicationName())); | 539 action->setStatusTip(tr("Save the current session into a new %1 session file").arg(QApplication::applicationName())); |
528 connect(action, SIGNAL(triggered()), this, SLOT(saveSessionAs())); | 540 connect(action, SIGNAL(triggered()), this, SLOT(saveSessionAs())); |
529 menu->addAction(action); | 541 menu->addAction(action); |
581 | 593 |
582 action = new QAction(tr("Export Image File..."), this); | 594 action = new QAction(tr("Export Image File..."), this); |
583 action->setStatusTip(tr("Export a single pane to an image file")); | 595 action->setStatusTip(tr("Export a single pane to an image file")); |
584 connect(action, SIGNAL(triggered()), this, SLOT(exportImage())); | 596 connect(action, SIGNAL(triggered()), this, SLOT(exportImage())); |
585 connect(this, SIGNAL(canExportImage(bool)), action, SLOT(setEnabled(bool))); | 597 connect(this, SIGNAL(canExportImage(bool)), action, SLOT(setEnabled(bool))); |
598 menu->addAction(action); | |
599 | |
600 action = new QAction(tr("Export SVG File..."), this); | |
601 action->setStatusTip(tr("Export a single pane to a scalable SVG image file")); | |
602 connect(action, SIGNAL(triggered()), this, SLOT(exportSVG())); | |
603 connect(this, SIGNAL(canExportImage(bool)), action, SLOT(setEnabled(bool))); | |
604 menu->addAction(action); | |
605 | |
606 menu->addSeparator(); | |
607 | |
608 action = new QAction(tr("Browse Recorded Audio Folder"), this); | |
609 action->setStatusTip(tr("Open the Recorded Audio folder in the system file browser")); | |
610 connect(action, SIGNAL(triggered()), this, SLOT(browseRecordedAudio())); | |
586 menu->addAction(action); | 611 menu->addAction(action); |
587 | 612 |
588 menu->addSeparator(); | 613 menu->addSeparator(); |
589 | 614 |
590 QString templatesMenuLabel = tr("Apply Session Template"); | 615 QString templatesMenuLabel = tr("Apply Session Template"); |
825 action = new QAction(tr("Renumber Selected Instants"), this); | 850 action = new QAction(tr("Renumber Selected Instants"), this); |
826 action->setStatusTip(tr("Renumber the selected instants using the current labelling scheme")); | 851 action->setStatusTip(tr("Renumber the selected instants using the current labelling scheme")); |
827 connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants())); | 852 connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants())); |
828 connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool))); | 853 connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool))); |
829 // m_keyReference->registerShortcut(action); | 854 // m_keyReference->registerShortcut(action); |
855 menu->addAction(action); | |
856 | |
857 menu->addSeparator(); | |
858 | |
859 action = new QAction(tr("Subdivide Selected Instants..."), this); | |
860 action->setStatusTip(tr("Add new instants at regular intervals between the selected instants")); | |
861 connect(action, SIGNAL(triggered()), this, SLOT(subdivideInstants())); | |
862 connect(this, SIGNAL(canSubdivideInstants(bool)), action, SLOT(setEnabled(bool))); | |
863 menu->addAction(action); | |
864 | |
865 action = new QAction(tr("Winnow Selected Instants..."), this); | |
866 action->setStatusTip(tr("Remove subdivisions, leaving only every Nth instant")); | |
867 connect(action, SIGNAL(triggered()), this, SLOT(winnowInstants())); | |
868 connect(this, SIGNAL(canWinnowInstants(bool)), action, SLOT(setEnabled(bool))); | |
830 menu->addAction(action); | 869 menu->addAction(action); |
831 } | 870 } |
832 | 871 |
833 void | 872 void |
834 MainWindow::setupViewMenu() | 873 MainWindow::setupViewMenu() |
1039 connect(action, SIGNAL(triggered()), this, SLOT(showUnitConverter())); | 1078 connect(action, SIGNAL(triggered()), this, SLOT(showUnitConverter())); |
1040 menu->addAction(action); | 1079 menu->addAction(action); |
1041 | 1080 |
1042 menu->addSeparator(); | 1081 menu->addSeparator(); |
1043 | 1082 |
1083 #ifndef Q_OS_MAC | |
1084 // Only on non-Mac platforms -- on the Mac this interacts very | |
1085 // badly with the "native" full-screen mode | |
1044 action = new QAction(tr("Go Full-Screen"), this); | 1086 action = new QAction(tr("Go Full-Screen"), this); |
1045 action->setShortcut(tr("F11")); | 1087 action->setShortcut(tr("F11")); |
1046 action->setStatusTip(tr("Expand the pane area to the whole screen")); | 1088 action->setStatusTip(tr("Expand the pane area to the whole screen")); |
1047 connect(action, SIGNAL(triggered()), this, SLOT(goFullScreen())); | 1089 connect(action, SIGNAL(triggered()), this, SLOT(goFullScreen())); |
1048 m_keyReference->registerShortcut(action); | 1090 m_keyReference->registerShortcut(action); |
1049 menu->addAction(action); | 1091 menu->addAction(action); |
1092 #endif | |
1050 } | 1093 } |
1051 | 1094 |
1052 void | 1095 void |
1053 MainWindow::setupPaneAndLayerMenus() | 1096 MainWindow::setupPaneAndLayerMenus() |
1054 { | 1097 { |
1164 bool mono = true; | 1207 bool mono = true; |
1165 | 1208 |
1166 // Avoid warnings/errors with -Wextra because we aren't explicitly | 1209 // Avoid warnings/errors with -Wextra because we aren't explicitly |
1167 // handling all layer types (-Wall is OK with this because of the | 1210 // handling all layer types (-Wall is OK with this because of the |
1168 // default but the stricter level insists) | 1211 // default but the stricter level insists) |
1212 #ifdef __GNUC__ | |
1169 #pragma GCC diagnostic ignored "-Wswitch-enum" | 1213 #pragma GCC diagnostic ignored "-Wswitch-enum" |
1214 #endif | |
1170 | 1215 |
1171 switch (type) { | 1216 switch (type) { |
1172 | 1217 |
1173 case LayerFactory::Waveform: | 1218 case LayerFactory::Waveform: |
1174 icon = il.load("waveform"); | 1219 icon = il.load("waveform"); |
1478 } | 1523 } |
1479 | 1524 |
1480 TransformFactory *factory = TransformFactory::getInstance(); | 1525 TransformFactory *factory = TransformFactory::getInstance(); |
1481 | 1526 |
1482 TransformList transforms = factory->getAllTransformDescriptions(); | 1527 TransformList transforms = factory->getAllTransformDescriptions(); |
1528 | |
1529 if (factory->getStartupFailureReport() != "") { | |
1530 pluginPopulationWarning(); | |
1531 } | |
1532 | |
1483 vector<TransformDescription::Type> types = factory->getAllTransformTypes(); | 1533 vector<TransformDescription::Type> types = factory->getAllTransformTypes(); |
1484 | 1534 |
1485 map<TransformDescription::Type, map<QString, SubdividingMenu *> > categoryMenus; | 1535 map<TransformDescription::Type, map<QString, SubdividingMenu *> > categoryMenus; |
1486 map<TransformDescription::Type, map<QString, SubdividingMenu *> > makerMenus; | 1536 map<TransformDescription::Type, map<QString, SubdividingMenu *> > makerMenus; |
1487 | 1537 |
1736 action = new QAction(tr("%1 on the &Web").arg(name), this); | 1786 action = new QAction(tr("%1 on the &Web").arg(name), this); |
1737 action->setStatusTip(tr("Open the %1 website").arg(name)); | 1787 action->setStatusTip(tr("Open the %1 website").arg(name)); |
1738 connect(action, SIGNAL(triggered()), this, SLOT(website())); | 1788 connect(action, SIGNAL(triggered()), this, SLOT(website())); |
1739 menu->addAction(action); | 1789 menu->addAction(action); |
1740 | 1790 |
1791 action = new QAction(tr("What's &New?").arg(name), this); | |
1792 action->setStatusTip(tr("Show changes in this release of %1").arg(name)); | |
1793 connect(action, SIGNAL(triggered()), this, SLOT(whatsNew())); | |
1794 menu->addAction(action); | |
1795 | |
1741 action = new QAction(tr("&About %1").arg(name), this); | 1796 action = new QAction(tr("&About %1").arg(name), this); |
1742 action->setStatusTip(tr("Show information about %1").arg(name)); | 1797 action->setStatusTip(tr("Show information about %1").arg(name)); |
1743 connect(action, SIGNAL(triggered()), this, SLOT(about())); | 1798 connect(action, SIGNAL(triggered()), this, SLOT(about())); |
1744 menu->addAction(action); | 1799 menu->addAction(action); |
1745 } | 1800 } |
1748 MainWindow::setupRecentFilesMenu() | 1803 MainWindow::setupRecentFilesMenu() |
1749 { | 1804 { |
1750 m_recentFilesMenu->clear(); | 1805 m_recentFilesMenu->clear(); |
1751 vector<QString> files = m_recentFiles.getRecent(); | 1806 vector<QString> files = m_recentFiles.getRecent(); |
1752 for (size_t i = 0; i < files.size(); ++i) { | 1807 for (size_t i = 0; i < files.size(); ++i) { |
1753 QAction *action = new QAction(files[i], this); | 1808 /* F. Nicol patch 13 Aug. 2016 */ |
1754 connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile())); | 1809 const QString& path = files[i]; |
1810 QAction *action = new QAction(path, this); | |
1811 connect(action, &QAction::triggered, [this, path] { openRecentFile(path);}); | |
1812 /* end of patch */ | |
1755 if (i == 0) { | 1813 if (i == 0) { |
1756 action->setShortcut(tr("Ctrl+R")); | 1814 action->setShortcut(tr("Ctrl+R")); |
1757 m_keyReference->registerShortcut | 1815 m_keyReference->registerShortcut |
1758 (tr("Re-open"), | 1816 (tr("Re-open"), |
1759 action->shortcut().toString(), | 1817 action->shortcut().toString(), |
1983 m_ffwdEndAction->setShortcut(tr("End")); | 2041 m_ffwdEndAction->setShortcut(tr("End")); |
1984 m_ffwdEndAction->setStatusTip(tr("Fast-forward to the end")); | 2042 m_ffwdEndAction->setStatusTip(tr("Fast-forward to the end")); |
1985 connect(m_ffwdEndAction, SIGNAL(triggered()), this, SLOT(ffwdEnd())); | 2043 connect(m_ffwdEndAction, SIGNAL(triggered()), this, SLOT(ffwdEnd())); |
1986 connect(this, SIGNAL(canPlay(bool)), m_ffwdEndAction, SLOT(setEnabled(bool))); | 2044 connect(this, SIGNAL(canPlay(bool)), m_ffwdEndAction, SLOT(setEnabled(bool))); |
1987 | 2045 |
2046 m_recordAction = toolbar->addAction(il.load("record"), | |
2047 tr("Record")); | |
2048 m_recordAction->setCheckable(true); | |
2049 m_recordAction->setShortcut(tr("Ctrl+Space")); | |
2050 m_recordAction->setStatusTip(tr("Record a new audio file")); | |
2051 connect(m_recordAction, SIGNAL(triggered()), this, SLOT(record())); | |
2052 connect(m_recordTarget, SIGNAL(recordStatusChanged(bool)), | |
2053 m_recordAction, SLOT(setChecked(bool))); | |
2054 connect(this, SIGNAL(canRecord(bool)), | |
2055 m_recordAction, SLOT(setEnabled(bool))); | |
2056 | |
1988 toolbar = addToolBar(tr("Play Mode Toolbar")); | 2057 toolbar = addToolBar(tr("Play Mode Toolbar")); |
1989 | 2058 |
1990 m_playSelectionAction = toolbar->addAction(il.load("playselection"), | 2059 m_playSelectionAction = toolbar->addAction(il.load("playselection"), |
1991 tr("Constrain Playback to Selection")); | 2060 tr("Constrain Playback to Selection")); |
1992 m_playSelectionAction->setCheckable(true); | 2061 m_playSelectionAction->setCheckable(true); |
2033 connect(alAction, SIGNAL(triggered()), this, SLOT(alignToggled())); | 2102 connect(alAction, SIGNAL(triggered()), this, SLOT(alignToggled())); |
2034 connect(this, SIGNAL(canAlign(bool)), alAction, SLOT(setEnabled(bool))); | 2103 connect(this, SIGNAL(canAlign(bool)), alAction, SLOT(setEnabled(bool))); |
2035 } | 2104 } |
2036 | 2105 |
2037 m_keyReference->registerShortcut(m_playAction); | 2106 m_keyReference->registerShortcut(m_playAction); |
2107 m_keyReference->registerShortcut(m_recordAction); | |
2038 m_keyReference->registerShortcut(m_playSelectionAction); | 2108 m_keyReference->registerShortcut(m_playSelectionAction); |
2039 m_keyReference->registerShortcut(m_playLoopAction); | 2109 m_keyReference->registerShortcut(m_playLoopAction); |
2040 m_keyReference->registerShortcut(m_soloAction); | 2110 m_keyReference->registerShortcut(m_soloAction); |
2041 if (alAction) m_keyReference->registerShortcut(alAction); | 2111 if (alAction) m_keyReference->registerShortcut(alAction); |
2042 m_keyReference->registerShortcut(m_rwdAction); | 2112 m_keyReference->registerShortcut(m_rwdAction); |
2045 m_keyReference->registerShortcut(m_ffwdSimilarAction); | 2115 m_keyReference->registerShortcut(m_ffwdSimilarAction); |
2046 m_keyReference->registerShortcut(m_rwdStartAction); | 2116 m_keyReference->registerShortcut(m_rwdStartAction); |
2047 m_keyReference->registerShortcut(m_ffwdEndAction); | 2117 m_keyReference->registerShortcut(m_ffwdEndAction); |
2048 | 2118 |
2049 menu->addAction(m_playAction); | 2119 menu->addAction(m_playAction); |
2120 menu->addAction(m_recordAction); | |
2050 menu->addAction(m_playSelectionAction); | 2121 menu->addAction(m_playSelectionAction); |
2051 menu->addAction(m_playLoopAction); | 2122 menu->addAction(m_playLoopAction); |
2052 menu->addAction(m_soloAction); | 2123 menu->addAction(m_soloAction); |
2053 if (alAction) menu->addAction(alAction); | 2124 if (alAction) menu->addAction(alAction); |
2054 menu->addSeparator(); | 2125 menu->addSeparator(); |
2059 menu->addAction(m_ffwdSimilarAction); | 2130 menu->addAction(m_ffwdSimilarAction); |
2060 menu->addSeparator(); | 2131 menu->addSeparator(); |
2061 menu->addAction(m_rwdStartAction); | 2132 menu->addAction(m_rwdStartAction); |
2062 menu->addAction(m_ffwdEndAction); | 2133 menu->addAction(m_ffwdEndAction); |
2063 menu->addSeparator(); | 2134 menu->addSeparator(); |
2135 menu->addAction(m_recordAction); | |
2136 menu->addSeparator(); | |
2064 | 2137 |
2065 m_rightButtonPlaybackMenu->addAction(m_playAction); | 2138 m_rightButtonPlaybackMenu->addAction(m_playAction); |
2139 m_rightButtonPlaybackMenu->addAction(m_recordAction); | |
2066 m_rightButtonPlaybackMenu->addAction(m_playSelectionAction); | 2140 m_rightButtonPlaybackMenu->addAction(m_playSelectionAction); |
2067 m_rightButtonPlaybackMenu->addAction(m_playLoopAction); | 2141 m_rightButtonPlaybackMenu->addAction(m_playLoopAction); |
2068 m_rightButtonPlaybackMenu->addAction(m_soloAction); | 2142 m_rightButtonPlaybackMenu->addAction(m_soloAction); |
2069 if (alAction) m_rightButtonPlaybackMenu->addAction(alAction); | 2143 if (alAction) m_rightButtonPlaybackMenu->addAction(alAction); |
2070 m_rightButtonPlaybackMenu->addSeparator(); | 2144 m_rightButtonPlaybackMenu->addSeparator(); |
2071 m_rightButtonPlaybackMenu->addAction(m_rwdAction); | 2145 m_rightButtonPlaybackMenu->addAction(m_rwdAction); |
2072 m_rightButtonPlaybackMenu->addAction(m_ffwdAction); | 2146 m_rightButtonPlaybackMenu->addAction(m_ffwdAction); |
2073 m_rightButtonPlaybackMenu->addSeparator(); | 2147 m_rightButtonPlaybackMenu->addSeparator(); |
2074 m_rightButtonPlaybackMenu->addAction(m_rwdStartAction); | 2148 m_rightButtonPlaybackMenu->addAction(m_rwdStartAction); |
2075 m_rightButtonPlaybackMenu->addAction(m_ffwdEndAction); | 2149 m_rightButtonPlaybackMenu->addAction(m_ffwdEndAction); |
2150 m_rightButtonPlaybackMenu->addSeparator(); | |
2151 m_rightButtonPlaybackMenu->addAction(m_recordAction); | |
2076 m_rightButtonPlaybackMenu->addSeparator(); | 2152 m_rightButtonPlaybackMenu->addSeparator(); |
2077 | 2153 |
2078 QAction *fastAction = menu->addAction(tr("Speed Up")); | 2154 QAction *fastAction = menu->addAction(tr("Speed Up")); |
2079 fastAction->setShortcut(tr("Ctrl+PgUp")); | 2155 fastAction->setShortcut(tr("Ctrl+PgUp")); |
2080 fastAction->setStatusTip(tr("Time-stretch playback to speed it up without changing pitch")); | 2156 fastAction->setStatusTip(tr("Time-stretch playback to speed it up without changing pitch")); |
2278 (currentPane != 0); | 2354 (currentPane != 0); |
2279 bool haveCurrentLayer = | 2355 bool haveCurrentLayer = |
2280 (haveCurrentPane && | 2356 (haveCurrentPane && |
2281 (currentLayer != 0)); | 2357 (currentLayer != 0)); |
2282 bool havePlayTarget = | 2358 bool havePlayTarget = |
2283 (m_playTarget != 0); | 2359 (m_playTarget != 0 || m_audioIO != 0); |
2284 bool haveSelection = | 2360 bool haveSelection = |
2285 (m_viewManager && | 2361 (m_viewManager && |
2286 !m_viewManager->getSelections().empty()); | 2362 !m_viewManager->getSelections().empty()); |
2287 bool haveCurrentEditableLayer = | 2363 bool haveCurrentEditableLayer = |
2288 (haveCurrentLayer && | 2364 (haveCurrentLayer && |
2342 return; | 2418 return; |
2343 } | 2419 } |
2344 | 2420 |
2345 QString description; | 2421 QString description; |
2346 | 2422 |
2423 //!!!??? | |
2424 | |
2347 sv_samplerate_t ssr = getMainModel()->getSampleRate(); | 2425 sv_samplerate_t ssr = getMainModel()->getSampleRate(); |
2348 sv_samplerate_t tsr = ssr; | 2426 sv_samplerate_t tsr = ssr; |
2349 if (m_playSource) tsr = m_playSource->getTargetSampleRate(); | 2427 if (m_playSource) tsr = m_playSource->getDeviceSampleRate(); |
2350 | 2428 |
2351 if (ssr != tsr) { | 2429 if (ssr != tsr) { |
2352 description = tr("%1Hz (resampling to %2Hz)").arg(ssr).arg(tsr); | 2430 description = tr("%1Hz (resampling to %2Hz)").arg(ssr).arg(tsr); |
2353 } else { | 2431 } else { |
2354 description = QString("%1Hz").arg(ssr); | 2432 description = QString("%1Hz").arg(ssr); |
2796 { | 2874 { |
2797 Pane *pane = m_paneStack->getCurrentPane(); | 2875 Pane *pane = m_paneStack->getCurrentPane(); |
2798 if (!pane) return; | 2876 if (!pane) return; |
2799 | 2877 |
2800 QString path = getSaveFileName(FileFinder::ImageFile); | 2878 QString path = getSaveFileName(FileFinder::ImageFile); |
2801 | |
2802 if (path == "") return; | 2879 if (path == "") return; |
2803 | |
2804 if (QFileInfo(path).suffix() == "") path += ".png"; | 2880 if (QFileInfo(path).suffix() == "") path += ".png"; |
2805 | 2881 |
2806 bool haveSelection = m_viewManager && !m_viewManager->getSelections().empty(); | 2882 bool haveSelection = m_viewManager && !m_viewManager->getSelections().empty(); |
2807 | 2883 |
2808 QSize total, visible, selected; | 2884 QSize total, visible, selected; |
2809 total = pane->getImageSize(); | 2885 total = pane->getRenderedImageSize(); |
2810 visible = pane->getImageSize(pane->getFirstVisibleFrame(), | 2886 visible = pane->getRenderedPartImageSize(pane->getFirstVisibleFrame(), |
2811 pane->getLastVisibleFrame()); | 2887 pane->getLastVisibleFrame()); |
2812 | 2888 |
2813 sv_frame_t sf0 = 0, sf1 = 0; | 2889 sv_frame_t sf0 = 0, sf1 = 0; |
2814 | 2890 |
2815 if (haveSelection) { | 2891 if (haveSelection) { |
2816 MultiSelection::SelectionList selections = m_viewManager->getSelections(); | 2892 MultiSelection::SelectionList selections = m_viewManager->getSelections(); |
2817 sf0 = selections.begin()->getStartFrame(); | 2893 sf0 = selections.begin()->getStartFrame(); |
2818 MultiSelection::SelectionList::iterator e = selections.end(); | 2894 MultiSelection::SelectionList::iterator e = selections.end(); |
2819 --e; | 2895 --e; |
2820 sf1 = e->getEndFrame(); | 2896 sf1 = e->getEndFrame(); |
2821 selected = pane->getImageSize(sf0, sf1); | 2897 selected = pane->getRenderedPartImageSize(sf0, sf1); |
2822 } | 2898 } |
2823 | 2899 |
2824 QStringList items; | 2900 QStringList items; |
2825 items << tr("Export the whole pane (%1x%2 pixels)") | 2901 items << tr("Export the whole pane (%1x%2 pixels)") |
2826 .arg(total.width()).arg(total.height()); | 2902 .arg(total.width()).arg(total.height()); |
2845 items, deflt); | 2921 items, deflt); |
2846 | 2922 |
2847 if (!haveSelection) { | 2923 if (!haveSelection) { |
2848 lid->setItemAvailability(2, false); | 2924 lid->setItemAvailability(2, false); |
2849 } | 2925 } |
2850 if (total.width() > 32767) { // appears to be the limit of a QImage | 2926 if (total.width() > 32767) { // appears to be limit of a QImage |
2851 lid->setItemAvailability(0, false); | 2927 lid->setItemAvailability(0, false); |
2852 lid->setFootnote(tr("Note: the whole pane is too wide to be exported as a single image.")); | 2928 lid->setFootnote(tr("Note: the whole pane is too wide to be exported as a single image.")); |
2853 } | 2929 } |
2854 | 2930 |
2855 bool ok = lid->exec(); | 2931 bool ok = lid->exec(); |
2859 if (!ok || item.isEmpty()) return; | 2935 if (!ok || item.isEmpty()) return; |
2860 | 2936 |
2861 settings.setValue("lastimageexportregion", deflt); | 2937 settings.setValue("lastimageexportregion", deflt); |
2862 | 2938 |
2863 QImage *image = 0; | 2939 QImage *image = 0; |
2864 | 2940 |
2865 if (item == items[0]) { | 2941 if (item == items[0]) { |
2866 image = pane->toNewImage(); | 2942 image = pane->renderToNewImage(); |
2867 } else if (item == items[1]) { | 2943 } else if (item == items[1]) { |
2868 image = pane->toNewImage(pane->getFirstVisibleFrame(), | 2944 image = pane->renderPartToNewImage(pane->getFirstVisibleFrame(), |
2869 pane->getLastVisibleFrame()); | 2945 pane->getLastVisibleFrame()); |
2870 } else if (haveSelection) { | 2946 } else if (haveSelection) { |
2871 image = pane->toNewImage(sf0, sf1); | 2947 image = pane->renderPartToNewImage(sf0, sf1); |
2872 } | 2948 } |
2873 | 2949 |
2874 if (!image) return; | 2950 if (!image) return; |
2875 | 2951 |
2876 if (!image->save(path, "PNG")) { | 2952 if (!image->save(path, "PNG")) { |
2877 QMessageBox::critical(this, tr("Failed to save image file"), | 2953 QMessageBox::critical(this, tr("Failed to save image file"), |
2878 tr("Failed to save image file %1").arg(path)); | 2954 tr("Failed to save image file %1").arg(path)); |
2879 } | 2955 } |
2880 | 2956 |
2881 delete image; | 2957 delete image; |
2958 } | |
2959 | |
2960 void | |
2961 MainWindow::exportSVG() | |
2962 { | |
2963 Pane *pane = m_paneStack->getCurrentPane(); | |
2964 if (!pane) return; | |
2965 | |
2966 QString path = getSaveFileName(FileFinder::SVGFile); | |
2967 if (path == "") return; | |
2968 if (QFileInfo(path).suffix() == "") path += ".svg"; | |
2969 | |
2970 bool haveSelection = m_viewManager && !m_viewManager->getSelections().empty(); | |
2971 | |
2972 sv_frame_t sf0 = 0, sf1 = 0; | |
2973 | |
2974 if (haveSelection) { | |
2975 MultiSelection::SelectionList selections = m_viewManager->getSelections(); | |
2976 sf0 = selections.begin()->getStartFrame(); | |
2977 MultiSelection::SelectionList::iterator e = selections.end(); | |
2978 --e; | |
2979 sf1 = e->getEndFrame(); | |
2980 } | |
2981 | |
2982 QStringList items; | |
2983 items << tr("Export the whole pane"); | |
2984 items << tr("Export the visible area only"); | |
2985 items << tr("Export the selection extent"); | |
2986 | |
2987 QSettings settings; | |
2988 settings.beginGroup("MainWindow"); | |
2989 int deflt = settings.value("lastsvgexportregion", 0).toInt(); | |
2990 if (deflt == 2 && !haveSelection) deflt = 1; | |
2991 | |
2992 ListInputDialog *lid = new ListInputDialog | |
2993 (this, tr("Select region to export"), | |
2994 tr("Which region of the current pane do you want to export as a scalable SVG image?"), | |
2995 items, deflt); | |
2996 | |
2997 if (!haveSelection) { | |
2998 lid->setItemAvailability(2, false); | |
2999 } | |
3000 | |
3001 bool ok = lid->exec(); | |
3002 QString item = lid->getCurrentString(); | |
3003 delete lid; | |
3004 | |
3005 if (!ok || item.isEmpty()) return; | |
3006 | |
3007 settings.setValue("lastsvgexportregion", deflt); | |
3008 | |
3009 bool result = false; | |
3010 | |
3011 if (item == items[0]) { | |
3012 result = pane->renderToSvgFile(path ); | |
3013 } else if (item == items[1]) { | |
3014 result = pane->renderPartToSvgFile(path, | |
3015 pane->getFirstVisibleFrame(), | |
3016 pane->getLastVisibleFrame()); | |
3017 } else if (haveSelection) { | |
3018 result = pane->renderPartToSvgFile(path, sf0, sf1); | |
3019 } | |
3020 | |
3021 if (!result) { | |
3022 QMessageBox::critical(this, tr("Failed to save SVG file"), | |
3023 tr("Failed to save SVG file %1").arg(path)); | |
3024 } | |
3025 } | |
3026 | |
3027 void | |
3028 MainWindow::browseRecordedAudio() | |
3029 { | |
3030 if (!m_recordTarget) return; | |
3031 | |
3032 QString path = m_recordTarget->getRecordContainerFolder(); | |
3033 if (path == "") path = m_recordTarget->getRecordFolder(); | |
3034 if (path == "") return; | |
3035 | |
3036 openLocalFolder(path); | |
2882 } | 3037 } |
2883 | 3038 |
2884 void | 3039 void |
2885 MainWindow::newSession() | 3040 MainWindow::newSession() |
2886 { | 3041 { |
3028 tr("<b>Audio required</b><p>Unable to load layer data from \"%1\" without an audio file.<br>Please load at least one audio file before importing annotations.").arg(text)); | 3183 tr("<b>Audio required</b><p>Unable to load layer data from \"%1\" without an audio file.<br>Please load at least one audio file before importing annotations.").arg(text)); |
3029 } | 3184 } |
3030 } | 3185 } |
3031 | 3186 |
3032 void | 3187 void |
3033 MainWindow::openRecentFile() | 3188 MainWindow::openRecentFile(const QString& path) |
3034 { | 3189 { |
3190 /* F. Nicol patch 13 Aug. 2016 */ | |
3191 #if 0 | |
3035 QObject *obj = sender(); | 3192 QObject *obj = sender(); |
3036 QAction *action = dynamic_cast<QAction *>(obj); | 3193 QAction *action = dynamic_cast<QAction *>(obj); |
3037 | 3194 |
3038 if (!action) { | 3195 if (!action) { |
3039 cerr << "WARNING: MainWindow::openRecentFile: sender is not an action" | 3196 cerr << "WARNING: MainWindow::openRecentFile: sender is not an action" |
3040 << endl; | 3197 << endl; |
3041 return; | 3198 return; |
3042 } | 3199 } |
3043 | 3200 |
3044 QString path = action->text(); | 3201 QString path = action->text(); |
3202 #endif | |
3203 /* End of F. Nicol patch 13 Aug. 2016 */ | |
3204 | |
3045 if (path == "") return; | 3205 if (path == "") return; |
3046 | 3206 |
3047 FileOpenStatus status = openPath(path, ReplaceSession); | 3207 FileOpenStatus status = openPath(path, ReplaceSession); |
3048 | 3208 |
3049 if (status == FileOpenFailed) { | 3209 if (status == FileOpenFailed) { |
3123 if (QMessageBox::warning(this, | 3283 if (QMessageBox::warning(this, |
3124 tr("Template file exists"), | 3284 tr("Template file exists"), |
3125 tr("<b>Template file exists</b><p>The template \"%1\" already exists.<br>Overwrite it?").arg(name), | 3285 tr("<b>Template file exists</b><p>The template \"%1\" already exists.<br>Overwrite it?").arg(name), |
3126 QMessageBox::Ok | QMessageBox::Cancel, | 3286 QMessageBox::Ok | QMessageBox::Cancel, |
3127 QMessageBox::Cancel) != QMessageBox::Ok) { | 3287 QMessageBox::Cancel) != QMessageBox::Ok) { |
3288 delete d; | |
3128 return; | 3289 return; |
3129 } | 3290 } |
3130 } | 3291 } |
3131 | 3292 |
3132 if (saveSessionTemplate(filename)) { | 3293 if (saveSessionTemplate(filename)) { |
3133 if (makeDefault->isChecked()) { | 3294 if (makeDefault->isChecked()) { |
3134 setDefaultSessionTemplate(name); | 3295 setDefaultSessionTemplate(name); |
3135 } | 3296 } |
3136 } | 3297 } |
3137 } | 3298 } |
3299 | |
3300 delete d; | |
3138 } | 3301 } |
3139 | 3302 |
3140 void | 3303 void |
3141 MainWindow::manageSavedTemplates() | 3304 MainWindow::manageSavedTemplates() |
3142 { | 3305 { |
3239 settings.endGroup(); | 3402 settings.endGroup(); |
3240 | 3403 |
3241 if (m_preferencesDialog && | 3404 if (m_preferencesDialog && |
3242 m_preferencesDialog->isVisible()) { | 3405 m_preferencesDialog->isVisible()) { |
3243 closeSession(); // otherwise we'll have to wait for prefs changes | 3406 closeSession(); // otherwise we'll have to wait for prefs changes |
3244 m_preferencesDialog->applicationClosing(false); | 3407 m_preferencesDialog->applicationClosing(true); |
3245 } | 3408 } |
3246 | 3409 |
3247 closeSession(); | 3410 closeSession(); |
3248 | 3411 |
3249 e->accept(); | 3412 e->accept(); |
3418 void | 3581 void |
3419 MainWindow::preferenceChanged(PropertyContainer::PropertyName name) | 3582 MainWindow::preferenceChanged(PropertyContainer::PropertyName name) |
3420 { | 3583 { |
3421 MainWindowBase::preferenceChanged(name); | 3584 MainWindowBase::preferenceChanged(name); |
3422 | 3585 |
3423 if (name == "Background Mode" && m_viewManager) { | 3586 if (name == "Background Mode") { |
3424 if (m_viewManager->getGlobalDarkBackground()) { | 3587 coloursChanged(); |
3425 m_panLayer->setBaseColour | |
3426 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green"))); | |
3427 } else { | |
3428 m_panLayer->setBaseColour | |
3429 (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); | |
3430 } | |
3431 } | 3588 } |
3589 } | |
3590 | |
3591 void | |
3592 MainWindow::coloursChanged() | |
3593 { | |
3594 QSettings settings; | |
3595 settings.beginGroup("Preferences"); | |
3596 QString defaultColourName(tr("Green")); | |
3597 if (m_viewManager && m_viewManager->getGlobalDarkBackground()) { | |
3598 defaultColourName = tr("Bright Green"); | |
3599 } | |
3600 ColourDatabase *cdb = ColourDatabase::getInstance(); | |
3601 QColor colour = QColor | |
3602 (settings.value("overview-colour", | |
3603 cdb->getColour(defaultColourName).name()).toString()); | |
3604 settings.endGroup(); | |
3605 | |
3606 int index = cdb->getColourIndex(colour); | |
3607 if (index >= 0) { | |
3608 m_panLayer->setBaseColour(index); | |
3609 } | |
3432 } | 3610 } |
3433 | 3611 |
3434 void | 3612 void |
3435 MainWindow::propertyStacksResized(int width) | 3613 MainWindow::propertyStacksResized(int width) |
3436 { | 3614 { |
4057 break; | 4235 break; |
4058 } | 4236 } |
4059 } | 4237 } |
4060 | 4238 |
4061 void | 4239 void |
4062 MainWindow::outputLevelsChanged(float left, float right) | 4240 MainWindow::monitoringLevelsChanged(float left, float right) |
4063 { | 4241 { |
4064 m_fader->setPeakLeft(left); | 4242 m_mainLevelPan->setMonitoringLevels(left, right); |
4065 m_fader->setPeakRight(right); | |
4066 } | 4243 } |
4067 | 4244 |
4068 void | 4245 void |
4069 MainWindow::sampleRateMismatch(sv_samplerate_t requested, | 4246 MainWindow::sampleRateMismatch(sv_samplerate_t requested, |
4070 sv_samplerate_t actual, | 4247 sv_samplerate_t actual, |
4096 if (shownOnce) return; | 4273 if (shownOnce) return; |
4097 QMessageBox::information | 4274 QMessageBox::information |
4098 (this, tr("Audio processing overload"), | 4275 (this, tr("Audio processing overload"), |
4099 tr("<b>Overloaded</b><p>Audio playback speed processing has been reduced to a single channel, due to a processing overload.")); | 4276 tr("<b>Overloaded</b><p>Audio playback speed processing has been reduced to a single channel, due to a processing overload.")); |
4100 shownOnce = true; | 4277 shownOnce = true; |
4278 } | |
4279 | |
4280 void | |
4281 MainWindow::betaReleaseWarning() | |
4282 { | |
4283 QMessageBox::information | |
4284 (this, tr("Beta release"), | |
4285 tr("<b>This is a beta release of Sonic Visualiser</b><p>Please see the \"What's New\" option in the Help menu for a list of changes since the last proper release.</p>")); | |
4286 } | |
4287 | |
4288 void | |
4289 MainWindow::pluginPopulationWarning() | |
4290 { | |
4291 QString scanWarning = PluginScan::getInstance()->getStartupFailureReport(); | |
4292 QString factWarning = TransformFactory::getInstance()->getStartupFailureReport(); | |
4293 QString warning; | |
4294 if (factWarning != "") { | |
4295 // The order of events on startup implies that, if scanWarning | |
4296 // and factWarning are both present, then we have already been | |
4297 // called once for scanWarning so don't want to report it again | |
4298 warning = factWarning; | |
4299 } else if (scanWarning != "") { | |
4300 warning = scanWarning; | |
4301 } | |
4302 if (warning != "") { | |
4303 emit hideSplash(); | |
4304 QMessageBox::warning(this, tr("Problems loading plugins"), warning); | |
4305 } | |
4101 } | 4306 } |
4102 | 4307 |
4103 void | 4308 void |
4104 MainWindow::midiEventsAvailable() | 4309 MainWindow::midiEventsAvailable() |
4105 { | 4310 { |
4235 { | 4440 { |
4236 m_panLayer->setModel(model); | 4441 m_panLayer->setModel(model); |
4237 | 4442 |
4238 MainWindowBase::mainModelChanged(model); | 4443 MainWindowBase::mainModelChanged(model); |
4239 | 4444 |
4445 if (m_playTarget || m_audioIO) { | |
4446 connect(m_mainLevelPan, SIGNAL(levelChanged(float)), | |
4447 this, SLOT(mainModelGainChanged(float))); | |
4448 connect(m_mainLevelPan, SIGNAL(panChanged(float)), | |
4449 this, SLOT(mainModelPanChanged(float))); | |
4450 } | |
4451 } | |
4452 | |
4453 void | |
4454 MainWindow::mainModelGainChanged(float gain) | |
4455 { | |
4240 if (m_playTarget) { | 4456 if (m_playTarget) { |
4241 connect(m_fader, SIGNAL(valueChanged(float)), | 4457 m_playTarget->setOutputGain(gain); |
4242 m_playTarget, SLOT(setOutputGain(float))); | 4458 } else if (m_audioIO) { |
4459 m_audioIO->setOutputGain(gain); | |
4460 } | |
4461 } | |
4462 | |
4463 void | |
4464 MainWindow::mainModelPanChanged(float balance) | |
4465 { | |
4466 // this is indeed stereo balance rather than pan | |
4467 if (m_playTarget) { | |
4468 m_playTarget->setOutputBalance(balance); | |
4469 } else if (m_audioIO) { | |
4470 m_audioIO->setOutputBalance(balance); | |
4243 } | 4471 } |
4244 } | 4472 } |
4245 | 4473 |
4246 void | 4474 void |
4247 MainWindow::modelAboutToBeDeleted(Model *model) | 4475 MainWindow::modelAboutToBeDeleted(Model *model) |
4299 | 4527 |
4300 void | 4528 void |
4301 MainWindow::resetInstantsCounters() | 4529 MainWindow::resetInstantsCounters() |
4302 { | 4530 { |
4303 if (m_labeller) m_labeller->resetCounters(); | 4531 if (m_labeller) m_labeller->resetCounters(); |
4532 } | |
4533 | |
4534 void | |
4535 MainWindow::subdivideInstants() | |
4536 { | |
4537 QSettings settings; | |
4538 settings.beginGroup("MainWindow"); | |
4539 int n = settings.value("subdivisions", 4).toInt(); | |
4540 | |
4541 bool ok; | |
4542 | |
4543 n = QInputDialog::getInt(this, | |
4544 tr("Subdivide instants"), | |
4545 tr("Number of subdivisions:"), | |
4546 n, 2, 96, 1, &ok); | |
4547 | |
4548 if (ok) { | |
4549 settings.setValue("subdivisions", n); | |
4550 subdivideInstantsBy(n); | |
4551 } | |
4552 | |
4553 settings.endGroup(); | |
4554 } | |
4555 | |
4556 void | |
4557 MainWindow::winnowInstants() | |
4558 { | |
4559 QSettings settings; | |
4560 settings.beginGroup("MainWindow"); | |
4561 int n = settings.value("winnow-subdivisions", 4).toInt(); | |
4562 | |
4563 bool ok; | |
4564 | |
4565 n = QInputDialog::getInt(this, | |
4566 tr("Winnow instants"), | |
4567 tr("Remove all instants apart from multiples of:"), | |
4568 n, 2, 96, 1, &ok); | |
4569 | |
4570 if (ok) { | |
4571 settings.setValue("winnow-subdivisions", n); | |
4572 winnowInstantsBy(n); | |
4573 } | |
4574 | |
4575 settings.endGroup(); | |
4304 } | 4576 } |
4305 | 4577 |
4306 void | 4578 void |
4307 MainWindow::modelGenerationFailed(QString transformName, QString message) | 4579 MainWindow::modelGenerationFailed(QString transformName, QString message) |
4308 { | 4580 { |
4374 QMessageBox::warning | 4646 QMessageBox::warning |
4375 (this, tr("Warning"), tr("<b>Warning when regenerating layer</b><p>When regenerating the derived layer \"%1\" using new data model as input:<p>%2").arg(layerName).arg(message), QMessageBox::Ok); | 4647 (this, tr("Warning"), tr("<b>Warning when regenerating layer</b><p>When regenerating the derived layer \"%1\" using new data model as input:<p>%2").arg(layerName).arg(message), QMessageBox::Ok); |
4376 } | 4648 } |
4377 | 4649 |
4378 void | 4650 void |
4379 MainWindow::alignmentFailed(QString transformName, QString message) | 4651 MainWindow::alignmentFailed(QString message) |
4380 { | 4652 { |
4381 emit hideSplash(); | |
4382 | |
4383 QMessageBox::warning | 4653 QMessageBox::warning |
4384 (this, | 4654 (this, |
4385 tr("Failed to calculate alignment"), | 4655 tr("Failed to calculate alignment"), |
4386 tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment using transform \"%1\":<p>%2") | 4656 tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment:<p>%1") |
4387 .arg(transformName).arg(message), | 4657 .arg(message), |
4388 QMessageBox::Ok); | 4658 QMessageBox::Ok); |
4389 } | 4659 } |
4390 | 4660 |
4391 void | 4661 void |
4392 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) | 4662 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) |
4440 return; | 4710 return; |
4441 } | 4711 } |
4442 | 4712 |
4443 m_preferencesDialog = new PreferencesDialog(this); | 4713 m_preferencesDialog = new PreferencesDialog(this); |
4444 | 4714 |
4715 connect(m_preferencesDialog, SIGNAL(audioDeviceChanged()), | |
4716 this, SLOT(recreateAudioIO())); | |
4717 connect(m_preferencesDialog, SIGNAL(coloursChanged()), | |
4718 this, SLOT(coloursChanged())); | |
4719 | |
4445 // DeleteOnClose is safe here, because m_preferencesDialog is a | 4720 // DeleteOnClose is safe here, because m_preferencesDialog is a |
4446 // QPointer that will be zeroed when the dialog is deleted. We | 4721 // QPointer that will be zeroed when the dialog is deleted. We |
4447 // use it in preference to leaving the dialog lying around because | 4722 // use it in preference to leaving the dialog lying around because |
4448 // if you Cancel the dialog, it resets the preferences state | 4723 // if you Cancel the dialog, it resets the preferences state |
4449 // without resetting its own widgets, so its state will be | 4724 // without resetting its own widgets, so its state will be |
4460 MainWindow::mouseEnteredWidget() | 4735 MainWindow::mouseEnteredWidget() |
4461 { | 4736 { |
4462 QWidget *w = dynamic_cast<QWidget *>(sender()); | 4737 QWidget *w = dynamic_cast<QWidget *>(sender()); |
4463 if (!w) return; | 4738 if (!w) return; |
4464 | 4739 |
4465 if (w == m_fader) { | 4740 if (w == m_mainLevelPan) { |
4466 contextHelpChanged(tr("Adjust the master playback level")); | 4741 contextHelpChanged(tr("Adjust the master playback level and pan")); |
4467 } else if (w == m_playSpeed) { | 4742 } else if (w == m_playSpeed) { |
4468 contextHelpChanged(tr("Adjust the master playback speed")); | 4743 contextHelpChanged(tr("Adjust the master playback speed")); |
4469 } | 4744 } |
4470 } | 4745 } |
4471 | 4746 |
4483 | 4758 |
4484 void | 4759 void |
4485 MainWindow::help() | 4760 MainWindow::help() |
4486 { | 4761 { |
4487 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/%1/en/").arg(SV_VERSION)); | 4762 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/%1/en/").arg(SV_VERSION)); |
4763 } | |
4764 | |
4765 void | |
4766 MainWindow::whatsNew() | |
4767 { | |
4768 QFile changelog(":CHANGELOG"); | |
4769 changelog.open(QFile::ReadOnly); | |
4770 QByteArray content = changelog.readAll(); | |
4771 QString text = QString::fromUtf8(content); | |
4772 | |
4773 QDialog *d = new QDialog(this); | |
4774 d->setWindowTitle(tr("What's New")); | |
4775 | |
4776 QGridLayout *layout = new QGridLayout; | |
4777 d->setLayout(layout); | |
4778 | |
4779 int row = 0; | |
4780 | |
4781 QLabel *iconLabel = new QLabel; | |
4782 iconLabel->setPixmap(QApplication::windowIcon().pixmap(64, 64)); | |
4783 layout->addWidget(iconLabel, row, 0); | |
4784 | |
4785 layout->addWidget | |
4786 (new QLabel(tr("<h3>What's New in %1</h3>") | |
4787 .arg(QApplication::applicationName())), | |
4788 row++, 1); | |
4789 layout->setColumnStretch(2, 10); | |
4790 | |
4791 QTextEdit *textEdit = new QTextEdit; | |
4792 layout->addWidget(textEdit, row++, 1, 1, 2); | |
4793 | |
4794 if (m_newerVersionIs != "") { | |
4795 layout->addWidget(new QLabel(tr("<b>Note:</b> A newer version of Sonic Visualiser is available.<br>(Version %1 is available; you are using version %2)").arg(m_newerVersionIs).arg(SV_VERSION)), row++, 1, 1, 2); | |
4796 } | |
4797 | |
4798 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok); | |
4799 layout->addWidget(bb, row++, 0, 1, 3); | |
4800 connect(bb, SIGNAL(accepted()), d, SLOT(accept())); | |
4801 | |
4802 text.replace(QRegExp("(.)\n +(.)"), "\\1 \\2"); | |
4803 text.replace(QRegExp("\n - ([^\n]+)"), "\n<li>\\1</li>"); | |
4804 text.replace(QRegExp(": *\n"), ":\n<ul>\n"); | |
4805 text.replace(QRegExp("</li>\n\\s*\n"), "</li>\n</ul>\n\n"); | |
4806 text.replace(QRegExp("\n(\\w[^:\n]+:)"), "\n<p><b>\\1</b></p>"); | |
4807 // text.replace(QRegExp("<li>([^,.\n]+)([,.] +\\w)"), "<li><b>\\1</b>\\2"); | |
4808 | |
4809 textEdit->setHtml(text); | |
4810 textEdit->setReadOnly(true); | |
4811 | |
4812 d->setMinimumSize(m_viewManager->scalePixelSize(520), | |
4813 m_viewManager->scalePixelSize(450)); | |
4814 | |
4815 d->exec(); | |
4816 | |
4817 delete d; | |
4488 } | 4818 } |
4489 | 4819 |
4490 void | 4820 void |
4491 MainWindow::about() | 4821 MainWindow::about() |
4492 { | 4822 { |
4510 | 4840 |
4511 QString aboutText; | 4841 QString aboutText; |
4512 | 4842 |
4513 aboutText += tr("<h3>About Sonic Visualiser</h3>"); | 4843 aboutText += tr("<h3>About Sonic Visualiser</h3>"); |
4514 aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for semantic music analysis and annotation.<br><a href=\"http://www.sonicvisualiser.org/\">http://www.sonicvisualiser.org/</a></p>"); | 4844 aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for semantic music analysis and annotation.<br><a href=\"http://www.sonicvisualiser.org/\">http://www.sonicvisualiser.org/</a></p>"); |
4515 aboutText += tr("<p><small>%1 : %2 configuration</small></p>") | 4845 aboutText += tr("<p><small>%1 : %2 configuration, %3-bit build</small></p>") |
4516 .arg(version) | 4846 .arg(version) |
4517 .arg(debug ? tr("Debug") : tr("Release")); | 4847 .arg(debug ? tr("Debug") : tr("Release")) |
4518 | 4848 .arg(sizeof(void *) * 8); |
4519 aboutText += "<small>"; | 4849 |
4520 | 4850 if (m_oscQueue && m_oscQueue->isOK()) { |
4521 aboutText += tr("With Qt v%1 © Nokia Corporation").arg(QT_VERSION_STR); | 4851 aboutText += tr("</small><p><small>The OSC URL for this instance is: \"%1\"").arg(m_oscQueue->getOSCURL()); |
4852 } | |
4853 | |
4854 aboutText += "</small><p><small>"; | |
4855 | |
4856 aboutText += tr("With Qt v%1 © The Qt Company").arg(QT_VERSION_STR); | |
4857 | |
4858 aboutText += "</small><small>"; | |
4522 | 4859 |
4523 #ifdef HAVE_JACK | 4860 #ifdef HAVE_JACK |
4524 #ifdef JACK_VERSION | 4861 #ifdef JACK_VERSION |
4525 aboutText += tr("<br>With JACK audio output library v%1 © Paul Davis and Jack O'Quin").arg(JACK_VERSION); | 4862 aboutText += tr("<br>With JACK audio output library v%1 © Paul Davis and Jack O'Quin").arg(JACK_VERSION); |
4526 #else // !JACK_VERSION | 4863 #else // !JACK_VERSION |
4572 aboutText += tr("<br>With FFTW3 © Matteo Frigo and MIT"); | 4909 aboutText += tr("<br>With FFTW3 © Matteo Frigo and MIT"); |
4573 #endif // FFTW3_VERSION | 4910 #endif // FFTW3_VERSION |
4574 #endif // HAVE_FFTW3F | 4911 #endif // HAVE_FFTW3F |
4575 #ifdef HAVE_RUBBERBAND | 4912 #ifdef HAVE_RUBBERBAND |
4576 #ifdef RUBBERBAND_VERSION | 4913 #ifdef RUBBERBAND_VERSION |
4577 aboutText += tr("<br>With Rubber Band v%1 © Chris Cannam").arg(RUBBERBAND_VERSION); | 4914 aboutText += tr("<br>With Rubber Band Library v%1 © Particular Programs Ltd").arg(RUBBERBAND_VERSION); |
4578 #else // !RUBBERBAND_VERSION | 4915 #else // !RUBBERBAND_VERSION |
4579 aboutText += tr("<br>With Rubber Band © Chris Cannam"); | 4916 aboutText += tr("<br>With Rubber Band Library © Particular Programs Ltd"); |
4580 #endif // RUBBERBAND_VERSION | 4917 #endif // RUBBERBAND_VERSION |
4581 #endif // HAVE_RUBBERBAND | 4918 #endif // HAVE_RUBBERBAND |
4582 #ifdef HAVE_VAMP | 4919 aboutText += tr("<br>With Vamp plugin support (API v%1, host SDK v%2) © Chris Cannam and QMUL").arg(VAMP_API_VERSION).arg(VAMP_SDK_VERSION); |
4583 aboutText += tr("<br>With Vamp plugin support (API v%1, host SDK v%2) © Chris Cannam").arg(VAMP_API_VERSION).arg(VAMP_SDK_VERSION); | |
4584 #endif // !HAVE_VAMP | |
4585 aboutText += tr("<br>With LADSPA plugin support (API v%1) © Richard Furse, Paul Davis, Stefan Westerfeld").arg(LADSPA_VERSION); | 4920 aboutText += tr("<br>With LADSPA plugin support (API v%1) © Richard Furse, Paul Davis, Stefan Westerfeld").arg(LADSPA_VERSION); |
4586 aboutText += tr("<br>With DSSI plugin support (API v%1) © Chris Cannam, Steve Harris, Sean Bolton").arg(DSSI_VERSION); | 4921 aboutText += tr("<br>With DSSI plugin support (API v%1) © Chris Cannam, Steve Harris, Sean Bolton").arg(DSSI_VERSION); |
4587 #ifdef REDLAND_VERSION | 4922 #ifdef REDLAND_VERSION |
4588 aboutText += tr("<br>With Redland RDF datastore v%1 © Dave Beckett and the University of Bristol").arg(REDLAND_VERSION); | 4923 aboutText += tr("<br>With Redland RDF datastore v%1 © Dave Beckett and the University of Bristol").arg(REDLAND_VERSION); |
4589 #else // !REDLAND_VERSION | 4924 #else // !REDLAND_VERSION |
4590 aboutText += tr("<br>With Redland RDF datastore © Dave Beckett and the University of Bristol"); | 4925 aboutText += tr("<br>With Redland RDF datastore © Dave Beckett and the University of Bristol"); |
4591 #endif // REDLAND_VERSION | 4926 #endif // REDLAND_VERSION |
4592 aboutText += tr("<br>With Serd and Sord RDF parser and store © David Robillard"); | 4927 aboutText += tr("<br>With Serd and Sord RDF parser and store © David Robillard"); |
4593 aboutText += tr("<br>With Dataquay Qt/RDF library © Chris Cannam"); | 4928 aboutText += tr("<br>With Dataquay Qt/RDF library © Particular Programs Ltd"); |
4594 | 4929 aboutText += tr("<br>With Cap'n Proto serialisation © Sandstorm Development Group"); |
4595 aboutText += tr("<br>With RtMidi © Gary P. Scavone"); | 4930 aboutText += tr("<br>With RtMidi © Gary P. Scavone"); |
4596 | 4931 |
4597 #ifdef HAVE_LIBLO | 4932 #ifdef HAVE_LIBLO |
4598 #ifdef LIBLO_VERSION | 4933 #ifdef LIBLO_VERSION |
4599 aboutText += tr("<br>With liblo Lite OSC library v%1 © Steve Harris").arg(LIBLO_VERSION); | 4934 aboutText += tr("<br>With liblo Lite OSC library v%1 © Steve Harris").arg(LIBLO_VERSION); |
4600 #else // !LIBLO_VERSION | 4935 #else // !LIBLO_VERSION |
4601 aboutText += tr("<br>With liblo Lite OSC library © Steve Harris"); | 4936 aboutText += tr("<br>With liblo Lite OSC library © Steve Harris"); |
4602 #endif // LIBLO_VERSION | 4937 #endif // LIBLO_VERSION |
4603 | 4938 |
4604 if (m_oscQueue && m_oscQueue->isOK()) { | |
4605 aboutText += tr("</small><p><small>The OSC URL for this instance is: \"%1\"").arg(m_oscQueue->getOSCURL()); | |
4606 } | |
4607 | |
4608 aboutText += "</small></p>"; | 4939 aboutText += "</small></p>"; |
4609 #endif // HAVE_LIBLO | 4940 #endif // HAVE_LIBLO |
4610 | 4941 |
4611 #ifndef BUILD_STATIC | |
4612 aboutText.replace(tr("With "), tr("Using ")); | |
4613 #endif | |
4614 | |
4615 aboutText += | 4942 aboutText += |
4616 "<p><small>Sonic Visualiser Copyright © 2005–2015 Chris Cannam and " | 4943 "<p><small>Sonic Visualiser Copyright © 2005–2017 Chris Cannam and " |
4617 "Queen Mary, University of London.</small></p>" | 4944 "Queen Mary, University of London.</small></p>" |
4618 "<p><small>This program is free software; you can redistribute it and/or " | 4945 "<p><small>This program is free software; you can redistribute it and/or " |
4619 "modify it under the terms of the GNU General Public License as " | 4946 "modify it under the terms of the GNU General Public License as " |
4620 "published by the Free Software Foundation; either version 2 of the " | 4947 "published by the Free Software Foundation; either version 2 of the " |
4621 "License, or (at your option) any later version.<br>See the file " | 4948 "License, or (at your option) any later version.<br>See the file " |
4622 "COPYING included with this distribution for more information.</small></p>"; | 4949 "COPYING included with this distribution for more information.</small></p>"; |
4950 | |
4951 // use our own dialog so we can influence the size | |
4952 | |
4953 QDialog *d = new QDialog(this); | |
4954 | |
4955 d->setWindowTitle(tr("About %1").arg(QApplication::applicationName())); | |
4956 | |
4957 QGridLayout *layout = new QGridLayout; | |
4958 d->setLayout(layout); | |
4959 | |
4960 int row = 0; | |
4623 | 4961 |
4624 QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText); | 4962 QLabel *iconLabel = new QLabel; |
4963 iconLabel->setPixmap(QApplication::windowIcon().pixmap(64, 64)); | |
4964 layout->addWidget(iconLabel, row, 0, Qt::AlignTop); | |
4965 | |
4966 QLabel *mainText = new QLabel(); | |
4967 layout->addWidget(mainText, row, 1, 1, 2); | |
4968 | |
4969 layout->setRowStretch(row, 10); | |
4970 layout->setColumnStretch(1, 10); | |
4971 | |
4972 ++row; | |
4973 | |
4974 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok); | |
4975 layout->addWidget(bb, row++, 0, 1, 3); | |
4976 connect(bb, SIGNAL(accepted()), d, SLOT(accept())); | |
4977 | |
4978 // mainText->setHtml(aboutText); | |
4979 // mainText->setReadOnly(true); | |
4980 mainText->setWordWrap(true); | |
4981 mainText->setOpenExternalLinks(true); | |
4982 mainText->setText(aboutText); | |
4983 | |
4984 d->setMinimumSize(m_viewManager->scalePixelSize(420), | |
4985 m_viewManager->scalePixelSize(200)); | |
4986 | |
4987 d->exec(); | |
4988 | |
4989 delete d; | |
4990 /* | |
4991 QMessageBox about(QMessageBox::Information, | |
4992 tr("About Sonic Visualiser"), | |
4993 aboutText, | |
4994 QMessageBox::StandardButtons(QMessageBox::Ok), | |
4995 this); | |
4996 | |
4997 QIcon icon = QApplication::windowIcon(); | |
4998 QSize size = icon.actualSize(QSize(64, 64)); | |
4999 about.setIconPixmap(icon.pixmap(size)); | |
5000 | |
5001 about.setMinimumSize(m_viewManager->scalePixelSize(400), | |
5002 m_viewManager->scalePixelSize(400)); | |
5003 | |
5004 about.exec(); | |
5005 */ | |
4625 } | 5006 } |
4626 | 5007 |
4627 void | 5008 void |
4628 MainWindow::keyReference() | 5009 MainWindow::keyReference() |
4629 { | 5010 { |
4631 } | 5012 } |
4632 | 5013 |
4633 void | 5014 void |
4634 MainWindow::newerVersionAvailable(QString version) | 5015 MainWindow::newerVersionAvailable(QString version) |
4635 { | 5016 { |
5017 m_newerVersionIs = version; | |
5018 | |
4636 QSettings settings; | 5019 QSettings settings; |
4637 settings.beginGroup("NewerVersionWarning"); | 5020 settings.beginGroup("NewerVersionWarning"); |
4638 QString tag = QString("version-%1-available-show").arg(version); | 5021 QString tag = QString("version-%1-available-show").arg(version); |
4639 if (settings.value(tag, true).toBool()) { | 5022 if (settings.value(tag, true).toBool()) { |
4640 QString title(tr("Newer version available")); | 5023 QString title(tr("Newer version available")); |