]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/FancyLineEdit.cpp
Set a maximum value to zoom level
[lyx.git] / src / frontends / qt4 / FancyLineEdit.cpp
1 /**
2  * \file fancylineedit.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Nokia Corporation (qt-info@nokia.com)
7  *
8  * Full author contact details are available in file CREDITS.
9  *
10  */
11
12 // Code taken from the Qt Creator project and customized a little
13
14 #include <config.h>
15
16 #include "FancyLineEdit.h"
17
18 #if QT_VERSION >= 0x040600
19
20 #include <QEvent>
21 #include <QDebug>
22 #include <QString>
23 #include <QPropertyAnimation>
24 #include <QApplication>
25 #include <QMenu>
26 #include <QMouseEvent>
27 #include <QLabel>
28 #include <QAbstractButton>
29 #include <QPainter>
30 #include <QStyle>
31 #include <QPaintEvent>
32
33 enum { margin = 6 };
34
35 #define ICONBUTTON_HEIGHT 18
36 #define FADE_TIME 160
37
38
39 namespace lyx {
40 namespace frontend {
41
42 // --------- FancyLineEditPrivate
43 class FancyLineEditPrivate : public QObject {
44 public:
45     explicit FancyLineEditPrivate(FancyLineEdit *parent);
46
47     virtual bool eventFilter(QObject *obj, QEvent *event);
48
49     FancyLineEdit  *m_lineEdit;
50     QPixmap m_pixmap[2];
51     QMenu *m_menu[2];
52     bool m_menuTabFocusTrigger[2];
53     IconButton *m_iconbutton[2];
54     bool m_iconEnabled[2];
55 };
56
57
58 FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
59     QObject(parent),
60     m_lineEdit(parent)
61 {
62     for (int i = 0; i < 2; ++i) {
63         m_menu[i] = 0;
64         m_menuTabFocusTrigger[i] = false;
65         m_iconbutton[i] = new IconButton(parent);
66         m_iconbutton[i]->installEventFilter(this);
67         m_iconbutton[i]->hide();
68         m_iconbutton[i]->setAutoHide(false);
69         m_iconEnabled[i] = false;
70     }
71 }
72
73 bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event)
74 {
75     int buttonIndex = -1;
76     for (int i = 0; i < 2; ++i) {
77         if (obj == m_iconbutton[i]) {
78             buttonIndex = i;
79             break;
80         }
81     }
82     if (buttonIndex == -1)
83         return QObject::eventFilter(obj, event);
84     switch (event->type()) {
85     case QEvent::FocusIn:
86         if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) {
87             m_lineEdit->setFocus();
88             m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal(
89                     m_iconbutton[buttonIndex]->rect().center()));
90             return true;
91         }
92     default:
93         break;
94     }
95     return QObject::eventFilter(obj, event);
96 }
97
98
99 // --------- FancyLineEdit
100 FancyLineEdit::FancyLineEdit(QWidget *parent) :
101     QLineEdit(parent),
102     m_d(new FancyLineEditPrivate(this))
103 {
104     ensurePolished();
105     updateMargins();
106
107     connect(this, SIGNAL(textChanged(QString)),
108             this, SLOT(checkButtons(QString)));
109     connect(m_d->m_iconbutton[Left], SIGNAL(clicked()),
110             this, SLOT(iconClicked()));
111     connect(m_d->m_iconbutton[Right], SIGNAL(clicked()),
112             this, SLOT(iconClicked()));
113 }
114
115 void FancyLineEdit::checkButtons(const QString &text)
116 {
117     if (m_oldText.isEmpty() || text.isEmpty()) {
118         for (int i = 0; i < 2; ++i) {
119             if (m_d->m_iconbutton[i]->hasAutoHide())
120                 m_d->m_iconbutton[i]->animateShow(!text.isEmpty());
121         }
122         m_oldText = text;
123     }
124 }
125
126 FancyLineEdit::~FancyLineEdit()
127 {
128 }
129
130 void FancyLineEdit::setButtonVisible(Side side, bool visible)
131 {
132     m_d->m_iconbutton[side]->setVisible(visible);
133     m_d->m_iconEnabled[side] = visible;
134     updateMargins();
135 }
136
137 bool FancyLineEdit::isButtonVisible(Side side) const
138 {
139     return m_d->m_iconEnabled[side];
140 }
141
142 void FancyLineEdit::iconClicked()
143 {
144     IconButton *button = qobject_cast<IconButton *>(sender());
145     int index = -1;
146     for (int i = 0; i < 2; ++i)
147         if (m_d->m_iconbutton[i] == button)
148             index = i;
149     if (index == -1)
150         return;
151     if (m_d->m_menu[index]) {
152         m_d->m_menu[index]->exec(QCursor::pos());
153     } else {
154                 buttonClicked((Side)index);
155         if (index == Left)
156                         leftButtonClicked();
157         else if (index == Right)
158                         rightButtonClicked();
159     }
160 }
161
162 void FancyLineEdit::updateMargins()
163 {
164     bool leftToRight = (layoutDirection() == Qt::LeftToRight);
165     Side realLeft = (leftToRight ? Left : Right);
166     Side realRight = (leftToRight ? Right : Left);
167
168     int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8;
169     int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8;
170     // Note KDE does not reserve space for the highlight color
171     if (style()->inherits("OxygenStyle")) {
172         leftMargin = qMax(24, leftMargin);
173         rightMargin = qMax(24, rightMargin);
174     }
175
176     QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0,
177                      (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0);
178
179     setTextMargins(margins);
180 }
181
182 void FancyLineEdit::updateButtonPositions()
183 {
184     QRect contentRect = rect();
185     for (int i = 0; i < 2; ++i) {
186         Side iconpos = (Side)i;
187         if (layoutDirection() == Qt::RightToLeft)
188             iconpos = (iconpos == Left ? Right : Left);
189
190         if (iconpos == FancyLineEdit::Right) {
191             const int iconoffset = textMargins().right() + 4;
192             m_d->m_iconbutton[i]->
193                     setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0));
194         } else {
195             const int iconoffset = textMargins().left() + 4;
196             m_d->m_iconbutton[i]->
197                     setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0));
198         }
199     }
200 }
201
202 void FancyLineEdit::resizeEvent(QResizeEvent *)
203 {
204     updateButtonPositions();
205 }
206
207
208 void FancyLineEdit::keyPressEvent(QKeyEvent * e)
209 {
210         if (e->type() == QEvent::KeyPress && e->key() == Qt::Key_Down)
211                 Q_EMIT downPressed();
212         else
213                 QLineEdit::keyPressEvent(e);
214 }
215
216
217 void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap)
218 {
219     m_d->m_iconbutton[side]->setPixmap(buttonPixmap);
220     updateMargins();
221     updateButtonPositions();
222     update();
223 }
224
225 QPixmap FancyLineEdit::buttonPixmap(Side side) const
226 {
227     return m_d->m_pixmap[side];
228 }
229
230 void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu)
231 {
232      m_d->m_menu[side] = buttonMenu;
233      m_d->m_iconbutton[side]->setIconOpacity(1.0);
234  }
235
236 QMenu *FancyLineEdit::buttonMenu(Side side) const
237 {
238     return  m_d->m_menu[side];
239 }
240
241 bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const
242 {
243     return m_d->m_menuTabFocusTrigger[side];
244 }
245
246 void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v)
247 {
248     if (m_d->m_menuTabFocusTrigger[side] == v)
249         return;
250
251     m_d->m_menuTabFocusTrigger[side] = v;
252     m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus);
253 }
254
255 bool FancyLineEdit::hasAutoHideButton(Side side) const
256 {
257     return m_d->m_iconbutton[side]->hasAutoHide();
258 }
259
260 void FancyLineEdit::setAutoHideButton(Side side, bool h)
261 {
262     m_d->m_iconbutton[side]->setAutoHide(h);
263     if (h)
264         m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ?  0.0 : 1.0);
265     else
266         m_d->m_iconbutton[side]->setIconOpacity(1.0);
267 }
268
269 void FancyLineEdit::setButtonToolTip(Side side, const QString &tip)
270 {
271     m_d->m_iconbutton[side]->setToolTip(tip);
272 }
273
274 void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy)
275 {
276     m_d->m_iconbutton[side]->setFocusPolicy(policy);
277 }
278
279 // IconButton - helper class to represent a clickable icon
280
281 IconButton::IconButton(QWidget *parent)
282     : QAbstractButton(parent), m_iconOpacity(0.0), m_autoHide(false)
283 {
284     setCursor(Qt::ArrowCursor);
285     setFocusPolicy(Qt::NoFocus);
286 }
287
288 void IconButton::paintEvent(QPaintEvent *)
289 {
290     QPainter painter(this);
291     QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
292     pixmapRect.moveCenter(rect().center());
293
294     if (m_autoHide)
295         painter.setOpacity(m_iconOpacity);
296
297     painter.drawPixmap(pixmapRect, m_pixmap);
298 }
299
300 void IconButton::animateShow(bool visible)
301 {
302     if (visible) {
303         QPropertyAnimation *animation =
304                 new QPropertyAnimation(this, "iconOpacity");
305         animation->setDuration(FADE_TIME);
306         animation->setEndValue(1.0);
307         animation->start(QAbstractAnimation::DeleteWhenStopped);
308     } else {
309         QPropertyAnimation *animation =
310                 new QPropertyAnimation(this, "iconOpacity");
311         animation->setDuration(FADE_TIME);
312         animation->setEndValue(0.0);
313         animation->start(QAbstractAnimation::DeleteWhenStopped);
314     }
315 }
316
317 } // namespace frontend
318
319 } // namespace lyx
320
321 #endif // QT_VERSION >= 0x040600
322
323 #include "moc_FancyLineEdit.cpp"