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>
36 #if QT_VERSION >= 0x050000
42 #define ICONBUTTON_HEIGHT 18
49 ////////////////////////////////////////////////////////////////////////
51 // FancyLineEditPrivate
53 ////////////////////////////////////////////////////////////////////////
55 class FancyLineEditPrivate : public QObject {
57 explicit FancyLineEditPrivate(FancyLineEdit *parent);
59 bool eventFilter(QObject *obj, QEvent *event) override;
61 FancyLineEdit *m_lineEdit;
64 bool m_menuTabFocusTrigger[2];
65 IconButton *m_iconbutton[2];
66 bool m_iconEnabled[2];
70 FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent)
71 : QObject(parent), m_lineEdit(parent)
73 for (int i = 0; i < 2; ++i) {
75 m_menuTabFocusTrigger[i] = false;
76 m_iconbutton[i] = new IconButton(parent);
77 m_iconbutton[i]->installEventFilter(this);
78 m_iconbutton[i]->hide();
79 m_iconbutton[i]->setAutoHide(false);
80 m_iconEnabled[i] = false;
85 bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
88 for (int i = 0; i < 2; ++i) {
89 if (obj == m_iconbutton[i]) {
94 if (buttonIndex == -1)
95 return QObject::eventFilter(obj, event);
96 switch (event->type()) {
98 if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
99 m_lineEdit->setFocus();
100 m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
101 m_iconbutton[buttonIndex]->rect().center()));
107 return QObject::eventFilter(obj, event);
111 ////////////////////////////////////////////////////////////////////////
115 ////////////////////////////////////////////////////////////////////////
117 FancyLineEdit::FancyLineEdit(QWidget *parent) :
119 m_d(new FancyLineEditPrivate(this))
124 connect(this, SIGNAL(textChanged(QString)),
125 this, SLOT(checkButtons(QString)));
126 connect(m_d->m_iconbutton[Left], SIGNAL(clicked()),
127 this, SLOT(iconClicked()));
128 connect(m_d->m_iconbutton[Right], SIGNAL(clicked()),
129 this, SLOT(iconClicked()));
133 void FancyLineEdit::checkButtons(const QString &text)
135 if (m_oldText.isEmpty() || text.isEmpty()) {
136 for (int i = 0; i < 2; ++i) {
137 if (m_d->m_iconbutton[i]->hasAutoHide())
138 m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
145 void FancyLineEdit::setClearButton(bool visible)
147 // QLineEdit::setClearButtonEnabled() has been implemented in Qt 5.2.
148 // In earlier Qt versions, we roll our own button
149 #if QT_VERSION < 0x050200
150 setButtonPixmap(FancyLineEdit::Right, getPixmap("images/", "editclear", "svgz,png"));
151 setButtonVisible(FancyLineEdit::Right, visible);
152 setAutoHideButton(FancyLineEdit::Right, true);
154 setClearButtonEnabled(visible);
159 void FancyLineEdit::setButtonVisible(Side side, bool visible)
161 m_d->m_iconbutton[side]->setVisible(visible);
162 m_d->m_iconEnabled[side] = visible;
167 bool FancyLineEdit::isButtonVisible(Side side) const
169 return m_d->m_iconEnabled[side];
173 void FancyLineEdit::iconClicked()
175 IconButton *button = qobject_cast<IconButton *>(sender());
177 for (int i = 0; i < 2; ++i)
178 if (m_d->m_iconbutton[i] == button)
182 if (m_d->m_menu[index]) {
183 m_d->m_menu[index]->exec(QCursor::pos());
185 buttonClicked((Side)index);
188 else if (index == Right)
189 rightButtonClicked();
194 void FancyLineEdit::updateMargins()
196 bool leftToRight = (layoutDirection() == Qt::LeftToRight);
197 Side realLeft = (leftToRight ? Left : Right);
198 Side realRight = (leftToRight ? Right : Left);
201 #if QT_VERSION >= 0x050000
202 // Consider device/pixel ratio (HiDPI)
203 dpr = devicePixelRatio();
205 int leftMargin = (m_d->m_iconbutton[realLeft]->pixmap().width() / dpr ) + 8;
206 int rightMargin = (m_d->m_iconbutton[realRight]->pixmap().width() / dpr) + 8;
207 // Note KDE does not reserve space for the highlight color
208 if (style()->inherits("OxygenStyle")) {
209 leftMargin = qMax(24, leftMargin);
210 rightMargin = qMax(24, rightMargin);
213 QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
214 (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
216 setTextMargins(margins);
220 void FancyLineEdit::updateButtonPositions()
222 QRect contentRect = rect();
223 for (int i = 0; i < 2; ++i) {
224 Side iconpos = (Side)i;
225 if (layoutDirection() == Qt::RightToLeft)
226 iconpos = (iconpos == Left ? Right : Left);
228 if (iconpos == FancyLineEdit::Right) {
229 const int iconoffset = textMargins().right() + 4;
230 m_d->m_iconbutton[i]->setGeometry(
231 contentRect.adjusted(width() - iconoffset,
234 const int iconoffset = textMargins().left() + 4;
235 m_d->m_iconbutton[i]->setGeometry(
236 contentRect.adjusted(0, 0,
237 -width() + iconoffset, 0));
243 void FancyLineEdit::resizeEvent(QResizeEvent *)
245 updateButtonPositions();
249 void FancyLineEdit::keyPressEvent(QKeyEvent * e)
251 if (e->type() == QEvent::KeyPress && e->key() == Qt::Key_Down)
252 Q_EMIT downPressed();
254 QLineEdit::keyPressEvent(e);
258 void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
260 m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
262 updateButtonPositions();
267 QPixmap FancyLineEdit::buttonPixmap(Side side) const
269 return m_d->m_pixmap[side];
273 void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
275 m_d->m_menu[side] = buttonMenu;
276 m_d->m_iconbutton[side]->setIconOpacity(1.0);
279 QMenu *FancyLineEdit::buttonMenu(Side side) const
281 return m_d->m_menu[side];
285 bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
287 return m_d->m_menuTabFocusTrigger[side];
291 void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
293 if (m_d->m_menuTabFocusTrigger[side] == v)
296 m_d->m_menuTabFocusTrigger[side] = v;
297 m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
301 bool FancyLineEdit::hasAutoHideButton(Side side) const
303 return m_d->m_iconbutton[side]->hasAutoHide();
307 void FancyLineEdit::setAutoHideButton(Side side, bool h)
309 m_d->m_iconbutton[side]->setAutoHide(h);
311 m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ? 0.0 : 1.0);
313 m_d->m_iconbutton[side]->setIconOpacity(1.0);
317 void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
319 m_d->m_iconbutton[side]->setToolTip(tip);
323 void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
325 m_d->m_iconbutton[side]->setFocusPolicy(policy);
329 ////////////////////////////////////////////////////////////////////////
331 // IconButton - helper class to represent a clickable icon
333 ////////////////////////////////////////////////////////////////////////
335 IconButton::IconButton(QWidget *parent)
336 : QAbstractButton(parent), m_iconOpacity(0.0), m_autoHide(false)
338 setCursor(Qt::ArrowCursor);
339 setFocusPolicy(Qt::NoFocus);
343 void IconButton::paintEvent(QPaintEvent *)
346 #if QT_VERSION >= 0x050000
347 // Consider device/pixel ratio (HiDPI)
348 QWindow * window = this->window()->windowHandle();
349 dpr = window->devicePixelRatio();
351 QRect pixmapRect(QPoint(), m_pixmap.size() / dpr);
352 pixmapRect.moveCenter(rect().center());
353 QPixmap pm = m_pixmap;
355 QPainter painter(this);
357 painter.setOpacity(m_iconOpacity);
359 painter.drawPixmap(pixmapRect, pm);
363 void IconButton::animateShow(bool visible)
366 QPropertyAnimation *animation =
367 new QPropertyAnimation(this, "iconOpacity");
368 animation->setDuration(FADE_TIME);
369 animation->setEndValue(1.0);
370 animation->start(QAbstractAnimation::DeleteWhenStopped);
372 QPropertyAnimation *animation =
373 new QPropertyAnimation(this, "iconOpacity");
374 animation->setDuration(FADE_TIME);
375 animation->setEndValue(0.0);
376 animation->start(QAbstractAnimation::DeleteWhenStopped);
380 } // namespace frontend
384 #endif // QT_VERSION >= 0x040600
386 #include "moc_FancyLineEdit.cpp"