summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/declarative/whatsnew.qdoc42
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp4
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp48
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp17
-rw-r--r--src/gui/widgets/qlinecontrol.cpp6
-rw-r--r--tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml26
-rw-r--r--tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp117
-rw-r--r--tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp10
9 files changed, 250 insertions, 22 deletions
diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc
index e8c2124..1a8ebd7 100644
--- a/doc/src/declarative/whatsnew.qdoc
+++ b/doc/src/declarative/whatsnew.qdoc
@@ -31,20 +31,33 @@
\section1 Qt 4.7.3 includes QtQuick 1.1
-QtQuick 1.1 is a minor feature update.
+QtQuick 1.1 is a minor feature update. \e {import QtQuick 1.1} to use the new features.
\section2 PinchArea
PinchArea provides support for the common two finger pinch gesture.
+\section2 LayoutMirroring
+
+\l {LayoutMirroring}{Layout mirroring} is useful when you need to support both left-to-right and right-to-left layout versions of your application that target different language areas.
+
+\section2 Anchors
+
+Added the following property:
+\list
+\o \l {Item::}{anchors.mirrored}
+\endlist
+
\section2 Text
Added the following properties:
\list
\o \l {Text::}{lineHeight}
+\o \l {Text::}{lineHeightMode}
\o \l {Text::}{lineCount}
\o \l {Text::}{maximumLineCount}
\o \l {Text::}{truncated}
+\o \l {Text::}{effectiveHorizontalAlignment}
\endlist
horizontalAlignment now accepts Text.AlignJustify alignment mode.
@@ -55,7 +68,11 @@ Added the following properties, methods and signal handlers:
\list
\o \l {TextEdit::}{canPaste}
\o \l {TextEdit::}{lineCount}
+\o \l {TextEdit::}{inputMethodComposing}
+\o \l {TextEdit::}{mouseSelectionMode}
+\o \l {TextEdit::}{effectiveHorizontalAlignment}
\o \l {TextEdit::}{deselect()}
+\o \l {TextEdit::}{isRightToLeft()}
\o \l {TextEdit::}{moveCursorSelection()} to enable selection by word
\o \l {TextEdit::}{onLinkActivated}
\endlist
@@ -64,9 +81,13 @@ Added the following properties, methods and signal handlers:
Added the following properties and methods:
\list
-\o \l{TextInput::}{canPaste}
-\o \l{TextInput::}{deselect()}
-\o \l{TextInput::}{moveCursorSelection()} to enable selection by word
+\o \l {TextInput::}{canPaste}
+\o \l {TextInput::}{inputMethodComposing}
+\o \l {TextInput::}{mouseSelectionMode}
+\o \l {TextInput::}{effectiveHorizontalAlignment}
+\o \l {TextInput::}{deselect()}
+\o \l {TextInput::}{isRightToLeft()}
+\o \l {TextInput::}{moveCursorSelection()} to enable selection by word
\endlist
\section2 Image, BorderImage and AnimatedImage
@@ -92,10 +113,19 @@ Added the following methods:
\o \l{Flickable::}{returnToBounds()}
\endlist
+\section2 MouseArea
+
+Added the following property:
+\list
+\o \l{MouseArea::}{preventStealing}
+\endlist
+
\section2 ListView and GridView
-Added the following methods:
+Added the following properties and methods:
\list
+\o \l{ListView::}{layoutDirection}
+\o \l{ListView::}{effectiveLayoutDirection}
\o \l{ListView::}{positionViewAtBeginning()}
\o \l{ListView::}{positionViewAtEnd()}
\endlist
@@ -105,6 +135,7 @@ Added the following methods:
Added the following properties:
\list
\o \l{Flow::}{layoutDirection}
+\o \l{Flow::}{effectiveLayoutDirection}
\endlist
\section2 Repeater
@@ -135,6 +166,7 @@ properties.
\list
\o Functions can be \l{Binding Properties from JavaScript}{assigned to properties from JavaScript}
to create property bindings.
+\o QtQuick now supports Right to Left layout in positioners, views, anchors and text elements.
\endlist
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index 1b1c476..9cf1e78 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -2317,6 +2317,8 @@ QDeclarativeAnchorLine QDeclarativeItemPrivate::baseline() const
\qmlproperty real Item::anchors.verticalCenterOffset
\qmlproperty real Item::anchors.baselineOffset
+ \qmlproperty bool Item::anchors.mirrored
+
Anchors provide a way to position an item by specifying its
relationship with other items.
@@ -2374,6 +2376,8 @@ QDeclarativeAnchorLine QDeclarativeItemPrivate::baseline() const
To clear an anchor value, set it to \c undefined.
+ \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}.
+
\note You can only anchor an item to siblings or a parent.
For more information see \l {anchor-layout}{Anchor Layouts}.
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index f9f1a48..2c23a1b 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -272,6 +272,22 @@ public:
void regenerate() {
Q_Q(QDeclarativeListView);
if (q->isComponentComplete()) {
+ if (header) {
+ if (q->scene())
+ q->scene()->removeItem(header->item);
+ header->item->deleteLater();
+ delete header;
+ header = 0;
+ }
+ if (footer) {
+ if (q->scene())
+ q->scene()->removeItem(footer->item);
+ footer->item->deleteLater();
+ delete footer;
+ footer = 0;
+ }
+ updateHeader();
+ updateFooter();
clear();
setPosition(0);
q->refill();
@@ -2633,7 +2649,8 @@ qreal QDeclarativeListView::maxYExtent() const
return height();
if (d->maxExtentDirty) {
if (!d->model || !d->model->count()) {
- d->maxExtent = 0;
+ d->maxExtent = d->header ? -d->header->size() : 0;
+ d->maxExtent += height();
} else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
if (d->highlightRangeEnd != d->highlightRangeStart)
@@ -2661,21 +2678,26 @@ qreal QDeclarativeListView::minXExtent() const
qreal highlightStart;
qreal highlightEnd;
- qreal endPositionFirstItem;
+ qreal endPositionFirstItem = 0;
if (d->isRightToLeft()) {
if (d->model && d->model->count())
endPositionFirstItem = d->positionAt(d->model->count()-1);
+ else if (d->header)
+ d->minExtent += d->header->size();
highlightStart = d->highlightRangeStartValid
? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
: d->size() - (d->lastPosition()-endPositionFirstItem);
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
if (d->footer)
d->minExtent += d->footer->size();
+ qreal maxX = maxXExtent();
+ if (d->minExtent < maxX)
+ d->minExtent = maxX;
} else {
endPositionFirstItem = d->endPositionAt(0);
highlightStart = d->highlightRangeStart;
highlightEnd = d->highlightRangeEnd;
- if (d->header)
+ if (d->header && d->visibleItems.count())
d->minExtent += d->header->size();
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
@@ -2696,7 +2718,8 @@ qreal QDeclarativeListView::maxXExtent() const
if (d->maxExtentDirty) {
qreal highlightStart;
qreal highlightEnd;
- qreal lastItemPosition;
+ qreal lastItemPosition = 0;
+ d->maxExtent = 0;
if (d->isRightToLeft()) {
highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
@@ -2708,7 +2731,9 @@ qreal QDeclarativeListView::maxXExtent() const
lastItemPosition = d->positionAt(d->model->count()-1);
}
if (!d->model || !d->model->count()) {
- d->maxExtent = 0;
+ if (!d->isRightToLeft())
+ d->maxExtent = d->header ? -d->header->size() : 0;
+ d->maxExtent += width();
} else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->maxExtent = -(lastItemPosition - highlightStart);
if (highlightEnd != highlightStart) {
@@ -2720,15 +2745,15 @@ qreal QDeclarativeListView::maxXExtent() const
d->maxExtent = -(d->endPosition() - width() + 1);
}
if (d->isRightToLeft()) {
- if (d->header)
+ if (d->header && d->visibleItems.count())
d->maxExtent -= d->header->size();
} else {
if (d->footer)
d->maxExtent -= d->footer->size();
+ qreal minX = minXExtent();
+ if (d->maxExtent > minX)
+ d->maxExtent = minX;
}
- qreal minX = minXExtent();
- if (d->maxExtent > minX)
- d->maxExtent = minX;
d->maxExtentDirty = false;
}
return d->maxExtent;
@@ -2776,6 +2801,11 @@ void QDeclarativeListView::geometryChanged(const QRectF &newGeometry,
Q_D(QDeclarativeListView);
d->maxExtentDirty = true;
d->minExtentDirty = true;
+ if (d->isRightToLeft() && d->orient == Qt::Horizontal) {
+ // maintain position relative to the right edge
+ int dx = newGeometry.width() - oldGeometry.width();
+ setContentX(contentX() - dx);
+ }
QDeclarativeFlickable::geometryChanged(newGeometry, oldGeometry);
}
diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
index babc020..2cb1c94 100644
--- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
@@ -1508,7 +1508,7 @@ bool QDeclarativeTextEdit::canPaste() const
}
/*!
- \qmlproperty bool TextEdit::isInputMethodComposing()
+ \qmlproperty bool TextEdit::inputMethodComposing
\since QtQuick 1.1
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
index 6c26fd3..c6de7a0 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
@@ -1374,7 +1374,10 @@ QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property)
case Qt::ImCursorPosition:
return QVariant(d->control->cursor());
case Qt::ImSurroundingText:
- return QVariant(text());
+ if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
+ return QVariant(displayText());
+ else
+ return QVariant(text());
case Qt::ImCurrentSelection:
return QVariant(selectedText());
case Qt::ImMaximumTextLength:
@@ -1672,8 +1675,8 @@ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode)
finder.setPosition(anchor);
const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
- if (anchor < text.length() && !(reasons & QTextBoundaryFinder::StartWord)
- || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor)) {
+ if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
+ || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
finder.toPreviousBoundary();
}
anchor = finder.position() != -1 ? finder.position() : 0;
@@ -1690,8 +1693,8 @@ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode)
finder.setPosition(anchor);
const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
- if (anchor > 0 && !(reasons & QTextBoundaryFinder::EndWord)
- || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor)) {
+ if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
+ || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
finder.toNextBoundary();
}
anchor = finder.position() != -1 ? finder.position() : text.length();
@@ -1821,7 +1824,7 @@ void QDeclarativeTextInput::focusInEvent(QFocusEvent *event)
}
/*!
- \qmlproperty bool TextInput::isInputMethodComposing()
+ \qmlproperty bool TextInput::inputMethodComposing
\since QtQuick 1.1
@@ -1867,6 +1870,8 @@ void QDeclarativeTextInputPrivate::init()
#endif // QT_NO_CLIPBOARD
q->connect(control, SIGNAL(updateMicroFocus()),
q, SLOT(updateMicroFocus()));
+ q->connect(control, SIGNAL(displayTextChanged(QString)),
+ q, SLOT(updateRect()));
q->updateSize();
oldValidity = control->hasAcceptableInput();
lastSelectionStart = 0;
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index f20e018..3eac64a 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -414,10 +414,14 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
if (isGettingInput) {
// If any text is being input, remove selected text.
priorState = m_undoState;
+ if (echoMode() == QLineEdit::PasswordEchoOnEdit && !passwordEchoEditing()) {
+ updatePasswordEchoEditing(true);
+ m_selstart = 0;
+ m_selend = m_text.length();
+ }
removeSelectedText();
}
-
int c = m_cursor; // cursor position after insertion of commit string
if (event->replacementStart() <= 0)
c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength());
diff --git a/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml b/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml
new file mode 100644
index 0000000..5633831
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.1
+
+ListView {
+ id: view
+ property bool horizontal: false
+ property bool rtl: false
+ width: 240
+ height: 320
+
+ orientation: horizontal ? ListView.Horizontal : ListView.Vertical
+ header: Rectangle {
+ objectName: "header"
+ width: horizontal ? 20 : view.width
+ height: horizontal ? view.height : 20
+ color: "red"
+ }
+ footer: Rectangle {
+ objectName: "footer"
+ width: horizontal ? 30 : view.width
+ height: horizontal ? view.height : 30
+ color: "blue"
+ }
+// model: testModel
+ delegate: Text { width: 30; height: 30; text: index + "(" + x + ")" }
+ layoutDirection: rtl ? Qt.RightToLeft : Qt.LeftToRight
+}
diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
index a699bbe..c87318e 100644
--- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
+++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
@@ -103,6 +103,7 @@ private slots:
void QTBUG_11105();
void header();
void footer();
+ void headerFooter();
void resizeView();
void sizeLessThan1();
void QTBUG_14821();
@@ -1958,6 +1959,112 @@ void tst_QDeclarativeListView::footer()
delete canvas;
}
+class LVAccessor : public QDeclarativeListView
+{
+public:
+ qreal minY() const { return minYExtent(); }
+ qreal maxY() const { return maxYExtent(); }
+ qreal minX() const { return minXExtent(); }
+ qreal maxX() const { return maxXExtent(); }
+};
+
+void tst_QDeclarativeListView::headerFooter()
+{
+ {
+ // Vertical
+ QDeclarativeView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->y(), 0.0);
+
+ QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->y(), 20.0);
+
+ QVERIFY(static_cast<LVAccessor*>(listview)->minY() == 0);
+ QVERIFY(static_cast<LVAccessor*>(listview)->maxY() == 0);
+
+ delete canvas;
+ }
+ {
+ // Horizontal
+ QDeclarativeView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
+ canvas->rootObject()->setProperty("horizontal", true);
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->x(), 0.0);
+
+ QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->x(), 20.0);
+
+ QVERIFY(static_cast<LVAccessor*>(listview)->minX() == 0);
+ QVERIFY(static_cast<LVAccessor*>(listview)->maxX() == 0);
+
+ delete canvas;
+ }
+ {
+ // Horizontal RTL
+ QDeclarativeView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
+ canvas->rootObject()->setProperty("horizontal", true);
+ canvas->rootObject()->setProperty("rtl", true);
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->x(), -20.0);
+
+ QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->x(), -50.0);
+
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240.);
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240.);
+
+ delete canvas;
+ }
+}
+
void tst_QDeclarativeListView::resizeView()
{
QDeclarativeView *canvas = createView();
@@ -2360,6 +2467,7 @@ void tst_QDeclarativeListView::testQtQuick11Attributes_data()
void tst_QDeclarativeListView::rightToLeft()
{
QDeclarativeView *canvas = createView();
+ canvas->setFixedSize(640,320);
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
qApp->processEvents();
@@ -2376,6 +2484,9 @@ void tst_QDeclarativeListView::rightToLeft()
QTRY_VERIFY(model->count() == 3);
QTRY_COMPARE(listview->currentIndex(), 0);
+ // initial position at first item, right edge aligned
+ QCOMPARE(listview->contentX(), -640.);
+
QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1");
QTRY_VERIFY(item);
QTRY_COMPARE(item->x(), -100.0);
@@ -2395,6 +2506,12 @@ void tst_QDeclarativeListView::rightToLeft()
QTRY_VERIFY(text);
QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
+ QCOMPARE(listview->contentX(), -640.);
+
+ // Ensure resizing maintains position relative to right edge
+ qobject_cast<QDeclarativeItem*>(canvas->rootObject())->setWidth(600);
+ QTRY_COMPARE(listview->contentX(), -600.);
+
delete canvas;
}
diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp
index 796ac23..45f38a4 100644
--- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp
+++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp
@@ -1829,13 +1829,23 @@ void tst_qdeclarativetextinput::echoMode()
QCOMPARE(input->inputMethodHints(), ref);
QCOMPARE(input->text(), initial);
QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
QTest::keyPress(canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
QTest::keyRelease(canvas, Qt::Key_A, Qt::NoModifier ,10);
QCOMPARE(input->text(), QLatin1String("a"));
QCOMPARE(input->displayText(), QLatin1String("a"));
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
input->setFocus(false);
QVERIFY(input->hasActiveFocus() == false);
QCOMPARE(input->displayText(), QLatin1String("Q"));
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
+ input->setFocus(true);
+ QInputMethodEvent inputEvent;
+ inputEvent.setCommitString(initial);
+ QApplication::sendEvent(canvas, &inputEvent);
+ QCOMPARE(input->text(), initial);
+ QCOMPARE(input->displayText(), initial);
+ QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
delete canvas;
}