source: trunk/src/declarative/graphicsitems/qdeclarativetextinput.cpp@ 846

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

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

File size: 46.9 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 QtDeclarative 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#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 <QTextCursor>
50#include <QApplication>
51#include <QFontMetrics>
52#include <QPainter>
53
54#ifndef QT_NO_LINEEDIT
55
56QT_BEGIN_NAMESPACE
57
58/*!
59 \qmlclass TextInput QDeclarativeTextInput
60 \ingroup qml-basic-visual-elements
61 \since 4.7
62 \brief The TextInput item displays an editable line of text.
63 \inherits Item
64
65 The TextInput element displays a single line of editable plain text.
66
67 TextInput is used to accept a line of text input. Input constraints
68 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
69 and setting \l echoMode to an appropriate value enables TextInput to be used for
70 a password input field.
71
72 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
73 If you want such bindings (on any platform), you will need to construct them in QML.
74
75 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
76*/
77QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent)
78 : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent)
79{
80 Q_D(QDeclarativeTextInput);
81 d->init();
82}
83
84QDeclarativeTextInput::~QDeclarativeTextInput()
85{
86}
87
88/*!
89 \qmlproperty string TextInput::text
90
91 The text in the TextInput.
92*/
93
94QString QDeclarativeTextInput::text() const
95{
96 Q_D(const QDeclarativeTextInput);
97 return d->control->text();
98}
99
100void QDeclarativeTextInput::setText(const QString &s)
101{
102 Q_D(QDeclarativeTextInput);
103 if(s == text())
104 return;
105 d->control->setText(s);
106}
107
108/*!
109 \qmlproperty string TextInput::font.family
110
111 Sets the family name of the font.
112
113 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
114 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
115 If the family isn't available a family will be set using the font matching algorithm.
116*/
117
118/*!
119 \qmlproperty bool TextInput::font.bold
120
121 Sets whether the font weight is bold.
122*/
123
124/*!
125 \qmlproperty enumeration TextInput::font.weight
126
127 Sets the font's weight.
128
129 The weight can be one of:
130 \list
131 \o Font.Light
132 \o Font.Normal - the default
133 \o Font.DemiBold
134 \o Font.Bold
135 \o Font.Black
136 \endlist
137
138 \qml
139 TextInput { text: "Hello"; font.weight: Font.DemiBold }
140 \endqml
141*/
142
143/*!
144 \qmlproperty bool TextInput::font.italic
145
146 Sets whether the font has an italic style.
147*/
148
149/*!
150 \qmlproperty bool TextInput::font.underline
151
152 Sets whether the text is underlined.
153*/
154
155/*!
156 \qmlproperty bool TextInput::font.strikeout
157
158 Sets whether the font has a strikeout style.
159*/
160
161/*!
162 \qmlproperty real TextInput::font.pointSize
163
164 Sets the font size in points. The point size must be greater than zero.
165*/
166
167/*!
168 \qmlproperty int TextInput::font.pixelSize
169
170 Sets the font size in pixels.
171
172 Using this function makes the font device dependent.
173 Use \c pointSize to set the size of the font in a device independent manner.
174*/
175
176/*!
177 \qmlproperty real TextInput::font.letterSpacing
178
179 Sets the letter spacing for the font.
180
181 Letter spacing changes the default spacing between individual letters in the font.
182 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
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
213QFont QDeclarativeTextInput::font() const
214{
215 Q_D(const QDeclarativeTextInput);
216 return d->sourceFont;
217}
218
219void QDeclarativeTextInput::setFont(const QFont &font)
220{
221 Q_D(QDeclarativeTextInput);
222 if (d->sourceFont == font)
223 return;
224
225 d->sourceFont = font;
226 QFont oldFont = d->font;
227 d->font = font;
228 if (d->font.pointSizeF() != -1) {
229 // 0.5pt resolution
230 qreal size = qRound(d->font.pointSizeF()*2.0);
231 d->font.setPointSizeF(size/2.0);
232 }
233
234 if (oldFont != d->font) {
235 d->control->setFont(d->font);
236 if(d->cursorItem){
237 d->cursorItem->setHeight(QFontMetrics(d->font).height());
238 moveCursor();
239 }
240 updateSize();
241 }
242 emit fontChanged(d->sourceFont);
243}
244
245/*!
246 \qmlproperty color TextInput::color
247
248 The text color.
249*/
250QColor QDeclarativeTextInput::color() const
251{
252 Q_D(const QDeclarativeTextInput);
253 return d->color;
254}
255
256void QDeclarativeTextInput::setColor(const QColor &c)
257{
258 Q_D(QDeclarativeTextInput);
259 if (c != d->color) {
260 d->color = c;
261 clearCache();
262 update();
263 emit colorChanged(c);
264 }
265}
266
267
268/*!
269 \qmlproperty color TextInput::selectionColor
270
271 The text highlight color, used behind selections.
272*/
273QColor QDeclarativeTextInput::selectionColor() const
274{
275 Q_D(const QDeclarativeTextInput);
276 return d->selectionColor;
277}
278
279void QDeclarativeTextInput::setSelectionColor(const QColor &color)
280{
281 Q_D(QDeclarativeTextInput);
282 if (d->selectionColor == color)
283 return;
284
285 d->selectionColor = color;
286 QPalette p = d->control->palette();
287 p.setColor(QPalette::Highlight, d->selectionColor);
288 d->control->setPalette(p);
289 if (d->control->hasSelectedText()) {
290 clearCache();
291 update();
292 }
293 emit selectionColorChanged(color);
294}
295
296/*!
297 \qmlproperty color TextInput::selectedTextColor
298
299 The highlighted text color, used in selections.
300*/
301QColor QDeclarativeTextInput::selectedTextColor() const
302{
303 Q_D(const QDeclarativeTextInput);
304 return d->selectedTextColor;
305}
306
307void QDeclarativeTextInput::setSelectedTextColor(const QColor &color)
308{
309 Q_D(QDeclarativeTextInput);
310 if (d->selectedTextColor == color)
311 return;
312
313 d->selectedTextColor = color;
314 QPalette p = d->control->palette();
315 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
316 d->control->setPalette(p);
317 if (d->control->hasSelectedText()) {
318 clearCache();
319 update();
320 }
321 emit selectedTextColorChanged(color);
322}
323
324/*!
325 \qmlproperty enumeration TextInput::horizontalAlignment
326
327 Sets the horizontal alignment of the text within the TextInput item's
328 width and height. By default, the text is left aligned.
329
330 TextInput does not have vertical alignment, as the natural height is
331 exactly the height of the single line of text. If you set the height
332 manually to something larger, TextInput will always be top aligned
333 vertically. You can use anchors to align it however you want within
334 another item.
335
336 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
337 \c TextInput.AlignHCenter.
338*/
339QDeclarativeTextInput::HAlignment QDeclarativeTextInput::hAlign() const
340{
341 Q_D(const QDeclarativeTextInput);
342 return d->hAlign;
343}
344
345void QDeclarativeTextInput::setHAlign(HAlignment align)
346{
347 Q_D(QDeclarativeTextInput);
348 if(align == d->hAlign)
349 return;
350 d->hAlign = align;
351 updateRect();
352 d->updateHorizontalScroll();
353 emit horizontalAlignmentChanged(d->hAlign);
354}
355
356bool QDeclarativeTextInput::isReadOnly() const
357{
358 Q_D(const QDeclarativeTextInput);
359 return d->control->isReadOnly();
360}
361
362void QDeclarativeTextInput::setReadOnly(bool ro)
363{
364 Q_D(QDeclarativeTextInput);
365 if (d->control->isReadOnly() == ro)
366 return;
367
368 d->control->setReadOnly(ro);
369
370 emit readOnlyChanged(ro);
371}
372
373int QDeclarativeTextInput::maxLength() const
374{
375 Q_D(const QDeclarativeTextInput);
376 return d->control->maxLength();
377}
378
379void QDeclarativeTextInput::setMaxLength(int ml)
380{
381 Q_D(QDeclarativeTextInput);
382 if (d->control->maxLength() == ml)
383 return;
384
385 d->control->setMaxLength(ml);
386
387 emit maximumLengthChanged(ml);
388}
389
390/*!
391 \qmlproperty bool TextInput::cursorVisible
392 Set to true when the TextInput shows a cursor.
393
394 This property is set and unset when the TextInput gets active focus, so that other
395 properties can be bound to whether the cursor is currently showing. As it
396 gets set and unset automatically, when you set the value yourself you must
397 keep in mind that your value may be overwritten.
398
399 It can be set directly in script, for example if a KeyProxy might
400 forward keys to it and you desire it to look active when this happens
401 (but without actually giving it active focus).
402
403 It should not be set directly on the element, like in the below QML,
404 as the specified value will be overridden an lost on focus changes.
405
406 \code
407 TextInput {
408 text: "Text"
409 cursorVisible: false
410 }
411 \endcode
412
413 In the above snippet the cursor will still become visible when the
414 TextInput gains active focus.
415*/
416bool QDeclarativeTextInput::isCursorVisible() const
417{
418 Q_D(const QDeclarativeTextInput);
419 return d->cursorVisible;
420}
421
422void QDeclarativeTextInput::setCursorVisible(bool on)
423{
424 Q_D(QDeclarativeTextInput);
425 if (d->cursorVisible == on)
426 return;
427 d->cursorVisible = on;
428 d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
429 QRect r = d->control->cursorRect();
430 if (d->control->inputMask().isEmpty())
431 updateRect(r);
432 else
433 updateRect();
434 emit cursorVisibleChanged(d->cursorVisible);
435}
436
437/*!
438 \qmlproperty int TextInput::cursorPosition
439 The position of the cursor in the TextInput.
440*/
441int QDeclarativeTextInput::cursorPosition() const
442{
443 Q_D(const QDeclarativeTextInput);
444 return d->control->cursor();
445}
446void QDeclarativeTextInput::setCursorPosition(int cp)
447{
448 Q_D(QDeclarativeTextInput);
449 if (cp < 0 || cp > d->control->text().length())
450 return;
451 d->control->moveCursor(cp);
452}
453
454/*!
455 Returns a Rect which encompasses the cursor, but which may be larger than is
456 required. Ignores custom cursor delegates.
457*/
458QRect QDeclarativeTextInput::cursorRectangle() const
459{
460 Q_D(const QDeclarativeTextInput);
461 QRect r = d->control->cursorRect();
462 r.setHeight(r.height()-1); // Make consistent with TextEdit (QLineControl inexplicably adds 1)
463 return r;
464}
465
466/*!
467 \qmlproperty int TextInput::selectionStart
468
469 The cursor position before the first character in the current selection.
470 Setting this and selectionEnd allows you to specify a selection in the
471 text edit.
472
473 Note that if selectionStart == selectionEnd then there is no current
474 selection.
475
476 \sa selectionEnd, cursorPosition, selectedText, select()
477*/
478int QDeclarativeTextInput::selectionStart() const
479{
480 Q_D(const QDeclarativeTextInput);
481 return d->lastSelectionStart;
482}
483
484/*!
485 \qmlproperty int TextInput::selectionEnd
486
487 The cursor position after the last character in the current selection.
488 Setting this and selectionStart allows you to specify a selection in the
489 text edit.
490
491 Note that if selectionStart == selectionEnd then there is no current
492 selection.
493
494 \sa selectionStart, cursorPosition, selectedText, select()
495*/
496int QDeclarativeTextInput::selectionEnd() const
497{
498 Q_D(const QDeclarativeTextInput);
499 return d->lastSelectionEnd;
500}
501
502/*!
503 \qmlmethod void TextInput::select(int start, int end)
504
505 Causes the text from \a start to \a end to be selected.
506
507 If either start or end is out of range, the selection is not changed.
508
509 After calling this, selectionStart will become the lesser
510 and selectionEnd will become the greater (regardless of the order passed
511 to this method).
512
513 \sa selectionStart, selectionEnd
514*/
515void QDeclarativeTextInput::select(int start, int end)
516{
517 Q_D(QDeclarativeTextInput);
518 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
519 return;
520 d->control->setSelection(start, end-start);
521}
522
523/*!
524 \qmlproperty string TextInput::selectedText
525
526 This read-only property provides the text currently selected in the
527 text input.
528
529 It is equivalent to the following snippet, but is faster and easier
530 to use.
531
532 \qml
533 myTextInput.text.toString().substring(myTextInput.selectionStart,
534 myTextInput.selectionEnd);
535 \endqml
536*/
537QString QDeclarativeTextInput::selectedText() const
538{
539 Q_D(const QDeclarativeTextInput);
540 return d->control->selectedText();
541}
542
543/*!
544 \qmlproperty bool TextInput::activeFocusOnPress
545
546 Whether the TextInput should gain active focus on a mouse press. By default this is
547 set to true.
548*/
549bool QDeclarativeTextInput::focusOnPress() const
550{
551 Q_D(const QDeclarativeTextInput);
552 return d->focusOnPress;
553}
554
555void QDeclarativeTextInput::setFocusOnPress(bool b)
556{
557 Q_D(QDeclarativeTextInput);
558 if (d->focusOnPress == b)
559 return;
560
561 d->focusOnPress = b;
562
563 emit activeFocusOnPressChanged(d->focusOnPress);
564}
565
566/*!
567 \qmlproperty bool TextInput::autoScroll
568
569 Whether the TextInput should scroll when the text is longer than the width. By default this is
570 set to true.
571*/
572bool QDeclarativeTextInput::autoScroll() const
573{
574 Q_D(const QDeclarativeTextInput);
575 return d->autoScroll;
576}
577
578void QDeclarativeTextInput::setAutoScroll(bool b)
579{
580 Q_D(QDeclarativeTextInput);
581 if (d->autoScroll == b)
582 return;
583
584 d->autoScroll = b;
585 //We need to repaint so that the scrolling is taking into account.
586 updateSize(true);
587 d->updateHorizontalScroll();
588 emit autoScrollChanged(d->autoScroll);
589}
590
591/*!
592 \qmlclass IntValidator QIntValidator
593 \ingroup qml-basic-visual-elements
594
595 This element provides a validator for integer values.
596*/
597/*!
598 \qmlproperty int IntValidator::top
599
600 This property holds the validator's highest acceptable value.
601 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
602*/
603/*!
604 \qmlproperty int IntValidator::bottom
605
606 This property holds the validator's lowest acceptable value.
607 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
608*/
609
610/*!
611 \qmlclass DoubleValidator QDoubleValidator
612 \ingroup qml-basic-visual-elements
613
614 This element provides a validator for non-integer numbers.
615*/
616
617/*!
618 \qmlproperty real DoubleValidator::top
619
620 This property holds the validator's maximum acceptable value.
621 By default, this property contains a value of infinity.
622*/
623/*!
624 \qmlproperty real DoubleValidator::bottom
625
626 This property holds the validator's minimum acceptable value.
627 By default, this property contains a value of -infinity.
628*/
629/*!
630 \qmlproperty int DoubleValidator::decimals
631
632 This property holds the validator's maximum number of digits after the decimal point.
633 By default, this property contains a value of 1000.
634*/
635/*!
636 \qmlproperty enumeration DoubleValidator::notation
637 This property holds the notation of how a string can describe a number.
638
639 The possible values for this property are:
640
641 \list
642 \o DoubleValidator.StandardNotation
643 \o DoubleValidator.ScientificNotation (default)
644 \endlist
645
646 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
647*/
648
649/*!
650 \qmlclass RegExpValidator QRegExpValidator
651 \ingroup qml-basic-visual-elements
652
653 This element provides a validator, which counts as valid any string which
654 matches a specified regular expression.
655*/
656/*!
657 \qmlproperty regExp RegExpValidator::regExp
658
659 This property holds the regular expression used for validation.
660
661 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
662 matching "a".
663
664 By default, this property contains a regular expression with the pattern .* that matches any string.
665*/
666
667/*!
668 \qmlproperty Validator TextInput::validator
669
670 Allows you to set a validator on the TextInput. When a validator is set
671 the TextInput will only accept input which leaves the text property in
672 an acceptable or intermediate state. The accepted signal will only be sent
673 if the text is in an acceptable state when enter is pressed.
674
675 Currently supported validators are IntValidator, DoubleValidator and
676 RegExpValidator. An example of using validators is shown below, which allows
677 input of integers between 11 and 31 into the text input:
678
679 \code
680 import QtQuick 1.0
681 TextInput{
682 validator: IntValidator{bottom: 11; top: 31;}
683 focus: true
684 }
685 \endcode
686
687 \sa acceptableInput, inputMask
688*/
689#ifndef QT_NO_VALIDATOR
690QValidator* QDeclarativeTextInput::validator() const
691{
692 Q_D(const QDeclarativeTextInput);
693 //###const cast isn't good, but needed for property system?
694 return const_cast<QValidator*>(d->control->validator());
695}
696
697void QDeclarativeTextInput::setValidator(QValidator* v)
698{
699 Q_D(QDeclarativeTextInput);
700 if (d->control->validator() == v)
701 return;
702
703 d->control->setValidator(v);
704 if(!d->control->hasAcceptableInput()){
705 d->oldValidity = false;
706 emit acceptableInputChanged();
707 }
708
709 emit validatorChanged();
710}
711#endif // QT_NO_VALIDATOR
712
713/*!
714 \qmlproperty string TextInput::inputMask
715
716 Allows you to set an input mask on the TextInput, restricting the allowable
717 text inputs. See QLineEdit::inputMask for further details, as the exact
718 same mask strings are used by TextInput.
719
720 \sa acceptableInput, validator
721*/
722QString QDeclarativeTextInput::inputMask() const
723{
724 Q_D(const QDeclarativeTextInput);
725 return d->control->inputMask();
726}
727
728void QDeclarativeTextInput::setInputMask(const QString &im)
729{
730 Q_D(QDeclarativeTextInput);
731 if (d->control->inputMask() == im)
732 return;
733
734 d->control->setInputMask(im);
735 emit inputMaskChanged(d->control->inputMask());
736}
737
738/*!
739 \qmlproperty bool TextInput::acceptableInput
740
741 This property is always true unless a validator or input mask has been set.
742 If a validator or input mask has been set, this property will only be true
743 if the current text is acceptable to the validator or input mask as a final
744 string (not as an intermediate string).
745*/
746bool QDeclarativeTextInput::hasAcceptableInput() const
747{
748 Q_D(const QDeclarativeTextInput);
749 return d->control->hasAcceptableInput();
750}
751
752/*!
753 \qmlproperty enumeration TextInput::echoMode
754
755 Specifies how the text should be displayed in the TextInput.
756 \list
757 \o TextInput.Normal - Displays the text as it is. (Default)
758 \o TextInput.Password - Displays asterixes instead of characters.
759 \o TextInput.NoEcho - Displays nothing.
760 \o TextInput.PasswordEchoOnEdit - Displays all but the current character as asterixes.
761 \endlist
762*/
763QDeclarativeTextInput::EchoMode QDeclarativeTextInput::echoMode() const
764{
765 Q_D(const QDeclarativeTextInput);
766 return (QDeclarativeTextInput::EchoMode)d->control->echoMode();
767}
768
769void QDeclarativeTextInput::setEchoMode(QDeclarativeTextInput::EchoMode echo)
770{
771 Q_D(QDeclarativeTextInput);
772 if (echoMode() == echo)
773 return;
774 Qt::InputMethodHints imHints = inputMethodHints();
775 if (echo == Password || echo == NoEcho)
776 imHints |= Qt::ImhHiddenText;
777 else
778 imHints &= ~Qt::ImhHiddenText;
779 if (echo != Normal)
780 imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
781 else
782 imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
783 setInputMethodHints(imHints);
784 d->control->setEchoMode((uint)echo);
785 q_textChanged();
786 emit echoModeChanged(echoMode());
787}
788
789/*!
790 \qmlproperty Component TextInput::cursorDelegate
791 The delegate for the cursor in the TextInput.
792
793 If you set a cursorDelegate for a TextInput, this delegate will be used for
794 drawing the cursor instead of the standard cursor. An instance of the
795 delegate will be created and managed by the TextInput when a cursor is
796 needed, and the x property of delegate instance will be set so as
797 to be one pixel before the top left of the current character.
798
799 Note that the root item of the delegate component must be a QDeclarativeItem or
800 QDeclarativeItem derived item.
801*/
802QDeclarativeComponent* QDeclarativeTextInput::cursorDelegate() const
803{
804 Q_D(const QDeclarativeTextInput);
805 return d->cursorComponent;
806}
807
808void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c)
809{
810 Q_D(QDeclarativeTextInput);
811 if (d->cursorComponent == c)
812 return;
813
814 d->cursorComponent = c;
815 if(!c){
816 //note that the components are owned by something else
817 disconnect(d->control, SIGNAL(cursorPositionChanged(int,int)),
818 this, SLOT(moveCursor()));
819 delete d->cursorItem;
820 }else{
821 d->startCreatingCursor();
822 }
823
824 emit cursorDelegateChanged();
825}
826
827void QDeclarativeTextInputPrivate::startCreatingCursor()
828{
829 Q_Q(QDeclarativeTextInput);
830 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
831 q, SLOT(moveCursor()));
832 if(cursorComponent->isReady()){
833 q->createCursor();
834 }else if(cursorComponent->isLoading()){
835 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
836 q, SLOT(createCursor()));
837 }else {//isError
838 qmlInfo(q, cursorComponent->errors()) << QDeclarativeTextInput::tr("Could not load cursor delegate");
839 }
840}
841
842void QDeclarativeTextInput::createCursor()
843{
844 Q_D(QDeclarativeTextInput);
845 if(d->cursorComponent->isError()){
846 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
847 return;
848 }
849
850 if(!d->cursorComponent->isReady())
851 return;
852
853 if(d->cursorItem)
854 delete d->cursorItem;
855 d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
856 if(!d->cursorItem){
857 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
858 return;
859 }
860
861 QDeclarative_setParent_noEvent(d->cursorItem, this);
862 d->cursorItem->setParentItem(this);
863 d->cursorItem->setX(d->control->cursorToX());
864 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
865}
866
867void QDeclarativeTextInput::moveCursor()
868{
869 Q_D(QDeclarativeTextInput);
870 if(!d->cursorItem)
871 return;
872 d->updateHorizontalScroll();
873 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
874}
875
876/*!
877 \qmlmethod rect TextInput::positionToRectangle(int pos)
878
879 This function takes a character position and returns the rectangle that the
880 cursor would occupy, if it was placed at that character position.
881
882 This is similar to setting the cursorPosition, and then querying the cursor
883 rectangle, but the cursorPosition is not changed.
884*/
885QRectF QDeclarativeTextInput::positionToRectangle(int pos) const
886{
887 Q_D(const QDeclarativeTextInput);
888 return QRectF(d->control->cursorToX(pos)-d->hscroll,
889 0.0,
890 d->control->cursorWidth(),
891 cursorRectangle().height());
892}
893
894/*!
895 \qmlmethod int TextInput::positionAt(int x)
896
897 This function returns the character position at
898 x pixels from the left of the textInput. Position 0 is before the
899 first character, position 1 is after the first character but before the second,
900 and so on until position text.length, which is after all characters.
901
902 This means that for all x values before the first character this function returns 0,
903 and for all x values after the last character this function returns text.length.
904*/
905int QDeclarativeTextInput::positionAt(int x) const
906{
907 Q_D(const QDeclarativeTextInput);
908 return d->control->xToPos(x + d->hscroll);
909}
910
911void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus)
912{
913 Q_Q(QDeclarativeTextInput);
914 focused = hasFocus;
915 q->setCursorVisible(hasFocus);
916 if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus)
917 control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
918 if (!hasFocus)
919 control->deselect();
920 QDeclarativeItemPrivate::focusChanged(hasFocus);
921}
922
923void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev)
924{
925 Q_D(QDeclarativeTextInput);
926 keyPressPreHandler(ev);
927 if (ev->isAccepted())
928 return;
929 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.
930 || (((d->control->cursor() == 0 && ev->key() == Qt::Key_Left)
931 || (d->control->cursor() == d->control->text().length()
932 && ev->key() == Qt::Key_Right))
933 && (d->lastSelectionStart == d->lastSelectionEnd)))
934 {
935 //ignore when moving off the end
936 //unless there is a selection, because then moving will do something (deselect)
937 ev->ignore();
938 }else{
939 d->control->processKeyEvent(ev);
940 }
941 if (!ev->isAccepted())
942 QDeclarativePaintedItem::keyPressEvent(ev);
943}
944
945void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev)
946{
947 Q_D(QDeclarativeTextInput);
948 ev->ignore();
949 inputMethodPreHandler(ev);
950 if (ev->isAccepted())
951 return;
952 if (d->control->isReadOnly()) {
953 ev->ignore();
954 } else {
955 d->control->processInputMethodEvent(ev);
956 updateSize();
957 }
958 if (!ev->isAccepted())
959 QDeclarativePaintedItem::inputMethodEvent(ev);
960}
961
962/*!
963\overload
964Handles the given mouse \a event.
965*/
966void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
967{
968 Q_D(QDeclarativeTextInput);
969 if (d->selectByMouse) {
970 int cursor = d->xToPos(event->pos().x());
971 d->control->selectWordAtPos(cursor);
972 event->setAccepted(true);
973 } else {
974 QDeclarativePaintedItem::mouseDoubleClickEvent(event);
975 }
976}
977
978void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
979{
980 Q_D(QDeclarativeTextInput);
981 if(d->focusOnPress){
982 bool hadActiveFocus = hasActiveFocus();
983 forceActiveFocus();
984 if (d->showInputPanelOnFocus) {
985 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
986 // re-open input panel on press if already focused
987 openSoftwareInputPanel();
988 }
989 } else { // show input panel on click
990 if (hasActiveFocus() && !hadActiveFocus) {
991 d->clickCausedFocus = true;
992 }
993 }
994 }
995 bool mark = event->modifiers() & Qt::ShiftModifier;
996 int cursor = d->xToPos(event->pos().x());
997 d->control->moveCursor(cursor, mark);
998 event->setAccepted(true);
999}
1000
1001void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1002{
1003 Q_D(QDeclarativeTextInput);
1004 if (d->selectByMouse) {
1005 d->control->moveCursor(d->xToPos(event->pos().x()), true);
1006 event->setAccepted(true);
1007 } else {
1008 QDeclarativePaintedItem::mouseMoveEvent(event);
1009 }
1010}
1011
1012/*!
1013\overload
1014Handles the given mouse \a event.
1015*/
1016void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1017{
1018 Q_D(QDeclarativeTextInput);
1019 if (!d->showInputPanelOnFocus) { // input panel on click
1020 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1021 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1022 if (view->scene() && view->scene() == scene()) {
1023 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1024 }
1025 }
1026 }
1027 }
1028 d->clickCausedFocus = false;
1029 d->control->processEvent(event);
1030 if (!event->isAccepted())
1031 QDeclarativePaintedItem::mouseReleaseEvent(event);
1032}
1033
1034bool QDeclarativeTextInput::event(QEvent* ev)
1035{
1036 Q_D(QDeclarativeTextInput);
1037 //Anything we don't deal with ourselves, pass to the control
1038 bool handled = false;
1039 switch(ev->type()){
1040 case QEvent::KeyPress:
1041 case QEvent::KeyRelease://###Should the control be doing anything with release?
1042 case QEvent::InputMethod:
1043 case QEvent::GraphicsSceneMousePress:
1044 case QEvent::GraphicsSceneMouseMove:
1045 case QEvent::GraphicsSceneMouseRelease:
1046 case QEvent::GraphicsSceneMouseDoubleClick:
1047 break;
1048 default:
1049 handled = d->control->processEvent(ev);
1050 }
1051 if(!handled)
1052 handled = QDeclarativePaintedItem::event(ev);
1053 return handled;
1054}
1055
1056void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
1057 const QRectF &oldGeometry)
1058{
1059 Q_D(QDeclarativeTextInput);
1060 if (newGeometry.width() != oldGeometry.width()) {
1061 updateSize();
1062 d->updateHorizontalScroll();
1063 }
1064 QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
1065}
1066
1067int QDeclarativeTextInputPrivate::calculateTextWidth()
1068{
1069 return qRound(control->naturalTextWidth());
1070}
1071
1072void QDeclarativeTextInputPrivate::updateHorizontalScroll()
1073{
1074 Q_Q(QDeclarativeTextInput);
1075 int cix = qRound(control->cursorToX());
1076 QRect br(q->boundingRect().toRect());
1077 int widthUsed = calculateTextWidth();
1078 if (autoScroll) {
1079 if (widthUsed <= br.width()) {
1080 // text fits in br; use hscroll for alignment
1081 switch (hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1082 case Qt::AlignRight:
1083 hscroll = widthUsed - br.width() - 1;
1084 break;
1085 case Qt::AlignHCenter:
1086 hscroll = (widthUsed - br.width()) / 2;
1087 break;
1088 default:
1089 // Left
1090 hscroll = 0;
1091 break;
1092 }
1093 } else if (cix - hscroll >= br.width()) {
1094 // text doesn't fit, cursor is to the right of br (scroll right)
1095 hscroll = cix - br.width() + 1;
1096 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1097 // text doesn't fit, cursor is to the left of br (scroll left)
1098 hscroll = cix;
1099 } else if (widthUsed - hscroll < br.width()) {
1100 // text doesn't fit, text document is to the left of br; align
1101 // right
1102 hscroll = widthUsed - br.width() + 1;
1103 }
1104 } else {
1105 if(hAlign == QDeclarativeTextInput::AlignRight){
1106 hscroll = q->width() - widthUsed;
1107 }else if(hAlign == QDeclarativeTextInput::AlignHCenter){
1108 hscroll = (q->width() - widthUsed) / 2;
1109 } else {
1110 hscroll = 0;
1111 }
1112 }
1113}
1114
1115void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r)
1116{
1117 Q_D(QDeclarativeTextInput);
1118 p->setRenderHint(QPainter::TextAntialiasing, true);
1119 p->save();
1120 p->setPen(QPen(d->color));
1121 int flags = QLineControl::DrawText;
1122 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1123 flags |= QLineControl::DrawCursor;
1124 if (d->control->hasSelectedText())
1125 flags |= QLineControl::DrawSelections;
1126 QPoint offset = QPoint(0,0);
1127 QFontMetrics fm = QFontMetrics(d->font);
1128 QRect br(boundingRect().toRect());
1129 if (d->autoScroll) {
1130 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1131 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1132 } else {
1133 offset = QPoint(d->hscroll, 0);
1134 }
1135 d->control->draw(p, offset, r, flags);
1136 p->restore();
1137}
1138
1139/*!
1140\overload
1141Returns the value of the given \a property.
1142*/
1143QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1144{
1145 Q_D(const QDeclarativeTextInput);
1146 switch(property) {
1147 case Qt::ImMicroFocus:
1148 return d->control->cursorRect();
1149 case Qt::ImFont:
1150 return font();
1151 case Qt::ImCursorPosition:
1152 return QVariant(d->control->cursor());
1153 case Qt::ImSurroundingText:
1154 return QVariant(text());
1155 case Qt::ImCurrentSelection:
1156 return QVariant(selectedText());
1157 case Qt::ImMaximumTextLength:
1158 return QVariant(maxLength());
1159 case Qt::ImAnchorPosition:
1160 if (d->control->selectionStart() == d->control->selectionEnd())
1161 return QVariant(d->control->cursor());
1162 else if (d->control->selectionStart() == d->control->cursor())
1163 return QVariant(d->control->selectionEnd());
1164 else
1165 return QVariant(d->control->selectionStart());
1166 default:
1167 return QVariant();
1168 }
1169}
1170
1171/*!
1172 \qmlmethod void TextInput::selectAll()
1173
1174 Causes all text to be selected.
1175*/
1176void QDeclarativeTextInput::selectAll()
1177{
1178 Q_D(QDeclarativeTextInput);
1179 d->control->setSelection(0, d->control->text().length());
1180}
1181
1182#ifndef QT_NO_CLIPBOARD
1183/*!
1184 \qmlmethod TextInput::cut()
1185
1186 Moves the currently selected text to the system clipboard.
1187*/
1188void QDeclarativeTextInput::cut()
1189{
1190 Q_D(QDeclarativeTextInput);
1191 d->control->copy();
1192 d->control->del();
1193}
1194
1195/*!
1196 \qmlmethod TextInput::copy()
1197
1198 Copies the currently selected text to the system clipboard.
1199*/
1200void QDeclarativeTextInput::copy()
1201{
1202 Q_D(QDeclarativeTextInput);
1203 d->control->copy();
1204}
1205
1206/*!
1207 \qmlmethod TextInput::paste()
1208
1209 Replaces the currently selected text by the contents of the system clipboard.
1210*/
1211void QDeclarativeTextInput::paste()
1212{
1213 Q_D(QDeclarativeTextInput);
1214 d->control->paste();
1215}
1216#endif // QT_NO_CLIPBOARD
1217
1218/*!
1219 \qmlmethod void TextInput::selectWord()
1220
1221 Causes the word closest to the current cursor position to be selected.
1222*/
1223void QDeclarativeTextInput::selectWord()
1224{
1225 Q_D(QDeclarativeTextInput);
1226 d->control->selectWordAtPos(d->control->cursor());
1227}
1228
1229/*!
1230 \qmlproperty bool TextInput::smooth
1231
1232 This property holds whether the text is smoothly scaled or transformed.
1233
1234 Smooth filtering gives better visual quality, but is slower. If
1235 the item is displayed at its natural size, this property has no visual or
1236 performance effect.
1237
1238 \note Generally scaling artifacts are only visible if the item is stationary on
1239 the screen. A common pattern when animating an item is to disable smooth
1240 filtering at the beginning of the animation and reenable it at the conclusion.
1241*/
1242
1243/*!
1244 \qmlproperty string TextInput::passwordCharacter
1245
1246 This is the character displayed when echoMode is set to Password or
1247 PasswordEchoOnEdit. By default it is an asterisk.
1248
1249 If this property is set to a string with more than one character,
1250 the first character is used. If the string is empty, the value
1251 is ignored and the property is not set.
1252*/
1253QString QDeclarativeTextInput::passwordCharacter() const
1254{
1255 Q_D(const QDeclarativeTextInput);
1256 return QString(d->control->passwordCharacter());
1257}
1258
1259void QDeclarativeTextInput::setPasswordCharacter(const QString &str)
1260{
1261 Q_D(QDeclarativeTextInput);
1262 if(str.length() < 1)
1263 return;
1264 d->control->setPasswordCharacter(str.constData()[0]);
1265 EchoMode echoMode_ = echoMode();
1266 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1267 updateSize();
1268 }
1269 emit passwordCharacterChanged();
1270}
1271
1272/*!
1273 \qmlproperty string TextInput::displayText
1274
1275 This is the text displayed in the TextInput.
1276
1277 If \l echoMode is set to TextInput::Normal, this holds the
1278 same value as the TextInput::text property. Otherwise,
1279 this property holds the text visible to the user, while
1280 the \l text property holds the actual entered text.
1281*/
1282QString QDeclarativeTextInput::displayText() const
1283{
1284 Q_D(const QDeclarativeTextInput);
1285 return d->control->displayText();
1286}
1287
1288/*!
1289 \qmlproperty bool TextInput::selectByMouse
1290
1291 Defaults to false.
1292
1293 If true, the user can use the mouse to select text in some
1294 platform-specific way. Note that for some platforms this may
1295 not be an appropriate interaction (eg. may conflict with how
1296 the text needs to behave inside a Flickable.
1297*/
1298bool QDeclarativeTextInput::selectByMouse() const
1299{
1300 Q_D(const QDeclarativeTextInput);
1301 return d->selectByMouse;
1302}
1303
1304void QDeclarativeTextInput::setSelectByMouse(bool on)
1305{
1306 Q_D(QDeclarativeTextInput);
1307 if (d->selectByMouse != on) {
1308 d->selectByMouse = on;
1309 emit selectByMouseChanged(on);
1310 }
1311}
1312
1313
1314/*!
1315 \qmlmethod void TextInput::moveCursorSelection(int position)
1316
1317 Moves the cursor to \a position and updates the selection accordingly.
1318 (To only move the cursor, set the \l cursorPosition property.)
1319
1320 When this method is called it additionally sets either the
1321 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1322 to the specified position. This allows you to easily extend and contract the selected
1323 text range.
1324
1325 For example, take this sequence of calls:
1326
1327 \code
1328 cursorPosition = 5
1329 moveCursorSelection(9)
1330 moveCursorSelection(7)
1331 \endcode
1332
1333 This moves the cursor to position 5, extend the selection end from 5 to 9
1334 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1335 selected (the 6th and 7th characters).
1336*/
1337void QDeclarativeTextInput::moveCursorSelection(int position)
1338{
1339 Q_D(QDeclarativeTextInput);
1340 d->control->moveCursor(position, true);
1341 d->updateHorizontalScroll();
1342}
1343
1344/*!
1345 \qmlmethod void TextInput::openSoftwareInputPanel()
1346
1347 Opens software input panels like virtual keyboards for typing, useful for
1348 customizing when you want the input keyboard to be shown and hidden in
1349 your application.
1350
1351 By default the opening of input panels follows the platform style. On Symbian^1 and
1352 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1353 the panels are automatically opened when TextInput element gains active focus. Input panels are
1354 always closed if no editor has active focus.
1355
1356 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1357 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1358 the behavior you want.
1359
1360 Only relevant on platforms, which provide virtual keyboards.
1361
1362 \qml
1363 import QtQuick 1.0
1364 TextInput {
1365 id: textInput
1366 text: "Hello world!"
1367 activeFocusOnPress: false
1368 MouseArea {
1369 anchors.fill: parent
1370 onClicked: {
1371 if (!textInput.activeFocus) {
1372 textInput.forceActiveFocus()
1373 textInput.openSoftwareInputPanel();
1374 } else {
1375 textInput.focus = false;
1376 }
1377 }
1378 onPressAndHold: textInput.closeSoftwareInputPanel();
1379 }
1380 }
1381 \endqml
1382*/
1383void QDeclarativeTextInput::openSoftwareInputPanel()
1384{
1385 QEvent event(QEvent::RequestSoftwareInputPanel);
1386 if (qApp) {
1387 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1388 if (view->scene() && view->scene() == scene()) {
1389 QApplication::sendEvent(view, &event);
1390 }
1391 }
1392 }
1393}
1394
1395/*!
1396 \qmlmethod void TextInput::closeSoftwareInputPanel()
1397
1398 Closes a software input panel like a virtual keyboard shown on the screen, useful
1399 for customizing when you want the input keyboard to be shown and hidden in
1400 your application.
1401
1402 By default the opening of input panels follows the platform style. On Symbian^1 and
1403 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1404 the panels are automatically opened when TextInput element gains active focus. Input panels are
1405 always closed if no editor has active focus.
1406
1407 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1408 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1409 the behavior you want.
1410
1411 Only relevant on platforms, which provide virtual keyboards.
1412
1413 \qml
1414 import QtQuick 1.0
1415 TextInput {
1416 id: textInput
1417 text: "Hello world!"
1418 activeFocusOnPress: false
1419 MouseArea {
1420 anchors.fill: parent
1421 onClicked: {
1422 if (!textInput.activeFocus) {
1423 textInput.forceActiveFocus();
1424 textInput.openSoftwareInputPanel();
1425 } else {
1426 textInput.focus = false;
1427 }
1428 }
1429 onPressAndHold: textInput.closeSoftwareInputPanel();
1430 }
1431 }
1432 \endqml
1433*/
1434void QDeclarativeTextInput::closeSoftwareInputPanel()
1435{
1436 QEvent event(QEvent::CloseSoftwareInputPanel);
1437 if (qApp) {
1438 QEvent event(QEvent::CloseSoftwareInputPanel);
1439 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1440 if (view->scene() && view->scene() == scene()) {
1441 QApplication::sendEvent(view, &event);
1442 }
1443 }
1444 }
1445}
1446
1447void QDeclarativeTextInput::focusInEvent(QFocusEvent *event)
1448{
1449 Q_D(const QDeclarativeTextInput);
1450 if (d->showInputPanelOnFocus) {
1451 if (d->focusOnPress && !isReadOnly()) {
1452 openSoftwareInputPanel();
1453 }
1454 }
1455 QDeclarativePaintedItem::focusInEvent(event);
1456}
1457
1458void QDeclarativeTextInputPrivate::init()
1459{
1460 Q_Q(QDeclarativeTextInput);
1461 control->setCursorWidth(1);
1462 control->setPasswordCharacter(QLatin1Char('*'));
1463 q->setSmooth(smooth);
1464 q->setAcceptedMouseButtons(Qt::LeftButton);
1465 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1466 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1467 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1468 q, SLOT(cursorPosChanged()));
1469 q->connect(control, SIGNAL(selectionChanged()),
1470 q, SLOT(selectionChanged()));
1471 q->connect(control, SIGNAL(textChanged(QString)),
1472 q, SLOT(q_textChanged()));
1473 q->connect(control, SIGNAL(accepted()),
1474 q, SIGNAL(accepted()));
1475 q->connect(control, SIGNAL(updateNeeded(QRect)),
1476 q, SLOT(updateRect(QRect)));
1477 q->updateSize();
1478 oldValidity = control->hasAcceptableInput();
1479 lastSelectionStart = 0;
1480 lastSelectionEnd = 0;
1481 QPalette p = control->palette();
1482 selectedTextColor = p.color(QPalette::HighlightedText);
1483 selectionColor = p.color(QPalette::Highlight);
1484}
1485
1486void QDeclarativeTextInput::cursorPosChanged()
1487{
1488 Q_D(QDeclarativeTextInput);
1489 d->updateHorizontalScroll();
1490 updateRect();//TODO: Only update rect between pos's
1491 updateMicroFocus();
1492 emit cursorPositionChanged();
1493 d->control->resetCursorBlinkTimer();
1494
1495 if(!d->control->hasSelectedText()){
1496 if(d->lastSelectionStart != d->control->cursor()){
1497 d->lastSelectionStart = d->control->cursor();
1498 emit selectionStartChanged();
1499 }
1500 if(d->lastSelectionEnd != d->control->cursor()){
1501 d->lastSelectionEnd = d->control->cursor();
1502 emit selectionEndChanged();
1503 }
1504 }
1505}
1506
1507void QDeclarativeTextInput::selectionChanged()
1508{
1509 Q_D(QDeclarativeTextInput);
1510 updateRect();//TODO: Only update rect in selection
1511 emit selectedTextChanged();
1512
1513 if(d->lastSelectionStart != d->control->selectionStart()){
1514 d->lastSelectionStart = d->control->selectionStart();
1515 if(d->lastSelectionStart == -1)
1516 d->lastSelectionStart = d->control->cursor();
1517 emit selectionStartChanged();
1518 }
1519 if(d->lastSelectionEnd != d->control->selectionEnd()){
1520 d->lastSelectionEnd = d->control->selectionEnd();
1521 if(d->lastSelectionEnd == -1)
1522 d->lastSelectionEnd = d->control->cursor();
1523 emit selectionEndChanged();
1524 }
1525}
1526
1527void QDeclarativeTextInput::q_textChanged()
1528{
1529 Q_D(QDeclarativeTextInput);
1530 updateSize();
1531 d->updateHorizontalScroll();
1532 updateMicroFocus();
1533 emit textChanged();
1534 emit displayTextChanged();
1535 if(hasAcceptableInput() != d->oldValidity){
1536 d->oldValidity = hasAcceptableInput();
1537 emit acceptableInputChanged();
1538 }
1539}
1540
1541void QDeclarativeTextInput::updateRect(const QRect &r)
1542{
1543 Q_D(QDeclarativeTextInput);
1544 if(r == QRect())
1545 clearCache();
1546 else
1547 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1548 update();
1549}
1550
1551QRectF QDeclarativeTextInput::boundingRect() const
1552{
1553 Q_D(const QDeclarativeTextInput);
1554 QRectF r = QDeclarativePaintedItem::boundingRect();
1555
1556 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1557
1558 // Could include font max left/right bearings to either side of rectangle.
1559
1560 r.setRight(r.right() + cursorWidth);
1561 return r;
1562}
1563
1564void QDeclarativeTextInput::updateSize(bool needsRedraw)
1565{
1566 Q_D(QDeclarativeTextInput);
1567 int w = width();
1568 int h = height();
1569 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1570 setImplicitWidth(d->calculateTextWidth());
1571 setContentsSize(QSize(width(), height()));//Repaints if changed
1572 if(w==width() && h==height() && needsRedraw){
1573 clearCache();
1574 update();
1575 }
1576}
1577
1578QT_END_NAMESPACE
1579
1580#endif // QT_NO_LINEEDIT
1581
Note: See TracBrowser for help on using the repository browser.