# HG changeset patch # User Chris Cannam # Date 1482165154 0 # Node ID e4f223fc909966abc430ed0be06b7714d1c383aa # Parent c8b03c666185b3b0ac1ab92bef5088955e79468f Implement "Export SVG file..." diff -r c8b03c666185 -r e4f223fc9099 .hgsubstate --- a/.hgsubstate Sat Dec 17 11:06:48 2016 +0000 +++ b/.hgsubstate Mon Dec 19 16:32:34 2016 +0000 @@ -7,7 +7,7 @@ 7d46098431f39c265e47254e420576559587b3fe icons/scalable 3257ddb6fff110cc88f3ffeaeefa0f29d5eb3b6f piper-cpp 5f67a29f0fc7f1b908f7cde4866173a7af337862 sv-dependency-builds -36076ef960fb86ade2dd2eca13edb1ed154ef55f svapp -576be7933ec70cd7a24327536c6ad5e315c51bde svcore -a68c25ba1153ae20c0a387f28a7a79be243d69b2 svgui +b777379e70d851aa75ff66b677fb3bd4c79808d4 svapp +b1a7f45544003003008ee5098628fc009771c5dc svcore +6828735468c9f096e02a3dfa67a6529876741f69 svgui 0eebd22a081a824067bf3d5de65326696feab653 vamp-plugin-sdk diff -r c8b03c666185 -r e4f223fc9099 CHANGELOG --- a/CHANGELOG Sat Dec 17 11:06:48 2016 +0000 +++ b/CHANGELOG Mon Dec 19 16:32:34 2016 +0000 @@ -14,6 +14,8 @@ - Add ability to open, display, and analyse very long audio files (of more than 2^32 sample frames) + - Add ability to export scalable (SVG) image files + - Run plugins in a separate process, so that if a plugin crashes, it no longer brings down Sonic Visualiser with it. In every other respect the behaviour should be unchanged @@ -40,7 +42,7 @@ - Finally switch the Windows built to 64-bit by default (with adapters to run either 32- or 64-bit plugins) - + Changes in Sonic Visualiser 2.5 since the previous release 2.4.1: diff -r c8b03c666185 -r e4f223fc9099 main/MainWindow.cpp --- a/main/MainWindow.cpp Sat Dec 17 11:06:48 2016 +0000 +++ b/main/MainWindow.cpp Mon Dec 19 16:32:34 2016 +0000 @@ -589,6 +589,12 @@ connect(this, SIGNAL(canExportImage(bool)), action, SLOT(setEnabled(bool))); menu->addAction(action); + action = new QAction(tr("Export SVG File..."), this); + action->setStatusTip(tr("Export a single pane to a scalable SVG image file")); + connect(action, SIGNAL(triggered()), this, SLOT(exportSVG())); + connect(this, SIGNAL(canExportImage(bool)), action, SLOT(setEnabled(bool))); + menu->addAction(action); + menu->addSeparator(); action = new QAction(tr("Browse Recorded Audio Folder"), this); @@ -2856,18 +2862,21 @@ Pane *pane = m_paneStack->getCurrentPane(); if (!pane) return; +//!!! QString path = getSaveFileName(FileFinder::ImageFile); +// if (path == "") return; +// if (QFileInfo(path).suffix() == "") path += ".png"; QString path = getSaveFileName(FileFinder::ImageFile); - if (path == "") return; - - if (QFileInfo(path).suffix() == "") path += ".png"; - + if (QFileInfo(path).suffix() == "") path += ".svg"; + + bool scalable = true; //!!! + bool haveSelection = m_viewManager && !m_viewManager->getSelections().empty(); QSize total, visible, selected; - total = pane->getImageSize(); - visible = pane->getImageSize(pane->getFirstVisibleFrame(), - pane->getLastVisibleFrame()); + total = pane->getRenderedImageSize(); + visible = pane->getRenderedPartImageSize(pane->getFirstVisibleFrame(), + pane->getLastVisibleFrame()); sv_frame_t sf0 = 0, sf1 = 0; @@ -2877,7 +2886,7 @@ MultiSelection::SelectionList::iterator e = selections.end(); --e; sf1 = e->getEndFrame(); - selected = pane->getImageSize(sf0, sf1); + selected = pane->getRenderedPartImageSize(sf0, sf1); } QStringList items; @@ -2896,7 +2905,7 @@ settings.beginGroup("MainWindow"); int deflt = settings.value("lastimageexportregion", 0).toInt(); if (deflt == 2 && !haveSelection) deflt = 1; - if (deflt == 0 && total.width() > 32767) deflt = 1; + if (deflt == 0 && !scalable && total.width() > 32767) deflt = 1; ListInputDialog *lid = new ListInputDialog (this, tr("Select region to export"), @@ -2906,7 +2915,7 @@ if (!haveSelection) { lid->setItemAvailability(2, false); } - if (total.width() > 32767) { // appears to be the limit of a QImage + if (!scalable && total.width() > 32767) { // appears to be limit of a QImage lid->setItemAvailability(0, false); lid->setFootnote(tr("Note: the whole pane is too wide to be exported as a single image.")); } @@ -2919,25 +2928,114 @@ settings.setValue("lastimageexportregion", deflt); - QImage *image = 0; - + if (scalable) { + + bool result = false; + + if (item == items[0]) { + result = pane->renderToSvgFile(path ); + } else if (item == items[1]) { + result = pane->renderPartToSvgFile(path, + pane->getFirstVisibleFrame(), + pane->getLastVisibleFrame()); + } else if (haveSelection) { + result = pane->renderPartToSvgFile(path, sf0, sf1); + } + + if (!result) { + QMessageBox::critical(this, tr("Failed to save SVG file"), + tr("Failed to save SVG file %1").arg(path)); + } + + } else { + + QImage *image = 0; + + if (item == items[0]) { + image = pane->renderToNewImage(); + } else if (item == items[1]) { + image = pane->renderPartToNewImage(pane->getFirstVisibleFrame(), + pane->getLastVisibleFrame()); + } else if (haveSelection) { + image = pane->renderPartToNewImage(sf0, sf1); + } + + if (!image) return; + + if (!image->save(path, "PNG")) { + QMessageBox::critical(this, tr("Failed to save image file"), + tr("Failed to save image file %1").arg(path)); + } + + delete image; + } +} + +void +MainWindow::exportSVG() +{ + Pane *pane = m_paneStack->getCurrentPane(); + if (!pane) return; + + QString path = getSaveFileName(FileFinder::SVGFile); + if (path == "") return; + if (QFileInfo(path).suffix() == "") path += ".svg"; + + bool haveSelection = m_viewManager && !m_viewManager->getSelections().empty(); + + sv_frame_t sf0 = 0, sf1 = 0; + + if (haveSelection) { + MultiSelection::SelectionList selections = m_viewManager->getSelections(); + sf0 = selections.begin()->getStartFrame(); + MultiSelection::SelectionList::iterator e = selections.end(); + --e; + sf1 = e->getEndFrame(); + } + + QStringList items; + items << tr("Export the whole pane"); + items << tr("Export the visible area only"); + items << tr("Export the selection extent"); + + QSettings settings; + settings.beginGroup("MainWindow"); + int deflt = settings.value("lastsvgexportregion", 0).toInt(); + if (deflt == 2 && !haveSelection) deflt = 1; + + ListInputDialog *lid = new ListInputDialog + (this, tr("Select region to export"), + tr("Which region of the current pane do you want to export as a scalable SVG image?"), + items, deflt); + + if (!haveSelection) { + lid->setItemAvailability(2, false); + } + + bool ok = lid->exec(); + QString item = lid->getCurrentString(); + delete lid; + + if (!ok || item.isEmpty()) return; + + settings.setValue("lastsvgexportregion", deflt); + + bool result = false; + if (item == items[0]) { - image = pane->toNewImage(); + result = pane->renderToSvgFile(path ); } else if (item == items[1]) { - image = pane->toNewImage(pane->getFirstVisibleFrame(), - pane->getLastVisibleFrame()); + result = pane->renderPartToSvgFile(path, + pane->getFirstVisibleFrame(), + pane->getLastVisibleFrame()); } else if (haveSelection) { - image = pane->toNewImage(sf0, sf1); - } - - if (!image) return; - - if (!image->save(path, "PNG")) { - QMessageBox::critical(this, tr("Failed to save image file"), - tr("Failed to save image file %1").arg(path)); + result = pane->renderPartToSvgFile(path, sf0, sf1); } - delete image; + if (!result) { + QMessageBox::critical(this, tr("Failed to save SVG file"), + tr("Failed to save SVG file %1").arg(path)); + } } void diff -r c8b03c666185 -r e4f223fc9099 main/MainWindow.h --- a/main/MainWindow.h Sat Dec 17 11:06:48 2016 +0000 +++ b/main/MainWindow.h Mon Dec 19 16:32:34 2016 +0000 @@ -63,6 +63,7 @@ virtual void importLayer(); virtual void exportLayer(); virtual void exportImage(); + virtual void exportSVG(); virtual void browseRecordedAudio(); virtual void saveSession(); virtual void saveSessionAs();