aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquicktextedit.cpp97
-rw-r--r--src/quick/items/qquicktextedit_p_p.h3
-rw-r--r--tests/auto/quick/qquicktextedit/data/mouseselection_align_bl.qml14
-rw-r--r--tests/auto/quick/qquicktextedit/data/mouseselection_align_center.qml14
-rw-r--r--tests/auto/quick/qquicktextedit/data/mouseselection_align_tr.qml14
-rw-r--r--tests/auto/quick/qquicktextedit/data/positionAt.qml1
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp67
7 files changed, 139 insertions, 71 deletions
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index df13075801..38a510eb9e 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -782,7 +782,7 @@ QRectF QQuickTextEdit::positionToRectangle(int pos) const
Q_D(const QQuickTextEdit);
QTextCursor c(d->document);
c.setPosition(pos);
- return d->control->cursorRect(c).translated(0, d->yoff);
+ return d->control->cursorRect(c).translated(d->xoff, d->yoff);
}
@@ -797,7 +797,10 @@ QRectF QQuickTextEdit::positionToRectangle(int pos) const
int QQuickTextEdit::positionAt(qreal x, qreal y) const
{
Q_D(const QQuickTextEdit);
- int r = d->document->documentLayout()->hitTest(QPointF(x,y-d->yoff), Qt::FuzzyHit);
+ x -= d->xoff;
+ y -= d->yoff;
+
+ int r = d->document->documentLayout()->hitTest(QPointF(x, y), Qt::FuzzyHit);
QTextCursor cursor = d->control->textCursor();
if (r > cursor.position()) {
// The cursor position includes positions within the preedit text, but only positions in the
@@ -808,7 +811,7 @@ int QQuickTextEdit::positionAt(qreal x, qreal y) const
? layout->preeditAreaText().length()
: 0;
if (preeditLength > 0
- && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) {
+ && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x, y)) {
r = r > cursor.position() + preeditLength
? r - preeditLength
: cursor.position();
@@ -1324,14 +1327,14 @@ bool QQuickTextEdit::isReadOnly() const
QRectF QQuickTextEdit::cursorRectangle() const
{
Q_D(const QQuickTextEdit);
- return d->control->cursorRect().translated(0, d->yoff);
+ return d->control->cursorRect().translated(d->xoff, d->yoff);
}
bool QQuickTextEdit::event(QEvent *event)
{
Q_D(QQuickTextEdit);
if (event->type() == QEvent::ShortcutOverride) {
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
return event->isAccepted();
}
return QQuickImplicitSizeItem::event(event);
@@ -1344,7 +1347,7 @@ Handles the given key \a event.
void QQuickTextEdit::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::keyPressEvent(event);
}
@@ -1356,7 +1359,7 @@ Handles the given key \a event.
void QQuickTextEdit::keyReleaseEvent(QKeyEvent *event)
{
Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::keyReleaseEvent(event);
}
@@ -1508,7 +1511,7 @@ Handles the given mouse \a event.
void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (d->focusOnPress){
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
@@ -1527,7 +1530,7 @@ Handles the given mouse \a event.
void QQuickTextEdit::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::mouseReleaseEvent(event);
@@ -1540,7 +1543,7 @@ Handles the given mouse \a event.
void QQuickTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
}
@@ -1552,7 +1555,7 @@ Handles the given mouse \a event.
void QQuickTextEdit::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickTextEdit);
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::mouseMoveEvent(event);
}
@@ -1565,7 +1568,7 @@ void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
{
Q_D(QQuickTextEdit);
const bool wasComposing = isInputMethodComposing();
- d->control->processEvent(event, QPointF(0, -d->yoff));
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
setCursorVisible(d->control->cursorVisible());
if (wasComposing != isInputMethodComposing())
emit inputMethodComposingChanged();
@@ -1577,7 +1580,7 @@ void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
if (change == ItemActiveFocusHasChanged) {
setCursorVisible(value.boolValue);
QFocusEvent focusEvent(value.boolValue ? QEvent::FocusIn : QEvent::FocusOut);
- d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
+ d->control->processEvent(&focusEvent, QPointF(-d->xoff, -d->yoff));
if (value.boolValue) {
q_updateAlignment();
connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
@@ -1651,9 +1654,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
node->deleteContent();
node->setMatrix(QMatrix4x4());
- QRectF bounds = boundingRect();
-
- node->addTextDocument(QPointF(0, bounds.y()), d->document, d->color, QQuickText::Normal, QColor(),
+ node->addTextDocument(QPointF(d->xoff, d->yoff), d->document, d->color, QQuickText::Normal, QColor(),
QColor(), d->selectionColor, d->selectedTextColor, selectionStart(),
selectionEnd() - 1); // selectionEnd() returns first char after
// selection
@@ -1810,7 +1811,6 @@ void QQuickTextEdit::q_textChanged()
void QQuickTextEdit::moveCursorDelegate()
{
Q_D(QQuickTextEdit);
- d->determineHorizontalAlignment();
updateInputMethod();
emit cursorRectangleChanged();
if (!d->cursorItem)
@@ -1836,7 +1836,12 @@ void QQuickTextEdit::updateSelectionMarkers()
QRectF QQuickTextEdit::boundingRect() const
{
Q_D(const QQuickTextEdit);
- QRectF r(0, -d->yoff, d->contentSize.width(), d->contentSize.height());
+ QRectF r(
+ QQuickTextUtil::alignedX(d->contentSize.width(), width(), effectiveHAlign()),
+ d->yoff,
+ d->contentSize.width(),
+ d->contentSize.height());
+
int cursorWidth = 1;
if (d->cursorItem)
cursorWidth = 0;
@@ -1844,34 +1849,8 @@ QRectF QQuickTextEdit::boundingRect() const
cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
// Could include font max left/right bearings to either side of rectangle.
-
r.setRight(r.right() + cursorWidth);
- qreal h = height();
- switch (d->vAlign) {
- case AlignTop:
- break;
- case AlignBottom:
- r.moveTop(h - r.height());
- break;
- case AlignVCenter:
- r.moveTop((h - r.height()) / 2);
- break;
- }
-
- qreal w = width();
- switch (d->hAlign) {
- case AlignLeft:
- case AlignJustify:
- break;
- case AlignRight:
- r.moveLeft(w - r.width());
- break;
- case AlignHCenter:
- r.moveLeft((w - r.width()) / 2);
- break;
- }
-
return r;
}
@@ -1935,34 +1914,17 @@ void QQuickTextEdit::updateSize()
} else {
d->document->setTextWidth(-1);
}
- QFontMetricsF fm(d->font);
- qreal dy = height();
- dy -= d->document->size().height();
-
- qreal nyoff;
- if (heightValid()) {
- if (d->vAlign == AlignBottom)
- nyoff = dy;
- else if (d->vAlign == AlignVCenter)
- nyoff = dy/2;
- else
- nyoff = 0;
- } else {
- nyoff = 0;
- }
- if (nyoff != d->yoff)
- d->yoff = nyoff;
- setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
- //### need to comfirm cost of always setting these
+ //### need to confirm cost of always setting these
qreal newWidth = d->document->idealWidth();
- if (!widthValid() && d->document->textWidth() != newWidth)
- d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
+ if ((!widthValid() || d->wrapMode == NoWrap) && d->document->textWidth() != newWidth)
+ d->document->setTextWidth(newWidth); // ### Text does not align if width is not set or the idealWidth exceeds the textWidth (QTextDoc bug)
// ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
qreal iWidth = -1;
if (!widthValid() && !d->requireImplicitWidth)
iWidth = newWidth;
+ QFontMetricsF fm(d->font);
qreal newHeight = d->document->isEmpty() ? qCeil(fm.height()) : d->document->size().height();
if (iWidth > -1)
@@ -1970,6 +1932,10 @@ void QQuickTextEdit::updateSize()
else
setImplicitHeight(newHeight);
+ d->xoff = QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign());
+ d->yoff = QQuickTextUtil::alignedY(d->document->size().height(), height(), d->vAlign);
+ setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
+
QSizeF size(newWidth, newHeight);
if (d->contentSize != size) {
d->contentSize = size;
@@ -2006,6 +1972,7 @@ void QQuickTextEdit::q_updateAlignment()
Q_D(QQuickTextEdit);
if (d->determineHorizontalAlignment()) {
d->updateDefaultTextOption();
+ d->xoff = QQuickTextUtil::alignedX(d->document->size().width(), width(), effectiveHAlign());
moveCursorDelegate();
}
}
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index f412aac7ec..c02e34c166 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -72,7 +72,7 @@ public:
QQuickTextEditPrivate()
: color(QRgb(0xFF000000)), selectionColor(QRgb(0xFF000080)), selectedTextColor(QRgb(0xFFFFFFFF))
- , textMargin(0.0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
+ , textMargin(0.0), xoff(0), yoff(0), font(sourceFont), cursorComponent(0), cursorItem(0), document(0), control(0)
, lastSelectionStart(0), lastSelectionEnd(0), lineCount(0)
, hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop)
, format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap)
@@ -109,6 +109,7 @@ public:
QSizeF contentSize;
qreal textMargin;
+ qreal xoff;
qreal yoff;
QString text;
diff --git a/tests/auto/quick/qquicktextedit/data/mouseselection_align_bl.qml b/tests/auto/quick/qquicktextedit/data/mouseselection_align_bl.qml
new file mode 100644
index 0000000000..4387cbcfc6
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/mouseselection_align_bl.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+TextEdit {
+ focus: true
+ text:
+"0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ
+9876543210
+
+ZXYWVUTSRQPON MLKJIHGFEDCBA"
+ width: implicitWidth - 10
+ selectByMouse: true
+ horizontalAlignment: TextEdit.AlignLeft
+ verticalAlignment: TextEdit.AlignBottom
+}
diff --git a/tests/auto/quick/qquicktextedit/data/mouseselection_align_center.qml b/tests/auto/quick/qquicktextedit/data/mouseselection_align_center.qml
new file mode 100644
index 0000000000..e8ee14cdf0
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/mouseselection_align_center.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+TextEdit {
+ focus: true
+ text:
+"0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ
+9876543210
+
+ZXYWVUTSRQPON MLKJIHGFEDCBA"
+ width: implicitWidth - 10
+ selectByMouse: true
+ horizontalAlignment: TextEdit.AlignHCenter
+ verticalAlignment: TextEdit.AlignVCenter
+}
diff --git a/tests/auto/quick/qquicktextedit/data/mouseselection_align_tr.qml b/tests/auto/quick/qquicktextedit/data/mouseselection_align_tr.qml
new file mode 100644
index 0000000000..a69bd8d9b9
--- /dev/null
+++ b/tests/auto/quick/qquicktextedit/data/mouseselection_align_tr.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+TextEdit {
+ focus: true
+ text:
+"0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ
+9876543210
+
+ZXYWVUTSRQPON MLKJIHGFEDCBA"
+ width: implicitWidth - 10
+ selectByMouse: true
+ horizontalAlignment: TextEdit.AlignRight
+ verticalAlignment: TextEdit.AlignTop
+}
diff --git a/tests/auto/quick/qquicktextedit/data/positionAt.qml b/tests/auto/quick/qquicktextedit/data/positionAt.qml
index 19093281fe..af0950c9ba 100644
--- a/tests/auto/quick/qquicktextedit/data/positionAt.qml
+++ b/tests/auto/quick/qquicktextedit/data/positionAt.qml
@@ -5,5 +5,6 @@ TextEdit {
objectName: "myInput"
width: 50
height: 25
+ font.pixelSize: 12
text: "This is\n a long piece of text"
}
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 562f24edd6..ffff922e52 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -134,6 +134,7 @@ private slots:
void dragMouseSelection();
void inputMethodHints();
+ void positionAt_data();
void positionAt();
void linkActivated();
@@ -217,6 +218,8 @@ Q_DECLARE_METATYPE(IntList)
typedef QList<Key> KeyList;
Q_DECLARE_METATYPE(KeyList)
+Q_DECLARE_METATYPE(QQuickTextEdit::HAlignment)
+Q_DECLARE_METATYPE(QQuickTextEdit::VAlignment)
Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
@@ -1789,6 +1792,10 @@ void tst_qquicktextedit::mouseSelection_data()
QTest::newRow("on triple click (40,50)") << testFile("mouseselection_true.qml") << 40 << 50 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
QTest::newRow("on triple click (50,25)") << testFile("mouseselection_true.qml") << 50 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
QTest::newRow("on triple click (50,40)") << testFile("mouseselection_true.qml") << 50 << 40 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+
+ QTest::newRow("on tr align") << testFile("mouseselection_align_tr.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on center align") << testFile("mouseselection_align_center.qml") << 4 << 9 << "45678" << true << true << 1;
+ QTest::newRow("on bl align") << testFile("mouseselection_align_bl.qml") << 4 << 9 << "45678" << true << true << 1;
}
void tst_qquicktextedit::mouseSelection()
@@ -1943,8 +1950,26 @@ void tst_qquicktextedit::inputMethodHints()
QCOMPARE(plainTextEdit.inputMethodHints(), Qt::ImhNone);
}
+void tst_qquicktextedit::positionAt_data()
+{
+ QTest::addColumn<QQuickTextEdit::HAlignment>("horizontalAlignment");
+ QTest::addColumn<QQuickTextEdit::VAlignment>("verticalAlignment");
+
+ QTest::newRow("top-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignTop;
+ QTest::newRow("bottom-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignBottom;
+ QTest::newRow("center-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignVCenter;
+
+ QTest::newRow("top-right") << QQuickTextEdit::AlignRight << QQuickTextEdit::AlignTop;
+ QTest::newRow("top-center") << QQuickTextEdit::AlignHCenter << QQuickTextEdit::AlignTop;
+
+ QTest::newRow("center") << QQuickTextEdit::AlignHCenter << QQuickTextEdit::AlignVCenter;
+}
+
void tst_qquicktextedit::positionAt()
{
+ QFETCH(QQuickTextEdit::HAlignment, horizontalAlignment);
+ QFETCH(QQuickTextEdit::VAlignment, verticalAlignment);
+
QQuickView canvas(testFileUrl("positionAt.qml"));
QVERIFY(canvas.rootObject() != 0);
canvas.show();
@@ -1953,8 +1978,10 @@ void tst_qquicktextedit::positionAt()
QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
QVERIFY(texteditObject != 0);
+ texteditObject->setHAlign(horizontalAlignment);
+ texteditObject->setVAlign(verticalAlignment);
- QTextLayout layout(texteditObject->text());
+ QTextLayout layout(texteditObject->text().replace(QLatin1Char('\n'), QChar::LineSeparator));
layout.setFont(texteditObject->font());
if (!qmlDisableDistanceField()) {
@@ -1965,15 +1992,45 @@ void tst_qquicktextedit::positionAt()
layout.beginLayout();
QTextLine line = layout.createLine();
+ line.setLineWidth(texteditObject->width());
+ QTextLine secondLine = layout.createLine();
+ secondLine.setLineWidth(texteditObject->width());
layout.endLayout();
- const int y0 = line.height() / 2;
- const int y1 = line.height() * 3 / 2;
+ qreal y0;
+ qreal y1;
+
+ switch (verticalAlignment) {
+ case QQuickTextEdit::AlignTop:
+ y0 = line.height() / 2;
+ y1 = line.height() * 3 / 2;
+ break;
+ case QQuickTextEdit::AlignVCenter:
+ y0 = (texteditObject->height() - line.height()) / 2;
+ y1 = (texteditObject->height() + line.height()) / 2;
+ break;
+ case QQuickTextEdit::AlignBottom:
+ y0 = texteditObject->height() - line.height() * 3 / 2;
+ y1 = texteditObject->height() - line.height() / 2;
+ break;
+ }
+ qreal xoff;
+ switch (horizontalAlignment) {
+ case QQuickTextEdit::AlignLeft:
+ xoff = 0;
+ break;
+ case QQuickTextEdit::AlignHCenter:
+ xoff = (texteditObject->width() - secondLine.naturalTextWidth()) / 2;
+ break;
+ case QQuickTextEdit::AlignRight:
+ xoff = texteditObject->width() - secondLine.naturalTextWidth();
+ break;
+ }
int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
- int widthBegin = floor(line.cursorToX(pos - 1));
- int widthEnd = ceil(line.cursorToX(pos + 1));
+ int widthBegin = floor(xoff + line.cursorToX(pos - 1));
+ int widthEnd = ceil(xoff + line.cursorToX(pos + 1));
QVERIFY(widthBegin <= texteditObject->width() / 2);
QVERIFY(widthEnd >= texteditObject->width() / 2);