Skip to content

Commit

Permalink
Use QgsFilterLineEdit for Qgs(Double)SpinBox
Browse files Browse the repository at this point in the history
Fixes issues with the current approach:
- poor appearance on certain environments (esp OSX)
- large area on spin boxes' right which "swallows" clicks
and blocks interactivity

Fix #12920
  • Loading branch information
nyalldawson committed Sep 8, 2016
1 parent 228ff23 commit f16b387
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 96 deletions.
40 changes: 31 additions & 9 deletions python/gui/editorwidgets/qgsdoublespinbox.sip
@@ -1,22 +1,40 @@
/** \ingroup gui
* @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
* The clear value can be either the minimum or the maiximum value of the spin box or a custom value.
* This value can then be handled by a special value text.
*/

class QgsDoubleSpinBox : QDoubleSpinBox
{
%TypeHeaderCode
#include <qgsdoublespinbox.h>
%End

public:

//! Behaviour when widget is cleared.
enum ClearValueMode
{
MinimumValue,
MaximumValue,
CustomValue
MinimumValue, //!< Reset value to minimum()
MaximumValue, //!< Reset value to maximum()
CustomValue, //!< Reset value to custom value (see setClearValue() )
};

/** Constructor for QgsDoubleSpinBox.
* @param parent parent widget
*/
explicit QgsDoubleSpinBox( QWidget *parent /TransferThis/ = 0 );

//! determines if the widget will show a clear button
//! @note the clear button will set the widget to its minimum value
/** Sets whether the widget will show a clear button. The clear button
* allows users to reset the widget to a default or empty state.
* @param showClearButton set to true to show the clear button, or false to hide it
* @see showClearButton()
*/
void setShowClearButton( const bool showClearButton );

/** Returns whether the widget is showing a clear button.
* @see setShowClearButton()
*/
bool showClearButton() const;

/** Sets if the widget will allow entry of simple expressions, which are
Expand All @@ -25,6 +43,7 @@ class QgsDoubleSpinBox : QDoubleSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );

/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
Expand All @@ -36,26 +55,29 @@ class QgsDoubleSpinBox : QDoubleSpinBox
virtual void clear();

/**
* @brief setClearValue defines the clear value as a custom value and will automatically set the clear value mode to CustomValue
* Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
* @see setClearValue()
*/
void setClearValue( double customValue, const QString& clearValueText = QString() );

/**
* @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
* Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );

//! returns the value used when clear() is called.
/** Returns the value used when clear() is called.
* @see setClearValue()
*/
double clearValue() const;

virtual double valueFromText( const QString & text ) const;
virtual QValidator::State validate( QString & input, int & pos ) const;

protected:
virtual void resizeEvent( QResizeEvent* event );
virtual void changeEvent( QEvent* event );
virtual void paintEvent( QPaintEvent* event );
};
41 changes: 32 additions & 9 deletions python/gui/editorwidgets/qgsspinbox.sip
@@ -1,22 +1,40 @@
/** \ingroup gui
* @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
* The clear value can be either the minimum or the maiximum value of the spin box or a custom value.
* This value can then be handled by a special value text.
*/

class QgsSpinBox : QSpinBox
{
%TypeHeaderCode
#include <qgsspinbox.h>
%End

public:

//! Behaviour when widget is cleared.
enum ClearValueMode
{
MinimumValue,
MaximumValue,
CustomValue
MinimumValue, //!< Reset value to minimum()
MaximumValue, //!< Reset value to maximum()
CustomValue, //!< Reset value to custom value (see setClearValue() )
};

/** Constructor for QgsSpinBox.
* @param parent parent widget
*/
explicit QgsSpinBox( QWidget *parent /TransferThis/ = 0 );

//! determines if the widget will show a clear button
//! @note the clear button will set the widget to its minimum value
/** Sets whether the widget will show a clear button. The clear button
* allows users to reset the widget to a default or empty state.
* @param showClearButton set to true to show the clear button, or false to hide it
* @see showClearButton()
*/
void setShowClearButton( const bool showClearButton );

/** Returns whether the widget is showing a clear button.
* @see setShowClearButton()
*/
bool showClearButton() const;

/** Sets if the widget will allow entry of simple expressions, which are
Expand All @@ -25,6 +43,7 @@ class QgsSpinBox : QSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );

/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
Expand All @@ -36,26 +55,30 @@ class QgsSpinBox : QSpinBox
virtual void clear();

/**
* @brief setClearValue defines the clear value for the widget and will automatically set the clear value mode to CustomValue
* Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
* @see setClearValue()
*/
void setClearValue( int customValue, const QString& clearValueText = QString() );

/**
* @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
* Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );

//! returns the value used when clear() is called.
/** Returns the value used when clear() is called.
* @see setClearValue()
*/
int clearValue() const;

virtual int valueFromText( const QString & text ) const;
virtual QValidator::State validate( QString & input, int & pos ) const;

protected:
virtual void resizeEvent( QResizeEvent* event );

virtual void changeEvent( QEvent* event );
virtual void paintEvent( QPaintEvent* event );
};
36 changes: 12 additions & 24 deletions src/gui/editorwidgets/qgsdoublespinbox.cpp
Expand Up @@ -17,12 +17,14 @@
#include <QMouseEvent>
#include <QSettings>
#include <QStyle>
#include <QToolButton>

#include "qgsdoublespinbox.h"
#include "qgsexpression.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsfilterlineedit.h"

#define CLEAR_ICON_SIZE 16

QgsDoubleSpinBox::QgsDoubleSpinBox( QWidget *parent )
: QDoubleSpinBox( parent )
Expand All @@ -31,25 +33,22 @@ QgsDoubleSpinBox::QgsDoubleSpinBox( QWidget *parent )
, mCustomClearValue( 0.0 )
, mExpressionsEnabled( true )
{
mClearButton = new QToolButton( this );
mClearButton->setIcon( QgsApplication::getThemeIcon( "/mIconClear.svg" ) );
mClearButton->setCursor( Qt::ArrowCursor );
mClearButton->setStyleSheet( "position: absolute; border: none; padding: 0px;" );
connect( mClearButton, SIGNAL( clicked() ), this, SLOT( clear() ) );
mLineEdit = new QgsSpinBoxLineEdit();

setStyleSheet( QString( "padding-right: %1px;" ).arg( mClearButton->sizeHint().width() + 18 + frameWidth() + 1 ) );
setLineEdit( mLineEdit );

QSize msz = minimumSizeHint();
setMinimumSize( qMax( msz.width(), mClearButton->sizeHint().height() + frameWidth() * 2 + 2 ),
qMax( msz.height(), mClearButton->sizeHint().height() + frameWidth() * 2 + 2 ) );
setMinimumSize( msz.width() + CLEAR_ICON_SIZE + 9 + frameWidth() * 2 + 2,
qMax( msz.height(), CLEAR_ICON_SIZE + frameWidth() * 2 + 2 ) );

connect( mLineEdit, SIGNAL( cleared() ), this, SLOT( clear() ) );
connect( this, SIGNAL( valueChanged( double ) ), this, SLOT( changed( double ) ) );
}

void QgsDoubleSpinBox::setShowClearButton( const bool showClearButton )
{
mShowClearButton = showClearButton;
mClearButton->setVisible( shouldShowClearForValue( value() ) );
mLineEdit->setShowClearButton( showClearButton );
}

void QgsDoubleSpinBox::setExpressionsEnabled( const bool enabled )
Expand All @@ -60,18 +59,18 @@ void QgsDoubleSpinBox::setExpressionsEnabled( const bool enabled )
void QgsDoubleSpinBox::changeEvent( QEvent *event )
{
QDoubleSpinBox::changeEvent( event );
mClearButton->setVisible( shouldShowClearForValue( value() ) );
mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
}

void QgsDoubleSpinBox::paintEvent( QPaintEvent *event )
{
mClearButton->setVisible( shouldShowClearForValue( value() ) );
mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
QDoubleSpinBox::paintEvent( event );
}

void QgsDoubleSpinBox::changed( double value )
{
mClearButton->setVisible( shouldShowClearForValue( value ) );
mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
}

void QgsDoubleSpinBox::clear()
Expand Down Expand Up @@ -187,14 +186,3 @@ bool QgsDoubleSpinBox::shouldShowClearForValue( const double value ) const
}
return value != clearValue();
}

void QgsDoubleSpinBox::resizeEvent( QResizeEvent * event )
{
QDoubleSpinBox::resizeEvent( event );

QSize sz = mClearButton->sizeHint();

mClearButton->move( rect().right() - frameWidth() - 18 - sz.width(),
( rect().bottom() + 1 - sz.height() ) / 2 );

}
48 changes: 32 additions & 16 deletions src/gui/editorwidgets/qgsdoublespinbox.h
Expand Up @@ -13,11 +13,12 @@
* *
***************************************************************************/

#ifndef QGSDOUBLESPPINBOX_H
#define QGSDOUBLESPPINBOX_H
#ifndef QGSDOUBLESPINBOX_H
#define QGSDOUBLESPINBOX_H

#include <QDoubleSpinBox>
#include <QToolButton>

class QgsSpinBoxLineEdit;

/** \ingroup gui
* @brief The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
Expand All @@ -28,21 +29,34 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
{
Q_OBJECT
Q_PROPERTY( bool showClearButton READ showClearButton WRITE setShowClearButton )
Q_PROPERTY( bool clearValue READ clearValue WRITE setClearValue )
Q_PROPERTY( bool expressionsEnabled READ expressionsEnabled WRITE setExpressionsEnabled )

public:

//! Behaviour when widget is cleared.
enum ClearValueMode
{
MinimumValue,
MaximumValue,
CustomValue
MinimumValue, //!< Reset value to minimum()
MaximumValue, //!< Reset value to maximum()
CustomValue, //!< Reset value to custom value (see setClearValue() )
};

/** Constructor for QgsDoubleSpinBox.
* @param parent parent widget
*/
explicit QgsDoubleSpinBox( QWidget *parent = nullptr );

//! determines if the widget will show a clear button
//! @note the clear button will set the widget to its minimum value
/** Sets whether the widget will show a clear button. The clear button
* allows users to reset the widget to a default or empty state.
* @param showClearButton set to true to show the clear button, or false to hide it
* @see showClearButton()
*/
void setShowClearButton( const bool showClearButton );

/** Returns whether the widget is showing a clear button.
* @see setShowClearButton()
*/
bool showClearButton() const {return mShowClearButton;}

/** Sets if the widget will allow entry of simple expressions, which are
Expand All @@ -51,6 +65,7 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
* @note added in QGIS 2.7
*/
void setExpressionsEnabled( const bool enabled );

/** Returns whether the widget will allow entry of simple expressions, which are
* evaluated and then discarded.
* @returns true if spin box allows expression entry
Expand All @@ -62,28 +77,30 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
virtual void clear() override;

/**
* @brief setClearValue defines the clear value as a custom value and will automatically set the clear value mode to CustomValue
* Defines the clear value as a custom value and will automatically set the clear value mode to CustomValue.
* @param customValue defines the numerical value used as the clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
* @see setClearValue()
*/
void setClearValue( double customValue, const QString& clearValueText = QString() );

/**
* @brief setClearValueMode defines if the clear value should be the minimum or maximum values of the widget or a custom value
* Defines if the clear value should be the minimum or maximum values of the widget or a custom value.
* @param mode mode to user for clear value
* @param clearValueText is the text displayed when the spin box is at the clear value. If not specified, no special value text is used.
*/
void setClearValueMode( ClearValueMode mode, const QString& clearValueText = QString() );

//! returns the value used when clear() is called.
/** Returns the value used when clear() is called.
* @see setClearValue()
*/
double clearValue() const;

virtual double valueFromText( const QString & text ) const override;
virtual QValidator::State validate( QString & input, int & pos ) const override;

void paintEvent( QPaintEvent* e ) override;

protected:
virtual void resizeEvent( QResizeEvent* event ) override;
virtual void changeEvent( QEvent* event ) override;

private slots:
Expand All @@ -93,16 +110,15 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
int frameWidth() const;
bool shouldShowClearForValue( const double value ) const;

void updateStyleSheet( const QColor& backgroundColor = QColor() );
QgsSpinBoxLineEdit* mLineEdit;

bool mShowClearButton;
ClearValueMode mClearValueMode;
double mCustomClearValue;

bool mExpressionsEnabled;

QToolButton* mClearButton;
QString stripped( const QString &originalText ) const;
};

#endif // QGSDOUBLESPPINBOX_H
#endif // QGSDOUBLESPINBOX_H

0 comments on commit f16b387

Please sign in to comment.