diff options
author | Alexis Menard <alexis.menard@nokia.com> | 2010-04-09 01:00:06 (GMT) |
---|---|---|
committer | Alexis Menard <alexis.menard@nokia.com> | 2010-04-09 01:05:25 (GMT) |
commit | 9615dfeca337c9f40d96485d2dd248eb8cefd563 (patch) | |
tree | c5258d8ca18734973f22f35f1e81b0c0633d8326 | |
parent | 411404e5126936d691d5bb2b77d1754902fab5e0 (diff) | |
download | Qt-9615dfeca337c9f40d96485d2dd248eb8cefd563.zip Qt-9615dfeca337c9f40d96485d2dd248eb8cefd563.tar.gz Qt-9615dfeca337c9f40d96485d2dd248eb8cefd563.tar.bz2 |
Make the TextInput element nicer. It has scrolling.
The TextInput has support for scrolling now so it's quite usable.
You can deactivate the auto scrolling with a property if you want to
do crazy animation while scrolling. This commit also fixed several bugs
with the current implementation especially regarding aligments : selection
was broken, moving the cursor also -> fixed. I have also added a tiny fix when
the TextInput lost the focus -> the selection is cleared.
Task-number:QT-2745
Reviewed-by:Michael Brasser
4 files changed, 121 insertions, 19 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 4b311af..1b8b84b 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -429,6 +429,29 @@ void QDeclarativeTextInput::setFocusOnPress(bool b) } /*! + \qmlproperty bool TextInput::autoScroll + + Whether the TextInput should scroll when the text is longer than the width. By default this is + set to true. +*/ +bool QDeclarativeTextInput::autoScroll() const +{ + Q_D(const QDeclarativeTextInput); + return d->autoScroll; +} + +void QDeclarativeTextInput::setAutoScroll(bool b) +{ + Q_D(QDeclarativeTextInput); + if (d->autoScroll == b) + return; + + d->autoScroll = b; + + emit autoScrollChanged(d->autoScroll); +} + +/*! \qmlproperty Validator TextInput::validator Allows you to set a validator on the TextInput. When a validator is set @@ -645,6 +668,8 @@ void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus) Q_Q(QDeclarativeTextInput); focused = hasFocus; q->setCursorVisible(hasFocus); + if (!hasFocus) + control->deselect(); QDeclarativeItemPrivate::focusChanged(hasFocus); } @@ -679,7 +704,15 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) } setFocus(true); } - d->control->processEvent(event); + bool mark = event->modifiers() & Qt::ShiftModifier; + int cursor = d->xToPos(event->pos().x()); + d->control->moveCursor(cursor, mark); +} + +void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativeTextInput); + d->control->moveCursor(d->xToPos(event->pos().x()), true); } /*! @@ -704,6 +737,7 @@ bool QDeclarativeTextInput::event(QEvent* ev) case QEvent::KeyPress: case QEvent::KeyRelease://###Should the control be doing anything with release? case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: break; default: @@ -733,28 +767,56 @@ void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r) int flags = QLineControl::DrawText; if(!isReadOnly() && d->cursorVisible && !d->cursorItem) flags |= QLineControl::DrawCursor; - if (d->control->hasSelectedText()){ + if (d->control->hasSelectedText()) flags |= QLineControl::DrawSelections; - } - QPoint offset = QPoint(0,0); - if(d->hAlign != AlignLeft){ - QFontMetrics fm = QFontMetrics(d->font); - //###Is this using bearing appropriately? - int minLB = qMax(0, -fm.minLeftBearing()); - int minRB = qMax(0, -fm.minRightBearing()); - int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; - int hOffset = 0; + QFontMetrics fm = QFontMetrics(d->font); + int cix = qRound(d->control->cursorToX()); + QRect br(boundingRect().toRect()); + //###Is this using bearing appropriately? + int minLB = qMax(0, -fm.minLeftBearing()); + int minRB = qMax(0, -fm.minRightBearing()); + int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; + if (d->autoScroll) { + if ((minLB + widthUsed) <= br.width()) { + // text fits in br; use hscroll for alignment + switch (d->hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + case Qt::AlignRight: + d->hscroll = widthUsed - br.width() + 1; + break; + case Qt::AlignHCenter: + d->hscroll = (widthUsed - br.width()) / 2; + break; + default: + // Left + d->hscroll = 0; + break; + } + d->hscroll -= minLB; + } else if (cix - d->hscroll >= br.width()) { + // text doesn't fit, cursor is to the right of br (scroll right) + d->hscroll = cix - br.width() + 1; + } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) { + // text doesn't fit, cursor is to the left of br (scroll left) + d->hscroll = cix; + } else if (widthUsed - d->hscroll < br.width()) { + // text doesn't fit, text document is to the left of br; align + // right + d->hscroll = widthUsed - br.width() + 1; + } + // the y offset is there to keep the baseline constant in case we have script changes in the text. + offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); + } else { if(d->hAlign == AlignRight){ - hOffset = width() - widthUsed; + d->hscroll = width() - widthUsed; }else if(d->hAlign == AlignHCenter){ - hOffset = (width() - widthUsed) / 2; + d->hscroll = (width() - widthUsed) / 2; } - hOffset -= minLB; - offset = QPoint(hOffset, 0); + d->hscroll -= minLB; + offset = QPoint(d->hscroll, 0); } - QRect clipRect = r; - d->control->draw(p, offset, clipRect, flags); + + d->control->draw(p, offset, r, flags); p->restore(); } @@ -892,10 +954,11 @@ void QDeclarativeTextInput::q_textChanged() void QDeclarativeTextInput::updateRect(const QRect &r) { + Q_D(QDeclarativeTextInput); if(r == QRect()) clearCache(); else - dirtyCache(r); + dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height())); update(); } diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 64aff7d..6e61580 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -86,6 +86,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextInput : public QDeclarativePaintedIte Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged) Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged) Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY focusOnPressChanged) + Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) public: QDeclarativeTextInput(QDeclarativeItem* parent=0); @@ -163,6 +164,9 @@ public: bool focusOnPress() const; void setFocusOnPress(bool); + bool autoScroll() const; + void setAutoScroll(bool); + bool hasAcceptableInput() const; void drawContents(QPainter *p,const QRect &r); @@ -189,12 +193,14 @@ Q_SIGNALS: void inputMaskChanged(const QString &inputMask); void echoModeChanged(EchoMode echoMode); void focusOnPressChanged(bool focusOnPress); + void autoScrollChanged(bool autoScroll); protected: virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void keyPressEvent(QKeyEvent* ev); bool event(QEvent *e); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 9e44b15..26cf78c 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -72,7 +72,7 @@ public: color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), - cursorVisible(false) + cursorVisible(false), autoScroll(true) { } @@ -81,6 +81,14 @@ public: delete control; } + int xToPos(int x, QTextLine::CursorPosition betweenOrOn = QTextLine::CursorBetweenCharacters) const + { + Q_Q(const QDeclarativeTextInput); + QRect cr = q->boundingRect().toRect(); + x-= cr.x() - hscroll; + return control->xToPos(x, betweenOrOn); + } + void init(); void startCreatingCursor(); void focusChanged(bool hasFocus); @@ -107,6 +115,7 @@ public: bool focused; bool focusOnPress; bool cursorVisible; + bool autoScroll; }; QT_END_NAMESPACE diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 2b0b151..dd74c09 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -73,6 +73,7 @@ private slots: void sendRequestSoftwareInputPanelEvent(); void setHAlignClearCache(); + void focusOutClearSelection(); private: void simulateKey(QDeclarativeView *, int key); @@ -725,6 +726,29 @@ void tst_qdeclarativetextinput::setHAlignClearCache() QCOMPARE(input.nbPaint, 2); } +void tst_qdeclarativetextinput::focusOutClearSelection() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + QDeclarativeTextInput input; + QDeclarativeTextInput input2; + input.setText(QLatin1String("Hello world")); + input.setFocus(true); + scene.addItem(&input2); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + input.setSelectionStart(2); + input.setSelectionEnd(5); + //The selection should work + QTRY_COMPARE(input.selectedText(), QLatin1String("llo")); + input2.setFocus(true); + QApplication::processEvents(); + //The input lost the focus selection should be cleared + QTRY_COMPARE(input.selectedText(), QLatin1String("")); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" |