changeset 1202:6828735468c9 svg

Implement "Export SVG file..."
author Chris Cannam
date Mon, 19 Dec 2016 16:32:34 +0000
parents a68c25ba1153
children ff042979331b
files view/Pane.cpp view/Pane.h view/View.cpp view/View.h widgets/InteractiveFileFinder.cpp
diffstat 5 files changed, 108 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/view/Pane.cpp	Fri Dec 16 19:35:57 2016 +0000
+++ b/view/Pane.cpp	Mon Dec 19 16:32:34 2016 +0000
@@ -1123,7 +1123,7 @@
 }
 
 QImage *
-Pane::toNewImage(sv_frame_t f0, sv_frame_t f1)
+Pane::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1)
 {
     int x0 = int(f0 / getZoomLevel());
     int x1 = int(f1 / getZoomLevel());
@@ -1162,9 +1162,9 @@
 }
 
 QSize
-Pane::getImageSize(sv_frame_t f0, sv_frame_t f1)
+Pane::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1)
 {
-    QSize s = View::getImageSize(f0, f1);
+    QSize s = View::getRenderedPartImageSize(f0, f1);
     QImage *image = new QImage(100, 100, QImage::Format_RGB32);
     QPainter paint(image);
 
--- a/view/Pane.h	Fri Dec 16 19:35:57 2016 +0000
+++ b/view/Pane.h	Mon Dec 19 16:32:34 2016 +0000
@@ -37,28 +37,35 @@
 
 public:
     Pane(QWidget *parent = 0);
-    virtual QString getPropertyContainerIconName() const { return "pane"; }
+    virtual QString getPropertyContainerIconName() const override { return "pane"; }
 
     virtual bool shouldIlluminateLocalFeatures(const Layer *layer,
-					       QPoint &pos) const;
+					       QPoint &pos) const override;
     virtual bool shouldIlluminateLocalSelection(QPoint &pos,
 						bool &closeToLeft,
-						bool &closeToRight) const;
+						bool &closeToRight) const override;
 
     void setCentreLineVisible(bool visible);
     bool getCentreLineVisible() const { return m_centreLineVisible; }
 
-    virtual sv_frame_t getFirstVisibleFrame() const;
+    virtual sv_frame_t getFirstVisibleFrame() const override;
 
-    virtual int getVerticalScaleWidth() const;
+    int getVerticalScaleWidth() const;
 
-    virtual QImage *toNewImage(sv_frame_t f0, sv_frame_t f1);
-    virtual QImage *toNewImage() { return View::toNewImage(); }
-    virtual QSize getImageSize(sv_frame_t f0, sv_frame_t f1);
-    virtual QSize getImageSize() { return View::getImageSize(); }
+    virtual QImage *renderToNewImage() override {
+        return View::renderToNewImage();
+    }
+    
+    virtual QImage *renderPartToNewImage(sv_frame_t f0, sv_frame_t f1) override;
+
+    virtual QSize getRenderedImageSize() override {
+        return View::getRenderedImageSize();
+    }
+    
+    virtual QSize getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1) override;
 
     virtual void toXml(QTextStream &stream, QString indent = "",
-                       QString extraAttributes = "") const;
+                       QString extraAttributes = "") const override;
 
     static void registerShortcuts(KeyReference &kr);
 
--- a/view/View.cpp	Fri Dec 16 19:35:57 2016 +0000
+++ b/view/View.cpp	Mon Dec 19 16:32:34 2016 +0000
@@ -41,6 +41,7 @@
 #include <QMessageBox>
 #include <QPushButton>
 #include <QSettings>
+#include <QSvgGenerator>
 
 #include <iostream>
 #include <cassert>
@@ -2461,16 +2462,16 @@
 }
 
 QImage *
-View::toNewImage()
+View::renderToNewImage()
 {
     sv_frame_t f0 = getModelsStartFrame();
     sv_frame_t f1 = getModelsEndFrame();
 
-    return toNewImage(f0, f1);
+    return renderPartToNewImage(f0, f1);
 }
 
 QImage *
-View::toNewImage(sv_frame_t f0, sv_frame_t f1)
+View::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1)
 {
     int x0 = int(f0 / getZoomLevel());
     int x1 = int(f1 / getZoomLevel());
@@ -2489,16 +2490,16 @@
 }
 
 QSize
-View::getImageSize()
+View::getRenderedImageSize()
 {
     sv_frame_t f0 = getModelsStartFrame();
     sv_frame_t f1 = getModelsEndFrame();
 
-    return getImageSize(f0, f1);
+    return getRenderedPartImageSize(f0, f1);
 }
     
 QSize
-View::getImageSize(sv_frame_t f0, sv_frame_t f1)
+View::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1)
 {
     int x0 = int(f0 / getZoomLevel());
     int x1 = int(f1 / getZoomLevel());
@@ -2506,6 +2507,35 @@
     return QSize(x1 - x0, height());
 }
 
+bool
+View::renderToSvgFile(QString filename)
+{
+    sv_frame_t f0 = getModelsStartFrame();
+    sv_frame_t f1 = getModelsEndFrame();
+
+    return renderPartToSvgFile(filename, f0, f1);
+}
+
+bool
+View::renderPartToSvgFile(QString filename, sv_frame_t f0, sv_frame_t f1)
+{
+    int x0 = int(f0 / getZoomLevel());
+    int x1 = int(f1 / getZoomLevel());
+
+    QSvgGenerator generator;
+    generator.setFileName(filename);
+    generator.setSize(QSize(x1 - x0, height()));
+    generator.setViewBox(QRect(0, 0, x1 - x0, height()));
+    generator.setTitle(tr("Exported image from %1")
+                       .arg(QApplication::applicationName()));
+    
+    QPainter paint;
+    paint.begin(&generator);
+    bool result = render(paint, 0, f0, f1);
+    paint.end();
+    return result;
+}
+
 void
 View::toXml(QTextStream &stream,
             QString indent, QString extraAttributes) const
--- a/view/View.h	Fri Dec 16 19:35:57 2016 +0000
+++ b/view/View.h	Mon Dec 19 16:32:34 2016 +0000
@@ -308,12 +308,42 @@
     virtual const PropertyContainer *getPropertyContainer(int i) const;
     virtual PropertyContainer *getPropertyContainer(int i);
 
-    // Render the contents on a wide canvas
-    virtual QImage *toNewImage(sv_frame_t f0, sv_frame_t f1);
-    virtual QImage *toNewImage();
-    virtual QSize getImageSize(sv_frame_t f0, sv_frame_t f1);
-    virtual QSize getImageSize();
+    /** 
+     * Render the view contents to a new QImage (which may be wider
+     * than the visible View).
+     */
+    virtual QImage *renderToNewImage();
 
+    /** 
+     * Render the view contents between the given frame extents to a
+     * new QImage (which may be wider than the visible View).
+     */
+    virtual QImage *renderPartToNewImage(sv_frame_t f0, sv_frame_t f1);
+
+    /**
+     * Calculate and return the size of image that will be generated
+     * by renderToNewImage().
+     */
+    virtual QSize getRenderedImageSize();
+
+    /**
+     * Calculate and return the size of image that will be generated
+     * by renderPartToNewImage(f0, f1).
+     */
+    virtual QSize getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1);
+
+    /**
+     * Render the view contents to a new SVG file.
+     */
+    virtual bool renderToSvgFile(QString filename);
+
+    /**
+     * Render the view contents between the given frame extents to a
+     * new SVG file.
+     */
+    virtual bool renderPartToSvgFile(QString filename,
+                                     sv_frame_t f0, sv_frame_t f1);
+    
     virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
 
     virtual bool getValueExtents(QString unit, double &min, double &max,
--- a/widgets/InteractiveFileFinder.cpp	Fri Dec 16 19:35:57 2016 +0000
+++ b/widgets/InteractiveFileFinder.cpp	Mon Dec 19 16:32:34 2016 +0000
@@ -134,6 +134,11 @@
         }
         break;
 
+    case SVGFile:
+        settingsKeyStub = "svg";
+        filter = tr("Scalable Vector Graphics files (*.svg)\nAll files (*.*)");
+        break;
+
     case CSVFile:
         settingsKeyStub = "layer";
         filter = tr("Comma-separated data files (*.csv)\nSpace-separated .lab files (*.lab)\nText files (*.txt)\nAll files (*.*)");
@@ -282,6 +287,12 @@
         filter = tr("Portable Network Graphics files (*.png)\nAll files (*.*)");
         break;
 
+    case SVGFile:
+        settingsKeyStub = "savesvg";
+        title = tr("Select a file to export to");
+        filter = tr("Scalable Vector Graphics files (*.svg)\nAll files (*.*)");
+        break;
+
     case CSVFile:
         settingsKeyStub = "savelayer";
         title = tr("Select a file to export to");
@@ -330,6 +341,8 @@
         defaultSuffix = "wav";
     } else if (type == ImageFile) {
         defaultSuffix = "png";
+    } else if (type == SVGFile) {
+        defaultSuffix = "svg";
     } else if (type == CSVFile) {
         defaultSuffix = "csv";
     }
@@ -450,6 +463,10 @@
         settingsKeyStub = "image";
         break;
 
+    case SVGFile:
+        settingsKeyStub = "svg";
+        break;
+
     case CSVFile:
         settingsKeyStub = "layer";
         break;