diff --git a/src/libs/utils/images/fileexport.png b/src/libs/utils/images/fileexport.png
new file mode 100644
index 00000000000..98b87d7b502
Binary files /dev/null and b/src/libs/utils/images/fileexport.png differ
diff --git a/src/libs/utils/images/fileexport@2x.png b/src/libs/utils/images/fileexport@2x.png
new file mode 100644
index 00000000000..580a99a06e1
Binary files /dev/null and b/src/libs/utils/images/fileexport@2x.png differ
diff --git a/src/libs/utils/images/filemultiexport.png b/src/libs/utils/images/filemultiexport.png
new file mode 100644
index 00000000000..c475f9600b1
Binary files /dev/null and b/src/libs/utils/images/filemultiexport.png differ
diff --git a/src/libs/utils/images/filemultiexport@2x.png b/src/libs/utils/images/filemultiexport@2x.png
new file mode 100644
index 00000000000..134bbf3de81
Binary files /dev/null and b/src/libs/utils/images/filemultiexport@2x.png differ
diff --git a/src/libs/utils/utils.qrc b/src/libs/utils/utils.qrc
index 60894bf88d4..d0bb9891da2 100644
--- a/src/libs/utils/utils.qrc
+++ b/src/libs/utils/utils.qrc
@@ -52,6 +52,10 @@
         images/editpaste@2x.png
         images/empty14.png
         images/empty16.png
+        images/fileexport.png
+        images/fileexport@2x.png
+        images/filemultiexport.png
+        images/filemultiexport@2x.png
         images/filenew.png
         images/filenew@2x.png
         images/fileopen.png
diff --git a/src/libs/utils/utilsicons.cpp b/src/libs/utils/utilsicons.cpp
index 2a602705384..bc9adecdada 100644
--- a/src/libs/utils/utilsicons.cpp
+++ b/src/libs/utils/utilsicons.cpp
@@ -93,6 +93,12 @@ const Icon SAVEFILE({
         {QLatin1String(":/utils/images/filesave.png"), Theme::PanelTextColorMid}}, Icon::Tint);
 const Icon SAVEFILE_TOOLBAR({
         {QLatin1String(":/utils/images/filesave.png"), Theme::IconsBaseColor}});
+
+const Icon EXPORTFILE_TOOLBAR({
+        {QLatin1String(":/utils/images/fileexport.png"), Theme::IconsBaseColor}});
+const Icon MULTIEXPORTFILE_TOOLBAR({
+        {QLatin1String(":/utils/images/filemultiexport.png"), Theme::IconsBaseColor}});
+
 const Icon UNDO({
         {QLatin1String(":/utils/images/undo.png"), Theme::PanelTextColorMid}}, Icon::Tint);
 const Icon UNDO_TOOLBAR({
diff --git a/src/libs/utils/utilsicons.h b/src/libs/utils/utilsicons.h
index c836cd3bc35..c4230fcb687 100644
--- a/src/libs/utils/utilsicons.h
+++ b/src/libs/utils/utilsicons.h
@@ -61,6 +61,10 @@ QTCREATOR_UTILS_EXPORT extern const Icon OPENFILE;
 QTCREATOR_UTILS_EXPORT extern const Icon OPENFILE_TOOLBAR;
 QTCREATOR_UTILS_EXPORT extern const Icon SAVEFILE;
 QTCREATOR_UTILS_EXPORT extern const Icon SAVEFILE_TOOLBAR;
+
+QTCREATOR_UTILS_EXPORT extern const Icon EXPORTFILE_TOOLBAR;
+QTCREATOR_UTILS_EXPORT extern const Icon MULTIEXPORTFILE_TOOLBAR;
+
 QTCREATOR_UTILS_EXPORT extern const Icon UNDO;
 QTCREATOR_UTILS_EXPORT extern const Icon UNDO_TOOLBAR;
 QTCREATOR_UTILS_EXPORT extern const Icon REDO;
diff --git a/src/plugins/imageviewer/exportdialog.cpp b/src/plugins/imageviewer/exportdialog.cpp
index 778d90e9ecf..1b641591315 100644
--- a/src/plugins/imageviewer/exportdialog.cpp
+++ b/src/plugins/imageviewer/exportdialog.cpp
@@ -24,6 +24,7 @@
 ****************************************************************************/
 
 #include "exportdialog.h"
+#include "imageview.h" // ExportData
 
 #include 
 
@@ -56,7 +57,7 @@ namespace Internal {
 
 enum { exportMinimumSize = 1, exportMaximumSize = 2000 };
 
-static QString imageNameFilterString()
+QString ExportDialog::imageNameFilterString()
 {
     static QString result;
     if (result.isEmpty()) {
@@ -198,5 +199,10 @@ void ExportDialog::setExportFileName(const QString &f)
     m_pathChooser->setFileName(Utils::FileName::fromString(f));
 }
 
+ExportData ExportDialog::exportData() const
+{
+    return {exportFileName(), exportSize()};
+}
+
 } // namespace Internal
 } // namespace ImageViewer
diff --git a/src/plugins/imageviewer/exportdialog.h b/src/plugins/imageviewer/exportdialog.h
index 76296e8ba4d..2480c2dcafe 100644
--- a/src/plugins/imageviewer/exportdialog.h
+++ b/src/plugins/imageviewer/exportdialog.h
@@ -34,6 +34,8 @@ namespace Utils { class PathChooser; }
 namespace ImageViewer {
 namespace Internal {
 
+struct ExportData;
+
 class ExportDialog : public QDialog
 {
     Q_OBJECT
@@ -46,8 +48,12 @@ public:
     QString exportFileName() const;
     void setExportFileName(const QString &);
 
+    ExportData exportData() const;
+
     void accept() override;
 
+    static QString imageNameFilterString();
+
 private:
     void resetExportSize();
     void exportWidthChanged(int width);
diff --git a/src/plugins/imageviewer/imageview.cpp b/src/plugins/imageviewer/imageview.cpp
index db7869cd2e3..dfa4a547fe5 100644
--- a/src/plugins/imageviewer/imageview.cpp
+++ b/src/plugins/imageviewer/imageview.cpp
@@ -51,6 +51,7 @@
 #include "imageview.h"
 
 #include "exportdialog.h"
+#include "multiexportdialog.h"
 #include "imageviewerfile.h"
 
 #include 
@@ -156,6 +157,53 @@ void ImageView::drawBackground(QPainter *p, const QRectF &)
     p->restore();
 }
 
+QImage ImageView::renderSvg(const QSize &imageSize) const
+{
+    QImage image(imageSize, QImage::Format_ARGB32);
+    image.fill(Qt::transparent);
+    QPainter painter;
+    painter.begin(&image);
+#ifndef QT_NO_SVG
+    QGraphicsSvgItem *svgItem = qgraphicsitem_cast(m_imageItem);
+    QTC_ASSERT(svgItem, return image);
+    svgItem->renderer()->render(&painter, QRectF(QPointF(), QSizeF(imageSize)));
+#endif
+    painter.end();
+    return image;
+}
+
+bool ImageView::exportSvg(const ExportData &ed)
+{
+    const bool result = renderSvg(ed.size).save(ed.fileName);
+    if (result) {
+        const QString message = tr("Exported \"%1\", %2x%3, %4 bytes")
+            .arg(QDir::toNativeSeparators(ed.fileName))
+            .arg(ed.size.width()).arg(ed.size.height())
+            .arg(QFileInfo(ed.fileName).size());
+        Core::MessageManager::write(message);
+    } else {
+        const QString message = tr("Could not write file \"%1\".").arg(QDir::toNativeSeparators(ed.fileName));
+        QMessageBox::critical(this, tr("Export Image"), message);
+    }
+    return result;
+}
+
+static QString suggestedExportFileName(const QFileInfo &fi)
+{
+    return fi.absolutePath() + QLatin1Char('/') + fi.baseName()
+        + QStringLiteral(".png");
+}
+
+QSize ImageView::svgSize() const
+{
+    QSize result;
+#ifndef QT_NO_SVG
+    if (const QGraphicsSvgItem *svgItem = qgraphicsitem_cast(m_imageItem))
+        result = svgItem->boundingRect().size().toSize();
+#endif // !QT_NO_SVG
+    return result;
+}
+
 void ImageView::exportImage()
 {
 #ifndef QT_NO_SVG
@@ -163,37 +211,42 @@ void ImageView::exportImage()
     QTC_ASSERT(svgItem, return);
 
     const QFileInfo origFi = m_file->filePath().toFileInfo();
-    const QString suggestedFileName = origFi.absolutePath() + QLatin1Char('/')
-        + origFi.baseName() + QStringLiteral(".png");
-
     ExportDialog exportDialog(this);
     exportDialog.setWindowTitle(tr("Export %1").arg(origFi.fileName()));
-    exportDialog.setExportSize(svgItem->boundingRect().size().toSize());
-    exportDialog.setExportFileName(suggestedFileName);
+    exportDialog.setExportSize(svgSize());
+    exportDialog.setExportFileName(suggestedExportFileName(origFi));
 
-    while (true) {
-        if (exportDialog.exec() != QDialog::Accepted)
-            break;
+    while (exportDialog.exec() == QDialog::Accepted && !exportSvg(exportDialog.exportData())) {}
+#endif // !QT_NO_SVG
+}
 
-        const QSize imageSize = exportDialog.exportSize();
-        QImage image(imageSize, QImage::Format_ARGB32);
-        image.fill(Qt::transparent);
-        QPainter painter;
-        painter.begin(&image);
-        svgItem->renderer()->render(&painter, QRectF(QPointF(), QSizeF(imageSize)));
-        painter.end();
+void ImageView::exportMultiImages()
+{
+#ifndef QT_NO_SVG
+    QTC_ASSERT(qgraphicsitem_cast(m_imageItem), return);
 
-        const QString fileName = exportDialog.exportFileName();
-        if (image.save(fileName)) {
-            const QString message = tr("Exported \"%1\", %2x%3, %4 bytes")
-                .arg(QDir::toNativeSeparators(fileName)).arg(imageSize.width()).arg(imageSize.height())
-                .arg(QFileInfo(fileName).size());
-            Core::MessageManager::write(message);
-            break;
-        } else {
-            QMessageBox::critical(this, tr("Export Image"),
-                                  tr("Could not write file \"%1\".").arg(QDir::toNativeSeparators(fileName)));
+    const QFileInfo origFi = m_file->filePath().toFileInfo();
+    const QSize size = svgSize();
+    const QString title =
+        tr("Export a Series of Images from %1 (%2x%3")
+          .arg(origFi.fileName()).arg(size.width()).arg(size.height());
+    MultiExportDialog multiExportDialog;
+    multiExportDialog.setWindowTitle(title);
+    multiExportDialog.setExportFileName(suggestedExportFileName(origFi));
+    multiExportDialog.setSvgSize(size);
+    multiExportDialog.suggestSizes();
+
+    while (multiExportDialog.exec() == QDialog::Accepted) {
+        const auto exportData = multiExportDialog.exportData();
+        bool ok = true;
+        for (const auto &data : exportData) {
+            if (!exportSvg(data)) {
+                ok = false;
+                break;
+            }
         }
+        if (ok)
+            break;
     }
 #endif // !QT_NO_SVG
 }
diff --git a/src/plugins/imageviewer/imageview.h b/src/plugins/imageviewer/imageview.h
index 4e797b66015..76f4a38de67 100644
--- a/src/plugins/imageviewer/imageview.h
+++ b/src/plugins/imageviewer/imageview.h
@@ -52,11 +52,18 @@
 
 #include 
 
+QT_FORWARD_DECLARE_CLASS(QImage)
+
 namespace ImageViewer {
 namespace Internal {
 
 class ImageViewerFile;
 
+struct ExportData {
+    QString fileName;
+    QSize size;
+};
+
 class ImageView : public QGraphicsView
 {
     Q_OBJECT
@@ -69,6 +76,7 @@ public:
     void createScene();
 
     void exportImage();
+    void exportMultiImages();
     void setViewBackground(bool enable);
     void setViewOutline(bool enable);
     void zoomIn();
@@ -83,6 +91,9 @@ signals:
 private:
     void emitScaleFactor();
     void doScale(qreal factor);
+    QSize svgSize() const;
+    QImage renderSvg(const QSize &imageSize) const;
+    bool exportSvg(const ExportData &ed);
 
     void drawBackground(QPainter *p, const QRectF &rect);
     void hideEvent(QHideEvent *event);
diff --git a/src/plugins/imageviewer/imageviewer.cpp b/src/plugins/imageviewer/imageviewer.cpp
index 7c98b7bb6ba..ea32b433dfe 100644
--- a/src/plugins/imageviewer/imageviewer.cpp
+++ b/src/plugins/imageviewer/imageviewer.cpp
@@ -102,9 +102,8 @@ void ImageViewer::ctor()
     // toolbar
     d->toolbar = new QWidget();
     d->ui_toolbar.setupUi(d->toolbar);
-    d->ui_toolbar.toolButtonExportImage->setIcon(
-                QIcon::fromTheme(QLatin1String("document-save"),
-                                 Utils::Icons::SAVEFILE_TOOLBAR.icon()));
+    d->ui_toolbar.toolButtonExportImage->setIcon(Utils::Icons::EXPORTFILE_TOOLBAR.icon());
+    d->ui_toolbar.toolButtonMultiExportImages->setIcon(Utils::Icons::MULTIEXPORTFILE_TOOLBAR.icon());
     const Utils::Icon backgroundIcon({
             {QLatin1String(":/utils/images/desktopdevicesmall.png"), Utils::Theme::IconsBaseColor}});
     d->ui_toolbar.toolButtonBackground->setIcon(backgroundIcon.icon());
@@ -125,6 +124,7 @@ void ImageViewer::ctor()
     updateButtonIconByTheme(d->ui_toolbar.toolButtonOutline, QLatin1String("emblem-photos"));
 
     d->ui_toolbar.toolButtonExportImage->setCommandId(Constants::ACTION_EXPORT_IMAGE);
+    d->ui_toolbar.toolButtonMultiExportImages->setCommandId(Constants::ACTION_EXPORT_MULTI_IMAGES);
     d->ui_toolbar.toolButtonZoomIn->setCommandId(Core::Constants::ZOOM_IN);
     d->ui_toolbar.toolButtonZoomOut->setCommandId(Core::Constants::ZOOM_OUT);
     d->ui_toolbar.toolButtonOriginalSize->setCommandId(Core::Constants::ZOOM_RESET);
@@ -136,6 +136,8 @@ void ImageViewer::ctor()
     // connections
     connect(d->ui_toolbar.toolButtonExportImage, &QAbstractButton::clicked,
             d->imageView, &ImageView::exportImage);
+    connect(d->ui_toolbar.toolButtonMultiExportImages, &QAbstractButton::clicked,
+            d->imageView, &ImageView::exportMultiImages);
     connect(d->ui_toolbar.toolButtonZoomIn, &QAbstractButton::clicked,
             d->imageView, &ImageView::zoomIn);
     connect(d->ui_toolbar.toolButtonZoomOut, &QAbstractButton::clicked,
@@ -198,6 +200,12 @@ void ImageViewer::exportImage()
         d->ui_toolbar.toolButtonExportImage->click();
 }
 
+void ImageViewer::exportMultiImages()
+{
+    if (d->file->type() == ImageViewerFile::TypeSvg)
+        d->ui_toolbar.toolButtonMultiExportImages->click();
+}
+
 void ImageViewer::imageSizeUpdated(const QSize &size)
 {
     QString imageSizeText;
@@ -244,7 +252,9 @@ void ImageViewer::fitToScreen()
 
 void ImageViewer::updateToolButtons()
 {
-    d->ui_toolbar.toolButtonExportImage->setEnabled(d->file->type() == ImageViewerFile::TypeSvg);
+    const bool isSvg = d->file->type() == ImageViewerFile::TypeSvg;
+    d->ui_toolbar.toolButtonExportImage->setEnabled(isSvg);
+    d->ui_toolbar.toolButtonMultiExportImages->setEnabled(isSvg);
     updatePauseAction();
 }
 
diff --git a/src/plugins/imageviewer/imageviewer.h b/src/plugins/imageviewer/imageviewer.h
index 38ee2ab0357..1d3418ac4df 100644
--- a/src/plugins/imageviewer/imageviewer.h
+++ b/src/plugins/imageviewer/imageviewer.h
@@ -55,6 +55,7 @@ public:
     IEditor *duplicate() override;
 
     void exportImage();
+    void exportMultiImages();
     void imageSizeUpdated(const QSize &size);
     void scaleFactorUpdate(qreal factor);
 
diff --git a/src/plugins/imageviewer/imageviewer.pro b/src/plugins/imageviewer/imageviewer.pro
index a3d81825884..18e99acf6c1 100644
--- a/src/plugins/imageviewer/imageviewer.pro
+++ b/src/plugins/imageviewer/imageviewer.pro
@@ -7,7 +7,8 @@ HEADERS += \
     imageviewerfile.h \
     imageviewer.h \
     imageview.h \
-    imageviewerconstants.h
+    imageviewerconstants.h \
+    multiexportdialog.h
 
 SOURCES += \
     exportdialog.cpp \
@@ -15,7 +16,8 @@ SOURCES += \
     imageviewerfactory.cpp \
     imageviewerfile.cpp \
     imageviewer.cpp \
-    imageview.cpp
+    imageview.cpp \
+    multiexportdialog.cpp
 
 !isEmpty(QT.svg.name): QT += svg
 else: DEFINES += QT_NO_SVG
diff --git a/src/plugins/imageviewer/imageviewerconstants.h b/src/plugins/imageviewer/imageviewerconstants.h
index 1fac9a69067..d8d5536df1b 100644
--- a/src/plugins/imageviewer/imageviewerconstants.h
+++ b/src/plugins/imageviewer/imageviewerconstants.h
@@ -33,6 +33,7 @@ const char IMAGEVIEWER_ID[] = "Editors.ImageViewer";
 const char IMAGEVIEWER_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Image Viewer");
 
 const char ACTION_EXPORT_IMAGE[] = "ImageViewer.ExportImage";
+const char ACTION_EXPORT_MULTI_IMAGES[] = "ImageViewer.ExportMultiImages";
 const char ACTION_FIT_TO_SCREEN[] = "ImageViewer.FitToScreen";
 const char ACTION_BACKGROUND[] = "ImageViewer.Background";
 const char ACTION_OUTLINE[] = "ImageViewer.Outline";
diff --git a/src/plugins/imageviewer/imageviewerplugin.cpp b/src/plugins/imageviewer/imageviewerplugin.cpp
index 1e2a493a0f9..82f46964f8e 100644
--- a/src/plugins/imageviewer/imageviewerplugin.cpp
+++ b/src/plugins/imageviewer/imageviewerplugin.cpp
@@ -113,6 +113,14 @@ void ImageViewerPlugin::extensionsInitialized()
         if (ImageViewer *iv = currentImageViewer())
             iv->exportImage();
     });
+
+    a = registerNewAction(Constants::ACTION_EXPORT_MULTI_IMAGES, tr("Export Multiple Images"),
+                          QKeySequence());
+    connect(a, &QAction::triggered, this, []() {
+        if (ImageViewer *iv = currentImageViewer())
+            iv->exportMultiImages();
+    });
+
 }
 
 QAction *ImageViewerPlugin::registerNewAction(Core::Id id,
diff --git a/src/plugins/imageviewer/imageviewertoolbar.ui b/src/plugins/imageviewer/imageviewertoolbar.ui
index 0a230946d3c..3aac796f5d3 100644
--- a/src/plugins/imageviewer/imageviewertoolbar.ui
+++ b/src/plugins/imageviewer/imageviewertoolbar.ui
@@ -24,6 +24,13 @@
      
     
    
+   - 
+    
+     
+      Export Images of Multiple Sizes
+     
+    
+   
 
    - 
     
      
@@ -134,8 +141,5 @@
    coreplugin/actionmanager/commandbutton.h
   
  
- 
-  
- 
  
 
diff --git a/src/plugins/imageviewer/multiexportdialog.cpp b/src/plugins/imageviewer/multiexportdialog.cpp
new file mode 100644
index 00000000000..fe3a66a84b9
--- /dev/null
+++ b/src/plugins/imageviewer/multiexportdialog.cpp
@@ -0,0 +1,346 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "multiexportdialog.h"
+#include "exportdialog.h"
+#include "imageview.h" // ExportData
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+namespace ImageViewer {
+namespace Internal {
+
+static const int standardIconSizesValues[] = {16, 24, 32, 48, 64, 128, 256};
+
+// Helpers to convert a size specifications from QString to QSize
+// and vv. The format is '2x4' or '4' as shortcut for '4x4'.
+static QSize sizeFromString(const QStringRef &r)
+{
+    if (r.isEmpty())
+        return QSize();
+    const int xPos = r.indexOf('x');
+    bool ok;
+    const int width = xPos < 0
+        ? r.toInt(&ok)
+        : r.left(xPos).toInt(&ok);
+    if (!ok || width <= 0)
+        return QSize();
+    if (xPos < 0)
+        return QSize(width, width);
+    const int height = r.mid(xPos + 1).toInt(&ok);
+    if (!ok || height <= 0)
+        return QSize();
+    return QSize(width, height);
+}
+
+static void appendSizeSpec(const QSize &size, QString *target)
+{
+    target->append(QString::number(size.width()));
+    if (size.width() != size.height()) {
+        target->append('x');
+        target->append(QString::number(size.height()));
+    }
+}
+
+static inline QString sizeToString(const QSize &size)
+{
+    QString result;
+    appendSizeSpec(size, &result);
+    return result;
+}
+
+static QString sizesToString(const QVector &sizes)
+{
+    QString result;
+    for (int i = 0, size = sizes.size(); i < size; ++i) {
+        if (i)
+            result.append(',');
+        appendSizeSpec(sizes.at(i), &result);
+    }
+    return result;
+}
+
+static QVector stringToSizes(const QString &s)
+{
+    QVector result;
+    const QString trimmed = s.trimmed();
+    const QVector &sizes = trimmed.splitRef(',', QString::SkipEmptyParts);
+    result.reserve(sizes.size());
+    for (const QStringRef &sizeSpec : sizes) {
+        const QSize size = sizeFromString(sizeSpec);
+        if (!size.isValid() || size.isEmpty())
+            return QVector();
+        else
+            result.append(size);
+    }
+    return result;
+}
+
+static QString fileNameForSize(QString pattern, const QSize &s)
+{
+    pattern.replace("%1", QString::number(s.width()));
+    pattern.replace("%2", QString::number(s.height()));
+    return pattern;
+}
+
+// Helpers for writing/reading the user-specified size specifications
+// from/to the settings.
+static inline QString settingsGroup() { return QStringLiteral("ExportSvgSizes"); }
+
+static QVector readSettings(const QSize &size)
+{
+    QVector result;
+    QSettings *settings = Core::ICore::settings();
+    settings->beginGroup(settingsGroup());
+    const QStringList keys = settings->allKeys();
+    const int idx = keys.indexOf(sizeToString(size));
+    if (idx >= 0)
+        result = stringToSizes(settings->value(keys.at(idx)).toString());
+    settings->endGroup();
+    return result;
+}
+
+static void writeSettings(const QSize &size, const QString &sizeSpec)
+{
+    QSettings *settings = Core::ICore::settings();
+    settings->beginGroup(settingsGroup());
+    const QString spec = sizeToString(size);
+    settings->setValue(spec, QVariant(sizeSpec));
+
+    // Limit the number of sizes to 10. Remove the
+    // first element unless it is the newly added spec.
+    QStringList keys = settings->allKeys();
+    while (keys.size() > 10) {
+        const int existingIndex = keys.indexOf(spec);
+        const int removeIndex = existingIndex == 0 ? 1 : 0;
+        settings->remove(keys.takeAt(removeIndex));
+    }
+    settings->endGroup();
+}
+
+QVector MultiExportDialog::standardIconSizes()
+{
+    QVector result;
+    const int size = int(sizeof(standardIconSizesValues) / sizeof(standardIconSizesValues[0]));
+    result.reserve(size);
+    for (int i = 0; i < size; ++i)
+        result.append(QSize(standardIconSizesValues[i], standardIconSizesValues[i]));
+    return result;
+}
+
+// --- MultiExportDialog
+MultiExportDialog::MultiExportDialog(QWidget *parent)
+    : QDialog(parent)
+    , m_pathChooser(new Utils::PathChooser(this))
+    , m_sizesLineEdit(new QLineEdit)
+{
+    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+    QFormLayout *formLayout = new QFormLayout(this);
+
+    m_pathChooser->setMinimumWidth(QApplication::desktop()->availableGeometry(this).width() / 5);
+    m_pathChooser->setExpectedKind(Utils::PathChooser::SaveFile);
+    m_pathChooser->setPromptDialogFilter(ExportDialog::imageNameFilterString());
+    const QString pathChooserToolTip =
+        tr("Enter a file name containing place holders %1 "
+           "which will be replaced by the width and height of the image, respectively.")
+          .arg("%1, %2");
+    m_pathChooser->setToolTip(pathChooserToolTip);
+    QLabel *pathChooserLabel = new QLabel(tr("File:"));
+    pathChooserLabel->setToolTip(pathChooserToolTip);
+    formLayout->addRow(pathChooserLabel, m_pathChooser);
+
+    QToolButton *sizeEditButton = new QToolButton;
+    sizeEditButton->setFocusPolicy(Qt::NoFocus);
+    sizeEditButton->setIcon(Utils::Icons::ARROW_DOWN.icon());
+    QMenu *sizeEditMenu = new QMenu(this);
+    sizeEditMenu->addAction(tr("Clear"),
+                            m_sizesLineEdit, &QLineEdit::clear);
+    sizeEditMenu->addAction(tr("Set Standard Icon Sizes"), this,
+                            &MultiExportDialog::setStandardIconSizes);
+    sizeEditMenu->addAction(tr("Generate Sizes"), this,
+                            &MultiExportDialog::setGeneratedSizes);
+    sizeEditButton->setMenu(sizeEditMenu);
+    sizeEditButton->setPopupMode(QToolButton::InstantPopup);
+
+    const QString sizesToolTip =
+        tr("A comma-separated list of size specifications of the form \"x\".");
+    QLabel *sizesLabel = new QLabel(tr("Sizes:"));
+    sizesLabel->setToolTip(sizesToolTip);
+    formLayout->addRow(sizesLabel, m_sizesLineEdit);
+    m_sizesLineEdit->setToolTip(sizesToolTip);
+    QWidgetAction *optionsAction = new QWidgetAction(this);
+    optionsAction->setDefaultWidget(sizeEditButton);
+    m_sizesLineEdit->addAction(optionsAction, QLineEdit::TrailingPosition);
+
+    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+    connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
+    connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+    formLayout->addRow(buttonBox);
+}
+
+void MultiExportDialog::setSizes(const QVector &s)
+{
+    m_sizesLineEdit->setText(sizesToString(s));
+}
+
+QVector MultiExportDialog::sizes() const
+{
+    return stringToSizes(sizesSpecification());
+}
+
+void MultiExportDialog::setStandardIconSizes()
+{
+    setSizes(standardIconSizes());
+}
+
+void MultiExportDialog::setGeneratedSizes()
+{
+    QVector sizes;
+    if (m_svgSize.width() >= 16)
+        sizes.append(m_svgSize / 2);
+    sizes.append(m_svgSize);
+    for (int factor = 2; sizes.size() < 4; factor *= 2)
+        sizes.append(m_svgSize * factor);
+    setSizes(sizes);
+}
+
+void MultiExportDialog::suggestSizes()
+{
+    const QVector settingsEntries = readSettings(m_svgSize);
+    if (!settingsEntries.isEmpty())
+        setSizes(settingsEntries);
+    else if (m_svgSize.width() == m_svgSize.height()) // Square: Assume this is an icon
+        setStandardIconSizes();
+    else
+        setGeneratedSizes();
+}
+
+QVector MultiExportDialog::exportData() const
+{
+    const QVector sizeList = sizes();
+    const QString pattern = exportFileName();
+     QVector result;
+     result.reserve(sizeList.size());
+     for (const QSize &s : sizeList)
+         result.append({fileNameForSize(pattern, s), s});
+     return result;
+}
+
+QString MultiExportDialog::sizesSpecification() const
+{
+    return m_sizesLineEdit->text().trimmed();
+}
+
+void MultiExportDialog::accept()
+{
+    if (!m_pathChooser->isValid()) {
+        QMessageBox::warning(this, windowTitle(), m_pathChooser->errorMessage());
+        return;
+    }
+
+    const QString &sizeSpec = sizesSpecification();
+    if (sizeSpec.isEmpty()) {
+        QMessageBox::warning(this, windowTitle(), tr("Please specify some sizes."));
+        return;
+    }
+
+    const QVector &data = exportData();
+    if (data.isEmpty()) {
+        QMessageBox::warning(this, windowTitle(),
+                             tr("Invalid size specification: %1").arg(sizeSpec));
+        return;
+    }
+    if (data.size() > 1 && data.at(0).fileName == data.at(1).fileName) {
+        QMessageBox::warning(this, windowTitle(),
+                             tr("The file name must contain one of the placeholders %1, %2.").arg("%1", "%2"));
+        return;
+    }
+
+    writeSettings(m_svgSize, sizeSpec);
+
+    QStringList existingFiles;
+    for (const ExportData &d : data) {
+        if (QFileInfo::exists(d.fileName))
+            existingFiles.append(d.fileName);
+    }
+    if (!existingFiles.isEmpty()) {
+        const QString message = existingFiles.size() == 1
+            ? tr("The file %1 already exists.\nWould you like to overwrite it?")
+                .arg(QDir::toNativeSeparators(existingFiles.constFirst()))
+            : tr("The files %1 already exist.\nWould you like to overwrite them?")
+                .arg(QDir::toNativeSeparators(existingFiles.join(", ")));
+        QMessageBox messageBox(QMessageBox::Question, windowTitle(), message,
+                               QMessageBox::Yes | QMessageBox::No, this);
+        if (messageBox.exec() != QMessageBox::Yes)
+            return;
+    }
+
+    QDialog::accept();
+}
+
+QString MultiExportDialog::exportFileName() const
+{
+    return m_pathChooser->fileName().toString();
+}
+
+void MultiExportDialog::setExportFileName(QString f)
+{
+    const int lastDot = f.lastIndexOf('.');
+    if (lastDot != -1)
+        f.insert(lastDot, "-%1");
+    m_pathChooser->setFileName(Utils::FileName::fromString(f));
+}
+
+} // namespace Internal
+} // namespace ImageViewer
diff --git a/src/plugins/imageviewer/multiexportdialog.h b/src/plugins/imageviewer/multiexportdialog.h
new file mode 100644
index 00000000000..cb78c3347ae
--- /dev/null
+++ b/src/plugins/imageviewer/multiexportdialog.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include 
+
+#include 
+#include 
+#include 
+
+QT_FORWARD_DECLARE_CLASS(QLineEdit)
+
+namespace Utils { class PathChooser; }
+
+namespace ImageViewer {
+namespace Internal {
+
+struct ExportData;
+
+class MultiExportDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit MultiExportDialog(QWidget *parent = nullptr);
+
+    QString exportFileName() const;
+    void setExportFileName(QString);
+
+    void accept() override;
+
+    void setSizes(const QVector &);
+    QVector sizes() const;
+
+    QVector exportData() const;
+
+    static QVector standardIconSizes();
+
+    QSize svgSize() const { return m_svgSize; }
+    void setSvgSize(const QSize &svgSize) { m_svgSize = svgSize; }
+
+public slots:
+    void setStandardIconSizes();
+    void setGeneratedSizes();
+    void suggestSizes();
+
+private:
+    QString sizesSpecification() const;
+
+    Utils::PathChooser *m_pathChooser;
+    QLineEdit *m_sizesLineEdit;
+    QSize m_svgSize;
+
+};
+
+} // namespace Internal
+} // namespace ImageViewer
diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg
index 2fd16a1b7ae..32639a51b02 100644
--- a/src/tools/icons/qtcreatoricons.svg
+++ b/src/tools/icons/qtcreatoricons.svg
@@ -9068,4 +9068,40 @@
        inkscape:connector-curvature="0"
        sodipodi:nodetypes="ccccccccc" />
   
+  
+    
+    
+  
+  
+    
+    
+