tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 #include <QtGui>
       
    45 #include "../../shared/util.h"
       
    46 #include <private/qlayoutengine_p.h>    // qSmartMin functions...
       
    47 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
    48 #include <QMacStyle>
       
    49 #endif
       
    50 #ifdef Q_WS_X11
       
    51 #include <private/qt_x11_p.h>
       
    52 #endif
       
    53 
       
    54 static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton)
       
    55 {
       
    56     QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0);
       
    57     QApplication::sendEvent(widget, &event);
       
    58 }
       
    59 
       
    60 
       
    61 #ifndef QT_NO_STYLE_CLEANLOOKS
       
    62 /*
       
    63     Notes:
       
    64 
       
    65     1) The proxy and the widget geometries are linked.
       
    66        proxy resize => widget resize => stop (no livelock)
       
    67        widget resize => proxy resize => stop (no livelock)
       
    68 
       
    69     2) As far as possible, the properties are linked.
       
    70        proxy enable => widget enable => stop
       
    71        widget disabled => proxy disabled => stop
       
    72 
       
    73     3) Windowed state is linked
       
    74        Windowed proxy state => windowed widget state => stop
       
    75        Windowed widget state => windowed proxy state => stop
       
    76 */
       
    77 
       
    78 class EventSpy : public QObject
       
    79 {
       
    80 public:
       
    81     EventSpy(QObject *receiver)
       
    82     {
       
    83         receiver->installEventFilter(this);
       
    84     }
       
    85 
       
    86     QMap<QEvent::Type, int> counts;
       
    87 
       
    88 protected:
       
    89     bool eventFilter(QObject *, QEvent *event)
       
    90     {
       
    91         ++counts[event->type()];
       
    92         return false;
       
    93     }
       
    94 };
       
    95 
       
    96 class tst_QGraphicsProxyWidget : public QObject
       
    97 {
       
    98     Q_OBJECT
       
    99 
       
   100 public slots:
       
   101     void initTestCase();
       
   102     void cleanupTestCase();
       
   103     void init();
       
   104     void cleanup();
       
   105 
       
   106 private slots:
       
   107     void qgraphicsproxywidget_data();
       
   108     void qgraphicsproxywidget();
       
   109     void paint();
       
   110     void paint_2();
       
   111     void setWidget_data();
       
   112     void setWidget();
       
   113     void eventFilter_data();
       
   114     void eventFilter();
       
   115     void focusInEvent_data();
       
   116     void focusInEvent();
       
   117     void focusInEventNoWidget();
       
   118     void focusNextPrevChild_data();
       
   119     void focusNextPrevChild();
       
   120     void focusOutEvent_data();
       
   121     void focusOutEvent();
       
   122     void hoverEnterLeaveEvent_data();
       
   123     void hoverEnterLeaveEvent();
       
   124     void hoverMoveEvent_data();
       
   125     void hoverMoveEvent();
       
   126     void keyPressEvent_data();
       
   127     void keyPressEvent();
       
   128     void keyReleaseEvent_data();
       
   129     void keyReleaseEvent();
       
   130     void mouseDoubleClickEvent_data();
       
   131     void mouseDoubleClickEvent();
       
   132     void mousePressReleaseEvent_data();
       
   133     void mousePressReleaseEvent();
       
   134     void resizeEvent_data();
       
   135     void resizeEvent();
       
   136     void paintEvent();
       
   137     void wheelEvent();
       
   138     void sizeHint_data();
       
   139     void sizeHint();
       
   140     void sizePolicy();
       
   141     void minimumSize();
       
   142     void maximumSize();
       
   143     void scrollUpdate();
       
   144     void setWidget_simple();
       
   145     void setWidget_ownership();
       
   146     void resize_simple_data();
       
   147     void resize_simple();
       
   148     void symmetricMove();
       
   149     void symmetricResize();
       
   150     void symmetricEnabled();
       
   151     void symmetricVisible();
       
   152     void tabFocus_simpleWidget();
       
   153     void tabFocus_simpleTwoWidgets();
       
   154     void tabFocus_complexWidget();
       
   155     void tabFocus_complexTwoWidgets();
       
   156     void setFocus_simpleWidget();
       
   157     void setFocus_simpleTwoWidgets();
       
   158     void setFocus_complexTwoWidgets();
       
   159     void popup_basic();
       
   160     void popup_subwidget();
       
   161     void changingCursor_basic();
       
   162     void tooltip_basic();
       
   163     void childPos_data();
       
   164     void childPos();
       
   165     void autoShow();
       
   166     void windowOpacity();
       
   167     void stylePropagation();
       
   168     void palettePropagation();
       
   169     void fontPropagation();
       
   170     void dontCrashWhenDie();
       
   171     void createProxyForChildWidget();
       
   172     void actionsContextMenu();
       
   173     void actionsContextMenu_data();
       
   174     void deleteProxyForChildWidget();
       
   175     void bypassGraphicsProxyWidget_data();
       
   176     void bypassGraphicsProxyWidget();
       
   177     void dragDrop();
       
   178     void windowFlags_data();
       
   179     void windowFlags();
       
   180     void comboboxWindowFlags();
       
   181     void updateAndDelete();
       
   182     void inputMethod();
       
   183     void clickFocus();
       
   184 };
       
   185 
       
   186 // Subclass that exposes the protected functions.
       
   187 class SubQGraphicsProxyWidget : public QGraphicsProxyWidget
       
   188 {
       
   189 
       
   190 public:
       
   191     SubQGraphicsProxyWidget(QGraphicsItem *parent = 0) : QGraphicsProxyWidget(parent),
       
   192     paintCount(0), keyPress(0), focusOut(0)
       
   193         {}
       
   194 
       
   195     bool call_eventFilter(QObject* object, QEvent* event)
       
   196         { return SubQGraphicsProxyWidget::eventFilter(object, event); }
       
   197 
       
   198     void call_focusInEvent(QFocusEvent* event)
       
   199         { return SubQGraphicsProxyWidget::focusInEvent(event); }
       
   200 
       
   201     bool call_focusNextPrevChild(bool next)
       
   202         { return SubQGraphicsProxyWidget::focusNextPrevChild(next); }
       
   203 
       
   204     void call_focusOutEvent(QFocusEvent* event)
       
   205         { return SubQGraphicsProxyWidget::focusOutEvent(event); }
       
   206 
       
   207     void call_hideEvent(QHideEvent* event)
       
   208         { return SubQGraphicsProxyWidget::hideEvent(event); }
       
   209 
       
   210     void call_hoverEnterEvent(QGraphicsSceneHoverEvent* event)
       
   211         { return SubQGraphicsProxyWidget::hoverEnterEvent(event); }
       
   212 
       
   213     void call_hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
       
   214         { return SubQGraphicsProxyWidget::hoverLeaveEvent(event); }
       
   215 
       
   216     void call_hoverMoveEvent(QGraphicsSceneHoverEvent* event)
       
   217         { return SubQGraphicsProxyWidget::hoverMoveEvent(event); }
       
   218 
       
   219     void call_keyPressEvent(QKeyEvent* event)
       
   220         { return SubQGraphicsProxyWidget::keyPressEvent(event); }
       
   221 
       
   222     void call_keyReleaseEvent(QKeyEvent* event)
       
   223         { return SubQGraphicsProxyWidget::keyReleaseEvent(event); }
       
   224 
       
   225     void call_mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
       
   226         { return SubQGraphicsProxyWidget::mouseDoubleClickEvent(event); }
       
   227 
       
   228     void call_mouseMoveEvent(QGraphicsSceneMouseEvent* event)
       
   229         { return SubQGraphicsProxyWidget::mouseMoveEvent(event); }
       
   230 
       
   231     void call_mousePressEvent(QGraphicsSceneMouseEvent* event)
       
   232         { return SubQGraphicsProxyWidget::mousePressEvent(event); }
       
   233 
       
   234     void call_mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
       
   235         { return SubQGraphicsProxyWidget::mouseReleaseEvent(event); }
       
   236 
       
   237     void call_resizeEvent(QGraphicsSceneResizeEvent* event)
       
   238         { return SubQGraphicsProxyWidget::resizeEvent(event); }
       
   239 
       
   240     QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
       
   241         { return SubQGraphicsProxyWidget::sizeHint(which, constraint); }
       
   242 
       
   243     void call_showEvent(QShowEvent* event)
       
   244         { return SubQGraphicsProxyWidget::showEvent(event); }
       
   245 
       
   246     void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)    {
       
   247         paintCount++;
       
   248         QGraphicsProxyWidget::paint(painter, option, widget);
       
   249     }
       
   250 
       
   251     void focusOutEvent(QFocusEvent *event)
       
   252     {
       
   253         focusOut++;
       
   254         QGraphicsProxyWidget::focusOutEvent(event);
       
   255     }
       
   256 
       
   257     bool eventFilter(QObject *object, QEvent *event) {
       
   258         if (event->type() == QEvent::KeyPress && object == widget())
       
   259             keyPress++;
       
   260         return QGraphicsProxyWidget::eventFilter(object, event);
       
   261     }
       
   262     int paintCount;
       
   263     int keyPress;
       
   264     int focusOut;
       
   265 };
       
   266 
       
   267 class WheelWidget : public QWidget
       
   268 {
       
   269 public:
       
   270     WheelWidget() : wheelEventCalled(false) { setFocusPolicy(Qt::WheelFocus); }
       
   271 
       
   272     virtual void wheelEvent(QWheelEvent *event) { event->accept(); wheelEventCalled = true; }
       
   273 
       
   274     bool wheelEventCalled;
       
   275 };
       
   276 
       
   277 // This will be called before the first test function is executed.
       
   278 // It is only called once.
       
   279 void tst_QGraphicsProxyWidget::initTestCase()
       
   280 {
       
   281 #ifdef Q_OS_WINCE //disable magic for WindowsCE
       
   282     qApp->setAutoMaximizeThreshold(-1);
       
   283 #endif
       
   284 }
       
   285 
       
   286 // This will be called after the last test function is executed.
       
   287 // It is only called once.
       
   288 void tst_QGraphicsProxyWidget::cleanupTestCase()
       
   289 {
       
   290 }
       
   291 
       
   292 // This will be called before each test function is executed.
       
   293 void tst_QGraphicsProxyWidget::init()
       
   294 {
       
   295 }
       
   296 
       
   297 // This will be called after every test function.
       
   298 void tst_QGraphicsProxyWidget::cleanup()
       
   299 {
       
   300 }
       
   301 
       
   302 void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data()
       
   303 {
       
   304 }
       
   305 
       
   306 void tst_QGraphicsProxyWidget::qgraphicsproxywidget()
       
   307 {
       
   308     SubQGraphicsProxyWidget proxy;
       
   309     proxy.paint(0, 0, 0);
       
   310     proxy.setWidget(0);
       
   311     QVERIFY(proxy.type() == QGraphicsProxyWidget::Type);
       
   312     QVERIFY(!proxy.widget());
       
   313     QEvent event(QEvent::None);
       
   314     proxy.call_eventFilter(0, &event);
       
   315     QFocusEvent focusEvent(QEvent::FocusIn);
       
   316     focusEvent.ignore();
       
   317     proxy.call_focusInEvent(&focusEvent);
       
   318     QCOMPARE(focusEvent.isAccepted(), false);
       
   319     QCOMPARE(proxy.call_focusNextPrevChild(false), false);
       
   320     QCOMPARE(proxy.call_focusNextPrevChild(true), false);
       
   321     proxy.call_focusOutEvent(&focusEvent);
       
   322     QHideEvent hideEvent;
       
   323     proxy.call_hideEvent(&hideEvent);
       
   324     QGraphicsSceneHoverEvent hoverEvent;
       
   325     proxy.call_hoverEnterEvent(&hoverEvent);
       
   326     proxy.call_hoverLeaveEvent(&hoverEvent);
       
   327     proxy.call_hoverMoveEvent(&hoverEvent);
       
   328     QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier);
       
   329     proxy.call_keyPressEvent(&keyEvent);
       
   330     proxy.call_keyReleaseEvent(&keyEvent);
       
   331     QGraphicsSceneMouseEvent mouseEvent;
       
   332     proxy.call_mouseDoubleClickEvent(&mouseEvent);
       
   333     proxy.call_mouseMoveEvent(&mouseEvent);
       
   334     proxy.call_mousePressEvent(&mouseEvent);
       
   335     proxy.call_mouseReleaseEvent(&mouseEvent);
       
   336     QGraphicsSceneResizeEvent resizeEvent;
       
   337     proxy.call_resizeEvent(&resizeEvent);
       
   338     QShowEvent showEvent;
       
   339     proxy.call_showEvent(&showEvent);
       
   340     proxy.call_sizeHint(Qt::PreferredSize, QSizeF());
       
   341 }
       
   342 
       
   343 // public void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget)
       
   344 void tst_QGraphicsProxyWidget::paint()
       
   345 {
       
   346     SubQGraphicsProxyWidget proxy;
       
   347     proxy.paint(0, 0, 0);
       
   348 }
       
   349 
       
   350 class MyProxyWidget : public QGraphicsProxyWidget
       
   351 {
       
   352 public:
       
   353     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
       
   354     {
       
   355         // Make sure QGraphicsProxyWidget::paint does not modify the render hints set on the painter.
       
   356         painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
       
   357                                 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
       
   358         const QPainter::RenderHints oldRenderHints = painter->renderHints();
       
   359         QGraphicsProxyWidget::paint(painter, option, widget);
       
   360         QCOMPARE(painter->renderHints(), oldRenderHints);
       
   361     }
       
   362 };
       
   363 
       
   364 void tst_QGraphicsProxyWidget::paint_2()
       
   365 {
       
   366     MyProxyWidget *proxyWidget = new MyProxyWidget;
       
   367     proxyWidget->setWidget(new QLineEdit);
       
   368 
       
   369     QGraphicsScene scene;
       
   370     scene.addItem(proxyWidget);
       
   371     scene.setSceneRect(scene.itemsBoundingRect());
       
   372 
       
   373     // Trigger repaint.
       
   374     QPixmap pixmap(scene.sceneRect().toRect().size());
       
   375     QPainter painter(&pixmap);
       
   376     scene.render(&painter);
       
   377 }
       
   378 
       
   379 void tst_QGraphicsProxyWidget::setWidget_data()
       
   380 {
       
   381     QTest::addColumn<bool>("widgetExists");
       
   382     QTest::addColumn<bool>("insertWidget");
       
   383     QTest::addColumn<bool>("hasParent");
       
   384     QTest::addColumn<bool>("proxyHasParent");
       
   385 
       
   386     QTest::newRow("setWidget(0)") << false << false << false << false;
       
   387     QTest::newRow("setWidget(widget)") << false << true << false << false;
       
   388     QTest::newRow("setWidget(widgetWParent)") << false << true << true << false;
       
   389     QTest::newRow("setWidget(1), setWidget(0)") << true << false << false << false;
       
   390     QTest::newRow("setWidget(1), setWidget(widget)") << true << true << false << false;
       
   391     QTest::newRow("setWidget(1), setWidget(widgetWParent)") << true << true << true << false;
       
   392     QTest::newRow("p setWidget(0)") << false << false << false << true;
       
   393     QTest::newRow("p setWidget(widget)") << false << true << false << true;
       
   394     QTest::newRow("p setWidget(widgetWParent)") << false << true << true << true;
       
   395     QTest::newRow("p setWidget(1), setWidget(0)") << true << false << false << true;
       
   396     QTest::newRow("p setWidget(1), setWidget(widget)") << true << true << false << true;
       
   397     QTest::newRow("p setWidget(1), setWidget(widgetWParent)") << true << true << true << true;
       
   398 }
       
   399 
       
   400 // public void setWidget(QWidget* widget)
       
   401 void tst_QGraphicsProxyWidget::setWidget()
       
   402 {
       
   403     QFETCH(bool, widgetExists);
       
   404     QFETCH(bool, insertWidget);
       
   405     QFETCH(bool, hasParent);
       
   406     QFETCH(bool, proxyHasParent);
       
   407 
       
   408     QGraphicsScene scene;
       
   409     QGraphicsView view(&scene);
       
   410     view.show();
       
   411 #ifdef Q_WS_X11
       
   412     qt_x11_wait_for_window_manager(&view);
       
   413 #endif
       
   414     QPointer<SubQGraphicsProxyWidget> proxy = new SubQGraphicsProxyWidget;
       
   415     SubQGraphicsProxyWidget parentProxy;
       
   416     scene.addItem(proxy);
       
   417     scene.addItem(&parentProxy);
       
   418     if (proxyHasParent)
       
   419         proxy->setParent(&parentProxy);
       
   420     QPointer<QWidget> existingSubWidget = new QWidget;
       
   421     proxy->setVisible(false);
       
   422     proxy->setEnabled(false);
       
   423 
       
   424     if (widgetExists) {
       
   425         existingSubWidget->setAttribute(Qt::WA_QuitOnClose, true);
       
   426         proxy->setWidget(existingSubWidget);
       
   427     }
       
   428 
       
   429     QWidget *widget = new QWidget;
       
   430 #ifndef QT_NO_CURSOR
       
   431     widget->setCursor(Qt::IBeamCursor);
       
   432 #endif
       
   433     widget->setPalette(QPalette(Qt::magenta));
       
   434     widget->setLayoutDirection(Qt::RightToLeft);
       
   435     QCleanlooksStyle cleanlooksStyle;
       
   436     widget->setStyle(&cleanlooksStyle);
       
   437     widget->setFont(QFont("Times"));
       
   438     widget->setVisible(true);
       
   439     QApplication::setActiveWindow(widget);
       
   440     widget->activateWindow();
       
   441     widget->setEnabled(true);
       
   442     widget->resize(325, 241);
       
   443     widget->setMinimumSize(100, 200);
       
   444     widget->setMaximumSize(1000, 2000);
       
   445     widget->setFocusPolicy(Qt::TabFocus);
       
   446     widget->setContentsMargins(10, 29, 19, 81);
       
   447     widget->setFocus(Qt::TabFocusReason);
       
   448     widget->setAcceptDrops(true);
       
   449     QTRY_VERIFY(widget->hasFocus());
       
   450     QVERIFY(widget->isActiveWindow());
       
   451 
       
   452     QWidget parentWidget;
       
   453     if (hasParent)
       
   454         widget->setParent(&parentWidget);
       
   455 
       
   456     QWidget *subWidget = insertWidget ? widget : 0;
       
   457     bool shouldBeInsertable = !hasParent && subWidget;
       
   458     if (shouldBeInsertable)
       
   459         subWidget->setAttribute(Qt::WA_QuitOnClose, true);
       
   460 
       
   461     proxy->setWidget(subWidget);
       
   462 
       
   463     if (shouldBeInsertable) {
       
   464         QCOMPARE(proxy->widget(), subWidget);
       
   465         QVERIFY(subWidget->testAttribute(Qt::WA_DontShowOnScreen));
       
   466         QVERIFY(!subWidget->testAttribute(Qt::WA_QuitOnClose));
       
   467         QCOMPARE(proxy->acceptHoverEvents(), true);
       
   468 #ifndef QT_NO_CURSOR
       
   469         QVERIFY(proxy->hasCursor());
       
   470 
       
   471         // These should match
       
   472         QCOMPARE(proxy->cursor().shape(), widget->cursor().shape());
       
   473 #endif
       
   474         //###QCOMPARE(proxy->palette(), widget->palette());
       
   475         QCOMPARE(proxy->layoutDirection(), widget->layoutDirection());
       
   476         QCOMPARE(proxy->style(), widget->style());
       
   477         QCOMPARE(proxy->isVisible(), widget->isVisible());
       
   478         QCOMPARE(proxy->isEnabled(), widget->isEnabled());
       
   479         QVERIFY(proxy->flags() & QGraphicsItem::ItemIsFocusable);
       
   480         QCOMPARE(proxy->effectiveSizeHint(Qt::MinimumSize).toSize(),
       
   481             qSmartMinSize(widget));
       
   482         QCOMPARE(proxy->minimumSize().toSize(),
       
   483                  qSmartMinSize(widget) );
       
   484         QCOMPARE(proxy->maximumSize().toSize(), QSize(1000, 2000));
       
   485         QCOMPARE(proxy->effectiveSizeHint(Qt::PreferredSize).toSize(),
       
   486                 qSmartMinSize(widget));
       
   487         QCOMPARE(proxy->size().toSize(), widget->size());
       
   488         QCOMPARE(proxy->rect().toRect(), widget->rect());
       
   489         QCOMPARE(proxy->focusPolicy(), Qt::WheelFocus);
       
   490         QVERIFY(proxy->acceptDrops());
       
   491         QCOMPARE(proxy->acceptsHoverEvents(), true); // to get widget enter events
       
   492         int left, top, right, bottom;
       
   493         widget->getContentsMargins(&left, &top, &right, &bottom);
       
   494         qreal rleft, rtop, rright, rbottom;
       
   495         proxy->getContentsMargins(&rleft, &rtop, &rright, &rbottom);
       
   496         QCOMPARE((qreal)left, rleft);
       
   497         QCOMPARE((qreal)top, rtop);
       
   498         QCOMPARE((qreal)right, rright);
       
   499         QCOMPARE((qreal)bottom, rbottom);
       
   500     } else {
       
   501         // proxy shouldn't mess with the widget if it can't insert it.
       
   502         QCOMPARE(proxy->widget(), (QWidget*)0);
       
   503         QCOMPARE(proxy->acceptHoverEvents(), false);
       
   504         if (subWidget) {
       
   505             QVERIFY(!subWidget->testAttribute(Qt::WA_DontShowOnScreen));
       
   506             QVERIFY(subWidget->testAttribute(Qt::WA_QuitOnClose));
       
   507             // reset
       
   508             subWidget->setAttribute(Qt::WA_QuitOnClose, false);
       
   509         }
       
   510     }
       
   511 
       
   512     if (widgetExists) {
       
   513         QCOMPARE(existingSubWidget->parent(), static_cast<QObject*>(0));
       
   514         QVERIFY(!existingSubWidget->testAttribute(Qt::WA_DontShowOnScreen));
       
   515         QVERIFY(!existingSubWidget->testAttribute(Qt::WA_QuitOnClose));
       
   516     }
       
   517 
       
   518     if (hasParent)
       
   519         widget->setParent(0);
       
   520 
       
   521     delete widget;
       
   522     if (shouldBeInsertable)
       
   523         QVERIFY(!proxy);
       
   524     delete existingSubWidget;
       
   525     if (!shouldBeInsertable) {
       
   526         QVERIFY(proxy);
       
   527         delete proxy;
       
   528     }
       
   529     QVERIFY(!proxy);
       
   530 }
       
   531 
       
   532 Q_DECLARE_METATYPE(QEvent::Type)
       
   533 void tst_QGraphicsProxyWidget::eventFilter_data()
       
   534 {
       
   535     QTest::addColumn<QEvent::Type>("eventType");
       
   536     QTest::addColumn<bool>("fromObject"); // big grin evil
       
   537     QTest::newRow("none") << QEvent::None << false;
       
   538     for (int i = 0; i < 2; ++i) {
       
   539         bool fromObject = (i == 0);
       
   540         QTest::newRow(QString("resize %1").arg(fromObject).toLatin1()) << QEvent::Resize << fromObject;
       
   541         QTest::newRow(QString("move %1").arg(fromObject).toLatin1()) << QEvent::Move << fromObject;
       
   542         QTest::newRow(QString("hide %1").arg(fromObject).toLatin1()) << QEvent::Hide << fromObject;
       
   543         QTest::newRow(QString("show %1").arg(fromObject).toLatin1()) << QEvent::Show << fromObject;
       
   544         QTest::newRow(QString("enabled %1").arg(fromObject).toLatin1()) << QEvent::EnabledChange << fromObject;
       
   545         QTest::newRow(QString("focusIn %1").arg(fromObject).toLatin1()) << QEvent::FocusIn << fromObject;
       
   546         QTest::newRow(QString("focusOut %1").arg(fromObject).toLatin1()) << QEvent::FocusOut << fromObject;
       
   547         QTest::newRow(QString("keyPress %1").arg(fromObject).toLatin1()) << QEvent::KeyPress << fromObject;
       
   548     }
       
   549 }
       
   550 
       
   551 // protected bool eventFilter(QObject* object, QEvent* event)
       
   552 void tst_QGraphicsProxyWidget::eventFilter()
       
   553 {
       
   554     QFETCH(QEvent::Type, eventType);
       
   555     QFETCH(bool, fromObject);
       
   556 
       
   557     QGraphicsScene scene;
       
   558     QEvent windowActivate(QEvent::WindowActivate);
       
   559     qApp->sendEvent(&scene, &windowActivate);
       
   560 
       
   561     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
   562     scene.addItem(proxy);
       
   563 
       
   564     QWidget *widget = new QWidget(0, Qt::FramelessWindowHint);
       
   565     widget->setFocusPolicy(Qt::TabFocus);
       
   566     widget->resize(10, 10);
       
   567     widget->show();
       
   568     proxy->setWidget(widget);
       
   569     proxy->show();
       
   570 
       
   571     // mirror whatever is happening to the widget
       
   572     // don't get in a loop
       
   573     switch (eventType) {
       
   574     case QEvent::None: {
       
   575         QEvent event(QEvent::None);
       
   576         proxy->call_eventFilter(widget, &event);
       
   577         break;
       
   578                        }
       
   579     case QEvent::Resize: {
       
   580         QSize oldSize = widget->size();
       
   581         QSize newSize = QSize(100, 100);
       
   582         if (fromObject) {
       
   583             widget->resize(newSize);
       
   584         } else {
       
   585             proxy->resize(newSize);
       
   586         }
       
   587         QCOMPARE(proxy->size().toSize(), newSize);
       
   588         QCOMPARE(widget->size(), newSize);
       
   589         break;
       
   590                          }
       
   591     case QEvent::Move: {
       
   592         QPoint oldPoint = widget->pos();
       
   593         QPoint newPoint = QPoint(100, 100);
       
   594         if (fromObject) {
       
   595             widget->move(newPoint);
       
   596         } else {
       
   597             proxy->setPos(newPoint);
       
   598         }
       
   599         QCOMPARE(proxy->pos().toPoint(), newPoint);
       
   600         QCOMPARE(widget->pos(), newPoint);
       
   601         break;
       
   602                          }
       
   603     case QEvent::Hide: {
       
   604         // A hide event can only come from a widget
       
   605         if (fromObject) {
       
   606             widget->setFocus(Qt::TabFocusReason);
       
   607             widget->hide();
       
   608         } else {
       
   609             QHideEvent event;
       
   610             proxy->call_eventFilter(widget, &event);
       
   611         }
       
   612         QCOMPARE(proxy->isVisible(), false);
       
   613         break;
       
   614                          }
       
   615     case QEvent::Show: {
       
   616         // A show event can either come from a widget or somewhere else
       
   617         widget->hide();
       
   618         if (fromObject) {
       
   619             widget->show();
       
   620         } else {
       
   621             QShowEvent event;
       
   622             proxy->call_eventFilter(widget, &event);
       
   623         }
       
   624         QCOMPARE(proxy->isVisible(), true);
       
   625         break;
       
   626                          }
       
   627     case QEvent::EnabledChange: {
       
   628         widget->setEnabled(false);
       
   629         proxy->setEnabled(false);
       
   630         if (fromObject) {
       
   631             widget->setEnabled(true);
       
   632             QCOMPARE(proxy->isEnabled(), true);
       
   633             widget->setEnabled(false);
       
   634             QCOMPARE(proxy->isEnabled(), false);
       
   635         } else {
       
   636             QEvent event(QEvent::EnabledChange);
       
   637             proxy->call_eventFilter(widget, &event);
       
   638             // match the widget not the event
       
   639             QCOMPARE(proxy->isEnabled(), false);
       
   640         }
       
   641         break;
       
   642                          }
       
   643     case QEvent::FocusIn: {
       
   644         if (fromObject) {
       
   645             widget->setFocus(Qt::TabFocusReason);
       
   646             QVERIFY(proxy->hasFocus());
       
   647         }
       
   648         break;
       
   649                          }
       
   650     case QEvent::FocusOut: {
       
   651         widget->setFocus(Qt::TabFocusReason);
       
   652         QVERIFY(proxy->hasFocus());
       
   653         QVERIFY(widget->hasFocus());
       
   654         if (fromObject) {
       
   655             widget->clearFocus();
       
   656             QVERIFY(!proxy->hasFocus());
       
   657         }
       
   658         break;
       
   659                          }
       
   660     case QEvent::KeyPress: {
       
   661         if (fromObject) {
       
   662             QTest::keyPress(widget, Qt::Key_A, Qt::NoModifier);
       
   663         } else {
       
   664             QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
       
   665             proxy->call_eventFilter(widget, &event);
       
   666         }
       
   667         QCOMPARE(proxy->keyPress, 1);
       
   668         break;
       
   669                          }
       
   670     default:
       
   671         break;
       
   672     }
       
   673 }
       
   674 
       
   675 void tst_QGraphicsProxyWidget::focusInEvent_data()
       
   676 {
       
   677     QTest::addColumn<bool>("widgetHasFocus");
       
   678     QTest::addColumn<bool>("widgetCanHaveFocus");
       
   679     QTest::newRow("no focus, can't get") << false << false;
       
   680     QTest::newRow("no focus, can get") << false << true;
       
   681     QTest::newRow("has focus, can't get") << true << false;
       
   682     QTest::newRow("has focus, can get") << true << true;
       
   683     // ### add test for widget having a focusNextPrevChild
       
   684 }
       
   685 
       
   686 // protected void focusInEvent(QFocusEvent* event)
       
   687 void tst_QGraphicsProxyWidget::focusInEvent()
       
   688 {
       
   689     // ### This test is just plain old broken
       
   690     QFETCH(bool, widgetHasFocus);
       
   691     QFETCH(bool, widgetCanHaveFocus);
       
   692 
       
   693     QGraphicsScene scene;
       
   694     QEvent windowActivate(QEvent::WindowActivate);
       
   695     qApp->sendEvent(&scene, &windowActivate);
       
   696 
       
   697     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
   698     proxy->setEnabled(true);
       
   699     scene.addItem(proxy);
       
   700     proxy->setVisible(true);
       
   701 
       
   702     QWidget *widget = new QWidget;
       
   703     widget->resize(100, 100);
       
   704     if (widgetCanHaveFocus)
       
   705         widget->setFocusPolicy(Qt::WheelFocus);
       
   706     widget->show();
       
   707 
       
   708     if (widgetHasFocus)
       
   709         widget->setFocus(Qt::TabFocusReason);
       
   710 
       
   711     proxy->setWidget(widget);
       
   712     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
       
   713 
       
   714     // ### This test is just plain old broken - sending a focus in event
       
   715     // does not cause items to gain input focus. The widget has focus
       
   716     // because the proxy has focus, not because it got this event.
       
   717 
       
   718     QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
       
   719     event.ignore();
       
   720     proxy->call_focusInEvent(&event);
       
   721     QTRY_COMPARE(widget->hasFocus(), widgetCanHaveFocus);
       
   722 }
       
   723 
       
   724 void tst_QGraphicsProxyWidget::focusInEventNoWidget()
       
   725 {
       
   726     QGraphicsView view;
       
   727     QGraphicsScene scene(&view);
       
   728     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
   729     proxy->setEnabled(true);
       
   730     scene.addItem(proxy);
       
   731     proxy->setVisible(true);
       
   732     view.show();
       
   733 
       
   734     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
       
   735     QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
       
   736     event.ignore();
       
   737     //should not crash
       
   738     proxy->call_focusInEvent(&event);
       
   739 }
       
   740 
       
   741 void tst_QGraphicsProxyWidget::focusNextPrevChild_data()
       
   742 {
       
   743     QTest::addColumn<bool>("hasWidget");
       
   744     QTest::addColumn<bool>("hasScene");
       
   745     QTest::addColumn<bool>("next");
       
   746     QTest::addColumn<bool>("focusNextPrevChild");
       
   747 
       
   748     for (int i = 0; i < 2; ++i) {
       
   749         for (int j = 0; j < 2; ++j) {
       
   750             for (int k = 0; k < 2; ++k) {
       
   751                 bool next = (i == 0);
       
   752                 bool hasWidget = (j == 0);
       
   753                 bool hasScene = (k == 0);
       
   754                 bool result = hasScene && hasWidget;
       
   755                 QString name = QString("Forward: %1, hasWidget: %2, hasScene: %3, result: %4").arg(next).arg(hasWidget).arg(hasScene).arg(result);
       
   756                 QTest::newRow(name.toLatin1()) << hasWidget << hasScene << next << result;
       
   757             }
       
   758         }
       
   759     }
       
   760 }
       
   761 
       
   762 // protected bool focusNextPrevChild(bool next)
       
   763 void tst_QGraphicsProxyWidget::focusNextPrevChild()
       
   764 {
       
   765     QFETCH(bool, next);
       
   766     QFETCH(bool, focusNextPrevChild);
       
   767     QFETCH(bool, hasWidget);
       
   768     QFETCH(bool, hasScene);
       
   769 
       
   770     // If a widget has its own focusNextPrevChild we need to respect it
       
   771     // otherwise respect the scene
       
   772     // Respect the widget over the scene!
       
   773 
       
   774     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
   775 
       
   776     QLabel *widget = new QLabel;
       
   777     // I can't believe designer adds this much junk!
       
   778     widget->setText("<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\"> <p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.slashdot.org\"><span style=\" text-decoration: underline; color:#0000ff;\">old</span></a> foo <a href=\"http://www.reddit.org\"><span style=\" text-decoration: underline; color:#0000ff;\">new</span></a></p></body></html>");
       
   779     widget->setTextInteractionFlags(Qt::TextBrowserInteraction);
       
   780 
       
   781     if (hasWidget)
       
   782         proxy->setWidget(widget);
       
   783 
       
   784     QGraphicsScene scene;
       
   785     QGraphicsView view(&scene);
       
   786     view.show();
       
   787     QApplication::setActiveWindow(&view);
       
   788     QTest::qWaitForWindowShown(&view);
       
   789     QApplication::processEvents();
       
   790     QTRY_COMPARE(QApplication::activeWindow(), &view);
       
   791     if (hasScene) {
       
   792         scene.addItem(proxy);
       
   793         proxy->show();
       
   794 
       
   795         // widget should take precedence over scene so make scene.focusNextPrevChild return false
       
   796         // so we know that a true can only come from the widget
       
   797         if (!(hasWidget && hasScene)) {
       
   798             QGraphicsTextItem *item = new QGraphicsTextItem("Foo");
       
   799             item->setTextInteractionFlags(Qt::TextBrowserInteraction);
       
   800             scene.addItem(item);
       
   801             item->setPos(50, 40);
       
   802         }
       
   803         scene.setFocusItem(proxy);
       
   804         QVERIFY(proxy->hasFocus());
       
   805     }
       
   806 
       
   807     QCOMPARE(proxy->call_focusNextPrevChild(next), focusNextPrevChild);
       
   808 
       
   809     if (!hasScene)
       
   810         delete proxy;
       
   811 }
       
   812 
       
   813 void tst_QGraphicsProxyWidget::focusOutEvent_data()
       
   814 {
       
   815     QTest::addColumn<bool>("hasWidget");
       
   816     QTest::addColumn<bool>("call");
       
   817     QTest::newRow("no widget, focus to other widget") << false << false;
       
   818     QTest::newRow("no widget, focusOutCalled") << false << true;
       
   819     QTest::newRow("widget, focus to other widget") << true << false;
       
   820     QTest::newRow("widget, focusOutCalled") << true << true;
       
   821 }
       
   822 
       
   823 // protected void focusOutEvent(QFocusEvent* event)
       
   824 void tst_QGraphicsProxyWidget::focusOutEvent()
       
   825 {
       
   826     QFETCH(bool, hasWidget);
       
   827     QFETCH(bool, call);
       
   828 
       
   829     QGraphicsScene scene;
       
   830     QGraphicsView view(&scene);
       
   831     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
   832     scene.addItem(proxy);
       
   833     view.show();
       
   834     QApplication::setActiveWindow(&view);
       
   835     view.activateWindow();
       
   836     view.setFocus();
       
   837     QTest::qWaitForWindowShown(&view);
       
   838     QApplication::processEvents();
       
   839     QTRY_VERIFY(view.isVisible());
       
   840     QTRY_COMPARE(QApplication::activeWindow(), &view);
       
   841 
       
   842     QWidget *widget = new QWidget;
       
   843     widget->setFocusPolicy(Qt::WheelFocus);
       
   844     if (hasWidget)
       
   845         proxy->setWidget(widget);
       
   846     proxy->show();
       
   847     proxy->setFocus();
       
   848     QVERIFY(proxy->hasFocus());
       
   849     QEXPECT_FAIL("widget, focus to other widget", "Widget should have focus but doesn't", Continue);
       
   850     QEXPECT_FAIL("widget, focusOutCalled", "Widget should have focus but doesn't", Continue);
       
   851     QCOMPARE(widget->hasFocus(), hasWidget);
       
   852 
       
   853     if (!call) {
       
   854         QWidget *other = new QLineEdit(&view);
       
   855         other->show();
       
   856         QApplication::processEvents();
       
   857         QTRY_VERIFY(other->isVisible());
       
   858         other->setFocus();
       
   859         QTRY_VERIFY(other->hasFocus());
       
   860         qApp->processEvents();
       
   861         QTRY_COMPARE(proxy->hasFocus(), false);
       
   862         QVERIFY(proxy->focusOut);
       
   863         QCOMPARE(widget->hasFocus(), false);
       
   864     } else {
       
   865         {
       
   866             /*
       
   867             ### Test doesn't make sense
       
   868             QFocusEvent focusEvent(QEvent::FocusOut);
       
   869             proxy->call_focusOutEvent(&focusEvent);
       
   870             QCOMPARE(focusEvent.isAccepted(), hasWidget);
       
   871             qApp->processEvents();
       
   872             QCOMPARE(proxy->paintCount, hasWidget ? 1 : 0);
       
   873             */
       
   874         }
       
   875         {
       
   876             /*
       
   877             ### Test doesn't make sense
       
   878             proxy->setFlag(QGraphicsItem::ItemIsFocusable, false);
       
   879             QFocusEvent focusEvent(QEvent::FocusOut);
       
   880             proxy->call_focusOutEvent(&focusEvent);
       
   881             QCOMPARE(focusEvent.isAccepted(), hasWidget);
       
   882             qApp->processEvents();
       
   883             QCOMPARE(proxy->paintCount, 0);
       
   884             */
       
   885         }
       
   886     }
       
   887 }
       
   888 
       
   889 class EventLogger : public QWidget
       
   890 {
       
   891 public:
       
   892     EventLogger() : QWidget(), enterCount(0), leaveCount(0), moveCount(0),
       
   893         hoverEnter(0), hoverLeave(0), hoverMove(0)
       
   894     {
       
   895         installEventFilter(this);
       
   896     }
       
   897 
       
   898     void enterEvent(QEvent *event)
       
   899     {
       
   900         enterCount++;
       
   901         QWidget::enterEvent(event);
       
   902     }
       
   903 
       
   904     void leaveEvent(QEvent *event )
       
   905     {
       
   906         leaveCount++;
       
   907         QWidget::leaveEvent(event);
       
   908     }
       
   909 
       
   910     void mouseMoveEvent(QMouseEvent *event)
       
   911     {
       
   912         event->setAccepted(true);
       
   913         moveCount++;
       
   914         QWidget::mouseMoveEvent(event);
       
   915     }
       
   916 
       
   917     int enterCount;
       
   918     int leaveCount;
       
   919     int moveCount;
       
   920 
       
   921     int hoverEnter;
       
   922     int hoverLeave;
       
   923     int hoverMove;
       
   924 protected:
       
   925     bool eventFilter(QObject *object, QEvent *event)
       
   926     {
       
   927         switch (event->type()) {
       
   928         case QEvent::HoverEnter:
       
   929              hoverEnter++;
       
   930              break;
       
   931         case QEvent::HoverLeave:
       
   932              hoverLeave++;
       
   933              break;
       
   934         case QEvent::HoverMove:
       
   935              hoverMove++;
       
   936              break;
       
   937         default:
       
   938              break;
       
   939         }
       
   940         return QWidget::eventFilter(object, event);
       
   941     }
       
   942 };
       
   943 
       
   944 void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent_data()
       
   945 {
       
   946     QTest::addColumn<bool>("hasWidget");
       
   947     QTest::addColumn<bool>("hoverEnabled");
       
   948     QTest::newRow("widget, no hover") << true << false;
       
   949     QTest::newRow("no widget, no hover") << false << false;
       
   950     QTest::newRow("widget, hover") << true << true;
       
   951     QTest::newRow("no widget, hover") << false << true;
       
   952 }
       
   953 
       
   954 // protected void hoverEnterEvent(QGraphicsSceneHoverEvent* event)
       
   955 void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
       
   956 {
       
   957     QFETCH(bool, hasWidget);
       
   958     QFETCH(bool, hoverEnabled);
       
   959 
       
   960 #if defined(Q_OS_WINCE) && (!defined(GWES_ICONCURS) || defined(QT_NO_CURSOR))
       
   961     QSKIP("hover events not supported on this platform", SkipAll);
       
   962 #endif
       
   963 
       
   964     // proxy should translate this into events that the widget would expect
       
   965 
       
   966     QGraphicsScene scene;
       
   967     QGraphicsView view(&scene);
       
   968     //do not let the window manager move the window while we are moving the mouse on it
       
   969     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
       
   970     view.show();
       
   971 #ifdef Q_WS_X11
       
   972     qt_x11_wait_for_window_manager(&view);
       
   973 #endif
       
   974 
       
   975     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
   976     EventLogger *widget = new EventLogger;
       
   977     widget->resize(50, 50);
       
   978     widget->setAttribute(Qt::WA_Hover, hoverEnabled);
       
   979     widget->setMouseTracking(true);
       
   980     view.resize(100, 100);
       
   981     if (hasWidget)
       
   982         proxy->setWidget(widget);
       
   983     proxy->setPos(50, 0);
       
   984     scene.addItem(proxy);
       
   985     QTest::qWait(30);
       
   986     QTest::mouseMove(&view, QPoint(10, 10));
       
   987     QTest::qWait(30);
       
   988 
       
   989     // in
       
   990     QTest::mouseMove(&view, QPoint(50, 50));
       
   991     QTest::qWait(25);
       
   992     QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), hasWidget ? true : false);
       
   993     // ### this attribute isn't supported
       
   994     QCOMPARE(widget->enterCount, hasWidget ? 1 : 0);
       
   995     QCOMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
       
   996     // does not work on all platforms
       
   997     //QCOMPARE(widget->moveCount, 0);
       
   998 
       
   999     // out
       
  1000     QTest::mouseMove(&view, QPoint(10, 10));
       
  1001     QTest::qWait(25);
       
  1002     // QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), false);
       
  1003     // ### this attribute isn't supported
       
  1004     QCOMPARE(widget->leaveCount, hasWidget ? 1 : 0);
       
  1005     QCOMPARE(widget->hoverLeave, (hasWidget && hoverEnabled) ? 1 : 0);
       
  1006     // does not work on all platforms
       
  1007     //QCOMPARE(widget->moveCount, 0);
       
  1008 
       
  1009     if (!hasWidget)
       
  1010         delete widget;
       
  1011 }
       
  1012 
       
  1013 void tst_QGraphicsProxyWidget::hoverMoveEvent_data()
       
  1014 {
       
  1015     QTest::addColumn<bool>("hasWidget");
       
  1016     QTest::addColumn<bool>("hoverEnabled");
       
  1017     QTest::addColumn<bool>("mouseTracking");
       
  1018     QTest::addColumn<bool>("mouseDown");
       
  1019     for (int i = 0; i < 2; ++i) {
       
  1020         for (int j = 0; j < 2; ++j) {
       
  1021             for (int k = 0; k < 2; ++k) {
       
  1022                 for (int l = 0; l < 2; ++l) {
       
  1023                     bool hasWidget = (i == 0);
       
  1024                     bool hoverEnabled = (j == 0);
       
  1025                     bool mouseTracking = (k == 0);
       
  1026                     bool mouseDown = (l == 0);
       
  1027                     QString name = QString("hasWidget:%1, hover:%2, mouseTracking:%3, mouseDown: %4").arg(hasWidget).arg(hoverEnabled).arg(mouseTracking).arg(mouseDown);
       
  1028                     QTest::newRow(name.toLatin1()) << hasWidget << hoverEnabled << mouseTracking << mouseDown;
       
  1029                 }
       
  1030             }
       
  1031         }
       
  1032     }
       
  1033 }
       
  1034 
       
  1035 // protected void hoverMoveEvent(QGraphicsSceneHoverEvent* event)
       
  1036 void tst_QGraphicsProxyWidget::hoverMoveEvent()
       
  1037 {
       
  1038     QFETCH(bool, hasWidget);
       
  1039     QFETCH(bool, hoverEnabled);
       
  1040     QFETCH(bool, mouseTracking);
       
  1041     QFETCH(bool, mouseDown);
       
  1042 
       
  1043     QSKIP("Ambiguous test...", SkipAll);
       
  1044 
       
  1045     // proxy should translate the move events to what the widget would expect
       
  1046 
       
  1047     QGraphicsScene scene;
       
  1048     QGraphicsView view(&scene);
       
  1049     view.show();
       
  1050 
       
  1051     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  1052     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
       
  1053     EventLogger *widget = new EventLogger;
       
  1054     widget->resize(50, 50);
       
  1055     widget->setAttribute(Qt::WA_Hover, hoverEnabled);
       
  1056     if (mouseTracking)
       
  1057         widget->setMouseTracking(true);
       
  1058     view.resize(100, 100);
       
  1059     if (hasWidget)
       
  1060         proxy->setWidget(widget);
       
  1061     proxy->setPos(50, 0);
       
  1062     scene.addItem(proxy);
       
  1063 
       
  1064     // in
       
  1065     QTest::mouseMove(&view, QPoint(50, 50));
       
  1066     QTest::qWait(12);
       
  1067 
       
  1068     if (mouseDown)
       
  1069         QTest::mousePress(view.viewport(), Qt::LeftButton);
       
  1070 
       
  1071     // move a little bit
       
  1072     QTest::mouseMove(&view, QPoint(60, 60));
       
  1073     QTest::qWait(12);
       
  1074     QTRY_COMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
       
  1075     QCOMPARE(widget->moveCount, (hasWidget && mouseTracking) || (hasWidget && mouseDown) ? 1 : 0);
       
  1076 
       
  1077     if (!hasWidget)
       
  1078         delete widget;
       
  1079 }
       
  1080 
       
  1081 void tst_QGraphicsProxyWidget::keyPressEvent_data()
       
  1082 {
       
  1083     QTest::addColumn<bool>("hasWidget");
       
  1084     QTest::newRow("widget") << true;
       
  1085     QTest::newRow("no widget") << false;
       
  1086 }
       
  1087 
       
  1088 // protected void keyPressEvent(QKeyEvent* event)
       
  1089 void tst_QGraphicsProxyWidget::keyPressEvent()
       
  1090 {
       
  1091     QFETCH(bool, hasWidget);
       
  1092 
       
  1093     QGraphicsScene scene;
       
  1094     QGraphicsView view(&scene);
       
  1095     view.show();
       
  1096     view.viewport()->setFocus();
       
  1097     QApplication::setActiveWindow(&view);
       
  1098     QTest::qWaitForWindowShown(&view);
       
  1099     QApplication::processEvents();
       
  1100     QTRY_COMPARE(QApplication::activeWindow(), &view);
       
  1101 
       
  1102     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  1103     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
       
  1104 
       
  1105     QLineEdit *widget = new QLineEdit;
       
  1106     widget->resize(50, 50);
       
  1107     view.resize(100, 100);
       
  1108     if (hasWidget) {
       
  1109         proxy->setWidget(widget);
       
  1110         proxy->show();
       
  1111     }
       
  1112     proxy->setPos(50, 0);
       
  1113     scene.addItem(proxy);
       
  1114     proxy->setFocus();
       
  1115 
       
  1116     QTest::keyPress(view.viewport(), 'x');
       
  1117 
       
  1118     QTRY_COMPARE(widget->text(), hasWidget ? QString("x") : QString());
       
  1119 
       
  1120     if (!hasWidget)
       
  1121         delete widget;
       
  1122 }
       
  1123 
       
  1124 void tst_QGraphicsProxyWidget::keyReleaseEvent_data()
       
  1125 {
       
  1126     QTest::addColumn<bool>("hasWidget");
       
  1127     QTest::newRow("widget") << true;
       
  1128     QTest::newRow("no widget") << false;
       
  1129 }
       
  1130 
       
  1131 // protected void keyReleaseEvent(QKeyEvent* event)
       
  1132 void tst_QGraphicsProxyWidget::keyReleaseEvent()
       
  1133 {
       
  1134     QFETCH(bool, hasWidget);
       
  1135 
       
  1136     QGraphicsScene scene;
       
  1137     QGraphicsView view(&scene);
       
  1138     view.show();
       
  1139     QApplication::setActiveWindow(&view);
       
  1140     QTest::qWaitForWindowShown(&view);
       
  1141     QTRY_COMPARE(QApplication::activeWindow(), &view);
       
  1142 
       
  1143 
       
  1144     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  1145     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
       
  1146     QPushButton *widget = new QPushButton;
       
  1147     QSignalSpy spy(widget, SIGNAL(clicked()));
       
  1148     widget->resize(50, 50);
       
  1149     view.resize(100, 100);
       
  1150     if (hasWidget) {
       
  1151         proxy->setWidget(widget);
       
  1152         proxy->show();
       
  1153     }
       
  1154     proxy->setPos(50, 0);
       
  1155     scene.addItem(proxy);
       
  1156     proxy->setFocus();
       
  1157 
       
  1158     QTest::keyPress(view.viewport(), Qt::Key_Space);
       
  1159     QTRY_COMPARE(spy.count(), 0);
       
  1160     QTest::keyRelease(view.viewport(), Qt::Key_Space);
       
  1161     QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
       
  1162 
       
  1163     if (!hasWidget)
       
  1164         delete widget;
       
  1165 }
       
  1166 
       
  1167 void tst_QGraphicsProxyWidget::mouseDoubleClickEvent_data()
       
  1168 {
       
  1169     QTest::addColumn<bool>("hasWidget");
       
  1170     QTest::newRow("widget") << true;
       
  1171     QTest::newRow("no widget") << false;
       
  1172 }
       
  1173 
       
  1174 // protected void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
       
  1175 void tst_QGraphicsProxyWidget::mouseDoubleClickEvent()
       
  1176 {
       
  1177     QFETCH(bool, hasWidget);
       
  1178 
       
  1179     QGraphicsScene scene;
       
  1180     QGraphicsView view(&scene);
       
  1181     view.show();
       
  1182 
       
  1183     QApplication::setActiveWindow(&view);
       
  1184     QTest::qWaitForWindowShown(&view);
       
  1185     QTRY_COMPARE(QApplication::activeWindow(), &view);
       
  1186 
       
  1187     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  1188     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
       
  1189     QLineEdit *widget = new QLineEdit;
       
  1190     widget->setText("foo");
       
  1191     widget->resize(50, 50);
       
  1192     view.resize(100, 100);
       
  1193     if (hasWidget) {
       
  1194         proxy->setWidget(widget);
       
  1195         proxy->show();
       
  1196     }
       
  1197     proxy->setPos(50, 0);
       
  1198     scene.addItem(proxy);
       
  1199     proxy->setFocus();
       
  1200 
       
  1201     QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
       
  1202     QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
       
  1203     QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
       
  1204     QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
       
  1205     QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
       
  1206 
       
  1207     QTRY_COMPARE(widget->selectedText(), hasWidget ? QString("foo") : QString());
       
  1208 
       
  1209     if (!hasWidget)
       
  1210         delete widget;
       
  1211 }
       
  1212 
       
  1213 void tst_QGraphicsProxyWidget::mousePressReleaseEvent_data()
       
  1214 {
       
  1215     QTest::addColumn<bool>("hasWidget");
       
  1216     QTest::newRow("widget") << true;
       
  1217     QTest::newRow("no widget") << false;
       
  1218 }
       
  1219 
       
  1220 // protected void mousePressEvent(QGraphicsSceneMouseEvent* event)
       
  1221 void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
       
  1222 {
       
  1223     QFETCH(bool, hasWidget);
       
  1224 
       
  1225     QGraphicsScene scene;
       
  1226     QGraphicsView view(&scene);
       
  1227     view.show();
       
  1228     QTest::qWaitForWindowShown(&view);
       
  1229 
       
  1230     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  1231     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
       
  1232     QPushButton *widget = new QPushButton;
       
  1233     QSignalSpy spy(widget, SIGNAL(clicked()));
       
  1234     widget->resize(50, 50);
       
  1235     view.resize(100, 100);
       
  1236     if (hasWidget) {
       
  1237         proxy->setWidget(widget);
       
  1238 	proxy->show();
       
  1239     }
       
  1240     proxy->setPos(50, 0);
       
  1241     scene.addItem(proxy);
       
  1242     proxy->setFocus();
       
  1243 
       
  1244     QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
       
  1245 		      view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
       
  1246     QTRY_COMPARE(spy.count(), 0);
       
  1247     QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
       
  1248 		      view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
       
  1249     QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
       
  1250 
       
  1251     if (!hasWidget)
       
  1252         delete widget;
       
  1253 }
       
  1254 
       
  1255 void tst_QGraphicsProxyWidget::resizeEvent_data()
       
  1256 {
       
  1257     QTest::addColumn<bool>("hasWidget");
       
  1258     QTest::newRow("widget") << true;
       
  1259     QTest::newRow("no widget") << false;
       
  1260 }
       
  1261 
       
  1262 // protected void resizeEvent(QGraphicsSceneResizeEvent* event)
       
  1263 void tst_QGraphicsProxyWidget::resizeEvent()
       
  1264 {
       
  1265     QFETCH(bool, hasWidget);
       
  1266 
       
  1267     SubQGraphicsProxyWidget proxy;
       
  1268     QWidget *widget = new QWidget;
       
  1269     if (hasWidget)
       
  1270         proxy.setWidget(widget);
       
  1271 
       
  1272     QSize newSize(100, 100);
       
  1273     QGraphicsSceneResizeEvent event;
       
  1274     event.setOldSize(QSize(10, 10));
       
  1275     event.setNewSize(newSize);
       
  1276     proxy.call_resizeEvent(&event);
       
  1277     if (hasWidget)
       
  1278         QCOMPARE(widget->size(), newSize);
       
  1279     if (!hasWidget)
       
  1280         delete widget;
       
  1281 }
       
  1282 
       
  1283 void tst_QGraphicsProxyWidget::paintEvent()
       
  1284 {
       
  1285     //we test that calling update on a widget inside a QGraphicsView is triggering a repaint
       
  1286     QGraphicsScene scene;
       
  1287     QGraphicsView view(&scene);
       
  1288     view.show();
       
  1289     QTest::qWaitForWindowShown(&view);
       
  1290     QTest::qWait(70);
       
  1291 
       
  1292     SubQGraphicsProxyWidget proxy;
       
  1293 
       
  1294     QWidget *w = new QWidget;
       
  1295     //showing the widget here seems to create a bug in Graphics View
       
  1296     //this bug prevents the widget from being updated
       
  1297 
       
  1298     w->show();
       
  1299     QTest::qWaitForWindowShown(w);
       
  1300     QApplication::processEvents();
       
  1301     QTest::qWait(100);
       
  1302     proxy.setWidget(w);
       
  1303     scene.addItem(&proxy);
       
  1304 
       
  1305     //make sure we flush all the paint events
       
  1306     QTest::qWait(70);
       
  1307     QTRY_VERIFY(proxy.paintCount > 1);
       
  1308     QTest::qWait(110);
       
  1309     proxy.paintCount = 0;
       
  1310 
       
  1311     w->update();
       
  1312     QTest::qWait(30);
       
  1313     QTRY_COMPARE(proxy.paintCount, 1); //the widget should have been painted now
       
  1314 }
       
  1315 
       
  1316 
       
  1317 void tst_QGraphicsProxyWidget::wheelEvent()
       
  1318 {
       
  1319     QGraphicsScene scene;
       
  1320     QGraphicsView view(&scene);
       
  1321     view.show();
       
  1322 #ifdef Q_WS_X11
       
  1323     qt_x11_wait_for_window_manager(&view);
       
  1324 #endif
       
  1325 
       
  1326     WheelWidget *wheelWidget = new WheelWidget();
       
  1327     wheelWidget->setFixedSize(400, 400);
       
  1328 
       
  1329     QGraphicsProxyWidget *proxy = scene.addWidget(wheelWidget);
       
  1330     proxy->setVisible(true);
       
  1331 
       
  1332     QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel);
       
  1333     event.setScenePos(QPoint(50, 50));
       
  1334     event.setAccepted(false);
       
  1335     wheelWidget->wheelEventCalled = false;
       
  1336 
       
  1337     QApplication::sendEvent(&scene, &event);
       
  1338 
       
  1339     QVERIFY(event.isAccepted());
       
  1340     QVERIFY(wheelWidget->wheelEventCalled);
       
  1341 }
       
  1342 
       
  1343 Q_DECLARE_METATYPE(Qt::SizeHint)
       
  1344 void tst_QGraphicsProxyWidget::sizeHint_data()
       
  1345 {
       
  1346     QTest::addColumn<Qt::SizeHint>("which");
       
  1347     QTest::addColumn<QSizeF>("constraint");
       
  1348     QTest::addColumn<QSizeF>("sizeHint");
       
  1349     QTest::addColumn<bool>("hasWidget");
       
  1350 
       
  1351     for (int i = 0; i < 2; ++i) {
       
  1352         bool hasWidget = (i == 0);
       
  1353         // ### What should these do?
       
  1354         QTest::newRow("min") << Qt::MinimumSize << QSizeF() << QSizeF() << hasWidget;
       
  1355         QTest::newRow("pre") << Qt::PreferredSize << QSizeF() << QSizeF() << hasWidget;
       
  1356         QTest::newRow("max") << Qt::MaximumSize << QSizeF() << QSizeF() << hasWidget;
       
  1357         QTest::newRow("mindes") << Qt::MinimumDescent << QSizeF() << QSizeF() << hasWidget;
       
  1358         QTest::newRow("nsize") << Qt::NSizeHints << QSizeF() << QSizeF() << hasWidget;
       
  1359     }
       
  1360 }
       
  1361 
       
  1362 // protected QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
       
  1363 void tst_QGraphicsProxyWidget::sizeHint()
       
  1364 {
       
  1365     QFETCH(Qt::SizeHint, which);
       
  1366     QFETCH(QSizeF, constraint);
       
  1367     QFETCH(QSizeF, sizeHint);
       
  1368     QFETCH(bool, hasWidget);
       
  1369     QSKIP("Broken test", SkipAll);
       
  1370     SubQGraphicsProxyWidget proxy;
       
  1371     QWidget *widget = new QWidget;
       
  1372     if (hasWidget)
       
  1373         proxy.setWidget(widget);
       
  1374     QCOMPARE(proxy.call_sizeHint(which, constraint), sizeHint);
       
  1375     if (!hasWidget)
       
  1376         delete widget;
       
  1377 }
       
  1378 
       
  1379 void tst_QGraphicsProxyWidget::sizePolicy()
       
  1380 {
       
  1381     for (int p = 0; p < 2; ++p) {
       
  1382         bool hasWidget = (p == 0 ? true : false);
       
  1383         SubQGraphicsProxyWidget proxy;
       
  1384         QWidget *widget = new QWidget;
       
  1385         QSizePolicy proxyPol(QSizePolicy::Maximum, QSizePolicy::Expanding);
       
  1386         proxy.setSizePolicy(proxyPol);
       
  1387         QSizePolicy widgetPol(QSizePolicy::Fixed, QSizePolicy::Minimum);
       
  1388         widget->setSizePolicy(widgetPol);
       
  1389 
       
  1390         QCOMPARE(proxy.sizePolicy(), proxyPol);
       
  1391         QCOMPARE(widget->sizePolicy(), widgetPol);
       
  1392         if (hasWidget) {
       
  1393             proxy.setWidget(widget);
       
  1394             QCOMPARE(proxy.sizePolicy(), widgetPol);
       
  1395         } else {
       
  1396             QCOMPARE(proxy.sizePolicy(), proxyPol);
       
  1397         }
       
  1398         QCOMPARE(widget->sizePolicy(), widgetPol);
       
  1399 
       
  1400         proxy.setSizePolicy(widgetPol);
       
  1401         widget->setSizePolicy(proxyPol);
       
  1402         if (hasWidget)
       
  1403             QCOMPARE(proxy.sizePolicy(), proxyPol);
       
  1404         else
       
  1405             QCOMPARE(proxy.sizePolicy(), widgetPol);
       
  1406     }
       
  1407 }
       
  1408 
       
  1409 void tst_QGraphicsProxyWidget::minimumSize()
       
  1410 {
       
  1411     SubQGraphicsProxyWidget proxy;
       
  1412     QWidget *widget = new QWidget;
       
  1413     QSize minSize(50, 50);
       
  1414     widget->setMinimumSize(minSize);
       
  1415     proxy.resize(30, 30);
       
  1416     widget->resize(30,30);
       
  1417     QCOMPARE(proxy.size(), QSizeF(30, 30));
       
  1418     proxy.setWidget(widget);
       
  1419     QCOMPARE(proxy.size().toSize(), minSize);
       
  1420     QCOMPARE(proxy.minimumSize().toSize(), minSize);
       
  1421     widget->setMinimumSize(70, 70);
       
  1422     QCOMPARE(proxy.minimumSize(), QSizeF(70, 70));
       
  1423     QCOMPARE(proxy.size(), QSizeF(70, 70));
       
  1424 }
       
  1425 
       
  1426 void tst_QGraphicsProxyWidget::maximumSize()
       
  1427 {
       
  1428     SubQGraphicsProxyWidget proxy;
       
  1429     QWidget *widget = new QWidget;
       
  1430     QSize maxSize(150, 150);
       
  1431     widget->setMaximumSize(maxSize);
       
  1432     proxy.resize(200, 200);
       
  1433     widget->resize(200,200);
       
  1434     QCOMPARE(proxy.size(), QSizeF(200, 200));
       
  1435     proxy.setWidget(widget);
       
  1436     QCOMPARE(proxy.size().toSize(), maxSize);
       
  1437     QCOMPARE(proxy.maximumSize().toSize(), maxSize);
       
  1438     widget->setMaximumSize(70, 70);
       
  1439     QCOMPARE(proxy.maximumSize(), QSizeF(70, 70));
       
  1440     QCOMPARE(proxy.size(), QSizeF(70, 70));
       
  1441 }
       
  1442 
       
  1443 class View : public QGraphicsView
       
  1444 {
       
  1445 public:
       
  1446     View(QGraphicsScene *scene, QWidget *parent = 0)
       
  1447 	: QGraphicsView(scene, parent), npaints(0)
       
  1448     { }
       
  1449     QRegion paintEventRegion;
       
  1450     int npaints;
       
  1451 protected:
       
  1452     void paintEvent(QPaintEvent *event)
       
  1453     {
       
  1454 	++npaints;
       
  1455 	paintEventRegion += event->region();
       
  1456 	QGraphicsView::paintEvent(event);
       
  1457     }
       
  1458 };
       
  1459 
       
  1460 class ScrollWidget : public QWidget
       
  1461 {
       
  1462     Q_OBJECT
       
  1463 public:
       
  1464     ScrollWidget() : npaints(0)
       
  1465     {
       
  1466 	resize(200, 200);
       
  1467     }
       
  1468     QRegion paintEventRegion;
       
  1469     int npaints;
       
  1470 
       
  1471 public slots:
       
  1472     void updateScroll()
       
  1473     {
       
  1474 	update(0, 0, 200, 10);
       
  1475 	scroll(0, 10, QRect(0, 0, 100, 20));
       
  1476     }
       
  1477 
       
  1478 protected:
       
  1479     void paintEvent(QPaintEvent *event)
       
  1480     {
       
  1481 	++npaints;
       
  1482 	paintEventRegion += event->region();
       
  1483 	QPainter painter(this);
       
  1484 	painter.fillRect(event->rect(), Qt::blue);
       
  1485     }
       
  1486 };
       
  1487 
       
  1488 void tst_QGraphicsProxyWidget::scrollUpdate()
       
  1489 {
       
  1490     ScrollWidget *widget = new ScrollWidget;
       
  1491 
       
  1492     QGraphicsScene scene;
       
  1493     scene.addWidget(widget);
       
  1494 
       
  1495     View view(&scene);
       
  1496     view.show();
       
  1497     QTest::qWaitForWindowShown(&view);
       
  1498     QTRY_VERIFY(view.npaints >= 1);
       
  1499     QTest::qWait(20);
       
  1500     widget->paintEventRegion = QRegion();
       
  1501     widget->npaints = 0;
       
  1502     view.paintEventRegion = QRegion();
       
  1503     view.npaints = 0;
       
  1504     QTimer::singleShot(0, widget, SLOT(updateScroll()));
       
  1505     QTest::qWait(50);
       
  1506     QTRY_COMPARE(view.npaints, 2);
       
  1507     // QRect(0, 0, 200, 12) is the first update, expanded (-2, -2, 2, 2)
       
  1508     // QRect(0, 12, 102, 10) is the scroll update, expanded (-2, -2, 2, 2),
       
  1509     // intersected with the above update.
       
  1510     QCOMPARE(view.paintEventRegion.rects(),
       
  1511 	     QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
       
  1512     QCOMPARE(widget->npaints, 2);
       
  1513     QCOMPARE(widget->paintEventRegion.rects(),
       
  1514              QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
       
  1515 }
       
  1516 
       
  1517 void tst_QGraphicsProxyWidget::setWidget_simple()
       
  1518 {
       
  1519     QGraphicsProxyWidget proxy;
       
  1520     QLineEdit *lineEdit = new QLineEdit;
       
  1521     proxy.setWidget(lineEdit);
       
  1522 
       
  1523     QVERIFY(lineEdit->testAttribute(Qt::WA_DontShowOnScreen));
       
  1524     // Size hints
       
  1525     // ### size hints are tested in a different test
       
  1526     // QCOMPARE(proxy.effectiveSizeHint(Qt::MinimumSize).toSize(), lineEdit->minimumSizeHint());
       
  1527     // QCOMPARE(proxy.effectiveSizeHint(Qt::MaximumSize).toSize(), lineEdit->maximumSize());
       
  1528     // QCOMPARE(proxy.effectiveSizeHint(Qt::PreferredSize).toSize(), lineEdit->sizeHint());
       
  1529     QCOMPARE(proxy.size().toSize(), lineEdit->minimumSizeHint().expandedTo(lineEdit->size()));
       
  1530     QRect rect = lineEdit->rect();
       
  1531     rect.setSize(rect.size().expandedTo(lineEdit->minimumSizeHint()));
       
  1532     QCOMPARE(proxy.rect().toRect(), rect);
       
  1533 
       
  1534     // Properties
       
  1535     // QCOMPARE(proxy.focusPolicy(), lineEdit->focusPolicy());
       
  1536     // QCOMPARE(proxy.palette(), lineEdit->palette());
       
  1537 #ifndef QT_NO_CURSOR
       
  1538     QCOMPARE(proxy.cursor().shape(), lineEdit->cursor().shape());
       
  1539 #endif
       
  1540     QCOMPARE(proxy.layoutDirection(), lineEdit->layoutDirection());
       
  1541     QCOMPARE(proxy.style(), lineEdit->style());
       
  1542     QCOMPARE(proxy.font(), lineEdit->font());
       
  1543     QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
       
  1544     QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
       
  1545 }
       
  1546 
       
  1547 void tst_QGraphicsProxyWidget::setWidget_ownership()
       
  1548 {
       
  1549     QPointer<QLineEdit> lineEdit = new QLineEdit;
       
  1550     QPointer<QLineEdit> lineEdit2 = new QLineEdit;
       
  1551     QVERIFY(lineEdit);
       
  1552     {
       
  1553         // Create a proxy and transfer ownership to it
       
  1554         QGraphicsProxyWidget proxy;
       
  1555         proxy.setWidget(lineEdit);
       
  1556         QCOMPARE(proxy.widget(), (QWidget *)lineEdit);
       
  1557 
       
  1558         // Remove the widget without destroying it.
       
  1559         proxy.setWidget(0);
       
  1560         QVERIFY(!proxy.widget());
       
  1561         QVERIFY(lineEdit);
       
  1562 
       
  1563         // Assign the widget again and switch to another widget.
       
  1564         proxy.setWidget(lineEdit);
       
  1565         proxy.setWidget(lineEdit2);
       
  1566         QCOMPARE(proxy.widget(), (QWidget *)lineEdit2);
       
  1567 
       
  1568         // Assign the first widget, and destroy the proxy.
       
  1569         proxy.setWidget(lineEdit);
       
  1570     }
       
  1571     QVERIFY(!lineEdit);
       
  1572     QVERIFY(lineEdit2);
       
  1573 
       
  1574     QGraphicsScene scene;
       
  1575     QPointer<QGraphicsProxyWidget> proxy = scene.addWidget(lineEdit2);
       
  1576 
       
  1577     delete lineEdit2;
       
  1578     QVERIFY(!proxy);
       
  1579 }
       
  1580 
       
  1581 void tst_QGraphicsProxyWidget::resize_simple_data()
       
  1582 {
       
  1583     QTest::addColumn<QSizeF>("size");
       
  1584 
       
  1585     QTest::newRow("200, 200") << QSizeF(200, 200);
       
  1586 #if !defined(QT_ARCH_ARM) && !defined(Q_OS_WINCE)
       
  1587     QTest::newRow("1000, 1000") << QSizeF(1000, 1000);
       
  1588     // Since 4.5, 10000x10000 runs out of memory.
       
  1589     // QTest::newRow("10000, 10000") << QSizeF(10000, 10000);
       
  1590 #endif
       
  1591 }
       
  1592 
       
  1593 void tst_QGraphicsProxyWidget::resize_simple()
       
  1594 {
       
  1595     QFETCH(QSizeF, size);
       
  1596 
       
  1597     QGraphicsProxyWidget proxy;
       
  1598     QWidget *widget = new QWidget;
       
  1599     widget->setGeometry(0, 0, (int)size.width(), (int)size.height());
       
  1600     proxy.setWidget(widget);
       
  1601     widget->show();
       
  1602     QCOMPARE(widget->pos(), QPoint());
       
  1603 
       
  1604     // The proxy resizes itself, the line edit follows
       
  1605     proxy.resize(size);
       
  1606     QCOMPARE(proxy.size(), size);
       
  1607     QCOMPARE(proxy.size().toSize(), widget->size());
       
  1608 
       
  1609     // The line edit resizes itself, the proxy follows (no loopback/live lock)
       
  1610     QSize doubleSize = size.toSize() * 2;
       
  1611     widget->resize(doubleSize);
       
  1612     QCOMPARE(widget->size(), doubleSize);
       
  1613     QCOMPARE(widget->size(), proxy.size().toSize());
       
  1614 }
       
  1615 
       
  1616 void tst_QGraphicsProxyWidget::symmetricMove()
       
  1617 {
       
  1618     QGraphicsProxyWidget proxy;
       
  1619     QLineEdit *lineEdit = new QLineEdit;
       
  1620     proxy.setWidget(lineEdit);
       
  1621     lineEdit->show();
       
  1622 
       
  1623     proxy.setPos(10, 10);
       
  1624     QCOMPARE(proxy.pos(), QPointF(10, 10));
       
  1625     QCOMPARE(lineEdit->pos(), QPoint(10, 10));
       
  1626 
       
  1627     lineEdit->move(5, 5);
       
  1628     QCOMPARE(proxy.pos(), QPointF(5, 5));
       
  1629     QCOMPARE(lineEdit->pos(), QPoint(5, 5));
       
  1630 }
       
  1631 
       
  1632 void tst_QGraphicsProxyWidget::symmetricResize()
       
  1633 {
       
  1634     QGraphicsProxyWidget proxy;
       
  1635     QLineEdit *lineEdit = new QLineEdit;
       
  1636     proxy.setWidget(lineEdit);
       
  1637     lineEdit->show();
       
  1638 
       
  1639     proxy.resize(256, 256);
       
  1640     QCOMPARE(proxy.size(), QSizeF(256, 256));
       
  1641     QCOMPARE(lineEdit->size(), QSize(256, 256));
       
  1642 
       
  1643     lineEdit->resize(512, 512);
       
  1644     QCOMPARE(proxy.size(), QSizeF(512, 512));
       
  1645     QCOMPARE(lineEdit->size(), QSize(512, 512));
       
  1646 }
       
  1647 
       
  1648 void tst_QGraphicsProxyWidget::symmetricVisible()
       
  1649 {
       
  1650     QGraphicsProxyWidget proxy;
       
  1651     QLineEdit *lineEdit = new QLineEdit;
       
  1652     proxy.setWidget(lineEdit);
       
  1653     lineEdit->show();
       
  1654 
       
  1655     QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
       
  1656 
       
  1657     proxy.hide();
       
  1658     QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
       
  1659     proxy.show();
       
  1660     QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
       
  1661     lineEdit->hide();
       
  1662     QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
       
  1663     lineEdit->show();
       
  1664     QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
       
  1665  }
       
  1666 
       
  1667 void tst_QGraphicsProxyWidget::symmetricEnabled()
       
  1668 {
       
  1669     QGraphicsProxyWidget proxy;
       
  1670     QLineEdit *lineEdit = new QLineEdit;
       
  1671     proxy.setWidget(lineEdit);
       
  1672     lineEdit->show();
       
  1673 
       
  1674     QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
       
  1675     proxy.setEnabled(false);
       
  1676     QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
       
  1677     proxy.setEnabled(true);
       
  1678     QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
       
  1679     lineEdit->setEnabled(false);
       
  1680     QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
       
  1681     lineEdit->setEnabled(true);
       
  1682     QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
       
  1683 }
       
  1684 
       
  1685 void tst_QGraphicsProxyWidget::tabFocus_simpleWidget()
       
  1686 {
       
  1687     QGraphicsScene scene;
       
  1688     QLineEdit *edit = new QLineEdit;
       
  1689     QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
       
  1690     editProxy->show();
       
  1691 
       
  1692     QDial *leftDial = new QDial;
       
  1693     QDial *rightDial = new QDial;
       
  1694     QGraphicsView *view = new QGraphicsView(&scene);
       
  1695 
       
  1696     QWidget window;
       
  1697     QHBoxLayout *layout = new QHBoxLayout;
       
  1698     layout->addWidget(leftDial);
       
  1699     layout->addWidget(view);
       
  1700     layout->addWidget(rightDial);
       
  1701     window.setLayout(layout);
       
  1702 
       
  1703     window.show();
       
  1704     QApplication::setActiveWindow(&window);
       
  1705     window.activateWindow();
       
  1706     QTest::qWaitForWindowShown(&window);
       
  1707 
       
  1708     leftDial->setFocus();
       
  1709     QApplication::processEvents();
       
  1710     QTRY_VERIFY(leftDial->hasFocus());
       
  1711 
       
  1712     EventSpy eventSpy(edit);
       
  1713 
       
  1714     // Tab into line edit
       
  1715     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1716     QApplication::processEvents();
       
  1717     QTRY_VERIFY(!leftDial->hasFocus());
       
  1718     QTRY_VERIFY(view->hasFocus());
       
  1719     QVERIFY(view->viewport()->hasFocus());
       
  1720     QVERIFY(scene.hasFocus());
       
  1721     QVERIFY(editProxy->hasFocus());
       
  1722     QVERIFY(edit->hasFocus());
       
  1723     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1724     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
       
  1725 
       
  1726     // Tab into right dial
       
  1727     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1728     QApplication::processEvents();
       
  1729     QTRY_VERIFY(!view->hasFocus());
       
  1730     QVERIFY(!view->viewport()->hasFocus());
       
  1731     QVERIFY(!scene.hasFocus());
       
  1732     QVERIFY(!editProxy->hasFocus());
       
  1733     QVERIFY(!edit->hasFocus());
       
  1734     QTRY_VERIFY(rightDial->hasFocus());
       
  1735     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1736     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1737 
       
  1738     // Backtab into line edit
       
  1739     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1740     QApplication::processEvents();
       
  1741     QTRY_VERIFY(view->hasFocus());
       
  1742     QVERIFY(view->viewport()->hasFocus());
       
  1743     QTRY_VERIFY(scene.hasFocus());
       
  1744     QVERIFY(editProxy->hasFocus());
       
  1745     QVERIFY(edit->hasFocus());
       
  1746     QVERIFY(!rightDial->hasFocus());
       
  1747     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
       
  1748     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1749 
       
  1750     // Backtab into left dial
       
  1751     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1752     QApplication::processEvents();
       
  1753     QTRY_VERIFY(!view->hasFocus());
       
  1754     QVERIFY(!view->viewport()->hasFocus());
       
  1755     QVERIFY(!scene.hasFocus());
       
  1756     QVERIFY(!editProxy->hasFocus());
       
  1757     QVERIFY(!edit->hasFocus());
       
  1758     QTRY_VERIFY(leftDial->hasFocus());
       
  1759     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
       
  1760     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
       
  1761 
       
  1762     delete view;
       
  1763 }
       
  1764 
       
  1765 void tst_QGraphicsProxyWidget::tabFocus_simpleTwoWidgets()
       
  1766 {
       
  1767     QGraphicsScene scene;
       
  1768     QLineEdit *edit = new QLineEdit;
       
  1769     QLineEdit *edit2 = new QLineEdit;
       
  1770     QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
       
  1771     editProxy->show();
       
  1772     QGraphicsProxyWidget *editProxy2 = scene.addWidget(edit2);
       
  1773     editProxy2->show();
       
  1774     editProxy2->setPos(0, editProxy->rect().height() * 1.1);
       
  1775 
       
  1776     QDial *leftDial = new QDial;
       
  1777     QDial *rightDial = new QDial;
       
  1778     QGraphicsView *view = new QGraphicsView(&scene);
       
  1779 
       
  1780     QWidget window;
       
  1781     QHBoxLayout *layout = new QHBoxLayout;
       
  1782     layout->addWidget(leftDial);
       
  1783     layout->addWidget(view);
       
  1784     layout->addWidget(rightDial);
       
  1785     window.setLayout(layout);
       
  1786 
       
  1787     window.show();
       
  1788     QApplication::setActiveWindow(&window);
       
  1789     window.activateWindow();
       
  1790     QTest::qWaitForWindowShown(&window);
       
  1791 
       
  1792     leftDial->setFocus();
       
  1793     QApplication::processEvents();
       
  1794     QTRY_VERIFY(leftDial->hasFocus());
       
  1795 
       
  1796     EventSpy eventSpy(edit);
       
  1797     EventSpy eventSpy2(edit2);
       
  1798 
       
  1799     // Tab into line edit
       
  1800     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1801     QApplication::processEvents();
       
  1802     QVERIFY(!leftDial->hasFocus());
       
  1803     QVERIFY(view->hasFocus());
       
  1804     QVERIFY(view->viewport()->hasFocus());
       
  1805     QVERIFY(scene.hasFocus());
       
  1806     QVERIFY(editProxy->hasFocus());
       
  1807     QVERIFY(edit->hasFocus());
       
  1808     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1809     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
       
  1810 
       
  1811     // Tab into second line edit
       
  1812     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1813     QApplication::processEvents();
       
  1814     QVERIFY(view->hasFocus());
       
  1815     QVERIFY(view->viewport()->hasFocus());
       
  1816     QVERIFY(scene.hasFocus());
       
  1817     QVERIFY(!editProxy->hasFocus());
       
  1818     QVERIFY(!edit->hasFocus());
       
  1819     QVERIFY(editProxy2->hasFocus());
       
  1820     QVERIFY(edit2->hasFocus());
       
  1821     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1822     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1823     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
       
  1824     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
       
  1825 
       
  1826     // Tab into right dial
       
  1827     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1828     QApplication::processEvents();
       
  1829     QVERIFY(!view->hasFocus());
       
  1830     QVERIFY(!view->viewport()->hasFocus());
       
  1831     QVERIFY(!scene.hasFocus());
       
  1832     QVERIFY(!editProxy->hasFocus());
       
  1833     QVERIFY(!edit->hasFocus());
       
  1834     QVERIFY(!editProxy2->hasFocus());
       
  1835     QVERIFY(!edit2->hasFocus());
       
  1836     QVERIFY(rightDial->hasFocus());
       
  1837     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1838     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1839     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
       
  1840     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
       
  1841 
       
  1842     // Backtab into line edit 2
       
  1843     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1844     QApplication::processEvents();
       
  1845     QVERIFY(view->hasFocus());
       
  1846     QVERIFY(view->viewport()->hasFocus());
       
  1847     QVERIFY(scene.hasFocus());
       
  1848     QVERIFY(!editProxy->hasFocus());
       
  1849     QVERIFY(!edit->hasFocus());
       
  1850     QVERIFY(editProxy2->hasFocus());
       
  1851     QVERIFY(edit2->hasFocus());
       
  1852     QVERIFY(!rightDial->hasFocus());
       
  1853     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1854     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1855     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
       
  1856     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
       
  1857 
       
  1858     // Backtab into line edit 1
       
  1859     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1860     QApplication::processEvents();
       
  1861     QVERIFY(view->hasFocus());
       
  1862     QVERIFY(view->viewport()->hasFocus());
       
  1863     QVERIFY(scene.hasFocus());
       
  1864     QVERIFY(editProxy->hasFocus());
       
  1865     QVERIFY(edit->hasFocus());
       
  1866     QVERIFY(!editProxy2->hasFocus());
       
  1867     QVERIFY(!edit2->hasFocus());
       
  1868     QVERIFY(!rightDial->hasFocus());
       
  1869     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
       
  1870     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1871     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
       
  1872     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 2);
       
  1873 
       
  1874     // Backtab into left dial
       
  1875     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1876     QApplication::processEvents();
       
  1877     QVERIFY(!view->hasFocus());
       
  1878     QVERIFY(!view->viewport()->hasFocus());
       
  1879     QVERIFY(!scene.hasFocus());
       
  1880     QVERIFY(!editProxy->hasFocus());
       
  1881     QVERIFY(!edit->hasFocus());
       
  1882     QVERIFY(leftDial->hasFocus());
       
  1883     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
       
  1884     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
       
  1885 
       
  1886     delete view;
       
  1887 }
       
  1888 
       
  1889 void tst_QGraphicsProxyWidget::tabFocus_complexWidget()
       
  1890 {
       
  1891     QGraphicsScene scene;
       
  1892 
       
  1893     QLineEdit *edit1 = new QLineEdit;
       
  1894     edit1->setText("QLineEdit 1");
       
  1895     QLineEdit *edit2 = new QLineEdit;
       
  1896     edit2->setText("QLineEdit 2");
       
  1897     QVBoxLayout *vlayout = new QVBoxLayout;
       
  1898     vlayout->addWidget(edit1);
       
  1899     vlayout->addWidget(edit2);
       
  1900 
       
  1901     QGroupBox *box = new QGroupBox("QGroupBox");
       
  1902     box->setCheckable(true);
       
  1903     box->setChecked(true);
       
  1904     box->setLayout(vlayout);
       
  1905 
       
  1906     QGraphicsProxyWidget *proxy = scene.addWidget(box);
       
  1907     proxy->show();
       
  1908 
       
  1909     QDial *leftDial = new QDial;
       
  1910     QDial *rightDial = new QDial;
       
  1911     QGraphicsView *view = new QGraphicsView(&scene);
       
  1912 
       
  1913     QWidget window;
       
  1914     QHBoxLayout *layout = new QHBoxLayout;
       
  1915     layout->addWidget(leftDial);
       
  1916     layout->addWidget(view);
       
  1917     layout->addWidget(rightDial);
       
  1918     window.setLayout(layout);
       
  1919 
       
  1920     window.show();
       
  1921     QApplication::setActiveWindow(&window);
       
  1922     window.activateWindow();
       
  1923     QTest::qWaitForWindowShown(&window);
       
  1924 
       
  1925     leftDial->setFocus();
       
  1926     QApplication::processEvents();
       
  1927     QTRY_VERIFY(leftDial->hasFocus());
       
  1928 
       
  1929     EventSpy eventSpy(edit1);
       
  1930     EventSpy eventSpy2(edit2);
       
  1931     EventSpy eventSpyBox(box);
       
  1932 
       
  1933     // Tab into group box
       
  1934     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1935     QApplication::processEvents();
       
  1936     QVERIFY(!leftDial->hasFocus());
       
  1937     QVERIFY(view->hasFocus());
       
  1938     QVERIFY(view->viewport()->hasFocus());
       
  1939     QVERIFY(scene.hasFocus());
       
  1940     QVERIFY(proxy->hasFocus());
       
  1941     QVERIFY(box->hasFocus());
       
  1942 
       
  1943     // Tab into line edit
       
  1944     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1945     QApplication::processEvents();
       
  1946     edit1->hasFocus();
       
  1947     QVERIFY(!box->hasFocus());
       
  1948     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1949     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
       
  1950 
       
  1951     // Tab into line edit 2
       
  1952     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1953     QApplication::processEvents();
       
  1954     edit2->hasFocus();
       
  1955     QVERIFY(!edit1->hasFocus());
       
  1956     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  1957     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  1958     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
       
  1959     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
       
  1960 
       
  1961     // Tab into right dial
       
  1962     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  1963     QApplication::processEvents();
       
  1964     QVERIFY(!edit2->hasFocus());
       
  1965     rightDial->hasFocus();
       
  1966     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
       
  1967     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
       
  1968 
       
  1969     // Backtab into line edit 2
       
  1970     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1971     QApplication::processEvents();
       
  1972     QVERIFY(!rightDial->hasFocus());
       
  1973     edit2->hasFocus();
       
  1974     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
       
  1975     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
       
  1976 
       
  1977     // Backtab into line edit 1
       
  1978     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1979     QApplication::processEvents();
       
  1980     QVERIFY(!edit2->hasFocus());
       
  1981     edit1->hasFocus();
       
  1982     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 2);
       
  1983     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
       
  1984 
       
  1985     // Backtab into line box
       
  1986     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1987     QApplication::processEvents();
       
  1988     QVERIFY(!edit1->hasFocus());
       
  1989     box->hasFocus();
       
  1990     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
       
  1991 
       
  1992     // Backtab into left dial
       
  1993     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  1994     QApplication::processEvents();
       
  1995     QVERIFY(!box->hasFocus());
       
  1996     leftDial->hasFocus();
       
  1997 
       
  1998     delete view;
       
  1999 }
       
  2000 
       
  2001 void tst_QGraphicsProxyWidget::tabFocus_complexTwoWidgets()
       
  2002 {
       
  2003     // ### add event spies to this test.
       
  2004     QGraphicsScene scene;
       
  2005 
       
  2006     QLineEdit *edit1 = new QLineEdit;
       
  2007     edit1->setText("QLineEdit 1");
       
  2008     QLineEdit *edit2 = new QLineEdit;
       
  2009     edit2->setText("QLineEdit 2");
       
  2010     QFontComboBox *fontComboBox = new QFontComboBox;
       
  2011     QVBoxLayout *vlayout = new QVBoxLayout;
       
  2012     vlayout->addWidget(edit1);
       
  2013     vlayout->addWidget(fontComboBox);
       
  2014     vlayout->addWidget(edit2);
       
  2015 
       
  2016     QGroupBox *box = new QGroupBox("QGroupBox");
       
  2017     box->setCheckable(true);
       
  2018     box->setChecked(true);
       
  2019     box->setLayout(vlayout);
       
  2020 
       
  2021     QLineEdit *edit1_2 = new QLineEdit;
       
  2022     edit1_2->setText("QLineEdit 1_2");
       
  2023     QLineEdit *edit2_2 = new QLineEdit;
       
  2024     edit2_2->setText("QLineEdit 2_2");
       
  2025     QFontComboBox *fontComboBox2 = new QFontComboBox;
       
  2026     vlayout = new QVBoxLayout;
       
  2027     vlayout->addWidget(edit1_2);
       
  2028     vlayout->addWidget(fontComboBox2);
       
  2029     vlayout->addWidget(edit2_2);
       
  2030 
       
  2031     QGroupBox *box_2 = new QGroupBox("QGroupBox 2");
       
  2032     box_2->setCheckable(true);
       
  2033     box_2->setChecked(true);
       
  2034     box_2->setLayout(vlayout);
       
  2035 
       
  2036     QGraphicsProxyWidget *proxy = scene.addWidget(box);
       
  2037     proxy->show();
       
  2038 
       
  2039     QGraphicsProxyWidget *proxy_2 = scene.addWidget(box_2);
       
  2040     proxy_2->setPos(proxy->boundingRect().width() * 1.2, 0);
       
  2041     proxy_2->show();
       
  2042 
       
  2043     QDial *leftDial = new QDial;
       
  2044     QDial *rightDial = new QDial;
       
  2045     QGraphicsView *view = new QGraphicsView(&scene);
       
  2046     view->setRenderHint(QPainter::Antialiasing);
       
  2047     view->rotate(45);
       
  2048     view->scale(0.5, 0.5);
       
  2049 
       
  2050     QWidget window;
       
  2051     QHBoxLayout *layout = new QHBoxLayout;
       
  2052     layout->addWidget(leftDial);
       
  2053     layout->addWidget(view);
       
  2054     layout->addWidget(rightDial);
       
  2055     window.setLayout(layout);
       
  2056 
       
  2057     window.show();
       
  2058     QApplication::setActiveWindow(&window);
       
  2059     window.activateWindow();
       
  2060     QTest::qWaitForWindowShown(&window);
       
  2061     QTRY_COMPARE(QApplication::activeWindow(), &window);
       
  2062 
       
  2063     leftDial->setFocus();
       
  2064     QApplication::processEvents();
       
  2065     QTRY_VERIFY(leftDial->hasFocus());
       
  2066 
       
  2067     EventSpy eventSpy(edit1);
       
  2068     EventSpy eventSpy2(edit2);
       
  2069     EventSpy eventSpy3(fontComboBox);
       
  2070     EventSpy eventSpy1_2(edit1_2);
       
  2071     EventSpy eventSpy2_2(edit2_2);
       
  2072     EventSpy eventSpy2_3(fontComboBox2);
       
  2073     EventSpy eventSpyBox(box);
       
  2074 
       
  2075     // Tab into group box
       
  2076     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2077     QApplication::processEvents();
       
  2078     QVERIFY(!leftDial->hasFocus());
       
  2079     QVERIFY(view->hasFocus());
       
  2080     QVERIFY(view->viewport()->hasFocus());
       
  2081     QVERIFY(scene.hasFocus());
       
  2082     QVERIFY(proxy->hasFocus());
       
  2083     QVERIFY(box->hasFocus());
       
  2084 
       
  2085     // Tab into line edit
       
  2086     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2087     QApplication::processEvents();
       
  2088     edit1->hasFocus();
       
  2089     QVERIFY(!box->hasFocus());
       
  2090     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2091     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
       
  2092 
       
  2093     // Tab to the font combobox
       
  2094     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2095     QApplication::processEvents();
       
  2096     fontComboBox->hasFocus();
       
  2097     QVERIFY(!edit2->hasFocus());
       
  2098     QCOMPARE(eventSpy3.counts[QEvent::FocusIn], 1);
       
  2099     QCOMPARE(eventSpy3.counts[QEvent::FocusOut], 0);
       
  2100     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2101     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  2102 
       
  2103     // Tab into line edit 2
       
  2104     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2105     QApplication::processEvents();
       
  2106     edit2->hasFocus();
       
  2107     QVERIFY(!edit1->hasFocus());
       
  2108     QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
       
  2109     QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
       
  2110     QCOMPARE(eventSpy3.counts[QEvent::FocusOut], 1);
       
  2111     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2112     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  2113 
       
  2114     // Tab into right box
       
  2115     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2116     QApplication::processEvents();
       
  2117     QVERIFY(!edit2->hasFocus());
       
  2118     box_2->hasFocus();
       
  2119 
       
  2120     // Tab into right top line edit
       
  2121     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2122     QApplication::processEvents();
       
  2123     QVERIFY(!box_2->hasFocus());
       
  2124     edit1_2->hasFocus();
       
  2125     QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
       
  2126     QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 0);
       
  2127 
       
  2128     // Tab into right font combobox
       
  2129     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2130     QApplication::processEvents();
       
  2131     QVERIFY(!edit1_2->hasFocus());
       
  2132     fontComboBox2->hasFocus();
       
  2133     QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
       
  2134     QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 1);
       
  2135     QCOMPARE(eventSpy2_3.counts[QEvent::FocusIn], 1);
       
  2136     QCOMPARE(eventSpy2_3.counts[QEvent::FocusOut], 0);
       
  2137 
       
  2138     // Tab into right bottom line edit
       
  2139     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2140     QApplication::processEvents();
       
  2141     QVERIFY(!edit1_2->hasFocus());
       
  2142     edit2_2->hasFocus();
       
  2143     QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
       
  2144     QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 1);
       
  2145     QCOMPARE(eventSpy2_3.counts[QEvent::FocusIn], 1);
       
  2146     QCOMPARE(eventSpy2_3.counts[QEvent::FocusOut], 1);
       
  2147     QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
       
  2148     QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 0);
       
  2149 
       
  2150     // Tab into right dial
       
  2151     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
       
  2152     QApplication::processEvents();
       
  2153     QVERIFY(!edit2->hasFocus());
       
  2154     rightDial->hasFocus();
       
  2155     QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
       
  2156 
       
  2157     // Backtab into line edit 2
       
  2158     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2159     QApplication::processEvents();
       
  2160     QVERIFY(!rightDial->hasFocus());
       
  2161     edit2_2->hasFocus();
       
  2162 
       
  2163     // Backtab into the right font combobox
       
  2164     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2165     QApplication::processEvents();
       
  2166     QVERIFY(!edit2_2->hasFocus());
       
  2167     fontComboBox2->hasFocus();
       
  2168 
       
  2169     // Backtab into line edit 1
       
  2170     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2171     QApplication::processEvents();
       
  2172     QVERIFY(!edit2_2->hasFocus());
       
  2173     edit1_2->hasFocus();
       
  2174 
       
  2175     // Backtab into line box
       
  2176     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2177     QApplication::processEvents();
       
  2178     QVERIFY(!edit1_2->hasFocus());
       
  2179     box_2->hasFocus();
       
  2180 
       
  2181     // Backtab into line edit 2
       
  2182     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2183     QApplication::processEvents();
       
  2184     QVERIFY(!rightDial->hasFocus());
       
  2185     edit2->hasFocus();
       
  2186 
       
  2187     // Backtab into the font combobox
       
  2188     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2189     QApplication::processEvents();
       
  2190     QVERIFY(!edit2->hasFocus());
       
  2191     fontComboBox->hasFocus();
       
  2192 
       
  2193     // Backtab into line edit 1
       
  2194     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2195     QApplication::processEvents();
       
  2196     QVERIFY(!fontComboBox->hasFocus());
       
  2197     edit1->hasFocus();
       
  2198 
       
  2199     // Backtab into line box
       
  2200     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2201     QApplication::processEvents();
       
  2202     QVERIFY(!edit1->hasFocus());
       
  2203     box->hasFocus();
       
  2204 
       
  2205     // Backtab into left dial
       
  2206     QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
       
  2207     QApplication::processEvents();
       
  2208     QVERIFY(!box->hasFocus());
       
  2209     leftDial->hasFocus();
       
  2210 
       
  2211     delete view;
       
  2212 }
       
  2213 
       
  2214 void tst_QGraphicsProxyWidget::setFocus_simpleWidget()
       
  2215 {
       
  2216     QGraphicsScene scene;
       
  2217     QLineEdit *edit = new QLineEdit;
       
  2218     QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
       
  2219     editProxy->show();
       
  2220 
       
  2221     QDial *leftDial = new QDial;
       
  2222     QDial *rightDial = new QDial;
       
  2223     QGraphicsView *view = new QGraphicsView(&scene);
       
  2224 
       
  2225     QWidget window;
       
  2226     QHBoxLayout *layout = new QHBoxLayout;
       
  2227     layout->addWidget(leftDial);
       
  2228     layout->addWidget(view);
       
  2229     layout->addWidget(rightDial);
       
  2230     window.setLayout(layout);
       
  2231 
       
  2232     window.show();
       
  2233     QApplication::setActiveWindow(&window);
       
  2234     window.activateWindow();
       
  2235     QTest::qWaitForWindowShown(&window);
       
  2236     QTRY_COMPARE(QApplication::activeWindow(), &window);
       
  2237 
       
  2238     leftDial->setFocus();
       
  2239     QApplication::processEvents();
       
  2240     QTRY_VERIFY(leftDial->hasFocus());
       
  2241 
       
  2242     EventSpy eventSpy(edit);
       
  2243 
       
  2244     // Calling setFocus for the line edit when the view doesn't have input
       
  2245     // focus does not steal focus from the dial. The edit, proxy and scene
       
  2246     // have focus but only in their own little space.
       
  2247     edit->setFocus();
       
  2248     QVERIFY(scene.hasFocus());
       
  2249     QVERIFY(edit->hasFocus());
       
  2250     QVERIFY(!view->hasFocus());
       
  2251     QVERIFY(!view->viewport()->hasFocus());
       
  2252     QVERIFY(leftDial->hasFocus());
       
  2253 
       
  2254     // Clearing focus is a local operation.
       
  2255     edit->clearFocus();
       
  2256     QVERIFY(scene.hasFocus());
       
  2257     QVERIFY(!edit->hasFocus());
       
  2258     QVERIFY(!view->hasFocus());
       
  2259     QVERIFY(leftDial->hasFocus());
       
  2260 
       
  2261     view->setFocus();
       
  2262     QVERIFY(scene.hasFocus());
       
  2263     QVERIFY(view->hasFocus());
       
  2264     QVERIFY(!leftDial->hasFocus());
       
  2265     QVERIFY(!edit->hasFocus());
       
  2266 
       
  2267     scene.clearFocus();
       
  2268     QVERIFY(!scene.hasFocus());
       
  2269 
       
  2270     edit->setFocus();
       
  2271     QVERIFY(scene.hasFocus());
       
  2272     QVERIFY(edit->hasFocus());
       
  2273     QVERIFY(editProxy->hasFocus());
       
  2274 
       
  2275     // Symmetry
       
  2276     editProxy->clearFocus();
       
  2277     QVERIFY(!edit->hasFocus());
       
  2278 
       
  2279     delete view;
       
  2280 }
       
  2281 
       
  2282 void tst_QGraphicsProxyWidget::setFocus_simpleTwoWidgets()
       
  2283 {
       
  2284     QGraphicsScene scene;
       
  2285     QLineEdit *edit = new QLineEdit;
       
  2286     QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
       
  2287     editProxy->show();
       
  2288     QLineEdit *edit2 = new QLineEdit;
       
  2289     QGraphicsProxyWidget *edit2Proxy = scene.addWidget(edit2);
       
  2290     edit2Proxy->show();
       
  2291     edit2Proxy->setPos(editProxy->boundingRect().width() * 1.01, 0);
       
  2292 
       
  2293     QDial *leftDial = new QDial;
       
  2294     QDial *rightDial = new QDial;
       
  2295     QGraphicsView *view = new QGraphicsView(&scene);
       
  2296 
       
  2297     QWidget window;
       
  2298     QHBoxLayout *layout = new QHBoxLayout;
       
  2299     layout->addWidget(leftDial);
       
  2300     layout->addWidget(view);
       
  2301     layout->addWidget(rightDial);
       
  2302     window.setLayout(layout);
       
  2303 
       
  2304     window.show();
       
  2305     QApplication::setActiveWindow(&window);
       
  2306     window.activateWindow();
       
  2307     QTest::qWaitForWindowShown(&window);
       
  2308     QTRY_COMPARE(QApplication::activeWindow(), &window);
       
  2309 
       
  2310     leftDial->setFocus();
       
  2311     QApplication::processEvents();
       
  2312     QTRY_VERIFY(leftDial->hasFocus());
       
  2313 
       
  2314     EventSpy eventSpy(edit);
       
  2315 
       
  2316     view->setFocus();
       
  2317     QVERIFY(!edit->hasFocus());
       
  2318 
       
  2319     edit->setFocus();
       
  2320     QVERIFY(scene.hasFocus());
       
  2321     QVERIFY(edit->hasFocus());
       
  2322     QVERIFY(editProxy->hasFocus());
       
  2323 
       
  2324     edit2->setFocus();
       
  2325     QVERIFY(scene.hasFocus());
       
  2326     QVERIFY(!edit->hasFocus());
       
  2327     QVERIFY(!editProxy->hasFocus());
       
  2328     QVERIFY(edit2->hasFocus());
       
  2329     QVERIFY(edit2Proxy->hasFocus());
       
  2330 
       
  2331     delete view;
       
  2332 }
       
  2333 
       
  2334 void tst_QGraphicsProxyWidget::setFocus_complexTwoWidgets()
       
  2335 {
       
  2336     // ### add event spies to this test.
       
  2337     QGraphicsScene scene;
       
  2338 
       
  2339     QLineEdit *edit1 = new QLineEdit;
       
  2340     edit1->setText("QLineEdit 1");
       
  2341     QLineEdit *edit2 = new QLineEdit;
       
  2342     edit2->setText("QLineEdit 2");
       
  2343     QVBoxLayout *vlayout = new QVBoxLayout;
       
  2344     vlayout->addWidget(edit1);
       
  2345     vlayout->addWidget(edit2);
       
  2346 
       
  2347     QGroupBox *box = new QGroupBox("QGroupBox");
       
  2348     box->setCheckable(true);
       
  2349     box->setChecked(true);
       
  2350     box->setLayout(vlayout);
       
  2351 
       
  2352     QLineEdit *edit1_2 = new QLineEdit;
       
  2353     edit1_2->setText("QLineEdit 1_2");
       
  2354     QLineEdit *edit2_2 = new QLineEdit;
       
  2355     edit2_2->setText("QLineEdit 2_2");
       
  2356     vlayout = new QVBoxLayout;
       
  2357     vlayout->addWidget(edit1_2);
       
  2358     vlayout->addWidget(edit2_2);
       
  2359 
       
  2360     QGroupBox *box_2 = new QGroupBox("QGroupBox 2");
       
  2361     box_2->setCheckable(true);
       
  2362     box_2->setChecked(true);
       
  2363     box_2->setLayout(vlayout);
       
  2364 
       
  2365     QGraphicsProxyWidget *proxy = scene.addWidget(box);
       
  2366     proxy->show();
       
  2367 
       
  2368     QGraphicsProxyWidget *proxy_2 = scene.addWidget(box_2);
       
  2369     proxy_2->setPos(proxy->boundingRect().width() * 1.2, 0);
       
  2370     proxy_2->show();
       
  2371 
       
  2372     QDial *leftDial = new QDial;
       
  2373     QDial *rightDial = new QDial;
       
  2374     QGraphicsView *view = new QGraphicsView(&scene);
       
  2375 
       
  2376     QWidget window;
       
  2377     QHBoxLayout *layout = new QHBoxLayout;
       
  2378     layout->addWidget(leftDial);
       
  2379     layout->addWidget(view);
       
  2380     layout->addWidget(rightDial);
       
  2381     window.setLayout(layout);
       
  2382 
       
  2383     window.show();
       
  2384     QApplication::setActiveWindow(&window);
       
  2385     window.activateWindow();
       
  2386     QTest::qWaitForWindowShown(&window);
       
  2387     QTRY_COMPARE(QApplication::activeWindow(), &window);
       
  2388 
       
  2389     leftDial->setFocus();
       
  2390     QApplication::processEvents();
       
  2391     QTRY_VERIFY(leftDial->hasFocus());
       
  2392 
       
  2393     EventSpy eventSpy(edit1);
       
  2394     EventSpy eventSpy2(edit2);
       
  2395     EventSpy eventSpyBox(box);
       
  2396     EventSpy eventSpy_2(edit1_2);
       
  2397     EventSpy eventSpy2_2(edit2_2);
       
  2398     EventSpy eventSpyBox_2(box_2);
       
  2399 
       
  2400     view->setFocus();
       
  2401 
       
  2402     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 0);
       
  2403 
       
  2404     edit1->setFocus();
       
  2405     QApplication::processEvents();
       
  2406     QVERIFY(scene.hasFocus());
       
  2407     QVERIFY(edit1->hasFocus());
       
  2408     QVERIFY(!box->hasFocus());
       
  2409     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2410     QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 0);
       
  2411 
       
  2412     edit2_2->setFocus();
       
  2413     QApplication::processEvents();
       
  2414     QVERIFY(!edit1->hasFocus());
       
  2415     QVERIFY(!box_2->hasFocus());
       
  2416     QVERIFY(edit2_2->hasFocus());
       
  2417     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2418     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  2419     QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
       
  2420     QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 0);
       
  2421     QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
       
  2422 
       
  2423     box->setFocus();
       
  2424     QApplication::processEvents();
       
  2425     QVERIFY(!edit2_2->hasFocus());
       
  2426     QVERIFY(!edit1->hasFocus());
       
  2427     QVERIFY(box->hasFocus());
       
  2428     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2429     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  2430     QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
       
  2431     QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
       
  2432     QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 1);
       
  2433     QCOMPARE(eventSpyBox.counts[QEvent::FocusOut], 0);
       
  2434     QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
       
  2435     QCOMPARE(eventSpyBox_2.counts[QEvent::FocusOut], 0);
       
  2436 
       
  2437     edit2_2->setFocus();
       
  2438     QApplication::processEvents();
       
  2439     QVERIFY(edit2_2->hasFocus());
       
  2440     QVERIFY(!edit1->hasFocus());
       
  2441     QVERIFY(!box->hasFocus());
       
  2442     QVERIFY(!box_2->hasFocus());
       
  2443     QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
       
  2444     QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
       
  2445     QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 2);
       
  2446     QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
       
  2447     QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 1);
       
  2448     QCOMPARE(eventSpyBox.counts[QEvent::FocusOut], 1);
       
  2449     QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
       
  2450     QCOMPARE(eventSpyBox_2.counts[QEvent::FocusOut], 0);
       
  2451 
       
  2452     delete view;
       
  2453 }
       
  2454 
       
  2455 void tst_QGraphicsProxyWidget::popup_basic()
       
  2456 {
       
  2457     // ProxyWidget should automatically create proxy's when the widget creates a child
       
  2458     QGraphicsScene *scene = new QGraphicsScene;
       
  2459     QGraphicsView view(scene);
       
  2460     view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
       
  2461     view.setGeometry(0, 100, 480, 500);
       
  2462     view.show();
       
  2463 
       
  2464     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  2465     QComboBox *box = new QComboBox;
       
  2466     box->setGeometry(0, 0, 320, 40);
       
  2467     box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
       
  2468 		  << "thursday" << "saturday" << "sunday");
       
  2469     QCOMPARE(proxy->childItems().count(), 0);
       
  2470     proxy->setWidget(box);
       
  2471     proxy->show();
       
  2472     scene->addItem(proxy);
       
  2473 
       
  2474     QCOMPARE(box->pos(), QPoint());
       
  2475     QCOMPARE(proxy->pos(), QPointF());
       
  2476 
       
  2477     QTest::qWaitForWindowShown(&view);
       
  2478     QTest::qWait(125);
       
  2479     QApplication::processEvents();
       
  2480 
       
  2481     QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
       
  2482 		      view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
       
  2483 
       
  2484     QTest::qWait(12);
       
  2485 
       
  2486     QCOMPARE(box->pos(), QPoint());
       
  2487 
       
  2488     QCOMPARE(proxy->childItems().count(), 1);
       
  2489     QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0];
       
  2490     QVERIFY(child->isWidget());
       
  2491     QVERIFY(child->widget());
       
  2492     QStyleOptionComboBox opt;
       
  2493     opt.initFrom(box);
       
  2494     opt.editable = box->isEditable();
       
  2495     if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
       
  2496         QSKIP("Does not work due to SH_Combobox_Popup", SkipAll);
       
  2497     QCOMPARE(child->widget()->parent(), static_cast<QObject*>(box));
       
  2498 
       
  2499     QTest::qWait(12);
       
  2500     QTRY_COMPARE(proxy->pos(), QPointF(box->pos()));
       
  2501     QCOMPARE(child->x(), qreal(box->x()));
       
  2502     QCOMPARE(child->y(), qreal(box->rect().bottom()));
       
  2503 #ifndef Q_OS_WIN
       
  2504     // The popup's coordinates on Windows are in global space,
       
  2505     // regardless.
       
  2506     QCOMPARE(child->widget()->x(), box->x());
       
  2507     QCOMPARE(child->widget()->y(), box->rect().bottom());
       
  2508     QCOMPARE(child->geometry().toRect(), child->widget()->geometry());
       
  2509 #endif
       
  2510     QTest::qWait(12);
       
  2511 }
       
  2512 
       
  2513 void tst_QGraphicsProxyWidget::popup_subwidget()
       
  2514 {
       
  2515     QGroupBox *groupBox = new QGroupBox;
       
  2516     groupBox->setTitle("GroupBox");
       
  2517     groupBox->setCheckable(true);
       
  2518 
       
  2519     QComboBox *box = new QComboBox;
       
  2520     box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
       
  2521 		  << "thursday" << "saturday" << "sunday");
       
  2522 
       
  2523     QVBoxLayout *layout = new QVBoxLayout;
       
  2524     layout->addWidget(new QLineEdit("QLineEdit"));
       
  2525     layout->addWidget(box);
       
  2526     layout->addWidget(new QLineEdit("QLineEdit"));
       
  2527     groupBox->setLayout(layout);
       
  2528 
       
  2529     QGraphicsScene scene;
       
  2530     QGraphicsProxyWidget *groupBoxProxy = scene.addWidget(groupBox);
       
  2531     groupBox->show();
       
  2532     groupBox->move(10000, 10000);
       
  2533     QCOMPARE(groupBox->pos(), QPoint(10000, 10000));
       
  2534     QCOMPARE(groupBoxProxy->pos(), QPointF(10000, 10000));
       
  2535 
       
  2536     QGraphicsView view(&scene);
       
  2537     view.show();
       
  2538 #ifdef Q_WS_X11
       
  2539     qt_x11_wait_for_window_manager(&view);
       
  2540 #endif
       
  2541 
       
  2542     box->showPopup();
       
  2543 
       
  2544     QVERIFY(!groupBoxProxy->childItems().isEmpty());
       
  2545 
       
  2546     QStyleOptionComboBox opt;
       
  2547     opt.initFrom(box);
       
  2548     opt.editable = box->isEditable();
       
  2549     if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
       
  2550         QSKIP("Does not work due to SH_Combobox_Popup", SkipAll);
       
  2551     QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(groupBoxProxy->childItems())[0];
       
  2552     QWidget *popup = child->widget();
       
  2553     QCOMPARE(popup->parent(), static_cast<QObject*>(box));
       
  2554     QCOMPARE(popup->x(), box->mapToGlobal(QPoint()).x());
       
  2555     QCOMPARE(popup->y(), QRect(box->mapToGlobal(QPoint()), box->size()).bottom());
       
  2556     QCOMPARE(popup->size(), child->size().toSize());
       
  2557 }
       
  2558 
       
  2559 void tst_QGraphicsProxyWidget::changingCursor_basic()
       
  2560 {
       
  2561 #if defined(Q_OS_WINCE) && (!defined(GWES_ICONCURS) || defined(QT_NO_CURSOR))
       
  2562     QSKIP("hover events not supported on this platform", SkipAll);
       
  2563 #endif
       
  2564 #ifndef QT_NO_CURSOR
       
  2565     // Confirm that mouse events are working properly by checking that
       
  2566     // when moving the mouse over a line edit it will change the cursor into the I
       
  2567     QGraphicsScene scene;
       
  2568     QGraphicsView view(&scene);
       
  2569     view.show();
       
  2570 
       
  2571     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  2572     QLineEdit *widget = new QLineEdit;
       
  2573     proxy->setWidget(widget);
       
  2574     proxy->show();
       
  2575     scene.addItem(proxy);
       
  2576     QTest::qWaitForWindowShown(&view);
       
  2577     QApplication::processEvents();
       
  2578 
       
  2579     // in
       
  2580     QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
       
  2581     sendMouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
       
  2582     QTest::qWait(125);
       
  2583     QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
       
  2584 
       
  2585     // out
       
  2586     QTest::mouseMove(view.viewport(), QPoint(1, 1));
       
  2587     sendMouseMove(view.viewport(), QPoint(1, 1));
       
  2588     QTest::qWait(125);
       
  2589     QCOMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
       
  2590 #endif
       
  2591 }
       
  2592 
       
  2593 void tst_QGraphicsProxyWidget::tooltip_basic()
       
  2594 {
       
  2595     // Confirm that mouse events are working properly by checking that
       
  2596     // when moving the mouse over a label with a tooptip the tooltip appears
       
  2597     QGraphicsScene scene;
       
  2598     QGraphicsView view(&scene);
       
  2599     view.show();
       
  2600 
       
  2601     QSKIP("Tooltips don't work yet", SkipAll);
       
  2602 
       
  2603     SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
       
  2604     QLabel *widget = new QLabel;
       
  2605     widget->setText("If it ain't tested it's broken");
       
  2606     widget->setToolTip("When in doubt, test");
       
  2607     proxy->setWidget(widget);
       
  2608     widget->show();
       
  2609     scene.addItem(proxy);
       
  2610     QTest::qWait(125);
       
  2611 
       
  2612     // in
       
  2613     QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
       
  2614     QTest::qWait(3000);
       
  2615 
       
  2616     QCOMPARE(proxy->childItems().count(), 1);
       
  2617     QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0];
       
  2618     QVERIFY(child->isWidget());
       
  2619     QVERIFY(child->widget());
       
  2620     QCOMPARE(child->widget()->parent(), static_cast<QObject*>(widget));
       
  2621     QCOMPARE(child->widget()->x(), widget->x()); // ### ???
       
  2622     QCOMPARE(child->widget()->y(), widget->y() + widget->height()); // ### ???
       
  2623 }
       
  2624 
       
  2625 void tst_QGraphicsProxyWidget::childPos_data()
       
  2626 {
       
  2627     QTest::addColumn<bool>("moveCombo");
       
  2628     QTest::addColumn<QPoint>("comboPos");
       
  2629     QTest::addColumn<QPointF>("proxyPos");
       
  2630     QTest::addColumn<QPointF>("menuPos");
       
  2631 
       
  2632     QTest::newRow("0") << true << QPoint() << QPointF() << QPointF();
       
  2633     QTest::newRow("1") << true << QPoint(10, 0) << QPointF(10, 0) << QPointF();
       
  2634     QTest::newRow("2") << true << QPoint(100, 0) << QPointF(100, 0) << QPointF();
       
  2635     QTest::newRow("3") << true << QPoint(1000, 0) << QPointF(1000, 0) << QPointF();
       
  2636     QTest::newRow("4") << true << QPoint(10000, 0) << QPointF(10000, 0) << QPointF();
       
  2637     QTest::newRow("5") << true << QPoint(-10000, 0) << QPointF(-10000, 0) << QPointF();
       
  2638     QTest::newRow("6") << true << QPoint(-1000, 0) << QPointF(-1000, 0) << QPointF();
       
  2639     QTest::newRow("7") << true << QPoint(-100, 0) << QPointF(-100, 0) << QPointF();
       
  2640     QTest::newRow("8") << true << QPoint(-10, 0) << QPointF(-10, 0) << QPointF();
       
  2641     QTest::newRow("0-") << false << QPoint() << QPointF() << QPointF();
       
  2642     QTest::newRow("1-") << false << QPoint(10, 0) << QPointF(10, 0) << QPointF();
       
  2643     QTest::newRow("2-") << false << QPoint(100, 0) << QPointF(100, 0) << QPointF();
       
  2644     QTest::newRow("3-") << false << QPoint(1000, 0) << QPointF(1000, 0) << QPointF();
       
  2645     QTest::newRow("4-") << false << QPoint(10000, 0) << QPointF(10000, 0) << QPointF();
       
  2646     QTest::newRow("5-") << false << QPoint(-10000, 0) << QPointF(-10000, 0) << QPointF();
       
  2647     QTest::newRow("6-") << false << QPoint(-1000, 0) << QPointF(-1000, 0) << QPointF();
       
  2648     QTest::newRow("7-") << false << QPoint(-100, 0) << QPointF(-100, 0) << QPointF();
       
  2649     QTest::newRow("8-") << false << QPoint(-10, 0) << QPointF(-10, 0) << QPointF();
       
  2650 }
       
  2651 
       
  2652 void tst_QGraphicsProxyWidget::childPos()
       
  2653 {
       
  2654 #ifdef Q_OS_IRIX
       
  2655     QSKIP("This test is not reliable on IRIX.", SkipAll);
       
  2656 #endif
       
  2657     QFETCH(bool, moveCombo);
       
  2658     QFETCH(QPoint, comboPos);
       
  2659     QFETCH(QPointF, proxyPos);
       
  2660     QFETCH(QPointF, menuPos);
       
  2661 
       
  2662     QGraphicsScene scene;
       
  2663 
       
  2664     QComboBox *box = new QComboBox;
       
  2665     box->addItem("Item 1");
       
  2666     box->addItem("Item 2");
       
  2667     box->addItem("Item 3");
       
  2668     box->addItem("Item 4");
       
  2669 
       
  2670     if (moveCombo)
       
  2671         box->move(comboPos);
       
  2672 
       
  2673     QGraphicsProxyWidget *proxy = scene.addWidget(box);
       
  2674     proxy->show();
       
  2675     QVERIFY(proxy->isVisible());
       
  2676     QVERIFY(box->isVisible());
       
  2677 
       
  2678     if (!moveCombo)
       
  2679         proxy->setPos(proxyPos);
       
  2680 
       
  2681     QCOMPARE(proxy->pos(), proxyPos);
       
  2682     QCOMPARE(box->pos(), comboPos);
       
  2683 
       
  2684     for (int i = 0; i < 2; ++i) {
       
  2685         box->showPopup();
       
  2686         QApplication::processEvents();
       
  2687         QApplication::processEvents();
       
  2688 
       
  2689         QWidget *menu = 0;
       
  2690         foreach (QObject *child, box->children()) {
       
  2691             if ((menu = qobject_cast<QWidget *>(child)))
       
  2692                 break;
       
  2693         }
       
  2694         QVERIFY(menu);
       
  2695         QVERIFY(menu->isVisible());
       
  2696         QVERIFY(menu->testAttribute(Qt::WA_DontShowOnScreen));
       
  2697 
       
  2698         QCOMPARE(proxy->childItems().size(), 1);
       
  2699         QGraphicsProxyWidget *proxyChild = 0;
       
  2700         foreach (QGraphicsItem *child, proxy->childItems()) {
       
  2701             if (child->isWidget() && (proxyChild = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))))
       
  2702                 break;
       
  2703         }
       
  2704         QVERIFY(proxyChild);
       
  2705         QVERIFY(proxyChild->isVisible());
       
  2706         qreal expectedXPosition = 0.0;
       
  2707 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  2708         // The Mac style wants the popup to show up at QPoint(4 - 11, 1).
       
  2709         // See QMacStyle::subControlRect SC_ComboBoxListBoxPopup.
       
  2710         if (qobject_cast<QMacStyle *>(QApplication::style()))
       
  2711             expectedXPosition = qreal(4 - 11);
       
  2712 #endif
       
  2713         QCOMPARE(proxyChild->pos().x(), expectedXPosition);
       
  2714         menu->hide();
       
  2715     }
       
  2716 }
       
  2717 
       
  2718 void tst_QGraphicsProxyWidget::autoShow()
       
  2719 {
       
  2720     QGraphicsScene scene;
       
  2721     QGraphicsView view(&scene);
       
  2722 
       
  2723     QGraphicsProxyWidget *proxy1 = scene.addWidget(new QPushButton("Button1"));
       
  2724 
       
  2725     QPushButton *button2 = new QPushButton("Button2");
       
  2726     button2->hide();
       
  2727     QGraphicsProxyWidget *proxy2 = new QGraphicsProxyWidget();
       
  2728     proxy2->setWidget(button2);
       
  2729     scene.addItem(proxy2);
       
  2730 
       
  2731     view.show();
       
  2732     QApplication::processEvents();
       
  2733 
       
  2734     QCOMPARE(proxy1->isVisible(), true);
       
  2735     QCOMPARE(proxy2->isVisible(), false);
       
  2736 
       
  2737 }
       
  2738 
       
  2739 Q_DECLARE_METATYPE(QList<QRectF>)
       
  2740 void tst_QGraphicsProxyWidget::windowOpacity()
       
  2741 {
       
  2742     QGraphicsScene scene;
       
  2743     QGraphicsView view(&scene);
       
  2744 
       
  2745     QWidget *widget = new QWidget;
       
  2746     widget->resize(100, 100);
       
  2747     QGraphicsProxyWidget *proxy = scene.addWidget(widget);
       
  2748     proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache);
       
  2749     view.show();
       
  2750     QTest::qWaitForWindowShown(&view);
       
  2751     QApplication::sendPostedEvents();
       
  2752     QTest::qWait(150);
       
  2753 
       
  2754     qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
       
  2755     QSignalSpy signalSpy(&scene, SIGNAL(changed(const QList<QRectF> &)));
       
  2756 
       
  2757     EventSpy eventSpy(widget);
       
  2758     QVERIFY(widget->isVisible());
       
  2759 
       
  2760     widget->setWindowOpacity(0.5);
       
  2761     QApplication::processEvents();
       
  2762 
       
  2763     // Make sure setWindowOpacity triggers an update on the scene,
       
  2764     // and not on the widget or the proxy itself. The entire proxy needs an update
       
  2765     // in case it has a window decoration. Update: QGraphicsItem::CacheMode is
       
  2766     // disabled on platforms without alpha channel support in QPixmap (e.g.,
       
  2767     // X11 without XRender).
       
  2768     int paints = 0;
       
  2769 #ifdef Q_WS_X11
       
  2770     paints = !X11->use_xrender;
       
  2771 #endif
       
  2772     QTRY_COMPARE(eventSpy.counts[QEvent::UpdateRequest], 0);
       
  2773     QTRY_COMPARE(eventSpy.counts[QEvent::Paint], paints);
       
  2774 
       
  2775     QCOMPARE(signalSpy.count(), 1);
       
  2776     const QList<QVariant> arguments = signalSpy.takeFirst();
       
  2777     const QList<QRectF> updateRects = qvariant_cast<QList<QRectF> >(arguments.at(0));
       
  2778     QCOMPARE(updateRects.size(), 1);
       
  2779     QCOMPARE(updateRects.at(0), proxy->sceneBoundingRect());
       
  2780 }
       
  2781 
       
  2782 void tst_QGraphicsProxyWidget::stylePropagation()
       
  2783 {
       
  2784     QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
       
  2785 
       
  2786     QLineEdit *edit = new QLineEdit;
       
  2787     QGraphicsProxyWidget proxy;
       
  2788     proxy.setWidget(edit);
       
  2789 
       
  2790     EventSpy editSpy(edit);
       
  2791     EventSpy proxySpy(&proxy);
       
  2792 
       
  2793     // Widget to proxy
       
  2794     QCOMPARE(proxy.style(), QApplication::style());
       
  2795     edit->setStyle(windowsStyle);
       
  2796     QCOMPARE(editSpy.counts[QEvent::StyleChange], 1);
       
  2797     QCOMPARE(proxySpy.counts[QEvent::StyleChange], 1);
       
  2798     QCOMPARE(proxy.style(), (QStyle *)windowsStyle);
       
  2799     edit->setStyle(0);
       
  2800     QCOMPARE(editSpy.counts[QEvent::StyleChange], 2);
       
  2801     QCOMPARE(proxySpy.counts[QEvent::StyleChange], 2);
       
  2802     QCOMPARE(proxy.style(), QApplication::style());
       
  2803     QCOMPARE(edit->style(), QApplication::style());
       
  2804     QVERIFY(windowsStyle); // not deleted
       
  2805 
       
  2806     // Proxy to widget
       
  2807     proxy.setStyle(windowsStyle);
       
  2808     QCOMPARE(editSpy.counts[QEvent::StyleChange], 3);
       
  2809     QCOMPARE(proxySpy.counts[QEvent::StyleChange], 3);
       
  2810     QCOMPARE(edit->style(), (QStyle *)windowsStyle);
       
  2811     proxy.setStyle(0);
       
  2812     QCOMPARE(editSpy.counts[QEvent::StyleChange], 4);
       
  2813     QCOMPARE(proxySpy.counts[QEvent::StyleChange], 4);
       
  2814     QCOMPARE(proxy.style(), QApplication::style());
       
  2815     QCOMPARE(edit->style(), QApplication::style());
       
  2816     QVERIFY(windowsStyle); // not deleted
       
  2817 
       
  2818     delete windowsStyle;
       
  2819 }
       
  2820 
       
  2821 void tst_QGraphicsProxyWidget::palettePropagation()
       
  2822 {
       
  2823     // Construct a palette with an unlikely setup
       
  2824     QPalette lineEditPalette = QApplication::palette("QLineEdit");
       
  2825     QPalette palette = lineEditPalette;
       
  2826     palette.setBrush(QPalette::Text, Qt::red);
       
  2827 
       
  2828     QLineEdit *edit = new QLineEdit;
       
  2829     QGraphicsProxyWidget proxy;
       
  2830     proxy.setWidget(edit);
       
  2831 
       
  2832     EventSpy editSpy(edit);
       
  2833     EventSpy proxySpy(&proxy);
       
  2834 
       
  2835     // Widget to proxy (no change)
       
  2836     QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
       
  2837     edit->setPalette(palette);
       
  2838     QCOMPARE(editSpy.counts[QEvent::PaletteChange], 1);
       
  2839     QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 0);
       
  2840     QVERIFY(edit->testAttribute(Qt::WA_SetPalette));
       
  2841     QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
       
  2842     QCOMPARE(proxy.palette(), QPalette());
       
  2843     edit->setPalette(QPalette());
       
  2844     QCOMPARE(editSpy.counts[QEvent::PaletteChange], 2);
       
  2845     QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 0);
       
  2846     QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
       
  2847     QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
       
  2848     QCOMPARE(proxy.palette(), QPalette());
       
  2849 
       
  2850     // Proxy to widget
       
  2851     proxy.setPalette(palette);
       
  2852     QVERIFY(proxy.testAttribute(Qt::WA_SetPalette));
       
  2853     QCOMPARE(editSpy.counts[QEvent::PaletteChange], 3);
       
  2854     QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 1);
       
  2855     QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
       
  2856     QCOMPARE(edit->palette(), palette);
       
  2857     QCOMPARE(edit->palette(), proxy.palette());
       
  2858     QCOMPARE(edit->palette().color(QPalette::Text), QColor(Qt::red));
       
  2859     proxy.setPalette(QPalette());
       
  2860     QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
       
  2861     QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
       
  2862     QCOMPARE(editSpy.counts[QEvent::PaletteChange], 4);
       
  2863     QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 2);
       
  2864     QCOMPARE(edit->palette(), lineEditPalette);
       
  2865 }
       
  2866 
       
  2867 void tst_QGraphicsProxyWidget::fontPropagation()
       
  2868 {
       
  2869     // Construct a font with an unlikely setup
       
  2870     QGraphicsScene scene;
       
  2871     QFont lineEditFont = QApplication::font("QLineEdit");
       
  2872     QFont font = lineEditFont;
       
  2873     font.setPointSize(43);
       
  2874 
       
  2875     QLineEdit *edit = new QLineEdit;
       
  2876     QGraphicsProxyWidget proxy;
       
  2877     proxy.setWidget(edit);
       
  2878 
       
  2879     scene.addItem(&proxy);
       
  2880     EventSpy editSpy(edit);
       
  2881     EventSpy proxySpy(&proxy);
       
  2882 
       
  2883     // Widget to proxy (no change)
       
  2884     QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
       
  2885     edit->setFont(font);
       
  2886     QCOMPARE(editSpy.counts[QEvent::FontChange], 1);
       
  2887     QCOMPARE(proxySpy.counts[QEvent::FontChange], 0);
       
  2888     QVERIFY(edit->testAttribute(Qt::WA_SetFont));
       
  2889     QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
       
  2890     QCOMPARE(proxy.font(), lineEditFont);
       
  2891     edit->setFont(QFont());
       
  2892     QCOMPARE(editSpy.counts[QEvent::FontChange], 2);
       
  2893     QCOMPARE(proxySpy.counts[QEvent::FontChange], 0);
       
  2894     QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
       
  2895     QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
       
  2896     QCOMPARE(proxy.font(), lineEditFont);
       
  2897 
       
  2898     // Proxy to widget
       
  2899     proxy.setFont(font);
       
  2900     QApplication::processEvents();  // wait for QEvent::Polish
       
  2901     QVERIFY(proxy.testAttribute(Qt::WA_SetFont));
       
  2902     QCOMPARE(editSpy.counts[QEvent::FontChange], 3);
       
  2903     QCOMPARE(proxySpy.counts[QEvent::FontChange], 1);
       
  2904     QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
       
  2905     QCOMPARE(edit->font(), font);
       
  2906     QCOMPARE(edit->font(), proxy.font());
       
  2907     QCOMPARE(edit->font().pointSize(), 43);
       
  2908     proxy.setFont(QFont());
       
  2909     QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
       
  2910     QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
       
  2911     QCOMPARE(editSpy.counts[QEvent::FontChange], 4);
       
  2912     QCOMPARE(proxySpy.counts[QEvent::FontChange], 2);
       
  2913     QCOMPARE(edit->font(), lineEditFont);
       
  2914 
       
  2915     proxy.setFont(font);
       
  2916     QLineEdit *edit2 = new QLineEdit;
       
  2917     proxy.setWidget(edit2);
       
  2918     delete edit;
       
  2919     QCOMPARE(edit2->font().pointSize(), 43);
       
  2920 }
       
  2921 
       
  2922 class MainWidget : public QMainWindow
       
  2923 {
       
  2924 Q_OBJECT
       
  2925 public:
       
  2926     MainWidget() : QMainWindow() {
       
  2927       view = new QGraphicsView(this);
       
  2928       scene = new QGraphicsScene(this);
       
  2929       item = new QGraphicsWidget();
       
  2930       widget = new QGraphicsProxyWidget(item);
       
  2931       layout = new QGraphicsLinearLayout(item);
       
  2932       layout->addItem(widget);
       
  2933       item->setLayout(layout);
       
  2934       button = new QPushButton("Push me");
       
  2935       widget->setWidget(button);
       
  2936       setCentralWidget(view);
       
  2937       scene->addItem(item);
       
  2938       view->setScene(scene);
       
  2939       scene->setFocusItem(item);
       
  2940       layout->activate();
       
  2941     }
       
  2942     QGraphicsView* view;
       
  2943     QGraphicsScene* scene;
       
  2944     QGraphicsWidget * item;
       
  2945     QGraphicsLinearLayout * layout;
       
  2946     QGraphicsProxyWidget * widget;
       
  2947     QPushButton * button;
       
  2948 };
       
  2949 
       
  2950 void tst_QGraphicsProxyWidget::dontCrashWhenDie()
       
  2951 {
       
  2952     MainWidget *w = new MainWidget();
       
  2953     w->show();
       
  2954     QTest::qWaitForWindowShown(w);
       
  2955     QTest::qWait(100);
       
  2956     QTest::mouseMove(w->view->viewport(), w->view->mapFromScene(w->widget->mapToScene(w->widget->boundingRect().center())));
       
  2957     delete w->item;
       
  2958 
       
  2959     QApplication::processEvents();
       
  2960     delete w;
       
  2961 }
       
  2962 
       
  2963 void tst_QGraphicsProxyWidget::createProxyForChildWidget()
       
  2964 {
       
  2965     QGraphicsScene scene;
       
  2966 
       
  2967     QLineEdit *edit1 = new QLineEdit;
       
  2968     edit1->setText("QLineEdit 1");
       
  2969     QLineEdit *edit2 = new QLineEdit;
       
  2970     edit2->setText("QLineEdit 2");
       
  2971     QCheckBox *checkbox = new QCheckBox("QCheckBox");
       
  2972     QVBoxLayout *vlayout = new QVBoxLayout;
       
  2973 
       
  2974     vlayout->addWidget(edit1);
       
  2975     vlayout->addWidget(edit2);
       
  2976     vlayout->addWidget(checkbox);
       
  2977     vlayout->insertStretch(-1);
       
  2978 
       
  2979     QGroupBox *box = new QGroupBox("QGroupBox");
       
  2980     box->setCheckable(true);
       
  2981     box->setChecked(true);
       
  2982     box->setLayout(vlayout);
       
  2983 
       
  2984     QDial *leftDial = new QDial;
       
  2985     QDial *rightDial = new QDial;
       
  2986 
       
  2987     QWidget window;
       
  2988     QHBoxLayout *layout = new QHBoxLayout;
       
  2989     layout->addWidget(leftDial);
       
  2990     layout->addWidget(box);
       
  2991     layout->addWidget(rightDial);
       
  2992     window.setLayout(layout);
       
  2993 
       
  2994     QVERIFY(window.graphicsProxyWidget() == 0);
       
  2995     QVERIFY(checkbox->graphicsProxyWidget() == 0);
       
  2996 
       
  2997     QGraphicsProxyWidget *windowProxy = scene.addWidget(&window);
       
  2998     QGraphicsView view(&scene);
       
  2999     view.show();
       
  3000     view.resize(500,500);
       
  3001 
       
  3002     QVERIFY(window.graphicsProxyWidget() == windowProxy);
       
  3003     QVERIFY(box->graphicsProxyWidget() == 0);
       
  3004     QVERIFY(checkbox->graphicsProxyWidget() == 0);
       
  3005 
       
  3006     QPointer<QGraphicsProxyWidget> checkboxProxy = windowProxy->createProxyForChildWidget(checkbox);
       
  3007 
       
  3008     QGraphicsProxyWidget *boxProxy = box->graphicsProxyWidget();
       
  3009 
       
  3010     QVERIFY(boxProxy);
       
  3011     QVERIFY(checkbox->graphicsProxyWidget() == checkboxProxy);
       
  3012     QVERIFY(checkboxProxy->parentItem() == boxProxy);
       
  3013     QVERIFY(boxProxy->parentItem() == windowProxy);
       
  3014 
       
  3015     QVERIFY(checkboxProxy->mapToScene(QPointF()) == checkbox->mapTo(&window, QPoint()));
       
  3016     QVERIFY(checkboxProxy->size() == checkbox->size());
       
  3017     QVERIFY(boxProxy->size() == box->size());
       
  3018 
       
  3019     window.resize(500,500);
       
  3020     QVERIFY(windowProxy->size() == QSize(500,500));
       
  3021     QVERIFY(checkboxProxy->mapToScene(QPointF()) == checkbox->mapTo(&window, QPoint()));
       
  3022     QVERIFY(checkboxProxy->size() == checkbox->size());
       
  3023     QVERIFY(boxProxy->size() == box->size());
       
  3024 
       
  3025     QTest::qWait(10);
       
  3026 
       
  3027 
       
  3028     QSignalSpy spy(checkbox, SIGNAL(clicked()));
       
  3029 
       
  3030     QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
       
  3031                       view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
       
  3032     QTRY_COMPARE(spy.count(), 0);
       
  3033     QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
       
  3034                         view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
       
  3035     QTRY_COMPARE(spy.count(), 1);
       
  3036 
       
  3037 
       
  3038 
       
  3039     boxProxy->setWidget(0);
       
  3040 
       
  3041     QVERIFY(checkbox->graphicsProxyWidget() == 0);
       
  3042     QVERIFY(box->graphicsProxyWidget() == 0);
       
  3043     QVERIFY(checkboxProxy == 0);
       
  3044 
       
  3045     delete boxProxy;
       
  3046 }
       
  3047 
       
  3048 class ContextMenuWidget : public QWidget
       
  3049 {
       
  3050     Q_OBJECT
       
  3051 public:
       
  3052     ContextMenuWidget()
       
  3053         : embeddedPopup(false),
       
  3054           gotContextMenuEvent(false)
       
  3055     { }
       
  3056     bool embeddedPopup;
       
  3057     bool gotContextMenuEvent;
       
  3058 protected:
       
  3059     bool event(QEvent *event)
       
  3060     {
       
  3061         if (event->type() == QEvent::ContextMenu)
       
  3062             QTimer::singleShot(0, this, SLOT(checkMenu()));
       
  3063         return QWidget::event(event);
       
  3064     }
       
  3065     void contextMenuEvent(QContextMenuEvent *)
       
  3066     {
       
  3067         gotContextMenuEvent = true;
       
  3068     }
       
  3069 
       
  3070 private slots:
       
  3071     void checkMenu()
       
  3072     {
       
  3073         if (qFindChild<QMenu *>(this))
       
  3074             embeddedPopup = true;
       
  3075         hide();
       
  3076     }
       
  3077 };
       
  3078 
       
  3079 void tst_QGraphicsProxyWidget::actionsContextMenu_data()
       
  3080 {
       
  3081     QTest::addColumn<bool>("actionsContextMenu");
       
  3082     QTest::addColumn<bool>("hasFocus");
       
  3083 
       
  3084     QTest::newRow("without actionsContextMenu and with focus") << false << true;
       
  3085     QTest::newRow("without actionsContextMenu and without focus") << false << false;
       
  3086     QTest::newRow("with actionsContextMenu and focus") << true << true;
       
  3087     QTest::newRow("with actionsContextMenu without focus") << true << false;
       
  3088 }
       
  3089 
       
  3090 void tst_QGraphicsProxyWidget::actionsContextMenu()
       
  3091 {
       
  3092     QFETCH(bool, hasFocus);
       
  3093     QFETCH(bool, actionsContextMenu);
       
  3094 
       
  3095     ContextMenuWidget *widget = new ContextMenuWidget;
       
  3096     if (actionsContextMenu) {
       
  3097         widget->addAction(new QAction("item 1", widget));
       
  3098         widget->addAction(new QAction("item 2", widget));
       
  3099         widget->addAction(new QAction("item 3", widget));
       
  3100         widget->setContextMenuPolicy(Qt::ActionsContextMenu);
       
  3101     }
       
  3102     QGraphicsScene scene;
       
  3103 
       
  3104     QGraphicsView view(&scene);
       
  3105     view.show();
       
  3106     QApplication::setActiveWindow(&view);
       
  3107     QTest::qWaitForWindowShown(&view);
       
  3108     view.setFocus();
       
  3109     QTRY_VERIFY(view.hasFocus());
       
  3110 
       
  3111     if (hasFocus)
       
  3112         scene.addWidget(widget)->setFocus();
       
  3113     else
       
  3114         scene.addWidget(widget)->clearFocus();
       
  3115 
       
  3116     QApplication::processEvents();
       
  3117 
       
  3118     QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse,
       
  3119                                        view.viewport()->rect().center(),
       
  3120                                        view.viewport()->mapToGlobal(view.viewport()->rect().center()));
       
  3121     contextMenuEvent.accept();
       
  3122     qApp->sendEvent(view.viewport(), &contextMenuEvent);
       
  3123 
       
  3124     if (hasFocus) {
       
  3125         if (actionsContextMenu) {
       
  3126             //actionsContextMenu embedded popup but no contextMenuEvent (widget has focus)
       
  3127             QVERIFY(widget->embeddedPopup);
       
  3128             QVERIFY(!widget->gotContextMenuEvent);
       
  3129         } else {
       
  3130             //no embedded popup but contextMenuEvent (widget has focus)
       
  3131             QVERIFY(!widget->embeddedPopup);
       
  3132             QVERIFY(widget->gotContextMenuEvent);
       
  3133         }
       
  3134     } else {
       
  3135         //qgraphicsproxywidget doesn't have the focus, the widget must not receive any contextMenuEvent and must not create any QMenu
       
  3136         QVERIFY(!widget->embeddedPopup);
       
  3137         QVERIFY(!widget->gotContextMenuEvent);
       
  3138     }
       
  3139 
       
  3140 }
       
  3141 
       
  3142 
       
  3143 void tst_QGraphicsProxyWidget::deleteProxyForChildWidget()
       
  3144 {
       
  3145     QDialog dialog;
       
  3146     dialog.resize(320, 120);
       
  3147     dialog.move(80, 40);
       
  3148 
       
  3149     QGraphicsScene scene;
       
  3150     scene.setSceneRect(QRectF(0, 0, 640, 480));
       
  3151     QGraphicsView view(&scene);
       
  3152     QComboBox *combo = new QComboBox;
       
  3153     combo->addItems(QStringList() << "red" << "green" << "blue" << "white" << "black" << "yellow" << "cyan" << "magenta");
       
  3154     dialog.setLayout(new QVBoxLayout);
       
  3155     dialog.layout()->addWidget(combo);
       
  3156 
       
  3157     QGraphicsProxyWidget *proxy = scene.addWidget(&dialog);
       
  3158     view.show();
       
  3159 
       
  3160     proxy->setWidget(0);
       
  3161     //just don't crash
       
  3162     QApplication::processEvents();
       
  3163     delete combo;
       
  3164 }
       
  3165 
       
  3166 void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data()
       
  3167 {
       
  3168     QTest::addColumn<bool>("bypass");
       
  3169 
       
  3170     QTest::newRow("autoembed") << false;
       
  3171     QTest::newRow("bypass") << true;
       
  3172 }
       
  3173 
       
  3174 void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
       
  3175 {
       
  3176     QFETCH(bool, bypass);
       
  3177 
       
  3178     QWidget *widget = new QWidget;
       
  3179     widget->resize(100, 100);
       
  3180 
       
  3181     QGraphicsScene scene;
       
  3182     QGraphicsView view(&scene);
       
  3183     view.show();
       
  3184 
       
  3185     QGraphicsProxyWidget *proxy = scene.addWidget(widget);
       
  3186 
       
  3187     QCOMPARE(proxy->widget(), widget);
       
  3188     QVERIFY(proxy->childItems().isEmpty());
       
  3189 
       
  3190     Qt::WindowFlags flags;
       
  3191     flags |= Qt::Dialog;
       
  3192     if (bypass)
       
  3193         flags |= Qt::BypassGraphicsProxyWidget;
       
  3194     QFileDialog *dialog = new QFileDialog(widget, flags);
       
  3195     dialog->setOption(QFileDialog::DontUseNativeDialog, true);
       
  3196     dialog->show();
       
  3197 
       
  3198     QCOMPARE(proxy->childItems().size(), bypass ? 0 : 1);
       
  3199     if (!bypass)
       
  3200         QCOMPARE(((QGraphicsProxyWidget *)proxy->childItems().first())->widget(), (QWidget *)dialog);
       
  3201 
       
  3202     dialog->hide();
       
  3203     QApplication::processEvents();
       
  3204     delete dialog;
       
  3205     delete widget;
       
  3206 }
       
  3207 
       
  3208 static void makeDndEvent(QGraphicsSceneDragDropEvent *event, QGraphicsView *view, const QPointF &pos)
       
  3209 {
       
  3210     event->setScenePos(pos);
       
  3211     event->setScreenPos(view->mapToGlobal(view->mapFromScene(pos)));
       
  3212     event->setButtons(Qt::LeftButton);
       
  3213     event->setModifiers(0);
       
  3214     event->setPossibleActions(Qt::CopyAction);
       
  3215     event->setProposedAction(Qt::CopyAction);
       
  3216     event->setDropAction(Qt::CopyAction);
       
  3217     event->setWidget(view->viewport());
       
  3218     event->setSource(view->viewport());
       
  3219     event->ignore();
       
  3220 }
       
  3221 
       
  3222 void tst_QGraphicsProxyWidget::dragDrop()
       
  3223 {
       
  3224     QPushButton *button = new QPushButton; // acceptDrops(false)
       
  3225     QLineEdit *edit = new QLineEdit; // acceptDrops(true)
       
  3226 
       
  3227     QGraphicsScene scene;
       
  3228     QGraphicsProxyWidget *buttonProxy = scene.addWidget(button);
       
  3229     QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
       
  3230     QVERIFY(buttonProxy->acceptDrops());
       
  3231     QVERIFY(editProxy->acceptDrops());
       
  3232 
       
  3233     button->setGeometry(0, 0, 100, 50);
       
  3234     edit->setGeometry(0, 60, 100, 50);
       
  3235 
       
  3236     QGraphicsView view(&scene);
       
  3237     view.show();
       
  3238 #ifdef Q_WS_X11
       
  3239     qt_x11_wait_for_window_manager(&view);
       
  3240 #endif
       
  3241 
       
  3242     QMimeData data;
       
  3243     data.setText("hei");
       
  3244     {
       
  3245         QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragEnter);
       
  3246         makeDndEvent(&event, &view, QPointF(50, 25));
       
  3247         event.setMimeData(&data);
       
  3248         qApp->sendEvent(&scene, &event);
       
  3249         QVERIFY(event.isAccepted());
       
  3250     }
       
  3251     {
       
  3252         QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
       
  3253         makeDndEvent(&event, &view, QPointF(50, 25));
       
  3254         event.setMimeData(&data);
       
  3255         qApp->sendEvent(&scene, &event);
       
  3256         QVERIFY(!event.isAccepted());
       
  3257     }
       
  3258     {
       
  3259         QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
       
  3260         makeDndEvent(&event, &view, QPointF(50, 75));
       
  3261         event.setMimeData(&data);
       
  3262         qApp->sendEvent(&scene, &event);
       
  3263         QVERIFY(event.isAccepted());
       
  3264     }
       
  3265     {
       
  3266         QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDrop);
       
  3267         makeDndEvent(&event, &view, QPointF(50, 75));
       
  3268         event.setMimeData(&data);
       
  3269         qApp->sendEvent(&scene, &event);
       
  3270         QVERIFY(event.isAccepted());
       
  3271     }
       
  3272     QCOMPARE(edit->text(), QString("hei"));
       
  3273 }
       
  3274 
       
  3275 void tst_QGraphicsProxyWidget::windowFlags_data()
       
  3276 {
       
  3277     QTest::addColumn<int>("proxyFlags");
       
  3278     QTest::addColumn<int>("widgetFlags");
       
  3279     QTest::addColumn<int>("resultingProxyFlags");
       
  3280     QTest::addColumn<int>("resultingWidgetFlags");
       
  3281 
       
  3282     QTest::newRow("proxy(0) widget(0)") << 0 << 0 << 0 << int(Qt::Window);
       
  3283     QTest::newRow("proxy(window)") << int(Qt::Window) << 0 << int(Qt::Window) << int(Qt::Window);
       
  3284     QTest::newRow("proxy(window) widget(window)") << int(Qt::Window) << int(Qt::Window) << int(Qt::Window) << int(Qt::Window);
       
  3285     QTest::newRow("proxy(0) widget(window)") << int(0) << int(Qt::Window) << int(0) << int(Qt::Window);
       
  3286 }
       
  3287 
       
  3288 void tst_QGraphicsProxyWidget::windowFlags()
       
  3289 {
       
  3290     QFETCH(int, proxyFlags);
       
  3291     QFETCH(int, widgetFlags);
       
  3292     QFETCH(int, resultingProxyFlags);
       
  3293     QFETCH(int, resultingWidgetFlags);
       
  3294     Qt::WindowFlags proxyWFlags = Qt::WindowFlags(proxyFlags);
       
  3295     Qt::WindowFlags widgetWFlags = Qt::WindowFlags(widgetFlags);
       
  3296     Qt::WindowFlags resultingProxyWFlags = Qt::WindowFlags(resultingProxyFlags);
       
  3297     Qt::WindowFlags resultingWidgetWFlags = Qt::WindowFlags(resultingWidgetFlags);
       
  3298 
       
  3299     QGraphicsProxyWidget proxy(0, proxyWFlags);
       
  3300     QVERIFY((proxy.windowFlags() & proxyWFlags) == proxyWFlags);
       
  3301 
       
  3302     QWidget *widget = new QWidget(0, widgetWFlags);
       
  3303     QVERIFY((widget->windowFlags() & widgetWFlags) == widgetWFlags);
       
  3304 
       
  3305     proxy.setWidget(widget);
       
  3306 
       
  3307     if (resultingProxyFlags == 0)
       
  3308         QVERIFY(!proxy.windowFlags());
       
  3309     else
       
  3310         QVERIFY((proxy.windowFlags() & resultingProxyWFlags) == resultingProxyWFlags);
       
  3311     QVERIFY((widget->windowFlags() & resultingWidgetWFlags) == resultingWidgetWFlags);
       
  3312 }
       
  3313 
       
  3314 void tst_QGraphicsProxyWidget::comboboxWindowFlags()
       
  3315 {
       
  3316     QComboBox *comboBox = new QComboBox;
       
  3317     comboBox->addItem("Item 1");
       
  3318     comboBox->addItem("Item 2");
       
  3319     comboBox->addItem("Item 3");
       
  3320     QWidget *embedWidget = comboBox;
       
  3321 
       
  3322     QGraphicsScene scene;
       
  3323     QGraphicsProxyWidget *proxy = scene.addWidget(embedWidget);
       
  3324     proxy->setWindowFlags(Qt::Window);
       
  3325     QVERIFY(embedWidget->isWindow());
       
  3326     QVERIFY(proxy->isWindow());
       
  3327 
       
  3328     comboBox->showPopup();
       
  3329 
       
  3330     QCOMPARE(proxy->childItems().size(), 1);
       
  3331     QGraphicsItem *popupProxy = proxy->childItems().first();
       
  3332     QVERIFY(popupProxy->isWindow());
       
  3333     QVERIFY((static_cast<QGraphicsWidget *>(popupProxy)->windowFlags() & Qt::Popup) == Qt::Popup);
       
  3334 }
       
  3335 
       
  3336 void tst_QGraphicsProxyWidget::updateAndDelete()
       
  3337 {
       
  3338     QGraphicsScene scene;
       
  3339     QGraphicsProxyWidget *proxy = scene.addWidget(new QPushButton("Hello World"));
       
  3340     View view(&scene);
       
  3341     view.show();
       
  3342 #ifdef Q_WS_X11
       
  3343     qt_x11_wait_for_window_manager(&view);
       
  3344 #endif
       
  3345     QTest::qWait(20);
       
  3346     QTRY_VERIFY(view.npaints > 0);
       
  3347 
       
  3348     const QRect itemDeviceBoundingRect = proxy->deviceTransform(view.viewportTransform())
       
  3349                                          .mapRect(proxy->boundingRect()).toRect();
       
  3350     const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
       
  3351 
       
  3352     view.npaints = 0;
       
  3353     view.paintEventRegion = QRegion();
       
  3354 
       
  3355     // Update and hide.
       
  3356     proxy->update();
       
  3357     proxy->hide();
       
  3358     QTest::qWait(50);
       
  3359     QCOMPARE(view.npaints, 1);
       
  3360     QCOMPARE(view.paintEventRegion, expectedRegion);
       
  3361 
       
  3362     proxy->show();
       
  3363     QTest::qWait(50);
       
  3364     view.npaints = 0;
       
  3365     view.paintEventRegion = QRegion();
       
  3366 
       
  3367     // Update and delete.
       
  3368     proxy->update();
       
  3369     delete proxy;
       
  3370     QTest::qWait(50);
       
  3371     QCOMPARE(view.npaints, 1);
       
  3372     QCOMPARE(view.paintEventRegion, expectedRegion);
       
  3373 }
       
  3374 
       
  3375 class InputMethod_LineEdit : public QLineEdit
       
  3376 {
       
  3377     bool event(QEvent *e)
       
  3378     {
       
  3379         if (e->type() == QEvent::InputMethod)
       
  3380             ++inputMethodEvents;
       
  3381         return QLineEdit::event(e);
       
  3382     }
       
  3383 public:
       
  3384     int inputMethodEvents;
       
  3385 };
       
  3386 
       
  3387 void tst_QGraphicsProxyWidget::inputMethod()
       
  3388 {
       
  3389     QGraphicsScene scene;
       
  3390 
       
  3391     // check that the proxy is initialized with the correct input method sensitivity
       
  3392     for (int i = 0; i < 2; ++i)
       
  3393     {
       
  3394         QLineEdit *lineEdit = new QLineEdit;
       
  3395         lineEdit->setAttribute(Qt::WA_InputMethodEnabled, !!i);
       
  3396         QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit);
       
  3397         QCOMPARE(!!(proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod), !!i);
       
  3398     }
       
  3399 
       
  3400     // check that input method events are only forwarded to widgets with focus
       
  3401     for (int i = 0; i < 2; ++i)
       
  3402     {
       
  3403         InputMethod_LineEdit *lineEdit = new InputMethod_LineEdit;
       
  3404         lineEdit->setAttribute(Qt::WA_InputMethodEnabled, true);
       
  3405         QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit);
       
  3406 
       
  3407         if (i)
       
  3408             lineEdit->setFocus();
       
  3409 
       
  3410         lineEdit->inputMethodEvents = 0;
       
  3411         QInputMethodEvent event;
       
  3412         qApp->sendEvent(proxy, &event);
       
  3413         QCOMPARE(lineEdit->inputMethodEvents, i);
       
  3414     }
       
  3415 }
       
  3416 
       
  3417 void tst_QGraphicsProxyWidget::clickFocus()
       
  3418 {
       
  3419     QGraphicsScene scene;
       
  3420     scene.setItemIndexMethod(QGraphicsScene::NoIndex);
       
  3421     QGraphicsProxyWidget *proxy = scene.addWidget(new QLineEdit);
       
  3422 
       
  3423     EventSpy proxySpy(proxy);
       
  3424     EventSpy widgetSpy(proxy->widget());
       
  3425 
       
  3426     QGraphicsView view(&scene);
       
  3427     view.setFrameStyle(0);
       
  3428     view.resize(300, 300);
       
  3429     view.show();
       
  3430 #ifdef Q_WS_X11
       
  3431     qt_x11_wait_for_window_manager(&view);
       
  3432 #endif
       
  3433     QApplication::setActiveWindow(&view);
       
  3434     QTest::qWait(25);
       
  3435     QTRY_COMPARE(QApplication::activeWindow(), &view);
       
  3436 
       
  3437     QVERIFY(!proxy->hasFocus());
       
  3438     QVERIFY(!proxy->widget()->hasFocus());
       
  3439 
       
  3440     QCOMPARE(proxySpy.counts[QEvent::FocusIn], 0);
       
  3441     QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
       
  3442     QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 0);
       
  3443     QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
       
  3444 
       
  3445     QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center());
       
  3446     // Spontaneous mouse click sets focus on a clickable widget.
       
  3447     for (int retry = 0; retry < 50 && !proxy->hasFocus(); retry++)
       
  3448         QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
       
  3449     QVERIFY(proxy->hasFocus());
       
  3450     QVERIFY(proxy->widget()->hasFocus());
       
  3451     QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1);
       
  3452     QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1);
       
  3453 
       
  3454     scene.setFocusItem(0);
       
  3455     QVERIFY(!proxy->hasFocus());
       
  3456     QVERIFY(!proxy->widget()->hasFocus());
       
  3457     QCOMPARE(proxySpy.counts[QEvent::FocusOut], 1);
       
  3458     QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 1);
       
  3459 
       
  3460     // Non-spontaneous mouse click sets focus if the widget has been clicked before
       
  3461     {
       
  3462         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
       
  3463         event.setScenePos(lineEditCenter);
       
  3464         event.setButton(Qt::LeftButton);
       
  3465         qApp->sendEvent(&scene, &event);
       
  3466         QVERIFY(proxy->hasFocus());
       
  3467         QVERIFY(proxy->widget()->hasFocus());
       
  3468         QCOMPARE(proxySpy.counts[QEvent::FocusIn], 2);
       
  3469         QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 2);
       
  3470     }
       
  3471 
       
  3472     scene.setFocusItem(0);
       
  3473     proxy->setWidget(new QLineEdit); // resets focusWidget
       
  3474     QVERIFY(!proxy->hasFocus());
       
  3475     QVERIFY(!proxy->widget()->hasFocus());
       
  3476     QCOMPARE(proxySpy.counts[QEvent::FocusOut], 2);
       
  3477     QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 2);
       
  3478 
       
  3479     // Non-spontaneous mouse click does not set focus on the embedded widget.
       
  3480     {
       
  3481         QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
       
  3482         event.setScenePos(lineEditCenter);
       
  3483         event.setButton(Qt::LeftButton);
       
  3484         qApp->sendEvent(&scene, &event);
       
  3485         QVERIFY(!proxy->hasFocus());
       
  3486         QVERIFY(!proxy->widget()->hasFocus());
       
  3487         QCOMPARE(proxySpy.counts[QEvent::FocusIn], 2);
       
  3488         QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 2);
       
  3489     }
       
  3490 
       
  3491     scene.setFocusItem(0);
       
  3492     QVERIFY(!proxy->hasFocus());
       
  3493     QVERIFY(!proxy->widget()->hasFocus());
       
  3494     QCOMPARE(proxySpy.counts[QEvent::FocusOut], 2);
       
  3495     QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 2);
       
  3496 
       
  3497     // Spontaneous click on non-clickable widget does not give focus.
       
  3498     proxy->widget()->setFocusPolicy(Qt::NoFocus);
       
  3499     QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
       
  3500     QVERIFY(!proxy->hasFocus());
       
  3501     QVERIFY(!proxy->widget()->hasFocus());
       
  3502 }
       
  3503 
       
  3504 QTEST_MAIN(tst_QGraphicsProxyWidget)
       
  3505 #include "tst_qgraphicsproxywidget.moc"
       
  3506 
       
  3507 #else // QT_NO_STYLE_CLEANLOOKS
       
  3508 QTEST_NOOP_MAIN
       
  3509 #endif