diff --git a/python/gui/qgsfilterlineedit.sip b/python/gui/qgsfilterlineedit.sip index e9f75c851c8..d657557b89d 100644 --- a/python/gui/qgsfilterlineedit.sip +++ b/python/gui/qgsfilterlineedit.sip @@ -257,16 +257,8 @@ Will select all text when this widget receives the focus. %End protected: - virtual void mousePressEvent( QMouseEvent *e ); - - virtual void mouseMoveEvent( QMouseEvent *e ); - virtual void focusInEvent( QFocusEvent *e ); - virtual void paintEvent( QPaintEvent *e ); - - virtual void leaveEvent( QEvent *e ); - }; diff --git a/src/gui/qgsfilterlineedit.cpp b/src/gui/qgsfilterlineedit.cpp index 2012efd3bfa..d654a93f013 100644 --- a/src/gui/qgsfilterlineedit.cpp +++ b/src/gui/qgsfilterlineedit.cpp @@ -19,6 +19,7 @@ #include "qgsapplication.h" #include "qgsanimatedicon.h" +#include #include #include #include @@ -28,27 +29,22 @@ QgsFilterLineEdit::QgsFilterLineEdit( QWidget *parent, const QString &nullValue : QLineEdit( parent ) , mNullValue( nullValue ) { - // need mouse tracking to handle cursor changes - setMouseTracking( true ); - - QIcon clearIcon = QgsApplication::getThemeIcon( "/mIconClearText.svg" ); - // icon size is about 2/3 height of text, but minimum size of 16 int iconSize = std::floor( std::max( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 0.75, 16.0 ) ); - mClearIconSize = QSize( iconSize, iconSize ); - mClearIconPixmap = clearIcon.pixmap( mClearIconSize ); - QIcon hoverIcon = QgsApplication::getThemeIcon( "/mIconClearTextHover.svg" ); - mClearHoverPixmap = hoverIcon.pixmap( mClearIconSize ); + QIcon clearIcon; + clearIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconClearText.svg" ).pixmap( QSize( iconSize, iconSize ) ), QIcon::Normal, QIcon::On ); + clearIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconClearTextHover.svg" ).pixmap( QSize( iconSize, iconSize ) ), QIcon::Selected, QIcon::On ); + mClearAction = new QAction( clearIcon, this ); + mClearAction->setCheckable( false ); + addAction( mClearAction, QLineEdit::TrailingPosition ); + connect( mClearAction, &QAction::triggered, this, &QgsFilterLineEdit::clearValue ); QIcon searchIcon = QgsApplication::getThemeIcon( "/search.svg" ); - mSearchIconSize = QSize( iconSize, iconSize ); - mSearchIconPixmap = searchIcon.pixmap( mSearchIconSize ); - - // Make some space for the clear icon - QMargins margins( textMargins( ) ); - margins.setRight( iconSize ); - setTextMargins( margins ); + mSearchAction = new QAction( searchIcon, this ); + mSearchAction->setCheckable( false ); + addAction( mSearchAction, QLineEdit::TrailingPosition ); + mSearchAction->setVisible( false ); connect( this, &QLineEdit::textChanged, this, &QgsFilterLineEdit::onTextChanged ); @@ -56,56 +52,19 @@ QgsFilterLineEdit::QgsFilterLineEdit( QWidget *parent, const QString &nullValue void QgsFilterLineEdit::setShowClearButton( bool visible ) { - bool changed = mClearButtonVisible != visible; mClearButtonVisible = visible; - if ( !visible ) - mClearHover = false; - - if ( changed ) - update(); + updateClearIcon(); } void QgsFilterLineEdit::setShowSearchIcon( bool visible ) { - bool changed = mSearchIconVisible != visible; - if ( changed ) - { - mSearchIconVisible = visible; - update(); - } + mSearchIconVisible = visible; + mSearchAction->setVisible( visible ); } -void QgsFilterLineEdit::mousePressEvent( QMouseEvent *e ) +void QgsFilterLineEdit::updateClearIcon() { - if ( !mFocusInEvent ) - QLineEdit::mousePressEvent( e ); - else - mFocusInEvent = false; - - if ( shouldShowClear() && clearRect().contains( e->pos() ) ) - { - clearValue(); - } -} - -void QgsFilterLineEdit::mouseMoveEvent( QMouseEvent *e ) -{ - QLineEdit::mouseMoveEvent( e ); - if ( shouldShowClear() && clearRect().contains( e->pos() ) ) - { - if ( !mClearHover ) - { - setCursor( Qt::ArrowCursor ); - mClearHover = true; - update(); - } - } - else if ( mClearHover ) - { - setCursor( Qt::IBeamCursor ); - mClearHover = false; - update(); - } + mClearAction->setVisible( shouldShowClear() ); } void QgsFilterLineEdit::focusInEvent( QFocusEvent *e ) @@ -132,57 +91,14 @@ void QgsFilterLineEdit::clearValue() break; } - if ( mClearHover ) - { - setCursor( Qt::IBeamCursor ); - mClearHover = false; - } - setModified( true ); emit cleared(); } -void QgsFilterLineEdit::paintEvent( QPaintEvent *e ) -{ - QLineEdit::paintEvent( e ); - if ( shouldShowClear() ) - { - QRect r = clearRect(); - QPainter p( this ); - if ( mClearHover ) - p.drawPixmap( r.left(), r.top(), mClearHoverPixmap ); - else - p.drawPixmap( r.left(), r.top(), mClearIconPixmap ); - } - - if ( mSearchIconVisible && !shouldShowClear() ) - { - QRect r = searchRect(); - QPainter p( this ); - p.drawPixmap( r.left(), r.top(), mSearchIconPixmap ); - } - - if ( mShowSpinner ) - { - QRect r = busySpinnerRect(); - QPainter p( this ); - p.drawPixmap( r.left(), r.top(), mBusySpinner->icon().pixmap( r.size() ) ); - } -} - -void QgsFilterLineEdit::leaveEvent( QEvent *e ) -{ - if ( mClearHover ) - { - mClearHover = false; - update(); - } - - QLineEdit::leaveEvent( e ); -} - void QgsFilterLineEdit::onTextChanged( const QString &text ) { + updateClearIcon(); + if ( isNull() ) { setStyleSheet( QStringLiteral( "QLineEdit { font: italic; color: gray; } %1" ).arg( mStyleSheet ) ); @@ -193,17 +109,15 @@ void QgsFilterLineEdit::onTextChanged( const QString &text ) setStyleSheet( mStyleSheet ); emit valueChanged( text ); } - - if ( mClearHover && !shouldShowClear() ) - { - setCursor( Qt::IBeamCursor ); - mClearHover = false; - } } void QgsFilterLineEdit::updateBusySpinner() { - update(); + if ( !mBusySpinnerAction ) + { + mBusySpinnerAction = addAction( mBusySpinnerAnimatedIcon->icon(), QLineEdit::TrailingPosition ); + } + mBusySpinnerAction->setIcon( mBusySpinnerAnimatedIcon->icon() ); } bool QgsFilterLineEdit::selectOnFocus() const @@ -227,20 +141,22 @@ bool QgsFilterLineEdit::showSpinner() const void QgsFilterLineEdit::setShowSpinner( bool showSpinner ) { + if ( showSpinner == mShowSpinner ) return; if ( showSpinner ) { - if ( !mBusySpinner ) - mBusySpinner = new QgsAnimatedIcon( QgsApplication::iconPath( QStringLiteral( "/mIconLoading.gif" ) ), this ); + if ( !mBusySpinnerAnimatedIcon ) + mBusySpinnerAnimatedIcon = new QgsAnimatedIcon( QgsApplication::iconPath( QStringLiteral( "/mIconLoading.gif" ) ), this ); - mBusySpinner->connectFrameChanged( this, &QgsFilterLineEdit::updateBusySpinner ); + mBusySpinnerAnimatedIcon->connectFrameChanged( this, &QgsFilterLineEdit::updateBusySpinner ); } else { - mBusySpinner->disconnectFrameChanged( this, &QgsFilterLineEdit::updateBusySpinner ); - update(); + mBusySpinnerAnimatedIcon->disconnectFrameChanged( this, &QgsFilterLineEdit::updateBusySpinner ); + removeAction( mBusySpinnerAction ); + mBusySpinnerAction = nullptr; } mShowSpinner = showSpinner; @@ -262,33 +178,3 @@ bool QgsFilterLineEdit::shouldShowClear() const } return false; //avoid warnings } - -QRect QgsFilterLineEdit::clearRect() const -{ - int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ); - return QRect( rect().right() - frameWidth * 2 - mClearIconSize.width(), - ( rect().bottom() + 1 - mClearIconSize.height() ) / 2, - mClearIconSize.width(), - mClearIconSize.height() ); -} - -QRect QgsFilterLineEdit::busySpinnerRect() const -{ - int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ); - - int offset = shouldShowClear() ? mClearIconSize.width() + frameWidth * 2 : frameWidth; - - return QRect( rect().right() - offset - mClearIconSize.width(), - ( rect().bottom() + 1 - mClearIconSize.height() ) / 2, - mClearIconSize.width(), - mClearIconSize.height() ); -} - -QRect QgsFilterLineEdit::searchRect() const -{ - int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ); - return QRect( rect().left() + frameWidth * 2, - ( rect().bottom() + 1 - mSearchIconSize.height() ) / 2, - mSearchIconSize.width(), - mSearchIconSize.height() ); -} diff --git a/src/gui/qgsfilterlineedit.h b/src/gui/qgsfilterlineedit.h index 4e0a0b0797b..a8968177e4c 100644 --- a/src/gui/qgsfilterlineedit.h +++ b/src/gui/qgsfilterlineedit.h @@ -254,17 +254,17 @@ class GUI_EXPORT QgsFilterLineEdit : public QLineEdit void selectOnFocusChanged(); protected: - void mousePressEvent( QMouseEvent *e ) override; - void mouseMoveEvent( QMouseEvent *e ) override; void focusInEvent( QFocusEvent *e ) override; - void paintEvent( QPaintEvent *e ) override; - void leaveEvent( QEvent *e ) override; private slots: void onTextChanged( const QString &text ); void updateBusySpinner(); + void updateClearIcon(); private: + QAction *mClearAction; + QAction *mSearchAction; + QAction *mBusySpinnerAction = nullptr; bool mClearButtonVisible = true; bool mSearchIconVisible = false; @@ -276,23 +276,12 @@ class GUI_EXPORT QgsFilterLineEdit : public QLineEdit QString mDefaultValue; QString mStyleSheet; bool mFocusInEvent = false; - bool mClearHover = false; bool mSelectOnFocus = false; - QSize mClearIconSize; - QPixmap mClearIconPixmap; - QPixmap mClearHoverPixmap; - - QSize mSearchIconSize; - QPixmap mSearchIconPixmap; - QgsAnimatedIcon *mBusySpinner = nullptr; + QgsAnimatedIcon *mBusySpinnerAnimatedIcon = nullptr; //! Returns true if clear button should be shown bool shouldShowClear() const; - - QRect clearRect() const; - QRect searchRect() const; - QRect busySpinnerRect() const; }; /// @cond PRIVATE