QGIS API Documentation  3.25.0-Master (dec16ba68b)
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 
36 void QgsRatioLockButton::setLocked( const bool locked )
37 {
38  if ( mLocked != locked )
39  buttonClicked();
40 }
41 
42 void QgsRatioLockButton::buttonClicked()
43 {
44  mLocked = !mLocked;
45  setDown( mLocked );
46 
47  emit lockChanged( mLocked );
48 
49  drawButton();
50 }
51 
52 void 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 
68 void 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 
93 void QgsRatioLockButton::showEvent( QShowEvent *e )
94 {
95  drawButton();
96  QToolButton::showEvent( e );
97 }
98 
99 void QgsRatioLockButton::resizeEvent( QResizeEvent *event )
100 {
101  QToolButton::resizeEvent( event );
102  drawButton();
103 }
104 
105 void 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 
145 void 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 
152 void 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:1990