QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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
18#include "qgis.h"
19#include "qgsapplication.h"
20#include "qgssvgcache.h"
21
22#include <QApplication>
23#include <QDoubleSpinBox>
24#include <QMouseEvent>
25#include <QPainter>
26#include <QPushButton>
27#include <QWidget>
28
29#include "moc_qgsratiolockbutton.cpp"
30
32 : QToolButton( parent )
33{
34 setMinimumSize( QSize( 24, 24 ) );
35 setMaximumWidth( fontMetrics().horizontalAdvance( '0' ) * 3 );
36 setCheckable( true );
37 setAutoRaise( true );
38 connect( this, &QPushButton::clicked, this, &QgsRatioLockButton::buttonClicked );
39}
40
42{
43 if ( mLocked != locked )
44 buttonClicked();
45}
46
47void QgsRatioLockButton::buttonClicked()
48{
49 mLocked = !mLocked;
50 setChecked( mLocked );
51
52 emit lockChanged( mLocked );
53
54 drawButton();
55}
56
57void QgsRatioLockButton::widthSpinBoxChanged( double value )
58{
59 if ( mUpdatingRatio || qgsDoubleNear( value, 0.0 ) || qgsDoubleNear( mPrevWidth, 0.0 )
60 || qgsDoubleNear( mPrevHeight, 0.0 ) || !mHeightSpinBox || !mLocked )
61 {
62 mPrevWidth = value;
63 return;
64 }
65
66 const double oldRatio = mPrevHeight / mPrevWidth;
67 mUpdatingRatio = true;
68 mHeightSpinBox->setValue( oldRatio * value );
69 mUpdatingRatio = false;
70 mPrevWidth = value;
71}
72
73void QgsRatioLockButton::heightSpinBoxChanged( double value )
74{
75 if ( mUpdatingRatio || qgsDoubleNear( value, 0.0 ) || qgsDoubleNear( mPrevWidth, 0.0 )
76 || qgsDoubleNear( mPrevHeight, 0.0 ) || !mWidthSpinBox || !mLocked )
77 {
78 mPrevHeight = value;
79 return;
80 }
81
82 const double oldRatio = mPrevWidth / mPrevHeight;
83 mUpdatingRatio = true;
84 mWidthSpinBox->setValue( oldRatio * value );
85 mUpdatingRatio = false;
86 mPrevHeight = value;
87}
88
90{
91 if ( e->type() == QEvent::EnabledChange )
92 {
93 drawButton();
94 }
95 QToolButton::changeEvent( e );
96}
97
98void QgsRatioLockButton::showEvent( QShowEvent *e )
99{
100 drawButton();
101 QToolButton::showEvent( e );
102}
103
104void QgsRatioLockButton::resizeEvent( QResizeEvent *event )
105{
106 QToolButton::resizeEvent( event );
107 drawButton();
108}
109
110void QgsRatioLockButton::drawButton()
111{
112 QSize currentIconSize;
113
114#ifdef Q_OS_WIN
115 currentIconSize = QSize( width() - 10, height() - 6 );
116#else
117 currentIconSize = QSize( width() - 10, height() - 12 );
118#endif
119
120 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
121 {
122 return;
123 }
124
125 const double pixelRatio = devicePixelRatioF();
126 QPixmap pm( currentIconSize * pixelRatio );
127 pm.setDevicePixelRatio( pixelRatio );
128 pm.fill( Qt::transparent );
129
130 QPainter painter;
131 QPen pen = QPen( QColor( 136, 136, 136 ) );
132 pen.setWidth( 2 );
133
134 painter.begin( &pm );
135 painter.setRenderHint( QPainter::Antialiasing, true );
136 painter.setPen( pen );
137
138 painter.drawLine( QPointF( 1, 1 ), QPointF( currentIconSize.width() / 2, 1 ) );
139 painter.drawLine( QPointF( currentIconSize.width() / 2, 1 ), QPointF( currentIconSize.width() / 2, currentIconSize.height() / 2 - 13 ) );
140 painter.drawLine( QPointF( currentIconSize.width() / 2, currentIconSize.height() / 2 + 13 ), QPointF( currentIconSize.width() / 2, currentIconSize.height() - 2 ) );
141 painter.drawLine( QPointF( currentIconSize.width() / 2, currentIconSize.height() - 2 ), QPointF( 1, currentIconSize.height() - 2 ) );
142
143 const QString imageSource = mLocked ? QStringLiteral( ":/images/themes/default/lockedGray.svg" ) : QStringLiteral( ":/images/themes/default/unlockedGray.svg" );
144 bool fitsInCache = false;
145 QImage image = QgsApplication::svgCache()->svgAsImage(
146 imageSource, 16 * pixelRatio, QColor(), QColor(), 0, 1, fitsInCache
147 );
148 image.setDevicePixelRatio( pixelRatio );
149 painter.drawImage( QRectF( currentIconSize.width() / 2 - 8, currentIconSize.height() / 2 - 8, 16, 16 ), image );
150
151 painter.end();
152
153 setIconSize( currentIconSize );
154 setIcon( pm );
155}
156
157void QgsRatioLockButton::setWidthSpinBox( QDoubleSpinBox *widget )
158{
159 mWidthSpinBox = widget;
160 mPrevWidth = widget->value();
161 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRatioLockButton::widthSpinBoxChanged );
162}
163
164void QgsRatioLockButton::setHeightSpinBox( QDoubleSpinBox *widget )
165{
166 mHeightSpinBox = widget;
167 mPrevHeight = widget->value();
168 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRatioLockButton::heightSpinBoxChanged );
169}
170
172{
173 mPrevWidth = mWidthSpinBox ? mWidthSpinBox->value() : 0.0;
174 mPrevHeight = mHeightSpinBox ? mHeightSpinBox->value() : 0.0;
175}
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:6607