|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 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 QtDeclarative module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "private/qdeclarativetextinput_p.h" |
|
43 #include "private/qdeclarativetextinput_p_p.h" |
|
44 |
|
45 #include <private/qdeclarativeglobal_p.h> |
|
46 #include <qdeclarativeinfo.h> |
|
47 |
|
48 #include <QValidator> |
|
49 #include <QApplication> |
|
50 #include <QFontMetrics> |
|
51 #include <QPainter> |
|
52 |
|
53 QT_BEGIN_NAMESPACE |
|
54 |
|
55 /*! |
|
56 \qmlclass TextInput QDeclarativeTextInput |
|
57 \since 4.7 |
|
58 \brief The TextInput item allows you to add an editable line of text to a scene. |
|
59 |
|
60 TextInput can only display a single line of text, and can only display |
|
61 plain text. However it can provide addition input constraints on the text. |
|
62 |
|
63 Input constraints include setting a QValidator, an input mask, or a |
|
64 maximum input length. |
|
65 |
|
66 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled. |
|
67 If you want such bindings (on any platform), you will need to construct them in QML. |
|
68 */ |
|
69 QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent) |
|
70 : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent) |
|
71 { |
|
72 Q_D(QDeclarativeTextInput); |
|
73 d->init(); |
|
74 } |
|
75 |
|
76 QDeclarativeTextInput::~QDeclarativeTextInput() |
|
77 { |
|
78 } |
|
79 |
|
80 /*! |
|
81 \qmlproperty string TextInput::text |
|
82 |
|
83 The text in the TextInput. |
|
84 */ |
|
85 |
|
86 QString QDeclarativeTextInput::text() const |
|
87 { |
|
88 Q_D(const QDeclarativeTextInput); |
|
89 return d->control->text(); |
|
90 } |
|
91 |
|
92 void QDeclarativeTextInput::setText(const QString &s) |
|
93 { |
|
94 Q_D(QDeclarativeTextInput); |
|
95 if(s == text()) |
|
96 return; |
|
97 d->control->setText(s); |
|
98 //emit textChanged(); |
|
99 } |
|
100 |
|
101 /*! |
|
102 \qmlproperty string TextInput::font.family |
|
103 |
|
104 Sets the family name of the font. |
|
105 |
|
106 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". |
|
107 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. |
|
108 If the family isn't available a family will be set using the font matching algorithm. |
|
109 */ |
|
110 |
|
111 /*! |
|
112 \qmlproperty bool TextInput::font.bold |
|
113 |
|
114 Sets whether the font weight is bold. |
|
115 */ |
|
116 |
|
117 /*! |
|
118 \qmlproperty enumeration TextInput::font.weight |
|
119 |
|
120 Sets the font's weight. |
|
121 |
|
122 The weight can be one of: |
|
123 \list |
|
124 \o Font.Light |
|
125 \o Font.Normal - the default |
|
126 \o Font.DemiBold |
|
127 \o Font.Bold |
|
128 \o Font.Black |
|
129 \endlist |
|
130 |
|
131 \qml |
|
132 TextInput { text: "Hello"; font.weight: Font.DemiBold } |
|
133 \endqml |
|
134 */ |
|
135 |
|
136 /*! |
|
137 \qmlproperty bool TextInput::font.italic |
|
138 |
|
139 Sets whether the font has an italic style. |
|
140 */ |
|
141 |
|
142 /*! |
|
143 \qmlproperty bool TextInput::font.underline |
|
144 |
|
145 Sets whether the text is underlined. |
|
146 */ |
|
147 |
|
148 /*! |
|
149 \qmlproperty bool TextInput::font.outline |
|
150 |
|
151 Sets whether the font has an outline style. |
|
152 */ |
|
153 |
|
154 /*! |
|
155 \qmlproperty bool TextInput::font.strikeout |
|
156 |
|
157 Sets whether the font has a strikeout style. |
|
158 */ |
|
159 |
|
160 /*! |
|
161 \qmlproperty real TextInput::font.pointSize |
|
162 |
|
163 Sets the font size in points. The point size must be greater than zero. |
|
164 */ |
|
165 |
|
166 /*! |
|
167 \qmlproperty int TextInput::font.pixelSize |
|
168 |
|
169 Sets the font size in pixels. |
|
170 |
|
171 Using this function makes the font device dependent. |
|
172 Use \c pointSize to set the size of the font in a device independent manner. |
|
173 */ |
|
174 |
|
175 /*! |
|
176 \qmlproperty real TextInput::font.letterSpacing |
|
177 |
|
178 Sets the letter spacing for the font. |
|
179 |
|
180 Letter spacing changes the default spacing between individual letters in the font. |
|
181 A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the spacing after a character by |
|
182 the width of the character itself. |
|
183 */ |
|
184 |
|
185 /*! |
|
186 \qmlproperty real TextInput::font.wordSpacing |
|
187 |
|
188 Sets the word spacing for the font. |
|
189 |
|
190 Word spacing changes the default spacing between individual words. |
|
191 A positive value increases the word spacing by a corresponding amount of pixels, |
|
192 while a negative value decreases the inter-word spacing accordingly. |
|
193 */ |
|
194 |
|
195 /*! |
|
196 \qmlproperty enumeration TextInput::font.capitalization |
|
197 |
|
198 Sets the capitalization for the text. |
|
199 |
|
200 \list |
|
201 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. |
|
202 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type. |
|
203 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type. |
|
204 \o Font.SmallCaps - This alters the text to be rendered in small-caps type. |
|
205 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. |
|
206 \endlist |
|
207 |
|
208 \qml |
|
209 TextInput { text: "Hello"; font.capitalization: Font.AllLowercase } |
|
210 \endqml |
|
211 */ |
|
212 |
|
213 QFont QDeclarativeTextInput::font() const |
|
214 { |
|
215 Q_D(const QDeclarativeTextInput); |
|
216 return d->font; |
|
217 } |
|
218 |
|
219 void QDeclarativeTextInput::setFont(const QFont &font) |
|
220 { |
|
221 Q_D(QDeclarativeTextInput); |
|
222 if (d->font == font) |
|
223 return; |
|
224 |
|
225 d->font = font; |
|
226 |
|
227 d->control->setFont(d->font); |
|
228 if(d->cursorItem){ |
|
229 d->cursorItem->setHeight(QFontMetrics(d->font).height()); |
|
230 moveCursor(); |
|
231 } |
|
232 updateSize(); |
|
233 emit fontChanged(d->font); |
|
234 } |
|
235 |
|
236 /*! |
|
237 \qmlproperty color TextInput::color |
|
238 |
|
239 The text color. |
|
240 */ |
|
241 QColor QDeclarativeTextInput::color() const |
|
242 { |
|
243 Q_D(const QDeclarativeTextInput); |
|
244 return d->color; |
|
245 } |
|
246 |
|
247 void QDeclarativeTextInput::setColor(const QColor &c) |
|
248 { |
|
249 Q_D(QDeclarativeTextInput); |
|
250 d->color = c; |
|
251 } |
|
252 |
|
253 |
|
254 /*! |
|
255 \qmlproperty color TextInput::selectionColor |
|
256 |
|
257 The text highlight color, used behind selections. |
|
258 */ |
|
259 QColor QDeclarativeTextInput::selectionColor() const |
|
260 { |
|
261 Q_D(const QDeclarativeTextInput); |
|
262 return d->selectionColor; |
|
263 } |
|
264 |
|
265 void QDeclarativeTextInput::setSelectionColor(const QColor &color) |
|
266 { |
|
267 Q_D(QDeclarativeTextInput); |
|
268 if (d->selectionColor == color) |
|
269 return; |
|
270 |
|
271 d->selectionColor = color; |
|
272 QPalette p = d->control->palette(); |
|
273 p.setColor(QPalette::Highlight, d->selectionColor); |
|
274 d->control->setPalette(p); |
|
275 emit selectionColorChanged(color); |
|
276 } |
|
277 |
|
278 /*! |
|
279 \qmlproperty color TextInput::selectedTextColor |
|
280 |
|
281 The highlighted text color, used in selections. |
|
282 */ |
|
283 QColor QDeclarativeTextInput::selectedTextColor() const |
|
284 { |
|
285 Q_D(const QDeclarativeTextInput); |
|
286 return d->selectedTextColor; |
|
287 } |
|
288 |
|
289 void QDeclarativeTextInput::setSelectedTextColor(const QColor &color) |
|
290 { |
|
291 Q_D(QDeclarativeTextInput); |
|
292 if (d->selectedTextColor == color) |
|
293 return; |
|
294 |
|
295 d->selectedTextColor = color; |
|
296 QPalette p = d->control->palette(); |
|
297 p.setColor(QPalette::HighlightedText, d->selectedTextColor); |
|
298 d->control->setPalette(p); |
|
299 emit selectedTextColorChanged(color); |
|
300 } |
|
301 |
|
302 /*! |
|
303 \qmlproperty enumeration TextInput::horizontalAlignment |
|
304 |
|
305 Sets the horizontal alignment of the text within the TextInput item's |
|
306 width and height. By default, the text is left aligned. |
|
307 |
|
308 TextInput does not have vertical alignment, as the natural height is |
|
309 exactly the height of the single line of text. If you set the height |
|
310 manually to something larger, TextInput will always be top aligned |
|
311 vertically. You can use anchors to align it however you want within |
|
312 another item. |
|
313 |
|
314 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and |
|
315 \c TextInput.AlignHCenter. |
|
316 */ |
|
317 QDeclarativeTextInput::HAlignment QDeclarativeTextInput::hAlign() const |
|
318 { |
|
319 Q_D(const QDeclarativeTextInput); |
|
320 return d->hAlign; |
|
321 } |
|
322 |
|
323 void QDeclarativeTextInput::setHAlign(HAlignment align) |
|
324 { |
|
325 Q_D(QDeclarativeTextInput); |
|
326 if(align == d->hAlign) |
|
327 return; |
|
328 d->hAlign = align; |
|
329 updateRect(); |
|
330 emit horizontalAlignmentChanged(d->hAlign); |
|
331 } |
|
332 |
|
333 bool QDeclarativeTextInput::isReadOnly() const |
|
334 { |
|
335 Q_D(const QDeclarativeTextInput); |
|
336 return d->control->isReadOnly(); |
|
337 } |
|
338 |
|
339 void QDeclarativeTextInput::setReadOnly(bool ro) |
|
340 { |
|
341 Q_D(QDeclarativeTextInput); |
|
342 if (d->control->isReadOnly() == ro) |
|
343 return; |
|
344 |
|
345 d->control->setReadOnly(ro); |
|
346 |
|
347 emit readOnlyChanged(ro); |
|
348 } |
|
349 |
|
350 int QDeclarativeTextInput::maxLength() const |
|
351 { |
|
352 Q_D(const QDeclarativeTextInput); |
|
353 return d->control->maxLength(); |
|
354 } |
|
355 |
|
356 void QDeclarativeTextInput::setMaxLength(int ml) |
|
357 { |
|
358 Q_D(QDeclarativeTextInput); |
|
359 if (d->control->maxLength() == ml) |
|
360 return; |
|
361 |
|
362 d->control->setMaxLength(ml); |
|
363 |
|
364 emit maximumLengthChanged(ml); |
|
365 } |
|
366 |
|
367 /*! |
|
368 \qmlproperty bool TextInput::cursorVisible |
|
369 Set to true when the TextInput shows a cursor. |
|
370 |
|
371 This property is set and unset when the TextInput gets focus, so that other |
|
372 properties can be bound to whether the cursor is currently showing. As it |
|
373 gets set and unset automatically, when you set the value yourself you must |
|
374 keep in mind that your value may be overwritten. |
|
375 |
|
376 It can be set directly in script, for example if a KeyProxy might |
|
377 forward keys to it and you desire it to look active when this happens |
|
378 (but without actually giving it the focus). |
|
379 |
|
380 It should not be set directly on the element, like in the below QML, |
|
381 as the specified value will be overridden an lost on focus changes. |
|
382 |
|
383 \code |
|
384 TextInput { |
|
385 text: "Text" |
|
386 cursorVisible: false |
|
387 } |
|
388 \endcode |
|
389 |
|
390 In the above snippet the cursor will still become visible when the |
|
391 TextInput gains focus. |
|
392 */ |
|
393 bool QDeclarativeTextInput::isCursorVisible() const |
|
394 { |
|
395 Q_D(const QDeclarativeTextInput); |
|
396 return d->cursorVisible; |
|
397 } |
|
398 |
|
399 void QDeclarativeTextInput::setCursorVisible(bool on) |
|
400 { |
|
401 Q_D(QDeclarativeTextInput); |
|
402 if (d->cursorVisible == on) |
|
403 return; |
|
404 d->cursorVisible = on; |
|
405 d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0); |
|
406 //d->control should emit the cursor update regions |
|
407 emit cursorVisibleChanged(d->cursorVisible); |
|
408 } |
|
409 |
|
410 /*! |
|
411 \qmlproperty int TextInput::cursorPosition |
|
412 The position of the cursor in the TextInput. |
|
413 */ |
|
414 int QDeclarativeTextInput::cursorPosition() const |
|
415 { |
|
416 Q_D(const QDeclarativeTextInput); |
|
417 return d->control->cursor(); |
|
418 } |
|
419 void QDeclarativeTextInput::setCursorPosition(int cp) |
|
420 { |
|
421 Q_D(QDeclarativeTextInput); |
|
422 d->control->moveCursor(cp); |
|
423 } |
|
424 |
|
425 /*! |
|
426 \internal |
|
427 |
|
428 Returns a Rect which encompasses the cursor, but which may be larger than is |
|
429 required. Ignores custom cursor delegates. |
|
430 */ |
|
431 QRect QDeclarativeTextInput::cursorRect() const |
|
432 { |
|
433 Q_D(const QDeclarativeTextInput); |
|
434 return d->control->cursorRect(); |
|
435 } |
|
436 |
|
437 /*! |
|
438 \qmlproperty int TextInput::selectionStart |
|
439 |
|
440 The cursor position before the first character in the current selection. |
|
441 Setting this and selectionEnd allows you to specify a selection in the |
|
442 text edit. |
|
443 |
|
444 Note that if selectionStart == selectionEnd then there is no current |
|
445 selection. If you attempt to set selectionStart to a value outside of |
|
446 the current text, selectionStart will not be changed. |
|
447 |
|
448 \sa selectionEnd, cursorPosition, selectedText |
|
449 */ |
|
450 int QDeclarativeTextInput::selectionStart() const |
|
451 { |
|
452 Q_D(const QDeclarativeTextInput); |
|
453 return d->lastSelectionStart; |
|
454 } |
|
455 |
|
456 void QDeclarativeTextInput::setSelectionStart(int s) |
|
457 { |
|
458 Q_D(QDeclarativeTextInput); |
|
459 if(d->lastSelectionStart == s || s < 0 || s > text().length()) |
|
460 return; |
|
461 d->lastSelectionStart = s; |
|
462 d->control->setSelection(s, d->lastSelectionEnd - s); |
|
463 } |
|
464 |
|
465 /*! |
|
466 \qmlproperty int TextInput::selectionEnd |
|
467 |
|
468 The cursor position after the last character in the current selection. |
|
469 Setting this and selectionStart allows you to specify a selection in the |
|
470 text edit. |
|
471 |
|
472 Note that if selectionStart == selectionEnd then there is no current |
|
473 selection. If you attempt to set selectionEnd to a value outside of |
|
474 the current text, selectionEnd will not be changed. |
|
475 |
|
476 \sa selectionStart, cursorPosition, selectedText |
|
477 */ |
|
478 int QDeclarativeTextInput::selectionEnd() const |
|
479 { |
|
480 Q_D(const QDeclarativeTextInput); |
|
481 return d->lastSelectionEnd; |
|
482 } |
|
483 |
|
484 void QDeclarativeTextInput::setSelectionEnd(int s) |
|
485 { |
|
486 Q_D(QDeclarativeTextInput); |
|
487 if(d->lastSelectionEnd == s || s < 0 || s > text().length()) |
|
488 return; |
|
489 d->lastSelectionEnd = s; |
|
490 d->control->setSelection(d->lastSelectionStart, s - d->lastSelectionStart); |
|
491 } |
|
492 |
|
493 /*! |
|
494 \qmlproperty string TextInput::selectedText |
|
495 |
|
496 This read-only property provides the text currently selected in the |
|
497 text input. |
|
498 |
|
499 It is equivalent to the following snippet, but is faster and easier |
|
500 to use. |
|
501 |
|
502 \qml |
|
503 myTextInput.text.toString().substring(myTextInput.selectionStart, |
|
504 myTextInput.selectionEnd); |
|
505 \endqml |
|
506 */ |
|
507 QString QDeclarativeTextInput::selectedText() const |
|
508 { |
|
509 Q_D(const QDeclarativeTextInput); |
|
510 return d->control->selectedText(); |
|
511 } |
|
512 |
|
513 /*! |
|
514 \qmlproperty bool TextInput::focusOnPress |
|
515 |
|
516 Whether the TextInput should gain focus on a mouse press. By default this is |
|
517 set to true. |
|
518 */ |
|
519 bool QDeclarativeTextInput::focusOnPress() const |
|
520 { |
|
521 Q_D(const QDeclarativeTextInput); |
|
522 return d->focusOnPress; |
|
523 } |
|
524 |
|
525 void QDeclarativeTextInput::setFocusOnPress(bool b) |
|
526 { |
|
527 Q_D(QDeclarativeTextInput); |
|
528 if (d->focusOnPress == b) |
|
529 return; |
|
530 |
|
531 d->focusOnPress = b; |
|
532 |
|
533 emit focusOnPressChanged(d->focusOnPress); |
|
534 } |
|
535 |
|
536 /*! |
|
537 \qmlproperty bool TextInput::autoScroll |
|
538 |
|
539 Whether the TextInput should scroll when the text is longer than the width. By default this is |
|
540 set to true. |
|
541 */ |
|
542 bool QDeclarativeTextInput::autoScroll() const |
|
543 { |
|
544 Q_D(const QDeclarativeTextInput); |
|
545 return d->autoScroll; |
|
546 } |
|
547 |
|
548 void QDeclarativeTextInput::setAutoScroll(bool b) |
|
549 { |
|
550 Q_D(QDeclarativeTextInput); |
|
551 if (d->autoScroll == b) |
|
552 return; |
|
553 |
|
554 d->autoScroll = b; |
|
555 |
|
556 emit autoScrollChanged(d->autoScroll); |
|
557 } |
|
558 |
|
559 /*! |
|
560 \qmlclass IntValidator QIntValidator |
|
561 |
|
562 This element provides a validator for integer values |
|
563 */ |
|
564 /*! |
|
565 \qmlproperty int IntValidator::top |
|
566 |
|
567 This property holds the validator's highest acceptable value. |
|
568 By default, this property's value is derived from the highest signed integer available (typically 2147483647). |
|
569 */ |
|
570 /*! |
|
571 \qmlproperty int IntValidator::bottom |
|
572 |
|
573 This property holds the validator's lowest acceptable value. |
|
574 By default, this property's value is derived from the lowest signed integer available (typically -2147483647). |
|
575 */ |
|
576 |
|
577 /*! |
|
578 \qmlclass DoubleValidator QDoubleValidator |
|
579 |
|
580 This element provides a validator for non-integer numbers. |
|
581 */ |
|
582 |
|
583 /*! |
|
584 \qmlproperty real DoubleValidator::top |
|
585 |
|
586 This property holds the validator's maximum acceptable value. |
|
587 By default, this property contains a value of infinity. |
|
588 */ |
|
589 /*! |
|
590 \qmlproperty real DoubleValidator::bottom |
|
591 |
|
592 This property holds the validator's minimum acceptable value. |
|
593 By default, this property contains a value of -infinity. |
|
594 */ |
|
595 /*! |
|
596 \qmlproperty int DoubleValidator::decimals |
|
597 |
|
598 This property holds the validator's maximum number of digits after the decimal point. |
|
599 By default, this property contains a value of 1000. |
|
600 */ |
|
601 /*! |
|
602 \qmlproperty enumeration DoubleValidator::notation |
|
603 This property holds the notation of how a string can describe a number. |
|
604 |
|
605 The values for this property are DoubleValidator.StandardNotation or DoubleValidator.ScientificNotation. |
|
606 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part(i.e. 1.5E-2). |
|
607 |
|
608 By default, this property is set to DoubleValidator.ScientificNotation. |
|
609 */ |
|
610 |
|
611 /*! |
|
612 \qmlclass RegExpValidator QRegExpValidator |
|
613 |
|
614 This element provides a validator, which counts as valid any string which |
|
615 matches a specified regular expression. |
|
616 */ |
|
617 /*! |
|
618 \qmlproperty regExp RegExpValidator::regExp |
|
619 |
|
620 This property holds the regular expression used for validation. |
|
621 |
|
622 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression |
|
623 matching "a". |
|
624 |
|
625 By default, this property contains a regular expression with the pattern .* that matches any string. |
|
626 */ |
|
627 |
|
628 /*! |
|
629 \qmlproperty Validator TextInput::validator |
|
630 |
|
631 Allows you to set a validator on the TextInput. When a validator is set |
|
632 the TextInput will only accept input which leaves the text property in |
|
633 an acceptable or intermediate state. The accepted signal will only be sent |
|
634 if the text is in an acceptable state when enter is pressed. |
|
635 |
|
636 Currently supported validators are IntValidator, DoubleValidator and |
|
637 RegExpValidator. An example of using validators is shown below, which allows |
|
638 input of integers between 11 and 31 into the text input: |
|
639 |
|
640 \code |
|
641 import Qt 4.7 |
|
642 TextInput{ |
|
643 validator: IntValidator{bottom: 11; top: 31;} |
|
644 focus: true |
|
645 } |
|
646 \endcode |
|
647 |
|
648 \sa acceptableInput, inputMask |
|
649 */ |
|
650 QValidator* QDeclarativeTextInput::validator() const |
|
651 { |
|
652 Q_D(const QDeclarativeTextInput); |
|
653 //###const cast isn't good, but needed for property system? |
|
654 return const_cast<QValidator*>(d->control->validator()); |
|
655 } |
|
656 |
|
657 void QDeclarativeTextInput::setValidator(QValidator* v) |
|
658 { |
|
659 Q_D(QDeclarativeTextInput); |
|
660 if (d->control->validator() == v) |
|
661 return; |
|
662 |
|
663 d->control->setValidator(v); |
|
664 if(!d->control->hasAcceptableInput()){ |
|
665 d->oldValidity = false; |
|
666 emit acceptableInputChanged(); |
|
667 } |
|
668 |
|
669 emit validatorChanged(); |
|
670 } |
|
671 |
|
672 /*! |
|
673 \qmlproperty string TextInput::inputMask |
|
674 |
|
675 Allows you to set an input mask on the TextInput, restricting the allowable |
|
676 text inputs. See QLineEdit::inputMask for further details, as the exact |
|
677 same mask strings are used by TextInput. |
|
678 |
|
679 \sa acceptableInput, validator |
|
680 */ |
|
681 QString QDeclarativeTextInput::inputMask() const |
|
682 { |
|
683 Q_D(const QDeclarativeTextInput); |
|
684 return d->control->inputMask(); |
|
685 } |
|
686 |
|
687 void QDeclarativeTextInput::setInputMask(const QString &im) |
|
688 { |
|
689 Q_D(QDeclarativeTextInput); |
|
690 if (d->control->inputMask() == im) |
|
691 return; |
|
692 |
|
693 d->control->setInputMask(im); |
|
694 emit inputMaskChanged(d->control->inputMask()); |
|
695 } |
|
696 |
|
697 /*! |
|
698 \qmlproperty bool TextInput::acceptableInput |
|
699 |
|
700 This property is always true unless a validator or input mask has been set. |
|
701 If a validator or input mask has been set, this property will only be true |
|
702 if the current text is acceptable to the validator or input mask as a final |
|
703 string (not as an intermediate string). |
|
704 */ |
|
705 bool QDeclarativeTextInput::hasAcceptableInput() const |
|
706 { |
|
707 Q_D(const QDeclarativeTextInput); |
|
708 return d->control->hasAcceptableInput(); |
|
709 } |
|
710 |
|
711 /*! |
|
712 \qmlproperty enumeration TextInput::echoMode |
|
713 |
|
714 Specifies how the text should be displayed in the TextInput. |
|
715 \list |
|
716 \o TextInput.Normal - Displays the text as it is. (Default) |
|
717 \o TextInput.Password - Displays asterixes instead of characters. |
|
718 \o TextInput.NoEcho - Displays nothing. |
|
719 \o TextInput.PasswordEchoOnEdit - Displays all but the current character as asterixes. |
|
720 \endlist |
|
721 */ |
|
722 QDeclarativeTextInput::EchoMode QDeclarativeTextInput::echoMode() const |
|
723 { |
|
724 Q_D(const QDeclarativeTextInput); |
|
725 return (QDeclarativeTextInput::EchoMode)d->control->echoMode(); |
|
726 } |
|
727 |
|
728 void QDeclarativeTextInput::setEchoMode(QDeclarativeTextInput::EchoMode echo) |
|
729 { |
|
730 Q_D(QDeclarativeTextInput); |
|
731 if (echoMode() == echo) |
|
732 return; |
|
733 Qt::InputMethodHints imHints = inputMethodHints(); |
|
734 if (echo == Password || echo == NoEcho) |
|
735 imHints |= Qt::ImhHiddenText; |
|
736 else |
|
737 imHints &= ~Qt::ImhHiddenText; |
|
738 if (echo != Normal) |
|
739 imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); |
|
740 else |
|
741 imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); |
|
742 setInputMethodHints(imHints); |
|
743 d->control->setEchoMode((uint)echo); |
|
744 update(); |
|
745 emit echoModeChanged(echoMode()); |
|
746 } |
|
747 |
|
748 /*! |
|
749 \qmlproperty Component TextInput::cursorDelegate |
|
750 The delegate for the cursor in the TextInput. |
|
751 |
|
752 If you set a cursorDelegate for a TextInput, this delegate will be used for |
|
753 drawing the cursor instead of the standard cursor. An instance of the |
|
754 delegate will be created and managed by the TextInput when a cursor is |
|
755 needed, and the x property of delegate instance will be set so as |
|
756 to be one pixel before the top left of the current character. |
|
757 |
|
758 Note that the root item of the delegate component must be a QDeclarativeItem or |
|
759 QDeclarativeItem derived item. |
|
760 */ |
|
761 QDeclarativeComponent* QDeclarativeTextInput::cursorDelegate() const |
|
762 { |
|
763 Q_D(const QDeclarativeTextInput); |
|
764 return d->cursorComponent; |
|
765 } |
|
766 |
|
767 void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c) |
|
768 { |
|
769 Q_D(QDeclarativeTextInput); |
|
770 if (d->cursorComponent == c) |
|
771 return; |
|
772 |
|
773 d->cursorComponent = c; |
|
774 if(!c){ |
|
775 //note that the components are owned by something else |
|
776 disconnect(d->control, SIGNAL(cursorPositionChanged(int, int)), |
|
777 this, SLOT(moveCursor())); |
|
778 delete d->cursorItem; |
|
779 }else{ |
|
780 d->startCreatingCursor(); |
|
781 } |
|
782 |
|
783 emit cursorDelegateChanged(); |
|
784 } |
|
785 |
|
786 void QDeclarativeTextInputPrivate::startCreatingCursor() |
|
787 { |
|
788 Q_Q(QDeclarativeTextInput); |
|
789 q->connect(control, SIGNAL(cursorPositionChanged(int, int)), |
|
790 q, SLOT(moveCursor())); |
|
791 if(cursorComponent->isReady()){ |
|
792 q->createCursor(); |
|
793 }else if(cursorComponent->isLoading()){ |
|
794 q->connect(cursorComponent, SIGNAL(statusChanged(int)), |
|
795 q, SLOT(createCursor())); |
|
796 }else {//isError |
|
797 qmlInfo(q, cursorComponent->errors()) << QDeclarativeTextInput::tr("Could not load cursor delegate"); |
|
798 } |
|
799 } |
|
800 |
|
801 void QDeclarativeTextInput::createCursor() |
|
802 { |
|
803 Q_D(QDeclarativeTextInput); |
|
804 if(d->cursorComponent->isError()){ |
|
805 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate"); |
|
806 return; |
|
807 } |
|
808 |
|
809 if(!d->cursorComponent->isReady()) |
|
810 return; |
|
811 |
|
812 if(d->cursorItem) |
|
813 delete d->cursorItem; |
|
814 d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create()); |
|
815 if(!d->cursorItem){ |
|
816 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate"); |
|
817 return; |
|
818 } |
|
819 |
|
820 QDeclarative_setParent_noEvent(d->cursorItem, this); |
|
821 d->cursorItem->setParentItem(this); |
|
822 d->cursorItem->setX(d->control->cursorToX()); |
|
823 d->cursorItem->setHeight(d->control->height()); |
|
824 } |
|
825 |
|
826 void QDeclarativeTextInput::moveCursor() |
|
827 { |
|
828 Q_D(QDeclarativeTextInput); |
|
829 if(!d->cursorItem) |
|
830 return; |
|
831 d->cursorItem->setX(d->control->cursorToX() - d->hscroll); |
|
832 } |
|
833 |
|
834 /*! |
|
835 \qmlmethod int TextInput::xToPosition(int x) |
|
836 |
|
837 This function returns the character position at |
|
838 x pixels from the left of the textInput. Position 0 is before the |
|
839 first character, position 1 is after the first character but before the second, |
|
840 and so on until position text.length, which is after all characters. |
|
841 |
|
842 This means that for all x values before the first character this function returns 0, |
|
843 and for all x values after the last character this function returns text.length. |
|
844 */ |
|
845 int QDeclarativeTextInput::xToPosition(int x) |
|
846 { |
|
847 Q_D(const QDeclarativeTextInput); |
|
848 return d->control->xToPos(x - d->hscroll); |
|
849 } |
|
850 |
|
851 void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus) |
|
852 { |
|
853 Q_Q(QDeclarativeTextInput); |
|
854 focused = hasFocus; |
|
855 q->setCursorVisible(hasFocus); |
|
856 if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus) |
|
857 control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events |
|
858 if (!hasFocus) |
|
859 control->deselect(); |
|
860 QDeclarativeItemPrivate::focusChanged(hasFocus); |
|
861 } |
|
862 |
|
863 void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev) |
|
864 { |
|
865 Q_D(QDeclarativeTextInput); |
|
866 keyPressPreHandler(ev); |
|
867 if (ev->isAccepted()) |
|
868 return; |
|
869 if (((ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier) // Don't allow MacOSX up/down support, and we don't allow a completer. |
|
870 || (((d->control->cursor() == 0 && ev->key() == Qt::Key_Left) |
|
871 || (d->control->cursor() == d->control->text().length() |
|
872 && ev->key() == Qt::Key_Right)) |
|
873 && (d->lastSelectionStart == d->lastSelectionEnd))) |
|
874 { |
|
875 //ignore when moving off the end |
|
876 //unless there is a selection, because then moving will do something (deselect) |
|
877 ev->ignore(); |
|
878 }else{ |
|
879 d->control->processKeyEvent(ev); |
|
880 } |
|
881 if (!ev->isAccepted()) |
|
882 QDeclarativePaintedItem::keyPressEvent(ev); |
|
883 } |
|
884 |
|
885 void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) |
|
886 { |
|
887 Q_D(QDeclarativeTextInput); |
|
888 bool hadFocus = hasFocus(); |
|
889 if(d->focusOnPress){ |
|
890 QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope? |
|
891 while(p) { |
|
892 if (p->flags() & QGraphicsItem::ItemIsFocusScope) |
|
893 p->setFocus(); |
|
894 p = p->parentItem(); |
|
895 } |
|
896 setFocus(true); |
|
897 } |
|
898 if (!hadFocus && hasFocus()) |
|
899 d->clickCausedFocus = true; |
|
900 |
|
901 bool mark = event->modifiers() & Qt::ShiftModifier; |
|
902 int cursor = d->xToPos(event->pos().x()); |
|
903 d->control->moveCursor(cursor, mark); |
|
904 event->setAccepted(true); |
|
905 } |
|
906 |
|
907 void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) |
|
908 { |
|
909 Q_D(QDeclarativeTextInput); |
|
910 if (d->selectByMouse) { |
|
911 d->control->moveCursor(d->xToPos(event->pos().x()), true); |
|
912 event->setAccepted(true); |
|
913 } else { |
|
914 QDeclarativePaintedItem::mouseMoveEvent(event); |
|
915 } |
|
916 } |
|
917 |
|
918 /*! |
|
919 \overload |
|
920 Handles the given mouse \a event. |
|
921 */ |
|
922 void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) |
|
923 { |
|
924 Q_D(QDeclarativeTextInput); |
|
925 QWidget *widget = event->widget(); |
|
926 if (widget && !d->control->isReadOnly() && boundingRect().contains(event->pos())) |
|
927 qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus); |
|
928 d->clickCausedFocus = false; |
|
929 if (!event->isAccepted()) |
|
930 QDeclarativePaintedItem::mouseReleaseEvent(event); |
|
931 } |
|
932 |
|
933 bool QDeclarativeTextInput::event(QEvent* ev) |
|
934 { |
|
935 Q_D(QDeclarativeTextInput); |
|
936 //Anything we don't deal with ourselves, pass to the control |
|
937 bool handled = false; |
|
938 switch(ev->type()){ |
|
939 case QEvent::KeyPress: |
|
940 case QEvent::KeyRelease://###Should the control be doing anything with release? |
|
941 case QEvent::GraphicsSceneMousePress: |
|
942 case QEvent::GraphicsSceneMouseMove: |
|
943 case QEvent::GraphicsSceneMouseRelease: |
|
944 break; |
|
945 default: |
|
946 if (ev->type() == QEvent::GraphicsSceneMouseDoubleClick && !d->selectByMouse) |
|
947 break; |
|
948 handled = d->control->processEvent(ev); |
|
949 if (ev->type() == QEvent::InputMethod) |
|
950 updateSize(); |
|
951 } |
|
952 if(!handled) |
|
953 handled = QDeclarativePaintedItem::event(ev); |
|
954 return handled; |
|
955 } |
|
956 |
|
957 void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry, |
|
958 const QRectF &oldGeometry) |
|
959 { |
|
960 if (newGeometry.width() != oldGeometry.width()) |
|
961 updateSize(); |
|
962 QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry); |
|
963 } |
|
964 |
|
965 void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r) |
|
966 { |
|
967 Q_D(QDeclarativeTextInput); |
|
968 p->setRenderHint(QPainter::TextAntialiasing, true); |
|
969 p->save(); |
|
970 p->setPen(QPen(d->color)); |
|
971 int flags = QLineControl::DrawText; |
|
972 if(!isReadOnly() && d->cursorVisible && !d->cursorItem) |
|
973 flags |= QLineControl::DrawCursor; |
|
974 if (d->control->hasSelectedText()) |
|
975 flags |= QLineControl::DrawSelections; |
|
976 QPoint offset = QPoint(0,0); |
|
977 QFontMetrics fm = QFontMetrics(d->font); |
|
978 int cix = qRound(d->control->cursorToX()); |
|
979 QRect br(boundingRect().toRect()); |
|
980 //###Is this using bearing appropriately? |
|
981 int minLB = qMax(0, -fm.minLeftBearing()); |
|
982 int minRB = qMax(0, -fm.minRightBearing()); |
|
983 int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; |
|
984 if (d->autoScroll) { |
|
985 if ((minLB + widthUsed) <= br.width()) { |
|
986 // text fits in br; use hscroll for alignment |
|
987 switch (d->hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { |
|
988 case Qt::AlignRight: |
|
989 d->hscroll = widthUsed - br.width() + 1; |
|
990 break; |
|
991 case Qt::AlignHCenter: |
|
992 d->hscroll = (widthUsed - br.width()) / 2; |
|
993 break; |
|
994 default: |
|
995 // Left |
|
996 d->hscroll = 0; |
|
997 break; |
|
998 } |
|
999 d->hscroll -= minLB; |
|
1000 } else if (cix - d->hscroll >= br.width()) { |
|
1001 // text doesn't fit, cursor is to the right of br (scroll right) |
|
1002 d->hscroll = cix - br.width() + 1; |
|
1003 } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) { |
|
1004 // text doesn't fit, cursor is to the left of br (scroll left) |
|
1005 d->hscroll = cix; |
|
1006 } else if (widthUsed - d->hscroll < br.width()) { |
|
1007 // text doesn't fit, text document is to the left of br; align |
|
1008 // right |
|
1009 d->hscroll = widthUsed - br.width() + 1; |
|
1010 } |
|
1011 // the y offset is there to keep the baseline constant in case we have script changes in the text. |
|
1012 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); |
|
1013 } else { |
|
1014 if(d->hAlign == AlignRight){ |
|
1015 d->hscroll = width() - widthUsed; |
|
1016 }else if(d->hAlign == AlignHCenter){ |
|
1017 d->hscroll = (width() - widthUsed) / 2; |
|
1018 } |
|
1019 d->hscroll -= minLB; |
|
1020 offset = QPoint(d->hscroll, 0); |
|
1021 } |
|
1022 |
|
1023 d->control->draw(p, offset, r, flags); |
|
1024 |
|
1025 p->restore(); |
|
1026 } |
|
1027 |
|
1028 /*! |
|
1029 \overload |
|
1030 Returns the value of the given \a property. |
|
1031 */ |
|
1032 QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) const |
|
1033 { |
|
1034 Q_D(const QDeclarativeTextInput); |
|
1035 switch(property) { |
|
1036 case Qt::ImMicroFocus: |
|
1037 return d->control->cursorRect(); |
|
1038 case Qt::ImFont: |
|
1039 return font(); |
|
1040 case Qt::ImCursorPosition: |
|
1041 return QVariant(d->control->cursor()); |
|
1042 case Qt::ImSurroundingText: |
|
1043 return QVariant(text()); |
|
1044 case Qt::ImCurrentSelection: |
|
1045 return QVariant(selectedText()); |
|
1046 case Qt::ImMaximumTextLength: |
|
1047 return QVariant(maxLength()); |
|
1048 case Qt::ImAnchorPosition: |
|
1049 if (d->control->selectionStart() == d->control->selectionEnd()) |
|
1050 return QVariant(d->control->cursor()); |
|
1051 else if (d->control->selectionStart() == d->control->cursor()) |
|
1052 return QVariant(d->control->selectionEnd()); |
|
1053 else |
|
1054 return QVariant(d->control->selectionStart()); |
|
1055 default: |
|
1056 return QVariant(); |
|
1057 } |
|
1058 } |
|
1059 |
|
1060 void QDeclarativeTextInput::selectAll() |
|
1061 { |
|
1062 Q_D(QDeclarativeTextInput); |
|
1063 d->control->setSelection(0, d->control->text().length()); |
|
1064 } |
|
1065 |
|
1066 |
|
1067 /*! |
|
1068 \qmlproperty bool TextInput::smooth |
|
1069 |
|
1070 This property holds whether the text is smoothly scaled or transformed. |
|
1071 |
|
1072 Smooth filtering gives better visual quality, but is slower. If |
|
1073 the item is displayed at its natural size, this property has no visual or |
|
1074 performance effect. |
|
1075 |
|
1076 \note Generally scaling artifacts are only visible if the item is stationary on |
|
1077 the screen. A common pattern when animating an item is to disable smooth |
|
1078 filtering at the beginning of the animation and reenable it at the conclusion. |
|
1079 */ |
|
1080 |
|
1081 /*! |
|
1082 \qmlproperty string TextInput::passwordCharacter |
|
1083 |
|
1084 This is the character displayed when echoMode is set to Password or |
|
1085 PasswordEchoOnEdit. By default it is an asterisk. |
|
1086 |
|
1087 If this property is set to a string with more than one character, |
|
1088 the first character is used. If the string is empty, the value |
|
1089 is ignored and the property is not set. |
|
1090 */ |
|
1091 QString QDeclarativeTextInput::passwordCharacter() const |
|
1092 { |
|
1093 Q_D(const QDeclarativeTextInput); |
|
1094 return QString(d->control->passwordCharacter()); |
|
1095 } |
|
1096 |
|
1097 void QDeclarativeTextInput::setPasswordCharacter(const QString &str) |
|
1098 { |
|
1099 Q_D(QDeclarativeTextInput); |
|
1100 if(str.length() < 1) |
|
1101 return; |
|
1102 emit passwordCharacterChanged(); |
|
1103 d->control->setPasswordCharacter(str.constData()[0]); |
|
1104 } |
|
1105 |
|
1106 /*! |
|
1107 \qmlproperty string TextInput::displayText |
|
1108 |
|
1109 This is the text displayed in the TextInput. |
|
1110 |
|
1111 If \l echoMode is set to TextInput::Normal, this holds the |
|
1112 same value as the TextInput::text property. Otherwise, |
|
1113 this property holds the text visible to the user, while |
|
1114 the \l text property holds the actual entered text. |
|
1115 */ |
|
1116 QString QDeclarativeTextInput::displayText() const |
|
1117 { |
|
1118 Q_D(const QDeclarativeTextInput); |
|
1119 return d->control->displayText(); |
|
1120 } |
|
1121 |
|
1122 /*! |
|
1123 \qmlproperty string TextInput::selectByMouse |
|
1124 |
|
1125 Defaults to false. |
|
1126 |
|
1127 If true, the user can use the mouse to select text in some |
|
1128 platform-specific way. Note that for some platforms this may |
|
1129 not be an appropriate interaction (eg. may conflict with how |
|
1130 the text needs to behave inside a Flickable. |
|
1131 */ |
|
1132 bool QDeclarativeTextInput::selectByMouse() const |
|
1133 { |
|
1134 Q_D(const QDeclarativeTextInput); |
|
1135 return d->selectByMouse; |
|
1136 } |
|
1137 |
|
1138 void QDeclarativeTextInput::setSelectByMouse(bool on) |
|
1139 { |
|
1140 Q_D(QDeclarativeTextInput); |
|
1141 if (d->selectByMouse != on) { |
|
1142 d->selectByMouse = on; |
|
1143 emit selectByMouseChanged(on); |
|
1144 } |
|
1145 } |
|
1146 |
|
1147 |
|
1148 /*! |
|
1149 \qmlmethod void TextInput::moveCursorSelection(int position) |
|
1150 |
|
1151 Moves the cursor to \a position and updates the selection accordingly. |
|
1152 (To only move the cursor, set the \l cursorPosition property.) |
|
1153 |
|
1154 When this method is called it additionally sets either the |
|
1155 selectionStart or the selectionEnd (whichever was at the previous cursor position) |
|
1156 to the specified position. This allows you to easily extend and contract the selected |
|
1157 text range. |
|
1158 |
|
1159 For example, take this sequence of calls: |
|
1160 |
|
1161 \code |
|
1162 cursorPosition = 5 |
|
1163 moveCursorSelection(9) |
|
1164 moveCursorSelection(7) |
|
1165 \endcode |
|
1166 |
|
1167 This moves the cursor to position 5, extend the selection end from 5 to 9 |
|
1168 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7 |
|
1169 selected (the 6th and 7th characters). |
|
1170 */ |
|
1171 void QDeclarativeTextInput::moveCursorSelection(int position) |
|
1172 { |
|
1173 Q_D(QDeclarativeTextInput); |
|
1174 d->control->moveCursor(position, true); |
|
1175 } |
|
1176 |
|
1177 void QDeclarativeTextInputPrivate::init() |
|
1178 { |
|
1179 Q_Q(QDeclarativeTextInput); |
|
1180 control->setCursorWidth(1); |
|
1181 control->setPasswordCharacter(QLatin1Char('*')); |
|
1182 control->setLayoutDirection(Qt::LeftToRight); |
|
1183 q->setSmooth(smooth); |
|
1184 q->setAcceptedMouseButtons(Qt::LeftButton); |
|
1185 q->setFlag(QGraphicsItem::ItemHasNoContents, false); |
|
1186 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod); |
|
1187 q->connect(control, SIGNAL(cursorPositionChanged(int,int)), |
|
1188 q, SLOT(cursorPosChanged())); |
|
1189 q->connect(control, SIGNAL(selectionChanged()), |
|
1190 q, SLOT(selectionChanged())); |
|
1191 q->connect(control, SIGNAL(textChanged(const QString &)), |
|
1192 q, SIGNAL(displayTextChanged(const QString &))); |
|
1193 q->connect(control, SIGNAL(textChanged(const QString &)), |
|
1194 q, SLOT(q_textChanged())); |
|
1195 q->connect(control, SIGNAL(accepted()), |
|
1196 q, SIGNAL(accepted())); |
|
1197 q->connect(control, SIGNAL(updateNeeded(QRect)), |
|
1198 q, SLOT(updateRect(QRect))); |
|
1199 q->connect(control, SIGNAL(cursorPositionChanged(int,int)), |
|
1200 q, SLOT(updateRect()));//TODO: Only update rect between pos's |
|
1201 q->connect(control, SIGNAL(selectionChanged()), |
|
1202 q, SLOT(updateRect()));//TODO: Only update rect in selection |
|
1203 //Note that above TODOs probably aren't that big a savings |
|
1204 q->updateSize(); |
|
1205 oldValidity = control->hasAcceptableInput(); |
|
1206 lastSelectionStart = 0; |
|
1207 lastSelectionEnd = 0; |
|
1208 QPalette p = control->palette(); |
|
1209 selectedTextColor = p.color(QPalette::HighlightedText); |
|
1210 selectionColor = p.color(QPalette::Highlight); |
|
1211 } |
|
1212 |
|
1213 void QDeclarativeTextInput::cursorPosChanged() |
|
1214 { |
|
1215 Q_D(QDeclarativeTextInput); |
|
1216 emit cursorPositionChanged(); |
|
1217 |
|
1218 if(!d->control->hasSelectedText()){ |
|
1219 if(d->lastSelectionStart != d->control->cursor()){ |
|
1220 d->lastSelectionStart = d->control->cursor(); |
|
1221 emit selectionStartChanged(); |
|
1222 } |
|
1223 if(d->lastSelectionEnd != d->control->cursor()){ |
|
1224 d->lastSelectionEnd = d->control->cursor(); |
|
1225 emit selectionEndChanged(); |
|
1226 } |
|
1227 } |
|
1228 } |
|
1229 |
|
1230 void QDeclarativeTextInput::selectionChanged() |
|
1231 { |
|
1232 Q_D(QDeclarativeTextInput); |
|
1233 emit selectedTextChanged(); |
|
1234 |
|
1235 if(d->lastSelectionStart != d->control->selectionStart()){ |
|
1236 d->lastSelectionStart = d->control->selectionStart(); |
|
1237 if(d->lastSelectionStart == -1) |
|
1238 d->lastSelectionStart = d->control->cursor(); |
|
1239 emit selectionStartChanged(); |
|
1240 } |
|
1241 if(d->lastSelectionEnd != d->control->selectionEnd()){ |
|
1242 d->lastSelectionEnd = d->control->selectionEnd(); |
|
1243 if(d->lastSelectionEnd == -1) |
|
1244 d->lastSelectionEnd = d->control->cursor(); |
|
1245 emit selectionEndChanged(); |
|
1246 } |
|
1247 } |
|
1248 |
|
1249 void QDeclarativeTextInput::q_textChanged() |
|
1250 { |
|
1251 Q_D(QDeclarativeTextInput); |
|
1252 updateSize(); |
|
1253 emit textChanged(); |
|
1254 if(hasAcceptableInput() != d->oldValidity){ |
|
1255 d->oldValidity = hasAcceptableInput(); |
|
1256 emit acceptableInputChanged(); |
|
1257 } |
|
1258 } |
|
1259 |
|
1260 void QDeclarativeTextInput::updateRect(const QRect &r) |
|
1261 { |
|
1262 Q_D(QDeclarativeTextInput); |
|
1263 if(r == QRect()) |
|
1264 clearCache(); |
|
1265 else |
|
1266 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height())); |
|
1267 update(); |
|
1268 } |
|
1269 |
|
1270 void QDeclarativeTextInput::updateSize(bool needsRedraw) |
|
1271 { |
|
1272 Q_D(QDeclarativeTextInput); |
|
1273 int w = width(); |
|
1274 int h = height(); |
|
1275 setImplicitHeight(d->control->height()); |
|
1276 int cursorWidth = d->control->cursorWidth(); |
|
1277 if(d->cursorItem) |
|
1278 cursorWidth = d->cursorItem->width(); |
|
1279 setImplicitWidth(d->control->naturalTextWidth() + cursorWidth); |
|
1280 setContentsSize(QSize(width(), height()));//Repaints if changed |
|
1281 if(w==width() && h==height() && needsRedraw){ |
|
1282 clearCache(); |
|
1283 update(); |
|
1284 } |
|
1285 } |
|
1286 |
|
1287 QT_END_NAMESPACE |
|
1288 |