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