Skip to content

Commit

Permalink
Rework QgsFilterLineEdit handling of clear button
Browse files Browse the repository at this point in the history
Don't use a child button but instead paint the icon when
required. Improves interaction with the widget/clear
button.

Cherry-picked from 98f25f5
  • Loading branch information
nyalldawson committed Sep 8, 2016
1 parent d6b485a commit 65b6ad3
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 36 deletions.
2 changes: 2 additions & 0 deletions images/images.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,8 @@
<file>themes/default/mActionAddAfsLayer.svg</file>
<file>themes/default/mIconFormSelect.svg</file>
<file>themes/default/mActionMultiEdit.svg</file>
<file>themes/default/mIconClearText.svg</file>
<file>themes/default/mIconClearTextHover.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
Expand Down
72 changes: 72 additions & 0 deletions images/themes/default/mIconClearText.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions images/themes/default/mIconClearTextHover.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions python/gui/qgsfilterlineedit.sip
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class QgsFilterLineEdit : QLineEdit

protected:
void mousePressEvent( QMouseEvent* e );
void mouseMoveEvent( QMouseEvent* e );
void focusInEvent( QFocusEvent* e );
void resizeEvent( QResizeEvent* e );
void changeEvent( QEvent* e );
void paintEvent( QPaintEvent* e );
void leaveEvent( QEvent* e );
};
103 changes: 72 additions & 31 deletions src/gui/qgsfilterlineedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,30 @@
#include <QToolButton>
#include <QStyle>
#include <QFocusEvent>
#include <QPainter>

QgsFilterLineEdit::QgsFilterLineEdit( QWidget* parent, const QString& nullValue )
: QLineEdit( parent )
, mNullValue( nullValue )
, mFocusInEvent( false )
, mClearHover( false )
{
btnClear = new QToolButton( this );
btnClear->setIcon( QgsApplication::getThemeIcon( "/mIconClear.svg" ) );
btnClear->setCursor( Qt::ArrowCursor );
btnClear->setFocusPolicy( Qt::NoFocus );
btnClear->setStyleSheet( "QToolButton { border: none; padding: 0px; }" );
btnClear->hide();

connect( btnClear, SIGNAL( clicked() ), this, SLOT( clear() ) );
connect( btnClear, SIGNAL( clicked() ), this, SIGNAL( cleared() ) );
// need mouse tracking to handle cursor changes
setMouseTracking( true );

QIcon clearIcon = QgsApplication::getThemeIcon( "/mIconClearText.svg" );
mClearIconSize = QSize( 16, 16 );
mClearIconPixmap = clearIcon.pixmap( mClearIconSize );
QIcon hoverIcon = QgsApplication::getThemeIcon( "/mIconClearTextHover.svg" );
mClearHoverPixmap = hoverIcon.pixmap( mClearIconSize );

connect( this, SIGNAL( textChanged( const QString& ) ), this,
SLOT( onTextChanged( const QString& ) ) );

int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
mStyleSheet = QString( "QLineEdit { padding-right: %1px; } " )
.arg( btnClear->sizeHint().width() + frameWidth + 1 );

QSize msz = minimumSizeHint();
setMinimumSize( qMax( msz.width(), btnClear->sizeHint().height() + frameWidth * 2 + 2 ),
qMax( msz.height(), btnClear->sizeHint().height() + frameWidth * 2 + 2 ) );
setMinimumSize( qMax( msz.width(), mClearIconSize.width() + frameWidth * 2 + 2 ),
qMax( msz.height(), mClearIconSize.height() + frameWidth * 2 + 2 ) );
}

void QgsFilterLineEdit::mousePressEvent( QMouseEvent* e )
Expand All @@ -54,6 +53,32 @@ void QgsFilterLineEdit::mousePressEvent( QMouseEvent* e )
QLineEdit::mousePressEvent( e );
else
mFocusInEvent = false;

if ( shouldShowClear() && clearRect().contains( e->pos() ) )
{
clear();
emit cleared();
}
}

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();
}
}

void QgsFilterLineEdit::focusInEvent( QFocusEvent* e )
Expand All @@ -66,37 +91,39 @@ void QgsFilterLineEdit::focusInEvent( QFocusEvent* e )
}
}

void QgsFilterLineEdit::resizeEvent( QResizeEvent * )
{
QSize sz = btnClear->sizeHint();
int frameWidth = style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
btnClear->move( rect().right() - frameWidth - sz.width(),
( rect().bottom() + 1 - sz.height() ) / 2 );
}

void QgsFilterLineEdit::clear()
{
setText( mNullValue );
setModified( true );
}

void QgsFilterLineEdit::changeEvent( QEvent *e )
{
QLineEdit::changeEvent( e );
btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
}

void QgsFilterLineEdit::paintEvent( QPaintEvent* e )
{
QLineEdit::paintEvent( e );
btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );
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 );
}
}

void QgsFilterLineEdit::leaveEvent( QEvent* e )
{
if ( mClearHover )
{
mClearHover = false;
update();
}

QLineEdit::leaveEvent( e );
}

void QgsFilterLineEdit::onTextChanged( const QString &text )
{
btnClear->setVisible( isEnabled() && !isReadOnly() && !isNull() );

if ( isNull() )
{
setStyleSheet( QString( "QLineEdit { font: italic; color: gray; } %1" ).arg( mStyleSheet ) );
Expand All @@ -108,3 +135,17 @@ void QgsFilterLineEdit::onTextChanged( const QString &text )
emit valueChanged( text );
}
}

bool QgsFilterLineEdit::shouldShowClear() const
{
return isEnabled() && !isReadOnly() && !isNull();
}

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() );
}
15 changes: 12 additions & 3 deletions src/gui/qgsfilterlineedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,29 @@ class GUI_EXPORT QgsFilterLineEdit : public QLineEdit

protected:
void mousePressEvent( QMouseEvent* e ) override;
void mouseMoveEvent( QMouseEvent* e ) override;
void focusInEvent( QFocusEvent* e ) override;
void resizeEvent( QResizeEvent* e ) override;
void changeEvent( QEvent* e ) override;
void paintEvent( QPaintEvent* e ) override;
void leaveEvent( QEvent* e ) override;

private slots:
void clear();
void onTextChanged( const QString &text );

private:
QString mNullValue;
QToolButton *btnClear;
QString mStyleSheet;
bool mFocusInEvent;
bool mClearHover;

QSize mClearIconSize;
QPixmap mClearIconPixmap;
QPixmap mClearHoverPixmap;

//! Returns true if clear button should be shown
bool shouldShowClear() const;

QRect clearRect() const;
};

#endif // QGSFILTERLINEEDIT_H

0 comments on commit 65b6ad3

Please sign in to comment.