QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsratiolockbutton.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsratiolockbutton.cpp - Lock button
3 --------------------------------------
4 Date : July, 2017
5 Copyright : (C) 2017 by Mathieu Pellerin
6 Email : nirvn dot asia at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsratiolockbutton.h"
17#include "moc_qgsratiolockbutton.cpp"
18#include "qgsapplication.h"
19#include "qgssvgcache.h"
20#include "qgis.h"
21
22#include <QApplication>
23#include <QMouseEvent>
24#include <QPainter>
25#include <QPushButton>
26#include <QWidget>
27#include <QDoubleSpinBox>
28
30 : QToolButton( parent )
31{
32 setMinimumSize( QSize( 24, 24 ) );
33 setMaximumWidth( fontMetrics().horizontalAdvance( '0' ) * 3 );
34 setCheckable( true );
35 setAutoRaise( true );
36 connect( this, &QPushButton::clicked, this, &QgsRatioLockButton::buttonClicked );
37}
38
39void QgsRatioLockButton::setLocked( const bool locked )
40{
41 if ( mLocked != locked )
42 buttonClicked();
43}
44
45void QgsRatioLockButton::buttonClicked()
46{
47 mLocked = !mLocked;
48 setChecked( mLocked );
49
50 emit lockChanged( mLocked );
51
52 drawButton();
53}
54
55void QgsRatioLockButton::widthSpinBoxChanged( double value )
56{
57 if ( mUpdatingRatio || qgsDoubleNear( value, 0.0 ) || qgsDoubleNear( mPrevWidth, 0.0 )
58 || qgsDoubleNear( mPrevHeight, 0.0 ) || !mHeightSpinBox || !mLocked )
59 {
60 mPrevWidth = value;
61 return;
62 }
63
64 const double oldRatio = mPrevHeight / mPrevWidth;
65 mUpdatingRatio = true;
66 mHeightSpinBox->setValue( oldRatio * value );
67 mUpdatingRatio = false;
68 mPrevWidth = value;
69}
70
71void QgsRatioLockButton::heightSpinBoxChanged( double value )
72{
73 if ( mUpdatingRatio || qgsDoubleNear( value, 0.0 ) || qgsDoubleNear( mPrevWidth, 0.0 )
74 || qgsDoubleNear( mPrevHeight, 0.0 ) || !mWidthSpinBox || !mLocked )
75 {
76 mPrevHeight = value;
77 return;
78 }
79
80 const double oldRatio = mPrevWidth / mPrevHeight;
81 mUpdatingRatio = true;
82 mWidthSpinBox->setValue( oldRatio * value );
83 mUpdatingRatio = false;
84 mPrevHeight = value;
85}
86
88{
89 if ( e->type() == QEvent::EnabledChange )
90 {
91 drawButton();
92 }
93 QToolButton::changeEvent( e );
94}
95
96void QgsRatioLockButton::showEvent( QShowEvent *e )
97{
98 drawButton();
99 QToolButton::showEvent( e );
100}
101
102void QgsRatioLockButton::resizeEvent( QResizeEvent *event )
103{
104 QToolButton::resizeEvent( event );
105 drawButton();
106}
107
108void QgsRatioLockButton::drawButton()
109{
110 QSize currentIconSize;
111
112#ifdef Q_OS_WIN
113 currentIconSize = QSize( width() - 10, height() - 6 );
114#else
115 currentIconSize = QSize( width() - 10, height() - 12 );
116#endif
117
118 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
119 {
120 return;
121 }
122
123 const double pixelRatio = devicePixelRatioF();
124 QPixmap pm( currentIconSize * pixelRatio );
125 pm.setDevicePixelRatio( pixelRatio );
126 pm.fill( Qt::transparent );
127
128 QPainter painter;
129 QPen pen = QPen( QColor( 136, 136, 136 ) );
130 pen.setWidth( 2 );
131
132 painter.begin( &pm );
133 painter.setRenderHint( QPainter::Antialiasing, true );
134 painter.setPen( pen );
135
136 painter.drawLine( QPointF( 1, 1 ), QPointF( currentIconSize.width() / 2, 1 ) );
137 painter.drawLine( QPointF( currentIconSize.width() / 2, 1 ), QPointF( currentIconSize.width() / 2, currentIconSize.height() / 2 - 13 ) );
138 painter.drawLine( QPointF( currentIconSize.width() / 2, currentIconSize.height() / 2 + 13 ), QPointF( currentIconSize.width() / 2, currentIconSize.height() - 2 ) );
139 painter.drawLine( QPointF( currentIconSize.width() / 2, currentIconSize.height() - 2 ), QPointF( 1, currentIconSize.height() - 2 ) );
140
141 const QString imageSource = mLocked ? QStringLiteral( ":/images/themes/default/lockedGray.svg" ) : QStringLiteral( ":/images/themes/default/unlockedGray.svg" );
142 bool fitsInCache = false;
143 QImage image = QgsApplication::svgCache()->svgAsImage(
144 imageSource, 16 * pixelRatio, QColor(), QColor(), 0, 1, fitsInCache
145 );
146 image.setDevicePixelRatio( pixelRatio );
147 painter.drawImage( QRectF( currentIconSize.width() / 2 - 8, currentIconSize.height() / 2 - 8, 16, 16 ), image );
148
149 painter.end();
150
151 setIconSize( currentIconSize );
152 setIcon( pm );
153}
154
155void QgsRatioLockButton::setWidthSpinBox( QDoubleSpinBox *widget )
156{
157 mWidthSpinBox = widget;
158 mPrevWidth = widget->value();
159 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRatioLockButton::widthSpinBoxChanged );
160}
161
162void QgsRatioLockButton::setHeightSpinBox( QDoubleSpinBox *widget )
163{
164 mHeightSpinBox = widget;
165 mPrevHeight = widget->value();
166 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRatioLockButton::heightSpinBoxChanged );
167}
168
170{
171 mPrevWidth = mWidthSpinBox ? mWidthSpinBox->value() : 0.0;
172 mPrevHeight = mHeightSpinBox ? mHeightSpinBox->value() : 0.0;
173}
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
void setHeightSpinBox(QDoubleSpinBox *widget)
Registers a spin box widget as the linked "height" spin box.
void setLocked(bool locked)
Sets whether the button state is locked.
void resetRatio()
Resets the current width/height ratio, taking the width and height from the current values of the wid...
void changeEvent(QEvent *e) override
void resizeEvent(QResizeEvent *event) override
QgsRatioLockButton(QWidget *parent=nullptr)
Construct a new ratio lock button.
void showEvent(QShowEvent *e) override
void lockChanged(bool locked)
Emitted whenever the lock state changes.
void setWidthSpinBox(QDoubleSpinBox *widget)
Registers a spin box widget as the linked "width" spin box.
QImage svgAsImage(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >())
Returns an SVG drawing as a QImage.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6066