Add SVG multi export

Add a second SVG export option that allows for exporting
a series of icons of various size in one go. A dialog is shown
that allows for entering a file name pattern with place holders
and a list of sizes.

Change-Id: Ic644a9d402aa44af5899c29cf83051fdd7bba3d1
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Diana de Sousa <diana.desousa@theqtcompany.com>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Friedemann Kleint
2018-01-12 15:32:10 +01:00
parent 43936b1e86
commit cd85d3aba5
20 changed files with 612 additions and 35 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

View File

@@ -52,6 +52,10 @@
<file>images/editpaste@2x.png</file>
<file>images/empty14.png</file>
<file>images/empty16.png</file>
<file>images/fileexport.png</file>
<file>images/fileexport@2x.png</file>
<file>images/filemultiexport.png</file>
<file>images/filemultiexport@2x.png</file>
<file>images/filenew.png</file>
<file>images/filenew@2x.png</file>
<file>images/fileopen.png</file>

View File

@@ -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({

View File

@@ -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;

View File

@@ -24,6 +24,7 @@
****************************************************************************/
#include "exportdialog.h"
#include "imageview.h" // ExportData
#include <coreplugin/coreicons.h>
@@ -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

View File

@@ -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);

View File

@@ -51,6 +51,7 @@
#include "imageview.h"
#include "exportdialog.h"
#include "multiexportdialog.h"
#include "imageviewerfile.h"
#include <coreplugin/messagemanager.h>
@@ -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<QGraphicsSvgItem *>(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<QGraphicsSvgItem *>(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<QGraphicsSvgItem *>(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
}

View File

@@ -52,11 +52,18 @@
#include <QGraphicsView>
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);

View File

@@ -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();
}

View File

@@ -55,6 +55,7 @@ public:
IEditor *duplicate() override;
void exportImage();
void exportMultiImages();
void imageSizeUpdated(const QSize &size);
void scaleFactorUpdate(qreal factor);

View File

@@ -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

View File

@@ -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";

View File

@@ -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,

View File

@@ -24,6 +24,13 @@
</property>
</widget>
</item>
<item>
<widget class="Core::CommandButton" name="toolButtonMultiExportImages">
<property name="toolTipBase">
<string>Export Images of Multiple Sizes</string>
</property>
</widget>
</item>
<item>
<widget class="Core::CommandButton" name="toolButtonBackground">
<property name="toolTipBase">
@@ -134,8 +141,5 @@
<header>coreplugin/actionmanager/commandbutton.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="imageviewer.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -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 <coreplugin/coreicons.h>
#include <coreplugin/icore.h>
#include <utils/pathchooser.h>
#include <utils/utilsicons.h>
#include <QApplication>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QMenu>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSpinBox>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidgetAction>
#include <QImageWriter>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QSettings>
#include <QTextStream>
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<QSize> &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<QSize> stringToSizes(const QString &s)
{
QVector<QSize> result;
const QString trimmed = s.trimmed();
const QVector<QStringRef> &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<QSize>();
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<QSize> readSettings(const QSize &size)
{
QVector<QSize> 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<QSize> MultiExportDialog::standardIconSizes()
{
QVector<QSize> 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 \"<width>x<height>\".");
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<QSize> &s)
{
m_sizesLineEdit->setText(sizesToString(s));
}
QVector<QSize> MultiExportDialog::sizes() const
{
return stringToSizes(sizesSpecification());
}
void MultiExportDialog::setStandardIconSizes()
{
setSizes(standardIconSizes());
}
void MultiExportDialog::setGeneratedSizes()
{
QVector<QSize> 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<QSize> 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<ExportData> MultiExportDialog::exportData() const
{
const QVector<QSize> sizeList = sizes();
const QString pattern = exportFileName();
QVector<ExportData> 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<ExportData> &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

View File

@@ -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 <QDialog>
#include <QPair>
#include <QSize>
#include <QVector>
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<QSize> &);
QVector<QSize> sizes() const;
QVector<ExportData> exportData() const;
static QVector<QSize> 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

View File

@@ -9068,4 +9068,40 @@
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
</g>
<g
id="src/libs/utils/images/fileexport"
transform="translate(80)">
<use
x="0"
y="0"
xlink:href="#backgroundRect"
id="use5933-0-4"
width="100%"
height="100%"
transform="translate(1740,132)" />
<path
sodipodi:nodetypes="ccccccccccc"
inkscape:connector-curvature="0"
d="m 1730,572 2.5,-2.5 2.5,2.5 m -2.5,-2 v 8 m -1.5,-4.5 h -3.5 v 8 h 10 v -8 h -3.5"
style="fill:none;stroke:#000000"
id="path6789-4" />
</g>
<g
id="src/libs/utils/images/filemultiexport"
transform="translate(96)">
<use
x="0"
y="0"
xlink:href="#backgroundRect"
id="use5933-0"
width="100%"
height="100%"
transform="translate(1740,132)" />
<path
sodipodi:nodetypes="ccccccccccccccccc"
inkscape:connector-curvature="0"
d="m 1730,572 2.5,-2.5 2.5,2.5 m -2.5,-2 v 7 m -4.5,-1.5 h -1.5 v 6 h 12 v -6 h -1.5 m -6,-2 h -2.5 v 6 h 8 v -6 h -2.5"
style="fill:none;stroke:#000000"
id="path6789" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 323 KiB