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