From 7bc98d7bd7aabc6086e5cd27a167769d7aa71d83 Mon Sep 17 00:00:00 2001 From: jasplin Date: Fri, 3 Jul 2009 15:40:20 +0200 Subject: Improved the support for input methods in Graphics View. This patch improves the graphics view support for input methods in several ways: * A new ItemAcceptsInputMethod flag is introduced to serve the same purpose for graphics items as WA_InputMethodEnabled does for widgets: Input method support can be controlled individually for each item. * The input method sensitivity of a view (i.e. the value of the WA_InputMethodEnabled flag) is updated dynamically whenever the input method support of the current focus item may change. * Input contexts are reset whenever an item that supports input methods loses focus. Reviewed-by: janarve Task-number: 254492 --- .../tst_qgraphicsproxywidget.cpp | 46 +++++++- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 58 ++++++++++ tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 118 +++++++++++++++++++++ 3 files changed, 220 insertions(+), 2 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 0b1d5cf9d2..dbc433914d 100644 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -178,6 +178,7 @@ private slots: void windowFlags_data(); void windowFlags(); void comboboxWindowFlags(); + void inputMethod(); }; // Subclass that exposes the protected functions. @@ -1572,7 +1573,7 @@ void tst_QGraphicsProxyWidget::resize_simple() QGraphicsProxyWidget proxy; QWidget *widget = new QWidget; - widget->setGeometry(0, 0, size.width(), size.height()); + widget->setGeometry(0, 0, (int)size.width(), (int)size.height()); proxy.setWidget(widget); widget->show(); QCOMPARE(widget->pos(), QPoint()); @@ -3217,10 +3218,51 @@ void tst_QGraphicsProxyWidget::comboboxWindowFlags() QVERIFY((static_cast(popupProxy)->windowFlags() & Qt::Popup) == Qt::Popup); } +class InputMethod_LineEdit : public QLineEdit +{ + bool event(QEvent *e) + { + if (e->type() == QEvent::InputMethod) + ++inputMethodEvents; + return QLineEdit::event(e); + } +public: + int inputMethodEvents; +}; + +void tst_QGraphicsProxyWidget::inputMethod() +{ + QGraphicsScene scene; + + // check that the proxy is initialized with the correct input method sensitivity + for (int i = 0; i < 2; ++i) + { + QLineEdit *lineEdit = new QLineEdit; + lineEdit->setAttribute(Qt::WA_InputMethodEnabled, !!i); + QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit); + QCOMPARE(!!(proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod), !!i); + } + + // check that input method events are only forwarded to widgets with focus + for (int i = 0; i < 2; ++i) + { + InputMethod_LineEdit *lineEdit = new InputMethod_LineEdit; + lineEdit->setAttribute(Qt::WA_InputMethodEnabled, true); + QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit); + + if (i) + lineEdit->setFocus(); + + lineEdit->inputMethodEvents = 0; + QInputMethodEvent event; + qApp->sendEvent(proxy, &event); + QCOMPARE(lineEdit->inputMethodEvents, i); + } +} + QTEST_MAIN(tst_QGraphicsProxyWidget) #include "tst_qgraphicsproxywidget.moc" #else // QT_NO_STYLE_CLEANLOOKS QTEST_NOOP_MAIN #endif - diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 4247cca3eb..d325f0f5d3 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -252,6 +252,8 @@ private slots: void stickyFocus_data(); void stickyFocus(); void sendEvent(); + void inputMethod_data(); + void inputMethod(); // task specific tests below me void task139710_bspTreeCrash(); @@ -3614,5 +3616,61 @@ void tst_QGraphicsScene::sendEvent() QCOMPARE(spy->count(), 1); } +void tst_QGraphicsScene::inputMethod_data() +{ + QTest::addColumn("flags"); + QTest::addColumn("callFocusItem"); + QTest::newRow("0") << 0 << false; + QTest::newRow("1") << (int)QGraphicsItem::ItemAcceptsInputMethod << false; + QTest::newRow("2") << (int)QGraphicsItem::ItemIsFocusable << false; + QTest::newRow("3") << + (int)(QGraphicsItem::ItemAcceptsInputMethod|QGraphicsItem::ItemIsFocusable) << true; +} + +class InputMethodTester : public QGraphicsRectItem +{ + void inputMethodEvent(QInputMethodEvent *) { ++eventCalls; } + QVariant inputMethodQuery(Qt::InputMethodQuery) const { ++queryCalls; return QVariant(); } +public: + int eventCalls; + mutable int queryCalls; +}; + +void tst_QGraphicsScene::inputMethod() +{ + QFETCH(int, flags); + QFETCH(bool, callFocusItem); + + InputMethodTester *item = new InputMethodTester; + item->setFlags((QGraphicsItem::GraphicsItemFlags)flags); + + QGraphicsScene scene; + scene.addItem(item); + QInputMethodEvent event; + + scene.setFocusItem(item); + QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item); + + item->eventCalls = 0; + qApp->sendEvent(&scene, &event); + QCOMPARE(item->eventCalls, callFocusItem ? 1 : 0); + + item->queryCalls = 0; + scene.inputMethodQuery((Qt::InputMethodQuery)0); + QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); + + scene.setFocusItem(0); + QCOMPARE(item->eventCalls, callFocusItem ? 2 : 0); // verify correct delivery of "reset" event + QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected + + item->eventCalls = 0; + qApp->sendEvent(&scene, &event); + QCOMPARE(item->eventCalls, 0); + + item->queryCalls = 0; + scene.inputMethodQuery((Qt::InputMethodQuery)0); + QCOMPARE(item->queryCalls, 0); +} + QTEST_MAIN(tst_QGraphicsScene) #include "tst_qgraphicsscene.moc" diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index d24e43712d..8b4ca4c65e 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -63,6 +63,7 @@ #include #include #include +#include //TESTED_CLASS= //TESTED_FILES= @@ -195,6 +196,8 @@ private slots: void mouseTracking2(); void render(); void exposeRegion(); + void inputMethodSensitivity(); + void inputContextReset(); // task specific tests below me void task172231_untransformableItems(); @@ -3357,6 +3360,121 @@ void tst_QGraphicsView::exposeRegion() QCOMPARE(item->paints, 0); } +void tst_QGraphicsView::inputMethodSensitivity() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + + QGraphicsRectItem *item = new QGraphicsRectItem; + + view.setAttribute(Qt::WA_InputMethodEnabled, true); + + scene.addItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + scene.removeItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + item->setFlag(QGraphicsItem::ItemAcceptsInputMethod); + scene.addItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + scene.removeItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + scene.addItem(item); + scene.setFocusItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + scene.removeItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + item->setFlag(QGraphicsItem::ItemIsFocusable); + scene.addItem(item); + scene.setFocusItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + + item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + + // introduce another item that is focusable but does not accept input methods + QGraphicsRectItem *item2 = new QGraphicsRectItem; + item2->setFlag(QGraphicsItem::ItemIsFocusable); + scene.addItem(item2); + scene.setFocusItem(item2); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + scene.setFocusItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + + view.setScene(0); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + view.setScene(&scene); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); + + scene.setFocusItem(item2); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + view.setScene(0); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + scene.setFocusItem(item); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false); + + view.setScene(&scene); + QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true); +} + +class InputContextTester : public QInputContext +{ + QString identifierName() { return QString(); } + bool isComposing() const { return false; } + QString language() { return QString(); } + void reset() { ++resets; } +public: + int resets; +}; + +void tst_QGraphicsView::inputContextReset() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + + InputContextTester inputContext; + view.setInputContext(&inputContext); + + QGraphicsItem *item1 = new QGraphicsRectItem; + item1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod); + + inputContext.resets = 0; + scene.addItem(item1); + QCOMPARE(inputContext.resets, 0); + + inputContext.resets = 0; + scene.setFocusItem(item1); + QCOMPARE(inputContext.resets, 0); + + inputContext.resets = 0; + scene.setFocusItem(0); + QCOMPARE(inputContext.resets, 1); + + // introduce another item that is focusable but does not accept input methods + QGraphicsItem *item2 = new QGraphicsRectItem; + item1->setFlags(QGraphicsItem::ItemIsFocusable); + + inputContext.resets = 0; + scene.setFocusItem(item2); + QCOMPARE(inputContext.resets, 0); + + inputContext.resets = 0; + scene.setFocusItem(item1); + QCOMPARE(inputContext.resets, 0); +} + void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged() { QGraphicsView view; -- cgit v1.2.3