lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam and QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "version.h" lbajardsilogic@0: lbajardsilogic@0: #include "MainWindow.h" lbajardsilogic@0: #include "document/Document.h" lbajardsilogic@0: #include "PreferencesDialog.h" lbajardsilogic@0: lbajardsilogic@0: #include "view/Pane.h" lbajardsilogic@0: #include "view/PaneStack.h" lbajardsilogic@0: #include "data/model/WaveFileModel.h" lbajardsilogic@0: #include "data/model/SparseOneDimensionalModel.h" lbajardsilogic@0: #include "view/ViewManager.h" lbajardsilogic@0: #include "base/Preferences.h" lbajardsilogic@0: #include "layer/WaveformLayer.h" lbajardsilogic@0: #include "layer/TimeRulerLayer.h" lbajardsilogic@0: #include "layer/TimeInstantLayer.h" lbajardsilogic@0: #include "layer/TimeValueLayer.h" lbajardsilogic@0: #include "layer/Colour3DPlotLayer.h" lbajardsilogic@0: #include "layer/SliceLayer.h" lbajardsilogic@0: #include "layer/SliceableLayer.h" lbajardsilogic@0: #include "widgets/Fader.h" lbajardsilogic@0: #include "view/Overview.h" lbajardsilogic@0: #include "widgets/PropertyBox.h" lbajardsilogic@0: #include "widgets/PropertyStack.h" lbajardsilogic@0: #include "widgets/AudioDial.h" lbajardsilogic@0: #include "widgets/LayerTree.h" lbajardsilogic@0: #include "widgets/ListInputDialog.h" lbajardsilogic@0: #include "widgets/SubdividingMenu.h" lbajardsilogic@0: #include "widgets/NotifyingPushButton.h" lbajardsilogic@2: #include "widgets/InfoWidget.h" lbajardsilogic@2: #include "widgets/SearchWidget.h" lbajardsilogic@2: #include "widgets/QueryResultsWidget.h" lbajardsilogic@2: #include "widgets/ExpandWidget.h" lbajardsilogic@2: #include "widgets/AdvancedToolBox.h" lbajardsilogic@25: #include "widgets/ConnectionStatus.h" lbajardsilogic@0: #include "audioio/AudioCallbackPlaySource.h" lbajardsilogic@0: #include "audioio/AudioCallbackPlayTarget.h" lbajardsilogic@0: #include "audioio/AudioTargetFactory.h" lbajardsilogic@0: #include "audioio/PlaySpeedRangeMapper.h" lbajardsilogic@0: #include "data/fileio/AudioFileReaderFactory.h" lbajardsilogic@0: #include "data/fileio/DataFileReaderFactory.h" lbajardsilogic@0: #include "data/fileio/WavFileWriter.h" lbajardsilogic@0: #include "data/fileio/CSVFileWriter.h" lbajardsilogic@0: #include "data/fileio/BZipFileDevice.h" lbajardsilogic@0: #include "data/fileio/RemoteFile.h" lbajardsilogic@0: #include "data/fft/FFTDataServer.h" lbajardsilogic@0: #include "base/RecentFiles.h" lbajardsilogic@0: #include "transform/TransformFactory.h" lbajardsilogic@0: #include "base/PlayParameterRepository.h" lbajardsilogic@0: #include "base/XmlExportable.h" lbajardsilogic@0: #include "base/CommandHistory.h" lbajardsilogic@0: #include "base/Profiler.h" lbajardsilogic@0: #include "base/Clipboard.h" lbajardsilogic@10: #include "base/TempDirectory.h" lbajardsilogic@0: #include "osc/OSCQueue.h" lbajardsilogic@21: #include "main/EasaierSessionManager.h" lbajardsilogic@0: lbajardsilogic@0: // For version information lbajardsilogic@0: #include "vamp/vamp.h" lbajardsilogic@0: #include "vamp-sdk/PluginBase.h" lbajardsilogic@0: #include "plugin/api/ladspa.h" lbajardsilogic@0: #include "plugin/api/dssi.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@21: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: using std::cerr; lbajardsilogic@0: using std::endl; lbajardsilogic@0: lbajardsilogic@0: using std::vector; lbajardsilogic@0: using std::map; lbajardsilogic@0: using std::set; lbajardsilogic@0: lbajardsilogic@2: MainWindow * MainWindow::m_instance = 0; lbajardsilogic@2: lbajardsilogic@2: MainWindow * MainWindow::instance() lbajardsilogic@2: { lbajardsilogic@2: return m_instance; lbajardsilogic@2: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : lbajardsilogic@0: m_document(0), lbajardsilogic@0: m_paneStack(0), lbajardsilogic@0: m_viewManager(0), lbajardsilogic@0: m_overview(0), lbajardsilogic@0: m_timeRulerLayer(0), lbajardsilogic@0: m_audioOutput(withAudioOutput), lbajardsilogic@0: m_playSource(0), lbajardsilogic@0: m_playTarget(0), lbajardsilogic@0: m_oscQueue(withOSCSupport ? new OSCQueue() : 0), lbajardsilogic@0: m_recentFiles("RecentFiles", 20), lbajardsilogic@0: m_recentTransforms("RecentTransforms", 20), lbajardsilogic@0: m_mainMenusCreated(false), lbajardsilogic@0: m_paneMenu(0), lbajardsilogic@0: m_layerMenu(0), lbajardsilogic@0: m_transformsMenu(0), lbajardsilogic@0: m_existingLayersMenu(0), lbajardsilogic@0: m_sliceMenu(0), lbajardsilogic@0: m_recentFilesMenu(0), lbajardsilogic@0: m_recentTransformsMenu(0), lbajardsilogic@0: m_rightButtonMenu(0), lbajardsilogic@0: m_rightButtonLayerMenu(0), lbajardsilogic@0: m_rightButtonTransformsMenu(0), lbajardsilogic@0: m_documentModified(false), lbajardsilogic@0: m_openingAudioFile(false), lbajardsilogic@0: m_abandoning(false), lbajardsilogic@0: m_preferencesDialog(0) lbajardsilogic@0: { lbajardsilogic@21: m_instance = this; lbajardsilogic@21: lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser")); lbajardsilogic@0: lbajardsilogic@0: UnitDatabase::getInstance()->registerUnit("Hz"); lbajardsilogic@0: UnitDatabase::getInstance()->registerUnit("dB"); lbajardsilogic@0: lbajardsilogic@0: connect(CommandHistory::getInstance(), SIGNAL(commandExecuted()), lbajardsilogic@0: this, SLOT(documentModified())); lbajardsilogic@0: connect(CommandHistory::getInstance(), SIGNAL(documentRestored()), lbajardsilogic@0: this, SLOT(documentRestored())); lbajardsilogic@0: lbajardsilogic@0: QFrame *frame = new QFrame; lbajardsilogic@0: setCentralWidget(frame); lbajardsilogic@0: lbajardsilogic@0: QGridLayout *layout = new QGridLayout; lbajardsilogic@0: lbajardsilogic@0: m_viewManager = new ViewManager(); lbajardsilogic@0: connect(m_viewManager, SIGNAL(selectionChanged()), lbajardsilogic@0: this, SLOT(updateMenuStates())); lbajardsilogic@0: connect(m_viewManager, SIGNAL(inProgressSelectionChanged()), lbajardsilogic@0: this, SLOT(inProgressSelectionChanged())); lbajardsilogic@0: lbajardsilogic@0: m_descriptionLabel = new QLabel; lbajardsilogic@0: lbajardsilogic@0: m_paneStack = new PaneStack(frame, m_viewManager); lbajardsilogic@0: connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)), lbajardsilogic@0: this, SLOT(currentPaneChanged(Pane *))); lbajardsilogic@0: connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)), lbajardsilogic@0: this, SLOT(currentLayerChanged(Pane *, Layer *))); lbajardsilogic@0: connect(m_paneStack, SIGNAL(rightButtonMenuRequested(Pane *, QPoint)), lbajardsilogic@0: this, SLOT(rightButtonMenuRequested(Pane *, QPoint))); lbajardsilogic@0: connect(m_paneStack, SIGNAL(propertyStacksResized()), lbajardsilogic@0: this, SLOT(propertyStacksResized())); lbajardsilogic@0: connect(m_paneStack, SIGNAL(contextHelpChanged(const QString &)), lbajardsilogic@0: this, SLOT(contextHelpChanged(const QString &))); lbajardsilogic@0: lbajardsilogic@0: m_overview = new Overview(frame); lbajardsilogic@0: m_overview->setViewManager(m_viewManager); lbajardsilogic@0: m_overview->setFixedHeight(40); lbajardsilogic@0: m_overview->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); lbajardsilogic@0: connect(m_overview, SIGNAL(contextHelpChanged(const QString &)), lbajardsilogic@0: this, SLOT(contextHelpChanged(const QString &))); lbajardsilogic@0: lbajardsilogic@0: m_panLayer = new WaveformLayer; lbajardsilogic@0: m_panLayer->setChannelMode(WaveformLayer::MergeChannels); lbajardsilogic@0: // m_panLayer->setScale(WaveformLayer::MeterScale); lbajardsilogic@0: // m_panLayer->setAutoNormalize(true); lbajardsilogic@0: m_panLayer->setBaseColour(Qt::darkGreen); lbajardsilogic@0: m_panLayer->setAggressiveCacheing(true); lbajardsilogic@0: m_overview->addLayer(m_panLayer); lbajardsilogic@0: lbajardsilogic@0: m_playSource = new AudioCallbackPlaySource(m_viewManager); lbajardsilogic@0: lbajardsilogic@0: connect(m_playSource, SIGNAL(sampleRateMismatch(size_t, size_t, bool)), lbajardsilogic@0: this, SLOT(sampleRateMismatch(size_t, size_t, bool))); lbajardsilogic@0: connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()), lbajardsilogic@0: this, SLOT(audioOverloadPluginDisabled())); lbajardsilogic@0: lbajardsilogic@0: m_fader = new Fader(frame, false); lbajardsilogic@0: connect(m_fader, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); lbajardsilogic@0: connect(m_fader, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); lbajardsilogic@0: lbajardsilogic@0: m_playSpeed = new AudioDial(frame); lbajardsilogic@0: m_playSpeed->setMinimum(0); lbajardsilogic@0: m_playSpeed->setMaximum(200); lbajardsilogic@0: m_playSpeed->setValue(100); lbajardsilogic@0: m_playSpeed->setFixedWidth(24); lbajardsilogic@0: m_playSpeed->setFixedHeight(24); lbajardsilogic@0: m_playSpeed->setNotchesVisible(true); lbajardsilogic@0: m_playSpeed->setPageStep(10); lbajardsilogic@0: m_playSpeed->setObjectName(tr("Playback Speedup")); lbajardsilogic@0: m_playSpeed->setDefaultValue(100); lbajardsilogic@0: m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper(0, 200)); lbajardsilogic@0: m_playSpeed->setShowToolTip(true); lbajardsilogic@0: connect(m_playSpeed, SIGNAL(valueChanged(int)), lbajardsilogic@0: this, SLOT(playSpeedChanged(int))); lbajardsilogic@0: connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); lbajardsilogic@0: connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); lbajardsilogic@0: lbajardsilogic@0: m_playSharpen = new NotifyingPushButton(frame); lbajardsilogic@0: m_playSharpen->setToolTip(tr("Sharpen percussive transients")); lbajardsilogic@0: m_playSharpen->setFixedSize(20, 20); lbajardsilogic@0: // m_playSharpen->setFlat(true); lbajardsilogic@0: m_playSharpen->setEnabled(false); lbajardsilogic@0: m_playSharpen->setCheckable(true); lbajardsilogic@0: m_playSharpen->setChecked(false); lbajardsilogic@0: m_playSharpen->setIcon(QIcon(":icons/sharpen.png")); lbajardsilogic@0: connect(m_playSharpen, SIGNAL(clicked()), this, SLOT(playSharpenToggled())); lbajardsilogic@0: connect(m_playSharpen, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); lbajardsilogic@0: connect(m_playSharpen, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); lbajardsilogic@0: lbajardsilogic@0: m_playMono = new NotifyingPushButton(frame); lbajardsilogic@0: m_playMono->setToolTip(tr("Run time stretcher in mono only")); lbajardsilogic@0: m_playMono->setFixedSize(20, 20); lbajardsilogic@0: // m_playMono->setFlat(true); lbajardsilogic@0: m_playMono->setEnabled(false); lbajardsilogic@0: m_playMono->setCheckable(true); lbajardsilogic@0: m_playMono->setChecked(false); lbajardsilogic@0: m_playMono->setIcon(QIcon(":icons/mono.png")); lbajardsilogic@0: connect(m_playMono, SIGNAL(clicked()), this, SLOT(playMonoToggled())); lbajardsilogic@0: connect(m_playMono, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); lbajardsilogic@0: connect(m_playMono, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); lbajardsilogic@0: lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: m_playSharpen->setChecked(settings.value("playsharpen", true).toBool()); lbajardsilogic@0: m_playMono->setChecked(settings.value("playmono", false).toBool()); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: lbajardsilogic@2: m_infoWidget = new InfoWidget(); lbajardsilogic@2: m_searchWidget = new SearchWidget(); lbajardsilogic@2: m_resultsWidget = new QueryResultsWidget(); lbajardsilogic@2: lbajardsilogic@2: m_qtabwidget = new QTabWidget(); lbajardsilogic@2: m_qtabwidget->addTab(m_searchWidget, tr("Search")); lbajardsilogic@2: m_qtabwidget->addTab(m_resultsWidget, tr("Result")); lbajardsilogic@2: m_qtabwidget->addTab(m_infoWidget, tr("Info")); lbajardsilogic@2: m_qtabwidget->addTab(new QWidget, tr("Related media")); lbajardsilogic@2: lbajardsilogic@2: QGridLayout *auxlayout = new QGridLayout; lbajardsilogic@2: auxlayout->addWidget(m_paneStack, 0, 0, 1, 5); lbajardsilogic@2: auxlayout->addWidget(m_overview, 1, 0); lbajardsilogic@2: auxlayout->addWidget(m_fader, 1, 1); lbajardsilogic@2: auxlayout->addWidget(m_playSpeed, 1, 2); lbajardsilogic@2: auxlayout->addWidget(m_playSharpen, 1, 3); lbajardsilogic@2: auxlayout->addWidget(m_playMono, 1, 4); lbajardsilogic@2: QWidget *auxwidget = new QWidget; lbajardsilogic@2: auxwidget->setLayout(auxlayout); lbajardsilogic@2: lbajardsilogic@2: ExpandWidget *bottomExpandWidget = new ExpandWidget(); lbajardsilogic@2: bottomExpandWidget->setWidgetLocation(ExpandWidget::Location_Bottom); lbajardsilogic@2: bottomExpandWidget->setPanes(auxwidget, m_qtabwidget); lbajardsilogic@2: lbajardsilogic@2: m_toolBox = new AdvancedToolBox(); lbajardsilogic@2: m_toolBox->addItem("Layers", new QWidget); lbajardsilogic@2: m_toolBox->addItem("Real-time filters", new QWidget); lbajardsilogic@2: lbajardsilogic@2: ExpandWidget *mainExpandWidget = new ExpandWidget(); lbajardsilogic@2: mainExpandWidget->setWidgetLocation(ExpandWidget::Location_Right); lbajardsilogic@2: mainExpandWidget->setPanes(bottomExpandWidget, m_toolBox); lbajardsilogic@2: lbajardsilogic@2: layout->addWidget(mainExpandWidget, 0, 0); lbajardsilogic@0: lbajardsilogic@0: m_paneStack->setPropertyStackMinWidth lbajardsilogic@0: (m_fader->width() + m_playSpeed->width() + m_playSharpen->width() + lbajardsilogic@0: m_playMono->width() + layout->spacing() * 4); lbajardsilogic@0: lbajardsilogic@0: layout->setColumnStretch(0, 10); lbajardsilogic@0: lbajardsilogic@0: frame->setLayout(layout); lbajardsilogic@0: lbajardsilogic@0: connect(m_viewManager, SIGNAL(outputLevelsChanged(float, float)), lbajardsilogic@0: this, SLOT(outputLevelsChanged(float, float))); lbajardsilogic@0: lbajardsilogic@0: connect(m_viewManager, SIGNAL(playbackFrameChanged(unsigned long)), lbajardsilogic@0: this, SLOT(playbackFrameChanged(unsigned long))); lbajardsilogic@0: lbajardsilogic@0: connect(m_viewManager, SIGNAL(globalCentreFrameChanged(unsigned long)), lbajardsilogic@0: this, SLOT(globalCentreFrameChanged(unsigned long))); lbajardsilogic@0: lbajardsilogic@0: connect(m_viewManager, SIGNAL(viewCentreFrameChanged(View *, unsigned long)), lbajardsilogic@0: this, SLOT(viewCentreFrameChanged(View *, unsigned long))); lbajardsilogic@0: lbajardsilogic@0: connect(m_viewManager, SIGNAL(viewZoomLevelChanged(View *, unsigned long, bool)), lbajardsilogic@0: this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool))); lbajardsilogic@0: lbajardsilogic@0: connect(Preferences::getInstance(), lbajardsilogic@0: SIGNAL(propertyChanged(PropertyContainer::PropertyName)), lbajardsilogic@0: this, lbajardsilogic@0: SLOT(preferenceChanged(PropertyContainer::PropertyName))); lbajardsilogic@0: lbajardsilogic@0: // preferenceChanged("Property Box Layout"); lbajardsilogic@0: lbajardsilogic@0: if (m_oscQueue && m_oscQueue->isOK()) { lbajardsilogic@0: connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC())); lbajardsilogic@0: QTimer *oscTimer = new QTimer(this); lbajardsilogic@0: connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); lbajardsilogic@0: oscTimer->start(1000); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@10: m_httpClient = new HttpClient(TempDirectory::getInstance()->getConfigPath()); lbajardsilogic@21: m_EasaierManager = new EasaierSessionManager(m_httpClient); lbajardsilogic@21: lbajardsilogic@21: connect(m_EasaierManager, SIGNAL(queryModelLoaded(QueryModel*)), lbajardsilogic@21: this, SLOT(queryModelLoaded(QueryModel*))); lbajardsilogic@10: lbajardsilogic@0: setupMenus(); lbajardsilogic@0: setupToolbars(); lbajardsilogic@0: lbajardsilogic@0: statusBar(); lbajardsilogic@0: lbajardsilogic@0: newSession(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::~MainWindow() lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::~MainWindow()" << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (!m_abandoning) { lbajardsilogic@0: closeSession(); lbajardsilogic@0: } lbajardsilogic@21: delete m_EasaierManager; lbajardsilogic@21: delete m_httpClient; lbajardsilogic@0: delete m_playTarget; lbajardsilogic@0: delete m_playSource; lbajardsilogic@0: delete m_viewManager; lbajardsilogic@0: delete m_oscQueue; lbajardsilogic@0: Profiles::getInstance()->dump(); lbajardsilogic@21: lbajardsilogic@21: m_instance = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: MainWindow::getOpenFileName(FileFinder::FileType type) lbajardsilogic@0: { lbajardsilogic@0: FileFinder *ff = FileFinder::getInstance(); lbajardsilogic@0: switch (type) { lbajardsilogic@0: case FileFinder::SessionFile: lbajardsilogic@0: return ff->getOpenFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::AudioFile: lbajardsilogic@0: return ff->getOpenFileName(type, m_audioFile); lbajardsilogic@0: case FileFinder::LayerFile: lbajardsilogic@0: return ff->getOpenFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::SessionOrAudioFile: lbajardsilogic@0: return ff->getOpenFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::ImageFile: lbajardsilogic@0: return ff->getOpenFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::AnyFile: lbajardsilogic@0: if (getMainModel() != 0 && lbajardsilogic@0: m_paneStack != 0 && lbajardsilogic@0: m_paneStack->getCurrentPane() != 0) { // can import a layer lbajardsilogic@0: return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile); lbajardsilogic@0: } else { lbajardsilogic@0: return ff->getOpenFileName(FileFinder::SessionOrAudioFile, lbajardsilogic@0: m_sessionFile); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: return ""; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: MainWindow::getSaveFileName(FileFinder::FileType type) lbajardsilogic@0: { lbajardsilogic@0: FileFinder *ff = FileFinder::getInstance(); lbajardsilogic@0: switch (type) { lbajardsilogic@0: case FileFinder::SessionFile: lbajardsilogic@0: return ff->getSaveFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::AudioFile: lbajardsilogic@0: return ff->getSaveFileName(type, m_audioFile); lbajardsilogic@0: case FileFinder::LayerFile: lbajardsilogic@0: return ff->getSaveFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::SessionOrAudioFile: lbajardsilogic@0: return ff->getSaveFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::ImageFile: lbajardsilogic@0: return ff->getSaveFileName(type, m_sessionFile); lbajardsilogic@0: case FileFinder::AnyFile: lbajardsilogic@0: return ff->getSaveFileName(type, m_sessionFile); lbajardsilogic@0: } lbajardsilogic@0: return ""; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::registerLastOpenedFilePath(FileFinder::FileType type, QString path) lbajardsilogic@0: { lbajardsilogic@0: FileFinder *ff = FileFinder::getInstance(); lbajardsilogic@0: ff->registerLastOpenedFilePath(type, path); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupMenus() lbajardsilogic@0: { lbajardsilogic@0: if (!m_mainMenusCreated) { lbajardsilogic@0: m_rightButtonMenu = new QMenu(); lbajardsilogic@0: lbajardsilogic@0: // No -- we don't want tear-off enabled on the right-button lbajardsilogic@0: // menu. If it is enabled, then simply right-clicking and lbajardsilogic@0: // releasing will pop up the menu, activate the tear-off, and lbajardsilogic@0: // leave the torn-off menu window in front of the main window. lbajardsilogic@0: // That isn't desirable. I'm not sure it ever would be, in a lbajardsilogic@0: // context menu -- perhaps technically a Qt bug? lbajardsilogic@0: // m_rightButtonMenu->setTearOffEnabled(true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (m_rightButtonLayerMenu) { lbajardsilogic@0: m_rightButtonLayerMenu->clear(); lbajardsilogic@0: } else { lbajardsilogic@0: m_rightButtonLayerMenu = m_rightButtonMenu->addMenu(tr("&Layer")); lbajardsilogic@0: m_rightButtonLayerMenu->setTearOffEnabled(true); lbajardsilogic@0: m_rightButtonMenu->addSeparator(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (m_rightButtonTransformsMenu) { lbajardsilogic@0: m_rightButtonTransformsMenu->clear(); lbajardsilogic@0: } else { lbajardsilogic@0: m_rightButtonTransformsMenu = m_rightButtonMenu->addMenu(tr("&Transform")); lbajardsilogic@0: m_rightButtonTransformsMenu->setTearOffEnabled(true); lbajardsilogic@0: m_rightButtonMenu->addSeparator(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!m_mainMenusCreated) { lbajardsilogic@0: CommandHistory::getInstance()->registerMenu(m_rightButtonMenu); lbajardsilogic@0: m_rightButtonMenu->addSeparator(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: setupFileMenu(); lbajardsilogic@21: setupEasaierMenu(); lbajardsilogic@0: setupEditMenu(); lbajardsilogic@0: setupViewMenu(); lbajardsilogic@0: setupPaneAndLayerMenus(); lbajardsilogic@0: setupTransformsMenu(); lbajardsilogic@2: setupSettingMenu(); lbajardsilogic@0: setupHelpMenu(); lbajardsilogic@0: lbajardsilogic@0: m_mainMenusCreated = true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupFileMenu() lbajardsilogic@0: { lbajardsilogic@0: if (m_mainMenusCreated) return; lbajardsilogic@0: lbajardsilogic@0: QMenu *menu = menuBar()->addMenu(tr("&File")); lbajardsilogic@0: menu->setTearOffEnabled(true); lbajardsilogic@21: //QToolBar *toolbar = addToolBar(tr("File Toolbar")); lbajardsilogic@0: lbajardsilogic@0: QIcon icon(":icons/filenew.png"); lbajardsilogic@0: icon.addFile(":icons/filenew-22.png"); lbajardsilogic@0: QAction *action = new QAction(icon, tr("&New Session"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+N")); lbajardsilogic@0: action->setStatusTip(tr("Abandon the current Sonic Visualiser session and start a new one")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(newSession())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@21: //toolbar->addAction(action); lbajardsilogic@0: lbajardsilogic@0: icon = QIcon(":icons/fileopensession.png"); lbajardsilogic@0: action = new QAction(icon, tr("&Open Session..."), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+O")); lbajardsilogic@0: action->setStatusTip(tr("Open a previously saved Sonic Visualiser session file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(openSession())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: icon = QIcon(":icons/fileopen.png"); lbajardsilogic@0: icon.addFile(":icons/fileopen-22.png"); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(icon, tr("&Open..."), this); lbajardsilogic@0: action->setStatusTip(tr("Open a session file, audio file, or layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(openSomething())); lbajardsilogic@21: //toolbar->addAction(action); lbajardsilogic@0: lbajardsilogic@0: icon = QIcon(":icons/filesave.png"); lbajardsilogic@0: icon.addFile(":icons/filesave-22.png"); lbajardsilogic@0: action = new QAction(icon, tr("&Save Session"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+S")); lbajardsilogic@0: action->setStatusTip(tr("Save the current session into a Sonic Visualiser session file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(saveSession())); lbajardsilogic@0: connect(this, SIGNAL(canSave(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@21: //toolbar->addAction(action); lbajardsilogic@0: lbajardsilogic@0: icon = QIcon(":icons/filesaveas.png"); lbajardsilogic@0: icon.addFile(":icons/filesaveas-22.png"); lbajardsilogic@0: action = new QAction(icon, tr("Save Session &As..."), this); lbajardsilogic@0: action->setStatusTip(tr("Save the current session into a new Sonic Visualiser session file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(saveSessionAs())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@21: //toolbar->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: icon = QIcon(":icons/fileopenaudio.png"); lbajardsilogic@0: action = new QAction(icon, tr("&Import Audio File..."), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+I")); lbajardsilogic@0: action->setStatusTip(tr("Import an existing audio file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(importAudio())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Import Secondary Audio File..."), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+Shift+I")); lbajardsilogic@0: action->setStatusTip(tr("Import an extra audio file as a separate layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(importMoreAudio())); lbajardsilogic@0: connect(this, SIGNAL(canImportMoreAudio(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("&Export Audio File..."), this); lbajardsilogic@0: action->setStatusTip(tr("Export selection as an audio file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(exportAudio())); lbajardsilogic@0: connect(this, SIGNAL(canExportAudio(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Import Annotation &Layer..."), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+L")); lbajardsilogic@0: action->setStatusTip(tr("Import layer data from an existing file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(importLayer())); lbajardsilogic@0: connect(this, SIGNAL(canImportLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Export Annotation Layer..."), this); lbajardsilogic@0: action->setStatusTip(tr("Export layer data to a file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(exportLayer())); lbajardsilogic@0: connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Export Image File..."), this); lbajardsilogic@0: action->setStatusTip(tr("Export a single pane to an image file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(exportImage())); lbajardsilogic@0: connect(this, SIGNAL(canExportImage(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Open Lo&cation..."), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+Shift+O")); lbajardsilogic@0: action->setStatusTip(tr("Open or import a file from a remote URL")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(openLocation())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: m_recentFilesMenu = menu->addMenu(tr("&Recent Files")); lbajardsilogic@0: m_recentFilesMenu->setTearOffEnabled(true); lbajardsilogic@0: setupRecentFilesMenu(); lbajardsilogic@0: connect(&m_recentFiles, SIGNAL(recentChanged()), lbajardsilogic@0: this, SLOT(setupRecentFilesMenu())); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: action = new QAction(tr("&Preferences..."), this); lbajardsilogic@0: action->setStatusTip(tr("Adjust the application preferences")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(preferences())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: /*!!! lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Play / Pause"), this); lbajardsilogic@0: action->setShortcut(tr("Space")); lbajardsilogic@0: action->setStatusTip(tr("Start or stop playback from the current position")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(play())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: action = new QAction(QIcon(":/icons/exit.png"), lbajardsilogic@0: tr("&Quit"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+Q")); lbajardsilogic@0: action->setStatusTip(tr("Exit Sonic Visualiser")); lbajardsilogic@10: connect(action, SIGNAL(triggered()), this, SLOT(exit())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@21: MainWindow::setupEasaierMenu() lbajardsilogic@21: { lbajardsilogic@21: if (m_mainMenusCreated) return; lbajardsilogic@21: lbajardsilogic@21: QMenu* menu = menuBar()->addMenu(tr("&Easaier")); lbajardsilogic@21: QToolBar *toolbar = addToolBar(tr("Easaier session Toolbar")); lbajardsilogic@21: lbajardsilogic@21: QIcon icon(":icons/filenew.png"); lbajardsilogic@21: QAction *action = new QAction(icon, tr("&New Session"), this); lbajardsilogic@21: action->setShortcut(tr("Ctrl+N")); lbajardsilogic@21: action->setStatusTip(tr("Clear the current Easaier session and start a new one")); lbajardsilogic@21: connect(action, SIGNAL(triggered()), this, SLOT(newEasaierSession())); lbajardsilogic@21: menu->addAction(action); lbajardsilogic@21: toolbar->addAction(action); lbajardsilogic@21: lbajardsilogic@21: icon = QIcon(":icons/fileopen.png"); lbajardsilogic@21: action = new QAction(icon, tr("&Open Session..."), this); lbajardsilogic@21: action->setShortcut(tr("Ctrl+O")); lbajardsilogic@21: action->setStatusTip(tr("Open a previously saved Easaier session file")); lbajardsilogic@21: connect(action, SIGNAL(triggered()), this, SLOT(openEasaierSession())); lbajardsilogic@21: menu->addAction(action); lbajardsilogic@21: toolbar->addAction(action); lbajardsilogic@21: lbajardsilogic@21: icon = QIcon(":icons/filesave.png"); lbajardsilogic@21: action = new QAction(icon, tr("&Save Session"), this); lbajardsilogic@21: action->setShortcut(tr("Ctrl+S")); lbajardsilogic@21: action->setStatusTip(tr("Save the current session into a Easaier session file")); lbajardsilogic@21: connect(action, SIGNAL(triggered()), this, SLOT(saveEasaierSession())); lbajardsilogic@21: //connect(this, SIGNAL(canSave(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@21: menu->addAction(action); lbajardsilogic@21: toolbar->addAction(action); lbajardsilogic@21: lbajardsilogic@21: icon = QIcon(":icons/filesaveas.png"); lbajardsilogic@21: action = new QAction(icon, tr("Save Session &As..."), this); lbajardsilogic@21: action->setStatusTip(tr("Save the current session into a new Easaier session file")); lbajardsilogic@21: connect(action, SIGNAL(triggered()), this, SLOT(saveEasaierSessionAs())); lbajardsilogic@21: menu->addAction(action); lbajardsilogic@21: toolbar->addAction(action); lbajardsilogic@21: lbajardsilogic@21: menu->addSeparator(); lbajardsilogic@21: lbajardsilogic@21: action = new QAction(QIcon(":/icons/exit.png"), lbajardsilogic@21: tr("&Quit"), this); lbajardsilogic@21: action->setShortcut(tr("Ctrl+Q")); lbajardsilogic@21: connect(action, SIGNAL(triggered()), this, SLOT(exit())); lbajardsilogic@21: menu->addAction(action); lbajardsilogic@21: lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void lbajardsilogic@0: MainWindow::setupEditMenu() lbajardsilogic@0: { lbajardsilogic@0: if (m_mainMenusCreated) return; lbajardsilogic@0: lbajardsilogic@0: QMenu *menu = menuBar()->addMenu(tr("&Edit")); lbajardsilogic@0: menu->setTearOffEnabled(true); lbajardsilogic@0: CommandHistory::getInstance()->registerMenu(menu); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: QAction *action = new QAction(QIcon(":/icons/editcut.png"), lbajardsilogic@0: tr("Cu&t"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+X")); lbajardsilogic@0: action->setStatusTip(tr("Cut the selection from the current layer to the clipboard")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(cut())); lbajardsilogic@0: connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/editcopy.png"), lbajardsilogic@0: tr("&Copy"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+C")); lbajardsilogic@0: action->setStatusTip(tr("Copy the selection from the current layer to the clipboard")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(copy())); lbajardsilogic@0: connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/editpaste.png"), lbajardsilogic@0: tr("&Paste"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+V")); lbajardsilogic@0: action->setStatusTip(tr("Paste from the clipboard to the current layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(paste())); lbajardsilogic@0: connect(this, SIGNAL(canPaste(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("&Delete Selected Items"), this); lbajardsilogic@0: action->setShortcut(tr("Del")); lbajardsilogic@0: action->setStatusTip(tr("Delete the selection from the current layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(deleteSelected())); lbajardsilogic@0: connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: m_rightButtonMenu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Select &All"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+A")); lbajardsilogic@0: action->setStatusTip(tr("Select the whole duration of the current session")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(selectAll())); lbajardsilogic@0: connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Select &Visible Range"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+Shift+A")); lbajardsilogic@0: action->setStatusTip(tr("Select the time range corresponding to the current window width")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(selectVisible())); lbajardsilogic@0: connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Select to &Start"), this); lbajardsilogic@0: action->setShortcut(tr("Shift+Left")); lbajardsilogic@0: action->setStatusTip(tr("Select from the start of the session to the current playback position")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(selectToStart())); lbajardsilogic@0: connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Select to &End"), this); lbajardsilogic@0: action->setShortcut(tr("Shift+Right")); lbajardsilogic@0: action->setStatusTip(tr("Select from the current playback position to the end of the session")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(selectToEnd())); lbajardsilogic@0: connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("C&lear Selection"), this); lbajardsilogic@0: action->setShortcut(tr("Esc")); lbajardsilogic@0: action->setStatusTip(tr("Clear the selection")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(clearSelection())); lbajardsilogic@0: connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("&Insert Instant at Playback Position"), this); lbajardsilogic@0: action->setShortcut(tr("Enter")); lbajardsilogic@0: action->setStatusTip(tr("Insert a new time instant at the current playback position, in a new layer if necessary")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(insertInstant())); lbajardsilogic@0: connect(this, SIGNAL(canInsertInstant(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Insert Instants at Selection &Boundaries"), this); lbajardsilogic@0: action->setShortcut(tr("Shift+Enter")); lbajardsilogic@0: action->setStatusTip(tr("Insert new time instants at the start and end of the current selection, in a new layer if necessary")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(insertInstantsAtBoundaries())); lbajardsilogic@0: connect(this, SIGNAL(canInsertInstantsAtBoundaries(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: // Laptop shortcut (no keypad Enter key) lbajardsilogic@0: connect(new QShortcut(tr(";"), this), SIGNAL(activated()), lbajardsilogic@0: this, SLOT(insertInstant())); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@2: MainWindow::setupSettingMenu() lbajardsilogic@2: { lbajardsilogic@2: if (m_mainMenusCreated) return; lbajardsilogic@2: lbajardsilogic@2: QAction *action = 0; lbajardsilogic@2: QMenu *menu = 0; lbajardsilogic@2: lbajardsilogic@2: menu = menuBar()->addMenu(tr("&Settings")); lbajardsilogic@2: menu->setTearOffEnabled(true); lbajardsilogic@2: lbajardsilogic@10: action = new QAction(tr("&Connection settings"), this); lbajardsilogic@10: connect(action, SIGNAL(triggered()), this, SLOT(connectionSettings())); lbajardsilogic@10: menu->addAction(action); lbajardsilogic@2: lbajardsilogic@2: action = new QAction(tr("&Style setting"), this); lbajardsilogic@2: connect(action, SIGNAL(triggered()), this, SLOT(styleSetting())); lbajardsilogic@2: menu->addAction(action); lbajardsilogic@2: } lbajardsilogic@2: lbajardsilogic@2: void lbajardsilogic@0: MainWindow::setupViewMenu() lbajardsilogic@0: { lbajardsilogic@0: if (m_mainMenusCreated) return; lbajardsilogic@0: lbajardsilogic@0: QAction *action = 0; lbajardsilogic@0: lbajardsilogic@0: QMenu *menu = menuBar()->addMenu(tr("&View")); lbajardsilogic@0: menu->setTearOffEnabled(true); lbajardsilogic@0: action = new QAction(tr("Scroll &Left"), this); lbajardsilogic@0: action->setShortcut(tr("Left")); lbajardsilogic@0: action->setStatusTip(tr("Scroll the current pane to the left")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(scrollLeft())); lbajardsilogic@0: connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Scroll &Right"), this); lbajardsilogic@0: action->setShortcut(tr("Right")); lbajardsilogic@0: action->setStatusTip(tr("Scroll the current pane to the right")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(scrollRight())); lbajardsilogic@0: connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("&Jump Left"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+Left")); lbajardsilogic@0: action->setStatusTip(tr("Scroll the current pane a big step to the left")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(jumpLeft())); lbajardsilogic@0: connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("J&ump Right"), this); lbajardsilogic@0: action->setShortcut(tr("Ctrl+Right")); lbajardsilogic@0: action->setStatusTip(tr("Scroll the current pane a big step to the right")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(jumpRight())); lbajardsilogic@0: connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/zoom-in.png"), lbajardsilogic@0: tr("Zoom &In"), this); lbajardsilogic@0: action->setShortcut(tr("Up")); lbajardsilogic@0: action->setStatusTip(tr("Increase the zoom level")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(zoomIn())); lbajardsilogic@0: connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/zoom-out.png"), lbajardsilogic@0: tr("Zoom &Out"), this); lbajardsilogic@0: action->setShortcut(tr("Down")); lbajardsilogic@0: action->setStatusTip(tr("Decrease the zoom level")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(zoomOut())); lbajardsilogic@0: connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Restore &Default Zoom"), this); lbajardsilogic@0: action->setStatusTip(tr("Restore the zoom level to the default")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(zoomDefault())); lbajardsilogic@0: connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/zoom-fit.png"), lbajardsilogic@0: tr("Zoom to &Fit"), this); lbajardsilogic@0: action->setStatusTip(tr("Zoom to show the whole file")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(zoomToFit())); lbajardsilogic@0: connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: QActionGroup *overlayGroup = new QActionGroup(this); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show &No Overlays"), this); lbajardsilogic@0: action->setShortcut(tr("0")); lbajardsilogic@0: action->setStatusTip(tr("Hide centre indicator, frame times, layer names and scale")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(showNoOverlays())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(false); lbajardsilogic@0: overlayGroup->addAction(action); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show &Minimal Overlays"), this); lbajardsilogic@0: action->setShortcut(tr("9")); lbajardsilogic@0: action->setStatusTip(tr("Show centre indicator only")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(showMinimalOverlays())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(false); lbajardsilogic@0: overlayGroup->addAction(action); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show &Standard Overlays"), this); lbajardsilogic@0: action->setShortcut(tr("8")); lbajardsilogic@0: action->setStatusTip(tr("Show centre indicator, frame times and scale")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(showStandardOverlays())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(true); lbajardsilogic@0: overlayGroup->addAction(action); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show &All Overlays"), this); lbajardsilogic@0: action->setShortcut(tr("7")); lbajardsilogic@0: action->setStatusTip(tr("Show all texts and scale")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(showAllOverlays())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(false); lbajardsilogic@0: overlayGroup->addAction(action); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show &Zoom Wheels"), this); lbajardsilogic@0: action->setShortcut(tr("Z")); lbajardsilogic@0: action->setStatusTip(tr("Show thumbwheels for zooming horizontally and vertically")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(toggleZoomWheels())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(m_viewManager->getZoomWheelsEnabled()); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show Property Bo&xes"), this); lbajardsilogic@0: action->setShortcut(tr("X")); lbajardsilogic@0: action->setStatusTip(tr("Show the layer property boxes at the side of the main window")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(togglePropertyBoxes())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(true); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show Status &Bar"), this); lbajardsilogic@0: action->setStatusTip(tr("Show context help information in the status bar at the bottom of the window")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(toggleStatusBar())); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(true); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: bool sb = settings.value("showstatusbar", true).toBool(); lbajardsilogic@0: if (!sb) { lbajardsilogic@0: action->setChecked(false); lbajardsilogic@0: statusBar()->hide(); lbajardsilogic@0: } lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: lbajardsilogic@0: /*!!! This one doesn't work properly yet lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Show La&yer Hierarchy"), this); lbajardsilogic@0: action->setShortcut(tr("Alt+L")); lbajardsilogic@0: action->setStatusTip(tr("Open a window displaying the hierarchy of panes and layers in this session")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: */ lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupPaneAndLayerMenus() lbajardsilogic@0: { lbajardsilogic@0: if (m_paneMenu) { lbajardsilogic@0: m_paneActions.clear(); lbajardsilogic@0: m_paneMenu->clear(); lbajardsilogic@0: } else { lbajardsilogic@0: m_paneMenu = menuBar()->addMenu(tr("&Pane")); lbajardsilogic@0: m_paneMenu->setTearOffEnabled(true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (m_layerMenu) { lbajardsilogic@0: m_layerActions.clear(); lbajardsilogic@0: m_layerMenu->clear(); lbajardsilogic@0: } else { lbajardsilogic@0: m_layerMenu = menuBar()->addMenu(tr("&Layer")); lbajardsilogic@0: m_layerMenu->setTearOffEnabled(true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QMenu *menu = m_paneMenu; lbajardsilogic@0: lbajardsilogic@0: QAction *action = new QAction(QIcon(":/icons/pane.png"), tr("Add &New Pane"), this); lbajardsilogic@0: action->setShortcut(tr("Alt+N")); lbajardsilogic@0: action->setStatusTip(tr("Add a new pane containing only a time ruler")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addPane())); lbajardsilogic@0: connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_paneActions[action] = PaneConfiguration(LayerFactory::TimeRuler); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: menu = m_layerMenu; lbajardsilogic@0: lbajardsilogic@0: // menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: LayerFactory::LayerTypeSet emptyLayerTypes = lbajardsilogic@0: LayerFactory::getInstance()->getValidEmptyLayerTypes(); lbajardsilogic@0: lbajardsilogic@0: for (LayerFactory::LayerTypeSet::iterator i = emptyLayerTypes.begin(); lbajardsilogic@0: i != emptyLayerTypes.end(); ++i) { lbajardsilogic@0: lbajardsilogic@0: QIcon icon; lbajardsilogic@0: QString mainText, tipText, channelText; lbajardsilogic@0: LayerFactory::LayerType type = *i; lbajardsilogic@0: QString name = LayerFactory::getInstance()->getLayerPresentationName(type); lbajardsilogic@0: lbajardsilogic@0: icon = QIcon(QString(":/icons/%1.png") lbajardsilogic@0: .arg(LayerFactory::getInstance()->getLayerIconName(type))); lbajardsilogic@0: lbajardsilogic@0: mainText = tr("Add New %1 Layer").arg(name); lbajardsilogic@0: tipText = tr("Add a new empty layer of type %1").arg(name); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(icon, mainText, this); lbajardsilogic@0: action->setStatusTip(tipText); lbajardsilogic@0: lbajardsilogic@0: if (type == LayerFactory::Text) { lbajardsilogic@0: action->setShortcut(tr("Alt+T")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_layerActions[action] = type; lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonLayerMenu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_rightButtonLayerMenu->addSeparator(); lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: LayerFactory::LayerType backgroundTypes[] = { lbajardsilogic@0: LayerFactory::Waveform, lbajardsilogic@0: LayerFactory::Spectrogram, lbajardsilogic@0: LayerFactory::MelodicRangeSpectrogram, lbajardsilogic@0: LayerFactory::PeakFrequencySpectrogram, lbajardsilogic@0: LayerFactory::Spectrum lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: std::vector models; lbajardsilogic@0: if (m_document) models = m_document->getTransformInputModels(); //!!! not well named for this! lbajardsilogic@0: bool plural = (models.size() > 1); lbajardsilogic@0: if (models.empty()) { lbajardsilogic@0: models.push_back(getMainModel()); // probably 0 lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: for (unsigned int i = 0; lbajardsilogic@0: i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) { lbajardsilogic@0: lbajardsilogic@0: for (int menuType = 0; menuType <= 1; ++menuType) { // pane, layer lbajardsilogic@0: lbajardsilogic@0: if (menuType == 0) menu = m_paneMenu; lbajardsilogic@0: else menu = m_layerMenu; lbajardsilogic@0: lbajardsilogic@0: QMenu *submenu = 0; lbajardsilogic@0: lbajardsilogic@0: QIcon icon; lbajardsilogic@0: QString mainText, shortcutText, tipText, channelText; lbajardsilogic@0: LayerFactory::LayerType type = backgroundTypes[i]; lbajardsilogic@0: bool mono = true; lbajardsilogic@0: lbajardsilogic@0: switch (type) { lbajardsilogic@0: lbajardsilogic@0: case LayerFactory::Waveform: lbajardsilogic@0: icon = QIcon(":/icons/waveform.png"); lbajardsilogic@0: mainText = tr("Add &Waveform"); lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: shortcutText = tr("Alt+W"); lbajardsilogic@0: tipText = tr("Add a new pane showing a waveform view"); lbajardsilogic@0: } else { lbajardsilogic@0: tipText = tr("Add a new layer showing a waveform view"); lbajardsilogic@0: } lbajardsilogic@0: mono = false; lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: case LayerFactory::Spectrogram: lbajardsilogic@0: icon = QIcon(":/icons/spectrogram.png"); lbajardsilogic@0: mainText = tr("Add &Spectrogram"); lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: shortcutText = tr("Alt+S"); lbajardsilogic@0: tipText = tr("Add a new pane showing a spectrogram"); lbajardsilogic@0: } else { lbajardsilogic@0: tipText = tr("Add a new layer showing a spectrogram"); lbajardsilogic@0: } lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: case LayerFactory::MelodicRangeSpectrogram: lbajardsilogic@0: icon = QIcon(":/icons/spectrogram.png"); lbajardsilogic@0: mainText = tr("Add &Melodic Range Spectrogram"); lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: shortcutText = tr("Alt+M"); lbajardsilogic@0: tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches"); lbajardsilogic@0: } else { lbajardsilogic@0: tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches"); lbajardsilogic@0: } lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: case LayerFactory::PeakFrequencySpectrogram: lbajardsilogic@0: icon = QIcon(":/icons/spectrogram.png"); lbajardsilogic@0: mainText = tr("Add &Peak Frequency Spectrogram"); lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: shortcutText = tr("Alt+P"); lbajardsilogic@0: tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies"); lbajardsilogic@0: } else { lbajardsilogic@0: tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies"); lbajardsilogic@0: } lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: case LayerFactory::Spectrum: lbajardsilogic@0: icon = QIcon(":/icons/spectrum.png"); lbajardsilogic@0: mainText = tr("Add Spectr&um"); lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: shortcutText = tr("Alt+U"); lbajardsilogic@0: tipText = tr("Add a new pane showing a frequency spectrum"); lbajardsilogic@0: } else { lbajardsilogic@0: tipText = tr("Add a new layer showing a frequency spectrum"); lbajardsilogic@0: } lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: default: break; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: std::vector candidateModels; lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: candidateModels = models; lbajardsilogic@0: } else { lbajardsilogic@0: candidateModels.push_back(0); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: for (std::vector::iterator mi = lbajardsilogic@0: candidateModels.begin(); lbajardsilogic@0: mi != candidateModels.end(); ++mi) { lbajardsilogic@0: lbajardsilogic@0: Model *model = *mi; lbajardsilogic@0: lbajardsilogic@0: int channels = 0; lbajardsilogic@0: if (model) { lbajardsilogic@0: DenseTimeValueModel *dtvm = lbajardsilogic@0: dynamic_cast(model); lbajardsilogic@0: if (dtvm) channels = dtvm->getChannelCount(); lbajardsilogic@0: } lbajardsilogic@0: if (channels < 1 && getMainModel()) { lbajardsilogic@0: channels = getMainModel()->getChannelCount(); lbajardsilogic@0: } lbajardsilogic@0: if (channels < 1) channels = 1; lbajardsilogic@0: lbajardsilogic@0: for (int c = 0; c <= channels; ++c) { lbajardsilogic@0: lbajardsilogic@0: if (c == 1 && channels == 1) continue; lbajardsilogic@0: bool isDefault = (c == 0); lbajardsilogic@0: bool isOnly = (isDefault && (channels == 1)); lbajardsilogic@0: lbajardsilogic@0: if (menuType == 1) { lbajardsilogic@0: if (isDefault) isOnly = true; lbajardsilogic@0: else continue; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (isOnly && (!plural || menuType == 1)) { lbajardsilogic@0: lbajardsilogic@0: if (menuType == 1 && type != LayerFactory::Waveform) { lbajardsilogic@0: action = new QAction(mainText, this); lbajardsilogic@0: } else { lbajardsilogic@0: action = new QAction(icon, mainText, this); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: action->setShortcut(shortcutText); lbajardsilogic@0: action->setStatusTip(tipText); lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: connect(action, SIGNAL(triggered()), lbajardsilogic@0: this, SLOT(addPane())); lbajardsilogic@0: connect(this, SIGNAL(canAddPane(bool)), lbajardsilogic@0: action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_paneActions[action] = PaneConfiguration(type); lbajardsilogic@0: } else { lbajardsilogic@0: connect(action, SIGNAL(triggered()), lbajardsilogic@0: this, SLOT(addLayer())); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), lbajardsilogic@0: action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_layerActions[action] = type; lbajardsilogic@0: } lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: if (!submenu) { lbajardsilogic@0: submenu = menu->addMenu(mainText); lbajardsilogic@0: submenu->setTearOffEnabled(true); lbajardsilogic@0: } else if (isDefault) { lbajardsilogic@0: submenu->addSeparator(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString actionText; lbajardsilogic@0: if (c == 0) { lbajardsilogic@0: if (mono) { lbajardsilogic@0: actionText = tr("&All Channels Mixed"); lbajardsilogic@0: } else { lbajardsilogic@0: actionText = tr("&All Channels"); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: actionText = tr("Channel &%1").arg(c); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (model) { lbajardsilogic@0: actionText = tr("%1: %2") lbajardsilogic@0: .arg(model->objectName()) lbajardsilogic@0: .arg(actionText); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (isDefault) { lbajardsilogic@0: action = new QAction(icon, actionText, this); lbajardsilogic@0: if (!model || model == getMainModel()) { lbajardsilogic@0: action->setShortcut(shortcutText); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: action = new QAction(actionText, this); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: action->setStatusTip(tipText); lbajardsilogic@0: lbajardsilogic@0: if (menuType == 0) { lbajardsilogic@0: connect(action, SIGNAL(triggered()), lbajardsilogic@0: this, SLOT(addPane())); lbajardsilogic@0: connect(this, SIGNAL(canAddPane(bool)), lbajardsilogic@0: action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_paneActions[action] = lbajardsilogic@0: PaneConfiguration(type, model, c - 1); lbajardsilogic@0: } else { lbajardsilogic@0: connect(action, SIGNAL(triggered()), lbajardsilogic@0: this, SLOT(addLayer())); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), lbajardsilogic@0: action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_layerActions[action] = type; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: submenu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: menu = m_paneMenu; lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Pane"), this); lbajardsilogic@0: action->setShortcut(tr("Alt+D")); lbajardsilogic@0: action->setStatusTip(tr("Delete the currently active pane")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentPane())); lbajardsilogic@0: connect(this, SIGNAL(canDeleteCurrentPane(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu = m_layerMenu; lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/timeruler.png"), tr("Add &Time Ruler"), this); lbajardsilogic@0: action->setStatusTip(tr("Add a new layer showing a time ruler")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_layerActions[action] = LayerFactory::TimeRuler; lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer")); lbajardsilogic@0: m_existingLayersMenu->setTearOffEnabled(true); lbajardsilogic@0: m_rightButtonLayerMenu->addMenu(m_existingLayersMenu); lbajardsilogic@0: lbajardsilogic@0: m_sliceMenu = menu->addMenu(tr("Add S&lice of Layer")); lbajardsilogic@0: m_sliceMenu->setTearOffEnabled(true); lbajardsilogic@0: m_rightButtonLayerMenu->addMenu(m_sliceMenu); lbajardsilogic@0: lbajardsilogic@0: setupExistingLayersMenus(); lbajardsilogic@0: lbajardsilogic@0: m_rightButtonLayerMenu->addSeparator(); lbajardsilogic@0: menu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("&Rename Layer..."), this); lbajardsilogic@0: action->setShortcut(tr("Alt+R")); lbajardsilogic@0: action->setStatusTip(tr("Rename the currently active layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(renameCurrentLayer())); lbajardsilogic@0: connect(this, SIGNAL(canRenameLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonLayerMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Layer"), this); lbajardsilogic@0: action->setShortcut(tr("Alt+Shift+D")); lbajardsilogic@0: action->setStatusTip(tr("Delete the currently active layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentLayer())); lbajardsilogic@0: connect(this, SIGNAL(canDeleteCurrentLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: m_rightButtonLayerMenu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupTransformsMenu() lbajardsilogic@0: { lbajardsilogic@0: if (m_transformsMenu) { lbajardsilogic@0: m_transformActions.clear(); lbajardsilogic@0: m_transformActionsReverse.clear(); lbajardsilogic@0: m_transformsMenu->clear(); lbajardsilogic@0: } else { lbajardsilogic@0: m_transformsMenu = menuBar()->addMenu(tr("&Transform")); lbajardsilogic@0: m_transformsMenu->setTearOffEnabled(true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: TransformFactory::TransformList transforms = lbajardsilogic@0: TransformFactory::getInstance()->getAllTransforms(); lbajardsilogic@0: lbajardsilogic@0: vector types = lbajardsilogic@0: TransformFactory::getInstance()->getAllTransformTypes(); lbajardsilogic@0: lbajardsilogic@0: map > categoryMenus; lbajardsilogic@0: map > makerMenus; lbajardsilogic@0: lbajardsilogic@0: map byPluginNameMenus; lbajardsilogic@0: map > pluginNameMenus; lbajardsilogic@0: lbajardsilogic@0: set pendingMenus; lbajardsilogic@0: lbajardsilogic@0: m_recentTransformsMenu = m_transformsMenu->addMenu(tr("&Recent Transforms")); lbajardsilogic@0: m_recentTransformsMenu->setTearOffEnabled(true); lbajardsilogic@0: m_rightButtonTransformsMenu->addMenu(m_recentTransformsMenu); lbajardsilogic@0: connect(&m_recentTransforms, SIGNAL(recentChanged()), lbajardsilogic@0: this, SLOT(setupRecentTransformsMenu())); lbajardsilogic@0: lbajardsilogic@0: m_transformsMenu->addSeparator(); lbajardsilogic@0: m_rightButtonTransformsMenu->addSeparator(); lbajardsilogic@0: lbajardsilogic@0: for (vector::iterator i = types.begin(); i != types.end(); ++i) { lbajardsilogic@0: lbajardsilogic@0: if (i != types.begin()) { lbajardsilogic@0: m_transformsMenu->addSeparator(); lbajardsilogic@0: m_rightButtonTransformsMenu->addSeparator(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString byCategoryLabel = tr("%1 by Category").arg(*i); lbajardsilogic@0: SubdividingMenu *byCategoryMenu = new SubdividingMenu(byCategoryLabel, lbajardsilogic@0: 20, 40); lbajardsilogic@0: byCategoryMenu->setTearOffEnabled(true); lbajardsilogic@0: m_transformsMenu->addMenu(byCategoryMenu); lbajardsilogic@0: m_rightButtonTransformsMenu->addMenu(byCategoryMenu); lbajardsilogic@0: pendingMenus.insert(byCategoryMenu); lbajardsilogic@0: lbajardsilogic@0: vector categories = lbajardsilogic@0: TransformFactory::getInstance()->getTransformCategories(*i); lbajardsilogic@0: lbajardsilogic@0: for (vector::iterator j = categories.begin(); lbajardsilogic@0: j != categories.end(); ++j) { lbajardsilogic@0: lbajardsilogic@0: QString category = *j; lbajardsilogic@0: if (category == "") category = tr("Unclassified"); lbajardsilogic@0: lbajardsilogic@0: if (categories.size() < 2) { lbajardsilogic@0: categoryMenus[*i][category] = byCategoryMenu; lbajardsilogic@0: continue; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QStringList components = category.split(" > "); lbajardsilogic@0: QString key; lbajardsilogic@0: lbajardsilogic@0: for (QStringList::iterator k = components.begin(); lbajardsilogic@0: k != components.end(); ++k) { lbajardsilogic@0: lbajardsilogic@0: QString parentKey = key; lbajardsilogic@0: if (key != "") key += " > "; lbajardsilogic@0: key += *k; lbajardsilogic@0: lbajardsilogic@0: if (categoryMenus[*i].find(key) == categoryMenus[*i].end()) { lbajardsilogic@0: SubdividingMenu *m = new SubdividingMenu(*k, 20, 40); lbajardsilogic@0: m->setTearOffEnabled(true); lbajardsilogic@0: pendingMenus.insert(m); lbajardsilogic@0: categoryMenus[*i][key] = m; lbajardsilogic@0: if (parentKey == "") { lbajardsilogic@0: byCategoryMenu->addMenu(m); lbajardsilogic@0: } else { lbajardsilogic@0: categoryMenus[*i][parentKey]->addMenu(m); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString byPluginNameLabel = tr("%1 by Plugin Name").arg(*i); lbajardsilogic@0: byPluginNameMenus[*i] = new SubdividingMenu(byPluginNameLabel); lbajardsilogic@0: byPluginNameMenus[*i]->setTearOffEnabled(true); lbajardsilogic@0: m_transformsMenu->addMenu(byPluginNameMenus[*i]); lbajardsilogic@0: m_rightButtonTransformsMenu->addMenu(byPluginNameMenus[*i]); lbajardsilogic@0: pendingMenus.insert(byPluginNameMenus[*i]); lbajardsilogic@0: lbajardsilogic@0: QString byMakerLabel = tr("%1 by Maker").arg(*i); lbajardsilogic@0: SubdividingMenu *byMakerMenu = new SubdividingMenu(byMakerLabel, 20, 40); lbajardsilogic@0: byMakerMenu->setTearOffEnabled(true); lbajardsilogic@0: m_transformsMenu->addMenu(byMakerMenu); lbajardsilogic@0: m_rightButtonTransformsMenu->addMenu(byMakerMenu); lbajardsilogic@0: pendingMenus.insert(byMakerMenu); lbajardsilogic@0: lbajardsilogic@0: vector makers = lbajardsilogic@0: TransformFactory::getInstance()->getTransformMakers(*i); lbajardsilogic@0: lbajardsilogic@0: for (vector::iterator j = makers.begin(); lbajardsilogic@0: j != makers.end(); ++j) { lbajardsilogic@0: lbajardsilogic@0: QString maker = *j; lbajardsilogic@0: if (maker == "") maker = tr("Unknown"); lbajardsilogic@0: maker.replace(QRegExp(tr(" [\\(<].*$")), ""); lbajardsilogic@0: lbajardsilogic@0: makerMenus[*i][maker] = new SubdividingMenu(maker, 30, 40); lbajardsilogic@0: makerMenus[*i][maker]->setTearOffEnabled(true); lbajardsilogic@0: byMakerMenu->addMenu(makerMenus[*i][maker]); lbajardsilogic@0: pendingMenus.insert(makerMenus[*i][maker]); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: for (unsigned int i = 0; i < transforms.size(); ++i) { lbajardsilogic@0: lbajardsilogic@0: QString name = transforms[i].name; lbajardsilogic@0: if (name == "") name = transforms[i].identifier; lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "Plugin Name: " << name.toStdString() << std::endl; lbajardsilogic@0: lbajardsilogic@0: QString type = transforms[i].type; lbajardsilogic@0: lbajardsilogic@0: QString category = transforms[i].category; lbajardsilogic@0: if (category == "") category = tr("Unclassified"); lbajardsilogic@0: lbajardsilogic@0: QString maker = transforms[i].maker; lbajardsilogic@0: if (maker == "") maker = tr("Unknown"); lbajardsilogic@0: maker.replace(QRegExp(tr(" [\\(<].*$")), ""); lbajardsilogic@0: lbajardsilogic@0: QString pluginName = name.section(": ", 0, 0); lbajardsilogic@0: QString output = name.section(": ", 1); lbajardsilogic@0: lbajardsilogic@0: QAction *action = new QAction(tr("%1...").arg(name), this); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); lbajardsilogic@0: m_transformActions[action] = transforms[i].identifier; lbajardsilogic@0: m_transformActionsReverse[transforms[i].identifier] = action; lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: action->setStatusTip(transforms[i].description); lbajardsilogic@0: lbajardsilogic@0: if (categoryMenus[type].find(category) == categoryMenus[type].end()) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::setupMenus: Internal error: " lbajardsilogic@0: << "No category menu for transform \"" lbajardsilogic@0: << name.toStdString() << "\" (category = \"" lbajardsilogic@0: << category.toStdString() << "\")" << std::endl; lbajardsilogic@0: } else { lbajardsilogic@0: categoryMenus[type][category]->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (makerMenus[type].find(maker) == makerMenus[type].end()) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::setupMenus: Internal error: " lbajardsilogic@0: << "No maker menu for transform \"" lbajardsilogic@0: << name.toStdString() << "\" (maker = \"" lbajardsilogic@0: << maker.toStdString() << "\")" << std::endl; lbajardsilogic@0: } else { lbajardsilogic@0: makerMenus[type][maker]->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("%1...").arg(output == "" ? pluginName : output), this); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); lbajardsilogic@0: m_transformActions[action] = transforms[i].identifier; lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: action->setStatusTip(transforms[i].description); lbajardsilogic@0: lbajardsilogic@0: // cerr << "Transform: \"" << name.toStdString() << "\": plugin name \"" << pluginName.toStdString() << "\"" << endl; lbajardsilogic@0: lbajardsilogic@0: if (pluginNameMenus[type].find(pluginName) == lbajardsilogic@0: pluginNameMenus[type].end()) { lbajardsilogic@0: lbajardsilogic@0: SubdividingMenu *parentMenu = byPluginNameMenus[type]; lbajardsilogic@0: parentMenu->setTearOffEnabled(true); lbajardsilogic@0: lbajardsilogic@0: if (output == "") { lbajardsilogic@0: parentMenu->addAction(pluginName, action); lbajardsilogic@0: } else { lbajardsilogic@0: pluginNameMenus[type][pluginName] = lbajardsilogic@0: parentMenu->addMenu(pluginName); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), lbajardsilogic@0: pluginNameMenus[type][pluginName], lbajardsilogic@0: SLOT(setEnabled(bool))); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (pluginNameMenus[type].find(pluginName) != lbajardsilogic@0: pluginNameMenus[type].end()) { lbajardsilogic@0: pluginNameMenus[type][pluginName]->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: for (set::iterator i = pendingMenus.begin(); lbajardsilogic@0: i != pendingMenus.end(); ++i) { lbajardsilogic@0: (*i)->entriesAdded(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: setupRecentTransformsMenu(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupHelpMenu() lbajardsilogic@0: { lbajardsilogic@0: if (m_mainMenusCreated) return; lbajardsilogic@0: lbajardsilogic@0: QMenu *menu = menuBar()->addMenu(tr("&Help")); lbajardsilogic@0: menu->setTearOffEnabled(true); lbajardsilogic@0: lbajardsilogic@0: QAction *action = new QAction(QIcon(":icons/help.png"), lbajardsilogic@0: tr("&Help Reference"), this); lbajardsilogic@0: action->setStatusTip(tr("Open the Sonic Visualiser reference manual")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(help())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("Sonic Visualiser on the &Web"), this); lbajardsilogic@0: action->setStatusTip(tr("Open the Sonic Visualiser website")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(website())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: action = new QAction(tr("&About Sonic Visualiser"), this); lbajardsilogic@0: action->setStatusTip(tr("Show information about Sonic Visualiser")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(about())); lbajardsilogic@0: menu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupRecentFilesMenu() lbajardsilogic@0: { lbajardsilogic@0: m_recentFilesMenu->clear(); lbajardsilogic@0: vector files = m_recentFiles.getRecent(); lbajardsilogic@0: for (size_t i = 0; i < files.size(); ++i) { lbajardsilogic@0: QAction *action = new QAction(files[i], this); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile())); lbajardsilogic@0: m_recentFilesMenu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupRecentTransformsMenu() lbajardsilogic@0: { lbajardsilogic@0: m_recentTransformsMenu->clear(); lbajardsilogic@0: vector transforms = m_recentTransforms.getRecent(); lbajardsilogic@0: for (size_t i = 0; i < transforms.size(); ++i) { lbajardsilogic@0: TransformActionReverseMap::iterator ti = lbajardsilogic@0: m_transformActionsReverse.find(transforms[i]); lbajardsilogic@0: if (ti == m_transformActionsReverse.end()) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::setupRecentTransformsMenu: " lbajardsilogic@0: << "Unknown transform \"" << transforms[i].toStdString() lbajardsilogic@0: << "\" in recent transforms list" << std::endl; lbajardsilogic@0: continue; lbajardsilogic@0: } lbajardsilogic@0: m_recentTransformsMenu->addAction(ti->second); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupExistingLayersMenus() lbajardsilogic@0: { lbajardsilogic@0: if (!m_existingLayersMenu) return; // should have been created by setupMenus lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "MainWindow::setupExistingLayersMenu" << std::endl; lbajardsilogic@0: lbajardsilogic@0: m_existingLayersMenu->clear(); lbajardsilogic@0: m_existingLayerActions.clear(); lbajardsilogic@0: lbajardsilogic@0: m_sliceMenu->clear(); lbajardsilogic@0: m_sliceActions.clear(); lbajardsilogic@0: lbajardsilogic@0: vector orderedLayers; lbajardsilogic@0: set observedLayers; lbajardsilogic@0: set sliceableLayers; lbajardsilogic@0: lbajardsilogic@0: LayerFactory *factory = LayerFactory::getInstance(); lbajardsilogic@0: lbajardsilogic@0: for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getPane(i); lbajardsilogic@0: if (!pane) continue; lbajardsilogic@0: lbajardsilogic@0: for (int j = 0; j < pane->getLayerCount(); ++j) { lbajardsilogic@0: lbajardsilogic@0: Layer *layer = pane->getLayer(j); lbajardsilogic@0: if (!layer) continue; lbajardsilogic@0: if (observedLayers.find(layer) != observedLayers.end()) { lbajardsilogic@0: // std::cerr << "found duplicate layer " << layer << std::endl; lbajardsilogic@0: continue; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "found new layer " << layer << " (name = " lbajardsilogic@0: // << layer->getLayerPresentationName().toStdString() << ")" << std::endl; lbajardsilogic@0: lbajardsilogic@0: orderedLayers.push_back(layer); lbajardsilogic@0: observedLayers.insert(layer); lbajardsilogic@0: lbajardsilogic@0: if (factory->isLayerSliceable(layer)) { lbajardsilogic@0: sliceableLayers.insert(layer); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: map observedNames; lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < orderedLayers.size(); ++i) { lbajardsilogic@0: lbajardsilogic@0: Layer *layer = orderedLayers[i]; lbajardsilogic@0: lbajardsilogic@0: QString name = layer->getLayerPresentationName(); lbajardsilogic@0: int n = ++observedNames[name]; lbajardsilogic@0: if (n > 1) name = QString("%1 <%2>").arg(name).arg(n); lbajardsilogic@0: lbajardsilogic@0: QIcon icon = QIcon(QString(":/icons/%1.png") lbajardsilogic@0: .arg(factory->getLayerIconName lbajardsilogic@0: (factory->getLayerType(layer)))); lbajardsilogic@0: lbajardsilogic@0: QAction *action = new QAction(icon, name, this); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_existingLayerActions[action] = layer; lbajardsilogic@0: lbajardsilogic@0: m_existingLayersMenu->addAction(action); lbajardsilogic@0: lbajardsilogic@0: if (sliceableLayers.find(layer) != sliceableLayers.end()) { lbajardsilogic@0: action = new QAction(icon, name, this); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); lbajardsilogic@0: connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: m_sliceActions[action] = layer; lbajardsilogic@0: m_sliceMenu->addAction(action); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_sliceMenu->setEnabled(!m_sliceActions.empty()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::setupToolbars() lbajardsilogic@0: { lbajardsilogic@0: QToolBar *toolbar = addToolBar(tr("Transport Toolbar")); lbajardsilogic@0: lbajardsilogic@0: QAction *action = toolbar->addAction(QIcon(":/icons/rewind-start.png"), lbajardsilogic@0: tr("Rewind to Start")); lbajardsilogic@0: action->setShortcut(tr("Home")); lbajardsilogic@0: action->setStatusTip(tr("Rewind to the start")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(rewindStart())); lbajardsilogic@0: connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/rewind.png"), lbajardsilogic@0: tr("Rewind")); lbajardsilogic@0: action->setShortcut(tr("PageUp")); lbajardsilogic@0: action->setStatusTip(tr("Rewind to the previous time instant in the current layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(rewind())); lbajardsilogic@0: connect(this, SIGNAL(canRewind(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/playpause.png"), lbajardsilogic@0: tr("Play / Pause")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setShortcut(tr("Space")); lbajardsilogic@0: action->setStatusTip(tr("Start or stop playback from the current position")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(play())); lbajardsilogic@0: connect(m_playSource, SIGNAL(playStatusChanged(bool)), lbajardsilogic@0: action, SLOT(setChecked(bool))); lbajardsilogic@0: connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/ffwd.png"), lbajardsilogic@0: tr("Fast Forward")); lbajardsilogic@0: action->setShortcut(tr("PageDown")); lbajardsilogic@0: action->setStatusTip(tr("Fast forward to the next time instant in the current layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(ffwd())); lbajardsilogic@0: connect(this, SIGNAL(canFfwd(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/ffwd-end.png"), lbajardsilogic@0: tr("Fast Forward to End")); lbajardsilogic@0: action->setShortcut(tr("End")); lbajardsilogic@0: action->setStatusTip(tr("Fast-forward to the end")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(ffwdEnd())); lbajardsilogic@0: connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: toolbar = addToolBar(tr("Play Mode Toolbar")); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/playselection.png"), lbajardsilogic@0: tr("Constrain Playback to Selection")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(m_viewManager->getPlaySelectionMode()); lbajardsilogic@0: action->setShortcut(tr("s")); lbajardsilogic@0: action->setStatusTip(tr("Constrain playback to the selected area")); lbajardsilogic@0: connect(m_viewManager, SIGNAL(playSelectionModeChanged(bool)), lbajardsilogic@0: action, SLOT(setChecked(bool))); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(playSelectionToggled())); lbajardsilogic@0: connect(this, SIGNAL(canPlaySelection(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/playloop.png"), lbajardsilogic@0: tr("Loop Playback")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(m_viewManager->getPlayLoopMode()); lbajardsilogic@0: action->setShortcut(tr("l")); lbajardsilogic@0: action->setStatusTip(tr("Loop playback")); lbajardsilogic@0: connect(m_viewManager, SIGNAL(playLoopModeChanged(bool)), lbajardsilogic@0: action, SLOT(setChecked(bool))); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(playLoopToggled())); lbajardsilogic@0: connect(this, SIGNAL(canPlay(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: lbajardsilogic@0: toolbar = addToolBar(tr("Edit Toolbar")); lbajardsilogic@0: CommandHistory::getInstance()->registerToolbar(toolbar); lbajardsilogic@0: lbajardsilogic@0: toolbar = addToolBar(tr("Tools Toolbar")); lbajardsilogic@0: QActionGroup *group = new QActionGroup(this); lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/navigate.png"), lbajardsilogic@0: tr("Navigate")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setChecked(true); lbajardsilogic@0: action->setShortcut(tr("1")); lbajardsilogic@0: action->setStatusTip(tr("Navigate")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(toolNavigateSelected())); lbajardsilogic@0: group->addAction(action); lbajardsilogic@0: m_toolActions[ViewManager::NavigateMode] = action; lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/select.png"), lbajardsilogic@0: tr("Select")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setShortcut(tr("2")); lbajardsilogic@0: action->setStatusTip(tr("Select ranges")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(toolSelectSelected())); lbajardsilogic@0: group->addAction(action); lbajardsilogic@0: m_toolActions[ViewManager::SelectMode] = action; lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/move.png"), lbajardsilogic@0: tr("Edit")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setShortcut(tr("3")); lbajardsilogic@0: action->setStatusTip(tr("Edit items in layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(toolEditSelected())); lbajardsilogic@0: connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: group->addAction(action); lbajardsilogic@0: m_toolActions[ViewManager::EditMode] = action; lbajardsilogic@0: lbajardsilogic@0: action = toolbar->addAction(QIcon(":/icons/draw.png"), lbajardsilogic@0: tr("Draw")); lbajardsilogic@0: action->setCheckable(true); lbajardsilogic@0: action->setShortcut(tr("4")); lbajardsilogic@0: action->setStatusTip(tr("Draw new items in layer")); lbajardsilogic@0: connect(action, SIGNAL(triggered()), this, SLOT(toolDrawSelected())); lbajardsilogic@0: connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool))); lbajardsilogic@0: group->addAction(action); lbajardsilogic@0: m_toolActions[ViewManager::DrawMode] = action; lbajardsilogic@0: lbajardsilogic@0: // action = toolbar->addAction(QIcon(":/icons/text.png"), lbajardsilogic@0: // tr("Text")); lbajardsilogic@0: // action->setCheckable(true); lbajardsilogic@0: // action->setShortcut(tr("5")); lbajardsilogic@0: // connect(action, SIGNAL(triggered()), this, SLOT(toolTextSelected())); lbajardsilogic@0: // group->addAction(action); lbajardsilogic@0: // m_toolActions[ViewManager::TextMode] = action; lbajardsilogic@0: lbajardsilogic@25: ConnectionStatus *connectionStatus = new ConnectionStatus(m_httpClient, tr("Connection status")); lbajardsilogic@25: addToolBar(connectionStatus); lbajardsilogic@25: lbajardsilogic@0: toolNavigateSelected(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::updateMenuStates() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = 0; lbajardsilogic@0: Layer *currentLayer = 0; lbajardsilogic@0: lbajardsilogic@0: if (m_paneStack) currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentLayer = currentPane->getSelectedLayer(); lbajardsilogic@0: lbajardsilogic@0: bool haveCurrentPane = lbajardsilogic@0: (currentPane != 0); lbajardsilogic@0: bool haveCurrentLayer = lbajardsilogic@0: (haveCurrentPane && lbajardsilogic@0: (currentLayer != 0)); lbajardsilogic@0: bool haveMainModel = lbajardsilogic@0: (getMainModel() != 0); lbajardsilogic@0: bool havePlayTarget = lbajardsilogic@0: (m_playTarget != 0); lbajardsilogic@0: bool haveSelection = lbajardsilogic@0: (m_viewManager && lbajardsilogic@0: !m_viewManager->getSelections().empty()); lbajardsilogic@0: bool haveCurrentEditableLayer = lbajardsilogic@0: (haveCurrentLayer && lbajardsilogic@0: currentLayer->isLayerEditable()); lbajardsilogic@0: bool haveCurrentTimeInstantsLayer = lbajardsilogic@0: (haveCurrentLayer && lbajardsilogic@0: dynamic_cast(currentLayer)); lbajardsilogic@0: bool haveCurrentTimeValueLayer = lbajardsilogic@0: (haveCurrentLayer && lbajardsilogic@0: dynamic_cast(currentLayer)); lbajardsilogic@0: bool haveCurrentColour3DPlot = lbajardsilogic@0: (haveCurrentLayer && lbajardsilogic@0: dynamic_cast(currentLayer)); lbajardsilogic@0: bool haveClipboardContents = lbajardsilogic@0: (m_viewManager && lbajardsilogic@0: !m_viewManager->getClipboard().empty()); lbajardsilogic@0: lbajardsilogic@0: emit canAddPane(haveMainModel); lbajardsilogic@0: emit canDeleteCurrentPane(haveCurrentPane); lbajardsilogic@0: emit canZoom(haveMainModel && haveCurrentPane); lbajardsilogic@0: emit canScroll(haveMainModel && haveCurrentPane); lbajardsilogic@0: emit canAddLayer(haveMainModel && haveCurrentPane); lbajardsilogic@0: emit canImportMoreAudio(haveMainModel); lbajardsilogic@0: emit canImportLayer(haveMainModel && haveCurrentPane); lbajardsilogic@0: emit canExportAudio(haveMainModel); lbajardsilogic@0: emit canExportLayer(haveMainModel && lbajardsilogic@0: (haveCurrentEditableLayer || haveCurrentColour3DPlot)); lbajardsilogic@0: emit canExportImage(haveMainModel && haveCurrentPane); lbajardsilogic@0: emit canDeleteCurrentLayer(haveCurrentLayer); lbajardsilogic@0: emit canRenameLayer(haveCurrentLayer); lbajardsilogic@0: emit canEditLayer(haveCurrentEditableLayer); lbajardsilogic@0: emit canSelect(haveMainModel && haveCurrentPane); lbajardsilogic@0: emit canPlay(/*!!! haveMainModel && */ havePlayTarget); lbajardsilogic@0: emit canFfwd(haveCurrentTimeInstantsLayer || haveCurrentTimeValueLayer); lbajardsilogic@0: emit canRewind(haveCurrentTimeInstantsLayer || haveCurrentTimeValueLayer); lbajardsilogic@0: emit canPaste(haveCurrentEditableLayer && haveClipboardContents); lbajardsilogic@0: emit canInsertInstant(haveCurrentPane); lbajardsilogic@0: emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection); lbajardsilogic@0: emit canPlaySelection(haveMainModel && havePlayTarget && haveSelection); lbajardsilogic@0: emit canClearSelection(haveSelection); lbajardsilogic@0: emit canEditSelection(haveSelection && haveCurrentEditableLayer); lbajardsilogic@0: emit canSave(m_sessionFile != "" && m_documentModified); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::updateDescriptionLabel() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) { lbajardsilogic@0: m_descriptionLabel->setText(tr("No audio file loaded.")); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString description; lbajardsilogic@0: lbajardsilogic@0: size_t ssr = getMainModel()->getSampleRate(); lbajardsilogic@0: size_t tsr = ssr; lbajardsilogic@0: if (m_playSource) tsr = m_playSource->getTargetSampleRate(); lbajardsilogic@0: lbajardsilogic@0: if (ssr != tsr) { lbajardsilogic@0: description = tr("%1Hz (resampling to %2Hz)").arg(ssr).arg(tsr); lbajardsilogic@0: } else { lbajardsilogic@0: description = QString("%1Hz").arg(ssr); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: description = QString("%1 - %2") lbajardsilogic@0: .arg(RealTime::frame2RealTime(getMainModel()->getEndFrame(), ssr) lbajardsilogic@0: .toText(false).c_str()) lbajardsilogic@0: .arg(description); lbajardsilogic@0: lbajardsilogic@0: m_descriptionLabel->setText(description); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::documentModified() lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::documentModified" << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (!m_documentModified) { lbajardsilogic@0: setWindowTitle(tr("%1 (modified)").arg(windowTitle())); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_documentModified = true; lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::documentRestored() lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::documentRestored" << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (m_documentModified) { lbajardsilogic@0: QString wt(windowTitle()); lbajardsilogic@0: wt.replace(tr(" (modified)"), ""); lbajardsilogic@0: setWindowTitle(wt); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_documentModified = false; lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::playLoopToggled() lbajardsilogic@0: { lbajardsilogic@0: QAction *action = dynamic_cast(sender()); lbajardsilogic@0: lbajardsilogic@0: if (action) { lbajardsilogic@0: m_viewManager->setPlayLoopMode(action->isChecked()); lbajardsilogic@0: } else { lbajardsilogic@0: m_viewManager->setPlayLoopMode(!m_viewManager->getPlayLoopMode()); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::playSelectionToggled() lbajardsilogic@0: { lbajardsilogic@0: QAction *action = dynamic_cast(sender()); lbajardsilogic@0: lbajardsilogic@0: if (action) { lbajardsilogic@0: m_viewManager->setPlaySelectionMode(action->isChecked()); lbajardsilogic@0: } else { lbajardsilogic@0: m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode()); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::currentPaneChanged(Pane *p) lbajardsilogic@0: { lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: updateVisibleRangeDisplay(p); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::currentLayerChanged(Pane *p, Layer *) lbajardsilogic@0: { lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: updateVisibleRangeDisplay(p); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toolNavigateSelected() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setToolMode(ViewManager::NavigateMode); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toolSelectSelected() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setToolMode(ViewManager::SelectMode); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toolEditSelected() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setToolMode(ViewManager::EditMode); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toolDrawSelected() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setToolMode(ViewManager::DrawMode); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: //void lbajardsilogic@0: //MainWindow::toolTextSelected() lbajardsilogic@0: //{ lbajardsilogic@0: // m_viewManager->setToolMode(ViewManager::TextMode); lbajardsilogic@0: //} lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::selectAll() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(), lbajardsilogic@0: getMainModel()->getEndFrame())); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::selectToStart() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(), lbajardsilogic@0: m_viewManager->getGlobalCentreFrame())); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::selectToEnd() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(), lbajardsilogic@0: getMainModel()->getEndFrame())); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::selectVisible() lbajardsilogic@0: { lbajardsilogic@0: Model *model = getMainModel(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!currentPane) return; lbajardsilogic@0: lbajardsilogic@0: size_t startFrame, endFrame; lbajardsilogic@0: lbajardsilogic@0: if (currentPane->getStartFrame() < 0) startFrame = 0; lbajardsilogic@0: else startFrame = currentPane->getStartFrame(); lbajardsilogic@0: lbajardsilogic@0: if (currentPane->getEndFrame() > model->getEndFrame()) endFrame = model->getEndFrame(); lbajardsilogic@0: else endFrame = currentPane->getEndFrame(); lbajardsilogic@0: lbajardsilogic@0: m_viewManager->setSelection(Selection(startFrame, endFrame)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::clearSelection() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->clearSelections(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::cut() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!currentPane) return; lbajardsilogic@0: lbajardsilogic@0: Layer *layer = currentPane->getSelectedLayer(); lbajardsilogic@0: if (!layer) return; lbajardsilogic@0: lbajardsilogic@0: Clipboard &clipboard = m_viewManager->getClipboard(); lbajardsilogic@0: clipboard.clear(); lbajardsilogic@0: lbajardsilogic@0: MultiSelection::SelectionList selections = m_viewManager->getSelections(); lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->startCompoundOperation(tr("Cut"), true); lbajardsilogic@0: lbajardsilogic@0: for (MultiSelection::SelectionList::iterator i = selections.begin(); lbajardsilogic@0: i != selections.end(); ++i) { lbajardsilogic@0: layer->copy(*i, clipboard); lbajardsilogic@0: layer->deleteSelection(*i); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->endCompoundOperation(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::copy() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!currentPane) return; lbajardsilogic@0: lbajardsilogic@0: Layer *layer = currentPane->getSelectedLayer(); lbajardsilogic@0: if (!layer) return; lbajardsilogic@0: lbajardsilogic@0: Clipboard &clipboard = m_viewManager->getClipboard(); lbajardsilogic@0: clipboard.clear(); lbajardsilogic@0: lbajardsilogic@0: MultiSelection::SelectionList selections = m_viewManager->getSelections(); lbajardsilogic@0: lbajardsilogic@0: for (MultiSelection::SelectionList::iterator i = selections.begin(); lbajardsilogic@0: i != selections.end(); ++i) { lbajardsilogic@0: layer->copy(*i, clipboard); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::paste() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!currentPane) return; lbajardsilogic@0: lbajardsilogic@0: //!!! if we have no current layer, we should create one of the most lbajardsilogic@0: // appropriate type lbajardsilogic@0: lbajardsilogic@0: Layer *layer = currentPane->getSelectedLayer(); lbajardsilogic@0: if (!layer) return; lbajardsilogic@0: lbajardsilogic@0: Clipboard &clipboard = m_viewManager->getClipboard(); lbajardsilogic@0: Clipboard::PointList contents = clipboard.getPoints(); lbajardsilogic@0: /* lbajardsilogic@0: long minFrame = 0; lbajardsilogic@0: bool have = false; lbajardsilogic@0: for (int i = 0; i < contents.size(); ++i) { lbajardsilogic@0: if (!contents[i].haveFrame()) continue; lbajardsilogic@0: if (!have || contents[i].getFrame() < minFrame) { lbajardsilogic@0: minFrame = contents[i].getFrame(); lbajardsilogic@0: have = true; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: long frameOffset = long(m_viewManager->getGlobalCentreFrame()) - minFrame; lbajardsilogic@0: lbajardsilogic@0: layer->paste(clipboard, frameOffset); lbajardsilogic@0: */ lbajardsilogic@0: layer->paste(clipboard, 0, true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::deleteSelected() lbajardsilogic@0: { lbajardsilogic@0: if (m_paneStack->getCurrentPane() && lbajardsilogic@0: m_paneStack->getCurrentPane()->getSelectedLayer()) { lbajardsilogic@0: lbajardsilogic@0: MultiSelection::SelectionList selections = lbajardsilogic@0: m_viewManager->getSelections(); lbajardsilogic@0: lbajardsilogic@0: for (MultiSelection::SelectionList::iterator i = selections.begin(); lbajardsilogic@0: i != selections.end(); ++i) { lbajardsilogic@0: lbajardsilogic@0: m_paneStack->getCurrentPane()->getSelectedLayer()->deleteSelection(*i); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::insertInstant() lbajardsilogic@0: { lbajardsilogic@0: int frame = m_viewManager->getPlaybackFrame(); lbajardsilogic@0: insertInstantAt(frame); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::insertInstantsAtBoundaries() lbajardsilogic@0: { lbajardsilogic@0: MultiSelection::SelectionList selections = m_viewManager->getSelections(); lbajardsilogic@0: for (MultiSelection::SelectionList::iterator i = selections.begin(); lbajardsilogic@0: i != selections.end(); ++i) { lbajardsilogic@0: size_t start = i->getStartFrame(); lbajardsilogic@0: size_t end = i->getEndFrame(); lbajardsilogic@0: if (start != end) { lbajardsilogic@0: insertInstantAt(i->getStartFrame()); lbajardsilogic@0: insertInstantAt(i->getEndFrame()); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::insertInstantAt(size_t frame) lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!pane) { lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Layer *layer = dynamic_cast lbajardsilogic@0: (pane->getSelectedLayer()); lbajardsilogic@0: lbajardsilogic@0: if (!layer) { lbajardsilogic@0: for (int i = pane->getLayerCount(); i > 0; --i) { lbajardsilogic@0: layer = dynamic_cast(pane->getLayer(i - 1)); lbajardsilogic@0: if (layer) break; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!layer) { lbajardsilogic@0: CommandHistory::getInstance()->startCompoundOperation lbajardsilogic@0: (tr("Add Point"), true); lbajardsilogic@0: layer = m_document->createEmptyLayer(LayerFactory::TimeInstants); lbajardsilogic@0: if (layer) { lbajardsilogic@0: m_document->addLayerToView(pane, layer); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, layer); lbajardsilogic@0: } lbajardsilogic@0: CommandHistory::getInstance()->endCompoundOperation(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (layer) { lbajardsilogic@0: lbajardsilogic@0: Model *model = layer->getModel(); lbajardsilogic@0: SparseOneDimensionalModel *sodm = dynamic_cast lbajardsilogic@0: (model); lbajardsilogic@0: lbajardsilogic@0: if (sodm) { lbajardsilogic@0: SparseOneDimensionalModel::Point point lbajardsilogic@0: (frame, QString("%1").arg(sodm->getPointCount() + 1)); lbajardsilogic@0: CommandHistory::getInstance()->addCommand lbajardsilogic@0: (new SparseOneDimensionalModel::AddPointCommand(sodm, point, lbajardsilogic@0: tr("Add Points")), lbajardsilogic@0: true, true); // bundled lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::importAudio() lbajardsilogic@0: { lbajardsilogic@0: QString path = getOpenFileName(FileFinder::AudioFile); lbajardsilogic@0: lbajardsilogic@0: if (path != "") { lbajardsilogic@0: if (openAudioFile(path, ReplaceMainModel) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("Audio file \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::importMoreAudio() lbajardsilogic@0: { lbajardsilogic@0: QString path = getOpenFileName(FileFinder::AudioFile); lbajardsilogic@0: lbajardsilogic@0: if (path != "") { lbajardsilogic@0: if (openAudioFile(path, CreateAdditionalModel) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("Audio file \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::exportAudio() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: lbajardsilogic@0: QString path = getSaveFileName(FileFinder::AudioFile); lbajardsilogic@0: lbajardsilogic@0: if (path == "") return; lbajardsilogic@0: lbajardsilogic@0: bool ok = false; lbajardsilogic@0: QString error; lbajardsilogic@0: lbajardsilogic@0: MultiSelection ms = m_viewManager->getSelection(); lbajardsilogic@0: MultiSelection::SelectionList selections = m_viewManager->getSelections(); lbajardsilogic@0: lbajardsilogic@0: bool multiple = false; lbajardsilogic@0: lbajardsilogic@0: MultiSelection *selectionToWrite = 0; lbajardsilogic@0: lbajardsilogic@0: if (selections.size() == 1) { lbajardsilogic@0: lbajardsilogic@0: QStringList items; lbajardsilogic@0: items << tr("Export the selected region only") lbajardsilogic@0: << tr("Export the whole audio file"); lbajardsilogic@0: lbajardsilogic@0: bool ok = false; lbajardsilogic@0: QString item = ListInputDialog::getItem lbajardsilogic@0: (this, tr("Select region to export"), lbajardsilogic@0: tr("Which region from the original audio file do you want to export?"), lbajardsilogic@0: items, 0, &ok); lbajardsilogic@0: lbajardsilogic@0: if (!ok || item.isEmpty()) return; lbajardsilogic@0: lbajardsilogic@0: if (item == items[0]) selectionToWrite = &ms; lbajardsilogic@0: lbajardsilogic@0: } else if (selections.size() > 1) { lbajardsilogic@0: lbajardsilogic@0: QStringList items; lbajardsilogic@0: items << tr("Export the selected regions into a single audio file") lbajardsilogic@0: << tr("Export the selected regions into separate files") lbajardsilogic@0: << tr("Export the whole audio file"); lbajardsilogic@0: lbajardsilogic@0: QString item = ListInputDialog::getItem lbajardsilogic@0: (this, tr("Select region to export"), lbajardsilogic@0: tr("Multiple regions of the original audio file are selected.\nWhat do you want to export?"), lbajardsilogic@0: items, 0, &ok); lbajardsilogic@0: lbajardsilogic@0: if (!ok || item.isEmpty()) return; lbajardsilogic@0: lbajardsilogic@0: if (item == items[0]) { lbajardsilogic@0: lbajardsilogic@0: selectionToWrite = &ms; lbajardsilogic@0: lbajardsilogic@0: } else if (item == items[1]) { lbajardsilogic@0: lbajardsilogic@0: multiple = true; lbajardsilogic@0: lbajardsilogic@0: int n = 1; lbajardsilogic@0: QString base = path; lbajardsilogic@0: base.replace(".wav", ""); lbajardsilogic@0: lbajardsilogic@0: for (MultiSelection::SelectionList::iterator i = selections.begin(); lbajardsilogic@0: i != selections.end(); ++i) { lbajardsilogic@0: lbajardsilogic@0: MultiSelection subms; lbajardsilogic@0: subms.setSelection(*i); lbajardsilogic@0: lbajardsilogic@0: QString subpath = QString("%1.%2.wav").arg(base).arg(n); lbajardsilogic@0: ++n; lbajardsilogic@0: lbajardsilogic@0: if (QFileInfo(subpath).exists()) { lbajardsilogic@0: error = tr("Fragment file %1 already exists, aborting").arg(subpath); lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: WavFileWriter subwriter(subpath, lbajardsilogic@0: getMainModel()->getSampleRate(), lbajardsilogic@0: getMainModel()->getChannelCount()); lbajardsilogic@0: subwriter.writeModel(getMainModel(), &subms); lbajardsilogic@0: ok = subwriter.isOK(); lbajardsilogic@0: lbajardsilogic@0: if (!ok) { lbajardsilogic@0: error = subwriter.getError(); lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!multiple) { lbajardsilogic@0: WavFileWriter writer(path, lbajardsilogic@0: getMainModel()->getSampleRate(), lbajardsilogic@0: getMainModel()->getChannelCount()); lbajardsilogic@0: writer.writeModel(getMainModel(), selectionToWrite); lbajardsilogic@0: ok = writer.isOK(); lbajardsilogic@0: error = writer.getError(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (ok) { lbajardsilogic@0: if (!multiple) { lbajardsilogic@0: m_recentFiles.addFile(path); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to write file"), error); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::importLayer() lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: lbajardsilogic@0: if (!pane) { lbajardsilogic@0: // shouldn't happen, as the menu action should have been disabled lbajardsilogic@0: std::cerr << "WARNING: MainWindow::importLayer: no current pane" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!getMainModel()) { lbajardsilogic@0: // shouldn't happen, as the menu action should have been disabled lbajardsilogic@0: std::cerr << "WARNING: MainWindow::importLayer: No main model -- hence no default sample rate available" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString path = getOpenFileName(FileFinder::LayerFile); lbajardsilogic@0: lbajardsilogic@0: if (path != "") { lbajardsilogic@0: lbajardsilogic@0: if (openLayerFile(path) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("File %1 could not be opened.").arg(path)); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openLayerFile(QString path) lbajardsilogic@0: { lbajardsilogic@0: return openLayerFile(path, path); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openLayerFile(QString path, QString location) lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: lbajardsilogic@0: if (!pane) { lbajardsilogic@0: // shouldn't happen, as the menu action should have been disabled lbajardsilogic@0: std::cerr << "WARNING: MainWindow::openLayerFile: no current pane" << std::endl; lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!getMainModel()) { lbajardsilogic@0: // shouldn't happen, as the menu action should have been disabled lbajardsilogic@0: std::cerr << "WARNING: MainWindow::openLayerFile: No main model -- hence no default sample rate available" << std::endl; lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool realFile = (location == path); lbajardsilogic@0: lbajardsilogic@0: if (path.endsWith(".svl") || path.endsWith(".xml")) { lbajardsilogic@0: lbajardsilogic@0: PaneCallback callback(this); lbajardsilogic@0: QFile file(path); lbajardsilogic@0: lbajardsilogic@0: if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { lbajardsilogic@0: std::cerr << "ERROR: MainWindow::openLayerFile(" lbajardsilogic@0: << location.toStdString() lbajardsilogic@0: << "): Failed to open file for reading" << std::endl; lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: SVFileReader reader(m_document, callback, location); lbajardsilogic@0: reader.setCurrentPane(pane); lbajardsilogic@0: lbajardsilogic@0: QXmlInputSource inputSource(&file); lbajardsilogic@0: reader.parse(inputSource); lbajardsilogic@0: lbajardsilogic@0: if (!reader.isOK()) { lbajardsilogic@0: std::cerr << "ERROR: MainWindow::openLayerFile(" lbajardsilogic@0: << location.toStdString() lbajardsilogic@0: << "): Failed to read XML file: " lbajardsilogic@0: << reader.getErrorString().toStdString() << std::endl; lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_recentFiles.addFile(location); lbajardsilogic@0: lbajardsilogic@0: if (realFile) { lbajardsilogic@0: registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return FileOpenSucceeded; lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: Model *model = DataFileReaderFactory::load(path, getMainModel()->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: if (model) { lbajardsilogic@0: lbajardsilogic@0: Layer *newLayer = m_document->createImportedLayer(model); lbajardsilogic@0: lbajardsilogic@0: if (newLayer) { lbajardsilogic@0: lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: m_recentFiles.addFile(location); lbajardsilogic@0: lbajardsilogic@0: if (realFile) { lbajardsilogic@0: registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return FileOpenSucceeded; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::exportLayer() lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!pane) return; lbajardsilogic@0: lbajardsilogic@0: Layer *layer = pane->getSelectedLayer(); lbajardsilogic@0: if (!layer) return; lbajardsilogic@0: lbajardsilogic@0: Model *model = layer->getModel(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: lbajardsilogic@0: QString path = getSaveFileName(FileFinder::LayerFile); lbajardsilogic@0: lbajardsilogic@0: if (path == "") return; lbajardsilogic@0: lbajardsilogic@0: if (QFileInfo(path).suffix() == "") path += ".svl"; lbajardsilogic@0: lbajardsilogic@0: QString error; lbajardsilogic@0: lbajardsilogic@0: if (path.endsWith(".xml") || path.endsWith(".svl")) { lbajardsilogic@0: lbajardsilogic@0: QFile file(path); lbajardsilogic@0: if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { lbajardsilogic@0: error = tr("Failed to open file %1 for writing").arg(path); lbajardsilogic@0: } else { lbajardsilogic@0: QTextStream out(&file); lbajardsilogic@0: out << "\n" lbajardsilogic@0: << "\n" lbajardsilogic@0: << "\n" lbajardsilogic@0: << " \n"; lbajardsilogic@0: lbajardsilogic@0: model->toXml(out, " "); lbajardsilogic@0: lbajardsilogic@0: out << " \n" lbajardsilogic@0: << " \n"; lbajardsilogic@0: lbajardsilogic@0: layer->toXml(out, " "); lbajardsilogic@0: lbajardsilogic@0: out << " \n" lbajardsilogic@0: << "\n"; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: CSVFileWriter writer(path, model, lbajardsilogic@0: (path.endsWith(".csv") ? "," : "\t")); lbajardsilogic@0: writer.write(); lbajardsilogic@0: lbajardsilogic@0: if (!writer.isOK()) { lbajardsilogic@0: error = writer.getError(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (error != "") { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to write file"), error); lbajardsilogic@0: } else { lbajardsilogic@0: m_recentFiles.addFile(path); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::exportImage() lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!pane) return; lbajardsilogic@0: lbajardsilogic@0: QString path = getSaveFileName(FileFinder::ImageFile); lbajardsilogic@0: lbajardsilogic@0: if (path == "") return; lbajardsilogic@0: lbajardsilogic@0: if (QFileInfo(path).suffix() == "") path += ".png"; lbajardsilogic@0: lbajardsilogic@0: bool haveSelection = m_viewManager && !m_viewManager->getSelections().empty(); lbajardsilogic@0: lbajardsilogic@0: QSize total, visible, selected; lbajardsilogic@0: total = pane->getImageSize(); lbajardsilogic@0: visible = pane->getImageSize(pane->getFirstVisibleFrame(), lbajardsilogic@0: pane->getLastVisibleFrame()); lbajardsilogic@0: lbajardsilogic@0: size_t sf0 = 0, sf1 = 0; lbajardsilogic@0: lbajardsilogic@0: if (haveSelection) { lbajardsilogic@0: MultiSelection::SelectionList selections = m_viewManager->getSelections(); lbajardsilogic@0: sf0 = selections.begin()->getStartFrame(); lbajardsilogic@0: MultiSelection::SelectionList::iterator e = selections.end(); lbajardsilogic@0: --e; lbajardsilogic@0: sf1 = e->getEndFrame(); lbajardsilogic@0: selected = pane->getImageSize(sf0, sf1); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QStringList items; lbajardsilogic@0: items << tr("Export the whole pane (%1x%2 pixels)") lbajardsilogic@0: .arg(total.width()).arg(total.height()); lbajardsilogic@0: items << tr("Export the visible area only (%1x%2 pixels)") lbajardsilogic@0: .arg(visible.width()).arg(visible.height()); lbajardsilogic@0: if (haveSelection) { lbajardsilogic@0: items << tr("Export the selection extent (%1x%2 pixels)") lbajardsilogic@0: .arg(selected.width()).arg(selected.height()); lbajardsilogic@0: } else { lbajardsilogic@0: items << tr("Export the selection extent"); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: int deflt = settings.value("lastimageexportregion", 0).toInt(); lbajardsilogic@0: if (deflt == 2 && !haveSelection) deflt = 1; lbajardsilogic@0: if (deflt == 0 && total.width() > 32767) deflt = 1; lbajardsilogic@0: lbajardsilogic@0: ListInputDialog *lid = new ListInputDialog lbajardsilogic@0: (this, tr("Select region to export"), lbajardsilogic@0: tr("Which region of the current pane do you want to export as an image?"), lbajardsilogic@0: items, deflt); lbajardsilogic@0: lbajardsilogic@0: if (!haveSelection) { lbajardsilogic@0: lid->setItemAvailability(2, false); lbajardsilogic@0: } lbajardsilogic@0: if (total.width() > 32767) { // appears to be the limit of a QImage lbajardsilogic@0: lid->setItemAvailability(0, false); lbajardsilogic@0: lid->setFootnote(tr("Note: the whole pane is too wide to be exported as a single image.")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool ok = lid->exec(); lbajardsilogic@0: QString item = lid->getCurrentString(); lbajardsilogic@0: delete lid; lbajardsilogic@0: lbajardsilogic@0: if (!ok || item.isEmpty()) return; lbajardsilogic@0: lbajardsilogic@0: settings.setValue("lastimageexportregion", deflt); lbajardsilogic@0: lbajardsilogic@0: QImage *image = 0; lbajardsilogic@0: lbajardsilogic@0: if (item == items[0]) { lbajardsilogic@0: image = pane->toNewImage(); lbajardsilogic@0: } else if (item == items[1]) { lbajardsilogic@0: image = pane->toNewImage(pane->getFirstVisibleFrame(), lbajardsilogic@0: pane->getLastVisibleFrame()); lbajardsilogic@0: } else if (haveSelection) { lbajardsilogic@0: image = pane->toNewImage(sf0, sf1); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!image) return; lbajardsilogic@0: lbajardsilogic@0: if (!image->save(path, "PNG")) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to save image file"), lbajardsilogic@0: tr("Failed to save image file %1").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: delete image; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openAudioFile(QString path, AudioFileOpenMode mode) lbajardsilogic@0: { lbajardsilogic@0: return openAudioFile(path, path, mode); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openAudioFile(QString path, QString location, AudioFileOpenMode mode) lbajardsilogic@0: { lbajardsilogic@0: if (!(QFileInfo(path).exists() && lbajardsilogic@0: QFileInfo(path).isFile() && lbajardsilogic@0: QFileInfo(path).isReadable())) { lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_openingAudioFile = true; lbajardsilogic@0: lbajardsilogic@0: WaveFileModel *newModel = new WaveFileModel(path, location); lbajardsilogic@0: lbajardsilogic@0: if (!newModel->isOK()) { lbajardsilogic@0: delete newModel; lbajardsilogic@0: m_openingAudioFile = false; lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool setAsMain = true; lbajardsilogic@0: static bool prevSetAsMain = true; lbajardsilogic@0: lbajardsilogic@0: bool realFile = (location == path); lbajardsilogic@0: lbajardsilogic@0: if (mode == CreateAdditionalModel) setAsMain = false; lbajardsilogic@0: else if (mode == AskUser) { lbajardsilogic@0: if (m_document->getMainModel()) { lbajardsilogic@0: lbajardsilogic@0: QStringList items; lbajardsilogic@0: items << tr("Replace the existing main waveform") lbajardsilogic@0: << tr("Load this file into a new waveform pane"); lbajardsilogic@0: lbajardsilogic@0: bool ok = false; lbajardsilogic@0: QString item = ListInputDialog::getItem lbajardsilogic@0: (this, tr("Select target for import"), lbajardsilogic@0: tr("You already have an audio waveform loaded.\nWhat would you like to do with the new audio file?"), lbajardsilogic@0: items, prevSetAsMain ? 0 : 1, &ok); lbajardsilogic@0: lbajardsilogic@0: if (!ok || item.isEmpty()) { lbajardsilogic@0: delete newModel; lbajardsilogic@0: m_openingAudioFile = false; lbajardsilogic@0: return FileOpenCancelled; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: setAsMain = (item == items[0]); lbajardsilogic@0: prevSetAsMain = setAsMain; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (setAsMain) { lbajardsilogic@0: lbajardsilogic@0: Model *prevMain = getMainModel(); lbajardsilogic@0: if (prevMain) { lbajardsilogic@0: m_playSource->removeModel(prevMain); lbajardsilogic@0: PlayParameterRepository::getInstance()->removeModel(prevMain); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: PlayParameterRepository::getInstance()->addModel(newModel); lbajardsilogic@0: lbajardsilogic@0: m_document->setMainModel(newModel); lbajardsilogic@0: setupMenus(); lbajardsilogic@0: lbajardsilogic@0: if (m_sessionFile == "") { lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser: %1") lbajardsilogic@0: .arg(QFileInfo(location).fileName())); lbajardsilogic@0: CommandHistory::getInstance()->clear(); lbajardsilogic@0: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@0: m_documentModified = false; lbajardsilogic@0: } else { lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser: %1 [%2]") lbajardsilogic@0: .arg(QFileInfo(m_sessionFile).fileName()) lbajardsilogic@0: .arg(QFileInfo(location).fileName())); lbajardsilogic@0: if (m_documentModified) { lbajardsilogic@0: m_documentModified = false; lbajardsilogic@0: documentModified(); // so as to restore "(modified)" window title lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (realFile) m_audioFile = path; lbajardsilogic@0: lbajardsilogic@0: } else { // !setAsMain lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->startCompoundOperation lbajardsilogic@0: (tr("Import \"%1\"").arg(QFileInfo(location).fileName()), true); lbajardsilogic@0: lbajardsilogic@0: m_document->addImportedModel(newModel); lbajardsilogic@0: lbajardsilogic@0: AddPaneCommand *command = new AddPaneCommand(this); lbajardsilogic@0: CommandHistory::getInstance()->addCommand(command); lbajardsilogic@0: lbajardsilogic@0: Pane *pane = command->getPane(); lbajardsilogic@0: lbajardsilogic@0: if (!m_timeRulerLayer) { lbajardsilogic@0: m_timeRulerLayer = m_document->createMainModelLayer lbajardsilogic@0: (LayerFactory::TimeRuler); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_document->addLayerToView(pane, m_timeRulerLayer); lbajardsilogic@0: lbajardsilogic@0: Layer *newLayer = m_document->createImportedLayer(newModel); lbajardsilogic@0: lbajardsilogic@0: if (newLayer) { lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->endCompoundOperation(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: m_recentFiles.addFile(location); lbajardsilogic@0: if (realFile) { lbajardsilogic@0: registerLastOpenedFilePath(FileFinder::AudioFile, path); // for file dialog lbajardsilogic@0: } lbajardsilogic@0: m_openingAudioFile = false; lbajardsilogic@0: lbajardsilogic@0: return FileOpenSucceeded; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::createPlayTarget() lbajardsilogic@0: { lbajardsilogic@0: if (m_playTarget) return; lbajardsilogic@0: lbajardsilogic@0: m_playTarget = AudioTargetFactory::createCallbackTarget(m_playSource); lbajardsilogic@0: if (!m_playTarget) { lbajardsilogic@0: QMessageBox::warning lbajardsilogic@0: (this, tr("Couldn't open audio device"), lbajardsilogic@0: tr("Could not open an audio device for playback.\nAudio playback will not be available during this session.\n"), lbajardsilogic@0: QMessageBox::Ok, 0); lbajardsilogic@0: } lbajardsilogic@0: connect(m_fader, SIGNAL(valueChanged(float)), lbajardsilogic@0: m_playTarget, SLOT(setOutputGain(float))); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: WaveFileModel * lbajardsilogic@0: MainWindow::getMainModel() lbajardsilogic@0: { lbajardsilogic@0: if (!m_document) return 0; lbajardsilogic@0: return m_document->getMainModel(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: const WaveFileModel * lbajardsilogic@0: MainWindow::getMainModel() const lbajardsilogic@0: { lbajardsilogic@0: if (!m_document) return 0; lbajardsilogic@0: return m_document->getMainModel(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::newSession() lbajardsilogic@0: { lbajardsilogic@0: if (!checkSaveModified()) return; lbajardsilogic@0: lbajardsilogic@0: closeSession(); lbajardsilogic@0: createDocument(); lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->addPane(); lbajardsilogic@0: lbajardsilogic@0: connect(pane, SIGNAL(contextHelpChanged(const QString &)), lbajardsilogic@0: this, SLOT(contextHelpChanged(const QString &))); lbajardsilogic@0: lbajardsilogic@0: if (!m_timeRulerLayer) { lbajardsilogic@0: m_timeRulerLayer = m_document->createMainModelLayer lbajardsilogic@0: (LayerFactory::TimeRuler); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_document->addLayerToView(pane, m_timeRulerLayer); lbajardsilogic@0: lbajardsilogic@0: Layer *waveform = m_document->createMainModelLayer(LayerFactory::Waveform); lbajardsilogic@0: m_document->addLayerToView(pane, waveform); lbajardsilogic@0: lbajardsilogic@0: m_overview->registerView(pane); lbajardsilogic@0: lbajardsilogic@21: m_EasaierManager->newSession(); lbajardsilogic@21: lbajardsilogic@0: CommandHistory::getInstance()->clear(); lbajardsilogic@0: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@0: documentRestored(); lbajardsilogic@0: updateMenuStates(); lbajardsilogic@2: lbajardsilogic@2: QWidget *properties = 0; lbajardsilogic@2: lbajardsilogic@2: properties = new PropertyStack(0, m_paneStack->getCurrentPane() ); lbajardsilogic@2: //properties->show(); lbajardsilogic@2: m_toolBox->removeItem(0); lbajardsilogic@2: m_toolBox->insertItem(0,"Layers", properties); lbajardsilogic@2: lbajardsilogic@2: /*connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), lbajardsilogic@2: this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); lbajardsilogic@2: properties->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); lbajardsilogic@2: */ lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::createDocument() lbajardsilogic@0: { lbajardsilogic@0: m_document = new Document; lbajardsilogic@0: lbajardsilogic@0: connect(m_document, SIGNAL(layerAdded(Layer *)), lbajardsilogic@0: this, SLOT(layerAdded(Layer *))); lbajardsilogic@0: connect(m_document, SIGNAL(layerRemoved(Layer *)), lbajardsilogic@0: this, SLOT(layerRemoved(Layer *))); lbajardsilogic@0: connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)), lbajardsilogic@0: this, SLOT(layerAboutToBeDeleted(Layer *))); lbajardsilogic@0: connect(m_document, SIGNAL(layerInAView(Layer *, bool)), lbajardsilogic@0: this, SLOT(layerInAView(Layer *, bool))); lbajardsilogic@0: lbajardsilogic@0: connect(m_document, SIGNAL(modelAdded(Model *)), lbajardsilogic@0: this, SLOT(modelAdded(Model *))); lbajardsilogic@0: connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)), lbajardsilogic@0: this, SLOT(mainModelChanged(WaveFileModel *))); lbajardsilogic@0: connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)), lbajardsilogic@0: this, SLOT(modelAboutToBeDeleted(Model *))); lbajardsilogic@0: lbajardsilogic@21: connect(m_document, SIGNAL(audioSourceInfoAdded(AudioSourceInfoModel *)), lbajardsilogic@21: this, SLOT(audioSourceInfoAdded(AudioSourceInfoModel *))); lbajardsilogic@21: lbajardsilogic@0: connect(m_document, SIGNAL(modelGenerationFailed(QString)), lbajardsilogic@0: this, SLOT(modelGenerationFailed(QString))); lbajardsilogic@0: connect(m_document, SIGNAL(modelRegenerationFailed(QString, QString)), lbajardsilogic@0: this, SLOT(modelRegenerationFailed(QString, QString))); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::closeSession() lbajardsilogic@0: { lbajardsilogic@0: if (!checkSaveModified()) return; lbajardsilogic@0: lbajardsilogic@0: while (m_paneStack->getPaneCount() > 0) { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1); lbajardsilogic@0: lbajardsilogic@0: while (pane->getLayerCount() > 0) { lbajardsilogic@0: m_document->removeLayerFromView lbajardsilogic@0: (pane, pane->getLayer(pane->getLayerCount() - 1)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_overview->unregisterView(pane); lbajardsilogic@0: m_paneStack->deletePane(pane); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: while (m_paneStack->getHiddenPaneCount() > 0) { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getHiddenPane lbajardsilogic@0: (m_paneStack->getHiddenPaneCount() - 1); lbajardsilogic@0: lbajardsilogic@0: while (pane->getLayerCount() > 0) { lbajardsilogic@0: m_document->removeLayerFromView lbajardsilogic@0: (pane, pane->getLayer(pane->getLayerCount() - 1)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_overview->unregisterView(pane); lbajardsilogic@0: m_paneStack->deletePane(pane); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@21: m_infoWidget->reset(); lbajardsilogic@21: m_searchWidget->reset(); lbajardsilogic@21: m_resultsWidget->reset(); lbajardsilogic@21: lbajardsilogic@0: delete m_document; lbajardsilogic@0: m_document = 0; lbajardsilogic@0: m_viewManager->clearSelections(); lbajardsilogic@0: m_timeRulerLayer = 0; // document owned this lbajardsilogic@0: lbajardsilogic@0: m_sessionFile = ""; lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser")); lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->clear(); lbajardsilogic@0: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@0: documentRestored(); lbajardsilogic@21: lbajardsilogic@21: m_EasaierManager->closeSession(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::openSession() lbajardsilogic@0: { lbajardsilogic@0: if (!checkSaveModified()) return; lbajardsilogic@0: lbajardsilogic@0: QString orig = m_audioFile; lbajardsilogic@0: if (orig == "") orig = "."; lbajardsilogic@0: else orig = QFileInfo(orig).absoluteDir().canonicalPath(); lbajardsilogic@0: lbajardsilogic@0: QString path = getOpenFileName(FileFinder::SessionFile); lbajardsilogic@0: lbajardsilogic@0: if (path.isEmpty()) return; lbajardsilogic@0: lbajardsilogic@0: if (openSessionFile(path) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("Session file \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::openSomething() lbajardsilogic@0: { lbajardsilogic@0: QString orig = m_audioFile; lbajardsilogic@0: if (orig == "") orig = "."; lbajardsilogic@0: else orig = QFileInfo(orig).absoluteDir().canonicalPath(); lbajardsilogic@0: lbajardsilogic@0: bool canImportLayer = (getMainModel() != 0 && lbajardsilogic@0: m_paneStack != 0 && lbajardsilogic@0: m_paneStack->getCurrentPane() != 0); lbajardsilogic@0: lbajardsilogic@0: QString path = getOpenFileName(FileFinder::AnyFile); lbajardsilogic@0: lbajardsilogic@0: if (path.isEmpty()) return; lbajardsilogic@0: lbajardsilogic@0: if (path.endsWith(".sv")) { lbajardsilogic@0: lbajardsilogic@0: if (!checkSaveModified()) return; lbajardsilogic@0: lbajardsilogic@0: if (openSessionFile(path) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("Session file \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: if (openAudioFile(path, AskUser) == FileOpenFailed) { lbajardsilogic@0: lbajardsilogic@0: if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) { lbajardsilogic@0: lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("File \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::openLocation() lbajardsilogic@0: { lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: QString lastLocation = settings.value("lastremote", "").toString(); lbajardsilogic@0: lbajardsilogic@0: bool ok = false; lbajardsilogic@0: QString text = QInputDialog::getText lbajardsilogic@0: (this, tr("Open Location"), lbajardsilogic@0: tr("Please enter the URL of the location to open:"), lbajardsilogic@0: QLineEdit::Normal, lastLocation, &ok); lbajardsilogic@0: lbajardsilogic@0: if (!ok) return; lbajardsilogic@0: lbajardsilogic@0: settings.setValue("lastremote", text); lbajardsilogic@0: lbajardsilogic@0: if (text.isEmpty()) return; lbajardsilogic@0: lbajardsilogic@0: if (openURL(QUrl(text)) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open location"), lbajardsilogic@0: tr("URL \"%1\" could not be opened").arg(text)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::openRecentFile() lbajardsilogic@0: { lbajardsilogic@0: QObject *obj = sender(); lbajardsilogic@0: QAction *action = dynamic_cast(obj); lbajardsilogic@0: lbajardsilogic@0: if (!action) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::openRecentFile: sender is not an action" lbajardsilogic@0: << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString path = action->text(); lbajardsilogic@0: if (path == "") return; lbajardsilogic@0: lbajardsilogic@0: QUrl url(path); lbajardsilogic@0: if (RemoteFile::canHandleScheme(url)) { lbajardsilogic@0: openURL(url); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (path.endsWith("sv")) { lbajardsilogic@0: lbajardsilogic@0: if (!checkSaveModified()) return; lbajardsilogic@0: lbajardsilogic@0: if (openSessionFile(path) == FileOpenFailed) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("Session file \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: if (openAudioFile(path, AskUser) == FileOpenFailed) { lbajardsilogic@0: lbajardsilogic@0: bool canImportLayer = (getMainModel() != 0 && lbajardsilogic@0: m_paneStack != 0 && lbajardsilogic@0: m_paneStack->getCurrentPane() != 0); lbajardsilogic@0: lbajardsilogic@0: if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) { lbajardsilogic@0: lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@0: tr("File \"%1\" could not be opened").arg(path)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openURL(QUrl url) lbajardsilogic@0: { lbajardsilogic@0: if (url.scheme().toLower() == "file") { lbajardsilogic@0: return openSomeFile(url.toLocalFile()); lbajardsilogic@0: } else if (!RemoteFile::canHandleScheme(url)) { lbajardsilogic@0: QMessageBox::critical(this, tr("Unsupported scheme in URL"), lbajardsilogic@0: tr("The URL scheme \"%1\" is not supported") lbajardsilogic@0: .arg(url.scheme())); lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } else { lbajardsilogic@0: RemoteFile rf(url); lbajardsilogic@0: rf.wait(); lbajardsilogic@0: if (!rf.isOK()) { lbajardsilogic@0: QMessageBox::critical(this, tr("File download failed"), lbajardsilogic@0: tr("Failed to download URL \"%1\": %2") lbajardsilogic@0: .arg(url.toString()).arg(rf.getErrorString())); lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: FileOpenStatus status; lbajardsilogic@0: if ((status = openSomeFile(rf.getLocalFilename(), url.toString())) != lbajardsilogic@0: FileOpenSucceeded) { lbajardsilogic@0: rf.deleteLocalFile(); lbajardsilogic@0: } lbajardsilogic@0: return status; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openSomeFile(QString path, AudioFileOpenMode mode) lbajardsilogic@0: { lbajardsilogic@0: return openSomeFile(path, path, mode); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openSomeFile(QString path, QString location, lbajardsilogic@0: AudioFileOpenMode mode) lbajardsilogic@0: { lbajardsilogic@0: FileOpenStatus status; lbajardsilogic@0: lbajardsilogic@0: bool canImportLayer = (getMainModel() != 0 && lbajardsilogic@0: m_paneStack != 0 && lbajardsilogic@0: m_paneStack->getCurrentPane() != 0); lbajardsilogic@0: lbajardsilogic@0: if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) { lbajardsilogic@0: return status; lbajardsilogic@0: } else if ((status = openSessionFile(path, location)) != FileOpenFailed) { lbajardsilogic@0: return status; lbajardsilogic@0: } else if (!canImportLayer) { lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } else if ((status = openLayerFile(path, location)) != FileOpenFailed) { lbajardsilogic@0: return status; lbajardsilogic@0: } else { lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openSessionFile(QString path) lbajardsilogic@0: { lbajardsilogic@0: return openSessionFile(path, path); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::FileOpenStatus lbajardsilogic@0: MainWindow::openSessionFile(QString path, QString location) lbajardsilogic@0: { lbajardsilogic@0: BZipFileDevice bzFile(path); lbajardsilogic@0: if (!bzFile.open(QIODevice::ReadOnly)) { lbajardsilogic@0: std::cerr << "Failed to open session file \"" << location.toStdString() lbajardsilogic@0: << "\": " << bzFile.errorString().toStdString() << std::endl; lbajardsilogic@0: return FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!checkSaveModified()) return FileOpenCancelled; lbajardsilogic@0: lbajardsilogic@0: QString error; lbajardsilogic@0: closeSession(); lbajardsilogic@0: createDocument(); lbajardsilogic@0: lbajardsilogic@0: PaneCallback callback(this); lbajardsilogic@0: m_viewManager->clearSelections(); lbajardsilogic@0: lbajardsilogic@0: SVFileReader reader(m_document, callback, location); lbajardsilogic@0: QXmlInputSource inputSource(&bzFile); lbajardsilogic@0: reader.parse(inputSource); lbajardsilogic@0: lbajardsilogic@0: if (!reader.isOK()) { lbajardsilogic@0: error = tr("SV XML file read error:\n%1").arg(reader.getErrorString()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bzFile.close(); lbajardsilogic@0: lbajardsilogic@0: bool ok = (error == ""); lbajardsilogic@0: lbajardsilogic@0: bool realFile = (location == path); lbajardsilogic@0: lbajardsilogic@0: if (ok) { lbajardsilogic@0: lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser: %1") lbajardsilogic@0: .arg(QFileInfo(location).fileName())); lbajardsilogic@0: lbajardsilogic@0: if (realFile) m_sessionFile = path; lbajardsilogic@0: lbajardsilogic@0: setupMenus(); lbajardsilogic@0: CommandHistory::getInstance()->clear(); lbajardsilogic@0: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@0: m_documentModified = false; lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: lbajardsilogic@0: m_recentFiles.addFile(location); lbajardsilogic@0: lbajardsilogic@0: if (realFile) { lbajardsilogic@0: registerLastOpenedFilePath(FileFinder::SessionFile, path); // for file dialog lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return ok ? FileOpenSucceeded : FileOpenFailed; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::closeEvent(QCloseEvent *e) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::closeEvent" << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (m_openingAudioFile) { lbajardsilogic@0: // std::cerr << "Busy - ignoring close event" << std::endl; lbajardsilogic@0: e->ignore(); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!m_abandoning && !checkSaveModified()) { lbajardsilogic@0: // std::cerr << "Ignoring close event" << std::endl; lbajardsilogic@0: e->ignore(); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: settings.setValue("size", size()); lbajardsilogic@0: settings.setValue("position", pos()); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: lbajardsilogic@0: e->accept(); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool lbajardsilogic@0: MainWindow::commitData(bool mayAskUser) lbajardsilogic@0: { lbajardsilogic@0: if (mayAskUser) { lbajardsilogic@0: return checkSaveModified(); lbajardsilogic@0: } else { lbajardsilogic@0: if (!m_documentModified) return true; lbajardsilogic@0: lbajardsilogic@0: // If we can't check with the user first, then we can't save lbajardsilogic@0: // to the original session file (even if we have it) -- have lbajardsilogic@0: // to use a temporary file lbajardsilogic@0: lbajardsilogic@0: QString svDirBase = ".sv1"; lbajardsilogic@0: QString svDir = QDir::home().filePath(svDirBase); lbajardsilogic@0: lbajardsilogic@0: if (!QFileInfo(svDir).exists()) { lbajardsilogic@0: if (!QDir::home().mkdir(svDirBase)) return false; lbajardsilogic@0: } else { lbajardsilogic@0: if (!QFileInfo(svDir).isDir()) return false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // This name doesn't have to be unguessable lbajardsilogic@0: #ifndef _WIN32 lbajardsilogic@0: QString fname = QString("tmp-%1-%2.sv") lbajardsilogic@0: .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz")) lbajardsilogic@0: .arg(QProcess().pid()); lbajardsilogic@0: #else lbajardsilogic@0: QString fname = QString("tmp-%1.sv") lbajardsilogic@0: .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz")); lbajardsilogic@0: #endif lbajardsilogic@0: QString fpath = QDir(svDir).filePath(fname); lbajardsilogic@0: if (saveSessionFile(fpath)) { lbajardsilogic@0: m_recentFiles.addFile(fpath); lbajardsilogic@0: return true; lbajardsilogic@0: } else { lbajardsilogic@0: return false; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool lbajardsilogic@0: MainWindow::checkSaveModified() lbajardsilogic@0: { lbajardsilogic@0: // Called before some destructive operation (e.g. new session, lbajardsilogic@0: // exit program). Return true if we can safely proceed, false to lbajardsilogic@0: // cancel. lbajardsilogic@0: lbajardsilogic@0: if (!m_documentModified) return true; lbajardsilogic@0: lbajardsilogic@0: int button = lbajardsilogic@0: QMessageBox::warning(this, lbajardsilogic@0: tr("Session modified"), lbajardsilogic@0: tr("The current session has been modified.\nDo you want to save it?"), lbajardsilogic@0: QMessageBox::Yes, lbajardsilogic@0: QMessageBox::No, lbajardsilogic@0: QMessageBox::Cancel); lbajardsilogic@0: lbajardsilogic@0: if (button == QMessageBox::Yes) { lbajardsilogic@0: saveSession(); lbajardsilogic@0: if (m_documentModified) { // save failed -- don't proceed! lbajardsilogic@0: return false; lbajardsilogic@0: } else { lbajardsilogic@0: return true; // saved, so it's safe to continue now lbajardsilogic@0: } lbajardsilogic@0: } else if (button == QMessageBox::No) { lbajardsilogic@0: m_documentModified = false; // so we know to abandon it lbajardsilogic@0: return true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // else cancel lbajardsilogic@0: return false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::saveSession() lbajardsilogic@0: { lbajardsilogic@0: if (m_sessionFile != "") { lbajardsilogic@0: if (!saveSessionFile(m_sessionFile)) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to save file"), lbajardsilogic@0: tr("Session file \"%1\" could not be saved.").arg(m_sessionFile)); lbajardsilogic@0: } else { lbajardsilogic@0: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@0: documentRestored(); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: saveSessionAs(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::saveSessionAs() lbajardsilogic@0: { lbajardsilogic@0: QString orig = m_audioFile; lbajardsilogic@0: if (orig == "") orig = "."; lbajardsilogic@0: else orig = QFileInfo(orig).absoluteDir().canonicalPath(); lbajardsilogic@0: lbajardsilogic@0: QString path = getSaveFileName(FileFinder::SessionFile); lbajardsilogic@0: lbajardsilogic@0: if (path == "") return; lbajardsilogic@0: lbajardsilogic@0: if (!saveSessionFile(path)) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to save file"), lbajardsilogic@0: tr("Session file \"%1\" could not be saved.").arg(path)); lbajardsilogic@0: } else { lbajardsilogic@0: setWindowTitle(tr("Sonic Visualiser: %1") lbajardsilogic@0: .arg(QFileInfo(path).fileName())); lbajardsilogic@0: m_sessionFile = path; lbajardsilogic@0: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@0: documentRestored(); lbajardsilogic@0: m_recentFiles.addFile(path); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool lbajardsilogic@0: MainWindow::saveSessionFile(QString path) lbajardsilogic@0: { lbajardsilogic@0: BZipFileDevice bzFile(path); lbajardsilogic@0: if (!bzFile.open(QIODevice::WriteOnly)) { lbajardsilogic@0: std::cerr << "Failed to open session file \"" << path.toStdString() lbajardsilogic@0: << "\" for writing: " lbajardsilogic@0: << bzFile.errorString().toStdString() << std::endl; lbajardsilogic@0: return false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); lbajardsilogic@0: lbajardsilogic@0: QTextStream out(&bzFile); lbajardsilogic@0: toXml(out); lbajardsilogic@0: out.flush(); lbajardsilogic@0: lbajardsilogic@0: QApplication::restoreOverrideCursor(); lbajardsilogic@0: lbajardsilogic@0: if (!bzFile.isOK()) { lbajardsilogic@0: QMessageBox::critical(this, tr("Failed to write file"), lbajardsilogic@0: tr("Failed to write to file \"%1\": %2") lbajardsilogic@0: .arg(path).arg(bzFile.errorString())); lbajardsilogic@0: bzFile.close(); lbajardsilogic@0: return false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bzFile.close(); lbajardsilogic@0: return true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toXml(QTextStream &out) lbajardsilogic@0: { lbajardsilogic@0: QString indent(" "); lbajardsilogic@0: lbajardsilogic@0: out << "\n"; lbajardsilogic@0: out << "\n"; lbajardsilogic@0: out << "\n"; lbajardsilogic@0: lbajardsilogic@0: m_document->toXml(out, "", ""); lbajardsilogic@0: lbajardsilogic@0: out << "\n"; lbajardsilogic@0: lbajardsilogic@0: out << QString(" \n") lbajardsilogic@0: .arg(width()).arg(height()); lbajardsilogic@0: lbajardsilogic@0: for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getPane(i); lbajardsilogic@0: lbajardsilogic@0: if (pane) { lbajardsilogic@0: pane->toXml(out, indent); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: out << "\n"; lbajardsilogic@0: lbajardsilogic@0: m_viewManager->getSelection().toXml(out); lbajardsilogic@0: lbajardsilogic@0: out << "\n"; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@21: void MainWindow::toEasaierXml(QTextStream &out) lbajardsilogic@21: { lbajardsilogic@21: QString s; lbajardsilogic@21: QString indent(" "); lbajardsilogic@21: lbajardsilogic@21: s += "\n"; lbajardsilogic@21: // s += "\n"; lbajardsilogic@21: s += "\n"; lbajardsilogic@21: lbajardsilogic@21: s += "\n"; lbajardsilogic@21: lbajardsilogic@21: s += QString(" \n") lbajardsilogic@21: .arg(width()).arg(height()); lbajardsilogic@21: lbajardsilogic@21: for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { lbajardsilogic@21: lbajardsilogic@21: Pane *pane = m_paneStack->getPane(i); lbajardsilogic@21: lbajardsilogic@21: if (pane) { lbajardsilogic@21: s += pane->toEasaierXmlString(indent); lbajardsilogic@21: } lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: s += "\n"; lbajardsilogic@21: lbajardsilogic@21: // s += m_viewManager->getSelection().toXmlString(); lbajardsilogic@21: lbajardsilogic@21: s += m_document->toEasaierXmlString(indent, ""); lbajardsilogic@21: lbajardsilogic@21: s += "\n"; lbajardsilogic@21: lbajardsilogic@21: out << s; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@0: Pane * lbajardsilogic@0: MainWindow::addPaneToStack() lbajardsilogic@0: { lbajardsilogic@0: AddPaneCommand *command = new AddPaneCommand(this); lbajardsilogic@0: CommandHistory::getInstance()->addCommand(command); lbajardsilogic@0: return command->getPane(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::zoomIn() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->zoom(true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::zoomOut() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->zoom(false); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::zoomToFit() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!currentPane) return; lbajardsilogic@0: lbajardsilogic@0: Model *model = getMainModel(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: lbajardsilogic@0: size_t start = model->getStartFrame(); lbajardsilogic@0: size_t end = model->getEndFrame(); lbajardsilogic@0: size_t pixels = currentPane->width(); lbajardsilogic@0: size_t zoomLevel = (end - start) / pixels; lbajardsilogic@0: lbajardsilogic@0: currentPane->setZoomLevel(zoomLevel); lbajardsilogic@0: currentPane->setStartFrame(start); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::zoomDefault() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->setZoomLevel(1024); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::scrollLeft() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->scroll(false, false); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::jumpLeft() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->scroll(false, true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::scrollRight() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->scroll(true, false); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::jumpRight() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) currentPane->scroll(true, true); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::showNoOverlays() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::NoOverlays); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::showMinimalOverlays() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::showStandardOverlays() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::StandardOverlays); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::showAllOverlays() lbajardsilogic@0: { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::AllOverlays); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toggleZoomWheels() lbajardsilogic@0: { lbajardsilogic@0: if (m_viewManager->getZoomWheelsEnabled()) { lbajardsilogic@0: m_viewManager->setZoomWheelsEnabled(false); lbajardsilogic@0: } else { lbajardsilogic@0: m_viewManager->setZoomWheelsEnabled(true); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::togglePropertyBoxes() lbajardsilogic@0: { lbajardsilogic@0: if (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks) { lbajardsilogic@0: if (Preferences::getInstance()->getPropertyBoxLayout() == lbajardsilogic@0: Preferences::VerticallyStacked) { lbajardsilogic@0: m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout); lbajardsilogic@0: } else { lbajardsilogic@0: m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: m_paneStack->setLayoutStyle(PaneStack::NoPropertyStacks); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::toggleStatusBar() lbajardsilogic@0: { lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: bool sb = settings.value("showstatusbar", true).toBool(); lbajardsilogic@0: lbajardsilogic@0: if (sb) { lbajardsilogic@0: statusBar()->hide(); lbajardsilogic@0: } else { lbajardsilogic@0: statusBar()->show(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: settings.setValue("showstatusbar", !sb); lbajardsilogic@0: lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::preferenceChanged(PropertyContainer::PropertyName name) lbajardsilogic@0: { lbajardsilogic@0: if (name == "Property Box Layout") { lbajardsilogic@0: if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) { lbajardsilogic@0: if (Preferences::getInstance()->getPropertyBoxLayout() == lbajardsilogic@0: Preferences::VerticallyStacked) { lbajardsilogic@0: m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout); lbajardsilogic@0: } else { lbajardsilogic@0: m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::play() lbajardsilogic@0: { lbajardsilogic@0: if (m_playSource->isPlaying()) { lbajardsilogic@0: stop(); lbajardsilogic@0: } else { lbajardsilogic@0: playbackFrameChanged(m_viewManager->getPlaybackFrame()); lbajardsilogic@0: m_playSource->play(m_viewManager->getPlaybackFrame()); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::ffwd() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: lbajardsilogic@0: int frame = m_viewManager->getPlaybackFrame(); lbajardsilogic@0: ++frame; lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!pane) return; lbajardsilogic@0: lbajardsilogic@0: Layer *layer = pane->getSelectedLayer(); lbajardsilogic@0: lbajardsilogic@0: if (!dynamic_cast(layer) && lbajardsilogic@0: !dynamic_cast(layer)) return; lbajardsilogic@0: lbajardsilogic@0: size_t resolution = 0; lbajardsilogic@0: if (!layer->snapToFeatureFrame(pane, frame, resolution, Layer::SnapRight)) { lbajardsilogic@0: frame = getMainModel()->getEndFrame(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_viewManager->setPlaybackFrame(frame); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::ffwdEnd() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: m_viewManager->setPlaybackFrame(getMainModel()->getEndFrame()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::rewind() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: lbajardsilogic@0: int frame = m_viewManager->getPlaybackFrame(); lbajardsilogic@0: if (frame > 0) --frame; lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (!pane) return; lbajardsilogic@0: lbajardsilogic@0: Layer *layer = pane->getSelectedLayer(); lbajardsilogic@0: lbajardsilogic@0: if (!dynamic_cast(layer) && lbajardsilogic@0: !dynamic_cast(layer)) return; lbajardsilogic@0: lbajardsilogic@0: size_t resolution = 0; lbajardsilogic@0: if (!layer->snapToFeatureFrame(pane, frame, resolution, Layer::SnapLeft)) { lbajardsilogic@0: frame = getMainModel()->getEndFrame(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_viewManager->setPlaybackFrame(frame); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::rewindStart() lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel()) return; lbajardsilogic@0: m_viewManager->setPlaybackFrame(getMainModel()->getStartFrame()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::stop() lbajardsilogic@0: { lbajardsilogic@0: m_playSource->stop(); lbajardsilogic@0: lbajardsilogic@0: if (m_paneStack && m_paneStack->getCurrentPane()) { lbajardsilogic@0: updateVisibleRangeDisplay(m_paneStack->getCurrentPane()); lbajardsilogic@0: } else { lbajardsilogic@0: m_myStatusMessage = ""; lbajardsilogic@0: statusBar()->showMessage(""); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::addPane() lbajardsilogic@0: { lbajardsilogic@0: QObject *s = sender(); lbajardsilogic@0: QAction *action = dynamic_cast(s); lbajardsilogic@0: lbajardsilogic@0: if (!action) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::addPane: sender is not an action" lbajardsilogic@0: << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: PaneActionMap::iterator i = m_paneActions.find(action); lbajardsilogic@0: lbajardsilogic@0: if (i == m_paneActions.end()) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::addPane: unknown action " lbajardsilogic@0: << action->objectName().toStdString() << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: addPane(i->second, action->text()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::addPane(const PaneConfiguration &configuration, QString text) lbajardsilogic@0: { lbajardsilogic@0: CommandHistory::getInstance()->startCompoundOperation(text, true); lbajardsilogic@0: lbajardsilogic@0: AddPaneCommand *command = new AddPaneCommand(this); lbajardsilogic@0: CommandHistory::getInstance()->addCommand(command); lbajardsilogic@0: lbajardsilogic@0: Pane *pane = command->getPane(); lbajardsilogic@0: lbajardsilogic@0: if (configuration.layer == LayerFactory::Spectrum) { lbajardsilogic@0: pane->setPlaybackFollow(PlaybackScrollContinuous); lbajardsilogic@0: pane->setFollowGlobalZoom(false); lbajardsilogic@0: pane->setZoomLevel(512); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (configuration.layer != LayerFactory::TimeRuler && lbajardsilogic@0: configuration.layer != LayerFactory::Spectrum) { lbajardsilogic@0: lbajardsilogic@0: if (!m_timeRulerLayer) { lbajardsilogic@0: // std::cerr << "no time ruler layer, creating one" << std::endl; lbajardsilogic@0: m_timeRulerLayer = m_document->createMainModelLayer lbajardsilogic@0: (LayerFactory::TimeRuler); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "adding time ruler layer " << m_timeRulerLayer << std::endl; lbajardsilogic@0: lbajardsilogic@0: m_document->addLayerToView(pane, m_timeRulerLayer); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Layer *newLayer = m_document->createLayer(configuration.layer); lbajardsilogic@0: lbajardsilogic@0: Model *suggestedModel = configuration.sourceModel; lbajardsilogic@0: Model *model = 0; lbajardsilogic@0: lbajardsilogic@0: if (suggestedModel) { lbajardsilogic@0: lbajardsilogic@0: // check its validity lbajardsilogic@0: std::vector inputModels = m_document->getTransformInputModels(); lbajardsilogic@0: for (size_t j = 0; j < inputModels.size(); ++j) { lbajardsilogic@0: if (inputModels[j] == suggestedModel) { lbajardsilogic@0: model = suggestedModel; lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!model) { lbajardsilogic@0: std::cerr << "WARNING: Model " << (void *)suggestedModel lbajardsilogic@0: << " appears in pane action map, but is not reported " lbajardsilogic@0: << "by document as a valid transform source" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!model) model = m_document->getMainModel(); lbajardsilogic@0: lbajardsilogic@0: m_document->setModel(newLayer, model); lbajardsilogic@0: lbajardsilogic@0: m_document->setChannel(newLayer, configuration.channel); lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: lbajardsilogic@0: m_paneStack->setCurrentPane(pane); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, newLayer); lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "MainWindow::addPane: global centre frame is " lbajardsilogic@0: // << m_viewManager->getGlobalCentreFrame() << std::endl; lbajardsilogic@0: // pane->setCentreFrame(m_viewManager->getGlobalCentreFrame()); lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->endCompoundOperation(); lbajardsilogic@0: lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::AddPaneCommand::AddPaneCommand(MainWindow *mw) : lbajardsilogic@0: m_mw(mw), lbajardsilogic@0: m_pane(0), lbajardsilogic@0: m_prevCurrentPane(0), lbajardsilogic@0: m_added(false) lbajardsilogic@0: { lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::AddPaneCommand::~AddPaneCommand() lbajardsilogic@0: { lbajardsilogic@0: if (m_pane && !m_added) { lbajardsilogic@0: m_mw->m_paneStack->deletePane(m_pane); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: MainWindow::AddPaneCommand::getName() const lbajardsilogic@0: { lbajardsilogic@0: return tr("Add Pane"); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::AddPaneCommand::execute() lbajardsilogic@0: { lbajardsilogic@0: if (!m_pane) { lbajardsilogic@0: m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane(); lbajardsilogic@0: m_pane = m_mw->m_paneStack->addPane(); lbajardsilogic@0: lbajardsilogic@0: connect(m_pane, SIGNAL(contextHelpChanged(const QString &)), lbajardsilogic@0: m_mw, SLOT(contextHelpChanged(const QString &))); lbajardsilogic@0: } else { lbajardsilogic@0: m_mw->m_paneStack->showPane(m_pane); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_mw->m_paneStack->setCurrentPane(m_pane); lbajardsilogic@0: m_mw->m_overview->registerView(m_pane); lbajardsilogic@0: m_added = true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::AddPaneCommand::unexecute() lbajardsilogic@0: { lbajardsilogic@0: m_mw->m_paneStack->hidePane(m_pane); lbajardsilogic@0: m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane); lbajardsilogic@0: m_mw->m_overview->unregisterView(m_pane); lbajardsilogic@0: m_added = false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::RemovePaneCommand::RemovePaneCommand(MainWindow *mw, Pane *pane) : lbajardsilogic@0: m_mw(mw), lbajardsilogic@0: m_pane(pane), lbajardsilogic@0: m_added(true) lbajardsilogic@0: { lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: MainWindow::RemovePaneCommand::~RemovePaneCommand() lbajardsilogic@0: { lbajardsilogic@0: if (m_pane && !m_added) { lbajardsilogic@0: m_mw->m_paneStack->deletePane(m_pane); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: MainWindow::RemovePaneCommand::getName() const lbajardsilogic@0: { lbajardsilogic@0: return tr("Remove Pane"); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::RemovePaneCommand::execute() lbajardsilogic@0: { lbajardsilogic@0: m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane(); lbajardsilogic@0: m_mw->m_paneStack->hidePane(m_pane); lbajardsilogic@0: m_mw->m_overview->unregisterView(m_pane); lbajardsilogic@0: m_added = false; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::RemovePaneCommand::unexecute() lbajardsilogic@0: { lbajardsilogic@0: m_mw->m_paneStack->showPane(m_pane); lbajardsilogic@0: m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane); lbajardsilogic@0: m_mw->m_overview->registerView(m_pane); lbajardsilogic@0: m_added = true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::addLayer() lbajardsilogic@0: { lbajardsilogic@0: QObject *s = sender(); lbajardsilogic@0: QAction *action = dynamic_cast(s); lbajardsilogic@0: lbajardsilogic@0: if (!action) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::addLayer: sender is not an action" lbajardsilogic@0: << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: lbajardsilogic@0: if (!pane) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::addLayer: no current pane" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: ExistingLayerActionMap::iterator ei = m_existingLayerActions.find(action); lbajardsilogic@0: lbajardsilogic@0: if (ei != m_existingLayerActions.end()) { lbajardsilogic@0: Layer *newLayer = ei->second; lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, newLayer); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: ei = m_sliceActions.find(action); lbajardsilogic@0: lbajardsilogic@0: if (ei != m_sliceActions.end()) { lbajardsilogic@0: Layer *newLayer = m_document->createLayer(LayerFactory::Slice); lbajardsilogic@0: // document->setModel(newLayer, ei->second->getModel()); lbajardsilogic@0: SliceableLayer *source = dynamic_cast(ei->second); lbajardsilogic@0: SliceLayer *dest = dynamic_cast(newLayer); lbajardsilogic@0: if (source && dest) { lbajardsilogic@0: dest->setSliceableModel(source->getSliceableModel()); lbajardsilogic@0: connect(source, SIGNAL(sliceableModelReplaced(const Model *, const Model *)), lbajardsilogic@0: dest, SLOT(sliceableModelReplaced(const Model *, const Model *))); lbajardsilogic@0: connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)), lbajardsilogic@0: dest, SLOT(modelAboutToBeDeleted(Model *))); lbajardsilogic@0: } lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, newLayer); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: TransformActionMap::iterator i = m_transformActions.find(action); lbajardsilogic@0: lbajardsilogic@0: if (i == m_transformActions.end()) { lbajardsilogic@0: lbajardsilogic@0: LayerActionMap::iterator i = m_layerActions.find(action); lbajardsilogic@0: lbajardsilogic@0: if (i == m_layerActions.end()) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::addLayer: unknown action " lbajardsilogic@0: << action->objectName().toStdString() << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: LayerFactory::LayerType type = i->second; lbajardsilogic@0: lbajardsilogic@0: LayerFactory::LayerTypeSet emptyTypes = lbajardsilogic@0: LayerFactory::getInstance()->getValidEmptyLayerTypes(); lbajardsilogic@0: lbajardsilogic@0: Layer *newLayer; lbajardsilogic@0: lbajardsilogic@0: if (emptyTypes.find(type) != emptyTypes.end()) { lbajardsilogic@0: lbajardsilogic@0: newLayer = m_document->createEmptyLayer(type); lbajardsilogic@0: m_toolActions[ViewManager::DrawMode]->trigger(); lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: newLayer = m_document->createMainModelLayer(type); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, newLayer); lbajardsilogic@0: lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: TransformId transform = i->second; lbajardsilogic@0: TransformFactory *factory = TransformFactory::getInstance(); lbajardsilogic@0: lbajardsilogic@0: QString configurationXml; lbajardsilogic@0: lbajardsilogic@0: int channel = -1; lbajardsilogic@0: // pick up the default channel from any existing layers on the same pane lbajardsilogic@0: for (int j = 0; j < pane->getLayerCount(); ++j) { lbajardsilogic@0: int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j)); lbajardsilogic@0: if (c != -1) { lbajardsilogic@0: channel = c; lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // We always ask for configuration, even if the plugin isn't lbajardsilogic@0: // supposed to be configurable, because we need to let the user lbajardsilogic@0: // change the execution context (block size etc). lbajardsilogic@0: lbajardsilogic@0: PluginTransform::ExecutionContext context(channel); lbajardsilogic@0: lbajardsilogic@0: std::vector candidateInputModels = lbajardsilogic@0: m_document->getTransformInputModels(); lbajardsilogic@0: lbajardsilogic@0: Model *inputModel = factory->getConfigurationForTransform(transform, lbajardsilogic@0: candidateInputModels, lbajardsilogic@0: context, lbajardsilogic@0: configurationXml, lbajardsilogic@0: m_playSource); lbajardsilogic@0: if (!inputModel) return; lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "MainWindow::addLayer: Input model is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; lbajardsilogic@0: lbajardsilogic@0: Layer *newLayer = m_document->createDerivedLayer(transform, lbajardsilogic@0: inputModel, lbajardsilogic@0: context, lbajardsilogic@0: configurationXml); lbajardsilogic@0: lbajardsilogic@0: if (newLayer) { lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: m_document->setChannel(newLayer, context.channel); lbajardsilogic@0: m_recentTransforms.add(transform); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, newLayer); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::deleteCurrentPane() lbajardsilogic@0: { lbajardsilogic@0: CommandHistory::getInstance()->startCompoundOperation lbajardsilogic@0: (tr("Delete Pane"), true); lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (pane) { lbajardsilogic@0: while (pane->getLayerCount() > 0) { lbajardsilogic@0: Layer *layer = pane->getLayer(0); lbajardsilogic@0: if (layer) { lbajardsilogic@0: m_document->removeLayerFromView(pane, layer); lbajardsilogic@0: } else { lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: RemovePaneCommand *command = new RemovePaneCommand(this, pane); lbajardsilogic@0: CommandHistory::getInstance()->addCommand(command); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->endCompoundOperation(); lbajardsilogic@0: lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::deleteCurrentLayer() lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (pane) { lbajardsilogic@0: Layer *layer = pane->getSelectedLayer(); lbajardsilogic@0: if (layer) { lbajardsilogic@0: m_document->removeLayerFromView(pane, layer); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::renameCurrentLayer() lbajardsilogic@0: { lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (pane) { lbajardsilogic@0: Layer *layer = pane->getSelectedLayer(); lbajardsilogic@0: if (layer) { lbajardsilogic@0: bool ok = false; lbajardsilogic@0: QString newName = QInputDialog::getText lbajardsilogic@0: (this, tr("Rename Layer"), lbajardsilogic@0: tr("New name for this layer:"), lbajardsilogic@0: QLineEdit::Normal, layer->objectName(), &ok); lbajardsilogic@0: if (ok) { lbajardsilogic@0: layer->setObjectName(newName); lbajardsilogic@0: setupExistingLayersMenus(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::playSpeedChanged(int position) lbajardsilogic@0: { lbajardsilogic@0: PlaySpeedRangeMapper mapper(0, 200); lbajardsilogic@0: lbajardsilogic@0: float percent = m_playSpeed->mappedValue(); lbajardsilogic@0: lbajardsilogic@0: float factor = mapper.getFactorForValue(percent); lbajardsilogic@0: lbajardsilogic@0: // float factor = mapper.getFactorForPosition(position); lbajardsilogic@0: // float percent = mapper.getValueForPosition(position); lbajardsilogic@0: lbajardsilogic@0: std::cerr << "speed = " << position << " percent = " << percent << " factor = " << factor << std::endl; lbajardsilogic@0: lbajardsilogic@0: //!!! bool slow = (position < 100); lbajardsilogic@0: bool something = (position != 100); lbajardsilogic@0: /*!!! lbajardsilogic@0: int pc = lrintf(percent); lbajardsilogic@0: lbajardsilogic@0: m_playSpeed->setToolTip(tr("Playback speed: %1%2%") lbajardsilogic@0: .arg(!slow ? "+" : "") lbajardsilogic@0: .arg(pc)); lbajardsilogic@0: */ lbajardsilogic@0: m_playSharpen->setEnabled(something); lbajardsilogic@0: m_playMono->setEnabled(something); lbajardsilogic@0: bool sharpen = (something && m_playSharpen->isChecked()); lbajardsilogic@0: bool mono = (something && m_playMono->isChecked()); lbajardsilogic@0: m_playSource->setTimeStretch(factor, sharpen, mono); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::playSharpenToggled() lbajardsilogic@0: { lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: settings.setValue("playsharpen", m_playSharpen->isChecked()); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: lbajardsilogic@0: playSpeedChanged(m_playSpeed->value()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::playMonoToggled() lbajardsilogic@0: { lbajardsilogic@0: QSettings settings; lbajardsilogic@0: settings.beginGroup("MainWindow"); lbajardsilogic@0: settings.setValue("playmono", m_playMono->isChecked()); lbajardsilogic@0: settings.endGroup(); lbajardsilogic@0: lbajardsilogic@0: playSpeedChanged(m_playSpeed->value()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::playbackFrameChanged(unsigned long frame) lbajardsilogic@0: { lbajardsilogic@0: if (!(m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; lbajardsilogic@0: lbajardsilogic@0: RealTime now = RealTime::frame2RealTime lbajardsilogic@0: (frame, getMainModel()->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: if (now.sec == m_lastPlayStatusSec) return; lbajardsilogic@0: lbajardsilogic@0: RealTime then = RealTime::frame2RealTime lbajardsilogic@0: (m_playSource->getPlayEndFrame(), getMainModel()->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: QString nowStr; lbajardsilogic@0: QString thenStr; lbajardsilogic@0: QString remainingStr; lbajardsilogic@0: lbajardsilogic@0: if (then.sec > 10) { lbajardsilogic@0: nowStr = now.toSecText().c_str(); lbajardsilogic@0: thenStr = then.toSecText().c_str(); lbajardsilogic@0: remainingStr = (then - now).toSecText().c_str(); lbajardsilogic@0: m_lastPlayStatusSec = now.sec; lbajardsilogic@0: } else { lbajardsilogic@0: nowStr = now.toText(true).c_str(); lbajardsilogic@0: thenStr = then.toText(true).c_str(); lbajardsilogic@0: remainingStr = (then - now).toText(true).c_str(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)") lbajardsilogic@0: .arg(nowStr).arg(thenStr).arg(remainingStr); lbajardsilogic@0: lbajardsilogic@0: statusBar()->showMessage(m_myStatusMessage); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::globalCentreFrameChanged(unsigned long ) lbajardsilogic@0: { lbajardsilogic@0: if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; lbajardsilogic@0: Pane *p = 0; lbajardsilogic@0: if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return; lbajardsilogic@0: if (!p->getFollowGlobalPan()) return; lbajardsilogic@0: updateVisibleRangeDisplay(p); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::viewCentreFrameChanged(View *v, unsigned long ) lbajardsilogic@0: { lbajardsilogic@0: if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; lbajardsilogic@0: Pane *p = 0; lbajardsilogic@0: if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return; lbajardsilogic@0: if (v == p) updateVisibleRangeDisplay(p); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::viewZoomLevelChanged(View *v, unsigned long , bool ) lbajardsilogic@0: { lbajardsilogic@0: if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return; lbajardsilogic@0: Pane *p = 0; lbajardsilogic@0: if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return; lbajardsilogic@0: if (v == p) updateVisibleRangeDisplay(p); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::updateVisibleRangeDisplay(Pane *p) const lbajardsilogic@0: { lbajardsilogic@0: if (!getMainModel() || !p) { lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool haveSelection = false; lbajardsilogic@0: size_t startFrame = 0, endFrame = 0; lbajardsilogic@0: lbajardsilogic@0: if (m_viewManager && m_viewManager->haveInProgressSelection()) { lbajardsilogic@0: lbajardsilogic@0: bool exclusive = false; lbajardsilogic@0: Selection s = m_viewManager->getInProgressSelection(exclusive); lbajardsilogic@0: lbajardsilogic@0: if (!s.isEmpty()) { lbajardsilogic@0: haveSelection = true; lbajardsilogic@0: startFrame = s.getStartFrame(); lbajardsilogic@0: endFrame = s.getEndFrame(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!haveSelection) { lbajardsilogic@0: startFrame = p->getFirstVisibleFrame(); lbajardsilogic@0: endFrame = p->getLastVisibleFrame(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: RealTime start = RealTime::frame2RealTime lbajardsilogic@0: (startFrame, getMainModel()->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: RealTime end = RealTime::frame2RealTime lbajardsilogic@0: (endFrame, getMainModel()->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: RealTime duration = end - start; lbajardsilogic@0: lbajardsilogic@0: QString startStr, endStr, durationStr; lbajardsilogic@0: startStr = start.toText(true).c_str(); lbajardsilogic@0: endStr = end.toText(true).c_str(); lbajardsilogic@0: durationStr = duration.toText(true).c_str(); lbajardsilogic@0: lbajardsilogic@0: if (haveSelection) { lbajardsilogic@0: m_myStatusMessage = tr("Selection: %1 to %2 (duration %3)") lbajardsilogic@0: .arg(startStr).arg(endStr).arg(durationStr); lbajardsilogic@0: } else { lbajardsilogic@0: m_myStatusMessage = tr("Visible: %1 to %2 (duration %3)") lbajardsilogic@0: .arg(startStr).arg(endStr).arg(durationStr); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: statusBar()->showMessage(m_myStatusMessage); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::outputLevelsChanged(float left, float right) lbajardsilogic@0: { lbajardsilogic@0: m_fader->setPeakLeft(left); lbajardsilogic@0: m_fader->setPeakRight(right); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::sampleRateMismatch(size_t requested, size_t actual, lbajardsilogic@0: bool willResample) lbajardsilogic@0: { lbajardsilogic@0: if (!willResample) { lbajardsilogic@0: //!!! more helpful message needed lbajardsilogic@0: QMessageBox::information lbajardsilogic@0: (this, tr("Sample rate mismatch"), lbajardsilogic@0: tr("The sample rate of this audio file (%1 Hz) does not match\nthe current playback rate (%2 Hz).\n\nThe file will play at the wrong speed and pitch.") lbajardsilogic@0: .arg(requested).arg(actual)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: updateDescriptionLabel(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::audioOverloadPluginDisabled() lbajardsilogic@0: { lbajardsilogic@0: QMessageBox::information lbajardsilogic@0: (this, tr("Audio processing overload"), lbajardsilogic@0: tr("Audio effects plugin auditioning has been disabled\ndue to a processing overload.")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::layerAdded(Layer *) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::layerAdded(" << layer << ")" << std::endl; lbajardsilogic@0: // setupExistingLayersMenu(); lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::layerRemoved(Layer *) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::layerRemoved(" << layer << ")" << std::endl; lbajardsilogic@0: setupExistingLayersMenus(); lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::layerAboutToBeDeleted(Layer *layer) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::layerAboutToBeDeleted(" << layer << ")" << std::endl; lbajardsilogic@0: if (layer == m_timeRulerLayer) { lbajardsilogic@0: // std::cerr << "(this is the time ruler layer)" << std::endl; lbajardsilogic@0: m_timeRulerLayer = 0; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::layerInAView(Layer *layer, bool inAView) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::layerInAView(" << layer << "," << inAView << ")" << std::endl; lbajardsilogic@0: lbajardsilogic@0: // Check whether we need to add or remove model from play source lbajardsilogic@0: Model *model = layer->getModel(); lbajardsilogic@0: if (model) { lbajardsilogic@0: if (inAView) { lbajardsilogic@0: m_playSource->addModel(model); lbajardsilogic@0: } else { lbajardsilogic@0: bool found = false; lbajardsilogic@0: for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { lbajardsilogic@0: Pane *pane = m_paneStack->getPane(i); lbajardsilogic@0: if (!pane) continue; lbajardsilogic@0: for (int j = 0; j < pane->getLayerCount(); ++j) { lbajardsilogic@0: Layer *pl = pane->getLayer(j); lbajardsilogic@0: if (pl && pl->getModel() == model) { lbajardsilogic@0: found = true; lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: if (found) break; lbajardsilogic@0: } lbajardsilogic@0: if (!found) m_playSource->removeModel(model); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: setupExistingLayersMenus(); lbajardsilogic@0: updateMenuStates(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::modelAdded(Model *model) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::modelAdded(" << model << ")" << std::endl; lbajardsilogic@0: m_playSource->addModel(model); lbajardsilogic@0: if (dynamic_cast(model)) { lbajardsilogic@0: setupPaneAndLayerMenus(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::mainModelChanged(WaveFileModel *model) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::mainModelChanged(" << model << ")" << std::endl; lbajardsilogic@0: updateDescriptionLabel(); lbajardsilogic@0: m_panLayer->setModel(model); lbajardsilogic@0: if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate()); lbajardsilogic@0: if (model && !m_playTarget && m_audioOutput) createPlayTarget(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::modelAboutToBeDeleted(Model *model) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::modelAboutToBeDeleted(" << model << ")" << std::endl; lbajardsilogic@0: m_playSource->removeModel(model); lbajardsilogic@0: FFTDataServer::modelAboutToBeDeleted(model); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::modelGenerationFailed(QString transformName) lbajardsilogic@0: { lbajardsilogic@0: QMessageBox::warning lbajardsilogic@0: (this, lbajardsilogic@0: tr("Failed to generate layer"), lbajardsilogic@0: tr("Failed to generate a derived layer.\n\nThe layer transform \"%1\" failed.\n\nThis probably means that a plugin failed to initialise, perhaps because it\nrejected the processing block size that was requested.") lbajardsilogic@0: .arg(transformName), lbajardsilogic@0: QMessageBox::Ok, 0); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::modelRegenerationFailed(QString layerName, QString transformName) lbajardsilogic@0: { lbajardsilogic@0: QMessageBox::warning lbajardsilogic@0: (this, lbajardsilogic@0: tr("Failed to regenerate layer"), lbajardsilogic@0: tr("Failed to regenerate derived layer \"%1\".\n\nThe layer transform \"%2\" failed to run.\n\nThis probably means the layer used a plugin that is not currently available.") lbajardsilogic@0: .arg(layerName).arg(transformName), lbajardsilogic@0: QMessageBox::Ok, 0); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "MainWindow::rightButtonMenuRequested(" << pane << ", " << position.x() << ", " << position.y() << ")" << std::endl; lbajardsilogic@0: m_paneStack->setCurrentPane(pane); lbajardsilogic@0: m_rightButtonMenu->popup(position); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::propertyStacksResized() lbajardsilogic@0: { lbajardsilogic@0: /* lbajardsilogic@0: std::cerr << "MainWindow::propertyStacksResized" << std::endl; lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (pane && m_overview) { lbajardsilogic@0: std::cerr << "Fixed width: " << pane->width() << std::endl; lbajardsilogic@0: m_overview->setFixedWidth(pane->width()); lbajardsilogic@0: } lbajardsilogic@0: */ lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::showLayerTree() lbajardsilogic@0: { lbajardsilogic@0: QTreeView *view = new QTreeView(); lbajardsilogic@0: LayerTreeModel *tree = new LayerTreeModel(m_paneStack); lbajardsilogic@0: view->expand(tree->index(0, 0, QModelIndex())); lbajardsilogic@0: view->setModel(tree); lbajardsilogic@0: view->show(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::pollOSC() lbajardsilogic@0: { lbajardsilogic@0: if (!m_oscQueue || m_oscQueue->isEmpty()) return; lbajardsilogic@0: std::cerr << "MainWindow::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (m_openingAudioFile) return; lbajardsilogic@0: lbajardsilogic@0: OSCMessage message = m_oscQueue->readMessage(); lbajardsilogic@0: lbajardsilogic@0: if (message.getTarget() != 0) { lbajardsilogic@0: return; //!!! for now -- this class is target 0, others not handled yet lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: handleOSCMessage(message); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::handleOSCMessage(const OSCMessage &message) lbajardsilogic@0: { lbajardsilogic@0: std::cerr << "MainWindow::handleOSCMessage: thread id = " lbajardsilogic@0: << QThread::currentThreadId() << std::endl; lbajardsilogic@0: lbajardsilogic@0: // This large function should really be abstracted out. lbajardsilogic@0: lbajardsilogic@0: if (message.getMethod() == "open") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: QString path = message.getArg(0).toString(); lbajardsilogic@0: if (openSomeFile(path, ReplaceMainModel) != FileOpenSucceeded) { lbajardsilogic@0: std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" lbajardsilogic@0: << path.toStdString() << "\"" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: //!!! we really need to spin here and not return until the lbajardsilogic@0: // file has been completely decoded... lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "openadditional") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: QString path = message.getArg(0).toString(); lbajardsilogic@0: if (openSomeFile(path, CreateAdditionalModel) != FileOpenSucceeded) { lbajardsilogic@0: std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" lbajardsilogic@0: << path.toStdString() << "\"" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "recent" || lbajardsilogic@0: message.getMethod() == "last") { lbajardsilogic@0: lbajardsilogic@0: int n = 0; lbajardsilogic@0: if (message.getMethod() == "recent" && lbajardsilogic@0: message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::Int)) { lbajardsilogic@0: n = message.getArg(0).toInt() - 1; lbajardsilogic@0: } lbajardsilogic@0: std::vector recent = m_recentFiles.getRecent(); lbajardsilogic@0: if (n >= 0 && n < int(recent.size())) { lbajardsilogic@0: if (openSomeFile(recent[n], ReplaceMainModel) != FileOpenSucceeded) { lbajardsilogic@0: std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" lbajardsilogic@0: << recent[n].toStdString() << "\"" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "save") { lbajardsilogic@0: lbajardsilogic@0: QString path; lbajardsilogic@0: if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: path = message.getArg(0).toString(); lbajardsilogic@0: if (QFileInfo(path).exists()) { lbajardsilogic@0: std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in save" << std::endl; lbajardsilogic@0: } else { lbajardsilogic@0: saveSessionFile(path); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "export") { lbajardsilogic@0: lbajardsilogic@0: QString path; lbajardsilogic@0: if (getMainModel()) { lbajardsilogic@0: if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: path = message.getArg(0).toString(); lbajardsilogic@0: if (QFileInfo(path).exists()) { lbajardsilogic@0: std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in export" << std::endl; lbajardsilogic@0: } else { lbajardsilogic@0: WavFileWriter writer(path, lbajardsilogic@0: getMainModel()->getSampleRate(), lbajardsilogic@0: getMainModel()->getChannelCount()); lbajardsilogic@0: MultiSelection ms = m_viewManager->getSelection(); lbajardsilogic@0: if (!ms.getSelections().empty()) { lbajardsilogic@0: writer.writeModel(getMainModel(), &ms); lbajardsilogic@0: } else { lbajardsilogic@0: writer.writeModel(getMainModel()); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "jump" || lbajardsilogic@0: message.getMethod() == "play") { lbajardsilogic@0: lbajardsilogic@0: if (getMainModel()) { lbajardsilogic@0: lbajardsilogic@0: unsigned long frame = m_viewManager->getPlaybackFrame(); lbajardsilogic@0: bool selection = false; lbajardsilogic@0: bool play = (message.getMethod() == "play"); lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 1) { lbajardsilogic@0: lbajardsilogic@0: if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "selection") { lbajardsilogic@0: lbajardsilogic@0: selection = true; lbajardsilogic@0: lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "end") { lbajardsilogic@0: lbajardsilogic@0: frame = getMainModel()->getEndFrame(); lbajardsilogic@0: lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::Double)) { lbajardsilogic@0: lbajardsilogic@0: double time = message.getArg(0).toDouble(); lbajardsilogic@0: if (time < 0.0) time = 0.0; lbajardsilogic@0: lbajardsilogic@0: frame = lrint(time * getMainModel()->getSampleRate()); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (frame > getMainModel()->getEndFrame()) { lbajardsilogic@0: frame = getMainModel()->getEndFrame(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (play) { lbajardsilogic@0: m_viewManager->setPlaySelectionMode(selection); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (selection) { lbajardsilogic@0: MultiSelection::SelectionList sl = m_viewManager->getSelections(); lbajardsilogic@0: if (!sl.empty()) { lbajardsilogic@0: frame = sl.begin()->getStartFrame(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_viewManager->setPlaybackFrame(frame); lbajardsilogic@0: lbajardsilogic@0: if (play && !m_playSource->isPlaying()) { lbajardsilogic@0: m_playSource->play(frame); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "stop") { lbajardsilogic@0: lbajardsilogic@0: if (m_playSource->isPlaying()) m_playSource->stop(); lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "loop") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: lbajardsilogic@0: QString str = message.getArg(0).toString(); lbajardsilogic@0: if (str == "on") { lbajardsilogic@0: m_viewManager->setPlayLoopMode(true); lbajardsilogic@0: } else if (str == "off") { lbajardsilogic@0: m_viewManager->setPlayLoopMode(false); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "select" || lbajardsilogic@0: message.getMethod() == "addselect") { lbajardsilogic@0: lbajardsilogic@0: if (getMainModel()) { lbajardsilogic@0: lbajardsilogic@0: int f0 = getMainModel()->getStartFrame(); lbajardsilogic@0: int f1 = getMainModel()->getEndFrame(); lbajardsilogic@0: lbajardsilogic@0: bool done = false; lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 2 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::Double) && lbajardsilogic@0: message.getArg(1).canConvert(QVariant::Double)) { lbajardsilogic@0: lbajardsilogic@0: double t0 = message.getArg(0).toDouble(); lbajardsilogic@0: double t1 = message.getArg(1).toDouble(); lbajardsilogic@0: if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; } lbajardsilogic@0: if (t0 < 0.0) t0 = 0.0; lbajardsilogic@0: if (t1 < 0.0) t1 = 0.0; lbajardsilogic@0: lbajardsilogic@0: f0 = lrint(t0 * getMainModel()->getSampleRate()); lbajardsilogic@0: f1 = lrint(t1 * getMainModel()->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: Layer *layer = 0; lbajardsilogic@0: if (pane) layer = pane->getSelectedLayer(); lbajardsilogic@0: if (layer) { lbajardsilogic@0: size_t resolution; lbajardsilogic@0: layer->snapToFeatureFrame(pane, f0, resolution, lbajardsilogic@0: Layer::SnapLeft); lbajardsilogic@0: layer->snapToFeatureFrame(pane, f1, resolution, lbajardsilogic@0: Layer::SnapRight); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: lbajardsilogic@0: QString str = message.getArg(0).toString(); lbajardsilogic@0: if (str == "none") { lbajardsilogic@0: m_viewManager->clearSelections(); lbajardsilogic@0: done = true; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!done) { lbajardsilogic@0: if (message.getMethod() == "select") { lbajardsilogic@0: m_viewManager->setSelection(Selection(f0, f1)); lbajardsilogic@0: } else { lbajardsilogic@0: m_viewManager->addSelection(Selection(f0, f1)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "add") { lbajardsilogic@0: lbajardsilogic@0: if (getMainModel()) { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() >= 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: lbajardsilogic@0: int channel = -1; lbajardsilogic@0: if (message.getArgCount() == 2 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::Int)) { lbajardsilogic@0: channel = message.getArg(0).toInt(); lbajardsilogic@0: if (channel < -1 || lbajardsilogic@0: channel > int(getMainModel()->getChannelCount())) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::handleOSCMessage: channel " lbajardsilogic@0: << channel << " out of range" << std::endl; lbajardsilogic@0: channel = -1; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString str = message.getArg(0).toString(); lbajardsilogic@0: lbajardsilogic@0: LayerFactory::LayerType type = lbajardsilogic@0: LayerFactory::getInstance()->getLayerTypeForName(str); lbajardsilogic@0: lbajardsilogic@0: if (type == LayerFactory::UnknownLayer) { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::handleOSCMessage: unknown layer " lbajardsilogic@0: << "type " << str.toStdString() << std::endl; lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: PaneConfiguration configuration(type, lbajardsilogic@0: getMainModel(), lbajardsilogic@0: channel); lbajardsilogic@0: lbajardsilogic@0: addPane(configuration, lbajardsilogic@0: tr("Add %1 Pane") lbajardsilogic@0: .arg(LayerFactory::getInstance()-> lbajardsilogic@0: getLayerPresentationName(type))); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "undo") { lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->undo(); lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "redo") { lbajardsilogic@0: lbajardsilogic@0: CommandHistory::getInstance()->redo(); lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "set") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 2 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(1).canConvert(QVariant::Double)) { lbajardsilogic@0: lbajardsilogic@0: QString property = message.getArg(0).toString(); lbajardsilogic@0: float value = (float)message.getArg(1).toDouble(); lbajardsilogic@0: lbajardsilogic@0: if (property == "gain") { lbajardsilogic@0: if (value < 0.0) value = 0.0; lbajardsilogic@0: m_fader->setValue(value); lbajardsilogic@0: if (m_playTarget) m_playTarget->setOutputGain(value); lbajardsilogic@0: } else if (property == "speedup") { lbajardsilogic@0: m_playSpeed->setMappedValue(value); lbajardsilogic@0: } else if (property == "overlays") { lbajardsilogic@0: if (value < 0.5) { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::NoOverlays); lbajardsilogic@0: } else if (value < 1.5) { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); lbajardsilogic@0: } else if (value < 2.5) { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::StandardOverlays); lbajardsilogic@0: } else { lbajardsilogic@0: m_viewManager->setOverlayMode(ViewManager::AllOverlays); lbajardsilogic@0: } lbajardsilogic@0: } else if (property == "zoomwheels") { lbajardsilogic@0: m_viewManager->setZoomWheelsEnabled(value > 0.5); lbajardsilogic@0: } else if (property == "propertyboxes") { lbajardsilogic@0: bool toggle = ((value < 0.5) != lbajardsilogic@0: (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks)); lbajardsilogic@0: if (toggle) togglePropertyBoxes(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: PropertyContainer *container = 0; lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (pane && lbajardsilogic@0: message.getArgCount() == 3 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(1).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(2).canConvert(QVariant::String)) { lbajardsilogic@0: if (message.getArg(0).toString() == "pane") { lbajardsilogic@0: container = pane->getPropertyContainer(0); lbajardsilogic@0: } else if (message.getArg(0).toString() == "layer") { lbajardsilogic@0: container = pane->getSelectedLayer(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: if (container) { lbajardsilogic@0: QString nameString = message.getArg(1).toString(); lbajardsilogic@0: QString valueString = message.getArg(2).toString(); lbajardsilogic@0: container->setPropertyWithCommand(nameString, valueString); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "setcurrent") { lbajardsilogic@0: lbajardsilogic@0: int paneIndex = -1, layerIndex = -1; lbajardsilogic@0: bool wantLayer = false; lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() >= 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::Int)) { lbajardsilogic@0: lbajardsilogic@0: paneIndex = message.getArg(0).toInt() - 1; lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() >= 2 && lbajardsilogic@0: message.getArg(1).canConvert(QVariant::Int)) { lbajardsilogic@0: wantLayer = true; lbajardsilogic@0: layerIndex = message.getArg(1).toInt() - 1; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (paneIndex >= 0 && paneIndex < m_paneStack->getPaneCount()) { lbajardsilogic@0: Pane *pane = m_paneStack->getPane(paneIndex); lbajardsilogic@0: m_paneStack->setCurrentPane(pane); lbajardsilogic@0: if (layerIndex >= 0 && layerIndex < pane->getLayerCount()) { lbajardsilogic@0: Layer *layer = pane->getLayer(layerIndex); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, layer); lbajardsilogic@0: } else if (wantLayer && layerIndex == -1) { lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, 0); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "delete") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: lbajardsilogic@0: QString target = message.getArg(0).toString(); lbajardsilogic@0: lbajardsilogic@0: if (target == "pane") { lbajardsilogic@0: lbajardsilogic@0: deleteCurrentPane(); lbajardsilogic@0: lbajardsilogic@0: } else if (target == "layer") { lbajardsilogic@0: lbajardsilogic@0: deleteCurrentLayer(); lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target.toStdString() << std::endl; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "zoom") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 1) { lbajardsilogic@0: if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "in") { lbajardsilogic@0: zoomIn(); lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "out") { lbajardsilogic@0: zoomOut(); lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "default") { lbajardsilogic@0: zoomDefault(); lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::Double)) { lbajardsilogic@0: double level = message.getArg(0).toDouble(); lbajardsilogic@0: Pane *currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (level < 1.0) level = 1.0; lbajardsilogic@0: if (currentPane) currentPane->setZoomLevel(lrint(level)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "zoomvertical") { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: Layer *layer = 0; lbajardsilogic@0: if (pane && pane->getLayerCount() > 0) { lbajardsilogic@0: layer = pane->getLayer(pane->getLayerCount() - 1); lbajardsilogic@0: } lbajardsilogic@0: int defaultStep = 0; lbajardsilogic@0: int steps = 0; lbajardsilogic@0: if (layer) { lbajardsilogic@0: steps = layer->getVerticalZoomSteps(defaultStep); lbajardsilogic@0: if (message.getArgCount() == 1 && steps > 0) { lbajardsilogic@0: if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "in") { lbajardsilogic@0: int step = layer->getCurrentVerticalZoomStep() + 1; lbajardsilogic@0: if (step < steps) layer->setVerticalZoomStep(step); lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "out") { lbajardsilogic@0: int step = layer->getCurrentVerticalZoomStep() - 1; lbajardsilogic@0: if (step >= 0) layer->setVerticalZoomStep(step); lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "default") { lbajardsilogic@0: layer->setVerticalZoomStep(defaultStep); lbajardsilogic@0: } lbajardsilogic@0: } else if (message.getArgCount() == 2) { lbajardsilogic@0: if (message.getArg(0).canConvert(QVariant::Double) && lbajardsilogic@0: message.getArg(1).canConvert(QVariant::Double)) { lbajardsilogic@0: double min = message.getArg(0).toDouble(); lbajardsilogic@0: double max = message.getArg(1).toDouble(); lbajardsilogic@0: layer->setDisplayExtents(min, max); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "quit") { lbajardsilogic@0: lbajardsilogic@0: m_abandoning = true; lbajardsilogic@0: close(); lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "resize") { lbajardsilogic@0: lbajardsilogic@0: if (message.getArgCount() == 2) { lbajardsilogic@0: lbajardsilogic@0: int width = 0, height = 0; lbajardsilogic@0: lbajardsilogic@0: if (message.getArg(1).canConvert(QVariant::Int)) { lbajardsilogic@0: lbajardsilogic@0: height = message.getArg(1).toInt(); lbajardsilogic@0: lbajardsilogic@0: if (message.getArg(0).canConvert(QVariant::String) && lbajardsilogic@0: message.getArg(0).toString() == "pane") { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (pane) pane->resize(pane->width(), height); lbajardsilogic@0: lbajardsilogic@0: } else if (message.getArg(0).canConvert(QVariant::Int)) { lbajardsilogic@0: lbajardsilogic@0: width = message.getArg(0).toInt(); lbajardsilogic@0: resize(width, height); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (message.getMethod() == "transform") { lbajardsilogic@0: lbajardsilogic@0: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@0: lbajardsilogic@0: if (getMainModel() && lbajardsilogic@0: pane && lbajardsilogic@0: message.getArgCount() == 1 && lbajardsilogic@0: message.getArg(0).canConvert(QVariant::String)) { lbajardsilogic@0: lbajardsilogic@0: TransformId transform = message.getArg(0).toString(); lbajardsilogic@0: lbajardsilogic@0: Layer *newLayer = m_document->createDerivedLayer lbajardsilogic@0: (transform, lbajardsilogic@0: getMainModel(), lbajardsilogic@0: TransformFactory::getInstance()->getDefaultContextForTransform lbajardsilogic@0: (transform, getMainModel()), lbajardsilogic@0: ""); lbajardsilogic@0: lbajardsilogic@0: if (newLayer) { lbajardsilogic@0: m_document->addLayerToView(pane, newLayer); lbajardsilogic@0: m_recentTransforms.add(transform); lbajardsilogic@0: m_paneStack->setCurrentLayer(pane, newLayer); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown or unsupported " lbajardsilogic@0: << "method \"" << message.getMethod().toStdString() lbajardsilogic@0: << "\"" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::preferences() lbajardsilogic@0: { lbajardsilogic@0: if (!m_preferencesDialog.isNull()) { lbajardsilogic@0: m_preferencesDialog->show(); lbajardsilogic@0: m_preferencesDialog->raise(); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_preferencesDialog = new PreferencesDialog(this); lbajardsilogic@0: lbajardsilogic@0: // DeleteOnClose is safe here, because m_preferencesDialog is a lbajardsilogic@0: // QPointer that will be zeroed when the dialog is deleted. We lbajardsilogic@0: // use it in preference to leaving the dialog lying around because lbajardsilogic@0: // if you Cancel the dialog, it resets the preferences state lbajardsilogic@0: // without resetting its own widgets, so its state will be lbajardsilogic@0: // incorrect when next shown unless we construct it afresh lbajardsilogic@0: m_preferencesDialog->setAttribute(Qt::WA_DeleteOnClose); lbajardsilogic@0: lbajardsilogic@0: m_preferencesDialog->show(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::mouseEnteredWidget() lbajardsilogic@0: { lbajardsilogic@0: QWidget *w = dynamic_cast(sender()); lbajardsilogic@0: if (!w) return; lbajardsilogic@0: lbajardsilogic@0: if (w == m_fader) { lbajardsilogic@0: contextHelpChanged(tr("Adjust the master playback level")); lbajardsilogic@0: } else if (w == m_playSpeed) { lbajardsilogic@0: contextHelpChanged(tr("Adjust the master playback speed")); lbajardsilogic@0: } else if (w == m_playSharpen && w->isEnabled()) { lbajardsilogic@0: contextHelpChanged(tr("Toggle transient sharpening for playback time scaling")); lbajardsilogic@0: } else if (w == m_playMono && w->isEnabled()) { lbajardsilogic@0: contextHelpChanged(tr("Toggle mono mode for playback time scaling")); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::mouseLeftWidget() lbajardsilogic@0: { lbajardsilogic@0: contextHelpChanged(""); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::inProgressSelectionChanged() lbajardsilogic@0: { lbajardsilogic@0: Pane *currentPane = 0; lbajardsilogic@0: if (m_paneStack) currentPane = m_paneStack->getCurrentPane(); lbajardsilogic@0: if (currentPane) updateVisibleRangeDisplay(currentPane); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::contextHelpChanged(const QString &s) lbajardsilogic@0: { lbajardsilogic@0: if (s == "" && m_myStatusMessage != "") { lbajardsilogic@0: statusBar()->showMessage(m_myStatusMessage); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: statusBar()->showMessage(s); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::website() lbajardsilogic@0: { lbajardsilogic@0: openHelpUrl(tr("http://www.sonicvisualiser.org/")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::help() lbajardsilogic@0: { lbajardsilogic@0: openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.0/en/")); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::openHelpUrl(QString url) lbajardsilogic@0: { lbajardsilogic@0: // This method mostly lifted from Qt Assistant source code lbajardsilogic@0: lbajardsilogic@0: QProcess *process = new QProcess(this); lbajardsilogic@0: connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater())); lbajardsilogic@0: lbajardsilogic@0: QStringList args; lbajardsilogic@0: lbajardsilogic@0: #ifdef Q_OS_MAC lbajardsilogic@0: args.append(url); lbajardsilogic@0: process->start("open", args); lbajardsilogic@0: #else lbajardsilogic@0: #ifdef Q_OS_WIN32 lbajardsilogic@0: lbajardsilogic@0: QString pf(getenv("ProgramFiles")); lbajardsilogic@0: QString command = pf + QString("\\Internet Explorer\\IEXPLORE.EXE"); lbajardsilogic@0: lbajardsilogic@0: args.append(url); lbajardsilogic@0: process->start(command, args); lbajardsilogic@0: lbajardsilogic@0: #else lbajardsilogic@0: #ifdef Q_WS_X11 lbajardsilogic@0: if (!qgetenv("KDE_FULL_SESSION").isEmpty()) { lbajardsilogic@0: args.append("exec"); lbajardsilogic@0: args.append(url); lbajardsilogic@0: process->start("kfmclient", args); lbajardsilogic@0: } else if (!qgetenv("BROWSER").isEmpty()) { lbajardsilogic@0: args.append(url); lbajardsilogic@0: process->start(qgetenv("BROWSER"), args); lbajardsilogic@0: } else { lbajardsilogic@0: args.append(url); lbajardsilogic@0: process->start("firefox", args); lbajardsilogic@0: } lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: MainWindow::about() lbajardsilogic@0: { lbajardsilogic@0: bool debug = false; lbajardsilogic@0: QString version = "(unknown version)"; lbajardsilogic@0: lbajardsilogic@0: #ifdef BUILD_DEBUG lbajardsilogic@0: debug = true; lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef SV_VERSION lbajardsilogic@0: #ifdef SVNREV lbajardsilogic@0: version = tr("Release %1 : Revision %2").arg(SV_VERSION).arg(SVNREV); lbajardsilogic@0: #else lbajardsilogic@0: version = tr("Release %1").arg(SV_VERSION); lbajardsilogic@0: #endif lbajardsilogic@0: #else lbajardsilogic@0: #ifdef SVNREV lbajardsilogic@0: version = tr("Unreleased : Revision %1").arg(SVNREV); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: QString aboutText; lbajardsilogic@0: lbajardsilogic@0: aboutText += tr("

About Sonic Visualiser

"); lbajardsilogic@0: aboutText += tr("

Sonic Visualiser is a program for viewing and exploring audio data for
semantic music analysis and annotation.

"); lbajardsilogic@0: aboutText += tr("

%1 : %2 configuration

") lbajardsilogic@0: .arg(version) lbajardsilogic@0: .arg(debug ? tr("Debug") : tr("Release")); lbajardsilogic@0: lbajardsilogic@0: #ifndef BUILD_STATIC lbajardsilogic@0: aboutText += tr("
Using Qt v%1 © Trolltech AS").arg(QT_VERSION_STR); lbajardsilogic@0: #else lbajardsilogic@0: #ifdef QT_SHARED lbajardsilogic@0: aboutText += tr("
Using Qt v%1 © Trolltech AS").arg(QT_VERSION_STR); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: #ifdef BUILD_STATIC lbajardsilogic@0: aboutText += tr("

Statically linked"); lbajardsilogic@0: #ifndef QT_SHARED lbajardsilogic@0: aboutText += tr("
With Qt (v%1) © Trolltech AS").arg(QT_VERSION_STR); lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_JACK lbajardsilogic@0: #ifdef JACK_VERSION lbajardsilogic@0: aboutText += tr("
With JACK audio output (v%1) © Paul Davis and Jack O'Quin").arg(JACK_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With JACK audio output © Paul Davis and Jack O'Quin"); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_PORTAUDIO lbajardsilogic@0: aboutText += tr("
With PortAudio audio output © Ross Bencina and Phil Burk"); lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_OGGZ lbajardsilogic@0: #ifdef OGGZ_VERSION lbajardsilogic@0: aboutText += tr("
With Ogg file decoder (oggz v%1, fishsound v%2) © CSIRO Australia").arg(OGGZ_VERSION).arg(FISHSOUND_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With Ogg file decoder © CSIRO Australia"); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_MAD lbajardsilogic@0: #ifdef MAD_VERSION lbajardsilogic@0: aboutText += tr("
With MAD mp3 decoder (v%1) © Underbit Technologies Inc").arg(MAD_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With MAD mp3 decoder © Underbit Technologies Inc"); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_SAMPLERATE lbajardsilogic@0: #ifdef SAMPLERATE_VERSION lbajardsilogic@0: aboutText += tr("
With libsamplerate (v%1) © Erik de Castro Lopo").arg(SAMPLERATE_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With libsamplerate © Erik de Castro Lopo"); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_SNDFILE lbajardsilogic@0: #ifdef SNDFILE_VERSION lbajardsilogic@0: aboutText += tr("
With libsndfile (v%1) © Erik de Castro Lopo").arg(SNDFILE_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With libsndfile © Erik de Castro Lopo"); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_FFTW3F lbajardsilogic@0: #ifdef FFTW3_VERSION lbajardsilogic@0: aboutText += tr("
With FFTW3 (v%1) © Matteo Frigo and MIT").arg(FFTW3_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With FFTW3 © Matteo Frigo and MIT"); lbajardsilogic@0: #endif lbajardsilogic@0: #endif lbajardsilogic@0: #ifdef HAVE_VAMP lbajardsilogic@0: aboutText += tr("
With Vamp plugin support (API v%1, host SDK v%2) © Chris Cannam").arg(VAMP_API_VERSION).arg(VAMP_SDK_VERSION); lbajardsilogic@0: #endif lbajardsilogic@0: aboutText += tr("
With LADSPA plugin support (API v%1) © Richard Furse, Paul Davis, Stefan Westerfeld").arg(LADSPA_VERSION); lbajardsilogic@0: aboutText += tr("
With DSSI plugin support (API v%1) © Chris Cannam, Steve Harris, Sean Bolton").arg(DSSI_VERSION); lbajardsilogic@0: #ifdef HAVE_LIBLO lbajardsilogic@0: #ifdef LIBLO_VERSION lbajardsilogic@0: aboutText += tr("
With liblo Lite OSC library (v%1) © Steve Harris").arg(LIBLO_VERSION); lbajardsilogic@0: #else lbajardsilogic@0: aboutText += tr("
With liblo Lite OSC library © Steve Harris").arg(LIBLO_VERSION); lbajardsilogic@0: #endif lbajardsilogic@0: if (m_oscQueue && m_oscQueue->isOK()) { lbajardsilogic@0: aboutText += tr("

The OSC URL for this instance is: \"%1\"").arg(m_oscQueue->getOSCURL()); lbajardsilogic@0: } lbajardsilogic@0: #endif lbajardsilogic@0: aboutText += "

"; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: aboutText += lbajardsilogic@0: "

Sonic Visualiser Copyright © 2005 - 2007 Chris Cannam and
" lbajardsilogic@0: "Queen Mary, University of London.

" lbajardsilogic@0: "

This program is free software; you can redistribute it and/or
" lbajardsilogic@0: "modify it under the terms of the GNU General Public License as
" lbajardsilogic@0: "published by the Free Software Foundation; either version 2 of the
" lbajardsilogic@0: "License, or (at your option) any later version.
See the file " lbajardsilogic@0: "COPYING included with this distribution for more information.

"; lbajardsilogic@0: lbajardsilogic@0: QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@10: void MainWindow::connectionSettings() lbajardsilogic@10: { lbajardsilogic@10: ConnectionSettings* connection = new ConnectionSettings(m_httpClient); lbajardsilogic@10: } lbajardsilogic@10: lbajardsilogic@2: void MainWindow::styleSetting() lbajardsilogic@2: { lbajardsilogic@2: m_gallery.show(); lbajardsilogic@10: } lbajardsilogic@10: lbajardsilogic@10: bool MainWindow::saveConfigFile() lbajardsilogic@10: { lbajardsilogic@10: QString s; lbajardsilogic@10: lbajardsilogic@10: s += QString("\n"); lbajardsilogic@10: lbajardsilogic@10: s += m_httpClient->toXmlString("\t"); lbajardsilogic@10: lbajardsilogic@10: s += QString("\n"); lbajardsilogic@10: lbajardsilogic@10: QString filePath = TempDirectory::getInstance()->getConfigPath(); lbajardsilogic@10: lbajardsilogic@10: QFile *file = new QFile(filePath); lbajardsilogic@10: lbajardsilogic@10: if (!file->open(QIODevice::WriteOnly)) lbajardsilogic@10: return false; lbajardsilogic@10: lbajardsilogic@10: QTextStream config(file); lbajardsilogic@10: lbajardsilogic@10: config << s; lbajardsilogic@10: lbajardsilogic@10: file->close(); lbajardsilogic@10: lbajardsilogic@10: return true; lbajardsilogic@10: } lbajardsilogic@10: lbajardsilogic@10: void MainWindow::exit() lbajardsilogic@10: { lbajardsilogic@10: closeSession(); lbajardsilogic@10: saveConfigFile(); lbajardsilogic@10: close(); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: QueryResultsWidget * MainWindow::getQueryResultsWidget() lbajardsilogic@21: { lbajardsilogic@21: return m_resultsWidget; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::newEasaierSession() lbajardsilogic@21: { lbajardsilogic@21: if (!checkSaveModified()) return; lbajardsilogic@21: lbajardsilogic@21: closeSession(); lbajardsilogic@21: createDocument(); lbajardsilogic@21: lbajardsilogic@21: Pane *pane = m_paneStack->addPane(); lbajardsilogic@21: lbajardsilogic@21: if (!m_timeRulerLayer) { lbajardsilogic@21: m_timeRulerLayer = m_document->createMainModelLayer lbajardsilogic@21: (LayerFactory::TimeRuler); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: m_document->addLayerToView(pane, m_timeRulerLayer); lbajardsilogic@21: lbajardsilogic@21: Layer *waveform = m_document->createMainModelLayer(LayerFactory::Waveform); lbajardsilogic@21: m_document->addLayerToView(pane, waveform); lbajardsilogic@21: lbajardsilogic@21: m_overview->registerView(pane); lbajardsilogic@21: lbajardsilogic@21: m_EasaierManager->newSession(); lbajardsilogic@21: lbajardsilogic@21: CommandHistory::getInstance()->clear(); lbajardsilogic@21: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@21: documentRestored(); lbajardsilogic@21: updateMenuStates(); lbajardsilogic@21: lbajardsilogic@21: /**************************************************/ lbajardsilogic@21: QWidget *properties = 0; lbajardsilogic@21: lbajardsilogic@21: properties = new PropertyStack(0, m_paneStack->getCurrentPane() ); lbajardsilogic@21: //properties->show(); lbajardsilogic@21: m_toolBox->removeItem(0); lbajardsilogic@21: m_toolBox->insertItem(0,"Layers", properties); lbajardsilogic@21: lbajardsilogic@21: /*connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), lbajardsilogic@21: this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); lbajardsilogic@21: properties->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); lbajardsilogic@21: */ lbajardsilogic@21: lbajardsilogic@21: /*************************************************/ lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::openEasaierSession() lbajardsilogic@21: { lbajardsilogic@21: if (!checkSaveModified()) return; lbajardsilogic@21: lbajardsilogic@21: QString orig = m_audioFile; lbajardsilogic@21: if (orig == "") orig = "."; lbajardsilogic@21: else orig = QFileInfo(orig).absoluteDir().canonicalPath(); lbajardsilogic@21: lbajardsilogic@21: QString path = QFileDialog::getOpenFileName lbajardsilogic@21: (this, tr("Select a session file"), orig, lbajardsilogic@21: tr("Sound Access session files (*.xml)\nAll files (*.*)")); lbajardsilogic@21: lbajardsilogic@21: if (path.isEmpty()) return; lbajardsilogic@21: lbajardsilogic@21: if (!(QFileInfo(path).exists() && lbajardsilogic@21: QFileInfo(path).isFile() && lbajardsilogic@21: QFileInfo(path).isReadable())) { lbajardsilogic@21: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@21: tr("File \"%1\" does not exist or is not a readable file").arg(path)); lbajardsilogic@21: return; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: if (!openEasaierSessionFile(path)) { lbajardsilogic@21: QMessageBox::critical(this, tr("Failed to open file"), lbajardsilogic@21: tr("Session file \"%1\" could not be opened").arg(path)); lbajardsilogic@21: } lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: bool MainWindow::openEasaierSessionFile(QString path) lbajardsilogic@21: { lbajardsilogic@21: QFile file(path); lbajardsilogic@21: if (!file.open(QIODevice::ReadOnly)) { lbajardsilogic@21: std::cerr << "Failed to open session file \"" << path.toStdString() lbajardsilogic@21: << "\": " << file.errorString().toStdString() << std::endl; lbajardsilogic@21: return false; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: QString error; lbajardsilogic@21: closeSession(); lbajardsilogic@21: createDocument(); lbajardsilogic@21: lbajardsilogic@21: PaneCallback callback(this); lbajardsilogic@21: m_viewManager->clearSelections(); lbajardsilogic@21: lbajardsilogic@21: ESFileReader reader(m_document, callback); lbajardsilogic@21: QXmlInputSource inputSource(&file); lbajardsilogic@21: reader.parse(inputSource); lbajardsilogic@21: lbajardsilogic@21: if (!reader.isOK()) { lbajardsilogic@21: error = tr("Easaier XML file read error:\n%1").arg(reader.getErrorString()); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: file.close(); lbajardsilogic@21: lbajardsilogic@21: bool ok = (error == ""); lbajardsilogic@21: lbajardsilogic@21: if (ok) { lbajardsilogic@21: setWindowTitle(tr("Sound Access: %1") lbajardsilogic@21: .arg(QFileInfo(path).fileName())); lbajardsilogic@21: m_sessionFile = path; lbajardsilogic@21: setupMenus(); lbajardsilogic@21: CommandHistory::getInstance()->clear(); lbajardsilogic@21: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@21: m_documentModified = false; lbajardsilogic@21: updateMenuStates(); lbajardsilogic@21: } else { lbajardsilogic@21: setWindowTitle(tr("Sound Access")); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: m_EasaierManager->openSession(m_document); lbajardsilogic@21: lbajardsilogic@21: /**************************************************/ lbajardsilogic@21: QWidget *properties = 0; lbajardsilogic@21: lbajardsilogic@21: properties = new PropertyStack(0, m_paneStack->getCurrentPane() ); lbajardsilogic@21: //properties->show(); lbajardsilogic@21: m_toolBox->removeItem(0); lbajardsilogic@21: m_toolBox->insertItem(0,"Layers", properties); lbajardsilogic@21: lbajardsilogic@21: /*connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), lbajardsilogic@21: this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); lbajardsilogic@21: properties->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); lbajardsilogic@21: */ lbajardsilogic@21: lbajardsilogic@21: /*************************************************/ lbajardsilogic@21: lbajardsilogic@21: lbajardsilogic@21: return ok; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::saveEasaierSession() lbajardsilogic@21: { lbajardsilogic@21: if (m_sessionFile != "") { lbajardsilogic@21: if (!saveEasaierSessionFile(m_sessionFile)) { lbajardsilogic@21: QMessageBox::critical(this, tr("Failed to save file"), lbajardsilogic@21: tr("Session file \"%1\" could not be saved.").arg(m_sessionFile)); lbajardsilogic@21: } else { lbajardsilogic@21: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@21: documentRestored(); lbajardsilogic@21: } lbajardsilogic@21: } else { lbajardsilogic@21: saveEasaierSessionAs(); lbajardsilogic@21: } lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void lbajardsilogic@21: MainWindow::saveEasaierSessionAs() lbajardsilogic@21: { lbajardsilogic@21: QString orig = m_audioFile; lbajardsilogic@21: if (orig == "") orig = "."; lbajardsilogic@21: else orig = QFileInfo(orig).absoluteDir().canonicalPath(); lbajardsilogic@21: lbajardsilogic@21: QString path; lbajardsilogic@21: bool good = false; lbajardsilogic@21: lbajardsilogic@21: while (!good) { lbajardsilogic@21: lbajardsilogic@21: path = QFileDialog::getSaveFileName lbajardsilogic@21: (this, tr("Select a file to save to"), orig, lbajardsilogic@21: tr("Sound Access session files (*.xml)\nAll files (*.*)"), 0, lbajardsilogic@21: QFileDialog::DontConfirmOverwrite); // we'll do that lbajardsilogic@21: lbajardsilogic@21: if (path.isEmpty()) return; lbajardsilogic@21: lbajardsilogic@21: if (!path.endsWith(".xml")) path = path + ".xml"; lbajardsilogic@21: lbajardsilogic@21: QFileInfo fi(path); lbajardsilogic@21: lbajardsilogic@21: if (fi.isDir()) { lbajardsilogic@21: QMessageBox::critical(this, tr("Directory selected"), lbajardsilogic@21: tr("File \"%1\" is a directory").arg(path)); lbajardsilogic@21: continue; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: if (fi.exists()) { lbajardsilogic@21: if (QMessageBox::question(this, tr("File exists"), lbajardsilogic@21: tr("The file \"%1\" already exists.\nDo you want to overwrite it?").arg(path), lbajardsilogic@21: QMessageBox::Ok, lbajardsilogic@21: QMessageBox::Cancel) == QMessageBox::Ok) { lbajardsilogic@21: good = true; lbajardsilogic@21: } else { lbajardsilogic@21: continue; lbajardsilogic@21: } lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: good = true; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: if (!saveEasaierSessionFile(path)) { lbajardsilogic@21: QMessageBox::critical(this, tr("Failed to save file"), lbajardsilogic@21: tr("Session file \"%1\" could not be saved.").arg(m_sessionFile)); lbajardsilogic@21: } else { lbajardsilogic@21: setWindowTitle(tr("Sound Access: %1") lbajardsilogic@21: .arg(QFileInfo(path).fileName())); lbajardsilogic@21: m_sessionFile = path; lbajardsilogic@21: CommandHistory::getInstance()->documentSaved(); lbajardsilogic@21: documentRestored(); lbajardsilogic@21: } lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: bool MainWindow::saveEasaierSessionFile(QString path) lbajardsilogic@21: { lbajardsilogic@21: QFile file(path); lbajardsilogic@21: lbajardsilogic@21: if (!file.open(QIODevice::WriteOnly)) { lbajardsilogic@21: std::cerr << "Failed to open session file \"" << path.toStdString() lbajardsilogic@21: << "\" for writing: " lbajardsilogic@21: << file.errorString().toStdString() << std::endl; lbajardsilogic@21: return false; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); lbajardsilogic@21: lbajardsilogic@21: QTextStream out(&file); lbajardsilogic@21: toEasaierXml(out); lbajardsilogic@21: out.flush(); lbajardsilogic@21: lbajardsilogic@21: QApplication::restoreOverrideCursor(); lbajardsilogic@21: lbajardsilogic@21: if (file.error()) { lbajardsilogic@21: QMessageBox::critical(this, tr("Failed to write file"), lbajardsilogic@21: tr("Failed to write to file \"%1\": %2") lbajardsilogic@21: .arg(path).arg(file.errorString())); lbajardsilogic@21: file.close(); lbajardsilogic@21: return false; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: file.close(); lbajardsilogic@21: return true; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::importEasaierLayer(const QString& filename) lbajardsilogic@21: { lbajardsilogic@21: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@21: m_EasaierManager->importMetadata(filename, pane); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::importEasaierFile(const QString& filename) lbajardsilogic@21: { lbajardsilogic@21: int i = m_paneStack->getPaneCount(); lbajardsilogic@21: while (i > 0) { lbajardsilogic@21: lbajardsilogic@21: Pane *pane = m_paneStack->getPane(i - 1); lbajardsilogic@21: lbajardsilogic@21: int j= pane->getLayerCount(); lbajardsilogic@21: while (j > 0) { lbajardsilogic@21: m_document->removeLayerFromView(pane, pane->getLayer(j - 1)); lbajardsilogic@21: j--; lbajardsilogic@21: } lbajardsilogic@21: i--; lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: delete m_document; lbajardsilogic@21: lbajardsilogic@21: createDocument(); lbajardsilogic@21: Pane *pane = m_paneStack->getCurrentPane(); lbajardsilogic@21: lbajardsilogic@21: if (!m_timeRulerLayer) { lbajardsilogic@21: m_timeRulerLayer = m_document->createMainModelLayer(LayerFactory::TimeRuler); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: m_document->addLayerToView(pane, m_timeRulerLayer); lbajardsilogic@21: lbajardsilogic@21: Layer *waveform = m_document->createMainModelLayer(LayerFactory::Waveform); lbajardsilogic@21: m_document->addLayerToView(pane, waveform); lbajardsilogic@21: lbajardsilogic@21: m_document->setAudioSourceInfoFileName(filename); lbajardsilogic@21: m_EasaierManager->openAudioInfoFile(m_document); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::queryModelLoaded(QueryModel* queryModel) lbajardsilogic@21: { lbajardsilogic@21: if (m_searchWidget) lbajardsilogic@21: m_searchWidget->displayQuerymodel(queryModel); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::audioSourceInfoAdded(AudioSourceInfoModel * info) lbajardsilogic@21: { lbajardsilogic@21: if (m_infoWidget) lbajardsilogic@21: m_infoWidget->displayAudioSourceInfo(info); lbajardsilogic@21: lbajardsilogic@21: m_qtabwidget->setCurrentIndex(Info); lbajardsilogic@21: } lbajardsilogic@21: lbajardsilogic@21: void MainWindow::queryDatabase() lbajardsilogic@21: { lbajardsilogic@21: QString themeName = sender()->objectName(); lbajardsilogic@21: lbajardsilogic@21: m_EasaierManager->queryDatabase(themeName); lbajardsilogic@21: lbajardsilogic@21: m_qtabwidget->setCurrentIndex(Result); lbajardsilogic@2: }