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