From 217931f9372972c8be86469e920de53d7f0d2384 Mon Sep 17 00:00:00 2001 From: Nathan Woodrow Date: Tue, 7 Jul 2015 07:59:48 +1000 Subject: [PATCH 1/2] Add export as SVG/PNG to style manager --- src/core/symbology-ng/qgsstylev2.cpp | 26 +++++++++++++ src/core/symbology-ng/qgsstylev2.h | 3 ++ .../symbology-ng/qgsstylev2managerdialog.cpp | 39 ++++++++++++++++++- .../symbology-ng/qgsstylev2managerdialog.h | 3 ++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/core/symbology-ng/qgsstylev2.cpp b/src/core/symbology-ng/qgsstylev2.cpp index a08e87e3816..28bd603bfda 100644 --- a/src/core/symbology-ng/qgsstylev2.cpp +++ b/src/core/symbology-ng/qgsstylev2.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -135,6 +136,31 @@ bool QgsStyleV2::saveSymbol( QString name, QgsSymbolV2* symbol, int groupid, QSt return true; } +void QgsStyleV2::exportSymbol( QString folder, QString name, QString format, QSize size ) +{ + QString fullname = folder + "/" + name + "." + format; + QgsSymbolV2 *sym = symbol( name ); + if ( format.toLower() == "svg" ) + { + QSvgGenerator generator; + generator.setFileName( fullname ); + generator.setSize( size ); + generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) ); + generator.setTitle( name ); + generator.setDescription( tr( "Exported symbol from QGIS" ) ); + + + QPainter painter( &generator ); + sym->drawPreviewIcon( &painter, size ); + painter.end(); + } + else + { + QImage image = sym->asImage( size ); + image.save( fullname ); + } +} + bool QgsStyleV2::removeSymbol( QString name ) { QgsSymbolV2 *symbol = mSymbols.take( name ); diff --git a/src/core/symbology-ng/qgsstylev2.h b/src/core/symbology-ng/qgsstylev2.h index eae72ae7054..c2015b0a904 100644 --- a/src/core/symbology-ng/qgsstylev2.h +++ b/src/core/symbology-ng/qgsstylev2.h @@ -167,6 +167,9 @@ class CORE_EXPORT QgsStyleV2 : public QObject */ bool detagSymbol( StyleEntity type, QString symbol, QStringList tags ); + //! export symbol as image + void exportSymbol( QString path, QString name, QString format, QSize size ); + //! remove symbol from style (and delete it) bool removeSymbol( QString name ); diff --git a/src/gui/symbology-ng/qgsstylev2managerdialog.cpp b/src/gui/symbology-ng/qgsstylev2managerdialog.cpp index c6cfe32db35..384f0d9ab0b 100644 --- a/src/gui/symbology-ng/qgsstylev2managerdialog.cpp +++ b/src/gui/symbology-ng/qgsstylev2managerdialog.cpp @@ -40,7 +40,6 @@ #include "qgsapplication.h" #include "qgslogger.h" - QgsStyleV2ManagerDialog::QgsStyleV2ManagerDialog( QgsStyleV2* style, QWidget* parent ) : QDialog( parent ), mStyle( style ), mModified( false ) { @@ -66,10 +65,16 @@ QgsStyleV2ManagerDialog::QgsStyleV2ManagerDialog( QgsStyleV2* style, QWidget* pa connect( btnRemoveItem, SIGNAL( clicked() ), this, SLOT( removeItem() ) ); QMenu *shareMenu = new QMenu( tr( "Share Menu" ), this ); + QAction *exportAsPNGAction = shareMenu->addAction( tr( "Export as PNG" ) ); + QAction *exportAsSVGAction = shareMenu->addAction( tr( "Export as SVG" ) ); QAction *exportAction = shareMenu->addAction( tr( "Export" ) ); QAction *importAction = shareMenu->addAction( tr( "Import" ) ); + exportAsPNGAction->setIcon( QIcon( QgsApplication::iconPath( "mActionSharingExport.svg" ) ) ); + exportAsSVGAction->setIcon( QIcon( QgsApplication::iconPath( "mActionSharingExport.svg" ) ) ); exportAction->setIcon( QIcon( QgsApplication::iconPath( "mActionSharingExport.svg" ) ) ); importAction->setIcon( QIcon( QgsApplication::iconPath( "mActionSharingImport.svg" ) ) ); + connect( exportAsPNGAction, SIGNAL( triggered() ), this, SLOT( exportItemsPNG() ) ); + connect( exportAsSVGAction, SIGNAL( triggered() ), this, SLOT( exportItemsSVG() ) ); connect( exportAction, SIGNAL( triggered() ), this, SLOT( exportItems() ) ); connect( importAction, SIGNAL( triggered() ), this, SLOT( importItems() ) ); btnShare->setMenu( shareMenu ); @@ -730,6 +735,38 @@ void QgsStyleV2ManagerDialog::itemChanged( QStandardItem* item ) } } +void QgsStyleV2ManagerDialog::exportItemsPNG() +{ + QString dir = QFileDialog::getExistingDirectory( this, tr( "Exported selected symbols as PNG" ), + QDir::home().absolutePath(), + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks ); + exportSelectedItemsImages( dir, "png", QSize( 32, 32 ) ); +} + +void QgsStyleV2ManagerDialog::exportItemsSVG() +{ + QString dir = QFileDialog::getExistingDirectory( this, tr( "Exported selected symbols as SVG" ), + QDir::home().absolutePath(), + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks ); + exportSelectedItemsImages( dir, "svg", QSize( 32, 32 ) ); +} + + +void QgsStyleV2ManagerDialog::exportSelectedItemsImages( QString dir, QString format, QSize size ) +{ + if ( dir.isEmpty() ) + return; + + QModelIndexList indexes = listItems->selectionModel()->selection().indexes(); + foreach ( QModelIndex index, indexes ) + { + QString name = index.data().toString(); + mStyle->exportSymbol( dir, name, format, size ); + } +} + void QgsStyleV2ManagerDialog::exportItems() { QgsStyleV2ExportImportDialog dlg( mStyle, this, QgsStyleV2ExportImportDialog::Export ); diff --git a/src/gui/symbology-ng/qgsstylev2managerdialog.h b/src/gui/symbology-ng/qgsstylev2managerdialog.h index 0b7b6c9581f..54281badd43 100644 --- a/src/gui/symbology-ng/qgsstylev2managerdialog.h +++ b/src/gui/symbology-ng/qgsstylev2managerdialog.h @@ -41,6 +41,9 @@ class GUI_EXPORT QgsStyleV2ManagerDialog : public QDialog, private Ui::QgsStyleV void addItem(); void editItem(); void removeItem(); + void exportItemsSVG(); + void exportItemsPNG(); + void exportSelectedItemsImages( QString dir, QString format, QSize size ); void exportItems(); void importItems(); From 659f0d661cf8eea52b23ca6b018ed04cd8848adc Mon Sep 17 00:00:00 2001 From: Nathan Woodrow Date: Tue, 7 Jul 2015 21:59:22 +1000 Subject: [PATCH 2/2] Add exportImage API to QgsSymbol --- python/core/symbology-ng/qgssymbolv2.sip | 4 +++ src/core/symbology-ng/qgsstylev2.cpp | 26 ------------------- src/core/symbology-ng/qgsstylev2.h | 3 --- src/core/symbology-ng/qgssymbolv2.cpp | 21 +++++++++++++++ src/core/symbology-ng/qgssymbolv2.h | 20 ++++++++------ .../symbology-ng/qgsstylev2managerdialog.cpp | 4 ++- 6 files changed, 40 insertions(+), 38 deletions(-) diff --git a/python/core/symbology-ng/qgssymbolv2.sip b/python/core/symbology-ng/qgssymbolv2.sip index 02af3f3fff3..71e4aff7a39 100644 --- a/python/core/symbology-ng/qgssymbolv2.sip +++ b/python/core/symbology-ng/qgssymbolv2.sip @@ -106,6 +106,10 @@ class QgsSymbolV2 //! @note customContext parameter added in 2.6 void drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext = 0 ); + //! export symbol as image format. PNG and SVG supported + void exportImage( QString path, QString format, QSize size ); + + //! Generate symbol as image QImage asImage( QSize size, QgsRenderContext* customContext = 0 ); QImage bigSymbolPreviewImage(); diff --git a/src/core/symbology-ng/qgsstylev2.cpp b/src/core/symbology-ng/qgsstylev2.cpp index 28bd603bfda..a08e87e3816 100644 --- a/src/core/symbology-ng/qgsstylev2.cpp +++ b/src/core/symbology-ng/qgsstylev2.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include @@ -136,31 +135,6 @@ bool QgsStyleV2::saveSymbol( QString name, QgsSymbolV2* symbol, int groupid, QSt return true; } -void QgsStyleV2::exportSymbol( QString folder, QString name, QString format, QSize size ) -{ - QString fullname = folder + "/" + name + "." + format; - QgsSymbolV2 *sym = symbol( name ); - if ( format.toLower() == "svg" ) - { - QSvgGenerator generator; - generator.setFileName( fullname ); - generator.setSize( size ); - generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) ); - generator.setTitle( name ); - generator.setDescription( tr( "Exported symbol from QGIS" ) ); - - - QPainter painter( &generator ); - sym->drawPreviewIcon( &painter, size ); - painter.end(); - } - else - { - QImage image = sym->asImage( size ); - image.save( fullname ); - } -} - bool QgsStyleV2::removeSymbol( QString name ) { QgsSymbolV2 *symbol = mSymbols.take( name ); diff --git a/src/core/symbology-ng/qgsstylev2.h b/src/core/symbology-ng/qgsstylev2.h index c2015b0a904..eae72ae7054 100644 --- a/src/core/symbology-ng/qgsstylev2.h +++ b/src/core/symbology-ng/qgsstylev2.h @@ -167,9 +167,6 @@ class CORE_EXPORT QgsStyleV2 : public QObject */ bool detagSymbol( StyleEntity type, QString symbol, QStringList tags ); - //! export symbol as image - void exportSymbol( QString path, QString name, QString format, QSize size ); - //! remove symbol from style (and delete it) bool removeSymbol( QString name ); diff --git a/src/core/symbology-ng/qgssymbolv2.cpp b/src/core/symbology-ng/qgssymbolv2.cpp index 36e6fc51066..38479425851 100644 --- a/src/core/symbology-ng/qgssymbolv2.cpp +++ b/src/core/symbology-ng/qgssymbolv2.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -352,6 +353,26 @@ void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderConte } } +void QgsSymbolV2::exportImage( QString path, QString format, QSize size ) +{ + if ( format.toLower() == "svg" ) + { + QSvgGenerator generator; + generator.setFileName( path ); + generator.setSize( size ); + generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) ); + + QPainter painter( &generator ); + drawPreviewIcon( &painter, size ); + painter.end(); + } + else + { + QImage image = asImage( size ); + image.save( path ); + } +} + QImage QgsSymbolV2::asImage( QSize size, QgsRenderContext* customContext ) { QImage image( size, QImage::Format_ARGB32_Premultiplied ); diff --git a/src/core/symbology-ng/qgssymbolv2.h b/src/core/symbology-ng/qgssymbolv2.h index 889a769b44c..141c94f5bdd 100644 --- a/src/core/symbology-ng/qgssymbolv2.h +++ b/src/core/symbology-ng/qgssymbolv2.h @@ -87,7 +87,7 @@ class CORE_EXPORT QgsSymbolV2 // symbol layers handling - /**Returns list of symbol layers contained in the symbol. + /** Returns list of symbol layers contained in the symbol. * @returns symbol layers list * @note added in QGIS 2.7 * @see symbolLayer @@ -95,7 +95,7 @@ class CORE_EXPORT QgsSymbolV2 */ QgsSymbolLayerV2List symbolLayers() { return mLayers; } - /**Returns a specific symbol layers contained in the symbol. + /** Returns a specific symbol layers contained in the symbol. * @param layer layer number * @returns corresponding symbol layer * @note added in QGIS 2.7 @@ -104,7 +104,7 @@ class CORE_EXPORT QgsSymbolV2 */ QgsSymbolLayerV2* symbolLayer( int layer ); - /**Returns total number of symbol layers contained in the symbol. + /** Returns total number of symbol layers contained in the symbol. * @returns count of symbol layers * @note added in QGIS 2.7 * @see symbolLayers @@ -138,6 +138,10 @@ class CORE_EXPORT QgsSymbolV2 //! @note customContext parameter added in 2.6 void drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext = 0 ); + //! export symbol as image format. PNG and SVG supported + void exportImage( QString path, QString format, QSize size ); + + //! Generate symbol as image QImage asImage( QSize size, QgsRenderContext* customContext = 0 ); QImage bigSymbolPreviewImage(); @@ -162,7 +166,7 @@ class CORE_EXPORT QgsSymbolV2 void setRenderHints( int hints ) { mRenderHints = hints; } int renderHints() const { return mRenderHints; } - /**Sets whether features drawn by the symbol should be clipped to the render context's + /** Sets whether features drawn by the symbol should be clipped to the render context's * extent. If this option is enabled then features which are partially outside the extent * will be clipped. This speeds up rendering of the feature, but may have undesirable * side effects for certain symbol types. @@ -172,7 +176,7 @@ class CORE_EXPORT QgsSymbolV2 */ void setClipFeaturesToExtent( bool clipFeaturesToExtent ) { mClipFeaturesToExtent = clipFeaturesToExtent; } - /**Returns whether features drawn by the symbol will be clipped to the render context's + /** Returns whether features drawn by the symbol will be clipped to the render context's * extent. If this option is enabled then features which are partially outside the extent * will be clipped. This speeds up rendering of the feature, but may have undesirable * side effects for certain symbol types. @@ -200,7 +204,7 @@ class CORE_EXPORT QgsSymbolV2 SymbolType mType; QgsSymbolLayerV2List mLayers; - /**Symbol opacity (in the range 0 - 1)*/ + /** Symbol opacity (in the range 0 - 1)*/ qreal mAlpha; int mRenderHints; @@ -397,9 +401,9 @@ class CORE_EXPORT QgsFillSymbolV2 : public QgsSymbolV2 private: void renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF &points, QList *rings, QgsSymbolV2RenderContext &context ); - /**Calculates the bounds of a polygon including rings*/ + /** Calculates the bounds of a polygon including rings*/ QRectF polygonBounds( const QPolygonF &points, const QList *rings ) const; - /**Translates the rings in a polygon by a set distance*/ + /** Translates the rings in a polygon by a set distance*/ QList* translateRings( const QList *rings, double dx, double dy ) const; }; diff --git a/src/gui/symbology-ng/qgsstylev2managerdialog.cpp b/src/gui/symbology-ng/qgsstylev2managerdialog.cpp index 384f0d9ab0b..84e313d71b5 100644 --- a/src/gui/symbology-ng/qgsstylev2managerdialog.cpp +++ b/src/gui/symbology-ng/qgsstylev2managerdialog.cpp @@ -763,7 +763,9 @@ void QgsStyleV2ManagerDialog::exportSelectedItemsImages( QString dir, QString fo foreach ( QModelIndex index, indexes ) { QString name = index.data().toString(); - mStyle->exportSymbol( dir, name, format, size ); + QString path = dir + "/" + name + "." + format; + QgsSymbolV2 *sym = mStyle->symbol( name ); + sym->exportImage( path, format, size ); } }