Adding user button and reset button support to QxtLineEdit

This commit is contained in:
Dee Holtsclaw 2011-08-19 15:54:26 -04:00
parent 4252dbbe35
commit 9583ac2c72
5 changed files with 385 additions and 3 deletions

View File

@ -23,9 +23,13 @@
**
****************************************************************************/
#include "qxtlineedit.h"
#include "qxtmetaobject.h"
#include <QStyleOptionFrameV2>
#include <QPainter>
#include <QStyle>
#include <QToolButton>
#include <QActionEvent>
#include <QApplication>
// copied from qlineedit.cpp:
#define vMargin 1
@ -33,16 +37,182 @@
class QxtLineEditPrivate : public QxtPrivate<QxtLineEdit>
{
QXT_DECLARE_PUBLIC(QxtLineEdit);
public:
QxtLineEditPrivate() : userBtn(0), resetBtn(0), btnPosn(QxtLineEdit::NoButton), resetMode(QxtLineEdit::HideResetButton) {}
QString sampleText;
QToolButton * userBtn; // Internal "user" button
QToolButton * resetBtn; // Internal "reset" button
QxtLineEdit::ButtonPosition btnPosn; // Current posn of user button
QxtLineEdit::ResetButtonMode resetMode; // Current mode of reset button
/*! \internal
* Constructs the user and reset buttons as well as setting the initial
* defaults for each. Buttons are initially hidden.
* This MUST be called by every QxtLineEdit constructor AFTER
* the standard QXT_INIT_PRIVATE().
*/
void initButtons()
{
QXT_P(QxtLineEdit);
// Construct the user button (hidden)
userBtn = new QToolButton(&p);
userBtn->setVisible(false);
userBtn->setCursor(Qt::ArrowCursor);
userBtn->setFocusPolicy(Qt::NoFocus);
userBtn->setIcon(QIcon(":/icons/search.png"));
QObject::connect(userBtn, SIGNAL(clicked(bool)), &p,
SIGNAL(buttonClicked()));
// Construct the reset button (also hidden)
resetBtn = new QToolButton(&p);
resetBtn->setVisible(false);
// resetBtn->setBackgroundRole(QPalette::Base);
resetBtn->setAutoRaise(true);
resetBtn->setCursor(Qt::ArrowCursor);
resetBtn->setFocusPolicy(Qt::NoFocus);
// resetBtn->setForegroundRole(QPalette::Text);
resetBtn->setIcon(QIcon(":/icons/reset.png"));
QObject::connect(resetBtn, SIGNAL(clicked(bool)), &p, SLOT(clear()));
// Connect a handler for adjusting the reset button visibilty
p.connect(&p, SIGNAL(textChanged(const QString &)),
SLOT(_qxt_textChanged(const QString &)));
}
/*! \internal
* Updates the button's geometry according to the specified position. This
* assures it is displayed in the proper location.
*/
void updateButtonGeom()
{
if(btnPosn == QxtLineEdit::NoButton &&
resetMode == QxtLineEdit::HideResetButton)
return;
QXT_P(QxtLineEdit);
// Compute the pixel-size (unadjusted) for button area
int pixUser = std::min(std::max(userBtn->sizeHint().width(),
resetBtn->sizeHint().width()),
p.testAttribute(Qt::WA_Resized) ? p.height() :
p.sizeHint().height());
int pixReset = pixUser - 4; // Inside
// Get the on-screen rectangle (physical geometry) and adjust if needed
QRect rUser = p.rect();
QRect rReset = rUser.adjusted(2, 2, -2, -2);
if(!(btnPosn & QxtLineEdit::PositionOuter)){
// Use inside voices
rUser = rReset;
pixUser = pixReset;
}
// Actually set the user button's geometry
if(btnPosn != QxtLineEdit::NoButton){
if(btnPosn & QxtLineEdit::PositionLeft){
userBtn->setGeometry(rUser.left(), rUser.top(), pixUser,
rUser.height());
rReset.adjust(pixUser, 0, 0, 0);
}
else{
userBtn->setGeometry(rUser.right()-pixUser+1, rUser.top(),
pixUser, rUser.height());
rReset.adjust(0, 0, -pixUser, 0);
}
}
// And that of the reset button
if(resetMode != QxtLineEdit::HideResetButton){
if(QApplication::isRightToLeft())
resetBtn->setGeometry(rReset.left(), rReset.top(), pixReset,
rReset.height());
else
resetBtn->setGeometry(rReset.right()-pixReset+1, rReset.top(),
pixReset, rReset.height());
}
}
/*! \internal
* Adjusts sizes & visibility for changes in button settings.
* \param posn New user button position
* \param mode New reset button mode
*/
void adjustButtons(QxtLineEdit::ButtonPosition posn,
QxtLineEdit::ResetButtonMode mode)
{
QXT_P(QxtLineEdit);
// Determine visibility
bool showReset = (mode == QxtLineEdit::ShowResetAlways ||
(mode == QxtLineEdit::ShowResetNotEmpty &&
!qxt_p().text().isEmpty()));
bool showUser = (posn != QxtLineEdit::NoButton);
// Get pixels to reserve for button size
int pix = std::min(std::max(userBtn->sizeHint().width(),
resetBtn->sizeHint().width()),
p.testAttribute(Qt::WA_Resized) ? p.height() :
p.sizeHint().height());
// Compute horizontal space needed for reset button
int rbl = 0, rbr = 0;
if((resetMode = mode) != QxtLineEdit::HideResetButton){
if(QApplication::isRightToLeft())
rbl = pix; // Reset is on the left
else
rbr = pix; // Reset is on the right
}
// Handle user button space requirements (and reset along the way)
if((btnPosn = posn) == QxtLineEdit::NoButton){
// Hide it and unreserve all space
p.setContentsMargins(0, 0, 0, 0);
p.setTextMargins(rbl, 0, rbr, 0);
}
else{
// Handle automatic positioning according to locale/language
if(posn & QxtLineEdit::PositionAuto){
if(QApplication::isRightToLeft())
btnPosn = static_cast<QxtLineEdit::ButtonPosition>(
posn | QxtLineEdit::PositionLeft);
else
btnPosn = static_cast<QxtLineEdit::ButtonPosition>(
posn & ~QxtLineEdit::PositionLeft);
}
// Reserve space appropriately
if(btnPosn & QxtLineEdit::PositionOuter){
// Outside -- text margins ziltch and contents set +2 for frame
p.setTextMargins(rbl, 0, rbr, 0);
if(btnPosn & QxtLineEdit::PositionLeft)
p.setContentsMargins(pix+2, 0, 0, 0);
else
p.setContentsMargins(0, 0, pix+2, 0);
}
else{
// Inside -- contents ziltch and text margins set
p.setContentsMargins(0, 0, 0, 0);
if(btnPosn & QxtLineEdit::PositionLeft)
p.setTextMargins(pix+rbl, 0, rbr, 0);
else
p.setTextMargins(rbl, 0, pix+rbr, 0);
}
}
// Update button geometry & redraw everything
updateButtonGeom();
if(showUser != userBtn->isVisible())
userBtn->setVisible(showUser);
if(showReset != resetBtn->isVisible())
resetBtn->setVisible(showReset);
}
/*! \internal
* Adjusts visibility for reset button when text changes.
* \param text New text content
*/
void adjustResetButton(const QString &text)
{
if(resetMode == QxtLineEdit::ShowResetNotEmpty){
if(resetBtn->isVisible() != !text.isEmpty())
resetBtn->setVisible(!text.isEmpty());
}
}
};
/*!
\class QxtLineEdit
\inmodule QxtGui
\brief The QxtLineEdit widget is a line edit that is able to show a sample text.
\brief The QxtLineEdit widget is a line edit that is able to show a sample text and embedded buttons.
QxtLineEdit is a line edit that is able to show a sample text.
QxtLineEdit is a line edit that is able to show a sample text, a user
configurable button and/or a reset button.
The sample text is shown when the line edit is empty and has
no focus.
@ -54,6 +224,8 @@ public:
*/
QxtLineEdit::QxtLineEdit(QWidget* parent) : QLineEdit(parent)
{
QXT_INIT_PRIVATE(QxtLineEdit);
qxt_d().initButtons();
}
/*!
@ -61,6 +233,8 @@ QxtLineEdit::QxtLineEdit(QWidget* parent) : QLineEdit(parent)
*/
QxtLineEdit::QxtLineEdit(const QString& text, QWidget* parent) : QLineEdit(text, parent)
{
QXT_INIT_PRIVATE(QxtLineEdit);
qxt_d().initButtons();
}
/*!
@ -72,7 +246,7 @@ QxtLineEdit::~QxtLineEdit()
/*!
\property QxtLineEdit::sampleText
\brief the sample text of the line edit
\brief The sample text of the line edit
The sample text is shown when the line edit is empty and has
no focus.
@ -92,6 +266,100 @@ void QxtLineEdit::setSampleText(const QString& text)
}
}
/*!
\property QxtLineEdit::buttonAutoRaise
\brief The \a autoRaise property of the embedded user button
This property mirrors the property of the embedded QToolButton and
causes the button to appear flat until the mouse hovers over it.
*/
bool QxtLineEdit::buttonAutoRaise() const
{
return qxt_d().userBtn->autoRaise();
}
void QxtLineEdit::setButtonAutoRaise(bool f)
{
qxt_d().userBtn->setAutoRaise(f);
}
/*!
\property QxtLineEdit::buttonIcon
\brief The \a icon property of the embedded user button
This property mirrors the property of the embedded QToolButton. The
default icon is a stock search pixmap which will be obtained from
the system style when available.
*/
QIcon QxtLineEdit::buttonIcon() const
{
return qxt_d().userBtn->icon();
}
void QxtLineEdit::setButtonIcon(const QIcon &icon)
{
qxt_d().userBtn->setIcon(icon);
}
/*!
\property QxtLineEdit::buttonPosition
\brief The \a position of the embedded user button
This property controls where the button is positioned within the
line edit. The default is \a NoButton.
\sa QxtLineEdit::ButtonPosition
*/
QxtLineEdit::ButtonPosition QxtLineEdit::buttonPosition() const
{
ButtonPosition result = qxt_d().btnPosn;
if(result & PositionAuto)
// Hide real direction when auto
result = static_cast<ButtonPosition>(result & ~PositionLeft);
return result;
}
void QxtLineEdit::setButtonPosition(ButtonPosition posn)
{
if(posn == qxt_d().btnPosn)
return;
qxt_d().adjustButtons(posn, qxt_d().resetMode);
update();
}
/*!
\property QxtLineEdit::resetButtonMode
\brief The \a mode of the embedded reset button
This property controls when the reset button is visible.
The default is \a HideResetButton.
\sa QxtLineEdit::ResetButtonMode
*/
QxtLineEdit::ResetButtonMode QxtLineEdit::resetButtonMode() const
{
return qxt_d().resetMode;
}
void QxtLineEdit::setResetButtonMode(ResetButtonMode mode)
{
if(mode == qxt_d().resetMode)
return;
qxt_d().adjustButtons(qxt_d().btnPosn, mode);
}
/*!
\brief Provides access to the embedded user button object
This method returns a pointer to the embedded user button. It
is never NULL. The QToolButton is owned by the line edit and
must not be deleted.
*/
QToolButton* QxtLineEdit::button() const
{
return qxt_d().userBtn;
}
/*!
\reimp
*/
@ -119,3 +387,69 @@ void QxtLineEdit::paintEvent(QPaintEvent* event)
style()->drawItemText(&painter, r, alignment(), pal, false, qxt_d().sampleText, QPalette::Text);
}
}
/*!
* \reimp
*/
void QxtLineEdit::actionEvent(QActionEvent *e)
{
// Transfer action events to the button since that's where they typically
// belong. All others are passed on to the base class implementation.
switch(e->type()){
case QEvent::ActionAdded:
qxt_d().userBtn->insertAction(e->before(), e->action());
break;
case QEvent::ActionRemoved:
qxt_d().userBtn->removeAction(e->action());
break;
default:
QLineEdit::actionEvent(e);
}
}
/*!
* \reimp
*/
void QxtLineEdit::resizeEvent(QResizeEvent *e)
{
// Adjust the button's geometry when resizing events occur so it doesn't
// end up out of place. The base implementation is always used as well.
qxt_d().updateButtonGeom();
QLineEdit::resizeEvent(e);
}
/*! \internal
* Forwards signal to private class
*/
void QxtLineEdit::_qxt_textChanged(const QString &text)
{
qxt_d().adjustResetButton(text);
}
/*!
\enum QxtLineEdit::ButtonPosition
\brief This enum controls the position of an embedded button.
\value NoButton The button is not displayed (default)
\value InnerRight Button is shown inside the frame on the right-hand side
\value InnerLeft Button is shown inside the frame on the left-hand side
\value InnerAuto Button is shown inside the frame, side determined by locale
\value OuterRight Button is shown outside the frame on the right-hand side
\value OuterLeft Button is shown outside the frame on the left-hand side
\value OuterAuto Button is shown outside the frame, side determined by locale
*/
/*!
\enum QxtLineEdit::ResetButtonMode
\brief This enum controls the display of a reset button.
\value HideResetButton The button is not displayed (default)
\value ShowResetNotEmpty The reset button appears only when the line-edit is not empty
\value ShowResetAlways The reset button is always visible
*/
/*!
\fn buttonClicked()
This signal is emitted when the user button is clicked.
\sa QToolButton::clicked(bool)
*/

View File

@ -26,27 +26,73 @@
#define QXTLINEEDIT_H
#include <QLineEdit>
#include <QIcon>
#include <qxtglobal.h>
class QxtLineEditPrivate;
class QActionEvent;
class QResizeEvent;
class QToolButton;
class QXT_GUI_EXPORT QxtLineEdit : public QLineEdit
{
Q_OBJECT
Q_ENUMS(ButtonPosition)
Q_ENUMS(ResetButtonMode)
Q_PROPERTY(bool buttonAutoRaise READ buttonAutoRaise WRITE setButtonAutoRaise)
Q_PROPERTY(QIcon buttonIcon READ buttonIcon WRITE setButtonIcon)
Q_PROPERTY(ButtonPosition buttonPosition READ buttonPosition WRITE setButtonPosition)
Q_PROPERTY(ResetButtonMode resetButtonMode READ resetButtonMode WRITE setResetButtonMode)
Q_PROPERTY(QString sampleText READ sampleText WRITE setSampleText)
public:
enum ButtonPosition
{
NoButton,
PositionLeft = 0x1,
PositionAuto = 0x2,
PositionOuter = 0x4,
InnerRight = 0x10,
InnerLeft = 0x11,
InnerAuto = 0x12,
OuterRight = 0x14,
OuterLeft = 0x15,
OuterAuto = 0x16
};
enum ResetButtonMode
{
HideResetButton,
ShowResetNotEmpty,
ShowResetAlways,
};
explicit QxtLineEdit(QWidget* parent = 0);
QxtLineEdit(const QString& text, QWidget* parent = 0);
virtual ~QxtLineEdit();
QString sampleText() const;
bool buttonAutoRaise() const;
void setButtonAutoRaise(bool);
QIcon buttonIcon() const;
void setButtonIcon(const QIcon &);
ButtonPosition buttonPosition() const;
void setButtonPosition(ButtonPosition);
ResetButtonMode resetButtonMode() const;
void setResetButtonMode(ResetButtonMode);
QToolButton *button() const;
public Q_SLOTS:
void setSampleText(const QString& text);
Q_SIGNALS:
void buttonClicked();
protected:
virtual void paintEvent(QPaintEvent* event);
virtual void actionEvent(QActionEvent *);
virtual void resizeEvent(QResizeEvent *);
private Q_SLOTS:
void _qxt_textChanged(const QString &text);
private:
QXT_DECLARE_PRIVATE(QxtLineEdit)

View File

@ -247,5 +247,7 @@
<file alias="flags/ZA.png">resources/flags/ZA.png</file>
<file alias="flags/ZM.png">resources/flags/ZM.png</file>
<file alias="flags/ZW.png">resources/flags/ZW.png</file>
<file alias="icons/search.png">resources/icons/search.png</file>
<file alias="icons/reset.png">resources/icons/reset.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB