1 // Commit: 47712d1f330e4b22ce6dd30e7557288ef7f7fca0
2 /****************************************************************************
4 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: http://www.qt-project.org/
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this
15 ** file. Please review the following information to ensure the GNU Lesser
16 ** General Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
23 ** GNU General Public License Usage
24 ** Alternatively, this file may be used under the terms of the GNU General
25 ** Public License version 3.0 as published by the Free Software Foundation
26 ** and appearing in the file LICENSE.GPL included in the packaging of this
27 ** file. Please review the following information to ensure the GNU General
28 ** Public License version 3.0 requirements will be met:
29 ** http://www.gnu.org/copyleft/gpl.html.
32 ** Alternatively, this file may be used in accordance with the terms and
33 ** conditions contained in a signed written agreement between you and Nokia.
41 ****************************************************************************/
43 #ifndef QQUICKTEXTINPUT_P_P_H
44 #define QQUICKTEXTINPUT_P_P_H
46 #include "qquicktextinput_p.h"
47 #include "qquicktext_p.h"
48 #include "qquickimplicitsizeitem_p_p.h"
50 #include <QtDeclarative/qdeclarative.h>
51 #include <QtCore/qelapsedtimer.h>
52 #include <QtCore/qpointer.h>
53 #include <QtCore/qbasictimer.h>
54 #include <QtGui/qclipboard.h>
55 #include <QtGui/qguiapplication.h>
56 #include <QtGui/qpalette.h>
57 #include <QtGui/qtextlayout.h>
58 #include <QtGui/qstylehints.h>
60 #include "qplatformdefs.h"
66 // This file is not part of the Qt API. It exists purely as an
67 // implementation detail. This header file may change from version to
68 // version without notice, or even be removed.
76 class Q_AUTOTEST_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate
78 Q_DECLARE_PUBLIC(QQuickTextInput)
80 QQuickTextInputPrivate()
100 , style(QQuickText::Normal)
101 , hAlign(QQuickTextInput::AlignLeft)
102 , vAlign(QQuickTextInput::AlignTop)
103 , wrapMode(QQuickTextInput::NoWrap)
104 , mouseSelectionMode(QQuickTextInput::SelectCharacters)
105 , inputMethodHints(Qt::ImhNone)
106 , m_layoutDirection(Qt::LayoutDirectionAuto)
107 , m_passwordCharacter(QLatin1Char('*'))
110 , cursorVisible(false)
112 , selectByMouse(false)
114 , canPasteValid(false)
117 , hAlignImplicit(true)
118 , selectPressed(false)
119 , textLayoutDirty(true)
120 , m_hideCursor(false)
123 , m_echoMode(QQuickTextInput::Normal)
128 , m_acceptableInput(1)
130 , m_passwordEchoEditing(false)
131 , updateType(UpdatePaintNode)
135 ~QQuickTextInputPrivate()
140 void startCreatingCursor();
141 void updateHorizontalScroll();
142 void updateVerticalScroll();
143 bool determineHorizontalAlignment();
144 bool setHAlign(QQuickTextInput::HAlignment, bool forceAlign = false);
146 bool sendMouseEventToInputContext(QMouseEvent *event);
147 void updateInputMethodHints();
151 struct MaskInputData {
152 enum Casemode { NoCaseMode, Upper, Lower };
153 QChar maskChar; // either the separator char or the inputmask
158 // undo/redo handling
159 enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
162 inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
165 int pos, selStart, selEnd;
170 DrawSelections = 0x02,
172 DrawAll = DrawText | DrawSelections | DrawCursor
175 QTextLayout m_textLayout;
178 QString m_cancelText;
179 QString m_tentativeCommit;
184 QColor selectionColor;
185 QColor selectedTextColor;
187 QPointer<QDeclarativeComponent> cursorComponent;
188 QPointer<QQuickItem> cursorItem;
189 #ifndef QT_NO_VALIDATOR
190 QPointer<QValidator> m_validator;
193 QQuickTextNode *textNode;
194 MaskInputData *m_maskData;
195 QElapsedTimer tripleClickTimer;
196 QPoint tripleClickStartPoint;
197 QList<int> m_transactions;
198 QVector<Command> m_history;
201 int lastSelectionStart;
202 int lastSelectionEnd;
210 int m_blinkPeriod; // 0 for non-blinking cursor
212 int m_deleteAllTimer;
213 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
214 QBasicTimer m_passwordEchoTimer;
224 QQuickText::TextStyle style;
225 QQuickTextInput::HAlignment hAlign;
226 QQuickTextInput::VAlignment vAlign;
227 QQuickTextInput::WrapMode wrapMode;
228 QQuickTextInput::SelectionMode mouseSelectionMode;
229 Qt::InputMethodHints inputMethodHints;
230 Qt::LayoutDirection m_layoutDirection;
233 QChar m_passwordCharacter;
237 bool cursorVisible:1;
239 bool selectByMouse:1;
241 bool canPasteValid:1;
244 bool hAlignImplicit:1;
245 bool selectPressed:1;
246 bool textLayoutDirty:1;
248 uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
249 uint m_separator : 1;
252 uint m_textDirty : 1;
253 uint m_preeditDirty : 1;
255 uint m_validInput : 1;
256 uint m_acceptableInput : 1;
257 uint m_blinkStatus : 1;
258 uint m_passwordEchoEditing;
262 UpdateOnlyPreprocess,
265 UpdateType updateType;
267 static inline QQuickTextInputPrivate *get(QQuickTextInput *t) {
270 bool hasPendingTripleClick() const {
271 return !tripleClickTimer.hasExpired(qApp->styleHints()->mouseDoubleClickInterval());
275 int nextMaskBlank(int pos)
277 int c = findInMask(pos, true, false);
278 m_separator |= (c != pos);
279 return (c != -1 ? c : m_maxLength);
282 int prevMaskBlank(int pos)
284 int c = findInMask(pos, false, false);
285 m_separator |= (c != pos);
286 return (c != -1 ? c : 0);
289 bool isUndoAvailable() const { return !m_readOnly && m_undoState; }
290 bool isRedoAvailable() const { return !m_readOnly && m_undoState < (int)m_history.size(); }
291 void clearUndo() { m_history.clear(); m_modifiedState = m_undoState = 0; }
293 bool isModified() const { return m_modifiedState != m_undoState; }
294 void setModified(bool modified) { m_modifiedState = modified ? -1 : m_undoState; }
296 bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
297 bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
299 void setSelection(int start, int length);
301 inline QString selectedText() const { return hasSelectedText() ? m_text.mid(m_selstart, m_selend - m_selstart) : QString(); }
302 QString textBeforeSelection() const { return hasSelectedText() ? m_text.left(m_selstart) : QString(); }
303 QString textAfterSelection() const { return hasSelectedText() ? m_text.mid(m_selend) : QString(); }
305 int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
306 int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
308 int positionAt(int x, int y, QTextLine::CursorPosition position) const;
309 int positionAt(const QPointF &point, QTextLine::CursorPosition position = QTextLine::CursorBetweenCharacters) const {
310 return positionAt(point.x(), point.y(), position);
313 void removeSelection()
315 int priorState = m_undoState;
316 removeSelectedText();
317 finishChange(priorState);
320 int start() const { return 0; }
321 int end() const { return m_text.length(); }
323 QString realText() const;
325 #ifndef QT_NO_CLIPBOARD
326 void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
327 void paste(QClipboard::Mode mode = QClipboard::Clipboard);
330 void commitPreedit();
332 Qt::CursorMoveStyle cursorMoveStyle() const { return m_textLayout.cursorMoveStyle(); }
333 void setCursorMoveStyle(Qt::CursorMoveStyle style) { m_textLayout.setCursorMoveStyle(style); }
335 void moveCursor(int pos, bool mark = false);
336 void cursorForward(bool mark, int steps)
341 c = cursorMoveStyle() == Qt::VisualMoveStyle ? m_textLayout.rightCursorPosition(c)
342 : m_textLayout.nextCursorPosition(c);
343 } else if (steps < 0) {
345 c = cursorMoveStyle() == Qt::VisualMoveStyle ? m_textLayout.leftCursorPosition(c)
346 : m_textLayout.previousCursorPosition(c);
351 void cursorWordForward(bool mark) { moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
352 void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
354 void home(bool mark) { moveCursor(0, mark); }
355 void end(bool mark) { moveCursor(q_func()->text().length(), mark); }
359 void deselect() { internalDeselect(); finishChange(); }
360 void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); }
362 void insert(const QString &);
364 void selectWordAtPos(int);
366 void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); }
370 QString inputMask() const { return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); }
371 void setInputMask(const QString &mask)
373 parseInputMask(mask);
375 moveCursor(nextMaskBlank(0));
380 bool composeMode() const { return !m_textLayout.preeditAreaText().isEmpty(); }
383 QString preeditAreaText() const { return m_textLayout.preeditAreaText(); }
385 void updatePasswordEchoEditing(bool editing);
387 void cancelPasswordEchoTimer() {
388 #ifdef QT_GUI_PASSWORD_ECHO_DELAY
389 m_passwordEchoTimer.stop();
393 Qt::LayoutDirection layoutDirection() const {
394 if (m_layoutDirection == Qt::LayoutDirectionAuto) {
395 if (m_text.isEmpty())
396 return qApp->inputPanel()->inputDirection();
397 return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight;
399 return m_layoutDirection;
401 void setLayoutDirection(Qt::LayoutDirection direction)
403 if (direction != m_layoutDirection) {
404 m_layoutDirection = direction;
409 void processInputMethodEvent(QInputMethodEvent *event);
410 void processKeyEvent(QKeyEvent* ev);
412 void setCursorBlinkPeriod(int msec);
413 void resetCursorBlinkTimer();
418 void init(const QString &txt);
419 void removeSelectedText();
420 void internalSetText(const QString &txt, int pos = -1, bool edited = true);
421 void updateDisplayText(bool forceUpdate = false);
423 void internalInsert(const QString &s);
424 void internalDelete(bool wasBackspace = false);
425 void internalRemove(int pos);
427 inline void internalDeselect()
429 m_selDirty |= (m_selend > m_selstart);
430 m_selstart = m_selend = 0;
433 void internalUndo(int until = -1);
435 void emitUndoRedoChanged();
437 bool emitCursorPositionChanged();
439 bool finishChange(int validateFromState = -1, bool update = false, bool edited = true);
441 void addCommand(const Command& cmd);
443 inline void separate() { m_separator = true; }
445 enum ValidatorState {
446 #ifndef QT_NO_VALIDATOR
447 InvalidInput = QValidator::Invalid,
448 IntermediateInput = QValidator::Intermediate,
449 AcceptableInput = QValidator::Acceptable
458 void parseInputMask(const QString &maskFields);
459 bool isValidInput(QChar key, QChar mask) const;
460 ValidatorState hasAcceptableInput(const QString &text) const;
462 QString maskString(uint pos, const QString &str, bool clear = false) const;
463 QString clearString(uint pos, uint len) const;
464 QString stripString(const QString &str) const;
465 int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
470 #endif // QQUICKTEXTINPUT_P_P_H