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