Mercurial > hg > sonic-visualiser
comparison main/MainWindow.cpp @ 200:1871581e4da9
* Split MainWindow out into MainWindowBase (pane stack management, basic file
I/O etc) and MainWindow (widget structure, menus and actions etc)
author | Chris Cannam |
---|---|
date | Mon, 22 Oct 2007 14:24:31 +0000 |
parents | 6e1d4d500092 |
children | 0de89bce24e4 |
comparison
equal
deleted
inserted
replaced
199:6e1d4d500092 | 200:1871581e4da9 |
---|---|
2 | 2 |
3 /* | 3 /* |
4 Sonic Visualiser | 4 Sonic Visualiser |
5 An audio file viewer and annotation editor. | 5 An audio file viewer and annotation editor. |
6 Centre for Digital Music, Queen Mary, University of London. | 6 Centre for Digital Music, Queen Mary, University of London. |
7 This file copyright 2006 Chris Cannam and QMUL. | 7 This file copyright 2006-2007 Chris Cannam and QMUL. |
8 | 8 |
9 This program is free software; you can redistribute it and/or | 9 This program is free software; you can redistribute it and/or |
10 modify it under the terms of the GNU General Public License as | 10 modify it under the terms of the GNU General Public License as |
11 published by the Free Software Foundation; either version 2 of the | 11 published by the Free Software Foundation; either version 2 of the |
12 License, or (at your option) any later version. See the file | 12 License, or (at your option) any later version. See the file |
68 #include "base/Clipboard.h" | 68 #include "base/Clipboard.h" |
69 #include "base/UnitDatabase.h" | 69 #include "base/UnitDatabase.h" |
70 #include "base/ColourDatabase.h" | 70 #include "base/ColourDatabase.h" |
71 #include "osc/OSCQueue.h" | 71 #include "osc/OSCQueue.h" |
72 | 72 |
73 //!!! | |
74 #include "data/model/AggregateWaveModel.h" | |
75 | |
76 // For version information | 73 // For version information |
77 #include "vamp/vamp.h" | 74 #include "vamp/vamp.h" |
78 #include "vamp-sdk/PluginBase.h" | 75 #include "vamp-sdk/PluginBase.h" |
79 #include "plugin/api/ladspa.h" | 76 #include "plugin/api/ladspa.h" |
80 #include "plugin/api/dssi.h" | 77 #include "plugin/api/dssi.h" |
113 using std::map; | 110 using std::map; |
114 using std::set; | 111 using std::set; |
115 | 112 |
116 | 113 |
117 MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : | 114 MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : |
118 m_document(0), | 115 MainWindowBase(withAudioOutput, withOSCSupport), |
119 m_paneStack(0), | |
120 m_viewManager(0), | |
121 m_overview(0), | 116 m_overview(0), |
122 m_timeRulerLayer(0), | |
123 m_audioOutput(withAudioOutput), | |
124 m_playSource(0), | |
125 m_playTarget(0), | |
126 m_oscQueue(withOSCSupport ? new OSCQueue() : 0), | |
127 m_recentFiles("RecentFiles", 20), | |
128 m_recentTransforms("RecentTransforms", 20), | |
129 m_mainMenusCreated(false), | 117 m_mainMenusCreated(false), |
130 m_paneMenu(0), | 118 m_paneMenu(0), |
131 m_layerMenu(0), | 119 m_layerMenu(0), |
132 m_transformsMenu(0), | 120 m_transformsMenu(0), |
133 m_playbackMenu(0), | 121 m_playbackMenu(0), |
139 m_rightButtonLayerMenu(0), | 127 m_rightButtonLayerMenu(0), |
140 m_rightButtonTransformsMenu(0), | 128 m_rightButtonTransformsMenu(0), |
141 m_rightButtonPlaybackMenu(0), | 129 m_rightButtonPlaybackMenu(0), |
142 m_ffwdAction(0), | 130 m_ffwdAction(0), |
143 m_rwdAction(0), | 131 m_rwdAction(0), |
144 m_documentModified(false), | |
145 m_openingAudioFile(false), | |
146 m_abandoning(false), | |
147 m_labeller(0), | |
148 m_preferencesDialog(0), | 132 m_preferencesDialog(0), |
149 m_layerTreeView(0), | 133 m_layerTreeView(0), |
150 m_keyReference(new KeyReference()) | 134 m_keyReference(new KeyReference()) |
151 { | 135 { |
152 setWindowTitle(tr("Sonic Visualiser")); | 136 setWindowTitle(tr("Sonic Visualiser")); |
168 cdb->setUseDarkBackground(cdb->addColour(QColor(30, 150, 255), tr("Bright Blue")), true); | 152 cdb->setUseDarkBackground(cdb->addColour(QColor(30, 150, 255), tr("Bright Blue")), true); |
169 cdb->setUseDarkBackground(cdb->addColour(Qt::green, tr("Bright Green")), true); | 153 cdb->setUseDarkBackground(cdb->addColour(Qt::green, tr("Bright Green")), true); |
170 cdb->setUseDarkBackground(cdb->addColour(QColor(225, 74, 255), tr("Bright Purple")), true); | 154 cdb->setUseDarkBackground(cdb->addColour(QColor(225, 74, 255), tr("Bright Purple")), true); |
171 cdb->setUseDarkBackground(cdb->addColour(QColor(255, 188, 80), tr("Bright Orange")), true); | 155 cdb->setUseDarkBackground(cdb->addColour(QColor(255, 188, 80), tr("Bright Orange")), true); |
172 | 156 |
173 connect(CommandHistory::getInstance(), SIGNAL(commandExecuted()), | |
174 this, SLOT(documentModified())); | |
175 connect(CommandHistory::getInstance(), SIGNAL(documentRestored()), | |
176 this, SLOT(documentRestored())); | |
177 | |
178 QFrame *frame = new QFrame; | 157 QFrame *frame = new QFrame; |
179 setCentralWidget(frame); | 158 setCentralWidget(frame); |
180 | 159 |
181 QGridLayout *layout = new QGridLayout; | 160 QGridLayout *layout = new QGridLayout; |
182 | |
183 m_viewManager = new ViewManager(); | |
184 connect(m_viewManager, SIGNAL(selectionChanged()), | |
185 this, SLOT(updateMenuStates())); | |
186 connect(m_viewManager, SIGNAL(inProgressSelectionChanged()), | |
187 this, SLOT(inProgressSelectionChanged())); | |
188 | |
189 Preferences::BackgroundMode mode = | |
190 Preferences::getInstance()->getBackgroundMode(); | |
191 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground(); | |
192 if (mode != Preferences::BackgroundFromTheme) { | |
193 m_viewManager->setGlobalDarkBackground | |
194 (mode == Preferences::DarkBackground); | |
195 } | |
196 | 161 |
197 m_descriptionLabel = new QLabel; | 162 m_descriptionLabel = new QLabel; |
198 | 163 |
199 QScrollArea *scroll = new QScrollArea(frame); | 164 QScrollArea *scroll = new QScrollArea(frame); |
200 scroll->setWidgetResizable(true); | 165 scroll->setWidgetResizable(true); |
201 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 166 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
202 scroll->setFrameShape(QFrame::NoFrame); | 167 scroll->setFrameShape(QFrame::NoFrame); |
203 | |
204 m_paneStack = new PaneStack(scroll, m_viewManager); | |
205 connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)), | |
206 this, SLOT(currentPaneChanged(Pane *))); | |
207 connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)), | |
208 this, SLOT(currentLayerChanged(Pane *, Layer *))); | |
209 connect(m_paneStack, SIGNAL(rightButtonMenuRequested(Pane *, QPoint)), | |
210 this, SLOT(rightButtonMenuRequested(Pane *, QPoint))); | |
211 connect(m_paneStack, SIGNAL(propertyStacksResized()), | |
212 this, SLOT(propertyStacksResized())); | |
213 connect(m_paneStack, SIGNAL(contextHelpChanged(const QString &)), | |
214 this, SLOT(contextHelpChanged(const QString &))); | |
215 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QStringList)), | |
216 this, SLOT(paneDropAccepted(Pane *, QStringList))); | |
217 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QString)), | |
218 this, SLOT(paneDropAccepted(Pane *, QString))); | |
219 | 168 |
220 scroll->setWidget(m_paneStack); | 169 scroll->setWidget(m_paneStack); |
221 | 170 |
222 m_overview = new Overview(frame); | 171 m_overview = new Overview(frame); |
223 m_overview->setViewManager(m_viewManager); | 172 m_overview->setViewManager(m_viewManager); |
240 m_panLayer->setBaseColour | 189 m_panLayer->setBaseColour |
241 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green"))); | 190 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green"))); |
242 } else { | 191 } else { |
243 m_panLayer->setBaseColour | 192 m_panLayer->setBaseColour |
244 (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); | 193 (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); |
245 } | 194 } |
246 | |
247 m_playSource = new AudioCallbackPlaySource(m_viewManager); | |
248 | |
249 connect(m_playSource, SIGNAL(sampleRateMismatch(size_t, size_t, bool)), | |
250 this, SLOT(sampleRateMismatch(size_t, size_t, bool))); | |
251 connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()), | |
252 this, SLOT(audioOverloadPluginDisabled())); | |
253 | 195 |
254 m_fader = new Fader(frame, false); | 196 m_fader = new Fader(frame, false); |
255 connect(m_fader, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); | 197 connect(m_fader, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); |
256 connect(m_fader, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); | 198 connect(m_fader, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); |
257 | 199 |
316 | 258 |
317 layout->setColumnStretch(0, 10); | 259 layout->setColumnStretch(0, 10); |
318 | 260 |
319 frame->setLayout(layout); | 261 frame->setLayout(layout); |
320 | 262 |
321 connect(m_viewManager, SIGNAL(outputLevelsChanged(float, float)), | |
322 this, SLOT(outputLevelsChanged(float, float))); | |
323 | |
324 connect(m_viewManager, SIGNAL(playbackFrameChanged(unsigned long)), | |
325 this, SLOT(playbackFrameChanged(unsigned long))); | |
326 | |
327 connect(m_viewManager, SIGNAL(globalCentreFrameChanged(unsigned long)), | |
328 this, SLOT(globalCentreFrameChanged(unsigned long))); | |
329 | |
330 connect(m_viewManager, SIGNAL(viewCentreFrameChanged(View *, unsigned long)), | |
331 this, SLOT(viewCentreFrameChanged(View *, unsigned long))); | |
332 | |
333 connect(m_viewManager, SIGNAL(viewZoomLevelChanged(View *, unsigned long, bool)), | |
334 this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool))); | |
335 | |
336 connect(Preferences::getInstance(), | |
337 SIGNAL(propertyChanged(PropertyContainer::PropertyName)), | |
338 this, | |
339 SLOT(preferenceChanged(PropertyContainer::PropertyName))); | |
340 | |
341 // preferenceChanged("Property Box Layout"); | |
342 | |
343 if (m_oscQueue && m_oscQueue->isOK()) { | |
344 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC())); | |
345 QTimer *oscTimer = new QTimer(this); | |
346 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); | |
347 oscTimer->start(1000); | |
348 } | |
349 | |
350 Labeller::ValueType labellerType = Labeller::ValueFromTwoLevelCounter; | |
351 settings.beginGroup("MainWindow"); | |
352 labellerType = (Labeller::ValueType) | |
353 settings.value("labellertype", (int)labellerType).toInt(); | |
354 int cycle = settings.value("labellercycle", 4).toInt(); | |
355 settings.endGroup(); | |
356 | |
357 m_labeller = new Labeller(labellerType); | |
358 m_labeller->setCounterCycleSize(cycle); | |
359 | |
360 setupMenus(); | 263 setupMenus(); |
361 setupToolbars(); | 264 setupToolbars(); |
362 setupHelpMenu(); | 265 setupHelpMenu(); |
363 | 266 |
364 statusBar(); | 267 statusBar(); |
366 newSession(); | 269 newSession(); |
367 } | 270 } |
368 | 271 |
369 MainWindow::~MainWindow() | 272 MainWindow::~MainWindow() |
370 { | 273 { |
371 // std::cerr << "MainWindow::~MainWindow()" << std::endl; | |
372 | |
373 if (!m_abandoning) { | |
374 closeSession(); | |
375 } | |
376 delete m_playTarget; | |
377 delete m_playSource; | |
378 delete m_viewManager; | |
379 delete m_oscQueue; | |
380 delete m_keyReference; | 274 delete m_keyReference; |
381 delete m_preferencesDialog; | 275 delete m_preferencesDialog; |
382 delete m_layerTreeView; | 276 delete m_layerTreeView; |
383 Profiles::getInstance()->dump(); | 277 Profiles::getInstance()->dump(); |
384 } | |
385 | |
386 QString | |
387 MainWindow::getOpenFileName(FileFinder::FileType type) | |
388 { | |
389 FileFinder *ff = FileFinder::getInstance(); | |
390 switch (type) { | |
391 case FileFinder::SessionFile: | |
392 return ff->getOpenFileName(type, m_sessionFile); | |
393 case FileFinder::AudioFile: | |
394 return ff->getOpenFileName(type, m_audioFile); | |
395 case FileFinder::LayerFile: | |
396 return ff->getOpenFileName(type, m_sessionFile); | |
397 case FileFinder::LayerFileNoMidi: | |
398 return ff->getOpenFileName(type, m_sessionFile); | |
399 case FileFinder::SessionOrAudioFile: | |
400 return ff->getOpenFileName(type, m_sessionFile); | |
401 case FileFinder::ImageFile: | |
402 return ff->getOpenFileName(type, m_sessionFile); | |
403 case FileFinder::AnyFile: | |
404 if (getMainModel() != 0 && | |
405 m_paneStack != 0 && | |
406 m_paneStack->getCurrentPane() != 0) { // can import a layer | |
407 return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile); | |
408 } else { | |
409 return ff->getOpenFileName(FileFinder::SessionOrAudioFile, | |
410 m_sessionFile); | |
411 } | |
412 } | |
413 return ""; | |
414 } | |
415 | |
416 QString | |
417 MainWindow::getSaveFileName(FileFinder::FileType type) | |
418 { | |
419 FileFinder *ff = FileFinder::getInstance(); | |
420 switch (type) { | |
421 case FileFinder::SessionFile: | |
422 return ff->getSaveFileName(type, m_sessionFile); | |
423 case FileFinder::AudioFile: | |
424 return ff->getSaveFileName(type, m_audioFile); | |
425 case FileFinder::LayerFile: | |
426 return ff->getSaveFileName(type, m_sessionFile); | |
427 case FileFinder::LayerFileNoMidi: | |
428 return ff->getSaveFileName(type, m_sessionFile); | |
429 case FileFinder::SessionOrAudioFile: | |
430 return ff->getSaveFileName(type, m_sessionFile); | |
431 case FileFinder::ImageFile: | |
432 return ff->getSaveFileName(type, m_sessionFile); | |
433 case FileFinder::AnyFile: | |
434 return ff->getSaveFileName(type, m_sessionFile); | |
435 } | |
436 return ""; | |
437 } | |
438 | |
439 void | |
440 MainWindow::registerLastOpenedFilePath(FileFinder::FileType type, QString path) | |
441 { | |
442 FileFinder *ff = FileFinder::getInstance(); | |
443 ff->registerLastOpenedFilePath(type, path); | |
444 } | 278 } |
445 | 279 |
446 void | 280 void |
447 MainWindow::setupMenus() | 281 MainWindow::setupMenus() |
448 { | 282 { |
775 | 609 |
776 QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size")); | 610 QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size")); |
777 QActionGroup *cycleGroup = new QActionGroup(this); | 611 QActionGroup *cycleGroup = new QActionGroup(this); |
778 | 612 |
779 int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 10, 12, 16 }; | 613 int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 10, 12, 16 }; |
780 for (int i = 0; i < sizeof(cycles)/sizeof(cycles[0]); ++i) { | 614 for (int i = 0; i < int(sizeof(cycles)/sizeof(cycles[0])); ++i) { |
781 action = new QAction(QString("%1").arg(cycles[i]), this); | 615 action = new QAction(QString("%1").arg(cycles[i]), this); |
782 connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle())); | 616 connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle())); |
783 action->setCheckable(true); | 617 action->setCheckable(true); |
784 action->setChecked(cycles[i] == m_labeller->getCounterCycleSize()); | 618 action->setChecked(cycles[i] == m_labeller->getCounterCycleSize()); |
785 cycleGroup->addAction(action); | 619 cycleGroup->addAction(action); |
1907 } | 1741 } |
1908 | 1742 |
1909 void | 1743 void |
1910 MainWindow::updateMenuStates() | 1744 MainWindow::updateMenuStates() |
1911 { | 1745 { |
1746 MainWindowBase::updateMenuStates(); | |
1747 | |
1912 Pane *currentPane = 0; | 1748 Pane *currentPane = 0; |
1913 Layer *currentLayer = 0; | 1749 Layer *currentLayer = 0; |
1914 | 1750 |
1915 if (m_paneStack) currentPane = m_paneStack->getCurrentPane(); | 1751 if (m_paneStack) currentPane = m_paneStack->getCurrentPane(); |
1916 if (currentPane) currentLayer = currentPane->getSelectedLayer(); | 1752 if (currentPane) currentLayer = currentPane->getSelectedLayer(); |
1918 bool haveCurrentPane = | 1754 bool haveCurrentPane = |
1919 (currentPane != 0); | 1755 (currentPane != 0); |
1920 bool haveCurrentLayer = | 1756 bool haveCurrentLayer = |
1921 (haveCurrentPane && | 1757 (haveCurrentPane && |
1922 (currentLayer != 0)); | 1758 (currentLayer != 0)); |
1923 bool haveMainModel = | |
1924 (getMainModel() != 0); | |
1925 bool havePlayTarget = | |
1926 (m_playTarget != 0); | |
1927 bool haveSelection = | 1759 bool haveSelection = |
1928 (m_viewManager && | 1760 (m_viewManager && |
1929 !m_viewManager->getSelections().empty()); | 1761 !m_viewManager->getSelections().empty()); |
1930 bool haveCurrentEditableLayer = | 1762 bool haveCurrentEditableLayer = |
1931 (haveCurrentLayer && | 1763 (haveCurrentLayer && |
1934 (haveCurrentLayer && | 1766 (haveCurrentLayer && |
1935 dynamic_cast<TimeInstantLayer *>(currentLayer)); | 1767 dynamic_cast<TimeInstantLayer *>(currentLayer)); |
1936 bool haveCurrentTimeValueLayer = | 1768 bool haveCurrentTimeValueLayer = |
1937 (haveCurrentLayer && | 1769 (haveCurrentLayer && |
1938 dynamic_cast<TimeValueLayer *>(currentLayer)); | 1770 dynamic_cast<TimeValueLayer *>(currentLayer)); |
1939 bool haveCurrentColour3DPlot = | 1771 |
1940 (haveCurrentLayer && | 1772 emit canChangePlaybackSpeed(true); |
1941 dynamic_cast<Colour3DPlotLayer *>(currentLayer)); | 1773 int v = m_playSpeed->value(); |
1942 bool haveClipboardContents = | 1774 emit canSpeedUpPlayback(v < m_playSpeed->maximum()); |
1943 (m_viewManager && | 1775 emit canSlowDownPlayback(v > m_playSpeed->minimum()); |
1944 !m_viewManager->getClipboard().empty()); | |
1945 | |
1946 emit canAddPane(haveMainModel); | |
1947 emit canDeleteCurrentPane(haveCurrentPane); | |
1948 emit canZoom(haveMainModel && haveCurrentPane); | |
1949 emit canScroll(haveMainModel && haveCurrentPane); | |
1950 emit canAddLayer(haveMainModel && haveCurrentPane); | |
1951 emit canImportMoreAudio(haveMainModel); | |
1952 emit canImportLayer(haveMainModel && haveCurrentPane); | |
1953 emit canExportAudio(haveMainModel); | |
1954 emit canExportLayer(haveMainModel && | |
1955 (haveCurrentEditableLayer || haveCurrentColour3DPlot)); | |
1956 emit canExportImage(haveMainModel && haveCurrentPane); | |
1957 emit canDeleteCurrentLayer(haveCurrentLayer); | |
1958 emit canRenameLayer(haveCurrentLayer); | |
1959 emit canEditLayer(haveCurrentEditableLayer); | |
1960 emit canMeasureLayer(haveCurrentLayer); | |
1961 emit canSelect(haveMainModel && haveCurrentPane); | |
1962 emit canPlay(havePlayTarget); | |
1963 emit canFfwd(true); | |
1964 emit canRewind(true); | |
1965 emit canPaste(haveCurrentEditableLayer && haveClipboardContents); | |
1966 emit canInsertInstant(haveCurrentPane); | |
1967 emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection); | |
1968 emit canRenumberInstants(haveCurrentTimeInstantsLayer && haveSelection); | |
1969 emit canPlaySelection(haveMainModel && havePlayTarget && haveSelection); | |
1970 emit canClearSelection(haveSelection); | |
1971 emit canEditSelection(haveSelection && haveCurrentEditableLayer); | |
1972 emit canSave(m_sessionFile != "" && m_documentModified); | |
1973 | 1776 |
1974 if (m_viewManager && | 1777 if (m_viewManager && |
1975 (m_viewManager->getToolMode() == ViewManager::MeasureMode)) { | 1778 (m_viewManager->getToolMode() == ViewManager::MeasureMode)) { |
1976 emit canDeleteSelection(haveCurrentLayer); | 1779 emit canDeleteSelection(haveCurrentLayer); |
1977 m_deleteSelectedAction->setText(tr("&Delete Current Measurement")); | 1780 m_deleteSelectedAction->setText(tr("&Delete Current Measurement")); |
1979 } else { | 1782 } else { |
1980 emit canDeleteSelection(haveSelection && haveCurrentEditableLayer); | 1783 emit canDeleteSelection(haveSelection && haveCurrentEditableLayer); |
1981 m_deleteSelectedAction->setText(tr("&Delete Selected Items")); | 1784 m_deleteSelectedAction->setText(tr("&Delete Selected Items")); |
1982 m_deleteSelectedAction->setStatusTip(tr("Delete items in current selection from the current layer")); | 1785 m_deleteSelectedAction->setStatusTip(tr("Delete items in current selection from the current layer")); |
1983 } | 1786 } |
1984 | |
1985 emit canChangePlaybackSpeed(true); | |
1986 int v = m_playSpeed->value(); | |
1987 emit canSpeedUpPlayback(v < m_playSpeed->maximum()); | |
1988 emit canSlowDownPlayback(v > m_playSpeed->minimum()); | |
1989 | 1787 |
1990 if (m_ffwdAction && m_rwdAction) { | 1788 if (m_ffwdAction && m_rwdAction) { |
1991 if (haveCurrentTimeInstantsLayer) { | 1789 if (haveCurrentTimeInstantsLayer) { |
1992 m_ffwdAction->setText(tr("Fast Forward to Next Instant")); | 1790 m_ffwdAction->setText(tr("Fast Forward to Next Instant")); |
1993 m_ffwdAction->setStatusTip(tr("Fast forward to the next time instant in the current layer")); | 1791 m_ffwdAction->setStatusTip(tr("Fast forward to the next time instant in the current layer")); |
2036 } | 1834 } |
2037 | 1835 |
2038 void | 1836 void |
2039 MainWindow::documentModified() | 1837 MainWindow::documentModified() |
2040 { | 1838 { |
2041 // std::cerr << "MainWindow::documentModified" << std::endl; | 1839 //!!! |
2042 | 1840 MainWindowBase::documentModified(); |
2043 if (!m_documentModified) { | |
2044 setWindowTitle(tr("%1 (modified)").arg(windowTitle())); | |
2045 } | |
2046 | |
2047 m_documentModified = true; | |
2048 updateMenuStates(); | |
2049 } | 1841 } |
2050 | 1842 |
2051 void | 1843 void |
2052 MainWindow::documentRestored() | 1844 MainWindow::documentRestored() |
2053 { | 1845 { |
2054 // std::cerr << "MainWindow::documentRestored" << std::endl; | 1846 //!!! |
2055 | 1847 MainWindowBase::documentRestored(); |
2056 if (m_documentModified) { | |
2057 QString wt(windowTitle()); | |
2058 wt.replace(tr(" (modified)"), ""); | |
2059 setWindowTitle(wt); | |
2060 } | |
2061 | |
2062 m_documentModified = false; | |
2063 updateMenuStates(); | |
2064 } | |
2065 | |
2066 void | |
2067 MainWindow::playLoopToggled() | |
2068 { | |
2069 QAction *action = dynamic_cast<QAction *>(sender()); | |
2070 | |
2071 if (action) { | |
2072 m_viewManager->setPlayLoopMode(action->isChecked()); | |
2073 } else { | |
2074 m_viewManager->setPlayLoopMode(!m_viewManager->getPlayLoopMode()); | |
2075 } | |
2076 } | |
2077 | |
2078 void | |
2079 MainWindow::playSelectionToggled() | |
2080 { | |
2081 QAction *action = dynamic_cast<QAction *>(sender()); | |
2082 | |
2083 if (action) { | |
2084 m_viewManager->setPlaySelectionMode(action->isChecked()); | |
2085 } else { | |
2086 m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode()); | |
2087 } | |
2088 } | |
2089 | |
2090 void | |
2091 MainWindow::playSoloToggled() | |
2092 { | |
2093 QAction *action = dynamic_cast<QAction *>(sender()); | |
2094 | |
2095 if (action) { | |
2096 m_viewManager->setPlaySoloMode(action->isChecked()); | |
2097 } else { | |
2098 m_viewManager->setPlaySoloMode(!m_viewManager->getPlaySoloMode()); | |
2099 } | |
2100 | |
2101 if (m_viewManager->getPlaySoloMode()) { | |
2102 currentPaneChanged(m_paneStack->getCurrentPane()); | |
2103 } else { | |
2104 m_viewManager->setPlaybackModel(0); | |
2105 if (m_playSource) { | |
2106 m_playSource->clearSoloModelSet(); | |
2107 } | |
2108 } | |
2109 } | |
2110 | |
2111 void | |
2112 MainWindow::currentPaneChanged(Pane *p) | |
2113 { | |
2114 updateMenuStates(); | |
2115 updateVisibleRangeDisplay(p); | |
2116 | |
2117 if (!p) return; | |
2118 | |
2119 if (!(m_viewManager && | |
2120 m_playSource && | |
2121 m_viewManager->getPlaySoloMode())) { | |
2122 if (m_viewManager) m_viewManager->setPlaybackModel(0); | |
2123 return; | |
2124 } | |
2125 | |
2126 Model *prevPlaybackModel = m_viewManager->getPlaybackModel(); | |
2127 | |
2128 View::ModelSet soloModels = p->getModels(); | |
2129 | |
2130 for (View::ModelSet::iterator mi = soloModels.begin(); | |
2131 mi != soloModels.end(); ++mi) { | |
2132 if (dynamic_cast<RangeSummarisableTimeValueModel *>(*mi)) { | |
2133 m_viewManager->setPlaybackModel(*mi); | |
2134 } | |
2135 } | |
2136 | |
2137 RangeSummarisableTimeValueModel *a = | |
2138 dynamic_cast<RangeSummarisableTimeValueModel *>(prevPlaybackModel); | |
2139 RangeSummarisableTimeValueModel *b = | |
2140 dynamic_cast<RangeSummarisableTimeValueModel *>(m_viewManager-> | |
2141 getPlaybackModel()); | |
2142 | |
2143 m_playSource->setSoloModelSet(soloModels); | |
2144 | |
2145 if (a && b && (a != b)) { | |
2146 int frame = m_playSource->getCurrentPlayingFrame(); | |
2147 //!!! I don't really believe that these functions are the right way around | |
2148 int rframe = a->alignFromReference(frame); | |
2149 int bframe = b->alignToReference(rframe); | |
2150 if (m_playSource->isPlaying()) m_playSource->play(bframe); | |
2151 } | |
2152 } | |
2153 | |
2154 void | |
2155 MainWindow::currentLayerChanged(Pane *p, Layer *) | |
2156 { | |
2157 updateMenuStates(); | |
2158 updateVisibleRangeDisplay(p); | |
2159 } | 1848 } |
2160 | 1849 |
2161 void | 1850 void |
2162 MainWindow::toolNavigateSelected() | 1851 MainWindow::toolNavigateSelected() |
2163 { | 1852 { |
2191 //void | 1880 //void |
2192 //MainWindow::toolTextSelected() | 1881 //MainWindow::toolTextSelected() |
2193 //{ | 1882 //{ |
2194 // m_viewManager->setToolMode(ViewManager::TextMode); | 1883 // m_viewManager->setToolMode(ViewManager::TextMode); |
2195 //} | 1884 //} |
2196 | |
2197 void | |
2198 MainWindow::selectAll() | |
2199 { | |
2200 if (!getMainModel()) return; | |
2201 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(), | |
2202 getMainModel()->getEndFrame())); | |
2203 } | |
2204 | |
2205 void | |
2206 MainWindow::selectToStart() | |
2207 { | |
2208 if (!getMainModel()) return; | |
2209 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(), | |
2210 m_viewManager->getGlobalCentreFrame())); | |
2211 } | |
2212 | |
2213 void | |
2214 MainWindow::selectToEnd() | |
2215 { | |
2216 if (!getMainModel()) return; | |
2217 m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(), | |
2218 getMainModel()->getEndFrame())); | |
2219 } | |
2220 | |
2221 void | |
2222 MainWindow::selectVisible() | |
2223 { | |
2224 Model *model = getMainModel(); | |
2225 if (!model) return; | |
2226 | |
2227 Pane *currentPane = m_paneStack->getCurrentPane(); | |
2228 if (!currentPane) return; | |
2229 | |
2230 size_t startFrame, endFrame; | |
2231 | |
2232 if (currentPane->getStartFrame() < 0) startFrame = 0; | |
2233 else startFrame = currentPane->getStartFrame(); | |
2234 | |
2235 if (currentPane->getEndFrame() > model->getEndFrame()) endFrame = model->getEndFrame(); | |
2236 else endFrame = currentPane->getEndFrame(); | |
2237 | |
2238 m_viewManager->setSelection(Selection(startFrame, endFrame)); | |
2239 } | |
2240 | |
2241 void | |
2242 MainWindow::clearSelection() | |
2243 { | |
2244 m_viewManager->clearSelections(); | |
2245 } | |
2246 | |
2247 void | |
2248 MainWindow::cut() | |
2249 { | |
2250 Pane *currentPane = m_paneStack->getCurrentPane(); | |
2251 if (!currentPane) return; | |
2252 | |
2253 Layer *layer = currentPane->getSelectedLayer(); | |
2254 if (!layer) return; | |
2255 | |
2256 Clipboard &clipboard = m_viewManager->getClipboard(); | |
2257 clipboard.clear(); | |
2258 | |
2259 MultiSelection::SelectionList selections = m_viewManager->getSelections(); | |
2260 | |
2261 CommandHistory::getInstance()->startCompoundOperation(tr("Cut"), true); | |
2262 | |
2263 for (MultiSelection::SelectionList::iterator i = selections.begin(); | |
2264 i != selections.end(); ++i) { | |
2265 layer->copy(*i, clipboard); | |
2266 layer->deleteSelection(*i); | |
2267 } | |
2268 | |
2269 CommandHistory::getInstance()->endCompoundOperation(); | |
2270 } | |
2271 | |
2272 void | |
2273 MainWindow::copy() | |
2274 { | |
2275 Pane *currentPane = m_paneStack->getCurrentPane(); | |
2276 if (!currentPane) return; | |
2277 | |
2278 Layer *layer = currentPane->getSelectedLayer(); | |
2279 if (!layer) return; | |
2280 | |
2281 Clipboard &clipboard = m_viewManager->getClipboard(); | |
2282 clipboard.clear(); | |
2283 | |
2284 MultiSelection::SelectionList selections = m_viewManager->getSelections(); | |
2285 | |
2286 for (MultiSelection::SelectionList::iterator i = selections.begin(); | |
2287 i != selections.end(); ++i) { | |
2288 layer->copy(*i, clipboard); | |
2289 } | |
2290 } | |
2291 | |
2292 void | |
2293 MainWindow::paste() | |
2294 { | |
2295 Pane *currentPane = m_paneStack->getCurrentPane(); | |
2296 if (!currentPane) return; | |
2297 | |
2298 //!!! if we have no current layer, we should create one of the most | |
2299 // appropriate type | |
2300 | |
2301 Layer *layer = currentPane->getSelectedLayer(); | |
2302 if (!layer) return; | |
2303 | |
2304 Clipboard &clipboard = m_viewManager->getClipboard(); | |
2305 Clipboard::PointList contents = clipboard.getPoints(); | |
2306 /* | |
2307 long minFrame = 0; | |
2308 bool have = false; | |
2309 for (int i = 0; i < contents.size(); ++i) { | |
2310 if (!contents[i].haveFrame()) continue; | |
2311 if (!have || contents[i].getFrame() < minFrame) { | |
2312 minFrame = contents[i].getFrame(); | |
2313 have = true; | |
2314 } | |
2315 } | |
2316 | |
2317 long frameOffset = long(m_viewManager->getGlobalCentreFrame()) - minFrame; | |
2318 | |
2319 layer->paste(clipboard, frameOffset); | |
2320 */ | |
2321 layer->paste(clipboard, 0, true); | |
2322 } | |
2323 | |
2324 void | |
2325 MainWindow::deleteSelected() | |
2326 { | |
2327 if (m_paneStack->getCurrentPane() && | |
2328 m_paneStack->getCurrentPane()->getSelectedLayer()) { | |
2329 | |
2330 Layer *layer = m_paneStack->getCurrentPane()->getSelectedLayer(); | |
2331 | |
2332 if (m_viewManager && | |
2333 (m_viewManager->getToolMode() == ViewManager::MeasureMode)) { | |
2334 | |
2335 layer->deleteCurrentMeasureRect(); | |
2336 | |
2337 } else { | |
2338 | |
2339 MultiSelection::SelectionList selections = | |
2340 m_viewManager->getSelections(); | |
2341 | |
2342 for (MultiSelection::SelectionList::iterator i = selections.begin(); | |
2343 i != selections.end(); ++i) { | |
2344 layer->deleteSelection(*i); | |
2345 } | |
2346 } | |
2347 } | |
2348 } | |
2349 | |
2350 void | |
2351 MainWindow::insertInstant() | |
2352 { | |
2353 int frame = m_viewManager->getPlaybackFrame(); | |
2354 insertInstantAt(frame); | |
2355 } | |
2356 | |
2357 void | |
2358 MainWindow::insertInstantsAtBoundaries() | |
2359 { | |
2360 MultiSelection::SelectionList selections = m_viewManager->getSelections(); | |
2361 for (MultiSelection::SelectionList::iterator i = selections.begin(); | |
2362 i != selections.end(); ++i) { | |
2363 size_t start = i->getStartFrame(); | |
2364 size_t end = i->getEndFrame(); | |
2365 if (start != end) { | |
2366 insertInstantAt(i->getStartFrame()); | |
2367 insertInstantAt(i->getEndFrame()); | |
2368 } | |
2369 } | |
2370 } | |
2371 | |
2372 void | |
2373 MainWindow::insertInstantAt(size_t frame) | |
2374 { | |
2375 Pane *pane = m_paneStack->getCurrentPane(); | |
2376 if (!pane) { | |
2377 return; | |
2378 } | |
2379 | |
2380 Layer *layer = dynamic_cast<TimeInstantLayer *> | |
2381 (pane->getSelectedLayer()); | |
2382 | |
2383 if (!layer) { | |
2384 for (int i = pane->getLayerCount(); i > 0; --i) { | |
2385 layer = dynamic_cast<TimeInstantLayer *>(pane->getLayer(i - 1)); | |
2386 if (layer) break; | |
2387 } | |
2388 | |
2389 if (!layer) { | |
2390 CommandHistory::getInstance()->startCompoundOperation | |
2391 (tr("Add Point"), true); | |
2392 layer = m_document->createEmptyLayer(LayerFactory::TimeInstants); | |
2393 if (layer) { | |
2394 m_document->addLayerToView(pane, layer); | |
2395 m_paneStack->setCurrentLayer(pane, layer); | |
2396 } | |
2397 CommandHistory::getInstance()->endCompoundOperation(); | |
2398 } | |
2399 } | |
2400 | |
2401 if (layer) { | |
2402 | |
2403 Model *model = layer->getModel(); | |
2404 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> | |
2405 (model); | |
2406 | |
2407 if (sodm) { | |
2408 SparseOneDimensionalModel::Point point(frame, ""); | |
2409 | |
2410 SparseOneDimensionalModel::Point prevPoint(0); | |
2411 bool havePrevPoint = false; | |
2412 | |
2413 SparseOneDimensionalModel::EditCommand *command = | |
2414 new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point")); | |
2415 | |
2416 if (m_labeller->actingOnPrevPoint()) { | |
2417 | |
2418 SparseOneDimensionalModel::PointList prevPoints = | |
2419 sodm->getPreviousPoints(frame); | |
2420 | |
2421 if (!prevPoints.empty()) { | |
2422 prevPoint = *prevPoints.begin(); | |
2423 havePrevPoint = true; | |
2424 } | |
2425 } | |
2426 | |
2427 if (m_labeller) { | |
2428 | |
2429 m_labeller->setSampleRate(sodm->getSampleRate()); | |
2430 | |
2431 if (havePrevPoint) { | |
2432 command->deletePoint(prevPoint); | |
2433 } | |
2434 | |
2435 m_labeller->label<SparseOneDimensionalModel::Point> | |
2436 (point, havePrevPoint ? &prevPoint : 0); | |
2437 | |
2438 if (havePrevPoint) { | |
2439 command->addPoint(prevPoint); | |
2440 } | |
2441 } | |
2442 | |
2443 command->addPoint(point); | |
2444 | |
2445 command->setName(tr("Add Point at %1 s") | |
2446 .arg(RealTime::frame2RealTime | |
2447 (frame, | |
2448 sodm->getSampleRate()) | |
2449 .toText(false).c_str())); | |
2450 | |
2451 command->finish(); | |
2452 } | |
2453 } | |
2454 } | |
2455 | |
2456 void | |
2457 MainWindow::setInstantsNumbering() | |
2458 { | |
2459 QAction *a = dynamic_cast<QAction *>(sender()); | |
2460 if (!a) return; | |
2461 | |
2462 int type = m_numberingActions[a]; | |
2463 | |
2464 if (m_labeller) m_labeller->setType(Labeller::ValueType(type)); | |
2465 | |
2466 QSettings settings; | |
2467 settings.beginGroup("MainWindow"); | |
2468 settings.setValue("labellertype", type); | |
2469 settings.endGroup(); | |
2470 } | |
2471 | |
2472 void | |
2473 MainWindow::setInstantsCounterCycle() | |
2474 { | |
2475 QAction *a = dynamic_cast<QAction *>(sender()); | |
2476 if (!a) return; | |
2477 | |
2478 int cycle = a->text().toInt(); | |
2479 if (cycle == 0) return; | |
2480 | |
2481 if (m_labeller) m_labeller->setCounterCycleSize(cycle); | |
2482 | |
2483 QSettings settings; | |
2484 settings.beginGroup("MainWindow"); | |
2485 settings.setValue("labellercycle", cycle); | |
2486 settings.endGroup(); | |
2487 } | |
2488 | |
2489 void | |
2490 MainWindow::resetInstantsCounters() | |
2491 { | |
2492 LabelCounterInputDialog dialog(m_labeller, this); | |
2493 dialog.exec(); | |
2494 } | |
2495 | |
2496 void | |
2497 MainWindow::renumberInstants() | |
2498 { | |
2499 Pane *pane = m_paneStack->getCurrentPane(); | |
2500 if (!pane) return; | |
2501 | |
2502 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer()); | |
2503 if (!layer) return; | |
2504 | |
2505 MultiSelection ms(m_viewManager->getSelection()); | |
2506 | |
2507 Model *model = layer->getModel(); | |
2508 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> | |
2509 (model); | |
2510 if (!sodm) return; | |
2511 | |
2512 if (!m_labeller) return; | |
2513 | |
2514 Labeller labeller(*m_labeller); | |
2515 labeller.setSampleRate(sodm->getSampleRate()); | |
2516 | |
2517 // This uses a command | |
2518 | |
2519 labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms); | |
2520 } | |
2521 | 1885 |
2522 void | 1886 void |
2523 MainWindow::importAudio() | 1887 MainWindow::importAudio() |
2524 { | 1888 { |
2525 QString path = getOpenFileName(FileFinder::AudioFile); | 1889 QString path = getOpenFileName(FileFinder::AudioFile); |
2855 } | 2219 } |
2856 | 2220 |
2857 delete image; | 2221 delete image; |
2858 } | 2222 } |
2859 | 2223 |
2860 MainWindow::FileOpenStatus | |
2861 MainWindow::open(QString fileOrUrl, AudioFileOpenMode mode) | |
2862 { | |
2863 return open(FileSource(fileOrUrl), mode); | |
2864 } | |
2865 | |
2866 MainWindow::FileOpenStatus | |
2867 MainWindow::open(FileSource source, AudioFileOpenMode mode) | |
2868 { | |
2869 FileOpenStatus status; | |
2870 | |
2871 if (!source.isAvailable()) return FileOpenFailed; | |
2872 source.waitForData(); | |
2873 | |
2874 bool canImportLayer = (getMainModel() != 0 && | |
2875 m_paneStack != 0 && | |
2876 m_paneStack->getCurrentPane() != 0); | |
2877 | |
2878 if ((status = openAudio(source, mode)) != FileOpenFailed) { | |
2879 return status; | |
2880 } else if ((status = openSession(source)) != FileOpenFailed) { | |
2881 return status; | |
2882 } else if ((status = openPlaylist(source, mode)) != FileOpenFailed) { | |
2883 return status; | |
2884 } else if (!canImportLayer) { | |
2885 return FileOpenWrongMode; | |
2886 } else if ((status = openImage(source)) != FileOpenFailed) { | |
2887 return status; | |
2888 } else if ((status = openLayer(source)) != FileOpenFailed) { | |
2889 return status; | |
2890 } else { | |
2891 return FileOpenFailed; | |
2892 } | |
2893 } | |
2894 | |
2895 MainWindow::FileOpenStatus | |
2896 MainWindow::openAudio(FileSource source, AudioFileOpenMode mode) | |
2897 { | |
2898 std::cerr << "MainWindow::openAudio(" << source.getLocation().toStdString() << ")" << std::endl; | |
2899 | |
2900 if (!source.isAvailable()) return FileOpenFailed; | |
2901 source.waitForData(); | |
2902 | |
2903 m_openingAudioFile = true; | |
2904 | |
2905 size_t rate = 0; | |
2906 | |
2907 if (Preferences::getInstance()->getResampleOnLoad()) { | |
2908 rate = m_playSource->getSourceSampleRate(); | |
2909 } | |
2910 | |
2911 WaveFileModel *newModel = new WaveFileModel(source, rate); | |
2912 | |
2913 if (!newModel->isOK()) { | |
2914 delete newModel; | |
2915 m_openingAudioFile = false; | |
2916 return FileOpenFailed; | |
2917 } | |
2918 | |
2919 std::cerr << "mode = " << mode << std::endl; | |
2920 | |
2921 if (mode == AskUser) { | |
2922 if (getMainModel()) { | |
2923 | |
2924 static bool prevSetAsMain = true; | |
2925 bool setAsMain = true; | |
2926 | |
2927 QStringList items; | |
2928 items << tr("Replace the existing main waveform") | |
2929 << tr("Load this file into a new waveform pane"); | |
2930 | |
2931 bool ok = false; | |
2932 QString item = ListInputDialog::getItem | |
2933 (this, tr("Select target for import"), | |
2934 tr("You already have an audio waveform loaded.\nWhat would you like to do with the new audio file?"), | |
2935 items, prevSetAsMain ? 0 : 1, &ok); | |
2936 | |
2937 if (!ok || item.isEmpty()) { | |
2938 delete newModel; | |
2939 m_openingAudioFile = false; | |
2940 return FileOpenCancelled; | |
2941 } | |
2942 | |
2943 setAsMain = (item == items[0]); | |
2944 prevSetAsMain = setAsMain; | |
2945 | |
2946 if (setAsMain) mode = ReplaceMainModel; | |
2947 else mode = CreateAdditionalModel; | |
2948 | |
2949 } else { | |
2950 mode = ReplaceMainModel; | |
2951 } | |
2952 } | |
2953 | |
2954 if (mode == ReplaceCurrentPane) { | |
2955 | |
2956 Pane *pane = m_paneStack->getCurrentPane(); | |
2957 if (pane) { | |
2958 if (getMainModel()) { | |
2959 View::ModelSet models(pane->getModels()); | |
2960 if (models.find(getMainModel()) != models.end()) { | |
2961 mode = ReplaceMainModel; | |
2962 } | |
2963 } else { | |
2964 mode = ReplaceMainModel; | |
2965 } | |
2966 } else { | |
2967 mode = CreateAdditionalModel; | |
2968 } | |
2969 } | |
2970 | |
2971 if (mode == CreateAdditionalModel && !getMainModel()) { | |
2972 mode = ReplaceMainModel; | |
2973 } | |
2974 | |
2975 if (mode == ReplaceMainModel) { | |
2976 | |
2977 Model *prevMain = getMainModel(); | |
2978 if (prevMain) { | |
2979 m_playSource->removeModel(prevMain); | |
2980 PlayParameterRepository::getInstance()->removeModel(prevMain); | |
2981 } | |
2982 PlayParameterRepository::getInstance()->addModel(newModel); | |
2983 | |
2984 m_document->setMainModel(newModel); | |
2985 setupMenus(); | |
2986 | |
2987 if (m_sessionFile == "") { | |
2988 setWindowTitle(tr("Sonic Visualiser: %1") | |
2989 .arg(source.getLocation())); | |
2990 CommandHistory::getInstance()->clear(); | |
2991 CommandHistory::getInstance()->documentSaved(); | |
2992 m_documentModified = false; | |
2993 } else { | |
2994 setWindowTitle(tr("Sonic Visualiser: %1 [%2]") | |
2995 .arg(QFileInfo(m_sessionFile).fileName()) | |
2996 .arg(source.getLocation())); | |
2997 if (m_documentModified) { | |
2998 m_documentModified = false; | |
2999 documentModified(); // so as to restore "(modified)" window title | |
3000 } | |
3001 } | |
3002 | |
3003 if (!source.isRemote()) m_audioFile = source.getLocalFilename(); | |
3004 | |
3005 } else if (mode == CreateAdditionalModel) { | |
3006 | |
3007 CommandHistory::getInstance()->startCompoundOperation | |
3008 (tr("Import \"%1\"").arg(source.getLocation()), true); | |
3009 | |
3010 m_document->addImportedModel(newModel); | |
3011 | |
3012 AddPaneCommand *command = new AddPaneCommand(this); | |
3013 CommandHistory::getInstance()->addCommand(command); | |
3014 | |
3015 Pane *pane = command->getPane(); | |
3016 | |
3017 if (!m_timeRulerLayer) { | |
3018 m_timeRulerLayer = m_document->createMainModelLayer | |
3019 (LayerFactory::TimeRuler); | |
3020 } | |
3021 | |
3022 m_document->addLayerToView(pane, m_timeRulerLayer); | |
3023 | |
3024 Layer *newLayer = m_document->createImportedLayer(newModel); | |
3025 | |
3026 if (newLayer) { | |
3027 m_document->addLayerToView(pane, newLayer); | |
3028 } | |
3029 | |
3030 CommandHistory::getInstance()->endCompoundOperation(); | |
3031 | |
3032 } else if (mode == ReplaceCurrentPane) { | |
3033 | |
3034 // We know there is a current pane, otherwise we would have | |
3035 // reset the mode to CreateAdditionalModel above; and we know | |
3036 // the current pane does not contain the main model, otherwise | |
3037 // we would have reset it to ReplaceMainModel. But we don't | |
3038 // know whether the pane contains a waveform model at all. | |
3039 | |
3040 Pane *pane = m_paneStack->getCurrentPane(); | |
3041 Layer *replace = 0; | |
3042 | |
3043 for (int i = 0; i < pane->getLayerCount(); ++i) { | |
3044 Layer *layer = pane->getLayer(i); | |
3045 if (dynamic_cast<WaveformLayer *>(layer)) { | |
3046 replace = layer; | |
3047 break; | |
3048 } | |
3049 } | |
3050 | |
3051 CommandHistory::getInstance()->startCompoundOperation | |
3052 (tr("Import \"%1\"").arg(source.getLocation()), true); | |
3053 | |
3054 m_document->addImportedModel(newModel); | |
3055 | |
3056 if (replace) { | |
3057 m_document->removeLayerFromView(pane, replace); | |
3058 } | |
3059 | |
3060 Layer *newLayer = m_document->createImportedLayer(newModel); | |
3061 | |
3062 if (newLayer) { | |
3063 m_document->addLayerToView(pane, newLayer); | |
3064 } | |
3065 | |
3066 CommandHistory::getInstance()->endCompoundOperation(); | |
3067 } | |
3068 | |
3069 updateMenuStates(); | |
3070 m_recentFiles.addFile(source.getLocation()); | |
3071 if (!source.isRemote()) { | |
3072 // for file dialog | |
3073 registerLastOpenedFilePath(FileFinder::AudioFile, | |
3074 source.getLocalFilename()); | |
3075 } | |
3076 m_openingAudioFile = false; | |
3077 | |
3078 currentPaneChanged(m_paneStack->getCurrentPane()); | |
3079 | |
3080 return FileOpenSucceeded; | |
3081 } | |
3082 | |
3083 MainWindow::FileOpenStatus | |
3084 MainWindow::openPlaylist(FileSource source, AudioFileOpenMode mode) | |
3085 { | |
3086 std::set<QString> extensions; | |
3087 PlaylistFileReader::getSupportedExtensions(extensions); | |
3088 QString extension = source.getExtension(); | |
3089 if (extensions.find(extension) == extensions.end()) return FileOpenFailed; | |
3090 | |
3091 if (!source.isAvailable()) return FileOpenFailed; | |
3092 source.waitForData(); | |
3093 | |
3094 PlaylistFileReader reader(source.getLocalFilename()); | |
3095 if (!reader.isOK()) return FileOpenFailed; | |
3096 | |
3097 PlaylistFileReader::Playlist playlist = reader.load(); | |
3098 | |
3099 bool someSuccess = false; | |
3100 | |
3101 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin(); | |
3102 i != playlist.end(); ++i) { | |
3103 | |
3104 FileOpenStatus status = openAudio(*i, mode); | |
3105 | |
3106 if (status == FileOpenCancelled) { | |
3107 return FileOpenCancelled; | |
3108 } | |
3109 | |
3110 if (status == FileOpenSucceeded) { | |
3111 someSuccess = true; | |
3112 mode = CreateAdditionalModel; | |
3113 } | |
3114 } | |
3115 | |
3116 if (someSuccess) return FileOpenSucceeded; | |
3117 else return FileOpenFailed; | |
3118 } | |
3119 | |
3120 MainWindow::FileOpenStatus | |
3121 MainWindow::openLayer(FileSource source) | |
3122 { | |
3123 Pane *pane = m_paneStack->getCurrentPane(); | |
3124 | |
3125 if (!pane) { | |
3126 // shouldn't happen, as the menu action should have been disabled | |
3127 std::cerr << "WARNING: MainWindow::openLayer: no current pane" << std::endl; | |
3128 return FileOpenWrongMode; | |
3129 } | |
3130 | |
3131 if (!getMainModel()) { | |
3132 // shouldn't happen, as the menu action should have been disabled | |
3133 std::cerr << "WARNING: MainWindow::openLayer: No main model -- hence no default sample rate available" << std::endl; | |
3134 return FileOpenWrongMode; | |
3135 } | |
3136 | |
3137 if (!source.isAvailable()) return FileOpenFailed; | |
3138 source.waitForData(); | |
3139 | |
3140 QString path = source.getLocalFilename(); | |
3141 | |
3142 if (source.getExtension() == "svl" || source.getExtension() == "xml") { | |
3143 | |
3144 PaneCallback callback(this); | |
3145 QFile file(path); | |
3146 | |
3147 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |
3148 std::cerr << "ERROR: MainWindow::openLayer(" | |
3149 << source.getLocation().toStdString() | |
3150 << "): Failed to open file for reading" << std::endl; | |
3151 return FileOpenFailed; | |
3152 } | |
3153 | |
3154 SVFileReader reader(m_document, callback, source.getLocation()); | |
3155 reader.setCurrentPane(pane); | |
3156 | |
3157 QXmlInputSource inputSource(&file); | |
3158 reader.parse(inputSource); | |
3159 | |
3160 if (!reader.isOK()) { | |
3161 std::cerr << "ERROR: MainWindow::openLayer(" | |
3162 << source.getLocation().toStdString() | |
3163 << "): Failed to read XML file: " | |
3164 << reader.getErrorString().toStdString() << std::endl; | |
3165 return FileOpenFailed; | |
3166 } | |
3167 | |
3168 m_recentFiles.addFile(source.getLocation()); | |
3169 | |
3170 if (!source.isRemote()) { | |
3171 registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog | |
3172 } | |
3173 | |
3174 } else { | |
3175 | |
3176 try { | |
3177 | |
3178 Model *model = DataFileReaderFactory::load | |
3179 (path, getMainModel()->getSampleRate()); | |
3180 | |
3181 if (model) { | |
3182 | |
3183 std::cerr << "MainWindow::openLayer: Have model" << std::endl; | |
3184 | |
3185 Layer *newLayer = m_document->createImportedLayer(model); | |
3186 | |
3187 if (newLayer) { | |
3188 | |
3189 m_document->addLayerToView(pane, newLayer); | |
3190 m_recentFiles.addFile(source.getLocation()); | |
3191 | |
3192 if (!source.isRemote()) { | |
3193 registerLastOpenedFilePath | |
3194 (FileFinder::LayerFile, | |
3195 path); // for file dialog | |
3196 } | |
3197 | |
3198 return FileOpenSucceeded; | |
3199 } | |
3200 } | |
3201 } catch (DataFileReaderFactory::Exception e) { | |
3202 if (e == DataFileReaderFactory::ImportCancelled) { | |
3203 return FileOpenCancelled; | |
3204 } | |
3205 } | |
3206 } | |
3207 | |
3208 source.setLeaveLocalFile(true); | |
3209 return FileOpenFailed; | |
3210 } | |
3211 | |
3212 MainWindow::FileOpenStatus | |
3213 MainWindow::openImage(FileSource source) | |
3214 { | |
3215 Pane *pane = m_paneStack->getCurrentPane(); | |
3216 | |
3217 if (!pane) { | |
3218 // shouldn't happen, as the menu action should have been disabled | |
3219 std::cerr << "WARNING: MainWindow::openImage: no current pane" << std::endl; | |
3220 return FileOpenWrongMode; | |
3221 } | |
3222 | |
3223 if (!m_document->getMainModel()) { | |
3224 return FileOpenWrongMode; | |
3225 } | |
3226 | |
3227 bool newLayer = false; | |
3228 | |
3229 ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer()); | |
3230 if (!il) { | |
3231 for (int i = pane->getLayerCount()-1; i >= 0; --i) { | |
3232 il = dynamic_cast<ImageLayer *>(pane->getLayer(i)); | |
3233 if (il) break; | |
3234 } | |
3235 } | |
3236 if (!il) { | |
3237 il = dynamic_cast<ImageLayer *> | |
3238 (m_document->createEmptyLayer(LayerFactory::Image)); | |
3239 if (!il) return FileOpenFailed; | |
3240 newLayer = true; | |
3241 } | |
3242 | |
3243 // We don't put the image file in Recent Files | |
3244 | |
3245 std::cerr << "openImage: trying location \"" << source.getLocation().toStdString() << "\" in image layer" << std::endl; | |
3246 | |
3247 if (!il->addImage(m_viewManager->getGlobalCentreFrame(), source.getLocation())) { | |
3248 if (newLayer) { | |
3249 m_document->setModel(il, 0); // releasing its model | |
3250 delete il; | |
3251 } | |
3252 return FileOpenFailed; | |
3253 } else { | |
3254 if (newLayer) { | |
3255 m_document->addLayerToView(pane, il); | |
3256 } | |
3257 m_paneStack->setCurrentLayer(pane, il); | |
3258 } | |
3259 | |
3260 return FileOpenSucceeded; | |
3261 } | |
3262 | |
3263 MainWindow::FileOpenStatus | |
3264 MainWindow::openSession(FileSource source) | |
3265 { | |
3266 if (!source.isAvailable()) return FileOpenFailed; | |
3267 if (source.getExtension() != "sv") return FileOpenFailed; | |
3268 source.waitForData(); | |
3269 | |
3270 BZipFileDevice bzFile(source.getLocalFilename()); | |
3271 if (!bzFile.open(QIODevice::ReadOnly)) return FileOpenFailed; | |
3272 | |
3273 if (!checkSaveModified()) return FileOpenCancelled; | |
3274 | |
3275 QString error; | |
3276 closeSession(); | |
3277 createDocument(); | |
3278 | |
3279 PaneCallback callback(this); | |
3280 m_viewManager->clearSelections(); | |
3281 | |
3282 SVFileReader reader(m_document, callback, source.getLocation()); | |
3283 QXmlInputSource inputSource(&bzFile); | |
3284 reader.parse(inputSource); | |
3285 | |
3286 if (!reader.isOK()) { | |
3287 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString()); | |
3288 } | |
3289 | |
3290 bzFile.close(); | |
3291 | |
3292 bool ok = (error == ""); | |
3293 | |
3294 if (ok) { | |
3295 | |
3296 setWindowTitle(tr("Sonic Visualiser: %1") | |
3297 .arg(source.getLocation())); | |
3298 | |
3299 if (!source.isRemote()) m_sessionFile = source.getLocalFilename(); | |
3300 | |
3301 setupMenus(); | |
3302 CommandHistory::getInstance()->clear(); | |
3303 CommandHistory::getInstance()->documentSaved(); | |
3304 m_documentModified = false; | |
3305 updateMenuStates(); | |
3306 | |
3307 m_recentFiles.addFile(source.getLocation()); | |
3308 | |
3309 if (!source.isRemote()) { | |
3310 // for file dialog | |
3311 registerLastOpenedFilePath(FileFinder::SessionFile, | |
3312 source.getLocalFilename()); | |
3313 } | |
3314 | |
3315 } else { | |
3316 setWindowTitle(tr("Sonic Visualiser")); | |
3317 } | |
3318 | |
3319 return ok ? FileOpenSucceeded : FileOpenFailed; | |
3320 } | |
3321 | |
3322 void | |
3323 MainWindow::createPlayTarget() | |
3324 { | |
3325 if (m_playTarget) return; | |
3326 | |
3327 m_playTarget = AudioTargetFactory::createCallbackTarget(m_playSource); | |
3328 if (!m_playTarget) { | |
3329 QMessageBox::warning | |
3330 (this, tr("Couldn't open audio device"), | |
3331 tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Audio playback will not be available during this session."), | |
3332 QMessageBox::Ok); | |
3333 } | |
3334 connect(m_fader, SIGNAL(valueChanged(float)), | |
3335 m_playTarget, SLOT(setOutputGain(float))); | |
3336 } | |
3337 | |
3338 WaveFileModel * | |
3339 MainWindow::getMainModel() | |
3340 { | |
3341 if (!m_document) return 0; | |
3342 return m_document->getMainModel(); | |
3343 } | |
3344 | |
3345 const WaveFileModel * | |
3346 MainWindow::getMainModel() const | |
3347 { | |
3348 if (!m_document) return 0; | |
3349 return m_document->getMainModel(); | |
3350 } | |
3351 | |
3352 void | 2224 void |
3353 MainWindow::newSession() | 2225 MainWindow::newSession() |
3354 { | 2226 { |
3355 if (!checkSaveModified()) return; | 2227 if (!checkSaveModified()) return; |
3356 | 2228 |
3379 documentRestored(); | 2251 documentRestored(); |
3380 updateMenuStates(); | 2252 updateMenuStates(); |
3381 } | 2253 } |
3382 | 2254 |
3383 void | 2255 void |
3384 MainWindow::createDocument() | |
3385 { | |
3386 m_document = new Document; | |
3387 | |
3388 connect(m_document, SIGNAL(layerAdded(Layer *)), | |
3389 this, SLOT(layerAdded(Layer *))); | |
3390 connect(m_document, SIGNAL(layerRemoved(Layer *)), | |
3391 this, SLOT(layerRemoved(Layer *))); | |
3392 connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)), | |
3393 this, SLOT(layerAboutToBeDeleted(Layer *))); | |
3394 connect(m_document, SIGNAL(layerInAView(Layer *, bool)), | |
3395 this, SLOT(layerInAView(Layer *, bool))); | |
3396 | |
3397 connect(m_document, SIGNAL(modelAdded(Model *)), | |
3398 this, SLOT(modelAdded(Model *))); | |
3399 connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)), | |
3400 this, SLOT(mainModelChanged(WaveFileModel *))); | |
3401 connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)), | |
3402 this, SLOT(modelAboutToBeDeleted(Model *))); | |
3403 | |
3404 connect(m_document, SIGNAL(modelGenerationFailed(QString)), | |
3405 this, SLOT(modelGenerationFailed(QString))); | |
3406 connect(m_document, SIGNAL(modelRegenerationFailed(QString, QString)), | |
3407 this, SLOT(modelRegenerationFailed(QString, QString))); | |
3408 } | |
3409 | |
3410 void | |
3411 MainWindow::closeSession() | 2256 MainWindow::closeSession() |
3412 { | 2257 { |
3413 if (!checkSaveModified()) return; | 2258 if (!checkSaveModified()) return; |
3414 | 2259 |
3415 while (m_paneStack->getPaneCount() > 0) { | 2260 while (m_paneStack->getPaneCount() > 0) { |
3463 | 2308 |
3464 QString path = getOpenFileName(FileFinder::SessionFile); | 2309 QString path = getOpenFileName(FileFinder::SessionFile); |
3465 | 2310 |
3466 if (path.isEmpty()) return; | 2311 if (path.isEmpty()) return; |
3467 | 2312 |
3468 if (openSession(path) == FileOpenFailed) { | 2313 if (openSessionFile(path) == FileOpenFailed) { |
3469 QMessageBox::critical(this, tr("Failed to open file"), | 2314 QMessageBox::critical(this, tr("Failed to open file"), |
3470 tr("<b>File open failed</b><p>Session file \"%1\" could not be opened").arg(path)); | 2315 tr("<b>File open failed</b><p>Session file \"%1\" could not be opened").arg(path)); |
3471 } | 2316 } |
3472 } | 2317 } |
3473 | 2318 |
3546 } else if (status == FileOpenWrongMode) { | 2391 } else if (status == FileOpenWrongMode) { |
3547 QMessageBox::critical(this, tr("Failed to open location"), | 2392 QMessageBox::critical(this, tr("Failed to open location"), |
3548 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); | 2393 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); |
3549 } | 2394 } |
3550 } | 2395 } |
2396 | |
2397 void | |
2398 MainWindow::paneAdded(Pane *pane) | |
2399 { | |
2400 if (m_overview) m_overview->registerView(pane); | |
2401 } | |
2402 | |
2403 void | |
2404 MainWindow::paneHidden(Pane *pane) | |
2405 { | |
2406 if (m_overview) m_overview->unregisterView(pane); | |
2407 } | |
2408 | |
2409 void | |
2410 MainWindow::paneAboutToBeDeleted(Pane *pane) | |
2411 { | |
2412 if (m_overview) m_overview->unregisterView(pane); | |
2413 } | |
3551 | 2414 |
3552 void | 2415 void |
3553 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) | 2416 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) |
3554 { | 2417 { |
3555 if (pane) m_paneStack->setCurrentPane(pane); | 2418 if (pane) m_paneStack->setCurrentPane(pane); |
3621 | 2484 |
3622 if (m_layerTreeView && | 2485 if (m_layerTreeView && |
3623 m_layerTreeView->isVisible()) { | 2486 m_layerTreeView->isVisible()) { |
3624 delete m_layerTreeView; | 2487 delete m_layerTreeView; |
3625 } | 2488 } |
2489 | |
2490 closeSession(); | |
3626 | 2491 |
3627 e->accept(); | 2492 e->accept(); |
3628 return; | 2493 return; |
3629 } | 2494 } |
3630 | 2495 |
3749 documentRestored(); | 2614 documentRestored(); |
3750 m_recentFiles.addFile(path); | 2615 m_recentFiles.addFile(path); |
3751 } | 2616 } |
3752 } | 2617 } |
3753 | 2618 |
3754 bool | |
3755 MainWindow::saveSessionFile(QString path) | |
3756 { | |
3757 BZipFileDevice bzFile(path); | |
3758 if (!bzFile.open(QIODevice::WriteOnly)) { | |
3759 std::cerr << "Failed to open session file \"" << path.toStdString() | |
3760 << "\" for writing: " | |
3761 << bzFile.errorString().toStdString() << std::endl; | |
3762 return false; | |
3763 } | |
3764 | |
3765 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); | |
3766 | |
3767 QTextStream out(&bzFile); | |
3768 toXml(out); | |
3769 out.flush(); | |
3770 | |
3771 QApplication::restoreOverrideCursor(); | |
3772 | |
3773 if (!bzFile.isOK()) { | |
3774 QMessageBox::critical(this, tr("Failed to write file"), | |
3775 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2") | |
3776 .arg(path).arg(bzFile.errorString())); | |
3777 bzFile.close(); | |
3778 return false; | |
3779 } | |
3780 | |
3781 bzFile.close(); | |
3782 return true; | |
3783 } | |
3784 | |
3785 void | |
3786 MainWindow::toXml(QTextStream &out) | |
3787 { | |
3788 QString indent(" "); | |
3789 | |
3790 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; | |
3791 out << "<!DOCTYPE sonic-visualiser>\n"; | |
3792 out << "<sv>\n"; | |
3793 | |
3794 m_document->toXml(out, "", ""); | |
3795 | |
3796 out << "<display>\n"; | |
3797 | |
3798 out << QString(" <window width=\"%1\" height=\"%2\"/>\n") | |
3799 .arg(width()).arg(height()); | |
3800 | |
3801 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { | |
3802 | |
3803 Pane *pane = m_paneStack->getPane(i); | |
3804 | |
3805 if (pane) { | |
3806 pane->toXml(out, indent); | |
3807 } | |
3808 } | |
3809 | |
3810 out << "</display>\n"; | |
3811 | |
3812 m_viewManager->getSelection().toXml(out); | |
3813 | |
3814 out << "</sv>\n"; | |
3815 } | |
3816 | |
3817 Pane * | |
3818 MainWindow::addPaneToStack() | |
3819 { | |
3820 AddPaneCommand *command = new AddPaneCommand(this); | |
3821 CommandHistory::getInstance()->addCommand(command); | |
3822 return command->getPane(); | |
3823 } | |
3824 | |
3825 void | |
3826 MainWindow::zoomIn() | |
3827 { | |
3828 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3829 if (currentPane) currentPane->zoom(true); | |
3830 } | |
3831 | |
3832 void | |
3833 MainWindow::zoomOut() | |
3834 { | |
3835 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3836 if (currentPane) currentPane->zoom(false); | |
3837 } | |
3838 | |
3839 void | |
3840 MainWindow::zoomToFit() | |
3841 { | |
3842 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3843 if (!currentPane) return; | |
3844 | |
3845 Model *model = getMainModel(); | |
3846 if (!model) return; | |
3847 | |
3848 size_t start = model->getStartFrame(); | |
3849 size_t end = model->getEndFrame(); | |
3850 size_t pixels = currentPane->width(); | |
3851 | |
3852 size_t sw = currentPane->getVerticalScaleWidth(); | |
3853 if (pixels > sw * 2) pixels -= sw * 2; | |
3854 else pixels = 1; | |
3855 if (pixels > 4) pixels -= 4; | |
3856 | |
3857 size_t zoomLevel = (end - start) / pixels; | |
3858 | |
3859 currentPane->setZoomLevel(zoomLevel); | |
3860 currentPane->setCentreFrame((start + end) / 2); | |
3861 } | |
3862 | |
3863 void | |
3864 MainWindow::zoomDefault() | |
3865 { | |
3866 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3867 if (currentPane) currentPane->setZoomLevel(1024); | |
3868 } | |
3869 | |
3870 void | |
3871 MainWindow::scrollLeft() | |
3872 { | |
3873 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3874 if (currentPane) currentPane->scroll(false, false); | |
3875 } | |
3876 | |
3877 void | |
3878 MainWindow::jumpLeft() | |
3879 { | |
3880 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3881 if (currentPane) currentPane->scroll(false, true); | |
3882 } | |
3883 | |
3884 void | |
3885 MainWindow::scrollRight() | |
3886 { | |
3887 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3888 if (currentPane) currentPane->scroll(true, false); | |
3889 } | |
3890 | |
3891 void | |
3892 MainWindow::jumpRight() | |
3893 { | |
3894 Pane *currentPane = m_paneStack->getCurrentPane(); | |
3895 if (currentPane) currentPane->scroll(true, true); | |
3896 } | |
3897 | |
3898 void | |
3899 MainWindow::showNoOverlays() | |
3900 { | |
3901 m_viewManager->setOverlayMode(ViewManager::NoOverlays); | |
3902 } | |
3903 | |
3904 void | |
3905 MainWindow::showMinimalOverlays() | |
3906 { | |
3907 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); | |
3908 } | |
3909 | |
3910 void | |
3911 MainWindow::showStandardOverlays() | |
3912 { | |
3913 m_viewManager->setOverlayMode(ViewManager::StandardOverlays); | |
3914 } | |
3915 | |
3916 void | |
3917 MainWindow::showAllOverlays() | |
3918 { | |
3919 m_viewManager->setOverlayMode(ViewManager::AllOverlays); | |
3920 } | |
3921 | |
3922 void | |
3923 MainWindow::toggleZoomWheels() | |
3924 { | |
3925 if (m_viewManager->getZoomWheelsEnabled()) { | |
3926 m_viewManager->setZoomWheelsEnabled(false); | |
3927 } else { | |
3928 m_viewManager->setZoomWheelsEnabled(true); | |
3929 } | |
3930 } | |
3931 | |
3932 void | |
3933 MainWindow::togglePropertyBoxes() | |
3934 { | |
3935 if (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks) { | |
3936 if (Preferences::getInstance()->getPropertyBoxLayout() == | |
3937 Preferences::VerticallyStacked) { | |
3938 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout); | |
3939 } else { | |
3940 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout); | |
3941 } | |
3942 } else { | |
3943 m_paneStack->setLayoutStyle(PaneStack::NoPropertyStacks); | |
3944 } | |
3945 } | |
3946 | |
3947 void | |
3948 MainWindow::toggleStatusBar() | |
3949 { | |
3950 QSettings settings; | |
3951 settings.beginGroup("MainWindow"); | |
3952 bool sb = settings.value("showstatusbar", true).toBool(); | |
3953 | |
3954 if (sb) { | |
3955 statusBar()->hide(); | |
3956 } else { | |
3957 statusBar()->show(); | |
3958 } | |
3959 | |
3960 settings.setValue("showstatusbar", !sb); | |
3961 | |
3962 settings.endGroup(); | |
3963 } | |
3964 | |
3965 void | 2619 void |
3966 MainWindow::preferenceChanged(PropertyContainer::PropertyName name) | 2620 MainWindow::preferenceChanged(PropertyContainer::PropertyName name) |
3967 { | 2621 { |
3968 if (name == "Property Box Layout") { | 2622 MainWindowBase::preferenceChanged(name); |
3969 if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) { | 2623 |
3970 if (Preferences::getInstance()->getPropertyBoxLayout() == | 2624 if (name == "Background Mode" && m_viewManager) { |
3971 Preferences::VerticallyStacked) { | |
3972 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout); | |
3973 } else { | |
3974 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout); | |
3975 } | |
3976 } | |
3977 } else if (name == "Background Mode" && m_viewManager) { | |
3978 Preferences::BackgroundMode mode = | |
3979 Preferences::getInstance()->getBackgroundMode(); | |
3980 if (mode == Preferences::BackgroundFromTheme) { | |
3981 m_viewManager->setGlobalDarkBackground(m_initialDarkBackground); | |
3982 } else if (mode == Preferences::DarkBackground) { | |
3983 m_viewManager->setGlobalDarkBackground(true); | |
3984 } else { | |
3985 m_viewManager->setGlobalDarkBackground(false); | |
3986 } | |
3987 if (m_viewManager->getGlobalDarkBackground()) { | 2625 if (m_viewManager->getGlobalDarkBackground()) { |
3988 m_panLayer->setBaseColour | 2626 m_panLayer->setBaseColour |
3989 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green"))); | 2627 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green"))); |
3990 } else { | 2628 } else { |
3991 m_panLayer->setBaseColour | 2629 m_panLayer->setBaseColour |
3992 (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); | 2630 (ColourDatabase::getInstance()->getColourIndex(tr("Green"))); |
3993 } | 2631 } |
3994 } | 2632 } |
3995 } | |
3996 | |
3997 void | |
3998 MainWindow::play() | |
3999 { | |
4000 if (m_playSource->isPlaying()) { | |
4001 stop(); | |
4002 } else { | |
4003 playbackFrameChanged(m_viewManager->getPlaybackFrame()); | |
4004 m_playSource->play(m_viewManager->getPlaybackFrame()); | |
4005 } | |
4006 } | |
4007 | |
4008 void | |
4009 MainWindow::ffwd() | |
4010 { | |
4011 if (!getMainModel()) return; | |
4012 | |
4013 int frame = m_viewManager->getPlaybackFrame(); | |
4014 ++frame; | |
4015 | |
4016 Layer *layer = getSnapLayer(); | |
4017 size_t sr = getMainModel()->getSampleRate(); | |
4018 | |
4019 if (!layer) { | |
4020 | |
4021 frame = RealTime::realTime2Frame | |
4022 (RealTime::frame2RealTime(frame, sr) + RealTime(2, 0), sr); | |
4023 if (frame > int(getMainModel()->getEndFrame())) { | |
4024 frame = getMainModel()->getEndFrame(); | |
4025 } | |
4026 | |
4027 } else { | |
4028 | |
4029 size_t resolution = 0; | |
4030 if (!layer->snapToFeatureFrame(m_paneStack->getCurrentPane(), | |
4031 frame, resolution, Layer::SnapRight)) { | |
4032 frame = getMainModel()->getEndFrame(); | |
4033 } | |
4034 } | |
4035 | |
4036 if (frame < 0) frame = 0; | |
4037 | |
4038 if (m_viewManager->getPlaySelectionMode()) { | |
4039 frame = m_viewManager->constrainFrameToSelection(size_t(frame)); | |
4040 } | |
4041 | |
4042 m_viewManager->setPlaybackFrame(frame); | |
4043 } | |
4044 | |
4045 void | |
4046 MainWindow::ffwdEnd() | |
4047 { | |
4048 if (!getMainModel()) return; | |
4049 | |
4050 size_t frame = getMainModel()->getEndFrame(); | |
4051 | |
4052 if (m_viewManager->getPlaySelectionMode()) { | |
4053 frame = m_viewManager->constrainFrameToSelection(frame); | |
4054 } | |
4055 | |
4056 m_viewManager->setPlaybackFrame(frame); | |
4057 } | |
4058 | |
4059 void | |
4060 MainWindow::rewind() | |
4061 { | |
4062 if (!getMainModel()) return; | |
4063 | |
4064 int frame = m_viewManager->getPlaybackFrame(); | |
4065 if (frame > 0) --frame; | |
4066 | |
4067 Layer *layer = getSnapLayer(); | |
4068 size_t sr = getMainModel()->getSampleRate(); | |
4069 | |
4070 // when rewinding during playback, we want to allow a period | |
4071 // following a rewind target point at which the rewind will go to | |
4072 // the prior point instead of the immediately neighbouring one | |
4073 if (m_playSource && m_playSource->isPlaying()) { | |
4074 RealTime ct = RealTime::frame2RealTime(frame, sr); | |
4075 ct = ct - RealTime::fromSeconds(0.25); | |
4076 if (ct < RealTime::zeroTime) ct = RealTime::zeroTime; | |
4077 // std::cerr << "rewind: frame " << frame << " -> "; | |
4078 frame = RealTime::realTime2Frame(ct, sr); | |
4079 // std::cerr << frame << std::endl; | |
4080 } | |
4081 | |
4082 if (!layer) { | |
4083 | |
4084 frame = RealTime::realTime2Frame | |
4085 (RealTime::frame2RealTime(frame, sr) - RealTime(2, 0), sr); | |
4086 if (frame < int(getMainModel()->getStartFrame())) { | |
4087 frame = getMainModel()->getStartFrame(); | |
4088 } | |
4089 | |
4090 } else { | |
4091 | |
4092 size_t resolution = 0; | |
4093 if (!layer->snapToFeatureFrame(m_paneStack->getCurrentPane(), | |
4094 frame, resolution, Layer::SnapLeft)) { | |
4095 frame = getMainModel()->getStartFrame(); | |
4096 } | |
4097 } | |
4098 | |
4099 if (frame < 0) frame = 0; | |
4100 | |
4101 if (m_viewManager->getPlaySelectionMode()) { | |
4102 frame = m_viewManager->constrainFrameToSelection(size_t(frame)); | |
4103 } | |
4104 | |
4105 m_viewManager->setPlaybackFrame(frame); | |
4106 } | |
4107 | |
4108 void | |
4109 MainWindow::rewindStart() | |
4110 { | |
4111 if (!getMainModel()) return; | |
4112 | |
4113 size_t frame = getMainModel()->getStartFrame(); | |
4114 | |
4115 if (m_viewManager->getPlaySelectionMode()) { | |
4116 frame = m_viewManager->constrainFrameToSelection(frame); | |
4117 } | |
4118 | |
4119 m_viewManager->setPlaybackFrame(frame); | |
4120 } | |
4121 | |
4122 Layer * | |
4123 MainWindow::getSnapLayer() const | |
4124 { | |
4125 Pane *pane = m_paneStack->getCurrentPane(); | |
4126 if (!pane) return 0; | |
4127 | |
4128 Layer *layer = pane->getSelectedLayer(); | |
4129 | |
4130 if (!dynamic_cast<TimeInstantLayer *>(layer) && | |
4131 !dynamic_cast<TimeValueLayer *>(layer) && | |
4132 !dynamic_cast<TimeRulerLayer *>(layer)) { | |
4133 | |
4134 layer = 0; | |
4135 | |
4136 for (int i = pane->getLayerCount(); i > 0; --i) { | |
4137 Layer *l = pane->getLayer(i-1); | |
4138 if (dynamic_cast<TimeRulerLayer *>(l)) { | |
4139 layer = l; | |
4140 break; | |
4141 } | |
4142 } | |
4143 } | |
4144 | |
4145 return layer; | |
4146 } | |
4147 | |
4148 void | |
4149 MainWindow::stop() | |
4150 { | |
4151 m_playSource->stop(); | |
4152 | |
4153 if (m_paneStack && m_paneStack->getCurrentPane()) { | |
4154 updateVisibleRangeDisplay(m_paneStack->getCurrentPane()); | |
4155 } else { | |
4156 m_myStatusMessage = ""; | |
4157 statusBar()->showMessage(""); | |
4158 } | |
4159 } | 2633 } |
4160 | 2634 |
4161 void | 2635 void |
4162 MainWindow::addPane() | 2636 MainWindow::addPane() |
4163 { | 2637 { |
4249 // pane->setCentreFrame(m_viewManager->getGlobalCentreFrame()); | 2723 // pane->setCentreFrame(m_viewManager->getGlobalCentreFrame()); |
4250 | 2724 |
4251 CommandHistory::getInstance()->endCompoundOperation(); | 2725 CommandHistory::getInstance()->endCompoundOperation(); |
4252 | 2726 |
4253 updateMenuStates(); | 2727 updateMenuStates(); |
4254 } | |
4255 | |
4256 MainWindow::AddPaneCommand::AddPaneCommand(MainWindow *mw) : | |
4257 m_mw(mw), | |
4258 m_pane(0), | |
4259 m_prevCurrentPane(0), | |
4260 m_added(false) | |
4261 { | |
4262 } | |
4263 | |
4264 MainWindow::AddPaneCommand::~AddPaneCommand() | |
4265 { | |
4266 if (m_pane && !m_added) { | |
4267 m_mw->m_paneStack->deletePane(m_pane); | |
4268 } | |
4269 } | |
4270 | |
4271 QString | |
4272 MainWindow::AddPaneCommand::getName() const | |
4273 { | |
4274 return tr("Add Pane"); | |
4275 } | |
4276 | |
4277 void | |
4278 MainWindow::AddPaneCommand::execute() | |
4279 { | |
4280 if (!m_pane) { | |
4281 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane(); | |
4282 m_pane = m_mw->m_paneStack->addPane(); | |
4283 | |
4284 connect(m_pane, SIGNAL(contextHelpChanged(const QString &)), | |
4285 m_mw, SLOT(contextHelpChanged(const QString &))); | |
4286 } else { | |
4287 m_mw->m_paneStack->showPane(m_pane); | |
4288 } | |
4289 | |
4290 m_mw->m_paneStack->setCurrentPane(m_pane); | |
4291 m_mw->m_overview->registerView(m_pane); | |
4292 m_added = true; | |
4293 } | |
4294 | |
4295 void | |
4296 MainWindow::AddPaneCommand::unexecute() | |
4297 { | |
4298 m_mw->m_paneStack->hidePane(m_pane); | |
4299 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane); | |
4300 m_mw->m_overview->unregisterView(m_pane); | |
4301 m_added = false; | |
4302 } | |
4303 | |
4304 MainWindow::RemovePaneCommand::RemovePaneCommand(MainWindow *mw, Pane *pane) : | |
4305 m_mw(mw), | |
4306 m_pane(pane), | |
4307 m_added(true) | |
4308 { | |
4309 } | |
4310 | |
4311 MainWindow::RemovePaneCommand::~RemovePaneCommand() | |
4312 { | |
4313 if (m_pane && !m_added) { | |
4314 m_mw->m_paneStack->deletePane(m_pane); | |
4315 } | |
4316 } | |
4317 | |
4318 QString | |
4319 MainWindow::RemovePaneCommand::getName() const | |
4320 { | |
4321 return tr("Remove Pane"); | |
4322 } | |
4323 | |
4324 void | |
4325 MainWindow::RemovePaneCommand::execute() | |
4326 { | |
4327 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane(); | |
4328 m_mw->m_paneStack->hidePane(m_pane); | |
4329 m_mw->m_overview->unregisterView(m_pane); | |
4330 m_added = false; | |
4331 } | |
4332 | |
4333 void | |
4334 MainWindow::RemovePaneCommand::unexecute() | |
4335 { | |
4336 m_mw->m_paneStack->showPane(m_pane); | |
4337 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane); | |
4338 m_mw->m_overview->registerView(m_pane); | |
4339 m_added = true; | |
4340 } | 2728 } |
4341 | 2729 |
4342 void | 2730 void |
4343 MainWindow::addLayer() | 2731 MainWindow::addLayer() |
4344 { | 2732 { |
4472 m_document->setChannel(newLayer, context.channel); | 2860 m_document->setChannel(newLayer, context.channel); |
4473 m_recentTransforms.add(transform); | 2861 m_recentTransforms.add(transform); |
4474 m_paneStack->setCurrentLayer(pane, newLayer); | 2862 m_paneStack->setCurrentLayer(pane, newLayer); |
4475 } | 2863 } |
4476 | 2864 |
4477 updateMenuStates(); | |
4478 } | |
4479 | |
4480 void | |
4481 MainWindow::deleteCurrentPane() | |
4482 { | |
4483 CommandHistory::getInstance()->startCompoundOperation | |
4484 (tr("Delete Pane"), true); | |
4485 | |
4486 Pane *pane = m_paneStack->getCurrentPane(); | |
4487 if (pane) { | |
4488 while (pane->getLayerCount() > 0) { | |
4489 Layer *layer = pane->getLayer(0); | |
4490 if (layer) { | |
4491 m_document->removeLayerFromView(pane, layer); | |
4492 } else { | |
4493 break; | |
4494 } | |
4495 } | |
4496 | |
4497 RemovePaneCommand *command = new RemovePaneCommand(this, pane); | |
4498 CommandHistory::getInstance()->addCommand(command); | |
4499 } | |
4500 | |
4501 CommandHistory::getInstance()->endCompoundOperation(); | |
4502 | |
4503 updateMenuStates(); | |
4504 } | |
4505 | |
4506 void | |
4507 MainWindow::deleteCurrentLayer() | |
4508 { | |
4509 Pane *pane = m_paneStack->getCurrentPane(); | |
4510 if (pane) { | |
4511 Layer *layer = pane->getSelectedLayer(); | |
4512 if (layer) { | |
4513 m_document->removeLayerFromView(pane, layer); | |
4514 } | |
4515 } | |
4516 updateMenuStates(); | 2865 updateMenuStates(); |
4517 } | 2866 } |
4518 | 2867 |
4519 void | 2868 void |
4520 MainWindow::renameCurrentLayer() | 2869 MainWindow::renameCurrentLayer() |
4612 { | 2961 { |
4613 m_playSpeed->setValue(m_playSpeed->defaultValue()); | 2962 m_playSpeed->setValue(m_playSpeed->defaultValue()); |
4614 } | 2963 } |
4615 | 2964 |
4616 void | 2965 void |
4617 MainWindow::playbackFrameChanged(unsigned long frame) | |
4618 { | |
4619 if (!(m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; | |
4620 | |
4621 RealTime now = RealTime::frame2RealTime | |
4622 (frame, getMainModel()->getSampleRate()); | |
4623 | |
4624 if (now.sec == m_lastPlayStatusSec) return; | |
4625 | |
4626 RealTime then = RealTime::frame2RealTime | |
4627 (m_playSource->getPlayEndFrame(), getMainModel()->getSampleRate()); | |
4628 | |
4629 QString nowStr; | |
4630 QString thenStr; | |
4631 QString remainingStr; | |
4632 | |
4633 if (then.sec > 10) { | |
4634 nowStr = now.toSecText().c_str(); | |
4635 thenStr = then.toSecText().c_str(); | |
4636 remainingStr = (then - now).toSecText().c_str(); | |
4637 m_lastPlayStatusSec = now.sec; | |
4638 } else { | |
4639 nowStr = now.toText(true).c_str(); | |
4640 thenStr = then.toText(true).c_str(); | |
4641 remainingStr = (then - now).toText(true).c_str(); | |
4642 } | |
4643 | |
4644 m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)") | |
4645 .arg(nowStr).arg(thenStr).arg(remainingStr); | |
4646 | |
4647 statusBar()->showMessage(m_myStatusMessage); | |
4648 } | |
4649 | |
4650 void | |
4651 MainWindow::globalCentreFrameChanged(unsigned long ) | |
4652 { | |
4653 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; | |
4654 Pane *p = 0; | |
4655 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return; | |
4656 if (!p->getFollowGlobalPan()) return; | |
4657 updateVisibleRangeDisplay(p); | |
4658 } | |
4659 | |
4660 void | |
4661 MainWindow::viewCentreFrameChanged(View *v, unsigned long ) | |
4662 { | |
4663 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; | |
4664 Pane *p = 0; | |
4665 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return; | |
4666 if (v == p) updateVisibleRangeDisplay(p); | |
4667 } | |
4668 | |
4669 void | |
4670 MainWindow::viewZoomLevelChanged(View *v, unsigned long , bool ) | |
4671 { | |
4672 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; | |
4673 Pane *p = 0; | |
4674 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return; | |
4675 if (v == p) updateVisibleRangeDisplay(p); | |
4676 } | |
4677 | |
4678 void | |
4679 MainWindow::updateVisibleRangeDisplay(Pane *p) const | 2966 MainWindow::updateVisibleRangeDisplay(Pane *p) const |
4680 { | 2967 { |
4681 if (!getMainModel() || !p) { | 2968 if (!getMainModel() || !p) { |
4682 return; | 2969 return; |
4683 } | 2970 } |
4754 (this, tr("Audio processing overload"), | 3041 (this, tr("Audio processing overload"), |
4755 tr("<b>Overloaded</b><p>Audio effects plugin auditioning has been disabled due to a processing overload.")); | 3042 tr("<b>Overloaded</b><p>Audio effects plugin auditioning has been disabled due to a processing overload.")); |
4756 } | 3043 } |
4757 | 3044 |
4758 void | 3045 void |
4759 MainWindow::layerAdded(Layer *) | 3046 MainWindow::layerRemoved(Layer *layer) |
4760 { | 3047 { |
4761 // std::cerr << "MainWindow::layerAdded(" << layer << ")" << std::endl; | |
4762 // setupExistingLayersMenu(); | |
4763 updateMenuStates(); | |
4764 } | |
4765 | |
4766 void | |
4767 MainWindow::layerRemoved(Layer *) | |
4768 { | |
4769 // std::cerr << "MainWindow::layerRemoved(" << layer << ")" << std::endl; | |
4770 setupExistingLayersMenus(); | 3048 setupExistingLayersMenus(); |
4771 updateMenuStates(); | 3049 MainWindowBase::layerRemoved(layer); |
4772 } | |
4773 | |
4774 void | |
4775 MainWindow::layerAboutToBeDeleted(Layer *layer) | |
4776 { | |
4777 // std::cerr << "MainWindow::layerAboutToBeDeleted(" << layer << ")" << std::endl; | |
4778 if (layer == m_timeRulerLayer) { | |
4779 // std::cerr << "(this is the time ruler layer)" << std::endl; | |
4780 m_timeRulerLayer = 0; | |
4781 } | |
4782 } | 3050 } |
4783 | 3051 |
4784 void | 3052 void |
4785 MainWindow::layerInAView(Layer *layer, bool inAView) | 3053 MainWindow::layerInAView(Layer *layer, bool inAView) |
4786 { | 3054 { |
4787 // std::cerr << "MainWindow::layerInAView(" << layer << "," << inAView << ")" << std::endl; | |
4788 | |
4789 // Check whether we need to add or remove model from play source | |
4790 Model *model = layer->getModel(); | |
4791 if (model) { | |
4792 if (inAView) { | |
4793 m_playSource->addModel(model); | |
4794 } else { | |
4795 bool found = false; | |
4796 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { | |
4797 Pane *pane = m_paneStack->getPane(i); | |
4798 if (!pane) continue; | |
4799 for (int j = 0; j < pane->getLayerCount(); ++j) { | |
4800 Layer *pl = pane->getLayer(j); | |
4801 if (pl && pl->getModel() == model) { | |
4802 found = true; | |
4803 break; | |
4804 } | |
4805 } | |
4806 if (found) break; | |
4807 } | |
4808 if (!found) m_playSource->removeModel(model); | |
4809 } | |
4810 } | |
4811 | |
4812 setupExistingLayersMenus(); | 3055 setupExistingLayersMenus(); |
4813 updateMenuStates(); | 3056 MainWindowBase::layerInAView(layer, inAView); |
4814 } | 3057 } |
4815 | 3058 |
4816 void | 3059 void |
4817 MainWindow::modelAdded(Model *model) | 3060 MainWindow::modelAdded(Model *model) |
4818 { | 3061 { |
4819 // std::cerr << "MainWindow::modelAdded(" << model << ")" << std::endl; | 3062 MainWindowBase::modelAdded(model); |
4820 m_playSource->addModel(model); | |
4821 if (dynamic_cast<DenseTimeValueModel *>(model)) { | 3063 if (dynamic_cast<DenseTimeValueModel *>(model)) { |
4822 setupPaneAndLayerMenus(); | 3064 setupPaneAndLayerMenus(); |
4823 } | 3065 } |
4824 } | 3066 } |
4825 | 3067 |
4826 void | 3068 void |
4827 MainWindow::mainModelChanged(WaveFileModel *model) | 3069 MainWindow::mainModelChanged(WaveFileModel *model) |
4828 { | 3070 { |
4829 // std::cerr << "MainWindow::mainModelChanged(" << model << ")" << std::endl; | |
4830 updateDescriptionLabel(); | |
4831 m_panLayer->setModel(model); | 3071 m_panLayer->setModel(model); |
4832 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate()); | 3072 |
4833 if (model && !m_playTarget && m_audioOutput) createPlayTarget(); | 3073 MainWindowBase::mainModelChanged(model); |
4834 } | 3074 |
4835 | 3075 if (m_playTarget) { |
4836 void | 3076 connect(m_fader, SIGNAL(valueChanged(float)), |
4837 MainWindow::modelAboutToBeDeleted(Model *model) | 3077 m_playTarget, SLOT(setOutputGain(float))); |
4838 { | 3078 } |
4839 // std::cerr << "MainWindow::modelAboutToBeDeleted(" << model << ")" << std::endl; | 3079 } |
4840 if (model == m_viewManager->getPlaybackModel()) { | 3080 |
4841 m_viewManager->setPlaybackModel(0); | 3081 void |
4842 } | 3082 MainWindow::setInstantsNumbering() |
4843 m_playSource->removeModel(model); | 3083 { |
4844 FFTDataServer::modelAboutToBeDeleted(model); | 3084 QAction *a = dynamic_cast<QAction *>(sender()); |
3085 if (!a) return; | |
3086 | |
3087 int type = m_numberingActions[a]; | |
3088 | |
3089 if (m_labeller) m_labeller->setType(Labeller::ValueType(type)); | |
3090 | |
3091 QSettings settings; | |
3092 settings.beginGroup("MainWindow"); | |
3093 settings.setValue("labellertype", type); | |
3094 settings.endGroup(); | |
3095 } | |
3096 | |
3097 void | |
3098 MainWindow::setInstantsCounterCycle() | |
3099 { | |
3100 QAction *a = dynamic_cast<QAction *>(sender()); | |
3101 if (!a) return; | |
3102 | |
3103 int cycle = a->text().toInt(); | |
3104 if (cycle == 0) return; | |
3105 | |
3106 if (m_labeller) m_labeller->setCounterCycleSize(cycle); | |
3107 | |
3108 QSettings settings; | |
3109 settings.beginGroup("MainWindow"); | |
3110 settings.setValue("labellercycle", cycle); | |
3111 settings.endGroup(); | |
3112 } | |
3113 | |
3114 void | |
3115 MainWindow::resetInstantsCounters() | |
3116 { | |
3117 LabelCounterInputDialog dialog(m_labeller, this); | |
3118 dialog.exec(); | |
4845 } | 3119 } |
4846 | 3120 |
4847 void | 3121 void |
4848 MainWindow::modelGenerationFailed(QString transformName) | 3122 MainWindow::modelGenerationFailed(QString transformName) |
4849 { | 3123 { |
4870 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) | 3144 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) |
4871 { | 3145 { |
4872 // std::cerr << "MainWindow::rightButtonMenuRequested(" << pane << ", " << position.x() << ", " << position.y() << ")" << std::endl; | 3146 // std::cerr << "MainWindow::rightButtonMenuRequested(" << pane << ", " << position.x() << ", " << position.y() << ")" << std::endl; |
4873 m_paneStack->setCurrentPane(pane); | 3147 m_paneStack->setCurrentPane(pane); |
4874 m_rightButtonMenu->popup(position); | 3148 m_rightButtonMenu->popup(position); |
4875 } | |
4876 | |
4877 void | |
4878 MainWindow::propertyStacksResized() | |
4879 { | |
4880 /* | |
4881 std::cerr << "MainWindow::propertyStacksResized" << std::endl; | |
4882 Pane *pane = m_paneStack->getCurrentPane(); | |
4883 if (pane && m_overview) { | |
4884 std::cerr << "Fixed width: " << pane->width() << std::endl; | |
4885 m_overview->setFixedWidth(pane->width()); | |
4886 } | |
4887 */ | |
4888 } | 3149 } |
4889 | 3150 |
4890 void | 3151 void |
4891 MainWindow::showLayerTree() | 3152 MainWindow::showLayerTree() |
4892 { | 3153 { |
4902 LayerTreeModel *tree = new LayerTreeModel(m_paneStack); | 3163 LayerTreeModel *tree = new LayerTreeModel(m_paneStack); |
4903 m_layerTreeView->resize(500, 300); //!!! | 3164 m_layerTreeView->resize(500, 300); //!!! |
4904 m_layerTreeView->setModel(tree); | 3165 m_layerTreeView->setModel(tree); |
4905 m_layerTreeView->expandAll(); | 3166 m_layerTreeView->expandAll(); |
4906 m_layerTreeView->show(); | 3167 m_layerTreeView->show(); |
4907 } | |
4908 | |
4909 void | |
4910 MainWindow::pollOSC() | |
4911 { | |
4912 if (!m_oscQueue || m_oscQueue->isEmpty()) return; | |
4913 std::cerr << "MainWindow::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << std::endl; | |
4914 | |
4915 if (m_openingAudioFile) return; | |
4916 | |
4917 OSCMessage message = m_oscQueue->readMessage(); | |
4918 | |
4919 if (message.getTarget() != 0) { | |
4920 return; //!!! for now -- this class is target 0, others not handled yet | |
4921 } | |
4922 | |
4923 handleOSCMessage(message); | |
4924 } | 3168 } |
4925 | 3169 |
4926 void | 3170 void |
4927 MainWindow::handleOSCMessage(const OSCMessage &message) | 3171 MainWindow::handleOSCMessage(const OSCMessage &message) |
4928 { | 3172 { |
5455 { | 3699 { |
5456 contextHelpChanged(""); | 3700 contextHelpChanged(""); |
5457 } | 3701 } |
5458 | 3702 |
5459 void | 3703 void |
5460 MainWindow::inProgressSelectionChanged() | |
5461 { | |
5462 Pane *currentPane = 0; | |
5463 if (m_paneStack) currentPane = m_paneStack->getCurrentPane(); | |
5464 if (currentPane) updateVisibleRangeDisplay(currentPane); | |
5465 } | |
5466 | |
5467 void | |
5468 MainWindow::contextHelpChanged(const QString &s) | |
5469 { | |
5470 if (s == "" && m_myStatusMessage != "") { | |
5471 statusBar()->showMessage(m_myStatusMessage); | |
5472 return; | |
5473 } | |
5474 statusBar()->showMessage(s); | |
5475 } | |
5476 | |
5477 void | |
5478 MainWindow::website() | 3704 MainWindow::website() |
5479 { | 3705 { |
5480 openHelpUrl(tr("http://www.sonicvisualiser.org/")); | 3706 openHelpUrl(tr("http://www.sonicvisualiser.org/")); |
5481 } | 3707 } |
5482 | 3708 |
5483 void | 3709 void |
5484 MainWindow::help() | 3710 MainWindow::help() |
5485 { | 3711 { |
5486 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.0/en/")); | 3712 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.0/en/")); |
5487 } | |
5488 | |
5489 void | |
5490 MainWindow::openHelpUrl(QString url) | |
5491 { | |
5492 // This method mostly lifted from Qt Assistant source code | |
5493 | |
5494 QProcess *process = new QProcess(this); | |
5495 connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater())); | |
5496 | |
5497 QStringList args; | |
5498 | |
5499 #ifdef Q_OS_MAC | |
5500 args.append(url); | |
5501 process->start("open", args); | |
5502 #else | |
5503 #ifdef Q_OS_WIN32 | |
5504 | |
5505 QString pf(getenv("ProgramFiles")); | |
5506 QString command = pf + QString("\\Internet Explorer\\IEXPLORE.EXE"); | |
5507 | |
5508 args.append(url); | |
5509 process->start(command, args); | |
5510 | |
5511 #else | |
5512 #ifdef Q_WS_X11 | |
5513 if (!qgetenv("KDE_FULL_SESSION").isEmpty()) { | |
5514 args.append("exec"); | |
5515 args.append(url); | |
5516 process->start("kfmclient", args); | |
5517 } else if (!qgetenv("BROWSER").isEmpty()) { | |
5518 args.append(url); | |
5519 process->start(qgetenv("BROWSER"), args); | |
5520 } else { | |
5521 args.append(url); | |
5522 process->start("firefox", args); | |
5523 } | |
5524 #endif | |
5525 #endif | |
5526 #endif | |
5527 } | 3713 } |
5528 | 3714 |
5529 void | 3715 void |
5530 MainWindow::about() | 3716 MainWindow::about() |
5531 { | 3717 { |