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