2 ******************************************************************************
4 * @file fancylineedit.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "fancylineedit.h"
31 #include <QtCore/QEvent>
32 #include <QtCore/QDebug>
33 #include <QtCore/QString>
34 #include <QtWidgets/QApplication>
36 #include <QMouseEvent>
42 static inline QString
sideToStyleSheetString(FancyLineEdit::Side side
)
44 return side
== FancyLineEdit::Left
? QLatin1String("left") : QLatin1String("right");
47 // Format style sheet for the label containing the pixmap. It has a margin on
48 // the outer side of the whole FancyLineEdit.
49 static QString
labelStyleSheet(FancyLineEdit::Side side
)
51 QString rc
= QLatin1String("QLabel { margin-");
53 rc
+= sideToStyleSheetString(side
);
54 rc
+= QLatin1String(": ");
55 rc
+= QString::number(margin
);
56 rc
+= QLatin1Char('}');
60 // --------- FancyLineEditPrivate as QObject with label
63 class FancyLineEditPrivate
: public QObject
{
65 explicit FancyLineEditPrivate(QLineEdit
*parent
);
67 virtual bool eventFilter(QObject
*obj
, QEvent
*event
);
69 const QString m_leftLabelStyleSheet
;
70 const QString m_rightLabelStyleSheet
;
72 QLineEdit
*m_lineEdit
;
76 FancyLineEdit::Side m_side
;
77 bool m_useLayoutDirection
;
78 bool m_menuTabFocusTrigger
;
80 bool m_showingHintText
;
84 FancyLineEditPrivate::FancyLineEditPrivate(QLineEdit
*parent
) :
86 m_leftLabelStyleSheet(labelStyleSheet(FancyLineEdit::Left
)),
87 m_rightLabelStyleSheet(labelStyleSheet(FancyLineEdit::Right
)),
91 m_side(FancyLineEdit::Left
),
92 m_useLayoutDirection(false),
93 m_menuTabFocusTrigger(false),
94 m_showingHintText(false)
97 bool FancyLineEditPrivate::eventFilter(QObject
*obj
, QEvent
*event
)
99 if (!m_menu
|| obj
!= m_menuLabel
) {
100 return QObject::eventFilter(obj
, event
);
103 switch (event
->type()) {
104 case QEvent::MouseButtonPress
:
106 const QMouseEvent
*me
= static_cast<QMouseEvent
*>(event
);
107 m_menu
->exec(me
->globalPos());
110 case QEvent::FocusIn
:
111 if (m_menuTabFocusTrigger
) {
112 m_lineEdit
->setFocus();
113 m_menu
->exec(m_menuLabel
->mapToGlobal(m_menuLabel
->rect().center()));
119 return QObject::eventFilter(obj
, event
);
122 // --------- FancyLineEdit
123 FancyLineEdit::FancyLineEdit(QWidget
*parent
) :
125 m_d(new FancyLineEditPrivate(this))
127 m_d
->m_menuLabel
= new QLabel(this);
128 m_d
->m_menuLabel
->installEventFilter(m_d
);
133 FancyLineEdit::~FancyLineEdit()
136 // Position the menu label left or right according to size.
137 // Called when switching side and from resizeEvent.
138 void FancyLineEdit::positionMenuLabel()
142 m_d
->m_menuLabel
->setGeometry(0, 0, m_d
->m_pixmap
.width() + margin
, height());
145 m_d
->m_menuLabel
->setGeometry(width() - m_d
->m_pixmap
.width() - margin
, 0,
146 m_d
->m_pixmap
.width() + margin
, height());
151 void FancyLineEdit::updateStyleSheet(Side side
)
153 // Udate the LineEdit style sheet. Make room for the label on the
154 // respective side and set color according to whether we are showing the
156 QString sheet
= QLatin1String("QLineEdit{ padding-");
158 sheet
+= sideToStyleSheetString(side
);
159 sheet
+= QLatin1String(": ");
160 sheet
+= QString::number(m_d
->m_pixmap
.width() + margin
);
161 sheet
+= QLatin1Char(';');
162 if (m_d
->m_showingHintText
) {
163 sheet
+= QLatin1String(" color: #BBBBBB;");
165 sheet
+= QLatin1Char('}');
166 setStyleSheet(sheet
);
169 void FancyLineEdit::updateMenuLabel()
171 m_d
->m_menuLabel
->setPixmap(m_d
->m_pixmap
);
172 const Side s
= side();
175 m_d
->m_menuLabel
->setAlignment(Qt::AlignVCenter
| Qt::AlignLeft
);
176 m_d
->m_menuLabel
->setStyleSheet(m_d
->m_leftLabelStyleSheet
);
179 m_d
->m_menuLabel
->setAlignment(Qt::AlignVCenter
| Qt::AlignRight
);
180 m_d
->m_menuLabel
->setStyleSheet(m_d
->m_rightLabelStyleSheet
);
187 void FancyLineEdit::setSide(Side side
)
193 FancyLineEdit::Side
FancyLineEdit::side() const
195 if (m_d
->m_useLayoutDirection
) {
196 return qApp
->layoutDirection() == Qt::LeftToRight
? Left
: Right
;
201 void FancyLineEdit::resizeEvent(QResizeEvent
*)
206 void FancyLineEdit::setPixmap(const QPixmap
&pixmap
)
208 m_d
->m_pixmap
= pixmap
;
212 QPixmap
FancyLineEdit::pixmap() const
214 return m_d
->m_pixmap
;
217 void FancyLineEdit::setMenu(QMenu
*menu
)
222 QMenu
*FancyLineEdit::menu() const
227 bool FancyLineEdit::useLayoutDirection() const
229 return m_d
->m_useLayoutDirection
;
232 void FancyLineEdit::setUseLayoutDirection(bool v
)
234 m_d
->m_useLayoutDirection
= v
;
237 bool FancyLineEdit::isSideStored() const
239 return !m_d
->m_useLayoutDirection
;
242 bool FancyLineEdit::hasMenuTabFocusTrigger() const
244 return m_d
->m_menuTabFocusTrigger
;
247 void FancyLineEdit::setMenuTabFocusTrigger(bool v
)
249 if (m_d
->m_menuTabFocusTrigger
== v
) {
253 m_d
->m_menuTabFocusTrigger
= v
;
254 m_d
->m_menuLabel
->setFocusPolicy(v
? Qt::TabFocus
: Qt::NoFocus
);
257 QString
FancyLineEdit::hintText() const
259 return m_d
->m_hintText
;
262 void FancyLineEdit::setHintText(const QString
&ht
)
264 // Updating magic to make the property work in Designer.
265 if (ht
== m_d
->m_hintText
) {
269 m_d
->m_hintText
= ht
;
270 if (!hasFocus() && !ht
.isEmpty()) {
275 void FancyLineEdit::showHintText()
277 if (!m_d
->m_showingHintText
&& text().isEmpty() && !m_d
->m_hintText
.isEmpty()) {
278 m_d
->m_showingHintText
= true;
279 setText(m_d
->m_hintText
);
280 updateStyleSheet(side());
284 void FancyLineEdit::hideHintText()
286 if (m_d
->m_showingHintText
&& !m_d
->m_hintText
.isEmpty()) {
287 m_d
->m_showingHintText
= false;
289 updateStyleSheet(side());
293 void FancyLineEdit::focusInEvent(QFocusEvent
*e
)
296 QLineEdit::focusInEvent(e
);
299 void FancyLineEdit::focusOutEvent(QFocusEvent
*e
)
301 // Focus out: Switch to displaying the hint text unless
302 // there is user input
304 QLineEdit::focusOutEvent(e
);
307 bool FancyLineEdit::isShowingHintText() const
309 return m_d
->m_showingHintText
;
312 QString
FancyLineEdit::typedText() const
314 return m_d
->m_showingHintText
? QString() : text();