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
16 #include "FancyLineEdit.h"
18 #if QT_VERSION < 0x050200
19 #include "GuiApplication.h"
22 #if QT_VERSION >= 0x040600
27 #include <QPropertyAnimation>
28 #include <QApplication>
30 #include <QMouseEvent>
32 #include <QAbstractButton>
35 #include <QPaintEvent>
39 #define ICONBUTTON_HEIGHT 18
46 ////////////////////////////////////////////////////////////////////////
48 // FancyLineEditPrivate
50 ////////////////////////////////////////////////////////////////////////
52 class FancyLineEditPrivate : public QObject {
54 explicit FancyLineEditPrivate(FancyLineEdit *parent);
56 bool eventFilter(QObject *obj, QEvent *event) override;
58 FancyLineEdit *m_lineEdit;
61 bool m_menuTabFocusTrigger[2];
62 IconButton *m_iconbutton[2];
63 bool m_iconEnabled[2];
67 FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent)
68 : QObject(parent), m_lineEdit(parent)
70 for (int i = 0; i < 2; ++i) {
72 m_menuTabFocusTrigger[i] = false;
73 m_iconbutton[i] = new IconButton(parent);
74 m_iconbutton[i]->installEventFilter(this);
75 m_iconbutton[i]->hide();
76 m_iconbutton[i]->setAutoHide(false);
77 m_iconEnabled[i] = false;
82 bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
85 for (int i = 0; i < 2; ++i) {
86 if (obj == m_iconbutton[i]) {
91 if (buttonIndex == -1)
92 return QObject::eventFilter(obj, event);
93 switch (event->type()) {
95 if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
96 m_lineEdit->setFocus();
97 m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
98 m_iconbutton[buttonIndex]->rect().center()));
104 return QObject::eventFilter(obj, event);
108 ////////////////////////////////////////////////////////////////////////
112 ////////////////////////////////////////////////////////////////////////
114 FancyLineEdit::FancyLineEdit(QWidget *parent) :
116 m_d(new FancyLineEditPrivate(this))
121 connect(this, SIGNAL(textChanged(QString)),
122 this, SLOT(checkButtons(QString)));
123 connect(m_d->m_iconbutton[Left], SIGNAL(clicked()),
124 this, SLOT(iconClicked()));
125 connect(m_d->m_iconbutton[Right], SIGNAL(clicked()),
126 this, SLOT(iconClicked()));
130 void FancyLineEdit::checkButtons(const QString &text)
132 if (m_oldText.isEmpty() || text.isEmpty()) {
133 for (int i = 0; i < 2; ++i) {
134 if (m_d->m_iconbutton[i]->hasAutoHide())
135 m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
142 void FancyLineEdit::setClearButton(bool visible)
144 // QLineEdit::setClearButtonEnabled() has been implemented in Qt 5.2.
145 // In earlier Qt versions, we roll our own button
146 #if QT_VERSION < 0x050200
147 setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "svgz,png"));
148 setButtonVisible(FancyLineEdit::Right, visible);
149 setAutoHideButton(FancyLineEdit::Right, true);
151 setClearButtonEnabled(visible);
156 void FancyLineEdit::setButtonVisible(Side side, bool visible)
158 m_d->m_iconbutton[side]->setVisible(visible);
159 m_d->m_iconEnabled[side] = visible;
164 bool FancyLineEdit::isButtonVisible(Side side) const
166 return m_d->m_iconEnabled[side];
170 void FancyLineEdit::iconClicked()
172 IconButton *button = qobject_cast<IconButton *>(sender());
174 for (int i = 0; i < 2; ++i)
175 if (m_d->m_iconbutton[i] == button)
179 if (m_d->m_menu[index]) {
180 m_d->m_menu[index]->exec(QCursor::pos());
182 buttonClicked((Side)index);
185 else if (index == Right)
186 rightButtonClicked();
191 void FancyLineEdit::updateMargins()
193 bool leftToRight = (layoutDirection() == Qt::LeftToRight);
194 Side realLeft = (leftToRight ? Left : Right);
195 Side realRight = (leftToRight ? Right : Left);
197 int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
198 int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
199 // Note KDE does not reserve space for the highlight color
200 if (style()->inherits("OxygenStyle")) {
201 leftMargin = qMax(24, leftMargin);
202 rightMargin = qMax(24, rightMargin);
205 QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
206 (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
208 setTextMargins(margins);
212 void FancyLineEdit::updateButtonPositions()
214 QRect contentRect = rect();
215 for (int i = 0; i < 2; ++i) {
216 Side iconpos = (Side)i;
217 if (layoutDirection() == Qt::RightToLeft)
218 iconpos = (iconpos == Left ? Right : Left);
220 if (iconpos == FancyLineEdit::Right) {
221 const int iconoffset = textMargins().right() + 4;
222 m_d->m_iconbutton[i]->setGeometry(
223 contentRect.adjusted(width() - iconoffset,
226 const int iconoffset = textMargins().left() + 4;
227 m_d->m_iconbutton[i]->setGeometry(
228 contentRect.adjusted(0, 0,
229 -width() + iconoffset, 0));
235 void FancyLineEdit::resizeEvent(QResizeEvent *)
237 updateButtonPositions();
241 void FancyLineEdit::keyPressEvent(QKeyEvent * e)
243 if (e->type() == QEvent::KeyPress && e->key() == Qt::Key_Down)
244 Q_EMIT downPressed();
246 QLineEdit::keyPressEvent(e);
250 void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
252 m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
254 updateButtonPositions();
259 QPixmap FancyLineEdit::buttonPixmap(Side side) const
261 return m_d->m_pixmap[side];
265 void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
267 m_d->m_menu[side] = buttonMenu;
268 m_d->m_iconbutton[side]->setIconOpacity(1.0);
271 QMenu *FancyLineEdit::buttonMenu(Side side) const
273 return m_d->m_menu[side];
277 bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
279 return m_d->m_menuTabFocusTrigger[side];
283 void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
285 if (m_d->m_menuTabFocusTrigger[side] == v)
288 m_d->m_menuTabFocusTrigger[side] = v;
289 m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
293 bool FancyLineEdit::hasAutoHideButton(Side side) const
295 return m_d->m_iconbutton[side]->hasAutoHide();
299 void FancyLineEdit::setAutoHideButton(Side side, bool h)
301 m_d->m_iconbutton[side]->setAutoHide(h);
303 m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ? 0.0 : 1.0);
305 m_d->m_iconbutton[side]->setIconOpacity(1.0);
309 void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
311 m_d->m_iconbutton[side]->setToolTip(tip);
315 void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
317 m_d->m_iconbutton[side]->setFocusPolicy(policy);
321 ////////////////////////////////////////////////////////////////////////
323 // IconButton - helper class to represent a clickable icon
325 ////////////////////////////////////////////////////////////////////////
327 IconButton::IconButton(QWidget *parent)
328 : QAbstractButton(parent), m_iconOpacity(0.0), m_autoHide(false)
330 setCursor(Qt::ArrowCursor);
331 setFocusPolicy(Qt::NoFocus);
335 void IconButton::paintEvent(QPaintEvent *)
337 QPainter painter(this);
338 QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
339 pixmapRect.moveCenter(rect().center());
342 painter.setOpacity(m_iconOpacity);
344 painter.drawPixmap(pixmapRect, m_pixmap);
348 void IconButton::animateShow(bool visible)
351 QPropertyAnimation *animation =
352 new QPropertyAnimation(this, "iconOpacity");
353 animation->setDuration(FADE_TIME);
354 animation->setEndValue(1.0);
355 animation->start(QAbstractAnimation::DeleteWhenStopped);
357 QPropertyAnimation *animation =
358 new QPropertyAnimation(this, "iconOpacity");
359 animation->setDuration(FADE_TIME);
360 animation->setEndValue(0.0);
361 animation->start(QAbstractAnimation::DeleteWhenStopped);
365 } // namespace frontend
369 #endif // QT_VERSION >= 0x040600
371 #include "moc_FancyLineEdit.cpp"