From d8b7b7278987462791488f756edd26842d059074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 11 Dec 2009 14:23:34 +0100 Subject: Fixed invalid read in QCache::unlink after recent change. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to store a pointer to the object in order to delete it later, since the node containing the pointer will be deleted when removing it from the hash. Reviewed-by: Jan-Arve Sæther --- src/corelib/tools/qcache.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index ee9523f..086a52f 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -70,8 +70,9 @@ class QCache if (l == &n) l = n.p; if (f == &n) f = n.n; total -= n.c; + T *object = n.t; hash.remove(*n.keyPtr); - delete n.t; + delete object; } inline T *relink(const Key &key) { typename QHash::iterator i = hash.find(key); -- cgit v0.12 From 0fecf4184e888b202766210b235fde09a81c5257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Fri, 11 Dec 2009 15:36:13 +0100 Subject: Add a simple check for a common wrong usage to avoid infinite recursion Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsanchorlayout.cpp | 23 ++++++++++++---------- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 7 +++++++ .../tst_qgraphicsanchorlayout.cpp | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 6718a28..f504c54 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -321,14 +321,14 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, // Horizontal anchor Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); - d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); + if (d->addAnchor(firstItem, firstEdge, secondItem, secondEdge)) { + // Vertical anchor + firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); + secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); + d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); - // Vertical anchor - firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); - secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); - d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); - - invalidate(); + invalidate(); + } } /*! @@ -351,11 +351,14 @@ void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem, Qt::Orientations orientations) { + bool ok = true; if (orientations & Qt::Horizontal) { - addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft); - addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); + // Currently, if the first is ok, then the rest of the calls should be ok + ok = addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft) != 0; + if (ok) + addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); } - if (orientations & Qt::Vertical) { + if (orientations & Qt::Vertical && ok) { addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); } diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 03ed63d..1dc6873 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -1666,6 +1666,13 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi return 0; } + const QGraphicsLayoutItem *parentWidget = q->parentLayoutItem(); + if (firstItem == parentWidget || secondItem == parentWidget) { + qWarning("QGraphicsAnchorLayout::addAnchor(): " + "You cannot add the parent of the layout to the layout."); + return 0; + } + // In QGraphicsAnchorLayout, items are represented in its internal // graph as four anchors that connect: // - Left -> HCenter diff --git a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index 6e78522..1cb9f0d 100644 --- a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -90,6 +90,7 @@ private slots: void parallelToHalfLayout(); void globalSpacing(); void graphicsAnchorHandling(); + void invalidHierarchyCheck(); }; class RectWidget : public QGraphicsWidget @@ -2058,5 +2059,24 @@ void tst_QGraphicsAnchorLayout::graphicsAnchorHandling() delete a; } +void tst_QGraphicsAnchorLayout::invalidHierarchyCheck() +{ + QGraphicsWidget window(0, Qt::Window); + QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; + window.setLayout(l); + + QCOMPARE(l->count(), 0); + QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): " + "You cannot add the parent of the layout to the layout."); + QVERIFY(!l->addAnchor(l, Qt::AnchorLeft, &window, Qt::AnchorLeft)); + QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): " + "You cannot add the parent of the layout to the layout."); + l->addAnchors(l, &window); + QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): " + "You cannot add the parent of the layout to the layout."); + l->addCornerAnchors(l, Qt::TopLeftCorner, &window, Qt::TopLeftCorner); + QCOMPARE(l->count(), 0); +} + QTEST_MAIN(tst_QGraphicsAnchorLayout) #include "tst_qgraphicsanchorlayout.moc" -- cgit v0.12 From 6a1cff7c47e1f47161f765ba2f7094b55aaa13c5 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 11 Dec 2009 16:41:00 +0100 Subject: Fixes Graphicsitem transformation problems when grouping/ungrouping. New transformation properties added in 4.6, such as rotation or transformOriginPoint were not taken into account in addTogroup and removeFromGroup. Autotest and manual test included. Task-number: QTBUG-5071 Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 46 ++- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 30 ++ tests/manual/qgraphicsitemgroup/customitem.cpp | 107 +++++++ tests/manual/qgraphicsitemgroup/customitem.h | 77 +++++ tests/manual/qgraphicsitemgroup/main.cpp | 51 ++++ .../qgraphicsitemgroup/qgraphicsitemgroup.pro | 8 + tests/manual/qgraphicsitemgroup/widget.cpp | 260 +++++++++++++++++ tests/manual/qgraphicsitemgroup/widget.h | 93 ++++++ tests/manual/qgraphicsitemgroup/widget.ui | 319 +++++++++++++++++++++ 9 files changed, 989 insertions(+), 2 deletions(-) create mode 100644 tests/manual/qgraphicsitemgroup/customitem.cpp create mode 100644 tests/manual/qgraphicsitemgroup/customitem.h create mode 100644 tests/manual/qgraphicsitemgroup/main.cpp create mode 100644 tests/manual/qgraphicsitemgroup/qgraphicsitemgroup.pro create mode 100644 tests/manual/qgraphicsitemgroup/widget.cpp create mode 100644 tests/manual/qgraphicsitemgroup/widget.h create mode 100644 tests/manual/qgraphicsitemgroup/widget.ui diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c879c5c..d955f16 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -10537,6 +10537,20 @@ void QGraphicsItemGroup::addToGroup(QGraphicsItem *item) if (!item->pos().isNull()) newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y()); + // removing additional transformations properties applied with itemTransform() + QPointF origin = item->transformOriginPoint(); + QMatrix4x4 m; + QList transformList = item->transformations(); + for (int i = 0; i < transformList.size(); ++i) + transformList.at(i)->applyTo(&m); + newItemTransform *= m.toTransform().inverted(); + newItemTransform.translate(origin.x(), origin.y()); + newItemTransform.rotate(-item->rotation()); + newItemTransform.scale(1/item->scale(), 1/item->scale()); + newItemTransform.translate(-origin.x(), -origin.y()); + + // ### Expensive, we could maybe use dirtySceneTransform bit for optimization + item->setTransform(newItemTransform); item->d_func()->setIsMemberOfGroup(true); prepareGeometryChange(); @@ -10561,11 +10575,39 @@ void QGraphicsItemGroup::removeFromGroup(QGraphicsItem *item) } QGraphicsItem *newParent = d_ptr->parent; + + // COMBINE + bool ok; + QTransform itemTransform; + if (newParent) + itemTransform = item->itemTransform(newParent, &ok); + else + itemTransform = item->sceneTransform(); + QPointF oldPos = item->mapToItem(newParent, 0, 0); item->setParentItem(newParent); - // ### This function should remap the item's matrix to keep the item's - // transformation unchanged relative to the scene. item->setPos(oldPos); + + // removing position from translation component of the new transform + if (!item->pos().isNull()) + itemTransform *= QTransform::fromTranslate(-item->x(), -item->y()); + + // removing additional transformations properties applied + // with itemTransform() or sceneTransform() + QPointF origin = item->transformOriginPoint(); + QMatrix4x4 m; + QList transformList = item->transformations(); + for (int i = 0; i < transformList.size(); ++i) + transformList.at(i)->applyTo(&m); + itemTransform *= m.toTransform().inverted(); + itemTransform.translate(origin.x(), origin.y()); + itemTransform.rotate(-item->rotation()); + itemTransform.scale(1 / item->scale(), 1 / item->scale()); + itemTransform.translate(-origin.x(), -origin.y()); + + // ### Expensive, we could maybe use dirtySceneTransform bit for optimization + + item->setTransform(itemTransform); item->d_func()->setIsMemberOfGroup(item->group() != 0); // ### Quite expensive. But removeFromGroup() isn't called very often. diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 3e7a2eb..a4931ab 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -318,6 +318,7 @@ private slots: void childrenBoundingRect3(); void group(); void setGroup(); + void setGroup2(); void nestedGroups(); void warpChildrenIntoGroup(); void removeFromGroup(); @@ -3345,6 +3346,35 @@ void tst_QGraphicsItem::setGroup() QCOMPARE(rect->parentItem(), (QGraphicsItem *)0); } +void tst_QGraphicsItem::setGroup2() +{ + QGraphicsScene scene; + QGraphicsItemGroup group; + scene.addItem(&group); + + QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black); + rect->setTransformOriginPoint(50,50); + rect->setRotation(45); + rect->setScale(1.5); + rect->translate(20,20); + group.translate(-30,-40); + group.setRotation(180); + group.setScale(0.5); + + QTransform oldSceneTransform = rect->sceneTransform(); + rect->setGroup(&group); + QCOMPARE(rect->sceneTransform(), oldSceneTransform); + + group.setRotation(20); + group.setScale(2); + rect->setRotation(90); + rect->setScale(0.8); + + oldSceneTransform = rect->sceneTransform(); + rect->setGroup(0); + QCOMPARE(rect->sceneTransform(), oldSceneTransform); +} + void tst_QGraphicsItem::nestedGroups() { QGraphicsItemGroup *group1 = new QGraphicsItemGroup; diff --git a/tests/manual/qgraphicsitemgroup/customitem.cpp b/tests/manual/qgraphicsitemgroup/customitem.cpp new file mode 100644 index 0000000..16da0c5 --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/customitem.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customitem.h" + +#include +#include +#include + +QList CustomScene::selectedCustomGroups() const +{ + QList all = selectedItems(); + QList groups; + + foreach (QGraphicsItem *item, all) { + CustomGroup* group = dynamic_cast(item); + if (group) + groups.append(group); + } + + return groups; +} + +QList CustomScene::selectedCustomItems() const +{ + QList all = selectedItems(); + QList items; + + foreach (QGraphicsItem *item, all) { + CustomItem* citem = dynamic_cast(item); + if (citem) + items.append(citem); + } + + return items; +} + +CustomGroup::CustomGroup() : + QGraphicsItemGroup() +{ + setFlag(QGraphicsItem::ItemIsMovable); + setFlag(QGraphicsItem::ItemIsSelectable); +} + +void CustomGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + if (option->state & QStyle::State_Selected) + painter->setOpacity(1.); + else + painter->setOpacity(0.2); + + painter->setPen(QPen(QColor(100, 100, 100), 2, Qt::DashLine)); + painter->drawRect(boundingRect().adjusted(-2, -2, 2, 2)); +} + +QRectF CustomGroup::boundingRect() const +{ + return QGraphicsItemGroup::boundingRect().adjusted(-4, -4, 4 ,4); +} + +CustomItem::CustomItem(qreal x, qreal y, qreal width, qreal height, const QBrush &brush) : + QGraphicsRectItem(x, y, width, height) +{ + setFlag(QGraphicsItem::ItemIsMovable); + setFlag(QGraphicsItem::ItemIsSelectable); + setBrush(brush); + setPen(Qt::NoPen); + setTransformOriginPoint(boundingRect().center()); +} diff --git a/tests/manual/qgraphicsitemgroup/customitem.h b/tests/manual/qgraphicsitemgroup/customitem.h new file mode 100644 index 0000000..387c8ce --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/customitem.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMITEM_H +#define CUSTOMITEM_H + +#include +#include +#include + +class CustomGroup : public QGraphicsItemGroup +{ +public: + CustomGroup(); + virtual ~CustomGroup() { } + +protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + virtual QRectF boundingRect() const; +}; + +class CustomItem : public QGraphicsRectItem +{ +public: + CustomItem(qreal x, qreal y, qreal width, qreal height, const QBrush & brush = QBrush()); + virtual ~CustomItem() { } +}; + +class CustomScene : public QGraphicsScene +{ + Q_OBJECT +public: + CustomScene() : QGraphicsScene() { } + + QList selectedCustomItems() const; + QList selectedCustomGroups() const; +}; + +#endif // CUSTOMITEM_H diff --git a/tests/manual/qgraphicsitemgroup/main.cpp b/tests/manual/qgraphicsitemgroup/main.cpp new file mode 100644 index 0000000..e7a6e11 --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "widget.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + Widget w; + w.show(); + return a.exec(); +} diff --git a/tests/manual/qgraphicsitemgroup/qgraphicsitemgroup.pro b/tests/manual/qgraphicsitemgroup/qgraphicsitemgroup.pro new file mode 100644 index 0000000..6676a2e --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/qgraphicsitemgroup.pro @@ -0,0 +1,8 @@ +TARGET = qgraphicsitemgroup +TEMPLATE = app +SOURCES += main.cpp \ + widget.cpp \ + customitem.cpp +HEADERS += widget.h \ + customitem.h +FORMS += widget.ui diff --git a/tests/manual/qgraphicsitemgroup/widget.cpp b/tests/manual/qgraphicsitemgroup/widget.cpp new file mode 100644 index 0000000..23bee3f --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/widget.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "widget.h" +#include "ui_widget.h" +#include +#include + +Widget::Widget(QWidget *parent) : + QWidget(parent), + ui(new Ui::Widget), + previousSelectionCount(0) +{ + ui->setupUi(this); + + effect = new QGraphicsOpacityEffect; + effect->setOpacity(0.3); + ui->groupBox->setGraphicsEffect(effect); + + fadeIn = new QPropertyAnimation(effect, "opacity"); + fadeIn->setDuration(200); + fadeIn->setStartValue(0.3); + fadeIn->setEndValue(1.); + + fadeOut = new QPropertyAnimation(effect, "opacity"); + fadeOut->setDuration(200); + fadeOut->setStartValue(1.); + fadeOut->setEndValue(0.3); + + scene = new CustomScene; + scene->setSceneRect(-250,-250,500,500); + ui->view->setScene(scene); + scene->setBackgroundBrush(Qt::white); + ui->view->setInteractive(true); + ui->view->setDragMode(QGraphicsView::RubberBandDrag); + ui->view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + ui->view->setRenderHints( QPainter::SmoothPixmapTransform | + QPainter::TextAntialiasing | + QPainter::Antialiasing ); + + rectBlue = new CustomItem(-100, -100, 50, 50, QColor(80, 80, 200)); + scene->addItem(rectBlue); + rectGreen = new CustomItem(100, -100, 50, 50, QColor(80, 200, 80)); + scene->addItem(rectGreen); + rectRed = new CustomItem(-100, 100, 50, 50, QColor(200, 80, 80)); + scene->addItem(rectRed); + rectYellow = new CustomItem(100, 100, 50, 50, QColor(200, 200, 20)); + scene->addItem(rectYellow); + + connect(scene, SIGNAL(selectionChanged()), this, SLOT(onSceneSelectionChanged())); +} + +Widget::~Widget() +{ + delete ui; + delete fadeIn; + delete fadeOut; +} + +void Widget::on_rotate_valueChanged(int value) +{ + if (scene->selectedItems().count() != 1) + return; + + QGraphicsItem *item = scene->selectedItems().at(0); + item->setRotation(value); + ui->rotateItem->setValue(checkedItem()->rotation()); +} + +void Widget::on_scale_valueChanged(int value) +{ + if (scene->selectedItems().count() != 1) + return; + + QGraphicsItem *item = scene->selectedItems().at(0); + item->setScale(value / 10.); + ui->scaleItem->setValue(checkedItem()->scale() * 10); +} + +void Widget::on_rotateItem_valueChanged(int value) +{ + if (!scene->selectedItems().empty() && scene->selectedItems().at(0) == checkedItem()) + ui->rotate->setValue(value); + else + checkedItem()->setRotation(value); +} + +void Widget::on_scaleItem_valueChanged(int value) +{ + if (!scene->selectedItems().empty() && scene->selectedItems().at(0) == checkedItem()) + ui->scale->setValue(value); + else + checkedItem()->setScale(value / 10.); +} + +void Widget::on_group_clicked() +{ + QList all = scene->selectedItems(); + if (all.size() < 2) + return; + + QList items = scene->selectedCustomItems(); + QList groups = scene->selectedCustomGroups(); + + if (groups.size() == 1) { + foreach (CustomItem *item, items) { + item->setSelected(false); + groups[0]->addToGroup(item); + } + + return; + } + + CustomGroup* group = new CustomGroup; + scene->addItem(group); + foreach (QGraphicsItem *item, all) { + item->setSelected(false); + group->addToGroup(item); + } + group->setSelected(true); + + updateUngroupButton(); +} + +void Widget::on_dismantle_clicked() +{ + QList groups = scene->selectedCustomGroups(); + + foreach (CustomGroup *group, groups) { + foreach (QGraphicsItem *item, group->childItems()) + group->removeFromGroup(item); + + delete group; + } + + updateUngroupButton(); +} + +void Widget::on_merge_clicked() +{ + QList groups = scene->selectedCustomGroups(); + if (groups.size() < 2) + return; + + CustomGroup *newBigGroup = groups.takeFirst(); + foreach (CustomGroup *group, groups) { + foreach (QGraphicsItem *item, group->childItems()) + item->setGroup(newBigGroup); + + delete group; + } +} + +void Widget::onSceneSelectionChanged() +{ + QList all = scene->selectedItems(); + QList groups = scene->selectedCustomGroups(); + + if (all.empty() && all.count() != previousSelectionCount) { + fadeOut->start(); + } else if (previousSelectionCount == 0) { + fadeIn->start(); + } + + if (all.count() == 1) { + QGraphicsItem *item = all.at(0); + ui->rotate->setValue(item->rotation()); + ui->scale->setValue(item->scale() * 10); + } else { + ui->rotate->setValue(ui->rotate->minimum()); + ui->scale->setValue(ui->scale->minimum()); + } + + ui->rotate->setEnabled(all.size() == 1); + ui->scale->setEnabled(all.size() == 1); + ui->group->setEnabled(all.size() > 1); + ui->dismantle->setEnabled(!groups.empty()); + ui->merge->setEnabled(groups.size() > 1); + + previousSelectionCount = all.size(); + + updateUngroupButton(); +} + +void Widget::on_ungroup_clicked() +{ + QGraphicsItemGroup *oldGroup = checkedItem()->group(); + checkedItem()->setGroup(0); + if (oldGroup && oldGroup->childItems().empty()) + delete oldGroup; + + updateUngroupButton(); +} + +void Widget::updateUngroupButton() +{ + ui->ungroup->setEnabled(checkedItem()->group() != 0); +} + +CustomItem * Widget::checkedItem() const +{ + CustomItem *item; + + if (ui->blue->isChecked()) + item = rectBlue; + else if (ui->red->isChecked()) + item = rectRed; + else if (ui->green->isChecked()) + item = rectGreen; + else if (ui->yellow->isChecked()) + item = rectYellow; + + return item; +} + +void Widget::on_buttonGroup_buttonClicked() +{ + ui->rotateItem->setValue(checkedItem()->rotation()); + ui->scaleItem->setValue(checkedItem()->scale() * 10); + + updateUngroupButton(); +} diff --git a/tests/manual/qgraphicsitemgroup/widget.h b/tests/manual/qgraphicsitemgroup/widget.h new file mode 100644 index 0000000..affc436 --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/widget.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WIDGET_H +#define WIDGET_H + +#include "customitem.h" + +#include +#include +#include + +namespace Ui { + class Widget; +} + +class QGraphicsOpacityEffect; +class QPropertyAnimation; + +class Widget : public QWidget +{ + Q_OBJECT +public: + Widget(QWidget *parent = 0); + ~Widget(); + +protected Q_SLOTS: + void on_rotate_valueChanged(int value); + void on_scale_valueChanged(int value); + void on_rotateItem_valueChanged(int value); + void on_scaleItem_valueChanged(int value); + void on_group_clicked(); + void on_dismantle_clicked(); + void on_merge_clicked(); + void onSceneSelectionChanged(); + void on_ungroup_clicked(); + void on_buttonGroup_buttonClicked(); + +private: + void updateUngroupButton(); + CustomItem * checkedItem() const; + + Ui::Widget *ui; + CustomScene *scene; + CustomItem *rectBlue; + CustomItem *rectRed; + CustomItem *rectGreen; + CustomItem *rectYellow; + QGraphicsOpacityEffect* effect; + QPropertyAnimation *fadeIn; + QPropertyAnimation *fadeOut; + int previousSelectionCount; +}; + +#endif // WIDGET_H diff --git a/tests/manual/qgraphicsitemgroup/widget.ui b/tests/manual/qgraphicsitemgroup/widget.ui new file mode 100644 index 0000000..7e3a4df --- /dev/null +++ b/tests/manual/qgraphicsitemgroup/widget.ui @@ -0,0 +1,319 @@ + + + Widget + + + + 0 + 0 + 782 + 695 + + + + Widget + + + + + + + + Items + + + + + + + + + + Blue + + + true + + + buttonGroup + + + + + + + Red + + + buttonGroup + + + + + + + Green + + + buttonGroup + + + + + + + Yellow + + + buttonGroup + + + + + + + + + + + Rotate + + + + + + + true + + + + 120 + 0 + + + + 360 + + + Qt::Horizontal + + + + + + + Scale + + + + + + + true + + + + 120 + 0 + + + + 5 + + + 30 + + + 10 + + + Qt::Horizontal + + + + + + + + + + + false + + + Ungroup + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 50 + 20 + + + + + + + + true + + + + 300 + 164 + + + + + 300 + 164 + + + + Selection + + + + + + + + false + + + Rotate + + + + + + + false + + + + 120 + 0 + + + + 360 + + + Qt::Horizontal + + + + + + + false + + + Scale + + + + + + + false + + + + 120 + 0 + + + + 5 + + + 30 + + + 10 + + + Qt::Horizontal + + + + + + + + + + + false + + + Group + + + + + + + false + + + Merge Groups + + + + + + + false + + + Dismantle Group + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + -- cgit v0.12 From 4e9063d7a8fc79d1cfee71d2c889877264d44086 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 11 Dec 2009 17:10:18 +0100 Subject: Itemviews: we needed to call ensurePolishedwhen asking for sizehints Reviewed-by: Pierre Rossi --- src/gui/itemviews/qabstractitemview.cpp | 4 ++++ src/gui/itemviews/qtreeview.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index de6e6cb..4a450b7 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -2867,6 +2867,8 @@ int QAbstractItemView::sizeHintForRow(int row) const if (row < 0 || row >= d->model->rowCount() || !model()) return -1; + ensurePolished(); + QStyleOptionViewItemV4 option = d->viewOptionsV4(); int height = 0; int colCount = d->model->columnCount(d->root); @@ -2896,6 +2898,8 @@ int QAbstractItemView::sizeHintForColumn(int column) const if (column < 0 || column >= d->model->columnCount() || !model()) return -1; + ensurePolished(); + QStyleOptionViewItemV4 option = d->viewOptionsV4(); int width = 0; int rows = d->model->rowCount(d->root); diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 3ad9fbb..bcf9cfb 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2774,6 +2774,7 @@ int QTreeView::sizeHintForColumn(int column) const d->executePostedLayout(); if (d->viewItems.isEmpty()) return -1; + ensurePolished(); int w = 0; QStyleOptionViewItemV4 option = d->viewOptionsV4(); const QVector viewItems = d->viewItems; -- cgit v0.12 From f555e06c3e8eee7cc67218331562c11ad77ec9c4 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 10 Dec 2009 15:33:21 +0100 Subject: Add missing benchmark to the benchmarks.pro This does not add the benchmark that runs too slowly. Reviewed-by: jasplin --- tests/benchmarks/benchmarks.pro | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro index 9170039..bffa009 100644 --- a/tests/benchmarks/benchmarks.pro +++ b/tests/benchmarks/benchmarks.pro @@ -20,6 +20,24 @@ SUBDIRS = containers-associative \ qregion \ qvariant \ qwidget \ - qtwidgets + qtwidgets \ + qapplication \ + qdir \ + qdiriterator \ + qgraphicsanchorlayout \ + qgraphicsitem \ + qgraphicswidget \ + qmetaobject \ + qpixmapcache \ + qquaternion \ + qscriptclass \ + qscriptengine \ + qscriptvalue \ + qstringbuilder \ + qstylesheetstyle \ + qsvgrenderer \ + qtableview + + contains(QT_CONFIG, opengl): SUBDIRS += opengl -- cgit v0.12 From c15c9cd2356eaeba33a5f8e62a90b0aeb45284e1 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 11 Dec 2009 17:18:54 +0100 Subject: Fixes cursor blinking in the QComboBox when it becomes editable while having the focus. The lineedit has the focus because it becomes focusproxy of the QComboBox. But the focusInEvent is not called because the combobox has already the focus when setFocusProxy is called. Workaround that in the show event. Task-number: QTBUG-1949 Reviewed-by: Thierry --- src/gui/widgets/qlineedit.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 2c1acdb..15dcda2 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1445,6 +1445,16 @@ bool QLineEdit::event(QEvent * e) d->control->processEvent(e); } else if (e->type() == QEvent::KeyRelease) { d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + } else if (e->type() == QEvent::Show) { + //In order to get the cursor blinking if QComboBox::setEditable is called when the combobox has focus + if (hasFocus()) { + d->control->setCursorBlinkPeriod(QApplication::cursorFlashTime()); + QStyleOptionFrameV2 opt; + initStyleOption(&opt); + if ((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) + || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) + d->setCursorVisible(true); + } } #ifdef QT_KEYPAD_NAVIGATION -- cgit v0.12