Skip to content
Permalink
Browse files
Merge pull request #4460 from nirvn/wallpapers
  • Loading branch information
nirvn committed May 2, 2017
2 parents 7d45914 + 295c212 commit 81ccfb0de45593e2fca63f6b62d4ccfc52f7d5af
@@ -100,6 +100,7 @@
%Include qgsmaprenderersequentialjob.sip
%Include qgsmaprenderertask.sip
%Include qgsmapsettings.sip
%Include qgsmapsettingsutils.sip
%Include qgsmaptopixel.sip
%Include qgsmapunitscale.sip
%Include qgsmargins.sip
@@ -52,6 +52,11 @@ class QgsMapRendererTask : QgsTask
Adds ``decorations`` to be rendered on the map.
%End

void setSaveWorldFile( bool save );
%Docstring
Sets whether a world file will be created alongside an image file.
%End

virtual void cancel();


@@ -0,0 +1,43 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsmapsettingsutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsMapSettingsUtils
{
%Docstring
Utilities for map settings.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsmapsettingsutils.h"
%End
public:

static QString worldFileContent( const QgsMapSettings &mapSettings );
%Docstring
Creates the content of a world file.
\param mapSettings map settings
.. note::

Uses 17 places of precision for all numbers output
:rtype: str
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsmapsettingsutils.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -5833,9 +5833,11 @@ void QgisApp::saveMapAsImage()
mapRendererTask->addDecorations( decorations );
}

mapRendererTask->setSaveWorldFile( dlg.saveWorldFile() );

connect( mapRendererTask, &QgsMapRendererTask::renderingComplete, this, [ = ]
{
messageBar()->pushSuccess( tr( "Save as image" ), tr( "Successfully saved canvas to image" ) );
messageBar()->pushSuccess( tr( "Save as image" ), tr( "Successfully saved map to image" ) );
} );
connect( mapRendererTask, &QgsMapRendererTask::errorOccurred, this, [ = ]( int error )
{
@@ -50,6 +50,8 @@ QgsMapSaveDialog::QgsMapSaveDialog( QWidget *parent, QgsMapCanvas *mapCanvas, co
mDrawDecorations->setText( tr( "Draw active decorations: %1" ).arg( !activeDecorations.isEmpty() ? activeDecorations : tr( "none" ) ) );

connect( mResolutionSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsMapSaveDialog::updateDpi );
connect( mOutputWidthSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsMapSaveDialog::updateOutputWidth );
connect( mOutputHeightSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsMapSaveDialog::updateOutputHeight );
connect( mExtentGroupBox, &QgsExtentGroupBox::extentChanged, this, &QgsMapSaveDialog::updateExtent );
connect( mScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsMapSaveDialog::updateScale );

@@ -64,6 +66,32 @@ void QgsMapSaveDialog::updateDpi( int dpi )
updateOutputSize();
}

void QgsMapSaveDialog::updateOutputWidth( int width )
{
double scale = ( double )width / mSize.width();
double adjustment = ( ( mExtent.width() * scale ) - mExtent.width() ) / 2;

mExtent.setXMinimum( mExtent.xMinimum() - adjustment );
mExtent.setXMaximum( mExtent.xMaximum() + adjustment );

whileBlocking( mExtentGroupBox )->setOutputExtentFromUser( mExtent, mExtentGroupBox->currentCrs() );

mSize.setWidth( width );
}

void QgsMapSaveDialog::updateOutputHeight( int height )
{
double scale = ( double )height / mSize.height();
double adjustment = ( ( mExtent.height() * scale ) - mExtent.height() ) / 2;

mExtent.setYMinimum( mExtent.yMinimum() - adjustment );
mExtent.setYMaximum( mExtent.yMaximum() + adjustment );

whileBlocking( mExtentGroupBox )->setOutputExtentFromUser( mExtent, mExtentGroupBox->currentCrs() );

mSize.setHeight( height );
}

void QgsMapSaveDialog::updateExtent( const QgsRectangle &extent )
{
mSize.setWidth( mSize.width() * extent.width() / mExtent.width() );
@@ -87,7 +115,8 @@ void QgsMapSaveDialog::updateScale( double scale )

void QgsMapSaveDialog::updateOutputSize()
{
mOutputSize->setText( tr( "Output size: %1 x %2 pixels" ).arg( mSize.width() ).arg( mSize.height() ) );
whileBlocking( mOutputWidthSpinBox )->setValue( mSize.width() );
whileBlocking( mOutputHeightSpinBox )->setValue( mSize.height() );
}

QgsRectangle QgsMapSaveDialog::extent() const
@@ -114,3 +143,8 @@ bool QgsMapSaveDialog::drawDecorations() const
{
return mDrawDecorations->isChecked();
}

bool QgsMapSaveDialog::saveWorldFile() const
{
return mSaveWorldFile->isChecked();
}
@@ -56,9 +56,14 @@ class APP_EXPORT QgsMapSaveDialog: public QDialog, private Ui::QgsMapSaveDialog
//! returns whether the draw decorations element is checked
bool drawDecorations() const;

//! returns whether a world file will be created
bool saveWorldFile() const;

private:

void updateDpi( int dpi );
void updateOutputWidth( int width );
void updateOutputHeight( int height );
void updateExtent( const QgsRectangle &extent );
void updateScale( double scale );
void updateOutputSize();
@@ -184,6 +184,7 @@ SET(QGIS_CORE_SRCS
qgsmaprenderersequentialjob.cpp
qgsmaprenderertask.cpp
qgsmapsettings.cpp
qgsmapsettingsutils.cpp
qgsmaptopixel.cpp
qgsmaptopixelgeometrysimplifier.cpp
qgsmapunitscale.cpp
@@ -751,6 +752,7 @@ SET(QGIS_CORE_HDRS
qgsmaplayerrenderer.h
qgsmaplayerstylemanager.h
qgsmapsettings.h
qgsmapsettingsutils.h
qgsmaptopixel.h
qgsmaptopixelgeometrysimplifier.h
qgsmapunitscale.h
@@ -18,7 +18,10 @@
#include "qgsannotation.h"
#include "qgsannotationmanager.h"
#include "qgsmaprenderertask.h"
#include "qgsmapsettingsutils.h"

#include <QFile>
#include <QTextStream>

QgsMapRendererTask::QgsMapRendererTask( const QgsMapSettings &ms, const QString &fileName, const QString &fileFormat )
: QgsTask( tr( "Saving as image" ) )
@@ -154,6 +157,23 @@ bool QgsMapRendererTask::run()
mError = ImageSaveFail;
return false;
}

if ( mSaveWorldFile )
{
QFileInfo info = QFileInfo( mFileName );

// build the world file name
QString outputSuffix = info.suffix();
QString worldFileName = info.absolutePath() + '/' + info.baseName() + '.'
+ outputSuffix.at( 0 ) + outputSuffix.at( info.suffix().size() - 1 ) + 'w';
QFile worldFile( worldFileName );

if ( worldFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) //don't use QIODevice::Text
{
QTextStream stream( &worldFile );
stream << QgsMapSettingsUtils::worldFileContent( mMapSettings );
}
}
}

return true;
@@ -73,6 +73,11 @@ class CORE_EXPORT QgsMapRendererTask : public QgsTask
*/
void addDecorations( QList< QgsMapDecoration * > decorations );

/**
* Sets whether a world file will be created alongside an image file.
*/
void setSaveWorldFile( bool save ) { mSaveWorldFile = save; }

void cancel() override;

signals:
@@ -103,6 +108,7 @@ class CORE_EXPORT QgsMapRendererTask : public QgsTask

QString mFileName;
QString mFileFormat;
bool mSaveWorldFile = false;

QList< QgsAnnotation * > mAnnotations;
QList< QgsMapDecoration * > mDecorations;
@@ -0,0 +1,44 @@
/***************************************************************************
qgsmapsettingsutils.cpp
-------------------
begin : May 2017
copyright : (C) 2017 by Mathieu Pellerin
email : nirvn dot asia at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmapsettings.h"
#include "qgsmapsettingsutils.h"

#include <QString>

QString QgsMapSettingsUtils::worldFileContent( const QgsMapSettings &mapSettings )
{
double xOrigin = mapSettings.visiblePolygon().at( 0 ).x() + ( mapSettings.mapUnitsPerPixel() / 2 );
double yOrigin = mapSettings.visiblePolygon().at( 0 ).y() - ( mapSettings.mapUnitsPerPixel() / 2 );

QString content;
// Pixel XDim
content += qgsDoubleToString( mapSettings.mapUnitsPerPixel() ) + "\r\n";
// Rotation on y axis
content += QString( "%1\r\n" ).arg( mapSettings.rotation() );
// Rotation on x axis
content += QString( "%1\r\n" ).arg( mapSettings.rotation() );
// Pixel YDim - almost always negative
// See https://en.wikipedia.org/wiki/World_file#cite_ref-3
content += '-' + qgsDoubleToString( mapSettings.mapUnitsPerPixel() ) + "\r\n";
// Origin X (center of top left cell)
content += qgsDoubleToString( xOrigin ) + "\r\n";
// Origin Y (center of top left cell)
content += qgsDoubleToString( yOrigin ) + "\r\n";

return content;
}
@@ -0,0 +1,43 @@
/***************************************************************************
qgsmapsettingsutils.h
-------------------
begin : May 2017
copyright : (C) 2017 by Mathieu Pellerin
email : nirvn dot asia at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMAPSETTINGSUTILS_H
#define QGSMAPSETTINGSUTILS_H

#include "qgis_core.h"
#include "qgsmapsettings.h"

#include <QString>

/** \ingroup core
* Utilities for map settings.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsMapSettingsUtils
{

public:

/** Creates the content of a world file.
* \param mapSettings map settings
* \note Uses 17 places of precision for all numbers output
*/
static QString worldFileContent( const QgsMapSettings &mapSettings );

};

#endif
@@ -56,6 +56,7 @@ email : sherman at mrcc.com
#include "qgsmaprenderercustompainterjob.h"
#include "qgsmaprendererparalleljob.h"
#include "qgsmaprenderersequentialjob.h"
#include "qgsmapsettingsutils.h"
#include "qgsmessagelog.h"
#include "qgsmessageviewer.h"
#include "qgspallabeling.h"
@@ -723,24 +724,8 @@ void QgsMapCanvas::saveAsImage( const QString &fileName, QPixmap *theQPixmap, co
painter.end();
image.save( fileName, format.toLocal8Bit().data() );

//create a world file to go with the image...
QgsRectangle myRect = mapSettings().visibleExtent();
QString myHeader;
// note: use 17 places of precision for all numbers output
//Pixel XDim
myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
//Rotation on y axis - hard coded
myHeader += QLatin1String( "0 \r\n" );
//Rotation on x axis - hard coded
myHeader += QLatin1String( "0 \r\n" );
//Pixel YDim - almost always negative - see
//http://en.wikipedia.org/wiki/World_file#cite_note-2
myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n";
//Origin X (center of top left cell)
myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
//Origin Y (center of top left cell)
myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n";
QFileInfo myInfo = QFileInfo( fileName );

// build the world file name
QString outputSuffix = myInfo.suffix();
QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.baseName() + '.'
@@ -751,7 +736,7 @@ void QgsMapCanvas::saveAsImage( const QString &fileName, QPixmap *theQPixmap, co
return;
}
QTextStream myStream( &myWorldFile );
myStream << myHeader;
myStream << QgsMapSettingsUtils::worldFileContent( mapSettings() );
} // saveAsImage


0 comments on commit 81ccfb0

Please sign in to comment.