1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QLINEEDIT_P_H
41 #define QLINEEDIT_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtWidgets/private/qtwidgetsglobal_p.h>
55 
56 #include "private/qwidget_p.h"
57 #include "QtWidgets/qlineedit.h"
58 #if QT_CONFIG(toolbutton)
59 #include "QtWidgets/qtoolbutton.h"
60 #endif
61 #include "QtGui/qtextlayout.h"
62 #include "QtGui/qicon.h"
63 #include "QtWidgets/qstyleoption.h"
64 #include "QtCore/qbasictimer.h"
65 #if QT_CONFIG(completer)
66 #include "QtWidgets/qcompleter.h"
67 #endif
68 #include "QtCore/qpointer.h"
69 #include "QtCore/qmimedata.h"
70 #include <QtCore/qmargins.h>
71 
72 #include "private/qwidgetlinecontrol_p.h"
73 
74 #include <algorithm>
75 
76 QT_REQUIRE_CONFIG(lineedit);
77 
78 QT_BEGIN_NAMESPACE
79 
80 class QLineEditPrivate;
81 
82 // QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text
83 #if QT_CONFIG(toolbutton)
84 class Q_AUTOTEST_EXPORT QLineEditIconButton : public QToolButton
85 {
86     Q_OBJECT
87     Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
88 public:
89     explicit QLineEditIconButton(QWidget *parent =  nullptr);
90 
opacity()91     qreal opacity() const { return m_opacity; }
92     void setOpacity(qreal value);
93 #if QT_CONFIG(animation)
94     void animateShow(bool visible);
95 
96     bool shouldHideWithText() const;
97     void setHideWithText(bool hide);
98 #endif
99 
100 protected:
101     void actionEvent(QActionEvent *e) override;
102     void paintEvent(QPaintEvent *event) override;
103 
104 private slots:
105     void updateCursor();
106 
107 #if QT_CONFIG(animation)
108     void onAnimationFinished();
109 #endif
110 
111 private:
112 #if QT_CONFIG(animation)
113     void startOpacityAnimation(qreal endValue);
114 #endif
115     QLineEditPrivate *lineEditPrivate() const;
116 
117     qreal m_opacity;
118 
119 #if QT_CONFIG(animation)
120     bool m_hideWithText = false;
121     bool m_wasHidden = false;
122 #endif
123 
124 };
125 #endif // QT_CONFIG(toolbutton)
126 
127 class Q_AUTOTEST_EXPORT QLineEditPrivate : public QWidgetPrivate
128 {
129     Q_DECLARE_PUBLIC(QLineEdit)
130 public:
131     enum SideWidgetFlag {
132         SideWidgetFadeInWithText = 0x1,
133         SideWidgetCreatedByWidgetAction = 0x2,
134         SideWidgetClearButton = 0x4
135     };
136 
137     struct SideWidgetEntry {
widgetSideWidgetEntry138         explicit SideWidgetEntry(QWidget *w = nullptr, QAction *a = nullptr, int _flags = 0) : widget(w), action(a), flags(_flags) {}
139 
140         QWidget *widget;
141         QAction *action;
142         int flags;
143     };
144     typedef std::vector<SideWidgetEntry> SideWidgetEntryList;
145 
146     struct SideWidgetParameters {
147         int iconSize;
148         int widgetWidth;
149         int widgetHeight;
150         int margin;
151     };
152 
QLineEditPrivate()153     QLineEditPrivate()
154         : control(nullptr), frame(1), contextMenuEnabled(1), cursorVisible(0),
155         dragEnabled(0), clickCausedFocus(0), edited(0), hscroll(0), vscroll(0),
156         alignment(Qt::AlignLeading | Qt::AlignVCenter),
157         textMargins{0, 0, 0, 0},
158         lastTextSize(0), mouseYThreshold(0)
159     {
160     }
161 
~QLineEditPrivate()162     ~QLineEditPrivate()
163     {
164     }
165 
166     QWidgetLineControl *control;
167 
168 #ifndef QT_NO_CONTEXTMENU
169     QPointer<QAction> selectAllAction;
170 #endif
171     void init(const QString&);
172     void initMouseYThreshold();
173 
174     QRect adjustedControlRect(const QRect &) const;
175 
176     int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
177     bool inSelection(int x) const;
178     QRect cursorRect() const;
179     void setCursorVisible(bool visible);
180     void setText(const QString& text);
181 
182     void updatePasswordEchoEditing(bool);
183 
184     void resetInputMethod();
185 
shouldEnableInputMethod()186     inline bool shouldEnableInputMethod() const
187     {
188         return !control->isReadOnly();
189     }
shouldShowPlaceholderText()190     inline bool shouldShowPlaceholderText() const
191     {
192         return control->text().isEmpty() && control->preeditAreaText().isEmpty()
193                 && !((alignment & Qt::AlignHCenter) && q_func()->hasFocus());
194     }
195 
get(QLineEdit * lineEdit)196     static inline QLineEditPrivate *get(QLineEdit *lineEdit) {
197         return lineEdit->d_func();
198     }
199 
200     QPoint tripleClick;
201     QBasicTimer tripleClickTimer;
202     uint frame : 1;
203     uint contextMenuEnabled : 1;
204     uint cursorVisible : 1;
205     uint dragEnabled : 1;
206     uint clickCausedFocus : 1;
207     uint edited : 1;
208     int hscroll;
209     int vscroll;
210     uint alignment;
211     static const int verticalMargin;
212     static const int horizontalMargin;
213 
214     bool sendMouseEventToInputContext(QMouseEvent *e);
215 
216     QRect adjustedContentsRect() const;
217 
218     void _q_handleWindowActivate();
219     void _q_textEdited(const QString &);
220     void _q_cursorPositionChanged(int, int);
221 #ifdef QT_KEYPAD_NAVIGATION
222     void _q_editFocusChange(bool);
223 #endif
224     void _q_selectionChanged();
225     void _q_updateNeeded(const QRect &);
226 #if QT_CONFIG(completer)
227     void _q_completionHighlighted(const QString &);
228 #endif
229     QPoint mousePressPos;
230 #if QT_CONFIG(draganddrop)
231     QBasicTimer dndTimer;
232     void drag();
233 #endif
234     void _q_textChanged(const QString &);
235     void _q_clearButtonClicked();
236 
237     QMargins textMargins; // use effectiveTextMargins() in case of icon.
238 
239     QString placeholderText;
240 
241     QWidget *addAction(QAction *newAction, QAction *before, QLineEdit::ActionPosition, int flags = 0);
242     void removeAction(QAction *action);
243     SideWidgetParameters sideWidgetParameters() const;
244     QIcon clearButtonIcon() const;
245     void setClearButtonEnabled(bool enabled);
246     void positionSideWidgets();
hasSideWidgets()247     inline bool hasSideWidgets() const { return !leadingSideWidgets.empty() || !trailingSideWidgets.empty(); }
leftSideWidgetList()248     inline const SideWidgetEntryList &leftSideWidgetList() const
249         { return q_func()->layoutDirection() == Qt::LeftToRight ? leadingSideWidgets : trailingSideWidgets; }
rightSideWidgetList()250     inline const SideWidgetEntryList &rightSideWidgetList() const
251         { return q_func()->layoutDirection() == Qt::LeftToRight ? trailingSideWidgets : leadingSideWidgets; }
252 
253     QMargins effectiveTextMargins() const;
254 
255 private:
256     struct SideWidgetLocation {
257         QLineEdit::ActionPosition position;
258         int index;
259 
isValidSideWidgetLocation260         bool isValid() const { return index >= 0; }
261     };
262     friend class QTypeInfo<SideWidgetLocation>;
263 
264     SideWidgetLocation findSideWidget(const QAction *a) const;
265 
266     SideWidgetEntryList leadingSideWidgets;
267     SideWidgetEntryList trailingSideWidgets;
268     int lastTextSize;
269     int mouseYThreshold;
270 };
271 Q_DECLARE_TYPEINFO(QLineEditPrivate::SideWidgetEntry, Q_PRIMITIVE_TYPE);
272 Q_DECLARE_TYPEINFO(QLineEditPrivate::SideWidgetLocation, Q_PRIMITIVE_TYPE);
273 
274 QT_END_NAMESPACE
275 
276 #endif // QLINEEDIT_P_H
277