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