diff --git a/python/gui/editorwidgets/qgsdoublespinbox.sip b/python/gui/editorwidgets/qgsdoublespinbox.sip
index 6fac256ff6b..1666a02ef71 100644
--- a/python/gui/editorwidgets/qgsdoublespinbox.sip
+++ b/python/gui/editorwidgets/qgsdoublespinbox.sip
@@ -1,3 +1,9 @@
+/** \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
@@ -5,18 +11,30 @@ class QgsDoubleSpinBox : QDoubleSpinBox
 %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
@@ -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
@@ -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 );
 };
diff --git a/python/gui/editorwidgets/qgsspinbox.sip b/python/gui/editorwidgets/qgsspinbox.sip
index 09e8b65d067..d5606414d98 100644
--- a/python/gui/editorwidgets/qgsspinbox.sip
+++ b/python/gui/editorwidgets/qgsspinbox.sip
@@ -1,3 +1,9 @@
+/** \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
@@ -5,18 +11,30 @@ class QgsSpinBox : QSpinBox
 %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
@@ -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
@@ -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 );
 };
diff --git a/src/gui/editorwidgets/qgsdoublespinbox.cpp b/src/gui/editorwidgets/qgsdoublespinbox.cpp
index 904cf0d7ceb..5325c5aeb26 100644
--- a/src/gui/editorwidgets/qgsdoublespinbox.cpp
+++ b/src/gui/editorwidgets/qgsdoublespinbox.cpp
@@ -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 )
@@ -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 )
@@ -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()
@@ -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 );
-
-}
diff --git a/src/gui/editorwidgets/qgsdoublespinbox.h b/src/gui/editorwidgets/qgsdoublespinbox.h
index 55cff69a6ab..6fc55dd27c7 100644
--- a/src/gui/editorwidgets/qgsdoublespinbox.h
+++ b/src/gui/editorwidgets/qgsdoublespinbox.h
@@ -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.
@@ -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
@@ -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
@@ -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:
@@ -93,7 +110,7 @@ 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;
@@ -101,8 +118,7 @@ class GUI_EXPORT QgsDoubleSpinBox : public QDoubleSpinBox
 
     bool mExpressionsEnabled;
 
-    QToolButton* mClearButton;
     QString stripped( const QString &originalText ) const;
 };
 
-#endif // QGSDOUBLESPPINBOX_H
+#endif // QGSDOUBLESPINBOX_H
diff --git a/src/gui/editorwidgets/qgsspinbox.cpp b/src/gui/editorwidgets/qgsspinbox.cpp
index c3f3f0c907e..5373b14f12b 100644
--- a/src/gui/editorwidgets/qgsspinbox.cpp
+++ b/src/gui/editorwidgets/qgsspinbox.cpp
@@ -17,12 +17,14 @@
 #include <QMouseEvent>
 #include <QSettings>
 #include <QStyle>
-#include <QToolButton>
 
 #include "qgsspinbox.h"
 #include "qgsexpression.h"
 #include "qgsapplication.h"
 #include "qgslogger.h"
+#include "qgsfilterlineedit.h"
+
+#define CLEAR_ICON_SIZE 16
 
 QgsSpinBox::QgsSpinBox( QWidget *parent )
     : QSpinBox( parent )
@@ -31,25 +33,22 @@ QgsSpinBox::QgsSpinBox( QWidget *parent )
     , mCustomClearValue( 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( int ) ), this, SLOT( changed( int ) ) );
 }
 
 void QgsSpinBox::setShowClearButton( const bool showClearButton )
 {
   mShowClearButton = showClearButton;
-  mClearButton->setVisible( shouldShowClearForValue( value() ) );
+  mLineEdit->setShowClearButton( showClearButton );
 }
 
 void QgsSpinBox::setExpressionsEnabled( const bool enabled )
@@ -60,18 +59,18 @@ void QgsSpinBox::setExpressionsEnabled( const bool enabled )
 void QgsSpinBox::changeEvent( QEvent *event )
 {
   QSpinBox::changeEvent( event );
-  mClearButton->setVisible( shouldShowClearForValue( value() ) );
+  mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
 }
 
 void QgsSpinBox::paintEvent( QPaintEvent *event )
 {
-  mClearButton->setVisible( shouldShowClearForValue( value() ) );
+  mLineEdit->setShowClearButton( shouldShowClearForValue( value() ) );
   QSpinBox::paintEvent( event );
 }
 
 void QgsSpinBox::changed( int value )
 {
-  mClearButton->setVisible( shouldShowClearForValue( value ) );
+  mLineEdit->setShowClearButton( shouldShowClearForValue( value ) );
 }
 
 void QgsSpinBox::clear()
@@ -187,14 +186,3 @@ QString QgsSpinBox::stripped( const QString &originalText ) const
 
   return text;
 }
-
-void QgsSpinBox::resizeEvent( QResizeEvent * event )
-{
-  QSpinBox::resizeEvent( event );
-
-  QSize sz = mClearButton->sizeHint();
-
-  mClearButton->move( rect().right() - frameWidth() - 18 - sz.width(),
-                      ( rect().bottom() + 1 - sz.height() ) / 2 );
-
-}
diff --git a/src/gui/editorwidgets/qgsspinbox.h b/src/gui/editorwidgets/qgsspinbox.h
index 38400cc5963..d0bff10bd32 100644
--- a/src/gui/editorwidgets/qgsspinbox.h
+++ b/src/gui/editorwidgets/qgsspinbox.h
@@ -13,11 +13,12 @@
  *                                                                         *
  ***************************************************************************/
 
-#ifndef QGSSPPINBOX_H
-#define QGSSPPINBOX_H
+#ifndef QGSSPINBOX_H
+#define QGSSPINBOX_H
 
 #include <QSpinBox>
-#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.
@@ -28,20 +29,34 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
 {
     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 QgsSpinBox.
+     * @param parent parent widget
+     */
     explicit QgsSpinBox( 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
@@ -50,6 +65,7 @@ class GUI_EXPORT QgsSpinBox : public 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
@@ -61,26 +77,30 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
     virtual void clear() override;
 
     /**
-     * @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 override;
     virtual QValidator::State validate( QString & input, int & pos ) const override;
 
   protected:
-    virtual void resizeEvent( QResizeEvent* event ) override;
+
     virtual void changeEvent( QEvent* event ) override;
     virtual void paintEvent( QPaintEvent* event ) override;
 
@@ -91,14 +111,15 @@ class GUI_EXPORT QgsSpinBox : public QSpinBox
     int frameWidth() const;
     bool shouldShowClearForValue( const int value ) const;
 
+    QgsSpinBoxLineEdit* mLineEdit;
+
     bool mShowClearButton;
     ClearValueMode mClearValueMode;
     int mCustomClearValue;
 
     bool mExpressionsEnabled;
 
-    QToolButton* mClearButton;
     QString stripped( const QString &originalText ) const;
 };
 
-#endif // QGSSPPINBOX_H
+#endif // QGSSPINBOX_H
diff --git a/src/gui/qgsfilterlineedit.h b/src/gui/qgsfilterlineedit.h
index 645fe216aca..9c9c8e89e12 100644
--- a/src/gui/qgsfilterlineedit.h
+++ b/src/gui/qgsfilterlineedit.h
@@ -197,4 +197,33 @@ class GUI_EXPORT QgsFilterLineEdit : public QLineEdit
     QRect clearRect() const;
 };
 
+/// @cond PRIVATE
+
+/** Private QgsFilterLineEdit subclass for use as a line edit in QgsSpinBox/QgsDoubleSpinBox
+ * we let QgsFilterLineEdit handle display of the clear button and detection
+ * of clicks, but override clearValue() and let Qgs(Double)SpinBox handle the clearing
+ * themselves.
+ */
+class QgsSpinBoxLineEdit : public QgsFilterLineEdit
+{
+    Q_OBJECT
+
+  public:
+
+    QgsSpinBoxLineEdit( QWidget* parent = nullptr )
+        : QgsFilterLineEdit( parent )
+    {}
+
+  public slots:
+
+    virtual void clearValue() override
+    {
+      // don't change the value - let spin boxes handle that by detecting cleared() signal
+      setCursor( Qt::IBeamCursor );
+      setModified( true );
+      emit cleared();
+    }
+};
+/// @endcond
+
 #endif // QGSFILTERLINEEDIT_H