summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexis Menard <alexis.menard@nokia.com>2010-04-09 01:00:06 (GMT)
committerAlexis Menard <alexis.menard@nokia.com>2010-04-09 01:05:25 (GMT)
commit9615dfeca337c9f40d96485d2dd248eb8cefd563 (patch)
treec5258d8ca18734973f22f35f1e81b0c0633d8326
parent411404e5126936d691d5bb2b77d1754902fab5e0 (diff)
downloadQt-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
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp99
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p.h6
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p_p.h11
-rw-r--r--tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp24
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"