source: trunk/src/gui/widgets/qlinecontrol_p.h

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 14.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QLINECONTROL_P_H
43#define QLINECONTROL_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists purely as an
50// implementation detail. This header file may change from version to
51// version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include "QtCore/qglobal.h"
57
58#ifndef QT_NO_LINEEDIT
59#include "private/qwidget_p.h"
60#include "QtGui/qlineedit.h"
61#include "QtGui/qtextlayout.h"
62#include "QtGui/qstyleoption.h"
63#include "QtCore/qpointer.h"
64#include "QtGui/qlineedit.h"
65#include "QtGui/qclipboard.h"
66#include "QtCore/qpoint.h"
67#include "QtGui/qcompleter.h"
68
69QT_BEGIN_HEADER
70
71QT_BEGIN_NAMESPACE
72
73QT_MODULE(Gui)
74
75class Q_GUI_EXPORT QLineControl : public QObject
76{
77 Q_OBJECT
78
79public:
80 QLineControl(const QString &txt = QString())
81 : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LayoutDirectionAuto),
82 m_hideCursor(false), m_separator(0), m_readOnly(0),
83 m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0),
84 m_validInput(1), m_blinkStatus(0), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0),
85 m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1),
86 m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0),
87 m_selstart(0), m_selend(0), m_passwordEchoEditing(false)
88 {
89 init(txt);
90 }
91
92 ~QLineControl()
93 {
94 delete [] m_maskData;
95 }
96
97 int nextMaskBlank(int pos)
98 {
99 int c = findInMask(pos, true, false);
100 m_separator |= (c != pos);
101 return (c != -1 ? c : m_maxLength);
102 }
103
104 int prevMaskBlank(int pos)
105 {
106 int c = findInMask(pos, false, false);
107 m_separator |= (c != pos);
108 return (c != -1 ? c : 0);
109 }
110
111 bool isUndoAvailable() const { return !m_readOnly && m_undoState; }
112 bool isRedoAvailable() const { return !m_readOnly && m_undoState < (int)m_history.size(); }
113 void clearUndo() { m_history.clear(); m_modifiedState = m_undoState = 0; }
114
115 bool isModified() const { return m_modifiedState != m_undoState; }
116 void setModified(bool modified) { m_modifiedState = modified ? -1 : m_undoState; }
117
118 bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
119 bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
120
121 int width() const { return qRound(m_textLayout.lineAt(0).width()) + 1; }
122 int height() const { return qRound(m_textLayout.lineAt(0).height()) + 1; }
123 int ascent() const { return m_ascent; }
124 qreal naturalTextWidth() const { return m_textLayout.lineAt(0).naturalTextWidth(); }
125
126 void setSelection(int start, int length);
127
128 inline QString selectedText() const { return hasSelectedText() ? m_text.mid(m_selstart, m_selend - m_selstart) : QString(); }
129 QString textBeforeSelection() const { return hasSelectedText() ? m_text.left(m_selstart) : QString(); }
130 QString textAfterSelection() const { return hasSelectedText() ? m_text.mid(m_selend) : QString(); }
131
132 int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
133 int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
134 bool inSelection(int x) const
135 {
136 if (m_selstart >= m_selend)
137 return false;
138 int pos = xToPos(x, QTextLine::CursorOnCharacter);
139 return pos >= m_selstart && pos < m_selend;
140 }
141
142 void removeSelection()
143 {
144 int priorState = m_undoState;
145 removeSelectedText();
146 finishChange(priorState);
147 }
148
149 int start() const { return 0; }
150 int end() const { return m_text.length(); }
151
152#ifndef QT_NO_CLIPBOARD
153 void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
154 void paste(QClipboard::Mode mode = QClipboard::Clipboard);
155#endif
156
157 int cursor() const{ return m_cursor; }
158 int preeditCursor() const { return m_preeditCursor; }
159
160 int cursorWidth() const { return m_cursorWidth; }
161 void setCursorWidth(int value) { m_cursorWidth = value; }
162
163
164 void moveCursor(int pos, bool mark = false);
165 void cursorForward(bool mark, int steps)
166 {
167 int c = m_cursor;
168 if (steps > 0) {
169 while (steps--)
170 c = m_textLayout.nextCursorPosition(c);
171 } else if (steps < 0) {
172 while (steps++)
173 c = m_textLayout.previousCursorPosition(c);
174 }
175 moveCursor(c, mark);
176 }
177
178 void cursorWordForward(bool mark) { moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
179 void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
180
181 void home(bool mark) { moveCursor(0, mark); }
182 void end(bool mark) { moveCursor(text().length(), mark); }
183
184 int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
185 QRect cursorRect() const;
186
187 qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); }
188 qreal cursorToX() const
189 {
190 int cursor = m_cursor;
191 if (m_preeditCursor != -1)
192 cursor += m_preeditCursor;
193 return cursorToX(cursor);
194 }
195
196 bool isReadOnly() const { return m_readOnly; }
197 void setReadOnly(bool enable) { m_readOnly = enable; }
198
199 QString text() const
200 {
201 QString res = m_maskData ? stripString(m_text) : m_text;
202 return (res.isNull() ? QString::fromLatin1("") : res);
203 }
204 void setText(const QString &txt) { internalSetText(txt, -1, false); }
205 QString displayText() const { return m_textLayout.text(); }
206
207 void backspace();
208 void del();
209 void deselect() { internalDeselect(); finishChange(); }
210 void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); }
211
212 void insert(const QString &);
213 void clear();
214 void undo() { internalUndo(); finishChange(-1, true); }
215 void redo() { internalRedo(); finishChange(); }
216 void selectWordAtPos(int);
217
218 uint echoMode() const { return m_echoMode; }
219 void setEchoMode(uint mode)
220 {
221 m_echoMode = mode;
222 m_passwordEchoEditing = false;
223 updateDisplayText();
224 }
225
226 int maxLength() const { return m_maxLength; }
227 void setMaxLength(int maxLength)
228 {
229 if (m_maskData)
230 return;
231 m_maxLength = maxLength;
232 setText(m_text);
233 }
234
235#ifndef QT_NO_VALIDATOR
236 const QValidator *validator() const { return m_validator; }
237 void setValidator(const QValidator *v) { m_validator = const_cast<QValidator*>(v); }
238#endif
239
240#ifndef QT_NO_COMPLETER
241 QCompleter *completer() const { return m_completer; }
242 /* Note that you must set the widget for the completer separately */
243 void setCompleter(const QCompleter *c) { m_completer = const_cast<QCompleter*>(c); }
244 void complete(int key);
245#endif
246
247 int cursorPosition() const { return m_cursor; }
248 void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); }
249
250 bool hasAcceptableInput() const { return hasAcceptableInput(m_text); }
251 bool fixup();
252
253 QString inputMask() const { return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); }
254 void setInputMask(const QString &mask)
255 {
256 parseInputMask(mask);
257 if (m_maskData)
258 moveCursor(nextMaskBlank(0));
259 }
260
261 // input methods
262#ifndef QT_NO_IM
263 bool composeMode() const { return !m_textLayout.preeditAreaText().isEmpty(); }
264 void setPreeditArea(int cursor, const QString &text) { m_textLayout.setPreeditArea(cursor, text); }
265#endif
266
267 QString preeditAreaText() const { return m_textLayout.preeditAreaText(); }
268
269 void updatePasswordEchoEditing(bool editing);
270 bool passwordEchoEditing() const { return m_passwordEchoEditing; }
271
272 QChar passwordCharacter() const { return m_passwordCharacter; }
273 void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); }
274
275 Qt::LayoutDirection layoutDirection() const {
276 if (m_layoutDirection == Qt::LayoutDirectionAuto) {
277 if (m_text.isEmpty())
278 return QApplication::keyboardInputDirection();
279 return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight;
280 }
281 return m_layoutDirection;
282 }
283 void setLayoutDirection(Qt::LayoutDirection direction)
284 {
285 if (direction != m_layoutDirection) {
286 m_layoutDirection = direction;
287 updateDisplayText();
288 }
289 }
290
291 void setFont(const QFont &font) { m_textLayout.setFont(font); updateDisplayText(); }
292
293 void processInputMethodEvent(QInputMethodEvent *event);
294 void processMouseEvent(QMouseEvent* ev);
295 void processKeyEvent(QKeyEvent* ev);
296
297 int cursorBlinkPeriod() const { return m_blinkPeriod; }
298 void setCursorBlinkPeriod(int msec);
299 void resetCursorBlinkTimer();
300
301 QString cancelText() const { return m_cancelText; }
302 void setCancelText(const QString &text) { m_cancelText = text; }
303
304 const QPalette &palette() const { return m_palette; }
305 void setPalette(const QPalette &p) { m_palette = p; }
306
307 enum DrawFlags {
308 DrawText = 0x01,
309 DrawSelections = 0x02,
310 DrawCursor = 0x04,
311 DrawAll = DrawText | DrawSelections | DrawCursor
312 };
313 void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll);
314
315 bool processEvent(QEvent *ev);
316
317private:
318 void init(const QString &txt);
319 void removeSelectedText();
320 void internalSetText(const QString &txt, int pos = -1, bool edited = true);
321 void updateDisplayText(bool forceUpdate = false);
322
323 void internalInsert(const QString &s);
324 void internalDelete(bool wasBackspace = false);
325 void internalRemove(int pos);
326
327 inline void internalDeselect()
328 {
329 m_selDirty |= (m_selend > m_selstart);
330 m_selstart = m_selend = 0;
331 }
332
333 void internalUndo(int until = -1);
334 void internalRedo();
335
336 QString m_text;
337 QPalette m_palette;
338 int m_cursor;
339 int m_preeditCursor;
340 int m_cursorWidth;
341 Qt::LayoutDirection m_layoutDirection;
342 uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
343 uint m_separator : 1;
344 uint m_readOnly : 1;
345 uint m_dragEnabled : 1;
346 uint m_echoMode : 2;
347 uint m_textDirty : 1;
348 uint m_selDirty : 1;
349 uint m_validInput : 1;
350 uint m_blinkStatus : 1;
351 int m_blinkPeriod; // 0 for non-blinking cursor
352 int m_blinkTimer;
353 int m_deleteAllTimer;
354 int m_ascent;
355 int m_maxLength;
356 int m_lastCursorPos;
357 QList<int> m_transactions;
358 QPoint m_tripleClick;
359 int m_tripleClickTimer;
360 QString m_cancelText;
361
362 void emitCursorPositionChanged();
363
364 bool finishChange(int validateFromState = -1, bool update = false, bool edited = true);
365
366#ifndef QT_NO_VALIDATOR
367 QPointer<QValidator> m_validator;
368#endif
369 QPointer<QCompleter> m_completer;
370#ifndef QT_NO_COMPLETER
371 bool advanceToEnabledItem(int dir);
372#endif
373
374 struct MaskInputData {
375 enum Casemode { NoCaseMode, Upper, Lower };
376 QChar maskChar; // either the separator char or the inputmask
377 bool separator;
378 Casemode caseMode;
379 };
380 QString m_inputMask;
381 QChar m_blank;
382 MaskInputData *m_maskData;
383
384 // undo/redo handling
385 enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
386 struct Command {
387 inline Command() {}
388 inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
389 uint type : 4;
390 QChar uc;
391 int pos, selStart, selEnd;
392 };
393 int m_modifiedState;
394 int m_undoState;
395 QVector<Command> m_history;
396 void addCommand(const Command& cmd);
397
398 inline void separate() { m_separator = true; }
399
400 // selection
401 int m_selstart;
402 int m_selend;
403
404 // masking
405 void parseInputMask(const QString &maskFields);
406 bool isValidInput(QChar key, QChar mask) const;
407 bool hasAcceptableInput(const QString &text) const;
408 QString maskString(uint pos, const QString &str, bool clear = false) const;
409 QString clearString(uint pos, uint len) const;
410 QString stripString(const QString &str) const;
411 int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
412
413 // complex text layout
414 QTextLayout m_textLayout;
415
416 bool m_passwordEchoEditing;
417 QChar m_passwordCharacter;
418
419Q_SIGNALS:
420 void cursorPositionChanged(int, int);
421 void selectionChanged();
422
423 void displayTextChanged(const QString &);
424 void textChanged(const QString &);
425 void textEdited(const QString &);
426
427 void resetInputContext();
428
429 void accepted();
430 void editingFinished();
431 void updateNeeded(const QRect &);
432
433#ifdef QT_KEYPAD_NAVIGATION
434 void editFocusChange(bool);
435#endif
436protected:
437 virtual void timerEvent(QTimerEvent *event);
438
439private Q_SLOTS:
440 void _q_clipboardChanged();
441 void _q_deleteSelected();
442
443};
444
445QT_END_NAMESPACE
446
447QT_END_HEADER
448
449#endif // QT_NO_LINEEDIT
450
451#endif // QLINECONTROL_P_H
Note: See TracBrowser for help on using the repository browser.