Skip to content

Commit 65b6ad3

Browse files
committed
Rework QgsFilterLineEdit handling of clear button
Don't use a child button but instead paint the icon when required. Improves interaction with the widget/clear button. Cherry-picked from 98f25f5
1 parent d6b485a commit 65b6ad3

File tree

6 files changed

+232
-36
lines changed

6 files changed

+232
-36
lines changed

images/images.qrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@
665665
<file>themes/default/mActionAddAfsLayer.svg</file>
666666
<file>themes/default/mIconFormSelect.svg</file>
667667
<file>themes/default/mActionMultiEdit.svg</file>
668+
<file>themes/default/mIconClearText.svg</file>
669+
<file>themes/default/mIconClearTextHover.svg</file>
668670
</qresource>
669671
<qresource prefix="/images/tips">
670672
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
Lines changed: 72 additions & 0 deletions
Loading
Lines changed: 72 additions & 0 deletions
Loading

python/gui/qgsfilterlineedit.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class QgsFilterLineEdit : QLineEdit
4646

4747
protected:
4848
void mousePressEvent( QMouseEvent* e );
49+
void mouseMoveEvent( QMouseEvent* e );
4950
void focusInEvent( QFocusEvent* e );
50-
void resizeEvent( QResizeEvent* e );
51-
void changeEvent( QEvent* e );
5251
void paintEvent( QPaintEvent* e );
52+
void leaveEvent( QEvent* e );
5353
};

src/gui/qgsfilterlineedit.cpp

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,30 @@
2121
#include <QToolButton>
2222
#include <QStyle>
2323
#include <QFocusEvent>
24+
#include <QPainter>
2425

2526
QgsFilterLineEdit::QgsFilterLineEdit( QWidget* parent, const QString& nullValue )
2627
: QLineEdit( parent )
2728
, mNullValue( nullValue )
2829
, mFocusInEvent( false )
30+
, mClearHover( false )
2931
{
30-
btnClear = new QToolButton( this );
31-
btnClear->setIcon( QgsApplication::getThemeIcon( "/mIconClear.svg" ) );
32-
btnClear->setCursor( Qt::ArrowCursor );
33-
btnClear->setFocusPolicy( Qt::NoFocus );
34-
btnClear->setStyleSheet( "QToolButton { border: none; padding: 0px; }" );
35-
btnClear->hide();
36-
37-
connect( btnClear, SIGNAL( clicked() ), this, SLOT( clear() ) );
38-
connect( btnClear, SIGNAL( clicked() ), this, SIGNAL( cleared() ) );
32+
// need mouse tracking to handle cursor changes
33+
setMouseTracking( true );
34+
35+
QIcon clearIcon = QgsApplication::getThemeIcon( "/mIconClearText.svg" );
36+
mClearIconSize = QSize( 16, 16 );
37+
mClearIconPixmap = clearIcon.pixmap( mClearIconSize );
38+
QIcon hoverIcon = QgsApplication::getThemeIcon( "/mIconClearTextHover.svg" );
39+
mClearHoverPixmap = hoverIcon.pixmap( mClearIconSize );
40+
3941
connect( this, SIGNAL( textChanged( const QString& ) ), this,
4042
SLOT( onTextChanged( const QString& ) ) );
4143

4244
int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
43-
mStyleSheet = QString( "QLineEdit { padding-right: %1px; } " )
44-
.arg( btnClear->sizeHint().width() + frameWidth + 1 );
45-
4645
QSize msz = minimumSizeHint();
47-
setMinimumSize( qMax( msz.width(), btnClear->sizeHint().height() + frameWidth * 2 + 2 ),
48-
qMax( msz.height(), btnClear->sizeHint().height() + frameWidth * 2 + 2 ) );
46+
setMinimumSize( qMax( msz.width(), mClearIconSize.width() + frameWidth * 2 + 2 ),
47+
qMax( msz.height(), mClearIconSize.height() + frameWidth * 2 + 2 ) );
4948
}
5049

5150
void QgsFilterLineEdit::mousePressEvent( QMouseEvent* e )
@@ -54,6 +53,32 @@ void QgsFilterLineEdit::mousePressEvent( QMouseEvent* e )
5453
QLineEdit::mousePressEvent( e );
5554
else
5655
mFocusInEvent = false;
56+
57+
if ( shouldShowClear() && clearRect().contains( e->pos() ) )
58+
{
59+
clear();
60+
emit cleared();
61+
}
62+
}
63+
64+
void QgsFilterLineEdit::mouseMoveEvent( QMouseEvent* e )
65+
{
66+
QLineEdit::mouseMoveEvent( e );
67+
if ( shouldShowClear() && clearRect().contains( e->pos() ) )
68+
{
69+
if ( !mClearHover )
70+
{
71+
setCursor( Qt::ArrowCursor );
72+
mClearHover = true;
73+
update();
74+
}
75+
}
76+
else if ( mClearHover )
77+
{
78+
setCursor( Qt::IBeamCursor );
79+
mClearHover = false;
80+
update();
81+
}
5782
}
5883

5984
void QgsFilterLineEdit::focusInEvent( QFocusEvent* e )
@@ -66,37 +91,39 @@ void QgsFilterLineEdit::focusInEvent( QFocusEvent* e )
6691
}
6792
}
6893

69-
void QgsFilterLineEdit::resizeEvent( QResizeEvent * )
70-
{
71-
QSize sz = btnClear->sizeHint();
72-
int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
73-
btnClear->move( rect().right() - frameWidth - sz.width(),
74-
( rect().bottom() + 1 - sz.height() ) / 2 );
75-
}
76-
7794
void QgsFilterLineEdit::clear()
7895
{
7996
setText( mNullValue );
8097
setModified( true );
8198
}
8299

83-
void QgsFilterLineEdit::changeEvent( QEvent *e )
84-
{
85-
QLineEdit::changeEvent( e );
86-
btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
87-
}
88-
89100
void QgsFilterLineEdit::paintEvent( QPaintEvent* e )
90101
{
91102
QLineEdit::paintEvent( e );
92-
btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
103+
if ( shouldShowClear() )
104+
{
105+
QRect r = clearRect();
106+
QPainter p( this );
107+
if ( mClearHover )
108+
p.drawPixmap( r.left() , r.top() , mClearHoverPixmap );
109+
else
110+
p.drawPixmap( r.left() , r.top() , mClearIconPixmap );
111+
}
93112
}
94113

114+
void QgsFilterLineEdit::leaveEvent( QEvent* e )
115+
{
116+
if ( mClearHover )
117+
{
118+
mClearHover = false;
119+
update();
120+
}
121+
122+
QLineEdit::leaveEvent( e );
123+
}
95124

96125
void QgsFilterLineEdit::onTextChanged( const QString &text )
97126
{
98-
btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
99-
100127
if ( isNull() )
101128
{
102129
setStyleSheet( QString( "QLineEdit { font: italic; color: gray; } %1" ).arg( mStyleSheet ) );
@@ -108,3 +135,17 @@ void QgsFilterLineEdit::onTextChanged( const QString &text )
108135
emit valueChanged( text );
109136
}
110137
}
138+
139+
bool QgsFilterLineEdit::shouldShowClear() const
140+
{
141+
return isEnabled() && !isReadOnly() && !isNull();
142+
}
143+
144+
QRect QgsFilterLineEdit::clearRect() const
145+
{
146+
int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
147+
return QRect( rect().right() - frameWidth * 2 - mClearIconSize.width(),
148+
( rect().bottom() + 1 - mClearIconSize.height() ) / 2,
149+
mClearIconSize.width(),
150+
mClearIconSize.height() );
151+
}

src/gui/qgsfilterlineedit.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,29 @@ class GUI_EXPORT QgsFilterLineEdit : public QLineEdit
7070

7171
protected:
7272
void mousePressEvent( QMouseEvent* e ) override;
73+
void mouseMoveEvent( QMouseEvent* e ) override;
7374
void focusInEvent( QFocusEvent* e ) override;
74-
void resizeEvent( QResizeEvent* e ) override;
75-
void changeEvent( QEvent* e ) override;
7675
void paintEvent( QPaintEvent* e ) override;
76+
void leaveEvent( QEvent* e ) override;
7777

7878
private slots:
7979
void clear();
8080
void onTextChanged( const QString &text );
8181

8282
private:
8383
QString mNullValue;
84-
QToolButton *btnClear;
8584
QString mStyleSheet;
8685
bool mFocusInEvent;
86+
bool mClearHover;
87+
88+
QSize mClearIconSize;
89+
QPixmap mClearIconPixmap;
90+
QPixmap mClearHoverPixmap;
91+
92+
//! Returns true if clear button should be shown
93+
bool shouldShowClear() const;
94+
95+
QRect clearRect() const;
8796
};
8897

8998
#endif // QGSFILTERLINEEDIT_H

0 commit comments

Comments
 (0)