# HG changeset patch # User Chris Cannam # Date 1192029482 0 # Node ID 4e030ebb6b3606dd7f167a0e588aa05d140660b0 # Parent d3477f673fb45fb8aadd3b9221b4da8995eef27b * Make it possible to drop audio files, layer files, session files and images onto SV panes. Need to do a bit more work on where we expect the dropped file to go, particularly in the case of audio files -- at the moment they're always opened in new panes, but it may be better to by default replace whatever is in the target pane. diff -r d3477f673fb4 -r 4e030ebb6b36 main/MainWindow.cpp --- a/main/MainWindow.cpp Wed Oct 10 10:22:34 2007 +0000 +++ b/main/MainWindow.cpp Wed Oct 10 15:18:02 2007 +0000 @@ -34,6 +34,7 @@ #include "layer/Colour3DPlotLayer.h" #include "layer/SliceLayer.h" #include "layer/SliceableLayer.h" +#include "layer/ImageLayer.h" #include "widgets/Fader.h" #include "view/Overview.h" #include "widgets/PropertyBox.h" @@ -211,6 +212,10 @@ this, SLOT(propertyStacksResized())); connect(m_paneStack, SIGNAL(contextHelpChanged(const QString &)), this, SLOT(contextHelpChanged(const QString &))); + connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QStringList)), + this, SLOT(paneDropAccepted(Pane *, QStringList))); + connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QString)), + this, SLOT(paneDropAccepted(Pane *, QString))); scroll->setWidget(m_paneStack); @@ -2529,7 +2534,7 @@ if (path != "") { if (openAudioFile(path, ReplaceMainModel) == FileOpenFailed) { QMessageBox::critical(this, tr("Failed to open file"), - tr("Audio file \"%1\" could not be opened").arg(path)); + tr("File open failed
Audio file \"%1\" could not be opened").arg(path)); } } } @@ -2542,7 +2547,7 @@ if (path != "") { if (openAudioFile(path, CreateAdditionalModel) == FileOpenFailed) { QMessageBox::critical(this, tr("Failed to open file"), - tr("Audio file \"%1\" could not be opened").arg(path)); + tr("File open failed
Audio file \"%1\" could not be opened").arg(path)); } } } @@ -2675,10 +2680,15 @@ if (path != "") { - if (openLayerFile(path) == FileOpenFailed) { + FileOpenStatus status = openLayerFile(path); + + if (status == FileOpenFailed) { QMessageBox::critical(this, tr("Failed to open file"), - tr("File %1 could not be opened.").arg(path)); + tr("File open failed
Layer file %1 could not be opened.").arg(path)); return; + } else if (status == FileOpenWrongMode) { + QMessageBox::critical(this, tr("Failed to open file"), + tr("Audio required
Please load at least one audio file before importing annotation data"));
}
}
}
@@ -2697,13 +2707,13 @@
if (!pane) {
// shouldn't happen, as the menu action should have been disabled
std::cerr << "WARNING: MainWindow::openLayerFile: no current pane" << std::endl;
- return FileOpenFailed;
+ return FileOpenWrongMode;
}
if (!getMainModel()) {
// shouldn't happen, as the menu action should have been disabled
std::cerr << "WARNING: MainWindow::openLayerFile: No main model -- hence no default sample rate available" << std::endl;
- return FileOpenFailed;
+ return FileOpenWrongMode;
}
bool realFile = (location == path);
@@ -2744,22 +2754,30 @@
} else {
- Model *model = DataFileReaderFactory::load(path, getMainModel()->getSampleRate());
+ try {
+
+ Model *model = DataFileReaderFactory::load
+ (path, getMainModel()->getSampleRate());
- if (model) {
-
- Layer *newLayer = m_document->createImportedLayer(model);
-
- if (newLayer) {
-
- m_document->addLayerToView(pane, newLayer);
- m_recentFiles.addFile(location);
-
- if (realFile) {
- registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
+ if (model) {
+
+ Layer *newLayer = m_document->createImportedLayer(model);
+
+ if (newLayer) {
+
+ m_document->addLayerToView(pane, newLayer);
+ m_recentFiles.addFile(location);
+
+ if (realFile) {
+ registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
+ }
+
+ return FileOpenSucceeded;
}
-
- return FileOpenSucceeded;
+ }
+ } catch (DataFileReaderFactory::Exception e) {
+ if (e == DataFileReaderFactory::ImportCancelled) {
+ return FileOpenCancelled;
}
}
}
@@ -2767,6 +2785,62 @@
return FileOpenFailed;
}
+MainWindow::FileOpenStatus
+MainWindow::openImageFile(QString path)
+{
+ return openImageFile(path, path);
+}
+
+MainWindow::FileOpenStatus
+MainWindow::openImageFile(QString path, QString location)
+{
+ Pane *pane = m_paneStack->getCurrentPane();
+
+ if (!pane) {
+ // shouldn't happen, as the menu action should have been disabled
+ std::cerr << "WARNING: MainWindow::openImageFile: no current pane" << std::endl;
+ return FileOpenWrongMode;
+ }
+
+ if (!m_document->getMainModel()) {
+ return FileOpenWrongMode;
+ }
+
+ bool newLayer = false;
+
+ ImageLayer *il = dynamic_cast Could not open an audio device for playback. Audio playback will not be available during this session."),
QMessageBox::Ok);
}
connect(m_fader, SIGNAL(valueChanged(float)),
@@ -3264,7 +3338,7 @@
if (openSessionFile(path) == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open file"),
- tr("Session file \"%1\" could not be opened").arg(path));
+ tr("File open failed Session file \"%1\" could not be opened").arg(path));
}
}
@@ -3275,36 +3349,18 @@
if (orig == "") orig = ".";
else orig = QFileInfo(orig).absoluteDir().canonicalPath();
- bool canImportLayer = (getMainModel() != 0 &&
- m_paneStack != 0 &&
- m_paneStack->getCurrentPane() != 0);
-
QString path = getOpenFileName(FileFinder::AnyFile);
if (path.isEmpty()) return;
- if (path.endsWith(".sv")) {
-
- if (!checkSaveModified()) return;
-
- if (openSessionFile(path) == FileOpenFailed) {
- QMessageBox::critical(this, tr("Failed to open file"),
- tr("Session file \"%1\" could not be opened").arg(path));
- }
-
- } else {
-
- if (openPlaylistFile(path, AskUser) == FileOpenFailed) {
-
- if (openAudioFile(path, AskUser) == FileOpenFailed) {
-
- if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) {
-
- QMessageBox::critical(this, tr("Failed to open file"),
- tr("File \"%1\" could not be opened").arg(path));
- }
- }
- }
+ FileOpenStatus status = openSomeFile(path, AskUser);
+
+ if (status == FileOpenFailed) {
+ QMessageBox::critical(this, tr("Failed to open file"),
+ tr("File open failed File \"%1\" could not be opened").arg(path));
+ } else if (status == FileOpenWrongMode) {
+ QMessageBox::critical(this, tr("Failed to open file"),
+ tr("Audio required Please load at least one audio file before importing annotation data"));
}
}
@@ -3327,9 +3383,14 @@
if (text.isEmpty()) return;
- if (openURL(QUrl(text)) == FileOpenFailed) {
+ FileOpenStatus status = openURL(QUrl(text));
+
+ if (status == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open location"),
- tr("URL \"%1\" could not be opened").arg(text));
+ tr("Open failed URL \"%1\" could not be opened").arg(text));
+ } else if (status == FileOpenWrongMode) {
+ QMessageBox::critical(this, tr("Failed to open location"),
+ tr("Audio required Please load at least one audio file before importing annotation data"));
}
}
@@ -3348,52 +3409,28 @@
QString path = action->text();
if (path == "") return;
- QUrl url(path);
- if (RemoteFile::canHandleScheme(url)) {
- openURL(url);
- return;
- }
-
- if (path.endsWith("sv")) {
-
- if (!checkSaveModified()) return;
-
- if (openSessionFile(path) == FileOpenFailed) {
- QMessageBox::critical(this, tr("Failed to open file"),
- tr("Session file \"%1\" could not be opened").arg(path));
- }
-
- } else {
-
- if (openPlaylistFile(path, AskUser) == FileOpenFailed) {
-
- if (openAudioFile(path, AskUser) == FileOpenFailed) {
-
- bool canImportLayer = (getMainModel() != 0 &&
- m_paneStack != 0 &&
- m_paneStack->getCurrentPane() != 0);
-
- if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) {
-
- QMessageBox::critical(this, tr("Failed to open file"),
- tr("File \"%1\" could not be opened").arg(path));
- }
- }
- }
+ FileOpenStatus status = openURL(path);
+
+ if (status == FileOpenFailed) {
+ QMessageBox::critical(this, tr("Failed to open location"),
+ tr("Open failed File or URL \"%1\" could not be opened").arg(path));
+ } else if (status == FileOpenWrongMode) {
+ QMessageBox::critical(this, tr("Failed to open location"),
+ tr("Audio required Please load at least one audio file before importing annotation data"));
}
}
MainWindow::FileOpenStatus
MainWindow::openURL(QUrl url, AudioFileOpenMode mode)
{
- if (url.scheme().toLower() == "file") {
+ if (url.scheme().toLower() == "file" || url.scheme() == "") {
return openSomeFile(url.toLocalFile(), mode);
} else if (!RemoteFile::canHandleScheme(url)) {
QMessageBox::critical(this, tr("Unsupported scheme in URL"),
- tr("The URL scheme \"%1\" is not supported")
+ tr("Download failed The URL scheme \"%1\" is not supported")
.arg(url.scheme()));
return FileOpenFailed;
@@ -3402,7 +3439,7 @@
rf.wait();
if (!rf.isOK()) {
QMessageBox::critical(this, tr("File download failed"),
- tr("Failed to download URL \"%1\": %2")
+ tr("Download failed Failed to download URL \"%1\": %2")
.arg(url.toString()).arg(rf.getErrorString()));
return FileOpenFailed;
}
@@ -3424,14 +3461,19 @@
QUrl url(ustr);
- if (url.scheme().toLower() == "file") {
-
- return openSomeFile(url.toLocalFile(), mode);
+ if (url.scheme().toLower() == "file" || url.scheme() == "") {
+
+ FileOpenStatus status = openSomeFile(url.toLocalFile(), mode);
+ if (status == FileOpenFailed) {
+ url.setEncodedUrl(ustr.toAscii());
+ status = openSomeFile(url.toLocalFile(), mode);
+ }
+ return status;
} else if (!RemoteFile::canHandleScheme(url)) {
QMessageBox::critical(this, tr("Unsupported scheme in URL"),
- tr("The URL scheme \"%1\" is not supported")
+ tr("Download failed The URL scheme \"%1\" is not supported")
.arg(url.scheme()));
return FileOpenFailed;
@@ -3479,10 +3521,13 @@
return status;
} else if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) {
return status;
- } else if ((status = openSessionFile(path, location)) != FileOpenFailed) {
+ } else if (QFileInfo(path).suffix().toLower() == "sv" &&
+ (status = openSessionFile(path, location)) != FileOpenFailed) {
return status;
} else if (!canImportLayer) {
- return FileOpenFailed;
+ return FileOpenWrongMode;
+ } else if ((status = openImageFile(path, location)) != FileOpenFailed) {
+ return status;
} else if ((status = openLayerFile(path, location)) != FileOpenFailed) {
return status;
} else {
@@ -3556,6 +3601,46 @@
}
void
+MainWindow::paneDropAccepted(Pane *pane, QStringList uriList)
+{
+ if (pane) m_paneStack->setCurrentPane(pane);
+
+ for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) {
+
+ FileOpenStatus status =
+ openURL(*i, (m_document->getMainModel() ?
+ CreateAdditionalModel : ReplaceMainModel));
+
+ if (status == FileOpenFailed) {
+ QMessageBox::critical(this, tr("Failed to open dropped URL"),
+ tr("Open failed Dropped URL \"%1\" could not be opened").arg(*i));
+ } else if (status == FileOpenWrongMode) {
+ QMessageBox::critical(this, tr("Failed to open dropped URL"),
+ tr("Audio required Please load at least one audio file before importing annotation data"));
+ }
+ }
+}
+
+void
+MainWindow::paneDropAccepted(Pane *pane, QString text)
+{
+ if (pane) m_paneStack->setCurrentPane(pane);
+
+ QUrl testUrl(text);
+ if (testUrl.scheme() == "file" ||
+ testUrl.scheme() == "http" ||
+ testUrl.scheme() == "ftp") {
+ QStringList list;
+ list.push_back(text);
+ paneDropAccepted(pane, list);
+ return;
+ }
+
+ //!!! open as text -- but by importing as if a CSV, or just adding
+ //to a text layer?
+}
+
+void
MainWindow::closeEvent(QCloseEvent *e)
{
// std::cerr << "MainWindow::closeEvent" << std::endl;
@@ -3659,7 +3744,7 @@
int button =
QMessageBox::warning(this,
tr("Session modified"),
- tr("The current session has been modified.\nDo you want to save it?"),
+ tr("Session modified The current session has been modified. Session file \"%1\" could not be saved.").arg(m_sessionFile));
} else {
CommandHistory::getInstance()->documentSaved();
documentRestored();
@@ -3708,7 +3793,7 @@
if (!saveSessionFile(path)) {
QMessageBox::critical(this, tr("Failed to save file"),
- tr("Session file \"%1\" could not be saved.").arg(path));
+ tr("Save failed Session file \"%1\" could not be saved.").arg(path));
} else {
setWindowTitle(tr("Sonic Visualiser: %1")
.arg(QFileInfo(path).fileName()));
@@ -3740,7 +3825,7 @@
if (!bzFile.isOK()) {
QMessageBox::critical(this, tr("Failed to write file"),
- tr("Failed to write to file \"%1\": %2")
+ tr("Save failed Failed to write to file \"%1\": %2")
.arg(path).arg(bzFile.errorString()));
bzFile.close();
return false;
@@ -4706,10 +4791,9 @@
bool willResample)
{
if (!willResample) {
- //!!! more helpful message needed
QMessageBox::information
(this, tr("Sample rate mismatch"),
- 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.")
+ tr("Wrong sample rate The sample rate of this audio file (%1 Hz) does not match\nthe current playback rate (%2 Hz). The file will play at the wrong speed and pitch. Change the Resample mismatching files on import option under File -> Preferences if you want to alter this behaviour.")
.arg(requested).arg(actual));
}
@@ -4721,7 +4805,7 @@
{
QMessageBox::information
(this, tr("Audio processing overload"),
- tr("Audio effects plugin auditioning has been disabled\ndue to a processing overload."));
+ tr("Overloaded Audio effects plugin auditioning has been disabled due to a processing overload."));
}
void
@@ -4819,7 +4903,7 @@
QMessageBox::warning
(this,
tr("Failed to generate layer"),
- 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.")
+ tr("Layer generation failed Failed to generate a derived layer. The layer transform \"%1\" failed. This may mean that a plugin failed to initialise, perhaps because it rejected the processing block size that was requested.")
.arg(transformName),
QMessageBox::Ok);
}
@@ -4830,7 +4914,7 @@
QMessageBox::warning
(this,
tr("Failed to regenerate layer"),
- 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.")
+ tr("Layer generation failed Failed to regenerate derived layer \"%1\". The layer transform \"%2\" failed to run. This may mean that the layer used a plugin that is not currently available.")
.arg(layerName).arg(transformName),
QMessageBox::Ok);
}
diff -r d3477f673fb4 -r 4e030ebb6b36 main/MainWindow.h
--- a/main/MainWindow.h Wed Oct 10 10:22:34 2007 +0000
+++ b/main/MainWindow.h Wed Oct 10 15:18:02 2007 +0000
@@ -75,13 +75,15 @@
enum FileOpenStatus {
FileOpenSucceeded,
FileOpenFailed,
- FileOpenCancelled
+ FileOpenCancelled,
+ FileOpenWrongMode // attempted to open layer when no main model present
};
FileOpenStatus openSomeFile(QString path, AudioFileOpenMode = AskUser);
FileOpenStatus openAudioFile(QString path, AudioFileOpenMode = AskUser);
FileOpenStatus openPlaylistFile(QString path, AudioFileOpenMode = AskUser);
FileOpenStatus openLayerFile(QString path);
+ FileOpenStatus openImageFile(QString path);
FileOpenStatus openSessionFile(QString path);
FileOpenStatus openURL(QUrl url, AudioFileOpenMode = AskUser);
FileOpenStatus openURL(QString url, AudioFileOpenMode = AskUser);
@@ -239,6 +241,9 @@
void propertyStacksResized();
+ void paneDropAccepted(Pane *, QStringList);
+ void paneDropAccepted(Pane *, QString);
+
void setupRecentFilesMenu();
void setupRecentTransformsMenu();
@@ -430,6 +435,7 @@
FileOpenStatus openPlaylistFile(QString path, QString location,
AudioFileOpenMode = AskUser);
FileOpenStatus openLayerFile(QString path, QString location);
+ FileOpenStatus openImageFile(QString path, QString location);
FileOpenStatus openSessionFile(QString path, QString location);
QString getOpenFileName(FileFinder::FileType type);
Do you want to save it?
"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
QMessageBox::Yes);
@@ -3685,7 +3770,7 @@
if (m_sessionFile != "") {
if (!saveSessionFile(m_sessionFile)) {
QMessageBox::critical(this, tr("Failed to save file"),
- tr("Session file \"%1\" could not be saved.").arg(m_sessionFile));
+ tr("Save failed