QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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 ) || qgsDoubleNear( mPrevHeight, 0.0 ) || !mHeightSpinBox || !mLocked )
63 {
64 mPrevWidth = value;
65 return;
66 }
67
68 const double oldRatio = mPrevHeight / mPrevWidth;
69 mUpdatingRatio = true;
70 mHeightSpinBox->setValue( oldRatio * value );
71 mUpdatingRatio = false;
72 mPrevWidth = value;
73}
74
75void QgsRatioLockButton::heightSpinBoxChanged( double value )
76{
77 if ( mUpdatingRatio || qgsDoubleNear( value, 0.0 ) || qgsDoubleNear( mPrevWidth, 0.0 ) || qgsDoubleNear( mPrevHeight, 0.0 ) || !mWidthSpinBox || !mLocked )
78 {
79 mPrevHeight = value;
80 return;
81 }
82
83 const double oldRatio = mPrevWidth / mPrevHeight;
84 mUpdatingRatio = true;
85 mWidthSpinBox->setValue( oldRatio * value );
86 mUpdatingRatio = false;
87 mPrevHeight = value;
88}
89
91{
92 if ( e->type() == QEvent::EnabledChange )
93 {
94 drawButton();
95 }
96 QToolButton::changeEvent( e );
97}
98
99void QgsRatioLockButton::showEvent( QShowEvent *e )
100{
101 drawButton();
102 QToolButton::showEvent( e );
103}
104
105void QgsRatioLockButton::resizeEvent( QResizeEvent *event )
106{
107 QToolButton::resizeEvent( event );
108 drawButton();
109}
110
111void QgsRatioLockButton::drawButton()
112{
113 QSize currentIconSize;
114
115#ifdef Q_OS_WIN
116 currentIconSize = QSize( width() - 10, height() - 6 );
117#else
118 currentIconSize = QSize( width() - 10, height() - 12 );
119#endif
120
121 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
122 {
123 return;
124 }
125
126 const double pixelRatio = devicePixelRatioF();
127 QPixmap pm( currentIconSize * pixelRatio );
128 pm.setDevicePixelRatio( pixelRatio );
129 pm.fill( Qt::transparent );
130
131 QPainter painter;
132 QPen pen = QPen( QColor( 136, 136, 136 ) );
133 pen.setWidth( 2 );
134
135 painter.begin( &pm );
136 painter.setRenderHint( QPainter::Antialiasing, true );
137 painter.setPen( pen );
138
139 painter.drawLine( QPointF( 1, 1 ), QPointF( currentIconSize.width() / 2, 1 ) );
140 painter.drawLine( QPointF( currentIconSize.width() / 2, 1 ), QPointF( currentIconSize.width() / 2, currentIconSize.height() / 2 - 13 ) );
141 painter.drawLine( QPointF( currentIconSize.width() / 2, currentIconSize.height() / 2 + 13 ), QPointF( currentIconSize.width() / 2, currentIconSize.height() - 2 ) );
142 painter.drawLine( QPointF( currentIconSize.width() / 2, currentIconSize.height() - 2 ), QPointF( 1, currentIconSize.height() - 2 ) );
143
144 const QString imageSource = mLocked ? u":/images/themes/default/lockedGray.svg"_s : u":/images/themes/default/unlockedGray.svg"_s;
145 bool fitsInCache = false;
146 QImage image = QgsApplication::svgCache()->svgAsImage( imageSource, 16 * pixelRatio, QColor(), QColor(), 0, 1, fitsInCache );
147 image.setDevicePixelRatio( pixelRatio );
148 painter.drawImage( QRectF( currentIconSize.width() / 2 - 8, currentIconSize.height() / 2 - 8, 16, 16 ), image );
149
150 painter.end();
151
152 setIconSize( currentIconSize );
153 setIcon( pm );
154}
155
156void QgsRatioLockButton::setWidthSpinBox( QDoubleSpinBox *widget )
157{
158 mWidthSpinBox = widget;
159 mPrevWidth = widget->value();
160 connect( mWidthSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRatioLockButton::widthSpinBoxChanged );
161}
162
163void QgsRatioLockButton::setHeightSpinBox( QDoubleSpinBox *widget )
164{
165 mHeightSpinBox = widget;
166 mPrevHeight = widget->value();
167 connect( mHeightSpinBox, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsRatioLockButton::heightSpinBoxChanged );
168}
169
171{
172 mPrevWidth = mWidthSpinBox ? mWidthSpinBox->value() : 0.0;
173 mPrevHeight = mHeightSpinBox ? mHeightSpinBox->value() : 0.0;
174}
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:6975