# HG changeset patch # User Chris Cannam # Date 1305635595 -3600 # Node ID db0c86c4e5e9b134f4a71d39e5b27d39f6732a39 # Parent ee927c1b7941df580e6bb18febfcec464f80eacb# Parent 5f22e0bbe4ba254dfb2d2c262d0539b174694457 Merge from the default branch diff -r 5f22e0bbe4ba -r db0c86c4e5e9 main/MainWindow.cpp --- a/main/MainWindow.cpp Wed May 11 11:05:10 2011 +0100 +++ b/main/MainWindow.cpp Tue May 17 13:33:15 2011 +0100 @@ -30,6 +30,7 @@ #include "framework/TransformUserConfigurator.h" #include "view/ViewManager.h" #include "base/Preferences.h" +#include "base/ResourceFinder.h" #include "layer/WaveformLayer.h" #include "layer/TimeRulerLayer.h" #include "layer/TimeInstantLayer.h" @@ -112,6 +113,8 @@ #include #include #include +#include +#include #include #include @@ -137,6 +140,7 @@ m_sliceMenu(0), m_recentFilesMenu(0), m_recentTransformsMenu(0), + m_templatesMenu(0), m_rightButtonMenu(0), m_rightButtonLayerMenu(0), m_rightButtonTransformsMenu(0), @@ -158,7 +162,8 @@ m_preferencesDialog(0), m_layerTreeDialog(0), m_activityLog(new ActivityLog()), - m_keyReference(new KeyReference()) + m_keyReference(new KeyReference()), + m_templateWatcher(0) { Profiler profiler("MainWindow::MainWindow"); @@ -388,7 +393,7 @@ m_keyReference->registerShortcut(action); menu->addAction(action); toolbar->addAction(action); - +/* icon = il.load("fileopensession"); action = new QAction(icon, tr("&Open Session..."), this); action->setShortcut(tr("Ctrl+O")); @@ -396,14 +401,51 @@ connect(action, SIGNAL(triggered()), this, SLOT(openSession())); m_keyReference->registerShortcut(action); menu->addAction(action); - +*/ icon = il.load("fileopen"); icon.addPixmap(il.loadPixmap("fileopen-22")); - action = new QAction(icon, tr("&Open..."), this); + action->setShortcut(tr("Ctrl+O")); action->setStatusTip(tr("Open a session file, audio file, or layer")); connect(action, SIGNAL(triggered()), this, SLOT(openSomething())); toolbar->addAction(action); + menu->addAction(action); + + // We want this one to go on the toolbar now, if we add it at all, + // but on the menu later + QAction *iaction = new QAction(tr("&Import More Audio..."), this); + iaction->setShortcut(tr("Ctrl+I")); + iaction->setStatusTip(tr("Import an extra audio file into a new pane")); + connect(iaction, SIGNAL(triggered()), this, SLOT(importMoreAudio())); + connect(this, SIGNAL(canImportMoreAudio(bool)), iaction, SLOT(setEnabled(bool))); + m_keyReference->registerShortcut(iaction); + + action = new QAction(tr("Open Lo&cation..."), this); + action->setShortcut(tr("Ctrl+Shift+O")); + action->setStatusTip(tr("Open or import a file from a remote URL")); + connect(action, SIGNAL(triggered()), this, SLOT(openLocation())); + m_keyReference->registerShortcut(action); + menu->addAction(action); + + m_recentFilesMenu = menu->addMenu(tr("Open &Recent")); + m_recentFilesMenu->setTearOffEnabled(true); + setupRecentFilesMenu(); + connect(&m_recentFiles, SIGNAL(recentChanged()), + this, SLOT(setupRecentFilesMenu())); + + menu->addSeparator(); + + QString templatesMenuLabel = tr("Session Template for Audio Files"); + +#ifdef Q_OS_MAC + // Normally this menu will go next to Preferences on the File + // menu. But on OS/X Preferences doesn't appear on the File menu, + // so we put it next to the other Session stuff instead. + m_templatesMenu = menu->addMenu(templatesMenuLabel); + m_templatesMenu->setTearOffEnabled(true); + setupTemplatesMenu(); + menu->addSeparator(); +#endif icon = il.load("filesave"); icon.addPixmap(il.loadPixmap("filesave-22")); @@ -427,6 +469,7 @@ menu->addSeparator(); +/* icon = il.load("fileopenaudio"); action = new QAction(icon, tr("&Import Audio File..."), this); action->setShortcut(tr("Ctrl+I")); @@ -434,14 +477,10 @@ connect(action, SIGNAL(triggered()), this, SLOT(importAudio())); m_keyReference->registerShortcut(action); menu->addAction(action); - - action = new QAction(tr("Import Secondary Audio File..."), this); - action->setShortcut(tr("Ctrl+Shift+I")); - action->setStatusTip(tr("Import an extra audio file as a separate layer")); - connect(action, SIGNAL(triggered()), this, SLOT(importMoreAudio())); - connect(this, SIGNAL(canImportMoreAudio(bool)), action, SLOT(setEnabled(bool))); - m_keyReference->registerShortcut(action); - menu->addAction(action); +*/ + + // the Import action we made earlier + menu->addAction(iaction); action = new QAction(tr("&Export Audio File..."), this); action->setStatusTip(tr("Export selection as an audio file")); @@ -475,22 +514,13 @@ menu->addSeparator(); - action = new QAction(tr("Open Lo&cation..."), this); - action->setShortcut(tr("Ctrl+Shift+O")); - action->setStatusTip(tr("Open or import a file from a remote URL")); - connect(action, SIGNAL(triggered()), this, SLOT(openLocation())); - m_keyReference->registerShortcut(action); - menu->addAction(action); - - menu->addSeparator(); - - m_recentFilesMenu = menu->addMenu(tr("&Recent Files")); - m_recentFilesMenu->setTearOffEnabled(true); - setupRecentFilesMenu(); - connect(&m_recentFiles, SIGNAL(recentChanged()), - this, SLOT(setupRecentFilesMenu())); - - menu->addSeparator(); +#ifndef Q_OS_MAC + // See note for Q_OS_MAC alternative above + m_templatesMenu = menu->addMenu(templatesMenuLabel); + m_templatesMenu->setTearOffEnabled(true); + setupTemplatesMenu(); +#endif + action = new QAction(tr("&Preferences..."), this); action->setStatusTip(tr("Adjust the application preferences")); connect(action, SIGNAL(triggered()), this, SLOT(preferences())); @@ -1617,6 +1647,86 @@ } void +MainWindow::setupTemplatesMenu() +{ + m_templatesMenu->clear(); + + QSettings settings; + settings.beginGroup("MainWindow"); + QString deflt = settings.value("sessiontemplate", "").toString(); + setDefaultSessionTemplate(deflt == "" ? "default" : deflt); + + QActionGroup *templatesGroup = new QActionGroup(this); + + bool haveFoundDefault = false; + + QAction *defaultAction = new QAction(tr("Default"), this); + defaultAction->setObjectName("default"); + connect(defaultAction, SIGNAL(triggered()), this, SLOT(changeTemplate())); + defaultAction->setCheckable(true); + if (deflt == "" || deflt == "default") { + defaultAction->setChecked(true); + haveFoundDefault = true; + } + templatesGroup->addAction(defaultAction); + m_templatesMenu->addAction(defaultAction); + + m_templatesMenu->addSeparator(); + + QAction *action = 0; + + QStringList templates = ResourceFinder().getResourceFiles("templates", "svt"); + + bool havePersonal = false; + + // (ordered by name) + std::set byName; + foreach (QString t, templates) { + if (!t.startsWith(":")) havePersonal = true; + byName.insert(QFileInfo(t).baseName()); + } + + foreach (QString t, byName) { + if (t.toLower() == "default") continue; + action = new QAction(t, this); + connect(action, SIGNAL(triggered()), this, SLOT(changeTemplate())); + action->setCheckable(true); + if (deflt == t) { + action->setChecked(true); + haveFoundDefault = true; + } + templatesGroup->addAction(action); + m_templatesMenu->addAction(action); + } + + if (!templates.empty()) m_templatesMenu->addSeparator(); + + if (!haveFoundDefault) { + defaultAction->setChecked(true); + setDefaultSessionTemplate("default"); + settings.setValue("sessiontemplate", ""); + } + + settings.endGroup(); + + action = new QAction(tr("Save Template from Current Session..."), this); + connect(action, SIGNAL(triggered()), this, SLOT(saveSessionAsTemplate())); + m_templatesMenu->addAction(action); + + action = new QAction(tr("Manage Saved Templates"), this); + connect(action, SIGNAL(triggered()), this, SLOT(manageSavedTemplates())); + action->setEnabled(havePersonal); + m_templatesMenu->addAction(action); + + if (!m_templateWatcher) { + m_templateWatcher = new QFileSystemWatcher(this); + m_templateWatcher->addPath(ResourceFinder().getResourceSaveDir("templates")); + connect(m_templateWatcher, SIGNAL(directoryChanged(const QString &)), + this, SLOT(setupTemplatesMenu())); + } +} + +void MainWindow::setupRecentTransformsMenu() { m_recentTransformsMenu->clear(); @@ -2149,7 +2259,7 @@ QString path = getOpenFileName(FileFinder::AudioFile); if (path != "") { - if (openAudio(path, ReplaceMainModel) == FileOpenFailed) { + if (openAudio(path, ReplaceSession) == FileOpenFailed) { emit hideSplash(); QMessageBox::critical(this, tr("Failed to open file"), tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); @@ -2673,7 +2783,7 @@ if (path.isEmpty()) return; - FileOpenStatus status = open(path, AskUser); + FileOpenStatus status = open(path, ReplaceSession); if (status == FileOpenFailed) { emit hideSplash(); @@ -2705,7 +2815,7 @@ if (text.isEmpty()) return; - FileOpenStatus status = open(text); + FileOpenStatus status = open(text, AskUser); if (status == FileOpenFailed) { emit hideSplash(); @@ -2733,7 +2843,7 @@ QString path = action->text(); if (path == "") return; - FileOpenStatus status = open(path); + FileOpenStatus status = open(path, ReplaceSession); if (status == FileOpenFailed) { emit hideSplash(); @@ -2747,6 +2857,68 @@ } void +MainWindow::changeTemplate() +{ + QObject *s = sender(); + QAction *action = qobject_cast(s); + + if (!action) { + std::cerr << "WARNING: MainWindow::changeTemplate: sender is not an action" + << std::endl; + return; + } + + QString n = action->objectName(); + if (n == "") n = action->text(); + + if (n == "") { + std::cerr << "WARNING: MainWindow::changeTemplate: sender has no name" + << std::endl; + return; + } + + setDefaultSessionTemplate(n); + + QSettings settings; + settings.beginGroup("MainWindow"); + settings.setValue("sessiontemplate", n); + settings.endGroup(); +} + +void +MainWindow::saveSessionAsTemplate() +{ + QString name = QInputDialog::getText + (this, tr("Enter template name"), + tr("Please enter a name for the saved template:")); + if (name == "") return; + + name.replace(QRegExp("[^\\w\\s\\.\"'-]"), "_"); + + ResourceFinder rf; + QString dir = rf.getResourceSaveDir("templates"); + QString filename = QString("%1/%2.svt").arg(dir).arg(name); + if (QFile(filename).exists()) { + if (QMessageBox::warning(this, + tr("Template file exists"), + tr("Template file exists

The template \"%1\" already exists.
Overwrite it?").arg(name), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel) != QMessageBox::Ok) { + return; + } + } + + saveSessionTemplate(filename); +} + +void +MainWindow::manageSavedTemplates() +{ + ResourceFinder rf; + QDesktopServices::openUrl("file:" + rf.getResourceSaveDir("templates")); +} + +void MainWindow::paneAdded(Pane *pane) { if (m_overview) m_overview->registerView(pane); diff -r 5f22e0bbe4ba -r db0c86c4e5e9 main/MainWindow.h --- a/main/MainWindow.h Wed May 11 11:05:10 2011 +0100 +++ b/main/MainWindow.h Tue May 17 13:33:15 2011 +0100 @@ -58,6 +58,7 @@ class KeyReference; class Labeller; class ActivityLog; +class QFileSystemWatcher; class MainWindow : public MainWindowBase { @@ -83,6 +84,7 @@ virtual void openSomething(); virtual void openLocation(); virtual void openRecentFile(); + virtual void changeTemplate(); virtual void exportAudio(); virtual void importLayer(); virtual void exportLayer(); @@ -140,6 +142,7 @@ virtual void setupRecentFilesMenu(); virtual void setupRecentTransformsMenu(); + virtual void setupTemplatesMenu(); virtual void playSpeedChanged(int); virtual void playSoloToggled(); @@ -169,6 +172,9 @@ virtual void midiEventsAvailable(); virtual void playStatusChanged(bool); + virtual void saveSessionAsTemplate(); + virtual void manageSavedTemplates(); + virtual void website(); virtual void help(); virtual void about(); @@ -190,6 +196,7 @@ QMenu *m_sliceMenu; QMenu *m_recentFilesMenu; QMenu *m_recentTransformsMenu; + QMenu *m_templatesMenu; QMenu *m_rightButtonMenu; QMenu *m_rightButtonLayerMenu; QMenu *m_rightButtonTransformsMenu; @@ -221,6 +228,8 @@ ActivityLog *m_activityLog; KeyReference *m_keyReference; + QFileSystemWatcher *m_templateWatcher; + struct LayerConfiguration { LayerConfiguration(LayerFactory::LayerType _layer = LayerFactory::TimeRuler, diff -r 5f22e0bbe4ba -r db0c86c4e5e9 main/main.cpp --- a/main/main.cpp Wed May 11 11:05:10 2011 +0100 +++ b/main/main.cpp Tue May 17 13:33:15 2011 +0100 @@ -468,7 +468,7 @@ } if (status != MainWindow::FileOpenSucceeded) { if (!haveMainModel) { - status = m_mainWindow->open(path, MainWindow::ReplaceMainModel); + status = m_mainWindow->open(path, MainWindow::ReplaceSession); if (status == MainWindow::FileOpenSucceeded) { haveMainModel = true; } diff -r 5f22e0bbe4ba -r db0c86c4e5e9 samples/silent.wav Binary file samples/silent.wav has changed diff -r 5f22e0bbe4ba -r db0c86c4e5e9 sonic-visualiser.qrc --- a/sonic-visualiser.qrc Wed May 11 11:05:10 2011 +0100 +++ b/sonic-visualiser.qrc Tue May 17 13:33:15 2011 +0100 @@ -100,10 +100,15 @@ samples/kick.wav samples/organ.wav samples/piano.wav + samples/silent.wav samples/snare.wav samples/stick.wav samples/strike.wav samples/tap.wav + templates/default.svt + templates/Scrolling Waveforms.svt + templates/Spectrograms.svt + templates/Waveform and Melodic Range Spectrogram.svt i18n/sonic-visualiser_ru.qm i18n/sonic-visualiser_en_GB.qm i18n/sonic-visualiser_en_US.qm diff -r 5f22e0bbe4ba -r db0c86c4e5e9 templates/Scrolling Waveforms.svt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/Scrolling Waveforms.svt Tue May 17 13:33:15 2011 +0100 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 5f22e0bbe4ba -r db0c86c4e5e9 templates/Spectrograms.svt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/Spectrograms.svt Tue May 17 13:33:15 2011 +0100 @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 5f22e0bbe4ba -r db0c86c4e5e9 templates/Waveform and Melodic Range Spectrogram.svt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/Waveform and Melodic Range Spectrogram.svt Tue May 17 13:33:15 2011 +0100 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 5f22e0bbe4ba -r db0c86c4e5e9 templates/default.svt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/default.svt Tue May 17 13:33:15 2011 +0100 @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +