summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/declarative/focus.qdoc2
-rw-r--r--src/declarative/graphicsitems/qmlgraphicsitem.cpp74
-rw-r--r--tests/auto/declarative/declarative.pro1
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/data/keys.qml15
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro7
-rw-r--r--tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp237
6 files changed, 334 insertions, 2 deletions
diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc
index ec6a02f..6eca667 100644
--- a/doc/src/declarative/focus.qdoc
+++ b/doc/src/declarative/focus.qdoc
@@ -75,6 +75,8 @@ Item {
\endlist
+See also the \l {Keys}{Keys attached property} and {KeyNavigation}{KeyNavigation attached property}.
+
\section1 Querying the Active Focus Item
Whether or not an \l Item has \e {active focus} can be queried through the
diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
index 77e6db8..a46c2be 100644
--- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp
@@ -389,6 +389,76 @@ void QmlGraphicsItemKeyFilter::componentComplete()
if (m_next) m_next->componentComplete();
}
+
+/*!
+ \qmlclass KeyNavigation
+ \brief The KeyNavigation attached property supports key navigation by arrow keys.
+
+ It is common in key-based UIs to use arrow keys to navigate
+ between focussed items. The KeyNavigation property provides a
+ convenient way of specifying which item will gain focus
+ when an arrow key is pressed. The following example provides
+ key navigation for a 2x2 grid of items.
+
+ \code
+ Grid {
+ columns: 2
+ width: 100; height: 100
+ Rectangle {
+ id: item1
+ focus: true
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.right: item2
+ KeyNavigation.down: item3
+ }
+ Rectangle {
+ id: item2
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.left: item1
+ KeyNavigation.down: item4
+ }
+ Rectangle {
+ id: item3
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.right: item4
+ KeyNavigation.up: item1
+ }
+ Rectangle {
+ id: item4
+ width: 50; height: 50
+ color: focus ? "red" : "lightgray"
+ KeyNavigation.left: item3
+ KeyNavigation.up: item2
+ }
+ }
+ \endcode
+
+ KeyNavigation receives key events after the item it is attached to.
+ If the item accepts an arrow key event, the KeyNavigation
+ attached property will not receive an event for that key.
+
+ If an item has been set for a direction and the KeyNavigation
+ attached property receives the corresponding
+ key press and release events, the events will be accepted by
+ KeyNaviagtion and will not propagate any further.
+
+ \sa {Keys}{Keys attached property}
+*/
+
+/*!
+ \qmlproperty Item KeyNavigation::left
+ \qmlproperty Item KeyNavigation::right
+ \qmlproperty Item KeyNavigation::up
+ \qmlproperty Item KeyNavigation::down
+
+ These properties hold the item to assign focus to
+ when Key_Left, Key_Right, Key_Up or Key_Down are
+ pressed.
+*/
+
class QmlGraphicsKeyNavigationAttachedPrivate : public QObjectPrivate
{
public:
@@ -606,7 +676,7 @@ void QmlGraphicsKeyNavigationAttached::keyReleased(QKeyEvent *event)
See \l {Qt::Key}{Qt.Key} for the list of keyboard codes.
- \sa KeyEvent
+ \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
*/
/*!
@@ -1119,7 +1189,7 @@ void QmlGraphicsKeysAttached::keyPressed(QKeyEvent *event)
// If we specifically handle a key then default to accepted
ke.setAccepted(true);
int idx = QmlGraphicsKeysAttached::staticMetaObject.indexOfSignal(keySignal);
- metaObject()->method(idx).invoke(this, Q_ARG(QmlGraphicsKeysAttached, &ke));
+ metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QmlGraphicsKeyEvent*, &ke));
}
}
if (!ke.isAccepted())
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
index 02d5a55..472fd93 100644
--- a/tests/auto/declarative/declarative.pro
+++ b/tests/auto/declarative/declarative.pro
@@ -20,6 +20,7 @@ SUBDIRS += \
qmldom \ # Cover
qmlecmascript \ # Cover
qmlfontloader \ # Cover
+ qmlgraphicsitem \ # Cover
qmlgraphicsborderimage \ # Cover
qmlgraphicsparticles \ # Cover
qmlgraphicstext \ # Cover
diff --git a/tests/auto/declarative/qmlgraphicsitem/data/keys.qml b/tests/auto/declarative/qmlgraphicsitem/data/keys.qml
new file mode 100644
index 0000000..7c16559
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/data/keys.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+Item {
+ focus: true
+ Keys.onPressed: keysTestObject.keyPress(event.key, event.text, event.modifiers)
+ Keys.onReleased: { keysTestObject.keyRelease(event.key, event.text, event.modifiers); event.accepted = true; }
+ Keys.onReturnPressed: keysTestObject.keyPress(event.key, "Return", event.modifiers)
+ Keys.forwardTo: [ item2 ]
+
+ Item {
+ id: item2
+ Keys.onPressed: keysTestObject.forwardedKey(event.key)
+ Keys.onReleased: keysTestObject.forwardedKey(event.key)
+ }
+}
diff --git a/tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro b/tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro
new file mode 100644
index 0000000..ddabf9a
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/qmlgraphicsitem.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qmlgraphicsitem.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp b/tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp
new file mode 100644
index 0000000..b3b5374
--- /dev/null
+++ b/tests/auto/declarative/qmlgraphicsitem/tst_qmlgraphicsitem.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlview.h>
+#include <qmlgraphicsitem.h>
+
+class tst_QmlGraphicsItem : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_QmlGraphicsItem();
+
+private slots:
+ void keys();
+ void keyNavigation();
+
+private:
+ template<typename T>
+ T *findItem(QmlGraphicsItem *parent, const QString &objectName);
+};
+
+class KeysTestObject : public QObject
+{
+ Q_OBJECT
+public:
+ KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0) {}
+
+ void reset() {
+ mKey = 0;
+ mText = QString();
+ mModifiers = 0;
+ mForwardedKey = 0;
+ }
+
+public slots:
+ void keyPress(int key, QString text, int modifiers) {
+ mKey = key;
+ mText = text;
+ mModifiers = modifiers;
+ }
+ void keyRelease(int key, QString text, int modifiers) {
+ mKey = key;
+ mText = text;
+ mModifiers = modifiers;
+ }
+ void forwardedKey(int key) {
+ mForwardedKey = key;
+ }
+
+public:
+ int mKey;
+ QString mText;
+ int mModifiers;
+ int mForwardedKey;
+
+private:
+};
+
+
+tst_QmlGraphicsItem::tst_QmlGraphicsItem()
+{
+}
+
+void tst_QmlGraphicsItem::keys()
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ canvas->setUrl(QUrl("file://" SRCDIR "/data/keys.qml"));
+
+ KeysTestObject *testObject = new KeysTestObject;
+ canvas->rootContext()->setContextProperty("keysTestObject", testObject);
+
+ canvas->execute();
+ canvas->show();
+ qApp->processEvents();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(!key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
+ QCOMPARE(testObject->mText, QLatin1String("A"));
+ QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
+ QVERIFY(key.isAccepted());
+
+ testObject->reset();
+
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QCOMPARE(testObject->mKey, int(Qt::Key_Return));
+ QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
+ QCOMPARE(testObject->mText, QLatin1String("Return"));
+ QVERIFY(testObject->mModifiers == Qt::NoModifier);
+ QVERIFY(key.isAccepted());
+
+ delete canvas;
+ delete testObject;
+}
+
+void tst_QmlGraphicsItem::keyNavigation()
+{
+ QmlView *canvas = new QmlView(0);
+ canvas->setFixedSize(240,320);
+
+ canvas->setUrl(QUrl("file://" SRCDIR "/data/keynavigation.qml"));
+ canvas->execute();
+ canvas->show();
+ qApp->processEvents();
+
+ QEvent wa(QEvent::WindowActivate);
+ QApplication::sendEvent(canvas, &wa);
+ QFocusEvent fe(QEvent::FocusIn);
+ QApplication::sendEvent(canvas, &fe);
+
+ QmlGraphicsItem *item = findItem<QmlGraphicsItem>(canvas->root(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // right
+ QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item2");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // down
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item4");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // left
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item3");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+
+ // up
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
+ QApplication::sendEvent(canvas, &key);
+ QVERIFY(key.isAccepted());
+
+ item = findItem<QmlGraphicsItem>(canvas->root(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasFocus());
+}
+
+template<typename T>
+T *tst_QmlGraphicsItem::findItem(QmlGraphicsItem *parent, const QString &objectName)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ //qDebug() << parent->QGraphicsObject::children().count() << "children";
+ for (int i = 0; i < parent->QGraphicsObject::children().count(); ++i) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem*>(parent->QGraphicsObject::children().at(i));
+ if(!item)
+ continue;
+ //qDebug() << "try" << item;
+ if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+ return static_cast<T*>(item);
+ item = findItem<T>(item, objectName);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+
+
+QTEST_MAIN(tst_QmlGraphicsItem)
+
+#include "tst_qmlgraphicsitem.moc"