Skip to content
Permalink
Browse files

[FEATURE] Locked aspect ratio state for Save as image/PDF" (#4880)

Sponsored by Andreas Neumann.
  • Loading branch information
nirvn committed Jul 19, 2017
1 parent 08c06de commit 0665072d940056f03e78ecbab6755657210b4e08
@@ -467,6 +467,7 @@
<file>themes/default/transformed.svg</file>
<file>themes/default/transp-background_8x8.png</file>
<file>themes/default/unlocked.svg</file>
<file>themes/default/unlockedGray.svg</file>
<file>themes/default/user.svg</file>
<file>flags/eu.png</file>
<file>flags/bn.png</file>
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" viewBox="0 0 16 16" width="16"><path d="M6 3.216c.665-.947 2.307-2.405 4.562-1.01 2.37 1.637 1.974 3.68-.04 6.93" fill="none" stroke="#888a85" stroke-width="3" stroke-linecap="square" stroke-linejoin="round"/><path d="M6 3.216C7 2 8.193.57 10.562 2.206c2.37 1.637 1.974 3.68-.04 6.93" fill="none" stroke="#eeeeec" stroke-linecap="square" stroke-linejoin="round"/><rect y="8.5" x="2.5" width="11" ry="1" rx=".846" height="7" fill="#666" stroke="#666" stroke-linecap="square"/></svg>
@@ -124,6 +124,7 @@
%Include qgslistwidget.sip
%Include qgslegendfilterbutton.sip
%Include qgslimitedrandomcolorrampdialog.sip
%Include qgsratiolockbutton.sip
%Include qgslonglongvalidator.sip
%Include qgsludialog.sip
%Include qgsmanageconnectionsdialog.sip
@@ -163,6 +163,24 @@ class QgsExtentGroupBox : QgsCollapsibleGroupBox
.. versionadded:: 3.0
%End

void setRatio( QSize ratio );
%Docstring
Sets a fixed aspect ratio to be used when dragging extent onto the canvas.
To unset a fixed aspect ratio, set the width and height to zero.
\param ratio aspect ratio's width and height
.. versionadded:: 3.0
*
%End

QSize ratio() const;
%Docstring
Returns the current fixed aspect ratio to be used when dragging extent onto the canvas.
If the aspect ratio isn't fixed, the width and height will be set to zero.
.. versionadded:: 3.0
*
:rtype: QSize
%End

signals:

void extentChanged( const QgsRectangle &r );
@@ -0,0 +1,69 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsratiolockbutton.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsRatioLockButton : QToolButton
{
%Docstring
A cross platform button subclass used to represent a locked / unlocked ratio state.
.. versionadded:: 3.0
%End

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

QgsRatioLockButton( QWidget *parent /TransferThis/ = 0 );
%Docstring
Construct a new ratio lock button.
Use ``parent`` to attach a parent QWidget to the button.
%End

void setLocked( const bool locked );
%Docstring
Sets whether the button state is locked.
\param locked locked state
.. seealso:: locked
%End

bool locked() const;
%Docstring
Returns whether the button state is locked.
:return: true if the button state is locked.
.. seealso:: setLocked
:rtype: bool
%End

signals:

void lockChanged( const bool locked );
%Docstring
Emitted whenever the lock state changes.
%End

protected:

virtual void changeEvent( QEvent *e );

virtual void showEvent( QShowEvent *e );

virtual void resizeEvent( QResizeEvent *event );


};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsratiolockbutton.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -81,6 +81,7 @@ QgsMapSaveDialog::QgsMapSaveDialog( QWidget *parent, QgsMapCanvas *mapCanvas, QL
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 );
connect( mLockAspectRatio, &QgsRatioLockButton::lockChanged, this, &QgsMapSaveDialog::lockChanged );

updateOutputSize();

@@ -126,25 +127,51 @@ void QgsMapSaveDialog::updateOutputWidth( int width )
double scale = ( double )width / mSize.width();
double adjustment = ( ( mExtent.width() * scale ) - mExtent.width() ) / 2;

mSize.setWidth( width );

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

whileBlocking( mExtentGroupBox )->setOutputExtentFromUser( mExtent, mExtentGroupBox->currentCrs() );
if ( mLockAspectRatio->locked() )
{
int height = width * mExtentGroupBox->ratio().height() / mExtentGroupBox->ratio().width();
double scale = ( double )height / mSize.height();
double adjustment = ( ( mExtent.height() * scale ) - mExtent.height() ) / 2;

mSize.setWidth( width );
whileBlocking( mOutputHeightSpinBox )->setValue( height );
mSize.setHeight( height );

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

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

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

mSize.setHeight( height );

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

whileBlocking( mExtentGroupBox )->setOutputExtentFromUser( mExtent, mExtentGroupBox->currentCrs() );
if ( mLockAspectRatio->locked() )
{
int width = height * mExtentGroupBox->ratio().width() / mExtentGroupBox->ratio().height();
double scale = ( double )width / mSize.width();
double adjustment = ( ( mExtent.width() * scale ) - mExtent.width() ) / 2;

mSize.setHeight( height );
whileBlocking( mOutputWidthSpinBox )->setValue( height );
mSize.setWidth( width );

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

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

void QgsMapSaveDialog::updateExtent( const QgsRectangle &extent )
@@ -153,6 +180,11 @@ void QgsMapSaveDialog::updateExtent( const QgsRectangle &extent )
mSize.setHeight( mSize.height() * extent.height() / mExtent.height() );
mExtent = extent;

if ( mLockAspectRatio->locked() )
{
mExtentGroupBox->setRatio( QSize( mSize.width(), mSize.height() ) );
}

updateOutputSize();
}

@@ -242,6 +274,18 @@ void QgsMapSaveDialog::applyMapSettings( QgsMapSettings &mapSettings )
mapSettings.setExpressionContext( expressionContext );
}

void QgsMapSaveDialog::lockChanged( const bool locked )
{
if ( locked )
{
mExtentGroupBox->setRatio( QSize( mOutputWidthSpinBox->value(), mOutputHeightSpinBox->value() ) );
}
else
{
mExtentGroupBox->setRatio( QSize( 0, 0 ) );
}
}

void QgsMapSaveDialog::accepted()
{
if ( mDialogType == Image )
@@ -77,6 +77,7 @@ class APP_EXPORT QgsMapSaveDialog: public QDialog, private Ui::QgsMapSaveDialog

private:

void lockChanged( const bool locked );
void accepted();

void updateDpi( int dpi );
@@ -263,6 +263,7 @@ SET(QGIS_GUI_SRCS
qgslistwidget.cpp
qgslegendfilterbutton.cpp
qgslimitedrandomcolorrampdialog.cpp
qgsratiolockbutton.cpp
qgsludialog.cpp
qgsmanageconnectionsdialog.cpp
qgsmapcanvas.cpp
@@ -421,6 +422,7 @@ SET(QGIS_GUI_MOC_HDRS
qgslistwidget.h
qgslegendfilterbutton.h
qgslimitedrandomcolorrampdialog.h
qgsratiolockbutton.h
qgslonglongvalidator.h
qgsludialog.h
qgsmanageconnectionsdialog.h
@@ -277,6 +277,7 @@ void QgsExtentGroupBox::setOutputExtentFromDrawOnCanvas()
mMapToolPrevious = nullptr;
} );
}
mMapToolExtent->setRatio( mRatio );
mCanvas->setMapTool( mMapToolExtent.get() );
window()->setVisible( false );
}
@@ -177,6 +177,19 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
*/
void setOutputExtentFromDrawOnCanvas();

/** Sets a fixed aspect ratio to be used when dragging extent onto the canvas.
* To unset a fixed aspect ratio, set the width and height to zero.
* \param ratio aspect ratio's width and height
* \since QGIS 3.0
* */
void setRatio( QSize ratio ) { mRatio = ratio; }

/** Returns the current fixed aspect ratio to be used when dragging extent onto the canvas.
* If the aspect ratio isn't fixed, the width and height will be set to zero.
* \since QGIS 3.0
* */
QSize ratio() const { return mRatio; }

signals:

/**
@@ -223,6 +236,7 @@ class GUI_EXPORT QgsExtentGroupBox : public QgsCollapsibleGroupBox, private Ui::
std::unique_ptr< QgsMapToolExtent > mMapToolExtent;
QPointer< QgsMapTool > mMapToolPrevious = nullptr;
QgsMapCanvas *mCanvas = nullptr;
QSize mRatio;

void setExtentToLayerExtent( const QString &layerId );

@@ -0,0 +1,110 @@
/***************************************************************************
qgsratiolockbutton.cpp - Lock button
--------------------------------------
Date : July, 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 "qgsratiolockbutton.h"

#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
#include <QPushButton>
#include <QWidget>

QgsRatioLockButton::QgsRatioLockButton( QWidget *parent )
: QToolButton( parent )
, mLocked( false )

{
setMinimumSize( QSize( 24, 24 ) );
setCheckable( true );
setAutoRaise( true );
connect( this, &QPushButton::clicked, this, &QgsRatioLockButton::buttonClicked );
}

void QgsRatioLockButton::setLocked( const bool locked )
{
if ( mLocked != locked )
buttonClicked();
}

void QgsRatioLockButton::buttonClicked()
{
mLocked = !mLocked;
setDown( mLocked );

emit lockChanged( mLocked );

drawButton();
}

void QgsRatioLockButton::changeEvent( QEvent *e )
{
if ( e->type() == QEvent::EnabledChange )
{
drawButton();
}
QToolButton::changeEvent( e );
}

void QgsRatioLockButton::showEvent( QShowEvent *e )
{
drawButton();
QToolButton::showEvent( e );
}

void QgsRatioLockButton::resizeEvent( QResizeEvent *event )
{
QToolButton::resizeEvent( event );
drawButton();
}

void QgsRatioLockButton::drawButton()
{
QSize currentIconSize;

#ifdef Q_OS_WIN
currentIconSize = QSize( width() - 10, height() - 6 );
#else
currentIconSize = QSize( width() - 10, height() - 12 );
#endif

if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
{
return;
}

QPixmap pm;
pm = QPixmap( currentIconSize );
pm.fill( Qt::transparent );

QPainter painter;
QPen pen = ( QColor( 136, 136, 136 ) );
pen.setWidth( 2 );

painter.begin( &pm );
painter.setPen( pen );

painter.drawLine( 1, 1, currentIconSize.width() / 2, 1 );
painter.drawLine( currentIconSize.width() / 2, 1, currentIconSize.width() / 2, currentIconSize.height() / 2 - 13 );
painter.drawLine( currentIconSize.width() / 2, currentIconSize.height() / 2 + 13, currentIconSize.width() / 2, currentIconSize.height() - 2 );
painter.drawLine( currentIconSize.width() / 2, currentIconSize.height() - 2, 1, currentIconSize.height() - 2 );

QImage image( mLocked ? QStringLiteral( ":/images/themes/default/lockedGray.svg" ) : QStringLiteral( ":/images/themes/default/unlockedGray.svg" ) );
painter.drawImage( QRectF( currentIconSize.width() / 2 - 8, currentIconSize.height() / 2 - 8, 16, 16 ), image, QRectF( 0, 0, 16, 16 ) );

painter.end();

setIconSize( currentIconSize );
setIcon( pm );
}

0 comments on commit 0665072

Please sign in to comment.
You can’t perform that action at this time.