2 * \file fancylineedit.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Nokia Corporation (qt-info@nokia.com)
8 * Full author contact details are available in file CREDITS.
12 // Code taken from the Qt Creator project and customized a little
14 #include "FancyLineEdit.h"
16 #include <QtCore/QEvent>
17 #include <QtCore/QDebug>
18 #include <QtCore/QString>
19 #include <QtCore/QPropertyAnimation>
20 #include <QtGui/QApplication>
21 #include <QtGui/QMenu>
22 #include <QtGui/QMouseEvent>
23 #include <QtGui/QLabel>
24 #include <QtGui/QAbstractButton>
25 #include <QtGui/QPainter>
26 #include <QtGui/QStyle>
27 #include <QtGui/QPaintEvent>
31 #define ICONBUTTON_HEIGHT 18
38 // --------- FancyLineEditPrivate
39 class FancyLineEditPrivate : public QObject {
41 explicit FancyLineEditPrivate(FancyLineEdit *parent);
43 virtual bool eventFilter(QObject *obj, QEvent *event);
45 FancyLineEdit *m_lineEdit;
48 bool m_menuTabFocusTrigger[2];
49 IconButton *m_iconbutton[2];
50 bool m_iconEnabled[2];
54 FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
58 for (int i = 0; i < 2; ++i) {
60 m_menuTabFocusTrigger[i] = false;
61 m_iconbutton[i] = new IconButton(parent);
62 m_iconbutton[i]->installEventFilter(this);
63 m_iconbutton[i]->hide();
64 m_iconbutton[i]->setAutoHide(false);
65 m_iconEnabled[i] = false;
69 bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
72 for (int i = 0; i < 2; ++i) {
73 if (obj == m_iconbutton[i]) {
78 if (buttonIndex == -1)
79 return QObject::eventFilter(obj, event);
80 switch (event->type()) {
82 if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
83 m_lineEdit->setFocus();
84 m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
85 m_iconbutton[buttonIndex]->rect().center()));
91 return QObject::eventFilter(obj, event);
95 // --------- FancyLineEdit
96 FancyLineEdit::FancyLineEdit(QWidget *parent) :
98 m_d(new FancyLineEditPrivate(this))
103 connect(this, SIGNAL(textChanged(QString)), this, SLOT(checkButtons(QString)));
104 connect(m_d->m_iconbutton[Left], SIGNAL(clicked()), this, SLOT(iconClicked()));
105 connect(m_d->m_iconbutton[Right], SIGNAL(clicked()), this, SLOT(iconClicked()));
108 void FancyLineEdit::checkButtons(const QString &text)
110 if (m_oldText.isEmpty() || text.isEmpty()) {
111 for (int i = 0; i < 2; ++i) {
112 if (m_d->m_iconbutton[i]->hasAutoHide())
113 m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
119 FancyLineEdit::~FancyLineEdit()
123 void FancyLineEdit::setButtonVisible(Side side, bool visible)
125 m_d->m_iconbutton[side]->setVisible(visible);
126 m_d->m_iconEnabled[side] = visible;
130 bool FancyLineEdit::isButtonVisible(Side side) const
132 return m_d->m_iconEnabled[side];
135 void FancyLineEdit::iconClicked()
137 IconButton *button = qobject_cast<IconButton *>(sender());
139 for (int i = 0; i < 2; ++i)
140 if (m_d->m_iconbutton[i] == button)
144 if (m_d->m_menu[index]) {
145 m_d->m_menu[index]->exec(QCursor::pos());
147 buttonClicked((Side)index);
150 else if (index == Right)
151 rightButtonClicked();
155 void FancyLineEdit::updateMargins()
157 bool leftToRight = (layoutDirection() == Qt::LeftToRight);
158 Side realLeft = (leftToRight ? Left : Right);
159 Side realRight = (leftToRight ? Right : Left);
161 int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
162 int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
163 // Note KDE does not reserve space for the highlight color
164 if (style()->inherits("OxygenStyle")) {
165 leftMargin = qMax(24, leftMargin);
166 rightMargin = qMax(24, rightMargin);
169 QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
170 (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
172 setTextMargins(margins);
175 void FancyLineEdit::updateButtonPositions()
177 QRect contentRect = rect();
178 for (int i = 0; i < 2; ++i) {
179 Side iconpos = (Side)i;
180 if (layoutDirection() == Qt::RightToLeft)
181 iconpos = (iconpos == Left ? Right : Left);
183 if (iconpos == FancyLineEdit::Right) {
184 const int iconoffset = textMargins().right() + 4;
185 m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));
187 const int iconoffset = textMargins().left() + 4;
188 m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));
193 void FancyLineEdit::resizeEvent(QResizeEvent *)
195 updateButtonPositions();
198 void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
200 m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
202 updateButtonPositions();
206 QPixmap FancyLineEdit::buttonPixmap(Side side) const
208 return m_d->m_pixmap[side];
211 void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
213 m_d->m_menu[side] = buttonMenu;
214 m_d->m_iconbutton[side]->setIconOpacity(1.0);
217 QMenu *FancyLineEdit::buttonMenu(Side side) const
219 return m_d->m_menu[side];
222 bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
224 return m_d->m_menuTabFocusTrigger[side];
227 void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
229 if (m_d->m_menuTabFocusTrigger[side] == v)
232 m_d->m_menuTabFocusTrigger[side] = v;
233 m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
236 bool FancyLineEdit::hasAutoHideButton(Side side) const
238 return m_d->m_iconbutton[side]->hasAutoHide();
241 void FancyLineEdit::setAutoHideButton(Side side, bool h)
243 m_d->m_iconbutton[side]->setAutoHide(h);
245 m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ? 0.0 : 1.0);
247 m_d->m_iconbutton[side]->setIconOpacity(1.0);
250 void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
252 m_d->m_iconbutton[side]->setToolTip(tip);
255 void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
257 m_d->m_iconbutton[side]->setFocusPolicy(policy);
260 // IconButton - helper class to represent a clickable icon
262 IconButton::IconButton(QWidget *parent)
263 : QAbstractButton(parent), m_autoHide(false)
265 setCursor(Qt::ArrowCursor);
266 setFocusPolicy(Qt::NoFocus);
269 void IconButton::paintEvent(QPaintEvent *)
271 QPainter painter(this);
272 // Note isDown should really use the active state but in most styles
273 // this has no proper feedback
274 QIcon::Mode state = QIcon::Disabled;
276 state = isDown() ? QIcon::Selected : QIcon::Normal;
277 QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
278 pixmapRect.moveCenter(rect().center());
281 painter.setOpacity(m_iconOpacity);
283 painter.drawPixmap(pixmapRect, m_pixmap);
286 void IconButton::animateShow(bool visible)
289 QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");
290 animation->setDuration(FADE_TIME);
291 animation->setEndValue(1.0);
292 animation->start(QAbstractAnimation::DeleteWhenStopped);
294 QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity");
295 animation->setDuration(FADE_TIME);
296 animation->setEndValue(0.0);
297 animation->start(QAbstractAnimation::DeleteWhenStopped);
305 #include "moc_FancyLineEdit.cpp"