qt6windows7/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp

3455 lines
116 KiB
C++
Raw Normal View History

2023-10-30 06:33:08 +08:00
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QTest>
#include <qgraphicswidget.h>
#include <qgraphicsscene.h>
#include <qgraphicssceneevent.h>
#include <qgraphicsview.h>
#include <qstyleoption.h>
#include <qgraphicslinearlayout.h>
#include <qlineedit.h>
#include <qboxlayout.h>
#include <qaction.h>
#include <qwidgetaction.h>
#include <qcommonstyle.h>
#include <qstylefactory.h>
#include <qscreen.h>
#include <qsignalspy.h>
#include <QtWidgets/private/qapplication_p.h>
typedef QList<QGraphicsItem *> QGraphicsItemList;
class EventSpy : public QObject
{
Q_OBJECT
public:
EventSpy(QObject *watched, QEvent::Type type)
: _count(0), spied(type)
{
watched->installEventFilter(this);
}
int count() const { return _count; }
protected:
bool eventFilter(QObject *watched, QEvent *event) override
{
Q_UNUSED(watched);
if (event->type() == spied)
++_count;
return false;
}
int _count;
QEvent::Type spied;
};
class tst_QGraphicsWidget : public QObject {
Q_OBJECT
private slots:
void qgraphicswidget();
void activation();
void boundingRect_data();
void boundingRect();
void dumpFocusChain_data();
void dumpFocusChain();
void focusWidget_data();
void focusWidget();
void focusWidget2();
void focusWidget3();
void focusPolicy_data();
void focusPolicy();
void font_data();
void font();
void fontPropagation();
void fontChangedEvent();
void fontPropagationWidgetItemWidget();
void fontPropagationSceneChange();
void geometry_data();
void geometry();
void geometryChanged();
void width();
void height();
void getContentsMargins_data();
void getContentsMargins();
void initStyleOption_data();
void initStyleOption();
void layout_data();
void layout();
void layoutDirection_data();
void layoutDirection();
void paint_data();
void paint();
void palettePropagation();
void parentWidget_data();
void parentWidget();
void resize_data();
void resize();
void setAttribute_data();
void setAttribute();
void setStyle_data();
void setStyle();
void setTabOrder_data();
void setTabOrder();
void setTabOrderAndReparent();
void topLevelWidget_data();
void topLevelWidget();
void unsetLayoutDirection_data();
void unsetLayoutDirection();
void focusNextPrevChild_data();
void focusNextPrevChild();
void verifyFocusChain();
void updateFocusChainWhenChildDie();
void sizeHint_data();
void sizeHint();
void consistentPosSizeGeometry_data();
void consistentPosSizeGeometry();
void setSizes_data();
void setSizes();
void closePopupOnOutsideClick();
void defaultSize();
void explicitMouseGrabber();
void implicitMouseGrabber();
void doubleClickAfterExplicitMouseGrab();
void popupMouseGrabber();
void windowFlags_data();
void windowFlags();
void shortcutsDeletion();
void painterStateProtectionOnWindowFrame();
void ensureClipping();
void widgetSendsGeometryChanges();
void respectHFW();
void addChildInpolishEvent();
void polishEvent();
void polishEvent2();
void autoFillBackground();
void initialShow();
void itemChangeEvents();
void itemSendGeometryPosChangesDeactivated();
void fontPropagatesResolveToChildren();
void fontPropagatesResolveToGrandChildren();
void fontPropagatesResolveInParentChange();
void fontPropagatesResolveViaNonWidget();
void fontPropagatesResolveFromScene();
void tabFocus();
void windowFrameSectionAt();
// Task fixes
void task236127_bspTreeIndexFails();
void task243004_setStyleCrash();
void task250119_shortcutContext();
void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
void QTBUG_45867_send_itemChildAddedChange_to_parent();
private:
static bool hasWindowActivation();
};
bool tst_QGraphicsWidget::hasWindowActivation()
{
return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
}
// Subclass that exposes the protected functions.
class SubQGraphicsWidget : public QGraphicsWidget {
public:
SubQGraphicsWidget(QGraphicsItem *parent = nullptr, Qt::WindowFlags windowFlags = { })
: QGraphicsWidget(parent, windowFlags), eventCount(0)
{ }
void initStyleOption(QStyleOption *option) const override
{ QGraphicsWidget::initStyleOption(option); }
void call_changeEvent(QEvent* event)
{ return QGraphicsWidget::changeEvent(event); }
bool call_event(QEvent *e)
{ return event(e); }
void call_focusInEvent(QFocusEvent* event)
{ return QGraphicsWidget::focusInEvent(event); }
bool call_focusNextPrevChild(bool next)
{ return QGraphicsWidget::focusNextPrevChild(next); }
void call_focusOutEvent(QFocusEvent* event)
{ return QGraphicsWidget::focusOutEvent(event); }
void call_hideEvent(QHideEvent* event)
{ return QGraphicsWidget::hideEvent(event); }
QVariant call_itemChange(QGraphicsItem::GraphicsItemChange change, QVariant const& value)
{ return QGraphicsWidget::itemChange(change, value); }
void call_moveEvent(QGraphicsSceneMoveEvent* event)
{ return QGraphicsWidget::moveEvent(event); }
void call_polishEvent()
{ return QGraphicsWidget::polishEvent(); }
QVariant call_propertyChange(QString const& propertyName, QVariant const& value)
{ return QGraphicsWidget::propertyChange(propertyName, value); }
void call_resizeEvent(QGraphicsSceneResizeEvent* event)
{ return QGraphicsWidget::resizeEvent(event); }
bool call_sceneEvent(QEvent* event)
{ return QGraphicsWidget::sceneEvent(event); }
void call_showEvent(QShowEvent* event)
{ return QGraphicsWidget::showEvent(event); }
QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
{ return QGraphicsWidget::sizeHint(which, constraint); }
void call_updateGeometry()
{ return QGraphicsWidget::updateGeometry(); }
Qt::WindowFrameSection call_windowFrameSectionAt(const QPointF &pos) const
{ return QGraphicsWidget::windowFrameSectionAt(pos); }
int eventCount;
Qt::LayoutDirection m_painterLayoutDirection;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
m_painterLayoutDirection = painter->layoutDirection();
QGraphicsWidget::paint(painter, option, widget);
if (hasFocus()) {
painter->setPen(Qt::DotLine);
painter->drawRect(rect());
}
//painter->drawText(QPointF(0,15), data(0).toString());
}
protected:
bool event(QEvent *event) override
{
eventCount++;
return QGraphicsWidget::event(event);
}
};
class SizeHinter : public QGraphicsWidget
{
public:
SizeHinter(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = { },
const QSizeF &min = QSizeF(5,5),
const QSizeF &pref = QSizeF(50, 50),
const QSizeF &max = QSizeF(500, 500))
: QGraphicsWidget(parent, wFlags)
{
m_sizes[Qt::MinimumSize] = min;
m_sizes[Qt::PreferredSize] = pref;
m_sizes[Qt::MaximumSize] = max;
}
void setSizeHint(Qt::SizeHint which, const QSizeF &newSizeHint)
{
m_sizes[which] = newSizeHint;
}
protected:
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override
{
Q_UNUSED(constraint);
return m_sizes[which];
}
private:
QSizeF m_sizes[4];
};
void tst_QGraphicsWidget::qgraphicswidget()
{
SubQGraphicsWidget widget;
QVERIFY(widget.isVisible());
QVERIFY(!widget.isWindow());
QCOMPARE(widget.boundingRect(), QRectF(0, 0, 0, 0));
QCOMPARE(widget.focusWidget(), nullptr);
QCOMPARE(widget.focusPolicy(), Qt::NoFocus);
QCOMPARE(widget.font(), QFont());
QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size()));
QCOMPARE(widget.layout(), nullptr);
QCOMPARE(widget.layoutDirection(), Qt::LeftToRight);
QCOMPARE(widget.palette(), QPalette());
QCOMPARE(widget.parentWidget(), nullptr);
QCOMPARE(widget.rect(), QRectF(QPointF(), widget.size()));
QCOMPARE(widget.size(), QSizeF(0, 0));
QVERIFY(widget.style() != (QStyle*)0);
QCOMPARE(widget.testAttribute(Qt::WA_AcceptDrops), false);
QCOMPARE(widget.topLevelWidget(), (QGraphicsWidget*)&widget);
QCOMPARE(widget.type(), (int)QGraphicsWidget::Type);
QCOMPARE(widget.call_propertyChange(QString(), QVariant()), QVariant());
widget.call_sizeHint(Qt::PreferredSize, QSizeF());
QGraphicsScene scene;
QGraphicsWidget *parent = new QGraphicsWidget;
SizeHinter *child = new SizeHinter(parent);
QCOMPARE(child->minimumSize(), QSizeF(5, 5));
}
void tst_QGraphicsWidget::activation()
{
QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsWidget *window1 = new QGraphicsWidget(0, Qt::Window);
QGraphicsWidget *window2 = new QGraphicsWidget(0, Qt::Window);
QVERIFY(!widget->isActiveWindow());
QVERIFY(!window1->isActiveWindow());
QVERIFY(!window2->isActiveWindow());
QGraphicsScene scene;
scene.addItem(widget);
scene.addItem(window1);
scene.addItem(window2);
QVERIFY(!widget->isActiveWindow());
QVERIFY(!window1->isActiveWindow());
QVERIFY(!window2->isActiveWindow());
QEvent activateEvent(QEvent::WindowActivate);
QApplication::sendEvent(&scene, &activateEvent);
QVERIFY(!widget->isActiveWindow());
QVERIFY(window1->isActiveWindow());
QVERIFY(!window2->isActiveWindow());
scene.setActiveWindow(window1);
QVERIFY(!widget->isActiveWindow());
QVERIFY(window1->isActiveWindow());
QVERIFY(!window2->isActiveWindow());
QEvent deactivateEvent(QEvent::WindowDeactivate);
QApplication::sendEvent(&scene, &deactivateEvent);
QVERIFY(!widget->isActiveWindow());
QVERIFY(!window1->isActiveWindow());
QVERIFY(!window2->isActiveWindow());
}
void tst_QGraphicsWidget::boundingRect_data()
{
QTest::addColumn<QSizeF>("size");
QTest::newRow("null") << QSizeF(0, 0);
QTest::newRow("avg") << QSizeF(10, 10);
}
// QRectF boundingRect() const public
void tst_QGraphicsWidget::boundingRect()
{
QFETCH(QSizeF, size);
SubQGraphicsWidget widget;
widget.resize(size);
QCOMPARE(widget.rect(), QRectF(QPointF(), size));
QCOMPARE(widget.boundingRect(), QRectF(QPointF(0, 0), size));
}
void tst_QGraphicsWidget::dumpFocusChain_data()
{
QTest::addColumn<bool>("scene");
QTest::addColumn<int>("children");
QTest::addColumn<bool>("setFocus");
QTest::newRow("empty world") << false << 0 << false;
QTest::newRow("one world") << true << 2 << false;
QTest::newRow("one world w/focus") << true << 2 << true;
}
// void dumpFocusChain(QGraphicsScene* scene) public (static)
void tst_QGraphicsWidget::dumpFocusChain()
{
// ### this test is very strange...
QFETCH(bool, scene);
SubQGraphicsWidget *parent = new SubQGraphicsWidget;
QGraphicsScene *theScene = nullptr;
if (scene) {
theScene = new QGraphicsScene(this);
theScene->addItem(parent);
}
QFETCH(int, children);
QFETCH(bool, setFocus);
for (int i = 0; i < children; ++i) {
SubQGraphicsWidget *widget = new SubQGraphicsWidget(parent);
if (setFocus) {
widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
if (scene)
theScene->setFocusItem(widget);
}
}
if (!scene)
delete parent;
}
void tst_QGraphicsWidget::focusWidget_data()
{
QTest::addColumn<int>("childCount");
QTest::addColumn<int>("childWithFocus");
QTest::newRow("none") << 0 << 0;
QTest::newRow("first") << 3 << 0;
QTest::newRow("last") << 3 << 2;
}
// QGraphicsWidget* focusWidget() const public
void tst_QGraphicsWidget::focusWidget()
{
SubQGraphicsWidget *parent = new SubQGraphicsWidget;
QCOMPARE(parent->focusWidget(), nullptr);
QGraphicsScene scene;
QEvent windowActivate(QEvent::WindowActivate);
qApp->sendEvent(&scene, &windowActivate);
scene.addItem(parent);
QFETCH(int, childCount);
QList<SubQGraphicsWidget *> children;
for (int i = 0; i < childCount; ++i) {
SubQGraphicsWidget *widget = new SubQGraphicsWidget(parent);
widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
children.append(widget);
}
if (childCount > 0) {
QFETCH(int, childWithFocus);
SubQGraphicsWidget *widget = children[childWithFocus];
widget->setFocus();
QTRY_VERIFY(widget->hasFocus());
QCOMPARE(parent->focusWidget(), static_cast<QGraphicsWidget*>(widget));
}
}
void tst_QGraphicsWidget::focusWidget2()
{
QGraphicsScene scene;
QEvent windowActivate(QEvent::WindowActivate);
qApp->sendEvent(&scene, &windowActivate);
QGraphicsWidget *widget = new QGraphicsWidget;
EventSpy focusInSpy(widget, QEvent::FocusIn);
EventSpy focusOutSpy(widget, QEvent::FocusOut);
scene.addItem(widget);
QTRY_VERIFY(!widget->hasFocus());
widget->setFocusPolicy(Qt::StrongFocus);
QTRY_VERIFY(!widget->hasFocus());
QGraphicsWidget *subWidget = new QGraphicsWidget(widget);
QTRY_VERIFY(!subWidget->hasFocus());
scene.setFocus();
QTRY_VERIFY(!widget->hasFocus());
QTRY_VERIFY(!subWidget->hasFocus());
widget->setFocus();
QTRY_VERIFY(widget->hasFocus());
QTRY_COMPARE(focusInSpy.count(), 1);
QTRY_VERIFY(!subWidget->hasFocus());
QGraphicsWidget *otherSubWidget = new QGraphicsWidget;
EventSpy otherFocusInSpy(otherSubWidget, QEvent::FocusIn);
EventSpy otherFocusOutSpy(otherSubWidget, QEvent::FocusOut);
otherSubWidget->setFocusPolicy(Qt::StrongFocus);
otherSubWidget->setParentItem(widget);
QTRY_VERIFY(widget->hasFocus());
QCOMPARE(scene.focusItem(), (QGraphicsItem *)widget);
QTRY_VERIFY(!subWidget->hasFocus());
QTRY_VERIFY(!otherSubWidget->hasFocus());
widget->hide();
QTRY_VERIFY(!widget->hasFocus()); // lose but still has subfocus
QCOMPARE(focusInSpy.count(), 1);
QCOMPARE(focusOutSpy.count(), 1);
widget->show();
QTRY_VERIFY(!widget->hasFocus()); // no regain
QCOMPARE(focusInSpy.count(), 1);
QCOMPARE(focusOutSpy.count(), 1);
widget->hide();
// try to setup subFocus on item that can't take focus
subWidget->setFocus();
QTRY_VERIFY(!subWidget->hasFocus());
QVERIFY(!scene.focusItem()); // but isn't the scene's focus item
// try to setup subFocus on item that can take focus
otherSubWidget->setFocus();
QTRY_VERIFY(!otherSubWidget->hasFocus());
QCOMPARE(widget->focusWidget(), otherSubWidget);
QVERIFY(!scene.focusItem()); // but isn't the scene's focus item
widget->show();
QTRY_COMPARE(scene.focusItem(), (QGraphicsItem *)otherSubWidget); // but isn't the scene's focus item
QCOMPARE(otherFocusInSpy.count(), 1);
QCOMPARE(otherFocusOutSpy.count(), 0);
delete otherSubWidget;
QTRY_COMPARE(otherFocusOutSpy.count(), 1);
QVERIFY(!scene.focusItem());
QVERIFY(!widget->focusWidget());
}
class FocusWatchWidget : public QGraphicsWidget
{
public:
FocusWatchWidget(QGraphicsItem *parent = nullptr)
: QGraphicsWidget(parent) { gotFocusInCount = 0; gotFocusOutCount = 0; }
int gotFocusInCount, gotFocusOutCount;
protected:
void focusInEvent(QFocusEvent *fe) override
{ gotFocusInCount++; QGraphicsWidget::focusInEvent(fe); }
void focusOutEvent(QFocusEvent *fe) override
{ gotFocusOutCount++; QGraphicsWidget::focusOutEvent(fe); }
};
void tst_QGraphicsWidget::focusWidget3()
{
QGraphicsScene scene;
QEvent windowActivate(QEvent::WindowActivate);
qApp->sendEvent(&scene, &windowActivate);
QGraphicsWidget *widget = new QGraphicsWidget;
FocusWatchWidget *subWidget = new FocusWatchWidget(widget);
subWidget->setFocusPolicy(Qt::StrongFocus);
scene.addItem(widget);
widget->show();
QTRY_VERIFY(!widget->hasFocus());
QTRY_VERIFY(!subWidget->hasFocus());
subWidget->setFocus();
QCOMPARE(subWidget->gotFocusInCount, 1);
QCOMPARE(subWidget->gotFocusOutCount, 0);
widget->hide();
QCOMPARE(subWidget->gotFocusOutCount, 1);
}
Q_DECLARE_METATYPE(Qt::FocusPolicy)
void tst_QGraphicsWidget::focusPolicy_data()
{
QTest::addColumn<Qt::FocusPolicy>("focusPolicy1");
QTest::addColumn<Qt::FocusPolicy>("focusPolicy2");
for (int i = 0; i < 25; ++i) {
QTestData &data = QTest::newRow(QByteArray::number(i).constData());
switch(i % 5) {
case 0: data << Qt::TabFocus; break;
case 1: data << Qt::ClickFocus; break;
case 2: data << Qt::StrongFocus; break;
case 3: data << Qt::WheelFocus; break;
case 4: data << Qt::NoFocus; break;
}
switch(i / 5) {
case 0: data << Qt::TabFocus; break;
case 1: data << Qt::ClickFocus; break;
case 2: data << Qt::StrongFocus; break;
case 3: data << Qt::WheelFocus; break;
case 4: data << Qt::NoFocus; break;
}
}
}
// Qt::FocusPolicy focusPolicy() const public
void tst_QGraphicsWidget::focusPolicy()
{
QGraphicsScene scene;
QEvent windowActivate(QEvent::WindowActivate);
qApp->sendEvent(&scene, &windowActivate);
SubQGraphicsWidget *widget = new SubQGraphicsWidget;
scene.addItem(widget);
QTRY_COMPARE(Qt::NoFocus, widget->focusPolicy());
QFETCH(Qt::FocusPolicy, focusPolicy1);
widget->setFocusPolicy(focusPolicy1);
QTRY_COMPARE(widget->focusPolicy(), focusPolicy1);
bool isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable;
bool wasFocusable = isFocusable;
QTRY_VERIFY(isFocusable == (focusPolicy1 != Qt::NoFocus));
widget->setFocus();
QTRY_COMPARE(widget->hasFocus(), isFocusable);
QFETCH(Qt::FocusPolicy, focusPolicy2);
widget->setFocusPolicy(focusPolicy2);
QCOMPARE(widget->focusPolicy(), focusPolicy2);
isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable;
QVERIFY(isFocusable == (focusPolicy2 != Qt::NoFocus));
QCOMPARE(widget->hasFocus(), wasFocusable && isFocusable);
}
void tst_QGraphicsWidget::font_data()
{
QTest::addColumn<QString>("fontName");
QTest::newRow("Helvetica") << "Helvetica";
}
// QFont font() const public
void tst_QGraphicsWidget::font()
{
QFETCH(QString, fontName);
SubQGraphicsWidget widget;
QCOMPARE(widget.font(), QFont());
QFont font(fontName);
widget.setFont(font);
QCOMPARE(widget.font().family(), font.family());
}
void tst_QGraphicsWidget::fontPropagatesResolveToChildren()
{
QGraphicsWidget *root = new QGraphicsWidget();
QGraphicsWidget *child1 = new QGraphicsWidget(root);
QGraphicsScene scene;
scene.addItem(root);
QFont font;
font.setItalic(true);
root->setFont(font);
QGraphicsWidget *child2 = new QGraphicsWidget(root);
QGraphicsWidget *child3 = new QGraphicsWidget();
child3->setParentItem(root);
QGraphicsView view;
view.setScene(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QCOMPARE(font.resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(root->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(child1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(child2->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(child3->font().resolveMask(), uint(QFont::StyleResolved));
}
void tst_QGraphicsWidget::fontPropagatesResolveToGrandChildren()
{
QGraphicsWidget *root = new QGraphicsWidget();
QGraphicsWidget *child1 = new QGraphicsWidget(root);
QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
QGraphicsScene scene;
scene.addItem(root);
QFont font;
font.setItalic(true);
root->setFont(font);
QGraphicsWidget *child2 = new QGraphicsWidget(root);
QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
QGraphicsWidget *child3 = new QGraphicsWidget();
QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
child3->setParentItem(root);
grandChild5->setParentItem(child3);
QGraphicsView view;
view.setScene(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QCOMPARE(font.resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild2->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild3->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild4->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild5->font().resolveMask(), uint(QFont::StyleResolved));
}
void tst_QGraphicsWidget::fontPropagatesResolveViaNonWidget()
{
QGraphicsWidget *root = new QGraphicsWidget();
QGraphicsPixmapItem *child1 = new QGraphicsPixmapItem(root);
QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
QGraphicsScene scene;
scene.addItem(root);
QFont font;
font.setItalic(true);
root->setFont(font);
QGraphicsPixmapItem *child2 = new QGraphicsPixmapItem(root);
QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
QGraphicsPixmapItem *child3 = new QGraphicsPixmapItem();
QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
child3->setParentItem(root);
grandChild5->setParentItem(child3);
QGraphicsView view;
view.setScene(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QCOMPARE(font.resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild2->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild3->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild4->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild5->font().resolveMask(), uint(QFont::StyleResolved));
}
void tst_QGraphicsWidget::fontPropagatesResolveFromScene()
{
QGraphicsWidget *root = new QGraphicsWidget();
QGraphicsWidget *child1 = new QGraphicsWidget(root);
QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
QGraphicsScene scene;
scene.addItem(root);
QFont font;
font.setItalic(true);
scene.setFont(font);
QGraphicsWidget *child2 = new QGraphicsWidget(root);
QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
QGraphicsWidget *child3 = new QGraphicsWidget();
QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
child3->setParentItem(root);
grandChild5->setParentItem(child3);
QGraphicsView view;
view.setScene(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QCOMPARE(font.resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(root->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(child1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(child2->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(child3->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild2->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild3->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild4->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild5->font().resolveMask(), uint(QFont::StyleResolved));
}
void tst_QGraphicsWidget::fontPropagatesResolveInParentChange()
{
QGraphicsWidget *root = new QGraphicsWidget();
QGraphicsWidget *child1 = new QGraphicsWidget(root);
QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
QGraphicsWidget *child2 = new QGraphicsWidget(root);
QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
QGraphicsScene scene;
scene.addItem(root);
QFont italicFont;
italicFont.setItalic(true);
child1->setFont(italicFont);
QFont boldFont;
boldFont.setBold(true);
child2->setFont(boldFont);
QVERIFY(grandChild1->font().italic());
QVERIFY(!grandChild1->font().bold());
QVERIFY(!grandChild2->font().italic());
QVERIFY(grandChild2->font().bold());
QCOMPARE(grandChild1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild2->font().resolveMask(), uint(QFont::WeightResolved));
grandChild2->setParentItem(child1);
QGraphicsView view;
view.setScene(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(grandChild1->font().italic());
QVERIFY(!grandChild1->font().bold());
QVERIFY(grandChild2->font().italic());
QVERIFY(!grandChild2->font().bold());
QCOMPARE(grandChild1->font().resolveMask(), uint(QFont::StyleResolved));
QCOMPARE(grandChild2->font().resolveMask(), uint(QFont::StyleResolved));
}
void tst_QGraphicsWidget::fontPropagation()
{
QGraphicsWidget *root = new QGraphicsWidget;
QGraphicsWidget *child0 = new QGraphicsWidget(root);
QGraphicsWidget *child1 = new QGraphicsWidget(child0);
QGraphicsWidget *child2 = new QGraphicsWidget(child1);
QGraphicsScene scene;
scene.addItem(root);
// Check that only the application fonts apply.
QFont appFont = QApplication::font();
QCOMPARE(scene.font(), appFont);
QCOMPARE(root->font(), appFont);
QCOMPARE(child0->font(), appFont);
QCOMPARE(child1->font(), appFont);
// Set child0's Text, and set ToolTipBase on child1.
QFont boldFont;
boldFont.setBold(true);
child0->setFont(boldFont);
QFont italicFont;
italicFont.setItalic(true);
child1->setFont(italicFont);
// Check that the above settings propagate correctly.
QCOMPARE(root->font(), appFont);
QCOMPARE(scene.font(), appFont);
QVERIFY(child0->font().bold());
QVERIFY(!child0->font().italic());
QVERIFY(child1->font().bold());
QVERIFY(child1->font().italic());
QVERIFY(child2->font().bold());
QVERIFY(child2->font().italic());
QGraphicsWidget *child3 = new QGraphicsWidget(child2);
QVERIFY(child3->font().bold());
QVERIFY(child3->font().italic());
QGraphicsWidget *child4 = new QGraphicsWidget;
child4->setParentItem(child3);
QVERIFY(child4->font().bold());
QVERIFY(child4->font().italic());
// Replace the app font for child2. Button should propagate but Text
// should still be ignored. The previous ToolTipBase setting is gone.
QFont sizeFont;
sizeFont.setPointSize(43);
child1->setFont(sizeFont);
// Check that the above settings propagate correctly.
QCOMPARE(root->font(), appFont);
QCOMPARE(scene.font(), appFont);
QVERIFY(child0->font().bold());
QVERIFY(!child0->font().italic());
QVERIFY(child1->font().bold());
QVERIFY(!child1->font().italic());
QCOMPARE(child1->font().pointSize(), 43);
QVERIFY(child2->font().bold());
QVERIFY(!child2->font().italic());
QCOMPARE(child2->font().pointSize(), 43);
}
void tst_QGraphicsWidget::fontChangedEvent()
{
QGraphicsWidget *root = new QGraphicsWidget;
QGraphicsScene scene;
scene.addItem(root);
// Check that only the application fonts apply.
QFont appFont = QApplication::font();
QCOMPARE(scene.font(), appFont);
QCOMPARE(root->font(), appFont);
EventSpy rootSpyFont(root, QEvent::FontChange);
EventSpy rootSpyPolish(root, QEvent::Polish);
QTRY_COMPARE(rootSpyFont.count(), 0);
QTRY_COMPARE(rootSpyPolish.count(), 1);
//The font is still the same so no fontChangeEvent
QTRY_COMPARE(rootSpyFont.count(), 0);
QFont font;
font.setPointSize(43);
root->setFont(font);
//The font changed
QTRY_COMPARE(rootSpyFont.count(), 1);
//then roll back to the default one.
root->setFont(appFont);
//The font changed
QTRY_COMPARE(rootSpyFont.count(), 2);
}
void tst_QGraphicsWidget::fontPropagationWidgetItemWidget()
{
QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsRectItem *rect = new QGraphicsRectItem(widget);
QGraphicsWidget *widget2 = new QGraphicsWidget(rect);
QGraphicsScene scene;
scene.addItem(widget);
QFont font;
font.setPointSize(43);
widget->setFont(font);
QCOMPARE(widget2->font().pointSize(), 43);
QCOMPARE(widget2->font().resolveMask(), uint(QFont::SizeResolved));
widget->setFont(QFont());
QCOMPARE(widget2->font().pointSize(), qApp->font().pointSize());
QCOMPARE(widget2->font().resolveMask(), QFont().resolveMask());
}
void tst_QGraphicsWidget::fontPropagationSceneChange()
{
QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsRectItem *rect = new QGraphicsRectItem(widget);
QGraphicsWidget *widget2 = new QGraphicsWidget(rect);
QGraphicsScene scene;
QGraphicsScene scene2;
QFont font;
font.setPointSize(47);
scene.setFont(font);
QFont font2;
font2.setPointSize(74);
scene2.setFont(font2);
scene.addItem(widget);
QCOMPARE(widget2->font().pointSize(), 47);
scene2.addItem(widget);
QCOMPARE(widget2->font().pointSize(), 74);
}
void tst_QGraphicsWidget::geometry_data()
{
QTest::addColumn<QPointF>("pos");
QTest::addColumn<QSizeF>("size");
QTest::newRow("null, null") << QPointF() << QSizeF(0, 0);
QTest::newRow("null, normal") << QPointF() << QSizeF(10, 10);
QTest::newRow("neg, normal") << QPointF(-5, -5) << QSizeF(10, 10);
}
// QRectF geometry() const public
void tst_QGraphicsWidget::geometry()
{
SubQGraphicsWidget widget;
QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size()));
QSignalSpy spy(&widget, SIGNAL(geometryChanged()));
QFETCH(QPointF, pos);
QFETCH(QSizeF, size);
widget.setPos(pos);
widget.resize(size);
if (!size.isNull() && !pos.isNull())
QCOMPARE(spy.size(), 2);
if (!size.isNull() && pos.isNull())
QCOMPARE(spy.size(), 1);
QCOMPARE(widget.geometry(), QRectF(pos, size));
}
void tst_QGraphicsWidget::geometryChanged()
{
QGraphicsWidget w;
w.setGeometry(0, 0, 200, 200);
QCOMPARE(w.geometry(), QRectF(0, 0, 200, 200));
QSignalSpy spy(&w, SIGNAL(geometryChanged()));
w.setGeometry(0, 0, 100, 100);
QCOMPARE(spy.size(), 1);
QCOMPARE(w.geometry(), QRectF(0, 0, 100, 100));
w.setPos(10, 10);
QCOMPARE(spy.size(), 2);
QCOMPARE(w.geometry(), QRectF(10, 10, 100, 100));
}
void tst_QGraphicsWidget::width()
{
QGraphicsWidget w;
QCOMPARE(w.property("width").toReal(), qreal(0));
QSignalSpy spy(&w, SIGNAL(widthChanged()));
w.setProperty("width", qreal(50));
QCOMPARE(w.property("width").toReal(), qreal(50));
QCOMPARE(spy.size(), 1);
//calling old school setGeometry should work too
w.setGeometry(0, 0, 200, 200);
QCOMPARE(spy.size(), 2);
}
void tst_QGraphicsWidget::height()
{
QGraphicsWidget w;
QCOMPARE(w.property("height").toReal(), qreal(0));
QSignalSpy spy(&w, SIGNAL(heightChanged()));
w.setProperty("height", qreal(50));
QCOMPARE(w.property("height").toReal(), qreal(50));
QCOMPARE(spy.size(), 1);
//calling old school setGeometry should work too
w.setGeometry(0, 0, 200, 200);
QCOMPARE(spy.size(), 2);
}
void tst_QGraphicsWidget::getContentsMargins_data()
{
QTest::addColumn<qreal>("left");
QTest::addColumn<qreal>("top");
QTest::addColumn<qreal>("right");
QTest::addColumn<qreal>("bottom");
QTest::newRow("null") << (qreal)0 << (qreal)0 << (qreal)0 << (qreal)0;
QTest::newRow("something") << (qreal)10 << (qreal)5 << (qreal)3 << (qreal)7;
QTest::newRow("real") << (qreal)1.7 << (qreal)5.9 << (qreal)3.2 << (qreal)9.7;
}
// void getContentsMargins(qreal* left, qreal* top, qreal* right, qreal* bottom) const public
void tst_QGraphicsWidget::getContentsMargins()
{
qreal gleft;
qreal gtop;
qreal gright;
qreal gbottom;
SubQGraphicsWidget widget;
widget.getContentsMargins(&gleft, &gtop, &gright, &gbottom);
QCOMPARE(gleft, (qreal)0);
QCOMPARE(gtop, (qreal)0);
QCOMPARE(gright, (qreal)0);
QCOMPARE(gbottom, (qreal)0);
QFETCH(qreal, left);
QFETCH(qreal, top);
QFETCH(qreal, right);
QFETCH(qreal, bottom);
int oldEventCounts = widget.eventCount;
widget.setContentsMargins(left, top, right, bottom);
QVERIFY(left == 0 || oldEventCounts != widget.eventCount);
widget.getContentsMargins(&gleft, &gtop, &gright, &gbottom);
QCOMPARE(gleft, left);
QCOMPARE(gtop, top);
QCOMPARE(gright, right);
QCOMPARE(gbottom, bottom);
}
Q_DECLARE_METATYPE(Qt::LayoutDirection)
void tst_QGraphicsWidget::initStyleOption_data()
{
QTest::addColumn<bool>("enabled");
QTest::addColumn<bool>("focus");
QTest::addColumn<bool>("underMouse");
QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
QTest::addColumn<QSizeF>("size");
QTest::addColumn<QPalette>("palette");
QTest::addColumn<QString>("fontName");
QTest::newRow("none") << false << false << false << Qt::LeftToRight << QSizeF(0, 0) << QPalette() << QString();
QTest::newRow("all") << true << true << true << Qt::RightToLeft << QSizeF(300, 300) << QPalette(Qt::magenta) << "Helvetica";
QTest::newRow("rand") << true << false << false << Qt::RightToLeft << QSizeF(1, 0) << QPalette(Qt::darkCyan) << "Times";
}
// void initStyleOption(QStyleOption* option) const public
void tst_QGraphicsWidget::initStyleOption()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
view.resize(300, 300);
view.show();
if (hasWindowActivation())
QVERIFY(QTest::qWaitForWindowActive(&view));
else
QVERIFY(QTest::qWaitForWindowExposed(&view));
view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
SubQGraphicsWidget *widget = new SubQGraphicsWidget;
widget->setAcceptHoverEvents(true);
QStyleOption option;
scene.addItem(widget);
QFETCH(QSizeF, size);
widget->resize(size);
QFETCH(bool, enabled);
widget->setEnabled(enabled);
QFETCH(bool, focus);
if (hasWindowActivation()) {
if (focus) {
widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
widget->setFocus();
QVERIFY(widget->hasFocus());
}
}
QFETCH(bool, underMouse);
if (underMouse) {
QCursor::setPos(view.viewport()->mapToGlobal(view.mapFromScene(widget->mapToScene(widget->boundingRect().center()))));
QTest::qWait(100);
}
QFETCH(QPalette, palette);
widget->setPalette(palette);
QFETCH(QString, fontName);
widget->setFont(QFont(fontName));
// The test
widget->initStyleOption(&option);
bool isEnabled = option.state & QStyle::State_Enabled;
QCOMPARE(isEnabled, enabled);
if (hasWindowActivation()) {
bool hasFocus = option.state & QStyle::State_HasFocus;
QCOMPARE(hasFocus, focus);
}
bool isUnderMouse = option.state & QStyle::State_MouseOver;
QCOMPARE(isUnderMouse, underMouse);
// if (layoutDirection != Qt::LeftToRight)
//QEXPECT_FAIL("", "QApplicaiton::layoutDirection doesn't propagate to QGraphicsWidget", Continue);
//QCOMPARE(option.direction, layoutDirection);
QCOMPARE(option.rect, QRectF(QPointF(), size).toRect());
QCOMPARE(option.palette, palette.resolve(QApplication::palette()));
QCOMPARE(option.fontMetrics, QFontMetrics(widget->font()));
}
void tst_QGraphicsWidget::layout_data()
{
QTest::addColumn<int>("childCount");
QTest::newRow("empty") << 0;
QTest::newRow("10") << 10;
}
// QGraphicsLayout* layout() const public
void tst_QGraphicsWidget::layout()
{
SubQGraphicsWidget widget;
widget.setContentsMargins(10, 5, 50, 100);
QCOMPARE(widget.layout(), nullptr);
QFETCH(int, childCount);
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
QList<SubQGraphicsWidget*> children;
for (int i = 0; i < childCount; ++i) {
SubQGraphicsWidget *item = new SubQGraphicsWidget;
layout->addItem(item);
children.append(item);
}
QSignalSpy spy(&widget, SIGNAL(layoutChanged()));
widget.setLayout(layout);
QTRY_COMPARE(widget.layout(), static_cast<QGraphicsLayout*>(layout));
for (int i = 0; i < children.size(); ++i) {
SubQGraphicsWidget *item = children[i];
QCOMPARE(item->parentWidget(), (QGraphicsWidget *)&widget);
QVERIFY(item->geometry() != QRectF(0, 0, -1, -1));
}
QCOMPARE(spy.size(), 1);
// don't crash
widget.setLayout(0);
}
void tst_QGraphicsWidget::layoutDirection_data()
{
QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
QTest::newRow("rtl") << Qt::RightToLeft;
QTest::newRow("ltr") << Qt::LeftToRight;
}
// Qt::LayoutDirection layoutDirection() const public
void tst_QGraphicsWidget::layoutDirection()
{
QFETCH(Qt::LayoutDirection, layoutDirection);
QGraphicsScene scene;
QScopedPointer<QGraphicsView> view(new QGraphicsView(&scene));
SubQGraphicsWidget widget;
scene.addItem(&widget);
QCOMPARE(widget.layoutDirection(), Qt::LeftToRight);
QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false);
QList<SubQGraphicsWidget*> children;
for (int i = 0; i < 10; ++i) {
SubQGraphicsWidget *item = new SubQGraphicsWidget(&widget);
children.append(item);
QCOMPARE(item->testAttribute(Qt::WA_SetLayoutDirection), false);
}
widget.setLayoutDirection(layoutDirection);
QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), true);
view->show();
QVERIFY(QTest::qWaitForWindowExposed(view.data()));
for (int i = 0; i < children.size(); ++i) {
QTRY_COMPARE(children[i]->layoutDirection(), layoutDirection);
QTRY_COMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false);
view->update();
QTRY_COMPARE(children[i]->m_painterLayoutDirection, layoutDirection);
}
}
void tst_QGraphicsWidget::paint_data()
{
// currently QGraphicsWidget doesn't paint or do anything ...
}
// void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget) public
void tst_QGraphicsWidget::paint()
{
SubQGraphicsWidget widget;
QPainter painter;
QStyleOptionGraphicsItem option;
widget.paint(&painter, &option, 0); // check that widget = 0 works.
}
void tst_QGraphicsWidget::palettePropagation()
{
QGraphicsWidget *root = new QGraphicsWidget;
QGraphicsWidget *child0 = new QGraphicsWidget(root);
QGraphicsWidget *child1 = new QGraphicsWidget(child0);
QGraphicsWidget *child2 = new QGraphicsWidget(child1);
QGraphicsScene scene;
scene.addItem(root);
// These colors are unlikely to be imposed on the default palette of
// QWidget ;-).
QColor overridePalText(42, 43, 44);
QColor overridePalToolTipBase(45, 46, 47);
QColor sysPalButton(99, 98, 97);
// Check that only the application fonts apply.
QPalette appPal = QApplication::palette();
QCOMPARE(scene.palette(), appPal);
QCOMPARE(root->palette(), appPal);
QCOMPARE(child0->palette(), appPal);
QCOMPARE(child1->palette(), appPal);
// Set child0's Text, and set ToolTipBase on child1.
QPalette textPalette;
textPalette.setColor(QPalette::Text, overridePalText);
child0->setPalette(textPalette);
QPalette toolTipPalette;
toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
child1->setPalette(toolTipPalette);
// Check that the above settings propagate correctly.
QCOMPARE(root->palette(), appPal);
QCOMPARE(scene.palette(), appPal);
QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child1->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child2->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
QGraphicsWidget *child3 = new QGraphicsWidget(child2);
QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child3->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
QGraphicsWidget *child4 = new QGraphicsWidget;
child4->setParentItem(child3);
QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
// Replace the app palette for child2. Button should propagate but Text
// should still be ignored. The previous ToolTipBase setting is gone.
QPalette buttonPalette;
buttonPalette.setColor(QPalette::Button, sysPalButton);
child1->setPalette(buttonPalette);
QCOMPARE(root->palette(), appPal);
QCOMPARE(scene.palette(), appPal);
QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
QCOMPARE(child1->palette().color(QPalette::Button), sysPalButton);
QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
QCOMPARE(child2->palette().color(QPalette::Button), sysPalButton);
}
void tst_QGraphicsWidget::parentWidget_data()
{
QTest::addColumn<int>("childrenCount");
QTest::newRow("0") << 0;
QTest::newRow("1") << 1;
QTest::newRow("10") << 10;
}
// QGraphicsWidget* parentWidget() const public
void tst_QGraphicsWidget::parentWidget()
{
QFETCH(int, childrenCount);
SubQGraphicsWidget standAlongWidget;
QGraphicsLineItem standAlongItem;
SubQGraphicsWidget widgetChild(&standAlongWidget);
SubQGraphicsWidget itemChild(&standAlongItem);
QCOMPARE(standAlongWidget.parentWidget(), nullptr);
QCOMPARE(widgetChild.parentWidget(), static_cast<QGraphicsWidget*>(&standAlongWidget));
QCOMPARE(itemChild.parentWidget(), nullptr);
for (int i = 0; i < childrenCount; ++i) {
SubQGraphicsWidget *item = new SubQGraphicsWidget(&standAlongWidget);
QCOMPARE(item->parentWidget(), static_cast<QGraphicsWidget*>(&standAlongWidget));
}
}
void tst_QGraphicsWidget::resize_data()
{
QTest::addColumn<QSizeF>("size");
QTest::newRow("null") << QSizeF();
QTest::newRow("10x10") << QSizeF(10, 10);
QTest::newRow("10x-1") << QSizeF(10, -1);
}
// void resize(qreal w, qreal h) public
void tst_QGraphicsWidget::resize()
{
QFETCH(QSizeF, size);
SubQGraphicsWidget widget;
int oldEventCounts = widget.eventCount;
QSizeF oldSize = widget.size();
widget.resize(size);
QSizeF boundedSize = size.expandedTo(widget.minimumSize()).boundedTo(widget.maximumSize());
QCOMPARE(widget.eventCount, oldEventCounts + ((oldSize == boundedSize) ? 0 : 1));
QCOMPARE(widget.size(), boundedSize);
}
Q_DECLARE_METATYPE(Qt::WidgetAttribute)
void tst_QGraphicsWidget::setAttribute_data()
{
QTest::addColumn<Qt::WidgetAttribute>("attribute");
QTest::addColumn<bool>("supported");
QTest::newRow("WA_SetLayoutDirection") << Qt::WA_SetLayoutDirection << true;
QTest::newRow("WA_RightToLeft") << Qt::WA_RightToLeft << true;
QTest::newRow("WA_SetStyle") << Qt::WA_SetStyle << true;
QTest::newRow("WA_Resized") << Qt::WA_Resized << true;
}
// void setAttribute(Qt::WidgetAttribute attribute, bool on = true) public
void tst_QGraphicsWidget::setAttribute()
{
QFETCH(Qt::WidgetAttribute, attribute);
QFETCH(bool, supported);
SubQGraphicsWidget widget;
widget.setAttribute(attribute);
QCOMPARE(widget.testAttribute(attribute), supported);
}
void tst_QGraphicsWidget::setStyle_data()
{
QTest::addColumn<QString>("style");
QTest::newRow("null") << "";
QTest::newRow("fusion") << "Fusion";
}
// void setStyle(QStyle* style) public
void tst_QGraphicsWidget::setStyle()
{
#ifndef Q_NO_STYLE_FUSION
SubQGraphicsWidget widget;
int oldEventCounts = widget.eventCount;
QFETCH(QString, style);
if (!style.isEmpty()) {
QStyle *fstyle = QStyleFactory::create(style);
widget.setStyle(fstyle);
QCOMPARE(widget.style(), static_cast<QStyle*>(fstyle));
} else {
widget.setStyle(0);
QVERIFY(widget.style() != (QStyle *)0);
}
QCOMPARE(widget.eventCount, oldEventCounts + 1);
QCOMPARE(widget.testAttribute(Qt::WA_SetStyle), !style.isEmpty());
// cleanup
widget.setStyle(0);
#else
QSKIP("This test requires the Fusion style");
#endif
}
void tst_QGraphicsWidget::setTabOrder_data()
{
QTest::addColumn<int>("childrenCount");
QTest::newRow("0") << 0;
QTest::newRow("1") << 1;
QTest::newRow("10") << 10;
}
// void setTabOrder(QGraphicsWidget* first, QGraphicsWidget* second) public
void tst_QGraphicsWidget::setTabOrder()
{
QFETCH(int, childrenCount);
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
QApplicationPrivate::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QGraphicsWidget *lastItem = nullptr;
QTest::ignoreMessage(QtWarningMsg, "QGraphicsWidget::setTabOrder(0, 0) is undefined");
QGraphicsWidget::setTabOrder(0, 0);
QList<SubQGraphicsWidget*> children;
for (int i = 0; i < childrenCount; ++i) {
SubQGraphicsWidget *item = new SubQGraphicsWidget();
item->setFocusPolicy(Qt::TabFocus);
children.append(item);
scene.addItem(item);
if (lastItem)
QGraphicsWidget::setTabOrder(lastItem, item);
lastItem = item;
}
if (!children.isEmpty()) {
QGraphicsWidget *first = children.first();
view.viewport()->setFocus();
QTRY_VERIFY(view.viewport()->hasFocus());
first->setFocus();
QVERIFY(first->hasFocus());
QVERIFY(scene.hasFocus());
QVERIFY(view.viewport()->hasFocus());
int currentItem = 0;
while (currentItem < children.size() - 1) {
QTest::keyPress(view.viewport(), Qt::Key_Tab);
++currentItem;
QVERIFY(children[currentItem % children.size()]->hasFocus());
}
}
}
template <class Iterator>
bool compareFocusChain(QGraphicsView *view,
Iterator i1, Iterator i2,
QByteArray *errorMessage)
{
QGraphicsScene *scene = view->scene();
QGraphicsItem *oldFocusItem = scene->focusItem();
Iterator last = i2 - 1;
for (Iterator i = i1; i != i2; ++i) {
QGraphicsItem *actualFocusItem = scene->focusItem();
QGraphicsItem *expectedFocusItem = *i;
if (actualFocusItem != expectedFocusItem) {
*errorMessage = "Actual:" + actualFocusItem->data(0).toByteArray()
+ " expected:" + expectedFocusItem->data(0).toByteArray();
scene->setFocusItem(oldFocusItem);
return false;
}
if (i != last)
QTest::keyPress(view, Qt::Key_Tab);
}
scene->setFocusItem(oldFocusItem);
return true;
}
template <class Container>
bool compareFocusChain(QGraphicsView *view, const Container &c,
QByteArray *errorMessage)
{
return compareFocusChain(view, c.constBegin(), c.constEnd(), errorMessage);
}
void tst_QGraphicsWidget::setTabOrderAndReparent()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
QApplicationPrivate::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget*)&view);
QGraphicsWidget *w[4];
for (int i = 0; i < 3; ++i) {
w[i] = new QGraphicsWidget;
w[i]->setFocusPolicy(Qt::StrongFocus);
w[i]->setData(0, 'w' + QByteArray::number(i + 1));
scene.addItem(w[i]);
}
w[0]->setFocus();
QTRY_VERIFY(w[0]->hasFocus());
QByteArray errorMessage;
QVERIFY2(compareFocusChain(&view, w, w + 3, &errorMessage), errorMessage.constData());
QGraphicsWidget *p = new QGraphicsWidget;
p->setData(0, QLatin1String("parent"));
p->setFocusPolicy(Qt::StrongFocus);
w[0]->setFocus();
QVERIFY2(compareFocusChain(&view, w, w + 3, &errorMessage), errorMessage.constData());
w[0]->setParentItem(p);
w[1]->setFocus();
QVERIFY2(compareFocusChain(&view, w + 1, w + 3, &errorMessage), errorMessage.constData());
w[1]->setParentItem(p);
w[2]->setFocus();
QVERIFY2(compareFocusChain(&view, w + 2, w + 3, &errorMessage), errorMessage.constData());
w[2]->setParentItem(p);
QCOMPARE(scene.focusItem(), nullptr);
scene.addItem(p);
p->setFocus();
QVERIFY2(compareFocusChain(&view, QGraphicsItemList() << p << w[0] << w[1] << w[2],
&errorMessage), errorMessage.constData());
delete p;
for (int i = 0; i < 4; ++i) {
w[i] = new QGraphicsWidget;
w[i]->setFocusPolicy(Qt::StrongFocus);
w[i]->setData(0, 'w' + QByteArray::number(i + 1));
scene.addItem(w[i]);
}
w[3]->setParentItem(w[0]);
QGraphicsWidget::setTabOrder(w[0], w[3]);
w[0]->setFocus();
QVERIFY2(compareFocusChain(&view, QGraphicsItemList() << w[0] << w[3] << w[1] << w[2],
&errorMessage), errorMessage.constData());
p = new QGraphicsWidget;
p->setData(0, QLatin1String("parent"));
p->setFocusPolicy(Qt::StrongFocus);
w[0]->setParentItem(p);
w[1]->setFocus();
QVERIFY2(compareFocusChain(&view, w + 1, w + 3, &errorMessage), errorMessage.constData());
scene.addItem(p);
w[1]->setFocus();
QVERIFY2(compareFocusChain(&view, QGraphicsItemList() << w[1] << w[2] << p << w[0] << w[3],
&errorMessage), errorMessage.constData());
}
void tst_QGraphicsWidget::topLevelWidget_data()
{
QTest::addColumn<QString>("str");
QTest::newRow("test one") << "foo";
}
// QGraphicsWidget* topLevelWidget() const public
void tst_QGraphicsWidget::topLevelWidget()
{
QFETCH(QString, str);
SubQGraphicsWidget widget;
QCOMPARE(widget.topLevelWidget(), (QGraphicsWidget *)&widget);
}
void tst_QGraphicsWidget::unsetLayoutDirection_data()
{
QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
QTest::newRow("rtl") << Qt::RightToLeft;
QTest::newRow("ltr") << Qt::LeftToRight;
}
// void unsetLayoutDirection() public
void tst_QGraphicsWidget::unsetLayoutDirection()
{
QApplication::setLayoutDirection(Qt::LeftToRight);
QFETCH(Qt::LayoutDirection, layoutDirection);
SubQGraphicsWidget widget;
QCOMPARE(Qt::LeftToRight, widget.layoutDirection());
QList<SubQGraphicsWidget*> children;
for (int i = 0; i < 10; ++i) {
SubQGraphicsWidget *item = new SubQGraphicsWidget(&widget);
children.append(item);
}
widget.setLayoutDirection(layoutDirection);
widget.unsetLayoutDirection();
QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false);
for (int i = 0; i < children.size(); ++i) {
QCOMPARE(children[i]->layoutDirection(), Qt::LeftToRight);
}
}
void tst_QGraphicsWidget::focusNextPrevChild_data()
{
QTest::addColumn<QString>("str");
QTest::newRow("test one") << "foo";
}
// bool focusNextPrevChild(bool next) protected
void tst_QGraphicsWidget::focusNextPrevChild()
{
QFETCH(QString, str);
SubQGraphicsWidget widget;
// ### write test after just calling it stops crashing :)
widget.call_focusNextPrevChild(true);
}
void tst_QGraphicsWidget::verifyFocusChain()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
QApplicationPrivate::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
{
// parent/child focus
SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
w->setFocusPolicy(Qt::StrongFocus);
SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
w1_1->setFocusPolicy(Qt::StrongFocus);
scene.addItem(w);
w->setFocus();
QVERIFY(w->hasFocus());
w->call_focusNextPrevChild(true);
QVERIFY(w1_1->hasFocus());
delete w;
}
{
// delete item in focus chain and verify chain
SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
SubQGraphicsWidget *w1_2 = new SubQGraphicsWidget(w);
SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget(w);
w1_1->setFocusPolicy(Qt::StrongFocus);
w1_2->setFocusPolicy(Qt::StrongFocus);
w1_3->setFocusPolicy(Qt::StrongFocus);
scene.addItem(w);
w1_1->setFocus();
QVERIFY(w1_1->hasFocus());
QCOMPARE(w->call_focusNextPrevChild(true), true);
QVERIFY(w1_2->hasFocus());
QCOMPARE(w->call_focusNextPrevChild(true), true);
QVERIFY(w1_3->hasFocus());
w1_1->setFocus();
delete w1_2;
w->call_focusNextPrevChild(true);
QVERIFY(w1_3->hasFocus());
delete w;
}
{
// parent/child focus
SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
w->setFocusPolicy(Qt::StrongFocus);
SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
w1_1->setFocusPolicy(Qt::StrongFocus);
scene.addItem(w);
w->setFocus();
QVERIFY(w->hasFocus());
w->call_focusNextPrevChild(true);
QVERIFY(w1_1->hasFocus());
delete w;
}
{
// QTBUG-30923:
// Child QGraphicsWidget with tabFocusFirst gets removed & deleted should not crash.
// This case simulates what QtQuick1 does when you have QGraphicsObject based
// item in different qml views that are loaded one after another.
QGraphicsItem *parent1 = new QGraphicsRectItem(0); // root item
scene.addItem(parent1);
for (int i = 0; i < 2; i++) {
SubQGraphicsWidget *w1 = new SubQGraphicsWidget(parent1);
w1->setFocusPolicy(Qt::StrongFocus);
w1->setFocus();
QVERIFY(w1->hasFocus());
scene.removeItem(w1);
delete w1;
QApplication::processEvents();
}
delete parent1;
}
{
// remove the tabFocusFirst widget from the scene.
QScopedPointer<QWidget> window(new QWidget);
QVBoxLayout *layout = new QVBoxLayout;
window->setLayout(layout);
QLineEdit *lineEdit = new QLineEdit;
layout->addWidget(lineEdit);
QGraphicsView *view = new QGraphicsView(&scene);
scene.setSceneRect(-20, -20, 200, 50);
layout->addWidget(view);
view->setMinimumSize(150, 50);
SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget;
w1_1->setData(0, "w1_1");
w1_1->setGeometry(0,0,25, 25);
w1_1->setFocusPolicy(Qt::StrongFocus);
scene.addItem(w1_1);
SubQGraphicsWidget *w1_2 = new SubQGraphicsWidget;
w1_2->setData(0, "w1_2");
w1_2->setGeometry(25,0,25, 25);
w1_2->setFocusPolicy(Qt::StrongFocus);
scene.addItem(w1_2);
window->show();
QApplicationPrivate::setActiveWindow(window.data());
QVERIFY(QTest::qWaitForWindowActive(window.data()));
lineEdit->setFocus();
QTRY_VERIFY(lineEdit->hasFocus());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
QTRY_VERIFY(w1_1->hasFocus());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
QTRY_VERIFY(w1_2->hasFocus());
// remove the tabFocusFirst and insert new item
delete w1_1; // calls _q_removeItemLater
SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget;
w1_3->setFocusPolicy(Qt::StrongFocus);
w1_3->setData(0, "w1_3");
w1_3->setGeometry(50,0,25, 25);
scene.addItem(w1_3);
QTRY_VERIFY(w1_2->hasFocus());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
QTRY_VERIFY(lineEdit->hasFocus());
// tabFocusFirst should now point to w1_2
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
QTRY_VERIFY(w1_2->hasFocus());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
QTRY_VERIFY(w1_3->hasFocus());
scene.removeItem(w1_2); // does not call _q_removeItemLater
delete w1_2; // calls _q_removeItemLater
SubQGraphicsWidget *w1_4 = new SubQGraphicsWidget;
w1_4->setFocusPolicy(Qt::StrongFocus);
w1_4->setData(0, "w1_4");
w1_4->setGeometry(75,0,25, 25);
scene.addItem(w1_4);
QTRY_VERIFY(w1_3->hasFocus());
QByteArray errorMessage;
const QGraphicsItemList expected = QGraphicsItemList() << w1_3 << w1_4;
QTRY_VERIFY2(compareFocusChain(view, expected, &errorMessage), errorMessage.constData());
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
QTRY_VERIFY(lineEdit->hasFocus());
// tabFocusFirst should now point to w1_3
QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
QTRY_VERIFY(w1_3->hasFocus());
QTRY_VERIFY2(compareFocusChain(view, expected, &errorMessage), errorMessage.constData());
}
}
void tst_QGraphicsWidget::updateFocusChainWhenChildDie()
{
if (!hasWindowActivation())
QSKIP("Window activation is not supported");
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
QGraphicsScene scene;
QGraphicsView view(&scene);
view.resize(200, 150);
view.move(availableGeometry.topLeft() + QPoint(50, 50));
view.show();
view.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&view));
// delete item in focus chain with no focus and verify chain
SubQGraphicsWidget *parent = new SubQGraphicsWidget(0, Qt::Window);
SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
w->resize(50,50);
w->resize(100,100);
SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
w1_1->setFocusPolicy(Qt::StrongFocus);
w->setFocusPolicy(Qt::StrongFocus);
scene.addItem(w);
scene.addItem(parent);
w1_1->setFocus();
QVERIFY(w1_1->hasFocus());
QWidget myWidget(0);
QLineEdit edit(&myWidget);
(new QHBoxLayout(&myWidget))->addWidget(&edit);
edit.setMinimumWidth(160); // Windows
myWidget.move(availableGeometry.topLeft() + QPoint(350, 50));
myWidget.show();
edit.setFocus();
QTRY_VERIFY(edit.hasFocus());
delete w1_1;
myWidget.hide();
w->setParentItem(parent);
//We don't crash perfect
QVERIFY(w);
view.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_COMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(w));
}
void tst_QGraphicsWidget::sizeHint_data()
{
QTest::addColumn<bool>("layout");
QTest::newRow("no layout") << false;
QTest::newRow("layout") << true;
}
// QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const protected
void tst_QGraphicsWidget::sizeHint()
{
QFETCH(bool, layout);
SubQGraphicsWidget widget;
if (layout) {
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
widget.setLayout(layout);
}
widget.call_sizeHint(Qt::MinimumSize, QSizeF());
}
void tst_QGraphicsWidget::consistentPosSizeGeometry_data()
{
QTest::addColumn<QSizeF>("minSize");
QTest::addColumn<QSizeF>("maxSize");
QTest::addColumn<QRectF>("geometry");
QTest::addColumn<QRectF>("expectedGeometry");
QTest::newRow("size is valid") << QSizeF(0, 0) << QSizeF(200, 200) << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100);
QTest::newRow("size is larger than max") << QSizeF(0, 0) << QSizeF(50, 50) << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50);
QTest::newRow("size is smaller than min") << QSizeF(50, 50) << QSizeF(150, 150) << QRectF(0, 0, 10, 10) << QRectF(0, 0, 50, 50);
}
void tst_QGraphicsWidget::consistentPosSizeGeometry()
{
QFETCH(QSizeF, minSize);
QFETCH(QSizeF, maxSize);
QFETCH(QRectF, geometry);
QFETCH(QRectF, expectedGeometry);
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsWidget *w = new QGraphicsWidget;
scene.addItem(w);
w->setMinimumSize(minSize);
w->setMaximumSize(maxSize);
w->setGeometry(geometry);
QCOMPARE(w->geometry(), expectedGeometry);
QCOMPARE(w->pos(), expectedGeometry.topLeft());
QCOMPARE(w->size(), expectedGeometry.size());
QRectF otherGeom = QRectF(QPointF(12.34,12.34), minSize);
w->setGeometry(otherGeom);
QCOMPARE(w->geometry(), otherGeom);
QCOMPARE(w->pos(), otherGeom.topLeft());
QCOMPARE(w->size(), otherGeom.size());
w->setPos(geometry.topLeft());
QCOMPARE(w->geometry().topLeft(), expectedGeometry.topLeft());
QCOMPARE(w->pos(), expectedGeometry.topLeft());
w->resize(geometry.size());
QCOMPARE(w->geometry().size(), expectedGeometry.size());
QCOMPARE(w->geometry(), expectedGeometry);
view.show();
}
enum WhichSize {
MinimumWidth,
PreferredWidth,
MaximumWidth,
MinimumHeight,
PreferredHeight,
MaximumHeight,
MinimumSize,
PreferredSize,
MaximumSize,
MinimumSizeHint,
PreferredSizeHint,
MaximumSizeHint,
WidgetSize,
None,
};
typedef QPair<int, QVariant> Inst;
Q_DECLARE_METATYPE(Inst)
void tst_QGraphicsWidget::setSizes_data()
{
QTest::addColumn<QList<Inst>>("inputInstructions");
QTest::addColumn<QList<Inst>>("compareInstructions");
QTest::newRow("minSize1") << (QList<Inst>()
<< Inst(WidgetSize, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10)))
<< (QList<Inst>() << Inst(WidgetSize, QSize(25, 25)));
QTest::newRow("minSize2") << (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 20))
<< Inst(MinimumSize, QSizeF(25, 25)))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(25, 25)));
QTest::newRow("minWidth1") << (QList<Inst>()
<< Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 20)));
QTest::newRow("minWidth2") << (QList<Inst>()
<< Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(25, 20)));
QTest::newRow("minHeight1") << (QList<Inst>()
<< Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 20)));
QTest::newRow("minHeight2") << (QList<Inst>()
<< Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 25)));
QTest::newRow("maxSize1") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40))
<< Inst(MaximumSize, QSizeF(30, 30)))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(30, 30)));
QTest::newRow("maxSize2") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40))
<< Inst(MaximumSize, QSizeF(30, -1)))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(30, 40)));
QTest::newRow("maxSize3") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40))
<< Inst(MaximumSize, QSizeF(-1, 30)))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 30)));
QTest::newRow("maxWidth1") << (QList<Inst>()
<< Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumWidth, 30))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(30, 40)));
QTest::newRow("maxHeight") << (QList<Inst>()
<< Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumHeight, 20))
<< (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 20)));
QTest::newRow("unsetMinSize") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40))
<< Inst(MinimumSize, QSizeF(-1, -1)))
<< (QList<Inst>() << Inst(MinimumSize, QSizeF(5, 5)));
QTest::newRow("unsetMaxSize") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40))
<< Inst(MaximumSize, QSizeF(-1, -1)))
<< (QList<Inst>() << Inst(MaximumSize, QSizeF(500, 500)));
QTest::newRow("unsetMinSize, expand size to minimumSizeHint")
<< (QList<Inst>() << Inst(MinimumSize, QSize(0, 0)) << Inst(WidgetSize, QSize(1, 1))
<< Inst(MinimumSize, QSize(-1.0, -1.0)))
<< (QList<Inst>() << Inst(WidgetSize, QSize(5, 5)) << Inst(MinimumSize, QSize(5, 5)));
}
void tst_QGraphicsWidget::setSizes()
{
QFETCH(QList<Inst>, inputInstructions);
QFETCH(QList<Inst>, compareInstructions);
QGraphicsScene scene;
QGraphicsView view(&scene);
SizeHinter *widget = new SizeHinter(0, Qt::Window);
QSizeF min = QSizeF(10, 10);
QSizeF pref = QSizeF(25, 25);
QSizeF max = QSizeF(50, 50);
int i;
for (i = 0; i < inputInstructions.size(); ++i) {
Inst input = inputInstructions.at(i);
// defaults
switch (input.first) {
case MinimumSize:
min = input.second.toSizeF();
break;
case PreferredSize:
pref = input.second.toSizeF();
break;
case MaximumSize:
max = input.second.toSizeF();
break;
case WidgetSize :
widget->resize(input.second.toSizeF());
break;
case MinimumWidth:
widget->setMinimumWidth(qreal(input.second.toDouble()));
break;
case PreferredWidth:
widget->setPreferredWidth(qreal(input.second.toDouble()));
break;
case MaximumWidth:
widget->setMaximumWidth(qreal(input.second.toDouble()));
break;
case MinimumHeight:
widget->setMinimumHeight(qreal(input.second.toDouble()));
break;
case PreferredHeight:
widget->setPreferredHeight(qreal(input.second.toDouble()));
break;
case MaximumHeight:
widget->setMaximumHeight(qreal(input.second.toDouble()));
break;
case MinimumSizeHint:
widget->setSizeHint(Qt::MinimumSize, input.second.toSizeF());
break;
case PreferredSizeHint:
widget->setSizeHint(Qt::PreferredSize, input.second.toSizeF());
break;
case MaximumSizeHint:
widget->setSizeHint(Qt::MaximumSize, input.second.toSizeF());
break;
default:
qWarning("instruction not implemented");
break;
}
}
widget->setMinimumSize(min);
widget->setPreferredSize(pref);
widget->setMaximumSize(max);
for (i = 0; i < compareInstructions.size(); ++i) {
Inst input = compareInstructions.at(i);
switch (input.first) {
case MinimumSize:
QTRY_COMPARE(widget->minimumSize(), input.second.toSizeF());
break;
case PreferredSize:
QTRY_COMPARE(widget->preferredSize(), input.second.toSizeF());
break;
case MaximumSize:
QTRY_COMPARE(widget->maximumSize(), input.second.toSizeF());
break;
case WidgetSize:
QTRY_COMPARE(widget->size(), input.second.toSizeF());
break;
case MinimumWidth:
QTRY_COMPARE(widget->minimumWidth(), qreal(input.second.toDouble()));
break;
case PreferredWidth:
QTRY_COMPARE(widget->preferredWidth(), qreal(input.second.toDouble()));
break;
case MaximumWidth:
QTRY_COMPARE(widget->maximumWidth(), qreal(input.second.toDouble()));
break;
default:
qWarning("instruction not implemented");
break;
}
}
delete widget;
}
void tst_QGraphicsWidget::closePopupOnOutsideClick()
{
QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
widget->resize(100, 100);
QGraphicsScene scene;
scene.addItem(widget);
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.ignore();
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
QVERIFY(widget->isVisible());
QVERIFY(event.isAccepted());
event.ignore();
event.setScenePos(QPointF(150, 150));
qApp->sendEvent(&scene, &event);
QVERIFY(!widget->isVisible());
QVERIFY(event.isAccepted());
}
void tst_QGraphicsWidget::task236127_bspTreeIndexFails()
{
QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsWidget *widget2 = new QGraphicsWidget;
widget->resize(10, 10);
widget2->resize(10, 10);
widget2->setZValue(1);
QCOMPARE(widget2->zValue(), qreal(1));
QCOMPARE(widget->zValue(), qreal(0));
widget->setData(0, "widget");
widget2->setData(0, "widget2");
QGraphicsScene scene;
scene.addItem(widget);
scene.addItem(widget2);
QGraphicsView view(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QTRY_VERIFY(scene.items(QPointF(25, 25)).isEmpty());
widget->setGeometry(0, 112, 360, 528);
QTRY_COMPARE(scene.items(QPointF(15, 120)).value(0, nullptr), (QGraphicsItem *)widget);
widget2->setGeometry(0, 573, 360, 67);
QTRY_COMPARE(scene.items(QPointF(15, 120)).value(0, nullptr), (QGraphicsItem *)widget);
QTRY_COMPARE(scene.items(QPointF(50, 585)).value(0, nullptr), (QGraphicsItem *)widget2);
}
void tst_QGraphicsWidget::defaultSize()
{
SubQGraphicsWidget *widget = new SubQGraphicsWidget;
widget->setMinimumSize(40, 40);
QGraphicsScene scene;
scene.addItem(widget);
QGraphicsView view(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QSizeF initialSize = widget->size();
widget->resize(initialSize);
QCOMPARE(widget->geometry().size(), initialSize);
widget->setVisible(false);
widget->setMinimumSize(10, 10);
widget->setPreferredSize(60, 60);
widget->setMaximumSize(110, 110);
widget->setVisible(true);
// should still have its size set to initialsize
QTRY_COMPARE(widget->geometry().size(), initialSize);
}
void tst_QGraphicsWidget::explicitMouseGrabber()
{
QGraphicsWidget *widget = new QGraphicsWidget;
EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
// Grab without scene
QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: cannot grab mouse without scene");
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 0);
QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
widget->ungrabMouse();
QCOMPARE(widgetUngrabEventSpy.count(), 0);
// Add to scene
QGraphicsScene scene;
scene.addItem(widget);
// Ungrab while not grabber
QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: not a mouse grabber");
widget->ungrabMouse();
// Simple grab with scene
QVERIFY(!scene.mouseGrabberItem());
widget->grabMouse();
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 1);
widget->ungrabMouse();
QCOMPARE(scene.mouseGrabberItem(), nullptr);
QCOMPARE(widgetUngrabEventSpy.count(), 1);
// Grab while grabbing
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 2);
QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: already a mouse grabber");
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 2);
QCOMPARE(widgetUngrabEventSpy.count(), 1);
widget->ungrabMouse();
QCOMPARE(widgetUngrabEventSpy.count(), 2);
// Add two more widgets to the scene
QGraphicsWidget *widget2 = new QGraphicsWidget;
scene.addItem(widget2);
EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
QGraphicsWidget *widget3 = new QGraphicsWidget;
scene.addItem(widget3);
EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
widget->setData(0, "widget");
widget2->setData(0, "widget2");
widget3->setData(0, "widget3");
// Simple nested grabbing
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 3);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
widget2->grabMouse();
QCOMPARE(widgetUngrabEventSpy.count(), 3);
QCOMPARE(widget2GrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
widget3->grabMouse();
QCOMPARE(widget2UngrabEventSpy.count(), 1);
QCOMPARE(widget3GrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
widget3->ungrabMouse();
QCOMPARE(widget3UngrabEventSpy.count(), 1);
QCOMPARE(widget2GrabEventSpy.count(), 2);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
widget2->ungrabMouse();
QCOMPARE(widget2UngrabEventSpy.count(), 2);
QCOMPARE(widgetGrabEventSpy.count(), 4);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
widget->ungrabMouse();
QCOMPARE(scene.mouseGrabberItem(), nullptr);
// Out of order ungrab
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 5);
widget2->grabMouse();
QCOMPARE(widget2GrabEventSpy.count(), 3);
widget3->grabMouse();
QCOMPARE(widget3GrabEventSpy.count(), 2);
widget2->ungrabMouse();
QCOMPARE(widget3UngrabEventSpy.count(), 2);
QCOMPARE(widget2UngrabEventSpy.count(), 4);
QCOMPARE(widgetGrabEventSpy.count(), 6);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
}
void tst_QGraphicsWidget::implicitMouseGrabber()
{
QGraphicsScene scene;
QGraphicsWidget *widget = new QGraphicsWidget;
widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
widget->resize(200, 200);
EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
scene.addItem(widget);
QVERIFY(!scene.mouseGrabberItem());
// Click on an item, see if gain and lose implicit mouse grab.
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 1);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), nullptr);
QCOMPARE(widgetGrabEventSpy.count(), 1);
QCOMPARE(widgetUngrabEventSpy.count(), 1);
// Click on an item that already grabs the mouse. Shouldn't have any effect.
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 2);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 2);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 2);
QCOMPARE(widgetUngrabEventSpy.count(), 1);
widget->ungrabMouse();
QCOMPARE(widgetUngrabEventSpy.count(), 2);
QCOMPARE(scene.mouseGrabberItem(), nullptr);
// Implicit mouse grabber tries to explicitly grab the mouse
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 3);
widget->grabMouse();
QCOMPARE(widgetUngrabEventSpy.count(), 2);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 3);
QCOMPARE(widgetUngrabEventSpy.count(), 2);
widget->ungrabMouse();
QCOMPARE(scene.mouseGrabberItem(), nullptr);
QCOMPARE(widgetGrabEventSpy.count(), 3);
QCOMPARE(widgetUngrabEventSpy.count(), 3);
// Arrival of a new widget
QGraphicsWidget *widget2 = new QGraphicsWidget;
widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
widget2->resize(200, 200);
widget2->setPos(205, 0);
EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
scene.addItem(widget2);
// Implicit grab while there's an explicit grab is not possible.
widget->grabMouse();
QCOMPARE(widgetGrabEventSpy.count(), 4);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(250, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
QCOMPARE(widgetGrabEventSpy.count(), 4);
QCOMPARE(widget2GrabEventSpy.count(), 0);
QCOMPARE(widget2UngrabEventSpy.count(), 0);
scene.removeItem(widget);
QCOMPARE(widgetUngrabEventSpy.count(), 4);
QCOMPARE(scene.mouseGrabberItem(), nullptr);
}
class GrabOnPressItem : public QGraphicsRectItem
{
public:
GrabOnPressItem(const QRectF &rect)
: QGraphicsRectItem(rect),
npress(0), nrelease(0), ndoubleClick(0),
ngrab(0), nungrab(0)
{
}
int npress;
int nrelease;
int ndoubleClick;
int ngrab;
int nungrab;
protected:
bool sceneEvent(QEvent *event) override
{
switch (event->type()) {
case QEvent::GrabMouse:
++ngrab;
break;
case QEvent::UngrabMouse:
++nungrab;
break;
default:
break;
}
return QGraphicsRectItem::sceneEvent(event);
}
void mousePressEvent(QGraphicsSceneMouseEvent *) override
{
grabMouse();
++npress;
}
void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override
{
ungrabMouse();
++nrelease;
}
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) override
{
++ndoubleClick;
}
};
void tst_QGraphicsWidget::doubleClickAfterExplicitMouseGrab()
{
QGraphicsScene scene;
GrabOnPressItem *item = new GrabOnPressItem(QRectF(0, 0, 100, 100));
scene.addItem(item);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.setButton(Qt::LeftButton);
event.setButtons(Qt::LeftButton);
event.ignore();
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
QCOMPARE(item->npress, 1);
QCOMPARE(item->ngrab, 1);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.setButton(Qt::LeftButton);
event.setButtons({});
event.ignore();
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), nullptr);
QCOMPARE(item->nrelease, 1);
QCOMPARE(item->nungrab, 1);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseDoubleClick);
event.setButton(Qt::LeftButton);
event.setButtons(Qt::LeftButton);
event.ignore();
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
QCOMPARE(item->ndoubleClick, 1);
QCOMPARE(item->ngrab, 2);
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
event.setButton(Qt::LeftButton);
event.setButtons({});
event.ignore();
event.setScenePos(QPointF(50, 50));
qApp->sendEvent(&scene, &event);
}
QCOMPARE(scene.mouseGrabberItem(), nullptr);
QCOMPARE(item->nrelease, 2);
QCOMPARE(item->nungrab, 2);
}
void tst_QGraphicsWidget::popupMouseGrabber()
{
QGraphicsScene scene;
QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
widget->resize(200, 200);
EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
// Simply adding a visible popup to the scene immediately grabs the mouse.
scene.addItem(widget);
QCOMPARE(widgetGrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
// Hiding it loses the grab again.
widget->hide();
QCOMPARE(widgetUngrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), nullptr);
// Showing it grabs the mouse again
widget->show();
QCOMPARE(widgetGrabEventSpy.count(), 2);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
// Add two popups
QGraphicsWidget *widget2 = new QGraphicsWidget(0, Qt::Popup);
widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
widget2->resize(200, 200);
EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
QGraphicsWidget *widget3 = new QGraphicsWidget(0, Qt::Popup);
widget3->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
widget3->resize(200, 200);
EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
// Adding to the scene grabs
scene.addItem(widget2);
QCOMPARE(widgetUngrabEventSpy.count(), 2);
QCOMPARE(widget2GrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
// Adding to the scene grabs again
scene.addItem(widget3);
QCOMPARE(widget2UngrabEventSpy.count(), 1);
QCOMPARE(widget3GrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
// Hiding the topmost widget causes widget 2 to regain grab.
widget3->hide();
QCOMPARE(widget2GrabEventSpy.count(), 2);
QCOMPARE(widget3UngrabEventSpy.count(), 1);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
widget3->show();
QCOMPARE(widget2UngrabEventSpy.count(), 2);
QCOMPARE(widget3GrabEventSpy.count(), 2);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
// Clicking outside the popup still causes it to close (despite that it's
// an explicit mouse grabber).
{
QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
event.ignore();
event.setButton(Qt::LeftButton);
event.setScenePos(QPointF(500, 500)); // outside
qApp->sendEvent(&scene, &event);
}
QVERIFY(!widget3->isVisible());
QCOMPARE(widget3UngrabEventSpy.count(), 2);
QCOMPARE(widget2GrabEventSpy.count(), 3);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
QVERIFY(widget2->isVisible());
QVERIFY(widget->isVisible());
widget3->show();
QCOMPARE(widget3GrabEventSpy.count(), 3);
QCOMPARE(widget2UngrabEventSpy.count(), 3);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
// This is something of a curiosity. What happens if you call
// ungrabMouse() on a popup? The answer is - it loses the grab. If you
// hide and show the popup again, it will regain the grab.
widget3->ungrabMouse();
QCOMPARE(widget3UngrabEventSpy.count(), 3);
QCOMPARE(widget2GrabEventSpy.count(), 4);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
widget3->hide();
widget3->show();
QCOMPARE(widget3GrabEventSpy.count(), 4);
QCOMPARE(widget2UngrabEventSpy.count(), 4);
QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
}
void tst_QGraphicsWidget::windowFlags_data()
{
QTest::addColumn<int>("inputFlags");
QTest::addColumn<int>("outputFlags");
QTest::newRow("nil") << 0 << 0;
// Window types
QTest::newRow("Qt::Window") << int(Qt::Window)
<< int(Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
QTest::newRow("Qt::SubWindow") << int(Qt::SubWindow)
<< int(Qt::SubWindow | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
QTest::newRow("Qt::Dialog") << int(Qt::Dialog)
<< int(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowContextHelpButtonHint);
QTest::newRow("Qt::Sheet") << int(Qt::Sheet)
<< int(Qt::Sheet | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowContextHelpButtonHint);
QTest::newRow("Qt::Tool") << int(Qt::Tool)
<< int(Qt::Tool | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
// Custom window flags
QTest::newRow("Qt::FramelessWindowHint") << int(Qt::FramelessWindowHint)
<< int(Qt::FramelessWindowHint);
QTest::newRow("Qt::CustomizeWindowHint") << int(Qt::CustomizeWindowHint)
<< int(Qt::CustomizeWindowHint);
}
void tst_QGraphicsWidget::windowFlags()
{
QFETCH(int, inputFlags);
QFETCH(int, outputFlags);
// Construct with flags set already
QGraphicsWidget widget(0, Qt::WindowFlags(inputFlags));
QCOMPARE(widget.windowFlags(), Qt::WindowFlags(outputFlags));
// Set flags after construction
QGraphicsWidget widget2;
widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
// Reset flags
widget2.setWindowFlags({});
QVERIFY(!widget2.windowFlags());
// Set flags back again
widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
// Construct with custom flags set already
QGraphicsWidget widget3(0, Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
QCOMPARE(widget3.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
// Set custom flags after construction
QGraphicsWidget widget4;
widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
// Reset flags
widget4.setWindowFlags({});
QVERIFY(!widget4.windowFlags());
// Set custom flags back again
widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
QGraphicsWidget *widget5 = new QGraphicsWidget;
widget5->setWindowFlags(Qt::WindowFlags(inputFlags));
QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
QGraphicsWidget window(nullptr, Qt::Window);
widget5->setParentItem(&window);
QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
}
void tst_QGraphicsWidget::shortcutsDeletion()
{
QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsWidget *widget2 = new QGraphicsWidget;
widget->setMinimumSize(40, 40);
QWidgetAction *del = new QWidgetAction(widget);
del->setIcon(QIcon("edit-delete"));
del->setShortcut(Qt::Key_Delete);
del->setShortcutContext(Qt::WidgetShortcut);
widget2->addAction(del);
widget2->addAction(del);
delete widget;
}
class MessUpPainterWidget : public QGraphicsWidget
{
public:
MessUpPainterWidget(QGraphicsItem * parent = nullptr, Qt::WindowFlags wFlags = { })
: QGraphicsWidget(parent, wFlags)
{}
void paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
QCOMPARE(painter->opacity(), 1.0);
painter->setOpacity(0.0);
QGraphicsWidget::paintWindowFrame(painter, option, widget);
}
void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
QCOMPARE(painter->opacity(), 1.0);
painter->drawRect(0, 0, 100, 100);
QGraphicsWidget::paint(painter, option, widget);
}
};
void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame()
{
MessUpPainterWidget *widget = new MessUpPainterWidget(0, Qt::Window);
QGraphicsScene scene(0, 0, 300, 300);
QGraphicsView view(&scene);
scene.addItem(widget);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
}
class ProxyStyle : public QCommonStyle
{
public:
ProxyStyle(QStyle *proxyStyle) : QCommonStyle()
{
m_proxyStyle = proxyStyle;
}
int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const override
{
return m_proxyStyle->pixelMetric(metric, option, widget);
}
private:
QStyle *m_proxyStyle;
};
class StyledGraphicsWidget : public QGraphicsWidget
{
public:
StyledGraphicsWidget(bool useOwnStyle) : QGraphicsWidget(), m_style(0) {
if (useOwnStyle) {
QStyle *oldStyle = style();
m_style = new ProxyStyle(oldStyle);
setStyle(m_style);
}
style()->pixelMetric(QStyle::PM_SmallIconSize); // crash when style() is still in widgetStyles
}
~StyledGraphicsWidget() {
delete m_style;
}
private:
QStyle *m_style;
};
void tst_QGraphicsWidget::task243004_setStyleCrash()
{
QGraphicsItem *item1 = new StyledGraphicsWidget(true);
delete item1; // item1 not removed from widgetStyles
QGraphicsItem *item2 = new StyledGraphicsWidget(false);
delete item2;
}
class GraphicsWidget_task250119 : public QGraphicsWidget
{
public:
GraphicsWidget_task250119()
: shortcutEvents(0)
{
setFocusPolicy(Qt::StrongFocus);
resize(100, 100);
}
int shortcutEvents;
private:
bool event(QEvent *event) override
{
if (event->type() == QEvent::Shortcut)
shortcutEvents++;
return QGraphicsWidget::event(event);
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
if (hasFocus()) {
painter->setPen(QPen(Qt::black, 0, Qt::DashLine));
painter->drawRect(rect());
}
painter->setPen(QPen(Qt::black, 0, Qt::SolidLine));
painter->fillRect(rect().adjusted(2, 2, -2, -2), Qt::yellow);
painter->drawRect(rect().adjusted(2, 2, -2, -2));
}
};
void tst_QGraphicsWidget::task250119_shortcutContext()
{
QGraphicsScene scene;
QGraphicsView view;
view.setScene(&scene);
view.show();
QApplicationPrivate::setActiveWindow(&view);
QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
// *** Event: ***
GraphicsWidget_task250119 w_event;
scene.addItem(&w_event);
const int id = w_event.grabShortcut(Qt::Key_A, Qt::WidgetWithChildrenShortcut);
w_event.setShortcutEnabled(id, true);
w_event.setFocus();
QTest::keyPress(&view, Qt::Key_A);
QCOMPARE(w_event.shortcutEvents, 1);
w_event.clearFocus();
QTest::keyPress(&view, Qt::Key_A);
QCOMPARE(w_event.shortcutEvents, 1);
scene.removeItem(&w_event);
// *** Signal: ***
GraphicsWidget_task250119 w_signal;
scene.addItem(&w_signal);
QAction action(0);
action.setShortcut(Qt::Key_B);
action.setShortcutContext(Qt::WidgetWithChildrenShortcut);
QSignalSpy spy(&action, SIGNAL(triggered()));
w_signal.addAction(&action);
w_signal.setFocus();
QTest::keyPress(&view, Qt::Key_B);
QCOMPARE(spy.size(), 1);
w_signal.clearFocus();
QTest::keyPress(&view, Qt::Key_B);
QCOMPARE(spy.size(), 1);
scene.removeItem(&w_signal);
}
class ClippingAndTransformsScene : public QGraphicsScene
{
public:
QList<QGraphicsItem *> drawnItems;
protected:
void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
const QStyleOptionGraphicsItem options[], QWidget *widget = 0) override
{
drawnItems.clear();
for (int i = 0; i < numItems; ++i)
drawnItems << items[i];
QGraphicsScene::drawItems(painter, numItems, items, options, widget);
}
};
class RectWidget : public QGraphicsWidget
{
public:
RectWidget(Qt::GlobalColor color, QGraphicsItem *parent=0) : QGraphicsWidget(parent), mColor(color) {}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
painter->setBrush(QBrush(mColor));
painter->drawRect(boundingRect());
}
Qt::GlobalColor mColor;
};
class RectItem : public QGraphicsItem
{
public:
RectItem(Qt::GlobalColor color, QGraphicsItem *parent=0) : QGraphicsItem(parent), mColor(color) {}
QRectF boundingRect() const override
{return QRectF(10,10,50,50);}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
painter->setBrush(QBrush(mColor));
painter->drawRect(boundingRect());
}
Qt::GlobalColor mColor;
};
void tst_QGraphicsWidget::ensureClipping()
{
ClippingAndTransformsScene scene;
scene.setSceneRect(-50, -50, 200, 200);
//A root that clip children
RectWidget *clipWidget = new RectWidget(Qt::black);
scene.addItem(clipWidget);
clipWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
//a child
RectWidget *childWidget = new RectWidget(Qt::red, clipWidget);
clipWidget->setGeometry(QRectF(10, 10, 100, 100));
childWidget->setGeometry(QRectF(25, 25, 50, 50));
//We put a QGraphicsItem to be sure this one is also paint
RectItem *childitem = new RectItem(Qt::blue, clipWidget);
QGraphicsView view(&scene);
view.setOptimizationFlag(QGraphicsView::IndirectPainting);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QList<QGraphicsItem *> expected;
expected << clipWidget << childWidget << childitem;
QTRY_VERIFY(scene.drawnItems.contains(clipWidget));
QVERIFY(scene.drawnItems.contains(childWidget));
QVERIFY(scene.drawnItems.contains(childitem));
}
class ItemChangeTester : public QGraphicsWidget
{
public:
ItemChangeTester()
{ setFlag(ItemSendsGeometryChanges); clear(); }
ItemChangeTester(QGraphicsItem *parent) : QGraphicsWidget(parent)
{ setFlag(ItemSendsGeometryChanges); clear(); }
void clear()
{
changes.clear();
values.clear();
oldValues.clear();
}
QList<GraphicsItemChange> changes;
QList<QVariant> values;
QList<QVariant> oldValues;
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override
{
changes << change;
values << value;
switch (change) {
case QGraphicsItem::ItemPositionChange:
oldValues << pos();
break;
case QGraphicsItem::ItemPositionHasChanged:
break;
default:
break;
}
return value;
}
};
void tst_QGraphicsWidget::widgetSendsGeometryChanges()
{
ItemChangeTester widget;
widget.setFlags({});
widget.clear();
QPointF pos(10, 10);
widget.setPos(pos);
QCOMPARE(widget.pos(), pos);
QCOMPARE(widget.changes.size(), 0);
widget.setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
QCOMPARE(widget.changes.size(), 2);
widget.setPos(QPointF());
QCOMPARE(widget.changes.size(), 4);
QCOMPARE(widget.pos(), QPointF());
QRectF geometry(20, 20, 50, 50);
widget.setGeometry(geometry);
QCOMPARE(widget.changes.size(), 6);
QCOMPARE(widget.geometry(), geometry);
QCOMPARE(widget.changes, QList<QGraphicsItem::GraphicsItemChange>()
<< QGraphicsItem::ItemFlagsChange
<< QGraphicsItem::ItemFlagsHaveChanged
<< QGraphicsItem::ItemPositionChange
<< QGraphicsItem::ItemPositionHasChanged
<< QGraphicsItem::ItemPositionChange
<< QGraphicsItem::ItemPositionHasChanged);
}
class HFWWidget : public QGraphicsWidget
{
public:
HFWWidget() : QGraphicsWidget(0, Qt::Window)
{
QSizePolicy sp;
sp.setHeightForWidth(true);
setSizePolicy(sp);
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
Q_UNUSED(option);
Q_UNUSED(widget);
qreal w = rect().width();
QRectF box(0, 0, w, 2400/w);
painter->drawRoundedRect(box, 25, 25, Qt::RelativeSize);
painter->drawLine(box.topLeft(), box.bottomRight());
painter->drawLine(box.bottomLeft(), box.topRight());
}
protected:
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override
{
qreal w = constraint.width();
switch (which) {
case Qt::MinimumSize:
if (w >= 0 && constraint.height() < 0) {
// keep the same area of 60x40 = 2400
return QSizeF(w, 2400.0/w);
} else {
return QSizeF(10, 10);
}
break;
case Qt::PreferredSize:
return QSizeF(48.989794, 48.989794);
default:
break;
}
return QGraphicsWidget::sizeHint(which, constraint);
}
};
void tst_QGraphicsWidget::respectHFW()
{
QGraphicsScene scene;
HFWWidget *window = new HFWWidget;
scene.addItem(window);
QScopedPointer<QGraphicsView> view(new QGraphicsView(&scene));
view->resize(400, 400);
view->setSceneRect(-100, -100, 300,300);
view->show();
window->setGeometry(0, 0, 70, 70);
QVERIFY(QTest::qWaitForWindowActive(view.data()));
{ // here we go - simulate a interactive resize of the window
QTest::mouseMove(view.data(), view->mapFromScene(71, 71)); // bottom right corner
QTest::mousePress(view->viewport(), Qt::LeftButton, {}, view->mapFromScene(71, 71), 200);
view->grabMouse();
// move both mouse cursor and set correct event in order to emulate resize
QTest::mouseMove(view->viewport(), view->mapFromScene(60, 30), 200);
auto pos = view->mapFromScene(60, 20);
QMouseEvent e(QEvent::MouseMove, pos, view->mapToGlobal(pos),
Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
QApplication::sendEvent(view->viewport(), &e);
view->releaseMouse();
}
const QSizeF winSize = window->size();
qreal minHFW = window->effectiveSizeHint(Qt::MinimumSize, QSizeF(winSize.width(), -1)).height();
#ifdef Q_OS_DARWIN
QEXPECT_FAIL("", "This test is known to fail on Apple platforms.", Continue);
#endif
QTRY_VERIFY(qAbs(minHFW - winSize.height()) < 1);
}
class PolishWidget : public QGraphicsWidget
{
public:
PolishWidget(Qt::GlobalColor color, QGraphicsItem *parent=0) :
QGraphicsWidget(parent), mColor(color)
{
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
painter->setBrush(QBrush(mColor));
painter->drawRect(boundingRect());
}
void polishEvent() override
{
if (!parentWidget()) {
//We add a child in the polish event for the parent
PolishWidget *childWidget = new PolishWidget(Qt::black, this);
childWidget->setGeometry(QRectF(10,10,30,30));
}
QGraphicsWidget::polishEvent();
mColor = Qt::red;
update();
numberOfPolish++;
}
static int numberOfPolish;
private:
Qt::GlobalColor mColor;
};
int PolishWidget::numberOfPolish = 0;
void tst_QGraphicsWidget::addChildInpolishEvent()
{
QGraphicsScene scene;
PolishWidget *parentWidget = new PolishWidget(Qt::white);
scene.addItem(parentWidget);
QGraphicsView view(&scene);
view.resize(200, 200);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QTRY_COMPARE(PolishWidget::numberOfPolish, 2);
}
void tst_QGraphicsWidget::polishEvent()
{
class MyGraphicsWidget : public QGraphicsWidget
{ public:
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override
{ events << QEvent::Paint; }
void polishEvent() override
{ events << QEvent::Polish; }
QList<QEvent::Type> events;
};
QGraphicsScene scene;
MyGraphicsWidget *widget = new MyGraphicsWidget;
scene.addItem(widget);
QGraphicsView view(&scene);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
// Make sure the item is painted.
QTRY_VERIFY(widget->events.contains(QEvent::Paint));
// Make sure the item got polish before paint.
QCOMPARE(widget->events.at(0), QEvent::Polish);
}
void tst_QGraphicsWidget::polishEvent2()
{
class MyGraphicsWidget : public QGraphicsWidget
{ public:
void polishEvent() override
{ events << QEvent::Polish; }
QList<QEvent::Type> events;
};
QGraphicsScene scene;
MyGraphicsWidget *widget = new MyGraphicsWidget;
widget->hide();
scene.addItem(widget);
widget->events.clear();
// Make sure the item got polish event.
QTRY_VERIFY(widget->events.contains(QEvent::Polish));
}
void tst_QGraphicsWidget::autoFillBackground()
{
QGraphicsWidget *widget = new QGraphicsWidget;
QCOMPARE(widget->autoFillBackground(), false);
widget->setAutoFillBackground(true);
QCOMPARE(widget->autoFillBackground(), true);
const QColor color(Qt::red);
const QRect rect(0, 0, 1, 1);
QGraphicsScene scene;
scene.addItem(widget);
widget->setGeometry(rect);
QPalette palette = widget->palette();
palette.setColor(QPalette::Window, color);
widget->setPalette(palette);
QImage image(rect.size(), QImage::Format_RGB32);
QPainter painter;
painter.begin(&image);
scene.render(&painter, rect, rect);
painter.end();
QCOMPARE(image.pixel(0, 0), color.rgb());
}
void tst_QGraphicsWidget::initialShow()
{
class MyGraphicsWidget : public QGraphicsWidget
{ public:
MyGraphicsWidget() : repaints(0) {}
int repaints;
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) override { ++repaints; }
void polishEvent() override { update(); }
};
// Don't let paint events triggered by the windowing system
// influence our test case. We're only interested in knowing
// whether a QGraphicsWidget generates an additional repaint
// on the initial show. Hence create a dummy scenario to find out
// how many repaints we should expect.
QGraphicsScene dummyScene(0, 0, 200, 200);
dummyScene.addItem(new QGraphicsRectItem(0, 0, 100, 100));
QScopedPointer<QGraphicsView> dummyView(new QGraphicsView(&dummyScene));
dummyView->setWindowFlags(Qt::X11BypassWindowManagerHint);
EventSpy paintSpy(dummyView->viewport(), QEvent::Paint);
dummyView->show();
QVERIFY(QTest::qWaitForWindowExposed(dummyView.data()));
const int expectedRepaintCount = paintSpy.count();
dummyView.reset();
MyGraphicsWidget *widget = new MyGraphicsWidget;
widget->resize(100, 100);
QGraphicsScene scene(0, 0, 200, 200);
scene.addItem(widget);
QGraphicsView view(&scene);
view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QTRY_COMPARE(widget->repaints, expectedRepaintCount);
}
void tst_QGraphicsWidget::itemChangeEvents()
{
class TestGraphicsWidget : public QGraphicsWidget
{ public:
TestGraphicsWidget() : QGraphicsWidget() {}
QHash<QEvent::Type, QVariant> valueDuringEvents;
bool event(QEvent *event) override {
Q_UNUSED(event);
switch (event->type()) {
case QEvent::EnabledChange: {
valueDuringEvents.insert(QEvent::EnabledChange, isEnabled());
break;
}
case QEvent::ParentAboutToChange: {
valueDuringEvents.insert(QEvent::ParentAboutToChange, QVariant::fromValue(parentItem()));
break;
}
case QEvent::ParentChange: {
valueDuringEvents.insert(QEvent::ParentChange, QVariant::fromValue(parentItem()));
break;
}
#ifndef QT_NO_CURSOR
case QEvent::CursorChange: {
valueDuringEvents.insert(QEvent::CursorChange, int(cursor().shape()));
break;
}
#endif
case QEvent::ToolTipChange: {
valueDuringEvents.insert(QEvent::ToolTipChange, toolTip());
break;
}
default: {
break;
}
}
return true;
}
void showEvent(QShowEvent *event) override {
Q_UNUSED(event);
valueDuringEvents.insert(QEvent::Show, isVisible());
}
void hideEvent(QHideEvent *event) override {
Q_UNUSED(event);
valueDuringEvents.insert(QEvent::Hide, isVisible());
}
};
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsWidget *parent = new QGraphicsWidget;
scene.addItem(parent);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
TestGraphicsWidget *item = new TestGraphicsWidget;
item->setParentItem(parent);
// ParentAboutToChange should be triggered before the parent has changed
QTRY_COMPARE(qvariant_cast<QGraphicsItem *>(item->valueDuringEvents.value(QEvent::ParentAboutToChange)),
static_cast<QGraphicsItem *>(0));
// ParentChange should be triggered after the parent has changed
QTRY_COMPARE(qvariant_cast<QGraphicsItem *>(item->valueDuringEvents.value(QEvent::ParentChange)),
static_cast<QGraphicsItem *>(parent));
// ShowEvent should be triggered before the item is shown
QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::Show).toBool());
// HideEvent should be triggered after the item is hidden
QVERIFY(item->isVisible());
item->setVisible(false);
QVERIFY(!item->isVisible());
QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::Hide).toBool());
#ifndef QT_NO_CURSOR
// CursorChange should be triggered after the cursor has changed
item->setCursor(Qt::PointingHandCursor);
QTRY_COMPARE(item->valueDuringEvents.value(QEvent::CursorChange).toInt(), int(item->cursor().shape()));
#endif
// ToolTipChange should be triggered after the tooltip has changed
item->setToolTip("tooltipText");
QTRY_COMPARE(item->valueDuringEvents.value(QEvent::ToolTipChange).toString(), item->toolTip());
// EnabledChange should be triggered after the enabled state has changed
QVERIFY(item->isEnabled());
item->setEnabled(false);
QVERIFY(!item->isEnabled());
QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::EnabledChange).toBool());
}
void tst_QGraphicsWidget::itemSendGeometryPosChangesDeactivated()
{
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsWidget *item = new QGraphicsWidget;
scene.addItem(item);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
item->setGeometry(QRectF(0, 0, 50, 50));
QTRY_COMPARE(item->geometry(), QRectF(0, 0, 50, 50));
item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
item->setGeometry(QRectF(0, 0, 60, 60));
QCOMPARE(item->geometry(), QRectF(0, 0, 60, 60));
QCOMPARE(item->pos(), QPointF(0, 0));
item->setPos(QPointF(10, 10));
QCOMPARE(item->pos(), QPointF(10, 10));
QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60));
item->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
item->setGeometry(QRectF(0, 0, 60, 60));
QCOMPARE(item->geometry(), QRectF(0, 0, 60, 60));
QCOMPARE(item->pos(), QPointF(0, 0));
item->setPos(QPointF(10, 10)); QCOMPARE(item->pos(), QPointF(10, 10));
QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60));
}
class TabFocusWidget : public QGraphicsWidget
{
Q_OBJECT
public:
TabFocusWidget(const QString &name, QGraphicsItem *parent = nullptr)
: QGraphicsWidget(parent)
{ setFocusPolicy(Qt::TabFocus); setData(0, name); }
};
void verifyTabFocus(QGraphicsScene *scene, const QList<QGraphicsWidget *> &chain, bool wrapsAround)
{
QKeyEvent tabEvent(QEvent::KeyPress, Qt::Key_Tab, {});
QKeyEvent backtabEvent(QEvent::KeyPress, Qt::Key_Backtab, {});
for (int i = 0; i < chain.size(); ++i)
chain.at(i)->clearFocus();
int n = chain.size() * (wrapsAround ? 3 : 1);
for (int i = 0; i < n; ++i)
{
qApp->sendEvent(scene, &tabEvent);
QVERIFY(chain.at(i % chain.size())->hasFocus());
QCOMPARE(scene->focusItem(), chain.at(i % chain.size()));
}
for (int i = n - 2; i >= 0; --i)
{
qApp->sendEvent(scene, &backtabEvent);
QVERIFY(chain.at(i % chain.size())->hasFocus());
QCOMPARE(scene->focusItem(), chain.at(i % chain.size()));
}
}
void tst_QGraphicsWidget::tabFocus()
{
QGraphicsScene scene;
scene.setFocus();
QEvent activate(QEvent::WindowActivate);
qApp->sendEvent(&scene, &activate);
TabFocusWidget *widget = new TabFocusWidget("1");
scene.addItem(widget);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget, false);
TabFocusWidget *widget2 = new TabFocusWidget("2");
scene.addItem(widget2);
scene.setFocusItem(0);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget << widget2, false);
TabFocusWidget *widget3 = new TabFocusWidget("3");
widget3->setFlag(QGraphicsItem::ItemIsPanel);
scene.addItem(widget3);
QCOMPARE(scene.activePanel(), (QGraphicsItem *)widget3);
scene.setActivePanel(0);
scene.setFocusItem(0);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget << widget2, false);
scene.setActivePanel(widget3);
QCOMPARE(scene.focusItem(), (QGraphicsItem *)widget3);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3, true);
TabFocusWidget *widget4 = new TabFocusWidget("4");
widget4->setParentItem(widget3);
QVERIFY(widget3->hasFocus());
widget3->clearFocus();
QVERIFY(!widget3->focusItem());
QCOMPARE(scene.activePanel(), (QGraphicsItem *)widget3);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4, true);
QGraphicsWidget *widget5 = new QGraphicsWidget; widget5->setData(0, QLatin1String("5"));
widget5->setParentItem(widget3);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4, true);
widget5->setFocusPolicy(Qt::TabFocus);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget5, true);
TabFocusWidget *widget6 = new TabFocusWidget("6");
widget6->setParentItem(widget4);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget5, true);
TabFocusWidget *widget7 = new TabFocusWidget("7", widget6);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget7 << widget5, true);
TabFocusWidget *widget8 = new TabFocusWidget("8", widget6);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget7 << widget8 << widget5, true);
widget6->setFlag(QGraphicsItem::ItemIsPanel);
widget6->setActive(true);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget6 << widget7 << widget8, true);
widget3->setActive(true);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget5, true);
widget6->setFlag(QGraphicsItem::ItemIsPanel, false);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget7 << widget8 << widget5, true);
scene.removeItem(widget6);
verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget5, true);
delete widget6;
}
void tst_QGraphicsWidget::windowFrameSectionAt()
{
SubQGraphicsWidget widget;
widget.setWindowFrameMargins(5, 5, 5, 5);
widget.setGeometry(0, 0, 200, 200);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(50, 50)), Qt::NoSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(-2, -2)), Qt::TopLeftSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(-2, 10)), Qt::TopLeftSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(-2, 30)), Qt::LeftSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(-2, 170)), Qt::LeftSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(-2, 198)), Qt::BottomLeftSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(-2, 202)), Qt::BottomLeftSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(202, -2)), Qt::TopRightSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(202, 10)), Qt::TopRightSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(202, 30)), Qt::RightSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(202, 170)), Qt::RightSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(202, 198)), Qt::BottomRightSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(202, 202)), Qt::BottomRightSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(50, -2)), Qt::TopSection);
QCOMPARE(widget.call_windowFrameSectionAt(QPointF(50, 202)), Qt::BottomSection);
}
void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems()
{
QGraphicsScene scene;
QGraphicsWidget* parent1 = new QGraphicsWidget;
QGraphicsWidget* child1_0 = new QGraphicsWidget;
QGraphicsWidget* child1_1 = new QGraphicsWidget;
QGraphicsWidget* parent2 = new QGraphicsWidget;
// Add the parent and child to the scene.
scene.addItem(parent1);
child1_0->setParentItem(parent1);
child1_1->setParentItem(parent1);
// Hide and show the child.
child1_0->setParentItem(NULL);
scene.removeItem(child1_0);
// Remove parent from the scene.
scene.removeItem(parent1);
delete child1_0;
delete child1_1;
delete parent1;
// Add an item into the scene.
scene.addItem(parent2);
//This should not crash
}
void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
{
QGraphicsScene scene;
QGraphicsWidget* item1 = new QGraphicsWidget;
QGraphicsWidget* item2 = new QGraphicsWidget;
QGraphicsWidget* item3 = new QGraphicsWidget;
scene.addItem(item1);
scene.addItem(item2);
scene.removeItem(item2);
scene.removeItem(item1);
delete item2;
delete item1;
scene.addItem(item3);
//This should not crash
}
void tst_QGraphicsWidget::QTBUG_45867_send_itemChildAddedChange_to_parent()
{
class GraphicsItem : public QGraphicsItem
{
public:
int m_itemChildAddedChangeNotificationsCount;
GraphicsItem()
: QGraphicsItem(),
m_itemChildAddedChangeNotificationsCount(0)
{
}
QRectF boundingRect() const override { return QRectF(); }
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override {}
protected:
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override
{
if (change == QGraphicsItem::ItemChildAddedChange)
++m_itemChildAddedChangeNotificationsCount;
return QGraphicsItem::itemChange(change, value);
}
};
GraphicsItem item;
QGraphicsWidget widget(&item);
QCOMPARE(item.m_itemChildAddedChangeNotificationsCount, 1);
}
QTEST_MAIN(tst_QGraphicsWidget)
#include "tst_qgraphicswidget.moc"