diff options
Diffstat (limited to 'src/gui/graphicsview')
52 files changed, 0 insertions, 48259 deletions
diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri deleted file mode 100644 index 547d7ce7ae..0000000000 --- a/src/gui/graphicsview/graphicsview.pri +++ /dev/null @@ -1,52 +0,0 @@ -# Qt graphicsview module -HEADERS += graphicsview/qgraphicsgridlayout.h \ - graphicsview/qgraphicsitem.h \ - graphicsview/qgraphicsitem_p.h \ - graphicsview/qgraphicsitemanimation.h \ - graphicsview/qgraphicslayout.h \ - graphicsview/qgraphicslayout_p.h \ - graphicsview/qgraphicslayoutitem.h \ - graphicsview/qgraphicslayoutitem_p.h \ - graphicsview/qgraphicslinearlayout.h \ - graphicsview/qgraphicsproxywidget.h \ - graphicsview/qgraphicsscene.h \ - graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscene_p.h \ - graphicsview/qgraphicsscenebsptreeindex_p.h \ - graphicsview/qgraphicssceneevent.h \ - graphicsview/qgraphicssceneindex_p.h \ - graphicsview/qgraphicsscenelinearindex_p.h \ - graphicsview/qgraphicstransform.h \ - graphicsview/qgraphicstransform_p.h \ - graphicsview/qgraphicsview.h \ - graphicsview/qgraphicsview_p.h \ - graphicsview/qgraphicswidget.h \ - graphicsview/qgraphicswidget_p.h \ - graphicsview/qgridlayoutengine_p.h \ - graphicsview/qgraph_p.h \ - graphicsview/qsimplex_p.h \ - graphicsview/qgraphicsanchorlayout_p.h \ - graphicsview/qgraphicsanchorlayout.h - -SOURCES += graphicsview/qgraphicsgridlayout.cpp \ - graphicsview/qgraphicsitem.cpp \ - graphicsview/qgraphicsitemanimation.cpp \ - graphicsview/qgraphicslayout.cpp \ - graphicsview/qgraphicslayout_p.cpp \ - graphicsview/qgraphicslayoutitem.cpp \ - graphicsview/qgraphicslinearlayout.cpp \ - graphicsview/qgraphicsproxywidget.cpp \ - graphicsview/qgraphicsscene.cpp \ - graphicsview/qgraphicsscene_bsp.cpp \ - graphicsview/qgraphicsscenebsptreeindex.cpp \ - graphicsview/qgraphicssceneevent.cpp \ - graphicsview/qgraphicssceneindex.cpp \ - graphicsview/qgraphicsscenelinearindex.cpp \ - graphicsview/qgraphicstransform.cpp \ - graphicsview/qgraphicsview.cpp \ - graphicsview/qgraphicswidget.cpp \ - graphicsview/qgraphicswidget_p.cpp \ - graphicsview/qgridlayoutengine.cpp \ - graphicsview/qsimplex_p.cpp \ - graphicsview/qgraphicsanchorlayout_p.cpp \ - graphicsview/qgraphicsanchorlayout.cpp diff --git a/src/gui/graphicsview/qgraph_p.h b/src/gui/graphicsview/qgraph_p.h deleted file mode 100644 index 3b9d839a17..0000000000 --- a/src/gui/graphicsview/qgraph_p.h +++ /dev/null @@ -1,286 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPH_P_H -#define QGRAPH_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QHash> -#include <QtCore/QQueue> -#include <QtCore/QString> -#include <QtCore/QDebug> - -#include <float.h> - -QT_BEGIN_NAMESPACE - -template <typename Vertex, typename EdgeData> -class Graph -{ -public: - Graph() {} - - class const_iterator { - public: - const_iterator(const Graph *graph, bool begin) : g(graph){ - if (begin) { - row = g->m_graph.constBegin(); - //test if the graph is empty - if (row != g->m_graph.constEnd()) - { - column = (*row)->constBegin(); - } - } else { - row = g->m_graph.constEnd(); - } - } - - inline Vertex *operator*() { - return column.key(); - } - - inline Vertex *from() const { - return row.key(); - } - - inline Vertex *to() const { - return column.key(); - } - - inline bool operator==(const const_iterator &o) const { return !(*this != o); } - inline bool operator!=(const const_iterator &o) const { - if (row == g->m_graph.end()) { - return row != o.row; - } else { - return row != o.row || column != o.column; - } - } - inline const_iterator& operator=(const const_iterator &o) const { row = o.row; column = o.column; return *this;} - - // prefix - const_iterator &operator++() { - if (row != g->m_graph.constEnd()) { - ++column; - if (column == (*row)->constEnd()) { - ++row; - if (row != g->m_graph.constEnd()) { - column = (*row)->constBegin(); - } - } - } - return *this; - } - - private: - const Graph *g; - Q_TYPENAME QHash<Vertex *, QHash<Vertex *, EdgeData *> * >::const_iterator row; - Q_TYPENAME QHash<Vertex *, EdgeData *>::const_iterator column; - }; - - const_iterator constBegin() const { - return const_iterator(this,true); - } - - const_iterator constEnd() const { - return const_iterator(this,false); - } - - /*! - * \internal - * - * If there is an edge between \a first and \a second, it will return a structure - * containing the data associated with the edge, otherwise it will return 0. - * - */ - EdgeData *edgeData(Vertex* first, Vertex* second) { - QHash<Vertex *, EdgeData *> *row = m_graph.value(first); - return row ? row->value(second) : 0; - } - - void createEdge(Vertex *first, Vertex *second, EdgeData *data) - { - // Creates a bidirectional edge -#if defined(QT_DEBUG) && 0 - qDebug("Graph::createEdge(): %s", - qPrintable(QString::fromAscii("%1-%2") - .arg(first->toString()).arg(second->toString()))); -#endif - if (edgeData(first, second)) { -#ifdef QT_DEBUG - qWarning("%s-%s already has an edge", qPrintable(first->toString()), qPrintable(second->toString())); -#endif - } - createDirectedEdge(first, second, data); - createDirectedEdge(second, first, data); - } - - void removeEdge(Vertex *first, Vertex *second) - { - // Removes a bidirectional edge -#if defined(QT_DEBUG) && 0 - qDebug("Graph::removeEdge(): %s", - qPrintable(QString::fromAscii("%1-%2") - .arg(first->toString()).arg(second->toString()))); -#endif - EdgeData *data = edgeData(first, second); - removeDirectedEdge(first, second); - removeDirectedEdge(second, first); - if (data) delete data; - } - - EdgeData *takeEdge(Vertex* first, Vertex* second) - { -#if defined(QT_DEBUG) && 0 - qDebug("Graph::takeEdge(): %s", - qPrintable(QString::fromAscii("%1-%2") - .arg(first->toString()).arg(second->toString()))); -#endif - // Removes a bidirectional edge - EdgeData *data = edgeData(first, second); - if (data) { - removeDirectedEdge(first, second); - removeDirectedEdge(second, first); - } - return data; - } - - QList<Vertex *> adjacentVertices(Vertex *vertex) const - { - QHash<Vertex *, EdgeData *> *row = m_graph.value(vertex); - QList<Vertex *> l; - if (row) - l = row->keys(); - return l; - } - - QSet<Vertex*> vertices() const { - QSet<Vertex *> setOfVertices; - for (const_iterator it = constBegin(); it != constEnd(); ++it) { - setOfVertices.insert(*it); - } - return setOfVertices; - } - - QList<QPair<Vertex*, Vertex*> > connections() const { - QList<QPair<Vertex*, Vertex*> > conns; - for (const_iterator it = constBegin(); it != constEnd(); ++it) { - Vertex *from = it.from(); - Vertex *to = it.to(); - // do not return (from,to) *and* (to,from) - if (from < to) { - conns.append(qMakePair(from, to)); - } - } - return conns; - } - -#if defined(QT_DEBUG) - QString serializeToDot() { // traversal - QString strVertices; - QString edges; - - QSet<Vertex *> setOfVertices = vertices(); - for (Q_TYPENAME QSet<Vertex*>::const_iterator it = setOfVertices.begin(); it != setOfVertices.end(); ++it) { - Vertex *v = *it; - QList<Vertex*> adjacents = adjacentVertices(v); - for (int i = 0; i < adjacents.count(); ++i) { - Vertex *v1 = adjacents.at(i); - EdgeData *data = edgeData(v, v1); - bool forward = data->from == v; - if (forward) { - edges += QString::fromAscii("\"%1\"->\"%2\" [label=\"[%3,%4,%5,%6,%7]\" color=\"#000000\"] \n") - .arg(v->toString()) - .arg(v1->toString()) - .arg(data->minSize) - .arg(data->minPrefSize) - .arg(data->prefSize) - .arg(data->maxPrefSize) - .arg(data->maxSize) - ; - } - } - strVertices += QString::fromAscii("\"%1\" [label=\"%2\"]\n").arg(v->toString()).arg(v->toString()); - } - return QString::fromAscii("%1\n%2\n").arg(strVertices).arg(edges); - } -#endif - -protected: - void createDirectedEdge(Vertex *from, Vertex *to, EdgeData *data) - { - QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from); - if (!adjacentToFirst) { - adjacentToFirst = new QHash<Vertex *, EdgeData *>(); - m_graph.insert(from, adjacentToFirst); - } - adjacentToFirst->insert(to, data); - } - - void removeDirectedEdge(Vertex *from, Vertex *to) - { - QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from); - Q_ASSERT(adjacentToFirst); - - adjacentToFirst->remove(to); - if (adjacentToFirst->isEmpty()) { - //nobody point to 'from' so we can remove it from the graph - m_graph.remove(from); - delete adjacentToFirst; - } - } - -private: - QHash<Vertex *, QHash<Vertex *, EdgeData *> *> m_graph; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp deleted file mode 100644 index 08c5972534..0000000000 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsAnchorLayout - \brief The QGraphicsAnchorLayout class provides a layout where one can anchor widgets - together in Graphics View. - \since 4.6 - \ingroup appearance - \ingroup geomanagement - \ingroup graphicsview-api - - The anchor layout allows developers to specify how widgets should be placed relative to - each other, and to the layout itself. The specification is made by adding anchors to the - layout by calling addAnchor(), addAnchors() or addCornerAnchors(). - - Existing anchors in the layout can be accessed with the anchor() function. - Items that are anchored are automatically added to the layout, and if items - are removed, all their anchors will be automatically removed. - - \div {class="float-left"} - \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets. - \enddiv - - Anchors are always set up between edges of an item, where the "center" is also considered to - be an edge. Consider the following example: - - \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors - - Here, the right edge of item \c a is anchored to the left edge of item \c b and the bottom - edge of item \c a is anchored to the top edge of item \c b, with the result that - item \c b will be placed diagonally to the right and below item \c b. - - The addCornerAnchors() function provides a simpler way of anchoring the corners - of two widgets than the two individual calls to addAnchor() shown in the code - above. Here, we see how a widget can be anchored to the top-left corner of the enclosing - layout: - - \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor - - In cases where anchors are used to match the widths or heights of widgets, it is - convenient to use the addAnchors() function. As with the other functions for specifying - anchors, it can also be used to anchor a widget to a layout. - - \clearfloat - \section1 Size Hints and Size Policies in an Anchor Layout - - QGraphicsAnchorLayout respects each item's size hints and size policies. - Note that there are some properties of QSizePolicy that are \l{Known issues}{not respected}. - - \section1 Spacing within an Anchor Layout - - The layout may distribute some space between the items. If the spacing has not been - explicitly specified, the actual amount of space will usually be 0. - - However, if the first edge is the \e opposite of the second edge (e.g., the right edge - of the first widget is anchored to the left edge of the second widget), the size of the - anchor will be queried from the style through a pixel metric: - \l{QStyle::}{PM_LayoutHorizontalSpacing} for horizontal anchors and - \l{QStyle::}{PM_LayoutVerticalSpacing} for vertical anchors. - - If the spacing is negative, the items will overlap to some extent. - - - \section1 Known issues - There are some features that QGraphicsAnchorLayout currently does not support. - This might change in the future, so avoid using these features if you want to - avoid any future regressions in behaviour: - \list - - \o Stretch factors are not respected. - - \o QSizePolicy::ExpandFlag is not respected. - - \o Height for width is not respected. - - \endlist - - \sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout -*/ - -/*! - \class QGraphicsAnchor - \brief The QGraphicsAnchor class represents an anchor between two items in a - QGraphicsAnchorLayout. - \since 4.6 - \ingroup appearance - \ingroup geomanagement - \ingroup graphicsview-api - - The graphics anchor provides an API that enables you to query and manipulate the - properties an anchor has. When an anchor is added to the layout with - QGraphicsAnchorLayout::addAnchor(), a QGraphicsAnchor instance is returned where the properties - are initialized to their default values. The properties can then be further changed, and they - will be picked up the next time the layout is activated. - - \sa QGraphicsAnchorLayout::anchor() - -*/ -#include "qgraphicsanchorlayout_p.h" -#ifndef QT_NO_GRAPHICSVIEW -QT_BEGIN_NAMESPACE - -QGraphicsAnchor::QGraphicsAnchor(QGraphicsAnchorLayout *parentLayout) - : QObject(*(new QGraphicsAnchorPrivate)) -{ - Q_D(QGraphicsAnchor); - Q_ASSERT(parentLayout); - d->layoutPrivate = parentLayout->d_func(); -} - -/*! - Removes the QGraphicsAnchor object from the layout and destroys it. -*/ -QGraphicsAnchor::~QGraphicsAnchor() -{ -} - -/*! - \property QGraphicsAnchor::sizePolicy - \brief the size policy for the QGraphicsAnchor. - - By setting the size policy on an anchor you can configure how the anchor can resize itself - from its preferred spacing. For instance, if the anchor has the size policy - QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size - can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed, - the anchor can neither grow or shrink, which means that the only size the anchor can have - is the spacing. QSizePolicy::Fixed is the default size policy. - QGraphicsAnchor always has a minimum spacing of 0 and a very large maximum spacing. - - \sa QGraphicsAnchor::spacing -*/ - -void QGraphicsAnchor::setSizePolicy(QSizePolicy::Policy policy) -{ - Q_D(QGraphicsAnchor); - d->setSizePolicy(policy); -} - -QSizePolicy::Policy QGraphicsAnchor::sizePolicy() const -{ - Q_D(const QGraphicsAnchor); - return d->sizePolicy; -} - -/*! - \property QGraphicsAnchor::spacing - \brief the preferred space between items in the QGraphicsAnchorLayout. - - Depending on the anchor type, the default spacing is either - 0 or a value returned from the style. - - \sa QGraphicsAnchorLayout::addAnchor() -*/ -void QGraphicsAnchor::setSpacing(qreal spacing) -{ - Q_D(QGraphicsAnchor); - d->setSpacing(spacing); -} - -qreal QGraphicsAnchor::spacing() const -{ - Q_D(const QGraphicsAnchor); - return d->spacing(); -} - -void QGraphicsAnchor::unsetSpacing() -{ - Q_D(QGraphicsAnchor); - d->unsetSpacing(); -} - -/*! - Constructs a QGraphicsAnchorLayout instance. \a parent is passed to - QGraphicsLayout's constructor. - */ -QGraphicsAnchorLayout::QGraphicsAnchorLayout(QGraphicsLayoutItem *parent) - : QGraphicsLayout(*new QGraphicsAnchorLayoutPrivate(), parent) -{ - Q_D(QGraphicsAnchorLayout); - d->createLayoutEdges(); -} - -/*! - Destroys the QGraphicsAnchorLayout object. -*/ -QGraphicsAnchorLayout::~QGraphicsAnchorLayout() -{ - Q_D(QGraphicsAnchorLayout); - - for (int i = count() - 1; i >= 0; --i) { - QGraphicsLayoutItem *item = d->items.at(i); - removeAt(i); - if (item) { - if (item->ownedByLayout()) - delete item; - } - } - - d->removeCenterConstraints(this, QGraphicsAnchorLayoutPrivate::Horizontal); - d->removeCenterConstraints(this, QGraphicsAnchorLayoutPrivate::Vertical); - d->deleteLayoutEdges(); - - Q_ASSERT(d->itemCenterConstraints[0].isEmpty()); - Q_ASSERT(d->itemCenterConstraints[1].isEmpty()); - Q_ASSERT(d->items.isEmpty()); - Q_ASSERT(d->m_vertexList.isEmpty()); -} - -/*! - Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge - of item \a secondItem. The spacing of the anchor is picked up from the style. Anchors - between a layout edge and an item edge will have a size of 0. - If there is already an anchor between the edges, the the new anchor will replace the old one. - - \a firstItem and \a secondItem are automatically added to the layout if they are not part - of the layout. This means that count() can increase by up to 2. - - The spacing an anchor will get depends on the type of anchor. For instance, anchors from the - Right edge of one item to the Left edge of another (or vice versa) will use the default - horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use - the default vertical spacing). For all other anchor combinations, the spacing will be 0. - All anchoring functions will follow this rule. - - The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method. - - Calling this function where \a firstItem or \a secondItem are ancestors of the layout have - undefined behaviour. - - \sa addAnchors(), addCornerAnchors() - */ -QGraphicsAnchor * -QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) -{ - Q_D(QGraphicsAnchorLayout); - QGraphicsAnchor *a = d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); - invalidate(); - return a; -} - -/*! - Returns the anchor between the anchor points defined by \a firstItem and \a firstEdge and - \a secondItem and \a secondEdge. If there is no such anchor, the function will return 0. -*/ -QGraphicsAnchor * -QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) -{ - Q_D(QGraphicsAnchorLayout); - return d->getAnchor(firstItem, firstEdge, secondItem, secondEdge); -} - -/*! - Creates two anchors between \a firstItem and \a secondItem specified by the corners, - \a firstCorner and \a secondCorner, where one is for the horizontal edge and another - one for the vertical edge. - - This is a convenience function, since anchoring corners can be expressed as anchoring - two edges. For instance: - - \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor in two steps - - This can also be achieved with the following line of code: - - \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor - - If there is already an anchor between the edge pairs, it will be replaced by the anchors that - this function specifies. - - \a firstItem and \a secondItem are automatically added to the layout if they are not part of the - layout. This means that count() can increase by up to 2. - - \sa addAnchor(), addAnchors() -*/ -void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, - Qt::Corner firstCorner, - QGraphicsLayoutItem *secondItem, - Qt::Corner secondCorner) -{ - Q_D(QGraphicsAnchorLayout); - - // Horizontal anchor - Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); - Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); - 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); - - invalidate(); - } -} - -/*! - Anchors two or four edges of \a firstItem with the corresponding - edges of \a secondItem, so that \a firstItem has the same size as - \a secondItem in the dimensions specified by \a orientations. - - For example, the following example anchors the left and right edges of two items - to match their widths: - - \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes in two steps - - This can also be achieved using the following line of code: - - \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes - - \sa addAnchor(), addCornerAnchors() -*/ -void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem, - Qt::Orientations orientations) -{ - bool ok = true; - if (orientations & Qt::Horizontal) { - // 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 && ok) { - addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); - addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); - } -} - -/*! - Sets the default horizontal spacing for the anchor layout to \a spacing. - - \sa horizontalSpacing(), setVerticalSpacing(), setSpacing() -*/ -void QGraphicsAnchorLayout::setHorizontalSpacing(qreal spacing) -{ - Q_D(QGraphicsAnchorLayout); - - d->spacings[0] = spacing; - invalidate(); -} - -/*! - Sets the default vertical spacing for the anchor layout to \a spacing. - - \sa verticalSpacing(), setHorizontalSpacing(), setSpacing() -*/ -void QGraphicsAnchorLayout::setVerticalSpacing(qreal spacing) -{ - Q_D(QGraphicsAnchorLayout); - - d->spacings[1] = spacing; - invalidate(); -} - -/*! - Sets the default horizontal and the default vertical spacing for the anchor layout to \a spacing. - - If an item is anchored with no spacing associated with the anchor, it will use the default - spacing. - - QGraphicsAnchorLayout does not support negative spacings. Setting a negative value will unset the - previous spacing and make the layout use the spacing provided by the current widget style. - - \sa setHorizontalSpacing(), setVerticalSpacing() -*/ -void QGraphicsAnchorLayout::setSpacing(qreal spacing) -{ - Q_D(QGraphicsAnchorLayout); - - d->spacings[0] = d->spacings[1] = spacing; - invalidate(); -} - -/*! - Returns the default horizontal spacing for the anchor layout. - - \sa verticalSpacing(), setHorizontalSpacing() -*/ -qreal QGraphicsAnchorLayout::horizontalSpacing() const -{ - Q_D(const QGraphicsAnchorLayout); - return d->styleInfo().defaultSpacing(Qt::Horizontal); -} - -/*! - Returns the default vertical spacing for the anchor layout. - - \sa horizontalSpacing(), setVerticalSpacing() -*/ -qreal QGraphicsAnchorLayout::verticalSpacing() const -{ - Q_D(const QGraphicsAnchorLayout); - return d->styleInfo().defaultSpacing(Qt::Vertical); -} - -/*! - \reimp -*/ -void QGraphicsAnchorLayout::setGeometry(const QRectF &geom) -{ - Q_D(QGraphicsAnchorLayout); - - QGraphicsLayout::setGeometry(geom); - d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Horizontal); - d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Vertical); - d->setItemsGeometries(geom); -} - -/*! - Removes the layout item at \a index without destroying it. Ownership of - the item is transferred to the caller. - - Removing an item will also remove any of the anchors associated with it. - - \sa itemAt(), count() -*/ -void QGraphicsAnchorLayout::removeAt(int index) -{ - Q_D(QGraphicsAnchorLayout); - QGraphicsLayoutItem *item = d->items.value(index); - - if (!item) - return; - - // Removing an item affects both horizontal and vertical graphs - d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Horizontal); - d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Vertical); - d->removeAnchors(item); - d->items.remove(index); - - item->setParentLayoutItem(0); - invalidate(); -} - -/*! - \reimp -*/ -int QGraphicsAnchorLayout::count() const -{ - Q_D(const QGraphicsAnchorLayout); - return d->items.size(); -} - -/*! - \reimp -*/ -QGraphicsLayoutItem *QGraphicsAnchorLayout::itemAt(int index) const -{ - Q_D(const QGraphicsAnchorLayout); - return d->items.value(index); -} - -/*! - \reimp -*/ -void QGraphicsAnchorLayout::invalidate() -{ - Q_D(QGraphicsAnchorLayout); - QGraphicsLayout::invalidate(); - d->calculateGraphCacheDirty = true; - d->styleInfoDirty = true; -} - -/*! - \reimp -*/ -QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_UNUSED(constraint); - Q_D(const QGraphicsAnchorLayout); - - // Some setup calculations are delayed until the information is - // actually needed, avoiding unnecessary recalculations when - // adding multiple anchors. - - // sizeHint() / effectiveSizeHint() already have a cache - // mechanism, using invalidate() to force recalculation. However - // sizeHint() is called three times after invalidation (for max, - // min and pref), but we just need do our setup once. - - const_cast<QGraphicsAnchorLayoutPrivate *>(d)->calculateGraphs(); - - // ### apply constraint! - QSizeF engineSizeHint( - d->sizeHints[QGraphicsAnchorLayoutPrivate::Horizontal][which], - d->sizeHints[QGraphicsAnchorLayoutPrivate::Vertical][which]); - - qreal left, top, right, bottom; - getContentsMargins(&left, &top, &right, &bottom); - - return engineSizeHint + QSizeF(left + right, top + bottom); -} - -QT_END_NAMESPACE -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h deleted file mode 100644 index c387893467..0000000000 --- a/src/gui/graphicsview/qgraphicsanchorlayout.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSANCHORLAYOUT_H -#define QGRAPHICSANCHORLAYOUT_H - -#include <QtGui/qgraphicsitem.h> -#include <QtGui/qgraphicslayout.h> - - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsAnchorPrivate; -class QGraphicsAnchorLayout; -class QGraphicsAnchorLayoutPrivate; - -class Q_GUI_EXPORT QGraphicsAnchor : public QObject -{ - Q_OBJECT - Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing RESET unsetSpacing) - Q_PROPERTY(QSizePolicy::Policy sizePolicy READ sizePolicy WRITE setSizePolicy) -public: - void setSpacing(qreal spacing); - void unsetSpacing(); - qreal spacing() const; - void setSizePolicy(QSizePolicy::Policy policy); - QSizePolicy::Policy sizePolicy() const; - ~QGraphicsAnchor(); -private: - QGraphicsAnchor(QGraphicsAnchorLayout *parent); - - Q_DECLARE_PRIVATE(QGraphicsAnchor) - - friend class QGraphicsAnchorLayoutPrivate; - friend struct AnchorData; -}; - -class Q_GUI_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout -{ -public: - QGraphicsAnchorLayout(QGraphicsLayoutItem *parent = 0); - virtual ~QGraphicsAnchorLayout(); - - QGraphicsAnchor *addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - QGraphicsAnchor *anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - - void addCornerAnchors(QGraphicsLayoutItem *firstItem, Qt::Corner firstCorner, - QGraphicsLayoutItem *secondItem, Qt::Corner secondCorner); - - void addAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem, - Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical); - - void setHorizontalSpacing(qreal spacing); - void setVerticalSpacing(qreal spacing); - void setSpacing(qreal spacing); - qreal horizontalSpacing() const; - qreal verticalSpacing() const; - - void removeAt(int index); - void setGeometry(const QRectF &rect); - int count() const; - QGraphicsLayoutItem *itemAt(int index) const; - - void invalidate(); -protected: - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - -private: - Q_DISABLE_COPY(QGraphicsAnchorLayout) - Q_DECLARE_PRIVATE(QGraphicsAnchorLayout) - - friend class QGraphicsAnchor; -}; - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp deleted file mode 100644 index eaa8ac2b50..0000000000 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ /dev/null @@ -1,3015 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtGui/qwidget.h> -#include <QtGui/qapplication.h> -#include <QtCore/qlinkedlist.h> -#include <QtCore/qstack.h> - -#ifdef QT_DEBUG -#include <QtCore/qfile.h> -#endif - -#include "qgraphicsanchorlayout_p.h" - -#ifndef QT_NO_GRAPHICSVIEW -QT_BEGIN_NAMESPACE - -// To ensure that all variables inside the simplex solver are non-negative, -// we limit the size of anchors in the interval [-limit, limit]. Then before -// sending them to the simplex solver we add "limit" as an offset, so that -// they are actually calculated in the interval [0, 2 * limit] -// To avoid numerical errors in platforms where we use single precision, -// we use a tighter limit for the variables range. -const qreal g_offset = (sizeof(qreal) == sizeof(double)) ? QWIDGETSIZE_MAX : QWIDGETSIZE_MAX / 32; - -QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) - : QObjectPrivate(version), layoutPrivate(0), data(0), - sizePolicy(QSizePolicy::Fixed), preferredSize(0), - hasSize(true) -{ -} - -QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() -{ - if (data) { - // The QGraphicsAnchor was already deleted at this moment. We must clean - // the dangling pointer to avoid double deletion in the AnchorData dtor. - data->graphicsAnchor = 0; - - layoutPrivate->removeAnchor(data->from, data->to); - } -} - -void QGraphicsAnchorPrivate::setSizePolicy(QSizePolicy::Policy policy) -{ - if (sizePolicy != policy) { - sizePolicy = policy; - layoutPrivate->q_func()->invalidate(); - } -} - -void QGraphicsAnchorPrivate::setSpacing(qreal value) -{ - if (!data) { - qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); - return; - } - - if (hasSize && (preferredSize == value)) - return; - - // The anchor has an user-defined size - hasSize = true; - preferredSize = value; - - layoutPrivate->q_func()->invalidate(); -} - -void QGraphicsAnchorPrivate::unsetSpacing() -{ - if (!data) { - qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); - return; - } - - // Return to standard direction - hasSize = false; - - layoutPrivate->q_func()->invalidate(); -} - -qreal QGraphicsAnchorPrivate::spacing() const -{ - if (!data) { - qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); - return 0; - } - - return preferredSize; -} - - -static void applySizePolicy(QSizePolicy::Policy policy, - qreal minSizeHint, qreal prefSizeHint, qreal maxSizeHint, - qreal *minSize, qreal *prefSize, - qreal *maxSize) -{ - // minSize, prefSize and maxSize are initialized - // with item's preferred Size: this is QSizePolicy::Fixed. - // - // Then we check each flag to find the resultant QSizePolicy, - // according to the following table: - // - // constant value - // QSizePolicy::Fixed 0 - // QSizePolicy::Minimum GrowFlag - // QSizePolicy::Maximum ShrinkFlag - // QSizePolicy::Preferred GrowFlag | ShrinkFlag - // QSizePolicy::Ignored GrowFlag | ShrinkFlag | IgnoreFlag - - if (policy & QSizePolicy::ShrinkFlag) - *minSize = minSizeHint; - else - *minSize = prefSizeHint; - - if (policy & QSizePolicy::GrowFlag) - *maxSize = maxSizeHint; - else - *maxSize = prefSizeHint; - - // Note that these two initializations are affected by the previous flags - if (policy & QSizePolicy::IgnoreFlag) - *prefSize = *minSize; - else - *prefSize = prefSizeHint; -} - -AnchorData::~AnchorData() -{ - if (graphicsAnchor) { - // Remove reference to ourself to avoid double removal in - // QGraphicsAnchorPrivate dtor. - graphicsAnchor->d_func()->data = 0; - - delete graphicsAnchor; - } -} - - -void AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) -{ - QSizePolicy::Policy policy; - qreal minSizeHint; - qreal prefSizeHint; - qreal maxSizeHint; - - if (item) { - // It is an internal anchor, fetch size information from the item - if (isLayoutAnchor) { - minSize = 0; - prefSize = 0; - maxSize = QWIDGETSIZE_MAX; - if (isCenterAnchor) - maxSize /= 2; - - minPrefSize = prefSize; - maxPrefSize = maxSize; - return; - } else { - if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) { - policy = item->sizePolicy().horizontalPolicy(); - minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).width(); - prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).width(); - maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).width(); - } else { - policy = item->sizePolicy().verticalPolicy(); - minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).height(); - prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).height(); - maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).height(); - } - - if (isCenterAnchor) { - minSizeHint /= 2; - prefSizeHint /= 2; - maxSizeHint /= 2; - } - } - } else { - // It is a user-created anchor, fetch size information from the associated QGraphicsAnchor - Q_ASSERT(graphicsAnchor); - QGraphicsAnchorPrivate *anchorPrivate = graphicsAnchor->d_func(); - - // Policy, min and max sizes are straightforward - policy = anchorPrivate->sizePolicy; - minSizeHint = 0; - maxSizeHint = QWIDGETSIZE_MAX; - - // Preferred Size - if (anchorPrivate->hasSize) { - // Anchor has user-defined size - prefSizeHint = anchorPrivate->preferredSize; - } else { - // Fetch size information from style - const Qt::Orientation orient = Qt::Orientation(QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + 1); - qreal s = styleInfo->defaultSpacing(orient); - if (s < 0) { - QSizePolicy::ControlType controlTypeFrom = from->m_item->sizePolicy().controlType(); - QSizePolicy::ControlType controlTypeTo = to->m_item->sizePolicy().controlType(); - s = styleInfo->perItemSpacing(controlTypeFrom, controlTypeTo, orient); - - // ### Currently we do not support negative anchors inside the graph. - // To avoid those being created by a negative style spacing, we must - // make this test. - if (s < 0) - s = 0; - } - prefSizeHint = s; - } - } - - // Fill minSize, prefSize and maxSize based on policy and sizeHints - applySizePolicy(policy, minSizeHint, prefSizeHint, maxSizeHint, - &minSize, &prefSize, &maxSize); - - minPrefSize = prefSize; - maxPrefSize = maxSize; - - // Set the anchor effective sizes to preferred. - // - // Note: The idea here is that all items should remain at their - // preferred size unless where that's impossible. In cases where - // the item is subject to restrictions (anchored to the layout - // edges, for instance), the simplex solver will be run to - // recalculate and override the values we set here. - sizeAtMinimum = prefSize; - sizeAtPreferred = prefSize; - sizeAtMaximum = prefSize; -} - -void ParallelAnchorData::updateChildrenSizes() -{ - firstEdge->sizeAtMinimum = sizeAtMinimum; - firstEdge->sizeAtPreferred = sizeAtPreferred; - firstEdge->sizeAtMaximum = sizeAtMaximum; - - if (secondForward()) { - secondEdge->sizeAtMinimum = sizeAtMinimum; - secondEdge->sizeAtPreferred = sizeAtPreferred; - secondEdge->sizeAtMaximum = sizeAtMaximum; - } else { - secondEdge->sizeAtMinimum = -sizeAtMinimum; - secondEdge->sizeAtPreferred = -sizeAtPreferred; - secondEdge->sizeAtMaximum = -sizeAtMaximum; - } - - firstEdge->updateChildrenSizes(); - secondEdge->updateChildrenSizes(); -} - -/* - \internal - - Initialize the parallel anchor size hints using the sizeHint information from - its children. - - Note that parallel groups can lead to unfeasibility, so during calculation, we can - find out one unfeasibility. Because of that this method return boolean. This can't - happen in sequential, so there the method is void. - */ -bool ParallelAnchorData::calculateSizeHints() -{ - // Normalize second child sizes. - // A negative anchor of sizes min, minPref, pref, maxPref and max, is equivalent - // to a forward anchor of sizes -max, -maxPref, -pref, -minPref, -min - qreal secondMin; - qreal secondMinPref; - qreal secondPref; - qreal secondMaxPref; - qreal secondMax; - - if (secondForward()) { - secondMin = secondEdge->minSize; - secondMinPref = secondEdge->minPrefSize; - secondPref = secondEdge->prefSize; - secondMaxPref = secondEdge->maxPrefSize; - secondMax = secondEdge->maxSize; - } else { - secondMin = -secondEdge->maxSize; - secondMinPref = -secondEdge->maxPrefSize; - secondPref = -secondEdge->prefSize; - secondMaxPref = -secondEdge->minPrefSize; - secondMax = -secondEdge->minSize; - } - - minSize = qMax(firstEdge->minSize, secondMin); - maxSize = qMin(firstEdge->maxSize, secondMax); - - // This condition means that the maximum size of one anchor being simplified is smaller than - // the minimum size of the other anchor. The consequence is that there won't be a valid size - // for this parallel setup. - if (minSize > maxSize) { - return false; - } - - // Preferred size calculation - // The calculation of preferred size is done as follows: - // - // 1) Check whether one of the child anchors is the layout structural anchor - // If so, we can simply copy the preferred information from the other child, - // after bounding it to our minimum and maximum sizes. - // If not, then we proceed with the actual calculations. - // - // 2) The whole algorithm for preferred size calculation is based on the fact - // that, if a given anchor cannot remain at its preferred size, it'd rather - // grow than shrink. - // - // What happens though is that while this affirmative is true for simple - // anchors, it may not be true for sequential anchors that have one or more - // reversed anchors inside it. That happens because when a sequential anchor - // grows, any reversed anchors inside it may be required to shrink, something - // we try to avoid, as said above. - // - // To overcome this, besides their actual preferred size "prefSize", each anchor - // exports what we call "minPrefSize" and "maxPrefSize". These two values define - // a surrounding interval where, if required to move, the anchor would rather - // remain inside. - // - // For standard anchors, this area simply represents the region between - // prefSize and maxSize, which makes sense since our first affirmation. - // For composed anchors, these values are calculated as to reduce the global - // "damage", that is, to reduce the total deviation and the total amount of - // anchors that had to shrink. - - if (firstEdge->isLayoutAnchor) { - prefSize = qBound(minSize, secondPref, maxSize); - minPrefSize = qBound(minSize, secondMinPref, maxSize); - maxPrefSize = qBound(minSize, secondMaxPref, maxSize); - } else if (secondEdge->isLayoutAnchor) { - prefSize = qBound(minSize, firstEdge->prefSize, maxSize); - minPrefSize = qBound(minSize, firstEdge->minPrefSize, maxSize); - maxPrefSize = qBound(minSize, firstEdge->maxPrefSize, maxSize); - } else { - // Calculate the intersection between the "preferred" regions of each child - const qreal lowerBoundary = - qBound(minSize, qMax(firstEdge->minPrefSize, secondMinPref), maxSize); - const qreal upperBoundary = - qBound(minSize, qMin(firstEdge->maxPrefSize, secondMaxPref), maxSize); - const qreal prefMean = - qBound(minSize, (firstEdge->prefSize + secondPref) / 2, maxSize); - - if (lowerBoundary < upperBoundary) { - // If there is an intersection between the two regions, this intersection - // will be used as the preferred region of the parallel anchor itself. - // The preferred size will be the bounded average between the two preferred - // sizes. - prefSize = qBound(lowerBoundary, prefMean, upperBoundary); - minPrefSize = lowerBoundary; - maxPrefSize = upperBoundary; - } else { - // If there is no intersection, we have to attribute "damage" to at least - // one of the children. The minimum total damage is achieved in points - // inside the region that extends from (1) the upper boundary of the lower - // region to (2) the lower boundary of the upper region. - // Then, we expose this region as _our_ preferred region and once again, - // use the bounded average as our preferred size. - prefSize = qBound(upperBoundary, prefMean, lowerBoundary); - minPrefSize = upperBoundary; - maxPrefSize = lowerBoundary; - } - } - - // See comment in AnchorData::refreshSizeHints() about sizeAt* values - sizeAtMinimum = prefSize; - sizeAtPreferred = prefSize; - sizeAtMaximum = prefSize; - - return true; -} - -/*! - \internal - returns the factor in the interval [-1, 1]. - -1 is at Minimum - 0 is at Preferred - 1 is at Maximum -*/ -static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal value, qreal min, - qreal minPref, qreal pref, - qreal maxPref, qreal max) -{ - QGraphicsAnchorLayoutPrivate::Interval interval; - qreal lower; - qreal upper; - - if (value < minPref) { - interval = QGraphicsAnchorLayoutPrivate::MinimumToMinPreferred; - lower = min; - upper = minPref; - } else if (value < pref) { - interval = QGraphicsAnchorLayoutPrivate::MinPreferredToPreferred; - lower = minPref; - upper = pref; - } else if (value < maxPref) { - interval = QGraphicsAnchorLayoutPrivate::PreferredToMaxPreferred; - lower = pref; - upper = maxPref; - } else { - interval = QGraphicsAnchorLayoutPrivate::MaxPreferredToMaximum; - lower = maxPref; - upper = max; - } - - qreal progress; - if (upper == lower) { - progress = 0; - } else { - progress = (value - lower) / (upper - lower); - } - - return qMakePair(interval, progress); -} - -static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> &factor, - qreal min, qreal minPref, qreal pref, qreal maxPref, qreal max) -{ - qreal lower = 0; - qreal upper = 0; - - switch (factor.first) { - case QGraphicsAnchorLayoutPrivate::MinimumToMinPreferred: - lower = min; - upper = minPref; - break; - case QGraphicsAnchorLayoutPrivate::MinPreferredToPreferred: - lower = minPref; - upper = pref; - break; - case QGraphicsAnchorLayoutPrivate::PreferredToMaxPreferred: - lower = pref; - upper = maxPref; - break; - case QGraphicsAnchorLayoutPrivate::MaxPreferredToMaximum: - lower = maxPref; - upper = max; - break; - } - - return lower + factor.second * (upper - lower); -} - -void SequentialAnchorData::updateChildrenSizes() -{ - // Band here refers if the value is in the Minimum To Preferred - // band (the lower band) or the Preferred To Maximum (the upper band). - - const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> minFactor = - getFactor(sizeAtMinimum, minSize, minPrefSize, prefSize, maxPrefSize, maxSize); - const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> prefFactor = - getFactor(sizeAtPreferred, minSize, minPrefSize, prefSize, maxPrefSize, maxSize); - const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> maxFactor = - getFactor(sizeAtMaximum, minSize, minPrefSize, prefSize, maxPrefSize, maxSize); - - // XXX This is not safe if Vertex simplification takes place after the sequential - // anchor is created. In that case, "prev" will be a group-vertex, different from - // "from" or "to", that _contains_ one of them. - AnchorVertex *prev = from; - - for (int i = 0; i < m_edges.count(); ++i) { - AnchorData *e = m_edges.at(i); - - const bool edgeIsForward = (e->from == prev); - if (edgeIsForward) { - e->sizeAtMinimum = interpolate(minFactor, e->minSize, e->minPrefSize, - e->prefSize, e->maxPrefSize, e->maxSize); - e->sizeAtPreferred = interpolate(prefFactor, e->minSize, e->minPrefSize, - e->prefSize, e->maxPrefSize, e->maxSize); - e->sizeAtMaximum = interpolate(maxFactor, e->minSize, e->minPrefSize, - e->prefSize, e->maxPrefSize, e->maxSize); - prev = e->to; - } else { - Q_ASSERT(prev == e->to); - e->sizeAtMinimum = interpolate(minFactor, e->maxSize, e->maxPrefSize, - e->prefSize, e->minPrefSize, e->minSize); - e->sizeAtPreferred = interpolate(prefFactor, e->maxSize, e->maxPrefSize, - e->prefSize, e->minPrefSize, e->minSize); - e->sizeAtMaximum = interpolate(maxFactor, e->maxSize, e->maxPrefSize, - e->prefSize, e->minPrefSize, e->minSize); - prev = e->from; - } - - e->updateChildrenSizes(); - } -} - -void SequentialAnchorData::calculateSizeHints() -{ - minSize = 0; - prefSize = 0; - maxSize = 0; - minPrefSize = 0; - maxPrefSize = 0; - - AnchorVertex *prev = from; - - for (int i = 0; i < m_edges.count(); ++i) { - AnchorData *edge = m_edges.at(i); - - const bool edgeIsForward = (edge->from == prev); - if (edgeIsForward) { - minSize += edge->minSize; - prefSize += edge->prefSize; - maxSize += edge->maxSize; - minPrefSize += edge->minPrefSize; - maxPrefSize += edge->maxPrefSize; - prev = edge->to; - } else { - Q_ASSERT(prev == edge->to); - minSize -= edge->maxSize; - prefSize -= edge->prefSize; - maxSize -= edge->minSize; - minPrefSize -= edge->maxPrefSize; - maxPrefSize -= edge->minPrefSize; - prev = edge->from; - } - } - - // See comment in AnchorData::refreshSizeHints() about sizeAt* values - sizeAtMinimum = prefSize; - sizeAtPreferred = prefSize; - sizeAtMaximum = prefSize; -} - -#ifdef QT_DEBUG -void AnchorData::dump(int indent) { - if (type == Parallel) { - qDebug("%*s type: parallel:", indent, ""); - ParallelAnchorData *p = static_cast<ParallelAnchorData *>(this); - p->firstEdge->dump(indent+2); - p->secondEdge->dump(indent+2); - } else if (type == Sequential) { - SequentialAnchorData *s = static_cast<SequentialAnchorData *>(this); - int kids = s->m_edges.count(); - qDebug("%*s type: sequential(%d):", indent, "", kids); - for (int i = 0; i < kids; ++i) { - s->m_edges.at(i)->dump(indent+2); - } - } else { - qDebug("%*s type: Normal:", indent, ""); - } -} - -#endif - -QSimplexConstraint *GraphPath::constraint(const GraphPath &path) const -{ - // Calculate - QSet<AnchorData *> cPositives; - QSet<AnchorData *> cNegatives; - QSet<AnchorData *> intersection; - - cPositives = positives + path.negatives; - cNegatives = negatives + path.positives; - - intersection = cPositives & cNegatives; - - cPositives -= intersection; - cNegatives -= intersection; - - // Fill - QSimplexConstraint *c = new QSimplexConstraint; - QSet<AnchorData *>::iterator i; - for (i = cPositives.begin(); i != cPositives.end(); ++i) - c->variables.insert(*i, 1.0); - - for (i = cNegatives.begin(); i != cNegatives.end(); ++i) - c->variables.insert(*i, -1.0); - - return c; -} - -#ifdef QT_DEBUG -QString GraphPath::toString() const -{ - QString string(QLatin1String("Path: ")); - foreach(AnchorData *edge, positives) - string += QString::fromAscii(" (+++) %1").arg(edge->toString()); - - foreach(AnchorData *edge, negatives) - string += QString::fromAscii(" (---) %1").arg(edge->toString()); - - return string; -} -#endif - -QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() - : calculateGraphCacheDirty(true), styleInfoDirty(true) -{ - for (int i = 0; i < NOrientations; ++i) { - for (int j = 0; j < 3; ++j) { - sizeHints[i][j] = -1; - } - interpolationProgress[i] = -1; - - spacings[i] = -1; - graphHasConflicts[i] = false; - - layoutFirstVertex[i] = 0; - layoutCentralVertex[i] = 0; - layoutLastVertex[i] = 0; - } -} - -Qt::AnchorPoint QGraphicsAnchorLayoutPrivate::oppositeEdge(Qt::AnchorPoint edge) -{ - switch (edge) { - case Qt::AnchorLeft: - edge = Qt::AnchorRight; - break; - case Qt::AnchorRight: - edge = Qt::AnchorLeft; - break; - case Qt::AnchorTop: - edge = Qt::AnchorBottom; - break; - case Qt::AnchorBottom: - edge = Qt::AnchorTop; - break; - default: - break; - } - return edge; -} - - -/*! - * \internal - * - * helper function in order to avoid overflowing anchor sizes - * the returned size will never be larger than FLT_MAX - * - */ -inline static qreal checkAdd(qreal a, qreal b) -{ - if (FLT_MAX - b < a) - return FLT_MAX; - return a + b; -} - -/*! - \internal - - Adds \a newAnchor to the graph. - - Returns the newAnchor itself if it could be added without further changes to the graph. If a - new parallel anchor had to be created, then returns the new parallel anchor. If a parallel anchor - had to be created and it results in an unfeasible setup, \a feasible is set to false, otherwise - true. - - Note that in the case a new parallel anchor is created, it might also take over some constraints - from its children anchors. -*/ -AnchorData *QGraphicsAnchorLayoutPrivate::addAnchorMaybeParallel(AnchorData *newAnchor, bool *feasible) -{ - Orientation orientation = Orientation(newAnchor->orientation); - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - *feasible = true; - - // If already exists one anchor where newAnchor is supposed to be, we create a parallel - // anchor. - if (AnchorData *oldAnchor = g.takeEdge(newAnchor->from, newAnchor->to)) { - ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, newAnchor); - - // The parallel anchor will "replace" its children anchors in - // every center constraint that they appear. - - // ### If the dependent (center) anchors had reference(s) to their constraints, we - // could avoid traversing all the itemCenterConstraints. - QList<QSimplexConstraint *> &constraints = itemCenterConstraints[orientation]; - - AnchorData *children[2] = { oldAnchor, newAnchor }; - QList<QSimplexConstraint *> *childrenConstraints[2] = { ¶llel->m_firstConstraints, - ¶llel->m_secondConstraints }; - - for (int i = 0; i < 2; ++i) { - AnchorData *child = children[i]; - QList<QSimplexConstraint *> *childConstraints = childrenConstraints[i]; - - // We need to fix the second child constraints if the parallel group will have the - // opposite direction of the second child anchor. For the point of view of external - // entities, this anchor was reversed. So if at some point we say that the parallel - // has a value of 20, this mean that the second child (when reversed) will be - // assigned -20. - const bool needsReverse = i == 1 && !parallel->secondForward(); - - if (!child->isCenterAnchor) - continue; - - parallel->isCenterAnchor = true; - - for (int j = 0; j < constraints.count(); ++j) { - QSimplexConstraint *c = constraints[j]; - if (c->variables.contains(child)) { - childConstraints->append(c); - qreal v = c->variables.take(child); - if (needsReverse) - v *= -1; - c->variables.insert(parallel, v); - } - } - } - - // At this point we can identify that the parallel anchor is not feasible, e.g. one - // anchor minimum size is bigger than the other anchor maximum size. - *feasible = parallel->calculateSizeHints(); - newAnchor = parallel; - } - - g.createEdge(newAnchor->from, newAnchor->to, newAnchor); - return newAnchor; -} - -/*! - \internal - - Takes the sequence of vertices described by (\a before, \a vertices, \a after) and removes - all anchors connected to the vertices in \a vertices, returning one simplified anchor between - \a before and \a after. - - Note that this function doesn't add the created anchor to the graph. This should be done by - the caller. -*/ -static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph, - AnchorVertex *before, - const QVector<AnchorVertex*> &vertices, - AnchorVertex *after) -{ -#if defined(QT_DEBUG) && 0 - QString strVertices; - for (int i = 0; i < vertices.count(); ++i) { - strVertices += QString::fromAscii("%1 - ").arg(vertices.at(i)->toString()); - } - QString strPath = QString::fromAscii("%1 - %2%3").arg(before->toString(), strVertices, after->toString()); - qDebug("simplifying [%s] to [%s - %s]", qPrintable(strPath), qPrintable(before->toString()), qPrintable(after->toString())); -#endif - - AnchorVertex *prev = before; - QVector<AnchorData *> edges; - - // Take from the graph, the edges that will be simplificated - for (int i = 0; i < vertices.count(); ++i) { - AnchorVertex *next = vertices.at(i); - AnchorData *ad = graph->takeEdge(prev, next); - Q_ASSERT(ad); - edges.append(ad); - prev = next; - } - - // Take the last edge (not covered in the loop above) - AnchorData *ad = graph->takeEdge(vertices.last(), after); - Q_ASSERT(ad); - edges.append(ad); - - // Create sequence - SequentialAnchorData *sequence = new SequentialAnchorData(vertices, edges); - sequence->from = before; - sequence->to = after; - - sequence->calculateSizeHints(); - - return sequence; -} - -/*! - \internal - - The purpose of this function is to simplify the graph. - Simplification serves two purposes: - 1. Reduce the number of edges in the graph, (thus the number of variables to the equation - solver is reduced, and the solver performs better). - 2. Be able to do distribution of sequences of edges more intelligently (esp. with sequential - anchors) - - It is essential that it must be possible to restore simplified anchors back to their "original" - form. This is done by restoreSimplifiedAnchor(). - - There are two types of simplification that can be done: - 1. Sequential simplification - Sequential simplification means that all sequences of anchors will be merged into one single - anchor. Only anhcors that points in the same direction will be merged. - 2. Parallel simplification - If a simplified sequential anchor is about to be inserted between two vertices in the graph - and there already exist an anchor between those two vertices, a parallel anchor will be - created that serves as a placeholder for the sequential anchor and the anchor that was - already between the two vertices. - - The process of simplification can be described as: - - 1. Simplify all sequences of anchors into one anchor. - If no further simplification was done, go to (3) - - If there already exist an anchor where the sequential anchor is supposed to be inserted, - take that anchor out of the graph - - Then create a parallel anchor that holds the sequential anchor and the anchor just taken - out of the graph. - 2. Go to (1) - 3. Done - - When creating the parallel anchors, the algorithm might identify unfeasible situations. In this - case the simplification process stops and returns false. Otherwise returns true. -*/ -bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) -{ - if (items.isEmpty()) - return true; - -#if defined(QT_DEBUG) && 0 - qDebug("Simplifying Graph for %s", - orientation == Horizontal ? "Horizontal" : "Vertical"); - - static int count = 0; - if (orientation == Horizontal) { - count++; - dumpGraph(QString::fromAscii("%1-full").arg(count)); - } -#endif - - // Vertex simplification - if (!simplifyVertices(orientation)) { - restoreVertices(orientation); - return false; - } - - // Anchor simplification - bool dirty; - bool feasible = true; - do { - dirty = simplifyGraphIteration(orientation, &feasible); - } while (dirty && feasible); - - // Note that if we are not feasible, we fallback and make sure that the graph is fully restored - if (!feasible) { - restoreSimplifiedGraph(orientation); - restoreVertices(orientation); - return false; - } - -#if defined(QT_DEBUG) && 0 - dumpGraph(QString::fromAscii("%1-simplified-%2").arg(count).arg( - QString::fromAscii(orientation == Horizontal ? "Horizontal" : "Vertical"))); -#endif - - return true; -} - -static AnchorVertex *replaceVertex_helper(AnchorData *data, AnchorVertex *oldV, AnchorVertex *newV) -{ - AnchorVertex *other; - if (data->from == oldV) { - data->from = newV; - other = data->to; - } else { - data->to = newV; - other = data->from; - } - return other; -} - -bool QGraphicsAnchorLayoutPrivate::replaceVertex(Orientation orientation, AnchorVertex *oldV, - AnchorVertex *newV, const QList<AnchorData *> &edges) -{ - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - bool feasible = true; - - for (int i = 0; i < edges.count(); ++i) { - AnchorData *ad = edges[i]; - AnchorVertex *otherV = replaceVertex_helper(ad, oldV, newV); - -#if defined(QT_DEBUG) - ad->name = QString::fromAscii("%1 --to--> %2").arg(ad->from->toString()).arg(ad->to->toString()); -#endif - - bool newFeasible; - AnchorData *newAnchor = addAnchorMaybeParallel(ad, &newFeasible); - feasible &= newFeasible; - - if (newAnchor != ad) { - // A parallel was created, we mark that in the list of anchors created by vertex - // simplification. This is needed because we want to restore them in a separate step - // from the restoration of anchor simplification. - anchorsFromSimplifiedVertices[orientation].append(newAnchor); - } - - g.takeEdge(oldV, otherV); - } - - return feasible; -} - -/*! - \internal -*/ -bool QGraphicsAnchorLayoutPrivate::simplifyVertices(Orientation orientation) -{ - Q_Q(QGraphicsAnchorLayout); - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - - // We'll walk through vertices - QStack<AnchorVertex *> stack; - stack.push(layoutFirstVertex[orientation]); - QSet<AnchorVertex *> visited; - - while (!stack.isEmpty()) { - AnchorVertex *v = stack.pop(); - visited.insert(v); - - // Each adjacent of 'v' is a possible vertex to be merged. So we traverse all of - // them. Since once a merge is made, we might add new adjacents, and we don't want to - // pass two times through one adjacent. The 'index' is used to track our position. - QList<AnchorVertex *> adjacents = g.adjacentVertices(v); - int index = 0; - - while (index < adjacents.count()) { - AnchorVertex *next = adjacents.at(index); - index++; - - AnchorData *data = g.edgeData(v, next); - const bool bothLayoutVertices = v->m_item == q && next->m_item == q; - const bool zeroSized = !data->minSize && !data->maxSize; - - if (!bothLayoutVertices && zeroSized) { - - // Create a new vertex pair, note that we keep a list of those vertices so we can - // easily process them when restoring the graph. - AnchorVertexPair *newV = new AnchorVertexPair(v, next, data); - simplifiedVertices[orientation].append(newV); - - // Collect the anchors of both vertices, the new vertex pair will take their place - // in those anchors - const QList<AnchorVertex *> &vAdjacents = g.adjacentVertices(v); - const QList<AnchorVertex *> &nextAdjacents = g.adjacentVertices(next); - - for (int i = 0; i < vAdjacents.count(); ++i) { - AnchorVertex *adjacent = vAdjacents.at(i); - if (adjacent != next) { - AnchorData *ad = g.edgeData(v, adjacent); - newV->m_firstAnchors.append(ad); - } - } - - for (int i = 0; i < nextAdjacents.count(); ++i) { - AnchorVertex *adjacent = nextAdjacents.at(i); - if (adjacent != v) { - AnchorData *ad = g.edgeData(next, adjacent); - newV->m_secondAnchors.append(ad); - - // We'll also add new vertices to the adjacent list of the new 'v', to be - // created as a vertex pair and replace the current one. - if (!adjacents.contains(adjacent)) - adjacents.append(adjacent); - } - } - - // ### merge this loop into the ones that calculated m_firstAnchors/m_secondAnchors? - // Make newV take the place of v and next - bool feasible = replaceVertex(orientation, v, newV, newV->m_firstAnchors); - feasible &= replaceVertex(orientation, next, newV, newV->m_secondAnchors); - - // Update the layout vertex information if one of the vertices is a layout vertex. - AnchorVertex *layoutVertex = 0; - if (v->m_item == q) - layoutVertex = v; - else if (next->m_item == q) - layoutVertex = next; - - if (layoutVertex) { - // Layout vertices always have m_item == q... - newV->m_item = q; - changeLayoutVertex(orientation, layoutVertex, newV); - } - - g.takeEdge(v, next); - - // If a non-feasibility is found, we leave early and cancel the simplification - if (!feasible) - return false; - - v = newV; - visited.insert(newV); - - } else if (!visited.contains(next) && !stack.contains(next)) { - // If the adjacent is not fit for merge and it wasn't visited by the outermost - // loop, we add it to the stack. - stack.push(next); - } - } - } - - return true; -} - -/*! - \internal - - One iteration of the simplification algorithm. Returns true if another iteration is needed. - - The algorithm walks the graph in depth-first order, and only collects vertices that has two - edges connected to it. If the vertex does not have two edges or if it is a layout edge, it - will take all the previously collected vertices and try to create a simplified sequential - anchor representing all the previously collected vertices. Once the simplified anchor is - inserted, the collected list is cleared in order to find the next sequence to simplify. - - Note that there are some catches to this that are not covered by the above explanation, see - the function comments for more details. -*/ -bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation, - bool *feasible) -{ - Q_Q(QGraphicsAnchorLayout); - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - - QSet<AnchorVertex *> visited; - QStack<QPair<AnchorVertex *, AnchorVertex *> > stack; - stack.push(qMakePair(static_cast<AnchorVertex *>(0), layoutFirstVertex[orientation])); - QVector<AnchorVertex*> candidates; - - // Walk depth-first, in the stack we store start of the candidate sequence (beforeSequence) - // and the vertex to be visited. - while (!stack.isEmpty()) { - QPair<AnchorVertex *, AnchorVertex *> pair = stack.pop(); - AnchorVertex *beforeSequence = pair.first; - AnchorVertex *v = pair.second; - - // The basic idea is to determine whether we found an end of sequence, - // if that's the case, we stop adding vertices to the candidate list - // and do a simplification step. - // - // A vertex can trigger an end of sequence if - // (a) it is a layout vertex, we don't simplify away the layout vertices; - // (b) it does not have exactly 2 adjacents; - // (c) its next adjacent is already visited (a cycle in the graph). - // (d) the next anchor is a center anchor. - - const QList<AnchorVertex *> &adjacents = g.adjacentVertices(v); - const bool isLayoutVertex = v->m_item == q; - AnchorVertex *afterSequence = v; - bool endOfSequence = false; - - // - // Identify the end cases. - // - - // Identifies cases (a) and (b) - endOfSequence = isLayoutVertex || adjacents.count() != 2; - - if (!endOfSequence) { - // This is a tricky part. We peek at the next vertex to find out whether - // - // - we already visited the next vertex (c); - // - the next anchor is a center (d). - // - // Those are needed to identify the remaining end of sequence cases. Note that unlike - // (a) and (b), we preempt the end of sequence by looking into the next vertex. - - // Peek at the next vertex - AnchorVertex *after; - if (candidates.isEmpty()) - after = (beforeSequence == adjacents.last() ? adjacents.first() : adjacents.last()); - else - after = (candidates.last() == adjacents.last() ? adjacents.first() : adjacents.last()); - - // ### At this point we assumed that candidates will not contain 'after', this may not hold - // when simplifying FLOATing anchors. - Q_ASSERT(!candidates.contains(after)); - - const AnchorData *data = g.edgeData(v, after); - Q_ASSERT(data); - const bool cycleFound = visited.contains(after); - - // Now cases (c) and (d)... - endOfSequence = cycleFound || data->isCenterAnchor; - - if (!endOfSequence) { - // If it's not an end of sequence, then the vertex didn't trigger neither of the - // previously three cases, so it can be added to the candidates list. - candidates.append(v); - } else if (cycleFound && (beforeSequence != after)) { - afterSequence = after; - candidates.append(v); - } - } - - // - // Add next non-visited vertices to the stack. - // - for (int i = 0; i < adjacents.count(); ++i) { - AnchorVertex *next = adjacents.at(i); - if (visited.contains(next)) - continue; - - // If current vertex is an end of sequence, and it'll reset the candidates list. So - // the next vertices will build candidates lists with the current vertex as 'before' - // vertex. If it's not an end of sequence, we keep the original 'before' vertex, - // since we are keeping the candidates list. - if (endOfSequence) - stack.push(qMakePair(v, next)); - else - stack.push(qMakePair(beforeSequence, next)); - } - - visited.insert(v); - - if (!endOfSequence || candidates.isEmpty()) - continue; - - // - // Create a sequence for (beforeSequence, candidates, afterSequence). - // - - // One restriction we have is to not simplify half of an anchor and let the other half - // unsimplified. So we remove center edges before and after the sequence. - const AnchorData *firstAnchor = g.edgeData(beforeSequence, candidates.first()); - if (firstAnchor->isCenterAnchor) { - beforeSequence = candidates.first(); - candidates.remove(0); - - // If there's not candidates to be simplified, leave. - if (candidates.isEmpty()) - continue; - } - - const AnchorData *lastAnchor = g.edgeData(candidates.last(), afterSequence); - if (lastAnchor->isCenterAnchor) { - afterSequence = candidates.last(); - candidates.remove(candidates.count() - 1); - - if (candidates.isEmpty()) - continue; - } - - // - // Add the sequence to the graph. - // - - AnchorData *sequence = createSequence(&g, beforeSequence, candidates, afterSequence); - - // If 'beforeSequence' and 'afterSequence' already had an anchor between them, we'll - // create a parallel anchor between the new sequence and the old anchor. - bool newFeasible; - AnchorData *newAnchor = addAnchorMaybeParallel(sequence, &newFeasible); - - if (!newFeasible) { - *feasible = false; - return false; - } - - // When a new parallel anchor is create in the graph, we finish the iteration and return - // true to indicate a new iteration is needed. This happens because a parallel anchor - // changes the number of adjacents one vertex has, possibly opening up oportunities for - // building candidate lists (when adjacents == 2). - if (newAnchor != sequence) - return true; - - // If there was no parallel simplification, we'll keep walking the graph. So we clear the - // candidates list to start again. - candidates.clear(); - } - - return false; -} - -void QGraphicsAnchorLayoutPrivate::restoreSimplifiedAnchor(AnchorData *edge) -{ -#if 0 - static const char *anchortypes[] = {"Normal", - "Sequential", - "Parallel"}; - qDebug("Restoring %s edge.", anchortypes[int(edge->type)]); -#endif - - Graph<AnchorVertex, AnchorData> &g = graph[edge->orientation]; - - if (edge->type == AnchorData::Normal) { - g.createEdge(edge->from, edge->to, edge); - - } else if (edge->type == AnchorData::Sequential) { - SequentialAnchorData *sequence = static_cast<SequentialAnchorData *>(edge); - - for (int i = 0; i < sequence->m_edges.count(); ++i) { - AnchorData *data = sequence->m_edges.at(i); - restoreSimplifiedAnchor(data); - } - - delete sequence; - - } else if (edge->type == AnchorData::Parallel) { - - // Skip parallel anchors that were created by vertex simplification, they will be processed - // later, when restoring vertex simplification. - // ### we could improve this check bit having a bit inside 'edge' - if (anchorsFromSimplifiedVertices[edge->orientation].contains(edge)) - return; - - ParallelAnchorData* parallel = static_cast<ParallelAnchorData*>(edge); - restoreSimplifiedConstraints(parallel); - - // ### Because of the way parallel anchors are created in the anchor simplification - // algorithm, we know that one of these will be a sequence, so it'll be safe if the other - // anchor create an edge between the same vertices as the parallel. - Q_ASSERT(parallel->firstEdge->type == AnchorData::Sequential - || parallel->secondEdge->type == AnchorData::Sequential); - restoreSimplifiedAnchor(parallel->firstEdge); - restoreSimplifiedAnchor(parallel->secondEdge); - - delete parallel; - } -} - -void QGraphicsAnchorLayoutPrivate::restoreSimplifiedConstraints(ParallelAnchorData *parallel) -{ - if (!parallel->isCenterAnchor) - return; - - for (int i = 0; i < parallel->m_firstConstraints.count(); ++i) { - QSimplexConstraint *c = parallel->m_firstConstraints.at(i); - qreal v = c->variables[parallel]; - c->variables.remove(parallel); - c->variables.insert(parallel->firstEdge, v); - } - - // When restoring, we might have to revert constraints back. See comments on - // addAnchorMaybeParallel(). - const bool needsReverse = !parallel->secondForward(); - - for (int i = 0; i < parallel->m_secondConstraints.count(); ++i) { - QSimplexConstraint *c = parallel->m_secondConstraints.at(i); - qreal v = c->variables[parallel]; - if (needsReverse) - v *= -1; - c->variables.remove(parallel); - c->variables.insert(parallel->secondEdge, v); - } -} - -void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation) -{ -#if 0 - qDebug("Restoring Simplified Graph for %s", - orientation == Horizontal ? "Horizontal" : "Vertical"); -#endif - - // Restore anchor simplification - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections(); - for (int i = 0; i < connections.count(); ++i) { - AnchorVertex *v1 = connections.at(i).first; - AnchorVertex *v2 = connections.at(i).second; - AnchorData *edge = g.edgeData(v1, v2); - - // We restore only sequential anchors and parallels that were not created by - // vertex simplification. - if (edge->type == AnchorData::Sequential - || (edge->type == AnchorData::Parallel && - !anchorsFromSimplifiedVertices[orientation].contains(edge))) { - - g.takeEdge(v1, v2); - restoreSimplifiedAnchor(edge); - } - } - - restoreVertices(orientation); -} - -void QGraphicsAnchorLayoutPrivate::restoreVertices(Orientation orientation) -{ - Q_Q(QGraphicsAnchorLayout); - - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - QList<AnchorVertexPair *> &toRestore = simplifiedVertices[orientation]; - - // Since we keep a list of parallel anchors and vertices that were created during vertex - // simplification, we can now iterate on those lists instead of traversing the graph - // recursively. - - // First, restore the constraints changed when we created parallel anchors. Note that this - // works at this point because the constraints doesn't depend on vertex information and at - // this point it's always safe to identify whether the second child is forward or backwards. - // In the next step, we'll change the anchors vertices so that would not be possible anymore. - QList<AnchorData *> ¶llelAnchors = anchorsFromSimplifiedVertices[orientation]; - - for (int i = parallelAnchors.count() - 1; i >= 0; --i) { - ParallelAnchorData *parallel = static_cast<ParallelAnchorData *>(parallelAnchors.at(i)); - restoreSimplifiedConstraints(parallel); - } - - // Then, we will restore the vertices in the inverse order of creation, this way we ensure that - // the vertex being restored was not wrapped by another simplification. - for (int i = toRestore.count() - 1; i >= 0; --i) { - AnchorVertexPair *pair = toRestore.at(i); - QList<AnchorVertex *> adjacents = g.adjacentVertices(pair); - - // Restore the removed edge, this will also restore both vertices 'first' and 'second' to - // the graph structure. - AnchorVertex *first = pair->m_first; - AnchorVertex *second = pair->m_second; - g.createEdge(first, second, pair->m_removedAnchor); - - // Restore the anchors for the first child vertex - for (int j = 0; j < pair->m_firstAnchors.count(); ++j) { - AnchorData *ad = pair->m_firstAnchors.at(j); - Q_ASSERT(ad->from == pair || ad->to == pair); - - replaceVertex_helper(ad, pair, first); - g.createEdge(ad->from, ad->to, ad); - } - - // Restore the anchors for the second child vertex - for (int j = 0; j < pair->m_secondAnchors.count(); ++j) { - AnchorData *ad = pair->m_secondAnchors.at(j); - Q_ASSERT(ad->from == pair || ad->to == pair); - - replaceVertex_helper(ad, pair, second); - g.createEdge(ad->from, ad->to, ad); - } - - for (int j = 0; j < adjacents.count(); ++j) { - g.takeEdge(pair, adjacents.at(j)); - } - - // The pair simplified a layout vertex, so place back the correct vertex in the variable - // that track layout vertices - if (pair->m_item == q) { - AnchorVertex *layoutVertex = first->m_item == q ? first : second; - Q_ASSERT(layoutVertex->m_item == q); - changeLayoutVertex(orientation, pair, layoutVertex); - } - - delete pair; - } - qDeleteAll(parallelAnchors); - parallelAnchors.clear(); - toRestore.clear(); -} - -QGraphicsAnchorLayoutPrivate::Orientation -QGraphicsAnchorLayoutPrivate::edgeOrientation(Qt::AnchorPoint edge) -{ - return edge > Qt::AnchorRight ? Vertical : Horizontal; -} - -/*! - \internal - - Create internal anchors to connect the layout edges (Left to Right and - Top to Bottom). - - These anchors doesn't have size restrictions, that will be enforced by - other anchors and items in the layout. -*/ -void QGraphicsAnchorLayoutPrivate::createLayoutEdges() -{ - Q_Q(QGraphicsAnchorLayout); - QGraphicsLayoutItem *layout = q; - - // Horizontal - AnchorData *data = new AnchorData; - addAnchor_helper(layout, Qt::AnchorLeft, layout, - Qt::AnchorRight, data); - data->maxSize = QWIDGETSIZE_MAX; - - // Save a reference to layout vertices - layoutFirstVertex[Horizontal] = internalVertex(layout, Qt::AnchorLeft); - layoutCentralVertex[Horizontal] = 0; - layoutLastVertex[Horizontal] = internalVertex(layout, Qt::AnchorRight); - - // Vertical - data = new AnchorData; - addAnchor_helper(layout, Qt::AnchorTop, layout, - Qt::AnchorBottom, data); - data->maxSize = QWIDGETSIZE_MAX; - - // Save a reference to layout vertices - layoutFirstVertex[Vertical] = internalVertex(layout, Qt::AnchorTop); - layoutCentralVertex[Vertical] = 0; - layoutLastVertex[Vertical] = internalVertex(layout, Qt::AnchorBottom); -} - -void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() -{ - Q_Q(QGraphicsAnchorLayout); - - Q_ASSERT(!internalVertex(q, Qt::AnchorHorizontalCenter)); - Q_ASSERT(!internalVertex(q, Qt::AnchorVerticalCenter)); - - removeAnchor_helper(internalVertex(q, Qt::AnchorLeft), - internalVertex(q, Qt::AnchorRight)); - removeAnchor_helper(internalVertex(q, Qt::AnchorTop), - internalVertex(q, Qt::AnchorBottom)); -} - -void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) -{ - items.append(item); - - // Create horizontal and vertical internal anchors for the item and - // refresh its size hint / policy values. - AnchorData *data = new AnchorData; - addAnchor_helper(item, Qt::AnchorLeft, item, Qt::AnchorRight, data); - data->refreshSizeHints(); - - data = new AnchorData; - addAnchor_helper(item, Qt::AnchorTop, item, Qt::AnchorBottom, data); - data->refreshSizeHints(); -} - -/*! - \internal - - By default, each item in the layout is represented internally as - a single anchor in each direction. For instance, from Left to Right. - - However, to support anchorage of items to the center of items, we - must split this internal anchor into two half-anchors. From Left - to Center and then from Center to Right, with the restriction that - these anchors must have the same time at all times. -*/ -void QGraphicsAnchorLayoutPrivate::createCenterAnchors( - QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge) -{ - Q_Q(QGraphicsAnchorLayout); - - Orientation orientation; - switch (centerEdge) { - case Qt::AnchorHorizontalCenter: - orientation = Horizontal; - break; - case Qt::AnchorVerticalCenter: - orientation = Vertical; - break; - default: - // Don't create center edges unless needed - return; - } - - // Check if vertex already exists - if (internalVertex(item, centerEdge)) - return; - - // Orientation code - Qt::AnchorPoint firstEdge; - Qt::AnchorPoint lastEdge; - - if (orientation == Horizontal) { - firstEdge = Qt::AnchorLeft; - lastEdge = Qt::AnchorRight; - } else { - firstEdge = Qt::AnchorTop; - lastEdge = Qt::AnchorBottom; - } - - AnchorVertex *first = internalVertex(item, firstEdge); - AnchorVertex *last = internalVertex(item, lastEdge); - Q_ASSERT(first && last); - - // Create new anchors - QSimplexConstraint *c = new QSimplexConstraint; - - AnchorData *data = new AnchorData; - c->variables.insert(data, 1.0); - addAnchor_helper(item, firstEdge, item, centerEdge, data); - data->isCenterAnchor = true; - data->dependency = AnchorData::Master; - data->refreshSizeHints(); - - data = new AnchorData; - c->variables.insert(data, -1.0); - addAnchor_helper(item, centerEdge, item, lastEdge, data); - data->isCenterAnchor = true; - data->dependency = AnchorData::Slave; - data->refreshSizeHints(); - - itemCenterConstraints[orientation].append(c); - - // Remove old one - removeAnchor_helper(first, last); - - if (item == q) { - layoutCentralVertex[orientation] = internalVertex(q, centerEdge); - } -} - -void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( - QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, - bool substitute) -{ - Q_Q(QGraphicsAnchorLayout); - - Orientation orientation; - switch (centerEdge) { - case Qt::AnchorHorizontalCenter: - orientation = Horizontal; - break; - case Qt::AnchorVerticalCenter: - orientation = Vertical; - break; - default: - // Don't remove edges that not the center ones - return; - } - - // Orientation code - Qt::AnchorPoint firstEdge; - Qt::AnchorPoint lastEdge; - - if (orientation == Horizontal) { - firstEdge = Qt::AnchorLeft; - lastEdge = Qt::AnchorRight; - } else { - firstEdge = Qt::AnchorTop; - lastEdge = Qt::AnchorBottom; - } - - AnchorVertex *center = internalVertex(item, centerEdge); - if (!center) - return; - AnchorVertex *first = internalVertex(item, firstEdge); - - Q_ASSERT(first); - Q_ASSERT(center); - - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - - - AnchorData *oldData = g.edgeData(first, center); - // Remove center constraint - for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) { - if (itemCenterConstraints[orientation].at(i)->variables.contains(oldData)) { - delete itemCenterConstraints[orientation].takeAt(i); - break; - } - } - - if (substitute) { - // Create the new anchor that should substitute the left-center-right anchors. - AnchorData *data = new AnchorData; - addAnchor_helper(item, firstEdge, item, lastEdge, data); - data->refreshSizeHints(); - - // Remove old anchors - removeAnchor_helper(first, center); - removeAnchor_helper(center, internalVertex(item, lastEdge)); - - } else { - // this is only called from removeAnchors() - // first, remove all non-internal anchors - QList<AnchorVertex*> adjacents = g.adjacentVertices(center); - for (int i = 0; i < adjacents.count(); ++i) { - AnchorVertex *v = adjacents.at(i); - if (v->m_item != item) { - removeAnchor_helper(center, internalVertex(v->m_item, v->m_edge)); - } - } - // when all non-internal anchors is removed it will automatically merge the - // center anchor into a left-right (or top-bottom) anchor. We must also delete that. - // by this time, the center vertex is deleted and merged into a non-centered internal anchor - removeAnchor_helper(first, internalVertex(item, lastEdge)); - } - - if (item == q) { - layoutCentralVertex[orientation] = 0; - } -} - - -void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item, - Orientation orientation) -{ - // Remove the item center constraints associated to this item - // ### This is a temporary solution. We should probably use a better - // data structure to hold items and/or their associated constraints - // so that we can remove those easily - - AnchorVertex *first = internalVertex(item, orientation == Horizontal ? - Qt::AnchorLeft : - Qt::AnchorTop); - AnchorVertex *center = internalVertex(item, orientation == Horizontal ? - Qt::AnchorHorizontalCenter : - Qt::AnchorVerticalCenter); - - // Skip if no center constraints exist - if (!center) - return; - - Q_ASSERT(first); - AnchorData *internalAnchor = graph[orientation].edgeData(first, center); - - // Look for our anchor in all item center constraints, then remove it - for (int i = 0; i < itemCenterConstraints[orientation].size(); ++i) { - if (itemCenterConstraints[orientation].at(i)->variables.contains(internalAnchor)) { - delete itemCenterConstraints[orientation].takeAt(i); - break; - } - } -} - -/*! - * \internal - * Implements the high level "addAnchor" feature. Called by the public API - * addAnchor method. - * - * The optional \a spacing argument defines the size of the anchor. If not provided, - * the anchor size is either 0 or not-set, depending on type of anchor created (see - * matrix below). - * - * All anchors that remain with size not-set will assume the standard spacing, - * set either by the layout style or through the "setSpacing" layout API. - */ -QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - qreal *spacing) -{ - Q_Q(QGraphicsAnchorLayout); - if ((firstItem == 0) || (secondItem == 0)) { - qWarning("QGraphicsAnchorLayout::addAnchor(): " - "Cannot anchor NULL items"); - return 0; - } - - if (firstItem == secondItem) { - qWarning("QGraphicsAnchorLayout::addAnchor(): " - "Cannot anchor the item to itself"); - return 0; - } - - if (edgeOrientation(secondEdge) != edgeOrientation(firstEdge)) { - qWarning("QGraphicsAnchorLayout::addAnchor(): " - "Cannot anchor edges of different orientations"); - 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 - // - HCenter-> Right - // - Top -> VCenter - // - VCenter -> Bottom - - // Ensure that the internal anchors have been created for both items. - if (firstItem != q && !items.contains(firstItem)) { - createItemEdges(firstItem); - addChildLayoutItem(firstItem); - } - if (secondItem != q && !items.contains(secondItem)) { - createItemEdges(secondItem); - addChildLayoutItem(secondItem); - } - - // Create center edges if needed - createCenterAnchors(firstItem, firstEdge); - createCenterAnchors(secondItem, secondEdge); - - // Use heuristics to find out what the user meant with this anchor. - correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); - - AnchorData *data = new AnchorData; - QGraphicsAnchor *graphicsAnchor = acquireGraphicsAnchor(data); - - addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); - - if (spacing) { - graphicsAnchor->setSpacing(*spacing); - } else { - // If firstItem or secondItem is the layout itself, the spacing will default to 0. - // Otherwise, the following matrix is used (questionmark means that the spacing - // is queried from the style): - // from - // to Left HCenter Right - // Left 0 0 ? - // HCenter 0 0 0 - // Right ? 0 0 - if (firstItem == q - || secondItem == q - || pickEdge(firstEdge, Horizontal) == Qt::AnchorHorizontalCenter - || oppositeEdge(firstEdge) != secondEdge) { - graphicsAnchor->setSpacing(0); - } else { - graphicsAnchor->unsetSpacing(); - } - } - - return graphicsAnchor; -} - -/* - \internal - - This method adds an AnchorData to the internal graph. It is responsible for doing - the boilerplate part of such task. - - If another AnchorData exists between the mentioned vertices, it is deleted and - the new one is inserted. -*/ -void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - AnchorData *data) -{ - Q_Q(QGraphicsAnchorLayout); - - const Orientation orientation = edgeOrientation(firstEdge); - - // Create or increase the reference count for the related vertices. - AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge); - AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge); - - // Remove previous anchor - if (graph[orientation].edgeData(v1, v2)) { - removeAnchor_helper(v1, v2); - } - - // If its an internal anchor, set the associated item - if (firstItem == secondItem) - data->item = firstItem; - - data->orientation = orientation; - - // Create a bi-directional edge in the sense it can be transversed both - // from v1 or v2. "data" however is shared between the two references - // so we still know that the anchor direction is from 1 to 2. - data->from = v1; - data->to = v2; -#ifdef QT_DEBUG - data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString()); -#endif - // ### bit to track internal anchors, since inside AnchorData methods - // we don't have access to the 'q' pointer. - data->isLayoutAnchor = (data->item == q); - - graph[orientation].createEdge(v1, v2, data); -} - -QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge) -{ - // Do not expose internal anchors - if (firstItem == secondItem) - return 0; - - const Orientation orientation = edgeOrientation(firstEdge); - AnchorVertex *v1 = internalVertex(firstItem, firstEdge); - AnchorVertex *v2 = internalVertex(secondItem, secondEdge); - - QGraphicsAnchor *graphicsAnchor = 0; - - AnchorData *data = graph[orientation].edgeData(v1, v2); - if (data) { - // We could use "acquireGraphicsAnchor" here, but to avoid a regression where - // an internal anchor was wrongly exposed, I want to ensure no new - // QGraphicsAnchor instances are created by this call. - // This assumption must hold because anchors are either user-created (and already - // have their public object created), or they are internal (and must not reach - // this point). - Q_ASSERT(data->graphicsAnchor); - graphicsAnchor = data->graphicsAnchor; - } - return graphicsAnchor; -} - -/*! - * \internal - * - * Implements the high level "removeAnchor" feature. Called by - * the QAnchorData destructor. - */ -void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex, - AnchorVertex *secondVertex) -{ - Q_Q(QGraphicsAnchorLayout); - - // Save references to items while it's safe to assume the vertices exist - QGraphicsLayoutItem *firstItem = firstVertex->m_item; - QGraphicsLayoutItem *secondItem = secondVertex->m_item; - - // Delete the anchor (may trigger deletion of center vertices) - removeAnchor_helper(firstVertex, secondVertex); - - // Ensure no dangling pointer is left behind - firstVertex = secondVertex = 0; - - // Checking if the item stays in the layout or not - bool keepFirstItem = false; - bool keepSecondItem = false; - - QPair<AnchorVertex *, int> v; - int refcount = -1; - - if (firstItem != q) { - for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) { - v = m_vertexList.value(qMakePair(firstItem, static_cast<Qt::AnchorPoint>(i))); - if (v.first) { - if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter) - refcount = 2; - else - refcount = 1; - - if (v.second > refcount) { - keepFirstItem = true; - break; - } - } - } - } else - keepFirstItem = true; - - if (secondItem != q) { - for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) { - v = m_vertexList.value(qMakePair(secondItem, static_cast<Qt::AnchorPoint>(i))); - if (v.first) { - if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter) - refcount = 2; - else - refcount = 1; - - if (v.second > refcount) { - keepSecondItem = true; - break; - } - } - } - } else - keepSecondItem = true; - - if (!keepFirstItem) - q->removeAt(items.indexOf(firstItem)); - - if (!keepSecondItem) - q->removeAt(items.indexOf(secondItem)); - - // Removing anchors invalidates the layout - q->invalidate(); -} - -/* - \internal - - Implements the low level "removeAnchor" feature. Called by - private methods. -*/ -void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2) -{ - Q_ASSERT(v1 && v2); - - // Remove edge from graph - const Orientation o = edgeOrientation(v1->m_edge); - graph[o].removeEdge(v1, v2); - - // Decrease vertices reference count (may trigger a deletion) - removeInternalVertex(v1->m_item, v1->m_edge); - removeInternalVertex(v2->m_item, v2->m_edge); -} - -AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item, - Qt::AnchorPoint edge) -{ - QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge); - QPair<AnchorVertex *, int> v = m_vertexList.value(pair); - - if (!v.first) { - Q_ASSERT(v.second == 0); - v.first = new AnchorVertex(item, edge); - } - v.second++; - m_vertexList.insert(pair, v); - return v.first; -} - -/** - * \internal - * - * returns the AnchorVertex that was dereferenced, also when it was removed. - * returns 0 if it did not exist. - */ -void QGraphicsAnchorLayoutPrivate::removeInternalVertex(QGraphicsLayoutItem *item, - Qt::AnchorPoint edge) -{ - QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge); - QPair<AnchorVertex *, int> v = m_vertexList.value(pair); - - if (!v.first) { - qWarning("This item with this edge is not in the graph"); - return; - } - - v.second--; - if (v.second == 0) { - // Remove reference and delete vertex - m_vertexList.remove(pair); - delete v.first; - } else { - // Update reference count - m_vertexList.insert(pair, v); - - if ((v.second == 2) && - ((edge == Qt::AnchorHorizontalCenter) || - (edge == Qt::AnchorVerticalCenter))) { - removeCenterAnchors(item, edge, true); - } - } -} - -void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) -{ - if (AnchorVertex *v = internalVertex(item, edge)) { - Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)]; - const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v); - AnchorVertex *v2; - foreach (v2, allVertices) { - g.removeEdge(v, v2); - removeInternalVertex(item, edge); - removeInternalVertex(v2->m_item, v2->m_edge); - } - } -} - -void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item) -{ - // remove the center anchor first!! - removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false); - removeVertex(item, Qt::AnchorLeft); - removeVertex(item, Qt::AnchorRight); - - removeCenterAnchors(item, Qt::AnchorVerticalCenter, false); - removeVertex(item, Qt::AnchorTop); - removeVertex(item, Qt::AnchorBottom); -} - -/*! - \internal - - Use heuristics to determine the correct orientation of a given anchor. - - After API discussions, we decided we would like expressions like - anchor(A, Left, B, Right) to mean the same as anchor(B, Right, A, Left). - The problem with this is that anchors could become ambiguous, for - instance, what does the anchor A, B of size X mean? - - "pos(B) = pos(A) + X" or "pos(A) = pos(B) + X" ? - - To keep the API user friendly and at the same time, keep our algorithm - deterministic, we use an heuristic to determine a direction for each - added anchor and then keep it. The heuristic is based on the fact - that people usually avoid overlapping items, therefore: - - "A, RIGHT to B, LEFT" means that B is to the LEFT of A. - "B, LEFT to A, RIGHT" is corrected to the above anchor. - - Special correction is also applied when one of the items is the - layout. We handle Layout Left as if it was another items's Right - and Layout Right as another item's Left. -*/ -void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&firstItem, - Qt::AnchorPoint &firstEdge, - QGraphicsLayoutItem *&secondItem, - Qt::AnchorPoint &secondEdge) -{ - Q_Q(QGraphicsAnchorLayout); - - if ((firstItem != q) && (secondItem != q)) { - // If connection is between widgets (not the layout itself) - // Ensure that "right-edges" sit to the left of "left-edges". - if (firstEdge < secondEdge) { - qSwap(firstItem, secondItem); - qSwap(firstEdge, secondEdge); - } - } else if (firstItem == q) { - // If connection involves the right or bottom of a layout, ensure - // the layout is the second item. - if ((firstEdge == Qt::AnchorRight) || (firstEdge == Qt::AnchorBottom)) { - qSwap(firstItem, secondItem); - qSwap(firstEdge, secondEdge); - } - } else if ((secondEdge != Qt::AnchorRight) && (secondEdge != Qt::AnchorBottom)) { - // If connection involves the left, center or top of layout, ensure - // the layout is the first item. - qSwap(firstItem, secondItem); - qSwap(firstEdge, secondEdge); - } -} - -QLayoutStyleInfo &QGraphicsAnchorLayoutPrivate::styleInfo() const -{ - if (styleInfoDirty) { - Q_Q(const QGraphicsAnchorLayout); - //### Fix this if QGV ever gets support for Metal style or different Aqua sizes. - QWidget *wid = 0; - - QGraphicsLayoutItem *parent = q->parentLayoutItem(); - while (parent && parent->isLayout()) { - parent = parent->parentLayoutItem(); - } - QGraphicsWidget *w = 0; - if (parent) { - QGraphicsItem *parentItem = parent->graphicsItem(); - if (parentItem && parentItem->isWidget()) - w = static_cast<QGraphicsWidget*>(parentItem); - } - - QStyle *style = w ? w->style() : QApplication::style(); - cachedStyleInfo = QLayoutStyleInfo(style, wid); - cachedStyleInfo.setDefaultSpacing(Qt::Horizontal, spacings[0]); - cachedStyleInfo.setDefaultSpacing(Qt::Vertical, spacings[1]); - - styleInfoDirty = false; - } - return cachedStyleInfo; -} - -/*! - \internal - - Called on activation. Uses Linear Programming to define minimum, preferred - and maximum sizes for the layout. Also calculates the sizes that each item - should assume when the layout is in one of such situations. -*/ -void QGraphicsAnchorLayoutPrivate::calculateGraphs() -{ - if (!calculateGraphCacheDirty) - return; - calculateGraphs(Horizontal); - calculateGraphs(Vertical); - calculateGraphCacheDirty = false; -} - -// ### Maybe getGraphParts could return the variables when traversing, at least -// for trunk... -QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints) -{ - QSet<AnchorData *> variableSet; - for (int i = 0; i < constraints.count(); ++i) { - const QSimplexConstraint *c = constraints.at(i); - foreach (QSimplexVariable *var, c->variables.keys()) { - variableSet += static_cast<AnchorData *>(var); - } - } - return variableSet.toList(); -} - -/*! - \internal - - Calculate graphs is the method that puts together all the helper routines - so that the AnchorLayout can calculate the sizes of each item. - - In a nutshell it should do: - - 1) Refresh anchor nominal sizes, that is, the size that each anchor would - have if no other restrictions applied. This is done by quering the - layout style and the sizeHints of the items belonging to the layout. - - 2) Simplify the graph by grouping together parallel and sequential anchors - into "group anchors". These have equivalent minimum, preferred and maximum - sizeHints as the anchors they replace. - - 3) Check if we got to a trivial case. In some cases, the whole graph can be - simplified into a single anchor. If so, use this information. If not, - then call the Simplex solver to calculate the anchors sizes. - - 4) Once the root anchors had its sizes calculated, propagate that to the - anchors they represent. -*/ -void QGraphicsAnchorLayoutPrivate::calculateGraphs( - QGraphicsAnchorLayoutPrivate::Orientation orientation) -{ -#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) - lastCalculationUsedSimplex[orientation] = false; -#endif - - static bool simplificationEnabled = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); - - // Reset the nominal sizes of each anchor based on the current item sizes - refreshAllSizeHints(orientation); - - // Simplify the graph - if (simplificationEnabled && !simplifyGraph(orientation)) { - qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); - graphHasConflicts[orientation] = true; - return; - } - - // Traverse all graph edges and store the possible paths to each vertex - findPaths(orientation); - - // From the paths calculated above, extract the constraints that the current - // anchor setup impose, to our Linear Programming problem. - constraintsFromPaths(orientation); - - // Split the constraints and anchors into groups that should be fed to the - // simplex solver independently. Currently we find two groups: - // - // 1) The "trunk", that is, the set of anchors (items) that are connected - // to the two opposite sides of our layout, and thus need to stretch in - // order to fit in the current layout size. - // - // 2) The floating or semi-floating anchors (items) that are those which - // are connected to only one (or none) of the layout sides, thus are not - // influenced by the layout size. - QList<QList<QSimplexConstraint *> > parts = getGraphParts(orientation); - - // Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes - // of the "trunk" set of constraints and variables. - // ### does trunk always exist? empty = trunk is the layout left->center->right - QList<QSimplexConstraint *> trunkConstraints = parts.at(0); - QList<AnchorData *> trunkVariables = getVariables(trunkConstraints); - - // For minimum and maximum, use the path between the two layout sides as the - // objective function. - AnchorVertex *v = layoutLastVertex[orientation]; - GraphPath trunkPath = graphPaths[orientation].value(v); - - bool feasible = calculateTrunk(orientation, trunkPath, trunkConstraints, trunkVariables); - - // For the other parts that not the trunk, solve only for the preferred size - // that is the size they will remain at, since they are not stretched by the - // layout. - - // Skipping the first (trunk) - for (int i = 1; i < parts.count(); ++i) { - if (!feasible) - break; - - QList<QSimplexConstraint *> partConstraints = parts.at(i); - QList<AnchorData *> partVariables = getVariables(partConstraints); - Q_ASSERT(!partVariables.isEmpty()); - feasible &= calculateNonTrunk(partConstraints, partVariables); - } - - // Propagate the new sizes down the simplified graph, ie. tell the - // group anchors to set their children anchors sizes. - updateAnchorSizes(orientation); - - graphHasConflicts[orientation] = !feasible; - - // Clean up our data structures. They are not needed anymore since - // distribution uses just interpolation. - qDeleteAll(constraints[orientation]); - constraints[orientation].clear(); - graphPaths[orientation].clear(); // ### - - if (simplificationEnabled) - restoreSimplifiedGraph(orientation); -} - -/*! - \internal - - Shift all the constraints by a certain amount. This allows us to deal with negative values in - the linear program if they are bounded by a certain limit. Functions should be careful to - call it again with a negative amount, to shift the constraints back. -*/ -static void shiftConstraints(const QList<QSimplexConstraint *> &constraints, qreal amount) -{ - for (int i = 0; i < constraints.count(); ++i) { - QSimplexConstraint *c = constraints.at(i); - qreal multiplier = 0; - foreach (qreal v, c->variables.values()) { - multiplier += v; - } - c->constant += multiplier * amount; - } -} - -/*! - \internal - - Calculate the sizes for all anchors which are part of the trunk. This works - on top of a (possibly) simplified graph. -*/ -bool QGraphicsAnchorLayoutPrivate::calculateTrunk(Orientation orientation, const GraphPath &path, - const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables) -{ - bool feasible = true; - bool needsSimplex = !constraints.isEmpty(); - -#if 0 - qDebug("Simplex %s for trunk of %s", needsSimplex ? "used" : "NOT used", - orientation == Horizontal ? "Horizontal" : "Vertical"); -#endif - - if (needsSimplex) { - - QList<QSimplexConstraint *> sizeHintConstraints = constraintsFromSizeHints(variables); - QList<QSimplexConstraint *> allConstraints = constraints + sizeHintConstraints; - - shiftConstraints(allConstraints, g_offset); - - // Solve min and max size hints - qreal min, max; - feasible = solveMinMax(allConstraints, path, &min, &max); - - if (feasible) { - solvePreferred(constraints, variables); - - // Calculate and set the preferred size for the layout, - // from the edge sizes that were calculated above. - qreal pref(0.0); - foreach (const AnchorData *ad, path.positives) { - pref += ad->sizeAtPreferred; - } - foreach (const AnchorData *ad, path.negatives) { - pref -= ad->sizeAtPreferred; - } - - sizeHints[orientation][Qt::MinimumSize] = min; - sizeHints[orientation][Qt::PreferredSize] = pref; - sizeHints[orientation][Qt::MaximumSize] = max; - } - - qDeleteAll(sizeHintConstraints); - shiftConstraints(constraints, -g_offset); - - } else { - // No Simplex is necessary because the path was simplified all the way to a single - // anchor. - Q_ASSERT(path.positives.count() == 1); - Q_ASSERT(path.negatives.count() == 0); - - AnchorData *ad = path.positives.toList()[0]; - ad->sizeAtMinimum = ad->minSize; - ad->sizeAtPreferred = ad->prefSize; - ad->sizeAtMaximum = ad->maxSize; - - sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum; - sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred; - sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum; - } - -#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) - lastCalculationUsedSimplex[orientation] = needsSimplex; -#endif - - return feasible; -} - -/*! - \internal -*/ -bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables) -{ - shiftConstraints(constraints, g_offset); - bool feasible = solvePreferred(constraints, variables); - - if (feasible) { - // Propagate size at preferred to other sizes. Semi-floats always will be - // in their sizeAtPreferred. - for (int j = 0; j < variables.count(); ++j) { - AnchorData *ad = variables.at(j); - Q_ASSERT(ad); - ad->sizeAtMinimum = ad->sizeAtPreferred; - ad->sizeAtMaximum = ad->sizeAtPreferred; - } - } - - shiftConstraints(constraints, -g_offset); - return feasible; -} - -/*! - \internal - - Traverse the graph refreshing the size hints. Edges will query their associated - item or graphicsAnchor for their size hints. -*/ -void QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) -{ - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections(); - - QLayoutStyleInfo styleInf = styleInfo(); - for (int i = 0; i < vertices.count(); ++i) { - AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second); - data->refreshSizeHints(&styleInf); - } -} - -/*! - \internal - - This method walks the graph using a breadth-first search to find paths - between the root vertex and each vertex on the graph. The edges - directions in each path are considered and they are stored as a - positive edge (left-to-right) or negative edge (right-to-left). - - The list of paths is used later to generate a list of constraints. - */ -void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation) -{ - QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue; - - QSet<AnchorData *> visited; - - AnchorVertex *root = layoutFirstVertex[orientation]; - - graphPaths[orientation].insert(root, GraphPath()); - - foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) { - queue.enqueue(qMakePair(root, v)); - } - - while(!queue.isEmpty()) { - QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue(); - AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second); - - if (visited.contains(edge)) - continue; - - visited.insert(edge); - GraphPath current = graphPaths[orientation].value(pair.first); - - if (edge->from == pair.first) - current.positives.insert(edge); - else - current.negatives.insert(edge); - - graphPaths[orientation].insert(pair.second, current); - - foreach (AnchorVertex *v, - graph[orientation].adjacentVertices(pair.second)) { - queue.enqueue(qMakePair(pair.second, v)); - } - } - - // We will walk through every reachable items (non-float) store them in a temporary set. - // We them create a set of all items and subtract the non-floating items from the set in - // order to get the floating items. The floating items is then stored in m_floatItems - identifyFloatItems(visited, orientation); -} - -/*! - \internal - - Each vertex on the graph that has more than one path to it - represents a contra int to the sizes of the items in these paths. - - This method walks the list of paths to each vertex, generate - the constraints and store them in a list so they can be used later - by the Simplex solver. -*/ -void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation) -{ - foreach (AnchorVertex *vertex, graphPaths[orientation].uniqueKeys()) - { - int valueCount = graphPaths[orientation].count(vertex); - if (valueCount == 1) - continue; - - QList<GraphPath> pathsToVertex = graphPaths[orientation].values(vertex); - for (int i = 1; i < valueCount; ++i) { - constraints[orientation] += \ - pathsToVertex[0].constraint(pathsToVertex.at(i)); - } - } -} - -/*! - \internal -*/ -void QGraphicsAnchorLayoutPrivate::updateAnchorSizes(Orientation orientation) -{ - Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - const QList<QPair<AnchorVertex *, AnchorVertex *> > &vertices = g.connections(); - - for (int i = 0; i < vertices.count(); ++i) { - AnchorData *ad = g.edgeData(vertices.at(i).first, vertices.at(i).second); - ad->updateChildrenSizes(); - } -} - -/*! - \internal - - Create LP constraints for each anchor based on its minimum and maximum - sizes, as specified in its size hints -*/ -QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints( - const QList<AnchorData *> &anchors) -{ - if (anchors.isEmpty()) - return QList<QSimplexConstraint *>(); - - // Look for the layout edge. That can be either the first half in case the - // layout is split in two, or the whole layout anchor. - Orientation orient = Orientation(anchors.first()->orientation); - AnchorData *layoutEdge = 0; - if (layoutCentralVertex[orient]) { - layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutCentralVertex[orient]); - } else { - layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutLastVertex[orient]); - } - - // If maxSize is less then "infinite", that means there are other anchors - // grouped together with this one. We can't ignore its maximum value so we - // set back the variable to NULL to prevent the continue condition from being - // satisfied in the loop below. - const qreal expectedMax = layoutCentralVertex[orient] ? QWIDGETSIZE_MAX / 2 : QWIDGETSIZE_MAX; - qreal actualMax; - if (layoutEdge->from == layoutFirstVertex[orient]) { - actualMax = layoutEdge->maxSize; - } else { - actualMax = -layoutEdge->minSize; - } - if (actualMax != expectedMax) { - layoutEdge = 0; - } - - // For each variable, create constraints based on size hints - QList<QSimplexConstraint *> anchorConstraints; - bool unboundedProblem = true; - for (int i = 0; i < anchors.size(); ++i) { - AnchorData *ad = anchors.at(i); - - // Anchors that have their size directly linked to another one don't need constraints - // For exammple, the second half of an item has exactly the same size as the first half - // thus constraining the latter is enough. - if (ad->dependency == AnchorData::Slave) - continue; - - // To use negative variables inside simplex, we shift them so the minimum negative value is - // mapped to zero before solving. To make sure that it works, we need to guarantee that the - // variables are all inside a certain boundary. - qreal boundedMin = qBound(-g_offset, ad->minSize, g_offset); - qreal boundedMax = qBound(-g_offset, ad->maxSize, g_offset); - - if ((boundedMin == boundedMax) || qFuzzyCompare(boundedMin, boundedMax)) { - QSimplexConstraint *c = new QSimplexConstraint; - c->variables.insert(ad, 1.0); - c->constant = boundedMin; - c->ratio = QSimplexConstraint::Equal; - anchorConstraints += c; - unboundedProblem = false; - } else { - QSimplexConstraint *c = new QSimplexConstraint; - c->variables.insert(ad, 1.0); - c->constant = boundedMin; - c->ratio = QSimplexConstraint::MoreOrEqual; - anchorConstraints += c; - - // We avoid adding restrictions to the layout internal anchors. That's - // to prevent unnecessary fair distribution from happening due to this - // artificial restriction. - if (ad == layoutEdge) - continue; - - c = new QSimplexConstraint; - c->variables.insert(ad, 1.0); - c->constant = boundedMax; - c->ratio = QSimplexConstraint::LessOrEqual; - anchorConstraints += c; - unboundedProblem = false; - } - } - - // If no upper boundary restriction was added, add one to avoid unbounded problem - if (unboundedProblem) { - QSimplexConstraint *c = new QSimplexConstraint; - c->variables.insert(layoutEdge, 1.0); - // The maximum size that the layout can take - c->constant = g_offset; - c->ratio = QSimplexConstraint::LessOrEqual; - anchorConstraints += c; - } - - return anchorConstraints; -} - -/*! - \internal -*/ -QList< QList<QSimplexConstraint *> > -QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) -{ - Q_ASSERT(layoutFirstVertex[orientation] && layoutLastVertex[orientation]); - - AnchorData *edgeL1 = 0; - AnchorData *edgeL2 = 0; - - // The layout may have a single anchor between Left and Right or two half anchors - // passing through the center - if (layoutCentralVertex[orientation]) { - edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutCentralVertex[orientation]); - edgeL2 = graph[orientation].edgeData(layoutCentralVertex[orientation], layoutLastVertex[orientation]); - } else { - edgeL1 = graph[orientation].edgeData(layoutFirstVertex[orientation], layoutLastVertex[orientation]); - } - - QLinkedList<QSimplexConstraint *> remainingConstraints; - for (int i = 0; i < constraints[orientation].count(); ++i) { - remainingConstraints += constraints[orientation].at(i); - } - for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) { - remainingConstraints += itemCenterConstraints[orientation].at(i); - } - - QList<QSimplexConstraint *> trunkConstraints; - QSet<QSimplexVariable *> trunkVariables; - - trunkVariables += edgeL1; - if (edgeL2) - trunkVariables += edgeL2; - - bool dirty; - do { - dirty = false; - - QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin(); - while (it != remainingConstraints.end()) { - QSimplexConstraint *c = *it; - bool match = false; - - // Check if this constraint have some overlap with current - // trunk variables... - foreach (QSimplexVariable *ad, trunkVariables) { - if (c->variables.contains(ad)) { - match = true; - break; - } - } - - // If so, we add it to trunk, and erase it from the - // remaining constraints. - if (match) { - trunkConstraints += c; - trunkVariables += QSet<QSimplexVariable *>::fromList(c->variables.keys()); - it = remainingConstraints.erase(it); - dirty = true; - } else { - // Note that we don't erase the constraint if it's not - // a match, since in a next iteration of a do-while we - // can pass on it again and it will be a match. - // - // For example: if trunk share a variable with - // remainingConstraints[1] and it shares with - // remainingConstraints[0], we need a second iteration - // of the do-while loop to match both. - ++it; - } - } - } while (dirty); - - QList< QList<QSimplexConstraint *> > result; - result += trunkConstraints; - - if (!remainingConstraints.isEmpty()) { - QList<QSimplexConstraint *> nonTrunkConstraints; - QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin(); - while (it != remainingConstraints.end()) { - nonTrunkConstraints += *it; - ++it; - } - result += nonTrunkConstraints; - } - - return result; -} - -/*! - \internal - - Use all visited Anchors on findPaths() so we can identify non-float Items. -*/ -void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> &visited, Orientation orientation) -{ - QSet<QGraphicsLayoutItem *> nonFloating; - - foreach (const AnchorData *ad, visited) - identifyNonFloatItems_helper(ad, &nonFloating); - - QSet<QGraphicsLayoutItem *> allItems; - foreach (QGraphicsLayoutItem *item, items) - allItems.insert(item); - m_floatItems[orientation] = allItems - nonFloating; -} - - -/*! - \internal - - Given an anchor, if it is an internal anchor and Normal we must mark it's item as non-float. - If the anchor is Sequential or Parallel, we must iterate on its children recursively until we reach - internal anchors (items). -*/ -void QGraphicsAnchorLayoutPrivate::identifyNonFloatItems_helper(const AnchorData *ad, QSet<QGraphicsLayoutItem *> *nonFloatingItemsIdentifiedSoFar) -{ - Q_Q(QGraphicsAnchorLayout); - - switch(ad->type) { - case AnchorData::Normal: - if (ad->item && ad->item != q) - nonFloatingItemsIdentifiedSoFar->insert(ad->item); - break; - case AnchorData::Sequential: - foreach (const AnchorData *d, static_cast<const SequentialAnchorData *>(ad)->m_edges) - identifyNonFloatItems_helper(d, nonFloatingItemsIdentifiedSoFar); - break; - case AnchorData::Parallel: - identifyNonFloatItems_helper(static_cast<const ParallelAnchorData *>(ad)->firstEdge, nonFloatingItemsIdentifiedSoFar); - identifyNonFloatItems_helper(static_cast<const ParallelAnchorData *>(ad)->secondEdge, nonFloatingItemsIdentifiedSoFar); - break; - } -} - -/*! - \internal - - Use the current vertices distance to calculate and set the geometry of - each item. -*/ -void QGraphicsAnchorLayoutPrivate::setItemsGeometries(const QRectF &geom) -{ - Q_Q(QGraphicsAnchorLayout); - AnchorVertex *firstH, *secondH, *firstV, *secondV; - - qreal top; - qreal left; - qreal right; - - q->getContentsMargins(&left, &top, &right, 0); - const Qt::LayoutDirection visualDir = visualDirection(); - if (visualDir == Qt::RightToLeft) - qSwap(left, right); - - left += geom.left(); - top += geom.top(); - right = geom.right() - right; - - foreach (QGraphicsLayoutItem *item, items) { - QRectF newGeom; - QSizeF itemPreferredSize = item->effectiveSizeHint(Qt::PreferredSize); - if (m_floatItems[Horizontal].contains(item)) { - newGeom.setLeft(0); - newGeom.setRight(itemPreferredSize.width()); - } else { - firstH = internalVertex(item, Qt::AnchorLeft); - secondH = internalVertex(item, Qt::AnchorRight); - - if (visualDir == Qt::LeftToRight) { - newGeom.setLeft(left + firstH->distance); - newGeom.setRight(left + secondH->distance); - } else { - newGeom.setLeft(right - secondH->distance); - newGeom.setRight(right - firstH->distance); - } - } - - if (m_floatItems[Vertical].contains(item)) { - newGeom.setTop(0); - newGeom.setBottom(itemPreferredSize.height()); - } else { - firstV = internalVertex(item, Qt::AnchorTop); - secondV = internalVertex(item, Qt::AnchorBottom); - - newGeom.setTop(top + firstV->distance); - newGeom.setBottom(top + secondV->distance); - } - - item->setGeometry(newGeom); - } -} - -/*! - \internal - - Calculate the position of each vertex based on the paths to each of - them as well as the current edges sizes. -*/ -void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( - QGraphicsAnchorLayoutPrivate::Orientation orientation) -{ - QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue; - QSet<AnchorVertex *> visited; - - // Get root vertex - AnchorVertex *root = layoutFirstVertex[orientation]; - - root->distance = 0; - visited.insert(root); - - // Add initial edges to the queue - foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) { - queue.enqueue(qMakePair(root, v)); - } - - // Do initial calculation required by "interpolateEdge()" - setupEdgesInterpolation(orientation); - - // Traverse the graph and calculate vertex positions - while (!queue.isEmpty()) { - QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue(); - AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second); - - if (visited.contains(pair.second)) - continue; - - visited.insert(pair.second); - interpolateEdge(pair.first, edge); - - QList<AnchorVertex *> adjacents = graph[orientation].adjacentVertices(pair.second); - for (int i = 0; i < adjacents.count(); ++i) { - if (!visited.contains(adjacents.at(i))) - queue.enqueue(qMakePair(pair.second, adjacents.at(i))); - } - } -} - -/*! - \internal - - Calculate interpolation parameters based on current Layout Size. - Must be called once before calling "interpolateEdgeSize()" for - the edges. -*/ -void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation( - Orientation orientation) -{ - Q_Q(QGraphicsAnchorLayout); - - qreal current; - current = (orientation == Horizontal) ? q->contentsRect().width() : q->contentsRect().height(); - - QPair<Interval, qreal> result; - result = getFactor(current, - sizeHints[orientation][Qt::MinimumSize], - sizeHints[orientation][Qt::PreferredSize], - sizeHints[orientation][Qt::PreferredSize], - sizeHints[orientation][Qt::PreferredSize], - sizeHints[orientation][Qt::MaximumSize]); - - interpolationInterval[orientation] = result.first; - interpolationProgress[orientation] = result.second; -} - -/*! - \internal - - Calculate the current Edge size based on the current Layout size and the - size the edge is supposed to have when the layout is at its: - - - minimum size, - - preferred size, - - maximum size. - - These three key values are calculated in advance using linear - programming (more expensive) or the simplification algorithm, then - subsequential resizes of the parent layout require a simple - interpolation. -*/ -void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorData *edge) -{ - const Orientation orientation = Orientation(edge->orientation); - const QPair<Interval, qreal> factor(interpolationInterval[orientation], - interpolationProgress[orientation]); - - qreal edgeDistance = interpolate(factor, edge->sizeAtMinimum, edge->sizeAtPreferred, - edge->sizeAtPreferred, edge->sizeAtPreferred, - edge->sizeAtMaximum); - - Q_ASSERT(edge->from == base || edge->to == base); - - // Calculate the distance for the vertex opposite to the base - if (edge->from == base) { - edge->to->distance = base->distance + edgeDistance; - } else { - edge->from->distance = base->distance - edgeDistance; - } -} - -bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> &constraints, - GraphPath path, qreal *min, qreal *max) -{ - QSimplex simplex; - bool feasible = simplex.setConstraints(constraints); - if (feasible) { - // Obtain the objective constraint - QSimplexConstraint objective; - QSet<AnchorData *>::const_iterator iter; - for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter) - objective.variables.insert(*iter, 1.0); - - for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter) - objective.variables.insert(*iter, -1.0); - - const qreal objectiveOffset = (path.positives.count() - path.negatives.count()) * g_offset; - simplex.setObjective(&objective); - - // Calculate minimum values - *min = simplex.solveMin() - objectiveOffset; - - // Save sizeAtMinimum results - QList<AnchorData *> variables = getVariables(constraints); - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = static_cast<AnchorData *>(variables.at(i)); - ad->sizeAtMinimum = ad->result - g_offset; - } - - // Calculate maximum values - *max = simplex.solveMax() - objectiveOffset; - - // Save sizeAtMaximum results - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = static_cast<AnchorData *>(variables.at(i)); - ad->sizeAtMaximum = ad->result - g_offset; - } - } - return feasible; -} - -enum slackType { Grower = -1, Shrinker = 1 }; -static QPair<QSimplexVariable *, QSimplexConstraint *> createSlack(QSimplexConstraint *sizeConstraint, - qreal interval, slackType type) -{ - QSimplexVariable *slack = new QSimplexVariable; - sizeConstraint->variables.insert(slack, type); - - QSimplexConstraint *limit = new QSimplexConstraint; - limit->variables.insert(slack, 1.0); - limit->ratio = QSimplexConstraint::LessOrEqual; - limit->constant = interval; - - return qMakePair(slack, limit); -} - -bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables) -{ - QList<QSimplexConstraint *> preferredConstraints; - QList<QSimplexVariable *> preferredVariables; - QSimplexConstraint objective; - - // Fill the objective coefficients for this variable. In the - // end the objective function will be - // - // z = n * (A_shrinker_hard + A_grower_hard + B_shrinker_hard + B_grower_hard + ...) + - // (A_shrinker_soft + A_grower_soft + B_shrinker_soft + B_grower_soft + ...) - // - // where n is the number of variables that have - // slacks. Note that here we use the number of variables - // as coefficient, this is to mark the "shrinker slack - // variable" less likely to get value than the "grower - // slack variable". - - // This will fill the values for the structural constraints - // and we now fill the values for the slack constraints (one per variable), - // which have this form (the constant A_pref was set when creating the slacks): - // - // A + A_shrinker_hard + A_shrinker_soft - A_grower_hard - A_grower_soft = A_pref - // - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = variables.at(i); - - // The layout original structure anchors are not relevant in preferred size calculation - if (ad->isLayoutAnchor) - continue; - - // By default, all variables are equal to their preferred size. If they have room to - // grow or shrink, such flexibility will be added by the additional variables below. - QSimplexConstraint *sizeConstraint = new QSimplexConstraint; - preferredConstraints += sizeConstraint; - sizeConstraint->variables.insert(ad, 1.0); - sizeConstraint->constant = ad->prefSize + g_offset; - - // Can easily shrink - QPair<QSimplexVariable *, QSimplexConstraint *> slack; - const qreal softShrinkInterval = ad->prefSize - ad->minPrefSize; - if (softShrinkInterval) { - slack = createSlack(sizeConstraint, softShrinkInterval, Shrinker); - preferredVariables += slack.first; - preferredConstraints += slack.second; - - // Add to objective with ratio == 1 (soft) - objective.variables.insert(slack.first, 1.0); - } - - // Can easily grow - const qreal softGrowInterval = ad->maxPrefSize - ad->prefSize; - if (softGrowInterval) { - slack = createSlack(sizeConstraint, softGrowInterval, Grower); - preferredVariables += slack.first; - preferredConstraints += slack.second; - - // Add to objective with ratio == 1 (soft) - objective.variables.insert(slack.first, 1.0); - } - - // Can shrink if really necessary - const qreal hardShrinkInterval = ad->minPrefSize - ad->minSize; - if (hardShrinkInterval) { - slack = createSlack(sizeConstraint, hardShrinkInterval, Shrinker); - preferredVariables += slack.first; - preferredConstraints += slack.second; - - // Add to objective with ratio == N (hard) - objective.variables.insert(slack.first, variables.size()); - } - - // Can grow if really necessary - const qreal hardGrowInterval = ad->maxSize - ad->maxPrefSize; - if (hardGrowInterval) { - slack = createSlack(sizeConstraint, hardGrowInterval, Grower); - preferredVariables += slack.first; - preferredConstraints += slack.second; - - // Add to objective with ratio == N (hard) - objective.variables.insert(slack.first, variables.size()); - } - } - - QSimplex *simplex = new QSimplex; - bool feasible = simplex->setConstraints(constraints + preferredConstraints); - if (feasible) { - simplex->setObjective(&objective); - - // Calculate minimum values - simplex->solveMin(); - - // Save sizeAtPreferred results - for (int i = 0; i < variables.size(); ++i) { - AnchorData *ad = variables.at(i); - ad->sizeAtPreferred = ad->result - g_offset; - } - - // Make sure we delete the simplex solver -before- we delete the - // constraints used by it. - delete simplex; - } - // Delete constraints and variables we created. - qDeleteAll(preferredConstraints); - qDeleteAll(preferredVariables); - - return feasible; -} - -/*! - \internal - Returns true if there are no arrangement that satisfies all constraints. - Otherwise returns false. - - \sa addAnchor() -*/ -bool QGraphicsAnchorLayoutPrivate::hasConflicts() const -{ - QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate*>(this); - that->calculateGraphs(); - - bool floatConflict = !m_floatItems[0].isEmpty() || !m_floatItems[1].isEmpty(); - - return graphHasConflicts[0] || graphHasConflicts[1] || floatConflict; -} - -#ifdef QT_DEBUG -void QGraphicsAnchorLayoutPrivate::dumpGraph(const QString &name) -{ - QFile file(QString::fromAscii("anchorlayout.%1.dot").arg(name)); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) - qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData()); - - QString str = QString::fromAscii("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1}"); - QString dotContents = graph[0].serializeToDot(); - dotContents += graph[1].serializeToDot(); - file.write(str.arg(dotContents).toLocal8Bit()); - - file.close(); -} -#endif - -QT_END_NAMESPACE -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h deleted file mode 100644 index d78e5c89c3..0000000000 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ /dev/null @@ -1,594 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSANCHORLAYOUT_P_H -#define QGRAPHICSANCHORLAYOUT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QGraphicsWidget> -#include <private/qobject_p.h> - -#include "qgraphicslayout_p.h" -#include "qgraphicsanchorlayout.h" -#include "qgraph_p.h" -#include "qsimplex_p.h" -#ifndef QT_NO_GRAPHICSVIEW -QT_BEGIN_NAMESPACE - -/* - The public QGraphicsAnchorLayout interface represents an anchorage point - as a pair of a <QGraphicsLayoutItem *> and a <Qt::AnchorPoint>. - - Internally though, it has a graph of anchorage points (vertices) and - anchors (edges), represented by the AnchorVertex and AnchorData structs - respectively. -*/ - -/*! - \internal - - Represents a vertex (anchorage point) in the internal graph -*/ -struct AnchorVertex { - enum Type { - Normal = 0, - Pair - }; - - AnchorVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) - : m_item(item), m_edge(edge), m_type(Normal) {} - - AnchorVertex() - : m_item(0), m_edge(Qt::AnchorPoint(0)), m_type(Normal) {} - -#ifdef QT_DEBUG - inline QString toString() const; -#endif - - QGraphicsLayoutItem *m_item; - Qt::AnchorPoint m_edge; - uint m_type : 1; - - // Current distance from this vertex to the layout edge (Left or Top) - // Value is calculated from the current anchors sizes. - qreal distance; -}; - -/*! - \internal - - Represents an edge (anchor) in the internal graph. -*/ -struct AnchorData : public QSimplexVariable { - enum Type { - Normal = 0, - Sequential, - Parallel - }; - - enum Dependency { - Independent = 0, - Master, - Slave - }; - - AnchorData() - : QSimplexVariable(), from(0), to(0), - minSize(0), prefSize(0), maxSize(0), - minPrefSize(0), maxPrefSize(0), - sizeAtMinimum(0), sizeAtPreferred(0), - sizeAtMaximum(0), item(0), graphicsAnchor(0), - type(Normal), isLayoutAnchor(false), - isCenterAnchor(false), orientation(0), - dependency(Independent) {} - virtual ~AnchorData(); - - virtual void updateChildrenSizes() {} - void refreshSizeHints(const QLayoutStyleInfo *styleInfo = 0); - -#ifdef QT_DEBUG - void dump(int indent = 2); - inline QString toString() const; - QString name; -#endif - - // Anchor is semantically directed - AnchorVertex *from; - AnchorVertex *to; - - // Nominal sizes - // These are the intrinsic size restrictions for a given item. They are - // used as input for the calculation of the actual sizes. - // These values are filled by the refreshSizeHints method, based on the - // anchor size policy, the size hints of the item it (possibly) represents - // and the layout spacing information. - qreal minSize; - qreal prefSize; - qreal maxSize; - - qreal minPrefSize; - qreal maxPrefSize; - - // Calculated sizes - // These attributes define which sizes should that anchor be in when the - // layout is at its minimum, preferred or maximum sizes. Values are - // calculated by the Simplex solver based on the current layout setup. - qreal sizeAtMinimum; - qreal sizeAtPreferred; - qreal sizeAtMaximum; - - // References to the classes that represent this anchor in the public world - // An anchor may represent a LayoutItem, it may also be acessible externally - // through a GraphicsAnchor "handler". - QGraphicsLayoutItem *item; - QGraphicsAnchor *graphicsAnchor; - - uint type : 2; // either Normal, Sequential or Parallel - uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor - uint isCenterAnchor : 1; - uint orientation : 1; - uint dependency : 2; // either Independent, Master or Slave -}; - -#ifdef QT_DEBUG -inline QString AnchorData::toString() const -{ - return QString::fromAscii("Anchor(%1)").arg(name); -} -#endif - -struct SequentialAnchorData : public AnchorData -{ - SequentialAnchorData(const QVector<AnchorVertex *> &vertices, const QVector<AnchorData *> &edges) - : AnchorData(), m_children(vertices), m_edges(edges) - { - type = AnchorData::Sequential; - orientation = m_edges.at(0)->orientation; -#ifdef QT_DEBUG - name = QString::fromAscii("%1 -- %2").arg(vertices.first()->toString(), vertices.last()->toString()); -#endif - } - - virtual void updateChildrenSizes(); - void calculateSizeHints(); - - QVector<AnchorVertex*> m_children; // list of vertices in the sequence - QVector<AnchorData*> m_edges; // keep the list of edges too. -}; - -struct ParallelAnchorData : public AnchorData -{ - ParallelAnchorData(AnchorData *first, AnchorData *second) - : AnchorData(), firstEdge(first), secondEdge(second) - { - type = AnchorData::Parallel; - orientation = first->orientation; - - // This assert whether the child anchors share their vertices - Q_ASSERT(((first->from == second->from) && (first->to == second->to)) || - ((first->from == second->to) && (first->to == second->from))); - - // Our convention will be that the parallel group anchor will have the same - // direction as the first anchor. - from = first->from; - to = first->to; -#ifdef QT_DEBUG - name = QString::fromAscii("%1 | %2").arg(first->toString(), second->toString()); -#endif - } - - virtual void updateChildrenSizes(); - bool calculateSizeHints(); - - bool secondForward() const { - // We have the convention that the first children will define the direction of the - // pararell group. Note that we can't rely on 'this->from' or 'this->to' because they - // might be changed by vertex simplification. - return firstEdge->from == secondEdge->from; - } - - AnchorData* firstEdge; - AnchorData* secondEdge; - - QList<QSimplexConstraint *> m_firstConstraints; - QList<QSimplexConstraint *> m_secondConstraints; -}; - -struct AnchorVertexPair : public AnchorVertex { - AnchorVertexPair(AnchorVertex *v1, AnchorVertex *v2, AnchorData *data) - : AnchorVertex(), m_first(v1), m_second(v2), m_removedAnchor(data) { - m_type = AnchorVertex::Pair; - } - - AnchorVertex *m_first; - AnchorVertex *m_second; - - AnchorData *m_removedAnchor; - QList<AnchorData *> m_firstAnchors; - QList<AnchorData *> m_secondAnchors; -}; - -#ifdef QT_DEBUG -inline QString AnchorVertex::toString() const -{ - if (!this) { - return QLatin1String("NULL"); - } else if (m_type == Pair) { - const AnchorVertexPair *vp = static_cast<const AnchorVertexPair *>(this); - return QString::fromAscii("(%1, %2)").arg(vp->m_first->toString()).arg(vp->m_second->toString()); - } else if (!m_item) { - return QString::fromAscii("NULL_%1").arg(quintptr(this)); - } - QString edge; - switch (m_edge) { - case Qt::AnchorLeft: - edge = QLatin1String("Left"); - break; - case Qt::AnchorHorizontalCenter: - edge = QLatin1String("HorizontalCenter"); - break; - case Qt::AnchorRight: - edge = QLatin1String("Right"); - break; - case Qt::AnchorTop: - edge = QLatin1String("Top"); - break; - case Qt::AnchorVerticalCenter: - edge = QLatin1String("VerticalCenter"); - break; - case Qt::AnchorBottom: - edge = QLatin1String("Bottom"); - break; - default: - edge = QLatin1String("None"); - break; - } - QString itemName; - if (m_item->isLayout()) { - itemName = QLatin1String("layout"); - } else { - if (QGraphicsItem *item = m_item->graphicsItem()) { - itemName = item->data(0).toString(); - } - } - edge.insert(0, QLatin1String("%1_")); - return edge.arg(itemName); -} -#endif - -/*! - \internal - - Representation of a valid path for a given vertex in the graph. - In this struct, "positives" is the set of anchors that have been - traversed in the forward direction, while "negatives" is the set - with the ones walked backwards. - - This paths are compared against each other to produce LP Constraints, - the exact order in which the anchors were traversed is not relevant. -*/ -class GraphPath -{ -public: - GraphPath() {} - - QSimplexConstraint *constraint(const GraphPath &path) const; -#ifdef QT_DEBUG - QString toString() const; -#endif - QSet<AnchorData *> positives; - QSet<AnchorData *> negatives; -}; - -class QGraphicsAnchorLayoutPrivate; -/*! - \internal -*/ -class QGraphicsAnchorPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsAnchor) - -public: - explicit QGraphicsAnchorPrivate(int version = QObjectPrivateVersion); - ~QGraphicsAnchorPrivate(); - - void setSpacing(qreal value); - void unsetSpacing(); - qreal spacing() const; - - void setSizePolicy(QSizePolicy::Policy policy); - - QGraphicsAnchorLayoutPrivate *layoutPrivate; - AnchorData *data; - - // Size information for user controlled anchor - QSizePolicy::Policy sizePolicy; - qreal preferredSize; - - uint hasSize : 1; // if false, get size from style. -}; - - - - -/*! - \internal - - QGraphicsAnchorLayout private methods and attributes. -*/ -class Q_AUTOTEST_EXPORT QGraphicsAnchorLayoutPrivate : public QGraphicsLayoutPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsAnchorLayout) - -public: - // When the layout geometry is different from its Minimum, Preferred - // or Maximum values, interpolation is used to calculate the geometries - // of the items. - // - // Interval represents which interpolation interval are we operating in. - enum Interval { - MinimumToMinPreferred = 0, - MinPreferredToPreferred, - PreferredToMaxPreferred, - MaxPreferredToMaximum - }; - - // Several structures internal to the layout are duplicated to handle - // both Horizontal and Vertical restrictions. - // - // Orientation is used to reference the right structure in each context - enum Orientation { - Horizontal = 0, - Vertical, - NOrientations - }; - - QGraphicsAnchorLayoutPrivate(); - - static QGraphicsAnchorLayoutPrivate *get(QGraphicsAnchorLayout *q) - { - return q ? q->d_func() : 0; - } - - static Qt::AnchorPoint oppositeEdge( - Qt::AnchorPoint edge); - - static Orientation edgeOrientation(Qt::AnchorPoint edge); - - static Qt::AnchorPoint pickEdge(Qt::AnchorPoint edge, Orientation orientation) - { - if (orientation == Vertical && int(edge) <= 2) - return (Qt::AnchorPoint)(edge + 3); - else if (orientation == Horizontal && int(edge) >= 3) { - return (Qt::AnchorPoint)(edge - 3); - } - return edge; - } - - // Init methods - void createLayoutEdges(); - void deleteLayoutEdges(); - void createItemEdges(QGraphicsLayoutItem *item); - void createCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge); - void removeCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, bool substitute = true); - void removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation); - - QGraphicsAnchor *acquireGraphicsAnchor(AnchorData *data) - { - Q_Q(QGraphicsAnchorLayout); - if (!data->graphicsAnchor) { - data->graphicsAnchor = new QGraphicsAnchor(q); - data->graphicsAnchor->d_func()->data = data; - } - return data->graphicsAnchor; - } - - // function used by the 4 API functions - QGraphicsAnchor *addAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - qreal *spacing = 0); - - // Helper for Anchor Manipulation methods - void addAnchor_helper(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - AnchorData *data); - - QGraphicsAnchor *getAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - - void removeAnchor(AnchorVertex *firstVertex, AnchorVertex *secondVertex); - void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); - - void removeAnchors(QGraphicsLayoutItem *item); - - void removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); - - void correctEdgeDirection(QGraphicsLayoutItem *&firstItem, - Qt::AnchorPoint &firstEdge, - QGraphicsLayoutItem *&secondItem, - Qt::AnchorPoint &secondEdge); - - QLayoutStyleInfo &styleInfo() const; - - AnchorData *addAnchorMaybeParallel(AnchorData *newAnchor, bool *feasible); - - // Activation - void calculateGraphs(); - void calculateGraphs(Orientation orientation); - - // Simplification - bool simplifyGraph(Orientation orientation); - bool simplifyVertices(Orientation orientation); - bool simplifyGraphIteration(Orientation orientation, bool *feasible); - - bool replaceVertex(Orientation orientation, AnchorVertex *oldV, - AnchorVertex *newV, const QList<AnchorData *> &edges); - - - void restoreSimplifiedGraph(Orientation orientation); - void restoreSimplifiedAnchor(AnchorData *edge); - void restoreSimplifiedConstraints(ParallelAnchorData *parallel); - void restoreVertices(Orientation orientation); - - bool calculateTrunk(Orientation orientation, const GraphPath &trunkPath, - const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables); - bool calculateNonTrunk(const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables); - - // Support functions for calculateGraph() - void refreshAllSizeHints(Orientation orientation); - void findPaths(Orientation orientation); - void constraintsFromPaths(Orientation orientation); - void updateAnchorSizes(Orientation orientation); - QList<QSimplexConstraint *> constraintsFromSizeHints(const QList<AnchorData *> &anchors); - QList<QList<QSimplexConstraint *> > getGraphParts(Orientation orientation); - void identifyFloatItems(const QSet<AnchorData *> &visited, Orientation orientation); - void identifyNonFloatItems_helper(const AnchorData *ad, QSet<QGraphicsLayoutItem *> *nonFloatingItemsIdentifiedSoFar); - - inline AnchorVertex *internalVertex(const QPair<QGraphicsLayoutItem*, Qt::AnchorPoint> &itemEdge) const - { - return m_vertexList.value(itemEdge).first; - } - - inline AnchorVertex *internalVertex(const QGraphicsLayoutItem *item, Qt::AnchorPoint edge) const - { - return internalVertex(qMakePair(const_cast<QGraphicsLayoutItem *>(item), edge)); - } - - inline void changeLayoutVertex(Orientation orientation, AnchorVertex *oldV, AnchorVertex *newV) - { - if (layoutFirstVertex[orientation] == oldV) - layoutFirstVertex[orientation] = newV; - else if (layoutCentralVertex[orientation] == oldV) - layoutCentralVertex[orientation] = newV; - else if (layoutLastVertex[orientation] == oldV) - layoutLastVertex[orientation] = newV; - } - - - AnchorVertex *addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); - void removeInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); - - // Geometry interpolation methods - void setItemsGeometries(const QRectF &geom); - - void calculateVertexPositions(Orientation orientation); - void setupEdgesInterpolation(Orientation orientation); - void interpolateEdge(AnchorVertex *base, AnchorData *edge); - - // Linear Programming solver methods - bool solveMinMax(const QList<QSimplexConstraint *> &constraints, - GraphPath path, qreal *min, qreal *max); - bool solvePreferred(const QList<QSimplexConstraint *> &constraints, - const QList<AnchorData *> &variables); - bool hasConflicts() const; - -#ifdef QT_DEBUG - void dumpGraph(const QString &name = QString()); -#endif - - - qreal spacings[NOrientations]; - // Size hints from simplex engine - qreal sizeHints[2][3]; - - // Items - QVector<QGraphicsLayoutItem *> items; - - // Mapping between high level anchorage points (Item, Edge) to low level - // ones (Graph Vertices) - - QHash<QPair<QGraphicsLayoutItem*, Qt::AnchorPoint>, QPair<AnchorVertex *, int> > m_vertexList; - - // Internal graph of anchorage points and anchors, for both orientations - Graph<AnchorVertex, AnchorData> graph[2]; - - AnchorVertex *layoutFirstVertex[2]; - AnchorVertex *layoutCentralVertex[2]; - AnchorVertex *layoutLastVertex[2]; - - // Combined anchors in order of creation - QList<AnchorVertexPair *> simplifiedVertices[2]; - QList<AnchorData *> anchorsFromSimplifiedVertices[2]; - - // Graph paths and constraints, for both orientations - QMultiHash<AnchorVertex *, GraphPath> graphPaths[2]; - QList<QSimplexConstraint *> constraints[2]; - QList<QSimplexConstraint *> itemCenterConstraints[2]; - - // The interpolation interval and progress based on the current size - // as well as the key values (minimum, preferred and maximum) - Interval interpolationInterval[2]; - qreal interpolationProgress[2]; - - bool graphHasConflicts[2]; - QSet<QGraphicsLayoutItem *> m_floatItems[2]; - -#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) - bool lastCalculationUsedSimplex[2]; -#endif - - uint calculateGraphCacheDirty : 1; - mutable uint styleInfoDirty : 1; - mutable QLayoutStyleInfo cachedStyleInfo; - - friend class QGraphicsAnchorPrivate; -}; - -QT_END_NAMESPACE -#endif //QT_NO_GRAPHICSVIEW - -#endif diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp deleted file mode 100644 index 2fbfc5dda9..0000000000 --- a/src/gui/graphicsview/qgraphicsgridlayout.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsGridLayout - \brief The QGraphicsGridLayout class provides a grid layout for managing - widgets in Graphics View. - \since 4.4 - - \ingroup graphicsview-api - - The most common way to use QGraphicsGridLayout is to construct an object - on the heap with no parent, add widgets and layouts by calling addItem(), - and finally assign the layout to a widget by calling - QGraphicsWidget::setLayout(). QGraphicsGridLayout automatically computes - the dimensions of the grid as you add items. - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsgridlayout.cpp 0 - - The layout takes ownership of the items. In some cases when the layout - item also inherits from QGraphicsItem (such as QGraphicsWidget) there will be a - ambiguity in ownership because the layout item belongs to two ownership hierarchies. - See the documentation of QGraphicsLayoutItem::setOwnedByLayout() how to handle - this. - You can access each item in the layout by calling count() and itemAt(). Calling - removeAt() will remove an item from the layout, without - destroying it. - - \section1 Size Hints and Size Policies in QGraphicsGridLayout - - QGraphicsGridLayout respects each item's size hints and size policies, - and when a cell in the grid has more space than the items can fill, each item - is arranged according to the layout's alignment for that item. You can set - an alignment for each item by calling setAlignment(), and check the - alignment for any item by calling alignment(). You can also set the alignment - for an entire row or column by calling setRowAlignment() and setColumnAlignment() - respectively. By default, items are aligned to the top left. - - - \sa QGraphicsLinearLayout, QGraphicsWidget -*/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qapplication.h" -#include "qwidget.h" -#include "qgraphicslayout_p.h" -#include "qgraphicslayoutitem.h" -#include "qgraphicsgridlayout.h" -#include "qgraphicswidget.h" -#include "qgridlayoutengine_p.h" -#include <QtCore/qdebug.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsGridLayoutPrivate : public QGraphicsLayoutPrivate -{ -public: - QGraphicsGridLayoutPrivate() { } - QLayoutStyleInfo styleInfo() const; - - QGridLayoutEngine engine; -#ifdef QT_DEBUG - void dump(int indent) const; -#endif -}; - -Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget); - -QLayoutStyleInfo QGraphicsGridLayoutPrivate::styleInfo() const -{ - QGraphicsItem *item = parentItem(); - QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); - return QLayoutStyleInfo(style, globalStyleInfoWidget()); -} - -/*! - Constructs a QGraphicsGridLayout instance. \a parent is passed to - QGraphicsLayout's constructor. -*/ -QGraphicsGridLayout::QGraphicsGridLayout(QGraphicsLayoutItem *parent) - : QGraphicsLayout(*new QGraphicsGridLayoutPrivate(), parent) -{ -} - -/*! - Destroys the QGraphicsGridLayout object. -*/ -QGraphicsGridLayout::~QGraphicsGridLayout() -{ - for (int i = count() - 1; i >= 0; --i) { - QGraphicsLayoutItem *item = itemAt(i); - // The following lines can be removed, but this removes the item - // from the layout more efficiently than the implementation of - // ~QGraphicsLayoutItem. - removeAt(i); - if (item) { - item->setParentLayoutItem(0); - if (item->ownedByLayout()) - delete item; - } - } -} - -/*! - Adds \a item to the grid on \a row and \a column. You can specify a - \a rowSpan and \a columnSpan and an optional \a alignment. -*/ -void QGraphicsGridLayout::addItem(QGraphicsLayoutItem *item, int row, int column, - int rowSpan, int columnSpan, Qt::Alignment alignment) -{ - Q_D(QGraphicsGridLayout); - if (row < 0 || column < 0) { - qWarning("QGraphicsGridLayout::addItem: invalid row/column: %d", - row < 0 ? row : column); - return; - } - if (columnSpan < 1 || rowSpan < 1) { - qWarning("QGraphicsGridLayout::addItem: invalid row span/column span: %d", - rowSpan < 1 ? rowSpan : columnSpan); - return; - } - if (!item) { - qWarning("QGraphicsGridLayout::addItem: cannot add null item"); - return; - } - if (item == this) { - qWarning("QGraphicsGridLayout::addItem: cannot insert itself"); - return; - } - - d->addChildLayoutItem(item); - - new QGridLayoutItem(&d->engine, item, row, column, rowSpan, columnSpan, alignment); - invalidate(); -} - -/*! - \fn QGraphicsGridLayout::addItem(QGraphicsLayoutItem *item, int row, int column, Qt::Alignment alignment = 0) - - Adds \a item to the grid on \a row and \a column. You can specify - an optional \a alignment for \a item. -*/ - -/*! - Sets the default horizontal spacing for the grid layout to \a spacing. -*/ -void QGraphicsGridLayout::setHorizontalSpacing(qreal spacing) -{ - Q_D(QGraphicsGridLayout); - d->engine.setSpacing(spacing, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the default horizontal spacing for the grid layout. -*/ -qreal QGraphicsGridLayout::horizontalSpacing() const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.spacing(d->styleInfo(), Qt::Horizontal); -} - -/*! - Sets the default vertical spacing for the grid layout to \a spacing. -*/ -void QGraphicsGridLayout::setVerticalSpacing(qreal spacing) -{ - Q_D(QGraphicsGridLayout); - d->engine.setSpacing(spacing, Qt::Vertical); - invalidate(); -} - -/*! - Returns the default vertical spacing for the grid layout. -*/ -qreal QGraphicsGridLayout::verticalSpacing() const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.spacing(d->styleInfo(), Qt::Vertical); -} - -/*! - Sets the grid layout's default spacing, both vertical and - horizontal, to \a spacing. - - \sa rowSpacing(), columnSpacing() -*/ -void QGraphicsGridLayout::setSpacing(qreal spacing) -{ - Q_D(QGraphicsGridLayout); - d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical); - invalidate(); -} - -/*! - Sets the spacing for \a row to \a spacing. -*/ -void QGraphicsGridLayout::setRowSpacing(int row, qreal spacing) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSpacing(row, spacing, Qt::Vertical); - invalidate(); -} - -/*! - Returns the row spacing for \a row. -*/ -qreal QGraphicsGridLayout::rowSpacing(int row) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSpacing(row, Qt::Vertical); -} - -/*! - Sets the spacing for \a column to \a spacing. -*/ -void QGraphicsGridLayout::setColumnSpacing(int column, qreal spacing) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSpacing(column, spacing, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the column spacing for \a column. -*/ -qreal QGraphicsGridLayout::columnSpacing(int column) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSpacing(column, Qt::Horizontal); -} - -/*! - Sets the stretch factor for \a row to \a stretch. -*/ -void QGraphicsGridLayout::setRowStretchFactor(int row, int stretch) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowStretchFactor(row, stretch, Qt::Vertical); - invalidate(); -} - -/*! - Returns the stretch factor for \a row. -*/ -int QGraphicsGridLayout::rowStretchFactor(int row) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowStretchFactor(row, Qt::Vertical); -} - -/*! - Sets the stretch factor for \a column to \a stretch. -*/ -void QGraphicsGridLayout::setColumnStretchFactor(int column, int stretch) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowStretchFactor(column, stretch, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the stretch factor for \a column. -*/ -int QGraphicsGridLayout::columnStretchFactor(int column) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowStretchFactor(column, Qt::Horizontal); -} - -/*! - Sets the minimum height for row, \a row, to \a height. -*/ -void QGraphicsGridLayout::setRowMinimumHeight(int row, qreal height) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::MinimumSize, row, height, Qt::Vertical); - invalidate(); -} - -/*! - Returns the minimum height for row, \a row. -*/ -qreal QGraphicsGridLayout::rowMinimumHeight(int row) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSizeHint(Qt::MinimumSize, row, Qt::Vertical); -} - -/*! - Sets the preferred height for row, \a row, to \a height. -*/ -void QGraphicsGridLayout::setRowPreferredHeight(int row, qreal height) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::PreferredSize, row, height, Qt::Vertical); - invalidate(); -} - -/*! - Returns the preferred height for row, \a row. -*/ -qreal QGraphicsGridLayout::rowPreferredHeight(int row) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSizeHint(Qt::PreferredSize, row, Qt::Vertical); -} - -/*! - Sets the maximum height for row, \a row, to \a height. -*/ -void QGraphicsGridLayout::setRowMaximumHeight(int row, qreal height) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::MaximumSize, row, height, Qt::Vertical); - invalidate(); -} - -/*! - Returns the maximum height for row, \a row. -*/ -qreal QGraphicsGridLayout::rowMaximumHeight(int row) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSizeHint(Qt::MaximumSize, row, Qt::Vertical); -} - -/*! - Sets the fixed height for row, \a row, to \a height. -*/ -void QGraphicsGridLayout::setRowFixedHeight(int row, qreal height) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::MinimumSize, row, height, Qt::Vertical); - d->engine.setRowSizeHint(Qt::MaximumSize, row, height, Qt::Vertical); - invalidate(); -} - -/*! - Sets the minimum width for \a column to \a width. -*/ -void QGraphicsGridLayout::setColumnMinimumWidth(int column, qreal width) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::MinimumSize, column, width, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the minimum width for \a column. -*/ -qreal QGraphicsGridLayout::columnMinimumWidth(int column) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSizeHint(Qt::MinimumSize, column, Qt::Horizontal); -} - -/*! - Sets the preferred width for \a column to \a width. -*/ -void QGraphicsGridLayout::setColumnPreferredWidth(int column, qreal width) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::PreferredSize, column, width, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the preferred width for \a column. -*/ -qreal QGraphicsGridLayout::columnPreferredWidth(int column) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSizeHint(Qt::PreferredSize, column, Qt::Horizontal); -} - -/*! - Sets the maximum width of \a column to \a width. -*/ -void QGraphicsGridLayout::setColumnMaximumWidth(int column, qreal width) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::MaximumSize, column, width, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the maximum width for \a column. -*/ -qreal QGraphicsGridLayout::columnMaximumWidth(int column) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowSizeHint(Qt::MaximumSize, column, Qt::Horizontal); -} - -/*! - Sets the fixed width of \a column to \a width. -*/ -void QGraphicsGridLayout::setColumnFixedWidth(int column, qreal width) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowSizeHint(Qt::MinimumSize, column, width, Qt::Horizontal); - d->engine.setRowSizeHint(Qt::MaximumSize, column, width, Qt::Horizontal); - invalidate(); -} - -/*! - Sets the alignment of \a row to \a alignment. -*/ -void QGraphicsGridLayout::setRowAlignment(int row, Qt::Alignment alignment) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowAlignment(row, alignment, Qt::Vertical); - invalidate(); -} - -/*! - Returns the alignment of \a row. -*/ -Qt::Alignment QGraphicsGridLayout::rowAlignment(int row) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowAlignment(row, Qt::Vertical); -} - -/*! - Sets the alignment for \a column to \a alignment. -*/ -void QGraphicsGridLayout::setColumnAlignment(int column, Qt::Alignment alignment) -{ - Q_D(QGraphicsGridLayout); - d->engine.setRowAlignment(column, alignment, Qt::Horizontal); - invalidate(); -} - -/*! - Returns the alignment for \a column. -*/ -Qt::Alignment QGraphicsGridLayout::columnAlignment(int column) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.rowAlignment(column, Qt::Horizontal); -} - -/*! - Sets the alignment for \a item to \a alignment. -*/ -void QGraphicsGridLayout::setAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment) -{ - Q_D(QGraphicsGridLayout); - d->engine.setAlignment(item, alignment); - invalidate(); -} - -/*! - Returns the alignment for \a item. -*/ -Qt::Alignment QGraphicsGridLayout::alignment(QGraphicsLayoutItem *item) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.alignment(item); -} - -/*! - Returns the number of rows in the grid layout. This is always one more - than the index of the last row that is occupied by a layout item (empty - rows are counted except for those at the end). -*/ -int QGraphicsGridLayout::rowCount() const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.effectiveLastRow(Qt::Vertical) + 1; -} - -/*! - Returns the number of columns in the grid layout. This is always one more - than the index of the last column that is occupied by a layout item (empty - columns are counted except for those at the end). -*/ -int QGraphicsGridLayout::columnCount() const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.effectiveLastRow(Qt::Horizontal) + 1; -} - -/*! - Returns a pointer to the layout item at (\a row, \a column). -*/ -QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int row, int column) const -{ - Q_D(const QGraphicsGridLayout); - if (row < 0 || row >= rowCount() || column < 0 || column >= columnCount()) { - qWarning("QGraphicsGridLayout::itemAt: invalid row, column %d, %d", row, column); - return 0; - } - if (QGridLayoutItem *item = d->engine.itemAt(row, column)) - return item->layoutItem(); - return 0; -} - -/*! - Returns the number of layout items in this grid layout. -*/ -int QGraphicsGridLayout::count() const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.itemCount(); -} - -/*! - Returns the layout item at \a index, or 0 if there is no layout item at - this index. -*/ -QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int index) const -{ - Q_D(const QGraphicsGridLayout); - if (index < 0 || index >= d->engine.itemCount()) { - qWarning("QGraphicsGridLayout::itemAt: invalid index %d", index); - return 0; - } - QGraphicsLayoutItem *item = 0; - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) - item = gridItem->layoutItem(); - return item; -} - -/*! - Removes the layout item at \a index without destroying it. Ownership of - the item is transferred to the caller. - - \sa addItem() -*/ -void QGraphicsGridLayout::removeAt(int index) -{ - Q_D(QGraphicsGridLayout); - if (index < 0 || index >= d->engine.itemCount()) { - qWarning("QGraphicsGridLayout::removeAt: invalid index %d", index); - return; - } - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) { - if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem()) - layoutItem->setParentLayoutItem(0); - d->engine.removeItem(gridItem); - - // recalculate rowInfo.count if we remove an item that is on the right/bottommost row - for (int j = 0; j < NOrientations; ++j) { - // 0: Hor, 1: Ver - const Qt::Orientation orient = (j == 0 ? Qt::Horizontal : Qt::Vertical); - const int oldCount = d->engine.rowCount(orient); - if (gridItem->lastRow(orient) == oldCount - 1) { - const int newCount = d->engine.effectiveLastRow(orient) + 1; - d->engine.removeRows(newCount, oldCount - newCount, orient); - } - } - - delete gridItem; - invalidate(); - } -} - -/*! - Removes the layout item \a item without destroying it. - Ownership of the item is transferred to the caller. - - \sa addItem() -*/ -void QGraphicsGridLayout::removeItem(QGraphicsLayoutItem *item) -{ - Q_D(QGraphicsGridLayout); - int index = d->engine.indexOf(item); - removeAt(index); -} -/*! - \reimp -*/ -void QGraphicsGridLayout::invalidate() -{ - Q_D(QGraphicsGridLayout); - d->engine.invalidate(); - QGraphicsLayout::invalidate(); -} - -#ifdef QT_DEBUG -void QGraphicsGridLayoutPrivate::dump(int indent) const -{ - if (qt_graphicsLayoutDebug()) { - engine.dump(indent + 1); - } -} -#endif - -/*! - Sets the bounding geometry of the grid layout to \a rect. -*/ -void QGraphicsGridLayout::setGeometry(const QRectF &rect) -{ - Q_D(QGraphicsGridLayout); - QGraphicsLayout::setGeometry(rect); - QRectF effectiveRect = geometry(); - qreal left, top, right, bottom; - getContentsMargins(&left, &top, &right, &bottom); - Qt::LayoutDirection visualDir = d->visualDirection(); - d->engine.setVisualDirection(visualDir); - if (visualDir == Qt::RightToLeft) - qSwap(left, right); - effectiveRect.adjust(+left, +top, -right, -bottom); - d->engine.setGeometries(d->styleInfo(), effectiveRect); -#ifdef QT_DEBUG - if (qt_graphicsLayoutDebug()) { - static int counter = 0; - qDebug("==== BEGIN DUMP OF QGraphicsGridLayout (%d)====", counter++); - d->dump(1); - qDebug("==== END DUMP OF QGraphicsGridLayout ===="); - } -#endif -} - -/*! - \reimp -*/ -QSizeF QGraphicsGridLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_D(const QGraphicsGridLayout); - qreal left, top, right, bottom; - getContentsMargins(&left, &top, &right, &bottom); - const QSizeF extraMargins(left + right, top + bottom); - return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins; -} - - -#if 0 -// ### kill? (implement and kill?) -QRect QGraphicsGridLayout::cellRect(int row, int column, int rowSpan, int columnSpan) const -{ - Q_D(const QGraphicsGridLayout); - return QRect(); -// return d->engine.cellRect(parentLayoutable(), contentsGeometry(), row, column, rowSpan, columnSpan); -} - -QSizePolicy::ControlTypes QGraphicsGridLayout::controlTypes(LayoutSide side) const -{ - Q_D(const QGraphicsGridLayout); - return d->engine.controlTypes(side); -} -#endif - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h deleted file mode 100644 index 771c8a074c..0000000000 --- a/src/gui/graphicsview/qgraphicsgridlayout.h +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSGRIDLAYOUT_H -#define QGRAPHICSGRIDLAYOUT_H - -#include <QtGui/qgraphicsitem.h> -#include <QtGui/qgraphicslayout.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsGridLayoutPrivate; - -class Q_GUI_EXPORT QGraphicsGridLayout : public QGraphicsLayout -{ -public: - QGraphicsGridLayout(QGraphicsLayoutItem *parent = 0); - virtual ~QGraphicsGridLayout(); - - void addItem(QGraphicsLayoutItem *item, int row, int column, int rowSpan, int columnSpan, - Qt::Alignment alignment = 0); - inline void addItem(QGraphicsLayoutItem *item, int row, int column, Qt::Alignment alignment = 0); - - void setHorizontalSpacing(qreal spacing); - qreal horizontalSpacing() const; - void setVerticalSpacing(qreal spacing); - qreal verticalSpacing() const; - void setSpacing(qreal spacing); - - void setRowSpacing(int row, qreal spacing); - qreal rowSpacing(int row) const; - void setColumnSpacing(int column, qreal spacing); - qreal columnSpacing(int column) const; - - void setRowStretchFactor(int row, int stretch); - int rowStretchFactor(int row) const; - void setColumnStretchFactor(int column, int stretch); - int columnStretchFactor(int column) const; - - void setRowMinimumHeight(int row, qreal height); - qreal rowMinimumHeight(int row) const; - void setRowPreferredHeight(int row, qreal height); - qreal rowPreferredHeight(int row) const; - void setRowMaximumHeight(int row, qreal height); - qreal rowMaximumHeight(int row) const; - void setRowFixedHeight(int row, qreal height); - - void setColumnMinimumWidth(int column, qreal width); - qreal columnMinimumWidth(int column) const; - void setColumnPreferredWidth(int column, qreal width); - qreal columnPreferredWidth(int column) const; - void setColumnMaximumWidth(int column, qreal width); - qreal columnMaximumWidth(int column) const; - void setColumnFixedWidth(int column, qreal width); - - void setRowAlignment(int row, Qt::Alignment alignment); - Qt::Alignment rowAlignment(int row) const; - void setColumnAlignment(int column, Qt::Alignment alignment); - Qt::Alignment columnAlignment(int column) const; - - void setAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment); - Qt::Alignment alignment(QGraphicsLayoutItem *item) const; - - int rowCount() const; - int columnCount() const; - - QGraphicsLayoutItem *itemAt(int row, int column) const; - - // inherited from QGraphicsLayout - int count() const; - QGraphicsLayoutItem *itemAt(int index) const; - void removeAt(int index); - void removeItem(QGraphicsLayoutItem *item); - - void invalidate(); - - // inherited from QGraphicsLayoutItem - void setGeometry(const QRectF &rect); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - - // #### - //QRect cellRect(int row, int column, int rowSpan = 1, int columnSpan = 1) const; - //QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; - -private: - Q_DISABLE_COPY(QGraphicsGridLayout) - Q_DECLARE_PRIVATE(QGraphicsGridLayout) -}; - -inline void QGraphicsGridLayout::addItem(QGraphicsLayoutItem *aitem, int arow, int acolumn, Qt::Alignment aalignment) -{ addItem(aitem, arow, acolumn, 1, 1, aalignment); } - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif - diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp deleted file mode 100644 index ef539634d9..0000000000 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ /dev/null @@ -1,11601 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsItem - \brief The QGraphicsItem class is the base class for all graphical - items in a QGraphicsScene. - \since 4.2 - - \ingroup graphicsview-api - - It provides a light-weight foundation for writing your own custom items. - This includes defining the item's geometry, collision detection, its - painting implementation and item interaction through its event handlers. - QGraphicsItem is part of the \l{Graphics View Framework} - - \image graphicsview-items.png - - For convenience, Qt provides a set of standard graphics items for the most - common shapes. These are: - - \list - \o QGraphicsEllipseItem provides an ellipse item - \o QGraphicsLineItem provides a line item - \o QGraphicsPathItem provides an arbitrary path item - \o QGraphicsPixmapItem provides a pixmap item - \o QGraphicsPolygonItem provides a polygon item - \o QGraphicsRectItem provides a rectangular item - \o QGraphicsSimpleTextItem provides a simple text label item - \o QGraphicsTextItem provides an advanced text browser item - \endlist - - All of an item's geometric information is based on its local coordinate - system. The item's position, pos(), is the only function that does not - operate in local coordinates, as it returns a position in parent - coordinates. \l {The Graphics View Coordinate System} describes the coordinate - system in detail. - - You can set whether an item should be visible (i.e., drawn, and accepting - events), by calling setVisible(). Hiding an item will also hide its - children. Similarly, you can enable or disable an item by calling - setEnabled(). If you disable an item, all its children will also be - disabled. By default, items are both visible and enabled. To toggle - whether an item is selected or not, first enable selection by setting - the ItemIsSelectable flag, and then call setSelected(). Normally, - selection is toggled by the scene, as a result of user interaction. - - To write your own graphics item, you first create a subclass of - QGraphicsItem, and then start by implementing its two pure virtual public - functions: boundingRect(), which returns an estimate of the area painted - by the item, and paint(), which implements the actual painting. For - example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 0 - - The boundingRect() function has many different purposes. - QGraphicsScene bases its item index on boundingRect(), and - QGraphicsView uses it both for culling invisible items, and for - determining the area that needs to be recomposed when drawing - overlapping items. In addition, QGraphicsItem's collision - detection mechanisms use boundingRect() to provide an efficient - cut-off. The fine grained collision algorithm in - collidesWithItem() is based on calling shape(), which returns an - accurate outline of the item's shape as a QPainterPath. - - QGraphicsScene expects all items boundingRect() and shape() to - remain unchanged unless it is notified. If you want to change an - item's geometry in any way, you must first call - prepareGeometryChange() to allow QGraphicsScene to update its - bookkeeping. - - Collision detection can be done in two ways: - - \list 1 - - \o Reimplement shape() to return an accurate shape for your item, - and rely on the default implementation of collidesWithItem() to do - shape-shape intersection. This can be rather expensive if the - shapes are complex. - - \o Reimplement collidesWithItem() to provide your own custom item - and shape collision algorithm. - - \endlist - - The contains() function can be called to determine whether the item \e - contains a point or not. This function can also be reimplemented by the - item. The default behavior of contains() is based on calling shape(). - - Items can contain other items, and also be contained by other items. All - items can have a parent item and a list of children. Unless the item has - no parent, its position is in \e parent coordinates (i.e., the parent's - local coordinates). Parent items propagate both their position and their - transformation to all children. - - \img graphicsview-parentchild.png - - \target Transformations - \section1 Transformations - - QGraphicsItem supports projective transformations in addition to its base - position, pos(). There are several ways to change an item's transformation. - For simple transformations, you can call either of the convenience - functions setRotation() or setScale(), or you can pass any transformation - matrix to setTransform(). For advanced transformation control you also have - the option of setting several combined transformations by calling - setTransformations(). - - Item transformations accumulate from parent to child, so if both a parent - and child item are rotated 90 degrees, the child's total transformation - will be 180 degrees. Similarly, if the item's parent is scaled to 2x its - original size, its children will also be twice as large. An item's - transformation does not affect its own local geometry; all geometry - functions (e.g., contains(), update(), and all the mapping functions) still - operate in local coordinates. For convenience, QGraphicsItem provides the - functions sceneTransform(), which returns the item's total transformation - matrix (including its position and all parents' positions and - transformations), and scenePos(), which returns its position in scene - coordinates. To reset an item's matrix, call resetTransform(). - - Certain transformation operations produce a different outcome depending on - the order in which they are applied. For example, if you scale an - transform, and then rotate it, you may get a different result than if the - transform was rotated first. However, the order you set the transformation - properties on QGraphicsItem does not affect the resulting transformation; - QGraphicsItem always applies the properties in a fixed, defined order: - - \list - \o The item's base transform is applied (transform()) - \o The item's transformations list is applied in order (transformations()) - \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint()) - \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint()) - \endlist - - \section1 Painting - - The paint() function is called by QGraphicsView to paint the item's - contents. The item has no background or default fill of its own; whatever - is behind the item will shine through all areas that are not explicitly - painted in this function. You can call update() to schedule a repaint, - optionally passing the rectangle that needs a repaint. Depending on - whether or not the item is visible in a view, the item may or may not be - repainted; there is no equivalent to QWidget::repaint() in QGraphicsItem. - - Items are painted by the view, starting with the parent items and then - drawing children, in ascending stacking order. You can set an item's - stacking order by calling setZValue(), and test it by calling - zValue(), where items with low z-values are painted before items with - high z-values. Stacking order applies to sibling items; parents are always - drawn before their children. - - \section1 Sorting - - All items are drawn in a defined, stable order, and this same order decides - which items will receive mouse input first when you click on the scene. - Normally you don't have to worry about sorting, as the items follow a - "natural order", following the logical structure of the scene. - - An item's children are stacked on top of the parent, and sibling items are - stacked by insertion order (i.e., in the same order that they were either - added to the scene, or added to the same parent). If you add item A, and - then B, then B will be on top of A. If you then add C, the items' stacking - order will be A, then B, then C. - - \image graphicsview-zorder.png - - This example shows the stacking order of all limbs of the robot from the - \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is - the root item (all other items are children or descendants of the torso), - so it is drawn first. Next, the head is drawn, as it is the first item in - the torso's list of children. Then the upper left arm is drawn. As the - lower arm is a child of the upper arm, the lower arm is then drawn, - followed by the upper arm's next sibling, which is the upper right arm, and - so on. - - For advanced users, there are ways to alter how your items are sorted: - - \list - \o You can call setZValue() on an item to explicitly stack it on top of, or - under, other sibling items. The default Z value for an item is 0. Items - with the same Z value are stacked by insertion order. - - \o You can call stackBefore() to reorder the list of children. This will - directly modify the insertion order. - - \o You can set the ItemStacksBehindParent flag to stack a child item behind - its parent. - \endlist - - The stacking order of two sibling items also counts for each item's - children and descendant items. So if one item is on top of another, then - all its children will also be on top of all the other item's children as - well. - - \section1 Events - - QGraphicsItem receives events from QGraphicsScene through the virtual - function sceneEvent(). This function distributes the most common events - to a set of convenience event handlers: - - \list - \o contextMenuEvent() handles context menu events - \o focusInEvent() and focusOutEvent() handle focus in and out events - \o hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() handles - hover enter, move and leave events - \o inputMethodEvent() handles input events, for accessibility support - \o keyPressEvent() and keyReleaseEvent() handle key press and release events - \o mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and - mouseDoubleClickEvent() handles mouse press, move, release, click and - doubleclick events - \endlist - - You can filter events for any other item by installing event filters. This - functionality is separate from Qt's regular event filters (see - QObject::installEventFilter()), which only work on subclasses of QObject. After - installing your item as an event filter for another item by calling - installSceneEventFilter(), the filtered events will be received by the virtual - function sceneEventFilter(). You can remove item event filters by calling - removeSceneEventFilter(). - - \section1 Custom Data - - Sometimes it's useful to register custom data with an item, be it a custom - item, or a standard item. You can call setData() on any item to store data - in it using a key-value pair (the key being an integer, and the value is a - QVariant). To get custom data from an item, call data(). This - functionality is completely untouched by Qt itself; it is provided for the - user's convenience. - - \sa QGraphicsScene, QGraphicsView, {Graphics View Framework} -*/ - -/*! - \variable QGraphicsItem::Type - - The type value returned by the virtual type() function in standard - graphics item classes in Qt. All such standard graphics item - classes in Qt are associated with a unique value for Type, - e.g. the value returned by QGraphicsPathItem::type() is 2. - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 18 -*/ - -/*! - \variable QGraphicsItem::UserType - - The lowest permitted type value for custom items (subclasses - of QGraphicsItem or any of the standard items). This value is - used in conjunction with a reimplementation of QGraphicsItem::type() - and declaring a Type enum value. Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 1 - - \note UserType = 65536 -*/ - -/*! - \enum QGraphicsItem::GraphicsItemFlag - - This enum describes different flags that you can set on an item to - toggle different features in the item's behavior. - - All flags are disabled by default. - - \value ItemIsMovable The item supports interactive movement using - the mouse. By clicking on the item and then dragging, the item - will move together with the mouse cursor. If the item has - children, all children are also moved. If the item is part of a - selection, all selected items are also moved. This feature is - provided as a convenience through the base implementation of - QGraphicsItem's mouse event handlers. - - \value ItemIsSelectable The item supports selection. Enabling this - feature will enable setSelected() to toggle selection for the - item. It will also let the item be selected automatically as a - result of calling QGraphicsScene::setSelectionArea(), by clicking - on an item, or by using rubber band selection in QGraphicsView. - - \value ItemIsFocusable The item supports keyboard input focus (i.e., it is - an input item). Enabling this flag will allow the item to accept focus, - which again allows the delivery of key events to - QGraphicsItem::keyPressEvent() and QGraphicsItem::keyReleaseEvent(). - - \value ItemClipsToShape The item clips to its own shape. The item cannot - draw or receive mouse, tablet, drag and drop or hover events outside its - shape. It is disabled by default. This behavior is enforced by - QGraphicsView::drawItems() or QGraphicsScene::drawItems(). This flag was - introduced in Qt 4.3. - - \value ItemClipsChildrenToShape The item clips the painting of all its - descendants to its own shape. Items that are either direct or indirect - children of this item cannot draw outside this item's shape. By default, - this flag is disabled; children can draw anywhere. This behavior is - enforced by QGraphicsView::drawItems() or - QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3. - - \value ItemIgnoresTransformations The item ignores inherited - transformations (i.e., its position is still anchored to its parent, but - the parent or view rotation, zoom or shear transformations are ignored). - This flag is useful for keeping text label items horizontal and unscaled, - so they will still be readable if the view is transformed. When set, the - item's view geometry and scene geometry will be maintained separately. You - must call deviceTransform() to map coordinates and detect collisions in - the view. By default, this flag is disabled. This flag was introduced in - Qt 4.3. \note With this flag set you can still scale the item itself, and - that scale transformation will influence the item's children. - - \value ItemIgnoresParentOpacity The item ignores its parent's opacity. The - item's effective opacity is the same as its own; it does not combine with - the parent's opacity. This flags allows your item to keep its absolute - opacity even if the parent is semitransparent. This flag was introduced in - Qt 4.5. - - \value ItemDoesntPropagateOpacityToChildren The item doesn't propagate its - opacity to its children. This flag allows you to create a semitransparent - item that does not affect the opacity of its children. This flag was - introduced in Qt 4.5. - - \value ItemStacksBehindParent The item is stacked behind its parent. By - default, child items are stacked on top of the parent item. But setting - this flag, the child will be stacked behind it. This flag is useful for - drop shadow effects and for decoration objects that follow the parent - item's geometry without drawing on top of it. This flag was introduced - in Qt 4.5. - - \value ItemUsesExtendedStyleOption The item makes use of either - \l{QStyleOptionGraphicsItem::} {exposedRect} or - \l{QStyleOptionGraphicsItem::} {matrix} in - QStyleOptionGraphicsItem. By default, the - \l{QStyleOptionGraphicsItem::} {exposedRect} is initialized to the - item's boundingRect() and the - \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. You can - enable this flag for the style options to be set up with more - fine-grained values. Note that - QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag - and always initialized to 1. Use - QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need - a higher value. This flag was introduced in Qt 4.6. - - \value ItemHasNoContents The item does not paint anything (i.e., calling - paint() on the item has no effect). You should set this flag on items that - do not need to be painted to ensure that Graphics View avoids unnecessary - painting preparations. This flag was introduced in Qt 4.6. - - \value ItemSendsGeometryChanges The item enables itemChange() - notifications for ItemPositionChange, ItemPositionHasChanged, - ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged, - ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged, - ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. For - performance reasons, these notifications are disabled by default. You must - enable this flag to receive notifications for position and transform - changes. This flag was introduced in Qt 4.6. - - \value ItemAcceptsInputMethod The item supports input methods typically - used for Asian languages. - This flag was introduced in Qt 4.6. - - \value ItemNegativeZStacksBehindParent The item automatically - stacks behind it's parent if it's z-value is negative. This flag - enables setZValue() to toggle ItemStacksBehindParent. This flag - was introduced in Qt 4.6. - - \value ItemIsPanel The item is a panel. A panel provides activation and - contained focus handling. Only one panel can be active at a time (see - QGraphicsItem::isActive()). When no panel is active, QGraphicsScene - activates all non-panel items. Window items (i.e., - QGraphicsItem::isWindow() returns true) are panels. This flag was - introduced in Qt 4.6. - - \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit - - \value ItemSendsScenePositionChanges The item enables itemChange() - notifications for ItemScenePositionHasChanged. For performance reasons, - these notifications are disabled by default. You must enable this flag - to receive notifications for scene position changes. This flag was - introduced in Qt 4.6. - - \omitvalue ItemStopsClickFocusPropagation \omit The item stops propagating - click focus to items underneath when being clicked on. This flag - allows you create a non-focusable item that can be clicked on without - changing the focus. \endomit - - \omitvalue ItemStopsFocusHandling \omit Same as - ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag - allows you to completely take over focus handling. - This flag was introduced in Qt 4.7. \endomit -*/ - -/*! - \enum QGraphicsItem::GraphicsItemChange - - This enum describes the state changes that are notified by - QGraphicsItem::itemChange(). The notifications are sent as the state - changes, and in some cases, adjustments can be made (see the documentation - for each change for details). - - Note: Be careful with calling functions on the QGraphicsItem itself inside - itemChange(), as certain function calls can lead to unwanted - recursion. For example, you cannot call setPos() in itemChange() on an - ItemPositionChange notification, as the setPos() function will again call - itemChange(ItemPositionChange). Instead, you can return the new, adjusted - position from itemChange(). - - \value ItemEnabledChange The item's enabled state changes. If the item is - presently enabled, it will become disabled, and vice verca. The value - argument is the new enabled state (i.e., true or false). Do not call - setEnabled() in itemChange() as this notification is delivered. Instead, - you can return the new state from itemChange(). - - \value ItemEnabledHasChanged The item's enabled state has changed. The - value argument is the new enabled state (i.e., true or false). Do not call - setEnabled() in itemChange() as this notification is delivered. The return - value is ignored. - - \value ItemMatrixChange The item's affine transformation matrix is - changing. This value is obsolete; you can use ItemTransformChange instead. - - \value ItemPositionChange The item's position changes. This notification - is sent if the ItemSendsGeometryChanges flag is enabled, and when the - item's local position changes, relative to its parent (i.e., as a result - of calling setPos() or moveBy()). The value argument is the new position - (i.e., a QPointF). You can call pos() to get the original position. Do - not call setPos() or moveBy() in itemChange() as this notification is - delivered; instead, you can return the new, adjusted position from - itemChange(). After this notification, QGraphicsItem immediately sends the - ItemPositionHasChanged notification if the position changed. - - \value ItemPositionHasChanged The item's position has changed. This - notification is sent if the ItemSendsGeometryChanges flag is enabled, and - after the item's local position, relative to its parent, has changed. The - value argument is the new position (the same as pos()), and QGraphicsItem - ignores the return value for this notification (i.e., a read-only - notification). - - \value ItemTransformChange The item's transformation matrix changes. This - notification is send if the ItemSendsGeometryChanges flag is enabled, and - when the item's local transformation matrix changes (i.e., as a result of - calling setTransform(). The value argument is the new matrix (i.e., a - QTransform); to get the old matrix, call transform(). Do not call - setTransform() or set any of the transformation properties in itemChange() - as this notification is delivered; instead, you can return the new matrix - from itemChange(). This notification is not sent if you change the - transformation properties. - - \value ItemTransformHasChanged The item's transformation matrix has - changed either because setTransform is called, or one of the - transformation properties is changed. This notification is sent if the - ItemSendsGeometryChanges flag is enabled, and after the item's local - transformation matrix has changed. The value argument is the new matrix - (same as transform()), and QGraphicsItem ignores the return value for this - notification (i.e., a read-only notification). - - \value ItemRotationChange The item's rotation property changes. This - notification is sent if the ItemSendsGeometryChanges flag is enabled, and - when the item's rotation property changes (i.e., as a result of calling - setRotation()). The value argument is the new rotation (i.e., a double); - to get the old rotation, call rotation(). Do not call setRotation() in - itemChange() as this notification is delivered; instead, you can return - the new rotation from itemChange(). - - \value ItemRotationHasChanged The item's rotation property has changed. - This notification is sent if the ItemSendsGeometryChanges flag is enabled, - and after the item's rotation property has changed. The value argument is - the new rotation (i.e., a double), and QGraphicsItem ignores the return - value for this notification (i.e., a read-only notification). Do not call - setRotation() in itemChange() as this notification is delivered. - - \value ItemScaleChange The item's scale property changes. This notification - is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's - scale property changes (i.e., as a result of calling setScale()). The value - argument is the new scale (i.e., a double); to get the old scale, call - scale(). Do not call setScale() in itemChange() as this notification is - delivered; instead, you can return the new scale from itemChange(). - - \value ItemScaleHasChanged The item's scale property has changed. This - notification is sent if the ItemSendsGeometryChanges flag is enabled, and - after the item's scale property has changed. The value argument is the new - scale (i.e., a double), and QGraphicsItem ignores the return value for this - notification (i.e., a read-only notification). Do not call setScale() in - itemChange() as this notification is delivered. - - \value ItemTransformOriginPointChange The item's transform origin point - property changes. This notification is sent if the ItemSendsGeometryChanges - flag is enabled, and when the item's transform origin point property changes - (i.e., as a result of calling setTransformOriginPoint()). The value argument - is the new origin point (i.e., a QPointF); to get the old origin point, call - transformOriginPoint(). Do not call setTransformOriginPoint() in itemChange() - as this notification is delivered; instead, you can return the new transform - origin point from itemChange(). - - \value ItemTransformOriginPointHasChanged The item's transform origin point - property has changed. This notification is sent if the ItemSendsGeometryChanges - flag is enabled, and after the item's transform origin point property has - changed. The value argument is the new origin point (i.e., a QPointF), and - QGraphicsItem ignores the return value for this notification (i.e., a read-only - notification). Do not call setTransformOriginPoint() in itemChange() as this - notification is delivered. - - \value ItemSelectedChange The item's selected state changes. If the item is - presently selected, it will become unselected, and vice verca. The value - argument is the new selected state (i.e., true or false). Do not call - setSelected() in itemChange() as this notification is delivered; instead, you - can return the new selected state from itemChange(). - - \value ItemSelectedHasChanged The item's selected state has changed. The - value argument is the new selected state (i.e., true or false). Do not - call setSelected() in itemChange() as this notification is delivered. The - return value is ignored. - - \value ItemVisibleChange The item's visible state changes. If the item is - presently visible, it will become invisible, and vice verca. The value - argument is the new visible state (i.e., true or false). Do not call - setVisible() in itemChange() as this notification is delivered; instead, - you can return the new visible state from itemChange(). - - \value ItemVisibleHasChanged The item's visible state has changed. The - value argument is the new visible state (i.e., true or false). Do not call - setVisible() in itemChange() as this notification is delivered. The return - value is ignored. - - \value ItemParentChange The item's parent changes. The value argument is - the new parent item (i.e., a QGraphicsItem pointer). Do not call - setParentItem() in itemChange() as this notification is delivered; - instead, you can return the new parent from itemChange(). - - \value ItemParentHasChanged The item's parent has changed. The value - argument is the new parent (i.e., a pointer to a QGraphicsItem). Do not - call setParentItem() in itemChange() as this notification is - delivered. The return value is ignored. - - \value ItemChildAddedChange A child is added to this item. The value - argument is the new child item (i.e., a QGraphicsItem pointer). Do not - pass this item to any item's setParentItem() function as this notification - is delivered. The return value is unused; you cannot adjust anything in - this notification. Note that the new child might not be fully constructed - when this notification is sent; calling pure virtual functions on - the child can lead to a crash. - - \value ItemChildRemovedChange A child is removed from this item. The value - argument is the child item that is about to be removed (i.e., a - QGraphicsItem pointer). The return value is unused; you cannot adjust - anything in this notification. - - \value ItemSceneChange The item is moved to a new scene. This notification is - also sent when the item is added to its initial scene, and when it is removed. - The item's scene() is the old scene (or 0 if the item has not been added to a - scene yet). The value argument is the new scene (i.e., a QGraphicsScene - pointer), or a null pointer if the item is removed from a scene. Do not - override this change by passing this item to QGraphicsScene::addItem() as this - notification is delivered; instead, you can return the new scene from - itemChange(). Use this feature with caution; objecting to a scene change can - quickly lead to unwanted recursion. - - \value ItemSceneHasChanged The item's scene has changed. The item's scene() is - the new scene. This notification is also sent when the item is added to its - initial scene, and when it is removed.The value argument is the new scene - (i.e., a pointer to a QGraphicsScene). Do not call setScene() in itemChange() - as this notification is delivered. The return value is ignored. - - \value ItemCursorChange The item's cursor changes. The value argument is - the new cursor (i.e., a QCursor). Do not call setCursor() in itemChange() - as this notification is delivered. Instead, you can return a new cursor - from itemChange(). - - \value ItemCursorHasChanged The item's cursor has changed. The value - argument is the new cursor (i.e., a QCursor). Do not call setCursor() as - this notification is delivered. The return value is ignored. - - \value ItemToolTipChange The item's tooltip changes. The value argument is - the new tooltip (i.e., a QToolTip). Do not call setToolTip() in - itemChange() as this notification is delivered. Instead, you can return a - new tooltip from itemChange(). - - \value ItemToolTipHasChanged The item's tooltip has changed. The value - argument is the new tooltip (i.e., a QToolTip). Do not call setToolTip() - as this notification is delivered. The return value is ignored. - - \value ItemFlagsChange The item's flags change. The value argument is the - new flags (i.e., a quint32). Do not call setFlags() in itemChange() as - this notification is delivered. Instead, you can return the new flags from - itemChange(). - - \value ItemFlagsHaveChanged The item's flags have changed. The value - argument is the new flags (i.e., a quint32). Do not call setFlags() in - itemChange() as this notification is delivered. The return value is - ignored. - - \value ItemZValueChange The item's Z-value changes. The value argument is - the new Z-value (i.e., a double). Do not call setZValue() in itemChange() - as this notification is delivered. Instead, you can return a new Z-value - from itemChange(). - - \value ItemZValueHasChanged The item's Z-value has changed. The value - argument is the new Z-value (i.e., a double). Do not call setZValue() as - this notification is delivered. The return value is ignored. - - \value ItemOpacityChange The item's opacity changes. The value argument is - the new opacity (i.e., a double). Do not call setOpacity() in itemChange() - as this notification is delivered. Instead, you can return a new opacity - from itemChange(). - - \value ItemOpacityHasChanged The item's opacity has changed. The value - argument is the new opacity (i.e., a double). Do not call setOpacity() as - this notification is delivered. The return value is ignored. - - \value ItemScenePositionHasChanged The item's scene position has changed. - This notification is sent if the ItemSendsScenePositionChanges flag is - enabled, and after the item's scene position has changed (i.e., the - position or transformation of the item itself or the position or - transformation of any ancestor has changed). The value argument is the - new scene position (the same as scenePos()), and QGraphicsItem ignores - the return value for this notification (i.e., a read-only notification). -*/ - -/*! - \enum QGraphicsItem::CacheMode - \since 4.4 - - This enum describes QGraphicsItem's cache modes. Caching is used to speed - up rendering by allocating and rendering to an off-screen pixel buffer, - which can be reused when the item requires redrawing. For some paint - devices, the cache is stored directly in graphics memory, which makes - rendering very quick. - - \value NoCache The default; all item caching is - disabled. QGraphicsItem::paint() is called every time the item needs - redrawing. - - \value ItemCoordinateCache Caching is enabled for the item's logical - (local) coordinate system. QGraphicsItem creates an off-screen pixel - buffer with a configurable size / resolution that you can pass to - QGraphicsItem::setCacheMode(). Rendering quality will typically degrade, - depending on the resolution of the cache and the item transformation. The - first time the item is redrawn, it will render itself into the cache, and - the cache is then reused for every subsequent expose. The cache is also - reused as the item is transformed. To adjust the resolution of the cache, - you can call setCacheMode() again. - - \value DeviceCoordinateCache Caching is enabled at the paint device level, - in device coordinates. This mode is for items that can move, but are not - rotated, scaled or sheared. If the item is transformed directly or - indirectly, the cache will be regenerated automatically. Unlike - ItemCoordinateCacheMode, DeviceCoordinateCache always renders at maximum - quality. - - \sa QGraphicsItem::setCacheMode() -*/ - -/*! - \enum QGraphicsItem::Extension - \internal - - Note: This is provided as a hook to avoid future problems related - to adding virtual functions. See also extension(), - supportsExtension() and setExtension(). -*/ - -/*! - \enum QGraphicsItem::PanelModality - \since 4.6 - - This enum specifies the behavior of a modal panel. A modal panel - is one that blocks input to other panels. Note that items that - are children of a modal panel are not blocked. - - The values are: - - \value NonModal The panel is not modal and does not block input to - other panels. This is the default value for panels. - - \value PanelModal The panel is modal to a single item hierarchy - and blocks input to its parent pane, all grandparent panels, and - all siblings of its parent and grandparent panels. - - \value SceneModal The window is modal to the entire scene and - blocks input to all panels. - - \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel -*/ - -#include "qgraphicsitem.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicsscene.h" -#include "qgraphicsscene_p.h" -#include "qgraphicssceneevent.h" -#include "qgraphicsview.h" -#include "qgraphicswidget.h" -#include "qgraphicsproxywidget.h" -#include "qgraphicsscenebsptreeindex_p.h" -#include <QtCore/qbitarray.h> -#include <QtCore/qdebug.h> -#include <QtCore/qpoint.h> -#include <QtCore/qstack.h> -#include <QtCore/qtimer.h> -#include <QtCore/qvariant.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qnumeric.h> -#include <QtGui/qapplication.h> -#include <QtGui/qbitmap.h> -#include <QtGui/qpainter.h> -#include <QtGui/qpainterpath.h> -#include <QtGui/qpixmapcache.h> -#include <QtGui/qstyleoption.h> -#include <QtGui/qevent.h> -#include <QtGui/qinputcontext.h> -#include <QtGui/qgraphicseffect.h> -#ifndef QT_NO_ACCESSIBILITY -# include "qaccessible.h" -#endif - -#include <private/qgraphicsitem_p.h> -#include <private/qgraphicswidget_p.h> -#include <private/qtextcontrol_p.h> -#include <private/qtextdocumentlayout_p.h> -#include <private/qtextengine_p.h> -#include <private/qwidget_p.h> -#include <private/qapplication_p.h> - -#ifdef Q_WS_X11 -#include <private/qt_x11_p.h> -#include <private/qpixmap_x11_p.h> -#endif - -#include <private/qgesturemanager_p.h> - -#include <math.h> - -QT_BEGIN_NAMESPACE - -static inline void _q_adjustRect(QRect *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(0, 0, 1, 0); - if (!rect->height()) - rect->adjust(0, 0, 0, 1); -} - -/* - ### Move this into QGraphicsItemPrivate - */ -class QGraphicsItemCustomDataStore -{ -public: - QMap<const QGraphicsItem *, QMap<int, QVariant> > data; -}; -Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore) - -/*! - \internal - - Returns a QPainterPath of \a path when stroked with the \a pen. - Ignoring dash pattern. -*/ -static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen) -{ - // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 - // if we pass a value of 0.0 to QPainterPathStroker::setWidth() - const qreal penWidthZero = qreal(0.00000001); - - if (path == QPainterPath()) - return path; - QPainterPathStroker ps; - ps.setCapStyle(pen.capStyle()); - if (pen.widthF() <= 0.0) - ps.setWidth(penWidthZero); - else - ps.setWidth(pen.widthF()); - ps.setJoinStyle(pen.joinStyle()); - ps.setMiterLimit(pen.miterLimit()); - QPainterPath p = ps.createStroke(path); - p.addPath(path); - return p; -} - -/*! - \internal - - Propagates the ancestor flag \a flag with value \a enabled to all this - item's children. If \a root is false, the flag is also set on this item - (default is true). -*/ -void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, - AncestorFlag flag, bool enabled, bool root) -{ - Q_Q(QGraphicsItem); - if (root) { - // For root items only. This is the item that has either enabled or - // disabled \a childFlag, or has been reparented. - switch (int(childFlag)) { - case -2: - flag = AncestorFiltersChildEvents; - enabled = q->filtersChildEvents(); - break; - case -1: - flag = AncestorHandlesChildEvents; - enabled = q->handlesChildEvents(); - break; - case QGraphicsItem::ItemClipsChildrenToShape: - flag = AncestorClipsChildren; - enabled = flags & QGraphicsItem::ItemClipsChildrenToShape; - break; - case QGraphicsItem::ItemIgnoresTransformations: - flag = AncestorIgnoresTransformations; - enabled = flags & QGraphicsItem::ItemIgnoresTransformations; - break; - default: - return; - } - - if (parent) { - // Inherit the enabled-state from our parents. - if ((parent->d_ptr->ancestorFlags & flag) - || (int(parent->d_ptr->flags & childFlag) == childFlag) - || (childFlag == -1 && parent->d_ptr->handlesChildEvents) - || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) { - enabled = true; - ancestorFlags |= flag; - } else { - ancestorFlags &= ~flag; - } - } else { - // Top-level root items don't have any ancestors, so there are no - // ancestor flags either. - ancestorFlags = 0; - } - } else { - // Don't set or propagate the ancestor flag if it's already correct. - if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled)) - return; - - // Set the flag. - if (enabled) - ancestorFlags |= flag; - else - ancestorFlags &= ~flag; - - // Don't process children if the item has the main flag set on itself. - if ((childFlag != -1 && int(flags & childFlag) == childFlag) - || (int(childFlag) == -1 && handlesChildEvents) - || (int(childFlag) == -2 && filtersDescendantEvents)) - return; - } - - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false); -} - -void QGraphicsItemPrivate::updateAncestorFlags() -{ - int flags = 0; - if (parent) { - // Inherit the parent's ancestor flags. - QGraphicsItemPrivate *pd = parent->d_ptr.data(); - flags = pd->ancestorFlags; - - // Add in flags from the parent. - if (pd->filtersDescendantEvents) - flags |= AncestorFiltersChildEvents; - if (pd->handlesChildEvents) - flags |= AncestorHandlesChildEvents; - if (pd->flags & QGraphicsItem::ItemClipsChildrenToShape) - flags |= AncestorClipsChildren; - if (pd->flags & QGraphicsItem::ItemIgnoresTransformations) - flags |= AncestorIgnoresTransformations; - } - - if (ancestorFlags == flags) - return; // No change; stop propagation. - ancestorFlags = flags; - - // Propagate to children recursively. - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->updateAncestorFlags(); -} - -/*! - \internal - - Propagates item group membership. -*/ -void QGraphicsItemPrivate::setIsMemberOfGroup(bool enabled) -{ - Q_Q(QGraphicsItem); - isMemberOfGroup = enabled; - if (!qgraphicsitem_cast<QGraphicsItemGroup *>(q)) { - foreach (QGraphicsItem *child, children) - child->d_func()->setIsMemberOfGroup(enabled); - } -} - -/*! - \internal - - Maps any item pos properties of \a event to \a item's coordinate system. -*/ -void QGraphicsItemPrivate::remapItemPos(QEvent *event, QGraphicsItem *item) -{ - Q_Q(QGraphicsItem); - switch (event->type()) { - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseDoubleClick: { - QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); - mouseEvent->setPos(item->mapFromItem(q, mouseEvent->pos())); - mouseEvent->setLastPos(item->mapFromItem(q, mouseEvent->pos())); - for (int i = 0x1; i <= 0x10; i <<= 1) { - if (mouseEvent->buttons() & i) { - Qt::MouseButton button = Qt::MouseButton(i); - mouseEvent->setButtonDownPos(button, item->mapFromItem(q, mouseEvent->buttonDownPos(button))); - } - } - break; - } - case QEvent::GraphicsSceneWheel: { - QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event); - wheelEvent->setPos(item->mapFromItem(q, wheelEvent->pos())); - break; - } - case QEvent::GraphicsSceneContextMenu: { - QGraphicsSceneContextMenuEvent *contextEvent = static_cast<QGraphicsSceneContextMenuEvent *>(event); - contextEvent->setPos(item->mapFromItem(q, contextEvent->pos())); - break; - } - case QEvent::GraphicsSceneHoverMove: { - QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event); - hoverEvent->setPos(item->mapFromItem(q, hoverEvent->pos())); - break; - } - default: - break; - } -} - -/*! - \internal - - Maps the point \a pos from scene to item coordinates. If \a view is passed and the item - is untransformable, this function will correctly map \a pos from the scene using the - view's transformation. -*/ -QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos, - const QWidget *viewport) const -{ - Q_Q(const QGraphicsItem); - if (!itemIsUntransformable()) - return q->mapFromScene(pos); - QGraphicsView *view = 0; - if (viewport) - view = qobject_cast<QGraphicsView *>(viewport->parentWidget()); - if (!view) - return q->mapFromScene(pos); - // ### More ping pong than needed. - return q->deviceTransform(view->viewportTransform()).inverted().map(view->mapFromScene(pos)); -} - -/*! - \internal - - Combines this item's position and transform onto \a transform. - - If you need to change this function (e.g., adding more transformation - modes / options), make sure to change all places marked with COMBINE. -*/ -void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const -{ - // COMBINE - if (viewTransform && itemIsUntransformable()) { - *x = q_ptr->deviceTransform(*viewTransform); - } else { - if (transformData) - *x *= transformData->computedFullTransform(); - if (!pos.isNull()) - *x *= QTransform::fromTranslate(pos.x(), pos.y()); - } -} - -/*! - \internal - - Combines this item's position and transform onto \a transform. - - If you need to change this function (e.g., adding more transformation - modes / options), make sure to change QGraphicsItem::deviceTransform() as - well. -*/ -void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const -{ - // COMBINE - if (viewTransform && itemIsUntransformable()) { - *x = q_ptr->deviceTransform(*viewTransform); - } else { - x->translate(pos.x(), pos.y()); - if (transformData) - *x = transformData->computedFullTransform(x); - } -} - -void QGraphicsItemPrivate::updateSceneTransformFromParent() -{ - if (parent) { - Q_ASSERT(!parent->d_ptr->dirtySceneTransform); - if (parent->d_ptr->sceneTransformTranslateOnly) { - sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(), - parent->d_ptr->sceneTransform.dy() + pos.y()); - } else { - sceneTransform = parent->d_ptr->sceneTransform; - sceneTransform.translate(pos.x(), pos.y()); - } - if (transformData) { - sceneTransform = transformData->computedFullTransform(&sceneTransform); - sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); - } else { - sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly; - } - } else if (!transformData) { - sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); - sceneTransformTranslateOnly = 1; - } else if (transformData->onlyTransform) { - sceneTransform = transformData->transform; - if (!pos.isNull()) - sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y()); - sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); - } else if (pos.isNull()) { - sceneTransform = transformData->computedFullTransform(); - sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); - } else { - sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); - sceneTransform = transformData->computedFullTransform(&sceneTransform); - sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); - } - dirtySceneTransform = 0; -} - -/*! - \internal - - This helper function helped us add input method query support in - Qt 4.4.1 without having to reimplement the inputMethodQuery() - function in QGraphicsProxyWidget. ### Qt 5: Remove. We cannot - remove it in 4.5+ even if we do reimplement the function properly, - because apps compiled with 4.4 will not be able to call the - reimplementation. -*/ -QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const -{ - Q_UNUSED(query); - return QVariant(); -} - -/*! - \internal - - Make sure not to trigger any pure virtual function calls (e.g., - prepareGeometryChange) if the item is in its destructor, i.e. - inDestructor is 1. -*/ -void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const QVariant *newParentVariant, - const QVariant *thisPointerVariant) -{ - Q_Q(QGraphicsItem); - if (newParent == parent) - return; - - if (isWidget) - static_cast<QGraphicsWidgetPrivate *>(this)->fixFocusChainBeforeReparenting((newParent && - newParent->isWidget()) ? static_cast<QGraphicsWidget *>(newParent) : 0, - scene); - if (scene) { - // Deliver the change to the index - if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex) - scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent); - - // Disable scene pos notifications for old ancestors - if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) - scene->d_func()->setScenePosItemEnabled(q, false); - } - - if (subFocusItem && parent) { - // Make sure none of the old parents point to this guy. - subFocusItem->d_ptr->clearSubFocus(parent); - } - - // We anticipate geometry changes. If the item is deleted, it will be - // removed from the index at a later stage, and the whole scene will be - // updated. - if (!inDestructor) - q_ptr->prepareGeometryChange(); - - if (parent) { - // Remove from current parent - parent->d_ptr->removeChild(q); - if (thisPointerVariant) - parent->itemChange(QGraphicsItem::ItemChildRemovedChange, *thisPointerVariant); - } - - // Update toplevelitem list. If this item is being deleted, its parent - // will be 0 but we don't want to register/unregister it in the TLI list. - if (scene && !inDestructor) { - if (parent && !newParent) { - scene->d_func()->registerTopLevelItem(q); - } else if (!parent && newParent) { - scene->d_func()->unregisterTopLevelItem(q); - } - } - - // Ensure any last parent focus scope does not point to this item or any of - // its descendents. - QGraphicsItem *p = parent; - QGraphicsItem *parentFocusScopeItem = 0; - while (p) { - if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { - // If this item's focus scope's focus scope item points - // to this item or a descendent, then clear it. - QGraphicsItem *fsi = p->d_ptr->focusScopeItem; - if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) { - parentFocusScopeItem = fsi; - p->d_ptr->focusScopeItem = 0; - fsi->d_ptr->focusScopeItemChange(false); - } - break; - } - p = p->d_ptr->parent; - } - - // Update graphics effect optimization flag - if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect)) - newParent->d_ptr->updateChildWithGraphicsEffectFlagRecursively(); - - // Update focus scope item ptr in new scope. - QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; - if (newFocusScopeItem && newParent) { - if (subFocusItem) { - // Find the subFocusItem's topmost focus scope. - QGraphicsItem *ancestorScope = 0; - QGraphicsItem *p = subFocusItem->d_ptr->parent; - while (p) { - if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) - ancestorScope = p; - if (p->d_ptr->flags & QGraphicsItem::ItemIsPanel) - break; - p = p->d_ptr->parent; - } - if (ancestorScope) - newFocusScopeItem = ancestorScope; - } - - QGraphicsItem *p = newParent; - while (p) { - if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { - p->d_ptr->focusScopeItem = newFocusScopeItem; - newFocusScopeItem->d_ptr->focusScopeItemChange(true); - // Ensure the new item is no longer the subFocusItem. The - // only way to set focus on a child of a focus scope is - // by setting focus on the scope itself. - if (subFocusItem && !p->focusItem()) - subFocusItem->d_ptr->clearSubFocus(); - break; - } - p = p->d_ptr->parent; - } - } - - // Resolve depth. - invalidateDepthRecursively(); - - if ((parent = newParent)) { - if (parent->d_func()->scene && parent->d_func()->scene != scene) { - // Move this item to its new parent's scene - parent->d_func()->scene->addItem(q); - } else if (!parent->d_func()->scene && scene) { - // Remove this item from its former scene - scene->removeItem(q); - } - - parent->d_ptr->addChild(q); - if (thisPointerVariant) - parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant); - if (scene) { - // Re-enable scene pos notifications for new ancestors - if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) - scene->d_func()->setScenePosItemEnabled(q, true); - } - - // Propagate dirty flags to the new parent - markParentDirty(/*updateBoundingRect=*/true); - - // Inherit ancestor flags from the new parent. - updateAncestorFlags(); - - // Update item visible / enabled. - if (parent->d_ptr->visible != visible) { - if (!parent->d_ptr->visible || !explicitlyHidden) - setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false); - } - if (parent->isEnabled() != enabled) { - if (!parent->d_ptr->enabled || !explicitlyDisabled) - setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false); - } - - // Auto-activate if visible and the parent is active. - if (visible && parent->isActive()) - q->setActive(true); - } else { - // Inherit ancestor flags from the new parent. - updateAncestorFlags(); - - if (!inDestructor) { - // Update item visible / enabled. - if (!visible && !explicitlyHidden) - setVisibleHelper(true, /* explicit = */ false); - if (!enabled && !explicitlyDisabled) - setEnabledHelper(true, /* explicit = */ false); - } - } - - dirtySceneTransform = 1; - if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData))) - transformChanged(); - - // Restore the sub focus chain. - if (subFocusItem) { - subFocusItem->d_ptr->setSubFocus(newParent); - if (parent && parent->isActive()) - subFocusItem->setFocus(); - } - - // Deliver post-change notification - if (newParentVariant) - q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant); - - if (isObject) - emit static_cast<QGraphicsObject *>(q)->parentChanged(); -} - -/*! - \internal - - Returns the bounding rect of this item's children (excluding itself). -*/ -void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem) -{ - Q_Q(QGraphicsItem); - - QRectF childrenRect; - QRectF *result = rect; - rect = &childrenRect; - const bool setTopMostEffectItem = !topMostEffectItem; - - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); - QGraphicsItemPrivate *childd = child->d_ptr.data(); - if (setTopMostEffectItem) - topMostEffectItem = child; - bool hasPos = !childd->pos.isNull(); - if (hasPos || childd->transformData) { - // COMBINE - QTransform matrix = childd->transformToParent(); - if (x) - matrix *= *x; - *rect |= matrix.mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem)); - if (!childd->children.isEmpty()) - childd->childrenBoundingRectHelper(&matrix, rect, topMostEffectItem); - } else { - if (x) - *rect |= x->mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem)); - else - *rect |= child->d_ptr->effectiveBoundingRect(topMostEffectItem); - if (!childd->children.isEmpty()) - childd->childrenBoundingRectHelper(x, rect, topMostEffectItem); - } - } - - if (flags & QGraphicsItem::ItemClipsChildrenToShape){ - if (x) - *rect &= x->mapRect(q->boundingRect()); - else - *rect &= q->boundingRect(); - } - - *result |= *rect; -} - -void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, - const QRegion &exposedRegion, bool allItems) const -{ - Q_ASSERT(option); - Q_Q(const QGraphicsItem); - - // Initialize standard QStyleOption values. - const QRectF brect = q->boundingRect(); - option->state = QStyle::State_None; - option->rect = brect.toRect(); - option->levelOfDetail = 1; - option->exposedRect = brect; - if (selected) - option->state |= QStyle::State_Selected; - if (enabled) - option->state |= QStyle::State_Enabled; - if (q->hasFocus()) - option->state |= QStyle::State_HasFocus; - if (scene) { - if (scene->d_func()->hoverItems.contains(q_ptr)) - option->state |= QStyle::State_MouseOver; - if (q == scene->mouseGrabberItem()) - option->state |= QStyle::State_Sunken; - } - - if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption)) - return; - - // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect). - option->matrix = worldTransform.toAffine(); //### discards perspective - - if (!allItems) { - // Determine the item's exposed area - option->exposedRect = QRectF(); - const QTransform reverseMap = worldTransform.inverted(); - const QVector<QRect> exposedRects(exposedRegion.rects()); - for (int i = 0; i < exposedRects.size(); ++i) { - option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i))); - if (option->exposedRect.contains(brect)) - break; - } - option->exposedRect &= brect; - } -} - -/*! - \internal - - Empty all cached pixmaps from the pixmap cache. -*/ -void QGraphicsItemCache::purge() -{ - QPixmapCache::remove(key); - key = QPixmapCache::Key(); - QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData); - while (it.hasNext()) { - DeviceData &data = it.next().value(); - QPixmapCache::remove(data.key); - data.cacheIndent = QPoint(); - } - deviceData.clear(); - allExposed = true; - exposed.clear(); -} - -/*! - Constructs a QGraphicsItem with the given \a parent item. - It does not modify the parent object returned by QObject::parent(). - - If \a parent is 0, you can add the item to a scene by calling - QGraphicsScene::addItem(). The item will then become a top-level item. - - \sa QGraphicsScene::addItem(), setParentItem() -*/ -QGraphicsItem::QGraphicsItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : d_ptr(new QGraphicsItemPrivate) -{ - d_ptr->q_ptr = this; - setParentItem(parent); - - if (scene && parent && parent->scene() != scene) { - qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is" - " different from parent's scene (%p)", - scene, parent->scene()); - return; - } - if (scene && !parent) - scene->addItem(this); -} - -/*! - \internal -*/ -QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, - QGraphicsScene *scene) - : d_ptr(&dd) -{ - d_ptr->q_ptr = this; - setParentItem(parent); - - if (scene && parent && parent->scene() != scene) { - qWarning("QGraphicsItem::QGraphicsItem: ignoring scene (%p), which is" - " different from parent's scene (%p)", - scene, parent->scene()); - return; - } - if (scene && !parent) - scene->addItem(this); -} - -/*! - Destroys the QGraphicsItem and all its children. If this item is currently - associated with a scene, the item will be removed from the scene before it - is deleted. - - \note It is more efficient to remove the item from the QGraphicsScene before - destroying the item. -*/ -QGraphicsItem::~QGraphicsItem() -{ - if (d_ptr->isObject) { - QGraphicsObject *o = static_cast<QGraphicsObject *>(this); - QObjectPrivate *p = QObjectPrivate::get(o); - p->wasDeleted = true; - if (p->declarativeData) { - QAbstractDeclarativeData::destroyed(p->declarativeData, o); - p->declarativeData = 0; - } - } - - d_ptr->inDestructor = 1; - d_ptr->removeExtraItemCache(); - -#ifndef QT_NO_GESTURES - if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) { - QGraphicsObject *o = static_cast<QGraphicsObject *>(this); - if (QGestureManager *manager = QGestureManager::instance()) { - foreach (Qt::GestureType type, d_ptr->gestureContext.keys()) - manager->cleanupCachedGestures(o, type); - } - } -#endif - - clearFocus(); - - // Update focus scope item ptr. - QGraphicsItem *p = d_ptr->parent; - while (p) { - if (p->flags() & ItemIsFocusScope) { - if (p->d_ptr->focusScopeItem == this) - p->d_ptr->focusScopeItem = 0; - break; - } - p = p->d_ptr->parent; - } - - if (!d_ptr->children.isEmpty()) { - while (!d_ptr->children.isEmpty()) - delete d_ptr->children.first(); - Q_ASSERT(d_ptr->children.isEmpty()); - } - - if (d_ptr->scene) { - d_ptr->scene->d_func()->removeItemHelper(this); - } else { - d_ptr->resetFocusProxy(); - setParentItem(0); - } - -#ifndef QT_NO_GRAPHICSEFFECT - delete d_ptr->graphicsEffect; -#endif //QT_NO_GRAPHICSEFFECT - if (d_ptr->transformData) { - for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) { - QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i); - static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0; - delete t; - } - } - delete d_ptr->transformData; - - if (QGraphicsItemCustomDataStore *dataStore = qt_dataStore()) - dataStore->data.remove(this); -} - -/*! - Returns the current scene for the item, or 0 if the item is not stored in - a scene. - - To add or move an item to a scene, call QGraphicsScene::addItem(). -*/ -QGraphicsScene *QGraphicsItem::scene() const -{ - return d_ptr->scene; -} - -/*! - Returns a pointer to this item's item group, or 0 if this item is not - member of a group. - - \sa QGraphicsItemGroup, QGraphicsScene::createItemGroup() -*/ -QGraphicsItemGroup *QGraphicsItem::group() const -{ - if (!d_ptr->isMemberOfGroup) - return 0; - QGraphicsItem *parent = const_cast<QGraphicsItem *>(this); - while ((parent = parent->d_ptr->parent)) { - if (QGraphicsItemGroup *group = qgraphicsitem_cast<QGraphicsItemGroup *>(parent)) - return group; - } - // Unreachable; if d_ptr->isMemberOfGroup is != 0, then one parent of this - // item is a group item. - return 0; -} - -/*! - Adds this item to the item group \a group. If \a group is 0, this item is - removed from any current group and added as a child of the previous - group's parent. - - \sa group(), QGraphicsScene::createItemGroup() -*/ -void QGraphicsItem::setGroup(QGraphicsItemGroup *group) -{ - if (!group) { - if (QGraphicsItemGroup *group = this->group()) - group->removeFromGroup(this); - } else { - group->addToGroup(this); - } -} - -/*! - Returns a pointer to this item's parent item. If this item does not have a - parent, 0 is returned. - - \sa setParentItem(), childItems() -*/ -QGraphicsItem *QGraphicsItem::parentItem() const -{ - return d_ptr->parent; -} - -/*! - Returns this item's top-level item. The top-level item is the item's - topmost ancestor item whose parent is 0. If an item has no parent, its own - pointer is returned (i.e., a top-level item is its own top-level item). - - \sa parentItem() -*/ -QGraphicsItem *QGraphicsItem::topLevelItem() const -{ - QGraphicsItem *parent = const_cast<QGraphicsItem *>(this); - while (QGraphicsItem *grandPa = parent->parentItem()) - parent = grandPa; - return parent; -} - -/*! - \since 4.6 - - Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item - is not a QGraphicsObject. - - \sa parentItem(), childItems() -*/ -QGraphicsObject *QGraphicsItem::parentObject() const -{ - QGraphicsItem *p = d_ptr->parent; - return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0; -} - -/*! - \since 4.4 - - Returns a pointer to the item's parent widget. The item's parent widget is - the closest parent item that is a widget. - - \sa parentItem(), childItems() -*/ -QGraphicsWidget *QGraphicsItem::parentWidget() const -{ - QGraphicsItem *p = parentItem(); - while (p && !p->isWidget()) - p = p->parentItem(); - return (p && p->isWidget()) ? static_cast<QGraphicsWidget *>(p) : 0; -} - -/*! - \since 4.4 - - Returns a pointer to the item's top level widget (i.e., the item's - ancestor whose parent is 0, or whose parent is not a widget), or 0 if this - item does not have a top level widget. If the item is its own top level - widget, this function returns a pointer to the item itself. -*/ -QGraphicsWidget *QGraphicsItem::topLevelWidget() const -{ - if (const QGraphicsWidget *p = parentWidget()) - return p->topLevelWidget(); - return isWidget() ? static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this)) : 0; -} - -/*! - \since 4.4 - - Returns the item's window, or 0 if this item does not have a window. If - the item is a window, it will return itself. Otherwise it will return the - closest ancestor that is a window. - - \sa QGraphicsWidget::isWindow() -*/ -QGraphicsWidget *QGraphicsItem::window() const -{ - QGraphicsItem *p = panel(); - if (p && p->isWindow()) - return static_cast<QGraphicsWidget *>(p); - return 0; -} - -/*! - \since 4.6 - - Returns the item's panel, or 0 if this item does not have a panel. If the - item is a panel, it will return itself. Otherwise it will return the - closest ancestor that is a panel. - - \sa isPanel(), ItemIsPanel -*/ -QGraphicsItem *QGraphicsItem::panel() const -{ - if (d_ptr->flags & ItemIsPanel) - return const_cast<QGraphicsItem *>(this); - return d_ptr->parent ? d_ptr->parent->panel() : 0; -} - -/*! - \since 4.6 - - Return the graphics item cast to a QGraphicsObject, if the class is actually a - graphics object, 0 otherwise. -*/ -QGraphicsObject *QGraphicsItem::toGraphicsObject() -{ - return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0; -} - -/*! - \since 4.6 - - Return the graphics item cast to a QGraphicsObject, if the class is actually a - graphics object, 0 otherwise. -*/ -const QGraphicsObject *QGraphicsItem::toGraphicsObject() const -{ - return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0; -} - -/*! - Sets this item's parent item to \a newParent. If this item already - has a parent, it is first removed from the previous parent. If \a - newParent is 0, this item will become a top-level item. - - Note that this implicitly adds this graphics item to the scene of - the parent. You should not \l{QGraphicsScene::addItem()}{add} the - item to the scene yourself. - - Calling this function on an item that is an ancestor of \a newParent - have undefined behaviour. - - \sa parentItem(), childItems() -*/ -void QGraphicsItem::setParentItem(QGraphicsItem *newParent) -{ - if (newParent == this) { - qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); - return; - } - if (newParent == d_ptr->parent) - return; - - const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange, - QVariant::fromValue<QGraphicsItem *>(newParent))); - newParent = qvariant_cast<QGraphicsItem *>(newParentVariant); - if (newParent == d_ptr->parent) - return; - - const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this)); - d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant); -} - -/*! - \obsolete - - Use childItems() instead. - - \sa setParentItem() -*/ -QList<QGraphicsItem *> QGraphicsItem::children() const -{ - return childItems(); -} - -/*! - \since 4.4 - - Returns a list of this item's children. - - The items are sorted by stacking order. This takes into account both the - items' insertion order and their Z-values. - - \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsItem::childItems() const -{ - const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren(); - return d_ptr->children; -} - -/*! - \since 4.4 - Returns true if this item is a widget (i.e., QGraphicsWidget); otherwise, - returns false. -*/ -bool QGraphicsItem::isWidget() const -{ - return d_ptr->isWidget; -} - -/*! - \since 4.4 - Returns true if the item is a QGraphicsWidget window, otherwise returns - false. - - \sa QGraphicsWidget::windowFlags() -*/ -bool QGraphicsItem::isWindow() const -{ - return d_ptr->isWidget && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window); -} - -/*! - \since 4.6 - Returns true if the item is a panel; otherwise returns false. - - \sa QGraphicsItem::panel(), ItemIsPanel -*/ -bool QGraphicsItem::isPanel() const -{ - return d_ptr->flags & ItemIsPanel; -} - -/*! - Returns this item's flags. The flags describe what configurable features - of the item are enabled and not. For example, if the flags include - ItemIsFocusable, the item can accept input focus. - - By default, no flags are enabled. - - \sa setFlags(), setFlag() -*/ -QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const -{ - return GraphicsItemFlags(d_ptr->flags); -} - -/*! - If \a enabled is true, the item flag \a flag is enabled; otherwise, it is - disabled. - - \sa flags(), setFlags() -*/ -void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled) -{ - if (enabled) - setFlags(GraphicsItemFlags(d_ptr->flags) | flag); - else - setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag); -} - -/*! - \internal - - Sets the flag \a flag on \a item and all its children, to \a enabled. -*/ -static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::GraphicsItemFlag flag, - bool enabled) -{ - if (item->flags() & flag) { - // If this item already has the correct flag set, we don't have to - // propagate it. - return; - } - item->setFlag(flag, enabled); - foreach (QGraphicsItem *child, item->children()) - _q_qgraphicsItemSetFlag(child, flag, enabled); -} - -/*! - Sets the item flags to \a flags. All flags in \a flags are enabled; all - flags not in \a flags are disabled. - - If the item had focus and \a flags does not enable ItemIsFocusable, the - item loses focus as a result of calling this function. Similarly, if the - item was selected, and \a flags does not enabled ItemIsSelectable, the - item is automatically unselected. - - By default, no flags are enabled. (QGraphicsWidget enables the - ItemSendsGeometryChanges flag by default in order to track position - changes.) - - \sa flags(), setFlag() -*/ -void QGraphicsItem::setFlags(GraphicsItemFlags flags) -{ - // Notify change and check for adjustment. - if (quint32(d_ptr->flags) == quint32(flags)) - return; - flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); - if (quint32(d_ptr->flags) == quint32(flags)) - return; - if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) - d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags); - - // Flags that alter the geometry of the item (or its children). - const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable); - bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); - if (fullUpdate) - d_ptr->updatePaintedViewBoundingRects(/*children=*/true); - - // Keep the old flags to compare the diff. - GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags); - - // Update flags. - d_ptr->flags = flags; - - if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) { - // Clear focus on the item if it has focus when the focusable flag - // is unset. - clearFocus(); - } - - if (!(d_ptr->flags & ItemIsSelectable) && isSelected()) { - // Unselect the item if it is selected when the selectable flag is - // unset. - setSelected(false); - } - - if ((flags & ItemClipsChildrenToShape) != (oldFlags & ItemClipsChildrenToShape)) { - // Item children clipping changes. Propagate the ancestor flag to - // all children. - d_ptr->updateAncestorFlag(ItemClipsChildrenToShape); - // The childrenBoundingRect is clipped to the boundingRect in case of ItemClipsChildrenToShape, - // which means we have to invalidate the cached childrenBoundingRect whenever this flag changes. - d_ptr->dirtyChildrenBoundingRect = 1; - d_ptr->markParentDirty(true); - } - - if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) { - // Item children clipping changes. Propagate the ancestor flag to - // all children. - d_ptr->updateAncestorFlag(ItemIgnoresTransformations); - } - - if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { - // NB! We change the flags directly here, so we must also update d_ptr->flags. - // Note that this has do be done before the ItemStacksBehindParent check - // below; otherwise we will loose the change. - - // Update stack-behind. - if (d_ptr->z < qreal(0.0)) - flags |= ItemStacksBehindParent; - else - flags &= ~ItemStacksBehindParent; - d_ptr->flags = flags; - } - - if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) { - // NB! This check has to come after the ItemNegativeZStacksBehindParent - // check above. Be careful. - - // Ensure child item sorting is up to date when toggling this flag. - if (d_ptr->parent) - d_ptr->parent->d_ptr->needSortChildren = 1; - else if (d_ptr->scene) - d_ptr->scene->d_func()->needSortTopLevelItems = 1; - } - - if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) { - // Update input method sensitivity in any views. - if (d_ptr->scene) - d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); - } - - - if ((d_ptr->panelModality != NonModal) - && d_ptr->scene - && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) { - // update the panel's modal state - if (flags & ItemIsPanel) - d_ptr->scene->d_func()->enterModal(this); - else - d_ptr->scene->d_func()->leaveModal(this); - } - - if (d_ptr->scene) { - if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) { - if (flags & ItemSendsScenePositionChanges) - d_ptr->scene->d_func()->registerScenePosItem(this); - else - d_ptr->scene->d_func()->unregisterScenePosItem(this); - } - d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); - } - - // Notify change. - itemChange(ItemFlagsHaveChanged, quint32(flags)); -} - -/*! - \since 4.4 - Returns the cache mode for this item. The default mode is NoCache (i.e., - cache is disabled and all painting is immediate). - - \sa setCacheMode() -*/ -QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const -{ - return QGraphicsItem::CacheMode(d_ptr->cacheMode); -} - -/*! - \since 4.4 - Sets the item's cache mode to \a mode. - - The optional \a logicalCacheSize argument is used only by - ItemCoordinateCache mode, and describes the resolution of the cache - buffer; if \a logicalCacheSize is (100, 100), QGraphicsItem will fit the - item into 100x100 pixels in graphics memory, regardless of the logical - size of the item itself. By default QGraphicsItem uses the size of - boundingRect(). For all other cache modes than ItemCoordinateCache, \a - logicalCacheSize is ignored. - - Caching can speed up rendering if your item spends a significant time - redrawing itself. In some cases the cache can also slow down rendering, in - particular when the item spends less time redrawing than QGraphicsItem - spends redrawing from the cache. When enabled, the item's paint() function - will be called only once for each call to update(); for any subsequent - repaint requests, the Graphics View framework will redraw from the - cache. This approach works particularly well with QGLWidget, which stores - all the cache as OpenGL textures. - - Be aware that QPixmapCache's cache limit may need to be changed to obtain - optimal performance. - - You can read more about the different cache modes in the CacheMode - documentation. - - \sa CacheMode, QPixmapCache::setCacheLimit() -*/ -void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize) -{ - CacheMode lastMode = CacheMode(d_ptr->cacheMode); - d_ptr->cacheMode = mode; - bool noVisualChange = (mode == NoCache && lastMode == NoCache) - || (mode == NoCache && lastMode == DeviceCoordinateCache) - || (mode == DeviceCoordinateCache && lastMode == NoCache) - || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache); - if (mode == NoCache) { - d_ptr->removeExtraItemCache(); - } else { - QGraphicsItemCache *cache = d_ptr->extraItemCache(); - - // Reset old cache - cache->purge(); - - if (mode == ItemCoordinateCache) { - if (lastMode == mode && cache->fixedSize == logicalCacheSize) - noVisualChange = true; - cache->fixedSize = logicalCacheSize; - } - } - if (!noVisualChange) - update(); -} - -/*! - \since 4.6 - - Returns the modality for this item. -*/ -QGraphicsItem::PanelModality QGraphicsItem::panelModality() const -{ - return d_ptr->panelModality; -} - -/*! - \since 4.6 - - Sets the modality for this item to \a panelModality. - - Changing the modality of a visible item takes effect immediately. -*/ -void QGraphicsItem::setPanelModality(PanelModality panelModality) -{ - if (d_ptr->panelModality == panelModality) - return; - - PanelModality previousModality = d_ptr->panelModality; - bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible()); - if (enterLeaveModal && panelModality == NonModal) - d_ptr->scene->d_func()->leaveModal(this); - d_ptr->panelModality = panelModality; - if (enterLeaveModal && d_ptr->panelModality != NonModal) - d_ptr->scene->d_func()->enterModal(this, previousModality); -} - -/*! - \since 4.6 - - Returns true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is - non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this - item is not blocked, \a blockingPanel will not be set by this function. - - This function always returns false for items not in a scene. - - \sa panelModality() setPanelModality() PanelModality -*/ -bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const -{ - if (!d_ptr->scene) - return false; - - - QGraphicsItem *dummy = 0; - if (!blockingPanel) - blockingPanel = &dummy; - - QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func(); - if (scene_d->modalPanels.isEmpty()) - return false; - - // ### - if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this) - return false; - - for (int i = 0; i < scene_d->modalPanels.count(); ++i) { - QGraphicsItem *modalPanel = scene_d->modalPanels.at(i); - if (modalPanel->panelModality() == QGraphicsItem::SceneModal) { - // Scene modal panels block all non-descendents. - if (modalPanel != this && !modalPanel->isAncestorOf(this)) { - *blockingPanel = modalPanel; - return true; - } - } else { - // Window modal panels block ancestors and siblings/cousins. - if (modalPanel != this - && !modalPanel->isAncestorOf(this) - && commonAncestorItem(modalPanel)) { - *blockingPanel = modalPanel; - return true; - } - } - } - return false; -} - -#ifndef QT_NO_TOOLTIP -/*! - Returns the item's tool tip, or an empty QString if no tool tip has been - set. - - \sa setToolTip(), QToolTip -*/ -QString QGraphicsItem::toolTip() const -{ - return d_ptr->extra(QGraphicsItemPrivate::ExtraToolTip).toString(); -} - -/*! - Sets the item's tool tip to \a toolTip. If \a toolTip is empty, the item's - tool tip is cleared. - - \sa toolTip(), QToolTip -*/ -void QGraphicsItem::setToolTip(const QString &toolTip) -{ - const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip)); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString()); - itemChange(ItemToolTipHasChanged, toolTipVariant); -} -#endif // QT_NO_TOOLTIP - -#ifndef QT_NO_CURSOR -/*! - Returns the current cursor shape for the item. The mouse cursor - will assume this shape when it's over this item. See the \link - Qt::CursorShape list of predefined cursor objects\endlink for a - range of useful shapes. - - An editor item might want to use an I-beam cursor: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 2 - - If no cursor has been set, the cursor of the item beneath is used. - - \sa setCursor(), hasCursor(), unsetCursor(), QWidget::cursor, - QApplication::overrideCursor() -*/ -QCursor QGraphicsItem::cursor() const -{ - return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); -} - -/*! - Sets the current cursor shape for the item to \a cursor. The mouse cursor - will assume this shape when it's over this item. See the \link - Qt::CursorShape list of predefined cursor objects\endlink for a range of - useful shapes. - - An editor item might want to use an I-beam cursor: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 3 - - If no cursor has been set, the cursor of the item beneath is used. - - \sa cursor(), hasCursor(), unsetCursor(), QWidget::cursor, - QApplication::overrideCursor() -*/ -void QGraphicsItem::setCursor(const QCursor &cursor) -{ - const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant)); - d_ptr->hasCursor = 1; - if (d_ptr->scene) { - d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; - foreach (QGraphicsView *view, d_ptr->scene->views()) { - view->viewport()->setMouseTracking(true); - // Note: Some of this logic is duplicated in QGraphicsView's mouse events. - if (view->underMouse()) { - foreach (QGraphicsItem *itemUnderCursor, view->items(view->mapFromGlobal(QCursor::pos()))) { - if (itemUnderCursor->hasCursor()) { - QMetaObject::invokeMethod(view, "_q_setViewportCursor", - Q_ARG(QCursor, itemUnderCursor->cursor())); - break; - } - } - break; - } - } - } - itemChange(ItemCursorHasChanged, cursorVariant); -} - -/*! - Returns true if this item has a cursor set; otherwise, false is returned. - - By default, items don't have any cursor set. cursor() will return a - standard pointing arrow cursor. - - \sa unsetCursor() -*/ -bool QGraphicsItem::hasCursor() const -{ - return d_ptr->hasCursor; -} - -/*! - Clears the cursor from this item. - - \sa hasCursor(), setCursor() -*/ -void QGraphicsItem::unsetCursor() -{ - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraCursor); - d_ptr->hasCursor = 0; - if (d_ptr->scene) { - foreach (QGraphicsView *view, d_ptr->scene->views()) { - if (view->underMouse() && view->itemAt(view->mapFromGlobal(QCursor::pos())) == this) { - QMetaObject::invokeMethod(view, "_q_unsetViewportCursor"); - break; - } - } - } -} - -#endif // QT_NO_CURSOR - -/*! - Returns true if the item is visible; otherwise, false is returned. - - Note that the item's general visibility is unrelated to whether or not it - is actually being visualized by a QGraphicsView. - - \sa setVisible() -*/ -bool QGraphicsItem::isVisible() const -{ - return d_ptr->visible; -} - -/*! - \since 4.4 - Returns true if the item is visible to \a parent; otherwise, false is - returned. \a parent can be 0, in which case this function will return - whether the item is visible to the scene or not. - - An item may not be visible to its ancestors even if isVisible() is true. If - any ancestor is hidden, the item itself will be implicitly hidden, in which - case this function will return false. - - \sa isVisible(), setVisible() -*/ -bool QGraphicsItem::isVisibleTo(const QGraphicsItem *parent) const -{ - if (!d_ptr->visible) - return false; - if (parent == this) - return true; - if (parentItem() && parentItem()->isVisibleTo(parent)) - return true; - if (!parent && !parentItem()) - return true; - return false; -} - -/*! - \internal - - Sets this item's visibility to \a newVisible. If \a explicitly is true, - this item will be "explicitly" \a newVisible; otherwise, it.. will not be. -*/ -void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bool update) -{ - Q_Q(QGraphicsItem); - - // Update explicit bit. - if (explicitly) - explicitlyHidden = newVisible ? 0 : 1; - - // Check if there's nothing to do. - if (visible == quint32(newVisible)) - return; - - // Don't show child if parent is not visible - if (parent && newVisible && !parent->d_ptr->visible) - return; - - // Modify the property. - const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, - quint32(newVisible))); - newVisible = newVisibleVariant.toBool(); - if (visible == quint32(newVisible)) - return; - visible = newVisible; - - // Schedule redrawing - if (update) { - QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); - if (c) - c->purge(); - if (scene) { -#ifndef QT_NO_GRAPHICSEFFECT - invalidateParentGraphicsEffectsRecursively(); -#endif //QT_NO_GRAPHICSEFFECT - scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true); - } - } - - // Certain properties are dropped as an item becomes invisible. - bool hasFocus = q_ptr->hasFocus(); - if (!newVisible) { - if (scene) { - if (scene->d_func()->mouseGrabberItems.contains(q)) - q->ungrabMouse(); - if (scene->d_func()->keyboardGrabberItems.contains(q)) - q->ungrabKeyboard(); - if (q->isPanel() && panelModality != QGraphicsItem::NonModal) - scene->d_func()->leaveModal(q_ptr); - } - if (hasFocus && scene) { - // Hiding the closest non-panel ancestor of the focus item - QGraphicsItem *focusItem = scene->focusItem(); - bool clear = true; - if (isWidget && !focusItem->isPanel()) { - do { - if (focusItem == q_ptr) { - clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true); - break; - } - } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel()); - } - if (clear) - clearFocusHelper(/* giveFocusToParent = */ false); - } - if (q_ptr->isSelected()) - q_ptr->setSelected(false); - } else { - geometryChanged = 1; - paintedViewBoundingRectsNeedRepaint = 1; - if (scene) { - if (isWidget) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); - if (widget->windowType() == Qt::Popup) - scene->d_func()->addPopup(widget); - } - if (q->isPanel() && panelModality != QGraphicsItem::NonModal) { - scene->d_func()->enterModal(q_ptr); - } - } - } - - // Update children with explicitly = false. - const bool updateChildren = update && !(flags & QGraphicsItem::ItemClipsChildrenToShape); - foreach (QGraphicsItem *child, children) { - if (!newVisible || !child->d_ptr->explicitlyHidden) - child->d_ptr->setVisibleHelper(newVisible, false, updateChildren); - } - - // Update activation - if (scene && q->isPanel()) { - if (newVisible) { - if (parent && parent->isActive()) - q->setActive(true); - } else { - if (q->isActive()) - scene->setActivePanel(parent); - } - } - - // Enable subfocus - if (scene) { - if (newVisible) { - // Item is shown - QGraphicsItem *p = parent; - bool done = false; - while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - QGraphicsItem *fsi = p->d_ptr->focusScopeItem; - if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) { - done = true; - while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible()) - fsi = fsi->d_ptr->focusScopeItem; - fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true, - /* focusFromHide = */ false); - } - break; - } - p = p->d_ptr->parent; - } - if (!done) { - QGraphicsItem *fi = subFocusItem; - if (fi && fi != scene->focusItem()) { - scene->setFocusItem(fi); - } else if (flags & QGraphicsItem::ItemIsFocusScope && - !scene->focusItem() && - q->isAncestorOf(scene->d_func()->lastFocusItem)) { - q_ptr->setFocus(); - } - } - } else { - // Item is hidden - if (hasFocus) { - QGraphicsItem *p = parent; - while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - if (p->d_ptr->visible) { - p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true, - /* focusFromHide = */ true); - } - break; - } - p = p->d_ptr->parent; - } - } - } - } - - // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant); - - if (isObject) - emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged(); -} - -/*! - If \a visible is true, the item is made visible. Otherwise, the item is - made invisible. Invisible items are not painted, nor do they receive any - events. In particular, mouse events pass right through invisible items, - and are delivered to any item that may be behind. Invisible items are also - unselectable, they cannot take input focus, and are not detected by - QGraphicsScene's item location functions. - - If an item becomes invisible while grabbing the mouse, (i.e., while it is - receiving mouse events,) it will automatically lose the mouse grab, and - the grab is not regained by making the item visible again; it must receive - a new mouse press to regain the mouse grab. - - Similarly, an invisible item cannot have focus, so if the item has focus - when it becomes invisible, it will lose focus, and the focus is not - regained by simply making the item visible again. - - If you hide a parent item, all its children will also be hidden. If you - show a parent item, all children will be shown, unless they have been - explicitly hidden (i.e., if you call setVisible(false) on a child, it will - not be reshown even if its parent is hidden, and then shown again). - - Items are visible by default; it is unnecessary to call - setVisible() on a new item. - - \sa isVisible(), show(), hide() -*/ -void QGraphicsItem::setVisible(bool visible) -{ - d_ptr->setVisibleHelper(visible, /* explicit = */ true); -} - -/*! - \fn void QGraphicsItem::hide() - - Hides the item. (Items are visible by default.) - - This convenience function is equivalent to calling \c setVisible(false). - - \sa show(), setVisible() -*/ - -/*! - \fn void QGraphicsItem::show() - - Shows the item. (Items are visible by default.) - - This convenience function is equivalent to calling \c setVisible(true). - - \sa hide(), setVisible() -*/ - -/*! - Returns true if the item is enabled; otherwise, false is returned. - - \sa setEnabled() -*/ -bool QGraphicsItem::isEnabled() const -{ - return d_ptr->enabled; -} - -/*! - \internal - - Sets this item's visibility to \a newEnabled. If \a explicitly is true, - this item will be "explicitly" \a newEnabled; otherwise, it.. will not be. -*/ -void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bool update) -{ - // Update explicit bit. - if (explicitly) - explicitlyDisabled = newEnabled ? 0 : 1; - - // Check if there's nothing to do. - if (enabled == quint32(newEnabled)) - return; - - // Certain properties are dropped when an item is disabled. - if (!newEnabled) { - if (scene && scene->mouseGrabberItem() == q_ptr) - q_ptr->ungrabMouse(); - if (q_ptr->hasFocus()) { - // Disabling the closest non-panel ancestor of the focus item - // causes focus to pop to the next item, otherwise it's cleared. - QGraphicsItem *focusItem = scene->focusItem(); - bool clear = true; - if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) { - do { - if (focusItem == q_ptr) { - clear = !static_cast<QGraphicsWidget *>(q_ptr)->focusNextPrevChild(true); - break; - } - } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel()); - } - if (clear) - q_ptr->clearFocus(); - } - if (q_ptr->isSelected()) - q_ptr->setSelected(false); - } - - // Modify the property. - const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, - quint32(newEnabled))); - enabled = newEnabledVariant.toBool(); - - // Schedule redraw. - if (update) - q_ptr->update(); - - foreach (QGraphicsItem *child, children) { - if (!newEnabled || !child->d_ptr->explicitlyDisabled) - child->d_ptr->setEnabledHelper(newEnabled, /* explicitly = */ false); - } - - // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); - - if (isObject) - emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged(); -} - -/*! - If \a enabled is true, the item is enabled; otherwise, it is disabled. - - Disabled items are visible, but they do not receive any events, and cannot - take focus nor be selected. Mouse events are discarded; they are not - propagated unless the item is also invisible, or if it does not accept - mouse events (see acceptedMouseButtons()). A disabled item cannot become the - mouse grabber, and as a result of this, an item loses the grab if it - becomes disabled when grabbing the mouse, just like it loses focus if it - had focus when it was disabled. - - Disabled items are traditionally drawn using grayed-out colors (see \l - QPalette::Disabled). - - If you disable a parent item, all its children will also be disabled. If - you enable a parent item, all children will be enabled, unless they have - been explicitly disabled (i.e., if you call setEnabled(false) on a child, - it will not be reenabled if its parent is disabled, and then enabled - again). - - Items are enabled by default. - - \note If you install an event filter, you can still intercept events - before they are delivered to items; this mechanism disregards the item's - enabled state. - - \sa isEnabled() -*/ -void QGraphicsItem::setEnabled(bool enabled) -{ - d_ptr->setEnabledHelper(enabled, /* explicitly = */ true); -} - -/*! - Returns true if this item is selected; otherwise, false is returned. - - Items that are in a group inherit the group's selected state. - - Items are not selected by default. - - \sa setSelected(), QGraphicsScene::setSelectionArea() -*/ -bool QGraphicsItem::isSelected() const -{ - if (QGraphicsItemGroup *group = this->group()) - return group->isSelected(); - return d_ptr->selected; -} - -/*! - If \a selected is true and this item is selectable, this item is selected; - otherwise, it is unselected. - - If the item is in a group, the whole group's selected state is toggled by - this function. If the group is selected, all items in the group are also - selected, and if the group is not selected, no item in the group is - selected. - - Only visible, enabled, selectable items can be selected. If \a selected - is true and this item is either invisible or disabled or unselectable, - this function does nothing. - - By default, items cannot be selected. To enable selection, set the - ItemIsSelectable flag. - - This function is provided for convenience, allowing individual toggling of - the selected state of an item. However, a more common way of selecting - items is to call QGraphicsScene::setSelectionArea(), which will call this - function for all visible, enabled, and selectable items within a specified - area on the scene. - - \sa isSelected(), QGraphicsScene::selectedItems() -*/ -void QGraphicsItem::setSelected(bool selected) -{ - if (QGraphicsItemGroup *group = this->group()) { - group->setSelected(selected); - return; - } - - if (!(d_ptr->flags & ItemIsSelectable) || !d_ptr->enabled || !d_ptr->visible) - selected = false; - if (d_ptr->selected == selected) - return; - const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected))); - bool newSelected = newSelectedVariant.toBool(); - if (d_ptr->selected == newSelected) - return; - d_ptr->selected = newSelected; - - update(); - if (d_ptr->scene) { - QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func(); - if (selected) { - sceneD->selectedItems << this; - } else { - // QGraphicsScene::selectedItems() lazily pulls out all items that are - // no longer selected. - } - if (!sceneD->selectionChanging) - emit d_ptr->scene->selectionChanged(); - } - - // Deliver post-change notification. - itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant); -} - -/*! - \since 4.5 - - Returns this item's local opacity, which is between 0.0 (transparent) and - 1.0 (opaque). This value is combined with parent and ancestor values into - the effectiveOpacity(). The effective opacity decides how the item is - rendered. - - The opacity property decides the state of the painter passed to the - paint() function. If the item is cached, i.e., ItemCoordinateCache or - DeviceCoordinateCache, the effective property will be applied to the item's - cache as it is rendered. - - The default opacity is 1.0; fully opaque. - - \sa setOpacity(), paint(), ItemIgnoresParentOpacity, - ItemDoesntPropagateOpacityToChildren -*/ -qreal QGraphicsItem::opacity() const -{ - return d_ptr->opacity; -} - -/*! - \since 4.5 - - Returns this item's \e effective opacity, which is between 0.0 - (transparent) and 1.0 (opaque). This value is a combination of this item's - local opacity, and its parent and ancestors' opacities. The effective - opacity decides how the item is rendered. - - \sa opacity(), setOpacity(), paint(), ItemIgnoresParentOpacity, - ItemDoesntPropagateOpacityToChildren -*/ -qreal QGraphicsItem::effectiveOpacity() const -{ - return d_ptr->effectiveOpacity(); -} - -/*! - \since 4.5 - - Sets this item's local \a opacity, between 0.0 (transparent) and 1.0 - (opaque). The item's local opacity is combined with parent and ancestor - opacities into the effectiveOpacity(). - - By default, opacity propagates from parent to child, so if a parent's - opacity is 0.5 and the child is also 0.5, the child's effective opacity - will be 0.25. - - The opacity property decides the state of the painter passed to the - paint() function. If the item is cached, i.e., ItemCoordinateCache or - DeviceCoordinateCache, the effective property will be applied to the - item's cache as it is rendered. - - There are two item flags that affect how the item's opacity is combined - with the parent: ItemIgnoresParentOpacity and - ItemDoesntPropagateOpacityToChildren. - - \sa opacity(), effectiveOpacity() -*/ -void QGraphicsItem::setOpacity(qreal opacity) -{ - // Notify change. - const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity)); - - // Normalized opacity - qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1)); - - // No change? Done. - if (newOpacity == d_ptr->opacity) - return; - - bool wasFullyTransparent = d_ptr->isOpacityNull(); - d_ptr->opacity = newOpacity; - - // Notify change. - itemChange(ItemOpacityHasChanged, newOpacityVariant); - - // Update. - if (d_ptr->scene) { -#ifndef QT_NO_GRAPHICSEFFECT - d_ptr->invalidateParentGraphicsEffectsRecursively(); - if (!(d_ptr->flags & ItemDoesntPropagateOpacityToChildren)) - d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged); -#endif //QT_NO_GRAPHICSEFFECT - d_ptr->scene->d_func()->markDirty(this, QRectF(), - /*invalidateChildren=*/true, - /*force=*/false, - /*ignoreOpacity=*/d_ptr->isOpacityNull()); - if (wasFullyTransparent) - d_ptr->paintedViewBoundingRectsNeedRepaint = 1; - } - - if (d_ptr->isObject) - emit static_cast<QGraphicsObject *>(this)->opacityChanged(); -} - -/*! - Returns a pointer to this item's effect if it has one; otherwise 0. - - \since 4.6 -*/ -#ifndef QT_NO_GRAPHICSEFFECT -QGraphicsEffect *QGraphicsItem::graphicsEffect() const -{ - return d_ptr->graphicsEffect; -} - -/*! - Sets \a effect as the item's effect. If there already is an effect installed - on this item, QGraphicsItem will delete the existing effect before installing - the new \a effect. - - If \a effect is the installed on a different item, setGraphicsEffect() will remove - the effect from the item and install it on this item. - - QGraphicsItem takes ownership of \a effect. - - \note This function will apply the effect on itself and all its children. - - \since 4.6 -*/ -void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) -{ - if (d_ptr->graphicsEffect == effect) - return; - - if (d_ptr->graphicsEffect) { - delete d_ptr->graphicsEffect; - d_ptr->graphicsEffect = 0; - } else if (d_ptr->parent) { - d_ptr->parent->d_ptr->updateChildWithGraphicsEffectFlagRecursively(); - } - - if (effect) { - // Set new effect. - QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this); - QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced); - d_ptr->graphicsEffect = effect; - effect->d_func()->setGraphicsEffectSource(source); - prepareGeometryChange(); - } -} -#endif //QT_NO_GRAPHICSEFFECT - -void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively() -{ -#ifndef QT_NO_GRAPHICSEFFECT - QGraphicsItemPrivate *itemPrivate = this; - do { - // parent chain already notified? - if (itemPrivate->mayHaveChildWithGraphicsEffect) - return; - itemPrivate->mayHaveChildWithGraphicsEffect = 1; - } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); -#endif -} - -/*! - \internal - \since 4.6 - Returns the effective bounding rect of the given item space rect. - If the item has no effect, the rect is returned unmodified. - If the item has an effect, the effective rect can be extend beyond the - item's bounding rect, depending on the effect. - - \sa boundingRect() -*/ -QRectF QGraphicsItemPrivate::effectiveBoundingRect(const QRectF &rect) const -{ -#ifndef QT_NO_GRAPHICSEFFECT - Q_Q(const QGraphicsItem); - QGraphicsEffect *effect = graphicsEffect; - if (scene && effect && effect->isEnabled()) { - if (scene->d_func()->views.isEmpty()) - return effect->boundingRectFor(rect); - QRectF sceneRect = q->mapRectToScene(rect); - QRectF sceneEffectRect; - foreach (QGraphicsView *view, scene->views()) { - QRectF deviceRect = view->d_func()->mapRectFromScene(sceneRect); - QRect deviceEffectRect = effect->boundingRectFor(deviceRect).toAlignedRect(); - sceneEffectRect |= view->d_func()->mapRectToScene(deviceEffectRect); - } - return q->mapRectFromScene(sceneEffectRect); - } -#endif //QT_NO_GRAPHICSEFFECT - return rect; -} - -/*! - \internal - \since 4.6 - Returns the effective bounding rect of the item. - If the item has no effect, this is the same as the item's bounding rect. - If the item has an effect, the effective rect can be larger than the item's - bouding rect, depending on the effect. - - \sa boundingRect() -*/ -QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectItem) const -{ -#ifndef QT_NO_GRAPHICSEFFECT - Q_Q(const QGraphicsItem); - QRectF brect = effectiveBoundingRect(q_ptr->boundingRect()); - if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q) - return brect; - - const QGraphicsItem *effectParent = parent; - while (effectParent) { - QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect; - if (scene && effect && effect->isEnabled()) { - const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect); - const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace); - brect = effectParent->mapRectToItem(q, effectRectInParentSpace); - } - if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren - || topMostEffectItem == effectParent) { - return brect; - } - effectParent = effectParent->d_ptr->parent; - } - - return brect; -#else //QT_NO_GRAPHICSEFFECT - return q_ptr->boundingRect(); -#endif //QT_NO_GRAPHICSEFFECT - -} - -/*! - \internal - \since 4.6 - Returns the effective bounding rect of this item in scene coordinates, - by combining sceneTransform() with boundingRect(), taking into account - the effect that the item might have. - - If the item has no effect, this is the same as sceneBoundingRect(). - - \sa effectiveBoundingRect(), sceneBoundingRect() -*/ -QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const -{ - // Find translate-only offset - // COMBINE - QPointF offset; - const QGraphicsItem *parentItem = q_ptr; - const QGraphicsItemPrivate *itemd; - do { - itemd = parentItem->d_ptr.data(); - if (itemd->transformData) - break; - offset += itemd->pos; - } while ((parentItem = itemd->parent)); - - QRectF br = effectiveBoundingRect(); - br.translate(offset); - return !parentItem ? br : parentItem->sceneTransform().mapRect(br); -} - -/*! - Returns true if this item can accept drag and drop events; otherwise, - returns false. By default, items do not accept drag and drop events; items - are transparent to drag and drop. - - \sa setAcceptDrops() -*/ -bool QGraphicsItem::acceptDrops() const -{ - return d_ptr->acceptDrops; -} - -/*! - If \a on is true, this item will accept drag and drop events; otherwise, - it is transparent for drag and drop events. By default, items do not - accept drag and drop events. - - \sa acceptDrops() -*/ -void QGraphicsItem::setAcceptDrops(bool on) -{ - d_ptr->acceptDrops = on; -} - -/*! - Returns the mouse buttons that this item accepts mouse events for. By - default, all mouse buttons are accepted. - - If an item accepts a mouse button, it will become the mouse - grabber item when a mouse press event is delivered for that mouse - button. However, if the item does not accept the button, - QGraphicsScene will forward the mouse events to the first item - beneath it that does. - - \sa setAcceptedMouseButtons(), mousePressEvent() -*/ -Qt::MouseButtons QGraphicsItem::acceptedMouseButtons() const -{ - return Qt::MouseButtons(d_ptr->acceptedMouseButtons); -} - -/*! - Sets the mouse \a buttons that this item accepts mouse events for. - - By default, all mouse buttons are accepted. If an item accepts a - mouse button, it will become the mouse grabber item when a mouse - press event is delivered for that button. However, if the item - does not accept the mouse button, QGraphicsScene will forward the - mouse events to the first item beneath it that does. - - To disable mouse events for an item (i.e., make it transparent for mouse - events), call setAcceptedMouseButtons(0). - - \sa acceptedMouseButtons(), mousePressEvent() -*/ -void QGraphicsItem::setAcceptedMouseButtons(Qt::MouseButtons buttons) -{ - if (Qt::MouseButtons(d_ptr->acceptedMouseButtons) != buttons) { - if (buttons == 0 && d_ptr->scene && d_ptr->scene->mouseGrabberItem() == this - && d_ptr->scene->d_func()->lastMouseGrabberItemHasImplicitMouseGrab) { - ungrabMouse(); - } - d_ptr->acceptedMouseButtons = quint32(buttons); - } -} - -/*! - \since 4.4 - - Returns true if an item accepts hover events - (QGraphicsSceneHoverEvent); otherwise, returns false. By default, - items do not accept hover events. - - \sa setAcceptedMouseButtons() -*/ -bool QGraphicsItem::acceptHoverEvents() const -{ - return d_ptr->acceptsHover; -} - -/*! - \obsolete - - Call acceptHoverEvents() instead. -*/ -bool QGraphicsItem::acceptsHoverEvents() const -{ - return d_ptr->acceptsHover; -} - -/*! - \since 4.4 - - If \a enabled is true, this item will accept hover events; - otherwise, it will ignore them. By default, items do not accept - hover events. - - Hover events are delivered when there is no current mouse grabber - item. They are sent when the mouse cursor enters an item, when it - moves around inside the item, and when the cursor leaves an - item. Hover events are commonly used to highlight an item when - it's entered, and for tracking the mouse cursor as it hovers over - the item (equivalent to QWidget::mouseTracking). - - Parent items receive hover enter events before their children, and - leave events after their children. The parent does not receive a - hover leave event if the cursor enters a child, though; the parent - stays "hovered" until the cursor leaves its area, including its - children's areas. - - If a parent item handles child events, it will receive hover move, - drag move, and drop events as the cursor passes through its - children, but it does not receive hover enter and hover leave, nor - drag enter and drag leave events on behalf of its children. - - A QGraphicsWidget with window decorations will accept hover events - regardless of the value of acceptHoverEvents(). - - \sa acceptHoverEvents(), hoverEnterEvent(), hoverMoveEvent(), - hoverLeaveEvent() -*/ -void QGraphicsItem::setAcceptHoverEvents(bool enabled) -{ - if (d_ptr->acceptsHover == quint32(enabled)) - return; - d_ptr->acceptsHover = quint32(enabled); - if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) { - d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false; - d_ptr->scene->d_func()->enableMouseTrackingOnViews(); - } -} - -/*! - \obsolete - - Use setAcceptHoverEvents(\a enabled) instead. -*/ -void QGraphicsItem::setAcceptsHoverEvents(bool enabled) -{ - setAcceptHoverEvents(enabled); -} - -/*! \since 4.6 - - Returns true if an item accepts \l{QTouchEvent}{touch events}; - otherwise, returns false. By default, items do not accept touch events. - - \sa setAcceptTouchEvents() -*/ -bool QGraphicsItem::acceptTouchEvents() const -{ - return d_ptr->acceptTouchEvents; -} - -/*! - \since 4.6 - - If \a enabled is true, this item will accept \l{QTouchEvent}{touch events}; - otherwise, it will ignore them. By default, items do not accept - touch events. -*/ -void QGraphicsItem::setAcceptTouchEvents(bool enabled) -{ - if (d_ptr->acceptTouchEvents == quint32(enabled)) - return; - d_ptr->acceptTouchEvents = quint32(enabled); - if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) { - d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false; - d_ptr->scene->d_func()->enableTouchEventsOnViews(); - } -} - -/*! - \since 4.6 - - Returns true if this item filters child events (i.e., all events - intended for any of its children are instead sent to this item); - otherwise, false is returned. - - The default value is false; child events are not filtered. - - \sa setFiltersChildEvents() -*/ -bool QGraphicsItem::filtersChildEvents() const -{ - return d_ptr->filtersDescendantEvents; -} - -/*! - \since 4.6 - - If \a enabled is true, this item is set to filter all events for - all its children (i.e., all events intented for any of its - children are instead sent to this item); otherwise, if \a enabled - is false, this item will only handle its own events. The default - value is false. - - \sa filtersChildEvents() -*/ -void QGraphicsItem::setFiltersChildEvents(bool enabled) -{ - if (d_ptr->filtersDescendantEvents == enabled) - return; - - d_ptr->filtersDescendantEvents = enabled; - d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); -} - -/*! - \obsolete - - Returns true if this item handles child events (i.e., all events - intended for any of its children are instead sent to this item); - otherwise, false is returned. - - This property is useful for item groups; it allows one item to - handle events on behalf of its children, as opposed to its - children handling their events individually. - - The default is to return false; children handle their own events. - The exception for this is if the item is a QGraphicsItemGroup, then - it defaults to return true. - - \sa setHandlesChildEvents() -*/ -bool QGraphicsItem::handlesChildEvents() const -{ - return d_ptr->handlesChildEvents; -} - -/*! - \obsolete - - If \a enabled is true, this item is set to handle all events for - all its children (i.e., all events intented for any of its - children are instead sent to this item); otherwise, if \a enabled - is false, this item will only handle its own events. The default - value is false. - - This property is useful for item groups; it allows one item to - handle events on behalf of its children, as opposed to its - children handling their events individually. - - If a child item accepts hover events, its parent will receive - hover move events as the cursor passes through the child, but it - does not receive hover enter and hover leave events on behalf of - its child. - - \sa handlesChildEvents() -*/ -void QGraphicsItem::setHandlesChildEvents(bool enabled) -{ - if (d_ptr->handlesChildEvents == enabled) - return; - - d_ptr->handlesChildEvents = enabled; - d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); -} -/*! - \since 4.6 - Returns true if this item is active; otherwise returns false. - - An item can only be active if the scene is active. An item is active - if it is, or is a descendent of, an active panel. Items in non-active - panels are not active. - - Items that are not part of a panel follow scene activation when the - scene has no active panel. - - Only active items can gain input focus. - - \sa QGraphicsScene::isActive(), QGraphicsScene::activePanel(), panel(), isPanel() -*/ -bool QGraphicsItem::isActive() const -{ - if (!d_ptr->scene || !d_ptr->scene->isActive()) - return false; - return panel() == d_ptr->scene->activePanel(); -} - -/*! - \since 4.6 - - If \a active is true, and the scene is active, this item's panel will be - activated. Otherwise, the panel is deactivated. - - If the item is not part of an active scene, \a active will decide what - happens to the panel when the scene becomes active or the item is added to - the scene. If true, the item's panel will be activated when the item is - either added to the scene or the scene is activated. Otherwise, the item - will stay inactive independent of the scene's activated state. - - \sa isPanel(), QGraphicsScene::setActivePanel(), QGraphicsScene::isActive() -*/ -void QGraphicsItem::setActive(bool active) -{ - d_ptr->explicitActivate = 1; - d_ptr->wantsActive = active; - if (d_ptr->scene) { - if (active) { - // Activate this item. - d_ptr->scene->setActivePanel(this); - } else { - // Deactivate this item, and reactivate the last active item - // (if any). - QGraphicsItem *lastActive = d_ptr->scene->d_func()->lastActivePanel; - d_ptr->scene->setActivePanel(lastActive != this ? lastActive : 0); - } - } -} - -/*! - Returns true if this item is active, and it or its \l{focusProxy()}{focus - proxy} has keyboard input focus; otherwise, returns false. - - \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem(), isActive() -*/ -bool QGraphicsItem::hasFocus() const -{ - if (!d_ptr->scene || !d_ptr->scene->isActive()) - return false; - - if (d_ptr->focusProxy) - return d_ptr->focusProxy->hasFocus(); - - if (d_ptr->scene->d_func()->focusItem != this) - return false; - - return panel() == d_ptr->scene->d_func()->activePanel; -} - -/*! - Gives keyboard input focus to this item. The \a focusReason argument will - be passed into any \l{QFocusEvent}{focus event} generated by this function; - it is used to give an explanation of what caused the item to get focus. - - Only enabled items that set the ItemIsFocusable flag can accept keyboard - focus. - - If this item is not visible, not active, or not associated with a scene, - it will not gain immediate input focus. However, it will be registered as - the preferred focus item for its subtree of items, should it later become - visible. - - As a result of calling this function, this item will receive a - \l{focusInEvent()}{focus in event} with \a focusReason. If another item - already has focus, that item will first receive a \l{focusOutEvent()} - {focus out event} indicating that it has lost input focus. - - \sa clearFocus(), hasFocus(), focusItem(), focusProxy() -*/ -void QGraphicsItem::setFocus(Qt::FocusReason focusReason) -{ - d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromHide = */ false); -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide) -{ - // Disabled / unfocusable items cannot accept focus. - if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable)) - return; - - // Find focus proxy. - QGraphicsItem *f = q_ptr; - while (f->d_ptr->focusProxy) - f = f->d_ptr->focusProxy; - - // Return if it already has focus. - if (scene && scene->focusItem() == f) - return; - - // Update focus scope item ptr. - QGraphicsItem *p = parent; - while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem; - p->d_ptr->focusScopeItem = q_ptr; - if (!p->focusItem() && !focusFromHide) { - if (oldFocusScopeItem) - oldFocusScopeItem->d_ptr->focusScopeItemChange(false); - focusScopeItemChange(true); - // If you call setFocus on a child of a focus scope that - // doesn't currently have a focus item, then stop. - return; - } - break; - } - p = p->d_ptr->parent; - } - - if (climb) { - while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible()) - f = f->d_ptr->focusScopeItem; - } - - // Update the child focus chain. - QGraphicsItem *commonAncestor = 0; - if (scene && scene->focusItem()) { - commonAncestor = scene->focusItem()->commonAncestorItem(f); - scene->focusItem()->d_ptr->clearSubFocus(scene->focusItem(), commonAncestor); - } - - f->d_ptr->setSubFocus(f, commonAncestor); - - // Update the scene's focus item. - if (scene) { - QGraphicsItem *p = q_ptr->panel(); - if ((!p && scene->isActive()) || (p && p->isActive())) { - // Visible items immediately gain focus from scene. - scene->d_func()->setFocusItemHelper(f, focusReason); - } - } -} - -/*! - Takes keyboard input focus from the item. - - If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this - item to tell it that it is about to lose the focus. - - Only items that set the ItemIsFocusable flag, or widgets that set an - appropriate focus policy, can accept keyboard focus. - - \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy -*/ -void QGraphicsItem::clearFocus() -{ - d_ptr->clearFocusHelper(/* giveFocusToParent = */ true); -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent) -{ - if (giveFocusToParent) { - // Pass focus to the closest parent focus scope - if (!inDestructor) { - QGraphicsItem *p = parent; - while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - if (p->d_ptr->focusScopeItem == q_ptr) { - p->d_ptr->focusScopeItem = 0; - if (!q_ptr->hasFocus()) //if it has focus, focusScopeItemChange is called elsewhere - focusScopeItemChange(false); - } - if (q_ptr->hasFocus()) - p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false, - /* focusFromHide = */ false); - return; - } - p = p->d_ptr->parent; - } - } - } - - if (q_ptr->hasFocus()) { - // Invisible items with focus must explicitly clear subfocus. - clearSubFocus(q_ptr); - - // If this item has the scene's input focus, clear it. - scene->setFocusItem(0); - } -} - -/*! - \since 4.6 - - Returns this item's focus proxy, or 0 if this item has no - focus proxy. - - \sa setFocusProxy(), setFocus(), hasFocus() -*/ -QGraphicsItem *QGraphicsItem::focusProxy() const -{ - return d_ptr->focusProxy; -} - -/*! - \since 4.6 - - Sets the item's focus proxy to \a item. - - If an item has a focus proxy, the focus proxy will receive - input focus when the item gains input focus. The item itself - will still have focus (i.e., hasFocus() will return true), - but only the focus proxy will receive the keyboard input. - - A focus proxy can itself have a focus proxy, and so on. In - such case, keyboard input will be handled by the outermost - focus proxy. - - The focus proxy \a item must belong to the same scene as - this item. - - \sa focusProxy(), setFocus(), hasFocus() -*/ -void QGraphicsItem::setFocusProxy(QGraphicsItem *item) -{ - if (item == d_ptr->focusProxy) - return; - if (item == this) { - qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy"); - return; - } - if (item) { - if (item->d_ptr->scene != d_ptr->scene) { - qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene"); - return; - } - for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) { - if (f == this) { - qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item); - return; - } - } - } - - QGraphicsItem *lastFocusProxy = d_ptr->focusProxy; - if (lastFocusProxy) - lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy); - d_ptr->focusProxy = item; - if (item) - item->d_ptr->focusProxyRefs << &d_ptr->focusProxy; -} - -/*! - \since 4.6 - - If this item, a child or descendant of this item currently has input - focus, this function will return a pointer to that item. If - no descendant has input focus, 0 is returned. - - \sa hasFocus(), setFocus(), QWidget::focusWidget() -*/ -QGraphicsItem *QGraphicsItem::focusItem() const -{ - return d_ptr->subFocusItem; -} - -/*! - \internal - - Returns this item's focus scope item. -*/ -QGraphicsItem *QGraphicsItem::focusScopeItem() const -{ - return d_ptr->focusScopeItem; -} - -/*! - \since 4.4 - Grabs the mouse input. - - This item will receive all mouse events for the scene until any of the - following events occurs: - - \list - \o The item becomes invisible - \o The item is removed from the scene - \o The item is deleted - \o The item call ungrabMouse() - \o Another item calls grabMouse(); the item will regain the mouse grab - when the other item calls ungrabMouse(). - \endlist - - When an item gains the mouse grab, it receives a QEvent::GrabMouse - event. When it loses the mouse grab, it receives a QEvent::UngrabMouse - event. These events can be used to detect when your item gains or loses - the mouse grab through other means than receiving mouse button events. - - It is almost never necessary to explicitly grab the mouse in Qt, as Qt - grabs and releases it sensibly. In particular, Qt grabs the mouse when you - press a mouse button, and keeps the mouse grabbed until you release the - last mouse button. Also, Qt::Popup widgets implicitly call grabMouse() - when shown, and ungrabMouse() when hidden. - - Note that only visible items can grab mouse input. Calling grabMouse() on - an invisible item has no effect. - - Keyboard events are not affected. - - \sa QGraphicsScene::mouseGrabberItem(), ungrabMouse(), grabKeyboard() -*/ -void QGraphicsItem::grabMouse() -{ - if (!d_ptr->scene) { - qWarning("QGraphicsItem::grabMouse: cannot grab mouse without scene"); - return; - } - if (!d_ptr->visible) { - qWarning("QGraphicsItem::grabMouse: cannot grab mouse while invisible"); - return; - } - d_ptr->scene->d_func()->grabMouse(this); -} - -/*! - \since 4.4 - Releases the mouse grab. - - \sa grabMouse(), ungrabKeyboard() -*/ -void QGraphicsItem::ungrabMouse() -{ - if (!d_ptr->scene) { - qWarning("QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene"); - return; - } - d_ptr->scene->d_func()->ungrabMouse(this); -} - -/*! - \since 4.4 - Grabs the keyboard input. - - The item will receive all keyboard input to the scene until one of the - following events occur: - - \list - \o The item becomes invisible - \o The item is removed from the scene - \o The item is deleted - \o The item calls ungrabKeyboard() - \o Another item calls grabKeyboard(); the item will regain the keyboard grab - when the other item calls ungrabKeyboard(). - \endlist - - When an item gains the keyboard grab, it receives a QEvent::GrabKeyboard - event. When it loses the keyboard grab, it receives a - QEvent::UngrabKeyboard event. These events can be used to detect when your - item gains or loses the keyboard grab through other means than gaining - input focus. - - It is almost never necessary to explicitly grab the keyboard in Qt, as Qt - grabs and releases it sensibly. In particular, Qt grabs the keyboard when - your item gains input focus, and releases it when your item loses input - focus, or when the item is hidden. - - Note that only visible items can grab keyboard input. Calling - grabKeyboard() on an invisible item has no effect. - - Keyboard events are not affected. - - \sa ungrabKeyboard(), grabMouse(), setFocus() -*/ -void QGraphicsItem::grabKeyboard() -{ - if (!d_ptr->scene) { - qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard without scene"); - return; - } - if (!d_ptr->visible) { - qWarning("QGraphicsItem::grabKeyboard: cannot grab keyboard while invisible"); - return; - } - d_ptr->scene->d_func()->grabKeyboard(this); -} - -/*! - \since 4.4 - Releases the keyboard grab. - - \sa grabKeyboard(), ungrabMouse() -*/ -void QGraphicsItem::ungrabKeyboard() -{ - if (!d_ptr->scene) { - qWarning("QGraphicsItem::ungrabKeyboard: cannot ungrab keyboard without scene"); - return; - } - d_ptr->scene->d_func()->ungrabKeyboard(this); -} - -/*! - Returns the position of the item in parent coordinates. If the item has no - parent, its position is given in scene coordinates. - - The position of the item describes its origin (local coordinate - (0, 0)) in parent coordinates; this function returns the same as - mapToParent(0, 0). - - For convenience, you can also call scenePos() to determine the - item's position in scene coordinates, regardless of its parent. - - \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System} -*/ -QPointF QGraphicsItem::pos() const -{ - return d_ptr->pos; -} - -/*! - \fn QGraphicsItem::x() const - - This convenience function is equivalent to calling pos().x(). - - \sa y() -*/ - -/*! - \since 4.6 - - Set's the \a x coordinate of the item's position. Equivalent to - calling setPos(x, y()). - - \sa x(), setPos() -*/ -void QGraphicsItem::setX(qreal x) -{ - if (d_ptr->inDestructor) - return; - - if (qIsNaN(x)) - return; - - setPos(QPointF(x, d_ptr->pos.y())); -} - -/*! - \fn QGraphicsItem::y() const - - This convenience function is equivalent to calling pos().y(). - - \sa x() -*/ - -/*! - \since 4.6 - - Set's the \a y coordinate of the item's position. Equivalent to - calling setPos(x(), y). - - \sa x(), setPos() -*/ -void QGraphicsItem::setY(qreal y) -{ - if (d_ptr->inDestructor) - return; - - if (qIsNaN(y)) - return; - - setPos(QPointF(d_ptr->pos.x(), y)); -} - -/*! - Returns the item's position in scene coordinates. This is - equivalent to calling \c mapToScene(0, 0). - - \sa pos(), sceneTransform(), {The Graphics View Coordinate System} -*/ -QPointF QGraphicsItem::scenePos() const -{ - return mapToScene(0, 0); -} - -/*! - \internal - - Sets the position \a pos. -*/ -void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) -{ - Q_Q(QGraphicsItem); - inSetPosHelper = 1; - if (scene) - q->prepareGeometryChange(); - QPointF oldPos = this->pos; - this->pos = pos; - dirtySceneTransform = 1; - inSetPosHelper = 0; - if (isObject) { - if (pos.x() != oldPos.x()) - emit static_cast<QGraphicsObject *>(q_ptr)->xChanged(); - if (pos.y() != oldPos.y()) - emit static_cast<QGraphicsObject *>(q_ptr)->yChanged(); - } -} - -/*! - \internal - - Sets the transform \a transform. -*/ -void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform) -{ - q_ptr->prepareGeometryChange(); - transformData->transform = transform; - dirtySceneTransform = 1; - transformChanged(); -} - -/*! - Sets the position of the item to \a pos, which is in parent - coordinates. For items with no parent, \a pos is in scene - coordinates. - - The position of the item describes its origin (local coordinate - (0, 0)) in parent coordinates. - - \sa pos(), scenePos(), {The Graphics View Coordinate System} -*/ -void QGraphicsItem::setPos(const QPointF &pos) -{ - if (d_ptr->pos == pos) - return; - - if (d_ptr->inDestructor) - return; - - // Update and repositition. - if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) { - d_ptr->setPosHelper(pos); - if (d_ptr->isWidget) - static_cast<QGraphicsWidget *>(this)->d_func()->setGeometryFromSetPos(); - if (d_ptr->scenePosDescendants) - d_ptr->sendScenePosChange(); - return; - } - - // Notify the item that the position is changing. - const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos))); - QPointF newPos = newPosVariant.toPointF(); - if (newPos == d_ptr->pos) - return; - - // Update and repositition. - d_ptr->setPosHelper(newPos); - - // Send post-notification. - itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); - d_ptr->sendScenePosChange(); -} - -/*! - \fn void QGraphicsItem::setPos(qreal x, qreal y) - \overload - - This convenience function is equivalent to calling setPos(QPointF(\a x, \a - y)). -*/ - -/*! - \fn void QGraphicsItem::moveBy(qreal dx, qreal dy) - - Moves the item by \a dx points horizontally, and \a dy point - vertically. This function is equivalent to calling setPos(pos() + - QPointF(\a dx, \a dy)). -*/ - -/*! - If this item is part of a scene that is viewed by a QGraphicsView, this - convenience function will attempt to scroll the view to ensure that \a - rect is visible inside the view's viewport. If \a rect is a null rect (the - default), QGraphicsItem will default to the item's bounding rect. \a xmargin - and \a ymargin are the number of pixels the view should use for margins. - - If the specified rect cannot be reached, the contents are scrolled to the - nearest valid position. - - If this item is not viewed by a QGraphicsView, this function does nothing. - - \sa QGraphicsView::ensureVisible() -*/ -void QGraphicsItem::ensureVisible(const QRectF &rect, int xmargin, int ymargin) -{ - if (d_ptr->scene) { - QRectF sceneRect; - if (!rect.isNull()) - sceneRect = sceneTransform().mapRect(rect); - else - sceneRect = sceneBoundingRect(); - foreach (QGraphicsView *view, d_ptr->scene->d_func()->views) - view->ensureVisible(sceneRect, xmargin, ymargin); - } -} - -/*! - \fn void QGraphicsItem::ensureVisible(qreal x, qreal y, qreal w, qreal h, - int xmargin = 50, int ymargin = 50) - - This convenience function is equivalent to calling - ensureVisible(QRectF(\a x, \a y, \a w, \a h), \a xmargin, \a ymargin): -*/ - -/*! - \obsolete - - Returns the item's affine transformation matrix. This is a subset or the - item's full transformation matrix, and might not represent the item's full - transformation. - - Use transform() instead. - - \sa setTransform(), sceneTransform() -*/ -QMatrix QGraphicsItem::matrix() const -{ - return transform().toAffine(); -} - -/*! - \since 4.3 - - Returns this item's transformation matrix. - - The transformation matrix is combined with the item's rotation(), scale() - and transformations() into a combined transformations for the item. - - The default transformation matrix is an identity matrix. - - \sa setTransform(), sceneTransform() -*/ -QTransform QGraphicsItem::transform() const -{ - if (!d_ptr->transformData) - return QTransform(); - return d_ptr->transformData->transform; -} - -/*! - \since 4.6 - - Returns the clockwise rotation, in degrees, around the Z axis. The default - value is 0 (i.e., the item is not rotated). - - The rotation is combined with the item's scale(), transform() and - transformations() to map the item's coordinate system to the parent item. - - \sa setRotation(), transformOriginPoint(), {Transformations} -*/ -qreal QGraphicsItem::rotation() const -{ - if (!d_ptr->transformData) - return 0; - return d_ptr->transformData->rotation; -} - -/*! - \since 4.6 - - Sets the clockwise rotation \a angle, in degrees, around the Z axis. The - default value is 0 (i.e., the item is not rotated). Assigning a negative - value will rotate the item counter-clockwise. Normally the rotation angle - is in the range (-360, 360), but it's also possible to assign values - outside of this range (e.g., a rotation of 370 degrees is the same as a - rotation of 10 degrees). - - The item is rotated around its transform origin point, which by default - is (0, 0). You can select a different transformation origin by calling - setTransformOriginPoint(). - - The rotation is combined with the item's scale(), transform() and - transformations() to map the item's coordinate system to the parent item. - - \sa rotation(), setTransformOriginPoint(), {Transformations} -*/ -void QGraphicsItem::setRotation(qreal angle) -{ - prepareGeometryChange(); - qreal newRotation = angle; - - if (d_ptr->flags & ItemSendsGeometryChanges) { - // Notify the item that the rotation is changing. - const QVariant newRotationVariant(itemChange(ItemRotationChange, angle)); - newRotation = newRotationVariant.toReal(); - } - - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - - if (d_ptr->transformData->rotation == newRotation) - return; - - d_ptr->transformData->rotation = newRotation; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; - - // Send post-notification. - if (d_ptr->flags & ItemSendsGeometryChanges) - itemChange(ItemRotationHasChanged, newRotation); - - if (d_ptr->isObject) - emit static_cast<QGraphicsObject *>(this)->rotationChanged(); - - d_ptr->transformChanged(); -} - -/*! - \since 4.6 - - Returns the scale factor of the item. The default scale factor is 1.0 - (i.e., the item is not scaled). - - The scale is combined with the item's rotation(), transform() and - transformations() to map the item's coordinate system to the parent item. - - \sa setScale(), rotation(), {Transformations} -*/ -qreal QGraphicsItem::scale() const -{ - if (!d_ptr->transformData) - return 1.; - return d_ptr->transformData->scale; -} - -/*! - \since 4.6 - - Sets the scale \a factor of the item. The default scale factor is 1.0 - (i.e., the item is not scaled). A scale factor of 0.0 will collapse the - item to a single point. If you provide a negative scale factor, the - item will be flipped and mirrored (i.e., rotated 180 degrees). - - The item is scaled around its transform origin point, which by default - is (0, 0). You can select a different transformation origin by calling - setTransformOriginPoint(). - - The scale is combined with the item's rotation(), transform() and - transformations() to map the item's coordinate system to the parent item. - - \sa scale(), setTransformOriginPoint(), {Transformations Example} -*/ -void QGraphicsItem::setScale(qreal factor) -{ - prepareGeometryChange(); - qreal newScale = factor; - - if (d_ptr->flags & ItemSendsGeometryChanges) { - // Notify the item that the scale is changing. - const QVariant newScaleVariant(itemChange(ItemScaleChange, factor)); - newScale = newScaleVariant.toReal(); - } - - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - - if (d_ptr->transformData->scale == newScale) - return; - - d_ptr->transformData->scale = newScale; - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; - - // Send post-notification. - if (d_ptr->flags & ItemSendsGeometryChanges) - itemChange(ItemScaleHasChanged, newScale); - - if (d_ptr->isObject) - emit static_cast<QGraphicsObject *>(this)->scaleChanged(); - - d_ptr->transformChanged(); -} - - -/*! - \since 4.6 - - Returns a list of graphics transforms that currently apply to this item. - - QGraphicsTransform is for applying and controlling a chain of individual - transformation operations on an item. It's particularly useful in - animations, where each transform operation needs to be interpolated - independently, or differently. - - The transformations are combined with the item's rotation(), scale() and - transform() to map the item's coordinate system to the parent item. - - \sa scale(), rotation(), transformOriginPoint(), {Transformations} -*/ -QList<QGraphicsTransform *> QGraphicsItem::transformations() const -{ - if (!d_ptr->transformData) - return QList<QGraphicsTransform *>(); - return d_ptr->transformData->graphicsTransforms; -} - -/*! - \since 4.6 - - Sets a list of graphics \a transformations (QGraphicsTransform) that - currently apply to this item. - - If all you want is to rotate or scale an item, you should call setRotation() - or setScale() instead. If you want to set an arbitrary transformation on - an item, you can call setTransform(). - - QGraphicsTransform is for applying and controlling a chain of individual - transformation operations on an item. It's particularly useful in - animations, where each transform operation needs to be interpolated - independently, or differently. - - The transformations are combined with the item's rotation(), scale() and - transform() to map the item's coordinate system to the parent item. - - \sa scale(), setTransformOriginPoint(), {Transformations} -*/ -void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations) -{ - prepareGeometryChange(); - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - d_ptr->transformData->graphicsTransforms = transformations; - for (int i = 0; i < transformations.size(); ++i) - transformations.at(i)->d_func()->setItem(this); - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; - d_ptr->transformChanged(); -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t) -{ - if (!transformData) - transformData = new QGraphicsItemPrivate::TransformData; - if (!transformData->graphicsTransforms.contains(t)) - transformData->graphicsTransforms.prepend(t); - - Q_Q(QGraphicsItem); - t->d_func()->setItem(q); - transformData->onlyTransform = false; - dirtySceneTransform = 1; - transformChanged(); -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t) -{ - if (!transformData) - transformData = new QGraphicsItemPrivate::TransformData; - if (!transformData->graphicsTransforms.contains(t)) - transformData->graphicsTransforms.append(t); - - Q_Q(QGraphicsItem); - t->d_func()->setItem(q); - transformData->onlyTransform = false; - dirtySceneTransform = 1; - transformChanged(); -} - -/*! - \since 4.6 - - Returns the origin point for the transformation in item coordinates. - - The default is QPointF(0,0). - - \sa setTransformOriginPoint(), {Transformations} -*/ -QPointF QGraphicsItem::transformOriginPoint() const -{ - if (!d_ptr->transformData) - return QPointF(0,0); - return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin); -} - -/*! - \since 4.6 - - Sets the \a origin point for the transformation in item coordinates. - - \sa transformOriginPoint(), {Transformations} -*/ -void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) -{ - prepareGeometryChange(); - QPointF newOrigin = origin; - - if (d_ptr->flags & ItemSendsGeometryChanges) { - // Notify the item that the origin point is changing. - const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange, - QVariant::fromValue<QPointF>(origin))); - newOrigin = newOriginVariant.toPointF(); - } - - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - - if (d_ptr->transformData->xOrigin == newOrigin.x() - && d_ptr->transformData->yOrigin == newOrigin.y()) { - return; - } - - d_ptr->transformData->xOrigin = newOrigin.x(); - d_ptr->transformData->yOrigin = newOrigin.y(); - d_ptr->transformData->onlyTransform = false; - d_ptr->dirtySceneTransform = 1; - - // Send post-notification. - if (d_ptr->flags & ItemSendsGeometryChanges) - itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin)); -} - -/*! - \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y) - - \since 4.6 - \overload - - Sets the origin point for the transformation in item coordinates. - This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)). - - \sa setTransformOriginPoint(), {Transformations} -*/ - - -/*! - \obsolete - - Use sceneTransform() instead. - - \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System} -*/ -QMatrix QGraphicsItem::sceneMatrix() const -{ - d_ptr->ensureSceneTransform(); - return d_ptr->sceneTransform.toAffine(); -} - - -/*! - \since 4.3 - - Returns this item's scene transformation matrix. This matrix can be used - to map coordinates and geometrical shapes from this item's local - coordinate system to the scene's coordinate system. To map coordinates - from the scene, you must first invert the returned matrix. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4 - - Unlike transform(), which returns only an item's local transformation, this - function includes the item's (and any parents') position, and all the transfomation properties. - - \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations} -*/ -QTransform QGraphicsItem::sceneTransform() const -{ - d_ptr->ensureSceneTransform(); - return d_ptr->sceneTransform; -} - -/*! - \since 4.3 - - Returns this item's device transformation matrix, using \a - viewportTransform to map from scene to device coordinates. This matrix can - be used to map coordinates and geometrical shapes from this item's local - coordinate system to the viewport's (or any device's) coordinate - system. To map coordinates from the viewport, you must first invert the - returned matrix. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 5 - - This function is the same as combining this item's scene transform with - the view's viewport transform, but it also understands the - ItemIgnoresTransformations flag. The device transform can be used to do - accurate coordinate mapping (and collision detection) for untransformable - items. - - \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate - System}, itemTransform() -*/ -QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const -{ - // Ensure we return the standard transform if we're not untransformable. - if (!d_ptr->itemIsUntransformable()) { - d_ptr->ensureSceneTransform(); - return d_ptr->sceneTransform * viewportTransform; - } - - // Find the topmost item that ignores view transformations. - const QGraphicsItem *untransformedAncestor = this; - QList<const QGraphicsItem *> parents; - while (untransformedAncestor && ((untransformedAncestor->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations))) { - parents.prepend(untransformedAncestor); - untransformedAncestor = untransformedAncestor->parentItem(); - } - - if (!untransformedAncestor) { - // Assert in debug mode, continue in release. - Q_ASSERT_X(untransformedAncestor, "QGraphicsItem::deviceTransform", - "Invalid object structure!"); - return QTransform(); - } - - // First translate the base untransformable item. - untransformedAncestor->d_ptr->ensureSceneTransform(); - QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0)); - - // COMBINE - QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y()); - if (untransformedAncestor->d_ptr->transformData) - matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix); - - // Then transform and translate all children. - for (int i = 0; i < parents.size(); ++i) { - const QGraphicsItem *parent = parents.at(i); - parent->d_ptr->combineTransformFromParent(&matrix); - } - - return matrix; -} - -/*! - \since 4.5 - - Returns a QTransform that maps coordinates from this item to \a other. If - \a ok is not null, and if there is no such transform, the boolean pointed - to by \a ok will be set to false; otherwise it will be set to true. - - This transform provides an alternative to the mapToItem() or mapFromItem() - functions, by returning the appropriate transform so that you can map - shapes and coordinates yourself. It also helps you write more efficient - code when repeatedly mapping between the same two items. - - \note In rare circumstances, there is no transform that maps between two - items. - - \sa mapToItem(), mapFromItem(), deviceTransform() -*/ -QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) const -{ - // Catch simple cases first. - if (other == 0) { - qWarning("QGraphicsItem::itemTransform: null pointer passed"); - return QTransform(); - } - if (other == this) { - if (ok) - *ok = true; - return QTransform(); - } - - QGraphicsItem *parent = d_ptr->parent; - const QGraphicsItem *otherParent = other->d_ptr->parent; - - // This is other's child - if (parent == other) { - if (ok) - *ok = true; - QTransform x; - d_ptr->combineTransformFromParent(&x); - return x; - } - - // This is other's parent - if (otherParent == this) { - const QPointF &otherPos = other->d_ptr->pos; - if (other->d_ptr->transformData) { - QTransform otherToParent; - other->d_ptr->combineTransformFromParent(&otherToParent); - return otherToParent.inverted(ok); - } - if (ok) - *ok = true; - return QTransform::fromTranslate(-otherPos.x(), -otherPos.y()); - } - - // Siblings - if (parent == otherParent) { - // COMBINE - const QPointF &itemPos = d_ptr->pos; - const QPointF &otherPos = other->d_ptr->pos; - if (!d_ptr->transformData && !other->d_ptr->transformData) { - QPointF delta = itemPos - otherPos; - if (ok) - *ok = true; - return QTransform::fromTranslate(delta.x(), delta.y()); - } - - QTransform itemToParent; - d_ptr->combineTransformFromParent(&itemToParent); - QTransform otherToParent; - other->d_ptr->combineTransformFromParent(&otherToParent); - return itemToParent * otherToParent.inverted(ok); - } - - // Find the closest common ancestor. If the two items don't share an - // ancestor, then the only way is to combine their scene transforms. - const QGraphicsItem *commonAncestor = commonAncestorItem(other); - if (!commonAncestor) { - d_ptr->ensureSceneTransform(); - other->d_ptr->ensureSceneTransform(); - return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok); - } - - // If the two items are cousins (in sibling branches), map both to the - // common ancestor, and combine the two transforms. - bool cousins = other != commonAncestor && this != commonAncestor; - if (cousins) { - bool good = false; - QTransform thisToScene = itemTransform(commonAncestor, &good); - QTransform otherToScene(Qt::Uninitialized); - if (good) - otherToScene = other->itemTransform(commonAncestor, &good); - if (!good) { - if (ok) - *ok = false; - return QTransform(); - } - return thisToScene * otherToScene.inverted(ok); - } - - // One is an ancestor of the other; walk the chain. - bool parentOfOther = isAncestorOf(other); - const QGraphicsItem *child = parentOfOther ? other : this; - const QGraphicsItem *root = parentOfOther ? this : other; - - QTransform x; - const QGraphicsItem *p = child; - do { - p->d_ptr.data()->combineTransformToParent(&x); - } while ((p = p->d_ptr->parent) && p != root); - if (parentOfOther) - return x.inverted(ok); - if (ok) - *ok = true; - return x; -} - -/*! - \obsolete - - Sets the item's affine transformation matrix. This is a subset or the - item's full transformation matrix, and might not represent the item's full - transformation. - - Use setTransform() instead. - - \sa transform(), {The Graphics View Coordinate System} -*/ -void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) -{ - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - - QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix)); - if (d_ptr->transformData->transform == newTransform) - return; - - // Update and set the new transformation. - if (!(d_ptr->flags & ItemSendsGeometryChanges)) { - d_ptr->setTransformHelper(newTransform); - return; - } - - // Notify the item that the transformation matrix is changing. - const QVariant newMatrixVariant = QVariant::fromValue<QMatrix>(newTransform.toAffine()); - newTransform = QTransform(qvariant_cast<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); - if (d_ptr->transformData->transform == newTransform) - return; - - // Update and set the new transformation. - d_ptr->setTransformHelper(newTransform); - - // Send post-notification. - itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform)); -} - -/*! - \since 4.3 - - Sets the item's current transformation matrix to \a matrix. - - If \a combine is true, then \a matrix is combined with the current matrix; - otherwise, \a matrix \e replaces the current matrix. \a combine is false - by default. - - To simplify interation with items using a transformed view, QGraphicsItem - provides mapTo... and mapFrom... functions that can translate between - items' and the scene's coordinates. For example, you can call mapToScene() - to map an item coordiate to a scene coordinate, or mapFromScene() to map - from scene coordinates to item coordinates. - - The transformation matrix is combined with the item's rotation(), scale() - and transformations() into a combined transformation that maps the item's - coordinate system to its parent. - - \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations} -*/ -void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) -{ - if (!d_ptr->transformData) - d_ptr->transformData = new QGraphicsItemPrivate::TransformData; - - QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix); - if (d_ptr->transformData->transform == newTransform) - return; - - // Update and set the new transformation. - if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) { - d_ptr->setTransformHelper(newTransform); - if (d_ptr->scenePosDescendants) - d_ptr->sendScenePosChange(); - return; - } - - // Notify the item that the transformation matrix is changing. - const QVariant newTransformVariant(itemChange(ItemTransformChange, - QVariant::fromValue<QTransform>(newTransform))); - newTransform = qvariant_cast<QTransform>(newTransformVariant); - if (d_ptr->transformData->transform == newTransform) - return; - - // Update and set the new transformation. - d_ptr->setTransformHelper(newTransform); - - // Send post-notification. - itemChange(ItemTransformHasChanged, newTransformVariant); - d_ptr->sendScenePosChange(); -} - -/*! - \obsolete - - Use resetTransform() instead. -*/ -void QGraphicsItem::resetMatrix() -{ - resetTransform(); -} - -/*! - \since 4.3 - - Resets this item's transformation matrix to the identity matrix or - all the transformation properties to their default values. - This is equivalent to calling \c setTransform(QTransform()). - - \sa setTransform(), transform() -*/ -void QGraphicsItem::resetTransform() -{ - setTransform(QTransform(), false); -} - -/*! - \obsolete - - Use - - \code - setRotation(rotation() + angle); - \endcode - - instead. - - Rotates the current item transformation \a angle degrees clockwise around - its origin. To translate around an arbitrary point (x, y), you need to - combine translation and rotation with setTransform(). - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6 - - \sa setTransform(), transform(), scale(), shear(), translate() -*/ -void QGraphicsItem::rotate(qreal angle) -{ - setTransform(QTransform().rotate(angle), true); -} - -/*! - \obsolete - - Use - - \code - setTransform(QTransform::fromScale(sx, sy), true); - \endcode - - instead. - - Scales the current item transformation by (\a sx, \a sy) around its - origin. To scale from an arbitrary point (x, y), you need to combine - translation and scaling with setTransform(). - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7 - - \sa setTransform(), transform() -*/ -void QGraphicsItem::scale(qreal sx, qreal sy) -{ - setTransform(QTransform::fromScale(sx, sy), true); -} - -/*! - \obsolete - - Use - - \code - setTransform(QTransform().shear(sh, sv), true); - \endcode - - instead. - - Shears the current item transformation by (\a sh, \a sv). - - \sa setTransform(), transform() -*/ -void QGraphicsItem::shear(qreal sh, qreal sv) -{ - setTransform(QTransform().shear(sh, sv), true); -} - -/*! - \obsolete - - Use setPos() or setTransformOriginPoint() instead. For identical - behavior, use - - \code - setTransform(QTransform::fromTranslate(dx, dy), true); - \endcode - - Translates the current item transformation by (\a dx, \a dy). - - If all you want is to move an item, you should call moveBy() or - setPos() instead; this function changes the item's translation, - which is conceptually separate from its position. - - \sa setTransform(), transform() -*/ -void QGraphicsItem::translate(qreal dx, qreal dy) -{ - setTransform(QTransform::fromTranslate(dx, dy), true); -} - -/*! - This virtual function is called twice for all items by the - QGraphicsScene::advance() slot. In the first phase, all items are called - with \a phase == 0, indicating that items on the scene are about to - advance, and then all items are called with \a phase == 1. Reimplement - this function to update your item if you need simple scene-controlled - animation. - - The default implementation does nothing. - - For individual item animation, an alternative to this function is to - either use QGraphicsItemAnimation, or to multiple-inherit from QObject and - QGraphicsItem, and animate your item using QObject::startTimer() and - QObject::timerEvent(). - - \sa QGraphicsItemAnimation, QTimeLine -*/ -void QGraphicsItem::advance(int phase) -{ - Q_UNUSED(phase); -} - -/*! - Returns the Z-value of the item. The Z-value affects the stacking order of - sibling (neighboring) items. - - The default Z-value is 0. - - \sa setZValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent -*/ -qreal QGraphicsItem::zValue() const -{ - return d_ptr->z; -} - -/*! - Sets the Z-value of the item to \a z. The Z value decides the stacking - order of sibling (neighboring) items. A sibling item of high Z value will - always be drawn on top of another sibling item with a lower Z value. - - If you restore the Z value, the item's insertion order will decide its - stacking order. - - The Z-value does not affect the item's size in any way. - - The default Z-value is 0. - - \sa zValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent -*/ -void QGraphicsItem::setZValue(qreal z) -{ - const QVariant newZVariant(itemChange(ItemZValueChange, z)); - qreal newZ = newZVariant.toReal(); - if (newZ == d_ptr->z) - return; - - if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) { - // Z Value has changed, we have to notify the index. - d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ); - } - - d_ptr->z = newZ; - if (d_ptr->parent) - d_ptr->parent->d_ptr->needSortChildren = 1; - else if (d_ptr->scene) - d_ptr->scene->d_func()->needSortTopLevelItems = 1; - - if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); - - itemChange(ItemZValueHasChanged, newZVariant); - - if (d_ptr->flags & ItemNegativeZStacksBehindParent) - setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0)); - - if (d_ptr->isObject) - emit static_cast<QGraphicsObject *>(this)->zChanged(); -} - -/*! - \internal - - Ensures that the list of children is sorted by insertion order, and that - the siblingIndexes are packed (no gaps), and start at 0. - - ### This function is almost identical to - QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes(). -*/ -void QGraphicsItemPrivate::ensureSequentialSiblingIndex() -{ - if (!sequentialOrdering) { - qSort(children.begin(), children.end(), insertionOrder); - sequentialOrdering = 1; - needSortChildren = 1; - } - if (holesInSiblingIndex) { - holesInSiblingIndex = 0; - for (int i = 0; i < children.size(); ++i) - children[i]->d_ptr->siblingIndex = i; - } -} - -/*! - \internal -*/ -inline void QGraphicsItemPrivate::sendScenePosChange() -{ - Q_Q(QGraphicsItem); - if (scene) { - if (flags & QGraphicsItem::ItemSendsScenePositionChanges) - q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos()); - if (scenePosDescendants) { - foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) { - if (q->isAncestorOf(item)) - item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos()); - } - } - } -} - -/*! - \since 4.6 - - Stacks this item before \a sibling, which must be a sibling item (i.e., the - two items must share the same parent item, or must both be toplevel items). - The \a sibling must have the same Z value as this item, otherwise calling - this function will have no effect. - - By default, all sibling items are stacked by insertion order (i.e., the - first item you add is drawn before the next item you add). If two items' Z - values are different, then the item with the highest Z value is drawn on - top. When the Z values are the same, the insertion order will decide the - stacking order. - - \sa setZValue(), ItemStacksBehindParent, {QGraphicsItem#Sorting}{Sorting} -*/ -void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) -{ - if (sibling == this) - return; - if (!sibling || d_ptr->parent != sibling->parentItem()) { - qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); - return; - } - QList<QGraphicsItem *> *siblings = d_ptr->parent - ? &d_ptr->parent->d_ptr->children - : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0); - if (!siblings) { - qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); - return; - } - - // First, make sure that the sibling indexes have no holes. This also - // marks the children list for sorting. - if (d_ptr->parent) - d_ptr->parent->d_ptr->ensureSequentialSiblingIndex(); - else - d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes(); - - // Only move items with the same Z value, and that need moving. - int siblingIndex = sibling->d_ptr->siblingIndex; - int myIndex = d_ptr->siblingIndex; - if (myIndex >= siblingIndex) { - siblings->move(myIndex, siblingIndex); - // Fixup the insertion ordering. - for (int i = 0; i < siblings->size(); ++i) { - int &index = siblings->at(i)->d_ptr->siblingIndex; - if (i != siblingIndex && index >= siblingIndex && index <= myIndex) - ++index; - } - d_ptr->siblingIndex = siblingIndex; - for (int i = 0; i < siblings->size(); ++i) { - int &index = siblings->at(i)->d_ptr->siblingIndex; - if (i != siblingIndex && index >= siblingIndex && index <= myIndex) - siblings->at(i)->d_ptr->siblingOrderChange(); - } - d_ptr->siblingOrderChange(); - } -} - -/*! - Returns the bounding rect of this item's descendants (i.e., its - children, their children, etc.) in local coordinates. The - rectangle will contain all descendants after they have been mapped - to local coordinates. If the item has no children, this function - returns an empty QRectF. - - This does not include this item's own bounding rect; it only returns - its descendants' accumulated bounding rect. If you need to include this - item's bounding rect, you can add boundingRect() to childrenBoundingRect() - using QRectF::operator|(). - - This function is linear in complexity; it determines the size of the - returned bounding rect by iterating through all descendants. - - \sa boundingRect(), sceneBoundingRect() -*/ -QRectF QGraphicsItem::childrenBoundingRect() const -{ - if (!d_ptr->dirtyChildrenBoundingRect) - return d_ptr->childrenBoundingRect; - - d_ptr->childrenBoundingRect = QRectF(); - d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect, 0); - d_ptr->dirtyChildrenBoundingRect = 0; - return d_ptr->childrenBoundingRect; -} - -/*! - \fn virtual QRectF QGraphicsItem::boundingRect() const = 0 - - This pure virtual function defines the outer bounds of the item as - a rectangle; all painting must be restricted to inside an item's - bounding rect. QGraphicsView uses this to determine whether the - item requires redrawing. - - Although the item's shape can be arbitrary, the bounding rect is - always rectangular, and it is unaffected by the items' - transformation. - - If you want to change the item's bounding rectangle, you must first call - prepareGeometryChange(). This notifies the scene of the imminent change, - so that its can update its item geometry index; otherwise, the scene will - be unaware of the item's new geometry, and the results are undefined - (typically, rendering artifacts are left around in the view). - - Reimplement this function to let QGraphicsView determine what - parts of the widget, if any, need to be redrawn. - - Note: For shapes that paint an outline / stroke, it is important - to include half the pen width in the bounding rect. It is not - necessary to compensate for antialiasing, though. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 8 - - \sa boundingRegion(), shape(), contains(), {The Graphics View Coordinate - System}, prepareGeometryChange() -*/ - -/*! - Returns the bounding rect of this item in scene coordinates, by combining - sceneTransform() with boundingRect(). - - \sa boundingRect(), {The Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::sceneBoundingRect() const -{ - // Find translate-only offset - // COMBINE - QPointF offset; - const QGraphicsItem *parentItem = this; - const QGraphicsItemPrivate *itemd; - do { - itemd = parentItem->d_ptr.data(); - if (itemd->transformData) - break; - offset += itemd->pos; - } while ((parentItem = itemd->parent)); - - QRectF br = boundingRect(); - br.translate(offset); - if (!parentItem) - return br; - if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) { - br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy()); - return br; - } - return parentItem->d_ptr->sceneTransform.mapRect(br); -} - -/*! - Returns the shape of this item as a QPainterPath in local - coordinates. The shape is used for many things, including collision - detection, hit tests, and for the QGraphicsScene::items() functions. - - The default implementation calls boundingRect() to return a simple - rectangular shape, but subclasses can reimplement this function to return - a more accurate shape for non-rectangular items. For example, a round item - may choose to return an elliptic shape for better collision detection. For - example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 9 - - The outline of a shape can vary depending on the width and style of the - pen used when drawing. If you want to include this outline in the item's - shape, you can create a shape from the stroke using QPainterPathStroker. - - This function is called by the default implementations of contains() and - collidesWithPath(). - - \sa boundingRect(), contains(), prepareGeometryChange(), QPainterPathStroker -*/ -QPainterPath QGraphicsItem::shape() const -{ - QPainterPath path; - path.addRect(boundingRect()); - return path; -} - -/*! - Returns true if this item is clipped. An item is clipped if it has either - set the \l ItemClipsToShape flag, or if it or any of its ancestors has set - the \l ItemClipsChildrenToShape flag. - - Clipping affects the item's appearance (i.e., painting), as well as mouse - and hover event delivery. - - \sa clipPath(), shape(), setFlags() -*/ -bool QGraphicsItem::isClipped() const -{ - Q_D(const QGraphicsItem); - return (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - || (d->flags & QGraphicsItem::ItemClipsToShape); -} - -/*! - \since 4.5 - - Returns this item's clip path, or an empty QPainterPath if this item is - not clipped. The clip path constrains the item's appearance and - interaction (i.e., restricts the area the item can draw, and it also - restricts the area that the item receives events). - - You can enable clipping by setting the ItemClipsToShape or - ItemClipsChildrenToShape flags. The item's clip path is calculated by - intersecting all clipping ancestors' shapes. If the item sets - ItemClipsToShape, the final clip is intersected with the item's own shape. - - \note Clipping introduces a performance penalty for all items involved; - you should generally avoid using clipping if you can (e.g., if your items - always draw inside boundingRect() or shape() boundaries, clipping is not - necessary). - - \sa isClipped(), shape(), setFlags() -*/ -QPainterPath QGraphicsItem::clipPath() const -{ - Q_D(const QGraphicsItem); - if (!isClipped()) - return QPainterPath(); - - const QRectF thisBoundingRect(boundingRect()); - if (thisBoundingRect.isEmpty()) - return QPainterPath(); - - QPainterPath clip; - // Start with the item's bounding rect. - clip.addRect(thisBoundingRect); - - if (d->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - const QGraphicsItem *parent = this; - const QGraphicsItem *lastParent = this; - - // Intersect any in-between clips starting at the top and moving downwards. - while ((parent = parent->d_ptr->parent)) { - if (parent->d_ptr->flags & ItemClipsChildrenToShape) { - // Map clip to the current parent and intersect with its shape/clipPath - clip = lastParent->itemTransform(parent).map(clip); - clip = clip.intersected(parent->shape()); - if (clip.isEmpty()) - return clip; - lastParent = parent; - } - - if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) - break; - } - - if (lastParent != this) { - // Map clip back to the item's transform. - // ### what if itemtransform fails - clip = lastParent->itemTransform(this).map(clip); - } - } - - if (d->flags & ItemClipsToShape) - clip = clip.intersected(shape()); - - return clip; -} - -/*! - Returns true if this item contains \a point, which is in local - coordinates; otherwise, false is returned. It is most often called from - QGraphicsView to determine what item is under the cursor, and for that - reason, the implementation of this function should be as light-weight as - possible. - - By default, this function calls shape(), but you can reimplement it in a - subclass to provide a (perhaps more efficient) implementation. - - \sa shape(), boundingRect(), collidesWithPath() -*/ -bool QGraphicsItem::contains(const QPointF &point) const -{ - return isClipped() ? clipPath().contains(point) : shape().contains(point); -} - -/*! - - Returns true if this item collides with \a other; otherwise - returns false. - - The \a mode is applied to \a other, and the resulting shape or - bounding rectangle is then compared to this item's shape. The - default value for \a mode is Qt::IntersectsItemShape; \a other - collides with this item if it either intersects, contains, or is - contained by this item's shape (see Qt::ItemSelectionMode for - details). - - The default implementation is based on shape intersection, and it calls - shape() on both items. Because the complexity of arbitrary shape-shape - intersection grows with an order of magnitude when the shapes are complex, - this operation can be noticably time consuming. You have the option of - reimplementing this function in a subclass of QGraphicsItem to provide a - custom algorithm. This allows you to make use of natural constraints in - the shapes of your own items, in order to improve the performance of the - collision detection. For instance, two untransformed perfectly circular - items' collision can be determined very efficiently by comparing their - positions and radii. - - Keep in mind that when reimplementing this function and calling shape() or - boundingRect() on \a other, the returned coordinates must be mapped to - this item's coordinate system before any intersection can take place. - - \sa contains(), shape() -*/ -bool QGraphicsItem::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode) const -{ - if (other == this) - return true; - if (!other) - return false; - // The items share the same clip if their closest clipper is the same, or - // if one clips the other. - bool clips = (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren); - bool otherClips = (other->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren); - if (clips || otherClips) { - const QGraphicsItem *closestClipper = isAncestorOf(other) ? this : parentItem(); - while (closestClipper && !(closestClipper->flags() & ItemClipsChildrenToShape)) - closestClipper = closestClipper->parentItem(); - const QGraphicsItem *otherClosestClipper = other->isAncestorOf(this) ? other : other->parentItem(); - while (otherClosestClipper && !(otherClosestClipper->flags() & ItemClipsChildrenToShape)) - otherClosestClipper = otherClosestClipper->parentItem(); - if (closestClipper == otherClosestClipper) { - d_ptr->localCollisionHack = 1; - bool res = collidesWithPath(mapFromItem(other, other->shape()), mode); - d_ptr->localCollisionHack = 0; - return res; - } - } - - QPainterPath otherShape = other->isClipped() ? other->clipPath() : other->shape(); - return collidesWithPath(mapFromItem(other, otherShape), mode); -} - -/*! - Returns true if this item collides with \a path. - - The collision is determined by \a mode. The default value for \a mode is - Qt::IntersectsItemShape; \a path collides with this item if it either - intersects, contains, or is contained by this item's shape. - - Note that this function checks whether the item's shape or - bounding rectangle (depending on \a mode) is contained within \a - path, and not whether \a path is contained within the items shape - or bounding rectangle. - - \sa collidesWithItem(), contains(), shape() -*/ -bool QGraphicsItem::collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode) const -{ - if (path.isEmpty()) { - // No collision with empty paths. - return false; - } - - QRectF rectA(boundingRect()); - _q_adjustRect(&rectA); - QRectF rectB(path.controlPointRect()); - _q_adjustRect(&rectB); - if (!rectA.intersects(rectB)) { - // This we can determine efficiently. If the two rects neither - // intersect nor contain eachother, then the two items do not collide. - return false; - } - - // For further testing, we need this item's shape or bounding rect. - QPainterPath thisShape; - if (mode == Qt::IntersectsItemShape || mode == Qt::ContainsItemShape) - thisShape = (isClipped() && !d_ptr->localCollisionHack) ? clipPath() : shape(); - else - thisShape.addRect(rectA); - - if (thisShape == QPainterPath()) { - // Empty shape? No collision. - return false; - } - - // Use QPainterPath boolean operations to determine the collision, O(N*logN). - if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) - return path.intersects(thisShape); - return path.contains(thisShape); -} - -/*! - Returns a list of all items that collide with this item. - - The way collisions are detected is determined by applying \a mode - to items that are compared to this item, i.e., each item's shape - or bounding rectangle is checked against this item's shape. The - default value for \a mode is Qt::IntersectsItemShape. - - \sa collidesWithItem() -*/ -QList<QGraphicsItem *> QGraphicsItem::collidingItems(Qt::ItemSelectionMode mode) const -{ - if (d_ptr->scene) - return d_ptr->scene->collidingItems(this, mode); - return QList<QGraphicsItem *>(); -} - -/*! - Returns true if this item's bounding rect is completely obscured by the - opaque shape of any of colliding items above it (i.e., with a higher Z - value than this item). - - Its implementation is based on calling isObscuredBy(), which you can - reimplement to provide a custom obscurity algorithm. - - \sa opaqueArea() -*/ -bool QGraphicsItem::isObscured() const -{ - return isObscured(QRectF()); -} - -/*! - \internal - - Item obscurity helper function. - - Returns true if the subrect \a rect of \a item's bounding rect is obscured - by \a other (i.e., \a other's opaque area covers \a item's \a rect - completely. \a other is assumed to already be "on top of" \a item - wrt. stacking order. -*/ -static bool qt_QGraphicsItem_isObscured(const QGraphicsItem *item, - const QGraphicsItem *other, - const QRectF &rect) -{ - return other->mapToItem(item, other->opaqueArea()).contains(rect); -} - -/*! - \overload - \since 4.3 - - Returns true if \a rect is completely obscured by the opaque shape of any - of colliding items above it (i.e., with a higher Z value than this item). - - Unlike the default isObscured() function, this function does not call - isObscuredBy(). - - \sa opaqueArea() -*/ -bool QGraphicsItem::isObscured(const QRectF &rect) const -{ - Q_D(const QGraphicsItem); - if (!d->scene) - return false; - - QRectF br = boundingRect(); - QRectF testRect = rect.isNull() ? br : rect; - - foreach (QGraphicsItem *item, d->scene->items(mapToScene(br), Qt::IntersectsItemBoundingRect)) { - if (item == this) - break; - if (qt_QGraphicsItem_isObscured(this, item, testRect)) - return true; - } - return false; -} - -/*! - \fn bool QGraphicsItem::isObscured(qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling isObscured(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Returns true if this item's bounding rect is completely obscured by the - opaque shape of \a item. - - The base implementation maps \a item's opaqueArea() to this item's - coordinate system, and then checks if this item's boundingRect() is fully - contained within the mapped shape. - - You can reimplement this function to provide a custom algorithm for - determining whether this item is obscured by \a item. - - \sa opaqueArea(), isObscured() -*/ -bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const -{ - if (!item) - return false; - return qt_closestItemFirst(item, this) - && qt_QGraphicsItem_isObscured(this, item, boundingRect()); -} - -/*! - This virtual function returns a shape representing the area where this - item is opaque. An area is opaque if it is filled using an opaque brush or - color (i.e., not transparent). - - This function is used by isObscuredBy(), which is called by underlying - items to determine if they are obscured by this item. - - The default implementation returns an empty QPainterPath, indicating that - this item is completely transparent and does not obscure any other items. - - \sa isObscuredBy(), isObscured(), shape() -*/ -QPainterPath QGraphicsItem::opaqueArea() const -{ - return QPainterPath(); -} - -/*! - \since 4.4 - - Returns the bounding region for this item. The coordinate space of the - returned region depends on \a itemToDeviceTransform. If you pass an - identity QTransform as a parameter, this function will return a local - coordinate region. - - The bounding region describes a coarse outline of the item's visual - contents. Although it's expensive to calculate, it's also more precise - than boundingRect(), and it can help to avoid unnecessary repainting when - an item is updated. This is particularly efficient for thin items (e.g., - lines or simple polygons). You can tune the granularity for the bounding - region by calling setBoundingRegionGranularity(). The default granularity - is 0; in which the item's bounding region is the same as its bounding - rect. - - \a itemToDeviceTransform is the transformation from item coordinates to - device coordinates. If you want this function to return a QRegion in scene - coordinates, you can pass sceneTransform() as an argument. - - \sa boundingRegionGranularity() -*/ -QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) const -{ - // ### Ideally we would have a better way to generate this region, - // preferably something in the lines of QPainterPath::toRegion(QTransform) - // coupled with a way to generate a painter path from a set of painter - // operations (e.g., QPicture::toPainterPath() or so). The current - // approach generates a bitmap with the size of the item's bounding rect - // in device coordinates, scaled by b.r.granularity, then paints the item - // into the bitmap, converts the result to a QRegion and scales the region - // back to device space with inverse granularity. - qreal granularity = boundingRegionGranularity(); - QRect deviceRect = itemToDeviceTransform.mapRect(boundingRect()).toRect(); - _q_adjustRect(&deviceRect); - if (granularity == 0.0) - return QRegion(deviceRect); - - int pad = 1; - QSize bitmapSize(qMax(1, int(deviceRect.width() * granularity) + pad * 2), - qMax(1, int(deviceRect.height() * granularity) + pad * 2)); - QImage mask(bitmapSize, QImage::Format_ARGB32_Premultiplied); - mask.fill(0); - QPainter p(&mask); - p.setRenderHints(QPainter::Antialiasing); - - // Transform painter (### this code is from QGraphicsScene::drawItemHelper - // and doesn't work properly with perspective transformations). - QPointF viewOrigo = itemToDeviceTransform.map(QPointF(0, 0)); - QPointF offset = viewOrigo - deviceRect.topLeft(); - p.scale(granularity, granularity); - p.translate(offset); - p.translate(pad, pad); - p.setWorldTransform(itemToDeviceTransform, true); - p.translate(itemToDeviceTransform.inverted().map(QPointF(0, 0))); - - // Render - QStyleOptionGraphicsItem option; - const_cast<QGraphicsItem *>(this)->paint(&p, &option, 0); - p.end(); - - // Transform QRegion back to device space - QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity); - QRegion r; - QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0)); - foreach (const QRect &rect, QRegion( colorMask ).rects()) { - QRect xrect = unscale.mapRect(rect).translated(deviceRect.topLeft() - QPoint(pad, pad)); - r += xrect.adjusted(-1, -1, 1, 1) & deviceRect; - } - return r; -} - -/*! - \since 4.4 - - Returns the item's bounding region granularity; a value between and - including 0 and 1. The default value is 0 (i.e., the lowest granularity, - where the bounding region corresponds to the item's bounding rectangle). - -\omit -### NOTE -\endomit - - \sa setBoundingRegionGranularity() -*/ -qreal QGraphicsItem::boundingRegionGranularity() const -{ - return d_ptr->hasBoundingRegionGranularity - ? qvariant_cast<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) - : 0; -} - -/*! - \since 4.4 - Sets the bounding region granularity to \a granularity; a value between - and including 0 and 1. The default value is 0 (i.e., the lowest - granularity, where the bounding region corresponds to the item's bounding - rectangle). - - The granularity is used by boundingRegion() to calculate how fine the - bounding region of the item should be. The highest achievable granularity - is 1, where boundingRegion() will return the finest outline possible for - the respective device (e.g., for a QGraphicsView viewport, this gives you - a pixel-perfect bounding region). The lowest possible granularity is - 0. The value of \a granularity describes the ratio between device - resolution and the resolution of the bounding region (e.g., a value of - 0.25 will provide a region where each chunk corresponds to 4x4 device - units / pixels). - - \sa boundingRegionGranularity() -*/ -void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) -{ - if (granularity < 0.0 || granularity > 1.0) { - qWarning("QGraphicsItem::setBoundingRegionGranularity: invalid granularity %g", granularity); - return; - } - if (granularity == 0.0) { - d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity); - d_ptr->hasBoundingRegionGranularity = 0; - return; - } - d_ptr->hasBoundingRegionGranularity = 1; - d_ptr->setExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity, - QVariant::fromValue<qreal>(granularity)); -} - -/*! - \fn virtual void QGraphicsItem::paint(QPainter *painter, const - QStyleOptionGraphicsItem *option, QWidget *widget = 0) = 0 - - This function, which is usually called by QGraphicsView, paints the - contents of an item in local coordinates. - - Reimplement this function in a QGraphicsItem subclass to provide the - item's painting implementation, using \a painter. The \a option parameter - provides style options for the item, such as its state, exposed area and - its level-of-detail hints. The \a widget argument is optional. If - provided, it points to the widget that is being painted on; otherwise, it - is 0. For cached painting, \a widget is always 0. - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 10 - - The painter's pen is 0-width by default, and its pen is initialized to the - QPalette::Text brush from the paint device's palette. The brush is - initialized to QPalette::Window. - - Make sure to constrain all painting inside the boundaries of - boundingRect() to avoid rendering artifacts (as QGraphicsView does not - clip the painter for you). In particular, when QPainter renders the - outline of a shape using an assigned QPen, half of the outline will be - drawn outside, and half inside, the shape you're rendering (e.g., with a - pen width of 2 units, you must draw outlines 1 unit inside - boundingRect()). QGraphicsItem does not support use of cosmetic pens with - a non-zero width. - - All painting is done in local coordinates. - - \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption -*/ - -/*! - \internal - Returns true if we can discard an update request; otherwise false. -*/ -bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreVisibleBit, bool ignoreDirtyBit, - bool ignoreOpacity) const -{ - // No scene, or if the scene is updating everything, means we have nothing - // to do. The only exception is if the scene tracks the growing scene rect. - return !scene - || (!visible && !ignoreVisibleBit && !this->ignoreVisible) - || (!ignoreDirtyBit && fullUpdatePending) - || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); -} - -/*! - \internal -*/ -int QGraphicsItemPrivate::depth() const -{ - if (itemDepth == -1) - const_cast<QGraphicsItemPrivate *>(this)->resolveDepth(); - - return itemDepth; -} - -/*! - \internal -*/ -#ifndef QT_NO_GRAPHICSEFFECT -void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively() -{ - QGraphicsItemPrivate *itemPrivate = this; - do { - if (itemPrivate->graphicsEffect) { - itemPrivate->notifyInvalidated = 1; - - if (!itemPrivate->updateDueToGraphicsEffect) - static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache(); - } - } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); -} - -void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason) -{ - if (!mayHaveChildWithGraphicsEffect) - return; - - for (int i = 0; i < children.size(); ++i) { - QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data(); - if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity)) - continue; - if (childPrivate->graphicsEffect) { - childPrivate->notifyInvalidated = 1; - static_cast<QGraphicsItemEffectSourcePrivate *>(childPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache(); - } - - childPrivate->invalidateChildGraphicsEffectsRecursively(reason); - } -} -#endif //QT_NO_GRAPHICSEFFECT - -/*! - \internal -*/ -void QGraphicsItemPrivate::invalidateDepthRecursively() -{ - if (itemDepth == -1) - return; - - itemDepth = -1; - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->invalidateDepthRecursively(); -} - -/*! - \internal - - Resolves the stacking depth of this object and all its ancestors. -*/ -void QGraphicsItemPrivate::resolveDepth() -{ - if (!parent) - itemDepth = 0; - else { - if (parent->d_ptr->itemDepth == -1) - parent->d_ptr->resolveDepth(); - itemDepth = parent->d_ptr->itemDepth + 1; - } -} - -/*! - \internal - - ### This function is almost identical to - QGraphicsScenePrivate::registerTopLevelItem(). -*/ -void QGraphicsItemPrivate::addChild(QGraphicsItem *child) -{ - // Remove all holes from the sibling index list. Now the max index - // number is equal to the size of the children list. - ensureSequentialSiblingIndex(); - needSortChildren = 1; // ### maybe 0 - child->d_ptr->siblingIndex = children.size(); - children.append(child); - if (isObject) - emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged(); -} - -/*! - \internal - - ### This function is almost identical to - QGraphicsScenePrivate::unregisterTopLevelItem(). -*/ -void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) -{ - // When removing elements in the middle of the children list, - // there will be a "gap" in the list of sibling indexes (0,1,3,4). - if (!holesInSiblingIndex) - holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1; - if (sequentialOrdering && !holesInSiblingIndex) - children.removeAt(child->d_ptr->siblingIndex); - else - children.removeOne(child); - // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because - // the child is not guaranteed to be at the index after the list is sorted. - // (see ensureSortedChildren()). - child->d_ptr->siblingIndex = -1; - if (isObject) - emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged(); -} - -/*! - \internal -*/ -QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const -{ - return (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); -} - -/*! - \internal -*/ -QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const -{ - QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); - if (!c) { - QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this); - c = new QGraphicsItemCache; - that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c)); - } - return c; -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::removeExtraItemCache() -{ - QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); - if (c) { - c->purge(); - delete c; - } - unsetExtra(ExtraCacheData); -} - -void QGraphicsItemPrivate::updatePaintedViewBoundingRects(bool updateChildren) -{ - if (!scene) - return; - - for (int i = 0; i < scene->d_func()->views.size(); ++i) { - QGraphicsViewPrivate *viewPrivate = scene->d_func()->views.at(i)->d_func(); - QRect rect = paintedViewBoundingRects.value(viewPrivate->viewport); - rect.translate(viewPrivate->dirtyScrollOffset); - viewPrivate->updateRect(rect); - } - - if (updateChildren) { - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->updatePaintedViewBoundingRects(true); - } -} - -// Traverses all the ancestors up to the top-level and updates the pointer to -// always point to the top-most item that has a dirty scene transform. -// It then backtracks to the top-most dirty item and start calculating the -// scene transform by combining the item's transform (+pos) with the parent's -// cached scene transform (which we at this point know for sure is valid). -void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem) -{ - Q_ASSERT(topMostDirtyItem); - - if (dirtySceneTransform) - *topMostDirtyItem = q_ptr; - - if (parent) - parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem); - - if (*topMostDirtyItem == q_ptr) { - if (!dirtySceneTransform) - return; // OK, neither my ancestors nor I have dirty scene transforms. - *topMostDirtyItem = 0; - } else if (*topMostDirtyItem) { - return; // Continue backtrack. - } - - // This item and all its descendants have dirty scene transforms. - // We're about to validate this item's scene transform, so we have to - // invalidate all the children; otherwise there's no way for the descendants - // to detect that the ancestor has changed. - invalidateChildrenSceneTransform(); - - // COMBINE my transform with the parent's scene transform. - updateSceneTransformFromParent(); - Q_ASSERT(!dirtySceneTransform); -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem, QGraphicsItem *stopItem) -{ - // Update focus child chain. Stop at panels, or if this item - // is hidden, stop at the first item with a visible parent. - QGraphicsItem *parent = rootItem ? rootItem : q_ptr; - if (parent->panel() != q_ptr->panel()) - return; - - do { - // Clear any existing ancestor's subFocusItem. - if (parent != q_ptr && parent->d_ptr->subFocusItem) { - if (parent->d_ptr->subFocusItem == q_ptr) - break; - parent->d_ptr->subFocusItem->d_ptr->clearSubFocus(0, stopItem); - } - parent->d_ptr->subFocusItem = q_ptr; - parent->d_ptr->subFocusItemChange(); - } while (!parent->isPanel() && (parent = parent->d_ptr->parent) && (visible || !parent->d_ptr->visible)); - - if (scene && !scene->isActive()) { - scene->d_func()->passiveFocusItem = subFocusItem; - scene->d_func()->lastFocusItem = subFocusItem; - } -} - -/*! - \internal -*/ -void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem, QGraphicsItem *stopItem) -{ - // Reset sub focus chain. - QGraphicsItem *parent = rootItem ? rootItem : q_ptr; - do { - if (parent->d_ptr->subFocusItem != q_ptr) - break; - parent->d_ptr->subFocusItem = 0; - if (parent != stopItem && !parent->isAncestorOf(stopItem)) - parent->d_ptr->subFocusItemChange(); - } while (!parent->isPanel() && (parent = parent->d_ptr->parent)); -} - -/*! - \internal - - Sets the focusProxy pointer to 0 for all items that have this item as their - focusProxy. ### Qt 5: Use QPointer instead. -*/ -void QGraphicsItemPrivate::resetFocusProxy() -{ - for (int i = 0; i < focusProxyRefs.size(); ++i) - *focusProxyRefs.at(i) = 0; - focusProxyRefs.clear(); -} - -/*! - \internal - - Subclasses can reimplement this function to be notified when subFocusItem - changes. -*/ -void QGraphicsItemPrivate::subFocusItemChange() -{ -} - -/*! - \internal - - Subclasses can reimplement this function to be notified when an item - becomes a focusScopeItem (or is no longer a focusScopeItem). -*/ -void QGraphicsItemPrivate::focusScopeItemChange(bool isSubFocusItem) -{ - Q_UNUSED(isSubFocusItem); -} - -/*! - \internal - - Subclasses can reimplement this function to be notified when its - siblingIndex order is changed. -*/ -void QGraphicsItemPrivate::siblingOrderChange() -{ -} - -/*! - \internal - - Tells us if it is a proxy widget -*/ -bool QGraphicsItemPrivate::isProxyWidget() const -{ - return false; -} - -/*! - Schedules a redraw of the area covered by \a rect in this item. You can - call this function whenever your item needs to be redrawn, such as if it - changes appearance or size. - - This function does not cause an immediate paint; instead it schedules a - paint request that is processed by QGraphicsView after control reaches the - event loop. The item will only be redrawn if it is visible in any - associated view. - - As a side effect of the item being repainted, other items that overlap the - area \a rect may also be repainted. - - If the item is invisible (i.e., isVisible() returns false), this function - does nothing. - - \sa paint(), boundingRect() -*/ -void QGraphicsItem::update(const QRectF &rect) -{ - if (rect.isEmpty() && !rect.isNull()) - return; - - // Make sure we notify effects about invalidated source. -#ifndef QT_NO_GRAPHICSEFFECT - d_ptr->invalidateParentGraphicsEffectsRecursively(); -#endif //QT_NO_GRAPHICSEFFECT - - if (CacheMode(d_ptr->cacheMode) != NoCache) { - // Invalidate cache. - QGraphicsItemCache *cache = d_ptr->extraItemCache(); - if (!cache->allExposed) { - if (rect.isNull()) { - cache->allExposed = true; - cache->exposed.clear(); - } else { - cache->exposed.append(rect); - } - } - // Only invalidate cache; item is already dirty. - if (d_ptr->fullUpdatePending) - return; - } - - if (d_ptr->scene) - d_ptr->scene->d_func()->markDirty(this, rect); -} - -/*! - \since 4.4 - Scrolls the contents of \a rect by \a dx, \a dy. If \a rect is a null rect - (the default), the item's bounding rect is scrolled. - - Scrolling provides a fast alternative to simply redrawing when the - contents of the item (or parts of the item) are shifted vertically or - horizontally. Depending on the current transformation and the capabilities - of the paint device (i.e., the viewport), this operation may consist of - simply moving pixels from one location to another using memmove(). In most - cases this is faster than rerendering the entire area. - - After scrolling, the item will issue an update for the newly exposed - areas. If scrolling is not supported (e.g., you are rendering to an OpenGL - viewport, which does not benefit from scroll optimizations), this function - is equivalent to calling update(\a rect). - - \bold{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache - is enabled; in all other cases calling this function is equivalent to calling - update(\a rect). If you for sure know that the item is opaque and not overlapped - by other items, you can map the \a rect to viewport coordinates and scroll the - viewport. - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 19 - - \sa boundingRect() -*/ -void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) -{ - Q_D(QGraphicsItem); - if (dx == 0.0 && dy == 0.0) - return; - if (!d->scene) - return; - - // Accelerated scrolling means moving pixels from one location to another - // and only redraw the newly exposed area. The following requirements must - // be fulfilled in order to do that: - // - // 1) Item is opaque. - // 2) Item is not overlapped by other items. - // - // There's (yet) no way to detect whether an item is opaque or not, which means - // we cannot do accelerated scrolling unless the cache is enabled. In case of using - // DeviceCoordinate cache we also have to take the device transform into account in - // order to determine whether we can do accelerated scrolling or not. That's left out - // for simplicity here, but it is definitely something we can consider in the future - // as a performance improvement. - if (d->cacheMode != QGraphicsItem::ItemCoordinateCache - || !qFuzzyIsNull(dx - int(dx)) || !qFuzzyIsNull(dy - int(dy))) { - update(rect); - return; - } - - QGraphicsItemCache *cache = d->extraItemCache(); - if (cache->allExposed || cache->fixedSize.isValid()) { - // Cache is either invalidated or item is scaled (see QGraphicsItem::setCacheMode). - update(rect); - return; - } - - // Find pixmap in cache. - QPixmap cachedPixmap; - if (!QPixmapCache::find(cache->key, &cachedPixmap)) { - update(rect); - return; - } - - QRect scrollRect = (rect.isNull() ? boundingRect() : rect).toAlignedRect(); - if (!scrollRect.intersects(cache->boundingRect)) - return; // Nothing to scroll. - - // Remove from cache to avoid deep copy when modifying. - QPixmapCache::remove(cache->key); - - QRegion exposed; - cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed); - - // Reinsert into cache. - cache->key = QPixmapCache::insert(cachedPixmap); - - // Translate the existing expose. - for (int i = 0; i < cache->exposed.size(); ++i) { - QRectF &e = cache->exposed[i]; - if (!rect.isNull() && !e.intersects(rect)) - continue; - e.translate(dx, dy); - } - - // Append newly exposed areas. Note that the exposed region is currently - // in pixmap coordinates, so we have to translate it to item coordinates. - exposed.translate(cache->boundingRect.topLeft()); - const QVector<QRect> exposedRects = exposed.rects(); - for (int i = 0; i < exposedRects.size(); ++i) - cache->exposed += exposedRects.at(i); - - // Trigger update. This will redraw the newly exposed area and make sure - // the pixmap is re-blitted in case there are overlapping items. - d->scene->d_func()->markDirty(this, rect); -} - -/*! - \fn void QGraphicsItem::update(qreal x, qreal y, qreal width, qreal height) - \overload - - This convenience function is equivalent to calling update(QRectF(\a x, \a - y, \a width, \a height)). -*/ - -/*! - Maps the point \a point, which is in this item's coordinate system, to \a - item's coordinate system, and returns the mapped coordinate. - - If \a item is 0, this function returns the same as mapToScene(). - - \sa itemTransform(), mapToParent(), mapToScene(), transform(), mapFromItem(), {The Graphics - View Coordinate System} -*/ -QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point) const -{ - if (item) - return itemTransform(item).map(point); - return mapToScene(point); -} - -/*! - \fn QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal x, qreal y) const - \overload - - This convenience function is equivalent to calling mapToItem(\a item, - QPointF(\a x, \a y)). -*/ - -/*! - Maps the point \a point, which is in this item's coordinate system, to its - parent's coordinate system, and returns the mapped coordinate. If the item - has no parent, \a point will be mapped to the scene's coordinate system. - - \sa mapToItem(), mapToScene(), transform(), mapFromParent(), {The Graphics - View Coordinate System} -*/ -QPointF QGraphicsItem::mapToParent(const QPointF &point) const -{ - // COMBINE - if (!d_ptr->transformData) - return point + d_ptr->pos; - return d_ptr->transformToParent().map(point); -} - -/*! - \fn QPointF QGraphicsItem::mapToParent(qreal x, qreal y) const - \overload - - This convenience function is equivalent to calling mapToParent(QPointF(\a - x, \a y)). -*/ - -/*! - Maps the point \a point, which is in this item's coordinate system, to the - scene's coordinate system, and returns the mapped coordinate. - - \sa mapToItem(), mapToParent(), transform(), mapFromScene(), {The Graphics - View Coordinate System} -*/ -QPointF QGraphicsItem::mapToScene(const QPointF &point) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.map(point); -} - -/*! - \fn QPointF QGraphicsItem::mapToScene(qreal x, qreal y) const - \overload - - This convenience function is equivalent to calling mapToScene(QPointF(\a - x, \a y)). -*/ - -/*! - Maps the rectangle \a rect, which is in this item's coordinate system, to - \a item's coordinate system, and returns the mapped rectangle as a polygon. - - If \a item is 0, this function returns the same as mapToScene(). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect) const -{ - if (item) - return itemTransform(item).map(rect); - return mapToScene(rect); -} - -/*! - \fn QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling mapToItem(item, QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Maps the rectangle \a rect, which is in this item's coordinate system, to - its parent's coordinate system, and returns the mapped rectangle as a - polygon. If the item has no parent, \a rect will be mapped to the scene's - coordinate system. - - \sa mapToScene(), mapToItem(), mapFromParent(), {The Graphics View - Coordinate System} -*/ -QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const -{ - // COMBINE - if (!d_ptr->transformData) - return rect.translated(d_ptr->pos); - return d_ptr->transformToParent().map(rect); -} - -/*! - \fn QPolygonF QGraphicsItem::mapToParent(qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling mapToParent(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Maps the rectangle \a rect, which is in this item's coordinate system, to - the scene's coordinate system, and returns the mapped rectangle as a polygon. - - \sa mapToParent(), mapToItem(), mapFromScene(), {The Graphics View - Coordinate System} -*/ -QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.map(rect); -} - -/*! - \fn QPolygonF QGraphicsItem::mapToScene(qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling mapToScene(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - \since 4.5 - - Maps the rectangle \a rect, which is in this item's coordinate system, to - \a item's coordinate system, and returns the mapped rectangle as a new - rectangle (i.e., the bounding rectangle of the resulting polygon). - - If \a item is 0, this function returns the same as mapRectToScene(). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rect) const -{ - if (item) - return itemTransform(item).mapRect(rect); - return mapRectToScene(rect); -} - -/*! - \fn QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const - \since 4.5 - - This convenience function is equivalent to calling mapRectToItem(item, QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - \since 4.5 - - Maps the rectangle \a rect, which is in this item's coordinate system, to - its parent's coordinate system, and returns the mapped rectangle as a new - rectangle (i.e., the bounding rectangle of the resulting polygon). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const -{ - // COMBINE - if (!d_ptr->transformData) - return rect.translated(d_ptr->pos); - return d_ptr->transformToParent().mapRect(rect); -} - -/*! - \fn QRectF QGraphicsItem::mapRectToParent(qreal x, qreal y, qreal w, qreal h) const - \since 4.5 - - This convenience function is equivalent to calling mapRectToParent(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - \since 4.5 - - Maps the rectangle \a rect, which is in this item's coordinate system, to - the scene coordinate system, and returns the mapped rectangle as a new - rectangle (i.e., the bounding rectangle of the resulting polygon). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.mapRect(rect); -} - -/*! - \fn QRectF QGraphicsItem::mapRectToScene(qreal x, qreal y, qreal w, qreal h) const - \since 4.5 - - This convenience function is equivalent to calling mapRectToScene(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - \since 4.5 - - Maps the rectangle \a rect, which is in \a item's coordinate system, to - this item's coordinate system, and returns the mapped rectangle as a new - rectangle (i.e., the bounding rectangle of the resulting polygon). - - If \a item is 0, this function returns the same as mapRectFromScene(). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &rect) const -{ - if (item) - return item->itemTransform(this).mapRect(rect); - return mapRectFromScene(rect); -} - -/*! - \fn QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const - \since 4.5 - - This convenience function is equivalent to calling mapRectFromItem(item, QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - \since 4.5 - - Maps the rectangle \a rect, which is in this item's parent's coordinate - system, to this item's coordinate system, and returns the mapped rectangle - as a new rectangle (i.e., the bounding rectangle of the resulting - polygon). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const -{ - // COMBINE - if (!d_ptr->transformData) - return rect.translated(-d_ptr->pos); - return d_ptr->transformToParent().inverted().mapRect(rect); -} - -/*! - \fn QRectF QGraphicsItem::mapRectFromParent(qreal x, qreal y, qreal w, qreal h) const - \since 4.5 - - This convenience function is equivalent to calling mapRectFromParent(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - \since 4.5 - - Maps the rectangle \a rect, which is in scene coordinates, to this item's - coordinate system, and returns the mapped rectangle as a new rectangle - (i.e., the bounding rectangle of the resulting polygon). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.inverted().mapRect(rect); -} - -/*! - \fn QRectF QGraphicsItem::mapRectFromScene(qreal x, qreal y, qreal w, qreal h) const - \since 4.5 - - This convenience function is equivalent to calling mapRectFromScene(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Maps the polygon \a polygon, which is in this item's coordinate system, to - \a item's coordinate system, and returns the mapped polygon. - - If \a item is 0, this function returns the same as mapToScene(). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &polygon) const -{ - if (item) - return itemTransform(item).map(polygon); - return mapToScene(polygon); -} - -/*! - Maps the polygon \a polygon, which is in this item's coordinate system, to - its parent's coordinate system, and returns the mapped polygon. If the - item has no parent, \a polygon will be mapped to the scene's coordinate - system. - - \sa mapToScene(), mapToItem(), mapFromParent(), {The Graphics View - Coordinate System} -*/ -QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const -{ - // COMBINE - if (!d_ptr->transformData) - return polygon.translated(d_ptr->pos); - return d_ptr->transformToParent().map(polygon); -} - -/*! - Maps the polygon \a polygon, which is in this item's coordinate system, to - the scene's coordinate system, and returns the mapped polygon. - - \sa mapToParent(), mapToItem(), mapFromScene(), {The Graphics View - Coordinate System} -*/ -QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.map(polygon); -} - -/*! - Maps the path \a path, which is in this item's coordinate system, to - \a item's coordinate system, and returns the mapped path. - - If \a item is 0, this function returns the same as mapToScene(). - - \sa itemTransform(), mapToParent(), mapToScene(), mapFromItem(), {The - Graphics View Coordinate System} -*/ -QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterPath &path) const -{ - if (item) - return itemTransform(item).map(path); - return mapToScene(path); -} - -/*! - Maps the path \a path, which is in this item's coordinate system, to - its parent's coordinate system, and returns the mapped path. If the - item has no parent, \a path will be mapped to the scene's coordinate - system. - - \sa mapToScene(), mapToItem(), mapFromParent(), {The Graphics View - Coordinate System} -*/ -QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const -{ - // COMBINE - if (!d_ptr->transformData) - return path.translated(d_ptr->pos); - return d_ptr->transformToParent().map(path); -} - -/*! - Maps the path \a path, which is in this item's coordinate system, to - the scene's coordinate system, and returns the mapped path. - - \sa mapToParent(), mapToItem(), mapFromScene(), {The Graphics View - Coordinate System} -*/ -QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.map(path); -} - -/*! - Maps the point \a point, which is in \a item's coordinate system, to this - item's coordinate system, and returns the mapped coordinate. - - If \a item is 0, this function returns the same as mapFromScene(). - - \sa itemTransform(), mapFromParent(), mapFromScene(), transform(), mapToItem(), {The Graphics - View Coordinate System} -*/ -QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &point) const -{ - if (item) - return item->itemTransform(this).map(point); - return mapFromScene(point); -} - -/*! - \fn QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, qreal x, qreal y) const - \overload - - This convenience function is equivalent to calling mapFromItem(\a item, - QPointF(\a x, \a y)). -*/ - -/*! - Maps the point \a point, which is in this item's parent's coordinate - system, to this item's coordinate system, and returns the mapped - coordinate. - - \sa mapFromItem(), mapFromScene(), transform(), mapToParent(), {The Graphics - View Coordinate System} -*/ -QPointF QGraphicsItem::mapFromParent(const QPointF &point) const -{ - // COMBINE - if (d_ptr->transformData) - return d_ptr->transformToParent().inverted().map(point); - return point - d_ptr->pos; -} - -/*! - \fn QPointF QGraphicsItem::mapFromParent(qreal x, qreal y) const - \overload - - This convenience function is equivalent to calling - mapFromParent(QPointF(\a x, \a y)). -*/ - -/*! - Maps the point \a point, which is in this item's scene's coordinate - system, to this item's coordinate system, and returns the mapped - coordinate. - - \sa mapFromItem(), mapFromParent(), transform(), mapToScene(), {The Graphics - View Coordinate System} -*/ -QPointF QGraphicsItem::mapFromScene(const QPointF &point) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.inverted().map(point); -} - -/*! - \fn QPointF QGraphicsItem::mapFromScene(qreal x, qreal y) const - \overload - - This convenience function is equivalent to calling mapFromScene(QPointF(\a - x, \a y)). -*/ - -/*! - Maps the rectangle \a rect, which is in \a item's coordinate system, to - this item's coordinate system, and returns the mapped rectangle as a - polygon. - - If \a item is 0, this function returns the same as mapFromScene() - - \sa itemTransform(), mapToItem(), mapFromParent(), transform(), {The Graphics View Coordinate - System} -*/ -QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &rect) const -{ - if (item) - return item->itemTransform(this).map(rect); - return mapFromScene(rect); -} - -/*! - \fn QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling mapFromItem(item, QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Maps the rectangle \a rect, which is in this item's parent's coordinate - system, to this item's coordinate system, and returns the mapped rectangle - as a polygon. - - \sa mapToParent(), mapFromItem(), transform(), {The Graphics View Coordinate - System} -*/ -QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const -{ - // COMBINE - if (!d_ptr->transformData) - return rect.translated(-d_ptr->pos); - return d_ptr->transformToParent().inverted().map(rect); -} - -/*! - \fn QPolygonF QGraphicsItem::mapFromParent(qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling mapFromItem(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Maps the rectangle \a rect, which is in this item's scene's coordinate - system, to this item's coordinate system, and returns the mapped rectangle - as a polygon. - - \sa mapToScene(), mapFromItem(), transform(), {The Graphics View Coordinate - System} -*/ -QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.inverted().map(rect); -} - -/*! - \fn QPolygonF QGraphicsItem::mapFromScene(qreal x, qreal y, qreal w, qreal h) const - \since 4.3 - - This convenience function is equivalent to calling mapFromScene(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Maps the polygon \a polygon, which is in \a item's coordinate system, to - this item's coordinate system, and returns the mapped polygon. - - If \a item is 0, this function returns the same as mapFromScene(). - - \sa itemTransform(), mapToItem(), mapFromParent(), transform(), {The - Graphics View Coordinate System} -*/ -QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF &polygon) const -{ - if (item) - return item->itemTransform(this).map(polygon); - return mapFromScene(polygon); -} - -/*! - Maps the polygon \a polygon, which is in this item's parent's coordinate - system, to this item's coordinate system, and returns the mapped polygon. - - \sa mapToParent(), mapToItem(), transform(), {The Graphics View Coordinate - System} -*/ -QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const -{ - // COMBINE - if (!d_ptr->transformData) - return polygon.translated(-d_ptr->pos); - return d_ptr->transformToParent().inverted().map(polygon); -} - -/*! - Maps the polygon \a polygon, which is in this item's scene's coordinate - system, to this item's coordinate system, and returns the mapped polygon. - - \sa mapToScene(), mapFromParent(), transform(), {The Graphics View Coordinate - System} -*/ -QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.inverted().map(polygon); -} - -/*! - Maps the path \a path, which is in \a item's coordinate system, to - this item's coordinate system, and returns the mapped path. - - If \a item is 0, this function returns the same as mapFromScene(). - - \sa itemTransform(), mapFromParent(), mapFromScene(), mapToItem(), {The - Graphics View Coordinate System} -*/ -QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainterPath &path) const -{ - if (item) - return item->itemTransform(this).map(path); - return mapFromScene(path); -} - -/*! - Maps the path \a path, which is in this item's parent's coordinate - system, to this item's coordinate system, and returns the mapped path. - - \sa mapFromScene(), mapFromItem(), mapToParent(), {The Graphics View - Coordinate System} -*/ -QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const -{ - // COMBINE - if (!d_ptr->transformData) - return path.translated(-d_ptr->pos); - return d_ptr->transformToParent().inverted().map(path); -} - -/*! - Maps the path \a path, which is in this item's scene's coordinate - system, to this item's coordinate system, and returns the mapped path. - - \sa mapFromParent(), mapFromItem(), mapToScene(), {The Graphics View - Coordinate System} -*/ -QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const -{ - if (d_ptr->hasTranslateOnlySceneTransform()) - return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); - return d_ptr->sceneTransform.inverted().map(path); -} - -/*! - Returns true if this item is an ancestor of \a child (i.e., if this item - is \a child's parent, or one of \a child's parent's ancestors). - - \sa parentItem() -*/ -bool QGraphicsItem::isAncestorOf(const QGraphicsItem *child) const -{ - if (!child || child == this) - return false; - if (child->d_ptr->depth() < d_ptr->depth()) - return false; - const QGraphicsItem *ancestor = child; - while ((ancestor = ancestor->d_ptr->parent)) { - if (ancestor == this) - return true; - } - return false; -} - -/*! - \since 4.4 - - Returns the closest common ancestor item of this item and \a other, or 0 - if either \a other is 0, or there is no common ancestor. - - \sa isAncestorOf() -*/ -QGraphicsItem *QGraphicsItem::commonAncestorItem(const QGraphicsItem *other) const -{ - if (!other) - return 0; - if (other == this) - return const_cast<QGraphicsItem *>(this); - const QGraphicsItem *thisw = this; - const QGraphicsItem *otherw = other; - int thisDepth = d_ptr->depth(); - int otherDepth = other->d_ptr->depth(); - while (thisDepth > otherDepth) { - thisw = thisw->d_ptr->parent; - --thisDepth; - } - while (otherDepth > thisDepth) { - otherw = otherw->d_ptr->parent; - --otherDepth; - } - while (thisw && thisw != otherw) { - thisw = thisw->d_ptr->parent; - otherw = otherw->d_ptr->parent; - } - return const_cast<QGraphicsItem *>(thisw); -} - -/*! - \since 4,4 - Returns true if this item is currently under the mouse cursor in one of - the views; otherwise, false is returned. - - \sa QGraphicsScene::views(), QCursor::pos() -*/ -bool QGraphicsItem::isUnderMouse() const -{ - Q_D(const QGraphicsItem); - if (!d->scene) - return false; - - QPoint cursorPos = QCursor::pos(); - foreach (QGraphicsView *view, d->scene->views()) { - if (contains(mapFromScene(view->mapToScene(view->mapFromGlobal(cursorPos))))) - return true; - } - return false; -} - -/*! - Returns this item's custom data for the key \a key as a QVariant. - - Custom item data is useful for storing arbitrary properties in any - item. Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 11 - - Qt does not use this feature for storing data; it is provided solely - for the convenience of the user. - - \sa setData() -*/ -QVariant QGraphicsItem::data(int key) const -{ - QGraphicsItemCustomDataStore *store = qt_dataStore(); - if (!store->data.contains(this)) - return QVariant(); - return store->data.value(this).value(key); -} - -/*! - Sets this item's custom data for the key \a key to \a value. - - Custom item data is useful for storing arbitrary properties for any - item. Qt does not use this feature for storing data; it is provided solely - for the convenience of the user. - - \sa data() -*/ -void QGraphicsItem::setData(int key, const QVariant &value) -{ - qt_dataStore()->data[this][key] = value; -} - -/*! - \fn T qgraphicsitem_cast(QGraphicsItem *item) - \relates QGraphicsItem - \since 4.2 - - Returns the given \a item cast to type T if \a item is of type T; - otherwise, 0 is returned. - - \note To make this function work correctly with custom items, reimplement - the \l{QGraphicsItem::}{type()} function for each custom QGraphicsItem - subclass. - - \sa QGraphicsItem::type(), QGraphicsItem::UserType -*/ - -/*! - Returns the type of an item as an int. All standard graphicsitem classes - are associated with a unique value; see QGraphicsItem::Type. This type - information is used by qgraphicsitem_cast() to distinguish between types. - - The default implementation (in QGraphicsItem) returns UserType. - - To enable use of qgraphicsitem_cast() with a custom item, reimplement this - function and declare a Type enum value equal to your custom item's type. - Custom items must return a value larger than or equal to UserType (65536). - - For example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp QGraphicsItem type - - \sa UserType -*/ -int QGraphicsItem::type() const -{ - return (int)UserType; -} - -/*! - Installs an event filter for this item on \a filterItem, causing - all events for this item to first pass through \a filterItem's - sceneEventFilter() function. - - To filter another item's events, install this item as an event filter - for the other item. Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 12 - - An item can only filter events for other items in the same - scene. Also, an item cannot filter its own events; instead, you - can reimplement sceneEvent() directly. - - Items must belong to a scene for scene event filters to be installed and - used. - - \sa removeSceneEventFilter(), sceneEventFilter(), sceneEvent() -*/ -void QGraphicsItem::installSceneEventFilter(QGraphicsItem *filterItem) -{ - if (!d_ptr->scene) { - qWarning("QGraphicsItem::installSceneEventFilter: event filters can only be installed" - " on items in a scene."); - return; - } - if (d_ptr->scene != filterItem->scene()) { - qWarning("QGraphicsItem::installSceneEventFilter: event filters can only be installed" - " on items in the same scene."); - return; - } - d_ptr->scene->d_func()->installSceneEventFilter(this, filterItem); -} - -/*! - Removes an event filter on this item from \a filterItem. - - \sa installSceneEventFilter() -*/ -void QGraphicsItem::removeSceneEventFilter(QGraphicsItem *filterItem) -{ - if (!d_ptr->scene || d_ptr->scene != filterItem->scene()) - return; - d_ptr->scene->d_func()->removeSceneEventFilter(this, filterItem); -} - -/*! - Filters events for the item \a watched. \a event is the filtered - event. - - Reimplementing this function in a subclass makes it possible - for the item to be used as an event filter for other items, - intercepting all the events send to those items before they are - able to respond. - - Reimplementations must return true to prevent further processing of - a given event, ensuring that it will not be delivered to the watched - item, or return false to indicate that the event should be propagated - further by the event system. - - \sa installSceneEventFilter() -*/ -bool QGraphicsItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event) -{ - Q_UNUSED(watched); - Q_UNUSED(event); - return false; -} - -/*! - This virtual function receives events to this item. Reimplement - this function to intercept events before they are dispatched to - the specialized event handlers contextMenuEvent(), focusInEvent(), - focusOutEvent(), hoverEnterEvent(), hoverMoveEvent(), - hoverLeaveEvent(), keyPressEvent(), keyReleaseEvent(), - mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(), and - mouseDoubleClickEvent(). - - Returns true if the event was recognized and handled; otherwise, (e.g., if - the event type was not recognized,) false is returned. - - \a event is the intercepted event. -*/ -bool QGraphicsItem::sceneEvent(QEvent *event) -{ - if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents) { - if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave - || event->type() == QEvent::DragEnter || event->type() == QEvent::DragLeave) { - // Hover enter and hover leave events for children are ignored; - // hover move events are forwarded. - return true; - } - - QGraphicsItem *handler = this; - do { - handler = handler->d_ptr->parent; - Q_ASSERT(handler); - } while (handler->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents); - // Forward the event to the closest parent that handles child - // events, mapping existing item-local coordinates to its - // coordinate system. - d_ptr->remapItemPos(event, handler); - handler->sceneEvent(event); - return true; - } - - if (event->type() == QEvent::FocusOut) { - focusOutEvent(static_cast<QFocusEvent *>(event)); - return true; - } - - if (!d_ptr->visible) { - // Eaten - return true; - } - - switch (event->type()) { - case QEvent::FocusIn: - focusInEvent(static_cast<QFocusEvent *>(event)); - break; - case QEvent::GraphicsSceneContextMenu: - contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent *>(event)); - break; - case QEvent::GraphicsSceneDragEnter: - dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneDragMove: - dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneDragLeave: - dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneDrop: - dropEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneHoverEnter: - hoverEnterEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); - break; - case QEvent::GraphicsSceneHoverMove: - hoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); - break; - case QEvent::GraphicsSceneHoverLeave: - hoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); - break; - case QEvent::GraphicsSceneMouseMove: - mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneMousePress: - mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneMouseRelease: - mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneMouseDoubleClick: - mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneWheel: - wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event)); - break; - case QEvent::KeyPress: { - QKeyEvent *k = static_cast<QKeyEvent *>(event); - if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) { - if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier? - bool res = false; - if (k->key() == Qt::Key_Backtab - || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) { - if (d_ptr->isWidget) { - res = static_cast<QGraphicsWidget *>(this)->focusNextPrevChild(false); - } else if (d_ptr->scene) { - res = d_ptr->scene->focusNextPrevChild(false); - } - } else if (k->key() == Qt::Key_Tab) { - if (d_ptr->isWidget) { - res = static_cast<QGraphicsWidget *>(this)->focusNextPrevChild(true); - } else if (d_ptr->scene) { - res = d_ptr->scene->focusNextPrevChild(true); - } - } - if (!res) - event->ignore(); - return true; - } - } - keyPressEvent(static_cast<QKeyEvent *>(event)); - break; - } - case QEvent::KeyRelease: - keyReleaseEvent(static_cast<QKeyEvent *>(event)); - break; - case QEvent::InputMethod: - inputMethodEvent(static_cast<QInputMethodEvent *>(event)); - break; - case QEvent::WindowActivate: - case QEvent::WindowDeactivate: - // Propagate panel activation. - if (d_ptr->scene) { - for (int i = 0; i < d_ptr->children.size(); ++i) { - QGraphicsItem *child = d_ptr->children.at(i); - if (child->isVisible() && !child->isPanel()) { - if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents)) - d_ptr->scene->sendEvent(child, event); - } - } - } - break; - default: - return false; - } - - return true; -} - -/*! - This event handler can be reimplemented in a subclass to process context - menu events. The \a event parameter contains details about the event to - be handled. - - If you ignore the event, (i.e., by calling QEvent::ignore(),) \a event - will propagate to any item beneath this item. If no items accept the - event, it will be ignored by the scene, and propagate to the view. - - It's common to open a QMenu in response to receiving a context menu - event. Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 13 - - The default implementation ignores the event. - - \sa sceneEvent() -*/ -void QGraphicsItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) -{ - event->ignore(); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - drag enter events for this item. Drag enter events are generated as the - cursor enters the item's area. - - By accepting the event, (i.e., by calling QEvent::accept(),) the item will - accept drop events, in addition to receiving drag move and drag - leave. Otherwise, the event will be ignored and propagate to the item - beneath. If the event is accepted, the item will receive a drag move event - before control goes back to the event loop. - - A common implementation of dragEnterEvent accepts or ignores \a event - depending on the associated mime data in \a event. Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 14 - - Items do not receive drag and drop events by default; to enable this - feature, call \c setAcceptDrops(true). - - The default implementation does nothing. - - \sa dropEvent(), dragMoveEvent(), dragLeaveEvent() -*/ -void QGraphicsItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsItem); - // binary compatibility workaround between 4.4 and 4.5 - if (d->isProxyWidget()) - static_cast<QGraphicsProxyWidget*>(this)->dragEnterEvent(event); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - drag leave events for this item. Drag leave events are generated as the - cursor leaves the item's area. Most often you will not need to reimplement - this function, but it can be useful for resetting state in your item - (e.g., highlighting). - - Calling QEvent::ignore() or QEvent::accept() on \a event has no effect. - - Items do not receive drag and drop events by default; to enable this - feature, call \c setAcceptDrops(true). - - The default implementation does nothing. - - \sa dragEnterEvent(), dropEvent(), dragMoveEvent() -*/ -void QGraphicsItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsItem); - // binary compatibility workaround between 4.4 and 4.5 - if (d->isProxyWidget()) - static_cast<QGraphicsProxyWidget*>(this)->dragLeaveEvent(event); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - drag move events for this item. Drag move events are generated as the - cursor moves around inside the item's area. Most often you will not need - to reimplement this function; it is used to indicate that only parts of - the item can accept drops. - - Calling QEvent::ignore() or QEvent::accept() on \a event toggles whether - or not the item will accept drops at the position from the event. By - default, \a event is accepted, indicating that the item allows drops at - the specified position. - - Items do not receive drag and drop events by default; to enable this - feature, call \c setAcceptDrops(true). - - The default implementation does nothing. - - \sa dropEvent(), dragEnterEvent(), dragLeaveEvent() -*/ -void QGraphicsItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsItem); - // binary compatibility workaround between 4.4 and 4.5 - if (d->isProxyWidget()) - static_cast<QGraphicsProxyWidget*>(this)->dragMoveEvent(event); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - drop events for this item. Items can only receive drop events if the last - drag move event was accepted. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no effect. - - Items do not receive drag and drop events by default; to enable this - feature, call \c setAcceptDrops(true). - - The default implementation does nothing. - - \sa dragEnterEvent(), dragMoveEvent(), dragLeaveEvent() -*/ -void QGraphicsItem::dropEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsItem); - // binary compatibility workaround between 4.4 and 4.5 - if (d->isProxyWidget()) - static_cast<QGraphicsProxyWidget*>(this)->dropEvent(event); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - focus in events for this item. The default implementation calls - ensureVisible(). - - \sa focusOutEvent(), sceneEvent(), setFocus() -*/ -void QGraphicsItem::focusInEvent(QFocusEvent *event) -{ - Q_UNUSED(event); - update(); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - focus out events for this item. The default implementation does nothing. - - \sa focusInEvent(), sceneEvent(), setFocus() -*/ -void QGraphicsItem::focusOutEvent(QFocusEvent *event) -{ - Q_UNUSED(event); - update(); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - hover enter events for this item. The default implementation calls - update(); otherwise it does nothing. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no effect. - - \sa hoverMoveEvent(), hoverLeaveEvent(), sceneEvent(), setAcceptHoverEvents() -*/ -void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); - update(); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - hover move events for this item. The default implementation does nothing. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no effect. - - \sa hoverEnterEvent(), hoverLeaveEvent(), sceneEvent(), setAcceptHoverEvents() -*/ -void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - hover leave events for this item. The default implementation calls - update(); otherwise it does nothing. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no effect. - - \sa hoverEnterEvent(), hoverMoveEvent(), sceneEvent(), setAcceptHoverEvents() -*/ -void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); - update(); -} - -/*! - This event handler, for event \a event, can be reimplemented to - receive key press events for this item. The default implementation - ignores the event. If you reimplement this handler, the event will by - default be accepted. - - Note that key events are only received for items that set the - ItemIsFocusable flag, and that have keyboard input focus. - - \sa keyReleaseEvent(), setFocus(), QGraphicsScene::setFocusItem(), - sceneEvent() -*/ -void QGraphicsItem::keyPressEvent(QKeyEvent *event) -{ - event->ignore(); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - key release events for this item. The default implementation - ignores the event. If you reimplement this handler, the event will by - default be accepted. - - Note that key events are only received for items that set the - ItemIsFocusable flag, and that have keyboard input focus. - - \sa keyPressEvent(), setFocus(), QGraphicsScene::setFocusItem(), - sceneEvent() -*/ -void QGraphicsItem::keyReleaseEvent(QKeyEvent *event) -{ - event->ignore(); -} - -/*! - This event handler, for event \a event, can be reimplemented to - receive mouse press events for this item. Mouse press events are - only delivered to items that accept the mouse button that is - pressed. By default, an item accepts all mouse buttons, but you - can change this by calling setAcceptedMouseButtons(). - - The mouse press event decides which item should become the mouse - grabber (see QGraphicsScene::mouseGrabberItem()). If you do not - reimplement this function, the press event will propagate to any - topmost item beneath this item, and no other mouse events will be - delivered to this item. - - If you do reimplement this function, \a event will by default be - accepted (see QEvent::accept()), and this item is then the mouse - grabber. This allows the item to receive future move, release and - doubleclick events. If you call QEvent::ignore() on \a event, this - item will lose the mouse grab, and \a event will propagate to any - topmost item beneath. No further mouse events will be delivered to - this item unless a new mouse press event is received. - - The default implementation handles basic item interaction, such as - selection and moving. If you want to keep the base implementation - when reimplementing this function, call - QGraphicsItem::mousePressEvent() in your reimplementation. - - The event is \l{QEvent::ignore()}d for items that are neither - \l{QGraphicsItem::ItemIsMovable}{movable} nor - \l{QGraphicsItem::ItemIsSelectable}{selectable}. - - \sa mouseMoveEvent(), mouseReleaseEvent(), - mouseDoubleClickEvent(), sceneEvent() -*/ -void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if (event->button() == Qt::LeftButton && (flags() & ItemIsSelectable)) { - bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0; - if (!multiSelect) { - if (!d_ptr->selected) { - if (QGraphicsScene *scene = d_ptr->scene) { - ++scene->d_func()->selectionChanging; - scene->clearSelection(); - --scene->d_func()->selectionChanging; - } - setSelected(true); - } - } - } else if (!(flags() & ItemIsMovable)) { - event->ignore(); - } - if (d_ptr->isWidget) { - // Qt::Popup closes when you click outside. - QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this); - if ((w->windowFlags() & Qt::Popup) == Qt::Popup) { - event->accept(); - if (!w->rect().contains(event->pos())) - w->close(); - } - } -} - -/*! - obsolete -*/ -bool _qt_movableAncestorIsSelected(const QGraphicsItem *item) -{ - const QGraphicsItem *parent = item->parentItem(); - return parent && (((parent->flags() & QGraphicsItem::ItemIsMovable) && parent->isSelected()) || _qt_movableAncestorIsSelected(parent)); -} - -bool QGraphicsItemPrivate::movableAncestorIsSelected(const QGraphicsItem *item) -{ - const QGraphicsItem *parent = item->d_ptr->parent; - return parent && (((parent->flags() & QGraphicsItem::ItemIsMovable) && parent->isSelected()) || _qt_movableAncestorIsSelected(parent)); -} - -/*! - This event handler, for event \a event, can be reimplemented to - receive mouse move events for this item. If you do receive this - event, you can be certain that this item also received a mouse - press event, and that this item is the current mouse grabber. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no - effect. - - The default implementation handles basic item interaction, such as - selection and moving. If you want to keep the base implementation - when reimplementing this function, call - QGraphicsItem::mouseMoveEvent() in your reimplementation. - - Please note that mousePressEvent() decides which graphics item it - is that receives mouse events. See the mousePressEvent() - description for details. - - \sa mousePressEvent(), mouseReleaseEvent(), - mouseDoubleClickEvent(), sceneEvent() -*/ -void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if ((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) { - // Determine the list of items that need to be moved. - QList<QGraphicsItem *> selectedItems; - QMap<QGraphicsItem *, QPointF> initialPositions; - if (d_ptr->scene) { - selectedItems = d_ptr->scene->selectedItems(); - initialPositions = d_ptr->scene->d_func()->movingItemsInitialPositions; - if (initialPositions.isEmpty()) { - foreach (QGraphicsItem *item, selectedItems) - initialPositions[item] = item->pos(); - initialPositions[this] = pos(); - } - d_ptr->scene->d_func()->movingItemsInitialPositions = initialPositions; - } - - // Find the active view. - QGraphicsView *view = 0; - if (event->widget()) - view = qobject_cast<QGraphicsView *>(event->widget()->parentWidget()); - - // Move all selected items - int i = 0; - bool movedMe = false; - while (i <= selectedItems.size()) { - QGraphicsItem *item = 0; - if (i < selectedItems.size()) - item = selectedItems.at(i); - else - item = this; - if (item == this) { - // Slightly clumsy-looking way to ensure that "this" is part - // of the list of items to move, this is to avoid allocations - // (appending this item to the list of selected items causes a - // detach). - if (movedMe) - break; - movedMe = true; - } - - if ((item->flags() & ItemIsMovable) && !QGraphicsItemPrivate::movableAncestorIsSelected(item)) { - QPointF currentParentPos; - QPointF buttonDownParentPos; - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations) { - // Items whose ancestors ignore transformations need to - // map screen coordinates to local coordinates, then map - // those to the parent. - QTransform viewToItemTransform = (item->deviceTransform(view->viewportTransform())).inverted(); - currentParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->screenPos())))); - buttonDownParentPos = mapToParent(viewToItemTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))))); - } else if (item->flags() & ItemIgnoresTransformations) { - // Root items that ignore transformations need to - // calculate their diff by mapping viewport coordinates - // directly to parent coordinates. - // COMBINE - QTransform itemTransform; - if (item->d_ptr->transformData) - itemTransform = item->d_ptr->transformData->computedFullTransform(); - itemTransform.translate(item->d_ptr->pos.x(), item->d_ptr->pos.y()); - QTransform viewToParentTransform = itemTransform - * (item->sceneTransform() * view->viewportTransform()).inverted(); - currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos()))); - buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton)))); - } else { - // All other items simply map from the scene. - currentParentPos = item->mapToParent(item->mapFromScene(event->scenePos())); - buttonDownParentPos = item->mapToParent(item->mapFromScene(event->buttonDownScenePos(Qt::LeftButton))); - } - - item->setPos(initialPositions.value(item) + currentParentPos - buttonDownParentPos); - - if (item->flags() & ItemIsSelectable) - item->setSelected(true); - } - ++i; - } - - } else { - event->ignore(); - } -} - -/*! - This event handler, for event \a event, can be reimplemented to - receive mouse release events for this item. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no - effect. - - The default implementation handles basic item interaction, such as - selection and moving. If you want to keep the base implementation - when reimplementing this function, call - QGraphicsItem::mouseReleaseEvent() in your reimplementation. - - Please note that mousePressEvent() decides which graphics item it - is that receives mouse events. See the mousePressEvent() - description for details. - - \sa mousePressEvent(), mouseMoveEvent(), mouseDoubleClickEvent(), - sceneEvent() -*/ -void QGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - if (flags() & ItemIsSelectable) { - bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0; - if (event->scenePos() == event->buttonDownScenePos(Qt::LeftButton)) { - // The item didn't move - if (multiSelect) { - setSelected(!isSelected()); - } else { - bool selectionChanged = false; - if (QGraphicsScene *scene = d_ptr->scene) { - ++scene->d_func()->selectionChanging; - // Clear everything but this item. Bypass - // QGraphicsScene::clearSelection()'s default behavior by - // temporarily removing this item from the selection list. - if (d_ptr->selected) { - scene->d_func()->selectedItems.remove(this); - foreach (QGraphicsItem *item, scene->d_func()->selectedItems) { - if (item->isSelected()) { - selectionChanged = true; - break; - } - } - } - scene->clearSelection(); - if (d_ptr->selected) - scene->d_func()->selectedItems.insert(this); - --scene->d_func()->selectionChanging; - if (selectionChanged) - emit d_ptr->scene->selectionChanged(); - } - setSelected(true); - } - } - } - if (d_ptr->scene && !event->buttons()) - d_ptr->scene->d_func()->movingItemsInitialPositions.clear(); -} - -/*! - This event handler, for event \a event, can be reimplemented to - receive mouse doubleclick events for this item. - - When doubleclicking an item, the item will first receive a mouse - press event, followed by a release event (i.e., a click), then a - doubleclick event, and finally a release event. - - Calling QEvent::ignore() or QEvent::accept() on \a event has no - effect. - - The default implementation calls mousePressEvent(). If you want to - keep the base implementation when reimplementing this function, - call QGraphicsItem::mouseDoubleClickEvent() in your - reimplementation. - - Note that an item will not receive double click events if it is - neither \l {QGraphicsItem::ItemIsSelectable}{selectable} nor - \l{QGraphicsItem::ItemIsMovable}{movable} (single mouse clicks are - ignored in this case, and that stops the generation of double - clicks). - - \sa mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), sceneEvent() -*/ -void QGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) -{ - mousePressEvent(event); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - wheel events for this item. If you reimplement this function, \a event - will be accepted by default. - - If you ignore the event, (i.e., by calling QEvent::ignore(),) it will - propagate to any item beneath this item. If no items accept the event, it - will be ignored by the scene, and propagate to the view (e.g., the view's - vertical scroll bar). - - The default implementation ignores the event. - - \sa sceneEvent() -*/ -void QGraphicsItem::wheelEvent(QGraphicsSceneWheelEvent *event) -{ - event->ignore(); -} - -/*! - This event handler, for event \a event, can be reimplemented to receive - input method events for this item. The default implementation ignores the - event. - - \sa inputMethodQuery(), sceneEvent() -*/ -void QGraphicsItem::inputMethodEvent(QInputMethodEvent *event) -{ - event->ignore(); -} - -/*! - This method is only relevant for input items. It is used by the - input method to query a set of properties of the item to be able - to support complex input method operations, such as support for - surrounding text and reconversions. \a query specifies which - property is queried. - - \sa inputMethodEvent(), QInputMethodEvent, QInputContext -*/ -QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const -{ - if (isWidget()) { - // ### Qt 5: Remove. The reimplementation in - // QGraphicsProxyWidget solves this problem (but requires a - // recompile to take effect). - return d_ptr->inputMethodQueryHelper(query); - } - - Q_UNUSED(query); - return QVariant(); -} - -/*! - Returns the current input method hints of this item. - - Input method hints are only relevant for input items. - The hints are used by the input method to indicate how it should operate. - For example, if the Qt::ImhNumbersOnly flag is set, the input method may change - its visual components to reflect that only numbers can be entered. - - The effect may vary between input method implementations. - - \since 4.6 - - \sa setInputMethodHints(), inputMethodQuery(), QInputContext -*/ -Qt::InputMethodHints QGraphicsItem::inputMethodHints() const -{ - Q_D(const QGraphicsItem); - return d->imHints; -} - -/*! - Sets the current input method hints of this item to \a hints. - - \since 4.6 - - \sa inputMethodHints(), inputMethodQuery(), QInputContext -*/ -void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints) -{ - Q_D(QGraphicsItem); - d->imHints = hints; - if (!hasFocus()) - return; - d->scene->d_func()->updateInputMethodSensitivityInViews(); -#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) - QWidget *fw = QApplication::focusWidget(); - if (!fw) - return; - for (int i = 0 ; i < scene()->views().count() ; ++i) - if (scene()->views().at(i) == fw) - if (QInputContext *inputContext = fw->inputContext()) - inputContext->update(); -#endif -} - -/*! - Updates the item's micro focus. - - \since 4.7 - - \sa QInputContext -*/ -void QGraphicsItem::updateMicroFocus() -{ -#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) - if (QWidget *fw = QApplication::focusWidget()) { - if (scene()) { - for (int i = 0 ; i < scene()->views().count() ; ++i) { - if (scene()->views().at(i) == fw) { - if (QInputContext *inputContext = fw->inputContext()) { - inputContext->update(); -#ifndef QT_NO_ACCESSIBILITY - // ##### is this correct - if (toGraphicsObject()) - QAccessible::updateAccessibility(toGraphicsObject(), 0, QAccessible::StateChanged); -#endif - break; - } - } - } - } - } -#endif -} - -/*! - This virtual function is called by QGraphicsItem to notify custom items - that some part of the item's state changes. By reimplementing this - function, your can react to a change, and in some cases, (depending on \a - change,) adjustments can be made. - - \a change is the parameter of the item that is changing. \a value is the - new value; the type of the value depends on \a change. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 15 - - The default implementation does nothing, and returns \a value. - - Note: Certain QGraphicsItem functions cannot be called in a - reimplementation of this function; see the GraphicsItemChange - documentation for details. - - \sa GraphicsItemChange -*/ -QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value) -{ - Q_UNUSED(change); - return value; -} - -/*! - \internal - - Note: This is provided as a hook to avoid future problems related - to adding virtual functions. -*/ -bool QGraphicsItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal - - Note: This is provided as a hook to avoid future problems related - to adding virtual functions. -*/ -void QGraphicsItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal - - Note: This is provided as a hook to avoid future problems related - to adding virtual functions. -*/ -QVariant QGraphicsItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \internal - - Adds this item to the scene's index. Called in conjunction with - removeFromIndex() to ensure the index bookkeeping is correct when - the item's position, transformation or shape changes. -*/ -void QGraphicsItem::addToIndex() -{ - if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### add to child index only if applicable - return; - } - if (d_ptr->scene) - d_ptr->scene->d_func()->index->addItem(this); -} - -/*! - \internal - - Removes this item from the scene's index. Called in conjunction - with addToIndex() to ensure the index bookkeeping is correct when - the item's position, transformation or shape changes. -*/ -void QGraphicsItem::removeFromIndex() -{ - if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; - } - if (d_ptr->scene) - d_ptr->scene->d_func()->index->removeItem(this); -} - -/*! - Prepares the item for a geometry change. Call this function before - changing the bounding rect of an item to keep QGraphicsScene's index up to - date. - - prepareGeometryChange() will call update() if this is necessary. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 16 - - \sa boundingRect() -*/ -void QGraphicsItem::prepareGeometryChange() -{ - if (d_ptr->inDestructor) - return; - if (d_ptr->scene) { - d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; - d_ptr->geometryChanged = 1; - d_ptr->paintedViewBoundingRectsNeedRepaint = 1; - d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper; - - QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->index->prepareBoundingRectChange(this); - scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false, - /*ignoreOpacity=*/ false, /*removingItemFromScene=*/ false, - /*updateBoundingRect=*/true); - - // For compatibility reasons, we have to update the item's old geometry - // if someone is connected to the changed signal or the scene has no views. - // Note that this has to be done *after* markDirty to ensure that - // _q_processDirtyItems is called before _q_emitUpdated. - if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex) - || scenePrivate->views.isEmpty()) { - if (d_ptr->hasTranslateOnlySceneTransform()) { - d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), - d_ptr->sceneTransform.dy())); - } else { - d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect())); - } - } - } - - d_ptr->markParentDirty(/*updateBoundingRect=*/true); -} - -/*! - \internal - - Highlights \a item as selected. - - NOTE: This function is a duplicate of qt_graphicsItem_highlightSelected() in - qgraphicssvgitem.cpp! -*/ -static void qt_graphicsItem_highlightSelected( - QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option) -{ - const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1)); - if (qFuzzyIsNull(qMax(murect.width(), murect.height()))) - return; - - const QRectF mbrect = painter->transform().mapRect(item->boundingRect()); - if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0)) - return; - - qreal itemPenWidth; - switch (item->type()) { - case QGraphicsEllipseItem::Type: - itemPenWidth = static_cast<QGraphicsEllipseItem *>(item)->pen().widthF(); - break; - case QGraphicsPathItem::Type: - itemPenWidth = static_cast<QGraphicsPathItem *>(item)->pen().widthF(); - break; - case QGraphicsPolygonItem::Type: - itemPenWidth = static_cast<QGraphicsPolygonItem *>(item)->pen().widthF(); - break; - case QGraphicsRectItem::Type: - itemPenWidth = static_cast<QGraphicsRectItem *>(item)->pen().widthF(); - break; - case QGraphicsSimpleTextItem::Type: - itemPenWidth = static_cast<QGraphicsSimpleTextItem *>(item)->pen().widthF(); - break; - case QGraphicsLineItem::Type: - itemPenWidth = static_cast<QGraphicsLineItem *>(item)->pen().widthF(); - break; - default: - itemPenWidth = 1.0; - } - const qreal pad = itemPenWidth / 2; - - const qreal penWidth = 0; // cosmetic pen - - const QColor fgcolor = option->palette.windowText().color(); - const QColor bgcolor( // ensure good contrast against fgcolor - fgcolor.red() > 127 ? 0 : 255, - fgcolor.green() > 127 ? 0 : 255, - fgcolor.blue() > 127 ? 0 : 255); - - painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine)); - painter->setBrush(Qt::NoBrush); - painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad)); - - painter->setPen(QPen(option->palette.windowText(), 0, Qt::DashLine)); - painter->setBrush(Qt::NoBrush); - painter->drawRect(item->boundingRect().adjusted(pad, pad, -pad, -pad)); -} - -/*! - \class QGraphicsObject - \brief The QGraphicsObject class provides a base class for all graphics items that - require signals, slots and properties. - \since 4.6 - \ingroup graphicsview-api - - The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms. - It maps many of QGraphicsItem's basic setters and getters to properties and adds notification - signals for many of them. - - \section1 Parents and Children - - Each graphics object can be constructed with a parent item. This ensures that the - item will be destroyed when its parent item is destroyed. Although QGraphicsObject - inherits from both QObject and QGraphicsItem, you should use the functions provided - by QGraphicsItem, \e not QObject, to manage the relationships between parent and - child items. - - The relationships between items can be explored using the parentItem() and childItems() - functions. In the hierarchy of items in a scene, the parentObject() and parentWidget() - functions are the equivalent of the QWidget::parent() and QWidget::parentWidget() - functions for QWidget subclasses. - - \sa QGraphicsWidget -*/ - -/*! - Constructs a QGraphicsObject with \a parent. -*/ -QGraphicsObject::QGraphicsObject(QGraphicsItem *parent) - : QGraphicsItem(parent) -{ - QGraphicsItem::d_ptr->isObject = true; -} - -/*! - \internal -*/ -QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene) - : QGraphicsItem(dd, parent, scene) -{ - QGraphicsItem::d_ptr->isObject = true; -} - -#ifndef QT_NO_GESTURES -/*! - Subscribes the graphics object to the given \a gesture with specific \a flags. - - \sa ungrabGesture(), QGestureEvent -*/ -void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags) -{ - bool contains = QGraphicsItem::d_ptr->gestureContext.contains(gesture); - QGraphicsItem::d_ptr->gestureContext.insert(gesture, flags); - if (!contains && QGraphicsItem::d_ptr->scene) - QGraphicsItem::d_ptr->scene->d_func()->grabGesture(this, gesture); -} - -/*! - Unsubscribes the graphics object from the given \a gesture. - - \sa grabGesture(), QGestureEvent -*/ -void QGraphicsObject::ungrabGesture(Qt::GestureType gesture) -{ - if (QGraphicsItem::d_ptr->gestureContext.remove(gesture) && QGraphicsItem::d_ptr->scene) - QGraphicsItem::d_ptr->scene->d_func()->ungrabGesture(this, gesture); -} -#endif // QT_NO_GESTURES - -/*! - Updates the item's micro focus. This is slot for convenience. - - \since 4.7 - - \sa QInputContext -*/ -void QGraphicsObject::updateMicroFocus() -{ - QGraphicsItem::updateMicroFocus(); -} - -void QGraphicsItemPrivate::children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item) -{ - if (item) { - QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object); - if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { - item->setParentItem(graphicsObject); - } else { - QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); - } - } -} - -int QGraphicsItemPrivate::children_count(QDeclarativeListProperty<QGraphicsObject> *list) -{ - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object)); - return d->children.count(); -} - -QGraphicsObject *QGraphicsItemPrivate::children_at(QDeclarativeListProperty<QGraphicsObject> *list, int index) -{ - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object)); - if (index >= 0 && index < d->children.count()) - return d->children.at(index)->toGraphicsObject(); - else - return 0; -} - -void QGraphicsItemPrivate::children_clear(QDeclarativeListProperty<QGraphicsObject> *list) -{ - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object)); - int childCount = d->children.count(); - if (d->sendParentChangeNotification) { - for (int index = 0; index < childCount; index++) - d->children.at(0)->setParentItem(0); - } else { - for (int index = 0; index < childCount; index++) - QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, 0, 0); - } -} - -/*! - Returns a list of this item's children. - - The items are sorted by stacking order. This takes into account both the - items' insertion order and their Z-values. - -*/ -QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList() -{ - Q_Q(QGraphicsItem); - if (isObject) { - QGraphicsObject *that = static_cast<QGraphicsObject *>(q); - return QDeclarativeListProperty<QGraphicsObject>(that, &children, children_append, - children_count, children_at, children_clear); - } else { - //QGraphicsItem is not supported for this property - return QDeclarativeListProperty<QGraphicsObject>(); - } -} - -/*! - \internal - Returns the width of the item - Reimplemented by QGraphicsWidget -*/ -qreal QGraphicsItemPrivate::width() const -{ - return 0; -} - -/*! - \internal - Set the width of the item - Reimplemented by QGraphicsWidget -*/ -void QGraphicsItemPrivate::setWidth(qreal w) -{ - Q_UNUSED(w); -} - -/*! - \internal - Reset the width of the item - Reimplemented by QGraphicsWidget -*/ -void QGraphicsItemPrivate::resetWidth() -{ -} - -/*! - \internal - Returns the height of the item - Reimplemented by QGraphicsWidget -*/ -qreal QGraphicsItemPrivate::height() const -{ - return 0; -} - -/*! - \internal - Set the height of the item - Reimplemented by QGraphicsWidget -*/ -void QGraphicsItemPrivate::setHeight(qreal h) -{ - Q_UNUSED(h); -} - -/*! - \internal - Reset the height of the item - Reimplemented by QGraphicsWidget -*/ -void QGraphicsItemPrivate::resetHeight() -{ -} - -/*! - \property QGraphicsObject::children - \since 4.7 - \internal -*/ - -/*! - \property QGraphicsObject::width - \since 4.7 - \internal -*/ - -/*! - \property QGraphicsObject::height - \since 4.7 - \internal -*/ - -/*! - \property QGraphicsObject::parent - \brief the parent of the item - - \note The item's parent is set independently of the parent object returned - by QObject::parent(). - - \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject() -*/ - -/*! - \property QGraphicsObject::opacity - \brief the opacity of the item - - \sa QGraphicsItem::setOpacity(), QGraphicsItem::opacity() -*/ - -/*! - \fn QGraphicsObject::opacityChanged() - - This signal gets emitted whenever the opacity of the item changes - - \sa QGraphicsItem::opacity() -*/ - -/*! - \fn QGraphicsObject::parentChanged() - - This signal gets emitted whenever the parent of the item changes -*/ - -/*! - \property QGraphicsObject::pos - \brief the position of the item - - Describes the items position. - - \sa QGraphicsItem::setPos(), QGraphicsItem::pos() -*/ - -/*! - \property QGraphicsObject::x - \brief the x position of the item - - Describes the items x position. - - \sa QGraphicsItem::setX(), setPos(), xChanged() -*/ - -/*! - \fn QGraphicsObject::xChanged() - - This signal gets emitted whenever the x position of the item changes - - \sa pos() -*/ - -/*! - \property QGraphicsObject::y - \brief the y position of the item - - Describes the items y position. - - \sa QGraphicsItem::setY(), setPos(), yChanged() -*/ - -/*! - \fn QGraphicsObject::yChanged() - - This signal gets emitted whenever the y position of the item changes. - - \sa pos() -*/ - -/*! - \property QGraphicsObject::z - \brief the z value of the item - - Describes the items z value. - - \sa QGraphicsItem::setZValue(), zValue(), zChanged() -*/ - -/*! - \fn QGraphicsObject::zChanged() - - This signal gets emitted whenever the z value of the item changes. - - \sa pos() -*/ - -/*! - \property QGraphicsObject::rotation - This property holds the rotation of the item in degrees. - - This specifies how many degrees to rotate the item around its transformOrigin. - The default rotation is 0 degrees (i.e. not rotated at all). -*/ - -/*! - \fn QGraphicsObject::rotationChanged() - - This signal gets emitted whenever the roation of the item changes. -*/ - -/*! - \property QGraphicsObject::scale - This property holds the scale of the item. - - A scale of less than 1 means the item will be displayed smaller than - normal, and a scale of greater than 1 means the item will be - displayed larger than normal. A negative scale means the item will - be mirrored. - - By default, items are displayed at a scale of 1 (i.e. at their - normal size). - - Scaling is from the item's transformOrigin. -*/ - -/*! - \fn void QGraphicsObject::scaleChanged() - - This signal is emitted when the scale of the item changes. -*/ - - -/*! - \property QGraphicsObject::enabled - \brief whether the item is enabled or not - - This property is declared in QGraphicsItem. - - By default, this property is true. - - \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled() - \sa QGraphicsObject::enabledChanged() -*/ - -/*! - \fn void QGraphicsObject::enabledChanged() - - This signal gets emitted whenever the item get's enabled or disabled. - - \sa isEnabled() -*/ - -/*! - \property QGraphicsObject::visible - \brief whether the item is visible or not - - This property is declared in QGraphicsItem. - - By default, this property is true. - - \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), visibleChanged() -*/ - -/*! - \fn QGraphicsObject::visibleChanged() - - This signal gets emitted whenever the visibility of the item changes - - \sa visible -*/ - -/*! - \fn const QObjectList &QGraphicsObject::children() const - \internal - - This function returns the same value as QObject::children(). It's - provided to differentiate between the obsolete member - QGraphicsItem::children() and QObject::children(). QGraphicsItem now - provides childItems() instead. -*/ - -/*! - \property QGraphicsObject::transformOriginPoint - \brief the transformation origin - - This property sets a specific point in the items coordiante system as the - origin for scale and rotation. - - \sa scale, rotation, QGraphicsItem::transformOriginPoint() -*/ - -/*! - \fn void QGraphicsObject::widthChanged() - \internal -*/ - -/*! - \fn void QGraphicsObject::heightChanged() - \internal -*/ - -/*! - - \fn QGraphicsObject::childrenChanged() - - This signal gets emitted whenever the children list changes - \internal -*/ - -/*! - \property QGraphicsObject::effect - \since 4.7 - \brief the effect attached to this item - - \sa QGraphicsItem::setGraphicsEffect(), QGraphicsItem::graphicsEffect() -*/ - -/*! - \class QAbstractGraphicsShapeItem - \brief The QAbstractGraphicsShapeItem class provides a common base for - all path items. - \since 4.2 - \ingroup graphicsview-api - - This class does not fully implement an item by itself; in particular, it - does not implement boundingRect() and paint(), which are inherited by - QGraphicsItem. - - You can subclass this item to provide a simple base implementation of - accessors for the item's pen and brush. - - \sa QGraphicsRectItem, QGraphicsEllipseItem, QGraphicsPathItem, - QGraphicsPolygonItem, QGraphicsTextItem, QGraphicsLineItem, - QGraphicsPixmapItem, {Graphics View Framework} -*/ - -class QAbstractGraphicsShapeItemPrivate : public QGraphicsItemPrivate -{ - Q_DECLARE_PUBLIC(QAbstractGraphicsShapeItem) -public: - - QBrush brush; - QPen pen; - - // Cached bounding rectangle - mutable QRectF boundingRect; -}; - -/*! - Constructs a QAbstractGraphicsShapeItem. \a parent is passed to - QGraphicsItem's constructor. -*/ -QAbstractGraphicsShapeItem::QAbstractGraphicsShapeItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QAbstractGraphicsShapeItemPrivate, parent, scene) -{ -} - -/*! - \internal -*/ -QAbstractGraphicsShapeItem::QAbstractGraphicsShapeItem(QAbstractGraphicsShapeItemPrivate &dd, - QGraphicsItem *parent, - QGraphicsScene *scene) - : QGraphicsItem(dd, parent, scene) -{ -} - -/*! - Destroys a QAbstractGraphicsShapeItem. -*/ -QAbstractGraphicsShapeItem::~QAbstractGraphicsShapeItem() -{ -} - -/*! - Returns the item's pen. If no pen has been set, this function returns - QPen(), a default black solid line pen with 0 width. -*/ -QPen QAbstractGraphicsShapeItem::pen() const -{ - Q_D(const QAbstractGraphicsShapeItem); - return d->pen; -} - -/*! - Sets the pen for this item to \a pen. - - The pen is used to draw the item's outline. - - \sa pen() -*/ -void QAbstractGraphicsShapeItem::setPen(const QPen &pen) -{ - Q_D(QAbstractGraphicsShapeItem); - if (d->pen == pen) - return; - prepareGeometryChange(); - d->pen = pen; - d->boundingRect = QRectF(); - update(); -} - -/*! - Returns the item's brush, or an empty brush if no brush has been set. - - \sa setBrush() -*/ -QBrush QAbstractGraphicsShapeItem::brush() const -{ - Q_D(const QAbstractGraphicsShapeItem); - return d->brush; -} - -/*! - Sets the item's brush to \a brush. - - The item's brush is used to fill the item. - - If you use a brush with a QGradient, the gradient - is relative to the item's coordinate system. - - \sa brush() -*/ -void QAbstractGraphicsShapeItem::setBrush(const QBrush &brush) -{ - Q_D(QAbstractGraphicsShapeItem); - if (d->brush == brush) - return; - d->brush = brush; - update(); -} - -/*! - \reimp -*/ -bool QAbstractGraphicsShapeItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QGraphicsItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QAbstractGraphicsShapeItem::opaqueArea() const -{ - Q_D(const QAbstractGraphicsShapeItem); - if (d->brush.isOpaque()) - return isClipped() ? clipPath() : shape(); - return QGraphicsItem::opaqueArea(); -} - -/*! - \class QGraphicsPathItem - \brief The QGraphicsPathItem class provides a path item that you - can add to a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - To set the item's path, pass a QPainterPath to QGraphicsPathItem's - constructor, or call the setPath() function. The path() function - returns the current path. - - \image graphicsview-pathitem.png - - QGraphicsPathItem uses the path to provide a reasonable - implementation of boundingRect(), shape(), and contains(). The - paint() function draws the path using the item's associated pen - and brush, which you can set by calling the setPen() and - setBrush() functions. - - \sa QGraphicsRectItem, QGraphicsEllipseItem, QGraphicsPolygonItem, - QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics - View Framework} -*/ - -class QGraphicsPathItemPrivate : public QAbstractGraphicsShapeItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPathItem) -public: - QPainterPath path; -}; - -/*! - Constructs a QGraphicsPath item using \a path as the default path. \a - parent is passed to QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsPathItem::QGraphicsPathItem(const QPainterPath &path, - QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsPathItemPrivate, parent, scene) -{ - if (!path.isEmpty()) - setPath(path); -} - -/*! - Constructs a QGraphicsPath. \a parent is passed to - QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsPathItem::QGraphicsPathItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsPathItemPrivate, parent, scene) -{ -} - -/*! - Destroys the QGraphicsPathItem. -*/ -QGraphicsPathItem::~QGraphicsPathItem() -{ -} - -/*! - Returns the item's path as a QPainterPath. If no item has been set, an - empty QPainterPath is returned. - - \sa setPath() -*/ -QPainterPath QGraphicsPathItem::path() const -{ - Q_D(const QGraphicsPathItem); - return d->path; -} - -/*! - Sets the item's path to be the given \a path. - - \sa path() -*/ -void QGraphicsPathItem::setPath(const QPainterPath &path) -{ - Q_D(QGraphicsPathItem); - if (d->path == path) - return; - prepareGeometryChange(); - d->path = path; - d->boundingRect = QRectF(); - update(); -} - -/*! - \reimp -*/ -QRectF QGraphicsPathItem::boundingRect() const -{ - Q_D(const QGraphicsPathItem); - if (d->boundingRect.isNull()) { - qreal pw = pen().widthF(); - if (pw == 0.0) - d->boundingRect = d->path.controlPointRect(); - else { - d->boundingRect = shape().controlPointRect(); - } - } - return d->boundingRect; -} - -/*! - \reimp -*/ -QPainterPath QGraphicsPathItem::shape() const -{ - Q_D(const QGraphicsPathItem); - return qt_graphicsItem_shapeFromPath(d->path, d->pen); -} - -/*! - \reimp -*/ -bool QGraphicsPathItem::contains(const QPointF &point) const -{ - return QAbstractGraphicsShapeItem::contains(point); -} - -/*! - \reimp -*/ -void QGraphicsPathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - Q_D(QGraphicsPathItem); - Q_UNUSED(widget); - painter->setPen(d->pen); - painter->setBrush(d->brush); - painter->drawPath(d->path); - - if (option->state & QStyle::State_Selected) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsPathItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QAbstractGraphicsShapeItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsPathItem::opaqueArea() const -{ - return QAbstractGraphicsShapeItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsPathItem::type() const -{ - return Type; -} - -/*! - \internal -*/ -bool QGraphicsPathItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsPathItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsPathItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsRectItem - \brief The QGraphicsRectItem class provides a rectangle item that you - can add to a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - To set the item's rectangle, pass a QRectF to QGraphicsRectItem's - constructor, or call the setRect() function. The rect() function - returns the current rectangle. - - \image graphicsview-rectitem.png - - QGraphicsRectItem uses the rectangle and the pen width to provide - a reasonable implementation of boundingRect(), shape(), and - contains(). The paint() function draws the rectangle using the - item's associated pen and brush, which you can set by calling the - setPen() and setBrush() functions. - - \note The rendering of invalid rectangles, such as those with negative - widths or heights, is undefined. If you cannot be sure that you are - using valid rectangles (for example, if you are creating - rectangles using data from an unreliable source) then you should - use QRectF::normalized() to create normalized rectangles, and use - those instead. - - \sa QGraphicsPathItem, QGraphicsEllipseItem, QGraphicsPolygonItem, - QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics - View Framework} -*/ - -class QGraphicsRectItemPrivate : public QAbstractGraphicsShapeItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsRectItem) -public: - QRectF rect; -}; - -/*! - Constructs a QGraphicsRectItem, using \a rect as the default rectangle. - \a parent is passed to QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsRectItem::QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsRectItemPrivate, parent, scene) -{ - setRect(rect); -} - -/*! - \fn QGraphicsRectItem::QGraphicsRectItem(qreal x, qreal y, qreal width, qreal height, - QGraphicsItem *parent) - - Constructs a QGraphicsRectItem with a default rectangle defined - by (\a x, \a y) and the given \a width and \a height. - - \a parent is passed to QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsRectItem::QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, - QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsRectItemPrivate, parent, scene) -{ - setRect(QRectF(x, y, w, h)); -} - -/*! - Constructs a QGraphicsRectItem. \a parent is passed to - QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsRectItem::QGraphicsRectItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsRectItemPrivate, parent, scene) -{ -} - -/*! - Destroys the QGraphicsRectItem. -*/ -QGraphicsRectItem::~QGraphicsRectItem() -{ -} - -/*! - Returns the item's rectangle. - - \sa setRect() -*/ -QRectF QGraphicsRectItem::rect() const -{ - Q_D(const QGraphicsRectItem); - return d->rect; -} - -/*! - \fn void QGraphicsRectItem::setRect(const QRectF &rectangle) - - Sets the item's rectangle to be the given \a rectangle. - - \sa rect() -*/ -void QGraphicsRectItem::setRect(const QRectF &rect) -{ - Q_D(QGraphicsRectItem); - if (d->rect == rect) - return; - prepareGeometryChange(); - d->rect = rect; - d->boundingRect = QRectF(); - update(); -} - -/*! - \fn void QGraphicsRectItem::setRect(qreal x, qreal y, qreal width, qreal height) - \fn void QGraphicsEllipseItem::setRect(qreal x, qreal y, qreal width, qreal height) - - Sets the item's rectangle to the rectangle defined by (\a x, \a y) - and the given \a width and \a height. - - This convenience function is equivalent to calling \c - {setRect(QRectF(x, y, width, height))} - - \sa rect() -*/ - -/*! - \reimp -*/ -QRectF QGraphicsRectItem::boundingRect() const -{ - Q_D(const QGraphicsRectItem); - if (d->boundingRect.isNull()) { - qreal halfpw = pen().widthF() / 2; - d->boundingRect = d->rect; - if (halfpw > 0.0) - d->boundingRect.adjust(-halfpw, -halfpw, halfpw, halfpw); - } - return d->boundingRect; -} - -/*! - \reimp -*/ -QPainterPath QGraphicsRectItem::shape() const -{ - Q_D(const QGraphicsRectItem); - QPainterPath path; - path.addRect(d->rect); - return qt_graphicsItem_shapeFromPath(path, d->pen); -} - -/*! - \reimp -*/ -bool QGraphicsRectItem::contains(const QPointF &point) const -{ - return QAbstractGraphicsShapeItem::contains(point); -} - -/*! - \reimp -*/ -void QGraphicsRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - Q_D(QGraphicsRectItem); - Q_UNUSED(widget); - painter->setPen(d->pen); - painter->setBrush(d->brush); - painter->drawRect(d->rect); - - if (option->state & QStyle::State_Selected) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsRectItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QAbstractGraphicsShapeItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsRectItem::opaqueArea() const -{ - return QAbstractGraphicsShapeItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsRectItem::type() const -{ - return Type; -} - -/*! - \internal -*/ -bool QGraphicsRectItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsRectItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsRectItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsEllipseItem - \brief The QGraphicsEllipseItem class provides an ellipse item that you - can add to a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - QGraphicsEllipseItem respresents an ellipse with a fill and an outline, - and you can also use it for ellipse segments (see startAngle(), - spanAngle()). - - \table - \row - \o \inlineimage graphicsview-ellipseitem.png - \o \inlineimage graphicsview-ellipseitem-pie.png - \endtable - - To set the item's ellipse, pass a QRectF to QGraphicsEllipseItem's - constructor, or call setRect(). The rect() function returns the - current ellipse geometry. - - QGraphicsEllipseItem uses the rect and the pen width to provide a - reasonable implementation of boundingRect(), shape(), and contains(). The - paint() function draws the ellipse using the item's associated pen and - brush, which you can set by calling setPen() and setBrush(). - - \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsPolygonItem, - QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics - View Framework} -*/ - -class QGraphicsEllipseItemPrivate : public QAbstractGraphicsShapeItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsEllipseItem) -public: - inline QGraphicsEllipseItemPrivate() - : startAngle(0), spanAngle(360 * 16) - { } - - QRectF rect; - int startAngle; - int spanAngle; -}; - -/*! - Constructs a QGraphicsEllipseItem using \a rect as the default rectangle. - \a parent is passed to QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsEllipseItem::QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsEllipseItemPrivate, parent, scene) -{ - setRect(rect); -} - -/*! - \fn QGraphicsEllipseItem::QGraphicsEllipseItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent) - \since 4.3 - - Constructs a QGraphicsEllipseItem using the rectangle defined by (\a x, \a - y) and the given \a width and \a height, as the default rectangle. \a - parent is passed to QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsEllipseItem::QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, - QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsEllipseItemPrivate, parent, scene) -{ - setRect(x,y,w,h); -} - - - -/*! - Constructs a QGraphicsEllipseItem. \a parent is passed to - QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsEllipseItem::QGraphicsEllipseItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsEllipseItemPrivate, parent, scene) -{ -} - -/*! - Destroys the QGraphicsEllipseItem. -*/ -QGraphicsEllipseItem::~QGraphicsEllipseItem() -{ -} - -/*! - Returns the item's ellipse geometry as a QRectF. - - \sa setRect(), QPainter::drawEllipse() -*/ -QRectF QGraphicsEllipseItem::rect() const -{ - Q_D(const QGraphicsEllipseItem); - return d->rect; -} - -/*! - Sets the item's ellipse geometry to \a rect. The rectangle's left edge - defines the left edge of the ellipse, and the rectangle's top edge - describes the top of the ellipse. The height and width of the rectangle - describe the height and width of the ellipse. - - \sa rect(), QPainter::drawEllipse() -*/ -void QGraphicsEllipseItem::setRect(const QRectF &rect) -{ - Q_D(QGraphicsEllipseItem); - if (d->rect == rect) - return; - prepareGeometryChange(); - d->rect = rect; - d->boundingRect = QRectF(); - update(); -} - -/*! - Returns the start angle for an ellipse segment in 16ths of a degree. This - angle is used together with spanAngle() for representing an ellipse - segment (a pie). By default, the start angle is 0. - - \sa setStartAngle(), spanAngle() -*/ -int QGraphicsEllipseItem::startAngle() const -{ - Q_D(const QGraphicsEllipseItem); - return d->startAngle; -} - -/*! - Sets the start angle for an ellipse segment to \a angle, which is in 16ths - of a degree. This angle is used together with spanAngle() for representing - an ellipse segment (a pie). By default, the start angle is 0. - - \sa startAngle(), setSpanAngle(), QPainter::drawPie() -*/ -void QGraphicsEllipseItem::setStartAngle(int angle) -{ - Q_D(QGraphicsEllipseItem); - if (angle != d->startAngle) { - prepareGeometryChange(); - d->boundingRect = QRectF(); - d->startAngle = angle; - update(); - } -} - -/*! - Returns the span angle of an ellipse segment in 16ths of a degree. This - angle is used together with startAngle() for representing an ellipse - segment (a pie). By default, this function returns 5760 (360 * 16, a full - ellipse). - - \sa setSpanAngle(), startAngle() -*/ -int QGraphicsEllipseItem::spanAngle() const -{ - Q_D(const QGraphicsEllipseItem); - return d->spanAngle; -} - -/*! - Sets the span angle for an ellipse segment to \a angle, which is in 16ths - of a degree. This angle is used together with startAngle() to represent an - ellipse segment (a pie). By default, the span angle is 5760 (360 * 16, a - full ellipse). - - \sa spanAngle(), setStartAngle(), QPainter::drawPie() -*/ -void QGraphicsEllipseItem::setSpanAngle(int angle) -{ - Q_D(QGraphicsEllipseItem); - if (angle != d->spanAngle) { - prepareGeometryChange(); - d->boundingRect = QRectF(); - d->spanAngle = angle; - update(); - } -} - -/*! - \reimp -*/ -QRectF QGraphicsEllipseItem::boundingRect() const -{ - Q_D(const QGraphicsEllipseItem); - if (d->boundingRect.isNull()) { - qreal pw = pen().widthF(); - if (pw == 0.0 && d->spanAngle == 360 * 16) - d->boundingRect = d->rect; - else - d->boundingRect = shape().controlPointRect(); - } - return d->boundingRect; -} - -/*! - \reimp -*/ -QPainterPath QGraphicsEllipseItem::shape() const -{ - Q_D(const QGraphicsEllipseItem); - QPainterPath path; - if (d->rect.isNull()) - return path; - if (d->spanAngle != 360 * 16) { - path.moveTo(d->rect.center()); - path.arcTo(d->rect, d->startAngle / 16.0, d->spanAngle / 16.0); - } else { - path.addEllipse(d->rect); - } - - return qt_graphicsItem_shapeFromPath(path, d->pen); -} - -/*! - \reimp -*/ -bool QGraphicsEllipseItem::contains(const QPointF &point) const -{ - return QAbstractGraphicsShapeItem::contains(point); -} - -/*! - \reimp -*/ -void QGraphicsEllipseItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - Q_D(QGraphicsEllipseItem); - Q_UNUSED(widget); - painter->setPen(d->pen); - painter->setBrush(d->brush); - if ((d->spanAngle != 0) && (qAbs(d->spanAngle) % (360 * 16) == 0)) - painter->drawEllipse(d->rect); - else - painter->drawPie(d->rect, d->startAngle, d->spanAngle); - - if (option->state & QStyle::State_Selected) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsEllipseItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QAbstractGraphicsShapeItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsEllipseItem::opaqueArea() const -{ - return QAbstractGraphicsShapeItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsEllipseItem::type() const -{ - return Type; -} - - -/*! - \internal -*/ -bool QGraphicsEllipseItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsEllipseItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsEllipseItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsPolygonItem - \brief The QGraphicsPolygonItem class provides a polygon item that you - can add to a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - To set the item's polygon, pass a QPolygonF to - QGraphicsPolygonItem's constructor, or call the setPolygon() - function. The polygon() function returns the current polygon. - - \image graphicsview-polygonitem.png - - QGraphicsPolygonItem uses the polygon and the pen width to provide - a reasonable implementation of boundingRect(), shape(), and - contains(). The paint() function draws the polygon using the - item's associated pen and brush, which you can set by calling the - setPen() and setBrush() functions. - - \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem, - QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics - View Framework} -*/ - -class QGraphicsPolygonItemPrivate : public QAbstractGraphicsShapeItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPolygonItem) -public: - inline QGraphicsPolygonItemPrivate() - : fillRule(Qt::OddEvenFill) - { } - - QPolygonF polygon; - Qt::FillRule fillRule; -}; - -/*! - Constructs a QGraphicsPolygonItem with \a polygon as the default - polygon. \a parent is passed to QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsPolygonItem::QGraphicsPolygonItem(const QPolygonF &polygon, - QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsPolygonItemPrivate, parent, scene) -{ - setPolygon(polygon); -} - -/*! - Constructs a QGraphicsPolygonItem. \a parent is passed to - QAbstractGraphicsShapeItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsPolygonItem::QGraphicsPolygonItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsPolygonItemPrivate, parent, scene) -{ -} - -/*! - Destroys the QGraphicsPolygonItem. -*/ -QGraphicsPolygonItem::~QGraphicsPolygonItem() -{ -} - -/*! - Returns the item's polygon, or an empty polygon if no polygon - has been set. - - \sa setPolygon() -*/ -QPolygonF QGraphicsPolygonItem::polygon() const -{ - Q_D(const QGraphicsPolygonItem); - return d->polygon; -} - -/*! - Sets the item's polygon to be the given \a polygon. - - \sa polygon() -*/ -void QGraphicsPolygonItem::setPolygon(const QPolygonF &polygon) -{ - Q_D(QGraphicsPolygonItem); - if (d->polygon == polygon) - return; - prepareGeometryChange(); - d->polygon = polygon; - d->boundingRect = QRectF(); - update(); -} - -/*! - Returns the fill rule of the polygon. The default fill rule is - Qt::OddEvenFill. - - \sa setFillRule(), QPainterPath::fillRule(), QPainter::drawPolygon() -*/ -Qt::FillRule QGraphicsPolygonItem::fillRule() const -{ - Q_D(const QGraphicsPolygonItem); - return d->fillRule; -} - -/*! - Sets the fill rule of the polygon to \a rule. The default fill rule is - Qt::OddEvenFill. - - \sa fillRule(), QPainterPath::fillRule(), QPainter::drawPolygon() -*/ -void QGraphicsPolygonItem::setFillRule(Qt::FillRule rule) -{ - Q_D(QGraphicsPolygonItem); - if (rule != d->fillRule) { - d->fillRule = rule; - update(); - } -} - -/*! - \reimp -*/ -QRectF QGraphicsPolygonItem::boundingRect() const -{ - Q_D(const QGraphicsPolygonItem); - if (d->boundingRect.isNull()) { - qreal pw = pen().widthF(); - if (pw == 0.0) - d->boundingRect = d->polygon.boundingRect(); - else - d->boundingRect = shape().controlPointRect(); - } - return d->boundingRect; -} - -/*! - \reimp -*/ -QPainterPath QGraphicsPolygonItem::shape() const -{ - Q_D(const QGraphicsPolygonItem); - QPainterPath path; - path.addPolygon(d->polygon); - return qt_graphicsItem_shapeFromPath(path, d->pen); -} - -/*! - \reimp -*/ -bool QGraphicsPolygonItem::contains(const QPointF &point) const -{ - return QAbstractGraphicsShapeItem::contains(point); -} - -/*! - \reimp -*/ -void QGraphicsPolygonItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_D(QGraphicsPolygonItem); - Q_UNUSED(widget); - painter->setPen(d->pen); - painter->setBrush(d->brush); - painter->drawPolygon(d->polygon, d->fillRule); - - if (option->state & QStyle::State_Selected) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsPolygonItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QAbstractGraphicsShapeItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsPolygonItem::opaqueArea() const -{ - return QAbstractGraphicsShapeItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsPolygonItem::type() const -{ - return Type; -} - -/*! - \internal -*/ -bool QGraphicsPolygonItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsPolygonItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsPolygonItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsLineItem - \brief The QGraphicsLineItem class provides a line item that you can add to a - QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - To set the item's line, pass a QLineF to QGraphicsLineItem's - constructor, or call the setLine() function. The line() function - returns the current line. By default the line is black with a - width of 0, but you can change this by calling setPen(). - - \img graphicsview-lineitem.png - - QGraphicsLineItem uses the line and the pen width to provide a reasonable - implementation of boundingRect(), shape(), and contains(). The paint() - function draws the line using the item's associated pen. - - \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem, - QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsPixmapItem, - {Graphics View Framework} -*/ - -class QGraphicsLineItemPrivate : public QGraphicsItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsLineItem) -public: - QLineF line; - QPen pen; -}; - -/*! - Constructs a QGraphicsLineItem, using \a line as the default line. \a - parent is passed to QGraphicsItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsLineItem::QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QGraphicsLineItemPrivate, parent, scene) -{ - setLine(line); -} - -/*! - Constructs a QGraphicsLineItem, using the line between (\a x1, \a y1) and - (\a x2, \a y2) as the default line. \a parent is passed to - QGraphicsItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsLineItem::QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QGraphicsLineItemPrivate, parent, scene) -{ - setLine(x1, y1, x2, y2); -} - - - -/*! - Constructs a QGraphicsLineItem. \a parent is passed to QGraphicsItem's - constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsLineItem::QGraphicsLineItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QGraphicsLineItemPrivate, parent, scene) -{ -} - -/*! - Destroys the QGraphicsLineItem. -*/ -QGraphicsLineItem::~QGraphicsLineItem() -{ -} - -/*! - Returns the item's pen, or a black solid 0-width pen if no pen has - been set. - - \sa setPen() -*/ -QPen QGraphicsLineItem::pen() const -{ - Q_D(const QGraphicsLineItem); - return d->pen; -} - -/*! - Sets the item's pen to \a pen. If no pen is set, the line will be painted - using a black solid 0-width pen. - - \sa pen() -*/ -void QGraphicsLineItem::setPen(const QPen &pen) -{ - Q_D(QGraphicsLineItem); - if (d->pen == pen) - return; - prepareGeometryChange(); - d->pen = pen; - update(); -} - -/*! - Returns the item's line, or a null line if no line has been set. - - \sa setLine() -*/ -QLineF QGraphicsLineItem::line() const -{ - Q_D(const QGraphicsLineItem); - return d->line; -} - -/*! - Sets the item's line to be the given \a line. - - \sa line() -*/ -void QGraphicsLineItem::setLine(const QLineF &line) -{ - Q_D(QGraphicsLineItem); - if (d->line == line) - return; - prepareGeometryChange(); - d->line = line; - update(); -} - -/*! - \fn void QGraphicsLineItem::setLine(qreal x1, qreal y1, qreal x2, qreal y2) - \overload - - Sets the item's line to be the line between (\a x1, \a y1) and (\a - x2, \a y2). - - This is the same as calling \c {setLine(QLineF(x1, y1, x2, y2))}. -*/ - -/*! - \reimp -*/ -QRectF QGraphicsLineItem::boundingRect() const -{ - Q_D(const QGraphicsLineItem); - if (d->pen.widthF() == 0.0) { - const qreal x1 = d->line.p1().x(); - const qreal x2 = d->line.p2().x(); - const qreal y1 = d->line.p1().y(); - const qreal y2 = d->line.p2().y(); - qreal lx = qMin(x1, x2); - qreal rx = qMax(x1, x2); - qreal ty = qMin(y1, y2); - qreal by = qMax(y1, y2); - return QRectF(lx, ty, rx - lx, by - ty); - } - return shape().controlPointRect(); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsLineItem::shape() const -{ - Q_D(const QGraphicsLineItem); - QPainterPath path; - if (d->line == QLineF()) - return path; - - path.moveTo(d->line.p1()); - path.lineTo(d->line.p2()); - return qt_graphicsItem_shapeFromPath(path, d->pen); -} - -/*! - \reimp -*/ -bool QGraphicsLineItem::contains(const QPointF &point) const -{ - return QGraphicsItem::contains(point); -} - -/*! - \reimp -*/ -void QGraphicsLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_D(QGraphicsLineItem); - Q_UNUSED(widget); - painter->setPen(d->pen); - painter->drawLine(d->line); - - if (option->state & QStyle::State_Selected) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsLineItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QGraphicsItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsLineItem::opaqueArea() const -{ - return QGraphicsItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsLineItem::type() const -{ - return Type; -} - -/*! - \internal -*/ -bool QGraphicsLineItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsLineItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsLineItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsPixmapItem - \brief The QGraphicsPixmapItem class provides a pixmap item that you can add to - a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - To set the item's pixmap, pass a QPixmap to QGraphicsPixmapItem's - constructor, or call the setPixmap() function. The pixmap() - function returns the current pixmap. - - QGraphicsPixmapItem uses pixmap's optional alpha mask to provide a - reasonable implementation of boundingRect(), shape(), and contains(). - - \image graphicsview-pixmapitem.png - - The pixmap is drawn at the item's (0, 0) coordinate, as returned by - offset(). You can change the drawing offset by calling setOffset(). - - You can set the pixmap's transformation mode by calling - setTransformationMode(). By default, Qt::FastTransformation is used, which - provides fast, non-smooth scaling. Qt::SmoothTransformation enables - QPainter::SmoothPixmapTransform on the painter, and the quality depends on - the platform and viewport. The result is usually not as good as calling - QPixmap::scale() directly. Call transformationMode() to get the current - transformation mode for the item. - - \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem, - QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsLineItem, - {Graphics View Framework} -*/ - -/*! - \enum QGraphicsPixmapItem::ShapeMode - - This enum describes how QGraphicsPixmapItem calculates its shape and - opaque area. - - The default value is MaskShape. - - \value MaskShape The shape is determined by calling QPixmap::mask(). - This shape includes only the opaque pixels of the pixmap. - Because the shape is more complex, however, it can be slower than the other modes, - and uses more memory. - - \value BoundingRectShape The shape is determined by tracing the outline of - the pixmap. This is the fastest shape mode, but it does not take into account - any transparent areas on the pixmap. - - \value HeuristicMaskShape The shape is determine by calling - QPixmap::createHeuristicMask(). The performance and memory consumption - is similar to MaskShape. -*/ -extern QPainterPath qt_regionToPath(const QRegion ®ion); - -class QGraphicsPixmapItemPrivate : public QGraphicsItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPixmapItem) -public: - QGraphicsPixmapItemPrivate() - : transformationMode(Qt::FastTransformation), - shapeMode(QGraphicsPixmapItem::MaskShape), - hasShape(false) - {} - - QPixmap pixmap; - Qt::TransformationMode transformationMode; - QPointF offset; - QGraphicsPixmapItem::ShapeMode shapeMode; - QPainterPath shape; - bool hasShape; - - void updateShape() - { - shape = QPainterPath(); - switch (shapeMode) { - case QGraphicsPixmapItem::MaskShape: { - QBitmap mask = pixmap.mask(); - if (!mask.isNull()) { - shape = qt_regionToPath(QRegion(mask).translated(offset.toPoint())); - break; - } - // FALL THROUGH - } - case QGraphicsPixmapItem::BoundingRectShape: - shape.addRect(QRectF(offset.x(), offset.y(), pixmap.width(), pixmap.height())); - break; - case QGraphicsPixmapItem::HeuristicMaskShape: -#ifndef QT_NO_IMAGE_HEURISTIC_MASK - shape = qt_regionToPath(QRegion(pixmap.createHeuristicMask()).translated(offset.toPoint())); -#else - shape.addRect(QRectF(offset.x(), offset.y(), pixmap.width(), pixmap.height())); -#endif - break; - } - } -}; - -/*! - Constructs a QGraphicsPixmapItem, using \a pixmap as the default pixmap. - \a parent is passed to QGraphicsItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsPixmapItem::QGraphicsPixmapItem(const QPixmap &pixmap, - QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QGraphicsPixmapItemPrivate, parent, scene) -{ - setPixmap(pixmap); -} - -/*! - Constructs a QGraphicsPixmapItem. \a parent is passed to QGraphicsItem's - constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsPixmapItem::QGraphicsPixmapItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QGraphicsPixmapItemPrivate, parent, scene) -{ -} - -/*! - Destroys the QGraphicsPixmapItem. -*/ -QGraphicsPixmapItem::~QGraphicsPixmapItem() -{ -} - -/*! - Sets the item's pixmap to \a pixmap. - - \sa pixmap() -*/ -void QGraphicsPixmapItem::setPixmap(const QPixmap &pixmap) -{ - Q_D(QGraphicsPixmapItem); - prepareGeometryChange(); - d->pixmap = pixmap; - d->hasShape = false; - update(); -} - -/*! - Returns the item's pixmap, or an invalid QPixmap if no pixmap has been - set. - - \sa setPixmap() -*/ -QPixmap QGraphicsPixmapItem::pixmap() const -{ - Q_D(const QGraphicsPixmapItem); - return d->pixmap; -} - -/*! - Returns the transformation mode of the pixmap. The default mode is - Qt::FastTransformation, which provides quick transformation with no - smoothing. - - \sa setTransformationMode() -*/ -Qt::TransformationMode QGraphicsPixmapItem::transformationMode() const -{ - Q_D(const QGraphicsPixmapItem); - return d->transformationMode; -} - -/*! - Sets the pixmap item's transformation mode to \a mode, and toggles an - update of the item. The default mode is Qt::FastTransformation, which - provides quick transformation with no smoothing. - - Qt::SmoothTransformation enables QPainter::SmoothPixmapTransform on the - painter, and the quality depends on the platform and viewport. The result - is usually not as good as calling QPixmap::scale() directly. - - \sa transformationMode() -*/ -void QGraphicsPixmapItem::setTransformationMode(Qt::TransformationMode mode) -{ - Q_D(QGraphicsPixmapItem); - if (mode != d->transformationMode) { - d->transformationMode = mode; - update(); - } -} - -/*! - Returns the pixmap item's \e offset, which defines the point of the - top-left corner of the pixmap, in local coordinates. - - \sa setOffset() -*/ -QPointF QGraphicsPixmapItem::offset() const -{ - Q_D(const QGraphicsPixmapItem); - return d->offset; -} - -/*! - Sets the pixmap item's offset to \a offset. QGraphicsPixmapItem will draw - its pixmap using \a offset for its top-left corner. - - \sa offset() -*/ -void QGraphicsPixmapItem::setOffset(const QPointF &offset) -{ - Q_D(QGraphicsPixmapItem); - if (d->offset == offset) - return; - prepareGeometryChange(); - d->offset = offset; - d->hasShape = false; - update(); -} - -/*! - \fn void QGraphicsPixmapItem::setOffset(qreal x, qreal y) - \since 4.3 - - This convenience function is equivalent to calling setOffset(QPointF(\a x, \a y)). -*/ - -/*! - \reimp -*/ -QRectF QGraphicsPixmapItem::boundingRect() const -{ - Q_D(const QGraphicsPixmapItem); - if (d->pixmap.isNull()) - return QRectF(); - if (d->flags & ItemIsSelectable) { - qreal pw = 1.0; - return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); - } else { - return QRectF(d->offset, d->pixmap.size()); - } -} - -/*! - \reimp -*/ -QPainterPath QGraphicsPixmapItem::shape() const -{ - Q_D(const QGraphicsPixmapItem); - if (!d->hasShape) { - QGraphicsPixmapItemPrivate *thatD = const_cast<QGraphicsPixmapItemPrivate *>(d); - thatD->updateShape(); - thatD->hasShape = true; - } - return d_func()->shape; -} - -/*! - \reimp -*/ -bool QGraphicsPixmapItem::contains(const QPointF &point) const -{ - return QGraphicsItem::contains(point); -} - -/*! - \reimp -*/ -void QGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - Q_D(QGraphicsPixmapItem); - Q_UNUSED(widget); - - painter->setRenderHint(QPainter::SmoothPixmapTransform, - (d->transformationMode == Qt::SmoothTransformation)); - - painter->drawPixmap(d->offset, d->pixmap); - - if (option->state & QStyle::State_Selected) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsPixmapItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QGraphicsItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsPixmapItem::opaqueArea() const -{ - return shape(); -} - -/*! - \reimp -*/ -int QGraphicsPixmapItem::type() const -{ - return Type; -} - -/*! - Returns the item's shape mode. The shape mode describes how - QGraphicsPixmapItem calculates its shape. The default mode is MaskShape. - - \sa setShapeMode(), ShapeMode -*/ -QGraphicsPixmapItem::ShapeMode QGraphicsPixmapItem::shapeMode() const -{ - return d_func()->shapeMode; -} - -/*! - Sets the item's shape mode to \a mode. The shape mode describes how - QGraphicsPixmapItem calculates its shape. The default mode is MaskShape. - - \sa shapeMode(), ShapeMode -*/ -void QGraphicsPixmapItem::setShapeMode(ShapeMode mode) -{ - Q_D(QGraphicsPixmapItem); - if (d->shapeMode == mode) - return; - d->shapeMode = mode; - d->hasShape = false; -} - -/*! - \internal -*/ -bool QGraphicsPixmapItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsPixmapItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsPixmapItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsTextItem - \brief The QGraphicsTextItem class provides a text item that you can add to - a QGraphicsScene to display formatted text. - \since 4.2 - \ingroup graphicsview-api - - If you only need to show plain text in an item, consider using QGraphicsSimpleTextItem - instead. - - To set the item's text, pass a QString to QGraphicsTextItem's - constructor, or call setHtml()/setPlainText(). - - QGraphicsTextItem uses the text's formatted size and the associated font - to provide a reasonable implementation of boundingRect(), shape(), - and contains(). You can set the font by calling setFont(). - - It is possible to make the item editable by setting the Qt::TextEditorInteraction flag - using setTextInteractionFlags(). - - The item's preferred text width can be set using setTextWidth() and obtained - using textWidth(). - - \note In order to align HTML text in the center, the item's text width must be set. - - \img graphicsview-textitem.png - - \note QGraphicsTextItem accepts \l{QGraphicsItem::acceptHoverEvents()}{hover events} - by default. You can change this with \l{QGraphicsItem::}{setAcceptHoverEvents()}. - - \sa QGraphicsSimpleTextItem, QGraphicsPathItem, QGraphicsRectItem, - QGraphicsEllipseItem, QGraphicsPixmapItem, QGraphicsPolygonItem, - QGraphicsLineItem, {Graphics View Framework} -*/ - -class QGraphicsTextItemPrivate -{ -public: - QGraphicsTextItemPrivate() - : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false), clickCausedFocus(0) - { } - - mutable QTextControl *control; - QTextControl *textControl() const; - - inline QPointF controlOffset() const - { return QPointF(0., pageNumber * control->document()->pageSize().height()); } - inline void sendControlEvent(QEvent *e) - { if (control) control->processEvent(e, controlOffset()); } - - void _q_updateBoundingRect(const QSizeF &); - void _q_update(QRectF); - void _q_ensureVisible(QRectF); - bool _q_mouseOnEdge(QGraphicsSceneMouseEvent *); - - QRectF boundingRect; - int pageNumber; - bool useDefaultImpl; - bool tabChangesFocus; - - uint clickCausedFocus : 1; - - QGraphicsTextItem *qq; -}; - - -/*! - Constructs a QGraphicsTextItem, using \a text as the default plain - text. \a parent is passed to QGraphicsItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsTextItem::QGraphicsTextItem(const QString &text, QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate) -{ - dd->qq = this; - if (!text.isEmpty()) - setPlainText(text); - setAcceptDrops(true); - setAcceptHoverEvents(true); - setFlags(ItemUsesExtendedStyleOption); -} - -/*! - Constructs a QGraphicsTextItem. \a parent is passed to QGraphicsItem's - constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsTextItem::QGraphicsTextItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate) -{ - dd->qq = this; - setAcceptDrops(true); - setAcceptHoverEvents(true); - setFlag(ItemUsesExtendedStyleOption); -} - -/*! - Destroys the QGraphicsTextItem. -*/ -QGraphicsTextItem::~QGraphicsTextItem() -{ - delete dd; -} - -/*! - Returns the item's text converted to HTML, or an empty QString if no text has been set. - - \sa setHtml() -*/ -QString QGraphicsTextItem::toHtml() const -{ -#ifndef QT_NO_TEXTHTMLPARSER - if (dd->control) - return dd->control->toHtml(); -#endif - return QString(); -} - -/*! - Sets the item's text to \a text, assuming that text is HTML formatted. If - the item has keyboard input focus, this function will also call - ensureVisible() to ensure that the text is visible in all viewports. - - \sa toHtml(), hasFocus(), QGraphicsSimpleTextItem -*/ -void QGraphicsTextItem::setHtml(const QString &text) -{ - dd->textControl()->setHtml(text); -} - -/*! - Returns the item's text converted to plain text, or an empty QString if no text has been set. - - \sa setPlainText() -*/ -QString QGraphicsTextItem::toPlainText() const -{ - if (dd->control) - return dd->control->toPlainText(); - return QString(); -} - -/*! - Sets the item's text to \a text. If the item has keyboard input focus, - this function will also call ensureVisible() to ensure that the text is - visible in all viewports. - - \sa toHtml(), hasFocus() -*/ -void QGraphicsTextItem::setPlainText(const QString &text) -{ - dd->textControl()->setPlainText(text); -} - -/*! - Returns the item's font, which is used to render the text. - - \sa setFont() -*/ -QFont QGraphicsTextItem::font() const -{ - if (!dd->control) - return QFont(); - return dd->control->document()->defaultFont(); -} - -/*! - Sets the font used to render the text item to \a font. - - \sa font() -*/ -void QGraphicsTextItem::setFont(const QFont &font) -{ - dd->textControl()->document()->setDefaultFont(font); -} - -/*! - Sets the color for unformatted text to \a col. -*/ -void QGraphicsTextItem::setDefaultTextColor(const QColor &col) -{ - QTextControl *c = dd->textControl(); - QPalette pal = c->palette(); - QColor old = pal.color(QPalette::Text); - pal.setColor(QPalette::Text, col); - c->setPalette(pal); - if (old != col) - update(); -} - -/*! - Returns the default text color that is used to for unformatted text. -*/ -QColor QGraphicsTextItem::defaultTextColor() const -{ - return dd->textControl()->palette().color(QPalette::Text); -} - -/*! - \reimp -*/ -QRectF QGraphicsTextItem::boundingRect() const -{ - return dd->boundingRect; -} - -/*! - \reimp -*/ -QPainterPath QGraphicsTextItem::shape() const -{ - if (!dd->control) - return QPainterPath(); - QPainterPath path; - path.addRect(dd->boundingRect); - return path; -} - -/*! - \reimp -*/ -bool QGraphicsTextItem::contains(const QPointF &point) const -{ - return dd->boundingRect.contains(point); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - Q_UNUSED(widget); - if (dd->control) { - painter->save(); - QRectF r = option->exposedRect; - painter->translate(-dd->controlOffset()); - r.translate(dd->controlOffset()); - - QTextDocument *doc = dd->control->document(); - QTextDocumentLayout *layout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout()); - - // the layout might need to expand the root frame to - // the viewport if NoWrap is set - if (layout) - layout->setViewport(dd->boundingRect); - - dd->control->drawContents(painter, r); - - if (layout) - layout->setViewport(QRect()); - - painter->restore(); - } - - if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus)) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsTextItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QGraphicsItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsTextItem::opaqueArea() const -{ - return QGraphicsItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsTextItem::type() const -{ - return Type; -} - -/*! - Sets the preferred width for the item's text. If the actual text - is wider than the specified width then it will be broken into - multiple lines. - - If \a width is set to -1 then the text will not be broken into - multiple lines unless it is enforced through an explicit line - break or a new paragraph. - - The default value is -1. - - Note that QGraphicsTextItem keeps a QTextDocument internally, - which is used to calculate the text width. - - \sa textWidth(), QTextDocument::setTextWidth() -*/ -void QGraphicsTextItem::setTextWidth(qreal width) -{ - dd->textControl()->setTextWidth(width); -} - -/*! - Returns the text width. - - The width is calculated with the QTextDocument that - QGraphicsTextItem keeps internally. - - \sa setTextWidth(), QTextDocument::textWidth() -*/ -qreal QGraphicsTextItem::textWidth() const -{ - if (!dd->control) - return -1; - return dd->control->textWidth(); -} - -/*! - Adjusts the text item to a reasonable size. -*/ -void QGraphicsTextItem::adjustSize() -{ - if (dd->control) - dd->control->adjustSize(); -} - -/*! - Sets the text document \a document on the item. -*/ -void QGraphicsTextItem::setDocument(QTextDocument *document) -{ - dd->textControl()->setDocument(document); - dd->_q_updateBoundingRect(dd->control->size()); -} - -/*! - Returns the item's text document. -*/ -QTextDocument *QGraphicsTextItem::document() const -{ - return dd->textControl()->document(); -} - -/*! - \reimp -*/ -bool QGraphicsTextItem::sceneEvent(QEvent *event) -{ - QEvent::Type t = event->type(); - if (!dd->tabChangesFocus && (t == QEvent::KeyPress || t == QEvent::KeyRelease)) { - int k = ((QKeyEvent *)event)->key(); - if (k == Qt::Key_Tab || k == Qt::Key_Backtab) { - dd->sendControlEvent(event); - return true; - } - } - bool result = QGraphicsItem::sceneEvent(event); - - // Ensure input context is updated. - switch (event->type()) { - case QEvent::ContextMenu: - case QEvent::FocusIn: - case QEvent::FocusOut: - case QEvent::GraphicsSceneDragEnter: - case QEvent::GraphicsSceneDragLeave: - case QEvent::GraphicsSceneDragMove: - case QEvent::GraphicsSceneDrop: - case QEvent::GraphicsSceneHoverEnter: - case QEvent::GraphicsSceneHoverLeave: - case QEvent::GraphicsSceneHoverMove: - case QEvent::GraphicsSceneMouseDoubleClick: - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::KeyPress: - case QEvent::KeyRelease: - // Reset the focus widget's input context, regardless - // of how this item gained or lost focus. - if (QWidget *fw = qApp->focusWidget()) { -#ifndef QT_NO_IM - if (QInputContext *qic = fw->inputContext()) { - if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) - qic->reset(); - else - qic->update(); - } -#endif //QT_NO_IM - } - break; - case QEvent::ShortcutOverride: - dd->sendControlEvent(event); - return true; - default: - break; - } - - return result; -} - -/*! - \reimp -*/ -void QGraphicsTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if ((QGraphicsItem::d_ptr->flags & (ItemIsSelectable | ItemIsMovable)) - && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) { - // User left-pressed on edge of selectable/movable item, use - // base impl. - dd->useDefaultImpl = true; - } else if (event->buttons() == event->button() - && dd->control->textInteractionFlags() == Qt::NoTextInteraction) { - // User pressed first button on non-interactive item. - dd->useDefaultImpl = true; - } - if (dd->useDefaultImpl) { - QGraphicsItem::mousePressEvent(event); - if (!event->isAccepted()) - dd->useDefaultImpl = false; - return; - } - - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - if (dd->useDefaultImpl) { - QGraphicsItem::mouseMoveEvent(event); - return; - } - - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - if (dd->useDefaultImpl) { - QGraphicsItem::mouseReleaseEvent(event); - if (dd->control->textInteractionFlags() == Qt::NoTextInteraction - && !event->buttons()) { - // User released last button on non-interactive item. - dd->useDefaultImpl = false; - } else if ((event->buttons() & Qt::LeftButton) == 0) { - // User released the left button on an interactive item. - dd->useDefaultImpl = false; - } - return; - } - - QWidget *widget = event->widget(); - if (widget && (dd->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) { - qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus); - } - dd->clickCausedFocus = 0; - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) -{ - if (dd->useDefaultImpl) { - QGraphicsItem::mouseDoubleClickEvent(event); - return; - } - - if (!hasFocus()) { - QGraphicsItem::mouseDoubleClickEvent(event); - return; - } - - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::keyPressEvent(QKeyEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::keyReleaseEvent(QKeyEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::focusInEvent(QFocusEvent *event) -{ - dd->sendControlEvent(event); - if (event->reason() == Qt::MouseFocusReason) { - dd->clickCausedFocus = 1; - } - update(); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::focusOutEvent(QFocusEvent *event) -{ - dd->sendControlEvent(event); - update(); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::dropEvent(QGraphicsSceneDragDropEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::inputMethodEvent(QInputMethodEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - dd->sendControlEvent(event); -} - -/*! - \reimp -*/ -QVariant QGraphicsTextItem::inputMethodQuery(Qt::InputMethodQuery query) const -{ - QVariant v; - if (dd->control) - v = dd->control->inputMethodQuery(query); - if (v.type() == QVariant::RectF) - v = v.toRectF().translated(-dd->controlOffset()); - else if (v.type() == QVariant::PointF) - v = v.toPointF() - dd->controlOffset(); - else if (v.type() == QVariant::Rect) - v = v.toRect().translated(-dd->controlOffset().toPoint()); - else if (v.type() == QVariant::Point) - v = v.toPoint() - dd->controlOffset().toPoint(); - return v; -} - -/*! - \internal -*/ -bool QGraphicsTextItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsTextItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsTextItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \internal -*/ -void QGraphicsTextItemPrivate::_q_update(QRectF rect) -{ - if (rect.isValid()) { - rect.translate(-controlOffset()); - } else { - rect = boundingRect; - } - if (rect.intersects(boundingRect)) - qq->update(rect); -} - -/*! - \internal -*/ -void QGraphicsTextItemPrivate::_q_updateBoundingRect(const QSizeF &size) -{ - if (!control) return; // can't happen - const QSizeF pageSize = control->document()->pageSize(); - // paged items have a constant (page) size - if (size == boundingRect.size() || pageSize.height() != -1) - return; - qq->prepareGeometryChange(); - boundingRect.setSize(size); - qq->update(); -} - -/*! - \internal -*/ -void QGraphicsTextItemPrivate::_q_ensureVisible(QRectF rect) -{ - if (qq->hasFocus()) { - rect.translate(-controlOffset()); - qq->ensureVisible(rect, /*xmargin=*/0, /*ymargin=*/0); - } -} - -QTextControl *QGraphicsTextItemPrivate::textControl() const -{ - if (!control) { - QGraphicsTextItem *that = const_cast<QGraphicsTextItem *>(qq); - control = new QTextControl(that); - control->setTextInteractionFlags(Qt::NoTextInteraction); - - QObject::connect(control, SIGNAL(updateRequest(QRectF)), - qq, SLOT(_q_update(QRectF))); - QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), - qq, SLOT(_q_updateBoundingRect(QSizeF))); - QObject::connect(control, SIGNAL(visibilityRequest(QRectF)), - qq, SLOT(_q_ensureVisible(QRectF))); - QObject::connect(control, SIGNAL(linkActivated(QString)), - qq, SIGNAL(linkActivated(QString))); - QObject::connect(control, SIGNAL(linkHovered(QString)), - qq, SIGNAL(linkHovered(QString))); - - const QSizeF pgSize = control->document()->pageSize(); - if (pgSize.height() != -1) { - qq->prepareGeometryChange(); - that->dd->boundingRect.setSize(pgSize); - qq->update(); - } else { - that->dd->_q_updateBoundingRect(control->size()); - } - } - return control; -} - -/*! - \internal -*/ -bool QGraphicsTextItemPrivate::_q_mouseOnEdge(QGraphicsSceneMouseEvent *event) -{ - QPainterPath path; - path.addRect(qq->boundingRect()); - - QPainterPath docPath; - const QTextFrameFormat format = control->document()->rootFrame()->frameFormat(); - docPath.addRect( - qq->boundingRect().adjusted( - format.leftMargin(), - format.topMargin(), - -format.rightMargin(), - -format.bottomMargin())); - - return path.subtracted(docPath).contains(event->pos()); -} - -/*! - \fn QGraphicsTextItem::linkActivated(const QString &link) - - This signal is emitted when the user clicks on a link on a text item - that enables Qt::LinksAccessibleByMouse or Qt::LinksAccessibleByKeyboard. - \a link is the link that was clicked. - - \sa setTextInteractionFlags() -*/ - -/*! - \fn QGraphicsTextItem::linkHovered(const QString &link) - - This signal is emitted when the user hovers over a link on a text item - that enables Qt::LinksAccessibleByMouse. \a link is - the link that was hovered over. - - \sa setTextInteractionFlags() -*/ - -/*! - Sets the flags \a flags to specify how the text item should react to user - input. - - The default for a QGraphicsTextItem is Qt::NoTextInteraction. This function - also affects the ItemIsFocusable QGraphicsItem flag by setting it if \a flags - is different from Qt::NoTextInteraction and clearing it otherwise. - - By default, the text is read-only. To transform the item into an editor, - set the Qt::TextEditable flag. -*/ -void QGraphicsTextItem::setTextInteractionFlags(Qt::TextInteractionFlags flags) -{ - if (flags == Qt::NoTextInteraction) - setFlags(this->flags() & ~(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod)); - else - setFlags(this->flags() | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod); - - dd->textControl()->setTextInteractionFlags(flags); -} - -/*! - Returns the current text interaction flags. - - \sa setTextInteractionFlags() -*/ -Qt::TextInteractionFlags QGraphicsTextItem::textInteractionFlags() const -{ - if (!dd->control) - return Qt::NoTextInteraction; - return dd->control->textInteractionFlags(); -} - -/*! - \since 4.5 - - If \a b is true, the \gui Tab key will cause the widget to change focus; - otherwise, the tab key will insert a tab into the document. - - In some occasions text edits should not allow the user to input tabulators - or change indentation using the \gui Tab key, as this breaks the focus - chain. The default is false. - - \sa tabChangesFocus(), ItemIsFocusable, textInteractionFlags() -*/ -void QGraphicsTextItem::setTabChangesFocus(bool b) -{ - dd->tabChangesFocus = b; -} - -/*! - \since 4.5 - - Returns true if the \gui Tab key will cause the widget to change focus; - otherwise, false is returned. - - By default, this behavior is disabled, and this function will return false. - - \sa setTabChangesFocus() -*/ -bool QGraphicsTextItem::tabChangesFocus() const -{ - return dd->tabChangesFocus; -} - -/*! - \property QGraphicsTextItem::openExternalLinks - - Specifies whether QGraphicsTextItem should automatically open links using - QDesktopServices::openUrl() instead of emitting the - linkActivated signal. - - The default value is false. -*/ -void QGraphicsTextItem::setOpenExternalLinks(bool open) -{ - dd->textControl()->setOpenExternalLinks(open); -} - -bool QGraphicsTextItem::openExternalLinks() const -{ - if (!dd->control) - return false; - return dd->control->openExternalLinks(); -} - -/*! - \property QGraphicsTextItem::textCursor - - This property represents the visible text cursor in an editable - text item. - - By default, if the item's text has not been set, this property - contains a null text cursor; otherwise it contains a text cursor - placed at the start of the item's document. -*/ -void QGraphicsTextItem::setTextCursor(const QTextCursor &cursor) -{ - dd->textControl()->setTextCursor(cursor); -} - -QTextCursor QGraphicsTextItem::textCursor() const -{ - if (!dd->control) - return QTextCursor(); - return dd->control->textCursor(); -} - -class QGraphicsSimpleTextItemPrivate : public QAbstractGraphicsShapeItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSimpleTextItem) -public: - inline QGraphicsSimpleTextItemPrivate() { - pen.setStyle(Qt::NoPen); - brush.setStyle(Qt::SolidPattern); - } - QString text; - QFont font; - QRectF boundingRect; - - void updateBoundingRect(); -}; - -static QRectF setupTextLayout(QTextLayout *layout) -{ - layout->setCacheEnabled(true); - layout->beginLayout(); - while (layout->createLine().isValid()) - ; - layout->endLayout(); - qreal maxWidth = 0; - qreal y = 0; - for (int i = 0; i < layout->lineCount(); ++i) { - QTextLine line = layout->lineAt(i); - maxWidth = qMax(maxWidth, line.naturalTextWidth()); - line.setPosition(QPointF(0, y)); - y += line.height(); - } - return QRectF(0, 0, maxWidth, y); -} - -void QGraphicsSimpleTextItemPrivate::updateBoundingRect() -{ - Q_Q(QGraphicsSimpleTextItem); - QRectF br; - if (text.isEmpty()) { - br = QRectF(); - } else { - QString tmp = text; - tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); - QStackTextEngine engine(tmp, font); - QTextLayout layout(&engine); - br = setupTextLayout(&layout); - } - if (br != boundingRect) { - q->prepareGeometryChange(); - boundingRect = br; - q->update(); - } -} - -/*! - \class QGraphicsSimpleTextItem - \brief The QGraphicsSimpleTextItem class provides a simple text path item - that you can add to a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - To set the item's text, you can either pass a QString to - QGraphicsSimpleTextItem's constructor, or call setText() to change the - text later. To set the text fill color, call setBrush(). - - The simple text item can have both a fill and an outline; setBrush() will - set the text fill (i.e., text color), and setPen() sets the pen that will - be used to draw the text outline. (The latter can be slow, especially for - complex pens, and items with long text content.) If all you want is to - draw a simple line of text, you should call setBrush() only, and leave the - pen unset; QGraphicsSimpleTextItem's pen is by default Qt::NoPen. - - QGraphicsSimpleTextItem uses the text's formatted size and the associated - font to provide a reasonable implementation of boundingRect(), shape(), - and contains(). You can set the font by calling setFont(). - - QGraphicsSimpleText does not display rich text; instead, you can use - QGraphicsTextItem, which provides full text control capabilities. - - \img graphicsview-simpletextitem.png - - \sa QGraphicsTextItem, QGraphicsPathItem, QGraphicsRectItem, - QGraphicsEllipseItem, QGraphicsPixmapItem, QGraphicsPolygonItem, - QGraphicsLineItem, {Graphics View Framework} -*/ - -/*! - Constructs a QGraphicsSimpleTextItem. - - \a parent is passed to QGraphicsItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsSimpleTextItem::QGraphicsSimpleTextItem(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsSimpleTextItemPrivate, parent, scene) -{ -} - -/*! - Constructs a QGraphicsSimpleTextItem, using \a text as the default plain text. - - \a parent is passed to QGraphicsItem's constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsSimpleTextItem::QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QAbstractGraphicsShapeItem(*new QGraphicsSimpleTextItemPrivate, parent, scene) -{ - setText(text); -} - -/*! - Destroys the QGraphicsSimpleTextItem. -*/ -QGraphicsSimpleTextItem::~QGraphicsSimpleTextItem() -{ -} - -/*! - Sets the item's text to \a text. The text will be displayed as - plain text. Newline characters ('\n') as well as characters of - type QChar::LineSeparator will cause item to break the text into - multiple lines. -*/ -void QGraphicsSimpleTextItem::setText(const QString &text) -{ - Q_D(QGraphicsSimpleTextItem); - if (d->text == text) - return; - d->text = text; - d->updateBoundingRect(); - update(); -} - -/*! - Returns the item's text. -*/ -QString QGraphicsSimpleTextItem::text() const -{ - Q_D(const QGraphicsSimpleTextItem); - return d->text; -} - -/*! - Sets the font that is used to draw the item's text to \a font. -*/ -void QGraphicsSimpleTextItem::setFont(const QFont &font) -{ - Q_D(QGraphicsSimpleTextItem); - d->font = font; - d->updateBoundingRect(); -} - -/*! - Returns the font that is used to draw the item's text. -*/ -QFont QGraphicsSimpleTextItem::font() const -{ - Q_D(const QGraphicsSimpleTextItem); - return d->font; -} - -/*! - \reimp -*/ -QRectF QGraphicsSimpleTextItem::boundingRect() const -{ - Q_D(const QGraphicsSimpleTextItem); - return d->boundingRect; -} - -/*! - \reimp -*/ -QPainterPath QGraphicsSimpleTextItem::shape() const -{ - Q_D(const QGraphicsSimpleTextItem); - QPainterPath path; - path.addRect(d->boundingRect); - return path; -} - -/*! - \reimp -*/ -bool QGraphicsSimpleTextItem::contains(const QPointF &point) const -{ - Q_D(const QGraphicsSimpleTextItem); - return d->boundingRect.contains(point); -} - -/*! - \reimp -*/ -void QGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(widget); - Q_D(QGraphicsSimpleTextItem); - - painter->setFont(d->font); - - QString tmp = d->text; - tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); - QStackTextEngine engine(tmp, d->font); - QTextLayout layout(&engine); - setupTextLayout(&layout); - - QPen p; - p.setBrush(d->brush); - painter->setPen(p); - if (d->pen.style() == Qt::NoPen && d->brush.style() == Qt::SolidPattern) { - painter->setBrush(Qt::NoBrush); - } else { - QTextLayout::FormatRange range; - range.start = 0; - range.length = layout.text().length(); - range.format.setTextOutline(d->pen); - QList<QTextLayout::FormatRange> formats; - formats.append(range); - layout.setAdditionalFormats(formats); - } - - layout.draw(painter, QPointF(0, 0)); - - if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus)) - qt_graphicsItem_highlightSelected(this, painter, option); -} - -/*! - \reimp -*/ -bool QGraphicsSimpleTextItem::isObscuredBy(const QGraphicsItem *item) const -{ - return QAbstractGraphicsShapeItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsSimpleTextItem::opaqueArea() const -{ - return QAbstractGraphicsShapeItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsSimpleTextItem::type() const -{ - return Type; -} - -/*! - \internal -*/ -bool QGraphicsSimpleTextItem::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension); - return false; -} - -/*! - \internal -*/ -void QGraphicsSimpleTextItem::setExtension(Extension extension, const QVariant &variant) -{ - Q_UNUSED(extension); - Q_UNUSED(variant); -} - -/*! - \internal -*/ -QVariant QGraphicsSimpleTextItem::extension(const QVariant &variant) const -{ - Q_UNUSED(variant); - return QVariant(); -} - -/*! - \class QGraphicsItemGroup - \brief The QGraphicsItemGroup class provides a container that treats - a group of items as a single item. - \since 4.2 - \ingroup graphicsview-api - - A QGraphicsItemGroup is a special type of compound item that - treats itself and all its children as one item (i.e., all events - and geometries for all children are merged together). It's common - to use item groups in presentation tools, when the user wants to - group several smaller items into one big item in order to simplify - moving and copying of items. - - If all you want is to store items inside other items, you can use - any QGraphicsItem directly by passing a suitable parent to - setParentItem(). - - The boundingRect() function of QGraphicsItemGroup returns the - bounding rectangle of all items in the item group. - QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on - its children (i.e., with respect to the geometry of the group - item, the children are treated as if they were transformable). - - There are two ways to construct an item group. The easiest and - most common approach is to pass a list of items (e.g., all - selected items) to QGraphicsScene::createItemGroup(), which - returns a new QGraphicsItemGroup item. The other approach is to - manually construct a QGraphicsItemGroup item, add it to the scene - calling QGraphicsScene::addItem(), and then add items to the group - manually, one at a time by calling addToGroup(). To dismantle - ("ungroup") an item group, you can either call - QGraphicsScene::destroyItemGroup(), or you can manually remove all - items from the group by calling removeFromGroup(). - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 17 - - The operation of adding and removing items preserves the items' - scene-relative position and transformation, as opposed to calling - setParentItem(), where only the child item's parent-relative - position and transformation are kept. - - The addtoGroup() function reparents the target item to this item - group, keeping the item's position and transformation intact - relative to the scene. Visually, this means that items added via - addToGroup() will remain completely unchanged as a result of this - operation, regardless of the item or the group's current position - or transformation; although the item's position and matrix are - likely to change. - - The removeFromGroup() function has similar semantics to - setParentItem(); it reparents the item to the parent item of the - item group. As with addToGroup(), the item's scene-relative - position and transformation remain intact. - - \sa QGraphicsItem, {Graphics View Framework} -*/ - -class QGraphicsItemGroupPrivate : public QGraphicsItemPrivate -{ -public: - QRectF itemsBoundingRect; -}; - -/*! - Constructs a QGraphicsItemGroup. \a parent is passed to QGraphicsItem's - constructor. - - \sa QGraphicsScene::addItem() -*/ -QGraphicsItemGroup::QGraphicsItemGroup(QGraphicsItem *parent -#ifndef Q_QDOC - // obsolete argument - , QGraphicsScene *scene -#endif - ) - : QGraphicsItem(*new QGraphicsItemGroupPrivate, parent, scene) -{ - setHandlesChildEvents(true); -} - -/*! - Destroys the QGraphicsItemGroup. -*/ -QGraphicsItemGroup::~QGraphicsItemGroup() -{ -} - -/*! - Adds the given \a item to this item group. The item will be - reparented to this group, but its position and transformation - relative to the scene will stay intact. - - \sa removeFromGroup(), QGraphicsScene::createItemGroup() -*/ -void QGraphicsItemGroup::addToGroup(QGraphicsItem *item) -{ - Q_D(QGraphicsItemGroup); - if (!item) { - qWarning("QGraphicsItemGroup::addToGroup: cannot add null item"); - return; - } - if (item == this) { - qWarning("QGraphicsItemGroup::addToGroup: cannot add a group to itself"); - return; - } - - // COMBINE - bool ok; - QTransform itemTransform = item->itemTransform(this, &ok); - - if (!ok) { - qWarning("QGraphicsItemGroup::addToGroup: could not find a valid transformation from item to group coordinates"); - return; - } - - QTransform newItemTransform(itemTransform); - item->setPos(mapFromItem(item, 0, 0)); - item->setParentItem(this); - - // removing position from translation component of the new transform - 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<QGraphicsTransform*> 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(); - d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect()); - update(); -} - -/*! - Removes the specified \a item from this group. The item will be - reparented to this group's parent item, or to 0 if this group has - no parent. Its position and transformation relative to the scene - will stay intact. - - \sa addToGroup(), QGraphicsScene::destroyItemGroup() -*/ -void QGraphicsItemGroup::removeFromGroup(QGraphicsItem *item) -{ - Q_D(QGraphicsItemGroup); - if (!item) { - qWarning("QGraphicsItemGroup::removeFromGroup: cannot remove null item"); - return; - } - - 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); - 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<QGraphicsTransform*> 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. - prepareGeometryChange(); - d->itemsBoundingRect = childrenBoundingRect(); -} - -/*! - \reimp - - Returns the bounding rect of this group item, and all its children. -*/ -QRectF QGraphicsItemGroup::boundingRect() const -{ - Q_D(const QGraphicsItemGroup); - return d->itemsBoundingRect; -} - -/*! - \reimp -*/ -void QGraphicsItemGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - Q_UNUSED(widget); - if (option->state & QStyle::State_Selected) { - Q_D(QGraphicsItemGroup); - painter->setBrush(Qt::NoBrush); - painter->drawRect(d->itemsBoundingRect); - } -} - -/*! - \reimp -*/ -bool QGraphicsItemGroup::isObscuredBy(const QGraphicsItem *item) const -{ - return QGraphicsItem::isObscuredBy(item); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsItemGroup::opaqueArea() const -{ - return QGraphicsItem::opaqueArea(); -} - -/*! - \reimp -*/ -int QGraphicsItemGroup::type() const -{ - return Type; -} - -#ifndef QT_NO_GRAPHICSEFFECT -QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const -{ - const bool deviceCoordinates = (system == Qt::DeviceCoordinates); - if (!info && deviceCoordinates) { - // Device coordinates without info not yet supported. - qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context"); - return QRectF(); - } - - QRectF rect = item->boundingRect(); - if (!item->d_ptr->children.isEmpty()) - rect |= item->childrenBoundingRect(); - - if (deviceCoordinates) { - Q_ASSERT(info->painter); - rect = info->painter->worldTransform().mapRect(rect); - } - - return rect; -} - -void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) -{ - if (!info) { - qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw"); - return; - } - - Q_ASSERT(item->d_ptr->scene); - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - if (painter == info->painter) { - scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform, - info->drawItem); - } else { - QTransform effectTransform = info->painter->worldTransform().inverted(); - effectTransform *= painter->worldTransform(); - scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion, - info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, - info->drawItem); - } -} - -// sourceRect must be in the given coordinate system -QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const -{ - QRectF effectRectF; - - if (unpadded) - *unpadded = false; - - if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) { - if (info) { - QRectF deviceRect = system == Qt::DeviceCoordinates ? sourceRect : info->painter->worldTransform().mapRect(sourceRect); - effectRectF = item->graphicsEffect()->boundingRectFor(deviceRect); - if (unpadded) - *unpadded = (effectRectF.size() == sourceRect.size()); - if (info && system == Qt::LogicalCoordinates) - effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF); - } else { - // no choice but to send a logical coordinate bounding rect to boundingRectFor - effectRectF = item->graphicsEffect()->boundingRectFor(sourceRect); - } - } else if (mode == QGraphicsEffect::PadToTransparentBorder) { - // adjust by 1.5 to account for cosmetic pens - effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5); - } else { - effectRectF = sourceRect; - if (unpadded) - *unpadded = true; - } - - return effectRectF.toAlignedRect(); -} - -QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, - QGraphicsEffect::PixmapPadMode mode) const -{ - const bool deviceCoordinates = (system == Qt::DeviceCoordinates); - if (!info && deviceCoordinates) { - // Device coordinates without info not yet supported. - qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); - return QPixmap(); - } - if (!item->d_ptr->scene) - return QPixmap(); - QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); - - bool unpadded; - const QRectF sourceRect = boundingRect(system); - QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded); - - if (offset) - *offset = effectRect.topLeft(); - - bool untransformed = !deviceCoordinates - || info->painter->worldTransform().type() <= QTransform::TxTranslate; - if (untransformed && unpadded && isPixmap()) { - if (offset) - *offset = boundingRect(system).topLeft().toPoint(); - return static_cast<QGraphicsPixmapItem *>(item)->pixmap(); - } - - if (effectRect.isEmpty()) - return QPixmap(); - - QPixmap pixmap(effectRect.size()); - pixmap.fill(Qt::transparent); - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing); - - QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y()); - if (deviceCoordinates && info->effectTransform) - effectTransform *= *info->effectTransform; - - if (!info) { - // Logical coordinates without info. - QTransform sceneTransform = item->sceneTransform(); - QTransform newEffectTransform = sceneTransform.inverted(); - newEffectTransform *= effectTransform; - scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0), - &newEffectTransform, false, true); - } else if (deviceCoordinates) { - // Device coordinates with info. - scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0, - info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, - info->drawItem); - } else { - // Item coordinates with info. - QTransform newEffectTransform = info->transformPtr->inverted(); - newEffectTransform *= effectTransform; - scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0, - info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform, - info->drawItem); - } - - pixmapPainter.end(); - - return pixmap; -} -#endif //QT_NO_GRAPHICSEFFECT - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug debug, QGraphicsItem *item) -{ - if (!item) { - debug << "QGraphicsItem(0)"; - return debug; - } - - if (QGraphicsObject *o = item->toGraphicsObject()) - debug << o->metaObject()->className(); - else - debug << "QGraphicsItem"; - debug << "(this =" << (void*)item - << ", parent =" << (void*)item->parentItem() - << ", pos =" << item->pos() - << ", z =" << item->zValue() << ", flags = " - << item->flags() << ")"; - return debug; -} - -QDebug operator<<(QDebug debug, QGraphicsObject *item) -{ - if (!item) { - debug << "QGraphicsObject(0)"; - return debug; - } - - debug.nospace() << item->metaObject()->className() << '(' << (void*)item; - if (!item->objectName().isEmpty()) - debug << ", name = " << item->objectName(); - debug.nospace() << ", parent = " << ((void*)item->parentItem()) - << ", pos = " << item->pos() - << ", z = " << item->zValue() << ", flags = " - << item->flags() << ')'; - return debug.space(); -} - -QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change) -{ - const char *str = "UnknownChange"; - switch (change) { - case QGraphicsItem::ItemChildAddedChange: - str = "ItemChildAddedChange"; - break; - case QGraphicsItem::ItemChildRemovedChange: - str = "ItemChildRemovedChange"; - break; - case QGraphicsItem::ItemCursorChange: - str = "ItemCursorChange"; - break; - case QGraphicsItem::ItemCursorHasChanged: - str = "ItemCursorHasChanged"; - break; - case QGraphicsItem::ItemEnabledChange: - str = "ItemEnabledChange"; - break; - case QGraphicsItem::ItemEnabledHasChanged: - str = "ItemEnabledHasChanged"; - break; - case QGraphicsItem::ItemFlagsChange: - str = "ItemFlagsChange"; - break; - case QGraphicsItem::ItemFlagsHaveChanged: - str = "ItemFlagsHaveChanged"; - break; - case QGraphicsItem::ItemMatrixChange: - str = "ItemMatrixChange"; - break; - case QGraphicsItem::ItemParentChange: - str = "ItemParentChange"; - break; - case QGraphicsItem::ItemParentHasChanged: - str = "ItemParentHasChanged"; - break; - case QGraphicsItem::ItemPositionChange: - str = "ItemPositionChange"; - break; - case QGraphicsItem::ItemPositionHasChanged: - str = "ItemPositionHasChanged"; - break; - case QGraphicsItem::ItemSceneChange: - str = "ItemSceneChange"; - break; - case QGraphicsItem::ItemSceneHasChanged: - str = "ItemSceneHasChanged"; - break; - case QGraphicsItem::ItemSelectedChange: - str = "ItemSelectedChange"; - break; - case QGraphicsItem::ItemSelectedHasChanged: - str = "ItemSelectedHasChanged"; - break; - case QGraphicsItem::ItemToolTipChange: - str = "ItemToolTipChange"; - break; - case QGraphicsItem::ItemToolTipHasChanged: - str = "ItemToolTipHasChanged"; - break; - case QGraphicsItem::ItemTransformChange: - str = "ItemTransformChange"; - break; - case QGraphicsItem::ItemTransformHasChanged: - str = "ItemTransformHasChanged"; - break; - case QGraphicsItem::ItemVisibleChange: - str = "ItemVisibleChange"; - break; - case QGraphicsItem::ItemVisibleHasChanged: - str = "ItemVisibleHasChanged"; - break; - case QGraphicsItem::ItemZValueChange: - str = "ItemZValueChange"; - break; - case QGraphicsItem::ItemZValueHasChanged: - str = "ItemZValueHasChanged"; - break; - case QGraphicsItem::ItemOpacityChange: - str = "ItemOpacityChange"; - break; - case QGraphicsItem::ItemOpacityHasChanged: - str = "ItemOpacityHasChanged"; - break; - case QGraphicsItem::ItemScenePositionHasChanged: - str = "ItemScenePositionHasChanged"; - break; - case QGraphicsItem::ItemRotationChange: - str = "ItemRotationChange"; - break; - case QGraphicsItem::ItemRotationHasChanged: - str = "ItemRotationHasChanged"; - break; - case QGraphicsItem::ItemScaleChange: - str = "ItemScaleChange"; - break; - case QGraphicsItem::ItemScaleHasChanged: - str = "ItemScaleHasChanged"; - break; - case QGraphicsItem::ItemTransformOriginPointChange: - str = "ItemTransformOriginPointChange"; - break; - case QGraphicsItem::ItemTransformOriginPointHasChanged: - str = "ItemTransformOriginPointHasChanged"; - break; - } - debug << str; - return debug; -} - -QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) -{ - const char *str = "UnknownFlag"; - switch (flag) { - case QGraphicsItem::ItemIsMovable: - str = "ItemIsMovable"; - break; - case QGraphicsItem::ItemIsSelectable: - str = "ItemIsSelectable"; - break; - case QGraphicsItem::ItemIsFocusable: - str = "ItemIsFocusable"; - break; - case QGraphicsItem::ItemClipsToShape: - str = "ItemClipsToShape"; - break; - case QGraphicsItem::ItemClipsChildrenToShape: - str = "ItemClipsChildrenToShape"; - break; - case QGraphicsItem::ItemIgnoresTransformations: - str = "ItemIgnoresTransformations"; - break; - case QGraphicsItem::ItemIgnoresParentOpacity: - str = "ItemIgnoresParentOpacity"; - break; - case QGraphicsItem::ItemDoesntPropagateOpacityToChildren: - str = "ItemDoesntPropagateOpacityToChildren"; - break; - case QGraphicsItem::ItemStacksBehindParent: - str = "ItemStacksBehindParent"; - break; - case QGraphicsItem::ItemUsesExtendedStyleOption: - str = "ItemUsesExtendedStyleOption"; - break; - case QGraphicsItem::ItemHasNoContents: - str = "ItemHasNoContents"; - break; - case QGraphicsItem::ItemSendsGeometryChanges: - str = "ItemSendsGeometryChanges"; - break; - case QGraphicsItem::ItemAcceptsInputMethod: - str = "ItemAcceptsInputMethod"; - break; - case QGraphicsItem::ItemNegativeZStacksBehindParent: - str = "ItemNegativeZStacksBehindParent"; - break; - case QGraphicsItem::ItemIsPanel: - str = "ItemIsPanel"; - break; - case QGraphicsItem::ItemIsFocusScope: - str = "ItemIsFocusScope"; - break; - case QGraphicsItem::ItemSendsScenePositionChanges: - str = "ItemSendsScenePositionChanges"; - break; - case QGraphicsItem::ItemStopsClickFocusPropagation: - str = "ItemStopsClickFocusPropagation"; - break; - case QGraphicsItem::ItemStopsFocusHandling: - str = "ItemStopsFocusHandling"; - break; - } - debug << str; - return debug; -} - -QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags) -{ - debug << '('; - bool f = false; - for (int i = 0; i < 17; ++i) { - if (flags & (1 << i)) { - if (f) - debug << '|'; - f = true; - debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i))); - } - } - debug << ')'; - return debug; -} - -#endif - -QT_END_NAMESPACE - -#include "moc_qgraphicsitem.cpp" - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h deleted file mode 100644 index a3443826c7..0000000000 --- a/src/gui/graphicsview/qgraphicsitem.h +++ /dev/null @@ -1,1172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSITEM_H -#define QGRAPHICSITEM_H - -#include <QtCore/qglobal.h> -#include <QtCore/qobject.h> -#include <QtCore/qvariant.h> -#include <QtCore/qrect.h> -#include <QtCore/qscopedpointer.h> -#include <QtGui/qpainterpath.h> -#include <QtGui/qpixmap.h> - -class tst_QGraphicsItem; - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QBrush; -class QCursor; -class QFocusEvent; -class QGraphicsEffect; -class QGraphicsItemGroup; -class QGraphicsObject; -class QGraphicsSceneContextMenuEvent; -class QGraphicsSceneDragDropEvent; -class QGraphicsSceneEvent; -class QGraphicsSceneHoverEvent; -class QGraphicsSceneMouseEvent; -class QGraphicsSceneWheelEvent; -class QGraphicsScene; -class QGraphicsTransform; -class QGraphicsWidget; -class QInputMethodEvent; -class QKeyEvent; -class QMatrix; -class QMenu; -class QPainter; -class QPen; -class QPointF; -class QRectF; -class QStyleOptionGraphicsItem; - -class QGraphicsItemPrivate; -class Q_GUI_EXPORT QGraphicsItem -{ -public: - enum GraphicsItemFlag { - ItemIsMovable = 0x1, - ItemIsSelectable = 0x2, - ItemIsFocusable = 0x4, - ItemClipsToShape = 0x8, - ItemClipsChildrenToShape = 0x10, - ItemIgnoresTransformations = 0x20, - ItemIgnoresParentOpacity = 0x40, - ItemDoesntPropagateOpacityToChildren = 0x80, - ItemStacksBehindParent = 0x100, - ItemUsesExtendedStyleOption = 0x200, - ItemHasNoContents = 0x400, - ItemSendsGeometryChanges = 0x800, - ItemAcceptsInputMethod = 0x1000, - ItemNegativeZStacksBehindParent = 0x2000, - ItemIsPanel = 0x4000, - ItemIsFocusScope = 0x8000, // internal - ItemSendsScenePositionChanges = 0x10000, - ItemStopsClickFocusPropagation = 0x20000, - ItemStopsFocusHandling = 0x40000 - // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. - }; - Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) - - enum GraphicsItemChange { - ItemPositionChange, - ItemMatrixChange, - ItemVisibleChange, - ItemEnabledChange, - ItemSelectedChange, - ItemParentChange, - ItemChildAddedChange, - ItemChildRemovedChange, - ItemTransformChange, - ItemPositionHasChanged, - ItemTransformHasChanged, - ItemSceneChange, - ItemVisibleHasChanged, - ItemEnabledHasChanged, - ItemSelectedHasChanged, - ItemParentHasChanged, - ItemSceneHasChanged, - ItemCursorChange, - ItemCursorHasChanged, - ItemToolTipChange, - ItemToolTipHasChanged, - ItemFlagsChange, - ItemFlagsHaveChanged, - ItemZValueChange, - ItemZValueHasChanged, - ItemOpacityChange, - ItemOpacityHasChanged, - ItemScenePositionHasChanged, - ItemRotationChange, - ItemRotationHasChanged, - ItemScaleChange, - ItemScaleHasChanged, - ItemTransformOriginPointChange, - ItemTransformOriginPointHasChanged - }; - - enum CacheMode { - NoCache, - ItemCoordinateCache, - DeviceCoordinateCache - }; - - enum PanelModality - { - NonModal, - PanelModal, - SceneModal - }; - - QGraphicsItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - virtual ~QGraphicsItem(); - - QGraphicsScene *scene() const; - - QGraphicsItem *parentItem() const; - QGraphicsItem *topLevelItem() const; - QGraphicsObject *parentObject() const; - QGraphicsWidget *parentWidget() const; - QGraphicsWidget *topLevelWidget() const; - QGraphicsWidget *window() const; - QGraphicsItem *panel() const; - void setParentItem(QGraphicsItem *parent); - QList<QGraphicsItem *> children() const; // ### obsolete - QList<QGraphicsItem *> childItems() const; - bool isWidget() const; - bool isWindow() const; - bool isPanel() const; - - QGraphicsObject *toGraphicsObject(); - const QGraphicsObject *toGraphicsObject() const; - - QGraphicsItemGroup *group() const; - void setGroup(QGraphicsItemGroup *group); - - GraphicsItemFlags flags() const; - void setFlag(GraphicsItemFlag flag, bool enabled = true); - void setFlags(GraphicsItemFlags flags); - - CacheMode cacheMode() const; - void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize()); - - PanelModality panelModality() const; - void setPanelModality(PanelModality panelModality); - bool isBlockedByModalPanel(QGraphicsItem **blockingPanel = 0) const; - -#ifndef QT_NO_TOOLTIP - QString toolTip() const; - void setToolTip(const QString &toolTip); -#endif - -#ifndef QT_NO_CURSOR - QCursor cursor() const; - void setCursor(const QCursor &cursor); - bool hasCursor() const; - void unsetCursor(); -#endif - - bool isVisible() const; - bool isVisibleTo(const QGraphicsItem *parent) const; - void setVisible(bool visible); - inline void hide() { setVisible(false); } - inline void show() { setVisible(true); } - - bool isEnabled() const; - void setEnabled(bool enabled); - - bool isSelected() const; - void setSelected(bool selected); - - bool acceptDrops() const; - void setAcceptDrops(bool on); - - qreal opacity() const; - qreal effectiveOpacity() const; - void setOpacity(qreal opacity); - -#ifndef QT_NO_GRAPHICSEFFECT - // Effect - QGraphicsEffect *graphicsEffect() const; - void setGraphicsEffect(QGraphicsEffect *effect); -#endif //QT_NO_GRAPHICSEFFECT - - Qt::MouseButtons acceptedMouseButtons() const; - void setAcceptedMouseButtons(Qt::MouseButtons buttons); - - bool acceptsHoverEvents() const; // ### obsolete - void setAcceptsHoverEvents(bool enabled); // ### obsolete - bool acceptHoverEvents() const; - void setAcceptHoverEvents(bool enabled); - bool acceptTouchEvents() const; - void setAcceptTouchEvents(bool enabled); - - bool filtersChildEvents() const; - void setFiltersChildEvents(bool enabled); - - bool handlesChildEvents() const; - void setHandlesChildEvents(bool enabled); - - bool isActive() const; - void setActive(bool active); - - bool hasFocus() const; - void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason); - void clearFocus(); - - QGraphicsItem *focusProxy() const; - void setFocusProxy(QGraphicsItem *item); - - QGraphicsItem *focusItem() const; - QGraphicsItem *focusScopeItem() const; - - void grabMouse(); - void ungrabMouse(); - void grabKeyboard(); - void ungrabKeyboard(); - - // Positioning in scene coordinates - QPointF pos() const; - inline qreal x() const { return pos().x(); } - void setX(qreal x); - inline qreal y() const { return pos().y(); } - void setY(qreal y); - QPointF scenePos() const; - void setPos(const QPointF &pos); - inline void setPos(qreal x, qreal y); - inline void moveBy(qreal dx, qreal dy) { setPos(pos().x() + dx, pos().y() + dy); } - - void ensureVisible(const QRectF &rect = QRectF(), int xmargin = 50, int ymargin = 50); - inline void ensureVisible(qreal x, qreal y, qreal w, qreal h, int xmargin = 50, int ymargin = 50); - - // Local transformation - QMatrix matrix() const; - QMatrix sceneMatrix() const; - void setMatrix(const QMatrix &matrix, bool combine = false); - void resetMatrix(); - QTransform transform() const; - QTransform sceneTransform() const; - QTransform deviceTransform(const QTransform &viewportTransform) const; - QTransform itemTransform(const QGraphicsItem *other, bool *ok = 0) const; - void setTransform(const QTransform &matrix, bool combine = false); - void resetTransform(); - - void rotate(qreal angle); // ### obsolete - void scale(qreal sx, qreal sy); // ### obsolete - void shear(qreal sh, qreal sv); // ### obsolete - void translate(qreal dx, qreal dy); // ### obsolete - - void setRotation(qreal angle); - qreal rotation() const; - - void setScale(qreal scale); - qreal scale() const; - - QList<QGraphicsTransform *> transformations() const; - void setTransformations(const QList<QGraphicsTransform *> &transformations); - - QPointF transformOriginPoint() const; - void setTransformOriginPoint(const QPointF &origin); - inline void setTransformOriginPoint(qreal ax, qreal ay) - { setTransformOriginPoint(QPointF(ax,ay)); } - - virtual void advance(int phase); - - // Stacking order - qreal zValue() const; - void setZValue(qreal z); - void stackBefore(const QGraphicsItem *sibling); - - // Hit test - virtual QRectF boundingRect() const = 0; - QRectF childrenBoundingRect() const; - QRectF sceneBoundingRect() const; - virtual QPainterPath shape() const; - bool isClipped() const; - QPainterPath clipPath() const; - virtual bool contains(const QPointF &point) const; - virtual bool collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - virtual bool collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList<QGraphicsItem *> collidingItems(Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - bool isObscured() const; - bool isObscured(const QRectF &rect) const; // ### Qt 5: merge with isObscured(), add QRectF arg to isObscuredBy() - inline bool isObscured(qreal x, qreal y, qreal w, qreal h) const; - virtual bool isObscuredBy(const QGraphicsItem *item) const; - virtual QPainterPath opaqueArea() const; - - QRegion boundingRegion(const QTransform &itemToDeviceTransform) const; - qreal boundingRegionGranularity() const; - void setBoundingRegionGranularity(qreal granularity); - - // Drawing - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) = 0; - void update(const QRectF &rect = QRectF()); - inline void update(qreal x, qreal y, qreal width, qreal height); - void scroll(qreal dx, qreal dy, const QRectF &rect = QRectF()); - - // Coordinate mapping - QPointF mapToItem(const QGraphicsItem *item, const QPointF &point) const; - QPointF mapToParent(const QPointF &point) const; - QPointF mapToScene(const QPointF &point) const; - QPolygonF mapToItem(const QGraphicsItem *item, const QRectF &rect) const; - QPolygonF mapToParent(const QRectF &rect) const; - QPolygonF mapToScene(const QRectF &rect) const; - QRectF mapRectToItem(const QGraphicsItem *item, const QRectF &rect) const; - QRectF mapRectToParent(const QRectF &rect) const; - QRectF mapRectToScene(const QRectF &rect) const; - QPolygonF mapToItem(const QGraphicsItem *item, const QPolygonF &polygon) const; - QPolygonF mapToParent(const QPolygonF &polygon) const; - QPolygonF mapToScene(const QPolygonF &polygon) const; - QPainterPath mapToItem(const QGraphicsItem *item, const QPainterPath &path) const; - QPainterPath mapToParent(const QPainterPath &path) const; - QPainterPath mapToScene(const QPainterPath &path) const; - QPointF mapFromItem(const QGraphicsItem *item, const QPointF &point) const; - QPointF mapFromParent(const QPointF &point) const; - QPointF mapFromScene(const QPointF &point) const; - QPolygonF mapFromItem(const QGraphicsItem *item, const QRectF &rect) const; - QPolygonF mapFromParent(const QRectF &rect) const; - QPolygonF mapFromScene(const QRectF &rect) const; - QRectF mapRectFromItem(const QGraphicsItem *item, const QRectF &rect) const; - QRectF mapRectFromParent(const QRectF &rect) const; - QRectF mapRectFromScene(const QRectF &rect) const; - QPolygonF mapFromItem(const QGraphicsItem *item, const QPolygonF &polygon) const; - QPolygonF mapFromParent(const QPolygonF &polygon) const; - QPolygonF mapFromScene(const QPolygonF &polygon) const; - QPainterPath mapFromItem(const QGraphicsItem *item, const QPainterPath &path) const; - QPainterPath mapFromParent(const QPainterPath &path) const; - QPainterPath mapFromScene(const QPainterPath &path) const; - - inline QPointF mapToItem(const QGraphicsItem *item, qreal x, qreal y) const; - inline QPointF mapToParent(qreal x, qreal y) const; - inline QPointF mapToScene(qreal x, qreal y) const; - inline QPolygonF mapToItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const; - inline QPolygonF mapToParent(qreal x, qreal y, qreal w, qreal h) const; - inline QPolygonF mapToScene(qreal x, qreal y, qreal w, qreal h) const; - inline QRectF mapRectToItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const; - inline QRectF mapRectToParent(qreal x, qreal y, qreal w, qreal h) const; - inline QRectF mapRectToScene(qreal x, qreal y, qreal w, qreal h) const; - inline QPointF mapFromItem(const QGraphicsItem *item, qreal x, qreal y) const; - inline QPointF mapFromParent(qreal x, qreal y) const; - inline QPointF mapFromScene(qreal x, qreal y) const; - inline QPolygonF mapFromItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const; - inline QPolygonF mapFromParent(qreal x, qreal y, qreal w, qreal h) const; - inline QPolygonF mapFromScene(qreal x, qreal y, qreal w, qreal h) const; - inline QRectF mapRectFromItem(const QGraphicsItem *item, qreal x, qreal y, qreal w, qreal h) const; - inline QRectF mapRectFromParent(qreal x, qreal y, qreal w, qreal h) const; - inline QRectF mapRectFromScene(qreal x, qreal y, qreal w, qreal h) const; - - bool isAncestorOf(const QGraphicsItem *child) const; - QGraphicsItem *commonAncestorItem(const QGraphicsItem *other) const; - bool isUnderMouse() const; - - // Custom data - QVariant data(int key) const; - void setData(int key, const QVariant &value); - - Qt::InputMethodHints inputMethodHints() const; - void setInputMethodHints(Qt::InputMethodHints hints); - - enum { - Type = 1, - UserType = 65536 - }; - virtual int type() const; - - void installSceneEventFilter(QGraphicsItem *filterItem); - void removeSceneEventFilter(QGraphicsItem *filterItem); - -protected: - void updateMicroFocus(); - virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); - virtual bool sceneEvent(QEvent *event); - virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); - virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event); - virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *event); - virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event); - virtual void dropEvent(QGraphicsSceneDragDropEvent *event); - virtual void focusInEvent(QFocusEvent *event); - virtual void focusOutEvent(QFocusEvent *event); - virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - virtual void keyPressEvent(QKeyEvent *event); - virtual void keyReleaseEvent(QKeyEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); - virtual void wheelEvent(QGraphicsSceneWheelEvent *event); - virtual void inputMethodEvent(QInputMethodEvent *event); - virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; - - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); - - enum Extension { - UserExtension = 0x80000000 - }; - virtual bool supportsExtension(Extension extension) const; - virtual void setExtension(Extension extension, const QVariant &variant); - virtual QVariant extension(const QVariant &variant) const; - -protected: - QGraphicsItem(QGraphicsItemPrivate &dd, - QGraphicsItem *parent, QGraphicsScene *scene); - QScopedPointer<QGraphicsItemPrivate> d_ptr; - - void addToIndex(); - void removeFromIndex(); - void prepareGeometryChange(); - -private: - Q_DISABLE_COPY(QGraphicsItem) - Q_DECLARE_PRIVATE(QGraphicsItem) - friend class QGraphicsItemGroup; - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; - friend class QGraphicsSceneFindItemBspTreeVisitor; - friend class QGraphicsSceneBspTree; - friend class QGraphicsView; - friend class QGraphicsViewPrivate; - friend class QGraphicsObject; - friend class QGraphicsWidget; - friend class QGraphicsWidgetPrivate; - friend class QGraphicsProxyWidgetPrivate; - friend class QGraphicsSceneIndex; - friend class QGraphicsSceneIndexPrivate; - friend class QGraphicsSceneBspTreeIndex; - friend class QGraphicsSceneBspTreeIndexPrivate; - friend class QGraphicsItemEffectSourcePrivate; - friend class QGraphicsTransformPrivate; -#ifndef QT_NO_GESTURES - friend class QGestureManager; -#endif - friend class ::tst_QGraphicsItem; - friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); - friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags) -Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem") - -inline void QGraphicsItem::setPos(qreal ax, qreal ay) -{ setPos(QPointF(ax, ay)); } -inline void QGraphicsItem::ensureVisible(qreal ax, qreal ay, qreal w, qreal h, int xmargin, int ymargin) -{ ensureVisible(QRectF(ax, ay, w, h), xmargin, ymargin); } -inline void QGraphicsItem::update(qreal ax, qreal ay, qreal width, qreal height) -{ update(QRectF(ax, ay, width, height)); } -inline bool QGraphicsItem::isObscured(qreal ax, qreal ay, qreal w, qreal h) const -{ return isObscured(QRectF(ax, ay, w, h)); } -inline QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal ax, qreal ay) const -{ return mapToItem(item, QPointF(ax, ay)); } -inline QPointF QGraphicsItem::mapToParent(qreal ax, qreal ay) const -{ return mapToParent(QPointF(ax, ay)); } -inline QPointF QGraphicsItem::mapToScene(qreal ax, qreal ay) const -{ return mapToScene(QPointF(ax, ay)); } -inline QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, qreal ax, qreal ay) const -{ return mapFromItem(item, QPointF(ax, ay)); } -inline QPointF QGraphicsItem::mapFromParent(qreal ax, qreal ay) const -{ return mapFromParent(QPointF(ax, ay)); } -inline QPointF QGraphicsItem::mapFromScene(qreal ax, qreal ay) const -{ return mapFromScene(QPointF(ax, ay)); } -inline QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, qreal ax, qreal ay, qreal w, qreal h) const -{ return mapToItem(item, QRectF(ax, ay, w, h)); } -inline QPolygonF QGraphicsItem::mapToParent(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapToParent(QRectF(ax, ay, w, h)); } -inline QPolygonF QGraphicsItem::mapToScene(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapToScene(QRectF(ax, ay, w, h)); } -inline QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, qreal ax, qreal ay, qreal w, qreal h) const -{ return mapRectToItem(item, QRectF(ax, ay, w, h)); } -inline QRectF QGraphicsItem::mapRectToParent(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapRectToParent(QRectF(ax, ay, w, h)); } -inline QRectF QGraphicsItem::mapRectToScene(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapRectToScene(QRectF(ax, ay, w, h)); } -inline QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, qreal ax, qreal ay, qreal w, qreal h) const -{ return mapFromItem(item, QRectF(ax, ay, w, h)); } -inline QPolygonF QGraphicsItem::mapFromParent(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapFromParent(QRectF(ax, ay, w, h)); } -inline QPolygonF QGraphicsItem::mapFromScene(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapFromScene(QRectF(ax, ay, w, h)); } -inline QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, qreal ax, qreal ay, qreal w, qreal h) const -{ return mapRectFromItem(item, QRectF(ax, ay, w, h)); } -inline QRectF QGraphicsItem::mapRectFromParent(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapRectFromParent(QRectF(ax, ay, w, h)); } -inline QRectF QGraphicsItem::mapRectFromScene(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapRectFromScene(QRectF(ax, ay, w, h)); } - - -class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem -{ - Q_OBJECT - Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false) - Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) - Q_PROPERTY(QPointF pos READ pos WRITE setPos FINAL) - Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL) - Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL) - Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged FINAL) - Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) - Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) - Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint) -#ifndef QT_NO_GRAPHICSEFFECT - Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect) -#endif - Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged) - Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL) - Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL) - Q_CLASSINFO("DefaultProperty", "children") - Q_INTERFACES(QGraphicsItem) -public: - QGraphicsObject(QGraphicsItem *parent = 0); - - // ### Qt 5: Disambiguate -#ifdef Q_NO_USING_KEYWORD - const QObjectList &children() const { return QObject::children(); } -#else - using QObject::children; -#endif - -#ifndef QT_NO_GESTURES - void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags()); - void ungrabGesture(Qt::GestureType type); -#endif - -protected Q_SLOTS: - void updateMicroFocus(); - -Q_SIGNALS: - void parentChanged(); - void opacityChanged(); - void visibleChanged(); - void enabledChanged(); - void xChanged(); - void yChanged(); - void zChanged(); - void rotationChanged(); - void scaleChanged(); - void childrenChanged(); - void widthChanged(); - void heightChanged(); - -protected: - QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); -private: - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; -}; - - -class QAbstractGraphicsShapeItemPrivate; -class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem -{ -public: - QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QAbstractGraphicsShapeItem(); - - QPen pen() const; - void setPen(const QPen &pen); - - QBrush brush() const; - void setBrush(const QBrush &brush); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - -protected: - QAbstractGraphicsShapeItem(QAbstractGraphicsShapeItemPrivate &dd, - QGraphicsItem *parent, QGraphicsScene *scene); - -private: - Q_DISABLE_COPY(QAbstractGraphicsShapeItem) - Q_DECLARE_PRIVATE(QAbstractGraphicsShapeItem) -}; - -class QGraphicsPathItemPrivate; -class Q_GUI_EXPORT QGraphicsPathItem : public QAbstractGraphicsShapeItem -{ -public: - QGraphicsPathItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsPathItem(const QPainterPath &path, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsPathItem(); - - QPainterPath path() const; - void setPath(const QPainterPath &path); - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 2 }; - int type() const; - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsPathItem) - Q_DECLARE_PRIVATE(QGraphicsPathItem) -}; - -class QGraphicsRectItemPrivate; -class Q_GUI_EXPORT QGraphicsRectItem : public QAbstractGraphicsShapeItem -{ -public: - QGraphicsRectItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsRectItem(); - - QRectF rect() const; - void setRect(const QRectF &rect); - inline void setRect(qreal x, qreal y, qreal w, qreal h); - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 3 }; - int type() const; - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsRectItem) - Q_DECLARE_PRIVATE(QGraphicsRectItem) -}; - -inline void QGraphicsRectItem::setRect(qreal ax, qreal ay, qreal w, qreal h) -{ setRect(QRectF(ax, ay, w, h)); } - -class QGraphicsEllipseItemPrivate; -class Q_GUI_EXPORT QGraphicsEllipseItem : public QAbstractGraphicsShapeItem -{ -public: - QGraphicsEllipseItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsEllipseItem(); - - QRectF rect() const; - void setRect(const QRectF &rect); - inline void setRect(qreal x, qreal y, qreal w, qreal h); - - int startAngle() const; - void setStartAngle(int angle); - - int spanAngle() const; - void setSpanAngle(int angle); - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 4 }; - int type() const; - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsEllipseItem) - Q_DECLARE_PRIVATE(QGraphicsEllipseItem) -}; - -inline void QGraphicsEllipseItem::setRect(qreal ax, qreal ay, qreal w, qreal h) -{ setRect(QRectF(ax, ay, w, h)); } - -class QGraphicsPolygonItemPrivate; -class Q_GUI_EXPORT QGraphicsPolygonItem : public QAbstractGraphicsShapeItem -{ -public: - QGraphicsPolygonItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsPolygonItem(const QPolygonF &polygon, - QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsPolygonItem(); - - QPolygonF polygon() const; - void setPolygon(const QPolygonF &polygon); - - Qt::FillRule fillRule() const; - void setFillRule(Qt::FillRule rule); - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 5 }; - int type() const; - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsPolygonItem) - Q_DECLARE_PRIVATE(QGraphicsPolygonItem) -}; - -class QGraphicsLineItemPrivate; -class Q_GUI_EXPORT QGraphicsLineItem : public QGraphicsItem -{ -public: - QGraphicsLineItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsLineItem(); - - QPen pen() const; - void setPen(const QPen &pen); - - QLineF line() const; - void setLine(const QLineF &line); - inline void setLine(qreal x1, qreal y1, qreal x2, qreal y2) - { setLine(QLineF(x1, y1, x2, y2)); } - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 6 }; - int type() const; - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsLineItem) - Q_DECLARE_PRIVATE(QGraphicsLineItem) -}; - -class QGraphicsPixmapItemPrivate; -class Q_GUI_EXPORT QGraphicsPixmapItem : public QGraphicsItem -{ -public: - enum ShapeMode { - MaskShape, - BoundingRectShape, - HeuristicMaskShape - }; - - QGraphicsPixmapItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsPixmapItem(); - - QPixmap pixmap() const; - void setPixmap(const QPixmap &pixmap); - - Qt::TransformationMode transformationMode() const; - void setTransformationMode(Qt::TransformationMode mode); - - QPointF offset() const; - void setOffset(const QPointF &offset); - inline void setOffset(qreal x, qreal y); - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 7 }; - int type() const; - - ShapeMode shapeMode() const; - void setShapeMode(ShapeMode mode); - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsPixmapItem) - Q_DECLARE_PRIVATE(QGraphicsPixmapItem) -}; - -inline void QGraphicsPixmapItem::setOffset(qreal ax, qreal ay) -{ setOffset(QPointF(ax, ay)); } - -class QGraphicsTextItemPrivate; -class QTextDocument; -class QTextCursor; -class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject -{ - Q_OBJECT - QDOC_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks) - QDOC_PROPERTY(QTextCursor textCursor READ textCursor WRITE setTextCursor) - -public: - QGraphicsTextItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsTextItem(const QString &text, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsTextItem(); - - QString toHtml() const; - void setHtml(const QString &html); - - QString toPlainText() const; - void setPlainText(const QString &text); - - QFont font() const; - void setFont(const QFont &font); - - void setDefaultTextColor(const QColor &c); - QColor defaultTextColor() const; - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 8 }; - int type() const; - - void setTextWidth(qreal width); - qreal textWidth() const; - - void adjustSize(); - - void setDocument(QTextDocument *document); - QTextDocument *document() const; - - void setTextInteractionFlags(Qt::TextInteractionFlags flags); - Qt::TextInteractionFlags textInteractionFlags() const; - - void setTabChangesFocus(bool b); - bool tabChangesFocus() const; - - void setOpenExternalLinks(bool open); - bool openExternalLinks() const; - - void setTextCursor(const QTextCursor &cursor); - QTextCursor textCursor() const; - -Q_SIGNALS: - void linkActivated(const QString &); - void linkHovered(const QString &); - -protected: - bool sceneEvent(QEvent *event); - void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); - void focusInEvent(QFocusEvent *event); - void focusOutEvent(QFocusEvent *event); - void dragEnterEvent(QGraphicsSceneDragDropEvent *event); - void dragLeaveEvent(QGraphicsSceneDragDropEvent *event); - void dragMoveEvent(QGraphicsSceneDragDropEvent *event); - void dropEvent(QGraphicsSceneDragDropEvent *event); - void inputMethodEvent(QInputMethodEvent *event); - void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - - QVariant inputMethodQuery(Qt::InputMethodQuery query) const; - - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsTextItem) - Q_PRIVATE_SLOT(dd, void _q_updateBoundingRect(const QSizeF &)) - Q_PRIVATE_SLOT(dd, void _q_update(QRectF)) - Q_PRIVATE_SLOT(dd, void _q_ensureVisible(QRectF)) - QGraphicsTextItemPrivate *dd; - friend class QGraphicsTextItemPrivate; -}; - -class QGraphicsSimpleTextItemPrivate; -class Q_GUI_EXPORT QGraphicsSimpleTextItem : public QAbstractGraphicsShapeItem -{ -public: - QGraphicsSimpleTextItem(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsSimpleTextItem(); - - void setText(const QString &text); - QString text() const; - - void setFont(const QFont &font); - QFont font() const; - - QRectF boundingRect() const; - QPainterPath shape() const; - bool contains(const QPointF &point) const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 9 }; - int type() const; - -protected: - bool supportsExtension(Extension extension) const; - void setExtension(Extension extension, const QVariant &variant); - QVariant extension(const QVariant &variant) const; - -private: - Q_DISABLE_COPY(QGraphicsSimpleTextItem) - Q_DECLARE_PRIVATE(QGraphicsSimpleTextItem) -}; - -class QGraphicsItemGroupPrivate; -class Q_GUI_EXPORT QGraphicsItemGroup : public QGraphicsItem -{ -public: - QGraphicsItemGroup(QGraphicsItem *parent = 0 -#ifndef Q_QDOC - // ### obsolete argument - , QGraphicsScene *scene = 0 -#endif - ); - ~QGraphicsItemGroup(); - - void addToGroup(QGraphicsItem *item); - void removeFromGroup(QGraphicsItem *item); - - QRectF boundingRect() const; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - - bool isObscuredBy(const QGraphicsItem *item) const; - QPainterPath opaqueArea() const; - - enum { Type = 10 }; - int type() const; - -private: - Q_DISABLE_COPY(QGraphicsItemGroup) - Q_DECLARE_PRIVATE(QGraphicsItemGroup) -}; - -template <class T> inline T qgraphicsitem_cast(QGraphicsItem *item) -{ - return int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type) - || (item && int(static_cast<T>(0)->Type) == item->type()) ? static_cast<T>(item) : 0; -} - -template <class T> inline T qgraphicsitem_cast(const QGraphicsItem *item) -{ - return int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type) - || (item && int(static_cast<T>(0)->Type) == item->type()) ? static_cast<T>(item) : 0; -} - -#ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem *item); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsObject *item); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags); -#endif - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QGraphicsItem *) -Q_DECLARE_METATYPE(QGraphicsScene *) - -QT_BEGIN_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSITEM_H diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h deleted file mode 100644 index afcb294442..0000000000 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ /dev/null @@ -1,891 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSITEM_P_H -#define QGRAPHICSITEM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsitem.h" -#include "qset.h" -#include "qpixmapcache.h" -#include <private/qgraphicsview_p.h> -#include "qgraphicstransform.h" -#include <private/qgraphicstransform_p.h> - -#include <private/qgraphicseffect_p.h> -#include <qgraphicseffect.h> - -#include <QtCore/qpoint.h> - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -QT_BEGIN_NAMESPACE - -class QGraphicsItemPrivate; - -#ifndef QDECLARATIVELISTPROPERTY -#define QDECLARATIVELISTPROPERTY -template<typename T> -class QDeclarativeListProperty { -public: - typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*); - typedef int (*CountFunction)(QDeclarativeListProperty<T> *); - typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int); - typedef void (*ClearFunction)(QDeclarativeListProperty<T> *); - - QDeclarativeListProperty() - : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {} - QDeclarativeListProperty(QObject *o, QList<T *> &list) - : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), - clear(qlist_clear), dummy1(0), dummy2(0) {} - QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0, - ClearFunction r = 0) - : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {} - - bool operator==(const QDeclarativeListProperty &o) const { - return object == o.object && - data == o.data && - append == o.append && - count == o.count && - at == o.at && - clear == o.clear; - } - - QObject *object; - void *data; - - AppendFunction append; - - CountFunction count; - AtFunction at; - - ClearFunction clear; - - void *dummy1; - void *dummy2; - -private: - static void qlist_append(QDeclarativeListProperty *p, T *v) { - ((QList<T *> *)p->data)->append(v); - } - static int qlist_count(QDeclarativeListProperty *p) { - return ((QList<T *> *)p->data)->count(); - } - static T *qlist_at(QDeclarativeListProperty *p, int idx) { - return ((QList<T *> *)p->data)->at(idx); - } - static void qlist_clear(QDeclarativeListProperty *p) { - return ((QList<T *> *)p->data)->clear(); - } -}; -#endif - -class QGraphicsItemCache -{ -public: - QGraphicsItemCache() : allExposed(false) { } - - // ItemCoordinateCache only - QRect boundingRect; - QSize fixedSize; - QPixmapCache::Key key; - - // DeviceCoordinateCache only - struct DeviceData { - DeviceData() {} - QTransform lastTransform; - QPoint cacheIndent; - QPixmapCache::Key key; - }; - QMap<QPaintDevice *, DeviceData> deviceData; - - // List of logical exposed rects - QVector<QRectF> exposed; - bool allExposed; - - // Empty cache - void purge(); -}; - -class Q_GUI_EXPORT QGraphicsItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsItem) -public: - enum Extra { - ExtraToolTip, - ExtraCursor, - ExtraCacheData, - ExtraMaxDeviceCoordCacheSize, - ExtraBoundingRegionGranularity - }; - - enum AncestorFlag { - NoFlag = 0, - AncestorHandlesChildEvents = 0x1, - AncestorClipsChildren = 0x2, - AncestorIgnoresTransformations = 0x4, - AncestorFiltersChildEvents = 0x8 - }; - - inline QGraphicsItemPrivate() - : z(0), - opacity(1.), - scene(0), - parent(0), - transformData(0), - graphicsEffect(0), - index(-1), - siblingIndex(-1), - itemDepth(-1), - focusProxy(0), - subFocusItem(0), - focusScopeItem(0), - imHints(Qt::ImhNone), - panelModality(QGraphicsItem::NonModal), - acceptedMouseButtons(0x1f), - visible(1), - explicitlyHidden(0), - enabled(1), - explicitlyDisabled(0), - selected(0), - acceptsHover(0), - acceptDrops(0), - isMemberOfGroup(0), - handlesChildEvents(0), - itemDiscovered(0), - hasCursor(0), - ancestorFlags(0), - cacheMode(0), - hasBoundingRegionGranularity(0), - isWidget(0), - dirty(0), - dirtyChildren(0), - localCollisionHack(0), - inSetPosHelper(0), - needSortChildren(0), - allChildrenDirty(0), - fullUpdatePending(0), - dirtyChildrenBoundingRect(1), - flags(0), - paintedViewBoundingRectsNeedRepaint(0), - dirtySceneTransform(1), - geometryChanged(1), - inDestructor(0), - isObject(0), - ignoreVisible(0), - ignoreOpacity(0), - acceptTouchEvents(0), - acceptedTouchBeginEvent(0), - filtersDescendantEvents(0), - sceneTransformTranslateOnly(0), - notifyBoundingRectChanged(0), - notifyInvalidated(0), - mouseSetsFocus(1), - explicitActivate(0), - wantsActive(0), - holesInSiblingIndex(0), - sequentialOrdering(1), - updateDueToGraphicsEffect(0), - scenePosDescendants(0), - pendingPolish(0), - mayHaveChildWithGraphicsEffect(0), - isDeclarativeItem(0), - sendParentChangeNotification(0), - globalStackingOrder(-1), - q_ptr(0) - { - } - - inline virtual ~QGraphicsItemPrivate() - { } - - static const QGraphicsItemPrivate *get(const QGraphicsItem *item) - { - return item->d_ptr.data(); - } - static QGraphicsItemPrivate *get(QGraphicsItem *item) - { - return item->d_ptr.data(); - } - - void updateChildWithGraphicsEffectFlagRecursively(); - void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, - AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); - void updateAncestorFlags(); - void setIsMemberOfGroup(bool enabled); - void remapItemPos(QEvent *event, QGraphicsItem *item); - QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; - inline bool itemIsUntransformable() const - { - return (flags & QGraphicsItem::ItemIgnoresTransformations) - || (ancestorFlags & AncestorIgnoresTransformations); - } - - void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; - void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; - virtual void updateSceneTransformFromParent(); - - // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. - virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; - static bool movableAncestorIsSelected(const QGraphicsItem *item); - - virtual void setPosHelper(const QPointF &pos); - void setTransformHelper(const QTransform &transform); - void prependGraphicsTransform(QGraphicsTransform *t); - void appendGraphicsTransform(QGraphicsTransform *t); - void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); - void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); - bool discardUpdateRequest(bool ignoreVisibleBit = false, - bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; - virtual void transformChanged() {} - int depth() const; -#ifndef QT_NO_GRAPHICSEFFECT - enum InvalidateReason { - OpacityChanged - }; - void invalidateParentGraphicsEffectsRecursively(); - void invalidateChildGraphicsEffectsRecursively(InvalidateReason reason); -#endif //QT_NO_GRAPHICSEFFECT - void invalidateDepthRecursively(); - void resolveDepth(); - void addChild(QGraphicsItem *child); - void removeChild(QGraphicsItem *child); - QDeclarativeListProperty<QGraphicsObject> childrenList(); - void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant, - const QVariant *thisPointerVariant); - void childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem); - void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, - const QRegion &exposedRegion, bool allItems = false) const; - QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem = 0) const; - QRectF sceneEffectiveBoundingRect() const; - - QRectF effectiveBoundingRect(const QRectF &rect) const; - - virtual void resolveFont(uint inheritedMask) - { - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->resolveFont(inheritedMask); - } - - virtual void resolvePalette(uint inheritedMask) - { - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->resolveFont(inheritedMask); - } - - virtual bool isProxyWidget() const; - - inline QVariant extra(Extra type) const - { - for (int i = 0; i < extras.size(); ++i) { - const ExtraStruct &extra = extras.at(i); - if (extra.type == type) - return extra.value; - } - return QVariant(); - } - - inline void setExtra(Extra type, const QVariant &value) - { - int index = -1; - for (int i = 0; i < extras.size(); ++i) { - if (extras.at(i).type == type) { - index = i; - break; - } - } - - if (index == -1) { - extras << ExtraStruct(type, value); - } else { - extras[index].value = value; - } - } - - inline void unsetExtra(Extra type) - { - for (int i = 0; i < extras.size(); ++i) { - if (extras.at(i).type == type) { - extras.removeAt(i); - return; - } - } - } - - struct ExtraStruct { - ExtraStruct(Extra type, QVariant value) - : type(type), value(value) - { } - - Extra type; - QVariant value; - - bool operator<(Extra extra) const - { return type < extra; } - }; - - QList<ExtraStruct> extras; - - QGraphicsItemCache *maybeExtraItemCache() const; - QGraphicsItemCache *extraItemCache() const; - void removeExtraItemCache(); - - void updatePaintedViewBoundingRects(bool updateChildren); - void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem); - inline void ensureSceneTransform() - { - QGraphicsItem *that = q_func(); - ensureSceneTransformRecursive(&that); - } - - inline bool hasTranslateOnlySceneTransform() - { - ensureSceneTransform(); - return sceneTransformTranslateOnly; - } - - inline void invalidateChildrenSceneTransform() - { - for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->dirtySceneTransform = 1; - } - - inline qreal calcEffectiveOpacity() const - { - qreal o = opacity; - QGraphicsItem *p = parent; - int myFlags = flags; - while (p) { - int parentFlags = p->d_ptr->flags; - - // If I have a parent, and I don't ignore my parent's opacity, and my - // parent propagates to me, then combine my local opacity with my parent's - // effective opacity into my effective opacity. - if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity) - || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { - break; - } - - o *= p->d_ptr->opacity; - p = p->d_ptr->parent; - myFlags = parentFlags; - } - return o; - } - - inline bool isOpacityNull() const - { return (opacity < qreal(0.001)); } - - static inline bool isOpacityNull(qreal opacity) - { return (opacity < qreal(0.001)); } - - inline bool isFullyTransparent() const - { - if (isOpacityNull()) - return true; - if (!parent) - return false; - - return isOpacityNull(calcEffectiveOpacity()); - } - - inline qreal effectiveOpacity() const { - if (!parent || !opacity) - return opacity; - - return calcEffectiveOpacity(); - } - - inline qreal combineOpacityFromParent(qreal parentOpacity) const - { - if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) - && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { - return parentOpacity * opacity; - } - return opacity; - } - - inline bool childrenCombineOpacity() const - { - if (!children.size()) - return true; - if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) - return false; - - for (int i = 0; i < children.size(); ++i) { - if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity) - return false; - } - return true; - } - - inline bool childrenClippedToShape() const - { return (flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty(); } - - inline bool isInvisible() const - { - return !visible || (childrenCombineOpacity() && isFullyTransparent()); - } - - inline void markParentDirty(bool updateBoundingRect = false); - - void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide); - void clearFocusHelper(bool giveFocusToParent); - void setSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0); - void clearSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0); - void resetFocusProxy(); - virtual void subFocusItemChange(); - virtual void focusScopeItemChange(bool isSubFocusItem); - - static void children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item); - static int children_count(QDeclarativeListProperty<QGraphicsObject> *list); - static QGraphicsObject *children_at(QDeclarativeListProperty<QGraphicsObject> *list, int); - static void children_clear(QDeclarativeListProperty<QGraphicsObject> *list); - - inline QTransform transformToParent() const; - inline void ensureSortedChildren(); - static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b); - void ensureSequentialSiblingIndex(); - inline void sendScenePosChange(); - virtual void siblingOrderChange(); - - // Private Properties - virtual qreal width() const; - virtual void setWidth(qreal); - virtual void resetWidth(); - - virtual qreal height() const; - virtual void setHeight(qreal); - virtual void resetHeight(); - - QRectF childrenBoundingRect; - QRectF needsRepaint; - QMap<QWidget *, QRect> paintedViewBoundingRects; - QPointF pos; - qreal z; - qreal opacity; - QGraphicsScene *scene; - QGraphicsItem *parent; - QList<QGraphicsItem *> children; - struct TransformData; - TransformData *transformData; - QGraphicsEffect *graphicsEffect; - QTransform sceneTransform; - int index; - int siblingIndex; - int itemDepth; // Lazily calculated when calling depth(). - QGraphicsItem *focusProxy; - QList<QGraphicsItem **> focusProxyRefs; - QGraphicsItem *subFocusItem; - QGraphicsItem *focusScopeItem; - Qt::InputMethodHints imHints; - QGraphicsItem::PanelModality panelModality; -#ifndef QT_NO_GESTURES - QMap<Qt::GestureType, Qt::GestureFlags> gestureContext; -#endif - - // Packed 32 bits - quint32 acceptedMouseButtons : 5; - quint32 visible : 1; - quint32 explicitlyHidden : 1; - quint32 enabled : 1; - quint32 explicitlyDisabled : 1; - quint32 selected : 1; - quint32 acceptsHover : 1; - quint32 acceptDrops : 1; - quint32 isMemberOfGroup : 1; - quint32 handlesChildEvents : 1; - quint32 itemDiscovered : 1; - quint32 hasCursor : 1; - quint32 ancestorFlags : 4; - quint32 cacheMode : 2; - quint32 hasBoundingRegionGranularity : 1; - quint32 isWidget : 1; - quint32 dirty : 1; - quint32 dirtyChildren : 1; - quint32 localCollisionHack : 1; - quint32 inSetPosHelper : 1; - quint32 needSortChildren : 1; - quint32 allChildrenDirty : 1; - quint32 fullUpdatePending : 1; - quint32 dirtyChildrenBoundingRect : 1; - - // Packed 32 bits - quint32 flags : 19; - quint32 paintedViewBoundingRectsNeedRepaint : 1; - quint32 dirtySceneTransform : 1; - quint32 geometryChanged : 1; - quint32 inDestructor : 1; - quint32 isObject : 1; - quint32 ignoreVisible : 1; - quint32 ignoreOpacity : 1; - quint32 acceptTouchEvents : 1; - quint32 acceptedTouchBeginEvent : 1; - quint32 filtersDescendantEvents : 1; - quint32 sceneTransformTranslateOnly : 1; - quint32 notifyBoundingRectChanged : 1; - quint32 notifyInvalidated : 1; - - // New 32 bits - quint32 mouseSetsFocus : 1; - quint32 explicitActivate : 1; - quint32 wantsActive : 1; - quint32 holesInSiblingIndex : 1; - quint32 sequentialOrdering : 1; - quint32 updateDueToGraphicsEffect : 1; - quint32 scenePosDescendants : 1; - quint32 pendingPolish : 1; - quint32 mayHaveChildWithGraphicsEffect : 1; - quint32 isDeclarativeItem : 1; - quint32 sendParentChangeNotification : 1; - quint32 padding : 21; - - // Optional stacking order - int globalStackingOrder; - QGraphicsItem *q_ptr; -}; - -struct QGraphicsItemPrivate::TransformData -{ - QTransform transform; - qreal scale; - qreal rotation; - qreal xOrigin; - qreal yOrigin; - QList<QGraphicsTransform *> graphicsTransforms; - bool onlyTransform; - - TransformData() : - scale(1.0), rotation(0.0), - xOrigin(0.0), yOrigin(0.0), - onlyTransform(true) - { } - - QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const - { - if (onlyTransform) { - if (!postmultiplyTransform || postmultiplyTransform->isIdentity()) - return transform; - if (transform.isIdentity()) - return *postmultiplyTransform; - return transform * *postmultiplyTransform; - } - - QTransform x(transform); - if (!graphicsTransforms.isEmpty()) { - QMatrix4x4 m; - for (int i = 0; i < graphicsTransforms.size(); ++i) - graphicsTransforms.at(i)->applyTo(&m); - x *= m.toTransform(); - } - x.translate(xOrigin, yOrigin); - x.rotate(rotation); - x.scale(scale, scale); - x.translate(-xOrigin, -yOrigin); - if (postmultiplyTransform) - x *= *postmultiplyTransform; - return x; - } -}; - -struct QGraphicsItemPaintInfo -{ - inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2, - const QTransform *const xform3, - QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt, - QPainter *p, qreal o, bool b1, bool b2) - : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w), - option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2) - {} - - const QTransform *viewTransform; - const QTransform *transformPtr; - const QTransform *effectTransform; - QRegion *exposedRegion; - QWidget *widget; - QStyleOptionGraphicsItem *option; - QPainter *painter; - qreal opacity; - quint32 wasDirtySceneTransform : 1; - quint32 drawItem : 1; -}; - -#ifndef QT_NO_GRAPHICSEFFECT -class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate -{ -public: - QGraphicsItemEffectSourcePrivate(QGraphicsItem *i) - : QGraphicsEffectSourcePrivate(), item(i), info(0) - {} - - inline void detach() - { - item->d_ptr->graphicsEffect = 0; - item->prepareGeometryChange(); - } - - inline const QGraphicsItem *graphicsItem() const - { return item; } - - inline const QWidget *widget() const - { return 0; } - - inline void update() { - item->d_ptr->updateDueToGraphicsEffect = true; - item->update(); - item->d_ptr->updateDueToGraphicsEffect = false; - } - - inline void effectBoundingRectChanged() - { item->prepareGeometryChange(); } - - inline bool isPixmap() const - { - return item->type() == QGraphicsPixmapItem::Type - && !(item->flags() & QGraphicsItem::ItemIsSelectable) - && item->d_ptr->children.size() == 0; - //|| (item->d_ptr->isObject && qobject_cast<QDeclarativeImage *>(q_func())); - } - - inline const QStyleOption *styleOption() const - { return info ? info->option : 0; } - - inline QRect deviceRect() const - { - if (!info || !info->widget) { - qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context"); - return QRect(); - } - return info->widget->rect(); - } - - QRectF boundingRect(Qt::CoordinateSystem system) const; - void draw(QPainter *); - QPixmap pixmap(Qt::CoordinateSystem system, - QPoint *offset, - QGraphicsEffect::PixmapPadMode mode) const; - QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const; - - QGraphicsItem *item; - QGraphicsItemPaintInfo *info; - QTransform lastEffectTransform; -}; -#endif //QT_NO_GRAPHICSEFFECT - -/*! - Returns true if \a item1 is on top of \a item2. - The items don't need to be siblings. - - \internal -*/ -inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Siblings? Just check their z-values. - const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); - const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); - if (d1->parent == d2->parent) - return qt_closestLeaf(item1, item2); - - // Find common ancestor, and each item's ancestor closest to the common - // ancestor. - int item1Depth = d1->depth(); - int item2Depth = d2->depth(); - const QGraphicsItem *p = item1; - const QGraphicsItem *t1 = item1; - while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { - if (p == item2) { - // item2 is one of item1's ancestors; item1 is on top - return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t1 = p; - --item1Depth; - } - p = item2; - const QGraphicsItem *t2 = item2; - while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { - if (p == item1) { - // item1 is one of item2's ancestors; item1 is not on top - return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t2 = p; - --item2Depth; - } - - // item1Ancestor is now at the same level as item2Ancestor, but not the same. - const QGraphicsItem *p1 = t1; - const QGraphicsItem *p2 = t2; - while (t1 && t1 != t2) { - p1 = t1; - p2 = t2; - t1 = t1->d_ptr->parent; - t2 = t2->d_ptr->parent; - } - - // in case we have a common ancestor, we compare the immediate children in the ancestor's path. - // otherwise we compare the respective items' topLevelItems directly. - return qt_closestLeaf(p1, p2); -} - -/*! - Returns true if \a item2 is on top of \a item1. - The items don't need to be siblings. - - \internal -*/ -inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return qt_closestItemFirst(item2, item1); -} - -/*! - \internal -*/ -inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Return true if sibling item1 is on top of item2. - const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); - const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); - bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; - bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) - return f2; - if (d1->z != d2->z) - return d1->z > d2->z; - return d1->siblingIndex > d2->siblingIndex; -} - -/*! - \internal -*/ -inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ return qt_closestLeaf(item2, item1); } - -/* - return the full transform of the item to the parent. This include the position and all the transform data -*/ -inline QTransform QGraphicsItemPrivate::transformToParent() const -{ - QTransform matrix; - combineTransformToParent(&matrix); - return matrix; -} - -/*! - \internal -*/ -inline void QGraphicsItemPrivate::ensureSortedChildren() -{ - if (needSortChildren) { - needSortChildren = 0; - sequentialOrdering = 1; - if (children.isEmpty()) - return; - qSort(children.begin(), children.end(), qt_notclosestLeaf); - for (int i = 0; i < children.size(); ++i) { - if (children.at(i)->d_ptr->siblingIndex != i) { - sequentialOrdering = 0; - break; - } - } - } -} - -/*! - \internal -*/ -inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b) -{ - return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex; -} - -/*! - \internal -*/ -inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect) -{ - QGraphicsItemPrivate *parentp = this; -#ifndef QT_NO_GRAPHICSEFFECT - if (updateBoundingRect && parentp->graphicsEffect && !parentp->inSetPosHelper) { - parentp->notifyInvalidated = 1; - static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func() - ->source->d_func())->invalidateCache(); - } -#endif - while (parentp->parent) { - parentp = parentp->parent->d_ptr.data(); - parentp->dirtyChildren = 1; - - if (updateBoundingRect) { - parentp->dirtyChildrenBoundingRect = 1; - // ### Only do this if the parent's effect applies to the entire subtree. - parentp->notifyBoundingRectChanged = 1; - } -#ifndef QT_NO_GRAPHICSEFFECT - if (parentp->graphicsEffect) { - if (updateBoundingRect) { - static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func() - ->source->d_func())->invalidateCache(); - parentp->notifyInvalidated = 1; - } - if (parentp->scene && parentp->graphicsEffect->isEnabled()) { - parentp->dirty = 1; - parentp->fullUpdatePending = 1; - } - } -#endif - } -} - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp deleted file mode 100644 index 104e21cf41..0000000000 --- a/src/gui/graphicsview/qgraphicsitemanimation.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsItemAnimation - \brief The QGraphicsItemAnimation class provides simple animation - support for QGraphicsItem. - \since 4.2 - \ingroup graphicsview-api - \deprecated - - The QGraphicsItemAnimation class animates a QGraphicsItem. You can - schedule changes to the item's transformation matrix at - specified steps. The QGraphicsItemAnimation class has a - current step value. When this value changes the transformations - scheduled at that step are performed. The current step of the - animation is set with the \c setStep() function. - - QGraphicsItemAnimation will do a simple linear interpolation - between the nearest adjacent scheduled changes to calculate the - matrix. For instance, if you set the position of an item at values - 0.0 and 1.0, the animation will show the item moving in a straight - line between these positions. The same is true for scaling and - rotation. - - It is usual to use the class with a QTimeLine. The timeline's - \l{QTimeLine::}{valueChanged()} signal is then connected to the - \c setStep() slot. For example, you can set up an item for rotation - by calling \c setRotationAt() for different step values. - The animations timeline is set with the setTimeLine() function. - - An example animation with a timeline follows: - - \snippet doc/src/snippets/timeline/main.cpp 0 - - Note that steps lie between 0.0 and 1.0. It may be necessary to use - \l{QTimeLine::}{setUpdateInterval()}. The default update interval - is 40 ms. A scheduled transformation cannot be removed when set, - so scheduling several transformations of the same kind (e.g., - rotations) at the same step is not recommended. - - \sa QTimeLine, {Graphics View Framework} -*/ - -#include "qgraphicsitemanimation.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicsitem.h" - -#include <QtCore/qtimeline.h> -#include <QtCore/qpoint.h> -#include <QtCore/qpointer.h> -#include <QtCore/qpair.h> -#include <QtGui/qmatrix.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsItemAnimationPrivate -{ -public: - inline QGraphicsItemAnimationPrivate() - : q(0), timeLine(0), item(0), step(0) - { } - - QGraphicsItemAnimation *q; - - QPointer<QTimeLine> timeLine; - QGraphicsItem *item; - - QPointF startPos; - QMatrix startMatrix; - - qreal step; - - struct Pair { - Pair(qreal a, qreal b) : step(a), value(b) {} - bool operator <(const Pair &other) const - { return step < other.step; } - bool operator==(const Pair &other) const - { return step == other.step; } - qreal step; - qreal value; - }; - QList<Pair> xPosition; - QList<Pair> yPosition; - QList<Pair> rotation; - QList<Pair> verticalScale; - QList<Pair> horizontalScale; - QList<Pair> verticalShear; - QList<Pair> horizontalShear; - QList<Pair> xTranslation; - QList<Pair> yTranslation; - - qreal linearValueForStep(qreal step, QList<Pair> *source, qreal defaultValue = 0); - void insertUniquePair(qreal step, qreal value, QList<Pair> *binList, const char* method); -}; - -qreal QGraphicsItemAnimationPrivate::linearValueForStep(qreal step, QList<Pair> *source, qreal defaultValue) -{ - if (source->isEmpty()) - return defaultValue; - step = qMin<qreal>(qMax<qreal>(step, 0), 1); - - if (step == 1) - return source->last().value; - - qreal stepBefore = 0; - qreal stepAfter = 1; - qreal valueBefore = source->first().step == 0 ? source->first().value : defaultValue; - qreal valueAfter = source->last().value; - - // Find the closest step and value before the given step. - for (int i = 0; i < source->size() && step >= source->at(i).step; ++i) { - stepBefore = source->at(i).step; - valueBefore = source->at(i).value; - } - - // Find the closest step and value after the given step. - for (int j = source->size() - 1; j >= 0 && step < source->at(j).step; --j) { - stepAfter = source->at(j).step; - valueAfter = source->at(j).value; - } - - // Do a simple linear interpolation. - return valueBefore + (valueAfter - valueBefore) * ((step - stepBefore) / (stepAfter - stepBefore)); -} - -void QGraphicsItemAnimationPrivate::insertUniquePair(qreal step, qreal value, QList<Pair> *binList, const char* method) -{ - if (step < 0.0 || step > 1.0) { - qWarning("QGraphicsItemAnimation::%s: invalid step = %f", method, step); - return; - } - - Pair pair(step, value); - - QList<Pair>::iterator result = qBinaryFind(binList->begin(), binList->end(), pair); - if (result != binList->end()) - result->value = value; - else { - *binList << pair; - qSort(binList->begin(), binList->end()); - } -} - -/*! - Constructs an animation object with the given \a parent. -*/ -QGraphicsItemAnimation::QGraphicsItemAnimation(QObject *parent) - : QObject(parent), d(new QGraphicsItemAnimationPrivate) -{ - d->q = this; -} - -/*! - Destroys the animation object. -*/ -QGraphicsItemAnimation::~QGraphicsItemAnimation() -{ - delete d; -} - -/*! - Returns the item on which the animation object operates. - - \sa setItem() -*/ -QGraphicsItem *QGraphicsItemAnimation::item() const -{ - return d->item; -} - -/*! - Sets the specified \a item to be used in the animation. - - \sa item() -*/ -void QGraphicsItemAnimation::setItem(QGraphicsItem *item) -{ - d->item = item; - d->startPos = d->item->pos(); -} - -/*! - Returns the timeline object used to control the rate at which the animation - occurs. - - \sa setTimeLine() -*/ -QTimeLine *QGraphicsItemAnimation::timeLine() const -{ - return d->timeLine; -} - -/*! - Sets the timeline object used to control the rate of animation to the \a timeLine - specified. - - \sa timeLine() -*/ -void QGraphicsItemAnimation::setTimeLine(QTimeLine *timeLine) -{ - if (d->timeLine == timeLine) - return; - if (d->timeLine) - delete d->timeLine; - if (!timeLine) - return; - d->timeLine = timeLine; - connect(timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(setStep(qreal))); -} - -/*! - Returns the position of the item at the given \a step value. - - \sa setPosAt() -*/ -QPointF QGraphicsItemAnimation::posAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::posAt: invalid step = %f", step); - - return QPointF(d->linearValueForStep(step, &d->xPosition, d->startPos.x()), - d->linearValueForStep(step, &d->yPosition, d->startPos.y())); -} - -/*! - \fn void QGraphicsItemAnimation::setPosAt(qreal step, const QPointF &point) - - Sets the position of the item at the given \a step value to the \a point specified. - - \sa posAt() -*/ -void QGraphicsItemAnimation::setPosAt(qreal step, const QPointF &pos) -{ - d->insertUniquePair(step, pos.x(), &d->xPosition, "setPosAt"); - d->insertUniquePair(step, pos.y(), &d->yPosition, "setPosAt"); -} - -/*! - Returns all explicitly inserted positions. - - \sa posAt(), setPosAt() -*/ -QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::posList() const -{ - QList<QPair<qreal, QPointF> > list; - for (int i = 0; i < d->xPosition.size(); ++i) - list << QPair<qreal, QPointF>(d->xPosition.at(i).step, QPointF(d->xPosition.at(i).value, d->yPosition.at(i).value)); - - return list; -} - -/*! - Returns the matrix used to transform the item at the specified \a step value. -*/ -QMatrix QGraphicsItemAnimation::matrixAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::matrixAt: invalid step = %f", step); - - QMatrix matrix; - if (!d->rotation.isEmpty()) - matrix.rotate(rotationAt(step)); - if (!d->verticalScale.isEmpty()) - matrix.scale(horizontalScaleAt(step), verticalScaleAt(step)); - if (!d->verticalShear.isEmpty()) - matrix.shear(horizontalShearAt(step), verticalShearAt(step)); - if (!d->xTranslation.isEmpty()) - matrix.translate(xTranslationAt(step), yTranslationAt(step)); - return matrix; -} - -/*! - Returns the angle at which the item is rotated at the specified \a step value. - - \sa setRotationAt() -*/ -qreal QGraphicsItemAnimation::rotationAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::rotationAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->rotation); -} - -/*! - Sets the rotation of the item at the given \a step value to the \a angle specified. - - \sa rotationAt() -*/ -void QGraphicsItemAnimation::setRotationAt(qreal step, qreal angle) -{ - d->insertUniquePair(step, angle, &d->rotation, "setRotationAt"); -} - -/*! - Returns all explicitly inserted rotations. - - \sa rotationAt(), setRotationAt() -*/ -QList<QPair<qreal, qreal> > QGraphicsItemAnimation::rotationList() const -{ - QList<QPair<qreal, qreal> > list; - for (int i = 0; i < d->rotation.size(); ++i) - list << QPair<qreal, qreal>(d->rotation.at(i).step, d->rotation.at(i).value); - - return list; -} - -/*! - Returns the horizontal translation of the item at the specified \a step value. - - \sa setTranslationAt() -*/ -qreal QGraphicsItemAnimation::xTranslationAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::xTranslationAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->xTranslation); -} - -/*! - Returns the vertical translation of the item at the specified \a step value. - - \sa setTranslationAt() -*/ -qreal QGraphicsItemAnimation::yTranslationAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::yTranslationAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->yTranslation); -} - -/*! - Sets the translation of the item at the given \a step value using the horizontal - and vertical coordinates specified by \a dx and \a dy. - - \sa xTranslationAt(), yTranslationAt() -*/ -void QGraphicsItemAnimation::setTranslationAt(qreal step, qreal dx, qreal dy) -{ - d->insertUniquePair(step, dx, &d->xTranslation, "setTranslationAt"); - d->insertUniquePair(step, dy, &d->yTranslation, "setTranslationAt"); -} - -/*! - Returns all explicitly inserted translations. - - \sa xTranslationAt(), yTranslationAt(), setTranslationAt() -*/ -QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::translationList() const -{ - QList<QPair<qreal, QPointF> > list; - for (int i = 0; i < d->xTranslation.size(); ++i) - list << QPair<qreal, QPointF>(d->xTranslation.at(i).step, QPointF(d->xTranslation.at(i).value, d->yTranslation.at(i).value)); - - return list; -} - -/*! - Returns the vertical scale for the item at the specified \a step value. - - \sa setScaleAt() -*/ -qreal QGraphicsItemAnimation::verticalScaleAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::verticalScaleAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->verticalScale, 1); -} - -/*! - Returns the horizontal scale for the item at the specified \a step value. - - \sa setScaleAt() -*/ -qreal QGraphicsItemAnimation::horizontalScaleAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::horizontalScaleAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->horizontalScale, 1); -} - -/*! - Sets the scale of the item at the given \a step value using the horizontal and - vertical scale factors specified by \a sx and \a sy. - - \sa verticalScaleAt(), horizontalScaleAt() -*/ -void QGraphicsItemAnimation::setScaleAt(qreal step, qreal sx, qreal sy) -{ - d->insertUniquePair(step, sx, &d->horizontalScale, "setScaleAt"); - d->insertUniquePair(step, sy, &d->verticalScale, "setScaleAt"); -} - -/*! - Returns all explicitly inserted scales. - - \sa verticalScaleAt(), horizontalScaleAt(), setScaleAt() -*/ -QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::scaleList() const -{ - QList<QPair<qreal, QPointF> > list; - for (int i = 0; i < d->horizontalScale.size(); ++i) - list << QPair<qreal, QPointF>(d->horizontalScale.at(i).step, QPointF(d->horizontalScale.at(i).value, d->verticalScale.at(i).value)); - - return list; -} - -/*! - Returns the vertical shear for the item at the specified \a step value. - - \sa setShearAt() -*/ -qreal QGraphicsItemAnimation::verticalShearAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::verticalShearAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->verticalShear, 0); -} - -/*! - Returns the horizontal shear for the item at the specified \a step value. - - \sa setShearAt() -*/ -qreal QGraphicsItemAnimation::horizontalShearAt(qreal step) const -{ - if (step < 0.0 || step > 1.0) - qWarning("QGraphicsItemAnimation::horizontalShearAt: invalid step = %f", step); - - return d->linearValueForStep(step, &d->horizontalShear, 0); -} - -/*! - Sets the shear of the item at the given \a step value using the horizontal and - vertical shear factors specified by \a sh and \a sv. - - \sa verticalShearAt(), horizontalShearAt() -*/ -void QGraphicsItemAnimation::setShearAt(qreal step, qreal sh, qreal sv) -{ - d->insertUniquePair(step, sh, &d->horizontalShear, "setShearAt"); - d->insertUniquePair(step, sv, &d->verticalShear, "setShearAt"); -} - -/*! - Returns all explicitly inserted shears. - - \sa verticalShearAt(), horizontalShearAt(), setShearAt() -*/ -QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::shearList() const -{ - QList<QPair<qreal, QPointF> > list; - for (int i = 0; i < d->horizontalShear.size(); ++i) - list << QPair<qreal, QPointF>(d->horizontalShear.at(i).step, QPointF(d->horizontalShear.at(i).value, d->verticalShear.at(i).value)); - - return list; -} - -/*! - Clears the scheduled transformations used for the animation, but - retains the item and timeline. -*/ -void QGraphicsItemAnimation::clear() -{ - d->xPosition.clear(); - d->yPosition.clear(); - d->rotation.clear(); - d->verticalScale.clear(); - d->horizontalScale.clear(); - d->verticalShear.clear(); - d->horizontalShear.clear(); - d->xTranslation.clear(); - d->yTranslation.clear(); -} - -/*! - \fn void QGraphicsItemAnimation::setStep(qreal step) - - Sets the current \a step value for the animation, causing the - transformations scheduled at this step to be performed. -*/ -void QGraphicsItemAnimation::setStep(qreal x) -{ - if (x < 0.0 || x > 1.0) { - qWarning("QGraphicsItemAnimation::setStep: invalid step = %f", x); - return; - } - - beforeAnimationStep(x); - - d->step = x; - if (d->item) { - if (!d->xPosition.isEmpty() || !d->yPosition.isEmpty()) - d->item->setPos(posAt(x)); - if (!d->rotation.isEmpty() - || !d->verticalScale.isEmpty() - || !d->horizontalScale.isEmpty() - || !d->verticalShear.isEmpty() - || !d->horizontalShear.isEmpty() - || !d->xTranslation.isEmpty() - || !d->yTranslation.isEmpty()) { - d->item->setMatrix(d->startMatrix * matrixAt(x)); - } - } - - afterAnimationStep(x); -} - -/*! - Resets the item to its starting position and transformation. - - \obsolete - - You can call setStep(0) instead. -*/ -void QGraphicsItemAnimation::reset() -{ - if (!d->item) - return; - d->startPos = d->item->pos(); - d->startMatrix = d->item->matrix(); -} - -/*! - \fn void QGraphicsItemAnimation::beforeAnimationStep(qreal step) - - This method is meant to be overridden by subclassed that needs to - execute additional code before a new step takes place. The - animation \a step is provided for use in cases where the action - depends on its value. -*/ -void QGraphicsItemAnimation::beforeAnimationStep(qreal step) -{ - Q_UNUSED(step); -} - -/*! - \fn void QGraphicsItemAnimation::afterAnimationStep(qreal step) - - This method is meant to be overridden in subclasses that need to - execute additional code after a new step has taken place. The - animation \a step is provided for use in cases where the action - depends on its value. -*/ -void QGraphicsItemAnimation::afterAnimationStep(qreal step) -{ - Q_UNUSED(step); -} - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsitemanimation.h b/src/gui/graphicsview/qgraphicsitemanimation.h deleted file mode 100644 index e4296cbb7b..0000000000 --- a/src/gui/graphicsview/qgraphicsitemanimation.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSITEMANIMATION_H -#define QGRAPHICSITEMANIMATION_H - -#include <QtCore/qobject.h> - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QGraphicsItem; -class QMatrix; -class QPointF; -class QTimeLine; -template <class T1, class T2> struct QPair; - -class QGraphicsItemAnimationPrivate; -class Q_GUI_EXPORT QGraphicsItemAnimation : public QObject -{ - Q_OBJECT -public: - QGraphicsItemAnimation(QObject *parent = 0); - virtual ~QGraphicsItemAnimation(); - - QGraphicsItem *item() const; - void setItem(QGraphicsItem *item); - - QTimeLine *timeLine() const; - void setTimeLine(QTimeLine *timeLine); - - QPointF posAt(qreal step) const; - QList<QPair<qreal, QPointF> > posList() const; - void setPosAt(qreal step, const QPointF &pos); - - QMatrix matrixAt(qreal step) const; - - qreal rotationAt(qreal step) const; - QList<QPair<qreal, qreal> > rotationList() const; - void setRotationAt(qreal step, qreal angle); - - qreal xTranslationAt(qreal step) const; - qreal yTranslationAt(qreal step) const; - QList<QPair<qreal, QPointF> > translationList() const; - void setTranslationAt(qreal step, qreal dx, qreal dy); - - qreal verticalScaleAt(qreal step) const; - qreal horizontalScaleAt(qreal step) const; - QList<QPair<qreal, QPointF> > scaleList() const; - void setScaleAt(qreal step, qreal sx, qreal sy); - - qreal verticalShearAt(qreal step) const; - qreal horizontalShearAt(qreal step) const; - QList<QPair<qreal, QPointF> > shearList() const; - void setShearAt(qreal step, qreal sh, qreal sv); - - void clear(); - -public Q_SLOTS: - void setStep(qreal x); - void reset(); - -protected: - virtual void beforeAnimationStep(qreal step); - virtual void afterAnimationStep(qreal step); - -private: - Q_DISABLE_COPY(QGraphicsItemAnimation) - QGraphicsItemAnimationPrivate *d; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QT_NO_GRAPHICSVIEW -#endif diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp deleted file mode 100644 index 76d2d040c7..0000000000 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" - -#ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicslayout.h" -#include "qgraphicslayout_p.h" -#include "qgraphicslayoutitem.h" -#include "qgraphicslayoutitem_p.h" -#include "qgraphicswidget.h" -#include "qgraphicswidget_p.h" -#include "qgraphicsscene.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QGraphicsLayout - \brief The QGraphicsLayout class provides the base class for all layouts - in Graphics View. - \since 4.4 - \ingroup graphicsview-api - - QGraphicsLayout is an abstract class that defines a virtual API for - arranging QGraphicsWidget children and other QGraphicsLayoutItem objects - for a QGraphicsWidget. QGraphicsWidget assigns responsibility to a - QGraphicsLayout through QGraphicsWidget::setLayout(). As the widget - is resized, the layout will automatically arrange the widget's children. - QGraphicsLayout inherits QGraphicsLayoutItem, so, it can be managed by - any layout, including its own subclasses. - - \section1 Writing a Custom Layout - - You can use QGraphicsLayout as a base to write your own custom layout - (e.g., a flowlayout), but it is more common to use one of its subclasses - instead - QGraphicsLinearLayout or QGraphicsGridLayout. When creating - a custom layout, the following functions must be reimplemented as a bare - minimum: - - \table - \header \o Function \o Description - \row \o QGraphicsLayoutItem::setGeometry() - \o Notifies you when the geometry of the layout is set. You can - store the geometry in your own layout class in a reimplementation - of this function. - \row \o QGraphicsLayoutItem::sizeHint() - \o Returns the layout's size hints. - \row \o QGraphicsLayout::count() - \o Returns the number of items in your layout. - \row \o QGraphicsLayout::itemAt() - \o Returns a pointer to an item in your layout. - \row \o QGraphicsLayout::removeAt() - \o Removes an item from your layout without destroying it. - \endtable - - For more details on how to implement each function, refer to the individual - function documentation. - - Each layout defines its own API for arranging widgets and layout items. - For example, with a grid layout, you require a row and a - column index with optional row and column spans, alignment, spacing, and more. - A linear layout, however, requires a single row or column index to position its - items. For a grid layout, the order of insertion does not affect the layout in - any way, but for a linear layout, the order is essential. When writing your own - layout subclass, you are free to choose the API that best suits your layout. - - \section1 Activating the Layout - - When the layout's geometry changes, QGraphicsLayout immediately rearranges - all of its managed items by calling setGeometry() on each item. This - rearrangement is called \e activating the layout. - - QGraphicsLayout updates its own geometry to match the contentsRect() of the - QGraphicsLayoutItem it is managing. Thus, it will automatically rearrange all - its items when the widget is resized. QGraphicsLayout caches the sizes of all - its managed items to avoid calling setGeometry() too often. - - \note A QGraphicsLayout will have the same geometry as the contentsRect() - of the widget (not the layout) it is assigned to. - - \section2 Activating the Layout Implicitly - - The layout can be activated implicitly using one of two ways: by calling - activate() or by calling invalidate(). Calling activate() activates the layout - immediately. In contrast, calling invalidate() is delayed, as it posts a - \l{QEvent::LayoutRequest}{LayoutRequest} event to the managed widget. Due - to event compression, the activate() will only be called once after control has - returned to the event loop. This is referred to as \e invalidating the layout. - Invalidating the layout also invalidates any cached information. Also, the - invalidate() function is a virtual function. So, you can invalidate your own - cache in a subclass of QGraphicsLayout by reimplementing this function. - - \section1 Event Handling - - QGraphicsLayout listens to events for the widget it manages through the - virtual widgetEvent() event handler. When the layout is assigned to a - widget, all events delivered to the widget are first processed by - widgetEvent(). This allows the layout to be aware of any relevant state - changes on the widget such as visibility changes or layout direction changes. - - \section1 Margin Handling - - The margins of a QGraphicsLayout can be modified by reimplementing - setContentsMargins() and getContentsMargins(). - -*/ - -/*! - Contructs a QGraphicsLayout object. - - \a parent is passed to QGraphicsLayoutItem's constructor and the - QGraphicsLayoutItem's isLayout argument is set to \e true. - - If \a parent is a QGraphicsWidget the layout will be installed - on that widget. (Note that installing a layout will delete the old one - installed.) -*/ -QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent) - : QGraphicsLayoutItem(*new QGraphicsLayoutPrivate) -{ - setParentLayoutItem(parent); - if (parent && !parent->isLayout()) { - // If a layout has a parent that is not a layout it must be a QGraphicsWidget. - QGraphicsItem *itemParent = parent->graphicsItem(); - if (itemParent && itemParent->isWidget()) { - static_cast<QGraphicsWidget *>(itemParent)->d_func()->setLayout_helper(this); - } else { - qWarning("QGraphicsLayout::QGraphicsLayout: Attempt to create a layout with a parent that is" - " neither a QGraphicsWidget nor QGraphicsLayout"); - } - } - d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType); - setOwnedByLayout(true); -} - -/*! - \internal -*/ -QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutPrivate &dd, QGraphicsLayoutItem *parent) - : QGraphicsLayoutItem(dd) -{ - setParentLayoutItem(parent); - if (parent && !parent->isLayout()) { - // If a layout has a parent that is not a layout it must be a QGraphicsWidget. - QGraphicsItem *itemParent = parent->graphicsItem(); - if (itemParent && itemParent->isWidget()) { - static_cast<QGraphicsWidget *>(itemParent)->d_func()->setLayout_helper(this); - } else { - qWarning("QGraphicsLayout::QGraphicsLayout: Attempt to create a layout with a parent that is" - " neither a QGraphicsWidget nor QGraphicsLayout"); - } - } - d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType); - setOwnedByLayout(true); -} - -/*! - Destroys the QGraphicsLayout object. -*/ -QGraphicsLayout::~QGraphicsLayout() -{ -} - -/*! - Sets the contents margins to \a left, \a top, \a right and \a bottom. The - default contents margins for toplevel layouts are style dependent - (by querying the pixelMetric for QStyle::PM_LayoutLeftMargin, - QStyle::PM_LayoutTopMargin, QStyle::PM_LayoutRightMargin and - QStyle::PM_LayoutBottomMargin). - - For sublayouts the default margins are 0. - - Changing the contents margins automatically invalidates the layout. - - \sa invalidate() -*/ -void QGraphicsLayout::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom) -{ - Q_D(QGraphicsLayout); - if (d->left == left && d->top == top && d->right == right && d->bottom == bottom) - return; - d->left = left; - d->right = right; - d->top = top; - d->bottom = bottom; - invalidate(); -} - -/*! - \reimp -*/ -void QGraphicsLayout::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const -{ - Q_D(const QGraphicsLayout); - d->getMargin(left, d->left, QStyle::PM_LayoutLeftMargin); - d->getMargin(top, d->top, QStyle::PM_LayoutTopMargin); - d->getMargin(right, d->right, QStyle::PM_LayoutRightMargin); - d->getMargin(bottom, d->bottom, QStyle::PM_LayoutBottomMargin); -} - -/*! - Activates the layout, causing all items in the layout to be immediately - rearranged. This function is based on calling count() and itemAt(), and - then calling setGeometry() on all items sequentially. When activated, - the layout will adjust its geometry to its parent's contentsRect(). - The parent will then invalidate any layout of its own. - - If called in sequence or recursively, e.g., by one of the arranged items - in response to being resized, this function will do nothing. - - Note that the layout is free to use geometry caching to optimize this - process. To forcefully invalidate any such cache, you can call - invalidate() before calling activate(). - - \sa invalidate() -*/ -void QGraphicsLayout::activate() -{ - Q_D(QGraphicsLayout); - if (d->activated) - return; - - d->activateRecursive(this); - - // we don't call activate on a sublayout, but somebody might. - // Therefore, we walk to the parentitem of the toplevel layout. - QGraphicsLayoutItem *parentItem = this; - while (parentItem && parentItem->isLayout()) - parentItem = parentItem->parentLayoutItem(); - if (!parentItem) - return; - Q_ASSERT(!parentItem->isLayout()); - - if (QGraphicsLayout::instantInvalidatePropagation()) { - QGraphicsWidget *parentWidget = static_cast<QGraphicsWidget*>(parentItem); - if (!parentWidget->parentLayoutItem()) { - // we've reached the topmost widget, resize it - bool wasResized = parentWidget->testAttribute(Qt::WA_Resized); - parentWidget->resize(parentWidget->size()); - parentWidget->setAttribute(Qt::WA_Resized, wasResized); - } - - setGeometry(parentItem->contentsRect()); // relayout children - } else { - setGeometry(parentItem->contentsRect()); // relayout children - parentLayoutItem()->updateGeometry(); - } -} - -/*! - Returns true if the layout is currently being activated; otherwise, - returns false. If the layout is being activated, this means that it is - currently in the process of rearranging its items (i.e., the activate() - function has been called, and has not yet returned). - - \sa activate(), invalidate() -*/ -bool QGraphicsLayout::isActivated() const -{ - Q_D(const QGraphicsLayout); - return d->activated; -} - -/*! - Clears any cached geometry and size hint information in the layout, and - posts a \l{QEvent::LayoutRequest}{LayoutRequest} event to the managed - parent QGraphicsLayoutItem. - - \sa activate(), setGeometry() -*/ -void QGraphicsLayout::invalidate() -{ - if (QGraphicsLayout::instantInvalidatePropagation()) { - updateGeometry(); - } else { - // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event. - QGraphicsLayoutItem *layoutItem = this; - while (layoutItem && layoutItem->isLayout()) { - // we could call updateGeometry(), but what if that method - // does not call the base implementation? In addition, updateGeometry() - // does more than we need. - layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true; - layoutItem = layoutItem->parentLayoutItem(); - } - if (layoutItem) { - layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true; - } - - bool postIt = layoutItem ? !layoutItem->isLayout() : false; - if (postIt) { - layoutItem = this; - while (layoutItem && layoutItem->isLayout() - && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) { - static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false; - layoutItem = layoutItem->parentLayoutItem(); - } - if (layoutItem && !layoutItem->isLayout()) { - // If a layout has a parent that is not a layout it must be a QGraphicsWidget. - QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest)); - } - } - } -} - -/*! - \reimp -*/ -void QGraphicsLayout::updateGeometry() -{ - Q_D(QGraphicsLayout); - if (QGraphicsLayout::instantInvalidatePropagation()) { - d->activated = false; - QGraphicsLayoutItem::updateGeometry(); - - QGraphicsLayoutItem *parentItem = parentLayoutItem(); - if (!parentItem) - return; - - if (parentItem->isLayout()) - static_cast<QGraphicsLayout *>(parentItem)->invalidate(); - else - parentItem->updateGeometry(); - } else { - QGraphicsLayoutItem::updateGeometry(); - if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) { - if (parentItem->isLayout()) { - parentItem->updateGeometry(); - } else { - invalidate(); - } - } - } -} - -/*! - This virtual event handler receives all events for the managed - widget. QGraphicsLayout uses this event handler to listen for layout - related events such as geometry changes, layout changes or layout - direction changes. - - \a e is a pointer to the event. - - You can reimplement this event handler to track similar events for your - own custom layout. - - \sa QGraphicsWidget::event(), QGraphicsItem::sceneEvent() -*/ -void QGraphicsLayout::widgetEvent(QEvent *e) -{ - switch (e->type()) { - case QEvent::GraphicsSceneResize: - if (isActivated()) { - setGeometry(parentLayoutItem()->contentsRect()); - } else { - activate(); // relies on that activate() will call updateGeometry() - } - break; - case QEvent::LayoutRequest: - activate(); - break; - case QEvent::LayoutDirectionChange: - invalidate(); - break; - default: - break; - } -} - -/*! - \fn virtual int QGraphicsLayout::count() const = 0 - - This pure virtual function must be reimplemented in a subclass of - QGraphicsLayout to return the number of items in the layout. - - The subclass is free to decide how to store the items. - - \sa itemAt(), removeAt() -*/ - -/*! - \fn virtual QGraphicsLayoutItem *QGraphicsLayout::itemAt(int i) const = 0 - - This pure virtual function must be reimplemented in a subclass of - QGraphicsLayout to return a pointer to the item at index \a i. The - reimplementation can assume that \a i is valid (i.e., it respects the - value of count()). - Together with count(), it is provided as a means of iterating over all items in a layout. - - The subclass is free to decide how to store the items, and the visual arrangement - does not have to be reflected through this function. - - \sa count(), removeAt() -*/ - -/*! - \fn virtual void QGraphicsLayout::removeAt(int index) = 0 - - This pure virtual function must be reimplemented in a subclass of - QGraphicsLayout to remove the item at \a index. The - reimplementation can assume that \a index is valid (i.e., it - respects the value of count()). - - The implementation must ensure that the parentLayoutItem() of - the removed item does not point to this layout, since the item is - considered to be removed from the layout hierarchy. - - If the layout is to be reused between applications, we recommend - that the layout deletes the item, but the graphics view framework - does not depend on this. - - The subclass is free to decide how to store the items. - - \sa itemAt(), count() -*/ - -/*! - \since 4.6 - - This function is a convenience function provided for custom layouts, and will go through - all items in the layout and reparent their graphics items to the closest QGraphicsWidget - ancestor of the layout. - - If \a layoutItem is already in a different layout, it will be removed from that layout. - - If custom layouts want special behaviour they can ignore to use this function, and implement - their own behaviour. - - \sa graphicsItem() - */ -void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) -{ - Q_D(QGraphicsLayout); - d->addChildLayoutItem(layoutItem); -} - -static bool g_instantInvalidatePropagation = false; - -/*! - \internal - \since 4.8 - \sa instantInvalidatePropagation() - - Calling this function with \a enable set to true will enable a feature that - makes propagation of invalidation up to ancestor layout items to be done in - one go. It will propagate up the parentLayoutItem() hierarchy until it has - reached the root. If the root item is a QGraphicsWidget, it will *post* a - layout request to it. When the layout request is consumed it will traverse - down the hierarchy of layouts and widgets and activate all layouts that is - invalid (not activated). This is the recommended behaviour. - - If not set it will also propagate up the parentLayoutItem() hierarchy, but - it will stop at the \e{first widget} it encounters, and post a layout - request to the widget. When the layout request is consumed, this might - cause it to continue propagation up to the parentLayoutItem() of the - widget. It will continue in this fashion until it has reached a widget with - no parentLayoutItem(). This strategy might cause drawing artifacts, since - it is not done in one go, and the consumption of layout requests might be - interleaved by consumption of paint events, which might cause significant - flicker. - Note, this is not the recommended behavior, but for compatibility reasons - this is the default behaviour. -*/ -void QGraphicsLayout::setInstantInvalidatePropagation(bool enable) -{ - g_instantInvalidatePropagation = enable; -} - -/*! - \internal - \since 4.8 - \sa setInstantInvalidatePropagation() - - returns true if the complete widget/layout hierarchy is rearranged in one go. -*/ -bool QGraphicsLayout::instantInvalidatePropagation() -{ - return g_instantInvalidatePropagation; -} - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h deleted file mode 100644 index d5bc841854..0000000000 --- a/src/gui/graphicsview/qgraphicslayout.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSLAYOUT_H -#define QGRAPHICSLAYOUT_H - -#include <QtGui/qgraphicslayoutitem.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsLayoutPrivate; -class QGraphicsLayoutItem; -class QGraphicsWidget; - -class Q_GUI_EXPORT QGraphicsLayout : public QGraphicsLayoutItem -{ -public: - QGraphicsLayout(QGraphicsLayoutItem *parent = 0); - ~QGraphicsLayout(); - - void setContentsMargins(qreal left, qreal top, qreal right, qreal bottom); - void getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const; - - void activate(); - bool isActivated() const; - virtual void invalidate(); - virtual void updateGeometry(); - - virtual void widgetEvent(QEvent *e); - - virtual int count() const = 0; - virtual QGraphicsLayoutItem *itemAt(int i) const = 0; - virtual void removeAt(int index) = 0; - - static void setInstantInvalidatePropagation(bool enable); - static bool instantInvalidatePropagation(); -protected: - QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *); - void addChildLayoutItem(QGraphicsLayoutItem *layoutItem); - -private: - Q_DISABLE_COPY(QGraphicsLayout) - Q_DECLARE_PRIVATE(QGraphicsLayout) - friend class QGraphicsWidget; -}; - -Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout") - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif - diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp deleted file mode 100644 index c0df2c0d64..0000000000 --- a/src/gui/graphicsview/qgraphicslayout_p.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicslayout_p.h" -#include "qgraphicslayout.h" -#include "qgraphicswidget.h" -#include "qapplication.h" - -QT_BEGIN_NAMESPACE - -/*! - \internal - - \a mw is the new parent. all items in the layout will be a child of \a mw. - */ -void QGraphicsLayoutPrivate::reparentChildItems(QGraphicsItem *newParent) -{ - Q_Q(QGraphicsLayout); - int n = q->count(); - //bool mwVisible = mw && mw->isVisible(); - for (int i = 0; i < n; ++i) { - QGraphicsLayoutItem *layoutChild = q->itemAt(i); - if (!layoutChild) { - // Skip stretch items - continue; - } - if (layoutChild->isLayout()) { - QGraphicsLayout *l = static_cast<QGraphicsLayout*>(layoutChild); - l->d_func()->reparentChildItems(newParent); - } else if (QGraphicsItem *itemChild = layoutChild->graphicsItem()){ - QGraphicsItem *childParent = itemChild->parentItem(); -#ifdef QT_DEBUG - if (childParent && childParent != newParent && itemChild->isWidget() && qt_graphicsLayoutDebug()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget*>(layoutChild); - qWarning("QGraphicsLayout::addChildLayout: widget %s \"%s\" in wrong parent; moved to correct parent", - w->metaObject()->className(), w->objectName().toLocal8Bit().constData()); - } -#endif - if (childParent != newParent) - itemChild->setParentItem(newParent); - } - } -} - -void QGraphicsLayoutPrivate::getMargin(qreal *result, qreal userMargin, QStyle::PixelMetric pm) const -{ - if (!result) - return; - Q_Q(const QGraphicsLayout); - - QGraphicsLayoutItem *parent = q->parentLayoutItem(); - if (userMargin >= 0.0) { - *result = userMargin; - } else if (!parent) { - *result = 0.0; - } else if (parent->isLayout()) { // sublayouts have 0 margin by default - *result = 0.0; - } else { - *result = 0.0; - if (QGraphicsItem *layoutParentItem = parentItem()) { - if (layoutParentItem->isWidget()) - *result = (qreal)static_cast<QGraphicsWidget*>(layoutParentItem)->style()->pixelMetric(pm, 0); - } - } -} - -Qt::LayoutDirection QGraphicsLayoutPrivate::visualDirection() const -{ - if (QGraphicsItem *maybeWidget = parentItem()) { - if (maybeWidget->isWidget()) - return static_cast<QGraphicsWidget*>(maybeWidget)->layoutDirection(); - } - return QApplication::layoutDirection(); -} - -static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem *layoutItem) -{ - if (!lay) - return false; - - for (int i = lay->count() - 1; i >= 0; --i) { - QGraphicsLayoutItem *child = lay->itemAt(i); - if (child && child->isLayout()) { - if (removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(child), layoutItem)) - return true; - } else if (child == layoutItem) { - lay->removeAt(i); - return true; - } - } - return false; -} - -/*! - \internal - - This function is called from subclasses to add a layout item \a layoutItem - to a layout. - - It takes care of automatically reparenting graphics items, if needed. - - If \a layoutItem is a is already in a layout, it will remove it from that layout. - -*/ -void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) -{ - Q_Q(QGraphicsLayout); - if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) { - if (maybeLayout->isLayout()) - removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(maybeLayout), layoutItem); - } - layoutItem->setParentLayoutItem(q); - if (layoutItem->isLayout()) { - if (QGraphicsItem *parItem = parentItem()) { - static_cast<QGraphicsLayout*>(layoutItem)->d_func()->reparentChildItems(parItem); - } - } else { - if (QGraphicsItem *item = layoutItem->graphicsItem()) { - QGraphicsItem *newParent = parentItem(); - QGraphicsItem *oldParent = item->parentItem(); - if (oldParent == newParent || !newParent) - return; - -#ifdef QT_DEBUG - if (oldParent && item->isWidget()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget*>(item); - qWarning("QGraphicsLayout::addChildLayoutItem: %s \"%s\" in wrong parent; moved to correct parent", - w->metaObject()->className(), w->objectName().toLocal8Bit().constData()); - } -#endif - - item->setParentItem(newParent); - } - } -} - -void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) -{ - if (item->isLayout()) { - QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item); - if (layout->d_func()->activated) { - if (QGraphicsLayout::instantInvalidatePropagation()) { - return; - } else { - layout->invalidate(); // ### LOOKS SUSPICIOUSLY WRONG!!??? - } - } - - for (int i = layout->count() - 1; i >= 0; --i) { - QGraphicsLayoutItem *childItem = layout->itemAt(i); - if (childItem) - activateRecursive(childItem); - } - layout->d_func()->activated = true; - } -} - - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h deleted file mode 100644 index 586cbc77e3..0000000000 --- a/src/gui/graphicsview/qgraphicslayout_p.h +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSLAYOUT_P_H -#define QGRAPHICSLAYOUT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include "qgraphicslayout.h" -#include "qgraphicslayoutitem_p.h" -#include <QtGui/qstyle.h> -#include <QtGui/qwidget.h> -#include <QtGui/qstyleoption.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsLayoutItem; -class QGraphicsWidget; - -#ifdef QT_DEBUG -inline bool qt_graphicsLayoutDebug() -{ - static int checked_env = -1; - if(checked_env == -1) - checked_env = !!qgetenv("QT_GRAPHICSLAYOUT_DEBUG").toInt(); - return checked_env; -} -#endif - - -class QLayoutStyleInfo -{ -public: - inline QLayoutStyleInfo() { invalidate(); } - inline QLayoutStyleInfo(QStyle *style, QWidget *widget) - : m_valid(true), m_style(style), m_widget(widget) - { - Q_ASSERT(style); - if (widget) //### - m_styleOption.initFrom(widget); - m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); - m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing); - } - - inline void invalidate() { m_valid = false; m_style = 0; m_widget = 0; } - - inline QStyle *style() const { return m_style; } - inline QWidget *widget() const { return m_widget; } - - inline bool operator==(const QLayoutStyleInfo &other) - { return m_style == other.m_style && m_widget == other.m_widget; } - inline bool operator!=(const QLayoutStyleInfo &other) - { return !(*this == other); } - - inline void setDefaultSpacing(Qt::Orientation o, qreal spacing){ - if (spacing >= 0) - m_defaultSpacing[o - 1] = spacing; - } - - inline qreal defaultSpacing(Qt::Orientation o) const { - return m_defaultSpacing[o - 1]; - } - - inline qreal perItemSpacing(QSizePolicy::ControlType control1, - QSizePolicy::ControlType control2, - Qt::Orientation orientation) const - { - Q_ASSERT(style()); - return style()->layoutSpacing(control1, control2, orientation, &m_styleOption, widget()); - } -private: - bool m_valid; - QStyle *m_style; - QWidget *m_widget; - QStyleOption m_styleOption; - qreal m_defaultSpacing[2]; -}; - -class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsLayout) - -public: - QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), - activated(true) { } - - void reparentChildItems(QGraphicsItem *newParent); - void getMargin(qreal *result, qreal userMargin, QStyle::PixelMetric pm) const; - Qt::LayoutDirection visualDirection() const; - - void addChildLayoutItem(QGraphicsLayoutItem *item); - void activateRecursive(QGraphicsLayoutItem *item); - - qreal left, top, right, bottom; - bool activated; -}; - - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW - -#endif diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp deleted file mode 100644 index 0631df80dd..0000000000 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ /dev/null @@ -1,935 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicslayout.h" -#include "qgraphicsscene.h" -#include "qgraphicslayoutitem.h" -#include "qgraphicslayoutitem_p.h" -#include "qwidget.h" -#include "qgraphicswidget.h" - -#include <QtDebug> - -QT_BEGIN_NAMESPACE - -/* - COMBINE_SIZE() is identical to combineSize(), except that it - doesn't evaluate 'size' unless necessary. -*/ -#define COMBINE_SIZE(result, size) \ - do { \ - if ((result).width() < 0 || (result).height() < 0) \ - combineSize((result), (size)); \ - } while (false) - -static void combineSize(QSizeF &result, const QSizeF &size) -{ - if (result.width() < 0) - result.setWidth(size.width()); - if (result.height() < 0) - result.setHeight(size.height()); -} - -static void boundSize(QSizeF &result, const QSizeF &size) -{ - if (size.width() >= 0 && size.width() < result.width()) - result.setWidth(size.width()); - if (size.height() >= 0 && size.height() < result.height()) - result.setHeight(size.height()); -} - -static void expandSize(QSizeF &result, const QSizeF &size) -{ - if (size.width() >= 0 && size.width() > result.width()) - result.setWidth(size.width()); - if (size.height() >= 0 && size.height() > result.height()) - result.setHeight(size.height()); -} - -static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent) -{ - if (minimum >= 0 && maximum >= 0 && minimum > maximum) - minimum = maximum; - - if (preferred >= 0) { - if (minimum >= 0 && preferred < minimum) { - preferred = minimum; - } else if (maximum >= 0 && preferred > maximum) { - preferred = maximum; - } - } - - if (minimum >= 0 && descent > minimum) - descent = minimum; -} - -/*! - \internal -*/ -QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout) - : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0) -{ -} - -/*! - \internal -*/ -QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate() -{ - // Remove any lazily allocated data - delete[] userSizeHints; -} - -/*! - \internal -*/ -void QGraphicsLayoutItemPrivate::init() -{ - sizeHintCacheDirty = true; - sizeHintWithConstraintCacheDirty = true; -} - -/*! - \internal -*/ -QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) const -{ - Q_Q(const QGraphicsLayoutItem); - QSizeF *sizeHintCache; - const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0; - if (hasConstraint) { - if (!sizeHintWithConstraintCacheDirty && constraint == cachedConstraint) - return cachedSizeHintsWithConstraints; - sizeHintCache = cachedSizeHintsWithConstraints; - } else { - if (!sizeHintCacheDirty) - return cachedSizeHints; - sizeHintCache = cachedSizeHints; - } - - for (int i = 0; i < Qt::NSizeHints; ++i) { - sizeHintCache[i] = constraint; - if (userSizeHints) - combineSize(sizeHintCache[i], userSizeHints[i]); - } - - QSizeF &minS = sizeHintCache[Qt::MinimumSize]; - QSizeF &prefS = sizeHintCache[Qt::PreferredSize]; - QSizeF &maxS = sizeHintCache[Qt::MaximumSize]; - QSizeF &descentS = sizeHintCache[Qt::MinimumDescent]; - - normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth()); - normalizeHints(minS.rheight(), prefS.rheight(), maxS.rheight(), descentS.rheight()); - - // if the minimum, preferred and maximum sizes contradict each other - // (e.g. the minimum is larger than the maximum) we give priority to - // the maximum size, then the minimum size and finally the preferred size - COMBINE_SIZE(maxS, q->sizeHint(Qt::MaximumSize, maxS)); - combineSize(maxS, QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); - expandSize(maxS, prefS); - expandSize(maxS, minS); - boundSize(maxS, QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); - - COMBINE_SIZE(minS, q->sizeHint(Qt::MinimumSize, minS)); - expandSize(minS, QSizeF(0, 0)); - boundSize(minS, prefS); - boundSize(minS, maxS); - - COMBINE_SIZE(prefS, q->sizeHint(Qt::PreferredSize, prefS)); - expandSize(prefS, minS); - boundSize(prefS, maxS); - - // Not supported yet - // COMBINE_SIZE(descentS, q->sizeHint(Qt::MinimumDescent, constraint)); - - if (hasConstraint) { - cachedConstraint = constraint; - sizeHintWithConstraintCacheDirty = false; - } else { - sizeHintCacheDirty = false; - } - return sizeHintCache; -} - - -/*! - \internal - - Returns the parent item of this layout, or 0 if this layout is - not installed on any widget. - - If this is the item that the layout is installed on, it will return "itself". - - If the layout is a sub-layout, this function returns the parent - widget of the parent layout. - - Note that it will traverse up the layout item hierarchy instead of just calling - QGraphicsItem::parentItem(). This is on purpose. - - \sa parent() -*/ -QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const -{ - Q_Q(const QGraphicsLayoutItem); - - const QGraphicsLayoutItem *parent = q; - while (parent && parent->isLayout()) { - parent = parent->parentLayoutItem(); - } - return parent ? parent->graphicsItem() : 0; -} - -/*! - \internal - - Ensures that userSizeHints is allocated. - This function must be called before any dereferencing. -*/ -void QGraphicsLayoutItemPrivate::ensureUserSizeHints() -{ - if (!userSizeHints) - userSizeHints = new QSizeF[Qt::NSizeHints]; -} - -/*! - \internal - - Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint. - */ -void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size) -{ - Q_Q(QGraphicsLayoutItem); - - if (userSizeHints) { - if (size == userSizeHints[which]) - return; - } else if (size.width() < 0 && size.height() < 0) { - return; - } - - ensureUserSizeHints(); - userSizeHints[which] = size; - q->updateGeometry(); -} - -/*! - \internal - - Sets the width of the user size hint \a which to \a width. - */ -void QGraphicsLayoutItemPrivate::setSizeComponent( - Qt::SizeHint which, SizeComponent component, qreal value) -{ - Q_Q(QGraphicsLayoutItem); - ensureUserSizeHints(); - qreal &userValue = (component == Width) - ? userSizeHints[which].rwidth() - : userSizeHints[which].rheight(); - if (value == userValue) - return; - userValue = value; - q->updateGeometry(); -} - - -bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const -{ - Q_Q(const QGraphicsLayoutItem); - if (isLayout) { - const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q); - for (int i = l->count() - 1; i >= 0; --i) { - if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasHeightForWidth()) - return true; - } - } else if (QGraphicsItem *item = q->graphicsItem()) { - if (item->isWidget()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item); - if (w->layout()) { - return QGraphicsLayoutItemPrivate::get(w->layout())->hasHeightForWidth(); - } - } - } - return q->sizePolicy().hasHeightForWidth(); -} - -bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const -{ - Q_Q(const QGraphicsLayoutItem); - if (isLayout) { - const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q); - for (int i = l->count() - 1; i >= 0; --i) { - if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasWidthForHeight()) - return true; - } - } else if (QGraphicsItem *item = q->graphicsItem()) { - if (item->isWidget()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item); - if (w->layout()) { - return QGraphicsLayoutItemPrivate::get(w->layout())->hasWidthForHeight(); - } - } - } - return q->sizePolicy().hasWidthForHeight(); -} - -/*! - \class QGraphicsLayoutItem - \brief The QGraphicsLayoutItem class can be inherited to allow your custom - items to be managed by layouts. - \since 4.4 - \ingroup graphicsview-api - - QGraphicsLayoutItem is an abstract class that defines a set of virtual - functions describing sizes, size policies, and size hints for any object - arranged by QGraphicsLayout. The API contains functions relevant - for both the item itself and for the user of the item as most of - QGraphicsLayoutItem's functions are also part of the subclass' public API. - - In most cases, existing layout-aware classes such as QGraphicsWidget and - QGraphicsLayout already provide the functionality you require. However, - subclassing these classes will enable you to create both graphical - elements that work well with layouts (QGraphicsWidget) or custom layouts - (QGraphicsLayout). - - \section1 Subclassing QGraphicsLayoutItem - - If you create a subclass of QGraphicsLayoutItem and reimplement its - virtual functions, you will enable the layout to resize and position your - item along with other QGraphicsLayoutItems including QGraphicsWidget - and QGraphicsLayout. - - You can start by reimplementing important functions: the protected - sizeHint() function, as well as the public setGeometry() - function. If you want your items to be aware of immediate geometry - changes, you can also reimplement updateGeometry(). - - The geometry, size hint, and size policy affect the item's size and - position. Calling setGeometry() will always resize and reposition the item - immediately. Normally, this function is called by QGraphicsLayout after - the layout has been activated, but it can also be called by the item's user - at any time. - - The sizeHint() function returns the item' minimum, preferred and maximum - size hints. You can override these properties by calling setMinimumSize(), - setPreferredSize() or setMaximumSize(). You can also use functions such as - setMinimumWidth() or setMaximumHeight() to set only the width or height - component if desired. - - The effectiveSizeHint() function, on the other hand, returns a size hint - for any given Qt::SizeHint, and guarantees that the returned size is bound - to the minimum and maximum sizes and size hints. You can set the item's - vertical and horizontal size policy by calling setSizePolicy(). The - sizePolicy property is used by the layout system to describe how this item - prefers to grow or shrink. - - \section1 Nesting QGraphicsLayoutItems - - QGraphicsLayoutItems can be nested within other QGraphicsLayoutItems, - similar to layouts that can contain sublayouts. This is done either by - passing a QGraphicsLayoutItem pointer to QGraphicsLayoutItem's - protected constructor, or by calling setParentLayoutItem(). The - parentLayoutItem() function returns a pointer to the item's layoutItem - parent. If the item's parent is 0 or if the parent does not inherit - from QGraphicsItem, the parentLayoutItem() function then returns 0. - isLayout() returns true if the QGraphicsLayoutItem subclass is itself a - layout, or false otherwise. - - Qt uses QGraphicsLayoutItem to provide layout functionality in the - \l{Graphics View Framework}, but in the future its use may spread - throughout Qt itself. - - \sa QGraphicsWidget, QGraphicsLayout, QGraphicsLinearLayout, - QGraphicsGridLayout -*/ - -/*! - Constructs the QGraphicsLayoutItem object. \a parent becomes the object's - parent. If \a isLayout is true the item is a layout, otherwise - \a isLayout is false. -*/ -QGraphicsLayoutItem::QGraphicsLayoutItem(QGraphicsLayoutItem *parent, bool isLayout) - : d_ptr(new QGraphicsLayoutItemPrivate(parent, isLayout)) -{ - Q_D(QGraphicsLayoutItem); - d->init(); - d->sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - d->q_ptr = this; -} - -/*! - \internal -*/ -QGraphicsLayoutItem::QGraphicsLayoutItem(QGraphicsLayoutItemPrivate &dd) - : d_ptr(&dd) -{ - Q_D(QGraphicsLayoutItem); - d->init(); - d->q_ptr = this; -} - -/*! - Destroys the QGraphicsLayoutItem object. -*/ -QGraphicsLayoutItem::~QGraphicsLayoutItem() -{ - QGraphicsLayoutItem *parentLI = parentLayoutItem(); - if (parentLI && parentLI->isLayout()) { - QGraphicsLayout *lay = static_cast<QGraphicsLayout*>(parentLI); - // this is not optimal - for (int i = lay->count() - 1; i >= 0; --i) { - if (lay->itemAt(i) == this) { - lay->removeAt(i); - break; - } - } - } -} - -/*! - \fn virtual QSizeF QGraphicsLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0; - - This pure virtual function returns the size hint for \a which of the - QGraphicsLayoutItem, using the width or height of \a constraint to - constrain the output. - - Reimplement this function in a subclass of QGraphicsLayoutItem to - provide the necessary size hints for your items. - - \sa effectiveSizeHint() -*/ - -/*! - Sets the size policy to \a policy. The size policy describes how the item - should grow horizontally and vertically when arranged in a layout. - - QGraphicsLayoutItem's default size policy is (QSizePolicy::Fixed, - QSizePolicy::Fixed, QSizePolicy::DefaultType), but it is common for - subclasses to change the default. For example, QGraphicsWidget defaults - to (QSizePolicy::Preferred, QSizePolicy::Preferred, - QSizePolicy::DefaultType). - - \sa sizePolicy(), QWidget::sizePolicy() -*/ -void QGraphicsLayoutItem::setSizePolicy(const QSizePolicy &policy) -{ - Q_D(QGraphicsLayoutItem); - if (d->sizePolicy == policy) - return; - d->sizePolicy = policy; - updateGeometry(); -} - -/*! - \overload - - This function is equivalent to calling - setSizePolicy(QSizePolicy(\a hPolicy, \a vPolicy, \a controlType)). - - \sa sizePolicy(), QWidget::sizePolicy() -*/ -void QGraphicsLayoutItem::setSizePolicy(QSizePolicy::Policy hPolicy, - QSizePolicy::Policy vPolicy, - QSizePolicy::ControlType controlType) -{ - setSizePolicy(QSizePolicy(hPolicy, vPolicy, controlType)); -} - -/*! - Returns the current size policy. - - \sa setSizePolicy(), QWidget::sizePolicy() -*/ -QSizePolicy QGraphicsLayoutItem::sizePolicy() const -{ - Q_D(const QGraphicsLayoutItem); - return d->sizePolicy; -} - -/*! - Sets the minimum size to \a size. This property overrides sizeHint() for - Qt::MinimumSize and ensures that effectiveSizeHint() will never return - a size smaller than \a size. In order to unset the minimum size, use an - invalid size. - - \sa minimumSize(), maximumSize(), preferredSize(), Qt::MinimumSize, - sizeHint(), setMinimumWidth(), setMinimumHeight() -*/ -void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size) -{ - d_ptr->setSize(Qt::MinimumSize, size); -} - -/*! - \fn QGraphicsLayoutItem::setMinimumSize(qreal w, qreal h) - - This convenience function is equivalent to calling - setMinimumSize(QSizeF(\a w, \a h)). - - \sa minimumSize(), setMaximumSize(), setPreferredSize(), sizeHint() -*/ - -/*! - Returns the minimum size. - - \sa setMinimumSize(), preferredSize(), maximumSize(), Qt::MinimumSize, - sizeHint() -*/ -QSizeF QGraphicsLayoutItem::minimumSize() const -{ - return effectiveSizeHint(Qt::MinimumSize); -} - -/*! - Sets the minimum width to \a width. - - \sa minimumWidth(), setMinimumSize(), minimumSize() -*/ -void QGraphicsLayoutItem::setMinimumWidth(qreal width) -{ - d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width); -} - -/*! - Sets the minimum height to \a height. - - \sa minimumHeight(), setMinimumSize(), minimumSize() -*/ -void QGraphicsLayoutItem::setMinimumHeight(qreal height) -{ - d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height); -} - - -/*! - Sets the preferred size to \a size. This property overrides sizeHint() for - Qt::PreferredSize and provides the default value for effectiveSizeHint(). - In order to unset the preferred size, use an invalid size. - - \sa preferredSize(), minimumSize(), maximumSize(), Qt::PreferredSize, - sizeHint() -*/ -void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size) -{ - d_ptr->setSize(Qt::PreferredSize, size); -} - -/*! - \fn QGraphicsLayoutItem::setPreferredSize(qreal w, qreal h) - - This convenience function is equivalent to calling - setPreferredSize(QSizeF(\a w, \a h)). - - \sa preferredSize(), setMaximumSize(), setMinimumSize(), sizeHint() -*/ - -/*! - Returns the preferred size. - - \sa setPreferredSize(), minimumSize(), maximumSize(), Qt::PreferredSize, - sizeHint() -*/ -QSizeF QGraphicsLayoutItem::preferredSize() const -{ - return effectiveSizeHint(Qt::PreferredSize); -} - -/*! - Sets the preferred height to \a height. - - \sa preferredWidth(), setPreferredSize(), preferredSize() -*/ -void QGraphicsLayoutItem::setPreferredHeight(qreal height) -{ - d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height); -} - -/*! - Sets the preferred width to \a width. - - \sa preferredHeight(), setPreferredSize(), preferredSize() -*/ -void QGraphicsLayoutItem::setPreferredWidth(qreal width) -{ - d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width); -} - -/*! - Sets the maximum size to \a size. This property overrides sizeHint() for - Qt::MaximumSize and ensures that effectiveSizeHint() will never return a - size larger than \a size. In order to unset the maximum size, use an - invalid size. - - \sa maximumSize(), minimumSize(), preferredSize(), Qt::MaximumSize, - sizeHint() -*/ -void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size) -{ - d_ptr->setSize(Qt::MaximumSize, size); -} - -/*! - \fn QGraphicsLayoutItem::setMaximumSize(qreal w, qreal h) - - This convenience function is equivalent to calling - setMaximumSize(QSizeF(\a w, \a h)). - - \sa maximumSize(), setMinimumSize(), setPreferredSize(), sizeHint() -*/ - -/*! - Returns the maximum size. - - \sa setMaximumSize(), minimumSize(), preferredSize(), Qt::MaximumSize, - sizeHint() -*/ -QSizeF QGraphicsLayoutItem::maximumSize() const -{ - return effectiveSizeHint(Qt::MaximumSize); -} - -/*! - Sets the maximum width to \a width. - - \sa maximumWidth(), setMaximumSize(), maximumSize() -*/ -void QGraphicsLayoutItem::setMaximumWidth(qreal width) -{ - d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width); -} - -/*! - Sets the maximum height to \a height. - - \sa maximumHeight(), setMaximumSize(), maximumSize() -*/ -void QGraphicsLayoutItem::setMaximumHeight(qreal height) -{ - d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height); -} - -/*! - \fn qreal QGraphicsLayoutItem::minimumWidth() const - - Returns the minimum width. - - \sa setMinimumWidth(), setMinimumSize(), minimumSize() -*/ - -/*! - \fn qreal QGraphicsLayoutItem::minimumHeight() const - - Returns the minimum height. - - \sa setMinimumHeight(), setMinimumSize(), minimumSize() -*/ - -/*! - \fn qreal QGraphicsLayoutItem::preferredWidth() const - - Returns the preferred width. - - \sa setPreferredWidth(), setPreferredSize(), preferredSize() -*/ - -/*! - \fn qreal QGraphicsLayoutItem::preferredHeight() const - - Returns the preferred height. - - \sa setPreferredHeight(), setPreferredSize(), preferredSize() -*/ - -/*! - \fn qreal QGraphicsLayoutItem::maximumWidth() const - - Returns the maximum width. - - \sa setMaximumWidth(), setMaximumSize(), maximumSize() -*/ - -/*! - \fn qreal QGraphicsLayoutItem::maximumHeight() const - - Returns the maximum height. - - \sa setMaximumHeight(), setMaximumSize(), maximumSize() -*/ - -/*! - \fn virtual void QGraphicsLayoutItem::setGeometry(const QRectF &rect) - - This virtual function sets the geometry of the QGraphicsLayoutItem to - \a rect, which is in parent coordinates (e.g., the top-left corner of \a rect - is equivalent to the item's position in parent coordinates). - - You must reimplement this function in a subclass of QGraphicsLayoutItem to - receive geometry updates. The layout will call this function when it does a - rearrangement. - - If \a rect is outside of the bounds of minimumSize and maximumSize, it - will be adjusted to its closest size so that it is within the legal - bounds. - - \sa geometry() -*/ -void QGraphicsLayoutItem::setGeometry(const QRectF &rect) -{ - Q_D(QGraphicsLayoutItem); - QSizeF effectiveSize = rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize)) - .boundedTo(effectiveSizeHint(Qt::MaximumSize)); - d->geom = QRectF(rect.topLeft(), effectiveSize); -} - -/*! - \fn QRectF QGraphicsLayoutItem::geometry() const - - Returns the item's geometry (e.g., position and size) as a - QRectF. This function is equivalent to QRectF(pos(), size()). - - \sa setGeometry() -*/ -QRectF QGraphicsLayoutItem::geometry() const -{ - Q_D(const QGraphicsLayoutItem); - return d->geom; -} - -/*! - This virtual function provides the \a left, \a top, \a right and \a bottom - contents margins for this QGraphicsLayoutItem. The default implementation - assumes all contents margins are 0. The parameters point to values stored - in qreals. If any of the pointers is 0, that value will not be updated. - - \sa QGraphicsWidget::setContentsMargins() -*/ -void QGraphicsLayoutItem::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const -{ - if (left) - *left = 0; - if (top) - *top = 0; - if (right) - *right = 0; - if (bottom) - *bottom = 0; -} - -/*! - Returns the contents rect in local coordinates. - - The contents rect defines the subrectangle used by an associated layout - when arranging subitems. This function is a convenience function that - adjusts the item's geometry() by its contents margins. Note that - getContentsMargins() is a virtual function that you can reimplement to - return the item's contents margins. - - \sa getContentsMargins(), geometry() -*/ -QRectF QGraphicsLayoutItem::contentsRect() const -{ - qreal left, top, right, bottom; - getContentsMargins(&left, &top, &right, &bottom); - return QRectF(QPointF(), geometry().size()).adjusted(+left, +top, -right, -bottom); -} - -/*! - Returns the effective size hint for this QGraphicsLayoutItem. - - \a which is the size hint in question. - \a constraint is an optional argument that defines a special constrain - when calculating the effective size hint. By default, \a constraint is - QSizeF(-1, -1), which means there is no constraint to the size hint. - - If you want to specify the widget's size hint for a given width or height, - you can provide the fixed dimension in \a constraint. This is useful for - widgets that can grow only either vertically or horizontally, and need to - set either their width or their height to a special value. - - For example, a text paragraph item fit into a column width of 200 may - grow vertically. You can pass QSizeF(200, -1) as a constraint to get a - suitable minimum, preferred and maximum height). - - You can adjust the effective size hint by reimplementing sizeHint() - in a QGraphicsLayoutItem subclass, or by calling one of the following - functions: setMinimumSize(), setPreferredSize, or setMaximumSize() - (or a combination of both). - - This function caches each of the size hints and guarantees that - sizeHint() will be called only once for each value of \a which - unless - \a constraint is not specified and updateGeometry() has been called. - - \sa sizeHint() -*/ -QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_D(const QGraphicsLayoutItem); - - if (!d->userSizeHints && constraint.isValid()) - return constraint; - - // ### should respect size policy??? - return d_ptr->effectiveSizeHints(constraint)[which]; -} - -/*! - This virtual function discards any cached size hint information. You - should always call this function if you change the return value of the - sizeHint() function. Subclasses must always call the base implementation - when reimplementing this function. - - \sa effectiveSizeHint() -*/ -void QGraphicsLayoutItem::updateGeometry() -{ - Q_D(QGraphicsLayoutItem); - d->sizeHintCacheDirty = true; - d->sizeHintWithConstraintCacheDirty = true; -} - -/*! - Returns the parent of this QGraphicsLayoutItem, or 0 if there is no parent, - or if the parent does not inherit from QGraphicsLayoutItem - (QGraphicsLayoutItem is often used through multiple inheritance with - QObject-derived classes). - - \sa setParentLayoutItem() -*/ -QGraphicsLayoutItem *QGraphicsLayoutItem::parentLayoutItem() const -{ - return d_func()->parent; -} - -/*! - Sets the parent of this QGraphicsLayoutItem to \a parent. - - \sa parentLayoutItem() -*/ -void QGraphicsLayoutItem::setParentLayoutItem(QGraphicsLayoutItem *parent) -{ - d_func()->parent = parent; -} - -/*! - Returns true if this QGraphicsLayoutItem is a layout (e.g., is inherited - by an object that arranges other QGraphicsLayoutItem objects); otherwise - returns false. - - \sa QGraphicsLayout -*/ -bool QGraphicsLayoutItem::isLayout() const -{ - return d_func()->isLayout; -} - -/*! - \since 4.6 - - Returns whether a layout should delete this item in its destructor. - If its true, then the layout will delete it. If its false, then it is - assumed that another object has the ownership of it, and the layout won't - delete this item. - - If the item inherits both QGraphicsItem and QGraphicsLayoutItem (such - as QGraphicsWidget does) the item is really part of two ownership - hierarchies. This property informs what the layout should do with its - child items when it is destructed. In the case of QGraphicsWidget, it - is preferred that when the layout is deleted it won't delete its children - (since they are also part of the graphics item hierarchy). - - By default this value is initialized to false in QGraphicsLayoutItem, - but it is overridden by QGraphicsLayout to return true. This is because - QGraphicsLayout is not normally part of the QGraphicsItem hierarchy, so the - parent layout should delete it. - Subclasses might override this default behaviour by calling - setOwnedByLayout(true). - - \sa setOwnedByLayout() -*/ -bool QGraphicsLayoutItem::ownedByLayout() const -{ - return d_func()->ownedByLayout; -} -/*! - \since 4.6 - - Sets whether a layout should delete this item in its destructor or not. - \a ownership must be true to in order for the layout to delete it. - \sa ownedByLayout() -*/ -void QGraphicsLayoutItem::setOwnedByLayout(bool ownership) -{ - d_func()->ownedByLayout = ownership; -} - -/*! - * Returns the QGraphicsItem that this layout item represents. - * For QGraphicsWidget it will return itself. For custom items it can return an - * aggregated value. - * - * \sa setGraphicsItem() - */ -QGraphicsItem *QGraphicsLayoutItem::graphicsItem() const -{ - return d_func()->graphicsItem; -} - -/*! - * If the QGraphicsLayoutItem represents a QGraphicsItem, and it wants to take - * advantage of the automatic reparenting capabilities of QGraphicsLayout it - * should set this value. - * Note that if you delete \a item and not delete the layout item, you are - * responsible of calling setGraphicsItem(0) in order to avoid having a - * dangling pointer. - * - * \sa graphicsItem() - */ -void QGraphicsLayoutItem::setGraphicsItem(QGraphicsItem *item) -{ - d_func()->graphicsItem = item; -} - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h deleted file mode 100644 index 12c1b892c4..0000000000 --- a/src/gui/graphicsview/qgraphicslayoutitem.h +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSLAYOUTITEM_H -#define QGRAPHICSLAYOUTITEM_H - -#include <QtCore/qscopedpointer.h> -#include <QtGui/qsizepolicy.h> -#include <QtGui/qevent.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsLayoutItemPrivate; -class QGraphicsItem; -class Q_GUI_EXPORT QGraphicsLayoutItem -{ -public: - QGraphicsLayoutItem(QGraphicsLayoutItem *parent = 0, bool isLayout = false); - virtual ~QGraphicsLayoutItem(); - - void setSizePolicy(const QSizePolicy &policy); - void setSizePolicy(QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy, QSizePolicy::ControlType controlType = QSizePolicy::DefaultType); - QSizePolicy sizePolicy() const; - - void setMinimumSize(const QSizeF &size); - inline void setMinimumSize(qreal w, qreal h); - QSizeF minimumSize() const; - void setMinimumWidth(qreal width); - inline qreal minimumWidth() const; - void setMinimumHeight(qreal height); - inline qreal minimumHeight() const; - - void setPreferredSize(const QSizeF &size); - inline void setPreferredSize(qreal w, qreal h); - QSizeF preferredSize() const; - void setPreferredWidth(qreal width); - inline qreal preferredWidth() const; - void setPreferredHeight(qreal height); - inline qreal preferredHeight() const; - - void setMaximumSize(const QSizeF &size); - inline void setMaximumSize(qreal w, qreal h); - QSizeF maximumSize() const; - void setMaximumWidth(qreal width); - inline qreal maximumWidth() const; - void setMaximumHeight(qreal height); - inline qreal maximumHeight() const; - - virtual void setGeometry(const QRectF &rect); - QRectF geometry() const; - virtual void getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const; - QRectF contentsRect() const; - - QSizeF effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - - virtual void updateGeometry(); //### rename to sizeHintChanged() - - QGraphicsLayoutItem *parentLayoutItem() const; - void setParentLayoutItem(QGraphicsLayoutItem *parent); - - bool isLayout() const; - // ###Qt5: Make automatic reparenting work regardless of item/object/widget type. - QGraphicsItem *graphicsItem() const; - bool ownedByLayout() const; - -protected: - void setGraphicsItem(QGraphicsItem *item); - void setOwnedByLayout(bool ownedByLayout); - QGraphicsLayoutItem(QGraphicsLayoutItemPrivate &dd); - - virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const = 0; - QScopedPointer<QGraphicsLayoutItemPrivate> d_ptr; - -private: - QSizeF *effectiveSizeHints(const QSizeF &constraint) const; - Q_DECLARE_PRIVATE(QGraphicsLayoutItem) - - friend class QGraphicsLayout; -}; - -Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem") - -inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah) -{ setMinimumSize(QSizeF(aw, ah)); } -inline void QGraphicsLayoutItem::setPreferredSize(qreal aw, qreal ah) -{ setPreferredSize(QSizeF(aw, ah)); } -inline void QGraphicsLayoutItem::setMaximumSize(qreal aw, qreal ah) -{ setMaximumSize(QSizeF(aw, ah)); } - -inline qreal QGraphicsLayoutItem::minimumWidth() const -{ return effectiveSizeHint(Qt::MinimumSize).width(); } -inline qreal QGraphicsLayoutItem::minimumHeight() const -{ return effectiveSizeHint(Qt::MinimumSize).height(); } - -inline qreal QGraphicsLayoutItem::preferredWidth() const -{ return effectiveSizeHint(Qt::PreferredSize).width(); } -inline qreal QGraphicsLayoutItem::preferredHeight() const -{ return effectiveSizeHint(Qt::PreferredSize).height(); } - -inline qreal QGraphicsLayoutItem::maximumWidth() const -{ return effectiveSizeHint(Qt::MaximumSize).width(); } -inline qreal QGraphicsLayoutItem::maximumHeight() const -{ return effectiveSizeHint(Qt::MaximumSize).height(); } - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/gui/graphicsview/qgraphicslayoutitem_p.h b/src/gui/graphicsview/qgraphicslayoutitem_p.h deleted file mode 100644 index c44dd81d29..0000000000 --- a/src/gui/graphicsview/qgraphicslayoutitem_p.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSLAYOUTITEM_P_H -#define QGRAPHICSLAYOUTITEM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QSizeF> -#include <QtGui/QSizePolicy> - -QT_BEGIN_NAMESPACE - -class QGraphicsLayoutItem; -class Q_AUTOTEST_EXPORT QGraphicsLayoutItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsLayoutItem) -public: - virtual ~QGraphicsLayoutItemPrivate(); - QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout); - static QGraphicsLayoutItemPrivate *get(QGraphicsLayoutItem *q) { return q->d_func();} - static const QGraphicsLayoutItemPrivate *get(const QGraphicsLayoutItem *q) { return q->d_func();} - - void init(); - QSizeF *effectiveSizeHints(const QSizeF &constraint) const; - QGraphicsItem *parentItem() const; - void ensureUserSizeHints(); - void setSize(Qt::SizeHint which, const QSizeF &size); - enum SizeComponent { Width, Height }; - void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value); - - bool hasHeightForWidth() const; - bool hasWidthForHeight() const; - - QSizePolicy sizePolicy; - QGraphicsLayoutItem *parent; - - QSizeF *userSizeHints; - mutable QSizeF cachedSizeHints[Qt::NSizeHints]; - mutable QSizeF cachedConstraint; - mutable QSizeF cachedSizeHintsWithConstraints[Qt::NSizeHints]; - - mutable quint32 sizeHintCacheDirty : 1; - mutable quint32 sizeHintWithConstraintCacheDirty : 1; - quint32 isLayout : 1; - quint32 ownedByLayout : 1; - - QGraphicsLayoutItem *q_ptr; - QRectF geom; - QGraphicsItem *graphicsItem; -}; - -QT_END_NAMESPACE - -#endif //QGRAPHICSLAYOUTITEM_P_H - diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp deleted file mode 100644 index 2a5d5a510e..0000000000 --- a/src/gui/graphicsview/qgraphicslinearlayout.cpp +++ /dev/null @@ -1,564 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsLinearLayout - \brief The QGraphicsLinearLayout class provides a horizontal or vertical - layout for managing widgets in Graphics View. - \since 4.4 - \ingroup graphicsview-api - - The default orientation for a linear layout is Qt::Horizontal. You can - choose a vertical orientation either by calling setOrientation(), or by - passing Qt::Vertical to QGraphicsLinearLayout's constructor. - - The most common way to use QGraphicsLinearLayout is to construct an object - on the heap with no parent, add widgets and layouts by calling addItem(), - and finally assign the layout to a widget by calling - QGraphicsWidget::setLayout(). - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicslinearlayout.cpp 0 - - You can add widgets, layouts, stretches (addStretch(), insertStretch() or - setStretchFactor()), and spacings (setItemSpacing()) to a linear - layout. The layout takes ownership of the items. In some cases when the layout - item also inherits from QGraphicsItem (such as QGraphicsWidget) there will be a - ambiguity in ownership because the layout item belongs to two ownership hierarchies. - See the documentation of QGraphicsLayoutItem::setOwnedByLayout() how to handle - this. - You can access each item in the layout by calling count() and itemAt(). Calling - removeAt() or removeItem() will remove an item from the layout, without - destroying it. - - \section1 Size Hints and Size Policies in QGraphicsLinearLayout - - QGraphicsLinearLayout respects each item's size hints and size policies, - and when the layout contains more space than the items can fill, each item - is arranged according to the layout's alignment for that item. You can set - an alignment for each item by calling setAlignment(), and check the - alignment for any item by calling alignment(). By default, items are - aligned to the top left. - - \section1 Spacing within QGraphicsLinearLayout - - Between the items, the layout distributes some space. The actual amount of - space depends on the managed widget's current style, but the common - spacing is 4. You can also set your own spacing by calling setSpacing(), - and get the current spacing value by calling spacing(). If you want to - configure individual spacing for your items, you can call setItemSpacing(). - - \section1 Stretch Factor in QGraphicsLinearLayout - - You can assign a stretch factor to each item to control how much space it - will get compared to the other items. By default, two identical widgets - arranged in a linear layout will have the same size, but if the first - widget has a stretch factor of 1 and the second widget has a stretch - factor of 2, the first widget will get 1/3 of the available space, and the - second will get 2/3. - - QGraphicsLinearLayout calculates the distribution of sizes by adding up - the stretch factors of all items, and then dividing the available space - accordingly. The default stretch factor is 0 for all items; a factor of 0 - means the item does not have any defined stretch factor; effectively this - is the same as setting the stretch factor to 1. The stretch factor only - applies to the available space in the lengthwise direction of the layout - (following its orientation). If you want to control both the item's - horizontal and vertical stretch, you can use QGraphicsGridLayout instead. - - \section1 QGraphicsLinearLayout Compared to Other Layouts - - QGraphicsLinearLayout is very similar to QVBoxLayout and QHBoxLayout, but - in contrast to these classes, it is used to manage QGraphicsWidget and - QGraphicsLayout instead of QWidget and QLayout. - - \sa QGraphicsGridLayout, QGraphicsWidget -*/ - -#include "qapplication.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qwidget.h" -#include "qgraphicslayout_p.h" -#include "qgraphicslayoutitem.h" -#include "qgraphicslinearlayout.h" -#include "qgraphicswidget.h" -#include "qgridlayoutengine_p.h" -#ifdef QT_DEBUG -#include <QtCore/qdebug.h> -#endif - -QT_BEGIN_NAMESPACE - -class QGraphicsLinearLayoutPrivate : public QGraphicsLayoutPrivate -{ -public: - QGraphicsLinearLayoutPrivate(Qt::Orientation orientation) : orientation(orientation) { } - - void removeGridItem(QGridLayoutItem *gridItem); - QLayoutStyleInfo styleInfo() const; - void fixIndex(int *index) const; - int gridRow(int index) const; - int gridColumn(int index) const; - - Qt::Orientation orientation; - QGridLayoutEngine engine; -}; - -void QGraphicsLinearLayoutPrivate::removeGridItem(QGridLayoutItem *gridItem) -{ - int index = gridItem->firstRow(orientation); - engine.removeItem(gridItem); - engine.removeRows(index, 1, orientation); -} - -void QGraphicsLinearLayoutPrivate::fixIndex(int *index) const -{ - int count = engine.rowCount(orientation); - if (uint(*index) > uint(count)) - *index = count; -} - -int QGraphicsLinearLayoutPrivate::gridRow(int index) const -{ - if (orientation == Qt::Horizontal) - return 0; - return int(qMin(uint(index), uint(engine.rowCount()))); -} - -int QGraphicsLinearLayoutPrivate::gridColumn(int index) const -{ - if (orientation == Qt::Vertical) - return 0; - return int(qMin(uint(index), uint(engine.columnCount()))); -} - -Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget) - -QLayoutStyleInfo QGraphicsLinearLayoutPrivate::styleInfo() const -{ - QGraphicsItem *item = parentItem(); - QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); - return QLayoutStyleInfo(style, globalStyleInfoWidget()); -} - -/*! - Constructs a QGraphicsLinearLayout instance. You can pass the - \a orientation for the layout, either horizontal or vertical, and - \a parent is passed to QGraphicsLayout's constructor. -*/ -QGraphicsLinearLayout::QGraphicsLinearLayout(Qt::Orientation orientation, QGraphicsLayoutItem *parent) - : QGraphicsLayout(*new QGraphicsLinearLayoutPrivate(orientation), parent) -{ -} - -/*! - Constructs a QGraphicsLinearLayout instance using Qt::Horizontal - orientation. \a parent is passed to QGraphicsLayout's constructor. -*/ -QGraphicsLinearLayout::QGraphicsLinearLayout(QGraphicsLayoutItem *parent) - : QGraphicsLayout(*new QGraphicsLinearLayoutPrivate(Qt::Horizontal), parent) -{ -} - -/*! - Destroys the QGraphicsLinearLayout object. -*/ -QGraphicsLinearLayout::~QGraphicsLinearLayout() -{ - for (int i = count() - 1; i >= 0; --i) { - QGraphicsLayoutItem *item = itemAt(i); - // The following lines can be removed, but this removes the item - // from the layout more efficiently than the implementation of - // ~QGraphicsLayoutItem. - removeAt(i); - if (item) { - item->setParentLayoutItem(0); - if (item->ownedByLayout()) - delete item; - } - } -} - -/*! - Change the layout orientation to \a orientation. Changing the layout - orientation will automatically invalidate the layout. - - \sa orientation() -*/ -void QGraphicsLinearLayout::setOrientation(Qt::Orientation orientation) -{ - Q_D(QGraphicsLinearLayout); - if (orientation != d->orientation) { - d->engine.transpose(); - d->orientation = orientation; - invalidate(); - } -} - -/*! - Returns the layout orientation. - \sa setOrientation() - */ -Qt::Orientation QGraphicsLinearLayout::orientation() const -{ - Q_D(const QGraphicsLinearLayout); - return d->orientation; -} - -/*! - \fn void QGraphicsLinearLayout::addItem(QGraphicsLayoutItem *item) - - This convenience function is equivalent to calling - insertItem(-1, \a item). -*/ - -/*! - \fn void QGraphicsLinearLayout::addStretch(int stretch) - - This convenience function is equivalent to calling - insertStretch(-1, \a stretch). -*/ - -/*! - Inserts \a item into the layout at \a index, or before any item that is - currently at \a index. - - \sa addItem(), itemAt(), insertStretch(), setItemSpacing() -*/ -void QGraphicsLinearLayout::insertItem(int index, QGraphicsLayoutItem *item) -{ - Q_D(QGraphicsLinearLayout); - if (!item) { - qWarning("QGraphicsLinearLayout::insertItem: cannot insert null item"); - return; - } - if (item == this) { - qWarning("QGraphicsLinearLayout::insertItem: cannot insert itself"); - return; - } - d->addChildLayoutItem(item); - - Q_ASSERT(item); - d->fixIndex(&index); - d->engine.insertRow(index, d->orientation); - new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index); - invalidate(); -} - -/*! - Inserts a stretch of \a stretch at \a index, or before any item that is - currently at \a index. - - \sa addStretch(), setStretchFactor(), setItemSpacing(), insertItem() -*/ -void QGraphicsLinearLayout::insertStretch(int index, int stretch) -{ - Q_D(QGraphicsLinearLayout); - d->fixIndex(&index); - d->engine.insertRow(index, d->orientation); - d->engine.setRowStretchFactor(index, stretch, d->orientation); - invalidate(); -} - -/*! - Removes \a item from the layout without destroying it. Ownership of - \a item is transferred to the caller. - - \sa removeAt(), insertItem() -*/ -void QGraphicsLinearLayout::removeItem(QGraphicsLayoutItem *item) -{ - Q_D(QGraphicsLinearLayout); - if (QGridLayoutItem *gridItem = d->engine.findLayoutItem(item)) { - item->setParentLayoutItem(0); - d->removeGridItem(gridItem); - delete gridItem; - invalidate(); - } -} - -/*! - Removes the item at \a index without destroying it. Ownership of the item - is transferred to the caller. - - \sa removeItem(), insertItem() -*/ -void QGraphicsLinearLayout::removeAt(int index) -{ - Q_D(QGraphicsLinearLayout); - if (index < 0 || index >= d->engine.itemCount()) { - qWarning("QGraphicsLinearLayout::removeAt: invalid index %d", index); - return; - } - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) { - if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem()) - layoutItem->setParentLayoutItem(0); - d->removeGridItem(gridItem); - delete gridItem; - invalidate(); - } -} - -/*! - Sets the layout's spacing to \a spacing. Spacing refers to the - vertical and horizontal distances between items. - - \sa setItemSpacing(), setStretchFactor(), QGraphicsGridLayout::setSpacing() -*/ -void QGraphicsLinearLayout::setSpacing(qreal spacing) -{ - Q_D(QGraphicsLinearLayout); - if (spacing < 0) { - qWarning("QGraphicsLinearLayout::setSpacing: invalid spacing %g", spacing); - return; - } - d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical); - invalidate(); -} - -/*! - Returns the layout's spacing. Spacing refers to the - vertical and horizontal distances between items. - - \sa setSpacing() - */ -qreal QGraphicsLinearLayout::spacing() const -{ - Q_D(const QGraphicsLinearLayout); - return d->engine.spacing(d->styleInfo(), d->orientation); -} - -/*! - Sets the spacing after item at \a index to \a spacing. -*/ -void QGraphicsLinearLayout::setItemSpacing(int index, qreal spacing) -{ - Q_D(QGraphicsLinearLayout); - d->engine.setRowSpacing(index, spacing, d->orientation); - invalidate(); -} -/*! - Returns the spacing after item at \a index. -*/ -qreal QGraphicsLinearLayout::itemSpacing(int index) const -{ - Q_D(const QGraphicsLinearLayout); - return d->engine.rowSpacing(index, d->orientation); -} - -/*! - Sets the stretch factor for \a item to \a stretch. If an item's stretch - factor changes, this function will invalidate the layout. - - Setting \a stretch to 0 removes the stretch factor from the item, and is - effectively equivalent to setting \a stretch to 1. - - \sa stretchFactor() -*/ -void QGraphicsLinearLayout::setStretchFactor(QGraphicsLayoutItem *item, int stretch) -{ - Q_D(QGraphicsLinearLayout); - if (!item) { - qWarning("QGraphicsLinearLayout::setStretchFactor: cannot assign" - " a stretch factor to a null item"); - return; - } - if (stretchFactor(item) == stretch) - return; - d->engine.setStretchFactor(item, stretch, d->orientation); - invalidate(); -} - -/*! - Returns the stretch factor for \a item. The default stretch factor is 0, - meaning that the item has no assigned stretch factor. - - \sa setStretchFactor() -*/ -int QGraphicsLinearLayout::stretchFactor(QGraphicsLayoutItem *item) const -{ - Q_D(const QGraphicsLinearLayout); - if (!item) { - qWarning("QGraphicsLinearLayout::setStretchFactor: cannot return" - " a stretch factor for a null item"); - return 0; - } - return d->engine.stretchFactor(item, d->orientation); -} - -/*! - Sets the alignment of \a item to \a alignment. If \a item's alignment - changes, the layout is automatically invalidated. - - \sa alignment(), invalidate() -*/ -void QGraphicsLinearLayout::setAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment) -{ - Q_D(QGraphicsLinearLayout); - if (this->alignment(item) == alignment) - return; - d->engine.setAlignment(item, alignment); - invalidate(); -} - -/*! - Returns the alignment for \a item. The default alignment is - Qt::AlignTop | Qt::AlignLeft. - - The alignment decides how the item is positioned within its assigned space - in the case where there's more space available in the layout than the - widgets can occupy. - - \sa setAlignment() -*/ -Qt::Alignment QGraphicsLinearLayout::alignment(QGraphicsLayoutItem *item) const -{ - Q_D(const QGraphicsLinearLayout); - return d->engine.alignment(item); -} - -#if 0 // ### -QSizePolicy::ControlTypes QGraphicsLinearLayout::controlTypes(LayoutSide side) const -{ - return d->engine.controlTypes(side); -} -#endif - -/*! - \reimp -*/ -int QGraphicsLinearLayout::count() const -{ - Q_D(const QGraphicsLinearLayout); - return d->engine.itemCount(); -} - -/*! - \reimp - When iterating from 0 and up, it will return the items in the visual arranged order. -*/ -QGraphicsLayoutItem *QGraphicsLinearLayout::itemAt(int index) const -{ - Q_D(const QGraphicsLinearLayout); - if (index < 0 || index >= d->engine.itemCount()) { - qWarning("QGraphicsLinearLayout::itemAt: invalid index %d", index); - return 0; - } - QGraphicsLayoutItem *item = 0; - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) - item = gridItem->layoutItem(); - return item; -} - -/*! - \reimp -*/ -void QGraphicsLinearLayout::setGeometry(const QRectF &rect) -{ - Q_D(QGraphicsLinearLayout); - QGraphicsLayout::setGeometry(rect); - QRectF effectiveRect = geometry(); - qreal left, top, right, bottom; - getContentsMargins(&left, &top, &right, &bottom); - Qt::LayoutDirection visualDir = d->visualDirection(); - d->engine.setVisualDirection(visualDir); - if (visualDir == Qt::RightToLeft) - qSwap(left, right); - effectiveRect.adjust(+left, +top, -right, -bottom); -#ifdef QT_DEBUG - if (qt_graphicsLayoutDebug()) { - static int counter = 0; - qDebug() << counter++ << "QGraphicsLinearLayout::setGeometry - " << rect; - dump(1); - } -#endif - d->engine.setGeometries(d->styleInfo(), effectiveRect); -#ifdef QT_DEBUG - if (qt_graphicsLayoutDebug()) { - qDebug() << "post dump"; - dump(1); - } -#endif -} - -/*! - \reimp -*/ -QSizeF QGraphicsLinearLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_D(const QGraphicsLinearLayout); - qreal left, top, right, bottom; - getContentsMargins(&left, &top, &right, &bottom); - const QSizeF extraMargins(left + right, top + bottom); - return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins; -} - -/*! - \reimp -*/ -void QGraphicsLinearLayout::invalidate() -{ - Q_D(QGraphicsLinearLayout); - d->engine.invalidate(); - QGraphicsLayout::invalidate(); -} - -/*! - \internal -*/ -void QGraphicsLinearLayout::dump(int indent) const -{ -#ifdef QT_DEBUG - if (qt_graphicsLayoutDebug()) { - Q_D(const QGraphicsLinearLayout); - qDebug("%*s%s layout", indent, "", - d->orientation == Qt::Horizontal ? "Horizontal" : "Vertical"); - d->engine.dump(indent + 1); - } -#else - Q_UNUSED(indent); -#endif -} - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslinearlayout.h b/src/gui/graphicsview/qgraphicslinearlayout.h deleted file mode 100644 index 031015c5eb..0000000000 --- a/src/gui/graphicsview/qgraphicslinearlayout.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSLINEARLAYOUT_H -#define QGRAPHICSLINEARLAYOUT_H - -#include <QtGui/qgraphicsitem.h> -#include <QtGui/qgraphicslayout.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsLinearLayoutPrivate; - -class Q_GUI_EXPORT QGraphicsLinearLayout : public QGraphicsLayout -{ -public: - QGraphicsLinearLayout(QGraphicsLayoutItem *parent = 0); - QGraphicsLinearLayout(Qt::Orientation orientation, QGraphicsLayoutItem *parent = 0); - virtual ~QGraphicsLinearLayout(); - - void setOrientation(Qt::Orientation orientation); - Qt::Orientation orientation() const; - - inline void addItem(QGraphicsLayoutItem *item) { insertItem(-1, item); } - inline void addStretch(int stretch = 1) { insertStretch(-1, stretch); } - - void insertItem(int index, QGraphicsLayoutItem *item); - void insertStretch(int index, int stretch = 1); - - void removeItem(QGraphicsLayoutItem *item); - void removeAt(int index); - - void setSpacing(qreal spacing); - qreal spacing() const; - void setItemSpacing(int index, qreal spacing); - qreal itemSpacing(int index) const; - - void setStretchFactor(QGraphicsLayoutItem *item, int stretch); - int stretchFactor(QGraphicsLayoutItem *item) const; - - void setAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment); - Qt::Alignment alignment(QGraphicsLayoutItem *item) const; - - void setGeometry(const QRectF &rect); - - int count() const; - QGraphicsLayoutItem *itemAt(int index) const; - - void invalidate(); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - -#if 0 // ### - Q5SizePolicy::ControlTypes controlTypes(LayoutSide side) const; -#endif - - void dump(int indent = 0) const; - -protected: -#if 0 - QSize contentsSizeHint(Qt::SizeHint which, const QSize &constraint = QSize()) const; -#endif - -private: - Q_DISABLE_COPY(QGraphicsLinearLayout) - Q_DECLARE_PRIVATE(QGraphicsLinearLayout) -}; - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif - diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp deleted file mode 100644 index fad88f5764..0000000000 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ /dev/null @@ -1,1569 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicslayout.h" -#include "qgraphicsproxywidget.h" -#include "private/qgraphicsproxywidget_p.h" -#include "private/qwidget_p.h" -#include "private/qapplication_p.h" - -#include <QtCore/qdebug.h> -#include <QtGui/qevent.h> -#include <QtGui/qgraphicsscene.h> -#include <QtGui/qgraphicssceneevent.h> -#include <QtGui/qlayout.h> -#include <QtGui/qpainter.h> -#include <QtGui/qstyleoption.h> -#include <QtGui/qgraphicsview.h> -#include <QtGui/qlistview.h> -#include <QtGui/qlineedit.h> -#include <QtGui/qtextedit.h> - -QT_BEGIN_NAMESPACE - -//#define GRAPHICSPROXYWIDGET_DEBUG - -/*! - \class QGraphicsProxyWidget - \brief The QGraphicsProxyWidget class provides a proxy layer for embedding - a QWidget in a QGraphicsScene. - \since 4.4 - \ingroup graphicsview-api - - QGraphicsProxyWidget embeds QWidget-based widgets, for example, a - QPushButton, QFontComboBox, or even QFileDialog, into - QGraphicsScene. It forwards events between the two objects and - translates between QWidget's integer-based geometry and - QGraphicsWidget's qreal-based geometry. QGraphicsProxyWidget - supports all core features of QWidget, including tab focus, - keyboard input, Drag & Drop, and popups. You can also embed - complex widgets, e.g., widgets with subwidgets. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 0 - - QGraphicsProxyWidget takes care of automatically embedding popup children - of embedded widgets through creating a child proxy for each popup. This - means that when an embedded QComboBox shows its popup list, a new - QGraphicsProxyWidget is created automatically, embedding the popup, and - positioning it correctly. This only works if the popup is child of the - embedded widget (for example QToolButton::setMenu() requires the QMenu instance - to be child of the QToolButton). - - \section1 Embedding a Widget with QGraphicsProxyWidget - - There are two ways to embed a widget using QGraphicsProxyWidget. The most - common way is to pass a widget pointer to QGraphicsScene::addWidget() - together with any relevant \l Qt::WindowFlags. This function returns a - pointer to a QGraphicsProxyWidget. You can then choose to reparent or - position either the proxy, or the embedded widget itself. - - For example, in the code snippet below, we embed a group box into the proxy: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 1 - - The image below is the output obtained with its contents margin and - contents rect labeled. - - \image qgraphicsproxywidget-embed.png - - Alternatively, you can start by creating a new QGraphicsProxyWidget item, - and then call setWidget() to embed a QWidget later. The widget() function - returns a pointer to the embedded widget. QGraphicsProxyWidget shares - ownership with QWidget, so if either of the two widgets are destroyed, the - other widget will be automatically destroyed as well. - - \section1 Synchronizing Widget States - - QGraphicsProxyWidget keeps its state in sync with the embedded widget. For - example, if the proxy is hidden or disabled, the embedded widget will be - hidden or disabled as well, and vice versa. When the widget is embedded by - calling addWidget(), QGraphicsProxyWidget copies the state from the widget - into the proxy, and after that, the two will stay synchronized where - possible. By default, when you embed a widget into a proxy, both the widget - and the proxy will be visible because a QGraphicsWidget is visible when - created (you do not have to call show()). If you explicitly hide the - embedded widget, the proxy will also become invisible. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsproxywidget.cpp 2 - - QGraphicsProxyWidget maintains symmetry for the following states: - - \table - \header \o QWidget state \o QGraphicsProxyWidget state \o Notes - \row \o QWidget::enabled - \o QGraphicsProxyWidget::enabled - \o - \row \o QWidget::visible - \o QGraphicsProxyWidget::visible - \o The explicit state is also symmetric. - \row \o QWidget::geometry - \o QGraphicsProxyWidget::geometry - \o Geometry is only guaranteed to be symmetric while - the embedded widget is visible. - \row \o QWidget::layoutDirection - \o QGraphicsProxyWidget::layoutDirection - \o - \row \o QWidget::style - \o QGraphicsProxyWidget::style - \o - \row \o QWidget::palette - \o QGraphicsProxyWidget::palette - \o - \row \o QWidget::font - \o QGraphicsProxyWidget::font - \o - \row \o QWidget::cursor - \o QGraphicsProxyWidget::cursor - \o The embedded widget overrides the proxy widget - cursor. The proxy cursor changes depending on - which embedded subwidget is currently under the - mouse. - \row \o QWidget::sizeHint() - \o QGraphicsProxyWidget::sizeHint() - \o All size hint functionality from the embedded - widget is forwarded by the proxy. - \row \o QWidget::getContentsMargins() - \o QGraphicsProxyWidget::getContentsMargins() - \o Updated once by setWidget(). - \row \o QWidget::windowTitle - \o QGraphicsProxyWidget::windowTitle - \o Updated once by setWidget(). - \endtable - - \note QGraphicsScene keeps the embedded widget in a special state that - prevents it from disturbing other widgets (both embedded and not embedded) - while the widget is embedded. In this state, the widget may differ slightly - in behavior from when it is not embedded. - - \warning This class is provided for convenience when bridging - QWidgets and QGraphicsItems, it should not be used for - high-performance scenarios. - - \sa QGraphicsScene::addWidget(), QGraphicsWidget -*/ - -extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); -Q_GUI_EXPORT extern bool qt_tab_all_widgets; - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::init() -{ - Q_Q(QGraphicsProxyWidget); - q->setFocusPolicy(Qt::WheelFocus); - q->setAcceptDrops(true); -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneHoverEvent *event) -{ - QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove); - mouseEvent.setPos(event->pos()); - mouseEvent.setScreenPos(event->screenPos()); - mouseEvent.setButton(Qt::NoButton); - mouseEvent.setButtons(0); - mouseEvent.setModifiers(event->modifiers()); - sendWidgetMouseEvent(&mouseEvent); - event->setAccepted(mouseEvent.isAccepted()); -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent *event) -{ - if (!event || !widget || !widget->isVisible()) - return; - Q_Q(QGraphicsProxyWidget); - - // Find widget position and receiver. - QPointF pos = event->pos(); - QPointer<QWidget> alienWidget = widget->childAt(pos.toPoint()); - QPointer<QWidget> receiver = alienWidget ? alienWidget : widget; - - if (QWidgetPrivate::nearestGraphicsProxyWidget(receiver) != q) - return; //another proxywidget will handle the events - - // Translate QGraphicsSceneMouse events to QMouseEvents. - QEvent::Type type = QEvent::None; - switch (event->type()) { - case QEvent::GraphicsSceneMousePress: - type = QEvent::MouseButtonPress; - if (!embeddedMouseGrabber) - embeddedMouseGrabber = receiver; - else - receiver = embeddedMouseGrabber; - break; - case QEvent::GraphicsSceneMouseRelease: - type = QEvent::MouseButtonRelease; - if (embeddedMouseGrabber) - receiver = embeddedMouseGrabber; - break; - case QEvent::GraphicsSceneMouseDoubleClick: - type = QEvent::MouseButtonDblClick; - if (!embeddedMouseGrabber) - embeddedMouseGrabber = receiver; - else - receiver = embeddedMouseGrabber; - break; - case QEvent::GraphicsSceneMouseMove: - type = QEvent::MouseMove; - if (embeddedMouseGrabber) - receiver = embeddedMouseGrabber; - break; - default: - Q_ASSERT_X(false, "QGraphicsProxyWidget", "internal error"); - break; - } - - if (!lastWidgetUnderMouse) { - QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : receiver, 0); - lastWidgetUnderMouse = receiver; - } - - // Map event position from us to the receiver - pos = mapToReceiver(pos, receiver); - - // Send mouse event. - QMouseEvent mouseEvent(type, pos, - receiver->mapToGlobal(pos.toPoint()), event->button(), - event->buttons(), event->modifiers()); - - QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber; - QApplicationPrivate::sendMouseEvent(receiver, &mouseEvent, alienWidget, widget, - &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous()); - embeddedMouseGrabber = embeddedMouseGrabberPtr; - - // Handle enter/leave events when last button is released from mouse - // grabber child widget. - if (embeddedMouseGrabber && type == QEvent::MouseButtonRelease && !event->buttons()) { - Q_Q(QGraphicsProxyWidget); - if (q->rect().contains(event->pos()) && q->acceptsHoverEvents()) - lastWidgetUnderMouse = alienWidget ? alienWidget : widget; - else // released on the frame our outside the item, or doesn't accept hover events. - lastWidgetUnderMouse = 0; - - QApplicationPrivate::dispatchEnterLeave(lastWidgetUnderMouse, embeddedMouseGrabber); - embeddedMouseGrabber = 0; - -#ifndef QT_NO_CURSOR - // ### Restore the cursor, don't override it. - if (!lastWidgetUnderMouse) - q->unsetCursor(); -#endif - } - - event->setAccepted(mouseEvent.isAccepted()); -} - -void QGraphicsProxyWidgetPrivate::sendWidgetKeyEvent(QKeyEvent *event) -{ - Q_Q(QGraphicsProxyWidget); - if (!event || !widget || !widget->isVisible()) - return; - - QPointer<QWidget> receiver = widget->focusWidget(); - if (!receiver) - receiver = widget; - Q_ASSERT(receiver); - - do { - bool res = QApplication::sendEvent(receiver, event); - if ((res && event->isAccepted()) || (q->isWindow() && receiver == widget)) - break; - receiver = receiver->parentWidget(); - } while (receiver); -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::removeSubFocusHelper(QWidget *widget, Qt::FocusReason reason) -{ - QFocusEvent event(QEvent::FocusOut, reason); - QPointer<QWidget> widgetGuard = widget; - QApplication::sendEvent(widget, &event); - if (widgetGuard && event.isAccepted()) - QApplication::sendEvent(widget->style(), &event); -} - -/*! - \internal - - Reimplemented from QGraphicsItemPrivate. ### Qt 5: Move impl to - reimplementation QGraphicsProxyWidget::inputMethodQuery(). -*/ -QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query) const -{ - Q_Q(const QGraphicsProxyWidget); - if (!widget || !q->hasFocus()) - return QVariant(); - - QWidget *focusWidget = widget->focusWidget(); - if (!focusWidget) - focusWidget = widget; - QVariant v = focusWidget->inputMethodQuery(query); - QPointF focusWidgetPos = q->subWidgetRect(focusWidget).topLeft(); - switch (v.type()) { - case QVariant::RectF: - v = v.toRectF().translated(focusWidgetPos); - break; - case QVariant::PointF: - v = v.toPointF() + focusWidgetPos; - break; - case QVariant::Rect: - v = v.toRect().translated(focusWidgetPos.toPoint()); - break; - case QVariant::Point: - v = v.toPoint() + focusWidgetPos.toPoint(); - break; - default: - break; - } - return v; -} - -/*! - \internal - Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper -*/ -QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const -{ - if (!widget) - return 0; - - // Run around the focus chain until we find a widget that can take tab focus. - if (!child) { - child = next ? (QWidget *)widget : widget->d_func()->focus_prev; - } else { - child = next ? child->d_func()->focus_next : child->d_func()->focus_prev; - if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) { - return 0; - } - } - - QWidget *oldChild = child; - uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus; - do { - if (child->isEnabled() - && child->isVisibleTo(widget) - && ((child->focusPolicy() & focus_flag) == focus_flag) - && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) { - return child; - } - child = next ? child->d_func()->focus_next : child->d_func()->focus_prev; - } while (child != oldChild && !(next && child == widget) && !(!next && child == widget->d_func()->focus_prev)); - return 0; -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot() -{ - Q_Q(QGraphicsProxyWidget); - widget = 0; - delete q; -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::updateWidgetGeometryFromProxy() -{ -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget() -{ - Q_Q(QGraphicsProxyWidget); - if (!widget) - return; - - QRectF widgetGeometry = widget->geometry(); - QWidget *parentWidget = widget->parentWidget(); - if (widget->isWindow()) { - QGraphicsProxyWidget *proxyParent = 0; - if (parentWidget && (proxyParent = qobject_cast<QGraphicsProxyWidget *>(q->parentWidget()))) { - // Nested window proxy (e.g., combobox popup), map widget to the - // parent widget's global coordinates, and map that to the parent - // proxy's child coordinates. - widgetGeometry.moveTo(proxyParent->subWidgetRect(parentWidget).topLeft() - + parentWidget->mapFromGlobal(widget->pos())); - } - } - - // Adjust to size hint if the widget has never been resized. - if (!widget->size().isValid()) - widgetGeometry.setSize(widget->sizeHint()); - - // Assign new geometry. - posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - q->setGeometry(widgetGeometry); - posChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode; -} - -/*! - \internal -*/ -void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget() -{ - Q_Q(QGraphicsProxyWidget); - if (!widget) - return; - - QWidget *focusWidget = widget->focusWidget(); - if (!focusWidget) - focusWidget = widget; - q->setFlag(QGraphicsItem::ItemAcceptsInputMethod, - focusWidget->testAttribute(Qt::WA_InputMethodEnabled)); -} - -/*! - \internal - - Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level - widget and a descendant of the widget managed by this proxy. A separate subproxy - will be created as a child of this proxy widget to manage \a subWin. -*/ -void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin) -{ - QWExtra *extra; - if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) { - QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags()); - subProxy->d_func()->setWidget_helper(subWin, false); - } -} - -/*! - \internal - - Removes ("unembeds") \a subWin and deletes the proxy holder item. This can - happen when QWidget::setParent() reparents the embedded window out of - "embedded space". -*/ -void QGraphicsProxyWidgetPrivate::unembedSubWindow(QWidget *subWin) -{ - foreach (QGraphicsItem *child, children) { - if (child->isWidget()) { - if (QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))) { - if (proxy->widget() == subWin) { - proxy->setWidget(0); - scene->removeItem(proxy); - delete proxy; - return; - } - } - } - } -} - -bool QGraphicsProxyWidgetPrivate::isProxyWidget() const -{ - return true; -} - -/*! - \internal -*/ -QPointF QGraphicsProxyWidgetPrivate::mapToReceiver(const QPointF &pos, const QWidget *receiver) const -{ - QPointF p = pos; - // Map event position from us to the receiver, preserving its - // precision (don't use QWidget::mapFrom here). - while (receiver && receiver != widget) { - p -= QPointF(receiver->pos()); - receiver = receiver->parentWidget(); - } - return p; -} - -/*! - Constructs a new QGraphicsProxy widget. \a parent and \a wFlags are passed - to QGraphicsItem's constructor. -*/ -QGraphicsProxyWidget::QGraphicsProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) - : QGraphicsWidget(*new QGraphicsProxyWidgetPrivate, parent, 0, wFlags) -{ - Q_D(QGraphicsProxyWidget); - d->init(); -} - -/*! - Destroys the proxy widget and any embedded widget. -*/ -QGraphicsProxyWidget::~QGraphicsProxyWidget() -{ - Q_D(QGraphicsProxyWidget); - if (d->widget) { - QObject::disconnect(d->widget, SIGNAL(destroyed()), this, SLOT(_q_removeWidgetSlot())); - delete d->widget; - } -} - -/*! - Embeds \a widget into this proxy widget. The embedded widget must reside - exclusively either inside or outside of Graphics View. You cannot embed a - widget as long as it is is visible elsewhere in the UI, at the same time. - - \a widget must be a top-level widget whose parent is 0. - - When the widget is embedded, its state (e.g., visible, enabled, geometry, - size hints) is copied into the proxy widget. If the embedded widget is - explicitly hidden or disabled, the proxy widget will become explicitly - hidden or disabled after embedding is complete. The class documentation - has a full overview over the shared state. - - QGraphicsProxyWidget's window flags determine whether the widget, after - embedding, will be given window decorations or not. - - After this function returns, QGraphicsProxyWidget will keep its state - synchronized with that of \a widget whenever possible. - - If a widget is already embedded by this proxy when this function is - called, that widget will first be automatically unembedded. Passing 0 for - the \a widget argument will only unembed the widget, and the ownership of - the currently embedded widget will be passed on to the caller. - Every child widget that are embedded will also be embedded and their proxy - widget destroyed. - - Note that widgets with the Qt::WA_PaintOnScreen widget attribute - set and widgets that wrap an external application or controller - cannot be embedded. Examples are QGLWidget and QAxWidget. - - \sa widget() -*/ -void QGraphicsProxyWidget::setWidget(QWidget *widget) -{ - Q_D(QGraphicsProxyWidget); - d->setWidget_helper(widget, true); -} - -void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool autoShow) -{ - Q_Q(QGraphicsProxyWidget); - if (newWidget == widget) - return; - if (widget) { - QObject::disconnect(widget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot())); - widget->removeEventFilter(q); - widget->setAttribute(Qt::WA_DontShowOnScreen, false); - widget->d_func()->extra->proxyWidget = 0; - resolveFont(inheritedFontResolveMask); - resolvePalette(inheritedPaletteResolveMask); - widget->update(); - - foreach (QGraphicsItem *child, q->childItems()) { - if (child->d_ptr->isProxyWidget()) { - QGraphicsProxyWidget *childProxy = static_cast<QGraphicsProxyWidget *>(child); - QWidget * parent = childProxy->widget(); - while (parent->parentWidget() != 0) { - if (parent == widget) - break; - parent = parent->parentWidget(); - } - if (!childProxy->widget() || parent != widget) - continue; - childProxy->setWidget(0); - delete childProxy; - } - } - - widget = 0; -#ifndef QT_NO_CURSOR - q->unsetCursor(); -#endif - q->setAcceptHoverEvents(false); - if (!newWidget) - q->update(); - } - if (!newWidget) - return; - if (!newWidget->isWindow()) { - QWExtra *extra = newWidget->parentWidget()->d_func()->extra; - if (!extra || !extra->proxyWidget) { - qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p " - "which is not a toplevel widget, and is not a child of an embedded widget", newWidget); - return; - } - } - - // Register this proxy within the widget's private. - // ### This is a bit backdoorish - QWExtra *extra = newWidget->d_func()->extra; - if (!extra) { - newWidget->d_func()->createExtra(); - extra = newWidget->d_func()->extra; - } - QGraphicsProxyWidget **proxyWidget = &extra->proxyWidget; - if (*proxyWidget) { - if (*proxyWidget != q) { - qWarning("QGraphicsProxyWidget::setWidget: cannot embed widget %p" - "; already embedded", newWidget); - } - return; - } - *proxyWidget = q; - - newWidget->setAttribute(Qt::WA_DontShowOnScreen); - newWidget->ensurePolished(); - // Do not wait for this widget to close before the app closes ### - // shouldn't this widget inherit the attribute? - newWidget->setAttribute(Qt::WA_QuitOnClose, false); - q->setAcceptHoverEvents(true); - - if (newWidget->testAttribute(Qt::WA_NoSystemBackground)) - q->setAttribute(Qt::WA_NoSystemBackground); - if (newWidget->testAttribute(Qt::WA_OpaquePaintEvent)) - q->setAttribute(Qt::WA_OpaquePaintEvent); - - widget = newWidget; - - // Changes only go from the widget to the proxy. - enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - posChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - sizeChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - - if ((autoShow && !newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide)) || !newWidget->testAttribute(Qt::WA_WState_Hidden)) { - newWidget->show(); - } - - // Copy the state from the widget onto the proxy. -#ifndef QT_NO_CURSOR - if (newWidget->testAttribute(Qt::WA_SetCursor)) - q->setCursor(widget->cursor()); -#endif - q->setEnabled(newWidget->isEnabled()); - q->setVisible(newWidget->isVisible()); - q->setLayoutDirection(newWidget->layoutDirection()); - if (newWidget->testAttribute(Qt::WA_SetStyle)) - q->setStyle(widget->style()); - - resolveFont(inheritedFontResolveMask); - resolvePalette(inheritedPaletteResolveMask); - - if (!newWidget->testAttribute(Qt::WA_Resized)) - newWidget->adjustSize(); - - int left, top, right, bottom; - newWidget->getContentsMargins(&left, &top, &right, &bottom); - q->setContentsMargins(left, top, right, bottom); - q->setWindowTitle(newWidget->windowTitle()); - - // size policies and constraints.. - q->setSizePolicy(newWidget->sizePolicy()); - QSize sz = newWidget->minimumSize(); - q->setMinimumSize(sz.isNull() ? QSizeF() : QSizeF(sz)); - sz = newWidget->maximumSize(); - q->setMaximumSize(sz.isNull() ? QSizeF() : QSizeF(sz)); - - updateProxyGeometryFromWidget(); - - updateProxyInputMethodAcceptanceFromWidget(); - - // Hook up the event filter to keep the state up to date. - newWidget->installEventFilter(q); - QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot())); - - // Changes no longer go only from the widget to the proxy. - enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - posChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode; -} - -/*! - Returns a pointer to the embedded widget. - - \sa setWidget() -*/ -QWidget *QGraphicsProxyWidget::widget() const -{ - Q_D(const QGraphicsProxyWidget); - return d->widget; -} - -/*! - Returns the rectangle for \a widget, which must be a descendant of - widget(), or widget() itself, in this proxy item's local coordinates. - - If no widget is embedded, \a widget is 0, or \a widget is not a - descendant of the embedded widget, this function returns an empty QRectF. - - \sa widget() -*/ -QRectF QGraphicsProxyWidget::subWidgetRect(const QWidget *widget) const -{ - Q_D(const QGraphicsProxyWidget); - if (!widget || !d->widget) - return QRectF(); - if (d->widget == widget || d->widget->isAncestorOf(widget)) - return QRectF(widget->mapTo(d->widget, QPoint(0, 0)), widget->size()); - return QRectF(); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::setGeometry(const QRectF &rect) -{ - Q_D(QGraphicsProxyWidget); - bool proxyResizesWidget = !d->posChangeMode && !d->sizeChangeMode; - if (proxyResizesWidget) { - d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - d->sizeChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - } - QGraphicsWidget::setGeometry(rect); - if (proxyResizesWidget) { - d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - d->sizeChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } -} - -/*! - \reimp -*/ -QVariant QGraphicsProxyWidget::itemChange(GraphicsItemChange change, - const QVariant &value) -{ - Q_D(QGraphicsProxyWidget); - - switch (change) { - case ItemPositionChange: - // The item's position is either changed directly on the proxy, in - // which case the position change should propagate to the widget, - // otherwise it happens as a side effect when filtering QEvent::Move. - if (!d->posChangeMode) - d->posChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - break; - case ItemPositionHasChanged: - // Move the internal widget if we're in widget-to-proxy - // mode. Otherwise the widget has already moved. - if (d->widget && d->posChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode) - d->widget->move(value.toPoint()); - if (d->posChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode) - d->posChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - break; - case ItemVisibleChange: - if (!d->visibleChangeMode) - d->visibleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - break; - case ItemVisibleHasChanged: - if (d->widget && d->visibleChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode) - d->widget->setVisible(isVisible()); - if (d->visibleChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode) - d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - break; - case ItemEnabledChange: - if (!d->enabledChangeMode) - d->enabledChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - break; - case ItemEnabledHasChanged: - if (d->widget && d->enabledChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode) - d->widget->setEnabled(isEnabled()); - if (d->enabledChangeMode == QGraphicsProxyWidgetPrivate::ProxyToWidgetMode) - d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - break; - default: - break; - } - return QGraphicsWidget::itemChange(change, value); -} - -/*! - \reimp -*/ -bool QGraphicsProxyWidget::event(QEvent *event) -{ - Q_D(QGraphicsProxyWidget); - if (!d->widget) - return QGraphicsWidget::event(event); - - switch (event->type()) { - case QEvent::StyleChange: - // Propagate style changes to the embedded widget. - if (!d->styleChangeMode) { - d->styleChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - d->widget->setStyle(style()); - d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } - break; - case QEvent::FontChange: { - // Propagate to widget. - QWidgetPrivate *wd = d->widget->d_func(); - int mask = d->font.resolve() | d->inheritedFontResolveMask; - wd->inheritedFontResolveMask = mask; - wd->resolveFont(); - break; - } - case QEvent::PaletteChange: { - // Propagate to widget. - QWidgetPrivate *wd = d->widget->d_func(); - int mask = d->palette.resolve() | d->inheritedPaletteResolveMask; - wd->inheritedPaletteResolveMask = mask; - wd->resolvePalette(); - break; - } - case QEvent::InputMethod: { - // Forward input method events if the focus widget enables - // input methods. - // ### Qt 4.5: this code must also go into a reimplementation - // of inputMethodEvent(). - QWidget *focusWidget = d->widget->focusWidget(); - if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) - QApplication::sendEvent(focusWidget, event); - break; - } - case QEvent::ShortcutOverride: { - QWidget *focusWidget = d->widget->focusWidget(); - while (focusWidget) { - QApplication::sendEvent(focusWidget, event); - if (event->isAccepted()) - return true; - focusWidget = focusWidget->parentWidget(); - } - return false; - } - case QEvent::KeyPress: { - QKeyEvent *k = static_cast<QKeyEvent *>(event); - if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) { - if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier? - QWidget *focusWidget = d->widget->focusWidget(); - while (focusWidget) { - bool res = QApplication::sendEvent(focusWidget, event); - if ((res && event->isAccepted()) || (isWindow() && focusWidget == d->widget)) { - event->accept(); - break; - } - focusWidget = focusWidget->parentWidget(); - } - return true; - } - } - break; - } -#ifndef QT_NO_TOOLTIP - case QEvent::GraphicsSceneHelp: { - // Propagate the help event (for tooltip) to the widget under mouse - if (d->lastWidgetUnderMouse) { - QGraphicsSceneHelpEvent *he = static_cast<QGraphicsSceneHelpEvent *>(event); - QPoint pos = d->mapToReceiver(mapFromScene(he->scenePos()), d->lastWidgetUnderMouse).toPoint(); - QHelpEvent e(QEvent::ToolTip, pos, he->screenPos()); - QApplication::sendEvent(d->lastWidgetUnderMouse, &e); - event->setAccepted(e.isAccepted()); - return e.isAccepted(); - } - break; - } - case QEvent::ToolTipChange: { - // Propagate tooltip change to the widget - if (!d->tooltipChangeMode) { - d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::ProxyToWidgetMode; - d->widget->setToolTip(toolTip()); - d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } - break; - } -#endif - default: - break; - } - return QGraphicsWidget::event(event); -} - -/*! - \reimp -*/ -bool QGraphicsProxyWidget::eventFilter(QObject *object, QEvent *event) -{ - Q_D(QGraphicsProxyWidget); - - if (object == d->widget) { - switch (event->type()) { - case QEvent::LayoutRequest: - updateGeometry(); - break; - case QEvent::Resize: - // If the widget resizes itself, we resize the proxy too. - // Prevent feed-back by checking the geometry change mode. - if (!d->sizeChangeMode) - d->updateProxyGeometryFromWidget(); - break; - case QEvent::Move: - // If the widget moves itself, we move the proxy too. Prevent - // feed-back by checking the geometry change mode. - if (!d->posChangeMode) - d->updateProxyGeometryFromWidget(); - break; - case QEvent::Hide: - case QEvent::Show: - // If the widget toggles its visible state, the proxy will follow. - if (!d->visibleChangeMode) { - d->visibleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - setVisible(event->type() == QEvent::Show); - d->visibleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } - break; - case QEvent::EnabledChange: - // If the widget toggles its enabled state, the proxy will follow. - if (!d->enabledChangeMode) { - d->enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - setEnabled(d->widget->isEnabled()); - d->enabledChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } - break; - case QEvent::StyleChange: - // Propagate style changes to the proxy. - if (!d->styleChangeMode) { - d->styleChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - setStyle(d->widget->style()); - d->styleChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } - break; -#ifndef QT_NO_TOOLTIP - case QEvent::ToolTipChange: - // Propagate tooltip change to the proxy. - if (!d->tooltipChangeMode) { - d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode; - setToolTip(d->widget->toolTip()); - d->tooltipChangeMode = QGraphicsProxyWidgetPrivate::NoMode; - } - break; -#endif - default: - break; - } - } - return QGraphicsWidget::eventFilter(object, event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::showEvent(QShowEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::hideEvent(QHideEvent *event) -{ - Q_UNUSED(event); -} - -#ifndef QT_NO_CONTEXTMENU -/*! - \reimp -*/ -void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) -{ - Q_D(QGraphicsProxyWidget); - if (!event || !d->widget || !d->widget->isVisible() || !hasFocus()) - return; - - // Find widget position and receiver. - QPointF pos = event->pos(); - QPointer<QWidget> alienWidget = d->widget->childAt(pos.toPoint()); - QPointer<QWidget> receiver = alienWidget ? alienWidget : d->widget; - - // Map event position from us to the receiver - pos = d->mapToReceiver(pos, receiver); - - QPoint globalPos = receiver->mapToGlobal(pos.toPoint()); - //If the receiver by-pass the proxy its popups - //will be top level QWidgets therefore they need - //the screen position. mapToGlobal expect the widget to - //have proper coordinates in regards of the windowing system - //but it's not true because the widget is embedded. - if (bypassGraphicsProxyWidget(receiver)) - globalPos = event->screenPos(); - - // Send mouse event. ### Doesn't propagate the event. - QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()), - pos.toPoint(), globalPos, event->modifiers()); - QApplication::sendEvent(receiver, &contextMenuEvent); - - event->setAccepted(contextMenuEvent.isAccepted()); -} -#endif // QT_NO_CONTEXTMENU - -#ifndef QT_NO_DRAGANDDROP -/*! - \reimp -*/ -void QGraphicsProxyWidget::dragEnterEvent(QGraphicsSceneDragDropEvent *event) -{ -#ifdef QT_NO_DRAGANDDROP - Q_UNUSED(event); -#else - Q_D(QGraphicsProxyWidget); - if (!d->widget) - return; - - QDragEnterEvent proxyDragEnter(event->pos().toPoint(), event->dropAction(), event->mimeData(), event->buttons(), event->modifiers()); - proxyDragEnter.setAccepted(event->isAccepted()); - QApplication::sendEvent(d->widget, &proxyDragEnter); - event->setAccepted(proxyDragEnter.isAccepted()); - if (proxyDragEnter.isAccepted()) // we discard answerRect - event->setDropAction(proxyDragEnter.dropAction()); -#endif -} -/*! - \reimp -*/ -void QGraphicsProxyWidget::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_UNUSED(event); -#ifndef QT_NO_DRAGANDDROP - Q_D(QGraphicsProxyWidget); - if (!d->widget || !d->dragDropWidget) - return; - QDragLeaveEvent proxyDragLeave; - QApplication::sendEvent(d->dragDropWidget, &proxyDragLeave); - d->dragDropWidget = 0; -#endif -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::dragMoveEvent(QGraphicsSceneDragDropEvent *event) -{ -#ifdef QT_NO_DRAGANDDROP - Q_UNUSED(event); -#else - Q_D(QGraphicsProxyWidget); - if (!d->widget) - return; - QPointF p = event->pos(); - event->ignore(); - QPointer<QWidget> subWidget = d->widget->childAt(p.toPoint()); - QPointer<QWidget> receiver = subWidget ? subWidget : d->widget; - bool eventDelivered = false; - for (; receiver; receiver = receiver->parentWidget()) { - if (!receiver->isEnabled() || !receiver->acceptDrops()) - continue; - // Map event position from us to the receiver - QPoint receiverPos = d->mapToReceiver(p, receiver).toPoint(); - if (receiver != d->dragDropWidget) { - // Try to enter before we leave - QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers()); - dragEnter.setDropAction(event->proposedAction()); - QApplication::sendEvent(receiver, &dragEnter); - event->setAccepted(dragEnter.isAccepted()); - event->setDropAction(dragEnter.dropAction()); - if (!event->isAccepted()) { - // propagate to the parent widget - continue; - } - - d->lastDropAction = event->dropAction(); - - if (d->dragDropWidget) { - QDragLeaveEvent dragLeave; - QApplication::sendEvent(d->dragDropWidget, &dragLeave); - } - d->dragDropWidget = receiver; - } - - QDragMoveEvent dragMove(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers()); - event->setDropAction(d->lastDropAction); - QApplication::sendEvent(receiver, &dragMove); - event->setAccepted(dragMove.isAccepted()); - event->setDropAction(dragMove.dropAction()); - if (event->isAccepted()) - d->lastDropAction = event->dropAction(); - eventDelivered = true; - break; - } - - if (!eventDelivered) { - if (d->dragDropWidget) { - // Leave the last drag drop item - QDragLeaveEvent dragLeave; - QApplication::sendEvent(d->dragDropWidget, &dragLeave); - d->dragDropWidget = 0; - } - // Propagate - event->setDropAction(Qt::IgnoreAction); - } -#endif -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event) -{ -#ifdef QT_NO_DRAGANDDROP - Q_UNUSED(event); -#else - Q_D(QGraphicsProxyWidget); - if (d->widget && d->dragDropWidget) { - QPoint widgetPos = d->mapToReceiver(event->pos(), d->dragDropWidget).toPoint(); - QDropEvent dropEvent(widgetPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers()); - QApplication::sendEvent(d->dragDropWidget, &dropEvent); - event->setAccepted(dropEvent.isAccepted()); - d->dragDropWidget = 0; - } -#endif -} -#endif - -/*! - \reimp -*/ -void QGraphicsProxyWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); - Q_D(QGraphicsProxyWidget); - // If hoverMove was compressed away, make sure we update properly here. - if (d->lastWidgetUnderMouse) { - QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse); - d->lastWidgetUnderMouse = 0; - } -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::hoverMoveEvent"; -#endif - // Ignore events on the window frame. - if (!d->widget || !rect().contains(event->pos())) { - if (d->lastWidgetUnderMouse) { - QApplicationPrivate::dispatchEnterLeave(0, d->lastWidgetUnderMouse); - d->lastWidgetUnderMouse = 0; - } - return; - } - - d->embeddedMouseGrabber = 0; - d->sendWidgetMouseEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::grabMouseEvent(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::ungrabMouseEvent(QEvent *event) -{ - Q_D(QGraphicsProxyWidget); - Q_UNUSED(event); - d->embeddedMouseGrabber = 0; -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::mouseMoveEvent"; -#endif - d->sendWidgetMouseEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::mousePressEvent"; -#endif - d->sendWidgetMouseEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::mouseDoubleClickEvent"; -#endif - d->sendWidgetMouseEvent(event); -} - -/*! - \reimp -*/ -#ifndef QT_NO_WHEELEVENT -void QGraphicsProxyWidget::wheelEvent(QGraphicsSceneWheelEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::wheelEvent"; -#endif - if (!d->widget) - return; - - QPointF pos = event->pos(); - QPointer<QWidget> receiver = d->widget->childAt(pos.toPoint()); - if (!receiver) - receiver = d->widget; - - // Map event position from us to the receiver - pos = d->mapToReceiver(pos, receiver); - - // Send mouse event. - QWheelEvent wheelEvent(pos.toPoint(), event->screenPos(), event->delta(), - event->buttons(), event->modifiers(), event->orientation()); - QPointer<QWidget> focusWidget = d->widget->focusWidget(); - extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); - qt_sendSpontaneousEvent(receiver, &wheelEvent); - event->setAccepted(wheelEvent.isAccepted()); - - // ### Remove, this should be done by proper focusIn/focusOut events. - if (focusWidget && !focusWidget->hasFocus()) { - focusWidget->update(); - focusWidget = d->widget->focusWidget(); - if (focusWidget && focusWidget->hasFocus()) - focusWidget->update(); - } -} -#endif - -/*! - \reimp -*/ -void QGraphicsProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::mouseReleaseEvent"; -#endif - d->sendWidgetMouseEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::keyPressEvent(QKeyEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::keyPressEvent"; -#endif - d->sendWidgetKeyEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::keyReleaseEvent(QKeyEvent *event) -{ - Q_D(QGraphicsProxyWidget); -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::keyReleaseEvent"; -#endif - d->sendWidgetKeyEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event) -{ -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::focusInEvent"; -#endif - Q_D(QGraphicsProxyWidget); - - if (d->focusFromWidgetToProxy) { - // Prevent recursion when the proxy autogains focus through the - // embedded widget calling setFocus(). ### Could be done with event - // filter on FocusIn instead? - return; - } - - d->proxyIsGivingFocus = true; - - switch (event->reason()) { - case Qt::TabFocusReason: { - if (QWidget *focusChild = d->findFocusChild(0, true)) - focusChild->setFocus(event->reason()); - break; - } - case Qt::BacktabFocusReason: - if (QWidget *focusChild = d->findFocusChild(0, false)) - focusChild->setFocus(event->reason()); - break; - default: - if (d->widget && d->widget->focusWidget()) { - d->widget->focusWidget()->setFocus(event->reason()); - } - break; - } - - d->proxyIsGivingFocus = false; -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::focusOutEvent(QFocusEvent *event) -{ -#ifdef GRAPHICSPROXYWIDGET_DEBUG - qDebug() << "QGraphicsProxyWidget::focusOutEvent"; -#endif - Q_D(QGraphicsProxyWidget); - if (d->widget) { - // We need to explicitly remove subfocus from the embedded widget's - // focus widget. - if (QWidget *focusWidget = d->widget->focusWidget()) - d->removeSubFocusHelper(focusWidget, event->reason()); - } -} - -/*! - \reimp -*/ -bool QGraphicsProxyWidget::focusNextPrevChild(bool next) -{ - Q_D(QGraphicsProxyWidget); - if (!d->widget || !d->scene) - return QGraphicsWidget::focusNextPrevChild(next); - - Qt::FocusReason reason = next ? Qt::TabFocusReason : Qt::BacktabFocusReason; - QWidget *lastFocusChild = d->widget->focusWidget(); - if (QWidget *newFocusChild = d->findFocusChild(lastFocusChild, next)) { - newFocusChild->setFocus(reason); - return true; - } - - return QGraphicsWidget::focusNextPrevChild(next); -} - -/*! - \reimp -*/ -QSizeF QGraphicsProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_D(const QGraphicsProxyWidget); - if (!d->widget) - return QGraphicsWidget::sizeHint(which, constraint); - - QSizeF sh; - switch (which) { - case Qt::PreferredSize: - if (QLayout *l = d->widget->layout()) - sh = l->sizeHint(); - else - sh = d->widget->sizeHint(); - break; - case Qt::MinimumSize: - if (QLayout *l = d->widget->layout()) - sh = l->minimumSize(); - else - sh = d->widget->minimumSizeHint(); - break; - case Qt::MaximumSize: - if (QLayout *l = d->widget->layout()) - sh = l->maximumSize(); - else - sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - break; - case Qt::MinimumDescent: - sh = constraint; - break; - default: - break; - } - return sh; -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event) -{ - Q_D(QGraphicsProxyWidget); - if (d->widget) { - if (d->sizeChangeMode != QGraphicsProxyWidgetPrivate::WidgetToProxyMode) - d->widget->resize(event->newSize().toSize()); - } - QGraphicsWidget::resizeEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_D(QGraphicsProxyWidget); - Q_UNUSED(widget); - if (!d->widget || !d->widget->isVisible()) - return; - - // Filter out repaints on the window frame. - const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect(); - if (exposedWidgetRect.isEmpty()) - return; - - // Disable QPainter's default pen being cosmetic. This allows widgets and - // styles to follow Qt's existing defaults without getting ugly cosmetic - // lines when scaled. - bool restore = !(painter->renderHints() & QPainter::NonCosmeticDefaultPen); - painter->setRenderHints(QPainter::NonCosmeticDefaultPen, true); - - d->widget->render(painter, exposedWidgetRect.topLeft(), exposedWidgetRect); - - // Restore the render hints if necessary. - if (restore) - painter->setRenderHints(QPainter::NonCosmeticDefaultPen, false); -} - -/*! - \reimp -*/ -int QGraphicsProxyWidget::type() const -{ - return Type; -} - -/*! - \since 4.5 - - Creates a proxy widget for the given \a child of the widget - contained in this proxy. - - This function makes it possible to acquire proxies for - non top-level widgets. For instance, you can embed a dialog, - and then transform only one of its widgets. - - If the widget is already embedded, return the existing proxy widget. - - \sa newProxyWidget(), QGraphicsScene::addWidget() -*/ -QGraphicsProxyWidget *QGraphicsProxyWidget::createProxyForChildWidget(QWidget *child) -{ - QGraphicsProxyWidget *proxy = child->graphicsProxyWidget(); - if (proxy) - return proxy; - if (!child->parentWidget()) { - qWarning("QGraphicsProxyWidget::createProxyForChildWidget: top-level widget not in a QGraphicsScene"); - return 0; - } - - QGraphicsProxyWidget *parentProxy = createProxyForChildWidget(child->parentWidget()); - if (!parentProxy) - return 0; - - if (!QMetaObject::invokeMethod(parentProxy, "newProxyWidget", Qt::DirectConnection, - Q_RETURN_ARG(QGraphicsProxyWidget*, proxy), Q_ARG(const QWidget*, child))) - return 0; - proxy->setParent(parentProxy); - proxy->setWidget(child); - return proxy; -} - -/*! - \fn QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *child) - \since 4.5 - - Creates a proxy widget for the given \a child of the widget contained in this - proxy. - - You should not call this function directly; use - QGraphicsProxyWidget::createProxyForChildWidget() instead. - - This function is a fake virtual slot that you can reimplement in - your subclass in order to control how new proxy widgets are - created. The default implementation returns a proxy created with - the QGraphicsProxyWidget() constructor with this proxy widget as - the parent. - - \sa createProxyForChildWidget() -*/ -QGraphicsProxyWidget *QGraphicsProxyWidget::newProxyWidget(const QWidget *) -{ - return new QGraphicsProxyWidget(this); -} - - - -QT_END_NAMESPACE - -#include "moc_qgraphicsproxywidget.cpp" - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsproxywidget.h b/src/gui/graphicsview/qgraphicsproxywidget.h deleted file mode 100644 index 3ff5ef1aac..0000000000 --- a/src/gui/graphicsview/qgraphicsproxywidget.h +++ /dev/null @@ -1,147 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSPROXYWIDGET_H -#define QGRAPHICSPROXYWIDGET_H - -#include <QtGui/qgraphicswidget.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsProxyWidgetPrivate; - -class Q_GUI_EXPORT QGraphicsProxyWidget : public QGraphicsWidget -{ - Q_OBJECT -public: - QGraphicsProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); - ~QGraphicsProxyWidget(); - - void setWidget(QWidget *widget); - QWidget *widget() const; - - QRectF subWidgetRect(const QWidget *widget) const; - - void setGeometry(const QRectF &rect); - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - - enum { - Type = 12 - }; - int type() const; - - QGraphicsProxyWidget *createProxyForChildWidget(QWidget *child); - -protected: - QVariant itemChange(GraphicsItemChange change, const QVariant &value); - - bool event(QEvent *event); - bool eventFilter(QObject *object, QEvent *event); - - void showEvent(QShowEvent *event); - void hideEvent(QHideEvent *event); - -#ifndef QT_NO_CONTEXTMENU - void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); -#endif - -#ifndef QT_NO_DRAGANDDROP - void dragEnterEvent(QGraphicsSceneDragDropEvent *event); - void dragLeaveEvent(QGraphicsSceneDragDropEvent *event); - void dragMoveEvent(QGraphicsSceneDragDropEvent *event); - void dropEvent(QGraphicsSceneDragDropEvent *event); -#endif - - void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - void grabMouseEvent(QEvent *event); - void ungrabMouseEvent(QEvent *event); - - void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - void mousePressEvent(QGraphicsSceneMouseEvent *event); - void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); -#ifndef QT_NO_WHEELEVENT - void wheelEvent(QGraphicsSceneWheelEvent *event); -#endif - - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); - - void focusInEvent(QFocusEvent *event); - void focusOutEvent(QFocusEvent *event); - bool focusNextPrevChild(bool next); - // ### Qt 4.5: - // QVariant inputMethodQuery(Qt::InputMethodQuery query) const; - // void inputMethodEvent(QInputMethodEvent *event); - - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - void resizeEvent(QGraphicsSceneResizeEvent *event); - -protected Q_SLOTS: - QGraphicsProxyWidget *newProxyWidget(const QWidget *); - -private: - Q_DISABLE_COPY(QGraphicsProxyWidget) - Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsProxyWidget) - Q_PRIVATE_SLOT(d_func(), void _q_removeWidgetSlot()) - - friend class QWidget; - friend class QWidgetPrivate; - friend class QGraphicsItem; -}; - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif - diff --git a/src/gui/graphicsview/qgraphicsproxywidget_p.h b/src/gui/graphicsview/qgraphicsproxywidget_p.h deleted file mode 100644 index 86aec5f86b..0000000000 --- a/src/gui/graphicsview/qgraphicsproxywidget_p.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSPROXYWIDGET_P_H -#define QGRAPHICSPROXYWIDGET_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsproxywidget.h" -#include "private/qgraphicswidget_p.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -QT_BEGIN_NAMESPACE - -class QGraphicsProxyWidgetPrivate : public QGraphicsWidgetPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsProxyWidget) -public: - QGraphicsProxyWidgetPrivate() - : dragDropWidget(0), - posChangeMode(NoMode), - sizeChangeMode(NoMode), - visibleChangeMode(NoMode), - enabledChangeMode(NoMode), - styleChangeMode(NoMode), - paletteChangeMode(NoMode), - tooltipChangeMode(NoMode), - focusFromWidgetToProxy(0) - { } - void init(); - void sendWidgetMouseEvent(QGraphicsSceneMouseEvent *event); - void sendWidgetMouseEvent(QGraphicsSceneHoverEvent *event); - void sendWidgetKeyEvent(QKeyEvent *event); - void setWidget_helper(QWidget *widget, bool autoShow); - - QWidget *findFocusChild(QWidget *child, bool next) const; - void removeSubFocusHelper(QWidget *widget, Qt::FocusReason reason); - - // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. - QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; - - void _q_removeWidgetSlot(); - - void embedSubWindow(QWidget *); - void unembedSubWindow(QWidget *); - - bool isProxyWidget() const; - - QPointer<QWidget> widget; - QPointer<QWidget> lastWidgetUnderMouse; - QPointer<QWidget> embeddedMouseGrabber; - QWidget *dragDropWidget; - Qt::DropAction lastDropAction; - - void updateWidgetGeometryFromProxy(); - void updateProxyGeometryFromWidget(); - - void updateProxyInputMethodAcceptanceFromWidget(); - - QPointF mapToReceiver(const QPointF &pos, const QWidget *receiver) const; - - enum ChangeMode { - NoMode, - ProxyToWidgetMode, - WidgetToProxyMode - }; - quint32 posChangeMode : 2; - quint32 sizeChangeMode : 2; - quint32 visibleChangeMode : 2; - quint32 enabledChangeMode : 2; - quint32 styleChangeMode : 2; - quint32 paletteChangeMode : 2; - quint32 tooltipChangeMode : 2; - quint32 focusFromWidgetToProxy : 1; - quint32 proxyIsGivingFocus : 1; -}; - -QT_END_NAMESPACE - -#endif - -#endif diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp deleted file mode 100644 index 655725b8e9..0000000000 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ /dev/null @@ -1,6503 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsScene - \brief The QGraphicsScene class provides a surface for managing a large - number of 2D graphical items. - \since 4.2 - \ingroup graphicsview-api - - - The class serves as a container for QGraphicsItems. It is used together - with QGraphicsView for visualizing graphical items, such as lines, - rectangles, text, or even custom items, on a 2D surface. QGraphicsScene is - part of the \l{Graphics View Framework}. - - QGraphicsScene also provides functionality that lets you efficiently - determine both the location of items, and for determining what items are - visible within an arbitrary area on the scene. With the QGraphicsView - widget, you can either visualize the whole scene, or zoom in and view only - parts of the scene. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 0 - - Note that QGraphicsScene has no visual appearance of its own; it only - manages the items. You need to create a QGraphicsView widget to visualize - the scene. - - To add items to a scene, you start off by constructing a QGraphicsScene - object. Then, you have two options: either add your existing QGraphicsItem - objects by calling addItem(), or you can call one of the convenience - functions addEllipse(), addLine(), addPath(), addPixmap(), addPolygon(), - addRect(), or addText(), which all return a pointer to the newly added item. - The dimensions of the items added with these functions are relative to the - item's coordinate system, and the items position is initialized to (0, - 0) in the scene. - - You can then visualize the scene using QGraphicsView. When the scene - changes, (e.g., when an item moves or is transformed) QGraphicsScene - emits the changed() signal. To remove an item, call removeItem(). - - QGraphicsScene uses an indexing algorithm to manage the location of items - efficiently. By default, a BSP (Binary Space Partitioning) tree is used; an - algorithm suitable for large scenes where most items remain static (i.e., - do not move around). You can choose to disable this index by calling - setItemIndexMethod(). For more information about the available indexing - algorithms, see the itemIndexMethod property. - - The scene's bounding rect is set by calling setSceneRect(). Items can be - placed at any position on the scene, and the size of the scene is by - default unlimited. The scene rect is used only for internal bookkeeping, - maintaining the scene's item index. If the scene rect is unset, - QGraphicsScene will use the bounding area of all items, as returned by - itemsBoundingRect(), as the scene rect. However, itemsBoundingRect() is a - relatively time consuming function, as it operates by collecting - positional information for every item on the scene. Because of this, you - should always set the scene rect when operating on large scenes. - - One of QGraphicsScene's greatest strengths is its ability to efficiently - determine the location of items. Even with millions of items on the scene, - the items() functions can determine the location of an item within few - milliseconds. There are several overloads to items(): one that finds items - at a certain position, one that finds items inside or intersecting with a - polygon or a rectangle, and more. The list of returned items is sorted by - stacking order, with the topmost item being the first item in the list. - For convenience, there is also an itemAt() function that returns the - topmost item at a given position. - - QGraphicsScene maintains selection information for the scene. To select - items, call setSelectionArea(), and to clear the current selection, call - clearSelection(). Call selectedItems() to get the list of all selected - items. - - \section1 Event Handling and Propagation - - Another responsibility that QGraphicsScene has, is to propagate events - from QGraphicsView. To send an event to a scene, you construct an event - that inherits QEvent, and then send it using, for example, - QApplication::sendEvent(). event() is responsible for dispatching - the event to the individual items. Some common events are handled by - convenience event handlers. For example, key press events are handled by - keyPressEvent(), and mouse press events are handled by mousePressEvent(). - - Key events are delivered to the \e {focus item}. To set the focus item, - you can either call setFocusItem(), passing an item that accepts focus, or - the item itself can call QGraphicsItem::setFocus(). Call focusItem() to - get the current focus item. For compatibility with widgets, the scene also - maintains its own focus information. By default, the scene does not have - focus, and all key events are discarded. If setFocus() is called, or if an - item on the scene gains focus, the scene automatically gains focus. If the - scene has focus, hasFocus() will return true, and key events will be - forwarded to the focus item, if any. If the scene loses focus, (i.e., - someone calls clearFocus()) while an item has focus, the scene will - maintain its item focus information, and once the scene regains focus, it - will make sure the last focus item regains focus. - - For mouse-over effects, QGraphicsScene dispatches \e {hover - events}. If an item accepts hover events (see - QGraphicsItem::acceptHoverEvents()), it will receive a \l - {QEvent::}{GraphicsSceneHoverEnter} event when the mouse enters - its area. As the mouse continues moving inside the item's area, - QGraphicsScene will send it \l {QEvent::}{GraphicsSceneHoverMove} - events. When the mouse leaves the item's area, the item will - receive a \l {QEvent::}{GraphicsSceneHoverLeave} event. - - All mouse events are delivered to the current \e {mouse grabber} - item. An item becomes the scene's mouse grabber if it accepts - mouse events (see QGraphicsItem::acceptedMouseButtons()) and it - receives a mouse press. It stays the mouse grabber until it - receives a mouse release when no other mouse buttons are - pressed. You can call mouseGrabberItem() to determine what item is - currently grabbing the mouse. - - \sa QGraphicsItem, QGraphicsView -*/ - -/*! - \enum QGraphicsScene::SceneLayer - \since 4.3 - - This enum describes the rendering layers in a QGraphicsScene. When - QGraphicsScene draws the scene contents, it renders each of these layers - separately, in order. - - Each layer represents a flag that can be OR'ed together when calling - functions such as invalidate() or QGraphicsView::invalidateScene(). - - \value ItemLayer The item layer. QGraphicsScene renders all items are in - this layer by calling the virtual function drawItems(). The item layer is - drawn after the background layer, but before the foreground layer. - - \value BackgroundLayer The background layer. QGraphicsScene renders the - scene's background in this layer by calling the virtual function - drawBackground(). The background layer is drawn first of all layers. - - \value ForegroundLayer The foreground layer. QGraphicsScene renders the - scene's foreground in this layer by calling the virtual function - drawForeground(). The foreground layer is drawn last of all layers. - - \value AllLayers All layers; this value represents a combination of all - three layers. - - \sa invalidate(), QGraphicsView::invalidateScene() -*/ - -/*! - \enum QGraphicsScene::ItemIndexMethod - - This enum describes the indexing algorithms QGraphicsScene provides for - managing positional information about items on the scene. - - \value BspTreeIndex A Binary Space Partitioning tree is applied. All - QGraphicsScene's item location algorithms are of an order close to - logarithmic complexity, by making use of binary search. Adding, moving and - removing items is logarithmic. This approach is best for static scenes - (i.e., scenes where most items do not move). - - \value NoIndex No index is applied. Item location is of linear complexity, - as all items on the scene are searched. Adding, moving and removing items, - however, is done in constant time. This approach is ideal for dynamic - scenes, where many items are added, moved or removed continuously. - - \sa setItemIndexMethod(), bspTreeDepth -*/ - -#include "qgraphicsscene.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicsitem.h" -#include "qgraphicsitem_p.h" -#include "qgraphicslayout.h" -#include "qgraphicsscene_p.h" -#include "qgraphicssceneevent.h" -#include "qgraphicsview.h" -#include "qgraphicsview_p.h" -#include "qgraphicswidget.h" -#include "qgraphicswidget_p.h" -#include "qgraphicssceneindex_p.h" -#include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicsscenelinearindex_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qlist.h> -#include <QtCore/qmath.h> -#include <QtCore/qrect.h> -#include <QtCore/qset.h> -#include <QtCore/qstack.h> -#include <QtCore/qtimer.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/QMetaMethod> -#include <QtGui/qapplication.h> -#include <QtGui/qdesktopwidget.h> -#include <QtGui/qevent.h> -#include <QtGui/qgraphicslayout.h> -#include <QtGui/qgraphicsproxywidget.h> -#include <QtGui/qgraphicswidget.h> -#include <QtGui/qmatrix.h> -#include <QtGui/qpaintengine.h> -#include <QtGui/qpainter.h> -#include <QtGui/qpixmapcache.h> -#include <QtGui/qpolygon.h> -#include <QtGui/qstyleoption.h> -#include <QtGui/qtooltip.h> -#include <QtGui/qtransform.h> -#include <QtGui/qinputcontext.h> -#include <QtGui/qgraphicseffect.h> -#ifndef QT_NO_ACCESSIBILITY -# include <QtGui/qaccessible.h> -#endif - -#include <private/qapplication_p.h> -#include <private/qobject_p.h> -#ifdef Q_WS_X11 -#include <private/qt_x11_p.h> -#endif -#include <private/qgraphicseffect_p.h> -#include <private/qgesturemanager_p.h> -#include <private/qpathclipper_p.h> - -// #define GESTURE_DEBUG -#ifndef GESTURE_DEBUG -# define DEBUG if (0) qDebug -#else -# define DEBUG qDebug -#endif - -QT_BEGIN_NAMESPACE - -bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); - -static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) -{ - hover->setWidget(mouseEvent->widget()); - hover->setPos(mouseEvent->pos()); - hover->setScenePos(mouseEvent->scenePos()); - hover->setScreenPos(mouseEvent->screenPos()); - hover->setLastPos(mouseEvent->lastPos()); - hover->setLastScenePos(mouseEvent->lastScenePos()); - hover->setLastScreenPos(mouseEvent->lastScreenPos()); - hover->setModifiers(mouseEvent->modifiers()); - hover->setAccepted(mouseEvent->isAccepted()); -} - -/*! - \internal -*/ -QGraphicsScenePrivate::QGraphicsScenePrivate() - : indexMethod(QGraphicsScene::BspTreeIndex), - index(0), - lastItemCount(0), - hasSceneRect(false), - dirtyGrowingItemsBoundingRect(true), - updateAll(false), - calledEmitUpdated(false), - processDirtyItemsEmitted(false), - needSortTopLevelItems(true), - holesInTopLevelSiblingIndex(false), - topLevelSequentialOrdering(true), - scenePosDescendantsUpdatePending(false), - stickyFocus(false), - hasFocus(false), - lastMouseGrabberItemHasImplicitMouseGrab(false), - allItemsIgnoreHoverEvents(true), - allItemsUseDefaultCursor(true), - painterStateProtection(true), - sortCacheEnabled(false), - allItemsIgnoreTouchEvents(true), - selectionChanging(0), - rectAdjust(2), - focusItem(0), - lastFocusItem(0), - passiveFocusItem(0), - tabFocusFirst(0), - activePanel(0), - lastActivePanel(0), - activationRefCount(0), - childExplicitActivation(0), - lastMouseGrabberItem(0), - dragDropItem(0), - enterWidget(0), - lastDropAction(Qt::IgnoreAction), - style(0) -{ -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::init() -{ - Q_Q(QGraphicsScene); - - index = new QGraphicsSceneBspTreeIndex(q); - - // Keep this index so we can check for connected slots later on. - changedSignalIndex = signalIndex("changed(QList<QRectF>)"); - processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()"); - polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()"); - - qApp->d_func()->scene_list.append(q); - q->update(); -} - -/*! - \internal -*/ -QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q) -{ - return q->d_func(); -} - -void QGraphicsScenePrivate::_q_emitUpdated() -{ - Q_Q(QGraphicsScene); - calledEmitUpdated = false; - - if (dirtyGrowingItemsBoundingRect) { - if (!hasSceneRect) { - const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; - growingItemsBoundingRect |= q->itemsBoundingRect(); - if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) - emit q->sceneRectChanged(growingItemsBoundingRect); - } - dirtyGrowingItemsBoundingRect = false; - } - - // Ensure all views are connected if anything is connected. This disables - // the optimization that items send updates directly to the views, but it - // needs to happen in order to keep compatibility with the behavior from - // Qt 4.4 and backward. - if (isSignalConnected(changedSignalIndex)) { - for (int i = 0; i < views.size(); ++i) { - QGraphicsView *view = views.at(i); - if (!view->d_func()->connectedToScene) { - view->d_func()->connectedToScene = true; - q->connect(q, SIGNAL(changed(QList<QRectF>)), - views.at(i), SLOT(updateScene(QList<QRectF>))); - } - } - } else { - if (views.isEmpty()) { - updateAll = false; - return; - } - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->processPendingUpdates(); - // It's important that we update all views before we dispatch, hence two for-loops. - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->dispatchPendingUpdateRequests(); - return; - } - - // Notify the changes to anybody interested. - QList<QRectF> oldUpdatedRects; - oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects; - updateAll = false; - updatedRects.clear(); - emit q->changed(oldUpdatedRects); -} - -/*! - \internal - - ### This function is almost identical to QGraphicsItemPrivate::addChild(). -*/ -void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) -{ - item->d_ptr->ensureSequentialSiblingIndex(); - needSortTopLevelItems = true; // ### maybe false - item->d_ptr->siblingIndex = topLevelItems.size(); - topLevelItems.append(item); -} - -/*! - \internal - - ### This function is almost identical to QGraphicsItemPrivate::removeChild(). -*/ -void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) -{ - if (!holesInTopLevelSiblingIndex) - holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1; - if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex) - topLevelItems.removeAt(item->d_ptr->siblingIndex); - else - topLevelItems.removeOne(item); - // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because - // the item is not guaranteed to be at the index after the list is sorted - // (see ensureSortedTopLevelItems()). - item->d_ptr->siblingIndex = -1; - if (topLevelSequentialOrdering) - topLevelSequentialOrdering = !holesInTopLevelSiblingIndex; -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::_q_polishItems() -{ - if (unpolishedItems.isEmpty()) - return; - - const QVariant booleanTrueVariant(true); - QGraphicsItem *item = 0; - QGraphicsItemPrivate *itemd = 0; - const int oldUnpolishedCount = unpolishedItems.count(); - - for (int i = 0; i < oldUnpolishedCount; ++i) { - item = unpolishedItems.at(i); - if (!item) - continue; - itemd = item->d_ptr.data(); - itemd->pendingPolish = false; - if (!itemd->explicitlyHidden) { - item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); - item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); - } - if (itemd->isWidget) { - QEvent event(QEvent::Polish); - QApplication::sendEvent((QGraphicsWidget *)item, &event); - } - } - - if (unpolishedItems.count() == oldUnpolishedCount) { - // No new items were added to the vector. - unpolishedItems.clear(); - } else { - // New items were appended; keep them and remove the old ones. - unpolishedItems.remove(0, oldUnpolishedCount); - unpolishedItems.squeeze(); - QMetaObject::invokeMethod(q_ptr, "_q_polishItems", Qt::QueuedConnection); - } -} - -void QGraphicsScenePrivate::_q_processDirtyItems() -{ - processDirtyItemsEmitted = false; - - if (updateAll) { - Q_ASSERT(calledEmitUpdated); - // No need for further processing (except resetting the dirty states). - // The growingItemsBoundingRect is updated in _q_emitUpdated. - for (int i = 0; i < topLevelItems.size(); ++i) - resetDirtyItem(topLevelItems.at(i), /*recursive=*/true); - return; - } - - const bool wasPendingSceneUpdate = calledEmitUpdated; - const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; - - // Process items recursively. - for (int i = 0; i < topLevelItems.size(); ++i) - processDirtyItemsRecursive(topLevelItems.at(i)); - - dirtyGrowingItemsBoundingRect = false; - if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) - emit q_func()->sceneRectChanged(growingItemsBoundingRect); - - if (wasPendingSceneUpdate) - return; - - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->processPendingUpdates(); - - if (calledEmitUpdated) { - // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive - // and we cannot wait for the control to reach the eventloop before the - // changed signal is emitted, so we emit it now. - _q_emitUpdated(); - } - - // Immediately dispatch all pending update requests on the views. - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->dispatchPendingUpdateRequests(); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled) -{ - QGraphicsItem *p = item->d_ptr->parent; - while (p) { - p->d_ptr->scenePosDescendants = enabled; - p = p->d_ptr->parent; - } - if (!enabled && !scenePosDescendantsUpdatePending) { - scenePosDescendantsUpdatePending = true; - QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection); - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item) -{ - scenePosItems.insert(item); - setScenePosItemEnabled(item, true); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item) -{ - scenePosItems.remove(item); - setScenePosItemEnabled(item, false); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::_q_updateScenePosDescendants() -{ - foreach (QGraphicsItem *item, scenePosItems) { - QGraphicsItem *p = item->d_ptr->parent; - while (p) { - p->d_ptr->scenePosDescendants = 1; - p = p->d_ptr->parent; - } - } - scenePosDescendantsUpdatePending = false; -} - -/*! - \internal - - Schedules an item for removal. This function leaves some stale indexes - around in the BSP tree if called from the item's destructor; these will - be cleaned up the next time someone triggers purgeRemovedItems(). - - Note: This function might get called from QGraphicsItem's destructor. \a item is - being destroyed, so we cannot call any pure virtual functions on it (such - as boundingRect()). Also, it is unnecessary to update the item's own state - in any way. -*/ -void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) -{ - Q_Q(QGraphicsScene); - - // Clear focus on the item to remove any reference in the focusWidget chain. - item->clearFocus(); - - markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false, - /*ignoreOpacity=*/false, /*removingItemFromScene=*/true); - - if (item->d_ptr->inDestructor) { - // The item is actually in its destructor, we call the special method in the index. - index->deleteItem(item); - } else { - // Can potentially call item->boundingRect() (virtual function), that's why - // we only can call this function if the item is not in its destructor. - index->removeItem(item); - } - - item->d_ptr->clearSubFocus(); - - if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) - unregisterScenePosItem(item); - - QGraphicsScene *oldScene = item->d_func()->scene; - item->d_func()->scene = 0; - - //We need to remove all children first because they might use their parent - //attributes (e.g. sceneTransform). - if (!item->d_ptr->inDestructor) { - // Remove all children recursively - for (int i = 0; i < item->d_ptr->children.size(); ++i) - q->removeItem(item->d_ptr->children.at(i)); - } - - if (!item->d_ptr->inDestructor && item == tabFocusFirst) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); - widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0); - } - - // Unregister focus proxy. - item->d_ptr->resetFocusProxy(); - - // Remove from parent, or unregister from toplevels. - if (QGraphicsItem *parentItem = item->parentItem()) { - if (parentItem->scene()) { - Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem", - "Parent item's scene is different from this item's scene"); - item->setParentItem(0); - } - } else { - unregisterTopLevelItem(item); - } - - // Reset the mouse grabber and focus item data. - if (item == focusItem) - focusItem = 0; - if (item == lastFocusItem) - lastFocusItem = 0; - if (item == passiveFocusItem) - passiveFocusItem = 0; - if (item == activePanel) { - // ### deactivate... - activePanel = 0; - } - if (item == lastActivePanel) - lastActivePanel = 0; - - // Cancel active touches - { - QMap<int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin(); - while (it != itemForTouchPointId.end()) { - if (it.value() == item) { - sceneCurrentTouchPoints.remove(it.key()); - it = itemForTouchPointId.erase(it); - } else { - ++it; - } - } - } - - // Disable selectionChanged() for individual items - ++selectionChanging; - int oldSelectedItemsSize = selectedItems.size(); - - // Update selected & hovered item bookkeeping - selectedItems.remove(item); - hoverItems.removeAll(item); - cachedItemsUnderMouse.removeAll(item); - if (item->d_ptr->pendingPolish) { - const int unpolishedIndex = unpolishedItems.indexOf(item); - if (unpolishedIndex != -1) - unpolishedItems[unpolishedIndex] = 0; - item->d_ptr->pendingPolish = false; - } - resetDirtyItem(item); - - //We remove all references of item from the sceneEventFilter arrays - QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin(); - while (iterator != sceneEventFilters.end()) { - if (iterator.value() == item || iterator.key() == item) - iterator = sceneEventFilters.erase(iterator); - else - ++iterator; - } - - if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) - leaveModal(item); - - // Reset the mouse grabber and focus item data. - if (mouseGrabberItems.contains(item)) - ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor); - - // Reset the keyboard grabber - if (keyboardGrabberItems.contains(item)) - ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor); - - // Reset the last mouse grabber item - if (item == lastMouseGrabberItem) - lastMouseGrabberItem = 0; - - // Reset the current drop item - if (item == dragDropItem) - dragDropItem = 0; - - // Reenable selectionChanged() for individual items - --selectionChanging; - if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize) - emit q->selectionChanged(); - -#ifndef QT_NO_GESTURES - QHash<QGesture *, QGraphicsObject *>::iterator it; - for (it = gestureTargets.begin(); it != gestureTargets.end();) { - if (it.value() == item) - it = gestureTargets.erase(it); - else - ++it; - } - - QGraphicsObject *dummy = static_cast<QGraphicsObject *>(item); - cachedTargetItems.removeOne(dummy); - cachedItemGestures.remove(dummy); - cachedAlreadyDeliveredGestures.remove(dummy); - - foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) - ungrabGesture(item, gesture); -#endif // QT_NO_GESTURES -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent) -{ - Q_Q(QGraphicsScene); - if (item && item->scene() != q) { - qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene", - item); - return; - } - - // Ensure the scene has focus when we change panel activation. - q->setFocus(Qt::ActiveWindowFocusReason); - - // Find the item's panel. - QGraphicsItem *panel = item ? item->panel() : 0; - lastActivePanel = panel ? activePanel : 0; - if (panel == activePanel || (!q->isActive() && !duringActivationEvent)) - return; - - // Deactivate the last active panel. - if (activePanel) { - if (QGraphicsItem *fi = activePanel->focusItem()) { - // Remove focus from the current focus item. - if (fi == q->focusItem()) - q->setFocusItem(0, Qt::ActiveWindowFocusReason); - } - - QEvent event(QEvent::WindowDeactivate); - q->sendEvent(activePanel, &event); - } else if (panel && !duringActivationEvent) { - // Deactivate the scene if changing activation to a panel. - QEvent event(QEvent::WindowDeactivate); - foreach (QGraphicsItem *item, q->items()) { - if (item->isVisible() && !item->isPanel() && !item->parentItem()) - q->sendEvent(item, &event); - } - } - - // Update activate state. - activePanel = panel; - QEvent event(QEvent::ActivationChange); - QApplication::sendEvent(q, &event); - - // Activate - if (panel) { - QEvent event(QEvent::WindowActivate); - q->sendEvent(panel, &event); - - // Set focus on the panel's focus item. - if (QGraphicsItem *focusItem = panel->focusItem()) - focusItem->setFocus(Qt::ActiveWindowFocusReason); - } else if (q->isActive()) { - // Activate the scene - QEvent event(QEvent::WindowActivate); - foreach (QGraphicsItem *item, q->items()) { - if (item->isVisible() && !item->isPanel() && !item->parentItem()) - q->sendEvent(item, &event); - } - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, - Qt::FocusReason focusReason) -{ - Q_Q(QGraphicsScene); - if (item == focusItem) - return; - - // Clear focus if asked to set focus on something that can't - // accept input focus. - if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable) - || !item->isVisible() || !item->isEnabled())) { - item = 0; - } - - // Set focus on the scene if an item requests focus. - if (item) { - q->setFocus(focusReason); - if (item == focusItem) - return; - } - - if (focusItem) { - lastFocusItem = focusItem; - -#ifndef QT_NO_IM - if (lastFocusItem - && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { - // Close any external input method panel. This happens - // automatically by removing WA_InputMethodEnabled on - // the views, but if we are changing focus, we have to - // do it ourselves. - for (int i = 0; i < views.size(); ++i) - if (views.at(i)->inputContext()) - views.at(i)->inputContext()->reset(); - } - - focusItem = 0; - QFocusEvent event(QEvent::FocusOut, focusReason); - sendEvent(lastFocusItem, &event); -#endif //QT_NO_IM - } - - // This handles the case that the item has been removed from the - // scene in response to the FocusOut event. - if (item && item->scene() != q) - item = 0; - - if (item) - focusItem = item; - updateInputMethodSensitivityInViews(); - -#ifndef QT_NO_ACCESSIBILITY - if (focusItem) { - if (QGraphicsObject *focusObj = focusItem->toGraphicsObject()) { - QAccessible::updateAccessibility(focusObj, 0, QAccessible::Focus); - } - } -#endif - if (item) { - QFocusEvent event(QEvent::FocusIn, focusReason); - sendEvent(item, &event); - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget) -{ - Q_ASSERT(widget); - Q_ASSERT(!popupWidgets.contains(widget)); - popupWidgets << widget; - if (QGraphicsWidget *focusWidget = widget->focusWidget()) { - focusWidget->setFocus(Qt::PopupFocusReason); - } else { - grabKeyboard((QGraphicsItem *)widget); - if (focusItem && popupWidgets.size() == 1) { - QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); - sendEvent(focusItem, &event); - } - } - grabMouse((QGraphicsItem *)widget); -} - -/*! - \internal - - Remove \a widget from the popup list. Important notes: - - \a widget is guaranteed to be in the list of popups, but it might not be - the last entry; you can hide any item in the pop list before the others, - and this must cause all later mouse grabbers to lose the grab. -*/ -void QGraphicsScenePrivate::removePopup(QGraphicsWidget *widget, bool itemIsDying) -{ - Q_ASSERT(widget); - int index = popupWidgets.indexOf(widget); - Q_ASSERT(index != -1); - - for (int i = popupWidgets.size() - 1; i >= index; --i) { - QGraphicsWidget *widget = popupWidgets.takeLast(); - ungrabMouse(widget, itemIsDying); - if (focusItem && popupWidgets.isEmpty()) { - QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason); - sendEvent(focusItem, &event); - } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) { - ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying); - } - if (!itemIsDying && widget->isVisible()) { - widget->QGraphicsItem::d_ptr->setVisibleHelper(false, /* explicit = */ false); - } - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::grabMouse(QGraphicsItem *item, bool implicit) -{ - // Append to list of mouse grabber items, and send a mouse grab event. - if (mouseGrabberItems.contains(item)) { - if (mouseGrabberItems.last() == item) { - Q_ASSERT(!implicit); - if (!lastMouseGrabberItemHasImplicitMouseGrab) { - qWarning("QGraphicsItem::grabMouse: already a mouse grabber"); - } else { - // Upgrade to an explicit mouse grab - lastMouseGrabberItemHasImplicitMouseGrab = false; - } - } else { - qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p", - mouseGrabberItems.last()); - } - return; - } - - // Send ungrab event to the last grabber. - if (!mouseGrabberItems.isEmpty()) { - QGraphicsItem *last = mouseGrabberItems.last(); - if (lastMouseGrabberItemHasImplicitMouseGrab) { - // Implicit mouse grab is immediately lost. - last->ungrabMouse(); - } else { - // Just send ungrab event to current grabber. - QEvent ungrabEvent(QEvent::UngrabMouse); - sendEvent(last, &ungrabEvent); - } - } - - mouseGrabberItems << item; - lastMouseGrabberItemHasImplicitMouseGrab = implicit; - - // Send grab event to current grabber. - QEvent grabEvent(QEvent::GrabMouse); - sendEvent(item, &grabEvent); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::ungrabMouse(QGraphicsItem *item, bool itemIsDying) -{ - int index = mouseGrabberItems.indexOf(item); - if (index == -1) { - qWarning("QGraphicsItem::ungrabMouse: not a mouse grabber"); - return; - } - - if (item != mouseGrabberItems.last()) { - // Recursively ungrab the next mouse grabber until we reach this item - // to ensure state consistency. - ungrabMouse(mouseGrabberItems.at(index + 1), itemIsDying); - } - if (!popupWidgets.isEmpty() && item == popupWidgets.last()) { - // If the item is a popup, go via removePopup to ensure state - // consistency and that it gets hidden correctly - beware that - // removePopup() reenters this function to continue removing the grab. - removePopup((QGraphicsWidget *)item, itemIsDying); - return; - } - - // Send notification about mouse ungrab. - if (!itemIsDying) { - QEvent event(QEvent::UngrabMouse); - sendEvent(item, &event); - } - - // Remove the item from the list of grabbers. Whenever this happens, we - // reset the implicitGrab (there can be only ever be one implicit grabber - // in a scene, and it is always the latest grabber; if the implicit grab - // is lost, it is not automatically regained. - mouseGrabberItems.takeLast(); - lastMouseGrabberItemHasImplicitMouseGrab = false; - - // Send notification about mouse regrab. ### It's unfortunate that all the - // items get a GrabMouse event, but this is a rare case with a simple - // implementation and it does ensure a consistent state. - if (!itemIsDying && !mouseGrabberItems.isEmpty()) { - QGraphicsItem *last = mouseGrabberItems.last(); - QEvent event(QEvent::GrabMouse); - sendEvent(last, &event); - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::clearMouseGrabber() -{ - if (!mouseGrabberItems.isEmpty()) - mouseGrabberItems.first()->ungrabMouse(); - lastMouseGrabberItem = 0; -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::grabKeyboard(QGraphicsItem *item) -{ - if (keyboardGrabberItems.contains(item)) { - if (keyboardGrabberItems.last() == item) - qWarning("QGraphicsItem::grabKeyboard: already a keyboard grabber"); - else - qWarning("QGraphicsItem::grabKeyboard: already blocked by keyboard grabber: %p", - keyboardGrabberItems.last()); - return; - } - - // Send ungrab event to the last grabber. - if (!keyboardGrabberItems.isEmpty()) { - // Just send ungrab event to current grabber. - QEvent ungrabEvent(QEvent::UngrabKeyboard); - sendEvent(keyboardGrabberItems.last(), &ungrabEvent); - } - - keyboardGrabberItems << item; - - // Send grab event to current grabber. - QEvent grabEvent(QEvent::GrabKeyboard); - sendEvent(item, &grabEvent); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::ungrabKeyboard(QGraphicsItem *item, bool itemIsDying) -{ - int index = keyboardGrabberItems.lastIndexOf(item); - if (index == -1) { - qWarning("QGraphicsItem::ungrabKeyboard: not a keyboard grabber"); - return; - } - if (item != keyboardGrabberItems.last()) { - // Recursively ungrab the topmost keyboard grabber until we reach this - // item to ensure state consistency. - ungrabKeyboard(keyboardGrabberItems.at(index + 1), itemIsDying); - } - - // Send notification about keyboard ungrab. - if (!itemIsDying) { - QEvent event(QEvent::UngrabKeyboard); - sendEvent(item, &event); - } - - // Remove the item from the list of grabbers. - keyboardGrabberItems.takeLast(); - - // Send notification about mouse regrab. - if (!itemIsDying && !keyboardGrabberItems.isEmpty()) { - QGraphicsItem *last = keyboardGrabberItems.last(); - QEvent event(QEvent::GrabKeyboard); - sendEvent(last, &event); - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::clearKeyboardGrabber() -{ - if (!keyboardGrabberItems.isEmpty()) - ungrabKeyboard(keyboardGrabberItems.first()); -} - -void QGraphicsScenePrivate::enableMouseTrackingOnViews() -{ - foreach (QGraphicsView *view, views) - view->viewport()->setMouseTracking(true); -} - -/*! - Returns all items for the screen position in \a event. -*/ -QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &/*screenPos*/, - const QPointF &scenePos, - QWidget *widget) const -{ - Q_Q(const QGraphicsScene); - QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0; - if (!view) - return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform()); - - const QRectF pointRect(scenePos, QSizeF(1, 1)); - if (!view->isTransformed()) - return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder); - - const QTransform viewTransform = view->viewportTransform(); - return q->items(pointRect, Qt::IntersectsItemShape, - Qt::DescendingOrder, viewTransform); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event) -{ - for (int i = 0x1; i <= 0x10; i <<= 1) { - if (event->buttons() & i) { - mouseGrabberButtonDownPos.insert(Qt::MouseButton(i), - mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(), - event->widget())); - mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos()); - mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos()); - } - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter) -{ - sceneEventFilters.insert(watched, filter); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter) -{ - if (!sceneEventFilters.contains(watched)) - return; - - QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator it = sceneEventFilters.lowerBound(watched); - QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator end = sceneEventFilters.upperBound(watched); - do { - if (it.value() == filter) - it = sceneEventFilters.erase(it); - else - ++it; - } while (it != end); -} - -/*! - \internal -*/ -bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event) -{ - if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) { - QGraphicsItem *parent = item->parentItem(); - while (parent) { - if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event)) - return true; - if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) - return false; - parent = parent->parentItem(); - } - } - return false; -} - -/*! - \internal -*/ -bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event) -{ - if (item && !sceneEventFilters.contains(item)) - return false; - - QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator it = sceneEventFilters.lowerBound(item); - QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator end = sceneEventFilters.upperBound(item); - while (it != end) { - // ### The filterer and filteree might both be deleted. - if (it.value()->sceneEventFilter(it.key(), event)) - return true; - ++it; - } - return false; -} - -/*! - \internal - - This is the final dispatch point for any events from the scene to the - item. It filters the event first - if the filter returns true, the event - is considered to have been eaten by the filter, and is therefore stopped - (the default filter returns false). Then/otherwise, if the item is - enabled, the event is sent; otherwise it is stopped. -*/ -bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) -{ - if (QGraphicsObject *object = item->toGraphicsObject()) { -#ifndef QT_NO_GESTURES - QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager; - if (gestureManager) { - if (gestureManager->filterEvent(object, event)) - return true; - } -#endif // QT_NO_GESTURES - } - - if (filterEvent(item, event)) - return false; - if (filterDescendantEvent(item, event)) - return false; - if (!item || !item->isEnabled()) - return false; - if (QGraphicsObject *o = item->toGraphicsObject()) { - bool spont = event->spontaneous(); - if (spont ? qt_sendSpontaneousEvent(o, event) : QApplication::sendEvent(o, event)) - return true; - event->spont = spont; - } - return item->sceneEvent(event); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest, - QGraphicsSceneDragDropEvent *source) -{ - dest->setWidget(source->widget()); - dest->setPos(source->pos()); - dest->setScenePos(source->scenePos()); - dest->setScreenPos(source->screenPos()); - dest->setButtons(source->buttons()); - dest->setModifiers(source->modifiers()); - dest->setPossibleActions(source->possibleActions()); - dest->setProposedAction(source->proposedAction()); - dest->setDropAction(source->dropAction()); - dest->setSource(source->source()); - dest->setMimeData(source->mimeData()); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::sendDragDropEvent(QGraphicsItem *item, - QGraphicsSceneDragDropEvent *dragDropEvent) -{ - dragDropEvent->setPos(item->d_ptr->genericMapFromScene(dragDropEvent->scenePos(), dragDropEvent->widget())); - sendEvent(item, dragDropEvent); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::sendHoverEvent(QEvent::Type type, QGraphicsItem *item, - QGraphicsSceneHoverEvent *hoverEvent) -{ - QGraphicsSceneHoverEvent event(type); - event.setWidget(hoverEvent->widget()); - event.setPos(item->d_ptr->genericMapFromScene(hoverEvent->scenePos(), hoverEvent->widget())); - event.setScenePos(hoverEvent->scenePos()); - event.setScreenPos(hoverEvent->screenPos()); - event.setLastPos(item->d_ptr->genericMapFromScene(hoverEvent->lastScenePos(), hoverEvent->widget())); - event.setLastScenePos(hoverEvent->lastScenePos()); - event.setLastScreenPos(hoverEvent->lastScreenPos()); - event.setModifiers(hoverEvent->modifiers()); - sendEvent(item, &event); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - if (mouseEvent->button() == 0 && mouseEvent->buttons() == 0 && lastMouseGrabberItemHasImplicitMouseGrab) { - // ### This is a temporary fix for until we get proper mouse - // grab events. - clearMouseGrabber(); - return; - } - - QGraphicsItem *item = mouseGrabberItems.last(); - if (item->isBlockedByModalPanel()) - return; - - for (int i = 0x1; i <= 0x10; i <<= 1) { - Qt::MouseButton button = Qt::MouseButton(i); - mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget()))); - mouseEvent->setButtonDownScenePos(button, mouseGrabberButtonDownScenePos.value(button, mouseEvent->scenePos())); - mouseEvent->setButtonDownScreenPos(button, mouseGrabberButtonDownScreenPos.value(button, mouseEvent->screenPos())); - } - mouseEvent->setPos(item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget())); - mouseEvent->setLastPos(item->d_ptr->genericMapFromScene(mouseEvent->lastScenePos(), mouseEvent->widget())); - sendEvent(item, mouseEvent); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent) -{ - Q_Q(QGraphicsScene); - - // Ignore by default, unless we find a mouse grabber that accepts it. - mouseEvent->ignore(); - - // Deliver to any existing mouse grabber. - if (!mouseGrabberItems.isEmpty()) { - if (mouseGrabberItems.last()->isBlockedByModalPanel()) - return; - // The event is ignored by default, but we disregard the event's - // accepted state after delivery; the mouse is grabbed, after all. - sendMouseEvent(mouseEvent); - return; - } - - // Start by determining the number of items at the current position. - // Reuse value from earlier calculations if possible. - if (cachedItemsUnderMouse.isEmpty()) { - cachedItemsUnderMouse = itemsAtPosition(mouseEvent->screenPos(), - mouseEvent->scenePos(), - mouseEvent->widget()); - } - - // Update window activation. - QGraphicsItem *topItem = cachedItemsUnderMouse.value(0); - QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0; - if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) { - // pass activation to the blocking modal window - newActiveWindow = topItem ? topItem->window() : 0; - } - - if (newActiveWindow != q->activeWindow()) - q->setActiveWindow(newActiveWindow); - - // Set focus on the topmost enabled item that can take focus. - bool setFocus = false; - - foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - if (item->isBlockedByModalPanel() - || (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling)) { - // Make sure we don't clear focus. - setFocus = true; - break; - } - if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable))) { - if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { - setFocus = true; - if (item != q->focusItem() && item->d_ptr->mouseSetsFocus) - q->setFocusItem(item, Qt::MouseFocusReason); - break; - } - } - if (item->isPanel()) - break; - if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) - break; - } - - // Check for scene modality. - bool sceneModality = false; - for (int i = 0; i < modalPanels.size(); ++i) { - if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) { - sceneModality = true; - break; - } - } - - // If nobody could take focus, clear it. - if (!stickyFocus && !setFocus && !sceneModality) - q->setFocusItem(0, Qt::MouseFocusReason); - - // Any item will do. - if (sceneModality && cachedItemsUnderMouse.isEmpty()) - cachedItemsUnderMouse << modalPanels.first(); - - // Find a mouse grabber by sending mouse press events to all mouse grabber - // candidates one at a time, until the event is accepted. It's accepted by - // default, so the receiver has to explicitly ignore it for it to pass - // through. - foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - if (!(item->acceptedMouseButtons() & mouseEvent->button())) { - // Skip items that don't accept the event's mouse button. - continue; - } - - // Check if this item is blocked by a modal panel and deliver the mouse event to the - // blocking panel instead of this item if blocked. - (void) item->isBlockedByModalPanel(&item); - - grabMouse(item, /* implicit = */ true); - mouseEvent->accept(); - - // check if the item we are sending to are disabled (before we send the event) - bool disabled = !item->isEnabled(); - bool isPanel = item->isPanel(); - if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick - && item != lastMouseGrabberItem && lastMouseGrabberItem) { - // If this item is different from the item that received the last - // mouse event, and mouseEvent is a doubleclick event, then the - // event is converted to a press. Known limitation: - // Triple-clicking will not generate a doubleclick, though. - QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress); - mousePress.spont = mouseEvent->spont; - mousePress.accept(); - mousePress.setButton(mouseEvent->button()); - mousePress.setButtons(mouseEvent->buttons()); - mousePress.setScreenPos(mouseEvent->screenPos()); - mousePress.setScenePos(mouseEvent->scenePos()); - mousePress.setModifiers(mouseEvent->modifiers()); - mousePress.setWidget(mouseEvent->widget()); - mousePress.setButtonDownPos(mouseEvent->button(), - mouseEvent->buttonDownPos(mouseEvent->button())); - mousePress.setButtonDownScenePos(mouseEvent->button(), - mouseEvent->buttonDownScenePos(mouseEvent->button())); - mousePress.setButtonDownScreenPos(mouseEvent->button(), - mouseEvent->buttonDownScreenPos(mouseEvent->button())); - sendMouseEvent(&mousePress); - mouseEvent->setAccepted(mousePress.isAccepted()); - } else { - sendMouseEvent(mouseEvent); - } - - bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item; - if (disabled) { - ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); - break; - } - if (mouseEvent->isAccepted()) { - if (!mouseGrabberItems.isEmpty()) - storeMouseButtonsForMouseGrabber(mouseEvent); - lastMouseGrabberItem = item; - return; - } - ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); - - // Don't propagate through panels. - if (isPanel) - break; - } - - // Is the event still ignored? Then the mouse press goes to the scene. - // Reset the mouse grabber, clear the selection, clear focus, and leave - // the event ignored so that it can propagate through the originating - // view. - if (!mouseEvent->isAccepted()) { - clearMouseGrabber(); - - QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0; - bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag; - if (!dontClearSelection) { - // Clear the selection if the originating view isn't in scroll - // hand drag mode. The view will clear the selection if no drag - // happened. - q->clearSelection(); - } - } -} - -/*! - \internal - - Ensures that the list of toplevels is sorted by insertion order, and that - the siblingIndexes are packed (no gaps), and start at 0. - - ### This function is almost identical to - QGraphicsItemPrivate::ensureSequentialSiblingIndex(). -*/ -void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes() -{ - if (!topLevelSequentialOrdering) { - qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder); - topLevelSequentialOrdering = true; - needSortTopLevelItems = 1; - } - if (holesInTopLevelSiblingIndex) { - holesInTopLevelSiblingIndex = 0; - for (int i = 0; i < topLevelItems.size(); ++i) - topLevelItems[i]->d_ptr->siblingIndex = i; - } -} - -/*! - \internal - - Set the font and propagate the changes if the font is different from the - current font. -*/ -void QGraphicsScenePrivate::setFont_helper(const QFont &font) -{ - if (this->font == font && this->font.resolve() == font.resolve()) - return; - updateFont(font); -} - -/*! - \internal - - Resolve the scene's font against the application font, and propagate the - changes too all items in the scene. -*/ -void QGraphicsScenePrivate::resolveFont() -{ - QFont naturalFont = QApplication::font(); - naturalFont.resolve(0); - QFont resolvedFont = font.resolve(naturalFont); - updateFont(resolvedFont); -} - -/*! - \internal - - Update the font, and whether or not it has changed, reresolve all fonts in - the scene. -*/ -void QGraphicsScenePrivate::updateFont(const QFont &font) -{ - Q_Q(QGraphicsScene); - - // Update local font setting. - this->font = font; - - // Resolve the fonts of all top-level widget items, or widget items - // whose parent is not a widget. - foreach (QGraphicsItem *item, q->items()) { - if (!item->parentItem()) { - // Resolvefont for an item is a noop operation, but - // every item can be a widget, or can have a widget - // childre. - item->d_ptr->resolveFont(font.resolve()); - } - } - - // Send the scene a FontChange event. - QEvent event(QEvent::FontChange); - QApplication::sendEvent(q, &event); -} - -/*! - \internal - - Set the palette and propagate the changes if the palette is different from - the current palette. -*/ -void QGraphicsScenePrivate::setPalette_helper(const QPalette &palette) -{ - if (this->palette == palette && this->palette.resolve() == palette.resolve()) - return; - updatePalette(palette); -} - -/*! - \internal - - Resolve the scene's palette against the application palette, and propagate - the changes too all items in the scene. -*/ -void QGraphicsScenePrivate::resolvePalette() -{ - QPalette naturalPalette = QApplication::palette(); - naturalPalette.resolve(0); - QPalette resolvedPalette = palette.resolve(naturalPalette); - updatePalette(resolvedPalette); -} - -/*! - \internal - - Update the palette, and whether or not it has changed, reresolve all - palettes in the scene. -*/ -void QGraphicsScenePrivate::updatePalette(const QPalette &palette) -{ - Q_Q(QGraphicsScene); - - // Update local palette setting. - this->palette = palette; - - // Resolve the palettes of all top-level widget items, or widget items - // whose parent is not a widget. - foreach (QGraphicsItem *item, q->items()) { - if (!item->parentItem()) { - // Resolvefont for an item is a noop operation, but - // every item can be a widget, or can have a widget - // childre. - item->d_ptr->resolvePalette(palette.resolve()); - } - } - - // Send the scene a PaletteChange event. - QEvent event(QEvent::PaletteChange); - QApplication::sendEvent(q, &event); -} - -/*! - Constructs a QGraphicsScene object. The \a parent parameter is - passed to QObject's constructor. -*/ -QGraphicsScene::QGraphicsScene(QObject *parent) - : QObject(*new QGraphicsScenePrivate, parent) -{ - d_func()->init(); -} - -/*! - Constructs a QGraphicsScene object, using \a sceneRect for its - scene rectangle. The \a parent parameter is passed to QObject's - constructor. - - \sa sceneRect -*/ -QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent) - : QObject(*new QGraphicsScenePrivate, parent) -{ - d_func()->init(); - setSceneRect(sceneRect); -} - -/*! - Constructs a QGraphicsScene object, using the rectangle specified - by (\a x, \a y), and the given \a width and \a height for its - scene rectangle. The \a parent parameter is passed to QObject's - constructor. - - \sa sceneRect -*/ -QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent) - : QObject(*new QGraphicsScenePrivate, parent) -{ - d_func()->init(); - setSceneRect(x, y, width, height); -} - -/*! - Removes and deletes all items from the scene object - before destroying the scene object. The scene object - is removed from the application's global scene list, - and it is removed from all associated views. -*/ -QGraphicsScene::~QGraphicsScene() -{ - Q_D(QGraphicsScene); - - // Remove this scene from qApp's global scene list. - qApp->d_func()->scene_list.removeAll(this); - - clear(); - - // Remove this scene from all associated views. - for (int j = 0; j < d->views.size(); ++j) - d->views.at(j)->setScene(0); -} - -/*! - \property QGraphicsScene::sceneRect - \brief the scene rectangle; the bounding rectangle of the scene - - The scene rectangle defines the extent of the scene. It is - primarily used by QGraphicsView to determine the view's default - scrollable area, and by QGraphicsScene to manage item indexing. - - If unset, or if set to a null QRectF, sceneRect() will return the largest - bounding rect of all items on the scene since the scene was created (i.e., - a rectangle that grows when items are added to or moved in the scene, but - never shrinks). - - \sa width(), height(), QGraphicsView::sceneRect -*/ -QRectF QGraphicsScene::sceneRect() const -{ - Q_D(const QGraphicsScene); - if (d->hasSceneRect) - return d->sceneRect; - - if (d->dirtyGrowingItemsBoundingRect) { - // Lazily update the growing items bounding rect - QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d); - QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect; - thatd->growingItemsBoundingRect |= itemsBoundingRect(); - thatd->dirtyGrowingItemsBoundingRect = false; - if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) - emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect); - } - return d->growingItemsBoundingRect; -} -void QGraphicsScene::setSceneRect(const QRectF &rect) -{ - Q_D(QGraphicsScene); - if (rect != d->sceneRect) { - d->hasSceneRect = !rect.isNull(); - d->sceneRect = rect; - emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect); - } -} - -/*! - \fn qreal QGraphicsScene::width() const - - This convenience function is equivalent to calling sceneRect().width(). - - \sa height() -*/ - -/*! - \fn qreal QGraphicsScene::height() const - - This convenience function is equivalent to calling \c sceneRect().height(). - - \sa width() -*/ - -/*! - Renders the \a source rect from scene into \a target, using \a painter. This - function is useful for capturing the contents of the scene onto a paint - device, such as a QImage (e.g., to take a screenshot), or for printing - with QPrinter. For example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 1 - - If \a source is a null rect, this function will use sceneRect() to - determine what to render. If \a target is a null rect, the dimensions of \a - painter's paint device will be used. - - The source rect contents will be transformed according to \a - aspectRatioMode to fit into the target rect. By default, the aspect ratio - is kept, and \a source is scaled to fit in \a target. - - \sa QGraphicsView::render() -*/ -void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source, - Qt::AspectRatioMode aspectRatioMode) -{ - // ### Switch to using the recursive rendering algorithm instead. - - // Default source rect = scene rect - QRectF sourceRect = source; - if (sourceRect.isNull()) - sourceRect = sceneRect(); - - // Default target rect = device rect - QRectF targetRect = target; - if (targetRect.isNull()) { - if (painter->device()->devType() == QInternal::Picture) - targetRect = sourceRect; - else - targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height()); - } - - // Find the ideal x / y scaling ratio to fit \a source into \a target. - qreal xratio = targetRect.width() / sourceRect.width(); - qreal yratio = targetRect.height() / sourceRect.height(); - - // Scale according to the aspect ratio mode. - switch (aspectRatioMode) { - case Qt::KeepAspectRatio: - xratio = yratio = qMin(xratio, yratio); - break; - case Qt::KeepAspectRatioByExpanding: - xratio = yratio = qMax(xratio, yratio); - break; - case Qt::IgnoreAspectRatio: - break; - } - - // Find all items to draw, and reverse the list (we want to draw - // in reverse order). - QList<QGraphicsItem *> itemList = items(sourceRect, Qt::IntersectsItemBoundingRect); - QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()]; - int numItems = itemList.size(); - for (int i = 0; i < numItems; ++i) - itemArray[numItems - i - 1] = itemList.at(i); - itemList.clear(); - - painter->save(); - - // Transform the painter. - painter->setClipRect(targetRect, Qt::IntersectClip); - QTransform painterTransform; - painterTransform *= QTransform() - .translate(targetRect.left(), targetRect.top()) - .scale(xratio, yratio) - .translate(-sourceRect.left(), -sourceRect.top()); - painter->setWorldTransform(painterTransform, true); - - // Two unit vectors. - QLineF v1(0, 0, 1, 0); - QLineF v2(0, 0, 0, 1); - - // Generate the style options - QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems]; - for (int i = 0; i < numItems; ++i) - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect()); - - // Render the scene. - drawBackground(painter, sourceRect); - drawItems(painter, numItems, itemArray, styleOptionArray); - drawForeground(painter, sourceRect); - - delete [] itemArray; - delete [] styleOptionArray; - - painter->restore(); -} - -/*! - \property QGraphicsScene::itemIndexMethod - \brief the item indexing method. - - QGraphicsScene applies an indexing algorithm to the scene, to speed up - item discovery functions like items() and itemAt(). Indexing is most - efficient for static scenes (i.e., where items don't move around). For - dynamic scenes, or scenes with many animated items, the index bookkeeping - can outweight the fast lookup speeds. - - For the common case, the default index method BspTreeIndex works fine. If - your scene uses many animations and you are experiencing slowness, you can - disable indexing by calling \c setItemIndexMethod(NoIndex). - - \sa bspTreeDepth -*/ -QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const -{ - Q_D(const QGraphicsScene); - return d->indexMethod; -} -void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) -{ - Q_D(QGraphicsScene); - if (d->indexMethod == method) - return; - - d->indexMethod = method; - - QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder); - delete d->index; - if (method == BspTreeIndex) - d->index = new QGraphicsSceneBspTreeIndex(this); - else - d->index = new QGraphicsSceneLinearIndex(this); - for (int i = oldItems.size() - 1; i >= 0; --i) - d->index->addItem(oldItems.at(i)); -} - -/*! - \property QGraphicsScene::bspTreeDepth - \brief the depth of QGraphicsScene's BSP index tree - \since 4.3 - - This property has no effect when NoIndex is used. - - This value determines the depth of QGraphicsScene's BSP tree. The depth - directly affects QGraphicsScene's performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, QGraphicsScene can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as QGraphicsScene retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 2 - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - - \sa itemIndexMethod -*/ -int QGraphicsScene::bspTreeDepth() const -{ - Q_D(const QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index); - return bspTree ? bspTree->bspTreeDepth() : 0; -} -void QGraphicsScene::setBspTreeDepth(int depth) -{ - Q_D(QGraphicsScene); - if (depth < 0) { - qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth); - return; - } - - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index); - if (!bspTree) { - qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); - return; - } - bspTree->setBspTreeDepth(depth); -} - -/*! - \property QGraphicsScene::sortCacheEnabled - \brief whether sort caching is enabled - \since 4.5 - \obsolete - - Since Qt 4.6, this property has no effect. -*/ -bool QGraphicsScene::isSortCacheEnabled() const -{ - Q_D(const QGraphicsScene); - return d->sortCacheEnabled; -} -void QGraphicsScene::setSortCacheEnabled(bool enabled) -{ - Q_D(QGraphicsScene); - if (d->sortCacheEnabled == enabled) - return; - d->sortCacheEnabled = enabled; -} - -/*! - Calculates and returns the bounding rect of all items on the scene. This - function works by iterating over all items, and because if this, it can - be slow for large scenes. - - \sa sceneRect() -*/ -QRectF QGraphicsScene::itemsBoundingRect() const -{ - // Does not take untransformable items into account. - QRectF boundingRect; - foreach (QGraphicsItem *item, items()) - boundingRect |= item->sceneBoundingRect(); - return boundingRect; -} - -/*! - Returns a list of all items in the scene in descending stacking order. - - \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items() const -{ - Q_D(const QGraphicsScene); - return d->index->items(Qt::DescendingOrder); -} - -/*! - Returns an ordered list of all items on the scene. \a order decides the - stacking order. - - \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const -{ - Q_D(const QGraphicsScene); - return d->index->items(order); -} - -/*! - \obsolete - - Returns all visible items at position \a pos in the scene. The items are - listed in descending stacking order (i.e., the first item in the list is the - top-most item, and the last item is the bottom-most item). - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const -{ - Q_D(const QGraphicsScene); - return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder); -} - -/*! - \overload - \obsolete - - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a rectangle. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rectangle are returned. - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsScene); - return d->index->items(rectangle, mode, Qt::DescendingOrder); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const - \obsolete - \since 4.3 - - This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode). - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. -*/ - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload - \since 4.6 - - \brief Returns all visible items that, depending on \a mode, are - either inside or intersect with the rectangle defined by \a x, \a y, - \a w and \a h, in a list sorted using \a order. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. -*/ - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const - \overload - \obsolete - - Returns all visible items that, depending on \a mode, are either inside or - intersect with the polygon \a polygon. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a polygon are returned. - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsScene); - return d->index->items(polygon, mode, Qt::DescendingOrder); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const - \overload - \obsolete - - Returns all visible items that, depending on \a path, are either inside or - intersect with the path \a path. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsScene); - return d->index->items(path, mode, Qt::DescendingOrder); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - \since 4.6 - - \brief Returns all visible items that, depending on \a mode, are at - the specified \a pos in a list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with \a pos are returned. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsScene); - return d->index->items(pos, mode, order, deviceTransform); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload - \since 4.6 - - \brief Returns all visible items that, depending on \a mode, are - either inside or intersect with the specified \a rect and return a - list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rect are returned. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsScene); - return d->index->items(rect, mode, order, deviceTransform); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload - \since 4.6 - - \brief Returns all visible items that, depending on \a mode, are - either inside or intersect with the specified \a polygon and return - a list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a polygon are returned. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsScene); - return d->index->items(polygon, mode, order, deviceTransform); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload - \since 4.6 - - \brief Returns all visible items that, depending on \a mode, are - either inside or intersect with the specified \a path and return a - list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsScene); - return d->index->items(path, mode, order, deviceTransform); -} - -/*! - Returns a list of all items that collide with \a item. Collisions are - determined by calling QGraphicsItem::collidesWithItem(); the collision - detection is determined by \a mode. By default, all items whose shape - intersects \a item or is contained inside \a item's shape are returned. - - The items are returned in descending stacking order (i.e., the first item - in the list is the uppermost item, and the last item is the lowermost - item). - - \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item, - Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsScene); - if (!item) { - qWarning("QGraphicsScene::collidingItems: cannot find collisions for null item"); - return QList<QGraphicsItem *>(); - } - - // Does not support ItemIgnoresTransformations. - QList<QGraphicsItem *> tmp; - foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder)) { - if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) - tmp << itemInVicinity; - } - return tmp; -} - -/*! - \overload - \obsolete - - Returns the topmost visible item at the specified \a position, or 0 if - there are no items at this position. - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. - - \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting} -*/ -QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const -{ - QList<QGraphicsItem *> itemsAtPoint = items(position); - return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); -} - -/*! - \since 4.6 - - Returns the topmost visible item at the specified \a position, or 0 - if there are no items at this position. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting} -*/ -QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const -{ - QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape, - Qt::DescendingOrder, deviceTransform); - return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); -} - -/*! - \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const - \overload - \since 4.6 - - Returns the topmost item at the position specified by (\a x, \a - y), or 0 if there are no items at this position. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - This convenience function is equivalent to calling \c - {itemAt(QPointF(x, y), deviceTransform)}. -*/ - -/*! - \fn QGraphicsScene::itemAt(qreal x, qreal y) const - \overload - \obsolete - - Returns the topmost item at the position specified by (\a x, \a - y), or 0 if there are no items at this position. - - This convenience function is equivalent to calling \c - {itemAt(QPointF(x, y))}. - - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. -*/ - -/*! - Returns a list of all currently selected items. The items are - returned in no particular order. - - \sa setSelectionArea() -*/ -QList<QGraphicsItem *> QGraphicsScene::selectedItems() const -{ - Q_D(const QGraphicsScene); - - // Optimization: Lazily removes items that are not selected. - QGraphicsScene *that = const_cast<QGraphicsScene *>(this); - QSet<QGraphicsItem *> actuallySelectedSet; - foreach (QGraphicsItem *item, that->d_func()->selectedItems) { - if (item->isSelected()) - actuallySelectedSet << item; - } - - that->d_func()->selectedItems = actuallySelectedSet; - - return d->selectedItems.values(); -} - -/*! - Returns the selection area that was previously set with - setSelectionArea(), or an empty QPainterPath if no selection area has been - set. - - \sa setSelectionArea() -*/ -QPainterPath QGraphicsScene::selectionArea() const -{ - Q_D(const QGraphicsScene); - return d->selectionArea; -} - -/*! - \since 4.6 - - Sets the selection area to \a path. All items within this area are - immediately selected, and all items outside are unselected. You can get - the list of all selected items by calling selectedItems(). - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - For an item to be selected, it must be marked as \e selectable - (QGraphicsItem::ItemIsSelectable). - - \sa clearSelection(), selectionArea() -*/ -void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform) -{ - setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform); -} - -/*! - \obsolete - \overload - - Sets the selection area to \a path. - - This function is deprecated and leads to incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. -*/ -void QGraphicsScene::setSelectionArea(const QPainterPath &path) -{ - setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); -} - -/*! - \obsolete - \overload - \since 4.3 - - Sets the selection area to \a path using \a mode to determine if items are - included in the selection area. - - \sa clearSelection(), selectionArea() -*/ -void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode) -{ - setSelectionArea(path, mode, QTransform()); -} - -/*! - \overload - \since 4.6 - - Sets the selection area to \a path using \a mode to determine if items are - included in the selection area. - - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. - - \sa clearSelection(), selectionArea() -*/ -void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, - const QTransform &deviceTransform) -{ - Q_D(QGraphicsScene); - - // Note: with boolean path operations, we can improve performance here - // quite a lot by "growing" the old path instead of replacing it. That - // allows us to only check the intersect area for changes, instead of - // reevaluating the whole path over again. - d->selectionArea = path; - - QSet<QGraphicsItem *> unselectItems = d->selectedItems; - - // Disable emitting selectionChanged() for individual items. - ++d->selectionChanging; - bool changed = false; - - // Set all items in path to selected. - foreach (QGraphicsItem *item, items(path, mode, Qt::DescendingOrder, deviceTransform)) { - if (item->flags() & QGraphicsItem::ItemIsSelectable) { - if (!item->isSelected()) - changed = true; - unselectItems.remove(item); - item->setSelected(true); - } - } - - // Unselect all items outside path. - foreach (QGraphicsItem *item, unselectItems) { - item->setSelected(false); - changed = true; - } - - // Reenable emitting selectionChanged() for individual items. - --d->selectionChanging; - - if (!d->selectionChanging && changed) - emit selectionChanged(); -} - -/*! - Clears the current selection. - - \sa setSelectionArea(), selectedItems() -*/ -void QGraphicsScene::clearSelection() -{ - Q_D(QGraphicsScene); - - // Disable emitting selectionChanged - ++d->selectionChanging; - bool changed = !d->selectedItems.isEmpty(); - - foreach (QGraphicsItem *item, d->selectedItems) - item->setSelected(false); - d->selectedItems.clear(); - - // Reenable emitting selectionChanged() for individual items. - --d->selectionChanging; - - if (!d->selectionChanging && changed) - emit selectionChanged(); -} - -/*! - \since 4.4 - - Removes and deletes all items from the scene, but otherwise leaves the - state of the scene unchanged. - - \sa addItem() -*/ -void QGraphicsScene::clear() -{ - Q_D(QGraphicsScene); - // NB! We have to clear the index before deleting items; otherwise the - // index might try to access dangling item pointers. - d->index->clear(); - // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items - while (!d->topLevelItems.isEmpty()) - delete d->topLevelItems.first(); - Q_ASSERT(d->topLevelItems.isEmpty()); - d->lastItemCount = 0; - d->allItemsIgnoreHoverEvents = true; - d->allItemsUseDefaultCursor = true; - d->allItemsIgnoreTouchEvents = true; -} - -/*! - Groups all items in \a items into a new QGraphicsItemGroup, and returns a - pointer to the group. The group is created with the common ancestor of \a - items as its parent, and with position (0, 0). The items are all - reparented to the group, and their positions and transformations are - mapped to the group. If \a items is empty, this function will return an - empty top-level QGraphicsItemGroup. - - QGraphicsScene has ownership of the group item; you do not need to delete - it. To dismantle (ungroup) a group, call destroyItemGroup(). - - \sa destroyItemGroup(), QGraphicsItemGroup::addToGroup() -*/ -QGraphicsItemGroup *QGraphicsScene::createItemGroup(const QList<QGraphicsItem *> &items) -{ - // Build a list of the first item's ancestors - QList<QGraphicsItem *> ancestors; - int n = 0; - if (!items.isEmpty()) { - QGraphicsItem *parent = items.at(n++); - while ((parent = parent->parentItem())) - ancestors.append(parent); - } - - // Find the common ancestor for all items - QGraphicsItem *commonAncestor = 0; - if (!ancestors.isEmpty()) { - while (n < items.size()) { - int commonIndex = -1; - QGraphicsItem *parent = items.at(n++); - do { - int index = ancestors.indexOf(parent, qMax(0, commonIndex)); - if (index != -1) { - commonIndex = index; - break; - } - } while ((parent = parent->parentItem())); - - if (commonIndex == -1) { - commonAncestor = 0; - break; - } - - commonAncestor = ancestors.at(commonIndex); - } - } - - // Create a new group at that level - QGraphicsItemGroup *group = new QGraphicsItemGroup(commonAncestor); - if (!commonAncestor) - addItem(group); - foreach (QGraphicsItem *item, items) - group->addToGroup(item); - return group; -} - -/*! - Reparents all items in \a group to \a group's parent item, then removes \a - group from the scene, and finally deletes it. The items' positions and - transformations are mapped from the group to the group's parent. - - \sa createItemGroup(), QGraphicsItemGroup::removeFromGroup() -*/ -void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group) -{ - foreach (QGraphicsItem *item, group->children()) - group->removeFromGroup(item); - removeItem(group); - delete group; -} - -/*! - Adds or moves the \a item and all its childen to this scene. - This scene takes ownership of the \a item. - - If the item is visible (i.e., QGraphicsItem::isVisible() returns - true), QGraphicsScene will emit changed() once control goes back - to the event loop. - - If the item is already in a different scene, it will first be - removed from its old scene, and then added to this scene as a - top-level. - - QGraphicsScene will send ItemSceneChange notifications to \a item - while it is added to the scene. If item does not currently belong - to a scene, only one notification is sent. If it does belong to - scene already (i.e., it is moved to this scene), QGraphicsScene - will send an addition notification as the item is removed from its - previous scene. - - If the item is a panel, the scene is active, and there is no - active panel in the scene, then the item will be activated. - - \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(), - addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting} -*/ -void QGraphicsScene::addItem(QGraphicsItem *item) -{ - Q_D(QGraphicsScene); - if (!item) { - qWarning("QGraphicsScene::addItem: cannot add null item"); - return; - } - if (item->d_ptr->scene == this) { - qWarning("QGraphicsScene::addItem: item has already been added to this scene"); - return; - } - // Remove this item from its existing scene - if (QGraphicsScene *oldScene = item->d_ptr->scene) - oldScene->removeItem(item); - - // Notify the item that its scene is changing, and allow the item to - // react. - const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - QVariant::fromValue<QGraphicsScene *>(this))); - QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); - if (targetScene != this) { - if (targetScene && item->d_ptr->scene != targetScene) - targetScene->addItem(item); - return; - } - - // QDeclarativeItems do not rely on initial itemChanged message, as the componentComplete - // function allows far more opportunity for delayed-construction optimization. - if (!item->d_ptr->isDeclarativeItem) { - if (d->unpolishedItems.isEmpty()) { - QMetaMethod method = metaObject()->method(d->polishItemsIndex); - method.invoke(this, Qt::QueuedConnection); - } - d->unpolishedItems.append(item); - item->d_ptr->pendingPolish = true; - } - - // Detach this item from its parent if the parent's scene is different - // from this scene. - if (QGraphicsItem *itemParent = item->d_ptr->parent) { - if (itemParent->d_ptr->scene != this) - item->setParentItem(0); - } - - // Add the item to this scene - item->d_func()->scene = targetScene; - - // Add the item in the index - d->index->addItem(item); - - // Add to list of toplevels if this item is a toplevel. - if (!item->d_ptr->parent) - d->registerTopLevelItem(item); - - // Add to list of items that require an update. We cannot assume that the - // item is fully constructed, so calling item->update() can lead to a pure - // virtual function call to boundingRect(). - d->markDirty(item); - d->dirtyGrowingItemsBoundingRect = true; - - // Disable selectionChanged() for individual items - ++d->selectionChanging; - int oldSelectedItemSize = d->selectedItems.size(); - - // Enable mouse tracking if the item accepts hover events or has a cursor set. - if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) { - d->allItemsIgnoreHoverEvents = false; - d->enableMouseTrackingOnViews(); - } -#ifndef QT_NO_CURSOR - if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) { - d->allItemsUseDefaultCursor = false; - if (d->allItemsIgnoreHoverEvents) // already enabled otherwise - d->enableMouseTrackingOnViews(); - } -#endif //QT_NO_CURSOR - - // Enable touch events if the item accepts touch events. - if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) { - d->allItemsIgnoreTouchEvents = false; - d->enableTouchEventsOnViews(); - } - -#ifndef QT_NO_GESTURES - foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) - d->grabGesture(item, gesture); -#endif - - // Update selection lists - if (item->isSelected()) - d->selectedItems << item; - if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup) - d->addPopup(static_cast<QGraphicsWidget *>(item)); - if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) - d->enterModal(item); - - // Update creation order focus chain. Make sure to leave the widget's - // internal tab order intact. - if (item->isWidget()) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); - if (!d->tabFocusFirst) { - // No first tab focus widget - make this the first tab focus - // widget. - d->tabFocusFirst = widget; - } else if (!widget->parentWidget()) { - // Adding a widget that is not part of a tab focus chain. - QGraphicsWidget *last = d->tabFocusFirst->d_func()->focusPrev; - QGraphicsWidget *lastNew = widget->d_func()->focusPrev; - last->d_func()->focusNext = widget; - widget->d_func()->focusPrev = last; - d->tabFocusFirst->d_func()->focusPrev = lastNew; - lastNew->d_func()->focusNext = d->tabFocusFirst; - } - } - - // Add all children recursively - item->d_ptr->ensureSortedChildren(); - for (int i = 0; i < item->d_ptr->children.size(); ++i) - addItem(item->d_ptr->children.at(i)); - - // Resolve font and palette. - item->d_ptr->resolveFont(d->font.resolve()); - item->d_ptr->resolvePalette(d->palette.resolve()); - - - // Reenable selectionChanged() for individual items - --d->selectionChanging; - if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize) - emit selectionChanged(); - - // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); - - // Update explicit activation - bool autoActivate = true; - if (!d->childExplicitActivation && item->d_ptr->explicitActivate) - d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2; - if (d->childExplicitActivation && item->isPanel()) { - if (d->childExplicitActivation == 1) - setActivePanel(item); - else - autoActivate = false; - d->childExplicitActivation = 0; - } else if (!item->d_ptr->parent) { - d->childExplicitActivation = 0; - } - - // Auto-activate this item's panel if nothing else has been activated - if (autoActivate) { - if (!d->lastActivePanel && !d->activePanel && item->isPanel()) { - if (isActive()) - setActivePanel(item); - else - d->lastActivePanel = item; - } - } - - if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges) - d->registerScenePosItem(item); - - // Ensure that newly added items that have subfocus set, gain - // focus automatically if there isn't a focus item already. - if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item) - item->focusItem()->setFocus(); - - d->updateInputMethodSensitivityInViews(); -} - -/*! - Creates and adds an ellipse item to the scene, and returns the item - pointer. The geometry of the ellipse is defined by \a rect, and its pen - and brush are initialized to \a pen and \a brush. - - Note that the item's geometry is provided in item coordinates, and its - position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addLine(), addPath(), addPixmap(), addRect(), addText(), addItem(), - addWidget() -*/ -QGraphicsEllipseItem *QGraphicsScene::addEllipse(const QRectF &rect, const QPen &pen, const QBrush &brush) -{ - QGraphicsEllipseItem *item = new QGraphicsEllipseItem(rect); - item->setPen(pen); - item->setBrush(brush); - addItem(item); - return item; -} - -/*! - \fn QGraphicsEllipseItem *QGraphicsScene::addEllipse(qreal x, qreal y, qreal w, qreal h, const QPen &pen, const QBrush &brush) - \since 4.3 - - This convenience function is equivalent to calling addEllipse(QRectF(\a x, - \a y, \a w, \a h), \a pen, \a brush). -*/ - -/*! - Creates and adds a line item to the scene, and returns the item - pointer. The geometry of the line is defined by \a line, and its pen - is initialized to \a pen. - - Note that the item's geometry is provided in item coordinates, and its - position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addPath(), addPixmap(), addRect(), addText(), addItem(), - addWidget() -*/ -QGraphicsLineItem *QGraphicsScene::addLine(const QLineF &line, const QPen &pen) -{ - QGraphicsLineItem *item = new QGraphicsLineItem(line); - item->setPen(pen); - addItem(item); - return item; -} - -/*! - \fn QGraphicsLineItem *QGraphicsScene::addLine(qreal x1, qreal y1, qreal x2, qreal y2, const QPen &pen) - \since 4.3 - - This convenience function is equivalent to calling addLine(QLineF(\a x1, - \a y1, \a x2, \a y2), \a pen). -*/ - -/*! - Creates and adds a path item to the scene, and returns the item - pointer. The geometry of the path is defined by \a path, and its pen and - brush are initialized to \a pen and \a brush. - - Note that the item's geometry is provided in item coordinates, and its - position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addLine(), addPixmap(), addRect(), addText(), addItem(), - addWidget() -*/ -QGraphicsPathItem *QGraphicsScene::addPath(const QPainterPath &path, const QPen &pen, const QBrush &brush) -{ - QGraphicsPathItem *item = new QGraphicsPathItem(path); - item->setPen(pen); - item->setBrush(brush); - addItem(item); - return item; -} - -/*! - Creates and adds a pixmap item to the scene, and returns the item - pointer. The pixmap is defined by \a pixmap. - - Note that the item's geometry is provided in item coordinates, and its - position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addLine(), addPath(), addRect(), addText(), addItem(), - addWidget() -*/ -QGraphicsPixmapItem *QGraphicsScene::addPixmap(const QPixmap &pixmap) -{ - QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); - addItem(item); - return item; -} - -/*! - Creates and adds a polygon item to the scene, and returns the item - pointer. The polygon is defined by \a polygon, and its pen and - brush are initialized to \a pen and \a brush. - - Note that the item's geometry is provided in item coordinates, and its - position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addLine(), addPath(), addRect(), addText(), addItem(), - addWidget() -*/ -QGraphicsPolygonItem *QGraphicsScene::addPolygon(const QPolygonF &polygon, - const QPen &pen, const QBrush &brush) -{ - QGraphicsPolygonItem *item = new QGraphicsPolygonItem(polygon); - item->setPen(pen); - item->setBrush(brush); - addItem(item); - return item; -} - -/*! - Creates and adds a rectangle item to the scene, and returns the item - pointer. The geometry of the rectangle is defined by \a rect, and its pen - and brush are initialized to \a pen and \a brush. - - Note that the item's geometry is provided in item coordinates, and its - position is initialized to (0, 0). For example, if a QRect(50, 50, 100, - 100) is added, its top-left corner will be at (50, 50) relative to the - origin in the items coordinate system. - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addText(), - addItem(), addWidget() -*/ -QGraphicsRectItem *QGraphicsScene::addRect(const QRectF &rect, const QPen &pen, const QBrush &brush) -{ - QGraphicsRectItem *item = new QGraphicsRectItem(rect); - item->setPen(pen); - item->setBrush(brush); - addItem(item); - return item; -} - -/*! - \fn QGraphicsRectItem *QGraphicsScene::addRect(qreal x, qreal y, qreal w, qreal h, const QPen &pen, const QBrush &brush) - \since 4.3 - - This convenience function is equivalent to calling addRect(QRectF(\a x, - \a y, \a w, \a h), \a pen, \a brush). -*/ - -/*! - Creates and adds a text item to the scene, and returns the item - pointer. The text string is initialized to \a text, and its font - is initialized to \a font. - - The item's position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(), - addItem(), addWidget() -*/ -QGraphicsTextItem *QGraphicsScene::addText(const QString &text, const QFont &font) -{ - QGraphicsTextItem *item = new QGraphicsTextItem(text); - item->setFont(font); - addItem(item); - return item; -} - -/*! - Creates and adds a QGraphicsSimpleTextItem to the scene, and returns the - item pointer. The text string is initialized to \a text, and its font is - initialized to \a font. - - The item's position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(), - addItem(), addWidget() -*/ -QGraphicsSimpleTextItem *QGraphicsScene::addSimpleText(const QString &text, const QFont &font) -{ - QGraphicsSimpleTextItem *item = new QGraphicsSimpleTextItem(text); - item->setFont(font); - addItem(item); - return item; -} - -/*! - Creates a new QGraphicsProxyWidget for \a widget, adds it to the scene, - and returns a pointer to the proxy. \a wFlags set the default window flags - for the embedding proxy widget. - - The item's position is initialized to (0, 0). - - If the item is visible (i.e., QGraphicsItem::isVisible() returns true), - QGraphicsScene will emit changed() once control goes back to the event - loop. - - Note that widgets with the Qt::WA_PaintOnScreen widget attribute - set and widgets that wrap an external application or controller - are not supported. Examples are QGLWidget and QAxWidget. - - \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(), - addText(), addSimpleText(), addItem() -*/ -QGraphicsProxyWidget *QGraphicsScene::addWidget(QWidget *widget, Qt::WindowFlags wFlags) -{ - QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(0, wFlags); - proxy->setWidget(widget); - addItem(proxy); - return proxy; -} - -/*! - Removes the item \a item and all its children from the scene. The - ownership of \a item is passed on to the caller (i.e., - QGraphicsScene will no longer delete \a item when destroyed). - - \sa addItem() -*/ -void QGraphicsScene::removeItem(QGraphicsItem *item) -{ - // ### Refactoring: This function shares much functionality with _q_removeItemLater() - Q_D(QGraphicsScene); - if (!item) { - qWarning("QGraphicsScene::removeItem: cannot remove 0-item"); - return; - } - if (item->scene() != this) { - qWarning("QGraphicsScene::removeItem: item %p's scene (%p)" - " is different from this scene (%p)", - item, item->scene(), this); - return; - } - - // Notify the item that it's scene is changing to 0, allowing the item to - // react. - const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - QVariant::fromValue<QGraphicsScene *>(0))); - QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); - if (targetScene != 0 && targetScene != this) { - targetScene->addItem(item); - return; - } - - d->removeItemHelper(item); - - // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); - - d->updateInputMethodSensitivityInViews(); -} - -/*! - When the scene is active, this functions returns the scene's current focus - item, or 0 if no item currently has focus. When the scene is inactive, this - functions returns the item that will gain input focus when the scene becomes - active. - - The focus item receives keyboard input when the scene receives a - key event. - - \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive() -*/ -QGraphicsItem *QGraphicsScene::focusItem() const -{ - Q_D(const QGraphicsScene); - return isActive() ? d->focusItem : d->passiveFocusItem; -} - -/*! - Sets the scene's focus item to \a item, with the focus reason \a - focusReason, after removing focus from any previous item that may have had - focus. - - If \a item is 0, or if it either does not accept focus (i.e., it does not - have the QGraphicsItem::ItemIsFocusable flag enabled), or is not visible - or not enabled, this function only removes focus from any previous - focusitem. - - If item is not 0, and the scene does not currently have focus (i.e., - hasFocus() returns false), this function will call setFocus() - automatically. - - \sa focusItem(), hasFocus(), setFocus() -*/ -void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason) -{ - Q_D(QGraphicsScene); - if (item) - item->setFocus(focusReason); - else - d->setFocusItemHelper(item, focusReason); -} - -/*! - Returns true if the scene has focus; otherwise returns false. If the scene - has focus, it will will forward key events from QKeyEvent to any item that - has focus. - - \sa setFocus(), setFocusItem() -*/ -bool QGraphicsScene::hasFocus() const -{ - Q_D(const QGraphicsScene); - return d->hasFocus; -} - -/*! - Sets focus on the scene by sending a QFocusEvent to the scene, passing \a - focusReason as the reason. If the scene regains focus after having - previously lost it while an item had focus, the last focus item will - receive focus with \a focusReason as the reason. - - If the scene already has focus, this function does nothing. - - \sa hasFocus(), clearFocus(), setFocusItem() -*/ -void QGraphicsScene::setFocus(Qt::FocusReason focusReason) -{ - Q_D(QGraphicsScene); - if (d->hasFocus || !isActive()) - return; - QFocusEvent event(QEvent::FocusIn, focusReason); - QCoreApplication::sendEvent(this, &event); -} - -/*! - Clears focus from the scene. If any item has focus when this function is - called, it will lose focus, and regain focus again once the scene regains - focus. - - A scene that does not have focus ignores key events. - - \sa hasFocus(), setFocus(), setFocusItem() -*/ -void QGraphicsScene::clearFocus() -{ - Q_D(QGraphicsScene); - if (d->hasFocus) { - d->hasFocus = false; - d->passiveFocusItem = d->focusItem; - setFocusItem(0, Qt::OtherFocusReason); - } -} - -/*! - \property QGraphicsScene::stickyFocus - \brief whether clicking into the scene background will clear focus - - \since 4.6 - - In a QGraphicsScene with stickyFocus set to true, focus will remain - unchanged when the user clicks into the scene background or on an item - that does not accept focus. Otherwise, focus will be cleared. - - By default, this property is false. - - Focus changes in response to a mouse press. You can reimplement - mousePressEvent() in a subclass of QGraphicsScene to toggle this property - based on where the user has clicked. - - \sa clearFocus(), setFocusItem() -*/ -void QGraphicsScene::setStickyFocus(bool enabled) -{ - Q_D(QGraphicsScene); - d->stickyFocus = enabled; -} -bool QGraphicsScene::stickyFocus() const -{ - Q_D(const QGraphicsScene); - return d->stickyFocus; -} - -/*! - Returns the current mouse grabber item, or 0 if no item is currently - grabbing the mouse. The mouse grabber item is the item that receives all - mouse events sent to the scene. - - An item becomes a mouse grabber when it receives and accepts a - mouse press event, and it stays the mouse grabber until either of - the following events occur: - - \list - \o If the item receives a mouse release event when there are no other - buttons pressed, it loses the mouse grab. - \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false)}), - or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false)}), - it loses the mouse grab. - \o If the item is removed from the scene, it loses the mouse grab. - \endlist - - If the item loses its mouse grab, the scene will ignore all mouse events - until a new item grabs the mouse (i.e., until a new item receives a mouse - press event). -*/ -QGraphicsItem *QGraphicsScene::mouseGrabberItem() const -{ - Q_D(const QGraphicsScene); - return !d->mouseGrabberItems.isEmpty() ? d->mouseGrabberItems.last() : 0; -} - -/*! - \property QGraphicsScene::backgroundBrush - \brief the background brush of the scene. - - Set this property to changes the scene's background to a different color, - gradient or texture. The default background brush is Qt::NoBrush. The - background is drawn before (behind) the items. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 3 - - QGraphicsScene::render() calls drawBackground() to draw the scene - background. For more detailed control over how the background is drawn, - you can reimplement drawBackground() in a subclass of QGraphicsScene. -*/ -QBrush QGraphicsScene::backgroundBrush() const -{ - Q_D(const QGraphicsScene); - return d->backgroundBrush; -} -void QGraphicsScene::setBackgroundBrush(const QBrush &brush) -{ - Q_D(QGraphicsScene); - d->backgroundBrush = brush; - foreach (QGraphicsView *view, d->views) { - view->resetCachedContent(); - view->viewport()->update(); - } - update(); -} - -/*! - \property QGraphicsScene::foregroundBrush - \brief the foreground brush of the scene. - - Change this property to set the scene's foreground to a different - color, gradient or texture. - - The foreground is drawn after (on top of) the items. The default - foreground brush is Qt::NoBrush ( i.e. the foreground is not - drawn). - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 4 - - QGraphicsScene::render() calls drawForeground() to draw the scene - foreground. For more detailed control over how the foreground is - drawn, you can reimplement the drawForeground() function in a - QGraphicsScene subclass. -*/ -QBrush QGraphicsScene::foregroundBrush() const -{ - Q_D(const QGraphicsScene); - return d->foregroundBrush; -} -void QGraphicsScene::setForegroundBrush(const QBrush &brush) -{ - Q_D(QGraphicsScene); - d->foregroundBrush = brush; - foreach (QGraphicsView *view, views()) - view->viewport()->update(); - update(); -} - -/*! - This method is used by input methods to query a set of properties of - the scene to be able to support complex input method operations as support - for surrounding text and reconversions. - - The \a query parameter specifies which property is queried. - - \sa QWidget::inputMethodQuery() -*/ -QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const -{ - Q_D(const QGraphicsScene); - if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) - return QVariant(); - const QTransform matrix = d->focusItem->sceneTransform(); - QVariant value = d->focusItem->inputMethodQuery(query); - if (value.type() == QVariant::RectF) - value = matrix.mapRect(value.toRectF()); - else if (value.type() == QVariant::PointF) - value = matrix.map(value.toPointF()); - else if (value.type() == QVariant::Rect) - value = matrix.mapRect(value.toRect()); - else if (value.type() == QVariant::Point) - value = matrix.map(value.toPoint()); - return value; -} - -/*! - \fn void QGraphicsScene::update(const QRectF &rect) - Schedules a redraw of the area \a rect on the scene. - - \sa sceneRect(), changed() -*/ -void QGraphicsScene::update(const QRectF &rect) -{ - Q_D(QGraphicsScene); - if (d->updateAll || (rect.isEmpty() && !rect.isNull())) - return; - - // Check if anyone's connected; if not, we can send updates directly to - // the views. Otherwise or if there are no views, use old behavior. - bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty(); - if (rect.isNull()) { - d->updateAll = true; - d->updatedRects.clear(); - if (directUpdates) { - // Update all views. - for (int i = 0; i < d->views.size(); ++i) - d->views.at(i)->d_func()->fullUpdatePending = true; - } - } else { - if (directUpdates) { - // Update all views. - for (int i = 0; i < d->views.size(); ++i) { - QGraphicsView *view = d->views.at(i); - if (view->isTransformed()) - view->d_func()->updateRectF(view->viewportTransform().mapRect(rect)); - else - view->d_func()->updateRectF(rect); - } - } else { - d->updatedRects << rect; - } - } - - if (!d->calledEmitUpdated) { - d->calledEmitUpdated = true; - QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection); - } -} - -/*! - \fn void QGraphicsScene::update(qreal x, qreal y, qreal w, qreal h) - \overload - \since 4.3 - - This function is equivalent to calling update(QRectF(\a x, \a y, \a w, - \a h)); -*/ - -/*! - Invalidates and schedules a redraw of the \a layers in \a rect on the - scene. Any cached content in \a layers is unconditionally invalidated and - redrawn. - - You can use this function overload to notify QGraphicsScene of changes to - the background or the foreground of the scene. This function is commonly - used for scenes with tile-based backgrounds to notify changes when - QGraphicsView has enabled - \l{QGraphicsView::CacheBackground}{CacheBackground}. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 5 - - Note that QGraphicsView currently supports background caching only (see - QGraphicsView::CacheBackground). This function is equivalent to calling - update() if any layer but BackgroundLayer is passed. - - \sa QGraphicsView::resetCachedContent() -*/ -void QGraphicsScene::invalidate(const QRectF &rect, SceneLayers layers) -{ - foreach (QGraphicsView *view, views()) - view->invalidateScene(rect, layers); - update(rect); -} - -/*! - \fn void QGraphicsScene::invalidate(qreal x, qreal y, qreal w, qreal h, SceneLayers layers) - \overload - \since 4.3 - - This convenience function is equivalent to calling invalidate(QRectF(\a x, \a - y, \a w, \a h), \a layers); -*/ - -/*! - Returns a list of all the views that display this scene. - - \sa QGraphicsView::scene() -*/ -QList <QGraphicsView *> QGraphicsScene::views() const -{ - Q_D(const QGraphicsScene); - return d->views; -} - -/*! - This slot \e advances the scene by one step, by calling - QGraphicsItem::advance() for all items on the scene. This is done in two - phases: in the first phase, all items are notified that the scene is about - to change, and in the second phase all items are notified that they can - move. In the first phase, QGraphicsItem::advance() is called passing a - value of 0 as an argument, and 1 is passed in the second phase. - - \sa QGraphicsItem::advance(), QGraphicsItemAnimation, QTimeLine -*/ -void QGraphicsScene::advance() -{ - for (int i = 0; i < 2; ++i) { - foreach (QGraphicsItem *item, items()) - item->advance(i); - } -} - -/*! - Processes the event \a event, and dispatches it to the respective - event handlers. - - In addition to calling the convenience event handlers, this - function is responsible for converting mouse move events to hover - events for when there is no mouse grabber item. Hover events are - delivered directly to items; there is no convenience function for - them. - - Unlike QWidget, QGraphicsScene does not have the convenience functions - \l{QWidget::}{enterEvent()} and \l{QWidget::}{leaveEvent()}. Use this - function to obtain those events instead. - - \sa contextMenuEvent(), keyPressEvent(), keyReleaseEvent(), - mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), - mouseDoubleClickEvent(), focusInEvent(), focusOutEvent() -*/ -bool QGraphicsScene::event(QEvent *event) -{ - Q_D(QGraphicsScene); - - switch (event->type()) { - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseDoubleClick: - case QEvent::GraphicsSceneHoverEnter: - case QEvent::GraphicsSceneHoverLeave: - case QEvent::GraphicsSceneHoverMove: - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - // Reset the under-mouse list to ensure that this event gets fresh - // item-under-mouse data. Be careful about this list; if people delete - // items from inside event handlers, this list can quickly end up - // having stale pointers in it. We need to clear it before dispatching - // events that use it. - // ### this should only be cleared if we received a new mouse move event, - // which relies on us fixing the replay mechanism in QGraphicsView. - d->cachedItemsUnderMouse.clear(); - default: - break; - } - - switch (event->type()) { - case QEvent::GraphicsSceneDragEnter: - dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneDragMove: - dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneDragLeave: - dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneDrop: - dropEvent(static_cast<QGraphicsSceneDragDropEvent *>(event)); - break; - case QEvent::GraphicsSceneContextMenu: - contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent *>(event)); - break; - case QEvent::KeyPress: - if (!d->focusItem) { - QKeyEvent *k = static_cast<QKeyEvent *>(event); - if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) { - if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier? - bool res = false; - if (k->key() == Qt::Key_Backtab - || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) { - res = focusNextPrevChild(false); - } else if (k->key() == Qt::Key_Tab) { - res = focusNextPrevChild(true); - } - if (!res) - event->ignore(); - return true; - } - } - } - keyPressEvent(static_cast<QKeyEvent *>(event)); - break; - case QEvent::KeyRelease: - keyReleaseEvent(static_cast<QKeyEvent *>(event)); - break; - case QEvent::ShortcutOverride: { - QGraphicsItem *parent = focusItem(); - while (parent) { - d->sendEvent(parent, event); - if (event->isAccepted()) - return true; - parent = parent->parentItem(); - } - } - return false; - case QEvent::GraphicsSceneMouseMove: - { - QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); - d->lastSceneMousePos = mouseEvent->scenePos(); - mouseMoveEvent(mouseEvent); - break; - } - case QEvent::GraphicsSceneMousePress: - mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneMouseRelease: - mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneMouseDoubleClick: - mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneWheel: - wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event)); - break; - case QEvent::FocusIn: - focusInEvent(static_cast<QFocusEvent *>(event)); - break; - case QEvent::FocusOut: - focusOutEvent(static_cast<QFocusEvent *>(event)); - break; - case QEvent::GraphicsSceneHoverEnter: - case QEvent::GraphicsSceneHoverLeave: - case QEvent::GraphicsSceneHoverMove: - { - QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event); - d->lastSceneMousePos = hoverEvent->scenePos(); - d->dispatchHoverEvent(hoverEvent); - break; - } - case QEvent::Leave: - // hackieshly unpacking the viewport pointer from the leave event. - d->leaveScene(reinterpret_cast<QWidget *>(event->d)); - break; - case QEvent::GraphicsSceneHelp: - helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event)); - break; - case QEvent::InputMethod: - inputMethodEvent(static_cast<QInputMethodEvent *>(event)); - break; - case QEvent::WindowActivate: - if (!d->activationRefCount++) { - if (d->lastActivePanel) { - // Activate the last panel. - d->setActivePanelHelper(d->lastActivePanel, true); - } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) { - // Activate the panel of the first item in the tab focus - // chain. - d->setActivePanelHelper(d->tabFocusFirst, true); - } else { - // Activate all toplevel items. - QEvent event(QEvent::WindowActivate); - foreach (QGraphicsItem *item, items()) { - if (item->isVisible() && !item->isPanel() && !item->parentItem()) - sendEvent(item, &event); - } - } - } - break; - case QEvent::WindowDeactivate: - if (!--d->activationRefCount) { - if (d->activePanel) { - // Deactivate the active panel (but keep it so we can - // reactivate it later). - QGraphicsItem *lastActivePanel = d->activePanel; - d->setActivePanelHelper(0, true); - d->lastActivePanel = lastActivePanel; - } else { - // Activate all toplevel items. - QEvent event(QEvent::WindowDeactivate); - foreach (QGraphicsItem *item, items()) { - if (item->isVisible() && !item->isPanel() && !item->parentItem()) - sendEvent(item, &event); - } - } - } - break; - case QEvent::ApplicationFontChange: { - // Resolve the existing scene font. - d->resolveFont(); - break; - } - case QEvent::FontChange: - // Update the entire scene when the font changes. - update(); - break; - case QEvent::ApplicationPaletteChange: { - // Resolve the existing scene palette. - d->resolvePalette(); - break; - } - case QEvent::PaletteChange: - // Update the entire scene when the palette changes. - update(); - break; - case QEvent::StyleChange: - // Reresolve all widgets' styles. Update all top-level widgets' - // geometries that do not have an explicit style set. - update(); - break; - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - d->touchEventHandler(static_cast<QTouchEvent *>(event)); - break; -#ifndef QT_NO_GESTURES - case QEvent::Gesture: - case QEvent::GestureOverride: - d->gestureEventHandler(static_cast<QGestureEvent *>(event)); - break; -#endif // QT_NO_GESTURES - default: - return QObject::event(event); - } - return true; -} - -/*! - \reimp - - QGraphicsScene filters QApplication's events to detect palette and font - changes. -*/ -bool QGraphicsScene::eventFilter(QObject *watched, QEvent *event) -{ - if (watched != qApp) - return false; - - switch (event->type()) { - case QEvent::ApplicationPaletteChange: - QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange)); - break; - case QEvent::ApplicationFontChange: - QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange)); - break; - default: - break; - } - return false; -} - -/*! - This event handler, for event \a contextMenuEvent, can be reimplemented in - a subclass to receive context menu events. The default implementation - forwards the event to the topmost item that accepts context menu events at - the position of the event. If no items accept context menu events at this - position, the event is ignored. - - \sa QGraphicsItem::contextMenuEvent() -*/ -void QGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent) -{ - Q_D(QGraphicsScene); - // Ignore by default. - contextMenuEvent->ignore(); - - // Send the event to all items at this position until one item accepts the - // event. - foreach (QGraphicsItem *item, d->itemsAtPosition(contextMenuEvent->screenPos(), - contextMenuEvent->scenePos(), - contextMenuEvent->widget())) { - contextMenuEvent->setPos(item->d_ptr->genericMapFromScene(contextMenuEvent->scenePos(), - contextMenuEvent->widget())); - contextMenuEvent->accept(); - if (!d->sendEvent(item, contextMenuEvent)) - break; - - if (contextMenuEvent->isAccepted()) - break; - } -} - -/*! - This event handler, for event \a event, can be reimplemented in a subclass - to receive drag enter events for the scene. - - The default implementation accepts the event and prepares the scene to - accept drag move events. - - \sa QGraphicsItem::dragEnterEvent(), dragMoveEvent(), dragLeaveEvent(), - dropEvent() -*/ -void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsScene); - d->dragDropItem = 0; - d->lastDropAction = Qt::IgnoreAction; - event->accept(); -} - -/*! - This event handler, for event \a event, can be reimplemented in a subclass - to receive drag move events for the scene. - - \sa QGraphicsItem::dragMoveEvent(), dragEnterEvent(), dragLeaveEvent(), - dropEvent() -*/ -void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsScene); - event->ignore(); - - if (!d->mouseGrabberItems.isEmpty()) { - // Mouse grabbers that start drag events lose the mouse grab. - d->clearMouseGrabber(); - d->mouseGrabberButtonDownPos.clear(); - d->mouseGrabberButtonDownScenePos.clear(); - d->mouseGrabberButtonDownScreenPos.clear(); - } - - bool eventDelivered = false; - - // Find the topmost enabled items under the cursor. They are all - // candidates for accepting drag & drop events. - foreach (QGraphicsItem *item, d->itemsAtPosition(event->screenPos(), - event->scenePos(), - event->widget())) { - if (!item->isEnabled() || !item->acceptDrops()) - continue; - - if (item != d->dragDropItem) { - // Enter the new drag drop item. If it accepts the event, we send - // the leave to the parent item. - QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter); - d->cloneDragDropEvent(&dragEnter, event); - dragEnter.setDropAction(event->proposedAction()); - d->sendDragDropEvent(item, &dragEnter); - event->setAccepted(dragEnter.isAccepted()); - event->setDropAction(dragEnter.dropAction()); - if (!event->isAccepted()) { - // Propagate to the item under - continue; - } - - d->lastDropAction = event->dropAction(); - - if (d->dragDropItem) { - // Leave the last drag drop item. A perfect implementation - // would set the position of this event to the point where - // this event and the last event intersect with the item's - // shape, but that's not easy to do. :-) - QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave); - d->cloneDragDropEvent(&dragLeave, event); - d->sendDragDropEvent(d->dragDropItem, &dragLeave); - } - - // We've got a new drag & drop item - d->dragDropItem = item; - } - - // Send the move event. - event->setDropAction(d->lastDropAction); - event->accept(); - d->sendDragDropEvent(item, event); - if (event->isAccepted()) - d->lastDropAction = event->dropAction(); - eventDelivered = true; - break; - } - - if (!eventDelivered) { - if (d->dragDropItem) { - // Leave the last drag drop item - QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave); - d->cloneDragDropEvent(&dragLeave, event); - d->sendDragDropEvent(d->dragDropItem, &dragLeave); - d->dragDropItem = 0; - } - // Propagate - event->setDropAction(Qt::IgnoreAction); - } -} - -/*! - This event handler, for event \a event, can be reimplemented in a subclass - to receive drag leave events for the scene. - - \sa QGraphicsItem::dragLeaveEvent(), dragEnterEvent(), dragMoveEvent(), - dropEvent() -*/ -void QGraphicsScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_D(QGraphicsScene); - if (d->dragDropItem) { - // Leave the last drag drop item - d->sendDragDropEvent(d->dragDropItem, event); - d->dragDropItem = 0; - } -} - -/*! - This event handler, for event \a event, can be reimplemented in a subclass - to receive drop events for the scene. - - \sa QGraphicsItem::dropEvent(), dragEnterEvent(), dragMoveEvent(), - dragLeaveEvent() -*/ -void QGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event) -{ - Q_UNUSED(event); - Q_D(QGraphicsScene); - if (d->dragDropItem) { - // Drop on the last drag drop item - d->sendDragDropEvent(d->dragDropItem, event); - d->dragDropItem = 0; - } -} - -/*! - This event handler, for event \a focusEvent, can be reimplemented in a - subclass to receive focus in events. - - The default implementation sets focus on the scene, and then on the last - focus item. - - \sa QGraphicsItem::focusOutEvent() -*/ -void QGraphicsScene::focusInEvent(QFocusEvent *focusEvent) -{ - Q_D(QGraphicsScene); - - d->hasFocus = true; - switch (focusEvent->reason()) { - case Qt::TabFocusReason: - if (!focusNextPrevChild(true)) - focusEvent->ignore(); - break; - case Qt::BacktabFocusReason: - if (!focusNextPrevChild(false)) - focusEvent->ignore(); - break; - default: - if (d->passiveFocusItem) { - // Set focus on the last focus item - setFocusItem(d->passiveFocusItem, focusEvent->reason()); - } - break; - } -} - -/*! - This event handler, for event \a focusEvent, can be reimplemented in a - subclass to receive focus out events. - - The default implementation removes focus from any focus item, then removes - focus from the scene. - - \sa QGraphicsItem::focusInEvent() -*/ -void QGraphicsScene::focusOutEvent(QFocusEvent *focusEvent) -{ - Q_D(QGraphicsScene); - d->hasFocus = false; - d->passiveFocusItem = d->focusItem; - setFocusItem(0, focusEvent->reason()); - - // Remove all popups when the scene loses focus. - if (!d->popupWidgets.isEmpty()) - d->removePopup(d->popupWidgets.first()); -} - -/*! - This event handler, for event \a helpEvent, can be - reimplemented in a subclass to receive help events. The events - are of type QEvent::ToolTip, which are created when a tooltip is - requested. - - The default implementation shows the tooltip of the topmost - item, i.e., the item with the highest z-value, at the mouse - cursor position. If no item has a tooltip set, this function - does nothing. - - \sa QGraphicsItem::toolTip(), QGraphicsSceneHelpEvent -*/ -void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) -{ -#ifdef QT_NO_TOOLTIP - Q_UNUSED(helpEvent); -#else - // Find the first item that does tooltips - Q_D(QGraphicsScene); - QList<QGraphicsItem *> itemsAtPos = d->itemsAtPosition(helpEvent->screenPos(), - helpEvent->scenePos(), - helpEvent->widget()); - QGraphicsItem *toolTipItem = 0; - for (int i = 0; i < itemsAtPos.size(); ++i) { - QGraphicsItem *tmp = itemsAtPos.at(i); - if (tmp->d_func()->isProxyWidget()) { - // if the item is a proxy widget, the event is forwarded to it - sendEvent(tmp, helpEvent); - if (helpEvent->isAccepted()) - return; - } - if (!tmp->toolTip().isEmpty()) { - toolTipItem = tmp; - break; - } - } - - // Show or hide the tooltip - QString text; - QPoint point; - if (toolTipItem && !toolTipItem->toolTip().isEmpty()) { - text = toolTipItem->toolTip(); - point = helpEvent->screenPos(); - } - QToolTip::showText(point, text, helpEvent->widget()); - helpEvent->setAccepted(!text.isEmpty()); -#endif -} - -bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const -{ - return (item->d_ptr->acceptsHover - || (item->d_ptr->isWidget - && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())) - && !item->isBlockedByModalPanel(); -} - -/*! - This event handler, for event \a hoverEvent, can be reimplemented in a - subclass to receive hover enter events. The default implementation - forwards the event to the topmost item that accepts hover events at the - scene position from the event. - - \sa QGraphicsItem::hoverEvent(), QGraphicsItem::setAcceptHoverEvents() -*/ -bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent) -{ - if (allItemsIgnoreHoverEvents) - return false; - - // Find the first item that accepts hover events, reusing earlier - // calculated data is possible. - if (cachedItemsUnderMouse.isEmpty()) { - cachedItemsUnderMouse = itemsAtPosition(hoverEvent->screenPos(), - hoverEvent->scenePos(), - hoverEvent->widget()); - } - - QGraphicsItem *item = 0; - for (int i = 0; i < cachedItemsUnderMouse.size(); ++i) { - QGraphicsItem *tmp = cachedItemsUnderMouse.at(i); - if (itemAcceptsHoverEvents_helper(tmp)) { - item = tmp; - break; - } - } - - // Find the common ancestor item for the new topmost hoverItem and the - // last item in the hoverItem list. - QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.last()) : 0; - while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem)) - commonAncestorItem = commonAncestorItem->parentItem(); - if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) { - // The common ancestor isn't in the same panel as the two hovered - // items. - commonAncestorItem = 0; - } - - // Check if the common ancestor item is known. - int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1; - // Send hover leaves to any existing hovered children of the common - // ancestor item. - for (int i = hoverItems.size() - 1; i > index; --i) { - QGraphicsItem *lastItem = hoverItems.takeLast(); - if (itemAcceptsHoverEvents_helper(lastItem)) - sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent); - } - - // Item is a child of a known item. Generate enter events for the - // missing links. - QList<QGraphicsItem *> parents; - QGraphicsItem *parent = item; - while (parent && parent != commonAncestorItem) { - parents.prepend(parent); - if (parent->isPanel()) { - // Stop at the panel - we don't deliver beyond this point. - break; - } - parent = parent->parentItem(); - } - for (int i = 0; i < parents.size(); ++i) { - parent = parents.at(i); - hoverItems << parent; - if (itemAcceptsHoverEvents_helper(parent)) - sendHoverEvent(QEvent::GraphicsSceneHoverEnter, parent, hoverEvent); - } - - // Generate a move event for the item itself - if (item - && !hoverItems.isEmpty() - && item == hoverItems.last()) { - sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent); - return true; - } - return false; -} - -/*! - \internal - - Handles all actions necessary to clean up the scene when the mouse leaves - the view. -*/ -void QGraphicsScenePrivate::leaveScene(QWidget *viewport) -{ -#ifndef QT_NO_TOOLTIP - QToolTip::hideText(); -#endif - QGraphicsView *view = qobject_cast<QGraphicsView *>(viewport->parent()); - // Send HoverLeave events to all existing hover items, topmost first. - QGraphicsSceneHoverEvent hoverEvent; - hoverEvent.setWidget(viewport); - - if (view) { - QPoint cursorPos = QCursor::pos(); - hoverEvent.setScenePos(view->mapToScene(viewport->mapFromGlobal(cursorPos))); - hoverEvent.setLastScenePos(hoverEvent.scenePos()); - hoverEvent.setScreenPos(cursorPos); - hoverEvent.setLastScreenPos(hoverEvent.screenPos()); - } - - while (!hoverItems.isEmpty()) { - QGraphicsItem *lastItem = hoverItems.takeLast(); - if (itemAcceptsHoverEvents_helper(lastItem)) - sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent); - } -} - -/*! - This event handler, for event \a keyEvent, can be reimplemented in a - subclass to receive keypress events. The default implementation forwards - the event to current focus item. - - \sa QGraphicsItem::keyPressEvent(), focusItem() -*/ -void QGraphicsScene::keyPressEvent(QKeyEvent *keyEvent) -{ - // ### Merge this function with keyReleaseEvent; they are identical - // ### (except this comment). - Q_D(QGraphicsScene); - QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.last() : 0; - if (!item) - item = focusItem(); - if (item) { - QGraphicsItem *p = item; - do { - // Accept the event by default - keyEvent->accept(); - // Send it; QGraphicsItem::keyPressEvent ignores it. If the event - // is filtered out, stop propagating it. - if (p->isBlockedByModalPanel()) - break; - if (!d->sendEvent(p, keyEvent)) - break; - } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem())); - } else { - keyEvent->ignore(); - } -} - -/*! - This event handler, for event \a keyEvent, can be reimplemented in a - subclass to receive key release events. The default implementation - forwards the event to current focus item. - - \sa QGraphicsItem::keyReleaseEvent(), focusItem() -*/ -void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent) -{ - // ### Merge this function with keyPressEvent; they are identical (except - // ### this comment). - Q_D(QGraphicsScene); - QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.last() : 0; - if (!item) - item = focusItem(); - if (item) { - QGraphicsItem *p = item; - do { - // Accept the event by default - keyEvent->accept(); - // Send it; QGraphicsItem::keyPressEvent ignores it. If the event - // is filtered out, stop propagating it. - if (p->isBlockedByModalPanel()) - break; - if (!d->sendEvent(p, keyEvent)) - break; - } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem())); - } else { - keyEvent->ignore(); - } -} - -/*! - This event handler, for event \a mouseEvent, can be reimplemented - in a subclass to receive mouse press events for the scene. - - The default implementation depends on the state of the scene. If - there is a mouse grabber item, then the event is sent to the mouse - grabber. Otherwise, it is forwarded to the topmost item that - accepts mouse events at the scene position from the event, and - that item promptly becomes the mouse grabber item. - - If there is no item at the given position on the scene, the - selection area is reset, any focus item loses its input focus, and - the event is then ignored. - - \sa QGraphicsItem::mousePressEvent(), - QGraphicsItem::setAcceptedMouseButtons() -*/ -void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - Q_D(QGraphicsScene); - if (d->mouseGrabberItems.isEmpty()) { - // Dispatch hover events - QGraphicsSceneHoverEvent hover; - _q_hoverFromMouseEvent(&hover, mouseEvent); - d->dispatchHoverEvent(&hover); - } - - d->mousePressEventHandler(mouseEvent); -} - -/*! - This event handler, for event \a mouseEvent, can be reimplemented - in a subclass to receive mouse move events for the scene. - - The default implementation depends on the mouse grabber state. If there is - a mouse grabber item, the event is sent to the mouse grabber. If there - are any items that accept hover events at the current position, the event - is translated into a hover event and accepted; otherwise it's ignored. - - \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseReleaseEvent(), - QGraphicsItem::mouseDoubleClickEvent(), QGraphicsItem::setAcceptedMouseButtons() -*/ -void QGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - Q_D(QGraphicsScene); - if (d->mouseGrabberItems.isEmpty()) { - if (mouseEvent->buttons()) - return; - QGraphicsSceneHoverEvent hover; - _q_hoverFromMouseEvent(&hover, mouseEvent); - mouseEvent->setAccepted(d->dispatchHoverEvent(&hover)); - return; - } - - // Forward the event to the mouse grabber - d->sendMouseEvent(mouseEvent); - mouseEvent->accept(); -} - -/*! - This event handler, for event \a mouseEvent, can be reimplemented - in a subclass to receive mouse release events for the scene. - - The default implementation depends on the mouse grabber state. If - there is no mouse grabber, the event is ignored. Otherwise, if - there is a mouse grabber item, the event is sent to the mouse - grabber. If this mouse release represents the last pressed button - on the mouse, the mouse grabber item then loses the mouse grab. - - \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseMoveEvent(), - QGraphicsItem::mouseDoubleClickEvent(), QGraphicsItem::setAcceptedMouseButtons() -*/ -void QGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - Q_D(QGraphicsScene); - if (d->mouseGrabberItems.isEmpty()) { - mouseEvent->ignore(); - return; - } - - // Forward the event to the mouse grabber - d->sendMouseEvent(mouseEvent); - mouseEvent->accept(); - - // Reset the mouse grabber when the last mouse button has been released. - if (!mouseEvent->buttons()) { - if (!d->mouseGrabberItems.isEmpty()) { - d->lastMouseGrabberItem = d->mouseGrabberItems.last(); - if (d->lastMouseGrabberItemHasImplicitMouseGrab) - d->mouseGrabberItems.last()->ungrabMouse(); - } else { - d->lastMouseGrabberItem = 0; - } - - // Generate a hoverevent - QGraphicsSceneHoverEvent hoverEvent; - _q_hoverFromMouseEvent(&hoverEvent, mouseEvent); - d->dispatchHoverEvent(&hoverEvent); - } -} - -/*! - This event handler, for event \a mouseEvent, can be reimplemented - in a subclass to receive mouse doubleclick events for the scene. - - If someone doubleclicks on the scene, the scene will first receive - a mouse press event, followed by a release event (i.e., a click), - then a doubleclick event, and finally a release event. If the - doubleclick event is delivered to a different item than the one - that received the first press and release, it will be delivered as - a press event. However, tripleclick events are not delivered as - doubleclick events in this case. - - The default implementation is similar to mousePressEvent(). - - \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseMoveEvent(), - QGraphicsItem::mouseReleaseEvent(), QGraphicsItem::setAcceptedMouseButtons() -*/ -void QGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - Q_D(QGraphicsScene); - d->mousePressEventHandler(mouseEvent); -} - -/*! - This event handler, for event \a wheelEvent, can be reimplemented in a - subclass to receive mouse wheel events for the scene. - - By default, the event is delivered to the topmost visible item under the - cursor. If ignored, the event propagates to the item beneath, and again - until the event is accepted, or it reaches the scene. If no items accept - the event, it is ignored. - - \sa QGraphicsItem::wheelEvent() -*/ -void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent) -{ - Q_D(QGraphicsScene); - QList<QGraphicsItem *> wheelCandidates = d->itemsAtPosition(wheelEvent->screenPos(), - wheelEvent->scenePos(), - wheelEvent->widget()); - -#ifdef Q_WS_MAC - // On Mac, ignore the event if the first item under the mouse is not the last opened - // popup (or one of its descendant) - if (!d->popupWidgets.isEmpty() && !wheelCandidates.isEmpty() && wheelCandidates.first() != d->popupWidgets.back() && !d->popupWidgets.back()->isAncestorOf(wheelCandidates.first())) { - wheelEvent->accept(); - return; - } -#else - // Find the first popup under the mouse (including the popup's descendants) starting from the last. - // Remove all popups after the one found, or all or them if no popup is under the mouse. - // Then continue with the event. - QList<QGraphicsWidget *>::const_iterator iter = d->popupWidgets.end(); - while (--iter >= d->popupWidgets.begin() && !wheelCandidates.isEmpty()) { - if (wheelCandidates.first() == *iter || (*iter)->isAncestorOf(wheelCandidates.first())) - break; - d->removePopup(*iter); - } -#endif - - bool hasSetFocus = false; - foreach (QGraphicsItem *item, wheelCandidates) { - if (!hasSetFocus && item->isEnabled() - && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { - if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) { - hasSetFocus = true; - if (item != focusItem()) - setFocusItem(item, Qt::MouseFocusReason); - } - } - - wheelEvent->setPos(item->d_ptr->genericMapFromScene(wheelEvent->scenePos(), - wheelEvent->widget())); - wheelEvent->accept(); - bool isPanel = item->isPanel(); - d->sendEvent(item, wheelEvent); - if (isPanel || wheelEvent->isAccepted()) - break; - } -} - -/*! - This event handler, for event \a event, can be reimplemented in a - subclass to receive input method events for the scene. - - The default implementation forwards the event to the focusItem(). - If no item currently has focus or the current focus item does not - accept input methods, this function does nothing. - - \sa QGraphicsItem::inputMethodEvent() -*/ -void QGraphicsScene::inputMethodEvent(QInputMethodEvent *event) -{ - Q_D(QGraphicsScene); - if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) - d->sendEvent(d->focusItem, event); -} - -/*! - Draws the background of the scene using \a painter, before any items and - the foreground are drawn. Reimplement this function to provide a custom - background for the scene. - - All painting is done in \e scene coordinates. The \a rect - parameter is the exposed rectangle. - - If all you want is to define a color, texture, or gradient for the - background, you can call setBackgroundBrush() instead. - - \sa drawForeground(), drawItems() -*/ -void QGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect) -{ - Q_D(QGraphicsScene); - - if (d->backgroundBrush.style() != Qt::NoBrush) { - if (d->painterStateProtection) - painter->save(); - painter->setBrushOrigin(0, 0); - painter->fillRect(rect, backgroundBrush()); - if (d->painterStateProtection) - painter->restore(); - } -} - -/*! - Draws the foreground of the scene using \a painter, after the background - and all items have been drawn. Reimplement this function to provide a - custom foreground for the scene. - - All painting is done in \e scene coordinates. The \a rect - parameter is the exposed rectangle. - - If all you want is to define a color, texture or gradient for the - foreground, you can call setForegroundBrush() instead. - - \sa drawBackground(), drawItems() -*/ -void QGraphicsScene::drawForeground(QPainter *painter, const QRectF &rect) -{ - Q_D(QGraphicsScene); - - if (d->foregroundBrush.style() != Qt::NoBrush) { - if (d->painterStateProtection) - painter->save(); - painter->setBrushOrigin(0, 0); - painter->fillRect(rect, foregroundBrush()); - if (d->painterStateProtection) - painter->restore(); - } -} - -static void _q_paintItem(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget, - bool useWindowOpacity, bool painterStateProtection) -{ - if (!item->isWidget()) { - item->paint(painter, option, widget); - return; - } - QGraphicsWidget *widgetItem = static_cast<QGraphicsWidget *>(item); - QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(widgetItem); - const qreal windowOpacity = (proxy && proxy->widget() && useWindowOpacity) - ? proxy->widget()->windowOpacity() : 1.0; - const qreal oldPainterOpacity = painter->opacity(); - - if (qFuzzyIsNull(windowOpacity)) - return; - // Set new painter opacity. - if (windowOpacity < 1.0) - painter->setOpacity(oldPainterOpacity * windowOpacity); - - // set layoutdirection on the painter - Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection(); - painter->setLayoutDirection(widgetItem->layoutDirection()); - - if (widgetItem->isWindow() && widgetItem->windowType() != Qt::Popup && widgetItem->windowType() != Qt::ToolTip - && !(widgetItem->windowFlags() & Qt::FramelessWindowHint)) { - if (painterStateProtection) - painter->save(); - widgetItem->paintWindowFrame(painter, option, widget); - if (painterStateProtection) - painter->restore(); - } else if (widgetItem->autoFillBackground()) { - painter->fillRect(option->exposedRect, widgetItem->palette().window()); - } - - widgetItem->paint(painter, option, widget); - - // Restore layoutdirection on the painter. - painter->setLayoutDirection(oldLayoutDirection); - // Restore painter opacity. - if (windowOpacity < 1.0) - painter->setOpacity(oldPainterOpacity); -} - -static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &pixmapExposed, - const QTransform &itemToPixmap, QPainter::RenderHints renderHints, - const QStyleOptionGraphicsItem *option, bool painterStateProtection) -{ - QPixmap subPix; - QPainter pixmapPainter; - QRect br = pixmapExposed.boundingRect(); - - // Don't use subpixmap if we get a full update. - if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) { - pix->fill(Qt::transparent); - pixmapPainter.begin(pix); - } else { - subPix = QPixmap(br.size()); - subPix.fill(Qt::transparent); - pixmapPainter.begin(&subPix); - pixmapPainter.translate(-br.topLeft()); - if (!pixmapExposed.isEmpty()) { - // Applied to subPix; paint is adjusted to the coordinate space is - // correct. - pixmapPainter.setClipRegion(pixmapExposed); - } - } - - pixmapPainter.setRenderHints(pixmapPainter.renderHints(), false); - pixmapPainter.setRenderHints(renderHints, true); - pixmapPainter.setWorldTransform(itemToPixmap, true); - - // Render. - _q_paintItem(item, &pixmapPainter, option, 0, false, painterStateProtection); - pixmapPainter.end(); - - if (!subPix.isNull()) { - // Blit the subpixmap into the main pixmap. - pixmapPainter.begin(pix); - pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source); - pixmapPainter.setClipRegion(pixmapExposed); - pixmapPainter.drawPixmap(br.topLeft(), subPix); - pixmapPainter.end(); - } -} - -// Copied from qpaintengine_vg.cpp -// Returns true for 90, 180, and 270 degree rotations. -static inline bool transformIsSimple(const QTransform& transform) -{ - QTransform::TransformationType type = transform.type(); - if (type <= QTransform::TxScale) { - return true; - } else if (type == QTransform::TxRotate) { - // Check for 90, and 270 degree rotations. - qreal m11 = transform.m11(); - qreal m12 = transform.m12(); - qreal m21 = transform.m21(); - qreal m22 = transform.m22(); - if (m11 == 0.0f && m22 == 0.0f) { - if (m12 == 1.0f && m21 == -1.0f) - return true; // 90 degrees. - else if (m12 == -1.0f && m21 == 1.0f) - return true; // 270 degrees. - else if (m12 == -1.0f && m21 == -1.0f) - return true; // 90 degrees inverted y. - else if (m12 == 1.0f && m21 == 1.0f) - return true; // 270 degrees inverted y. - } - } - return false; -} - -/*! - \internal - - Draws items directly, or using cache. -*/ -void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget, - bool painterStateProtection) -{ - QGraphicsItemPrivate *itemd = item->d_ptr.data(); - QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode); - - // Render directly, using no cache. - if (cacheMode == QGraphicsItem::NoCache -#ifdef Q_WS_X11 - || !X11->use_xrender -#endif - ) { - _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget, true, painterStateProtection); - return; - } - - const qreal oldPainterOpacity = painter->opacity(); - qreal newPainterOpacity = oldPainterOpacity; - QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(item)) : 0; - if (proxy && proxy->widget()) { - const qreal windowOpacity = proxy->widget()->windowOpacity(); - if (windowOpacity < 1.0) - newPainterOpacity *= windowOpacity; - } - - // Item's (local) bounding rect - QRectF brect = item->boundingRect(); - QRectF adjustedBrect(brect); - _q_adjustRect(&adjustedBrect); - if (adjustedBrect.isEmpty()) - return; - - // Fetch the off-screen transparent buffer and exposed area info. - QPixmapCache::Key pixmapKey; - QPixmap pix; - bool pixmapFound; - QGraphicsItemCache *itemCache = itemd->extraItemCache(); - if (cacheMode == QGraphicsItem::ItemCoordinateCache) { - pixmapKey = itemCache->key; - } else { - pixmapKey = itemCache->deviceData.value(widget).key; - } - - // Find pixmap in cache. - pixmapFound = QPixmapCache::find(pixmapKey, &pix); - - // Render using item coordinate cache mode. - if (cacheMode == QGraphicsItem::ItemCoordinateCache) { - QSize pixmapSize; - bool fixedCacheSize = false; - QRect br = brect.toAlignedRect(); - if ((fixedCacheSize = itemCache->fixedSize.isValid())) { - pixmapSize = itemCache->fixedSize; - } else { - pixmapSize = br.size(); - } - - // Create or recreate the pixmap. - int adjust = itemCache->fixedSize.isValid() ? 0 : 2; - QSize adjustSize(adjust*2, adjust*2); - br.adjust(-adjust, -adjust, adjust, adjust); - if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) { - pix = QPixmap(pixmapSize + adjustSize); - itemCache->boundingRect = br; - itemCache->exposed.clear(); - itemCache->allExposed = true; - } else if (itemCache->boundingRect != br) { - itemCache->boundingRect = br; - itemCache->exposed.clear(); - itemCache->allExposed = true; - } - - // Redraw any newly exposed areas. - if (itemCache->allExposed || !itemCache->exposed.isEmpty()) { - - //We know that we will modify the pixmap, removing it from the cache - //will detach the one we have and avoid a deep copy - if (pixmapFound) - QPixmapCache::remove(pixmapKey); - - // Fit the item's bounding rect into the pixmap's coordinates. - QTransform itemToPixmap; - if (fixedCacheSize) { - const QPointF scale(pixmapSize.width() / brect.width(), pixmapSize.height() / brect.height()); - itemToPixmap.scale(scale.x(), scale.y()); - } - itemToPixmap.translate(-br.x(), -br.y()); - - // Generate the item's exposedRect and map its list of expose - // rects to device coordinates. - styleOptionTmp = *option; - QRegion pixmapExposed; - QRectF exposedRect; - if (!itemCache->allExposed) { - for (int i = 0; i < itemCache->exposed.size(); ++i) { - QRectF r = itemCache->exposed.at(i); - exposedRect |= r; - pixmapExposed += itemToPixmap.mapRect(r).toAlignedRect(); - } - } else { - exposedRect = brect; - } - styleOptionTmp.exposedRect = exposedRect; - - // Render. - _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(), - &styleOptionTmp, painterStateProtection); - - // insert this pixmap into the cache. - itemCache->key = QPixmapCache::insert(pix); - - // Reset expose data. - itemCache->allExposed = false; - itemCache->exposed.clear(); - } - - // Redraw the exposed area using the transformed painter. Depending on - // the hardware, this may be a server-side operation, or an expensive - // qpixmap-image-transform-pixmap roundtrip. - if (newPainterOpacity != oldPainterOpacity) { - painter->setOpacity(newPainterOpacity); - painter->drawPixmap(br.topLeft(), pix); - painter->setOpacity(oldPainterOpacity); - } else { - painter->drawPixmap(br.topLeft(), pix); - } - return; - } - - // Render using device coordinate cache mode. - if (cacheMode == QGraphicsItem::DeviceCoordinateCache) { - // Find the item's bounds in device coordinates. - QRectF deviceBounds = painter->worldTransform().mapRect(brect); - QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); - if (deviceRect.isEmpty()) - return; - QRect viewRect = widget ? widget->rect() : QRect(); - if (widget && !viewRect.intersects(deviceRect)) - return; - - // Resort to direct rendering if the device rect exceeds the - // (optional) maximum bounds. (QGraphicsSvgItem uses this). - QSize maximumCacheSize = - itemd->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize(); - if (!maximumCacheSize.isEmpty() - && (deviceRect.width() > maximumCacheSize.width() - || deviceRect.height() > maximumCacheSize.height())) { - _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget, - oldPainterOpacity != newPainterOpacity, painterStateProtection); - return; - } - - // Create or reuse offscreen pixmap, possibly scroll/blit from the old one. - // If the world transform is rotated we always recreate the cache to avoid - // wrong blending. - bool pixModified = false; - QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget]; - bool invertable = true; - QTransform diff = deviceData->lastTransform.inverted(&invertable); - if (invertable) - diff *= painter->worldTransform(); - deviceData->lastTransform = painter->worldTransform(); - bool allowPartialCacheExposure = false; - bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate - && transformIsSimple(painter->worldTransform()); - if (!simpleTransform) { - pixModified = true; - itemCache->allExposed = true; - itemCache->exposed.clear(); - deviceData->cacheIndent = QPoint(); - pix = QPixmap(); - } else if (!viewRect.isNull()) { - allowPartialCacheExposure = deviceData->cacheIndent != QPoint(); - } - - // Allow partial cache exposure if the device rect isn't fully contained and - // deviceRect is 20% taller or wider than the viewRect. - if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) { - allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width()) - || (viewRect.height() * 1.2 < deviceRect.height()); - } - - QRegion scrollExposure; - if (allowPartialCacheExposure) { - // Part of pixmap is drawn. Either device contains viewrect (big - // item covers whole screen) or parts of device are outside the - // viewport. In either case the device rect must be the intersect - // between the two. - int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0; - int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0; - QPoint newCacheIndent(dx, dy); - deviceRect &= viewRect; - - if (pix.isNull()) { - deviceData->cacheIndent = QPoint(); - itemCache->allExposed = true; - itemCache->exposed.clear(); - pixModified = true; - } - - // Copy / "scroll" the old pixmap onto the new ole and calculate - // scrolled exposure. - if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size()) { - QPoint diff = newCacheIndent - deviceData->cacheIndent; - QPixmap newPix(deviceRect.size()); - // ### Investigate removing this fill (test with Plasma and - // graphicssystem raster). - newPix.fill(Qt::transparent); - if (!pix.isNull()) { - QPainter newPixPainter(&newPix); - newPixPainter.drawPixmap(-diff, pix); - newPixPainter.end(); - } - QRegion exposed; - exposed += newPix.rect(); - if (!pix.isNull()) - exposed -= QRect(-diff, pix.size()); - scrollExposure = exposed; - - pix = newPix; - pixModified = true; - } - deviceData->cacheIndent = newCacheIndent; - } else { - // Full pixmap is drawn. - deviceData->cacheIndent = QPoint(); - - // Auto-adjust the pixmap size. - if (deviceRect.size() != pix.size()) { - // exposed needs to cover the whole pixmap - pix = QPixmap(deviceRect.size()); - pixModified = true; - itemCache->allExposed = true; - itemCache->exposed.clear(); - } - } - - // Check for newly invalidated areas. - if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) { - //We know that we will modify the pixmap, removing it from the cache - //will detach the one we have and avoid a deep copy - if (pixmapFound) - QPixmapCache::remove(pixmapKey); - - // Construct an item-to-pixmap transform. - QPointF p = deviceRect.topLeft(); - QTransform itemToPixmap = painter->worldTransform(); - if (!p.isNull()) - itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y()); - - // Map the item's logical expose to pixmap coordinates. - QRegion pixmapExposed = scrollExposure; - if (!itemCache->allExposed) { - const QVector<QRectF> &exposed = itemCache->exposed; - for (int i = 0; i < exposed.size(); ++i) - pixmapExposed += itemToPixmap.mapRect(exposed.at(i)).toRect().adjusted(-1, -1, 1, 1); - } - - // Calculate the style option's exposedRect. - QRectF br; - if (itemCache->allExposed) { - br = item->boundingRect(); - } else { - const QVector<QRectF> &exposed = itemCache->exposed; - for (int i = 0; i < exposed.size(); ++i) - br |= exposed.at(i); - QTransform pixmapToItem = itemToPixmap.inverted(); - foreach (QRect r, scrollExposure.rects()) - br |= pixmapToItem.mapRect(r); - } - styleOptionTmp = *option; - styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1); - - // Render the exposed areas. - _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(), - &styleOptionTmp, painterStateProtection); - - // Reset expose data. - pixModified = true; - itemCache->allExposed = false; - itemCache->exposed.clear(); - } - - if (pixModified) { - // Insert this pixmap into the cache. - deviceData->key = QPixmapCache::insert(pix); - } - - // Redraw the exposed area using an untransformed painter. This - // effectively becomes a bitblit that does not transform the cache. - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - if (newPainterOpacity != oldPainterOpacity) { - painter->setOpacity(newPainterOpacity); - painter->drawPixmap(deviceRect.topLeft(), pix); - painter->setOpacity(oldPainterOpacity); - } else { - painter->drawPixmap(deviceRect.topLeft(), pix); - } - painter->setWorldTransform(restoreTransform); - return; - } -} - -void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, - QRegion *exposedRegion, QWidget *widget) -{ - // Make sure we don't have unpolished items before we draw. - if (!unpolishedItems.isEmpty()) - _q_polishItems(); - - updateAll = false; - QRectF exposedSceneRect; - if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { - exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); - if (viewTransform) - exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); - } - const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder); - for (int i = 0; i < tli.size(); ++i) - drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); -} - -void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, - const QTransform *const viewTransform, - QRegion *exposedRegion, QWidget *widget, - qreal parentOpacity, const QTransform *const effectTransform) -{ - Q_ASSERT(item); - - if (!item->d_ptr->visible) - return; - - const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents); - const bool itemHasChildren = !item->d_ptr->children.isEmpty(); - if (!itemHasContents && !itemHasChildren) - return; // Item has neither contents nor children!(?) - - const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); - if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) - return; - - QTransform transform(Qt::Uninitialized); - QTransform *transformPtr = 0; - bool translateOnlyTransform = false; -#define ENSURE_TRANSFORM_PTR \ - if (!transformPtr) { \ - Q_ASSERT(!itemIsUntransformable); \ - if (viewTransform) { \ - transform = item->d_ptr->sceneTransform; \ - transform *= *viewTransform; \ - transformPtr = &transform; \ - } else { \ - transformPtr = &item->d_ptr->sceneTransform; \ - translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \ - } \ - } - - // Update the item's scene transform if the item is transformable; - // otherwise calculate the full transform, - bool wasDirtyParentSceneTransform = false; - const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); - if (itemIsUntransformable) { - transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform()); - transformPtr = &transform; - } else if (item->d_ptr->dirtySceneTransform) { - item->d_ptr->updateSceneTransformFromParent(); - Q_ASSERT(!item->d_ptr->dirtySceneTransform); - wasDirtyParentSceneTransform = true; - } - - const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); - bool drawItem = itemHasContents && !itemIsFullyTransparent; - if (drawItem) { - const QRectF brect = adjustedItemEffectiveBoundingRect(item); - ENSURE_TRANSFORM_PTR - QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect() - : transformPtr->mapRect(brect).toAlignedRect(); - viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust); - if (widget) - item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); - drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) - : !viewBoundingRect.normalized().isEmpty(); - if (!drawItem) { - if (!itemHasChildren) - return; - if (itemClipsChildrenToShape) { - if (wasDirtyParentSceneTransform) - item->d_ptr->invalidateChildrenSceneTransform(); - return; - } - } - } // else we know for sure this item has children we must process. - - if (itemHasChildren && itemClipsChildrenToShape) - ENSURE_TRANSFORM_PTR; - -#ifndef QT_NO_GRAPHICSEFFECT - if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { - ENSURE_TRANSFORM_PTR; - QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, - painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent); - QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; - QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *> - (source->d_func()); - sourced->info = &info; - const QTransform restoreTransform = painter->worldTransform(); - if (effectTransform) - painter->setWorldTransform(*transformPtr * *effectTransform); - else - painter->setWorldTransform(*transformPtr); - painter->setOpacity(opacity); - - if (sourced->currentCachedSystem() != Qt::LogicalCoordinates - && sourced->lastEffectTransform != painter->worldTransform()) - { - if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate - && painter->worldTransform().type() <= QTransform::TxTranslate) - { - QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates); - QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect); - - sourced->setCachedOffset(effectRect.topLeft()); - } else { - sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); - } - - sourced->lastEffectTransform = painter->worldTransform(); - } - - item->d_ptr->graphicsEffect->draw(painter); - painter->setWorldTransform(restoreTransform); - sourced->info = 0; - } else -#endif //QT_NO_GRAPHICSEFFECT - { - draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, - effectTransform, wasDirtyParentSceneTransform, drawItem); - } -} - -static inline void setClip(QPainter *painter, QGraphicsItem *item) -{ - painter->save(); - QRectF clipRect; - const QPainterPath clipPath(item->shape()); - if (QPathClipper::pathToRect(clipPath, &clipRect)) - painter->setClipRect(clipRect, Qt::IntersectClip); - else - painter->setClipPath(clipPath, Qt::IntersectClip); -} - -static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr, - const QTransform *effectTransform) -{ - Q_ASSERT(transformPtr); - if (effectTransform) - painter->setWorldTransform(*transformPtr * *effectTransform); - else - painter->setWorldTransform(*transformPtr); -} - -void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, - const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, - qreal opacity, const QTransform *effectTransform, - bool wasDirtyParentSceneTransform, bool drawItem) -{ - const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); - const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); - const bool itemHasChildren = !item->d_ptr->children.isEmpty(); - bool setChildClip = itemClipsChildrenToShape; - bool itemHasChildrenStackedBehind = false; - - int i = 0; - if (itemHasChildren) { - if (itemClipsChildrenToShape) - setWorldTransform(painter, transformPtr, effectTransform); - - item->d_ptr->ensureSortedChildren(); - // Items with the 'ItemStacksBehindParent' flag are put in front of the list - // so all we have to do is to check the first item. - itemHasChildrenStackedBehind = (item->d_ptr->children.at(0)->d_ptr->flags - & QGraphicsItem::ItemStacksBehindParent); - - if (itemHasChildrenStackedBehind) { - if (itemClipsChildrenToShape) { - setClip(painter, item); - setChildClip = false; - } - - // Draw children behind - for (i = 0; i < item->d_ptr->children.size(); ++i) { - QGraphicsItem *child = item->d_ptr->children.at(i); - if (wasDirtyParentSceneTransform) - child->d_ptr->dirtySceneTransform = 1; - if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) - break; - if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) - continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); - } - } - } - - // Draw item - if (drawItem) { - Q_ASSERT(!itemIsFullyTransparent); - Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)); - Q_ASSERT(transformPtr); - item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion - ? *exposedRegion : QRegion(), exposedRegion == 0); - - const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape; - bool restorePainterClip = false; - - if (!itemHasChildren || !itemClipsChildrenToShape) { - // Item does not have children or clip children to shape. - setWorldTransform(painter, transformPtr, effectTransform); - if ((restorePainterClip = itemClipsToShape)) - setClip(painter, item); - } else if (itemHasChildrenStackedBehind){ - // Item clips children to shape and has children stacked behind, which means - // the painter is already clipped to the item's shape. - if (itemClipsToShape) { - // The clip is already correct. Ensure correct world transform. - setWorldTransform(painter, transformPtr, effectTransform); - } else { - // Remove clip (this also ensures correct world transform). - painter->restore(); - setChildClip = true; - } - } else if (itemClipsToShape) { - // Item clips children and itself to shape. It does not have hildren stacked - // behind, which means the clip has not yet been set. We set it now and re-use it - // for the children. - setClip(painter, item); - setChildClip = false; - } - - if (painterStateProtection && !restorePainterClip) - painter->save(); - - painter->setOpacity(opacity); - if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) - item->paint(painter, &styleOptionTmp, widget); - else - drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); - - if (painterStateProtection || restorePainterClip) - painter->restore(); - - static int drawRect = qgetenv("QT_DRAW_SCENE_ITEM_RECTS").toInt(); - if (drawRect) { - QPen oldPen = painter->pen(); - QBrush oldBrush = painter->brush(); - quintptr ptr = reinterpret_cast<quintptr>(item); - const QColor color = QColor::fromHsv(ptr % 255, 255, 255); - painter->setPen(color); - painter->setBrush(Qt::NoBrush); - painter->drawRect(adjustedItemBoundingRect(item)); - painter->setPen(oldPen); - painter->setBrush(oldBrush); - } - } - - // Draw children in front - if (itemHasChildren) { - if (setChildClip) - setClip(painter, item); - - for (; i < item->d_ptr->children.size(); ++i) { - QGraphicsItem *child = item->d_ptr->children.at(i); - if (wasDirtyParentSceneTransform) - child->d_ptr->dirtySceneTransform = 1; - if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) - continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); - } - - // Restore child clip - if (itemClipsChildrenToShape) - painter->restore(); - } -} - -void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, - bool force, bool ignoreOpacity, bool removingItemFromScene, - bool updateBoundingRect) -{ - Q_ASSERT(item); - if (updateAll) - return; - - if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) { - // If any of the item's ancestors ignore opacity, it means that the opacity - // was set to 0 (and the update request has not yet been processed). That - // also means that we have to ignore the opacity for the item itself; otherwise - // things like: parent->setOpacity(0); scene->removeItem(child) won't work. - // Note that we only do this when removing items from the scene. In all other - // cases the ignoreOpacity bit propagates properly in processDirtyItems, but - // since the item is removed immediately it won't be processed there. - QGraphicsItem *p = item->d_ptr->parent; - while (p) { - if (p->d_ptr->ignoreOpacity) { - item->d_ptr->ignoreOpacity = true; - break; - } - p = p->d_ptr->parent; - } - } - - if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force, - /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, - /*ignoreOpacity=*/ignoreOpacity)) { - if (item->d_ptr->dirty) { - // The item is already marked as dirty and will be processed later. However, - // we have to make sure ignoreVisible and ignoreOpacity are set properly; - // otherwise things like: item->update(); item->hide() (force is now true) - // won't work as expected. - if (force) - item->d_ptr->ignoreVisible = 1; - if (ignoreOpacity) - item->d_ptr->ignoreOpacity = 1; - } - return; - } - - const bool fullItemUpdate = rect.isNull(); - if (!fullItemUpdate && rect.isEmpty()) - return; - - if (!processDirtyItemsEmitted) { - QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex); - method.invoke(q_ptr, Qt::QueuedConnection); -// QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection); - processDirtyItemsEmitted = true; - } - - if (removingItemFromScene) { - // Note that this function can be called from the item's destructor, so - // do NOT call any virtual functions on it within this block. - if (isSignalConnected(changedSignalIndex) || views.isEmpty()) { - // This block of code is kept for compatibility. Since 4.5, by default - // QGraphicsView does not connect the signal and we use the below - // method of delivering updates. - q_func()->update(); - return; - } - - for (int i = 0; i < views.size(); ++i) { - QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func(); - QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport); - rect.translate(viewPrivate->dirtyScrollOffset); - viewPrivate->updateRect(rect); - } - return; - } - - bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents; - if (!hasNoContents) { - item->d_ptr->dirty = 1; - if (fullItemUpdate) - item->d_ptr->fullUpdatePending = 1; - else if (!item->d_ptr->fullUpdatePending) - item->d_ptr->needsRepaint |= rect; - } else if (item->d_ptr->graphicsEffect) { - invalidateChildren = true; - } - - if (invalidateChildren) { - item->d_ptr->allChildrenDirty = 1; - item->d_ptr->dirtyChildren = 1; - } - - if (force) - item->d_ptr->ignoreVisible = 1; - if (ignoreOpacity) - item->d_ptr->ignoreOpacity = 1; - - if (!updateBoundingRect) - item->d_ptr->markParentDirty(); -} - -static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, - const QRectF &rect, bool itemIsUntransformable) -{ - Q_ASSERT(view); - Q_ASSERT(item); - - QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr); - QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr); - - if (itemIsUntransformable) { - const QTransform xform = itemq->deviceTransform(viewq->viewportTransform()); - if (!item->hasBoundingRegionGranularity) - return view->updateRectF(xform.mapRect(rect)); - return view->updateRegion(rect, xform); - } - - if (item->sceneTransformTranslateOnly && view->identityMatrix) { - const qreal dx = item->sceneTransform.dx(); - const qreal dy = item->sceneTransform.dy(); - QRectF r(rect); - r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll()); - return view->updateRectF(r); - } - - if (!viewq->isTransformed()) { - if (!item->hasBoundingRegionGranularity) - return view->updateRectF(item->sceneTransform.mapRect(rect)); - return view->updateRegion(rect, item->sceneTransform); - } - - QTransform xform = item->sceneTransform; - xform *= viewq->viewportTransform(); - if (!item->hasBoundingRegionGranularity) - return view->updateRectF(xform.mapRect(rect)); - return view->updateRegion(rect, xform); -} - -void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, - qreal parentOpacity) -{ - Q_Q(QGraphicsScene); - Q_ASSERT(item); - Q_ASSERT(!updateAll); - - if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) { - resetDirtyItem(item); - return; - } - - const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; - if (itemIsHidden) { - resetDirtyItem(item, /*recursive=*/true); - return; - } - - bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents); - const bool itemHasChildren = !item->d_ptr->children.isEmpty(); - if (!itemHasContents) { - if (!itemHasChildren) { - resetDirtyItem(item); - return; // Item has neither contents nor children!(?) - } - if (item->d_ptr->graphicsEffect) - itemHasContents = true; - } - - const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity - && QGraphicsItemPrivate::isOpacityNull(opacity); - if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) { - resetDirtyItem(item, /*recursive=*/itemHasChildren); - return; - } - - bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform; - const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); - if (wasDirtyParentSceneTransform && !itemIsUntransformable) { - item->d_ptr->updateSceneTransformFromParent(); - Q_ASSERT(!item->d_ptr->dirtySceneTransform); - } - - const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; - if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) { - // Make sure we don't process invisible items or items with no content. - item->d_ptr->dirty = 0; - item->d_ptr->fullUpdatePending = 0; - // Might have a dirty view bounding rect otherwise. - if (itemIsFullyTransparent || !itemHasContents) - item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; - } - - if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) { - // Update growingItemsBoundingRect. - if (item->d_ptr->sceneTransformTranslateOnly) { - growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(), - item->d_ptr->sceneTransform.dy()); - } else { - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); - } - } - - // Process item. - if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { - const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex); - const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item); - - if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { - // This block of code is kept for compatibility. Since 4.5, by default - // QGraphicsView does not connect the signal and we use the below - // method of delivering updates. - if (item->d_ptr->sceneTransformTranslateOnly) { - q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(), - item->d_ptr->sceneTransform.dy())); - } else { - QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect); - if (!rect.isEmpty()) - q->update(rect); - } - } else { - QRectF dirtyRect; - bool uninitializedDirtyRect = true; - - for (int j = 0; j < views.size(); ++j) { - QGraphicsView *view = views.at(j); - QGraphicsViewPrivate *viewPrivate = view->d_func(); - QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; - if (viewPrivate->fullUpdatePending - || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) { - // Okay, if we have a full update pending or no viewport update, this item's - // paintedViewBoundingRect will be updated correctly in the next paintEvent if - // it is inside the viewport, but for now we can pretend that it is outside. - paintedViewBoundingRect = QRect(-1, -1, -1, -1); - continue; - } - - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { - paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); - if (!viewPrivate->updateRect(paintedViewBoundingRect)) - paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. - } - - if (!item->d_ptr->dirty) - continue; - - if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint - && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1 - && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) { - continue; // Outside viewport. - } - - if (uninitializedDirtyRect) { - dirtyRect = itemBoundingRect; - if (!item->d_ptr->fullUpdatePending) { - _q_adjustRect(&item->d_ptr->needsRepaint); - dirtyRect &= item->d_ptr->needsRepaint; - } - uninitializedDirtyRect = false; - } - - if (dirtyRect.isEmpty()) - continue; // Discard updates outside the bounding rect. - - if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable) - && item->d_ptr->paintedViewBoundingRectsNeedRepaint) { - paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. - } - } - } - } - - // Process children. - if (itemHasChildren && item->d_ptr->dirtyChildren) { - const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; - // Items with no content are threated as 'dummy' items which means they are never drawn and - // 'processed', so the painted view bounding rect is never up-to-date. This means that whenever - // such an item changes geometry, its children have to take care of the update regardless - // of whether the item clips children to shape or not. - const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects; - if (itemClipsChildrenToShape && !bypassUpdateClip) { - // Make sure child updates are clipped to the item's bounding rect. - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->setUpdateClip(item); - } - if (!dirtyAncestorContainsChildren) { - dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending - && itemClipsChildrenToShape; - } - const bool allChildrenDirty = item->d_ptr->allChildrenDirty; - const bool parentIgnoresVisible = item->d_ptr->ignoreVisible; - const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity; - for (int i = 0; i < item->d_ptr->children.size(); ++i) { - QGraphicsItem *child = item->d_ptr->children.at(i); - if (wasDirtyParentSceneTransform) - child->d_ptr->dirtySceneTransform = 1; - if (wasDirtyParentViewBoundingRects) - child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1; - if (parentIgnoresVisible) - child->d_ptr->ignoreVisible = 1; - if (parentIgnoresOpacity) - child->d_ptr->ignoreOpacity = 1; - if (allChildrenDirty) { - child->d_ptr->dirty = 1; - child->d_ptr->fullUpdatePending = 1; - child->d_ptr->dirtyChildren = 1; - child->d_ptr->allChildrenDirty = 1; - } - processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity); - } - - if (itemClipsChildrenToShape) { - // Reset updateClip. - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->setUpdateClip(0); - } - } else if (wasDirtyParentSceneTransform) { - item->d_ptr->invalidateChildrenSceneTransform(); - } - - resetDirtyItem(item); -} - -/*! - \obsolete - - Paints the given \a items using the provided \a painter, after the - background has been drawn, and before the foreground has been - drawn. All painting is done in \e scene coordinates. Before - drawing each item, the painter must be transformed using - QGraphicsItem::sceneTransform(). - - The \a options parameter is the list of style option objects for - each item in \a items. The \a numItems parameter is the number of - items in \a items and options in \a options. The \a widget - parameter is optional; if specified, it should point to the widget - that is being painted on. - - The default implementation prepares the painter matrix, and calls - QGraphicsItem::paint() on all items. Reimplement this function to - provide custom painting of all items for the scene; gaining - complete control over how each item is drawn. In some cases this - can increase drawing performance significantly. - - Example: - - \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0 - - Since Qt 4.6, this function is not called anymore unless - the QGraphicsView::IndirectPainting flag is given as an Optimization - flag. - - \sa drawBackground(), drawForeground() -*/ -void QGraphicsScene::drawItems(QPainter *painter, - int numItems, - QGraphicsItem *items[], - const QStyleOptionGraphicsItem options[], QWidget *widget) -{ - Q_D(QGraphicsScene); - // Make sure we don't have unpolished items before we draw. - if (!d->unpolishedItems.isEmpty()) - d->_q_polishItems(); - - const qreal opacity = painter->opacity(); - QTransform viewTransform = painter->worldTransform(); - Q_UNUSED(options); - - // Determine view, expose and flags. - QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0; - QRegion *expose = 0; - const quint32 oldRectAdjust = d->rectAdjust; - if (view) { - d->updateAll = false; - expose = &view->d_func()->exposedRegion; - if (view->d_func()->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - d->rectAdjust = 1; - else - d->rectAdjust = 2; - } - - // Find all toplevels, they are already sorted. - QList<QGraphicsItem *> topLevelItems; - for (int i = 0; i < numItems; ++i) { - QGraphicsItem *item = items[i]->topLevelItem(); - if (!item->d_ptr->itemDiscovered) { - topLevelItems << item; - item->d_ptr->itemDiscovered = 1; - d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget); - } - } - - d->rectAdjust = oldRectAdjust; - // Reset discovery bits. - for (int i = 0; i < topLevelItems.size(); ++i) - topLevelItems.at(i)->d_ptr->itemDiscovered = 0; - - painter->setWorldTransform(viewTransform); - painter->setOpacity(opacity); -} - -/*! - \since 4.4 - - Finds a new widget to give the keyboard focus to, as appropriate for Tab - and Shift+Tab, and returns true if it can find a new widget, or false if - it cannot. If \a next is true, this function searches forward; if \a next - is false, it searches backward. - - You can reimplement this function in a subclass of QGraphicsScene to - provide fine-grained control over how tab focus passes inside your - scene. The default implementation is based on the tab focus chain defined - by QGraphicsWidget::setTabOrder(). -*/ -bool QGraphicsScene::focusNextPrevChild(bool next) -{ - Q_D(QGraphicsScene); - - QGraphicsItem *item = focusItem(); - if (item && !item->isWidget()) { - // Tab out of the scene. - return false; - } - if (!item) { - if (d->lastFocusItem && !d->lastFocusItem->isWidget()) { - // Restore focus to the last focusable non-widget item that had - // focus. - setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason); - return true; - } - } - if (!d->tabFocusFirst) { - // No widgets... - return false; - } - - // The item must be a widget. - QGraphicsWidget *widget = 0; - if (!item) { - widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev; - } else { - QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item); - widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev; - if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev)) - return false; - } - QGraphicsWidget *widgetThatHadFocus = widget; - - // Run around the focus chain until we find a widget that can take tab focus. - do { - if (widget->flags() & QGraphicsItem::ItemIsFocusable - && widget->isEnabled() && widget->isVisibleTo(0) - && (widget->focusPolicy() & Qt::TabFocus) - && (!item || !item->isPanel() || item->isAncestorOf(widget)) - ) { - setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason); - return true; - } - widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev; - if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev)) - return false; - } while (widget != widgetThatHadFocus); - - return false; -} - -/*! - \fn QGraphicsScene::changed(const QList<QRectF> ®ion) - - This signal is emitted by QGraphicsScene when control reaches the - event loop, if the scene content changes. The \a region parameter - contains a list of scene rectangles that indicate the area that - has been changed. - - \sa QGraphicsView::updateScene() -*/ - -/*! - \fn QGraphicsScene::sceneRectChanged(const QRectF &rect) - - This signal is emitted by QGraphicsScene whenever the scene rect changes. - The \a rect parameter is the new scene rectangle. - - \sa QGraphicsView::updateSceneRect() -*/ - -/*! - \fn QGraphicsScene::selectionChanged() - \since 4.3 - - This signal is emitted by QGraphicsScene whenever the selection - changes. You can call selectedItems() to get the new list of selected - items. - - The selection changes whenever an item is selected or unselected, a - selection area is set, cleared or otherwise changed, if a preselected item - is added to the scene, or if a selected item is removed from the scene. - - QGraphicsScene emits this signal only once for group selection operations. - For example, if you set a selection area, select or unselect a - QGraphicsItemGroup, or if you add or remove from the scene a parent item - that contains several selected items, selectionChanged() is emitted only - once after the operation has completed (instead of once for each item). - - \sa setSelectionArea(), selectedItems(), QGraphicsItem::setSelected() -*/ - -/*! - \since 4.4 - - Returns the scene's style, or the same as QApplication::style() if the - scene has not been explicitly assigned a style. - - \sa setStyle() -*/ -QStyle *QGraphicsScene::style() const -{ - Q_D(const QGraphicsScene); - // ### This function, and the use of styles in general, is non-reentrant. - return d->style ? d->style : QApplication::style(); -} - -/*! - \since 4.4 - - Sets or replaces the style of the scene to \a style, and reparents the - style to this scene. Any previously assigned style is deleted. The scene's - style defaults to QApplication::style(), and serves as the default for all - QGraphicsWidget items in the scene. - - Changing the style, either directly by calling this function, or - indirectly by calling QApplication::setStyle(), will automatically update - the style for all widgets in the scene that do not have a style explicitly - assigned to them. - - If \a style is 0, QGraphicsScene will revert to QApplication::style(). - - \sa style() -*/ -void QGraphicsScene::setStyle(QStyle *style) -{ - Q_D(QGraphicsScene); - // ### This function, and the use of styles in general, is non-reentrant. - if (style == d->style) - return; - - // Delete the old style, - delete d->style; - if ((d->style = style)) - d->style->setParent(this); - - // Notify the scene. - QEvent event(QEvent::StyleChange); - QApplication::sendEvent(this, &event); - - // Notify all widgets that don't have a style explicitly set. - foreach (QGraphicsItem *item, items()) { - if (item->isWidget()) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); - if (!widget->testAttribute(Qt::WA_SetStyle)) - QApplication::sendEvent(widget, &event); - } - } -} - -/*! - \property QGraphicsScene::font - \since 4.4 - \brief the scene's default font - - This property provides the scene's font. The scene font defaults to, - and resolves all its entries from, QApplication::font. - - If the scene's font changes, either directly through setFont() or - indirectly when the application font changes, QGraphicsScene first - sends itself a \l{QEvent::FontChange}{FontChange} event, and it then - sends \l{QEvent::FontChange}{FontChange} events to all top-level - widget items in the scene. These items respond by resolving their own - fonts to the scene, and they then notify their children, who again - notify their children, and so on, until all widget items have updated - their fonts. - - Changing the scene font, (directly or indirectly through - QApplication::setFont(),) automatically schedules a redraw the entire - scene. - - \sa QWidget::font, QApplication::setFont(), palette, style() -*/ -QFont QGraphicsScene::font() const -{ - Q_D(const QGraphicsScene); - return d->font; -} -void QGraphicsScene::setFont(const QFont &font) -{ - Q_D(QGraphicsScene); - QFont naturalFont = QApplication::font(); - naturalFont.resolve(0); - QFont resolvedFont = font.resolve(naturalFont); - d->setFont_helper(resolvedFont); -} - -/*! - \property QGraphicsScene::palette - \since 4.4 - \brief the scene's default palette - - This property provides the scene's palette. The scene palette defaults to, - and resolves all its entries from, QApplication::palette. - - If the scene's palette changes, either directly through setPalette() or - indirectly when the application palette changes, QGraphicsScene first - sends itself a \l{QEvent::PaletteChange}{PaletteChange} event, and it then - sends \l{QEvent::PaletteChange}{PaletteChange} events to all top-level - widget items in the scene. These items respond by resolving their own - palettes to the scene, and they then notify their children, who again - notify their children, and so on, until all widget items have updated - their palettes. - - Changing the scene palette, (directly or indirectly through - QApplication::setPalette(),) automatically schedules a redraw the entire - scene. - - \sa QWidget::palette, QApplication::setPalette(), font, style() -*/ -QPalette QGraphicsScene::palette() const -{ - Q_D(const QGraphicsScene); - return d->palette; -} -void QGraphicsScene::setPalette(const QPalette &palette) -{ - Q_D(QGraphicsScene); - QPalette naturalPalette = QApplication::palette(); - naturalPalette.resolve(0); - QPalette resolvedPalette = palette.resolve(naturalPalette); - d->setPalette_helper(resolvedPalette); -} - -/*! - \since 4.6 - - Returns true if the scene is active (e.g., it's viewed by - at least one QGraphicsView that is active); otherwise returns false. - - \sa QGraphicsItem::isActive(), QWidget::isActiveWindow() -*/ -bool QGraphicsScene::isActive() const -{ - Q_D(const QGraphicsScene); - return d->activationRefCount > 0; -} - -/*! - \since 4.6 - Returns the current active panel, or 0 if no panel is currently active. - - \sa QGraphicsScene::setActivePanel() -*/ -QGraphicsItem *QGraphicsScene::activePanel() const -{ - Q_D(const QGraphicsScene); - return d->activePanel; -} - -/*! - \since 4.6 - Activates \a item, which must be an item in this scene. You - can also pass 0 for \a item, in which case QGraphicsScene will - deactivate any currently active panel. - - If the scene is currently inactive, \a item remains inactive until the - scene becomes active (or, ir \a item is 0, no item will be activated). - - \sa activePanel(), isActive(), QGraphicsItem::isActive() -*/ -void QGraphicsScene::setActivePanel(QGraphicsItem *item) -{ - Q_D(QGraphicsScene); - d->setActivePanelHelper(item, false); -} - -/*! - \since 4.4 - - Returns the current active window, or 0 if no window is currently - active. - - \sa QGraphicsScene::setActiveWindow() -*/ -QGraphicsWidget *QGraphicsScene::activeWindow() const -{ - Q_D(const QGraphicsScene); - if (d->activePanel && d->activePanel->isWindow()) - return static_cast<QGraphicsWidget *>(d->activePanel); - return 0; -} - -/*! - \since 4.4 - Activates \a widget, which must be a widget in this scene. You can also - pass 0 for \a widget, in which case QGraphicsScene will deactivate any - currently active window. - - \sa activeWindow(), QGraphicsWidget::isActiveWindow() -*/ -void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) -{ - if (widget && widget->scene() != this) { - qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene", - widget); - return; - } - - // Activate the widget's panel (all windows are panels). - QGraphicsItem *panel = widget ? widget->panel() : 0; - setActivePanel(panel); - - // Raise - if (panel) { - QList<QGraphicsItem *> siblingWindows; - QGraphicsItem *parent = panel->parentItem(); - // Raise ### inefficient for toplevels - foreach (QGraphicsItem *sibling, parent ? parent->children() : items()) { - if (sibling != panel && sibling->isWindow()) - siblingWindows << sibling; - } - - // Find the highest z value. - qreal z = panel->zValue(); - for (int i = 0; i < siblingWindows.size(); ++i) - z = qMax(z, siblingWindows.at(i)->zValue()); - - // This will probably never overflow. - const qreal litt = qreal(0.001); - panel->setZValue(z + litt); - } -} - -/*! - \since 4.6 - - Sends event \a event to item \a item through possible event filters. - - The event is sent only if the item is enabled. - - Returns \c false if the event was filtered or if the item is disabled. - Otherwise returns the value that was returned from the event handler. - - \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter() -*/ -bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event) -{ - Q_D(QGraphicsScene); - if (!item) { - qWarning("QGraphicsScene::sendEvent: cannot send event to a null item"); - return false; - } - if (item->scene() != this) { - qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)" - " is different from this scene (%p)", - item, item->scene(), this); - return false; - } - return d->sendEvent(item, event); -} - -void QGraphicsScenePrivate::addView(QGraphicsView *view) -{ - views << view; -#ifndef QT_NO_GESTURES - foreach (Qt::GestureType gesture, grabbedGestures.keys()) - view->viewport()->grabGesture(gesture); -#endif -} - -void QGraphicsScenePrivate::removeView(QGraphicsView *view) -{ - views.removeAll(view); -} - -void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent) -{ - QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints(); - for (int i = 0; i < touchPoints.count(); ++i) { - QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; - touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect()); - touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), touchEvent->widget())); - touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), touchEvent->widget())); - } - touchEvent->setTouchPoints(touchPoints); -} - -int QGraphicsScenePrivate::findClosestTouchPointId(const QPointF &scenePos) -{ - int closestTouchPointId = -1; - qreal closestDistance = qreal(0.); - foreach (const QTouchEvent::TouchPoint &touchPoint, sceneCurrentTouchPoints) { - qreal distance = QLineF(scenePos, touchPoint.scenePos()).length(); - if (closestTouchPointId == -1|| distance < closestDistance) { - closestTouchPointId = touchPoint.id(); - closestDistance = distance; - } - } - return closestTouchPointId; -} - -void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent) -{ - typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints; - QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents; - - for (int i = 0; i < sceneTouchEvent->touchPoints().count(); ++i) { - const QTouchEvent::TouchPoint &touchPoint = sceneTouchEvent->touchPoints().at(i); - - // update state - QGraphicsItem *item = 0; - if (touchPoint.state() == Qt::TouchPointPressed) { - if (sceneTouchEvent->deviceType() == QTouchEvent::TouchPad) { - // on touch-pad devices, send all touch points to the same item - item = itemForTouchPointId.isEmpty() - ? 0 - : itemForTouchPointId.constBegin().value(); - } - - if (!item) { - // determine which item this touch point will go to - cachedItemsUnderMouse = itemsAtPosition(touchPoint.screenPos().toPoint(), - touchPoint.scenePos(), - sceneTouchEvent->widget()); - item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first(); - } - - if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) { - // on touch-screens, combine this touch point with the closest one we find - int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos()); - QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId); - if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem))) - item = closestItem; - } - if (!item) - continue; - - itemForTouchPointId.insert(touchPoint.id(), item); - sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint); - } else if (touchPoint.state() == Qt::TouchPointReleased) { - item = itemForTouchPointId.take(touchPoint.id()); - if (!item) - continue; - - sceneCurrentTouchPoints.remove(touchPoint.id()); - } else { - item = itemForTouchPointId.value(touchPoint.id()); - if (!item) - continue; - Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id())); - sceneCurrentTouchPoints[touchPoint.id()] = touchPoint; - } - - StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item]; - statesAndTouchPoints.first |= touchPoint.state(); - statesAndTouchPoints.second.append(touchPoint); - } - - if (itemsNeedingEvents.isEmpty()) { - sceneTouchEvent->accept(); - return; - } - - bool ignoreSceneTouchEvent = true; - QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin(); - const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd(); - for (; it != end; ++it) { - QGraphicsItem *item = it.key(); - - (void) item->isBlockedByModalPanel(&item); - - // determine event type from the state mask - QEvent::Type eventType; - switch (it.value().first) { - case Qt::TouchPointPressed: - // all touch points have pressed state - eventType = QEvent::TouchBegin; - break; - case Qt::TouchPointReleased: - // all touch points have released state - eventType = QEvent::TouchEnd; - break; - case Qt::TouchPointStationary: - // don't send the event if nothing changed - continue; - default: - // all other combinations - eventType = QEvent::TouchUpdate; - break; - } - - QTouchEvent touchEvent(eventType); - touchEvent.setWidget(sceneTouchEvent->widget()); - touchEvent.setDeviceType(sceneTouchEvent->deviceType()); - touchEvent.setModifiers(sceneTouchEvent->modifiers()); - touchEvent.setTouchPointStates(it.value().first); - touchEvent.setTouchPoints(it.value().second); - - switch (touchEvent.type()) { - case QEvent::TouchBegin: - { - // if the TouchBegin handler recurses, we assume that means the event - // has been implicitly accepted and continue to send touch events - item->d_ptr->acceptedTouchBeginEvent = true; - bool res = sendTouchBeginEvent(item, &touchEvent) - && touchEvent.isAccepted(); - if (!res) { - // forget about these touch points, we didn't handle them - for (int i = 0; i < touchEvent.touchPoints().count(); ++i) { - const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i); - itemForTouchPointId.remove(touchPoint.id()); - sceneCurrentTouchPoints.remove(touchPoint.id()); - } - ignoreSceneTouchEvent = false; - } - break; - } - default: - if (item->d_ptr->acceptedTouchBeginEvent) { - updateTouchPointsForItem(item, &touchEvent); - (void) sendEvent(item, &touchEvent); - ignoreSceneTouchEvent = false; - } - break; - } - } - sceneTouchEvent->setAccepted(ignoreSceneTouchEvent); -} - -bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent) -{ - Q_Q(QGraphicsScene); - - if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) { - const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first(); - cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(), - firstTouchPoint.scenePos(), - touchEvent->widget()); - } - Q_ASSERT(cachedItemsUnderMouse.first() == origin); - - // Set focus on the topmost enabled item that can take focus. - bool setFocus = false; - - foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { - if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { - setFocus = true; - if (item != q->focusItem()) - q->setFocusItem(item, Qt::MouseFocusReason); - break; - } - } - if (item->isPanel()) - break; - if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) - break; - if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) { - // Make sure we don't clear focus. - setFocus = true; - break; - } - } - - // If nobody could take focus, clear it. - if (!stickyFocus && !setFocus) - q->setFocusItem(0, Qt::MouseFocusReason); - - bool res = false; - bool eventAccepted = touchEvent->isAccepted(); - foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - // first, try to deliver the touch event - updateTouchPointsForItem(item, touchEvent); - bool acceptTouchEvents = item->acceptTouchEvents(); - touchEvent->setAccepted(acceptTouchEvents); - res = acceptTouchEvents && sendEvent(item, touchEvent); - eventAccepted = touchEvent->isAccepted(); - if (itemForTouchPointId.value(touchEvent->touchPoints().first().id()) == 0) { - // item was deleted - item = 0; - } else { - item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted); - } - touchEvent->spont = false; - if (res && eventAccepted) { - // the first item to accept the TouchBegin gets an implicit grab. - for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { - const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); - itemForTouchPointId[touchPoint.id()] = item; // can be zero - } - break; - } - if (item && item->isPanel()) - break; - } - - touchEvent->setAccepted(eventAccepted); - return res; -} - -void QGraphicsScenePrivate::enableTouchEventsOnViews() -{ - foreach (QGraphicsView *view, views) - view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true); -} - -void QGraphicsScenePrivate::updateInputMethodSensitivityInViews() -{ - for (int i = 0; i < views.size(); ++i) - views.at(i)->d_func()->updateInputMethodSensitivity(); -} - -void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality) -{ - Q_Q(QGraphicsScene); - Q_ASSERT(panel && panel->isPanel()); - - QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality; - if (previousModality != QGraphicsItem::NonModal) { - // the panel is changing from one modality type to another... temporarily set it back so - // that blockedPanels is populated correctly - panel->d_ptr->panelModality = previousModality; - } - - QSet<QGraphicsItem *> blockedPanels; - QList<QGraphicsItem *> items = q->items(); // ### store panels separately - for (int i = 0; i < items.count(); ++i) { - QGraphicsItem *item = items.at(i); - if (item->isPanel() && item->isBlockedByModalPanel()) - blockedPanels.insert(item); - } - // blockedPanels contains all currently blocked panels - - if (previousModality != QGraphicsItem::NonModal) { - // reset the modality to the proper value, since we changed it above - panel->d_ptr->panelModality = panelModality; - // remove this panel so that it will be reinserted at the front of the stack - modalPanels.removeAll(panel); - } - - modalPanels.prepend(panel); - - if (!hoverItems.isEmpty()) { - // send GraphicsSceneHoverLeave events to newly blocked hoverItems - QGraphicsSceneHoverEvent hoverEvent; - hoverEvent.setScenePos(lastSceneMousePos); - dispatchHoverEvent(&hoverEvent); - } - - if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) { - QGraphicsItem *item = mouseGrabberItems.last(); - if (item->isBlockedByModalPanel()) - ungrabMouse(item, /*itemIsDying =*/ false); - } - - QEvent windowBlockedEvent(QEvent::WindowBlocked); - QEvent windowUnblockedEvent(QEvent::WindowUnblocked); - for (int i = 0; i < items.count(); ++i) { - QGraphicsItem *item = items.at(i); - if (item->isPanel()) { - if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) { - // send QEvent::WindowBlocked to newly blocked panels - sendEvent(item, &windowBlockedEvent); - } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) { - // send QEvent::WindowUnblocked to unblocked panels when downgrading - // a panel from SceneModal to PanelModal - sendEvent(item, &windowUnblockedEvent); - } - } - } -} - -void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel) -{ - Q_Q(QGraphicsScene); - Q_ASSERT(panel && panel->isPanel()); - - QSet<QGraphicsItem *> blockedPanels; - QList<QGraphicsItem *> items = q->items(); // ### same as above - for (int i = 0; i < items.count(); ++i) { - QGraphicsItem *item = items.at(i); - if (item->isPanel() && item->isBlockedByModalPanel()) - blockedPanels.insert(item); - } - - modalPanels.removeAll(panel); - - QEvent e(QEvent::WindowUnblocked); - for (int i = 0; i < items.count(); ++i) { - QGraphicsItem *item = items.at(i); - if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel()) - sendEvent(item, &e); - } - - // send GraphicsSceneHoverEnter events to newly unblocked items - QGraphicsSceneHoverEvent hoverEvent; - hoverEvent.setScenePos(lastSceneMousePos); - dispatchHoverEvent(&hoverEvent); -} - -#ifndef QT_NO_GESTURES -void QGraphicsScenePrivate::gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures, - Qt::GestureFlag flag, - QHash<QGraphicsObject *, QSet<QGesture *> > *targets, - QSet<QGraphicsObject *> *itemsSet, - QSet<QGesture *> *normal, - QSet<QGesture *> *conflicts) -{ - QSet<QGesture *> normalGestures; // that are not in conflicted state. - foreach (QGesture *gesture, gestures) { - if (!gesture->hasHotSpot()) - continue; - const Qt::GestureType gestureType = gesture->gestureType(); - QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, 0); - for (int j = 0; j < items.size(); ++j) { - QGraphicsItem *item = items.at(j); - - // Check if the item is blocked by a modal panel and use it as - // a target instead of this item. - (void) item->isBlockedByModalPanel(&item); - - if (QGraphicsObject *itemobj = item->toGraphicsObject()) { - QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); - QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it = - d->gestureContext.find(gestureType); - if (it != d->gestureContext.end() && (!flag || (it.value() & flag))) { - if (normalGestures.contains(gesture)) { - normalGestures.remove(gesture); - if (conflicts) - conflicts->insert(gesture); - } else { - normalGestures.insert(gesture); - } - if (targets) - (*targets)[itemobj].insert(gesture); - if (itemsSet) - (*itemsSet).insert(itemobj); - } - } - // Don't propagate through panels. - if (item->isPanel()) - break; - } - } - if (normal) - *normal = normalGestures; -} - -void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) -{ - QWidget *viewport = event->widget(); - if (!viewport) - return; - QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent()); - if (!graphicsView) - return; - - QList<QGesture *> allGestures = event->gestures(); - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "Gestures:" << allGestures; - - QSet<QGesture *> startedGestures; - QPoint delta = viewport->mapFromGlobal(QPoint()); - QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y()) - * graphicsView->viewportTransform().inverted(); - foreach (QGesture *gesture, allGestures) { - // cache scene coordinates of the hot spot - if (gesture->hasHotSpot()) { - gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot()); - } else { - gesture->d_func()->sceneHotSpot = QPointF(); - } - - QGraphicsObject *target = gestureTargets.value(gesture, 0); - if (!target) { - // when we are not in started mode but don't have a target - // then the only one interested in gesture is the view/scene - if (gesture->state() == Qt::GestureStarted) - startedGestures.insert(gesture); - } - } - - if (!startedGestures.isEmpty()) { - QSet<QGesture *> normalGestures; // that have just one target - QSet<QGesture *> conflictedGestures; // that have multiple possible targets - gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, 0, - &normalGestures, &conflictedGestures); - cachedTargetItems = cachedItemGestures.keys(); - qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst); - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "Normal gestures:" << normalGestures - << "Conflicting gestures:" << conflictedGestures; - - // deliver conflicted gestures as override events AND remember - // initial gesture targets - if (!conflictedGestures.isEmpty()) { - for (int i = 0; i < cachedTargetItems.size(); ++i) { - QWeakPointer<QGraphicsObject> item = cachedTargetItems.at(i); - - // get gestures to deliver to the current item - QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data()); - if (gestures.isEmpty()) - continue; - - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "delivering override to" - << item.data() << gestures; - // send gesture override - QGestureEvent ev(gestures.toList()); - ev.t = QEvent::GestureOverride; - ev.setWidget(event->widget()); - // mark event and individual gestures as ignored - ev.ignore(); - foreach(QGesture *g, gestures) - ev.setAccepted(g, false); - sendEvent(item.data(), &ev); - // mark all accepted gestures to deliver them as normal gesture events - foreach (QGesture *g, gestures) { - if (ev.isAccepted() || ev.isAccepted(g)) { - conflictedGestures.remove(g); - // mark the item as a gesture target - if (item) { - gestureTargets.insert(g, item.data()); - QHash<QGraphicsObject *, QSet<QGesture *> >::iterator it, e; - it = cachedItemGestures.begin(); - e = cachedItemGestures.end(); - for(; it != e; ++it) - it.value().remove(g); - cachedItemGestures[item.data()].insert(g); - } - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "override was accepted:" - << g << item.data(); - } - // remember the first item that received the override event - // as it most likely become a target if no one else accepts - // the override event - if (!gestureTargets.contains(g) && item) - gestureTargets.insert(g, item.data()); - - } - if (conflictedGestures.isEmpty()) - break; - } - } - // remember the initial target item for each gesture that was not in - // the conflicted state. - if (!normalGestures.isEmpty()) { - for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) { - QGraphicsObject *item = cachedTargetItems.at(i); - - // get gestures to deliver to the current item - foreach (QGesture *g, cachedItemGestures.value(item)) { - if (!gestureTargets.contains(g)) { - gestureTargets.insert(g, item); - normalGestures.remove(g); - } - } - } - } - } - - - // deliver all gesture events - QSet<QGesture *> undeliveredGestures; - QSet<QGesture *> parentPropagatedGestures; - foreach (QGesture *gesture, allGestures) { - if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) { - cachedItemGestures[target].insert(gesture); - cachedTargetItems.append(target); - undeliveredGestures.insert(gesture); - QGraphicsItemPrivate *d = target->QGraphicsItem::d_func(); - const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType()); - if (flags & Qt::IgnoredGesturesPropagateToParent) - parentPropagatedGestures.insert(gesture); - } else { - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "no target for" << gesture << "at" - << gesture->hotSpot() << gesture->d_func()->sceneHotSpot; - } - } - qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst); - for (int i = 0; i < cachedTargetItems.size(); ++i) { - QWeakPointer<QGraphicsObject> receiver = cachedTargetItems.at(i); - QSet<QGesture *> gestures = - undeliveredGestures & cachedItemGestures.value(receiver.data()); - gestures -= cachedAlreadyDeliveredGestures.value(receiver.data()); - - if (gestures.isEmpty()) - continue; - - cachedAlreadyDeliveredGestures[receiver.data()] += gestures; - const bool isPanel = receiver.data()->isPanel(); - - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "delivering to" - << receiver.data() << gestures; - QGestureEvent ev(gestures.toList()); - ev.setWidget(event->widget()); - sendEvent(receiver.data(), &ev); - QSet<QGesture *> ignoredGestures; - foreach (QGesture *g, gestures) { - if (!ev.isAccepted() && !ev.isAccepted(g)) { - // if the gesture was ignored by its target, we will update the - // targetItems list with a possible target items (items that - // want to receive partial gestures). - // ### wont' work if the target was destroyed in the event - // we will just stop delivering it. - if (receiver && receiver.data() == gestureTargets.value(g, 0)) - ignoredGestures.insert(g); - } else { - if (receiver && g->state() == Qt::GestureStarted) { - // someone accepted the propagated initial GestureStarted - // event, let it be the new target for all following events. - gestureTargets[g] = receiver.data(); - } - undeliveredGestures.remove(g); - } - } - if (undeliveredGestures.isEmpty()) - break; - - // ignoredGestures list is only filled when delivering to the gesture - // target item, so it is safe to assume item == target. - if (!ignoredGestures.isEmpty() && !isPanel) { - // look for new potential targets for gestures that were ignored - // and should be propagated. - - QSet<QGraphicsObject *> targetsSet = cachedTargetItems.toSet(); - - if (receiver) { - // first if the gesture should be propagated to parents only - for (QSet<QGesture *>::iterator it = ignoredGestures.begin(); - it != ignoredGestures.end();) { - if (parentPropagatedGestures.contains(*it)) { - QGesture *gesture = *it; - const Qt::GestureType gestureType = gesture->gestureType(); - QGraphicsItem *item = receiver.data(); - while (item) { - if (QGraphicsObject *obj = item->toGraphicsObject()) { - if (item->d_func()->gestureContext.contains(gestureType)) { - targetsSet.insert(obj); - cachedItemGestures[obj].insert(gesture); - } - } - if (item->isPanel()) - break; - item = item->parentItem(); - } - - it = ignoredGestures.erase(it); - continue; - } - ++it; - } - } - - gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures, - &cachedItemGestures, &targetsSet, 0, 0); - - cachedTargetItems = targetsSet.toList(); - qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst); - DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" - << "new targets:" << cachedTargetItems; - i = -1; // start delivery again - continue; - } - } - - foreach (QGesture *g, startedGestures) { - if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) { - DEBUG() << "lets try to cancel some"; - // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them - cancelGesturesForChildren(g); - } - } - - // forget about targets for gestures that have ended - foreach (QGesture *g, allGestures) { - switch (g->state()) { - case Qt::GestureFinished: - case Qt::GestureCanceled: - gestureTargets.remove(g); - break; - default: - break; - } - } - - cachedTargetItems.clear(); - cachedItemGestures.clear(); - cachedAlreadyDeliveredGestures.clear(); -} - -void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original) -{ - Q_ASSERT(original); - QGraphicsItem *originalItem = gestureTargets.value(original); - if (originalItem == 0) // we only act on accepted gestures, which implies it has a target. - return; - - // iterate over all active gestures and for each find the owner - // if the owner is part of our sub-hierarchy, cancel it. - - QSet<QGesture *> canceledGestures; - QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin(); - while (iter != gestureTargets.end()) { - QGraphicsObject *item = iter.value(); - // note that we don't touch the gestures for our originalItem - if (item != originalItem && originalItem->isAncestorOf(item)) { - DEBUG() << " found a gesture to cancel" << iter.key(); - iter.key()->d_func()->state = Qt::GestureCanceled; - canceledGestures << iter.key(); - } - ++iter; - } - - // sort them per target item by cherry picking from almostCanceledGestures and delivering - QSet<QGesture *> almostCanceledGestures = canceledGestures; - QSet<QGesture *>::Iterator setIter; - while (!almostCanceledGestures.isEmpty()) { - QGraphicsObject *target = 0; - QSet<QGesture*> gestures; - setIter = almostCanceledGestures.begin(); - // sort per target item - while (setIter != almostCanceledGestures.end()) { - QGraphicsObject *item = gestureTargets.value(*setIter); - if (target == 0) - target = item; - if (target == item) { - gestures << *setIter; - setIter = almostCanceledGestures.erase(setIter); - } else { - ++setIter; - } - } - Q_ASSERT(target); - - QList<QGesture *> list = gestures.toList(); - QGestureEvent ev(list); - sendEvent(target, &ev); - - foreach (QGesture *g, list) { - if (ev.isAccepted() || ev.isAccepted(g)) - gestures.remove(g); - } - - foreach (QGesture *g, gestures) { - if (!g->hasHotSpot()) - continue; - - QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, 0); - for (int j = 0; j < items.size(); ++j) { - QGraphicsObject *item = items.at(j)->toGraphicsObject(); - if (!item) - continue; - QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); - if (d->gestureContext.contains(g->gestureType())) { - QList<QGesture *> list; - list << g; - QGestureEvent ev(list); - sendEvent(item, &ev); - if (ev.isAccepted() || ev.isAccepted(g)) - break; // successfully delivered - } - } - } - } - - QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager; - Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager. - for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) { - gestureManager->recycle(*setIter); - gestureTargets.remove(*setIter); - } -} - -void QGraphicsScenePrivate::grabGesture(QGraphicsItem *, Qt::GestureType gesture) -{ - (void)QGestureManager::instance(); // create a gesture manager - if (!grabbedGestures[gesture]++) { - foreach (QGraphicsView *view, views) - view->viewport()->grabGesture(gesture); - } -} - -void QGraphicsScenePrivate::ungrabGesture(QGraphicsItem *item, Qt::GestureType gesture) -{ - // we know this can only be an object - Q_ASSERT(item->d_ptr->isObject); - QGraphicsObject *obj = static_cast<QGraphicsObject *>(item); - QGestureManager::instance()->cleanupCachedGestures(obj, gesture); - if (!--grabbedGestures[gesture]) { - foreach (QGraphicsView *view, views) - view->viewport()->ungrabGesture(gesture); - } -} -#endif // QT_NO_GESTURES - -QT_END_NAMESPACE - -#include "moc_qgraphicsscene.cpp" - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h deleted file mode 100644 index 5aff805b76..0000000000 --- a/src/gui/graphicsview/qgraphicsscene.h +++ /dev/null @@ -1,329 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENE_H -#define QGRAPHICSSCENE_H - -#include <QtCore/qobject.h> -#include <QtCore/qpoint.h> -#include <QtCore/qrect.h> -#include <QtGui/qbrush.h> -#include <QtGui/qfont.h> -#include <QtGui/qtransform.h> -#include <QtGui/qmatrix.h> -#include <QtGui/qpen.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -template<typename T> class QList; -class QFocusEvent; -class QFont; -class QFontMetrics; -class QGraphicsEllipseItem; -class QGraphicsItem; -class QGraphicsItemGroup; -class QGraphicsLineItem; -class QGraphicsPathItem; -class QGraphicsPixmapItem; -class QGraphicsPolygonItem; -class QGraphicsProxyWidget; -class QGraphicsRectItem; -class QGraphicsSceneContextMenuEvent; -class QGraphicsSceneDragDropEvent; -class QGraphicsSceneEvent; -class QGraphicsSceneHelpEvent; -class QGraphicsSceneHoverEvent; -class QGraphicsSceneMouseEvent; -class QGraphicsSceneWheelEvent; -class QGraphicsSimpleTextItem; -class QGraphicsTextItem; -class QGraphicsView; -class QGraphicsWidget; -class QGraphicsSceneIndex; -class QHelpEvent; -class QInputMethodEvent; -class QKeyEvent; -class QLineF; -class QPainterPath; -class QPixmap; -class QPointF; -class QPolygonF; -class QRectF; -class QSizeF; -class QStyle; -class QStyleOptionGraphicsItem; - -class QGraphicsScenePrivate; -class Q_GUI_EXPORT QGraphicsScene : public QObject -{ - Q_OBJECT - Q_PROPERTY(QBrush backgroundBrush READ backgroundBrush WRITE setBackgroundBrush) - Q_PROPERTY(QBrush foregroundBrush READ foregroundBrush WRITE setForegroundBrush) - Q_PROPERTY(ItemIndexMethod itemIndexMethod READ itemIndexMethod WRITE setItemIndexMethod) - Q_PROPERTY(QRectF sceneRect READ sceneRect WRITE setSceneRect) - Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) - Q_PROPERTY(QPalette palette READ palette WRITE setPalette) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled) - Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus) - -public: - enum ItemIndexMethod { - BspTreeIndex, - NoIndex = -1 - }; - - enum SceneLayer { - ItemLayer = 0x1, - BackgroundLayer = 0x2, - ForegroundLayer = 0x4, - AllLayers = 0xffff - }; - Q_DECLARE_FLAGS(SceneLayers, SceneLayer) - - QGraphicsScene(QObject *parent = 0); - QGraphicsScene(const QRectF &sceneRect, QObject *parent = 0); - QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent = 0); - virtual ~QGraphicsScene(); - - QRectF sceneRect() const; - inline qreal width() const { return sceneRect().width(); } - inline qreal height() const { return sceneRect().height(); } - void setSceneRect(const QRectF &rect); - inline void setSceneRect(qreal x, qreal y, qreal w, qreal h) - { setSceneRect(QRectF(x, y, w, h)); } - - void render(QPainter *painter, - const QRectF &target = QRectF(), const QRectF &source = QRectF(), - Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio); - - ItemIndexMethod itemIndexMethod() const; - void setItemIndexMethod(ItemIndexMethod method); - - bool isSortCacheEnabled() const; - void setSortCacheEnabled(bool enabled); - - int bspTreeDepth() const; - void setBspTreeDepth(int depth); - - QRectF itemsBoundingRect() const; - - QList<QGraphicsItem *> items() const; - QList<QGraphicsItem *> items(Qt::SortOrder order) const; // ### Qt 5: unify - - QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - - QList<QGraphicsItem *> items(const QPointF &pos) const; // ### obsolete - QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete - QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete - QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete - - QList<QGraphicsItem *> collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - - QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete - QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const; - - inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const - { return items(QRectF(x, y, w, h), mode); } // ### obsolete - inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, - const QTransform &deviceTransform = QTransform()) const - { return items(QRectF(x, y, w, h), mode, order, deviceTransform); } - inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete - { return itemAt(QPointF(x, y)); } - inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const - { return itemAt(QPointF(x, y), deviceTransform); } - - QList<QGraphicsItem *> selectedItems() const; - QPainterPath selectionArea() const; - void setSelectionArea(const QPainterPath &path); // ### obsolete - void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform); - void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); // ### obsolete - void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform); - - QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items); - void destroyItemGroup(QGraphicsItemGroup *group); - - void addItem(QGraphicsItem *item); - QGraphicsEllipseItem *addEllipse(const QRectF &rect, const QPen &pen = QPen(), const QBrush &brush = QBrush()); - QGraphicsLineItem *addLine(const QLineF &line, const QPen &pen = QPen()); - QGraphicsPathItem *addPath(const QPainterPath &path, const QPen &pen = QPen(), const QBrush &brush = QBrush()); - QGraphicsPixmapItem *addPixmap(const QPixmap &pixmap); - QGraphicsPolygonItem *addPolygon(const QPolygonF &polygon, const QPen &pen = QPen(), const QBrush &brush = QBrush()); - QGraphicsRectItem *addRect(const QRectF &rect, const QPen &pen = QPen(), const QBrush &brush = QBrush()); - QGraphicsTextItem *addText(const QString &text, const QFont &font = QFont()); - QGraphicsSimpleTextItem *addSimpleText(const QString &text, const QFont &font = QFont()); - QGraphicsProxyWidget *addWidget(QWidget *widget, Qt::WindowFlags wFlags = 0); - inline QGraphicsEllipseItem *addEllipse(qreal x, qreal y, qreal w, qreal h, const QPen &pen = QPen(), const QBrush &brush = QBrush()) - { return addEllipse(QRectF(x, y, w, h), pen, brush); } - inline QGraphicsLineItem *addLine(qreal x1, qreal y1, qreal x2, qreal y2, const QPen &pen = QPen()) - { return addLine(QLineF(x1, y1, x2, y2), pen); } - inline QGraphicsRectItem *addRect(qreal x, qreal y, qreal w, qreal h, const QPen &pen = QPen(), const QBrush &brush = QBrush()) - { return addRect(QRectF(x, y, w, h), pen, brush); } - void removeItem(QGraphicsItem *item); - - QGraphicsItem *focusItem() const; - void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason = Qt::OtherFocusReason); - bool hasFocus() const; - void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason); - void clearFocus(); - - void setStickyFocus(bool enabled); - bool stickyFocus() const; - - QGraphicsItem *mouseGrabberItem() const; - - QBrush backgroundBrush() const; - void setBackgroundBrush(const QBrush &brush); - - QBrush foregroundBrush() const; - void setForegroundBrush(const QBrush &brush); - - virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; - - QList <QGraphicsView *> views() const; - - inline void update(qreal x, qreal y, qreal w, qreal h) - { update(QRectF(x, y, w, h)); } - inline void invalidate(qreal x, qreal y, qreal w, qreal h, SceneLayers layers = AllLayers) - { invalidate(QRectF(x, y, w, h), layers); } - - QStyle *style() const; - void setStyle(QStyle *style); - - QFont font() const; - void setFont(const QFont &font); - - QPalette palette() const; - void setPalette(const QPalette &palette); - - bool isActive() const; - QGraphicsItem *activePanel() const; - void setActivePanel(QGraphicsItem *item); - QGraphicsWidget *activeWindow() const; - void setActiveWindow(QGraphicsWidget *widget); - - bool sendEvent(QGraphicsItem *item, QEvent *event); - -public Q_SLOTS: - void update(const QRectF &rect = QRectF()); - void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers); - void advance(); - void clearSelection(); - void clear(); - -protected: - bool event(QEvent *event); - bool eventFilter(QObject *watched, QEvent *event); - virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); - virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event); - virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event); - virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent *event); - virtual void dropEvent(QGraphicsSceneDragDropEvent *event); - virtual void focusInEvent(QFocusEvent *event); - virtual void focusOutEvent(QFocusEvent *event); - virtual void helpEvent(QGraphicsSceneHelpEvent *event); - virtual void keyPressEvent(QKeyEvent *event); - virtual void keyReleaseEvent(QKeyEvent *event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); - virtual void wheelEvent(QGraphicsSceneWheelEvent *event); - virtual void inputMethodEvent(QInputMethodEvent *event); - - virtual void drawBackground(QPainter *painter, const QRectF &rect); - virtual void drawForeground(QPainter *painter, const QRectF &rect); - virtual void drawItems(QPainter *painter, int numItems, - QGraphicsItem *items[], - const QStyleOptionGraphicsItem options[], - QWidget *widget = 0); - -protected Q_SLOTS: - bool focusNextPrevChild(bool next); - -Q_SIGNALS: - void changed(const QList<QRectF> ®ion); - void sceneRectChanged(const QRectF &rect); - void selectionChanged(); - -private: - Q_DECLARE_PRIVATE(QGraphicsScene) - Q_DISABLE_COPY(QGraphicsScene) - Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) - Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) - Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems()) - Q_PRIVATE_SLOT(d_func(), void _q_updateScenePosDescendants()) - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - friend class QGraphicsObject; - friend class QGraphicsView; - friend class QGraphicsViewPrivate; - friend class QGraphicsWidget; - friend class QGraphicsWidgetPrivate; - friend class QGraphicsEffect; - friend class QGraphicsSceneIndex; - friend class QGraphicsSceneIndexPrivate; - friend class QGraphicsSceneBspTreeIndex; - friend class QGraphicsSceneBspTreeIndexPrivate; - friend class QGraphicsItemEffectSourcePrivate; -#ifndef QT_NO_GESTURES - friend class QGesture; -#endif -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp deleted file mode 100644 index cc8a558ad3..0000000000 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgraphicsscene_bsp_p.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include <QtCore/qstring.h> -#include <private/qgraphicsitem_p.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsSceneInsertItemBspTreeVisitor : public QGraphicsSceneBspTreeVisitor -{ -public: - QGraphicsItem *item; - - void visit(QList<QGraphicsItem *> *items) - { items->prepend(item); } -}; - -class QGraphicsSceneRemoveItemBspTreeVisitor : public QGraphicsSceneBspTreeVisitor -{ -public: - QGraphicsItem *item; - - void visit(QList<QGraphicsItem *> *items) - { items->removeAll(item); } -}; - -class QGraphicsSceneFindItemBspTreeVisitor : public QGraphicsSceneBspTreeVisitor -{ -public: - QList<QGraphicsItem *> *foundItems; - bool onlyTopLevelItems; - - void visit(QList<QGraphicsItem *> *items) - { - for (int i = 0; i < items->size(); ++i) { - QGraphicsItem *item = items->at(i); - if (onlyTopLevelItems && item->d_ptr->parent) - item = item->topLevelItem(); - if (!item->d_func()->itemDiscovered && item->d_ptr->visible) { - item->d_func()->itemDiscovered = 1; - foundItems->prepend(item); - } - } - } -}; - -QGraphicsSceneBspTree::QGraphicsSceneBspTree() - : leafCnt(0) -{ - insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; - removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; - findVisitor = new QGraphicsSceneFindItemBspTreeVisitor; -} - -QGraphicsSceneBspTree::~QGraphicsSceneBspTree() -{ - delete insertVisitor; - delete removeVisitor; - delete findVisitor; -} - -void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth) -{ - this->rect = rect; - leafCnt = 0; - nodes.resize((1 << (depth + 1)) - 1); - nodes.fill(Node()); - leaves.resize(1 << depth); - leaves.fill(QList<QGraphicsItem *>()); - - initialize(rect, depth, 0); -} - -void QGraphicsSceneBspTree::clear() -{ - leafCnt = 0; - nodes.clear(); - leaves.clear(); -} - -void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item, const QRectF &rect) -{ - insertVisitor->item = item; - climbTree(insertVisitor, rect); -} - -void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item, const QRectF &rect) -{ - removeVisitor->item = item; - climbTree(removeVisitor, rect); -} - -void QGraphicsSceneBspTree::removeItems(const QSet<QGraphicsItem *> &items) -{ - for (int i = 0; i < leaves.size(); ++i) { - QList<QGraphicsItem *> newItemList; - const QList<QGraphicsItem *> &oldItemList = leaves[i]; - for (int j = 0; j < oldItemList.size(); ++j) { - QGraphicsItem *item = oldItemList.at(j); - if (!items.contains(item)) - newItemList << item; - } - leaves[i] = newItemList; - } -} - -QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const -{ - QList<QGraphicsItem *> tmp; - findVisitor->foundItems = &tmp; - findVisitor->onlyTopLevelItems = onlyTopLevelItems; - climbTree(findVisitor, rect); - // Reset discovery bits. - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->d_ptr->itemDiscovered = 0; - return tmp; -} - -int QGraphicsSceneBspTree::leafCount() const -{ - return leafCnt; -} - -QString QGraphicsSceneBspTree::debug(int index) const -{ - const Node *node = &nodes.at(index); - - QString tmp; - if (node->type == Node::Leaf) { - QRectF rect = rectForIndex(index); - if (!leaves[node->leafIndex].isEmpty()) { - tmp += QString::fromLatin1("[%1, %2, %3, %4] contains %5 items\n") - .arg(rect.left()).arg(rect.top()) - .arg(rect.width()).arg(rect.height()) - .arg(leaves[node->leafIndex].size()); - } - } else { - if (node->type == Node::Horizontal) { - tmp += debug(firstChildIndex(index)); - tmp += debug(firstChildIndex(index) + 1); - } else { - tmp += debug(firstChildIndex(index)); - tmp += debug(firstChildIndex(index) + 1); - } - } - - return tmp; -} - -void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) -{ - Node *node = &nodes[index]; - if (index == 0) { - node->type = Node::Horizontal; - node->offset = rect.center().x(); - } - - if (depth) { - Node::Type type; - QRectF rect1, rect2; - qreal offset1, offset2; - - if (node->type == Node::Horizontal) { - type = Node::Vertical; - rect1.setRect(rect.left(), rect.top(), rect.width(), rect.height() / 2); - rect2.setRect(rect1.left(), rect1.bottom(), rect1.width(), rect.height() - rect1.height()); - offset1 = rect1.center().x(); - offset2 = rect2.center().x(); - } else { - type = Node::Horizontal; - rect1.setRect(rect.left(), rect.top(), rect.width() / 2, rect.height()); - rect2.setRect(rect1.right(), rect1.top(), rect.width() - rect1.width(), rect1.height()); - offset1 = rect1.center().y(); - offset2 = rect2.center().y(); - } - - int childIndex = firstChildIndex(index); - - Node *child = &nodes[childIndex]; - child->offset = offset1; - child->type = type; - - child = &nodes[childIndex + 1]; - child->offset = offset2; - child->type = type; - - initialize(rect1, depth - 1, childIndex); - initialize(rect2, depth - 1, childIndex + 1); - } else { - node->type = Node::Leaf; - node->leafIndex = leafCnt++; - } -} - -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const -{ - if (nodes.isEmpty()) - return; - - const Node &node = nodes.at(index); - const int childIndex = firstChildIndex(index); - - switch (node.type) { - case Node::Leaf: { - visitor->visit(const_cast<QList<QGraphicsItem*>*>(&leaves[node.leafIndex])); - break; - } - case Node::Vertical: - if (rect.left() < node.offset) { - climbTree(visitor, rect, childIndex); - if (rect.right() >= node.offset) - climbTree(visitor, rect, childIndex + 1); - } else { - climbTree(visitor, rect, childIndex + 1); - } - break; - case Node::Horizontal: - if (rect.top() < node.offset) { - climbTree(visitor, rect, childIndex); - if (rect.bottom() >= node.offset) - climbTree(visitor, rect, childIndex + 1); - } else { - climbTree(visitor, rect, childIndex + 1); - } - } -} - -QRectF QGraphicsSceneBspTree::rectForIndex(int index) const -{ - if (index <= 0) - return rect; - - int parentIdx = parentIndex(index); - QRectF rect = rectForIndex(parentIdx); - const Node *parent = &nodes.at(parentIdx); - - if (parent->type == Node::Horizontal) { - if (index & 1) - rect.setRight(parent->offset); - else - rect.setLeft(parent->offset); - } else { - if (index & 1) - rect.setBottom(parent->offset); - else - rect.setTop(parent->offset); - } - - return rect; -} - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h deleted file mode 100644 index 2e8149867b..0000000000 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEBSPTREE_P_H -#define QGRAPHICSSCENEBSPTREE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qlist.h> - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include <QtCore/qrect.h> -#include <QtCore/qset.h> -#include <QtCore/qvector.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsItem; -class QGraphicsSceneBspTreeVisitor; -class QGraphicsSceneInsertItemBspTreeVisitor; -class QGraphicsSceneRemoveItemBspTreeVisitor; -class QGraphicsSceneFindItemBspTreeVisitor; - -class QGraphicsSceneBspTree -{ -public: - struct Node - { - enum Type { Horizontal, Vertical, Leaf }; - union { - qreal offset; - int leafIndex; - }; - Type type; - }; - - QGraphicsSceneBspTree(); - ~QGraphicsSceneBspTree(); - - void initialize(const QRectF &rect, int depth); - void clear(); - - void insertItem(QGraphicsItem *item, const QRectF &rect); - void removeItem(QGraphicsItem *item, const QRectF &rect); - void removeItems(const QSet<QGraphicsItem *> &items); - - QList<QGraphicsItem *> items(const QRectF &rect, bool onlyTopLevelItems = false) const; - int leafCount() const; - - inline int firstChildIndex(int index) const - { return index * 2 + 1; } - - inline int parentIndex(int index) const - { return index > 0 ? ((index & 1) ? ((index - 1) / 2) : ((index - 2) / 2)) : -1; } - - QString debug(int index) const; - -private: - void initialize(const QRectF &rect, int depth, int index); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; - QRectF rectForIndex(int index) const; - - QVector<Node> nodes; - QVector<QList<QGraphicsItem *> > leaves; - int leafCnt; - QRectF rect; - - QGraphicsSceneInsertItemBspTreeVisitor *insertVisitor; - QGraphicsSceneRemoveItemBspTreeVisitor *removeVisitor; - QGraphicsSceneFindItemBspTreeVisitor *findVisitor; -}; - -class QGraphicsSceneBspTreeVisitor -{ -public: - virtual ~QGraphicsSceneBspTreeVisitor() { } - virtual void visit(QList<QGraphicsItem *> *items) = 0; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSSCENEBSPTREE_P_H diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h deleted file mode 100644 index 1e5c358e40..0000000000 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ /dev/null @@ -1,359 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENE_P_H -#define QGRAPHICSSCENE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsscene.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include "qgraphicssceneevent.h" -#include "qgraphicsview.h" -#include "qgraphicsview_p.h" -#include "qgraphicsitem_p.h" - -#include <private/qobject_p.h> -#include <QtCore/qbitarray.h> -#include <QtCore/qlist.h> -#include <QtCore/qmap.h> -#include <QtCore/qset.h> -#include <QtGui/qfont.h> -#include <QtGui/qpalette.h> -#include <QtGui/qstyle.h> -#include <QtGui/qstyleoption.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsSceneIndex; -class QGraphicsView; -class QGraphicsWidget; - -class Q_AUTOTEST_EXPORT QGraphicsScenePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsScene) -public: - QGraphicsScenePrivate(); - void init(); - - static QGraphicsScenePrivate *get(QGraphicsScene *q); - - int changedSignalIndex; - int processDirtyItemsIndex; - int polishItemsIndex; - - QGraphicsScene::ItemIndexMethod indexMethod; - QGraphicsSceneIndex *index; - - int lastItemCount; - - QRectF sceneRect; - - quint32 hasSceneRect : 1; - quint32 dirtyGrowingItemsBoundingRect : 1; - quint32 updateAll : 1; - quint32 calledEmitUpdated : 1; - quint32 processDirtyItemsEmitted : 1; - quint32 needSortTopLevelItems : 1; - quint32 holesInTopLevelSiblingIndex : 1; - quint32 topLevelSequentialOrdering : 1; - quint32 scenePosDescendantsUpdatePending : 1; - quint32 stickyFocus : 1; - quint32 hasFocus : 1; - quint32 lastMouseGrabberItemHasImplicitMouseGrab : 1; - quint32 allItemsIgnoreHoverEvents : 1; - quint32 allItemsUseDefaultCursor : 1; - quint32 painterStateProtection : 1; - quint32 sortCacheEnabled : 1; // for compatibility - quint32 allItemsIgnoreTouchEvents : 1; - quint32 padding : 15; - - QRectF growingItemsBoundingRect; - - void _q_emitUpdated(); - QList<QRectF> updatedRects; - - QPainterPath selectionArea; - int selectionChanging; - QSet<QGraphicsItem *> selectedItems; - QVector<QGraphicsItem *> unpolishedItems; - QList<QGraphicsItem *> topLevelItems; - - QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions; - void registerTopLevelItem(QGraphicsItem *item); - void unregisterTopLevelItem(QGraphicsItem *item); - void _q_updateLater(); - void _q_polishItems(); - - void _q_processDirtyItems(); - - QSet<QGraphicsItem *> scenePosItems; - void setScenePosItemEnabled(QGraphicsItem *item, bool enabled); - void registerScenePosItem(QGraphicsItem *item); - void unregisterScenePosItem(QGraphicsItem *item); - void _q_updateScenePosDescendants(); - - void removeItemHelper(QGraphicsItem *item); - - QBrush backgroundBrush; - QBrush foregroundBrush; - - quint32 rectAdjust; - QGraphicsItem *focusItem; - QGraphicsItem *lastFocusItem; - QGraphicsItem *passiveFocusItem; - QGraphicsWidget *tabFocusFirst; - QGraphicsItem *activePanel; - QGraphicsItem *lastActivePanel; - int activationRefCount; - int childExplicitActivation; - void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent); - void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason); - - QList<QGraphicsWidget *> popupWidgets; - void addPopup(QGraphicsWidget *widget); - void removePopup(QGraphicsWidget *widget, bool itemIsDying = false); - - QGraphicsItem *lastMouseGrabberItem; - QList<QGraphicsItem *> mouseGrabberItems; - void grabMouse(QGraphicsItem *item, bool implicit = false); - void ungrabMouse(QGraphicsItem *item, bool itemIsDying = false); - void clearMouseGrabber(); - - QList<QGraphicsItem *> keyboardGrabberItems; - void grabKeyboard(QGraphicsItem *item); - void ungrabKeyboard(QGraphicsItem *item, bool itemIsDying = false); - void clearKeyboardGrabber(); - - QGraphicsItem *dragDropItem; - QGraphicsWidget *enterWidget; - Qt::DropAction lastDropAction; - QList<QGraphicsItem *> cachedItemsUnderMouse; - QList<QGraphicsItem *> hoverItems; - QPointF lastSceneMousePos; - void enableMouseTrackingOnViews(); - QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos; - QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos; - QMap<Qt::MouseButton, QPoint> mouseGrabberButtonDownScreenPos; - QList<QGraphicsItem *> itemsAtPosition(const QPoint &screenPos, - const QPointF &scenePos, - QWidget *widget) const; - void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event); - - QList<QGraphicsView *> views; - void addView(QGraphicsView *view); - void removeView(QGraphicsView *view); - - QMultiMap<QGraphicsItem *, QGraphicsItem *> sceneEventFilters; - void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter); - void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter); - bool filterDescendantEvent(QGraphicsItem *item, QEvent *event); - bool filterEvent(QGraphicsItem *item, QEvent *event); - bool sendEvent(QGraphicsItem *item, QEvent *event); - - bool dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent); - bool itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const; - void leaveScene(QWidget *viewport); - - void cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest, - QGraphicsSceneDragDropEvent *source); - void sendDragDropEvent(QGraphicsItem *item, - QGraphicsSceneDragDropEvent *dragDropEvent); - void sendHoverEvent(QEvent::Type type, QGraphicsItem *item, - QGraphicsSceneHoverEvent *hoverEvent); - void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent); - void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); - QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - - void drawItemHelper(QGraphicsItem *item, QPainter *painter, - const QStyleOptionGraphicsItem *option, QWidget *widget, - bool painterStateProtection); - - void drawItems(QPainter *painter, const QTransform *const viewTransform, - QRegion *exposedRegion, QWidget *widget); - - void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, - QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0), - const QTransform *const effectTransform = 0); - void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, - QRegion *, QWidget *, qreal, const QTransform *const, bool, bool); - - void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, - bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false, - bool updateBoundingRect = false); - void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, - qreal parentOpacity = qreal(1.0)); - - inline void resetDirtyItem(QGraphicsItem *item, bool recursive = false) - { - Q_ASSERT(item); - item->d_ptr->dirty = 0; - item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; - item->d_ptr->geometryChanged = 0; - if (!item->d_ptr->dirtyChildren) - recursive = false; - item->d_ptr->dirtyChildren = 0; - item->d_ptr->needsRepaint = QRectF(); - item->d_ptr->allChildrenDirty = 0; - item->d_ptr->fullUpdatePending = 0; - item->d_ptr->ignoreVisible = 0; - item->d_ptr->ignoreOpacity = 0; -#ifndef QT_NO_GRAPHICSEFFECT - QGraphicsEffect::ChangeFlags flags; - if (item->d_ptr->notifyBoundingRectChanged) { - flags |= QGraphicsEffect::SourceBoundingRectChanged; - item->d_ptr->notifyBoundingRectChanged = 0; - } - if (item->d_ptr->notifyInvalidated) { - flags |= QGraphicsEffect::SourceInvalidated; - item->d_ptr->notifyInvalidated = 0; - } -#endif //QT_NO_GRAPHICSEFFECT - if (recursive) { - for (int i = 0; i < item->d_ptr->children.size(); ++i) - resetDirtyItem(item->d_ptr->children.at(i), recursive); - } -#ifndef QT_NO_GRAPHICSEFFECT - if (flags && item->d_ptr->graphicsEffect) - item->d_ptr->graphicsEffect->sourceChanged(flags); -#endif //QT_NO_GRAPHICSEFFECT - } - - inline void ensureSortedTopLevelItems() - { - if (needSortTopLevelItems) { - qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); - topLevelSequentialOrdering = false; - needSortTopLevelItems = false; - } - } - - void ensureSequentialTopLevelSiblingIndexes(); - - QStyle *style; - QFont font; - void setFont_helper(const QFont &font); - void resolveFont(); - void updateFont(const QFont &font); - QPalette palette; - void setPalette_helper(const QPalette &palette); - void resolvePalette(); - void updatePalette(const QPalette &palette); - - QStyleOptionGraphicsItem styleOptionTmp; - - QMap<int, QTouchEvent::TouchPoint> sceneCurrentTouchPoints; - QMap<int, QGraphicsItem *> itemForTouchPointId; - static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent); - int findClosestTouchPointId(const QPointF &scenePos); - void touchEventHandler(QTouchEvent *touchEvent); - bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent); - void enableTouchEventsOnViews(); - - QList<QGraphicsObject *> cachedTargetItems; -#ifndef QT_NO_GESTURES - QHash<QGraphicsObject *, QSet<QGesture *> > cachedItemGestures; - QHash<QGraphicsObject *, QSet<QGesture *> > cachedAlreadyDeliveredGestures; - QHash<QGesture *, QGraphicsObject *> gestureTargets; - QHash<Qt::GestureType, int> grabbedGestures; - void gestureEventHandler(QGestureEvent *event); - void gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures, - Qt::GestureFlag flag, - QHash<QGraphicsObject *, QSet<QGesture *> > *targets, - QSet<QGraphicsObject *> *itemsSet = 0, - QSet<QGesture *> *normal = 0, - QSet<QGesture *> *conflicts = 0); - void cancelGesturesForChildren(QGesture *original); - void grabGesture(QGraphicsItem *, Qt::GestureType gesture); - void ungrabGesture(QGraphicsItem *, Qt::GestureType gesture); -#endif // QT_NO_GESTURES - - void updateInputMethodSensitivityInViews(); - - QList<QGraphicsItem *> modalPanels; - void enterModal(QGraphicsItem *item, - QGraphicsItem::PanelModality panelModality = QGraphicsItem::NonModal); - void leaveModal(QGraphicsItem *item); -}; - -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(qreal(-0.00001), 0, qreal(0.00001), 0); - if (!rect->height()) - rect->adjust(0, qreal(-0.00001), 0, qreal(0.00001)); -} - -static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->boundingRect()); - _q_adjustRect(&boundingRect); - return boundingRect; -} - -static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(QGraphicsItemPrivate::get(item)->effectiveBoundingRect()); - _q_adjustRect(&boundingRect); - return boundingRect; -} - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp deleted file mode 100644 index 979ce6823b..0000000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ /dev/null @@ -1,719 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsSceneBspTreeIndex - \brief The QGraphicsSceneBspTreeIndex class provides an implementation of - a BSP indexing algorithm for discovering items in QGraphicsScene. - \since 4.6 - \ingroup graphicsview-api - - \internal - - QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) - implementation to discover items quickly. This implementation is - very efficient for static scenes. It has a depth that you can set. - The depth directly affects performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, the index can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the depth value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as the index retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - - \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex -*/ - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_GRAPHICSVIEW - -#include <private/qgraphicsscene_p.h> -#include <private/qgraphicsscenebsptreeindex_p.h> -#include <private/qgraphicssceneindex_p.h> - -#include <QtCore/qmath.h> -#include <QtCore/qdebug.h> - -QT_BEGIN_NAMESPACE - -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} - -/*! - Constructs a private scene bsp index. -*/ -QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) - : QGraphicsSceneIndexPrivate(scene), - bspTreeDepth(0), - indexTimerId(0), - restartIndexTimer(false), - regenerateIndex(true), - lastItemCount(0), - purgePending(false), - sortCacheEnabled(false), - updatingSortCache(false) -{ -} - - -/*! - This method will update the BSP index by removing the items from the temporary - unindexed list and add them in the indexedItems list. This will also - update the growingItemsBoundingRect if needed. This will update the BSP - implementation as well. - - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (!indexTimerId) - return; - - q->killTimer(indexTimerId); - indexTimerId = 0; - - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - Q_ASSERT(!item->d_ptr->itemDiscovered); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } - } - } - - // Determine whether we should regenerate the BSP tree. - if (bspTreeDepth == 0) { - int oldDepth = intmaxlog(lastItemCount); - bspTreeDepth = intmaxlog(indexedItems.size()); - static const int slack = 100; - if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - bsp.initialize(sceneRect, bspTreeDepth); - unindexedItems = indexedItems; - lastItemCount = indexedItems.size(); - } - - // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (item->d_ptr->itemIsUntransformable()) { - untransformableItems << item; - continue; - } - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect()); - } - } - unindexedItems.clear(); -} - - -/*! - \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() -{ - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - bsp.removeItems(removedItems); - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (!indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval) -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = q->startTimer(interval); - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::resetIndex() -{ - purgeRemovedItems(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - item->d_ptr->index = -1; - Q_ASSERT(!item->d_ptr->itemDiscovered); - unindexedItems << item; - } - } - indexedItems.clear(); - freeItemIndexes.clear(); - untransformableItems.clear(); - regenerateIndex = true; - startIndexTimer(); -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) -{ - if (!item->d_ptr->children.isEmpty()) { - QList<QGraphicsItem *> childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) - climbTree(childList.at(i), stackingOrder); - } - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (item->flags() & QGraphicsItem::ItemStacksBehindParent) - climbTree(childList.at(i), stackingOrder); - } - } else { - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - _q_updateIndex(); - - if (!sortCacheEnabled || !updatingSortCache) - return; - - updatingSortCache = false; - int stackingOrder = 0; - - QList<QGraphicsItem *> topLevels; - const QList<QGraphicsItem *> items = q->items(); - for (int i = 0; i < items.size(); ++i) { - QGraphicsItem *item = items.at(i); - if (item && !item->d_ptr->parent) - topLevels << item; - } - - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); - for (int i = 0; i < topLevels.size(); ++i) - climbTree(topLevels.at(i), &stackingOrder); -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (!sortCacheEnabled || updatingSortCache) - return; - - updatingSortCache = true; - QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); -} - -void QGraphicsSceneBspTreeIndexPrivate::addItem(QGraphicsItem *item, bool recursive) -{ - if (!item) - return; - - // Prevent reusing a recently deleted pointer: purge all removed item from our lists. - purgeRemovedItems(); - - // Invalidate any sort caching; arrival of a new item means we need to resort. - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - invalidateSortCache(); - - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. - if (item->d_ptr->index == -1) { - Q_ASSERT(!unindexedItems.contains(item)); - unindexedItems << item; - startIndexTimer(0); - } else { - Q_ASSERT(indexedItems.contains(item)); - qWarning("QGraphicsSceneBspTreeIndex::addItem: item has already been added to this BSP"); - } - - if (recursive) { - for (int i = 0; i < item->d_ptr->children.size(); ++i) - addItem(item->d_ptr->children.at(i), recursive); - } -} - -void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool recursive, - bool moveToUnindexedItems) -{ - if (!item) - return; - - if (item->d_ptr->index != -1) { - Q_ASSERT(item->d_ptr->index < indexedItems.size()); - Q_ASSERT(indexedItems.at(item->d_ptr->index) == item); - Q_ASSERT(!item->d_ptr->itemDiscovered); - freeItemIndexes << item->d_ptr->index; - indexedItems[item->d_ptr->index] = 0; - item->d_ptr->index = -1; - - if (item->d_ptr->itemIsUntransformable()) { - untransformableItems.removeOne(item); - } else if (item->d_ptr->inDestructor) { - // Avoid virtual function calls from the destructor. - purgePending = true; - removedItems << item; - } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect()); - } - } else { - unindexedItems.removeOne(item); - } - invalidateSortCache(); // ### Only do this when removing from BSP? - - Q_ASSERT(item->d_ptr->index == -1); - Q_ASSERT(!indexedItems.contains(item)); - Q_ASSERT(!unindexedItems.contains(item)); - Q_ASSERT(!untransformableItems.contains(item)); - - if (moveToUnindexedItems) - addItem(item); - - if (recursive) { - for (int i = 0; i < item->d_ptr->children.size(); ++i) - removeItem(item->d_ptr->children.at(i), recursive, moveToUnindexedItems); - } -} - -QList<QGraphicsItem *> QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QRectF &rect, Qt::SortOrder order, - bool onlyTopLevelItems) -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (onlyTopLevelItems && rect.isNull()) - return q->QGraphicsSceneIndex::estimateTopLevelItems(rect, order); - - purgeRemovedItems(); - _q_updateSortCache(); - Q_ASSERT(unindexedItems.isEmpty()); - - QList<QGraphicsItem *> rectItems = bsp.items(rect, onlyTopLevelItems); - if (onlyTopLevelItems) { - for (int i = 0; i < untransformableItems.size(); ++i) { - QGraphicsItem *item = untransformableItems.at(i); - if (!item->d_ptr->parent) { - rectItems << item; - } else { - item = item->topLevelItem(); - if (!rectItems.contains(item)) - rectItems << item; - } - } - } else { - rectItems += untransformableItems; - } - - sortItems(&rectItems, order, sortCacheEnabled, onlyTopLevelItems); - return rectItems; -} - -/*! - Sort a list of \a itemList in a specific \a order and use the cache if requested. - - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order, - bool sortCacheEnabled, bool onlyTopLevelItems) -{ - if (order == Qt::SortOrder(-1)) - return; - - if (onlyTopLevelItems) { - if (order == Qt::DescendingOrder) - qSort(itemList->begin(), itemList->end(), qt_closestLeaf); - else if (order == Qt::AscendingOrder) - qSort(itemList->begin(), itemList->end(), qt_notclosestLeaf); - return; - } - - if (sortCacheEnabled) { - if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); - } else if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); - } - } else { - if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), qt_closestItemFirst); - } else if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), qt_closestItemLast); - } - } -} - -/*! - Constructs a BSP scene index for the given \a scene. -*/ -QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) - : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) -{ - -} - -QGraphicsSceneBspTreeIndex::~QGraphicsSceneBspTreeIndex() -{ - Q_D(QGraphicsSceneBspTreeIndex); - for (int i = 0; i < d->indexedItems.size(); ++i) { - // Ensure item bits are reset properly. - if (QGraphicsItem *item = d->indexedItems.at(i)) { - Q_ASSERT(!item->d_ptr->itemDiscovered); - item->d_ptr->index = -1; - } - } -} - -/*! - \internal - Clear the all the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::clear() -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->bsp.clear(); - d->lastItemCount = 0; - d->freeItemIndexes.clear(); - for (int i = 0; i < d->indexedItems.size(); ++i) { - // Ensure item bits are reset properly. - if (QGraphicsItem *item = d->indexedItems.at(i)) { - Q_ASSERT(!item->d_ptr->itemDiscovered); - item->d_ptr->index = -1; - } - } - d->indexedItems.clear(); - d->unindexedItems.clear(); - d->untransformableItems.clear(); - d->regenerateIndex = true; -} - -/*! - Add the \a item into the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->addItem(item); -} - -/*! - Remove the \a item from the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->removeItem(item); -} - -/*! - \internal - Update the BSP when the \a item 's bounding rect has changed. -*/ -void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) -{ - if (!item) - return; - - if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable() - || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - return; // Item is not in BSP tree; nothing to do. - } - - Q_D(QGraphicsSceneBspTreeIndex); - QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item); - d->removeItem(thatItem, /*recursive=*/false, /*moveToUnindexedItems=*/true); - for (int i = 0; i < item->d_ptr->children.size(); ++i) // ### Do we really need this? - prepareBoundingRectChange(item->d_ptr->children.at(i)); -} - -/*! - Returns an estimation visible items that are either inside or - intersect with the specified \a rect and return a list sorted using \a order. - - \a deviceTransform is the transformation apply to the view. - -*/ -QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - return const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->estimateItems(rect, order); -} - -QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - return const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->estimateItems(rect, order, /*onlyTopLevels=*/true); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const; - - Return all items in the BSP index and sort them using \a order. -*/ -QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->purgeRemovedItems(); - QList<QGraphicsItem *> itemList; - - // If freeItemIndexes is empty, we know there are no holes in indexedItems and - // unindexedItems. - if (d->freeItemIndexes.isEmpty()) { - if (d->unindexedItems.isEmpty()) { - itemList = d->indexedItems; - } else { - itemList = d->indexedItems + d->unindexedItems; - } - } else { - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { - if (item) - itemList << item; - } - } - if (order != -1) { - //We sort descending order - d->sortItems(&itemList, order, d->sortCacheEnabled); - } - return itemList; -} - -/*! - \property QGraphicsSceneBspTreeIndex::bspTreeDepth - \brief the depth of the BSP index tree - \since 4.6 - - This value determines the depth of BSP tree. The depth - directly affects performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, the index can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as the index retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - -*/ -int QGraphicsSceneBspTreeIndex::bspTreeDepth() -{ - Q_D(const QGraphicsSceneBspTreeIndex); - return d->bspTreeDepth; -} - -void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) -{ - Q_D(QGraphicsSceneBspTreeIndex); - if (d->bspTreeDepth == depth) - return; - d->bspTreeDepth = depth; - d->resetIndex(); -} - -/*! - \internal - - This method react to the \a rect change of the scene and - reset the BSP tree index. -*/ -void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = rect; - d->resetIndex(); -} - -/*! - \internal - - This method react to the \a change of the \a item and use the \a value to - update the BSP tree if necessary. -*/ -void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value) -{ - Q_D(QGraphicsSceneBspTreeIndex); - switch (change) { - case QGraphicsItem::ItemFlagsChange: { - // Handle ItemIgnoresTransformations - QGraphicsItem::GraphicsItemFlags newFlags = *static_cast<const QGraphicsItem::GraphicsItemFlags *>(value); - bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations; - bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations; - bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; - bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape; - if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) { - QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item); - // Remove item and its descendants from the index and append - // them to the list of unindexed items. Then, when the index - // is updated, they will be put into the bsp-tree or the list - // of untransformable items. - d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true); - } - break; - } - case QGraphicsItem::ItemZValueChange: - d->invalidateSortCache(); - break; - case QGraphicsItem::ItemParentChange: { - d->invalidateSortCache(); - // Handle ItemIgnoresTransformations - const QGraphicsItem *newParent = static_cast<const QGraphicsItem *>(value); - bool ignoredTransform = item->d_ptr->itemIsUntransformable(); - bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations) - || (newParent && newParent->d_ptr->itemIsUntransformable()); - bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren; - bool ancestorWillClipChildren = newParent - && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) - || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)); - if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) { - QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item); - // Remove item and its descendants from the index and append - // them to the list of unindexed items. Then, when the index - // is updated, they will be put into the bsp-tree or the list - // of untransformable items. - d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true); - } - break; - } - default: - break; - } -} -/*! - \reimp - - Used to catch the timer event. - - \internal -*/ -bool QGraphicsSceneBspTreeIndex::event(QEvent *event) -{ - Q_D(QGraphicsSceneBspTreeIndex); - switch (event->type()) { - case QEvent::Timer: - if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) { - if (d->restartIndexTimer) { - d->restartIndexTimer = false; - } else { - // this call will kill the timer - d->_q_updateIndex(); - } - } - // Fallthrough intended - support timers in subclasses. - default: - return QObject::event(event); - } - return true; -} - -QT_END_NAMESPACE - -#include "moc_qgraphicsscenebsptreeindex_p.cpp" - -#endif // QT_NO_GRAPHICSVIEW - diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h deleted file mode 100644 index 0b353c74a4..0000000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ /dev/null @@ -1,206 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QGRAPHICSBSPTREEINDEX_H -#define QGRAPHICSBSPTREEINDEX_H - -#include <QtCore/qglobal.h> - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include "qgraphicssceneindex_p.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene_bsp_p.h" - -#include <QtCore/qrect.h> -#include <QtCore/qlist.h> - -QT_BEGIN_NAMESPACE - -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; - -class QGraphicsScene; -class QGraphicsSceneBspTreeIndexPrivate; - -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) -public: - QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - ~QGraphicsSceneBspTreeIndex(); - - QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const; - QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const; - QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const; - - int bspTreeDepth(); - void setBspTreeDepth(int depth); - -protected Q_SLOTS: - void updateSceneRect(const QRectF &rect); - -protected: - bool event(QEvent *event); - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); - - void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value); - -private : - Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) - Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) - - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; -}; - -class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) -public: - QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); - - QGraphicsSceneBspTree bsp; - QRectF sceneRect; - int bspTreeDepth; - int indexTimerId; - bool restartIndexTimer; - bool regenerateIndex; - int lastItemCount; - - QList<QGraphicsItem *> indexedItems; - QList<QGraphicsItem *> unindexedItems; - QList<QGraphicsItem *> untransformableItems; - QList<int> freeItemIndexes; - - bool purgePending; - QSet<QGraphicsItem *> removedItems; - void purgeRemovedItems(); - - void _q_updateIndex(); - void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - void resetIndex(); - - void _q_updateSortCache(); - bool sortCacheEnabled; - bool updatingSortCache; - void invalidateSortCache(); - void addItem(QGraphicsItem *item, bool recursive = false); - void removeItem(QGraphicsItem *item, bool recursive = false, bool moveToUnindexedItems = false); - QList<QGraphicsItem *> estimateItems(const QRectF &, Qt::SortOrder, bool b = false); - - static void climbTree(QGraphicsItem *item, int *stackingOrder); - - static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; - } - static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; - } - - static void sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order, - bool cached, bool onlyTopLevelItems = false); -}; - -static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) -{ - qreal xp = s.left(); - qreal yp = s.top(); - qreal w = s.width(); - qreal h = s.height(); - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - - qreal l2 = r.left(); - qreal r2 = r.left(); - if (w < 0) - l2 += r.width(); - else - r2 += r.width(); - - if (l1 >= r2 || l2 >= r1) - return false; - - qreal t1 = yp; - qreal b1 = yp; - if (h < 0) - t1 += h; - else - b1 += h; - - qreal t2 = r.top(); - qreal b2 = r.top(); - if (r.height() < 0) - t2 += r.height(); - else - b2 += r.height(); - - return !(t1 >= b2 || t2 >= b1); -} - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp deleted file mode 100644 index dd903be8ea..0000000000 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ /dev/null @@ -1,1674 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsSceneEvent - \brief The QGraphicsSceneEvent class provides a base class for all - graphics view related events. - \since 4.2 - \ingroup graphicsview-api - - When a QGraphicsView receives Qt mouse, keyboard, and drag and - drop events (QMouseEvent, QKeyEvent, QDragEvent, etc.), it - translates them into instances of QGraphicsSceneEvent subclasses - and forwards them to the QGraphicsScene it displays. The scene - then forwards the events to the relevant items. - - For example, when a QGraphicsView receives a QMouseEvent of type - MousePress as a response to a user click, the view sends a - QGraphicsSceneMouseEvent of type GraphicsSceneMousePress to the - underlying QGraphicsScene through its - \l{QGraphicsScene::}{mousePressEvent()} function. The default - QGraphicsScene::mousePressEvent() implementation determines which - item was clicked and forwards the event to - QGraphicsItem::mousePressEvent(). - - \omit ### Beskrive widget() \endomit - - Subclasses such as QGraphicsSceneMouseEvent and - QGraphicsSceneContextMenuEvent provide the coordinates from the - original QEvent in screen, scene, and item coordinates (see - \l{QGraphicsSceneMouseEvent::}{screenPos()}, - \l{QGraphicsSceneMouseEvent::}{scenePos()}, and - \l{QGraphicsSceneMouseEvent::}{pos()}). The item coordinates are - set by the QGraphicsScene before it forwards the event to the - event to a QGraphicsItem. The mouse events also add the - possibility to retrieve the coordinates from the last event - received by the view (see - \l{QGraphicsSceneMouseEvent::}{lastScreenPos()}, - \l{QGraphicsSceneMouseEvent::}{lastScenePos()}, and - \l{QGraphicsSceneMouseEvent::}{lastPos()}). - - \sa QEvent -*/ - -/*! - \class QGraphicsSceneMouseEvent - \brief The QGraphicsSceneMouseEvent class provides mouse events - in the graphics view framework. - \since 4.2 - \ingroup graphicsview-api - - When a QGraphicsView receives a QMouseEvent, it translates it to a - QGraphicsSceneMouseEvent. The event is then forwarded to the - QGraphicsScene associated with the view. If the event is not - handled by the scene, the view may use it, e.g., for the - \l{QGraphicsView::}{DragMode}. - - In addition to containing the item, scene, and screen coordinates - of the event (as pos(), scenePos(), and screenPos()), mouse - events also contain the coordinates of the previous mouse - event received by the view. These can be retrieved with - lastPos(), lastScreenPos(), and lastScenePos(). - - \sa QGraphicsSceneContextMenuEvent, - QGraphicsSceneHoverEvent, QGraphicsSceneWheelEvent, - QMouseEvent -*/ - -/*! - \class QGraphicsSceneWheelEvent - \brief The QGraphicsSceneWheelEvent class provides wheel events - in the graphics view framework. - \brief The QGraphicsSceneWheelEvent class provides wheel events in the - graphics view framework. - \since 4.2 - \ingroup graphicsview-api - - \l{QWheelEvent}{QWheelEvent}s received by a QGraphicsView are translated - into QGraphicsSceneWheelEvents; it translates the QWheelEvent::globalPos() - into item, scene, and screen coordinates (pos(), scenePos(), and - screenPos()). - - \sa QGraphicsSceneMouseEvent, QGraphicsSceneContextMenuEvent, - QGraphicsSceneHoverEvent, QWheelEvent -*/ - -/*! - \class QGraphicsSceneContextMenuEvent - \brief The QGraphicsSceneContextMenuEvent class provides context - menu events in the graphics view framework. - \since 4.2 - \ingroup graphicsview-api - - A QContextMenuEvent received by a QGraphicsView is translated - into a QGraphicsSceneContextMenuEvent. The - QContextMenuEvent::globalPos() is translated into item, scene, and - screen coordinates (pos(), scenePos(), and screenPos()). - - \sa QGraphicsSceneMouseEvent, QGraphicsSceneWheelEvent, - QContextMenuEvent -*/ - -/*! - \enum QGraphicsSceneContextMenuEvent::Reason - - This enum describes the reason why the context event was sent. - - \value Mouse The mouse caused the event to be sent. On most - platforms, this means the right mouse button was clicked. - - \value Keyboard The keyboard caused this event to be sent. On - Windows and Mac OS X, this means the menu button was pressed. - - \value Other The event was sent by some other means (i.e. not - by the mouse or keyboard). -*/ - -/*! - \class QGraphicsSceneHoverEvent - \brief The QGraphicsSceneHoverEvent class provides hover events - in the graphics view framework. - \since 4.2 - \ingroup graphicsview-api - - When a QGraphicsView receives a QHoverEvent event, it translates - it into QGraphicsSceneHoverEvent. The event is then forwarded to - the QGraphicsScene associated with the view. - - \sa QGraphicsSceneMouseEvent, QGraphicsSceneContextMenuEvent, - QGraphicsSceneWheelEvent, QHoverEvent -*/ - -/*! - \class QGraphicsSceneHelpEvent - \brief The QGraphicsSceneHelpEvent class provides events when a - tooltip is requested. - \since 4.2 - \ingroup graphicsview-api - - When a QGraphicsView receives a QEvent of type - QEvent::ToolTip, it creates a QGraphicsSceneHelpEvent, which is - forwarded to the scene. You can set a tooltip on a QGraphicsItem - with \l{QGraphicsItem::}{setToolTip()}; by default QGraphicsScene - displays the tooltip of the QGraphicsItem with the highest - z-value (i.e, the top-most item) under the mouse position. - - QGraphicsView does not forward events when - \l{QWhatsThis}{"What's This"} and \l{QStatusTipEvent}{status tip} - help is requested. If you need this, you can reimplement - QGraphicsView::viewportEvent() and forward QStatusTipEvent - events and \l{QEvent}{QEvents} of type QEvent::WhatsThis to the - scene. - - \sa QEvent -*/ - -/*! - \class QGraphicsSceneDragDropEvent - \brief The QGraphicsSceneDragDropEvent class provides events for - drag and drop in the graphics view framework. - \since 4.2 - \ingroup graphicsview-api - - QGraphicsView inherits the drag and drop functionality provided - by QWidget. When it receives a drag and drop event, it translates - it to a QGraphicsSceneDragDropEvent. - - QGraphicsSceneDragDropEvent stores events of type - GraphicsSceneDragEnter, GraphicsSceneDragLeave, - GraphicsSceneDragMove, or GraphicsSceneDrop. - - QGraphicsSceneDragDropEvent contains the position of the mouse - cursor in both item, scene, and screen coordinates; this can be - retrieved with pos(), scenePos(), and screenPos(). - - The scene sends the event to the first QGraphicsItem under the - mouse cursor that accepts drops; a graphics item is set to accept - drops with \l{QGraphicsItem::}{setAcceptDrops()}. -*/ - -/*! - \class QGraphicsSceneResizeEvent - \brief The QGraphicsSceneResizeEvent class provides events for widget - resizing in the graphics view framework. - \since 4.4 - \ingroup graphicsview-api - - A QGraphicsWidget sends itself a QGraphicsSceneResizeEvent immediately - when its geometry changes. - - It's similar to QResizeEvent, but its sizes, oldSize() and newSize(), use - QSizeF instead of QSize. - - \sa QGraphicsWidget::setGeometry(), QGraphicsWidget::resize() -*/ - -/*! - \class QGraphicsSceneMoveEvent - \brief The QGraphicsSceneMoveEvent class provides events for widget - moving in the graphics view framework. - \since 4.4 - \ingroup graphicsview-api - - A QGraphicsWidget sends itself a QGraphicsSceneMoveEvent immediately when - its local position changes. The delivery is implemented as part of - QGraphicsItem::itemChange(). - - It's similar to QMoveEvent, but its positions, oldPos() and newPos(), use - QPointF instead of QPoint. - - \sa QGraphicsItem::setPos(), QGraphicsItem::ItemPositionChange, - QGraphicsItem::ItemPositionHasChanged -*/ - -#include "qgraphicssceneevent.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#ifndef QT_NO_DEBUG -#include <QtCore/qdebug.h> -#endif -#include <QtCore/qmap.h> -#include <QtCore/qpoint.h> -#include <QtCore/qsize.h> -#include <QtCore/qstring.h> -#include "qgraphicsview.h" -#include "qgraphicsitem.h" -#include <QtGui/qgesture.h> -#include <private/qevent_p.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsSceneEventPrivate -{ -public: - inline QGraphicsSceneEventPrivate() - : widget(0), - q_ptr(0) - { } - - inline virtual ~QGraphicsSceneEventPrivate() - { } - - QWidget *widget; - QGraphicsSceneEvent *q_ptr; -}; - -/*! - \internal - - Constructs a generic graphics scene event of the specified \a type. -*/ -QGraphicsSceneEvent::QGraphicsSceneEvent(Type type) - : QEvent(type), d_ptr(new QGraphicsSceneEventPrivate) -{ - d_ptr->q_ptr = this; -} - -/*! - \internal - - Constructs a generic graphics scene event. -*/ -QGraphicsSceneEvent::QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type) - : QEvent(type), d_ptr(&dd) -{ - d_ptr->q_ptr = this; -} - -/*! - Destroys the event. -*/ -QGraphicsSceneEvent::~QGraphicsSceneEvent() -{ -} - -/*! - Returns the widget where the event originated, or 0 if the event - originates from another application. -*/ -QWidget *QGraphicsSceneEvent::widget() const -{ - return d_ptr->widget; -} - -/*! - \internal - - Sets the \a widget related to this event. - - \sa widget() -*/ -void QGraphicsSceneEvent::setWidget(QWidget *widget) -{ - d_ptr->widget = widget; -} - -class QGraphicsSceneMouseEventPrivate : public QGraphicsSceneEventPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneMouseEvent) -public: - inline QGraphicsSceneMouseEventPrivate() - : button(Qt::NoButton), - buttons(0), modifiers(0) - { } - - QPointF pos; - QPointF scenePos; - QPoint screenPos; - QPointF lastPos; - QPointF lastScenePos; - QPoint lastScreenPos; - QMap<Qt::MouseButton, QPointF> buttonDownPos; - QMap<Qt::MouseButton, QPointF> buttonDownScenePos; - QMap<Qt::MouseButton, QPoint> buttonDownScreenPos; - Qt::MouseButton button; - Qt::MouseButtons buttons; - Qt::KeyboardModifiers modifiers; -}; - -/*! - \internal - - Constructs a generic graphics scene mouse event of the specified \a type. -*/ -QGraphicsSceneMouseEvent::QGraphicsSceneMouseEvent(Type type) - : QGraphicsSceneEvent(*new QGraphicsSceneMouseEventPrivate, type) -{ -} - -/*! - Destroys the event. -*/ -QGraphicsSceneMouseEvent::~QGraphicsSceneMouseEvent() -{ -} - -/*! - Returns the mouse cursor position in item coordinates. - - \sa scenePos(), screenPos(), lastPos() -*/ -QPointF QGraphicsSceneMouseEvent::pos() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->pos; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->pos = pos; -} - -/*! - Returns the mouse cursor position in scene coordinates. - - \sa pos(), screenPos(), lastScenePos() -*/ -QPointF QGraphicsSceneMouseEvent::scenePos() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->scenePos; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->scenePos = pos; -} - -/*! - Returns the mouse cursor position in screen coordinates. - - \sa pos(), scenePos(), lastScreenPos() -*/ -QPoint QGraphicsSceneMouseEvent::screenPos() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->screenPos; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->screenPos = pos; -} - -/*! - Returns the mouse cursor position in item coordinates where the specified - \a button was clicked. - - \sa buttonDownScenePos(), buttonDownScreenPos(), pos() -*/ -QPointF QGraphicsSceneMouseEvent::buttonDownPos(Qt::MouseButton button) const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->buttonDownPos.value(button); -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setButtonDownPos(Qt::MouseButton button, const QPointF &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->buttonDownPos.insert(button, pos); -} - -/*! - Returns the mouse cursor position in scene coordinates where the - specified \a button was clicked. - - \sa buttonDownPos(), buttonDownScreenPos(), scenePos() -*/ -QPointF QGraphicsSceneMouseEvent::buttonDownScenePos(Qt::MouseButton button) const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->buttonDownScenePos.value(button); -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setButtonDownScenePos(Qt::MouseButton button, const QPointF &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->buttonDownScenePos.insert(button, pos); -} - -/*! - Returns the mouse cursor position in screen coordinates where the - specified \a button was clicked. - - \sa screenPos(), buttonDownPos(), buttonDownScenePos() -*/ -QPoint QGraphicsSceneMouseEvent::buttonDownScreenPos(Qt::MouseButton button) const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->buttonDownScreenPos.value(button); -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setButtonDownScreenPos(Qt::MouseButton button, const QPoint &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->buttonDownScreenPos.insert(button, pos); -} - -/*! - Returns the last recorded mouse cursor position in item - coordinates. - - \sa lastScenePos(), lastScreenPos(), pos() -*/ -QPointF QGraphicsSceneMouseEvent::lastPos() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->lastPos; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setLastPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->lastPos = pos; -} - -/*! - Returns the last recorded mouse cursor position in scene - coordinates. The last recorded position is the position of - the previous mouse event received by the view that created - the event. - - \sa lastPos(), lastScreenPos(), scenePos() -*/ -QPointF QGraphicsSceneMouseEvent::lastScenePos() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->lastScenePos; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setLastScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->lastScenePos = pos; -} - -/*! - Returns the last recorded mouse cursor position in screen - coordinates. The last recorded position is the position of - the previous mouse event received by the view that created - the event. - - \sa lastPos(), lastScenePos(), screenPos() -*/ -QPoint QGraphicsSceneMouseEvent::lastScreenPos() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->lastScreenPos; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setLastScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneMouseEvent); - d->lastScreenPos = pos; -} - -/*! - Returns the combination of mouse buttons that were pressed at the - time the event was sent. - - \sa button(), modifiers() -*/ -Qt::MouseButtons QGraphicsSceneMouseEvent::buttons() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->buttons; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setButtons(Qt::MouseButtons buttons) -{ - Q_D(QGraphicsSceneMouseEvent); - d->buttons = buttons; -} - -/*! - Returns the mouse button (if any) that caused the event. - - \sa buttons(), modifiers() -*/ -Qt::MouseButton QGraphicsSceneMouseEvent::button() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->button; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setButton(Qt::MouseButton button) -{ - Q_D(QGraphicsSceneMouseEvent); - d->button = button; -} - -/*! - Returns the keyboard modifiers in use at the time the event was - sent. - - \sa buttons(), button() -*/ -Qt::KeyboardModifiers QGraphicsSceneMouseEvent::modifiers() const -{ - Q_D(const QGraphicsSceneMouseEvent); - return d->modifiers; -} - -/*! - \internal -*/ -void QGraphicsSceneMouseEvent::setModifiers(Qt::KeyboardModifiers modifiers) -{ - Q_D(QGraphicsSceneMouseEvent); - d->modifiers = modifiers; -} - -class QGraphicsSceneWheelEventPrivate : public QGraphicsSceneEventPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneWheelEvent) -public: - inline QGraphicsSceneWheelEventPrivate() - : buttons(0), modifiers(0), delta(0), orientation(Qt::Horizontal) - { } - - QPointF pos; - QPointF scenePos; - QPoint screenPos; - Qt::MouseButtons buttons; - Qt::KeyboardModifiers modifiers; - int delta; - Qt::Orientation orientation; -}; - -/*! - \internal - - Constructs a QGraphicsSceneWheelEvent of type \a type, which - is always QEvent::GraphicsSceneWheel. -*/ -QGraphicsSceneWheelEvent::QGraphicsSceneWheelEvent(Type type) - : QGraphicsSceneEvent(*new QGraphicsSceneWheelEventPrivate, type) -{ -} - -/*! - Destroys the QGraphicsSceneWheelEvent. -*/ -QGraphicsSceneWheelEvent::~QGraphicsSceneWheelEvent() -{ -} - -/*! - Returns the position of the cursor in item coordinates when the - wheel event occurred. - - \sa scenePos(), screenPos() -*/ -QPointF QGraphicsSceneWheelEvent::pos() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->pos; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneWheelEvent); - d->pos = pos; -} - -/*! - Returns the position of the cursor in scene coordinates when the wheel - event occurred. - - \sa pos(), screenPos() -*/ -QPointF QGraphicsSceneWheelEvent::scenePos() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->scenePos; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneWheelEvent); - d->scenePos = pos; -} - -/*! - Returns the position of the cursor in screen coordinates when the wheel - event occurred. - - \sa pos(), scenePos() -*/ -QPoint QGraphicsSceneWheelEvent::screenPos() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->screenPos; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneWheelEvent); - d->screenPos = pos; -} - -/*! - Returns the mouse buttons that were pressed when the wheel event occurred. - - \sa modifiers() -*/ -Qt::MouseButtons QGraphicsSceneWheelEvent::buttons() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->buttons; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setButtons(Qt::MouseButtons buttons) -{ - Q_D(QGraphicsSceneWheelEvent); - d->buttons = buttons; -} - -/*! - Returns the keyboard modifiers that were active when the wheel event - occurred. - - \sa buttons() -*/ -Qt::KeyboardModifiers QGraphicsSceneWheelEvent::modifiers() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->modifiers; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setModifiers(Qt::KeyboardModifiers modifiers) -{ - Q_D(QGraphicsSceneWheelEvent); - d->modifiers = modifiers; -} - -/*! - Returns the distance that the wheel is rotated, in eighths (1/8s) - of a degree. A positive value indicates that the wheel was - rotated forwards away from the user; a negative value indicates - that the wheel was rotated backwards toward the user. - - Most mouse types work in steps of 15 degrees, in which case the delta - value is a multiple of 120 (== 15 * 8). -*/ -int QGraphicsSceneWheelEvent::delta() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->delta; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setDelta(int delta) -{ - Q_D(QGraphicsSceneWheelEvent); - d->delta = delta; -} - -/*! - Returns the wheel orientation. -*/ -Qt::Orientation QGraphicsSceneWheelEvent::orientation() const -{ - Q_D(const QGraphicsSceneWheelEvent); - return d->orientation; -} - -/*! - \internal -*/ -void QGraphicsSceneWheelEvent::setOrientation(Qt::Orientation orientation) -{ - Q_D(QGraphicsSceneWheelEvent); - d->orientation = orientation; -} - -class QGraphicsSceneContextMenuEventPrivate : public QGraphicsSceneEventPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneContextMenuEvent) - public: - inline QGraphicsSceneContextMenuEventPrivate() - : modifiers(0), reason(QGraphicsSceneContextMenuEvent::Other) - { } - - QPointF pos; - QPointF scenePos; - QPoint screenPos; - Qt::KeyboardModifiers modifiers; - QGraphicsSceneContextMenuEvent::Reason reason; -}; - -/*! - \internal - - Constructs a graphics scene context menu event of the specified \a type. -*/ -QGraphicsSceneContextMenuEvent::QGraphicsSceneContextMenuEvent(Type type) - : QGraphicsSceneEvent(*new QGraphicsSceneContextMenuEventPrivate, type) -{ -} - -/*! - Destroys the event. -*/ -QGraphicsSceneContextMenuEvent::~QGraphicsSceneContextMenuEvent() -{ -} - -/*! - Returns the position of the mouse cursor in item coordinates at the moment - the context menu was requested. - - \sa scenePos(), screenPos() -*/ -QPointF QGraphicsSceneContextMenuEvent::pos() const -{ - Q_D(const QGraphicsSceneContextMenuEvent); - return d->pos; -} - -/*! - \fn void QGraphicsSceneContextMenuEvent::setPos(const QPointF &point) - \internal - - Sets the position associated with the context menu to the given \a point - in item coordinates. -*/ -void QGraphicsSceneContextMenuEvent::setPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneContextMenuEvent); - d->pos = pos; -} - -/*! - Returns the position of the mouse cursor in scene coordinates at the moment the - the context menu was requested. - - \sa pos(), screenPos() -*/ -QPointF QGraphicsSceneContextMenuEvent::scenePos() const -{ - Q_D(const QGraphicsSceneContextMenuEvent); - return d->scenePos; -} - -/*! - \fn void QGraphicsSceneContextMenuEvent::setScenePos(const QPointF &point) - \internal - - Sets the position associated with the context menu to the given \a point - in scene coordinates. -*/ -void QGraphicsSceneContextMenuEvent::setScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneContextMenuEvent); - d->scenePos = pos; -} - -/*! - Returns the position of the mouse cursor in screen coordinates at the moment the - the context menu was requested. - - \sa pos(), scenePos() -*/ -QPoint QGraphicsSceneContextMenuEvent::screenPos() const -{ - Q_D(const QGraphicsSceneContextMenuEvent); - return d->screenPos; -} - -/*! - \fn void QGraphicsSceneContextMenuEvent::setScreenPos(const QPoint &point) - \internal - - Sets the position associated with the context menu to the given \a point - in screen coordinates. -*/ -void QGraphicsSceneContextMenuEvent::setScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneContextMenuEvent); - d->screenPos = pos; -} - -/*! - Returns the keyboard modifiers in use when the context menu was requested. -*/ -Qt::KeyboardModifiers QGraphicsSceneContextMenuEvent::modifiers() const -{ - Q_D(const QGraphicsSceneContextMenuEvent); - return d->modifiers; -} - -/*! - \internal - - Sets the keyboard modifiers associated with the context menu to the \a - modifiers specified. -*/ -void QGraphicsSceneContextMenuEvent::setModifiers(Qt::KeyboardModifiers modifiers) -{ - Q_D(QGraphicsSceneContextMenuEvent); - d->modifiers = modifiers; -} - -/*! - Returns the reason for the context menu event. - - \sa QGraphicsSceneContextMenuEvent::Reason -*/ -QGraphicsSceneContextMenuEvent::Reason QGraphicsSceneContextMenuEvent::reason() const -{ - Q_D(const QGraphicsSceneContextMenuEvent); - return d->reason; -} - -/*! - \internal - Sets the reason for the context menu event to \a reason. - - \sa reason() -*/ -void QGraphicsSceneContextMenuEvent::setReason(Reason reason) -{ - Q_D(QGraphicsSceneContextMenuEvent); - d->reason = reason; -} - -class QGraphicsSceneHoverEventPrivate : public QGraphicsSceneEventPrivate -{ -public: - QPointF pos; - QPointF scenePos; - QPoint screenPos; - QPointF lastPos; - QPointF lastScenePos; - QPoint lastScreenPos; - Qt::KeyboardModifiers modifiers; -}; - -/*! - \internal - - Constructs a graphics scene hover event of the specified \a type. -*/ -QGraphicsSceneHoverEvent::QGraphicsSceneHoverEvent(Type type) - : QGraphicsSceneEvent(*new QGraphicsSceneHoverEventPrivate, type) -{ -} - -/*! - Destroys the event. -*/ -QGraphicsSceneHoverEvent::~QGraphicsSceneHoverEvent() -{ -} - -/*! - Returns the position of the mouse cursor in item coordinates at the moment - the hover event was sent. - - \sa scenePos(), screenPos() -*/ -QPointF QGraphicsSceneHoverEvent::pos() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->pos; -} - -/*! - \fn void QGraphicsSceneHoverEvent::setPos(const QPointF &point) - \internal - - Sets the position associated with the hover event to the given \a point in - item coordinates. -*/ -void QGraphicsSceneHoverEvent::setPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneHoverEvent); - d->pos = pos; -} - -/*! - Returns the position of the mouse cursor in scene coordinates at the - moment the hover event was sent. - - \sa pos(), screenPos() -*/ -QPointF QGraphicsSceneHoverEvent::scenePos() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->scenePos; -} - -/*! - \fn void QGraphicsSceneHoverEvent::setScenePos(const QPointF &point) - \internal - - Sets the position associated with the hover event to the given \a point in - scene coordinates. -*/ -void QGraphicsSceneHoverEvent::setScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneHoverEvent); - d->scenePos = pos; -} - -/*! - Returns the position of the mouse cursor in screen coordinates at the - moment the hover event was sent. - - \sa pos(), scenePos() -*/ -QPoint QGraphicsSceneHoverEvent::screenPos() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->screenPos; -} - -/*! - \fn void QGraphicsSceneHoverEvent::setScreenPos(const QPoint &point) - \internal - - Sets the position associated with the hover event to the given \a point in - screen coordinates. -*/ -void QGraphicsSceneHoverEvent::setScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneHoverEvent); - d->screenPos = pos; -} - -/*! - \since 4.4 - - Returns the last recorded mouse cursor position in item coordinates. - - \sa lastScenePos(), lastScreenPos(), pos() -*/ -QPointF QGraphicsSceneHoverEvent::lastPos() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->lastPos; -} - -/*! - \internal -*/ -void QGraphicsSceneHoverEvent::setLastPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneHoverEvent); - d->lastPos = pos; -} - -/*! - \since 4.4 - - Returns the last recorded, the scene coordinates of the previous mouse or - hover event received by the view, that created the event mouse cursor - position in scene coordinates. - - \sa lastPos(), lastScreenPos(), scenePos() -*/ -QPointF QGraphicsSceneHoverEvent::lastScenePos() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->lastScenePos; -} - -/*! - \internal -*/ -void QGraphicsSceneHoverEvent::setLastScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneHoverEvent); - d->lastScenePos = pos; -} - -/*! - \since 4.4 - - Returns the last recorded mouse cursor position in screen coordinates. The - last recorded position is the position of the previous mouse or hover - event received by the view that created the event. - - \sa lastPos(), lastScenePos(), screenPos() -*/ -QPoint QGraphicsSceneHoverEvent::lastScreenPos() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->lastScreenPos; -} - -/*! - \internal -*/ -void QGraphicsSceneHoverEvent::setLastScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneHoverEvent); - d->lastScreenPos = pos; -} - -/*! - \since 4.4 - - Returns the keyboard modifiers at the moment the hover event was sent. -*/ -Qt::KeyboardModifiers QGraphicsSceneHoverEvent::modifiers() const -{ - Q_D(const QGraphicsSceneHoverEvent); - return d->modifiers; -} - -/*! - \fn void QGraphicsSceneHoverEvent::setModifiers(Qt::KeyboardModifiers modifiers) - \internal - - Sets the modifiers for the current hover event to \a modifiers. -*/ -void QGraphicsSceneHoverEvent::setModifiers(Qt::KeyboardModifiers modifiers) -{ - Q_D(QGraphicsSceneHoverEvent); - d->modifiers = modifiers; -} - -class QGraphicsSceneHelpEventPrivate : public QGraphicsSceneEventPrivate -{ -public: - QPointF scenePos; - QPoint screenPos; -}; - -/*! - \internal - - Constructs a graphics scene help event of the specified \a type. -*/ -QGraphicsSceneHelpEvent::QGraphicsSceneHelpEvent(Type type) - : QGraphicsSceneEvent(*new QGraphicsSceneHelpEventPrivate, type) -{ -} - -/*! - Destroys the event. -*/ -QGraphicsSceneHelpEvent::~QGraphicsSceneHelpEvent() -{ -} - -/*! - Returns the position of the mouse cursor in scene coordinates at the - moment the help event was sent. - - \sa screenPos() -*/ -QPointF QGraphicsSceneHelpEvent::scenePos() const -{ - Q_D(const QGraphicsSceneHelpEvent); - return d->scenePos; -} - -/*! - \fn void QGraphicsSceneHelpEvent::setScenePos(const QPointF &point) - \internal - - Sets the position associated with the context menu to the given \a point - in scene coordinates. -*/ -void QGraphicsSceneHelpEvent::setScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneHelpEvent); - d->scenePos = pos; -} - -/*! - Returns the position of the mouse cursor in screen coordinates at the - moment the help event was sent. - - \sa scenePos() -*/ -QPoint QGraphicsSceneHelpEvent::screenPos() const -{ - Q_D(const QGraphicsSceneHelpEvent); - return d->screenPos; -} - -/*! - \fn void QGraphicsSceneHelpEvent::setScreenPos(const QPoint &point) - \internal - - Sets the position associated with the context menu to the given \a point - in screen coordinates. -*/ -void QGraphicsSceneHelpEvent::setScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneHelpEvent); - d->screenPos = pos; -} - -class QGraphicsSceneDragDropEventPrivate : public QGraphicsSceneEventPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneDragDropEvent) -public: - inline QGraphicsSceneDragDropEventPrivate() - : source(0), mimeData(0) - { } - - QPointF pos; - QPointF scenePos; - QPoint screenPos; - Qt::MouseButtons buttons; - Qt::KeyboardModifiers modifiers; - Qt::DropActions possibleActions; - Qt::DropAction proposedAction; - Qt::DropAction dropAction; - QWidget *source; - const QMimeData *mimeData; -}; - -/*! - \internal - - Constructs a new QGraphicsSceneDragDropEvent of the - specified \a type. The type can be either - QEvent::GraphicsSceneDragEnter, QEvent::GraphicsSceneDragLeave, - QEvent::GraphicsSceneDragMove, or QEvent::GraphicsSceneDrop. -*/ -QGraphicsSceneDragDropEvent::QGraphicsSceneDragDropEvent(Type type) - : QGraphicsSceneEvent(*new QGraphicsSceneDragDropEventPrivate, type) -{ -} - -/*! - Destroys the object. -*/ -QGraphicsSceneDragDropEvent::~QGraphicsSceneDragDropEvent() -{ -} - -/*! - Returns the mouse position of the event relative to the - view that sent the event. - - \sa QGraphicsView, screenPos(), scenePos() -*/ -QPointF QGraphicsSceneDragDropEvent::pos() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->pos; -} - -/*! - \internal - Sets the position of the mouse to \a pos; this should be - relative to the widget that generated the event, which normally - is a QGraphicsView. - - \sa pos(), setScenePos(), setScreenPos() -*/ - -void QGraphicsSceneDragDropEvent::setPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->pos = pos; -} - -/*! - Returns the position of the mouse in scene coordinates. - - \sa pos(), screenPos() -*/ -QPointF QGraphicsSceneDragDropEvent::scenePos() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->scenePos; -} - -/*! - \internal - Sets the scene position of the mouse to \a pos. - - \sa scenePos(), setScreenPos(), setPos() -*/ -void QGraphicsSceneDragDropEvent::setScenePos(const QPointF &pos) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->scenePos = pos; -} - -/*! - Returns the position of the mouse relative to the screen. - - \sa pos(), scenePos() -*/ -QPoint QGraphicsSceneDragDropEvent::screenPos() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->screenPos; -} - -/*! - \internal - Sets the mouse position relative to the screen to \a pos. - - \sa screenPos(), setScenePos(), setPos() -*/ -void QGraphicsSceneDragDropEvent::setScreenPos(const QPoint &pos) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->screenPos = pos; -} - -/*! - Returns a Qt::MouseButtons value indicating which buttons - were pressed on the mouse when this mouse event was - generated. - - \sa Qt::MouseButtons -*/ -Qt::MouseButtons QGraphicsSceneDragDropEvent::buttons() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->buttons; -} - -/*! - \internal - Sets the mouse buttons that were pressed when the event was - created to \a buttons. - - \sa Qt::MouseButtons, buttons() -*/ -void QGraphicsSceneDragDropEvent::setButtons(Qt::MouseButtons buttons) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->buttons = buttons; -} - -/*! - Returns the keyboard modifiers that were pressed when the drag - and drop event was created. - - \sa Qt::KeyboardModifiers -*/ -Qt::KeyboardModifiers QGraphicsSceneDragDropEvent::modifiers() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->modifiers; -} - -/*! - \internal - Sets the keyboard modifiers that were pressed when the event - was created to \a modifiers. - - \sa Qt::KeyboardModifiers, modifiers() -*/ - -void QGraphicsSceneDragDropEvent::setModifiers(Qt::KeyboardModifiers modifiers) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->modifiers = modifiers; -} - -/*! - Returns the possible drop actions that the drag and - drop can result in. - - \sa Qt::DropActions -*/ - -Qt::DropActions QGraphicsSceneDragDropEvent::possibleActions() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->possibleActions; -} - -/*! - \internal - Sets the possible drop actions that the drag can - result in to \a actions. - - \sa Qt::DropActions, possibleActions() -*/ -void QGraphicsSceneDragDropEvent::setPossibleActions(Qt::DropActions actions) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->possibleActions = actions; -} - -/*! - Returns the drop action that is proposed, i.e., preferred. - The action must be one of the possible actions as defined by - \c possibleActions(). - - \sa Qt::DropAction, possibleActions() -*/ - -Qt::DropAction QGraphicsSceneDragDropEvent::proposedAction() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->proposedAction; -} - -/*! - \internal - Sets the proposed action to \a action. The proposed action - is a Qt::DropAction that is one of the possible actions as - given by \c possibleActions(). - - \sa proposedAction(), Qt::DropAction, possibleActions() -*/ - -void QGraphicsSceneDragDropEvent::setProposedAction(Qt::DropAction action) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->proposedAction = action; -} - -/*! - Sets the proposed action as accepted, i.e, the drop action - is set to the proposed action. This is equal to: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicssceneevent.cpp 0 - - When using this function, one should not call \c accept(). - - \sa dropAction(), setDropAction(), proposedAction() -*/ - -void QGraphicsSceneDragDropEvent::acceptProposedAction() -{ - Q_D(QGraphicsSceneDragDropEvent); - d->dropAction = d->proposedAction; -} - -/*! - Returns the action that was performed in this drag and drop. - This should be set by the receiver of the drop and is - returned by QDrag::exec(). - - \sa setDropAction(), acceptProposedAction() -*/ - -Qt::DropAction QGraphicsSceneDragDropEvent::dropAction() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->dropAction; -} - -/*! - This function lets the receiver of the drop set the drop - action that was performed to \a action, which should be one - of the - \l{QGraphicsSceneDragDropEvent::possibleActions()}{possible - actions}. Call \c accept() in stead of \c - acceptProposedAction() if you use this function. - - \sa dropAction(), accept(), possibleActions() -*/ -void QGraphicsSceneDragDropEvent::setDropAction(Qt::DropAction action) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->dropAction = action; -} - -/*! - This function returns the QGraphicsView that created the - QGraphicsSceneDragDropEvent. -*/ -QWidget *QGraphicsSceneDragDropEvent::source() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->source; -} - -/*! - \internal - This function set the source widget, i.e., the widget that - created the drop event, to \a source. -*/ -void QGraphicsSceneDragDropEvent::setSource(QWidget *source) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->source = source; -} - -/*! - This function returns the MIME data of the event. -*/ -const QMimeData *QGraphicsSceneDragDropEvent::mimeData() const -{ - Q_D(const QGraphicsSceneDragDropEvent); - return d->mimeData; -} - -/*! - \internal - This function sets the MIME data for the event. -*/ -void QGraphicsSceneDragDropEvent::setMimeData(const QMimeData *data) -{ - Q_D(QGraphicsSceneDragDropEvent); - d->mimeData = data; -} - -class QGraphicsSceneResizeEventPrivate : public QGraphicsSceneEventPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneResizeEvent) -public: - inline QGraphicsSceneResizeEventPrivate() - { } - - QSizeF oldSize; - QSizeF newSize; -}; - -/*! - Constructs a QGraphicsSceneResizeEvent. -*/ -QGraphicsSceneResizeEvent::QGraphicsSceneResizeEvent() - : QGraphicsSceneEvent(*new QGraphicsSceneResizeEventPrivate, QEvent::GraphicsSceneResize) -{ -} - -/*! - Destroys the QGraphicsSceneResizeEvent. -*/ -QGraphicsSceneResizeEvent::~QGraphicsSceneResizeEvent() -{ -} - -/*! - Returns the old size (i.e., the size immediately before the widget was - resized). - - \sa newSize(), QGraphicsWidget::resize() -*/ -QSizeF QGraphicsSceneResizeEvent::oldSize() const -{ - Q_D(const QGraphicsSceneResizeEvent); - return d->oldSize; -} - -/*! - \internal -*/ -void QGraphicsSceneResizeEvent::setOldSize(const QSizeF &size) -{ - Q_D(QGraphicsSceneResizeEvent); - d->oldSize = size; -} - -/*! - Returns the new size (i.e., the current size). - - \sa oldSize(), QGraphicsWidget::resize() -*/ -QSizeF QGraphicsSceneResizeEvent::newSize() const -{ - Q_D(const QGraphicsSceneResizeEvent); - return d->newSize; -} - -/*! - \internal -*/ -void QGraphicsSceneResizeEvent::setNewSize(const QSizeF &size) -{ - Q_D(QGraphicsSceneResizeEvent); - d->newSize = size; -} - -class QGraphicsSceneMoveEventPrivate : public QGraphicsSceneEventPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneMoveEvent) -public: - inline QGraphicsSceneMoveEventPrivate() - { } - - QPointF oldPos; - QPointF newPos; -}; - -/*! - Constructs a QGraphicsSceneMoveEvent. -*/ -QGraphicsSceneMoveEvent::QGraphicsSceneMoveEvent() - : QGraphicsSceneEvent(*new QGraphicsSceneMoveEventPrivate, QEvent::GraphicsSceneMove) -{ -} - -/*! - Destroys the QGraphicsSceneMoveEvent. -*/ -QGraphicsSceneMoveEvent::~QGraphicsSceneMoveEvent() -{ -} - -/*! - Returns the old position (i.e., the position immediately before the widget - was moved). - - \sa newPos(), QGraphicsItem::setPos() -*/ -QPointF QGraphicsSceneMoveEvent::oldPos() const -{ - Q_D(const QGraphicsSceneMoveEvent); - return d->oldPos; -} - -/*! - \internal -*/ -void QGraphicsSceneMoveEvent::setOldPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneMoveEvent); - d->oldPos = pos; -} - -/*! - Returns the new position (i.e., the current position). - - \sa oldPos(), QGraphicsItem::setPos() -*/ -QPointF QGraphicsSceneMoveEvent::newPos() const -{ - Q_D(const QGraphicsSceneMoveEvent); - return d->newPos; -} - -/*! - \internal -*/ -void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) -{ - Q_D(QGraphicsSceneMoveEvent); - d->newPos = pos; -} - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h deleted file mode 100644 index cbc211c542..0000000000 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ /dev/null @@ -1,326 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEEVENT_H -#define QGRAPHICSSCENEEVENT_H - -#include <QtCore/qcoreevent.h> -#include <QtCore/qpoint.h> -#include <QtCore/qscopedpointer.h> -#include <QtCore/qrect.h> -#include <QtGui/qpolygon.h> -#include <QtCore/qset.h> -#include <QtCore/qhash.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QMimeData; -class QPointF; -class QSizeF; -class QWidget; - -class QGraphicsSceneEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneEvent : public QEvent -{ -public: - QGraphicsSceneEvent(Type type); - ~QGraphicsSceneEvent(); - - QWidget *widget() const; - void setWidget(QWidget *widget); - -protected: - QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None); - QScopedPointer<QGraphicsSceneEventPrivate> d_ptr; - Q_DECLARE_PRIVATE(QGraphicsSceneEvent) -private: - Q_DISABLE_COPY(QGraphicsSceneEvent) -}; - -class QGraphicsSceneMouseEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneMouseEvent : public QGraphicsSceneEvent -{ -public: - QGraphicsSceneMouseEvent(Type type = None); - ~QGraphicsSceneMouseEvent(); - - QPointF pos() const; - void setPos(const QPointF &pos); - - QPointF scenePos() const; - void setScenePos(const QPointF &pos); - - QPoint screenPos() const; - void setScreenPos(const QPoint &pos); - - QPointF buttonDownPos(Qt::MouseButton button) const; - void setButtonDownPos(Qt::MouseButton button, const QPointF &pos); - - QPointF buttonDownScenePos(Qt::MouseButton button) const; - void setButtonDownScenePos(Qt::MouseButton button, const QPointF &pos); - - QPoint buttonDownScreenPos(Qt::MouseButton button) const; - void setButtonDownScreenPos(Qt::MouseButton button, const QPoint &pos); - - QPointF lastPos() const; - void setLastPos(const QPointF &pos); - - QPointF lastScenePos() const; - void setLastScenePos(const QPointF &pos); - - QPoint lastScreenPos() const; - void setLastScreenPos(const QPoint &pos); - - Qt::MouseButtons buttons() const; - void setButtons(Qt::MouseButtons buttons); - - Qt::MouseButton button() const; - void setButton(Qt::MouseButton button); - - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); - -private: - Q_DECLARE_PRIVATE(QGraphicsSceneMouseEvent) - Q_DISABLE_COPY(QGraphicsSceneMouseEvent) -}; - -class QGraphicsSceneWheelEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneWheelEvent : public QGraphicsSceneEvent -{ -public: - QGraphicsSceneWheelEvent(Type type = None); - ~QGraphicsSceneWheelEvent(); - - QPointF pos() const; - void setPos(const QPointF &pos); - - QPointF scenePos() const; - void setScenePos(const QPointF &pos); - - QPoint screenPos() const; - void setScreenPos(const QPoint &pos); - - Qt::MouseButtons buttons() const; - void setButtons(Qt::MouseButtons buttons); - - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); - - int delta() const; - void setDelta(int delta); - - Qt::Orientation orientation() const; - void setOrientation(Qt::Orientation orientation); - -private: - Q_DECLARE_PRIVATE(QGraphicsSceneWheelEvent) - Q_DISABLE_COPY(QGraphicsSceneWheelEvent) -}; - -class QGraphicsSceneContextMenuEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneContextMenuEvent : public QGraphicsSceneEvent -{ -public: - enum Reason { Mouse, Keyboard, Other }; - - QGraphicsSceneContextMenuEvent(Type type = None); - ~QGraphicsSceneContextMenuEvent(); - - QPointF pos() const; - void setPos(const QPointF &pos); - - QPointF scenePos() const; - void setScenePos(const QPointF &pos); - - QPoint screenPos() const; - void setScreenPos(const QPoint &pos); - - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); - - Reason reason() const; - void setReason(Reason reason); - -private: - Q_DECLARE_PRIVATE(QGraphicsSceneContextMenuEvent) - Q_DISABLE_COPY(QGraphicsSceneContextMenuEvent) -}; - -class QGraphicsSceneHoverEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneHoverEvent : public QGraphicsSceneEvent -{ -public: - QGraphicsSceneHoverEvent(Type type = None); - ~QGraphicsSceneHoverEvent(); - - QPointF pos() const; - void setPos(const QPointF &pos); - - QPointF scenePos() const; - void setScenePos(const QPointF &pos); - - QPoint screenPos() const; - void setScreenPos(const QPoint &pos); - - QPointF lastPos() const; - void setLastPos(const QPointF &pos); - - QPointF lastScenePos() const; - void setLastScenePos(const QPointF &pos); - - QPoint lastScreenPos() const; - void setLastScreenPos(const QPoint &pos); - - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); - -private: - Q_DECLARE_PRIVATE(QGraphicsSceneHoverEvent) - Q_DISABLE_COPY(QGraphicsSceneHoverEvent) -}; - -class QGraphicsSceneHelpEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneHelpEvent : public QGraphicsSceneEvent -{ -public: - QGraphicsSceneHelpEvent(Type type = None); - ~QGraphicsSceneHelpEvent(); - - QPointF scenePos() const; - void setScenePos(const QPointF &pos); - - QPoint screenPos() const; - void setScreenPos(const QPoint &pos); - -private: - Q_DECLARE_PRIVATE(QGraphicsSceneHelpEvent) - Q_DISABLE_COPY(QGraphicsSceneHelpEvent) -}; - -class QGraphicsSceneDragDropEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneDragDropEvent : public QGraphicsSceneEvent -{ -public: - QGraphicsSceneDragDropEvent(Type type = None); - ~QGraphicsSceneDragDropEvent(); - - QPointF pos() const; - void setPos(const QPointF &pos); - - QPointF scenePos() const; - void setScenePos(const QPointF &pos); - - QPoint screenPos() const; - void setScreenPos(const QPoint &pos); - - Qt::MouseButtons buttons() const; - void setButtons(Qt::MouseButtons buttons); - - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); - - Qt::DropActions possibleActions() const; - void setPossibleActions(Qt::DropActions actions); - - Qt::DropAction proposedAction() const; - void setProposedAction(Qt::DropAction action); - void acceptProposedAction(); - - Qt::DropAction dropAction() const; - void setDropAction(Qt::DropAction action); - - QWidget *source() const; - void setSource(QWidget *source); - - const QMimeData *mimeData() const; - void setMimeData(const QMimeData *data); - -private: - Q_DECLARE_PRIVATE(QGraphicsSceneDragDropEvent) - Q_DISABLE_COPY(QGraphicsSceneDragDropEvent) -}; - -class QGraphicsSceneResizeEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneResizeEvent : public QGraphicsSceneEvent -{ - Q_DECLARE_PRIVATE(QGraphicsSceneResizeEvent) - Q_DISABLE_COPY(QGraphicsSceneResizeEvent) -public: - QGraphicsSceneResizeEvent(); - ~QGraphicsSceneResizeEvent(); - - QSizeF oldSize() const; - void setOldSize(const QSizeF &size); - - QSizeF newSize() const; - void setNewSize(const QSizeF &size); -}; - -class QGraphicsSceneMoveEventPrivate; -class Q_GUI_EXPORT QGraphicsSceneMoveEvent : public QGraphicsSceneEvent -{ - Q_DECLARE_PRIVATE(QGraphicsSceneMoveEvent) - Q_DISABLE_COPY(QGraphicsSceneMoveEvent) -public: - QGraphicsSceneMoveEvent(); - ~QGraphicsSceneMoveEvent(); - - QPointF oldPos() const; - void setOldPos(const QPointF &pos); - - QPointF newPos() const; - void setNewPos(const QPointF &pos); -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp deleted file mode 100644 index d5ca504cae..0000000000 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ /dev/null @@ -1,648 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -/*! - \class QGraphicsSceneIndex - \brief The QGraphicsSceneIndex class provides a base class to implement - a custom indexing algorithm for discovering items in QGraphicsScene. - \since 4.6 - \ingroup graphicsview-api - - \internal - - The QGraphicsSceneIndex class provides a base class to implement - a custom indexing algorithm for discovering items in QGraphicsScene. You - need to subclass it and reimplement addItem, removeItem, estimateItems - and items in order to have an functional indexing. - - \sa QGraphicsScene, QGraphicsView -*/ - -#include "qdebug.h" -#include "qgraphicsscene.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene_p.h" -#include "qgraphicswidget.h" -#include "qgraphicssceneindex_p.h" -#include "qgraphicsscenebsptreeindex_p.h" - -#ifndef QT_NO_GRAPHICSVIEW - -QT_BEGIN_NAMESPACE - -class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector -{ -public: - bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &deviceTransform) const - { - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - // ### Add test for this (without making things slower?) - Q_UNUSED(exposeRect); - - bool keep = true; - const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item); - if (itemd->itemIsUntransformable()) { - // Untransformable items; map the scene rect to item coordinates. - const QTransform transform = item->deviceTransform(deviceTransform); - QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect); - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = itemRect.contains(brect) && itemRect != brect; - else - keep = itemRect.intersects(brect); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath itemPath; - itemPath.addRect(itemRect); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); - } - } else { - Q_ASSERT(!itemd->dirtySceneTransform); - const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly - ? brect.translated(itemd->sceneTransform.dx(), - itemd->sceneTransform.dy()) - : itemd->sceneTransform.mapRect(brect); - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect); - else - keep = sceneRect.intersects(itemSceneBoundingRect); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(sceneRect); - if (itemd->sceneTransformTranslateOnly) - rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy()); - else - rectPath = itemd->sceneTransform.inverted().map(rectPath); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, rectPath, mode); - } - } - return keep; - } - - QRectF sceneRect; -}; - -class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector -{ -public: - bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &deviceTransform) const - { - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - // ### Add test for this (without making things slower?) - Q_UNUSED(exposeRect); - - bool keep = false; - const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item); - if (itemd->itemIsUntransformable()) { - // Untransformable items; map the scene point to item coordinates. - const QTransform transform = item->deviceTransform(deviceTransform); - QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint); - keep = brect.contains(itemPoint); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath pointPath; - pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1))); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); - } - } else { - Q_ASSERT(!itemd->dirtySceneTransform); - QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly - ? brect.translated(itemd->sceneTransform.dx(), - itemd->sceneTransform.dy()) - : itemd->sceneTransform.mapRect(brect); - keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1))); - if (keep) { - QPointF p = itemd->sceneTransformTranslateOnly - ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(), - scenePoint.y() - itemd->sceneTransform.dy()) - : itemd->sceneTransform.inverted().map(scenePoint); - keep = item->contains(p); - } - } - - return keep; - } - - QPointF scenePoint; -}; - -class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector -{ -public: - bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &deviceTransform) const - { - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - // ### Add test for this (without making things slower?) - Q_UNUSED(exposeRect); - - bool keep = true; - const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item); - if (itemd->itemIsUntransformable()) { - // Untransformable items; map the scene rect to item coordinates. - const QTransform transform = item->deviceTransform(deviceTransform); - QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath); - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = itemPath.contains(brect); - else - keep = itemPath.intersects(brect); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); - } else { - Q_ASSERT(!itemd->dirtySceneTransform); - const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly - ? brect.translated(itemd->sceneTransform.dx(), - itemd->sceneTransform.dy()) - : itemd->sceneTransform.mapRect(brect); - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = scenePath.contains(itemSceneBoundingRect); - else - keep = scenePath.intersects(itemSceneBoundingRect); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath itemPath = itemd->sceneTransformTranslateOnly - ? scenePath.translated(-itemd->sceneTransform.dx(), - -itemd->sceneTransform.dy()) - : itemd->sceneTransform.inverted().map(scenePath); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); - } - } - return keep; - } - - QPainterPath scenePath; -}; - -/*! - Constructs a private scene index. -*/ -QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) -{ - pointIntersector = new QGraphicsSceneIndexPointIntersector; - rectIntersector = new QGraphicsSceneIndexRectIntersector; - pathIntersector = new QGraphicsSceneIndexPathIntersector; -} - -/*! - Destructor of private scene index. -*/ -QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() -{ - delete pointIntersector; - delete rectIntersector; - delete pathIntersector; -} - -/*! - \internal - - Checks if item collides with the path and mode, but also checks that if it - doesn't collide, maybe its frame rect will. -*/ -bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item, - const QPainterPath &path, - Qt::ItemSelectionMode mode) -{ - if (item->collidesWithPath(path, mode)) - return true; - if (item->isWidget()) { - // Check if this is a window, and if its frame rect collides. - const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item); - if (widget->isWindow()) { - QRectF frameRect = widget->windowFrameRect(); - QPainterPath framePath; - framePath.addRect(frameRect); - bool intersects = path.intersects(frameRect); - if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) - return intersects || path.contains(frameRect.topLeft()) - || framePath.contains(path.elementAt(0)); - return !intersects && path.contains(frameRect.topLeft()); - } - } - return false; -} - -/*! - \internal - This function returns the items in ascending order. -*/ -void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, - QGraphicsSceneIndexIntersector *intersector, - QList<QGraphicsItem *> *items, - const QTransform &viewTransform, - Qt::ItemSelectionMode mode, - qreal parentOpacity) const -{ - Q_ASSERT(item); - if (!item->d_ptr->visible) - return; - - const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity); - const bool itemHasChildren = !item->d_ptr->children.isEmpty(); - if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) - return; - - // Update the item's scene transform if dirty. - const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); - const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable; - if (wasDirtyParentSceneTransform) { - item->d_ptr->updateSceneTransformFromParent(); - Q_ASSERT(!item->d_ptr->dirtySceneTransform); - } - - const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); - bool processItem = !itemIsFullyTransparent; - if (processItem) { - processItem = intersector->intersect(item, exposeRect, mode, viewTransform); - if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) { - if (wasDirtyParentSceneTransform) - item->d_ptr->invalidateChildrenSceneTransform(); - return; - } - } // else we know for sure this item has children we must process. - - int i = 0; - if (itemHasChildren) { - // Sort children. - item->d_ptr->ensureSortedChildren(); - - // Clip to shape. - if (itemClipsChildrenToShape && !itemIsUntransformable) { - QPainterPath mappedShape = item->d_ptr->sceneTransformTranslateOnly - ? item->shape().translated(item->d_ptr->sceneTransform.dx(), - item->d_ptr->sceneTransform.dy()) - : item->d_ptr->sceneTransform.map(item->shape()); - exposeRect &= mappedShape.controlPointRect(); - } - - // Process children behind - for (i = 0; i < item->d_ptr->children.size(); ++i) { - QGraphicsItem *child = item->d_ptr->children.at(i); - if (wasDirtyParentSceneTransform) - child->d_ptr->dirtySceneTransform = 1; - if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) - break; - if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) - continue; - recursive_items_helper(child, exposeRect, intersector, items, viewTransform, - mode, opacity); - } - } - - // Process item - if (processItem) - items->append(item); - - // Process children in front - if (itemHasChildren) { - for (; i < item->d_ptr->children.size(); ++i) { - QGraphicsItem *child = item->d_ptr->children.at(i); - if (wasDirtyParentSceneTransform) - child->d_ptr->dirtySceneTransform = 1; - if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) - continue; - recursive_items_helper(child, exposeRect, intersector, items, viewTransform, - mode, opacity); - } - } -} - -void QGraphicsSceneIndexPrivate::init() -{ - if (!scene) - return; - - QObject::connect(scene, SIGNAL(sceneRectChanged(QRectF)), - q_func(), SLOT(updateSceneRect(QRectF))); -} - -/*! - Constructs an abstract scene index for a given \a scene. -*/ -QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) -: QObject(*new QGraphicsSceneIndexPrivate(scene), scene) -{ - d_func()->init(); -} - -/*! - \internal -*/ -QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene) - : QObject(dd, scene) -{ - d_func()->init(); -} - -/*! - Destroys the scene index. -*/ -QGraphicsSceneIndex::~QGraphicsSceneIndex() -{ - -} - -/*! - Returns the scene of this index. -*/ -QGraphicsScene* QGraphicsSceneIndex::scene() const -{ - Q_D(const QGraphicsSceneIndex); - return d->scene; -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, - Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform - &deviceTransform) const - - Returns all visible items that, depending on \a mode, are at the specified - \a pos and return a list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with \a pos are returned. - - \a deviceTransform is the transformation apply to the view. - - This method use the estimation of the index (estimateItems) and refine the - list to get an exact result. If you want to implement your own refinement - algorithm you can reimplement this method. - - \sa estimateItems() - -*/ -QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - - Q_D(const QGraphicsSceneIndex); - QList<QGraphicsItem *> itemList; - d->pointIntersector->scenePoint = pos; - d->items_helper(QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, deviceTransform, mode, order); - return itemList; -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, - Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform - &deviceTransform) const - - \overload - - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a rect and return a list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rect are returned. - - \a deviceTransform is the transformation apply to the view. - - This method use the estimation of the index (estimateItems) and refine - the list to get an exact result. If you want to implement your own - refinement algorithm you can reimplement this method. - - \sa estimateItems() - -*/ -QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsSceneIndex); - QRectF exposeRect = rect; - _q_adjustRect(&exposeRect); - QList<QGraphicsItem *> itemList; - d->rectIntersector->sceneRect = rect; - d->items_helper(exposeRect, d->rectIntersector, &itemList, deviceTransform, mode, order); - return itemList; -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF - &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const - QTransform &deviceTransform) const - - \overload - - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a polygon and return a list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a polygon are returned. - - \a deviceTransform is the transformation apply to the view. - - This method use the estimation of the index (estimateItems) and refine - the list to get an exact result. If you want to implement your own - refinement algorithm you can reimplement this method. - - \sa estimateItems() - -*/ -QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsSceneIndex); - QList<QGraphicsItem *> itemList; - QRectF exposeRect = polygon.boundingRect(); - _q_adjustRect(&exposeRect); - QPainterPath path; - path.addPolygon(polygon); - d->pathIntersector->scenePath = path; - d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order); - return itemList; -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath - &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform - &deviceTransform) const - - \overload - - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a path and return a list sorted using \a order. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. - - \a deviceTransform is the transformation apply to the view. - - This method use the estimation of the index (estimateItems) and refine - the list to get an exact result. If you want to implement your own - refinement algorithm you can reimplement this method. - - \sa estimateItems() - -*/ -QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsSceneIndex); - QList<QGraphicsItem *> itemList; - QRectF exposeRect = path.controlPointRect(); - _q_adjustRect(&exposeRect); - d->pathIntersector->scenePath = path; - d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order); - return itemList; -} - -/*! - This virtual function return an estimation of items at position \a point. - This method return a list sorted using \a order. -*/ -QList<QGraphicsItem *> QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const -{ - return estimateItems(QRectF(point, QSize(1, 1)), order); -} - -QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const -{ - Q_D(const QGraphicsSceneIndex); - Q_UNUSED(rect); - QGraphicsScenePrivate *scened = d->scene->d_func(); - scened->ensureSortedTopLevelItems(); - if (order == Qt::DescendingOrder) { - QList<QGraphicsItem *> sorted; - for (int i = scened->topLevelItems.size() - 1; i >= 0; --i) - sorted << scened->topLevelItems.at(i); - return sorted; - } - return scened->topLevelItems; -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const - - This pure virtual function all items in the index and sort them using - \a order. -*/ - - -/*! - Notifies the index that the scene's scene rect has changed. \a rect - is thew new scene rect. - - \sa QGraphicsScene::sceneRect() -*/ -void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect) -{ - Q_UNUSED(rect); -} - -/*! - This virtual function removes all items in the scene index. -*/ -void QGraphicsSceneIndex::clear() -{ - const QList<QGraphicsItem *> allItems = items(); - for (int i = 0 ; i < allItems.size(); ++i) - removeItem(allItems.at(i)); -} - -/*! - \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0 - - This pure virtual function inserts an \a item to the scene index. - - \sa removeItem(), deleteItem() -*/ - -/*! - \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0 - - This pure virtual function removes an \a item to the scene index. - - \sa addItem(), deleteItem() -*/ - -/*! - This method is called when an \a item has been deleted. - The default implementation call removeItem. Be carefull, - if your implementation of removeItem use pure virtual method - of QGraphicsItem like boundingRect(), then you should reimplement - this method. - - \sa addItem(), removeItem() -*/ -void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) -{ - removeItem(item); -} - -/*! - This virtual function is called by QGraphicsItem to notify the index - that some part of the \a item 's state changes. By reimplementing this - function, your can react to a change, and in some cases, (depending on \a - change,) adjustments in the index can be made. - - \a change is the parameter of the item that is changing. \a value is the - value that changed; the type of the value depends on \a change. - - The default implementation does nothing. - - \sa QGraphicsItem::GraphicsItemChange -*/ -void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value) -{ - Q_UNUSED(item); - Q_UNUSED(change); - Q_UNUSED(value); -} - -/*! - Notify the index for a geometry change of an \a item. - - \sa QGraphicsItem::prepareGeometryChange() -*/ -void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) -{ - Q_UNUSED(item); -} - -QT_END_NAMESPACE - -#include "moc_qgraphicssceneindex_p.cpp" - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h deleted file mode 100644 index d7e01f64b3..0000000000 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEINDEX_H -#define QGRAPHICSSCENEINDEX_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsscene_p.h" -#include "qgraphicsscene.h" -#include <private/qobject_p.h> - -#include <QtCore/qnamespace.h> -#include <QtCore/qobject.h> -#include <QtGui/qtransform.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsSceneIndexIntersector; -class QGraphicsSceneIndexPointIntersector; -class QGraphicsSceneIndexRectIntersector; -class QGraphicsSceneIndexPathIntersector; -class QGraphicsSceneIndexPrivate; -class QPointF; -class QRectF; -template<typename T> class QList; - -class Q_AUTOTEST_EXPORT QGraphicsSceneIndex : public QObject -{ - Q_OBJECT - -public: - QGraphicsSceneIndex(QGraphicsScene *scene = 0); - virtual ~QGraphicsSceneIndex(); - - QGraphicsScene *scene() const; - - virtual QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const = 0; - virtual QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList<QGraphicsItem *> estimateItems(const QPointF &point, Qt::SortOrder order) const; - virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const = 0; - virtual QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &, Qt::SortOrder order) const; - -protected Q_SLOTS: - virtual void updateSceneRect(const QRectF &rect); - -protected: - virtual void clear(); - virtual void addItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *item) = 0; - virtual void deleteItem(QGraphicsItem *item); - - virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const void *const value); - virtual void prepareBoundingRectChange(const QGraphicsItem *item); - - QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene); - - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - friend class QGraphicsSceneBspTreeIndex; -private: - Q_DISABLE_COPY(QGraphicsSceneIndex) - Q_DECLARE_PRIVATE(QGraphicsSceneIndex) -}; - -class QGraphicsSceneIndexPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneIndex) -public: - QGraphicsSceneIndexPrivate(QGraphicsScene *scene); - ~QGraphicsSceneIndexPrivate(); - - void init(); - static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); - - void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, - QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items, - const QTransform &viewTransform, - Qt::ItemSelectionMode mode, qreal parentOpacity = 1.0) const; - inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, - QList<QGraphicsItem *> *items, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order) const; - - QGraphicsScene *scene; - QGraphicsSceneIndexPointIntersector *pointIntersector; - QGraphicsSceneIndexRectIntersector *rectIntersector; - QGraphicsSceneIndexPathIntersector *pathIntersector; -}; - -inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, - QList<QGraphicsItem *> *items, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order) const -{ - Q_Q(const QGraphicsSceneIndex); - const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::AscendingOrder); - for (int i = 0; i < tli.size(); ++i) - recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode); - if (order == Qt::DescendingOrder) { - const int n = items->size(); - for (int i = 0; i < n / 2; ++i) - items->swap(i, n - i - 1); - } -} - -class QGraphicsSceneIndexIntersector -{ -public: - QGraphicsSceneIndexIntersector() { } - virtual ~QGraphicsSceneIndexIntersector() { } - virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &deviceTransform) const = 0; -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSSCENEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp deleted file mode 100644 index 9a4b3389bc..0000000000 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsSceneLinearIndex - \brief The QGraphicsSceneLinearIndex class provides an implementation of - a linear indexing algorithm for discovering items in QGraphicsScene. - \since 4.6 - \ingroup graphicsview-api - \internal - - QGraphicsSceneLinearIndex index is default linear implementation to discover items. - It basically store all items in a list and return them to the scene. - - \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex, QGraphicsSceneBspTreeIndex -*/ - -#include <private/qgraphicsscenelinearindex_p.h> - -/*! - \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): - - Construct a linear index for the given \a scene. -*/ - -/*! - \fn QList<QGraphicsItem *> QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const; - - Return all items in the index and sort them using \a order. -*/ - - -/*! - \fn virtual QList<QGraphicsItem *> QGraphicsSceneLinearIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const - - Returns an estimation visible items that are either inside or - intersect with the specified \a rect and return a list sorted using \a order. -*/ - -/*! - \fn void QGraphicsSceneLinearIndex::clear() - \internal - Clear the all the BSP index. -*/ - -/*! - \fn virtual void QGraphicsSceneLinearIndex::addItem(QGraphicsItem *item) - - Add the \a item into the index. -*/ - -/*! - \fn virtual void QGraphicsSceneLinearIndex::removeItem(QGraphicsItem *item) - - Add the \a item from the index. -*/ - diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h deleted file mode 100644 index 07dd6a22b6..0000000000 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_H -#define QGRAPHICSSCENELINEARINDEX_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include <QtCore/qrect.h> -#include <QtCore/qlist.h> -#include <QtGui/qgraphicsitem.h> -#include <private/qgraphicssceneindex_p.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene) - { } - - QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const - { Q_UNUSED(order); return m_items; } - - virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const - { - Q_UNUSED(rect); - Q_UNUSED(order); - return m_items; - } - -protected : - virtual void clear() - { m_items.clear(); } - - virtual void addItem(QGraphicsItem *item) - { m_items << item; } - - virtual void removeItem(QGraphicsItem *item) - { m_items.removeOne(item); } - -private: - QList<QGraphicsItem*> m_items; -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSSCENELINEARINDEX_H diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp deleted file mode 100644 index fa56427f36..0000000000 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ /dev/null @@ -1,594 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsTransform - \brief The QGraphicsTransform class is an abstract base class for building - advanced transformations on QGraphicsItems. - \since 4.6 - \ingroup graphicsview-api - - As an alternative to QGraphicsItem::transform, QGraphicsTransform lets you - create and control advanced transformations that can be configured - independently using specialized properties. - - QGraphicsItem allows you to assign any number of QGraphicsTransform - instances to one QGraphicsItem. Each QGraphicsTransform is applied in - order, one at a time, to the QGraphicsItem it's assigned to. - - QGraphicsTransform is particularly useful for animations. Whereas - QGraphicsItem::setTransform() lets you assign any transform directly to an - item, there is no direct way to interpolate between two different - transformations (e.g., when transitioning between two states, each for - which the item has a different arbitrary transform assigned). Using - QGraphicsTransform you can interpolate the property values of each - independent transformation. The resulting operation is then combined into a - single transform which is applied to QGraphicsItem. - - Transformations are computed in true 3D space using QMatrix4x4. - When the transformation is applied to a QGraphicsItem, it will be - projected back to a 2D QTransform. When multiple QGraphicsTransform - objects are applied to a QGraphicsItem, all of the transformations - are computed in true 3D space, with the projection back to 2D - only occurring after the last QGraphicsTransform is applied. - The exception to this is QGraphicsRotation, which projects back to - 2D after each rotation to preserve the perspective effect around - the X and Y axes. - - If you want to create your own configurable transformation, you can create - a subclass of QGraphicsTransform (or any or the existing subclasses), and - reimplement the pure virtual applyTo() function, which takes a pointer to a - QMatrix4x4. Each operation you would like to apply should be exposed as - properties (e.g., customTransform->setVerticalShear(2.5)). Inside you - reimplementation of applyTo(), you can modify the provided transform - respectively. - - QGraphicsTransform can be used together with QGraphicsItem::setTransform(), - QGraphicsItem::setRotation(), and QGraphicsItem::setScale(). - - \sa QGraphicsItem::transform(), QGraphicsScale, QGraphicsRotation -*/ - -#include "qgraphicstransform.h" -#include "qgraphicsitem_p.h" -#include "qgraphicstransform_p.h" -#include <QDebug> -#include <QtCore/qmath.h> -#include <QtCore/qnumeric.h> - -#ifndef QT_NO_GRAPHICSVIEW -QT_BEGIN_NAMESPACE -void QGraphicsTransformPrivate::setItem(QGraphicsItem *i) -{ - if (item == i) - return; - - if (item) { - Q_Q(QGraphicsTransform); - QGraphicsItemPrivate *d_ptr = item->d_ptr.data(); - - item->prepareGeometryChange(); - Q_ASSERT(d_ptr->transformData); - d_ptr->transformData->graphicsTransforms.removeAll(q); - d_ptr->dirtySceneTransform = 1; - item = 0; - } - - item = i; -} - -void QGraphicsTransformPrivate::updateItem(QGraphicsItem *item) -{ - item->prepareGeometryChange(); - item->d_ptr->dirtySceneTransform = 1; -} - -/*! - Constructs a new QGraphicsTransform with the given \a parent. -*/ -QGraphicsTransform::QGraphicsTransform(QObject *parent) - : QObject(*new QGraphicsTransformPrivate, parent) -{ -} - -/*! - Destroys the graphics transform. -*/ -QGraphicsTransform::~QGraphicsTransform() -{ - Q_D(QGraphicsTransform); - d->setItem(0); -} - -/*! - \internal -*/ -QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent) - : QObject(p, parent) -{ -} - -/*! - \fn void QGraphicsTransform::applyTo(QMatrix4x4 *matrix) const - - This pure virtual method has to be reimplemented in derived classes. - - It applies this transformation to \a matrix. - - \sa QGraphicsItem::transform(), QMatrix4x4::toTransform() -*/ - -/*! - Notifies that this transform operation has changed its parameters in such a - way that applyTo() will return a different result than before. - - When implementing you own custom graphics transform, you must call this - function every time you change a parameter, to let QGraphicsItem know that - its transformation needs to be updated. - - \sa applyTo() -*/ -void QGraphicsTransform::update() -{ - Q_D(QGraphicsTransform); - if (d->item) - d->updateItem(d->item); -} - -/*! - \class QGraphicsScale - \brief The QGraphicsScale class provides a scale transformation. - \since 4.6 - - QGraphicsScene provides certain parameters to help control how the scale - should be applied. - - The origin is the point that the item is scaled from (i.e., it stays fixed - relative to the parent as the rest of the item grows). By default the - origin is QPointF(0, 0). - - The parameters xScale, yScale, and zScale describe the scale factors to - apply in horizontal, vertical, and depth directions. They can take on any - value, including 0 (to collapse the item to a point) or negative value. - A negative xScale value will mirror the item horizontally. A negative yScale - value will flip the item vertically. A negative zScale will flip the - item end for end. - - \sa QGraphicsTransform, QGraphicsItem::setScale(), QTransform::scale() -*/ - -class QGraphicsScalePrivate : public QGraphicsTransformPrivate -{ -public: - QGraphicsScalePrivate() - : xScale(1), yScale(1), zScale(1) {} - QVector3D origin; - qreal xScale; - qreal yScale; - qreal zScale; -}; - -/*! - Constructs an empty QGraphicsScale object with the given \a parent. -*/ -QGraphicsScale::QGraphicsScale(QObject *parent) - : QGraphicsTransform(*new QGraphicsScalePrivate, parent) -{ -} - -/*! - Destroys the graphics scale. -*/ -QGraphicsScale::~QGraphicsScale() -{ -} - -/*! - \property QGraphicsScale::origin - \brief the origin of the scale in 3D space. - - All scaling will be done relative to this point (i.e., this point - will stay fixed, relative to the parent, when the item is scaled). - - \sa xScale, yScale, zScale -*/ -QVector3D QGraphicsScale::origin() const -{ - Q_D(const QGraphicsScale); - return d->origin; -} -void QGraphicsScale::setOrigin(const QVector3D &point) -{ - Q_D(QGraphicsScale); - if (d->origin == point) - return; - d->origin = point; - update(); - emit originChanged(); -} - -/*! - \property QGraphicsScale::xScale - \brief the horizontal scale factor. - - The scale factor can be any real number; the default value is 1.0. If you - set the factor to 0.0, the item will be collapsed to a single point. If you - provide a negative value, the item will be mirrored horizontally around its - origin. - - \sa yScale, zScale, origin -*/ -qreal QGraphicsScale::xScale() const -{ - Q_D(const QGraphicsScale); - return d->xScale; -} -void QGraphicsScale::setXScale(qreal scale) -{ - Q_D(QGraphicsScale); - if (d->xScale == scale) - return; - d->xScale = scale; - update(); - emit xScaleChanged(); - emit scaleChanged(); -} - -/*! - \property QGraphicsScale::yScale - \brief the vertical scale factor. - - The scale factor can be any real number; the default value is 1.0. If you - set the factor to 0.0, the item will be collapsed to a single point. If you - provide a negative value, the item will be flipped vertically around its - origin. - - \sa xScale, zScale, origin -*/ -qreal QGraphicsScale::yScale() const -{ - Q_D(const QGraphicsScale); - return d->yScale; -} -void QGraphicsScale::setYScale(qreal scale) -{ - Q_D(QGraphicsScale); - if (d->yScale == scale) - return; - d->yScale = scale; - update(); - emit yScaleChanged(); - emit scaleChanged(); -} - -/*! - \property QGraphicsScale::zScale - \brief the depth scale factor. - - The scale factor can be any real number; the default value is 1.0. If you - set the factor to 0.0, the item will be collapsed to a single point. If you - provide a negative value, the item will be flipped end for end around its - origin. - - \sa xScale, yScale, origin -*/ -qreal QGraphicsScale::zScale() const -{ - Q_D(const QGraphicsScale); - return d->zScale; -} -void QGraphicsScale::setZScale(qreal scale) -{ - Q_D(QGraphicsScale); - if (d->zScale == scale) - return; - d->zScale = scale; - update(); - emit zScaleChanged(); - emit scaleChanged(); -} - -/*! - \reimp -*/ -void QGraphicsScale::applyTo(QMatrix4x4 *matrix) const -{ - Q_D(const QGraphicsScale); - matrix->translate(d->origin); - matrix->scale(d->xScale, d->yScale, d->zScale); - matrix->translate(-d->origin); -} - -/*! - \fn QGraphicsScale::originChanged() - - QGraphicsScale emits this signal when its origin changes. - - \sa QGraphicsScale::origin -*/ - -/*! - \fn QGraphicsScale::xScaleChanged() - \since 4.7 - - This signal is emitted whenever the \l xScale property changes. -*/ - -/*! - \fn QGraphicsScale::yScaleChanged() - \since 4.7 - - This signal is emitted whenever the \l yScale property changes. -*/ - -/*! - \fn QGraphicsScale::zScaleChanged() - \since 4.7 - - This signal is emitted whenever the \l zScale property changes. -*/ - -/*! - \fn QGraphicsScale::scaleChanged() - - This signal is emitted whenever the xScale, yScale, or zScale - of the object changes. - - \sa QGraphicsScale::xScale, QGraphicsScale::yScale - \sa QGraphicsScale::zScale -*/ - -/*! - \class QGraphicsRotation - \brief The QGraphicsRotation class provides a rotation transformation around - a given axis. - \since 4.6 - - You can provide the desired axis by assigning a QVector3D to the axis property - or by passing a member if Qt::Axis to the setAxis convenience function. - By default the axis is (0, 0, 1) i.e., rotation around the Z axis. - - The angle property, which is provided by QGraphicsRotation, now - describes the number of degrees to rotate around this axis. - - QGraphicsRotation provides certain parameters to help control how the - rotation should be applied. - - The origin is the point that the item is rotated around (i.e., it stays - fixed relative to the parent as the rest of the item is rotated). By - default the origin is QPointF(0, 0). - - The angle property provides the number of degrees to rotate the item - clockwise around the origin. This value also be negative, indicating a - counter-clockwise rotation. For animation purposes it may also be useful to - provide rotation angles exceeding (-360, 360) degrees, for instance to - animate how an item rotates several times. - - Note: the final rotation is the combined effect of a rotation in - 3D space followed by a projection back to 2D. If several rotations - are performed in succession, they will not behave as expected unless - they were all around the Z axis. - - \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate() -*/ - -class QGraphicsRotationPrivate : public QGraphicsTransformPrivate -{ -public: - QGraphicsRotationPrivate() - : angle(0), axis(0, 0, 1) {} - QVector3D origin; - qreal angle; - QVector3D axis; -}; - -/*! - Constructs a new QGraphicsRotation with the given \a parent. -*/ -QGraphicsRotation::QGraphicsRotation(QObject *parent) - : QGraphicsTransform(*new QGraphicsRotationPrivate, parent) -{ -} - -/*! - Destroys the graphics rotation. -*/ -QGraphicsRotation::~QGraphicsRotation() -{ -} - -/*! - \property QGraphicsRotation::origin - \brief the origin of the rotation in 3D space. - - All rotations will be done relative to this point (i.e., this point - will stay fixed, relative to the parent, when the item is rotated). - - \sa angle -*/ -QVector3D QGraphicsRotation::origin() const -{ - Q_D(const QGraphicsRotation); - return d->origin; -} -void QGraphicsRotation::setOrigin(const QVector3D &point) -{ - Q_D(QGraphicsRotation); - if (d->origin == point) - return; - d->origin = point; - update(); - emit originChanged(); -} - -/*! - \property QGraphicsRotation::angle - \brief the angle for clockwise rotation, in degrees. - - The angle can be any real number; the default value is 0.0. A value of 180 - will rotate 180 degrees, clockwise. If you provide a negative number, the - item will be rotated counter-clockwise. Normally the rotation angle will be - in the range (-360, 360), but you can also provide numbers outside of this - range (e.g., a angle of 370 degrees gives the same result as 10 degrees). - Setting the angle to NaN results in no rotation. - - \sa origin -*/ -qreal QGraphicsRotation::angle() const -{ - Q_D(const QGraphicsRotation); - return d->angle; -} -void QGraphicsRotation::setAngle(qreal angle) -{ - Q_D(QGraphicsRotation); - if (d->angle == angle) - return; - d->angle = angle; - update(); - emit angleChanged(); -} - -/*! - \fn QGraphicsRotation::originChanged() - - This signal is emitted whenever the origin has changed. - - \sa QGraphicsRotation::origin -*/ - -/*! - \fn void QGraphicsRotation::angleChanged() - - This signal is emitted whenever the angle has changed. - - \sa QGraphicsRotation::angle -*/ - -/*! - \property QGraphicsRotation::axis - \brief a rotation axis, specified by a vector in 3D space. - - This can be any axis in 3D space. By default the axis is (0, 0, 1), - which is aligned with the Z axis. If you provide another axis, - QGraphicsRotation will provide a transformation that rotates - around this axis. For example, if you would like to rotate an item - around its X axis, you could pass (1, 0, 0) as the axis. - - \sa QTransform, QGraphicsRotation::angle -*/ -QVector3D QGraphicsRotation::axis() const -{ - Q_D(const QGraphicsRotation); - return d->axis; -} -void QGraphicsRotation::setAxis(const QVector3D &axis) -{ - Q_D(QGraphicsRotation); - if (d->axis == axis) - return; - d->axis = axis; - update(); - emit axisChanged(); -} - -/*! - \fn void QGraphicsRotation::setAxis(Qt::Axis axis) - - Convenience function to set the axis to \a axis. - - Note: the Qt::YAxis rotation for QTransform is inverted from the - correct mathematical rotation in 3D space. The QGraphicsRotation - class implements a correct mathematical rotation. The following - two sequences of code will perform the same transformation: - - \code - QTransform t; - t.rotate(45, Qt::YAxis); - - QGraphicsRotation r; - r.setAxis(Qt::YAxis); - r.setAngle(-45); - \endcode -*/ -void QGraphicsRotation::setAxis(Qt::Axis axis) -{ - switch (axis) - { - case Qt::XAxis: - setAxis(QVector3D(1, 0, 0)); - break; - case Qt::YAxis: - setAxis(QVector3D(0, 1, 0)); - break; - case Qt::ZAxis: - setAxis(QVector3D(0, 0, 1)); - break; - } -} - -/*! - \reimp -*/ -void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const -{ - Q_D(const QGraphicsRotation); - - if (d->angle == 0. || d->axis.isNull() || qIsNaN(d->angle)) - return; - - matrix->translate(d->origin); - matrix->projectedRotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z()); - matrix->translate(-d->origin); -} - -/*! - \fn void QGraphicsRotation::axisChanged() - - This signal is emitted whenever the axis of the object changes. - - \sa QGraphicsRotation::axis -*/ - -#include "moc_qgraphicstransform.cpp" - -QT_END_NAMESPACE -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h deleted file mode 100644 index a686edebc7..0000000000 --- a/src/gui/graphicsview/qgraphicstransform.h +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSTRANSFORM_H -#define QGRAPHICSTRANSFORM_H - -#include <QtCore/QObject> -#include <QtGui/QVector3D> -#include <QtGui/QTransform> -#include <QtGui/QMatrix4x4> - -#ifndef QT_NO_GRAPHICSVIEW -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QGraphicsItem; -class QGraphicsTransformPrivate; - -class Q_GUI_EXPORT QGraphicsTransform : public QObject -{ - Q_OBJECT -public: - QGraphicsTransform(QObject *parent = 0); - ~QGraphicsTransform(); - - virtual void applyTo(QMatrix4x4 *matrix) const = 0; - -protected Q_SLOTS: - void update(); - -protected: - QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent); - -private: - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - Q_DECLARE_PRIVATE(QGraphicsTransform) -}; - -class QGraphicsScalePrivate; - -class Q_GUI_EXPORT QGraphicsScale : public QGraphicsTransform -{ - Q_OBJECT - - Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged) - Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY xScaleChanged) - Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged) - Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged) -public: - QGraphicsScale(QObject *parent = 0); - ~QGraphicsScale(); - - QVector3D origin() const; - void setOrigin(const QVector3D &point); - - qreal xScale() const; - void setXScale(qreal); - - qreal yScale() const; - void setYScale(qreal); - - qreal zScale() const; - void setZScale(qreal); - - void applyTo(QMatrix4x4 *matrix) const; - -Q_SIGNALS: - void originChanged(); - void xScaleChanged(); - void yScaleChanged(); - void zScaleChanged(); - void scaleChanged(); - -private: - Q_DECLARE_PRIVATE(QGraphicsScale) -}; - -class QGraphicsRotationPrivate; - -class Q_GUI_EXPORT QGraphicsRotation : public QGraphicsTransform -{ - Q_OBJECT - - Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged) - Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) - Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged) -public: - QGraphicsRotation(QObject *parent = 0); - ~QGraphicsRotation(); - - QVector3D origin() const; - void setOrigin(const QVector3D &point); - - qreal angle() const; - void setAngle(qreal); - - QVector3D axis() const; - void setAxis(const QVector3D &axis); - void setAxis(Qt::Axis axis); - - void applyTo(QMatrix4x4 *matrix) const; - -Q_SIGNALS: - void originChanged(); - void angleChanged(); - void axisChanged(); - -private: - Q_DECLARE_PRIVATE(QGraphicsRotation) -}; - -QT_END_NAMESPACE - -QT_END_HEADER -#endif //QT_NO_GRAPHICSVIEW - -#endif // QFXTRANSFORM_H diff --git a/src/gui/graphicsview/qgraphicstransform_p.h b/src/gui/graphicsview/qgraphicstransform_p.h deleted file mode 100644 index d2b851fe97..0000000000 --- a/src/gui/graphicsview/qgraphicstransform_p.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSTRANSFORM_P_H -#define QGRAPHICSTRANSFORM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qobject_p.h" -#ifndef QT_NO_GRAPHICSVIEW -QT_BEGIN_NAMESPACE - -class QGraphicsItem; - -class QGraphicsTransformPrivate : public QObjectPrivate { -public: - Q_DECLARE_PUBLIC(QGraphicsTransform) - - QGraphicsTransformPrivate() - : QObjectPrivate(), item(0) {} - - QGraphicsItem *item; - - void setItem(QGraphicsItem *item); - static void updateItem(QGraphicsItem *item); -}; - -QT_END_NAMESPACE -#endif //QT_NO_GRAPHCISVIEW - -#endif // QGRAPHICSTRANSFORM_P_H diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp deleted file mode 100644 index 548f79fa17..0000000000 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ /dev/null @@ -1,3880 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50; - -static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < 2^9 - -/*! - \class QGraphicsView - \brief The QGraphicsView class provides a widget for displaying the - contents of a QGraphicsScene. - \since 4.2 - \ingroup graphicsview-api - - - QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable - viewport. To create a scene with geometrical items, see QGraphicsScene's - documentation. QGraphicsView is part of the \l{Graphics View Framework}. - - To visualize a scene, you start by constructing a QGraphicsView object, - passing the address of the scene you want to visualize to QGraphicsView's - constructor. Alternatively, you can call setScene() to set the scene at a - later point. After you call show(), the view will by default scroll to the - center of the scene and display any items that are visible at this - point. For example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 0 - - You can explicitly scroll to any position on the scene by using the - scroll bars, or by calling centerOn(). By passing a point to centerOn(), - QGraphicsView will scroll its viewport to ensure that the point is - centered in the view. An overload is provided for scrolling to a - QGraphicsItem, in which case QGraphicsView will see to that the center of - the item is centered in the view. If all you want is to ensure that a - certain area is visible, (but not necessarily centered,) you can call - ensureVisible() instead. - - QGraphicsView can be used to visualize a whole scene, or only parts of it. - The visualized area is by default detected automatically when the view is - displayed for the first time (by calling - QGraphicsScene::itemsBoundingRect()). To set the visualized area rectangle - yourself, you can call setSceneRect(). This will adjust the scroll bars' - ranges appropriately. Note that although the scene supports a virtually - unlimited size, the range of the scroll bars will never exceed the range of - an integer (INT_MIN, INT_MAX). - - QGraphicsView visualizes the scene by calling render(). By default, the - items are drawn onto the viewport by using a regular QPainter, and using - default render hints. To change the default render hints that - QGraphicsView passes to QPainter when painting items, you can call - setRenderHints(). - - By default, QGraphicsView provides a regular QWidget for the viewport - widget. You can access this widget by calling viewport(), or you can - replace it by calling setViewport(). To render using OpenGL, simply call - setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport - widget. - - QGraphicsView supports affine transformations, using QTransform. You can - either pass a matrix to setTransform(), or you can call one of the - convenience functions rotate(), scale(), translate() or shear(). The most - two common transformations are scaling, which is used to implement - zooming, and rotation. QGraphicsView keeps the center of the view fixed - during a transformation. Because of the scene alignment (setAligment()), - translating the view will have no visual impact. - - You can interact with the items on the scene by using the mouse and - keyboard. QGraphicsView translates the mouse and key events into \e scene - events, (events that inherit QGraphicsSceneEvent,), and forward them to - the visualized scene. In the end, it's the individual item that handles - the events and reacts to them. For example, if you click on a selectable - item, the item will typically let the scene know that it has been - selected, and it will also redraw itself to display a selection - rectangle. Similiary, if you click and drag the mouse to move a movable - item, it's the item that handles the mouse moves and moves itself. Item - interaction is enabled by default, and you can toggle it by calling - setInteractive(). - - You can also provide your own custom scene interaction, by creating a - subclass of QGraphicsView, and reimplementing the mouse and key event - handlers. To simplify how you programmatically interact with items in the - view, QGraphicsView provides the mapping functions mapToScene() and - mapFromScene(), and the item accessors items() and itemAt(). These - functions allow you to map points, rectangles, polygons and paths between - view coordinates and scene coordinates, and to find items on the scene - using view coordinates. - - \img graphicsview-view.png - - \sa QGraphicsScene, QGraphicsItem, QGraphicsSceneEvent -*/ - -/*! - \enum QGraphicsView::ViewportAnchor - - This enums describe the possible anchors that QGraphicsView can - use when the user resizes the view or when the view is - transformed. - - \value NoAnchor No anchor, i.e. the view leaves the scene's - position unchanged. - \value AnchorViewCenter The scene point at the center of the view - is used as the anchor. - \value AnchorUnderMouse The point under the mouse is used as the anchor. - - \sa resizeAnchor, transformationAnchor -*/ - -/*! - \enum QGraphicsView::ViewportUpdateMode - - \since 4.3 - - This enum describes how QGraphicsView updates its viewport when the scene - contents change or are exposed. - - \value FullViewportUpdate When any visible part of the scene changes or is - reexposed, QGraphicsView will update the entire viewport. This approach is - fastest when QGraphicsView spends more time figuring out what to draw than - it would spend drawing (e.g., when very many small items are repeatedly - updated). This is the preferred update mode for viewports that do not - support partial updates, such as QGLWidget, and for viewports that need to - disable scroll optimization. - - \value MinimalViewportUpdate QGraphicsView will determine the minimal - viewport region that requires a redraw, minimizing the time spent drawing - by avoiding a redraw of areas that have not changed. This is - QGraphicsView's default mode. Although this approach provides the best - performance in general, if there are many small visible changes on the - scene, QGraphicsView might end up spending more time finding the minimal - approach than it will spend drawing. - - \value SmartViewportUpdate QGraphicsView will attempt to find an optimal - update mode by analyzing the areas that require a redraw. - - \value BoundingRectViewportUpdate The bounding rectangle of all changes in - the viewport will be redrawn. This mode has the advantage that - QGraphicsView searches only one region for changes, minimizing time spent - determining what needs redrawing. The disadvantage is that areas that have - not changed also need to be redrawn. - - \value NoViewportUpdate QGraphicsView will never update its viewport when - the scene changes; the user is expected to control all updates. This mode - disables all (potentially slow) item visibility testing in QGraphicsView, - and is suitable for scenes that either require a fixed frame rate, or where - the viewport is otherwise updated externally. - - \sa viewportUpdateMode -*/ - -/*! - \enum QGraphicsView::OptimizationFlag - - \since 4.3 - - This enum describes flags that you can enable to improve rendering - performance in QGraphicsView. By default, none of these flags are set. - Note that setting a flag usually imposes a side effect, and this effect - can vary between paint devices and platforms. - - \value DontClipPainter This value is obsolete and has no effect. - - \value DontSavePainterState When rendering, QGraphicsView protects the - painter state (see QPainter::save()) when rendering the background or - foreground, and when rendering each item. This allows you to leave the - painter in an altered state (i.e., you can call QPainter::setPen() or - QPainter::setBrush() without restoring the state after painting). However, - if the items consistently do restore the state, you should enable this - flag to prevent QGraphicsView from doing the same. - - \value DontAdjustForAntialiasing Disables QGraphicsView's antialiasing - auto-adjustment of exposed areas. Items that render antialiased lines on - the boundaries of their QGraphicsItem::boundingRect() can end up rendering - parts of the line outside. To prevent rendering artifacts, QGraphicsView - expands all exposed regions by 2 pixels in all directions. If you enable - this flag, QGraphicsView will no longer perform these adjustments, - minimizing the areas that require redrawing, which improves performance. A - common side effect is that items that do draw with antialiasing can leave - painting traces behind on the scene as they are moved. - - \value IndirectPainting Since Qt 4.6, restore the old painting algorithm - that calls QGraphicsView::drawItems() and QGraphicsScene::drawItems(). - To be used only for compatibility with old code. -*/ - -/*! - \enum QGraphicsView::CacheModeFlag - - This enum describes the flags that you can set for a QGraphicsView's cache - mode. - - \value CacheNone All painting is done directly onto the viewport. - - \value CacheBackground The background is cached. This affects both custom - backgrounds, and backgrounds based on the backgroundBrush property. When - this flag is enabled, QGraphicsView will allocate one pixmap with the full - size of the viewport. - - \sa cacheMode -*/ - -/*! - \enum QGraphicsView::DragMode - - This enum describes the default action for the view when pressing and - dragging the mouse over the viewport. - - \value NoDrag Nothing happens; the mouse event is ignored. - - \value ScrollHandDrag The cursor changes into a pointing hand, and - dragging the mouse around will scroll the scrolbars. This mode works both - in \l{QGraphicsView::interactive}{interactive} and non-interactive mode. - - \value RubberBandDrag A rubber band will appear. Dragging the mouse will - set the rubber band geometry, and all items covered by the rubber band are - selected. This mode is disabled for non-interactive views. - - \sa dragMode, QGraphicsScene::setSelectionArea() -*/ - -#include "qgraphicsview.h" -#include "qgraphicsview_p.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicsitem.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene.h" -#include "qgraphicsscene_p.h" -#include "qgraphicssceneevent.h" -#include "qgraphicswidget.h" - -#include <QtCore/qdatetime.h> -#include <QtCore/qdebug.h> -#include <QtCore/qmath.h> -#include <QtGui/qapplication.h> -#include <QtGui/qdesktopwidget.h> -#include <QtGui/qevent.h> -#include <QtGui/qlayout.h> -#include <QtGui/qtransform.h> -#include <QtGui/qmatrix.h> -#include <QtGui/qpainter.h> -#include <QtGui/qscrollbar.h> -#include <QtGui/qstyleoption.h> -#include <QtGui/qinputcontext.h> -#ifdef Q_WS_X11 -#include <QtGui/qpaintengine.h> -#include <private/qt_x11_p.h> -#endif - -#include <private/qevent_p.h> - -QT_BEGIN_NAMESPACE - -bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); - -inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision -{ - if (d <= (qreal) INT_MIN) - return INT_MIN; - else if (d >= (qreal) INT_MAX) - return INT_MAX; - return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1); -} - -void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent) -{ - QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints(); - for (int i = 0; i < touchPoints.count(); ++i) { - QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; - // the scene will set the item local pos, startPos, lastPos, and rect before delivering to - // an item, but for now those functions are returning the view's local coordinates - touchPoint.setSceneRect(d->mapToScene(touchPoint.rect())); - touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos())); - touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos())); - - // screenPos, startScreenPos, lastScreenPos, and screenRect are already set - } - - touchEvent->setTouchPoints(touchPoints); -} - -/*! - \internal -*/ -QGraphicsViewPrivate::QGraphicsViewPrivate() - : renderHints(QPainter::TextAntialiasing), - dragMode(QGraphicsView::NoDrag), - sceneInteractionAllowed(true), hasSceneRect(false), - connectedToScene(false), - useLastMouseEvent(false), - identityMatrix(true), - dirtyScroll(true), - accelerateScrolling(true), - keepLastCenterPoint(true), - transforming(false), - handScrolling(false), - mustAllocateStyleOptions(false), - mustResizeBackgroundPixmap(true), - fullUpdatePending(true), - hasUpdateClip(false), - mousePressButton(Qt::NoButton), - leftIndent(0), topIndent(0), - lastMouseEvent(QEvent::None, QPoint(), Qt::NoButton, 0, 0), - alignment(Qt::AlignCenter), - transformationAnchor(QGraphicsView::AnchorViewCenter), resizeAnchor(QGraphicsView::NoAnchor), - viewportUpdateMode(QGraphicsView::MinimalViewportUpdate), - optimizationFlags(0), - scene(0), -#ifndef QT_NO_RUBBERBAND - rubberBanding(false), - rubberBandSelectionMode(Qt::IntersectsItemShape), -#endif - handScrollMotions(0), cacheMode(0), -#ifndef QT_NO_CURSOR - hasStoredOriginalCursor(false), -#endif - lastDragDropEvent(0), - updateSceneSlotReimplementedChecked(false) -{ - styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS); -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::recalculateContentSize() -{ - Q_Q(QGraphicsView); - - QSize maxSize = q->maximumViewportSize(); - int width = maxSize.width(); - int height = maxSize.height(); - QRectF viewRect = matrix.mapRect(q->sceneRect()); - - bool frameOnlyAround = (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)); - if (frameOnlyAround) { - if (hbarpolicy == Qt::ScrollBarAlwaysOn) - height -= frameWidth * 2; - if (vbarpolicy == Qt::ScrollBarAlwaysOn) - width -= frameWidth * 2; - } - - // Adjust the maximum width and height of the viewport based on the width - // of visible scroll bars. - int scrollBarExtent = q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q); - if (frameOnlyAround) - scrollBarExtent += frameWidth * 2; - - bool useHorizontalScrollBar = (viewRect.width() > width) && hbarpolicy != Qt::ScrollBarAlwaysOff; - bool useVerticalScrollBar = (viewRect.height() > height) && vbarpolicy != Qt::ScrollBarAlwaysOff; - if (useHorizontalScrollBar && !useVerticalScrollBar) { - if (viewRect.height() > height - scrollBarExtent) - useVerticalScrollBar = true; - } - if (useVerticalScrollBar && !useHorizontalScrollBar) { - if (viewRect.width() > width - scrollBarExtent) - useHorizontalScrollBar = true; - } - if (useHorizontalScrollBar && hbarpolicy != Qt::ScrollBarAlwaysOn) - height -= scrollBarExtent; - if (useVerticalScrollBar && vbarpolicy != Qt::ScrollBarAlwaysOn) - width -= scrollBarExtent; - - // Setting the ranges of these scroll bars can/will cause the values to - // change, and scrollContentsBy() will be called correspondingly. This - // will reset the last center point. - QPointF savedLastCenterPoint = lastCenterPoint; - - // Remember the former indent settings - qreal oldLeftIndent = leftIndent; - qreal oldTopIndent = topIndent; - - // If the whole scene fits horizontally, we center the scene horizontally, - // and ignore the horizontal scroll bars. - int left = q_round_bound(viewRect.left()); - int right = q_round_bound(viewRect.right() - width); - if (left >= right) { - hbar->setRange(0, 0); - - switch (alignment & Qt::AlignHorizontal_Mask) { - case Qt::AlignLeft: - leftIndent = -viewRect.left(); - break; - case Qt::AlignRight: - leftIndent = width - viewRect.width() - viewRect.left() - 1; - break; - case Qt::AlignHCenter: - default: - leftIndent = width / 2 - (viewRect.left() + viewRect.right()) / 2; - break; - } - } else { - hbar->setRange(left, right); - hbar->setPageStep(width); - hbar->setSingleStep(width / 20); - leftIndent = 0; - } - - // If the whole scene fits vertically, we center the scene vertically, and - // ignore the vertical scroll bars. - int top = q_round_bound(viewRect.top()); - int bottom = q_round_bound(viewRect.bottom() - height); - if (top >= bottom) { - vbar->setRange(0, 0); - - switch (alignment & Qt::AlignVertical_Mask) { - case Qt::AlignTop: - topIndent = -viewRect.top(); - break; - case Qt::AlignBottom: - topIndent = height - viewRect.height() - viewRect.top() - 1; - break; - case Qt::AlignVCenter: - default: - topIndent = height / 2 - (viewRect.top() + viewRect.bottom()) / 2; - break; - } - } else { - vbar->setRange(top, bottom); - vbar->setPageStep(height); - vbar->setSingleStep(height / 20); - topIndent = 0; - } - - // Restorethe center point from before the ranges changed. - lastCenterPoint = savedLastCenterPoint; - - // Issue a full update if the indents change. - // ### If the transform is still the same, we can get away with just a - // scroll instead. - if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) { - dirtyScroll = true; - updateAll(); - } else if (q->isRightToLeft() && !leftIndent) { - // In reverse mode, the horizontal scroll always changes after the content - // size has changed, as the scroll is calculated by summing the min and - // max values of the range and subtracting the current value. In normal - // mode the scroll remains unchanged unless the indent has changed. - dirtyScroll = true; - } - - if (cacheMode & QGraphicsView::CacheBackground) { - // Invalidate the background pixmap - mustResizeBackgroundPixmap = true; - } -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor) -{ - Q_Q(QGraphicsView); - switch (anchor) { - case QGraphicsView::AnchorUnderMouse: { - if (q->underMouse()) { - // Last scene pos: lastMouseMoveScenePoint - // Current mouse pos: - QPointF transformationDiff = q->mapToScene(viewport->rect().center()) - - q->mapToScene(viewport->mapFromGlobal(QCursor::pos())); - q->centerOn(lastMouseMoveScenePoint + transformationDiff); - } else { - q->centerOn(lastCenterPoint); - } - break; - } - case QGraphicsView::AnchorViewCenter: - q->centerOn(lastCenterPoint); - break; - case QGraphicsView::NoAnchor: - break; - } -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::updateLastCenterPoint() -{ - Q_Q(QGraphicsView); - lastCenterPoint = q->mapToScene(viewport->rect().center()); -} - -/*! - \internal - - Returns the horizontal scroll value (the X value of the left edge of the - viewport). -*/ -qint64 QGraphicsViewPrivate::horizontalScroll() const -{ - if (dirtyScroll) - const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); - return scrollX; -} - -/*! - \internal - - Returns the vertical scroll value (the X value of the top edge of the - viewport). -*/ -qint64 QGraphicsViewPrivate::verticalScroll() const -{ - if (dirtyScroll) - const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); - return scrollY; -} - -/*! - \internal - - Maps the given rectangle to the scene using QTransform::mapRect() -*/ -QRectF QGraphicsViewPrivate::mapRectToScene(const QRect &rect) const -{ - if (dirtyScroll) - const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); - QRectF scrolled = QRectF(rect.translated(scrollX, scrollY)); - return identityMatrix ? scrolled : matrix.inverted().mapRect(scrolled); -} - - -/*! - \internal - - Maps the given rectangle from the scene using QTransform::mapRect() -*/ -QRectF QGraphicsViewPrivate::mapRectFromScene(const QRectF &rect) const -{ - if (dirtyScroll) - const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); - return (identityMatrix ? rect : matrix.mapRect(rect)).translated(-scrollX, -scrollY); -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::updateScroll() -{ - Q_Q(QGraphicsView); - scrollX = qint64(-leftIndent); - if (q->isRightToLeft()) { - if (!leftIndent) { - scrollX += hbar->minimum(); - scrollX += hbar->maximum(); - scrollX -= hbar->value(); - } - } else { - scrollX += hbar->value(); - } - - scrollY = qint64(vbar->value() - topIndent); - - dirtyScroll = false; -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::replayLastMouseEvent() -{ - if (!useLastMouseEvent || !scene) - return; - mouseMoveEventHandler(&lastMouseEvent); -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::storeMouseEvent(QMouseEvent *event) -{ - useLastMouseEvent = true; - lastMouseEvent = QMouseEvent(QEvent::MouseMove, event->pos(), event->globalPos(), - event->button(), event->buttons(), event->modifiers()); -} - -void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event) -{ - Q_Q(QGraphicsView); - - storeMouseEvent(event); - lastMouseEvent.setAccepted(false); - - if (!sceneInteractionAllowed) - return; - if (handScrolling) - return; - if (!scene) - return; - - QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove); - mouseEvent.setWidget(viewport); - mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint); - mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint); - mouseEvent.setScenePos(q->mapToScene(event->pos())); - mouseEvent.setScreenPos(event->globalPos()); - mouseEvent.setLastScenePos(lastMouseMoveScenePoint); - mouseEvent.setLastScreenPos(lastMouseMoveScreenPoint); - mouseEvent.setButtons(event->buttons()); - mouseEvent.setButton(event->button()); - mouseEvent.setModifiers(event->modifiers()); - lastMouseMoveScenePoint = mouseEvent.scenePos(); - lastMouseMoveScreenPoint = mouseEvent.screenPos(); - mouseEvent.setAccepted(false); - if (event->spontaneous()) - qt_sendSpontaneousEvent(scene, &mouseEvent); - else - QApplication::sendEvent(scene, &mouseEvent); - - // Remember whether the last event was accepted or not. - lastMouseEvent.setAccepted(mouseEvent.isAccepted()); - - if (mouseEvent.isAccepted() && mouseEvent.buttons() != 0) { - // The event was delivered to a mouse grabber; the press is likely to - // have set a cursor, and we must not change it. - return; - } - -#ifndef QT_NO_CURSOR - // If all the items ignore hover events, we don't look-up any items - // in QGraphicsScenePrivate::dispatchHoverEvent, hence the - // cachedItemsUnderMouse list will be empty. We therefore do the look-up - // for cursor items here if not all items use the default cursor. - if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor - && scene->d_func()->cachedItemsUnderMouse.isEmpty()) { - scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(), - mouseEvent.scenePos(), - mouseEvent.widget()); - } - // Find the topmost item under the mouse with a cursor. - foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) { - if (item->hasCursor()) { - _q_setViewportCursor(item->cursor()); - return; - } - } - - // No items with cursors found; revert to the view cursor. - if (hasStoredOriginalCursor) { - // Restore the original viewport cursor. - hasStoredOriginalCursor = false; - viewport->setCursor(originalCursor); - } -#endif -} - -/*! - \internal -*/ -#ifndef QT_NO_RUBBERBAND -QRegion QGraphicsViewPrivate::rubberBandRegion(const QWidget *widget, const QRect &rect) const -{ - QStyleHintReturnMask mask; - QStyleOptionRubberBand option; - option.initFrom(widget); - option.rect = rect; - option.opaque = false; - option.shape = QRubberBand::Rectangle; - - QRegion tmp; - tmp += rect; - if (widget->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, widget, &mask)) - tmp &= mask.region; - return tmp; -} -#endif - -/*! - \internal -*/ -#ifndef QT_NO_CURSOR -void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor) -{ - if (!hasStoredOriginalCursor) { - hasStoredOriginalCursor = true; - originalCursor = viewport->cursor(); - } - viewport->setCursor(cursor); -} -#endif - -/*! - \internal -*/ -#ifndef QT_NO_CURSOR -void QGraphicsViewPrivate::_q_unsetViewportCursor() -{ - Q_Q(QGraphicsView); - foreach (QGraphicsItem *item, q->items(lastMouseEvent.pos())) { - if (item->hasCursor()) { - _q_setViewportCursor(item->cursor()); - return; - } - } - - // Restore the original viewport cursor. - if (hasStoredOriginalCursor) { - hasStoredOriginalCursor = false; - if (dragMode == QGraphicsView::ScrollHandDrag) - viewport->setCursor(Qt::OpenHandCursor); - else - viewport->setCursor(originalCursor); - } -} -#endif - -/*! - \internal -*/ -void QGraphicsViewPrivate::storeDragDropEvent(const QGraphicsSceneDragDropEvent *event) -{ - delete lastDragDropEvent; - lastDragDropEvent = new QGraphicsSceneDragDropEvent(event->type()); - lastDragDropEvent->setScenePos(event->scenePos()); - lastDragDropEvent->setScreenPos(event->screenPos()); - lastDragDropEvent->setButtons(event->buttons()); - lastDragDropEvent->setModifiers(event->modifiers()); - lastDragDropEvent->setPossibleActions(event->possibleActions()); - lastDragDropEvent->setProposedAction(event->proposedAction()); - lastDragDropEvent->setDropAction(event->dropAction()); - lastDragDropEvent->setMimeData(event->mimeData()); - lastDragDropEvent->setWidget(event->widget()); - lastDragDropEvent->setSource(event->source()); -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEvent *dest, - QDropEvent *source) -{ -#ifndef QT_NO_DRAGANDDROP - Q_Q(QGraphicsView); - dest->setScenePos(q->mapToScene(source->pos())); - dest->setScreenPos(q->mapToGlobal(source->pos())); - dest->setButtons(source->mouseButtons()); - dest->setModifiers(source->keyboardModifiers()); - dest->setPossibleActions(source->possibleActions()); - dest->setProposedAction(source->proposedAction()); - dest->setDropAction(source->dropAction()); - dest->setMimeData(source->mimeData()); - dest->setWidget(viewport); - dest->setSource(source->source()); -#else - Q_UNUSED(dest) - Q_UNUSED(source) -#endif -} - -/*! - \internal -*/ -QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const -{ - Q_Q(const QGraphicsView); - if (dirtyScroll) - const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); - - if (item->d_ptr->itemIsUntransformable()) { - QTransform itv = item->deviceTransform(q->viewportTransform()); - return itv.mapRect(rect).toAlignedRect(); - } - - // Translate-only - // COMBINE - QPointF offset; - const QGraphicsItem *parentItem = item; - const QGraphicsItemPrivate *itemd; - do { - itemd = parentItem->d_ptr.data(); - if (itemd->transformData) - break; - offset += itemd->pos; - } while ((parentItem = itemd->parent)); - - QRectF baseRect = rect.translated(offset.x(), offset.y()); - if (!parentItem) { - if (identityMatrix) { - baseRect.translate(-scrollX, -scrollY); - return baseRect.toAlignedRect(); - } - return matrix.mapRect(baseRect).translated(-scrollX, -scrollY).toAlignedRect(); - } - - QTransform tr = parentItem->sceneTransform(); - if (!identityMatrix) - tr *= matrix; - QRectF r = tr.mapRect(baseRect); - r.translate(-scrollX, -scrollY); - return r.toAlignedRect(); -} - -/*! - \internal -*/ -QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const -{ - Q_Q(const QGraphicsView); - if (dirtyScroll) - const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); - - // Accurate bounding region - QTransform itv = item->deviceTransform(q->viewportTransform()); - return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); -} - -/*! - \internal -*/ -void QGraphicsViewPrivate::processPendingUpdates() -{ - if (!scene) - return; - - if (fullUpdatePending) { - viewport->update(); - } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { - viewport->update(dirtyBoundingRect); - } else { - viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. - } - - dirtyBoundingRect = QRect(); - dirtyRegion = QRegion(); -} - -static inline bool intersectsViewport(const QRect &r, int width, int height) -{ return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); } - -static inline bool containsViewport(const QRect &r, int width, int height) -{ return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; } - -static inline void QRect_unite(QRect *rect, const QRect &other) -{ - if (rect->isEmpty()) { - *rect = other; - } else { - rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()), - qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom())); - } -} - -/* - Calling this function results in update rects being clipped to the item's - bounding rect. Note that updates prior to this function call is not clipped. - The clip is removed by passing 0. -*/ -void QGraphicsViewPrivate::setUpdateClip(QGraphicsItem *item) -{ - Q_Q(QGraphicsView); - // We simply ignore the request if the update mode is either FullViewportUpdate - // or NoViewportUpdate; in that case there's no point in clipping anything. - if (!item || viewportUpdateMode == QGraphicsView::NoViewportUpdate - || viewportUpdateMode == QGraphicsView::FullViewportUpdate) { - hasUpdateClip = false; - return; - } - - // Calculate the clip (item's bounding rect in view coordinates). - // Optimized version of: - // QRect clip = item->deviceTransform(q->viewportTransform()) - // .mapRect(item->boundingRect()).toAlignedRect(); - QRect clip; - if (item->d_ptr->itemIsUntransformable()) { - QTransform xform = item->deviceTransform(q->viewportTransform()); - clip = xform.mapRect(item->boundingRect()).toAlignedRect(); - } else if (item->d_ptr->sceneTransformTranslateOnly && identityMatrix) { - QRectF r(item->boundingRect()); - r.translate(item->d_ptr->sceneTransform.dx() - horizontalScroll(), - item->d_ptr->sceneTransform.dy() - verticalScroll()); - clip = r.toAlignedRect(); - } else if (!q->isTransformed()) { - clip = item->d_ptr->sceneTransform.mapRect(item->boundingRect()).toAlignedRect(); - } else { - QTransform xform = item->d_ptr->sceneTransform; - xform *= q->viewportTransform(); - clip = xform.mapRect(item->boundingRect()).toAlignedRect(); - } - - if (hasUpdateClip) { - // Intersect with old clip. - updateClip &= clip; - } else { - updateClip = clip; - hasUpdateClip = true; - } -} - -bool QGraphicsViewPrivate::updateRegion(const QRectF &rect, const QTransform &xform) -{ - if (rect.isEmpty()) - return false; - - if (viewportUpdateMode != QGraphicsView::MinimalViewportUpdate - && viewportUpdateMode != QGraphicsView::SmartViewportUpdate) { - // No point in updating with QRegion granularity; use the rect instead. - return updateRectF(xform.mapRect(rect)); - } - - // Update mode is either Minimal or Smart, so we have to do a potentially slow operation, - // which is clearly documented here: QGraphicsItem::setBoundingRegionGranularity. - const QRegion region = xform.map(QRegion(rect.toAlignedRect())); - QRect viewRect = region.boundingRect(); - const bool dontAdjustForAntialiasing = optimizationFlags & QGraphicsView::DontAdjustForAntialiasing; - if (dontAdjustForAntialiasing) - viewRect.adjust(-1, -1, 1, 1); - else - viewRect.adjust(-2, -2, 2, 2); - if (!intersectsViewport(viewRect, viewport->width(), viewport->height())) - return false; // Update region for sure outside viewport. - - const QVector<QRect> &rects = region.rects(); - for (int i = 0; i < rects.size(); ++i) { - viewRect = rects.at(i); - if (dontAdjustForAntialiasing) - viewRect.adjust(-1, -1, 1, 1); - else - viewRect.adjust(-2, -2, 2, 2); - if (hasUpdateClip) - viewRect &= updateClip; - dirtyRegion += viewRect; - } - - return true; -} - -// NB! Assumes the rect 'r' is already aligned and adjusted for antialiasing. -// For QRectF use updateRectF(const QRectF &) to ensure proper adjustments. -bool QGraphicsViewPrivate::updateRect(const QRect &r) -{ - if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate - || !intersectsViewport(r, viewport->width(), viewport->height())) { - return false; - } - - switch (viewportUpdateMode) { - case QGraphicsView::FullViewportUpdate: - fullUpdatePending = true; - viewport->update(); - break; - case QGraphicsView::BoundingRectViewportUpdate: - if (hasUpdateClip) - QRect_unite(&dirtyBoundingRect, r & updateClip); - else - QRect_unite(&dirtyBoundingRect, r); - if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { - fullUpdatePending = true; - viewport->update(); - } - break; - case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE - case QGraphicsView::MinimalViewportUpdate: - if (hasUpdateClip) - dirtyRegion += r & updateClip; - else - dirtyRegion += r; - break; - default: - break; - } - - return true; -} - -QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems) -{ - if (mustAllocateStyleOptions || (numItems > styleOptions.capacity())) - // too many items, let's allocate on-the-fly - return new QStyleOptionGraphicsItem[numItems]; - - // expand only whenever necessary - if (numItems > styleOptions.size()) - styleOptions.resize(numItems); - - mustAllocateStyleOptions = true; - return styleOptions.data(); -} - -void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array) -{ - mustAllocateStyleOptions = false; - if (array != styleOptions.data()) - delete [] array; -} - -extern QPainterPath qt_regionToPath(const QRegion ®ion); - -/*! - ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the - input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight() - (etc) when mapping the rectangle to a polygon (which is _wrong_). In - addition, as QGraphicsItem::boundingRect() is defined in logical space, - but the default pen for QPainter is cosmetic with a width of 0, QPainter - is at risk of painting 1 pixel outside the bounding rect. Therefore we - must search for items with an adjustment of (-1, -1, 1, 1). -*/ -QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems, - const QTransform &viewTransform) const -{ - Q_Q(const QGraphicsView); - - // Step 1) If all items are contained within the expose region, then - // return a list of all visible items. ### the scene's growing bounding - // rect does not take into account untransformable items. - const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1)) - .boundingRect(); - if (exposedRegionSceneBounds.contains(scene->sceneRect())) { - Q_ASSERT(allItems); - *allItems = true; - - // All items are guaranteed within the exposed region. - return scene->items(Qt::AscendingOrder); - } - - // Step 2) If the expose region is a simple rect and the view is only - // translated or scaled, search for items using - // QGraphicsScene::items(QRectF). - bool simpleRectLookup = exposedRegion.rectCount() == 1 && matrix.type() <= QTransform::TxScale; - if (simpleRectLookup) { - return scene->items(exposedRegionSceneBounds, - Qt::IntersectsItemBoundingRect, - Qt::AscendingOrder, viewTransform); - } - - // If the region is complex or the view has a complex transform, adjust - // the expose region, convert it to a path, and then search for items - // using QGraphicsScene::items(QPainterPath); - QRegion adjustedRegion; - foreach (const QRect &r, exposedRegion.rects()) - adjustedRegion += r.adjusted(-1, -1, 1, 1); - - const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); - return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect, - Qt::AscendingOrder, viewTransform); -} - -/*! - \internal - - Enables input methods for the view if and only if the current focus item of - the scene accepts input methods. Call function whenever that condition has - potentially changed. -*/ -void QGraphicsViewPrivate::updateInputMethodSensitivity() -{ - Q_Q(QGraphicsView); - QGraphicsItem *focusItem = 0; - bool enabled = scene && (focusItem = scene->focusItem()) - && (focusItem->d_ptr->flags & QGraphicsItem::ItemAcceptsInputMethod); - q->setAttribute(Qt::WA_InputMethodEnabled, enabled); - q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled); - - if (!enabled) { - q->setInputMethodHints(0); - return; - } - - QGraphicsProxyWidget *proxy = focusItem->d_ptr->isWidget && focusItem->d_ptr->isProxyWidget() - ? static_cast<QGraphicsProxyWidget *>(focusItem) : 0; - if (!proxy) { - q->setInputMethodHints(focusItem->inputMethodHints()); - } else if (QWidget *widget = proxy->widget()) { - if (QWidget *fw = widget->focusWidget()) - widget = fw; - q->setInputMethodHints(widget->inputMethodHints()); - } else { - q->setInputMethodHints(0); - } -} - -/*! - Constructs a QGraphicsView. \a parent is passed to QWidget's constructor. -*/ -QGraphicsView::QGraphicsView(QWidget *parent) - : QAbstractScrollArea(*new QGraphicsViewPrivate, parent) -{ - setViewport(0); - setAcceptDrops(true); - setBackgroundRole(QPalette::Base); - // Investigate leaving these disabled by default. - setAttribute(Qt::WA_InputMethodEnabled); - viewport()->setAttribute(Qt::WA_InputMethodEnabled); -} - -/*! - Constructs a QGraphicsView and sets the visualized scene to \a - scene. \a parent is passed to QWidget's constructor. -*/ -QGraphicsView::QGraphicsView(QGraphicsScene *scene, QWidget *parent) - : QAbstractScrollArea(*new QGraphicsViewPrivate, parent) -{ - setScene(scene); - setViewport(0); - setAcceptDrops(true); - setBackgroundRole(QPalette::Base); - // Investigate leaving these disabled by default. - setAttribute(Qt::WA_InputMethodEnabled); - viewport()->setAttribute(Qt::WA_InputMethodEnabled); -} - -/*! - \internal - */ -QGraphicsView::QGraphicsView(QGraphicsViewPrivate &dd, QWidget *parent) - : QAbstractScrollArea(dd, parent) -{ - setViewport(0); - setAcceptDrops(true); - setBackgroundRole(QPalette::Base); - // Investigate leaving these disabled by default. - setAttribute(Qt::WA_InputMethodEnabled); - viewport()->setAttribute(Qt::WA_InputMethodEnabled); -} - -/*! - Destructs the QGraphicsView object. -*/ -QGraphicsView::~QGraphicsView() -{ - Q_D(QGraphicsView); - if (d->scene) - d->scene->d_func()->views.removeAll(this); - delete d->lastDragDropEvent; -} - -/*! - \reimp -*/ -QSize QGraphicsView::sizeHint() const -{ - Q_D(const QGraphicsView); - if (d->scene) { - QSizeF baseSize = d->matrix.mapRect(sceneRect()).size(); - baseSize += QSizeF(d->frameWidth * 2, d->frameWidth * 2); - return baseSize.boundedTo((3 * QApplication::desktop()->size()) / 4).toSize(); - } - return QAbstractScrollArea::sizeHint(); -} - -/*! - \property QGraphicsView::renderHints - \brief the default render hints for the view - - These hints are - used to initialize QPainter before each visible item is drawn. QPainter - uses render hints to toggle rendering features such as antialiasing and - smooth pixmap transformation. - - QPainter::TextAntialiasing is enabled by default. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 1 -*/ -QPainter::RenderHints QGraphicsView::renderHints() const -{ - Q_D(const QGraphicsView); - return d->renderHints; -} -void QGraphicsView::setRenderHints(QPainter::RenderHints hints) -{ - Q_D(QGraphicsView); - if (hints == d->renderHints) - return; - d->renderHints = hints; - d->updateAll(); -} - -/*! - If \a enabled is true, the render hint \a hint is enabled; otherwise it - is disabled. - - \sa renderHints -*/ -void QGraphicsView::setRenderHint(QPainter::RenderHint hint, bool enabled) -{ - Q_D(QGraphicsView); - QPainter::RenderHints oldHints = d->renderHints; - if (enabled) - d->renderHints |= hint; - else - d->renderHints &= ~hint; - if (oldHints != d->renderHints) - d->updateAll(); -} - -/*! - \property QGraphicsView::alignment - \brief the alignment of the scene in the view when the whole - scene is visible. - - If the whole scene is visible in the view, (i.e., there are no visible - scroll bars,) the view's alignment will decide where the scene will be - rendered in the view. For example, if the alignment is Qt::AlignCenter, - which is default, the scene will be centered in the view, and if the - alignment is (Qt::AlignLeft | Qt::AlignTop), the scene will be rendered in - the top-left corner of the view. -*/ -Qt::Alignment QGraphicsView::alignment() const -{ - Q_D(const QGraphicsView); - return d->alignment; -} -void QGraphicsView::setAlignment(Qt::Alignment alignment) -{ - Q_D(QGraphicsView); - if (d->alignment != alignment) { - d->alignment = alignment; - d->recalculateContentSize(); - } -} - -/*! - \property QGraphicsView::transformationAnchor - \brief how the view should position the scene during transformations. - - QGraphicsView uses this property to decide how to position the scene in - the viewport when the transformation matrix changes, and the coordinate - system of the view is transformed. The default behavior, AnchorViewCenter, - ensures that the scene point at the center of the view remains unchanged - during transformations (e.g., when rotating, the scene will appear to - rotate around the center of the view). - - Note that the effect of this property is noticeable when only a part of the - scene is visible (i.e., when there are scroll bars). Otherwise, if the - whole scene fits in the view, QGraphicsScene uses the view \l alignment to - position the scene in the view. - - \sa alignment, resizeAnchor -*/ -QGraphicsView::ViewportAnchor QGraphicsView::transformationAnchor() const -{ - Q_D(const QGraphicsView); - return d->transformationAnchor; -} -void QGraphicsView::setTransformationAnchor(ViewportAnchor anchor) -{ - Q_D(QGraphicsView); - d->transformationAnchor = anchor; - - // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse - // in order to have up-to-date information for centering the view. - if (d->transformationAnchor == AnchorUnderMouse) - d->viewport->setMouseTracking(true); -} - -/*! - \property QGraphicsView::resizeAnchor - \brief how the view should position the scene when the view is resized. - - QGraphicsView uses this property to decide how to position the scene in - the viewport when the viewport widget's size changes. The default - behavior, NoAnchor, leaves the scene's position unchanged during a resize; - the top-left corner of the view will appear to be anchored while resizing. - - Note that the effect of this property is noticeable when only a part of the - scene is visible (i.e., when there are scroll bars). Otherwise, if the - whole scene fits in the view, QGraphicsScene uses the view \l alignment to - position the scene in the view. - - \sa alignment, transformationAnchor, Qt::WNorthWestGravity -*/ -QGraphicsView::ViewportAnchor QGraphicsView::resizeAnchor() const -{ - Q_D(const QGraphicsView); - return d->resizeAnchor; -} -void QGraphicsView::setResizeAnchor(ViewportAnchor anchor) -{ - Q_D(QGraphicsView); - d->resizeAnchor = anchor; - - // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse - // in order to have up-to-date information for centering the view. - if (d->resizeAnchor == AnchorUnderMouse) - d->viewport->setMouseTracking(true); -} - -/*! - \property QGraphicsView::viewportUpdateMode - \brief how the viewport should update its contents. - - \since 4.3 - - QGraphicsView uses this property to decide how to update areas of the - scene that have been reexposed or changed. Usually you do not need to - modify this property, but there are some cases where doing so can improve - rendering performance. See the ViewportUpdateMode documentation for - specific details. - - The default value is MinimalViewportUpdate, where QGraphicsView will - update as small an area of the viewport as possible when the contents - change. - - \sa ViewportUpdateMode, cacheMode -*/ -QGraphicsView::ViewportUpdateMode QGraphicsView::viewportUpdateMode() const -{ - Q_D(const QGraphicsView); - return d->viewportUpdateMode; -} -void QGraphicsView::setViewportUpdateMode(ViewportUpdateMode mode) -{ - Q_D(QGraphicsView); - d->viewportUpdateMode = mode; -} - -/*! - \property QGraphicsView::optimizationFlags - \brief flags that can be used to tune QGraphicsView's performance. - - \since 4.3 - - QGraphicsView uses clipping, extra bounding rect adjustments, and certain - other aids to improve rendering quality and performance for the common - case graphics scene. However, depending on the target platform, the scene, - and the viewport in use, some of these operations can degrade performance. - - The effect varies from flag to flag; see the OptimizationFlags - documentation for details. - - By default, no optimization flags are enabled. - - \sa setOptimizationFlag() -*/ -QGraphicsView::OptimizationFlags QGraphicsView::optimizationFlags() const -{ - Q_D(const QGraphicsView); - return d->optimizationFlags; -} -void QGraphicsView::setOptimizationFlags(OptimizationFlags flags) -{ - Q_D(QGraphicsView); - d->optimizationFlags = flags; -} - -/*! - Enables \a flag if \a enabled is true; otherwise disables \a flag. - - \sa optimizationFlags -*/ -void QGraphicsView::setOptimizationFlag(OptimizationFlag flag, bool enabled) -{ - Q_D(QGraphicsView); - if (enabled) - d->optimizationFlags |= flag; - else - d->optimizationFlags &= ~flag; -} - -/*! - \property QGraphicsView::dragMode - \brief the behavior for dragging the mouse over the scene while - the left mouse button is pressed. - - This property defines what should happen when the user clicks on the scene - background and drags the mouse (e.g., scrolling the viewport contents - using a pointing hand cursor, or selecting multiple items with a rubber - band). The default value, NoDrag, does nothing. - - This behavior only affects mouse clicks that are not handled by any item. - You can define a custom behavior by creating a subclass of QGraphicsView - and reimplementing mouseMoveEvent(). -*/ -QGraphicsView::DragMode QGraphicsView::dragMode() const -{ - Q_D(const QGraphicsView); - return d->dragMode; -} -void QGraphicsView::setDragMode(DragMode mode) -{ - Q_D(QGraphicsView); - if (d->dragMode == mode) - return; - -#ifndef QT_NO_CURSOR - if (d->dragMode == ScrollHandDrag) - viewport()->unsetCursor(); -#endif - - // If dragMode is unset while dragging, e.g. via a keyEvent, we - // don't unset the handScrolling state. When enabling scrolling - // again the mouseMoveEvent will automatically start scrolling, - // without a mousePress - if (d->dragMode == ScrollHandDrag && mode == NoDrag && d->handScrolling) - d->handScrolling = false; - - d->dragMode = mode; - -#ifndef QT_NO_CURSOR - if (d->dragMode == ScrollHandDrag) { - // Forget the stored viewport cursor when we enter scroll hand drag mode. - d->hasStoredOriginalCursor = false; - viewport()->setCursor(Qt::OpenHandCursor); - } -#endif -} - -#ifndef QT_NO_RUBBERBAND -/*! - \property QGraphicsView::rubberBandSelectionMode - \brief the behavior for selecting items with a rubber band selection rectangle. - \since 4.3 - - This property defines how items are selected when using the RubberBandDrag - drag mode. - - The default value is Qt::IntersectsItemShape; all items whose shape - intersects with or is contained by the rubber band are selected. - - \sa dragMode, items() -*/ -Qt::ItemSelectionMode QGraphicsView::rubberBandSelectionMode() const -{ - Q_D(const QGraphicsView); - return d->rubberBandSelectionMode; -} -void QGraphicsView::setRubberBandSelectionMode(Qt::ItemSelectionMode mode) -{ - Q_D(QGraphicsView); - d->rubberBandSelectionMode = mode; -} -#endif - -/*! - \property QGraphicsView::cacheMode - \brief which parts of the view are cached - - QGraphicsView can cache pre-rendered content in a QPixmap, which is then - drawn onto the viewport. The purpose of such caching is to speed up the - total rendering time for areas that are slow to render. Texture, gradient - and alpha blended backgrounds, for example, can be notibly slow to render; - especially with a transformed view. The CacheBackground flag enables - caching of the view's background. For example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 2 - - The cache is invalidated every time the view is transformed. However, when - scrolling, only partial invalidation is required. - - By default, nothing is cached. - - \sa resetCachedContent(), QPixmapCache -*/ -QGraphicsView::CacheMode QGraphicsView::cacheMode() const -{ - Q_D(const QGraphicsView); - return d->cacheMode; -} -void QGraphicsView::setCacheMode(CacheMode mode) -{ - Q_D(QGraphicsView); - if (mode == d->cacheMode) - return; - d->cacheMode = mode; - resetCachedContent(); -} - -/*! - Resets any cached content. Calling this function will clear - QGraphicsView's cache. If the current cache mode is \l CacheNone, this - function does nothing. - - This function is called automatically for you when the backgroundBrush or - QGraphicsScene::backgroundBrush properties change; you only need to call - this function if you have reimplemented QGraphicsScene::drawBackground() - or QGraphicsView::drawBackground() to draw a custom background, and need - to trigger a full redraw. - - \sa cacheMode() -*/ -void QGraphicsView::resetCachedContent() -{ - Q_D(QGraphicsView); - if (d->cacheMode == CacheNone) - return; - - if (d->cacheMode & CacheBackground) { - // Background caching is enabled. - d->mustResizeBackgroundPixmap = true; - d->updateAll(); - } else if (d->mustResizeBackgroundPixmap) { - // Background caching is disabled. - // Cleanup, free some resources. - d->mustResizeBackgroundPixmap = false; - d->backgroundPixmap = QPixmap(); - d->backgroundPixmapExposed = QRegion(); - } -} - -/*! - Invalidates and schedules a redraw of \a layers inside \a rect. \a rect is - in scene coordinates. Any cached content for \a layers inside \a rect is - unconditionally invalidated and redrawn. - - You can call this function to notify QGraphicsView of changes to the - background or the foreground of the scene. It is commonly used for scenes - with tile-based backgrounds to notify changes when QGraphicsView has - enabled background caching. - - Note that QGraphicsView currently supports background caching only (see - QGraphicsView::CacheBackground). This function is equivalent to calling update() if any - layer but QGraphicsScene::BackgroundLayer is passed. - - \sa QGraphicsScene::invalidate(), update() -*/ -void QGraphicsView::invalidateScene(const QRectF &rect, QGraphicsScene::SceneLayers layers) -{ - Q_D(QGraphicsView); - if ((layers & QGraphicsScene::BackgroundLayer) && !d->mustResizeBackgroundPixmap) { - QRect viewRect = mapFromScene(rect).boundingRect(); - if (viewport()->rect().intersects(viewRect)) { - // The updated background area is exposed; schedule this area for - // redrawing. - d->backgroundPixmapExposed += viewRect; - if (d->scene) - d->scene->update(rect); - } - } -} - -/*! - \property QGraphicsView::interactive - \brief whether the view allowed scene interaction. - - If enabled, this view is set to allow scene interaction. Otherwise, this - view will not allow interaction, and any mouse or key events are ignored - (i.e., it will act as a read-only view). - - By default, this property is true. -*/ -bool QGraphicsView::isInteractive() const -{ - Q_D(const QGraphicsView); - return d->sceneInteractionAllowed; -} -void QGraphicsView::setInteractive(bool allowed) -{ - Q_D(QGraphicsView); - d->sceneInteractionAllowed = allowed; -} - -/*! - Returns a pointer to the scene that is currently visualized in the - view. If no scene is currently visualized, 0 is returned. - - \sa setScene() -*/ -QGraphicsScene *QGraphicsView::scene() const -{ - Q_D(const QGraphicsView); - return d->scene; -} - -/*! - Sets the current scene to \a scene. If \a scene is already being - viewed, this function does nothing. - - When a scene is set on a view, the QGraphicsScene::changed() signal - is automatically connected to this view's updateScene() slot, and the - view's scroll bars are adjusted to fit the size of the scene. -*/ -void QGraphicsView::setScene(QGraphicsScene *scene) -{ - Q_D(QGraphicsView); - if (d->scene == scene) - return; - - // Always update the viewport when the scene changes. - d->updateAll(); - - // Remove the previously assigned scene. - if (d->scene) { - disconnect(d->scene, SIGNAL(changed(QList<QRectF>)), - this, SLOT(updateScene(QList<QRectF>))); - disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)), - this, SLOT(updateSceneRect(QRectF))); - d->scene->d_func()->removeView(this); - d->connectedToScene = false; - - if (isActiveWindow() && isVisible()) { - QEvent windowDeactivate(QEvent::WindowDeactivate); - QApplication::sendEvent(d->scene, &windowDeactivate); - } - if(hasFocus()) - d->scene->clearFocus(); - } - - // Assign the new scene and update the contents (scrollbars, etc.)). - if ((d->scene = scene)) { - connect(d->scene, SIGNAL(sceneRectChanged(QRectF)), - this, SLOT(updateSceneRect(QRectF))); - d->updateSceneSlotReimplementedChecked = false; - d->scene->d_func()->addView(this); - d->recalculateContentSize(); - d->lastCenterPoint = sceneRect().center(); - d->keepLastCenterPoint = true; - // We are only interested in mouse tracking if items accept - // hover events or use non-default cursors. - if (!d->scene->d_func()->allItemsIgnoreHoverEvents - || !d->scene->d_func()->allItemsUseDefaultCursor) { - d->viewport->setMouseTracking(true); - } - - // enable touch events if any items is interested in them - if (!d->scene->d_func()->allItemsIgnoreTouchEvents) - d->viewport->setAttribute(Qt::WA_AcceptTouchEvents); - - if (isActiveWindow() && isVisible()) { - QEvent windowActivate(QEvent::WindowActivate); - QApplication::sendEvent(d->scene, &windowActivate); - } - } else { - d->recalculateContentSize(); - } - - d->updateInputMethodSensitivity(); - - if (d->scene && hasFocus()) - d->scene->setFocus(); -} - -/*! - \property QGraphicsView::sceneRect - \brief the area of the scene visualized by this view. - - The scene rectangle defines the extent of the scene, and in the view's case, - this means the area of the scene that you can navigate using the scroll - bars. - - If unset, or if a null QRectF is set, this property has the same value as - QGraphicsScene::sceneRect, and it changes with - QGraphicsScene::sceneRect. Otherwise, the view's scene rect is unaffected - by the scene. - - Note that, although the scene supports a virtually unlimited size, the - range of the scroll bars will never exceed the range of an integer - (INT_MIN, INT_MAX). When the scene is larger than the scroll bars' values, - you can choose to use translate() to navigate the scene instead. - - By default, this property contains a rectangle at the origin with zero - width and height. - - \sa QGraphicsScene::sceneRect -*/ -QRectF QGraphicsView::sceneRect() const -{ - Q_D(const QGraphicsView); - if (d->hasSceneRect) - return d->sceneRect; - if (d->scene) - return d->scene->sceneRect(); - return QRectF(); -} -void QGraphicsView::setSceneRect(const QRectF &rect) -{ - Q_D(QGraphicsView); - d->hasSceneRect = !rect.isNull(); - d->sceneRect = rect; - d->recalculateContentSize(); -} - -/*! - Returns the current transformation matrix for the view. If no current - transformation is set, the identity matrix is returned. - - \sa setMatrix(), transform(), rotate(), scale(), shear(), translate() -*/ -QMatrix QGraphicsView::matrix() const -{ - Q_D(const QGraphicsView); - return d->matrix.toAffine(); -} - -/*! - Sets the view's current transformation matrix to \a matrix. - - If \a combine is true, then \a matrix is combined with the current matrix; - otherwise, \a matrix \e replaces the current matrix. \a combine is false - by default. - - The transformation matrix tranforms the scene into view coordinates. Using - the default transformation, provided by the identity matrix, one pixel in - the view represents one unit in the scene (e.g., a 10x10 rectangular item - is drawn using 10x10 pixels in the view). If a 2x2 scaling matrix is - applied, the scene will be drawn in 1:2 (e.g., a 10x10 rectangular item is - then drawn using 20x20 pixels in the view). - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 3 - - To simplify interation with items using a transformed view, QGraphicsView - provides mapTo... and mapFrom... functions that can translate between - scene and view coordinates. For example, you can call mapToScene() to map - a view coordinate to a floating point scene coordinate, or mapFromScene() - to map from floating point scene coordinates to view coordinates. - - \sa matrix(), setTransform(), rotate(), scale(), shear(), translate() -*/ -void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine) -{ - setTransform(QTransform(matrix), combine); -} - -/*! - Resets the view transformation matrix to the identity matrix. - - \sa resetTransform() -*/ -void QGraphicsView::resetMatrix() -{ - resetTransform(); -} - -/*! - Rotates the current view transformation \a angle degrees clockwise. - - \sa setTransform(), transform(), scale(), shear(), translate() -*/ -void QGraphicsView::rotate(qreal angle) -{ - Q_D(QGraphicsView); - QTransform matrix = d->matrix; - matrix.rotate(angle); - setTransform(matrix); -} - -/*! - Scales the current view transformation by (\a sx, \a sy). - - \sa setTransform(), transform(), rotate(), shear(), translate() -*/ -void QGraphicsView::scale(qreal sx, qreal sy) -{ - Q_D(QGraphicsView); - QTransform matrix = d->matrix; - matrix.scale(sx, sy); - setTransform(matrix); -} - -/*! - Shears the current view transformation by (\a sh, \a sv). - - \sa setTransform(), transform(), rotate(), scale(), translate() -*/ -void QGraphicsView::shear(qreal sh, qreal sv) -{ - Q_D(QGraphicsView); - QTransform matrix = d->matrix; - matrix.shear(sh, sv); - setTransform(matrix); -} - -/*! - Translates the current view transformation by (\a dx, \a dy). - - \sa setTransform(), transform(), rotate(), shear() -*/ -void QGraphicsView::translate(qreal dx, qreal dy) -{ - Q_D(QGraphicsView); - QTransform matrix = d->matrix; - matrix.translate(dx, dy); - setTransform(matrix); -} - -/*! - Scrolls the contents of the viewport to ensure that the scene - coordinate \a pos, is centered in the view. - - Because \a pos is a floating point coordinate, and the scroll bars operate - on integer coordinates, the centering is only an approximation. - - \note If the item is close to or outside the border, it will be visible - in the view, but not centered. - - \sa ensureVisible() -*/ -void QGraphicsView::centerOn(const QPointF &pos) -{ - Q_D(QGraphicsView); - qreal width = viewport()->width(); - qreal height = viewport()->height(); - QPointF viewPoint = d->matrix.map(pos); - QPointF oldCenterPoint = pos; - - if (!d->leftIndent) { - if (isRightToLeft()) { - qint64 horizontal = 0; - horizontal += horizontalScrollBar()->minimum(); - horizontal += horizontalScrollBar()->maximum(); - horizontal -= int(viewPoint.x() - width / 2.0); - horizontalScrollBar()->setValue(horizontal); - } else { - horizontalScrollBar()->setValue(int(viewPoint.x() - width / 2.0)); - } - } - if (!d->topIndent) - verticalScrollBar()->setValue(int(viewPoint.y() - height / 2.0)); - d->lastCenterPoint = oldCenterPoint; -} - -/*! - \fn QGraphicsView::centerOn(qreal x, qreal y) - \overload - - This function is provided for convenience. It's equivalent to calling - centerOn(QPointF(\a x, \a y)). -*/ - -/*! - \overload - - Scrolls the contents of the viewport to ensure that \a item - is centered in the view. - - \sa ensureVisible() -*/ -void QGraphicsView::centerOn(const QGraphicsItem *item) -{ - centerOn(item->sceneBoundingRect().center()); -} - -/*! - Scrolls the contents of the viewport so that the scene rectangle \a rect - is visible, with margins specified in pixels by \a xmargin and \a - ymargin. If the specified rect cannot be reached, the contents are - scrolled to the nearest valid position. The default value for both margins - is 50 pixels. - - \sa centerOn() -*/ -void QGraphicsView::ensureVisible(const QRectF &rect, int xmargin, int ymargin) -{ - Q_D(QGraphicsView); - qreal width = viewport()->width(); - qreal height = viewport()->height(); - QRectF viewRect = d->matrix.mapRect(rect); - - qreal left = d->horizontalScroll(); - qreal right = left + width; - qreal top = d->verticalScroll(); - qreal bottom = top + height; - - if (viewRect.left() <= left + xmargin) { - // need to scroll from the left - if (!d->leftIndent) - horizontalScrollBar()->setValue(int(viewRect.left() - xmargin - 0.5)); - } - if (viewRect.right() >= right - xmargin) { - // need to scroll from the right - if (!d->leftIndent) - horizontalScrollBar()->setValue(int(viewRect.right() - width + xmargin + 0.5)); - } - if (viewRect.top() <= top + ymargin) { - // need to scroll from the top - if (!d->topIndent) - verticalScrollBar()->setValue(int(viewRect.top() - ymargin - 0.5)); - } - if (viewRect.bottom() >= bottom - ymargin) { - // need to scroll from the bottom - if (!d->topIndent) - verticalScrollBar()->setValue(int(viewRect.bottom() - height + ymargin + 0.5)); - } -} - -/*! - \fn QGraphicsView::ensureVisible(qreal x, qreal y, qreal w, qreal h, - int xmargin, int ymargin) - \overload - - This function is provided for convenience. It's equivalent to calling - ensureVisible(QRectF(\a x, \a y, \a w, \a h), \a xmargin, \a ymargin). -*/ - -/*! - \overload - - Scrolls the contents of the viewport so that the center of item \a item is - visible, with margins specified in pixels by \a xmargin and \a ymargin. If - the specified point cannot be reached, the contents are scrolled to the - nearest valid position. The default value for both margins is 50 pixels. - - \sa centerOn() -*/ -void QGraphicsView::ensureVisible(const QGraphicsItem *item, int xmargin, int ymargin) -{ - ensureVisible(item->sceneBoundingRect(), xmargin, ymargin); -} - -/*! - Scales the view matrix and scrolls the scroll bars to ensure that the - scene rectangle \a rect fits inside the viewport. \a rect must be inside - the scene rect; otherwise, fitInView() cannot guarantee that the whole - rect is visible. - - This function keeps the view's rotation, translation, or shear. The view - is scaled according to \a aspectRatioMode. \a rect will be centered in the - view if it does not fit tightly. - - It's common to call fitInView() from inside a reimplementation of - resizeEvent(), to ensure that the whole scene, or parts of the scene, - scales automatically to fit the new size of the viewport as the view is - resized. Note though, that calling fitInView() from inside resizeEvent() - can lead to unwanted resize recursion, if the new transformation toggles - the automatic state of the scrollbars. You can toggle the scrollbar - policies to always on or always off to prevent this (see - horizontalScrollBarPolicy() and verticalScrollBarPolicy()). - - If \a rect is empty, or if the viewport is too small, this - function will do nothing. - - \sa setTransform(), ensureVisible(), centerOn() -*/ -void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode) -{ - Q_D(QGraphicsView); - if (!d->scene || rect.isNull()) - return; - - // Reset the view scale to 1:1. - QRectF unity = d->matrix.mapRect(QRectF(0, 0, 1, 1)); - if (unity.isEmpty()) - return; - scale(1 / unity.width(), 1 / unity.height()); - - // Find the ideal x / y scaling ratio to fit \a rect in the view. - int margin = 2; - QRectF viewRect = viewport()->rect().adjusted(margin, margin, -margin, -margin); - if (viewRect.isEmpty()) - return; - QRectF sceneRect = d->matrix.mapRect(rect); - if (sceneRect.isEmpty()) - return; - qreal xratio = viewRect.width() / sceneRect.width(); - qreal yratio = viewRect.height() / sceneRect.height(); - - // Respect the aspect ratio mode. - switch (aspectRatioMode) { - case Qt::KeepAspectRatio: - xratio = yratio = qMin(xratio, yratio); - break; - case Qt::KeepAspectRatioByExpanding: - xratio = yratio = qMax(xratio, yratio); - break; - case Qt::IgnoreAspectRatio: - break; - } - - // Scale and center on the center of \a rect. - scale(xratio, yratio); - centerOn(rect.center()); -} - -/*! - \fn void QGraphicsView::fitInView(qreal x, qreal y, qreal w, qreal h, - Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) - - \overload - - This convenience function is equivalent to calling - fitInView(QRectF(\a x, \a y, \a w, \a h), \a aspectRatioMode). - - \sa ensureVisible(), centerOn() -*/ - -/*! - \overload - - Ensures that \a item fits tightly inside the view, scaling the view - according to \a aspectRatioMode. - - \sa ensureVisible(), centerOn() -*/ -void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode) -{ - QPainterPath path = item->isClipped() ? item->clipPath() : item->shape(); - if (item->d_ptr->hasTranslateOnlySceneTransform()) { - path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy()); - fitInView(path.boundingRect(), aspectRatioMode); - } else { - fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode); - } -} - -/*! - Renders the \a source rect, which is in view coordinates, from the scene - into \a target, which is in paint device coordinates, using \a - painter. This function is useful for capturing the contents of the view - onto a paint device, such as a QImage (e.g., to take a screenshot), or for - printing to QPrinter. For example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 4 - - If \a source is a null rect, this function will use viewport()->rect() to - determine what to draw. If \a target is a null rect, the full dimensions - of \a painter's paint device (e.g., for a QPrinter, the page size) will be - used. - - The source rect contents will be transformed according to \a - aspectRatioMode to fit into the target rect. By default, the aspect ratio - is kept, and \a source is scaled to fit in \a target. - - \sa QGraphicsScene::render() -*/ -void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source, - Qt::AspectRatioMode aspectRatioMode) -{ - // ### Switch to using the recursive rendering algorithm instead. - - Q_D(QGraphicsView); - if (!d->scene || !(painter && painter->isActive())) - return; - - // Default source rect = viewport rect - QRect sourceRect = source; - if (source.isNull()) - sourceRect = viewport()->rect(); - - // Default target rect = device rect - QRectF targetRect = target; - if (target.isNull()) { - if (painter->device()->devType() == QInternal::Picture) - targetRect = sourceRect; - else - targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height()); - } - - // Find the ideal x / y scaling ratio to fit \a source into \a target. - qreal xratio = targetRect.width() / sourceRect.width(); - qreal yratio = targetRect.height() / sourceRect.height(); - - // Scale according to the aspect ratio mode. - switch (aspectRatioMode) { - case Qt::KeepAspectRatio: - xratio = yratio = qMin(xratio, yratio); - break; - case Qt::KeepAspectRatioByExpanding: - xratio = yratio = qMax(xratio, yratio); - break; - case Qt::IgnoreAspectRatio: - break; - } - - // Find all items to draw, and reverse the list (we want to draw - // in reverse order). - QPolygonF sourceScenePoly = mapToScene(sourceRect.adjusted(-1, -1, 1, 1)); - QList<QGraphicsItem *> itemList = d->scene->items(sourceScenePoly, - Qt::IntersectsItemBoundingRect); - QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()]; - int numItems = itemList.size(); - for (int i = 0; i < numItems; ++i) - itemArray[numItems - i - 1] = itemList.at(i); - itemList.clear(); - - // Setup painter matrix. - QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); - QTransform painterMatrix = d->matrix * moveMatrix; - painterMatrix *= QTransform() - .translate(targetRect.left(), targetRect.top()) - .scale(xratio, yratio) - .translate(-sourceRect.left(), -sourceRect.top()); - - // Generate the style options - QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); - for (int i = 0; i < numItems; ++i) - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect()); - - painter->save(); - - // Clip in device coordinates to avoid QRegion transformations. - painter->setClipRect(targetRect); - QPainterPath path; - path.addPolygon(sourceScenePoly); - path.closeSubpath(); - painter->setClipPath(painterMatrix.map(path), Qt::IntersectClip); - - // Transform the painter. - painter->setTransform(painterMatrix, true); - - // Render the scene. - QRectF sourceSceneRect = sourceScenePoly.boundingRect(); - drawBackground(painter, sourceSceneRect); - drawItems(painter, numItems, itemArray, styleOptionArray); - drawForeground(painter, sourceSceneRect); - - delete [] itemArray; - d->freeStyleOptionsArray(styleOptionArray); - - painter->restore(); -} - -/*! - Returns a list of all the items in the associated scene, in descending - stacking order (i.e., the first item in the returned list is the uppermost - item). - - \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsView::items() const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return QList<QGraphicsItem *>(); - return d->scene->items(); -} - -/*! - Returns a list of all the items at the position \a pos in the view. The - items are listed in descending stacking order (i.e., the first item in the - list is the uppermost item, and the last item is the lowermost item). \a - pos is in viewport coordinates. - - This function is most commonly called from within mouse event handlers in - a subclass in QGraphicsView. \a pos is in untransformed viewport - coordinates, just like QMouseEvent::pos(). - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5 - - \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return QList<QGraphicsItem *>(); - // ### Unify these two, and use the items(QPointF) version in - // QGraphicsScene instead. The scene items function could use the viewport - // transform to map the point to a rect/polygon. - if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { - // Use the rect version - QTransform xinv = viewportTransform().inverted(); - return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)), - Qt::IntersectsItemShape, - Qt::DescendingOrder, - viewportTransform()); - } - // Use the polygon version - return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1), - Qt::IntersectsItemShape, - Qt::DescendingOrder, - viewportTransform()); -} - -/*! - \fn QGraphicsView::items(int x, int y) const - - This function is provided for convenience. It's equivalent to calling - items(QPoint(\a x, \a y)). -*/ - -/*! - \overload - - Returns a list of all the items that, depending on \a mode, are either - contained by or intersect with \a rect. \a rect is in viewport - coordinates. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rect are returned. - - The items are sorted in descending stacking order (i.e., the first item in - the returned list is the uppermost item). - - \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return QList<QGraphicsItem *>(); - return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform()); -} - -/*! - \fn QList<QGraphicsItem *> QGraphicsView::items(int x, int y, int w, int h, Qt::ItemSelectionMode mode) const - \since 4.3 - - This convenience function is equivalent to calling items(QRectF(\a x, \a - y, \a w, \a h), \a mode). -*/ - -/*! - \overload - - Returns a list of all the items that, depending on \a mode, are either - contained by or intersect with \a polygon. \a polygon is in viewport - coordinates. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a polygon are returned. - - The items are sorted by descending stacking order (i.e., the first item in - the returned list is the uppermost item). - - \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return QList<QGraphicsItem *>(); - return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform()); -} - -/*! - \overload - - Returns a list of all the items that, depending on \a mode, are either - contained by or intersect with \a path. \a path is in viewport - coordinates. - - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. - - \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} -*/ -QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return QList<QGraphicsItem *>(); - return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform()); -} - -/*! - Returns the item at position \a pos, which is in viewport coordinates. - If there are several items at this position, this function returns - the topmost item. - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6 - - \sa items(), {QGraphicsItem#Sorting}{Sorting} -*/ -QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return 0; - QList<QGraphicsItem *> itemsAtPos = items(pos); - return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first(); -} - -/*! - \overload - \fn QGraphicsItem *QGraphicsView::itemAt(int x, int y) const - - This function is provided for convenience. It's equivalent to - calling itemAt(QPoint(\a x, \a y)). -*/ - -/*! - Returns the viewport coordinate \a point mapped to scene coordinates. - - Note: It can be useful to map the whole rectangle covered by the pixel at - \a point instead of the point itself. To do this, you can call - mapToScene(QRect(\a point, QSize(2, 2))). - - \sa mapFromScene() -*/ -QPointF QGraphicsView::mapToScene(const QPoint &point) const -{ - Q_D(const QGraphicsView); - QPointF p = point; - p.rx() += d->horizontalScroll(); - p.ry() += d->verticalScroll(); - return d->identityMatrix ? p : d->matrix.inverted().map(p); -} - -/*! - \fn QGraphicsView::mapToScene(int x, int y) const - - This function is provided for convenience. It's equivalent to calling - mapToScene(QPoint(\a x, \a y)). -*/ - -/*! - Returns the viewport rectangle \a rect mapped to a scene coordinate - polygon. - - \sa mapFromScene() -*/ -QPolygonF QGraphicsView::mapToScene(const QRect &rect) const -{ - Q_D(const QGraphicsView); - if (!rect.isValid()) - return QPolygonF(); - - QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll()); - QRect r = rect.adjusted(0, 0, 1, 1); - QPointF tl = scrollOffset + r.topLeft(); - QPointF tr = scrollOffset + r.topRight(); - QPointF br = scrollOffset + r.bottomRight(); - QPointF bl = scrollOffset + r.bottomLeft(); - - QPolygonF poly(4); - if (!d->identityMatrix) { - QTransform x = d->matrix.inverted(); - poly[0] = x.map(tl); - poly[1] = x.map(tr); - poly[2] = x.map(br); - poly[3] = x.map(bl); - } else { - poly[0] = tl; - poly[1] = tr; - poly[2] = br; - poly[3] = bl; - } - return poly; -} - -/*! - \fn QGraphicsView::mapToScene(int x, int y, int w, int h) const - - This function is provided for convenience. It's equivalent to calling - mapToScene(QRect(\a x, \a y, \a w, \a h)). -*/ - -/*! - Returns the viewport polygon \a polygon mapped to a scene coordinate - polygon. - - \sa mapFromScene() -*/ -QPolygonF QGraphicsView::mapToScene(const QPolygon &polygon) const -{ - QPolygonF poly; - foreach (const QPoint &point, polygon) - poly << mapToScene(point); - return poly; -} - -/*! - Returns the viewport painter path \a path mapped to a scene coordinate - painter path. - - \sa mapFromScene() -*/ -QPainterPath QGraphicsView::mapToScene(const QPainterPath &path) const -{ - Q_D(const QGraphicsView); - QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll()); - matrix *= d->matrix.inverted(); - return matrix.map(path); -} - -/*! - Returns the scene coordinate \a point to viewport coordinates. - - \sa mapToScene() -*/ -QPoint QGraphicsView::mapFromScene(const QPointF &point) const -{ - Q_D(const QGraphicsView); - QPointF p = d->identityMatrix ? point : d->matrix.map(point); - p.rx() -= d->horizontalScroll(); - p.ry() -= d->verticalScroll(); - return p.toPoint(); -} - -/*! - \fn QGraphicsView::mapFromScene(qreal x, qreal y) const - - This function is provided for convenience. It's equivalent to - calling mapFromScene(QPointF(\a x, \a y)). -*/ - -/*! - Returns the scene rectangle \a rect to a viewport coordinate - polygon. - - \sa mapToScene() -*/ -QPolygon QGraphicsView::mapFromScene(const QRectF &rect) const -{ - Q_D(const QGraphicsView); - QPointF tl; - QPointF tr; - QPointF br; - QPointF bl; - if (!d->identityMatrix) { - const QTransform &x = d->matrix; - tl = x.map(rect.topLeft()); - tr = x.map(rect.topRight()); - br = x.map(rect.bottomRight()); - bl = x.map(rect.bottomLeft()); - } else { - tl = rect.topLeft(); - tr = rect.topRight(); - br = rect.bottomRight(); - bl = rect.bottomLeft(); - } - QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll()); - tl -= scrollOffset; - tr -= scrollOffset; - br -= scrollOffset; - bl -= scrollOffset; - - QPolygon poly(4); - poly[0] = tl.toPoint(); - poly[1] = tr.toPoint(); - poly[2] = br.toPoint(); - poly[3] = bl.toPoint(); - return poly; -} - -/*! - \fn QGraphicsView::mapFromScene(qreal x, qreal y, qreal w, qreal h) const - - This function is provided for convenience. It's equivalent to - calling mapFromScene(QRectF(\a x, \a y, \a w, \a h)). -*/ - -/*! - Returns the scene coordinate polygon \a polygon to a viewport coordinate - polygon. - - \sa mapToScene() -*/ -QPolygon QGraphicsView::mapFromScene(const QPolygonF &polygon) const -{ - QPolygon poly; - foreach (const QPointF &point, polygon) - poly << mapFromScene(point); - return poly; -} - -/*! - Returns the scene coordinate painter path \a path to a viewport coordinate - painter path. - - \sa mapToScene() -*/ -QPainterPath QGraphicsView::mapFromScene(const QPainterPath &path) const -{ - Q_D(const QGraphicsView); - QTransform matrix = d->matrix; - matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); - return matrix.map(path); -} - -/*! - \reimp -*/ -QVariant QGraphicsView::inputMethodQuery(Qt::InputMethodQuery query) const -{ - Q_D(const QGraphicsView); - if (!d->scene) - return QVariant(); - - QVariant value = d->scene->inputMethodQuery(query); - if (value.type() == QVariant::RectF) - value = d->mapRectFromScene(value.toRectF()); - else if (value.type() == QVariant::PointF) - value = mapFromScene(value.toPointF()); - else if (value.type() == QVariant::Rect) - value = d->mapRectFromScene(value.toRect()).toRect(); - else if (value.type() == QVariant::Point) - value = mapFromScene(value.toPoint()); - return value; -} - -/*! - \property QGraphicsView::backgroundBrush - \brief the background brush of the scene. - - This property sets the background brush for the scene in this view. It is - used to override the scene's own background, and defines the behavior of - drawBackground(). To provide custom background drawing for this view, you - can reimplement drawBackground() instead. - - By default, this property contains a brush with the Qt::NoBrush pattern. - - \sa QGraphicsScene::backgroundBrush, foregroundBrush -*/ -QBrush QGraphicsView::backgroundBrush() const -{ - Q_D(const QGraphicsView); - return d->backgroundBrush; -} -void QGraphicsView::setBackgroundBrush(const QBrush &brush) -{ - Q_D(QGraphicsView); - d->backgroundBrush = brush; - d->updateAll(); - - if (d->cacheMode & CacheBackground) { - // Invalidate the background pixmap - d->mustResizeBackgroundPixmap = true; - } -} - -/*! - \property QGraphicsView::foregroundBrush - \brief the foreground brush of the scene. - - This property sets the foreground brush for the scene in this view. It is - used to override the scene's own foreground, and defines the behavior of - drawForeground(). To provide custom foreground drawing for this view, you - can reimplement drawForeground() instead. - - By default, this property contains a brush with the Qt::NoBrush pattern. - - \sa QGraphicsScene::foregroundBrush, backgroundBrush -*/ -QBrush QGraphicsView::foregroundBrush() const -{ - Q_D(const QGraphicsView); - return d->foregroundBrush; -} -void QGraphicsView::setForegroundBrush(const QBrush &brush) -{ - Q_D(QGraphicsView); - d->foregroundBrush = brush; - d->updateAll(); -} - -/*! - Schedules an update of the scene rectangles \a rects. - - \sa QGraphicsScene::changed() -*/ -void QGraphicsView::updateScene(const QList<QRectF> &rects) -{ - // ### Note: Since 4.5, this slot is only called if the user explicitly - // establishes a connection between the scene and the view, as the scene - // and view are no longer connected. We need to keep it working (basically - // leave it as it is), but the new delivery path is through - // QGraphicsScenePrivate::itemUpdate(). - Q_D(QGraphicsView); - if (d->fullUpdatePending || d->viewportUpdateMode == QGraphicsView::NoViewportUpdate) - return; - - // Extract and reset dirty scene rect info. - QVector<QRect> dirtyViewportRects; - const QVector<QRect> &dirtyRects = d->dirtyRegion.rects(); - for (int i = 0; i < dirtyRects.size(); ++i) - dirtyViewportRects += dirtyRects.at(i); - d->dirtyRegion = QRegion(); - d->dirtyBoundingRect = QRect(); - - bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate; - bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) - || (d->viewportUpdateMode == QGraphicsView::SmartViewportUpdate - && ((dirtyViewportRects.size() + rects.size()) >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)); - - QRegion updateRegion; - QRect boundingRect; - QRect viewportRect = viewport()->rect(); - bool redraw = false; - QTransform transform = viewportTransform(); - - // Convert scene rects to viewport rects. - foreach (const QRectF &rect, rects) { - QRect xrect = transform.mapRect(rect).toAlignedRect(); - if (!(d->optimizationFlags & DontAdjustForAntialiasing)) - xrect.adjust(-2, -2, 2, 2); - else - xrect.adjust(-1, -1, 1, 1); - if (!viewportRect.intersects(xrect)) - continue; - dirtyViewportRects << xrect; - } - - foreach (const QRect &rect, dirtyViewportRects) { - // Add the exposed rect to the update region. In rect update - // mode, we only count the bounding rect of items. - if (!boundingRectUpdate) { - updateRegion += rect; - } else { - boundingRect |= rect; - } - redraw = true; - if (fullUpdate) { - // If fullUpdate is true and we found a visible dirty rect, - // we're done. - break; - } - } - - if (!redraw) - return; - - if (fullUpdate) - viewport()->update(); - else if (boundingRectUpdate) - viewport()->update(boundingRect); - else - viewport()->update(updateRegion); -} - -/*! - Notifies QGraphicsView that the scene's scene rect has changed. \a rect - is the new scene rect. If the view already has an explicitly set scene - rect, this function does nothing. - - \sa sceneRect, QGraphicsScene::sceneRectChanged() -*/ -void QGraphicsView::updateSceneRect(const QRectF &rect) -{ - Q_D(QGraphicsView); - if (!d->hasSceneRect) { - d->sceneRect = rect; - d->recalculateContentSize(); - } -} - -/*! - This slot is called by QAbstractScrollArea after setViewport() has been - called. Reimplement this function in a subclass of QGraphicsView to - initialize the new viewport \a widget before it is used. - - \sa setViewport() -*/ -void QGraphicsView::setupViewport(QWidget *widget) -{ - Q_D(QGraphicsView); - - if (!widget) { - qWarning("QGraphicsView::setupViewport: cannot initialize null widget"); - return; - } - - const bool isGLWidget = widget->inherits("QGLWidget"); - - d->accelerateScrolling = !(isGLWidget); - - widget->setFocusPolicy(Qt::StrongFocus); - - if (!isGLWidget) { - // autoFillBackground enables scroll acceleration. - widget->setAutoFillBackground(true); - } - - // We are only interested in mouse tracking if items - // accept hover events or use non-default cursors or if - // AnchorUnderMouse is used as transformation or resize anchor. - if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents - || !d->scene->d_func()->allItemsUseDefaultCursor)) - || d->transformationAnchor == AnchorUnderMouse - || d->resizeAnchor == AnchorUnderMouse) { - widget->setMouseTracking(true); - } - - // enable touch events if any items is interested in them - if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents) - widget->setAttribute(Qt::WA_AcceptTouchEvents); - -#ifndef QT_NO_GESTURES - if (d->scene) { - foreach (Qt::GestureType gesture, d->scene->d_func()->grabbedGestures.keys()) - widget->grabGesture(gesture); - } -#endif - - widget->setAcceptDrops(acceptDrops()); -} - -/*! - \reimp -*/ -bool QGraphicsView::event(QEvent *event) -{ - Q_D(QGraphicsView); - - if (d->sceneInteractionAllowed) { - switch (event->type()) { - case QEvent::ShortcutOverride: - if (d->scene) - return QApplication::sendEvent(d->scene, event); - break; - case QEvent::KeyPress: - if (d->scene) { - QKeyEvent *k = static_cast<QKeyEvent *>(event); - if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) { - // Send the key events to the scene. This will invoke the - // scene's tab focus handling, and if the event is - // accepted, we return (prevent further event delivery), - // and the base implementation will call QGraphicsView's - // focusNextPrevChild() function. If the event is ignored, - // we fall back to standard tab focus handling. - QApplication::sendEvent(d->scene, event); - if (event->isAccepted()) - return true; - // Ensure the event doesn't propagate just because the - // scene ignored it. If the event propagates, then tab - // handling will be called twice (this and parent). - event->accept(); - } - } - break; - default: - break; - } - } - - return QAbstractScrollArea::event(event); -} - -/*! - \reimp -*/ -bool QGraphicsView::viewportEvent(QEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene) - return QAbstractScrollArea::viewportEvent(event); - - switch (event->type()) { - case QEvent::Enter: - QApplication::sendEvent(d->scene, event); - break; - case QEvent::WindowActivate: - QApplication::sendEvent(d->scene, event); - break; - case QEvent::WindowDeactivate: - // ### This is a temporary fix for until we get proper mouse - // grab events. mouseGrabberItem should be set to 0 if we lose - // the mouse grab. - // Remove all popups when the scene loses focus. - if (!d->scene->d_func()->popupWidgets.isEmpty()) - d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first()); - QApplication::sendEvent(d->scene, event); - break; - case QEvent::Show: - if (d->scene && isActiveWindow()) { - QEvent windowActivate(QEvent::WindowActivate); - QApplication::sendEvent(d->scene, &windowActivate); - } - break; - case QEvent::Hide: - // spontaneous event will generate a WindowDeactivate. - if (!event->spontaneous() && d->scene && isActiveWindow()) { - QEvent windowDeactivate(QEvent::WindowDeactivate); - QApplication::sendEvent(d->scene, &windowDeactivate); - } - break; - case QEvent::Leave: - // ### This is a temporary fix for until we get proper mouse grab - // events. activeMouseGrabberItem should be set to 0 if we lose the - // mouse grab. - if ((QApplication::activePopupWidget() && QApplication::activePopupWidget() != window()) - || (QApplication::activeModalWidget() && QApplication::activeModalWidget() != window()) - || (QApplication::activeWindow() != window())) { - if (!d->scene->d_func()->popupWidgets.isEmpty()) - d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first()); - } - d->useLastMouseEvent = false; - // a hack to pass a viewport pointer to the scene inside the leave event - Q_ASSERT(event->d == 0); - event->d = reinterpret_cast<QEventPrivate *>(viewport()); - QApplication::sendEvent(d->scene, event); - break; -#ifndef QT_NO_TOOLTIP - case QEvent::ToolTip: { - QHelpEvent *toolTip = static_cast<QHelpEvent *>(event); - QGraphicsSceneHelpEvent helpEvent(QEvent::GraphicsSceneHelp); - helpEvent.setWidget(viewport()); - helpEvent.setScreenPos(toolTip->globalPos()); - helpEvent.setScenePos(mapToScene(toolTip->pos())); - QApplication::sendEvent(d->scene, &helpEvent); - toolTip->setAccepted(helpEvent.isAccepted()); - return true; - } -#endif - case QEvent::Paint: - // Reset full update - d->fullUpdatePending = false; - d->dirtyScrollOffset = QPoint(); - if (d->scene) { - // Check if this view reimplements the updateScene slot; if it - // does, we can't do direct update delivery and have to fall back - // to connecting the changed signal. - if (!d->updateSceneSlotReimplementedChecked) { - d->updateSceneSlotReimplementedChecked = true; - const QMetaObject *mo = metaObject(); - if (mo != &QGraphicsView::staticMetaObject) { - if (mo->indexOfSlot("updateScene(QList<QRectF>)") - != QGraphicsView::staticMetaObject.indexOfSlot("updateScene(QList<QRectF>)")) { - connect(d->scene, SIGNAL(changed(QList<QRectF>)), - this, SLOT(updateScene(QList<QRectF>))); - } - } - } - } - break; - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - { - if (!isEnabled()) - return false; - - if (d->scene && d->sceneInteractionAllowed) { - // Convert and deliver the touch event to the scene. - QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); - touchEvent->setWidget(viewport()); - QGraphicsViewPrivate::translateTouchEvent(d, touchEvent); - (void) QApplication::sendEvent(d->scene, touchEvent); - } - - return true; - } -#ifndef QT_NO_GESTURES - case QEvent::Gesture: - case QEvent::GestureOverride: - { - if (!isEnabled()) - return false; - - if (d->scene && d->sceneInteractionAllowed) { - QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event); - gestureEvent->setWidget(viewport()); - (void) QApplication::sendEvent(d->scene, gestureEvent); - } - return true; - } -#endif // QT_NO_GESTURES - default: - break; - } - - return QAbstractScrollArea::viewportEvent(event); -} - -#ifndef QT_NO_CONTEXTMENU -/*! - \reimp -*/ -void QGraphicsView::contextMenuEvent(QContextMenuEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - - d->mousePressViewPoint = event->pos(); - d->mousePressScenePoint = mapToScene(d->mousePressViewPoint); - d->mousePressScreenPoint = event->globalPos(); - d->lastMouseMoveScenePoint = d->mousePressScenePoint; - d->lastMouseMoveScreenPoint = d->mousePressScreenPoint; - - QGraphicsSceneContextMenuEvent contextEvent(QEvent::GraphicsSceneContextMenu); - contextEvent.setWidget(viewport()); - contextEvent.setScenePos(d->mousePressScenePoint); - contextEvent.setScreenPos(d->mousePressScreenPoint); - contextEvent.setModifiers(event->modifiers()); - contextEvent.setReason((QGraphicsSceneContextMenuEvent::Reason)(event->reason())); - contextEvent.setAccepted(event->isAccepted()); - QApplication::sendEvent(d->scene, &contextEvent); - event->setAccepted(contextEvent.isAccepted()); -} -#endif // QT_NO_CONTEXTMENU - -/*! - \reimp -*/ -void QGraphicsView::dropEvent(QDropEvent *event) -{ -#ifndef QT_NO_DRAGANDDROP - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - - // Generate a scene event. - QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDrop); - d->populateSceneDragDropEvent(&sceneEvent, event); - - // Send it to the scene. - QApplication::sendEvent(d->scene, &sceneEvent); - - // Accept the originating event if the scene accepted the scene event. - event->setAccepted(sceneEvent.isAccepted()); - if (sceneEvent.isAccepted()) - event->setDropAction(sceneEvent.dropAction()); - - delete d->lastDragDropEvent; - d->lastDragDropEvent = 0; - -#else - Q_UNUSED(event) -#endif -} - -/*! - \reimp -*/ -void QGraphicsView::dragEnterEvent(QDragEnterEvent *event) -{ -#ifndef QT_NO_DRAGANDDROP - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - - // Disable replaying of mouse move events. - d->useLastMouseEvent = false; - - // Generate a scene event. - QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragEnter); - d->populateSceneDragDropEvent(&sceneEvent, event); - - // Store it for later use. - d->storeDragDropEvent(&sceneEvent); - - // Send it to the scene. - QApplication::sendEvent(d->scene, &sceneEvent); - - // Accept the originating event if the scene accepted the scene event. - if (sceneEvent.isAccepted()) { - event->setAccepted(true); - event->setDropAction(sceneEvent.dropAction()); - } -#else - Q_UNUSED(event) -#endif -} - -/*! - \reimp -*/ -void QGraphicsView::dragLeaveEvent(QDragLeaveEvent *event) -{ -#ifndef QT_NO_DRAGANDDROP - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - if (!d->lastDragDropEvent) { - qWarning("QGraphicsView::dragLeaveEvent: drag leave received before drag enter"); - return; - } - - // Generate a scene event. - QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragLeave); - sceneEvent.setScenePos(d->lastDragDropEvent->scenePos()); - sceneEvent.setScreenPos(d->lastDragDropEvent->screenPos()); - sceneEvent.setButtons(d->lastDragDropEvent->buttons()); - sceneEvent.setModifiers(d->lastDragDropEvent->modifiers()); - sceneEvent.setPossibleActions(d->lastDragDropEvent->possibleActions()); - sceneEvent.setProposedAction(d->lastDragDropEvent->proposedAction()); - sceneEvent.setDropAction(d->lastDragDropEvent->dropAction()); - sceneEvent.setMimeData(d->lastDragDropEvent->mimeData()); - sceneEvent.setWidget(d->lastDragDropEvent->widget()); - sceneEvent.setSource(d->lastDragDropEvent->source()); - delete d->lastDragDropEvent; - d->lastDragDropEvent = 0; - - // Send it to the scene. - QApplication::sendEvent(d->scene, &sceneEvent); - - // Accept the originating event if the scene accepted the scene event. - if (sceneEvent.isAccepted()) - event->setAccepted(true); -#else - Q_UNUSED(event) -#endif -} - -/*! - \reimp -*/ -void QGraphicsView::dragMoveEvent(QDragMoveEvent *event) -{ -#ifndef QT_NO_DRAGANDDROP - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - - // Generate a scene event. - QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragMove); - d->populateSceneDragDropEvent(&sceneEvent, event); - - // Store it for later use. - d->storeDragDropEvent(&sceneEvent); - - // Send it to the scene. - QApplication::sendEvent(d->scene, &sceneEvent); - - // Ignore the originating event if the scene ignored the scene event. - event->setAccepted(sceneEvent.isAccepted()); - if (sceneEvent.isAccepted()) - event->setDropAction(sceneEvent.dropAction()); -#else - Q_UNUSED(event) -#endif -} - -/*! - \reimp -*/ -void QGraphicsView::focusInEvent(QFocusEvent *event) -{ - Q_D(QGraphicsView); - d->updateInputMethodSensitivity(); - QAbstractScrollArea::focusInEvent(event); - if (d->scene) - QApplication::sendEvent(d->scene, event); - // Pass focus on if the scene cannot accept focus. - if (!d->scene || !event->isAccepted()) - QAbstractScrollArea::focusInEvent(event); -} - -/*! - \reimp -*/ -bool QGraphicsView::focusNextPrevChild(bool next) -{ - return QAbstractScrollArea::focusNextPrevChild(next); -} - -/*! - \reimp -*/ -void QGraphicsView::focusOutEvent(QFocusEvent *event) -{ - Q_D(QGraphicsView); - QAbstractScrollArea::focusOutEvent(event); - if (d->scene) - QApplication::sendEvent(d->scene, event); -} - -/*! - \reimp -*/ -void QGraphicsView::keyPressEvent(QKeyEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) { - QAbstractScrollArea::keyPressEvent(event); - return; - } - QApplication::sendEvent(d->scene, event); - if (!event->isAccepted()) - QAbstractScrollArea::keyPressEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsView::keyReleaseEvent(QKeyEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - QApplication::sendEvent(d->scene, event); - if (!event->isAccepted()) - QAbstractScrollArea::keyReleaseEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) - return; - - d->storeMouseEvent(event); - d->mousePressViewPoint = event->pos(); - d->mousePressScenePoint = mapToScene(d->mousePressViewPoint); - d->mousePressScreenPoint = event->globalPos(); - d->lastMouseMoveScenePoint = d->mousePressScenePoint; - d->lastMouseMoveScreenPoint = d->mousePressScreenPoint; - d->mousePressButton = event->button(); - - QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick); - mouseEvent.setWidget(viewport()); - mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint); - mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint); - mouseEvent.setScenePos(mapToScene(d->mousePressViewPoint)); - mouseEvent.setScreenPos(d->mousePressScreenPoint); - mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint); - mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint); - mouseEvent.setButtons(event->buttons()); - mouseEvent.setButtons(event->buttons()); - mouseEvent.setAccepted(false); - mouseEvent.setButton(event->button()); - mouseEvent.setModifiers(event->modifiers()); - if (event->spontaneous()) - qt_sendSpontaneousEvent(d->scene, &mouseEvent); - else - QApplication::sendEvent(d->scene, &mouseEvent); -} - -/*! - \reimp -*/ -void QGraphicsView::mousePressEvent(QMouseEvent *event) -{ - Q_D(QGraphicsView); - - // Store this event for replaying, finding deltas, and for - // scroll-dragging; even in non-interactive mode, scroll hand dragging is - // allowed, so we store the event at the very top of this function. - d->storeMouseEvent(event); - d->lastMouseEvent.setAccepted(false); - - if (d->sceneInteractionAllowed) { - // Store some of the event's button-down data. - d->mousePressViewPoint = event->pos(); - d->mousePressScenePoint = mapToScene(d->mousePressViewPoint); - d->mousePressScreenPoint = event->globalPos(); - d->lastMouseMoveScenePoint = d->mousePressScenePoint; - d->lastMouseMoveScreenPoint = d->mousePressScreenPoint; - d->mousePressButton = event->button(); - - if (d->scene) { - // Convert and deliver the mouse event to the scene. - QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress); - mouseEvent.setWidget(viewport()); - mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint); - mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint); - mouseEvent.setScenePos(d->mousePressScenePoint); - mouseEvent.setScreenPos(d->mousePressScreenPoint); - mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint); - mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint); - mouseEvent.setButtons(event->buttons()); - mouseEvent.setButton(event->button()); - mouseEvent.setModifiers(event->modifiers()); - mouseEvent.setAccepted(false); - if (event->spontaneous()) - qt_sendSpontaneousEvent(d->scene, &mouseEvent); - else - QApplication::sendEvent(d->scene, &mouseEvent); - - // Update the original mouse event accepted state. - bool isAccepted = mouseEvent.isAccepted(); - event->setAccepted(isAccepted); - - // Update the last mouse event accepted state. - d->lastMouseEvent.setAccepted(isAccepted); - - if (isAccepted) - return; - } - } - -#ifndef QT_NO_RUBBERBAND - if (d->dragMode == QGraphicsView::RubberBandDrag && !d->rubberBanding) { - if (d->sceneInteractionAllowed) { - // Rubberbanding is only allowed in interactive mode. - event->accept(); - d->rubberBanding = true; - d->rubberBandRect = QRect(); - if (d->scene) { - // Initiating a rubber band always clears the selection. - d->scene->clearSelection(); - } - } - } else -#endif - if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) { - // Left-button press in scroll hand mode initiates hand scrolling. - event->accept(); - d->handScrolling = true; - d->handScrollMotions = 0; -#ifndef QT_NO_CURSOR - viewport()->setCursor(Qt::ClosedHandCursor); -#endif - } -} - -/*! - \reimp -*/ -void QGraphicsView::mouseMoveEvent(QMouseEvent *event) -{ - Q_D(QGraphicsView); - -#ifndef QT_NO_RUBBERBAND - if (d->dragMode == QGraphicsView::RubberBandDrag && d->sceneInteractionAllowed) { - d->storeMouseEvent(event); - if (d->rubberBanding) { - // Check for enough drag distance - if ((d->mousePressViewPoint - event->pos()).manhattanLength() - < QApplication::startDragDistance()) { - return; - } - - // Update old rubberband - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isEmpty()) { - if (d->viewportUpdateMode != FullViewportUpdate) - viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); - else - d->updateAll(); - } - - // Stop rubber banding if the user has let go of all buttons (even - // if we didn't get the release events). - if (!event->buttons()) { - d->rubberBanding = false; - d->rubberBandRect = QRect(); - return; - } - - // Update rubberband position - const QPoint &mp = d->mousePressViewPoint; - QPoint ep = event->pos(); - d->rubberBandRect = QRect(qMin(mp.x(), ep.x()), qMin(mp.y(), ep.y()), - qAbs(mp.x() - ep.x()) + 1, qAbs(mp.y() - ep.y()) + 1); - - // Update new rubberband - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate){ - if (d->viewportUpdateMode != FullViewportUpdate) - viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); - else - d->updateAll(); - } - // Set the new selection area - QPainterPath selectionArea; - selectionArea.addPolygon(mapToScene(d->rubberBandRect)); - selectionArea.closeSubpath(); - if (d->scene) - d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode, - viewportTransform()); - return; - } - } else -#endif // QT_NO_RUBBERBAND - if (d->dragMode == QGraphicsView::ScrollHandDrag) { - if (d->handScrolling) { - QScrollBar *hBar = horizontalScrollBar(); - QScrollBar *vBar = verticalScrollBar(); - QPoint delta = event->pos() - d->lastMouseEvent.pos(); - hBar->setValue(hBar->value() + (isRightToLeft() ? delta.x() : -delta.x())); - vBar->setValue(vBar->value() - delta.y()); - - // Detect how much we've scrolled to disambiguate scrolling from - // clicking. - ++d->handScrollMotions; - } - } - - d->mouseMoveEventHandler(event); -} - -/*! - \reimp -*/ -void QGraphicsView::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QGraphicsView); - -#ifndef QT_NO_RUBBERBAND - if (d->dragMode == QGraphicsView::RubberBandDrag && d->sceneInteractionAllowed && !event->buttons()) { - if (d->rubberBanding) { - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate){ - if (d->viewportUpdateMode != FullViewportUpdate) - viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); - else - d->updateAll(); - } - d->rubberBanding = false; - d->rubberBandRect = QRect(); - } - } else -#endif - if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) { -#ifndef QT_NO_CURSOR - // Restore the open hand cursor. ### There might be items - // under the mouse that have a valid cursor at this time, so - // we could repeat the steps from mouseMoveEvent(). - viewport()->setCursor(Qt::OpenHandCursor); -#endif - d->handScrolling = false; - - if (d->scene && d->sceneInteractionAllowed && !d->lastMouseEvent.isAccepted() && d->handScrollMotions <= 6) { - // If we've detected very little motion during the hand drag, and - // no item accepted the last event, we'll interpret that as a - // click to the scene, and reset the selection. - d->scene->clearSelection(); - } - } - - d->storeMouseEvent(event); - - if (!d->sceneInteractionAllowed) - return; - - if (!d->scene) - return; - - QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease); - mouseEvent.setWidget(viewport()); - mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint); - mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint); - mouseEvent.setScenePos(mapToScene(event->pos())); - mouseEvent.setScreenPos(event->globalPos()); - mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint); - mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint); - mouseEvent.setButtons(event->buttons()); - mouseEvent.setButton(event->button()); - mouseEvent.setModifiers(event->modifiers()); - mouseEvent.setAccepted(false); - if (event->spontaneous()) - qt_sendSpontaneousEvent(d->scene, &mouseEvent); - else - QApplication::sendEvent(d->scene, &mouseEvent); - - // Update the last mouse event selected state. - d->lastMouseEvent.setAccepted(mouseEvent.isAccepted()); - -#ifndef QT_NO_CURSOR - if (mouseEvent.isAccepted() && mouseEvent.buttons() == 0 && viewport()->testAttribute(Qt::WA_SetCursor)) { - // The last mouse release on the viewport will trigger clearing the cursor. - d->_q_unsetViewportCursor(); - } -#endif -} - -#ifndef QT_NO_WHEELEVENT -/*! - \reimp -*/ -void QGraphicsView::wheelEvent(QWheelEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene || !d->sceneInteractionAllowed) { - QAbstractScrollArea::wheelEvent(event); - return; - } - - event->ignore(); - - QGraphicsSceneWheelEvent wheelEvent(QEvent::GraphicsSceneWheel); - wheelEvent.setWidget(viewport()); - wheelEvent.setScenePos(mapToScene(event->pos())); - wheelEvent.setScreenPos(event->globalPos()); - wheelEvent.setButtons(event->buttons()); - wheelEvent.setModifiers(event->modifiers()); - wheelEvent.setDelta(event->delta()); - wheelEvent.setOrientation(event->orientation()); - wheelEvent.setAccepted(false); - QApplication::sendEvent(d->scene, &wheelEvent); - event->setAccepted(wheelEvent.isAccepted()); - if (!event->isAccepted()) - QAbstractScrollArea::wheelEvent(event); -} -#endif // QT_NO_WHEELEVENT - -/*! - \reimp -*/ -void QGraphicsView::paintEvent(QPaintEvent *event) -{ - Q_D(QGraphicsView); - if (!d->scene) { - QAbstractScrollArea::paintEvent(event); - return; - } - - // Set up painter state protection. - d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState); - - // Determine the exposed region - d->exposedRegion = event->region(); - QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); - - // Set up the painter - QPainter painter(viewport()); -#ifndef QT_NO_RUBBERBAND - if (d->rubberBanding && !d->rubberBandRect.isEmpty()) - painter.save(); -#endif - // Set up render hints - painter.setRenderHints(painter.renderHints(), false); - painter.setRenderHints(d->renderHints, true); - - // Set up viewport transform - const bool viewTransformed = isTransformed(); - if (viewTransformed) - painter.setWorldTransform(viewportTransform()); - const QTransform viewTransform = painter.worldTransform(); - - // Draw background - if ((d->cacheMode & CacheBackground) -#ifdef Q_WS_X11 - && X11->use_xrender -#endif - ) { - // Recreate the background pixmap, and flag the whole background as - // exposed. - if (d->mustResizeBackgroundPixmap) { - d->backgroundPixmap = QPixmap(viewport()->size()); - QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole()); - if (!bgBrush.isOpaque()) - d->backgroundPixmap.fill(Qt::transparent); - QPainter p(&d->backgroundPixmap); - p.fillRect(0, 0, d->backgroundPixmap.width(), d->backgroundPixmap.height(), bgBrush); - d->backgroundPixmapExposed = QRegion(viewport()->rect()); - d->mustResizeBackgroundPixmap = false; - } - - // Redraw exposed areas - if (!d->backgroundPixmapExposed.isEmpty()) { - QPainter backgroundPainter(&d->backgroundPixmap); - backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); - if (viewTransformed) - backgroundPainter.setTransform(viewTransform); - QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect(); - drawBackground(&backgroundPainter, backgroundExposedSceneRect); - d->backgroundPixmapExposed = QRegion(); - } - - // Blit the background from the background pixmap - if (viewTransformed) { - painter.setWorldTransform(QTransform()); - painter.drawPixmap(QPoint(), d->backgroundPixmap); - painter.setWorldTransform(viewTransform); - } else { - painter.drawPixmap(QPoint(), d->backgroundPixmap); - } - } else { - if (!(d->optimizationFlags & DontSavePainterState)) - painter.save(); - drawBackground(&painter, exposedSceneRect); - if (!(d->optimizationFlags & DontSavePainterState)) - painter.restore(); - } - - // Items - if (!(d->optimizationFlags & IndirectPainting)) { - const quint32 oldRectAdjust = d->scene->d_func()->rectAdjust; - if (d->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - d->scene->d_func()->rectAdjust = 1; - else - d->scene->d_func()->rectAdjust = 2; - d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0, - &d->exposedRegion, viewport()); - d->scene->d_func()->rectAdjust = oldRectAdjust; - // Make sure the painter's world transform is restored correctly when - // drawing without painter state protection (DontSavePainterState). - // We only change the worldTransform() so there's no need to do a full-blown - // save() and restore(). Also note that we don't have to do this in case of - // IndirectPainting (the else branch), because in that case we always save() - // and restore() in QGraphicsScene::drawItems(). - if (!d->scene->d_func()->painterStateProtection) - painter.setOpacity(1.0); - painter.setWorldTransform(viewTransform); - } else { - // Make sure we don't have unpolished items before we draw - if (!d->scene->d_func()->unpolishedItems.isEmpty()) - d->scene->d_func()->_q_polishItems(); - // We reset updateAll here (after we've issued polish events) - // so that we can discard update requests coming from polishEvent(). - d->scene->d_func()->updateAll = false; - - // Find all exposed items - bool allItems = false; - QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform); - if (!itemList.isEmpty()) { - // Generate the style options. - const int numItems = itemList.size(); - QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. - QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); - QTransform transform(Qt::Uninitialized); - for (int i = 0; i < numItems; ++i) { - QGraphicsItem *item = itemArray[i]; - QGraphicsItemPrivate *itemd = item->d_ptr.data(); - itemd->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems); - // Cache the item's area in view coordinates. - // Note that we have to do this here in case the base class implementation - // (QGraphicsScene::drawItems) is not called. If it is, we'll do this - // operation twice, but that's the price one has to pay for using indirect - // painting :-/. - const QRectF brect = adjustedItemEffectiveBoundingRect(item); - if (!itemd->itemIsUntransformable()) { - transform = item->sceneTransform(); - if (viewTransformed) - transform *= viewTransform; - } else { - transform = item->deviceTransform(viewTransform); - } - itemd->paintedViewBoundingRects.insert(d->viewport, transform.mapRect(brect).toRect()); - } - // Draw the items. - drawItems(&painter, numItems, itemArray, styleOptionArray); - d->freeStyleOptionsArray(styleOptionArray); - } - } - - // Foreground - drawForeground(&painter, exposedSceneRect); - -#ifndef QT_NO_RUBBERBAND - // Rubberband - if (d->rubberBanding && !d->rubberBandRect.isEmpty()) { - painter.restore(); - QStyleOptionRubberBand option; - option.initFrom(viewport()); - option.rect = d->rubberBandRect; - option.shape = QRubberBand::Rectangle; - - QStyleHintReturnMask mask; - if (viewport()->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, viewport(), &mask)) { - // painter clipping for masked rubberbands - painter.setClipRegion(mask.region, Qt::IntersectClip); - } - - viewport()->style()->drawControl(QStyle::CE_RubberBand, &option, &painter, viewport()); - } -#endif - - painter.end(); - - // Restore painter state protection. - d->scene->d_func()->painterStateProtection = true; -} - -/*! - \reimp -*/ -void QGraphicsView::resizeEvent(QResizeEvent *event) -{ - Q_D(QGraphicsView); - // Save the last center point - the resize may scroll the view, which - // changes the center point. - QPointF oldLastCenterPoint = d->lastCenterPoint; - - QAbstractScrollArea::resizeEvent(event); - d->recalculateContentSize(); - - // Restore the center point again. - if (d->resizeAnchor == NoAnchor && !d->keepLastCenterPoint) { - d->updateLastCenterPoint(); - } else { - d->lastCenterPoint = oldLastCenterPoint; - } - d->centerView(d->resizeAnchor); - d->keepLastCenterPoint = false; - - if (d->cacheMode & CacheBackground) { - // Invalidate the background pixmap - d->mustResizeBackgroundPixmap = true; - } -} - -/*! - \reimp -*/ -void QGraphicsView::scrollContentsBy(int dx, int dy) -{ - Q_D(QGraphicsView); - d->dirtyScroll = true; - if (d->transforming) - return; - if (isRightToLeft()) - dx = -dx; - - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) { - if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) { - if (d->accelerateScrolling) { -#ifndef QT_NO_RUBBERBAND - // Update new and old rubberband regions - if (!d->rubberBandRect.isEmpty()) { - QRegion rubberBandRegion(d->rubberBandRegion(viewport(), d->rubberBandRect)); - rubberBandRegion += rubberBandRegion.translated(-dx, -dy); - viewport()->update(rubberBandRegion); - } -#endif - d->dirtyScrollOffset.rx() += dx; - d->dirtyScrollOffset.ry() += dy; - d->dirtyRegion.translate(dx, dy); - viewport()->scroll(dx, dy); - } else { - d->updateAll(); - } - } else { - d->updateAll(); - } - } - - d->updateLastCenterPoint(); - - if ((d->cacheMode & CacheBackground) -#ifdef Q_WS_X11 - && X11->use_xrender -#endif - ) { - // Scroll the background pixmap - QRegion exposed; - if (!d->backgroundPixmap.isNull()) - d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed); - - // Invalidate the background pixmap - d->backgroundPixmapExposed.translate(dx, dy); - d->backgroundPixmapExposed += exposed; - } - - // Always replay on scroll. - if (d->sceneInteractionAllowed) - d->replayLastMouseEvent(); -} - -/*! - \reimp -*/ -void QGraphicsView::showEvent(QShowEvent *event) -{ - Q_D(QGraphicsView); - d->recalculateContentSize(); - d->centerView(d->transformationAnchor); - QAbstractScrollArea::showEvent(event); -} - -/*! - \reimp -*/ -void QGraphicsView::inputMethodEvent(QInputMethodEvent *event) -{ - Q_D(QGraphicsView); - if (d->scene) - QApplication::sendEvent(d->scene, event); -} - -/*! - Draws the background of the scene using \a painter, before any items and - the foreground are drawn. Reimplement this function to provide a custom - background for this view. - - If all you want is to define a color, texture or gradient for the - background, you can call setBackgroundBrush() instead. - - All painting is done in \e scene coordinates. \a rect is the exposed - rectangle. - - The default implementation fills \a rect using the view's backgroundBrush. - If no such brush is defined (the default), the scene's drawBackground() - function is called instead. - - \sa drawForeground(), QGraphicsScene::drawBackground() -*/ -void QGraphicsView::drawBackground(QPainter *painter, const QRectF &rect) -{ - Q_D(QGraphicsView); - if (d->scene && d->backgroundBrush.style() == Qt::NoBrush) { - d->scene->drawBackground(painter, rect); - return; - } - - painter->fillRect(rect, d->backgroundBrush); -} - -/*! - Draws the foreground of the scene using \a painter, after the background - and all items are drawn. Reimplement this function to provide a custom - foreground for this view. - - If all you want is to define a color, texture or gradient for the - foreground, you can call setForegroundBrush() instead. - - All painting is done in \e scene coordinates. \a rect is the exposed - rectangle. - - The default implementation fills \a rect using the view's foregroundBrush. - If no such brush is defined (the default), the scene's drawForeground() - function is called instead. - - \sa drawBackground(), QGraphicsScene::drawForeground() -*/ -void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect) -{ - Q_D(QGraphicsView); - if (d->scene && d->foregroundBrush.style() == Qt::NoBrush) { - d->scene->drawForeground(painter, rect); - return; - } - - painter->fillRect(rect, d->foregroundBrush); -} - -/*! - \obsolete - - Draws the items \a items in the scene using \a painter, after the - background and before the foreground are drawn. \a numItems is the number - of items in \a items and options in \a options. \a options is a list of - styleoptions; one for each item. Reimplement this function to provide - custom item drawing for this view. - - The default implementation calls the scene's drawItems() function. - - Since Qt 4.6, this function is not called anymore unless - the QGraphicsView::IndirectPainting flag is given as an Optimization - flag. - - \sa drawForeground(), drawBackground(), QGraphicsScene::drawItems() -*/ -void QGraphicsView::drawItems(QPainter *painter, int numItems, - QGraphicsItem *items[], - const QStyleOptionGraphicsItem options[]) -{ - Q_D(QGraphicsView); - if (d->scene) { - QWidget *widget = painter->device() == viewport() ? viewport() : 0; - d->scene->drawItems(painter, numItems, items, options, widget); - } -} - -/*! - Returns the current transformation matrix for the view. If no current - transformation is set, the identity matrix is returned. - - \sa setTransform(), rotate(), scale(), shear(), translate() -*/ -QTransform QGraphicsView::transform() const -{ - Q_D(const QGraphicsView); - return d->matrix; -} - -/*! - Returns a matrix that maps viewport coordinates to scene coordinates. - - \sa mapToScene(), mapFromScene() -*/ -QTransform QGraphicsView::viewportTransform() const -{ - Q_D(const QGraphicsView); - QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); - return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix; -} - -/*! - \since 4.6 - - Returns true if the view is transformed (i.e., a non-identity transform - has been assigned, or the scrollbars are adjusted). - - \sa setTransform(), horizontalScrollBar(), verticalScrollBar() -*/ -bool QGraphicsView::isTransformed() const -{ - Q_D(const QGraphicsView); - return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll(); -} - -/*! - Sets the view's current transformation matrix to \a matrix. - - If \a combine is true, then \a matrix is combined with the current matrix; - otherwise, \a matrix \e replaces the current matrix. \a combine is false - by default. - - The transformation matrix tranforms the scene into view coordinates. Using - the default transformation, provided by the identity matrix, one pixel in - the view represents one unit in the scene (e.g., a 10x10 rectangular item - is drawn using 10x10 pixels in the view). If a 2x2 scaling matrix is - applied, the scene will be drawn in 1:2 (e.g., a 10x10 rectangular item is - then drawn using 20x20 pixels in the view). - - Example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 7 - - To simplify interation with items using a transformed view, QGraphicsView - provides mapTo... and mapFrom... functions that can translate between - scene and view coordinates. For example, you can call mapToScene() to map - a view coordiate to a floating point scene coordinate, or mapFromScene() - to map from floating point scene coordinates to view coordinates. - - \sa transform(), rotate(), scale(), shear(), translate() -*/ -void QGraphicsView::setTransform(const QTransform &matrix, bool combine ) -{ - Q_D(QGraphicsView); - QTransform oldMatrix = d->matrix; - if (!combine) - d->matrix = matrix; - else - d->matrix = matrix * d->matrix; - if (oldMatrix == d->matrix) - return; - - d->identityMatrix = d->matrix.isIdentity(); - d->transforming = true; - if (d->scene) { - d->recalculateContentSize(); - d->centerView(d->transformationAnchor); - } else { - d->updateLastCenterPoint(); - } - - if (d->sceneInteractionAllowed) - d->replayLastMouseEvent(); - d->transforming = false; - - // Any matrix operation requires a full update. - d->updateAll(); -} - -/*! - Resets the view transformation to the identity matrix. - - \sa transform(), setTransform() -*/ -void QGraphicsView::resetTransform() -{ - setTransform(QTransform()); -} - -QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const -{ - QPointF p = point; - p.rx() += horizontalScroll(); - p.ry() += verticalScroll(); - return identityMatrix ? p : matrix.inverted().map(p); -} - -QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const -{ - QPointF scrollOffset(horizontalScroll(), verticalScroll()); - QPointF tl = scrollOffset + rect.topLeft(); - QPointF tr = scrollOffset + rect.topRight(); - QPointF br = scrollOffset + rect.bottomRight(); - QPointF bl = scrollOffset + rect.bottomLeft(); - - QPolygonF poly(4); - if (!identityMatrix) { - QTransform x = matrix.inverted(); - poly[0] = x.map(tl); - poly[1] = x.map(tr); - poly[2] = x.map(br); - poly[3] = x.map(bl); - } else { - poly[0] = tl; - poly[1] = tr; - poly[2] = br; - poly[3] = bl; - } - return poly.boundingRect(); -} - -QT_END_NAMESPACE - -#include "moc_qgraphicsview.cpp" - -#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h deleted file mode 100644 index 1447eebcb1..0000000000 --- a/src/gui/graphicsview/qgraphicsview.h +++ /dev/null @@ -1,316 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSVIEW_H -#define QGRAPHICSVIEW_H - -#include <QtCore/qmetatype.h> -#include <QtGui/qpainter.h> -#include <QtGui/qscrollarea.h> -#include <QtGui/qgraphicsscene.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsItem; -class QPainterPath; -class QPolygonF; -class QStyleOptionGraphicsItem; - -class QGraphicsViewPrivate; -class Q_GUI_EXPORT QGraphicsView : public QAbstractScrollArea -{ - Q_OBJECT - Q_FLAGS(QPainter::RenderHints CacheMode OptimizationFlags) - Q_ENUMS(ViewportAnchor DragMode ViewportUpdateMode) - Q_PROPERTY(QBrush backgroundBrush READ backgroundBrush WRITE setBackgroundBrush) - Q_PROPERTY(QBrush foregroundBrush READ foregroundBrush WRITE setForegroundBrush) - Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive) - Q_PROPERTY(QRectF sceneRect READ sceneRect WRITE setSceneRect) - Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment) - Q_PROPERTY(QPainter::RenderHints renderHints READ renderHints WRITE setRenderHints) - Q_PROPERTY(DragMode dragMode READ dragMode WRITE setDragMode) - Q_PROPERTY(CacheMode cacheMode READ cacheMode WRITE setCacheMode) - Q_PROPERTY(ViewportAnchor transformationAnchor READ transformationAnchor WRITE setTransformationAnchor) - Q_PROPERTY(ViewportAnchor resizeAnchor READ resizeAnchor WRITE setResizeAnchor) - Q_PROPERTY(ViewportUpdateMode viewportUpdateMode READ viewportUpdateMode WRITE setViewportUpdateMode) -#ifndef QT_NO_RUBBERBAND - Q_PROPERTY(Qt::ItemSelectionMode rubberBandSelectionMode READ rubberBandSelectionMode WRITE setRubberBandSelectionMode) -#endif - Q_PROPERTY(OptimizationFlags optimizationFlags READ optimizationFlags WRITE setOptimizationFlags) - -public: - enum ViewportAnchor { - NoAnchor, - AnchorViewCenter, - AnchorUnderMouse - }; - - enum CacheModeFlag { - CacheNone = 0x0, - CacheBackground = 0x1 - }; - Q_DECLARE_FLAGS(CacheMode, CacheModeFlag) - - enum DragMode { - NoDrag, - ScrollHandDrag, - RubberBandDrag - }; - - enum ViewportUpdateMode { - FullViewportUpdate, - MinimalViewportUpdate, - SmartViewportUpdate, - NoViewportUpdate, - BoundingRectViewportUpdate - }; - - enum OptimizationFlag { - DontClipPainter = 0x1, // obsolete - DontSavePainterState = 0x2, - DontAdjustForAntialiasing = 0x4, - IndirectPainting = 0x8 - }; - Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag) - - QGraphicsView(QWidget *parent = 0); - QGraphicsView(QGraphicsScene *scene, QWidget *parent = 0); - ~QGraphicsView(); - - QSize sizeHint() const; - - QPainter::RenderHints renderHints() const; - void setRenderHint(QPainter::RenderHint hint, bool enabled = true); - void setRenderHints(QPainter::RenderHints hints); - - Qt::Alignment alignment() const; - void setAlignment(Qt::Alignment alignment); - - ViewportAnchor transformationAnchor() const; - void setTransformationAnchor(ViewportAnchor anchor); - - ViewportAnchor resizeAnchor() const; - void setResizeAnchor(ViewportAnchor anchor); - - ViewportUpdateMode viewportUpdateMode() const; - void setViewportUpdateMode(ViewportUpdateMode mode); - - OptimizationFlags optimizationFlags() const; - void setOptimizationFlag(OptimizationFlag flag, bool enabled = true); - void setOptimizationFlags(OptimizationFlags flags); - - DragMode dragMode() const; - void setDragMode(DragMode mode); - -#ifndef QT_NO_RUBBERBAND - Qt::ItemSelectionMode rubberBandSelectionMode() const; - void setRubberBandSelectionMode(Qt::ItemSelectionMode mode); -#endif - - CacheMode cacheMode() const; - void setCacheMode(CacheMode mode); - void resetCachedContent(); - - bool isInteractive() const; - void setInteractive(bool allowed); - - QGraphicsScene *scene() const; - void setScene(QGraphicsScene *scene); - - QRectF sceneRect() const; - void setSceneRect(const QRectF &rect); - inline void setSceneRect(qreal x, qreal y, qreal w, qreal h); - - QMatrix matrix() const; - void setMatrix(const QMatrix &matrix, bool combine = false); - void resetMatrix(); - QTransform transform() const; - QTransform viewportTransform() const; - bool isTransformed() const; - void setTransform(const QTransform &matrix, bool combine = false); - void resetTransform(); - void rotate(qreal angle); - void scale(qreal sx, qreal sy); - void shear(qreal sh, qreal sv); - void translate(qreal dx, qreal dy); - - void centerOn(const QPointF &pos); - inline void centerOn(qreal x, qreal y); - void centerOn(const QGraphicsItem *item); - void ensureVisible(const QRectF &rect, int xmargin = 50, int ymargin = 50); - inline void ensureVisible(qreal x, qreal y, qreal w, qreal h, int xmargin = 50, int ymargin = 50); - void ensureVisible(const QGraphicsItem *item, int xmargin = 50, int ymargin = 50); - void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio); - inline void fitInView(qreal x, qreal y, qreal w, qreal h, - Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio); - void fitInView(const QGraphicsItem *item, - Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio); - - void render(QPainter *painter, const QRectF &target = QRectF(), const QRect &source = QRect(), - Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio); - - QList<QGraphicsItem *> items() const; - QList<QGraphicsItem *> items(const QPoint &pos) const; - inline QList<QGraphicsItem *> items(int x, int y) const; - QList<QGraphicsItem *> items(const QRect &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - inline QList<QGraphicsItem *> items(int x, int y, int w, int h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList<QGraphicsItem *> items(const QPolygon &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QGraphicsItem *itemAt(const QPoint &pos) const; - inline QGraphicsItem *itemAt(int x, int y) const; - - QPointF mapToScene(const QPoint &point) const; - QPolygonF mapToScene(const QRect &rect) const; - QPolygonF mapToScene(const QPolygon &polygon) const; - QPainterPath mapToScene(const QPainterPath &path) const; - QPoint mapFromScene(const QPointF &point) const; - QPolygon mapFromScene(const QRectF &rect) const; - QPolygon mapFromScene(const QPolygonF &polygon) const; - QPainterPath mapFromScene(const QPainterPath &path) const; - inline QPointF mapToScene(int x, int y) const; - inline QPolygonF mapToScene(int x, int y, int w, int h) const; - inline QPoint mapFromScene(qreal x, qreal y) const; - inline QPolygon mapFromScene(qreal x, qreal y, qreal w, qreal h) const; - - QVariant inputMethodQuery(Qt::InputMethodQuery query) const; - - QBrush backgroundBrush() const; - void setBackgroundBrush(const QBrush &brush); - - QBrush foregroundBrush() const; - void setForegroundBrush(const QBrush &brush); - -public Q_SLOTS: - void updateScene(const QList<QRectF> &rects); - void invalidateScene(const QRectF &rect = QRectF(), QGraphicsScene::SceneLayers layers = QGraphicsScene::AllLayers); - void updateSceneRect(const QRectF &rect); - -protected Q_SLOTS: - void setupViewport(QWidget *widget); - -protected: - QGraphicsView(QGraphicsViewPrivate &, QWidget *parent = 0); - bool event(QEvent *event); - bool viewportEvent(QEvent *event); - -#ifndef QT_NO_CONTEXTMENU - void contextMenuEvent(QContextMenuEvent *event); -#endif - void dragEnterEvent(QDragEnterEvent *event); - void dragLeaveEvent(QDragLeaveEvent *event); - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); - void focusInEvent(QFocusEvent *event); - bool focusNextPrevChild(bool next); - void focusOutEvent(QFocusEvent *event); - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); -#ifndef QT_NO_WHEELEVENT - void wheelEvent(QWheelEvent *event); -#endif - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *event); - void scrollContentsBy(int dx, int dy); - void showEvent(QShowEvent *event); - void inputMethodEvent(QInputMethodEvent *event); - - virtual void drawBackground(QPainter *painter, const QRectF &rect); - virtual void drawForeground(QPainter *painter, const QRectF &rect); - virtual void drawItems(QPainter *painter, int numItems, - QGraphicsItem *items[], - const QStyleOptionGraphicsItem options[]); - -private: - Q_DECLARE_PRIVATE(QGraphicsView) - Q_DISABLE_COPY(QGraphicsView) -#ifndef QT_NO_CURSOR - Q_PRIVATE_SLOT(d_func(), void _q_setViewportCursor(const QCursor &)) - Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor()) -#endif - friend class QGraphicsSceneWidget; - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; - friend class QGraphicsItemPrivate; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsView::CacheMode) -Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsView::OptimizationFlags) - -inline void QGraphicsView::setSceneRect(qreal ax, qreal ay, qreal aw, qreal ah) -{ setSceneRect(QRectF(ax, ay, aw, ah)); } -inline void QGraphicsView::centerOn(qreal ax, qreal ay) -{ centerOn(QPointF(ax, ay)); } -inline void QGraphicsView::ensureVisible(qreal ax, qreal ay, qreal aw, qreal ah, int xmargin, int ymargin) -{ ensureVisible(QRectF(ax, ay, aw, ah), xmargin, ymargin); } -inline void QGraphicsView::fitInView(qreal ax, qreal ay, qreal w, qreal h, Qt::AspectRatioMode mode) -{ fitInView(QRectF(ax, ay, w, h), mode); } -inline QList<QGraphicsItem *> QGraphicsView::items(int ax, int ay) const -{ return items(QPoint(ax, ay)); } -inline QList<QGraphicsItem *> QGraphicsView::items(int ax, int ay, int w, int h, Qt::ItemSelectionMode mode) const -{ return items(QRect(ax, ay, w, h), mode); } -inline QGraphicsItem *QGraphicsView::itemAt(int ax, int ay) const -{ return itemAt(QPoint(ax, ay)); } -inline QPointF QGraphicsView::mapToScene(int ax, int ay) const -{ return mapToScene(QPoint(ax, ay)); } -inline QPolygonF QGraphicsView::mapToScene(int ax, int ay, int w, int h) const -{ return mapToScene(QRect(ax, ay, w, h)); } -inline QPoint QGraphicsView::mapFromScene(qreal ax, qreal ay) const -{ return mapFromScene(QPointF(ax, ay)); } -inline QPolygon QGraphicsView::mapFromScene(qreal ax, qreal ay, qreal w, qreal h) const -{ return mapFromScene(QRectF(ax, ay, w, h)); } - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSVIEW_H diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h deleted file mode 100644 index 021ab2df3c..0000000000 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ /dev/null @@ -1,233 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSVIEW_P_H -#define QGRAPHICSVIEW_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsview.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include <QtGui/qevent.h> -#include <QtCore/qcoreapplication.h> -#include "qgraphicssceneevent.h" -#include <QtGui/qstyleoption.h> -#include <private/qabstractscrollarea_p.h> -#include <private/qapplication_p.h> - -QT_BEGIN_NAMESPACE - -class Q_GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsView) -public: - QGraphicsViewPrivate(); - - void recalculateContentSize(); - void centerView(QGraphicsView::ViewportAnchor anchor); - - QPainter::RenderHints renderHints; - - QGraphicsView::DragMode dragMode; - - quint32 sceneInteractionAllowed : 1; - quint32 hasSceneRect : 1; - quint32 connectedToScene : 1; - quint32 useLastMouseEvent : 1; - quint32 identityMatrix : 1; - quint32 dirtyScroll : 1; - quint32 accelerateScrolling : 1; - quint32 keepLastCenterPoint : 1; - quint32 transforming : 1; - quint32 handScrolling : 1; - quint32 mustAllocateStyleOptions : 1; - quint32 mustResizeBackgroundPixmap : 1; - quint32 fullUpdatePending : 1; - quint32 hasUpdateClip : 1; - quint32 padding : 18; - - QRectF sceneRect; - void updateLastCenterPoint(); - - qint64 horizontalScroll() const; - qint64 verticalScroll() const; - - QRectF mapRectToScene(const QRect &rect) const; - QRectF mapRectFromScene(const QRectF &rect) const; - - QRect updateClip; - QPointF mousePressItemPoint; - QPointF mousePressScenePoint; - QPoint mousePressViewPoint; - QPoint mousePressScreenPoint; - QPointF lastMouseMoveScenePoint; - QPoint lastMouseMoveScreenPoint; - QPoint dirtyScrollOffset; - Qt::MouseButton mousePressButton; - QTransform matrix; - qint64 scrollX, scrollY; - void updateScroll(); - - qreal leftIndent; - qreal topIndent; - - // Replaying mouse events - QMouseEvent lastMouseEvent; - void replayLastMouseEvent(); - void storeMouseEvent(QMouseEvent *event); - void mouseMoveEventHandler(QMouseEvent *event); - - QPointF lastCenterPoint; - Qt::Alignment alignment; - - QGraphicsView::ViewportAnchor transformationAnchor; - QGraphicsView::ViewportAnchor resizeAnchor; - QGraphicsView::ViewportUpdateMode viewportUpdateMode; - QGraphicsView::OptimizationFlags optimizationFlags; - - QPointer<QGraphicsScene> scene; -#ifndef QT_NO_RUBBERBAND - QRect rubberBandRect; - QRegion rubberBandRegion(const QWidget *widget, const QRect &rect) const; - bool rubberBanding; - Qt::ItemSelectionMode rubberBandSelectionMode; -#endif - int handScrollMotions; - - QGraphicsView::CacheMode cacheMode; - - QVector<QStyleOptionGraphicsItem> styleOptions; - QStyleOptionGraphicsItem *allocStyleOptionsArray(int numItems); - void freeStyleOptionsArray(QStyleOptionGraphicsItem *array); - - QBrush backgroundBrush; - QBrush foregroundBrush; - QPixmap backgroundPixmap; - QRegion backgroundPixmapExposed; - -#ifndef QT_NO_CURSOR - QCursor originalCursor; - bool hasStoredOriginalCursor; - void _q_setViewportCursor(const QCursor &cursor); - void _q_unsetViewportCursor(); -#endif - - QGraphicsSceneDragDropEvent *lastDragDropEvent; - void storeDragDropEvent(const QGraphicsSceneDragDropEvent *event); - void populateSceneDragDropEvent(QGraphicsSceneDragDropEvent *dest, - QDropEvent *source); - - QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const; - QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const; - QRegion dirtyRegion; - QRect dirtyBoundingRect; - void processPendingUpdates(); - inline void updateAll() - { - viewport->update(); - fullUpdatePending = true; - dirtyBoundingRect = QRect(); - dirtyRegion = QRegion(); - } - - inline void dispatchPendingUpdateRequests() - { -#ifdef Q_WS_MAC - // QWidget::update() works slightly different on the Mac without the raster engine; - // it's not part of our backing store so it needs special threatment. - if (QApplicationPrivate::graphics_system_name != QLatin1String("raster")) { - // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) - // is called, which means there's a pending update request. We want to dispatch it - // now because otherwise graphics view updates would require two - // round-trips in the event loop before the item is painted. - extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); - qt_mac_dispatchPendingUpdateRequests(viewport->window()); - } else -#endif // !Q_WS_MAC - { - if (qt_widget_private(viewport)->paintOnScreen()) - QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); - else - QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); - } - } - - void setUpdateClip(QGraphicsItem *); - - inline bool updateRectF(const QRectF &rect) - { - if (rect.isEmpty()) - return false; - if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - return updateRect(rect.toAlignedRect().adjusted(-1, -1, 1, 1)); - return updateRect(rect.toAlignedRect().adjusted(-2, -2, 2, 2)); - } - - bool updateRect(const QRect &rect); - bool updateRegion(const QRectF &rect, const QTransform &xform); - bool updateSceneSlotReimplementedChecked; - QRegion exposedRegion; - - QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems, - const QTransform &viewTransform) const; - - QPointF mapToScene(const QPointF &point) const; - QRectF mapToScene(const QRectF &rect) const; - static void translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent); - void updateInputMethodSensitivity(); -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp deleted file mode 100644 index 804394ad85..0000000000 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ /dev/null @@ -1,2425 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicswidget.h" -#include "qgraphicswidget_p.h" -#include "qgraphicslayout.h" -#include "qgraphicslayout_p.h" -#include "qgraphicsscene.h" -#include "qgraphicssceneevent.h" - -#ifndef QT_NO_ACTION -#include <private/qaction_p.h> -#endif -#include <private/qapplication_p.h> -#include <private/qgraphicsscene_p.h> -#ifndef QT_NO_SHORTCUT -#include <private/qshortcutmap_p.h> -#endif -#include <QtCore/qmutex.h> -#include <QtGui/qapplication.h> -#include <QtGui/qgraphicsview.h> -#include <QtGui/qgraphicsproxywidget.h> -#include <QtGui/qpalette.h> -#include <QtGui/qstyleoption.h> - -#include <qdebug.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QGraphicsWidget - \brief The QGraphicsWidget class is the base class for all widget - items in a QGraphicsScene. - \since 4.4 - \ingroup graphicsview-api - - QGraphicsWidget is an extended base item that provides extra functionality - over QGraphicsItem. It is similar to QWidget in many ways: - - \list - \o Provides a \l palette, a \l font and a \l style(). - \o Has a defined geometry(). - \o Supports layouts with setLayout() and layout(). - \o Supports shortcuts and actions with grabShortcut() and insertAction() - \endlist - - Unlike QGraphicsItem, QGraphicsWidget is not an abstract class; you can - create instances of a QGraphicsWidget without having to subclass it. - This approach is useful for widgets that only serve the purpose of - organizing child widgets into a layout. - - QGraphicsWidget can be used as a base item for your own custom item if - you require advanced input focus handling, e.g., tab focus and activation, or - layouts. - - Since QGraphicsWidget resembles QWidget and has similar API, it is - easier to port a widget from QWidget to QGraphicsWidget, instead of - QGraphicsItem. - - \note QWidget-based widgets can be directly embedded into a - QGraphicsScene using QGraphicsProxyWidget. - - Noticeable differences between QGraphicsWidget and QWidget are: - - \table - \header \o QGraphicsWidget - \o QWidget - \row \o Coordinates and geometry are defined with qreals (doubles or - floats, depending on the platform). - \o QWidget uses integer geometry (QPoint, QRect). - \row \o The widget is already visible by default; you do not have to - call show() to display the widget. - \o QWidget is hidden by default until you call show(). - \row \o A subset of widget attributes are supported. - \o All widget attributes are supported. - \row \o A top-level item's style defaults to QGraphicsScene::style - \o A top-level widget's style defaults to QApplication::style - \row \o Graphics View provides a custom drag and drop framework, different - from QWidget. - \o Standard drag and drop framework. - \row \o Widget items do not support modality. - \o Full modality support. - \endtable - - QGraphicsWidget supports a subset of Qt's widget attributes, - (Qt::WidgetAttribute), as shown in the table below. Any attributes not - listed in this table are unsupported, or otherwise unused. - - \table - \header \o Widget Attribute \o Usage - \row \o Qt::WA_SetLayoutDirection - \o Set by setLayoutDirection(), cleared by - unsetLayoutDirection(). You can test this attribute to - check if the widget has been explicitly assigned a - \l{QGraphicsWidget::layoutDirection()} - {layoutDirection}. If the attribute is not set, the - \l{QGraphicsWidget::layoutDirection()} - {layoutDirection()} is inherited. - \row \o Qt::WA_RightToLeft - \o Toggled by setLayoutDirection(). Inherited from the - parent/scene. If set, the widget's layout will order - horizontally arranged widgets from right to left. - \row \o Qt::WA_SetStyle - \o Set and cleared by setStyle(). If this attribute is - set, the widget has been explicitly assigned a style. - If it is unset, the widget will use the scene's or the - application's style. - \row \o Qt::WA_Resized - \o Set by setGeometry() and resize(). - \row \o Qt::WA_SetPalette - \o Set by setPalette(). - \row \o Qt::WA_SetFont - \o Set by setPalette(). - \row \o Qt::WA_WindowPropagation - \o Enables propagation to window widgets. - \endtable - - Although QGraphicsWidget inherits from both QObject and QGraphicsItem, - you should use the functions provided by QGraphicsItem, \e not QObject, to - manage the relationships between parent and child items. These functions - control the stacking order of items as well as their ownership. - - \note The QObject::parent() should always return 0 for QGraphicsWidgets, - but this policy is not strictly defined. - - \sa QGraphicsProxyWidget, QGraphicsItem, {Widgets and Layouts} -*/ - -/*! - Constructs a QGraphicsWidget instance. The optional \a parent argument is - passed to QGraphicsItem's constructor. The optional \a wFlags argument - specifies the widget's window flags (e.g., whether the widget should be a - window, a tool, a popup, etc). -*/ -QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) - : QGraphicsObject(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false) -{ - Q_D(QGraphicsWidget); - d->init(parent, wFlags); -} - -/*! - \internal - - Constructs a new QGraphicsWidget, using \a dd as parent. -*/ -QGraphicsWidget::QGraphicsWidget(QGraphicsWidgetPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene, Qt::WindowFlags wFlags) - : QGraphicsObject(dd, 0, scene), QGraphicsLayoutItem(0, false) -{ - Q_D(QGraphicsWidget); - d->init(parent, wFlags); -} - -/* - \internal - \class QGraphicsWidgetStyles - - We use this thread-safe class to maintain a hash of styles for widgets - styles. Note that QApplication::style() itself isn't thread-safe, QStyle - isn't thread-safe, and we don't have a thread-safe factory for creating - the default style, nor cloning a style. -*/ -class QGraphicsWidgetStyles -{ -public: - QStyle *styleForWidget(const QGraphicsWidget *widget) const - { - QMutexLocker locker(&mutex); - return styles.value(widget, 0); - } - - void setStyleForWidget(QGraphicsWidget *widget, QStyle *style) - { - QMutexLocker locker(&mutex); - if (style) - styles[widget] = style; - else - styles.remove(widget); - } - -private: - QMap<const QGraphicsWidget *, QStyle *> styles; - mutable QMutex mutex; -}; -Q_GLOBAL_STATIC(QGraphicsWidgetStyles, widgetStyles) - -/*! - Destroys the QGraphicsWidget instance. -*/ -QGraphicsWidget::~QGraphicsWidget() -{ - Q_D(QGraphicsWidget); -#ifndef QT_NO_ACTION - // Remove all actions from this widget - for (int i = 0; i < d->actions.size(); ++i) { - QActionPrivate *apriv = d->actions.at(i)->d_func(); - apriv->graphicsWidgets.removeAll(this); - } - d->actions.clear(); -#endif - - if (QGraphicsScene *scn = scene()) { - QGraphicsScenePrivate *sceneD = scn->d_func(); - if (sceneD->tabFocusFirst == this) - sceneD->tabFocusFirst = (d->focusNext == this ? 0 : d->focusNext); - } - d->focusPrev->d_func()->focusNext = d->focusNext; - d->focusNext->d_func()->focusPrev = d->focusPrev; - - // Play it really safe - d->focusNext = this; - d->focusPrev = this; - - clearFocus(); - - //we check if we have a layout previously - if (d->layout) { - QGraphicsLayout *temp = d->layout; - foreach (QGraphicsItem * item, childItems()) { - // In case of a custom layout which doesn't remove and delete items, we ensure that - // the parent layout item does not point to the deleted layout. This code is here to - // avoid regression from 4.4 to 4.5, because according to 4.5 docs it is not really needed. - if (item->isWidget()) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); - if (widget->parentLayoutItem() == d->layout) - widget->setParentLayoutItem(0); - } - } - d->layout = 0; - delete temp; - } - - // Remove this graphics widget from widgetStyles - widgetStyles()->setStyleForWidget(this, 0); -} - -/*! - \property QGraphicsWidget::size - \brief the size of the widget - - Calling resize() resizes the widget to a \a size bounded by minimumSize() - and maximumSize(). This property only affects the widget's width and - height (e.g., its right and bottom edges); the widget's position and - top-left corner remains unaffected. - - Resizing a widget triggers the widget to immediately receive a - \l{QEvent::GraphicsSceneResize}{GraphicsSceneResize} event with the - widget's old and new size. If the widget has a layout assigned when this - event arrives, the layout will be activated and it will automatically - update any child widgets's geometry. - - This property does not affect any layout of the parent widget. If the - widget itself is managed by a parent layout; e.g., it has a parent widget - with a layout assigned, that layout will not activate. - - By default, this property contains a size with zero width and height. - - \sa setGeometry(), QGraphicsSceneResizeEvent, QGraphicsLayout -*/ -QSizeF QGraphicsWidget::size() const -{ - return QGraphicsLayoutItem::geometry().size(); -} - -void QGraphicsWidget::resize(const QSizeF &size) -{ - setGeometry(QRectF(pos(), size)); -} - -/*! - \fn void QGraphicsWidget::resize(qreal w, qreal h) - - This convenience function is equivalent to calling resize(QSizeF(w, h)). - - \sa setGeometry(), setTransform() -*/ - -/*! - \property QGraphicsWidget::sizePolicy - \brief the size policy for the widget - \sa sizePolicy(), setSizePolicy(), QWidget::sizePolicy() -*/ - -/*! - \fn QGraphicsWidget::geometryChanged() - - This signal gets emitted whenever the geometry is changed in setGeometry(). -*/ - -/*! - \property QGraphicsWidget::geometry - \brief the geometry of the widget - - Sets the item's geometry to \a rect. The item's position and size are - modified as a result of calling this function. The item is first moved, - then resized. - - A side effect of calling this function is that the widget will receive - a move event and a resize event. Also, if the widget has a layout - assigned, the layout will activate. - - \sa geometry(), resize() -*/ -void QGraphicsWidget::setGeometry(const QRectF &rect) -{ - QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func(); - QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data(); - QRectF newGeom; - QPointF oldPos = d->geom.topLeft(); - if (!wd->inSetPos) { - setAttribute(Qt::WA_Resized); - newGeom = rect; - newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize)) - .boundedTo(effectiveSizeHint(Qt::MaximumSize))); - - if (newGeom == d->geom) { - goto relayoutChildrenAndReturn; - } - - // setPos triggers ItemPositionChange, which can adjust position - wd->inSetGeometry = 1; - setPos(newGeom.topLeft()); - wd->inSetGeometry = 0; - newGeom.moveTopLeft(pos()); - - if (newGeom == d->geom) { - goto relayoutChildrenAndReturn; - } - - // Update and prepare to change the geometry (remove from index) if the size has changed. - if (wd->scene) { - if (rect.topLeft() == d->geom.topLeft()) { - prepareGeometryChange(); - } - } - } - - // Update the layout item geometry - { - bool moved = oldPos != pos(); - if (moved) { - // Send move event. - QGraphicsSceneMoveEvent event; - event.setOldPos(oldPos); - event.setNewPos(pos()); - QApplication::sendEvent(this, &event); - if (wd->inSetPos) { - //set the new pos - d->geom.moveTopLeft(pos()); - emit geometryChanged(); - goto relayoutChildrenAndReturn; - } - } - QSizeF oldSize = size(); - QGraphicsLayoutItem::setGeometry(newGeom); - // Send resize event - bool resized = newGeom.size() != oldSize; - if (resized) { - QGraphicsSceneResizeEvent re; - re.setOldSize(oldSize); - re.setNewSize(newGeom.size()); - if (oldSize.width() != newGeom.size().width()) - emit widthChanged(); - if (oldSize.height() != newGeom.size().height()) - emit heightChanged(); - QGraphicsLayout *lay = wd->layout; - if (QGraphicsLayout::instantInvalidatePropagation()) { - if (!lay || lay->isActivated()) { - QApplication::sendEvent(this, &re); - } - } else { - QApplication::sendEvent(this, &re); - } - } - } - - emit geometryChanged(); -relayoutChildrenAndReturn: - if (QGraphicsLayout::instantInvalidatePropagation()) { - if (QGraphicsLayout *lay = wd->layout) { - if (!lay->isActivated()) { - QEvent layoutRequest(QEvent::LayoutRequest); - QApplication::sendEvent(this, &layoutRequest); - } - } - } -} - -/*! - \fn QRectF QGraphicsWidget::rect() const - - Returns the item's local rect as a QRectF. This function is equivalent - to QRectF(QPointF(), size()). - - \sa setGeometry(), resize() -*/ - -/*! - \fn void QGraphicsWidget::setGeometry(qreal x, qreal y, qreal w, qreal h) - - This convenience function is equivalent to calling setGeometry(QRectF( - \a x, \a y, \a w, \a h)). - - \sa geometry(), resize() -*/ - -/*! - \property QGraphicsWidget::minimumSize - \brief the minimum size of the widget - - \sa setMinimumSize(), minimumSize(), preferredSize, maximumSize -*/ - -/*! - \property QGraphicsWidget::preferredSize - \brief the preferred size of the widget - - \sa setPreferredSize(), preferredSize(), minimumSize, maximumSize -*/ - -/*! - \property QGraphicsWidget::maximumSize - \brief the maximum size of the widget - - \sa setMaximumSize(), maximumSize(), minimumSize, preferredSize -*/ - -/*! - Sets the widget's contents margins to \a left, \a top, \a right and \a - bottom. - - Contents margins are used by the assigned layout to define the placement - of subwidgets and layouts. Margins are particularly useful for widgets - that constrain subwidgets to only a section of its own geometry. For - example, a group box with a layout will place subwidgets inside its frame, - but below the title. - - Changing a widget's contents margins will always trigger an update(), and - any assigned layout will be activated automatically. The widget will then - receive a \l{QEvent::ContentsRectChange}{ContentsRectChange} event. - - \sa getContentsMargins(), setGeometry() -*/ -void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qreal bottom) -{ - Q_D(QGraphicsWidget); - - if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0) - return; - d->ensureMargins(); - if (left == d->margins[d->Left] - && top == d->margins[d->Top] - && right == d->margins[d->Right] - && bottom == d->margins[d->Bottom]) - return; - - d->margins[d->Left] = left; - d->margins[d->Top] = top; - d->margins[d->Right] = right; - d->margins[d->Bottom] = bottom; - - if (QGraphicsLayout *l = d->layout) - l->invalidate(); - else - updateGeometry(); - - QEvent e(QEvent::ContentsRectChange); - QApplication::sendEvent(this, &e); -} - -/*! - Gets the widget's contents margins. The margins are stored in \a left, \a - top, \a right and \a bottom, as pointers to qreals. Each argument can - be \e {omitted} by passing 0. - - \sa setContentsMargins() -*/ -void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const -{ - Q_D(const QGraphicsWidget); - if (left || top || right || bottom) - d->ensureMargins(); - if (left) - *left = d->margins[d->Left]; - if (top) - *top = d->margins[d->Top]; - if (right) - *right = d->margins[d->Right]; - if (bottom) - *bottom = d->margins[d->Bottom]; -} - -/*! - Sets the widget's window frame margins to \a left, \a top, \a right and - \a bottom. The default frame margins are provided by the style, and they - depend on the current window flags. - - If you would like to draw your own window decoration, you can set your - own frame margins to override the default margins. - - \sa unsetWindowFrameMargins(), getWindowFrameMargins(), windowFrameRect() -*/ -void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom) -{ - Q_D(QGraphicsWidget); - - if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0) - return; - d->ensureWindowFrameMargins(); - bool unchanged = - d->windowFrameMargins[d->Left] == left - && d->windowFrameMargins[d->Top] == top - && d->windowFrameMargins[d->Right] == right - && d->windowFrameMargins[d->Bottom] == bottom; - if (d->setWindowFrameMargins && unchanged) - return; - if (!unchanged) - prepareGeometryChange(); - d->windowFrameMargins[d->Left] = left; - d->windowFrameMargins[d->Top] = top; - d->windowFrameMargins[d->Right] = right; - d->windowFrameMargins[d->Bottom] = bottom; - d->setWindowFrameMargins = true; -} - -/*! - Gets the widget's window frame margins. The margins are stored in \a left, - \a top, \a right and \a bottom as pointers to qreals. Each argument can - be \e {omitted} by passing 0. - - \sa setWindowFrameMargins(), windowFrameRect() -*/ -void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const -{ - Q_D(const QGraphicsWidget); - if (left || top || right || bottom) - d->ensureWindowFrameMargins(); - if (left) - *left = d->windowFrameMargins[d->Left]; - if (top) - *top = d->windowFrameMargins[d->Top]; - if (right) - *right = d->windowFrameMargins[d->Right]; - if (bottom) - *bottom = d->windowFrameMargins[d->Bottom]; -} - -/*! - Resets the window frame margins to the default value, provided by the style. - - \sa setWindowFrameMargins(), getWindowFrameMargins(), windowFrameRect() -*/ -void QGraphicsWidget::unsetWindowFrameMargins() -{ - Q_D(QGraphicsWidget); - if ((d->windowFlags & Qt::Window) && (d->windowFlags & Qt::WindowType_Mask) != Qt::Popup && - (d->windowFlags & Qt::WindowType_Mask) != Qt::ToolTip && !(d->windowFlags & Qt::FramelessWindowHint)) { - QStyleOptionTitleBar bar; - d->initStyleOptionTitleBar(&bar); - QStyle *style = this->style(); - qreal margin = style->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth); - qreal titleBarHeight = d->titleBarHeight(bar); - setWindowFrameMargins(margin, titleBarHeight, margin, margin); - } else { - setWindowFrameMargins(0, 0, 0, 0); - } - d->setWindowFrameMargins = false; -} - -/*! - Returns the widget's geometry in parent coordinates including any window - frame. - - \sa windowFrameRect(), getWindowFrameMargins(), setWindowFrameMargins() -*/ -QRectF QGraphicsWidget::windowFrameGeometry() const -{ - Q_D(const QGraphicsWidget); - return d->windowFrameMargins - ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top], - d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom]) - : geometry(); -} - -/*! - Returns the widget's local rect including any window frame. - - \sa windowFrameGeometry(), getWindowFrameMargins(), setWindowFrameMargins() -*/ -QRectF QGraphicsWidget::windowFrameRect() const -{ - Q_D(const QGraphicsWidget); - return d->windowFrameMargins - ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top], - d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom]) - : rect(); -} - -/*! - Populates a style option object for this widget based on its current - state, and stores the output in \a option. The default implementation - populates \a option with the following properties. - - \table - \header - \o Style Option Property - \o Value - \row - \o state & QStyle::State_Enabled - \o Corresponds to QGraphicsItem::isEnabled(). - \row - \o state & QStyle::State_HasFocus - \o Corresponds to QGraphicsItem::hasFocus(). - \row - \o state & QStyle::State_MouseOver - \o Corresponds to QGraphicsItem::isUnderMouse(). - \row - \o direction - \o Corresponds to QGraphicsWidget::layoutDirection(). - \row - \o rect - \o Corresponds to QGraphicsWidget::rect().toRect(). - \row - \o palette - \o Corresponds to QGraphicsWidget::palette(). - \row - \o fontMetrics - \o Corresponds to QFontMetrics(QGraphicsWidget::font()). - \endtable - - Subclasses of QGraphicsWidget should call the base implementation, and - then test the type of \a option using qstyleoption_cast<>() or test - QStyleOption::Type before storing widget-specific options. - - For example: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicswidget.cpp 0 - - \sa QStyleOption::initFrom() -*/ -void QGraphicsWidget::initStyleOption(QStyleOption *option) const -{ - Q_ASSERT(option); - - option->state = QStyle::State_None; - if (isEnabled()) - option->state |= QStyle::State_Enabled; - if (hasFocus()) - option->state |= QStyle::State_HasFocus; - // if (window->testAttribute(Qt::WA_KeyboardFocusChange)) // ### Window - // option->state |= QStyle::State_KeyboardFocusChange; - if (isUnderMouse()) - option->state |= QStyle::State_MouseOver; - if (QGraphicsWidget *w = window()) { - if (w->isActiveWindow()) - option->state |= QStyle::State_Active; - } - if (isWindow()) - option->state |= QStyle::State_Window; - /* - ### -#ifdef Q_WS_MAC - extern bool qt_mac_can_clickThrough(const QGraphicsWidget *w); //qwidget_mac.cpp - if (!(option->state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) - option->state &= ~QStyle::State_Enabled; - - switch (QMacStyle::widgetSizePolicy(widget)) { - case QMacStyle::SizeSmall: - option->state |= QStyle::State_Small; - break; - case QMacStyle::SizeMini: - option->state |= QStyle::State_Mini; - break; - default: - ; - } -#endif -#ifdef QT_KEYPAD_NAVIGATION - if (widget->hasEditFocus()) - state |= QStyle::State_HasEditFocus; -#endif - */ - option->direction = layoutDirection(); - option->rect = rect().toRect(); // ### truncation! - option->palette = palette(); - if (!isEnabled()) { - option->palette.setCurrentColorGroup(QPalette::Disabled); - } else if (isActiveWindow()) { - option->palette.setCurrentColorGroup(QPalette::Active); - } else { - option->palette.setCurrentColorGroup(QPalette::Inactive); - } - option->fontMetrics = QFontMetrics(font()); -} - -/*! - \reimp -*/ -QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - Q_D(const QGraphicsWidget); - QSizeF sh; - if (d->layout) { - QSizeF marginSize(0,0); - if (d->margins) { - marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right], - d->margins[d->Top] + d->margins[d->Bottom]); - } - sh = d->layout->effectiveSizeHint(which, constraint - marginSize); - sh += marginSize; - } else { - switch (which) { - case Qt::MinimumSize: - sh = QSizeF(0, 0); - break; - case Qt::PreferredSize: - sh = QSizeF(50, 50); //rather arbitrary - break; - case Qt::MaximumSize: - sh = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - break; - default: - qWarning("QGraphicsWidget::sizeHint(): Don't know how to handle the value of 'which'"); - break; - } - } - return sh; -} - -/*! - \property QGraphicsWidget::layout - \brief The layout of the widget - - Any existing layout manager is deleted before the new layout is assigned. If - \a layout is 0, the widget is left without a layout. Existing subwidgets' - geometries will remain unaffected. - - QGraphicsWidget takes ownership of \a layout. - - All widgets that are currently managed by \a layout or all of its - sublayouts, are automatically reparented to this item. The layout is then - invalidated, and the child widget geometries are adjusted according to - this item's geometry() and contentsMargins(). Children who are not - explicitly managed by \a layout remain unaffected by the layout after - it has been assigned to this widget. - - If no layout is currently managing this widget, layout() will return 0. - -*/ - -/*! - \fn void QGraphicsWidget::layoutChanged() - This signal gets emitted whenever the layout of the item changes - \internal -*/ - -/*! - Returns this widget's layout, or 0 if no layout is currently managing this - widget. - - \sa setLayout() -*/ -QGraphicsLayout *QGraphicsWidget::layout() const -{ - Q_D(const QGraphicsWidget); - return d->layout; -} - -/*! - \fn void QGraphicsWidget::setLayout(QGraphicsLayout *layout) - - Sets the layout for this widget to \a layout. Any existing layout manager - is deleted before the new layout is assigned. If \a layout is 0, the - widget is left without a layout. Existing subwidgets' geometries will - remain unaffected. - - All widgets that are currently managed by \a layout or all of its - sublayouts, are automatically reparented to this item. The layout is then - invalidated, and the child widget geometries are adjusted according to - this item's geometry() and contentsMargins(). Children who are not - explicitly managed by \a layout remain unaffected by the layout after - it has been assigned to this widget. - - QGraphicsWidget takes ownership of \a layout. - - \sa layout(), QGraphicsLinearLayout::addItem(), QGraphicsLayout::invalidate() -*/ -void QGraphicsWidget::setLayout(QGraphicsLayout *l) -{ - Q_D(QGraphicsWidget); - if (d->layout == l) - return; - d->setLayout_helper(l); - if (!l) - return; - - // Prevent assigning a layout that is already assigned to another widget. - QGraphicsLayoutItem *oldParent = l->parentLayoutItem(); - if (oldParent && oldParent != this) { - qWarning("QGraphicsWidget::setLayout: Attempting to set a layout on %s" - " \"%s\", when the layout already has a parent", - metaObject()->className(), qPrintable(objectName())); - return; - } - - // Install and activate the layout. - l->setParentLayoutItem(this); - l->d_func()->reparentChildItems(this); - l->invalidate(); - emit layoutChanged(); -} - -/*! - Adjusts the size of the widget to its effective preferred size hint. - - This function is called implicitly when the item is shown for the first - time. - - \sa effectiveSizeHint(), Qt::MinimumSize -*/ -void QGraphicsWidget::adjustSize() -{ - QSizeF sz = effectiveSizeHint(Qt::PreferredSize); - // What if sz is not valid?! - if (sz.isValid()) - resize(sz); -} - -/*! - \property QGraphicsWidget::layoutDirection - \brief the layout direction for this widget. - - This property modifies this widget's and all of its descendants' - Qt::WA_RightToLeft attribute. It also sets this widget's - Qt::WA_SetLayoutDirection attribute. - - The widget's layout direction determines the order in which the layout - manager horizontally arranges subwidgets of this widget. The default - value depends on the language and locale of the application, and is - typically in the same direction as words are read and written. With - Qt::LeftToRight, the layout starts placing subwidgets from the left - side of this widget towards the right. Qt::RightToLeft does the opposite - - the layout will place widgets starting from the right edge moving towards - the left. - - Subwidgets inherit their layout direction from the parent. Top-level - widget items inherit their layout direction from - QGraphicsScene::layoutDirection. If you change a widget's layout direction - by calling setLayoutDirection(), the widget will send itself a - \l{QEvent::LayoutDirectionChange}{LayoutDirectionChange} event, and then - propagate the new layout direction to all its descendants. - - \sa QWidget::layoutDirection, QApplication::layoutDirection -*/ -Qt::LayoutDirection QGraphicsWidget::layoutDirection() const -{ - return testAttribute(Qt::WA_RightToLeft) ? Qt::RightToLeft : Qt::LeftToRight; -} -void QGraphicsWidget::setLayoutDirection(Qt::LayoutDirection direction) -{ - Q_D(QGraphicsWidget); - setAttribute(Qt::WA_SetLayoutDirection, true); - d->setLayoutDirection_helper(direction); -} -void QGraphicsWidget::unsetLayoutDirection() -{ - Q_D(QGraphicsWidget); - setAttribute(Qt::WA_SetLayoutDirection, false); - d->resolveLayoutDirection(); -} - -/*! - Returns a pointer to the widget's style. If this widget does not have any - explicitly assigned style, the scene's style is returned instead. In turn, - if the scene does not have any assigned style, this function returns - QApplication::style(). - - \sa setStyle() -*/ -QStyle *QGraphicsWidget::style() const -{ - if (QStyle *style = widgetStyles()->styleForWidget(this)) - return style; - // ### This is not thread-safe. QApplication::style() is not thread-safe. - return scene() ? scene()->style() : QApplication::style(); -} - -/*! - Sets the widget's style to \a style. QGraphicsWidget does \e not take - ownership of \a style. - - If no style is assigned, or \a style is 0, the widget will use - QGraphicsScene::style() (if this has been set). Otherwise the widget will - use QApplication::style(). - - This function sets the Qt::WA_SetStyle attribute if \a style is not 0; - otherwise it clears the attribute. - - \sa style() -*/ -void QGraphicsWidget::setStyle(QStyle *style) -{ - setAttribute(Qt::WA_SetStyle, style != 0); - widgetStyles()->setStyleForWidget(this, style); - - // Deliver StyleChange to the widget itself (doesn't propagate). - QEvent event(QEvent::StyleChange); - QApplication::sendEvent(this, &event); -} - -/*! - \property QGraphicsWidget::font - \brief the widgets' font - - This property provides the widget's font. - - QFont consists of font properties that have been explicitly defined and - properties implicitly inherited from the widget's parent. Hence, font() - can return a different font compared to the one set with setFont(). - This scheme allows you to define single entries in a font without - affecting the font's inherited entries. - - When a widget's font changes, it resolves its entries against its - parent widget. If the widget does not have a parent widget, it resolves - its entries against the scene. The widget then sends itself a - \l{QEvent::FontChange}{FontChange} event and notifies all its - descendants so that they can resolve their fonts as well. - - By default, this property contains the application's default font. - - \sa QApplication::font(), QGraphicsScene::font, QFont::resolve() -*/ -QFont QGraphicsWidget::font() const -{ - Q_D(const QGraphicsWidget); - QFont fnt = d->font; - fnt.resolve(fnt.resolve() | d->inheritedFontResolveMask); - return fnt; -} -void QGraphicsWidget::setFont(const QFont &font) -{ - Q_D(QGraphicsWidget); - setAttribute(Qt::WA_SetFont, font.resolve() != 0); - - QFont naturalFont = d->naturalWidgetFont(); - QFont resolvedFont = font.resolve(naturalFont); - d->setFont_helper(resolvedFont); -} - -/*! - \property QGraphicsWidget::palette - \brief the widget's palette - - This property provides the widget's palette. The palette provides colors - and brushes for color groups (e.g., QPalette::Button) and states (e.g., - QPalette::Inactive), loosely defining the general look of the widget and - its children. - - QPalette consists of color groups that have been explicitly defined, and - groups that are implicitly inherited from the widget's parent. Because of - this, palette() can return a different palette than what has been set with - setPalette(). This scheme allows you to define single entries in a palette - without affecting the palette's inherited entries. - - When a widget's palette changes, it resolves its entries against its - parent widget, or if it doesn't have a parent widget, it resolves against - the scene. It then sends itself a \l{QEvent::PaletteChange}{PaletteChange} - event, and notifies all its descendants so they can resolve their palettes - as well. - - By default, this property contains the application's default palette. - - \sa QApplication::palette(), QGraphicsScene::palette, QPalette::resolve() -*/ -QPalette QGraphicsWidget::palette() const -{ - Q_D(const QGraphicsWidget); - return d->palette; -} -void QGraphicsWidget::setPalette(const QPalette &palette) -{ - Q_D(QGraphicsWidget); - setAttribute(Qt::WA_SetPalette, palette.resolve() != 0); - - QPalette naturalPalette = d->naturalWidgetPalette(); - QPalette resolvedPalette = palette.resolve(naturalPalette); - d->setPalette_helper(resolvedPalette); -} - -/*! - \property QGraphicsWidget::autoFillBackground - \brief whether the widget background is filled automatically - \since 4.7 - - If enabled, this property will cause Qt to fill the background of the - widget before invoking the paint() method. The color used is defined by the - QPalette::Window color role from the widget's \l{QPalette}{palette}. - - In addition, Windows are always filled with QPalette::Window, unless the - WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set. - - By default, this property is false. - - \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground, -*/ -bool QGraphicsWidget::autoFillBackground() const -{ - Q_D(const QGraphicsWidget); - return d->autoFillBackground; -} -void QGraphicsWidget::setAutoFillBackground(bool enabled) -{ - Q_D(QGraphicsWidget); - if (d->autoFillBackground != enabled) { - d->autoFillBackground = enabled; - update(); - } -} - -/*! - If this widget is currently managed by a layout, this function notifies - the layout that the widget's size hints have changed and the layout - may need to resize and reposition the widget accordingly. - - Call this function if the widget's sizeHint() has changed. - - \sa QGraphicsLayout::invalidate() -*/ -void QGraphicsWidget::updateGeometry() -{ - QGraphicsLayoutItem::updateGeometry(); - QGraphicsLayoutItem *parentItem = parentLayoutItem(); - - if (parentItem && parentItem->isLayout()) { - if (QGraphicsLayout::instantInvalidatePropagation()) { - static_cast<QGraphicsLayout *>(parentItem)->invalidate(); - } else { - parentItem->updateGeometry(); - } - } else { - if (parentItem) { - // This is for custom layouting - QGraphicsWidget *parentWid = parentWidget(); //### - if (parentWid->isVisible()) - QApplication::postEvent(parentWid, new QEvent(QEvent::LayoutRequest)); - } else { - /** - * If this is the topmost widget, post a LayoutRequest event to the widget. - * When the event is received, it will start flowing all the way down to the leaf - * widgets in one go. This will make a relayout flicker-free. - */ - if (QGraphicsLayout::instantInvalidatePropagation()) - QApplication::postEvent(static_cast<QGraphicsWidget *>(this), new QEvent(QEvent::LayoutRequest)); - } - if (!QGraphicsLayout::instantInvalidatePropagation()) { - bool wasResized = testAttribute(Qt::WA_Resized); - resize(size()); // this will restrict the size - setAttribute(Qt::WA_Resized, wasResized); - } - } -} - -/*! - \reimp - - QGraphicsWidget uses the base implementation of this function to catch and - deliver events related to state changes in the item. Because of this, it is - very important that subclasses call the base implementation. - - \a change specifies the type of change, and \a value is the new value. - - For example, QGraphicsWidget uses ItemVisibleChange to deliver - \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events, - ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events, - and ItemParentChange both to deliver \l{QEvent::ParentChange} - {ParentChange} events, and for managing the focus chain. - - QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in - order to track position changes. - - \sa QGraphicsItem::itemChange() -*/ -QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) -{ - Q_D(QGraphicsWidget); - switch (change) { - case ItemEnabledHasChanged: { - // Send EnabledChange after the enabled state has changed. - QEvent event(QEvent::EnabledChange); - QApplication::sendEvent(this, &event); - break; - } - case ItemVisibleChange: - if (value.toBool()) { - // Send Show event before the item has been shown. - QShowEvent event; - QApplication::sendEvent(this, &event); - bool resized = testAttribute(Qt::WA_Resized); - if (!resized) { - adjustSize(); - setAttribute(Qt::WA_Resized, false); - } - } - break; - case ItemVisibleHasChanged: - if (!value.toBool()) { - // Send Hide event after the item has been hidden. - QHideEvent event; - QApplication::sendEvent(this, &event); - } - break; - case ItemPositionHasChanged: - d->setGeometryFromSetPos(); - break; - case ItemParentChange: { - // Deliver ParentAboutToChange. - QEvent event(QEvent::ParentAboutToChange); - QApplication::sendEvent(this, &event); - break; - } - case ItemParentHasChanged: { - // Deliver ParentChange. - QEvent event(QEvent::ParentChange); - QApplication::sendEvent(this, &event); - break; - } - case ItemCursorHasChanged: { - // Deliver CursorChange. - QEvent event(QEvent::CursorChange); - QApplication::sendEvent(this, &event); - break; - } - case ItemToolTipHasChanged: { - // Deliver ToolTipChange. - QEvent event(QEvent::ToolTipChange); - QApplication::sendEvent(this, &event); - break; - } - default: - break; - } - return QGraphicsItem::itemChange(change, value); -} - -/*! - \internal - - This virtual function is used to notify changes to any property (both - dynamic properties, and registered with Q_PROPERTY) in the - widget. Depending on the property itself, the notification can be - delivered before or after the value has changed. - - \a propertyName is the name of the property (e.g., "size" or "font"), and - \a value is the (proposed) new value of the property. The function returns - the new value, which may be different from \a value if the notification - supports adjusting the property value. The base implementation simply - returns \a value for any \a propertyName. - - QGraphicsWidget delivers notifications for the following properties: - - \table \o propertyName \o Property - \row \o layoutDirection \o QGraphicsWidget::layoutDirection - \row \o size \o QGraphicsWidget::size - \row \o font \o QGraphicsWidget::font - \row \o palette \o QGraphicsWidget::palette - \endtable - - \sa itemChange() -*/ -QVariant QGraphicsWidget::propertyChange(const QString &propertyName, const QVariant &value) -{ - Q_UNUSED(propertyName); - return value; -} - -/*! - QGraphicsWidget's implementation of sceneEvent() simply passes \a event to - QGraphicsWidget::event(). You can handle all events for your widget in - event() or in any of the convenience functions; you should not have to - reimplement this function in a subclass of QGraphicsWidget. - - \sa QGraphicsItem::sceneEvent() -*/ -bool QGraphicsWidget::sceneEvent(QEvent *event) -{ - return QGraphicsItem::sceneEvent(event); -} - -/*! - This event handler, for \a event, receives events for the window frame if - this widget is a window. Its base implementation provides support for - default window frame interaction such as moving, resizing, etc. - - You can reimplement this handler in a subclass of QGraphicsWidget to - provide your own custom window frame interaction support. - - Returns true if \a event has been recognized and processed; otherwise, - returns false. - - \sa event() -*/ -bool QGraphicsWidget::windowFrameEvent(QEvent *event) -{ - Q_D(QGraphicsWidget); - switch (event->type()) { - case QEvent::GraphicsSceneMousePress: - d->windowFrameMousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneMouseMove: - d->ensureWindowData(); - if (d->windowData->grabbedSection != Qt::NoSection) { - d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - event->accept(); - } - break; - case QEvent::GraphicsSceneMouseRelease: - d->windowFrameMouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); - break; - case QEvent::GraphicsSceneHoverMove: - d->windowFrameHoverMoveEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); - break; - case QEvent::GraphicsSceneHoverLeave: - d->windowFrameHoverLeaveEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); - break; - default: - break; - } - return event->isAccepted(); -} - -/*! - \since 4.4 - - Returns the window frame section at position \a pos, or - Qt::NoSection if there is no window frame section at this - position. - - This function is used in QGraphicsWidget's base implementation for window - frame interaction. - - You can reimplement this function if you want to customize how a window - can be interactively moved or resized. For instance, if you only want to - allow a window to be resized by the bottom right corner, you can - reimplement this function to return Qt::NoSection for all sections except - Qt::BottomRightSection. - - \sa windowFrameEvent(), paintWindowFrame(), windowFrameGeometry() -*/ -Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) const -{ - Q_D(const QGraphicsWidget); - - const QRectF r = windowFrameRect(); - if (!r.contains(pos)) - return Qt::NoSection; - - const qreal left = r.left(); - const qreal top = r.top(); - const qreal right = r.right(); - const qreal bottom = r.bottom(); - const qreal x = pos.x(); - const qreal y = pos.y(); - - const qreal cornerMargin = 20; - //### Not sure of this one, it should be the same value for all edges. - const qreal windowFrameWidth = d->windowFrameMargins - ? d->windowFrameMargins[d->Left] : 0; - - Qt::WindowFrameSection s = Qt::NoSection; - if (x <= left + cornerMargin) { - if (y <= top + windowFrameWidth || (x <= left + windowFrameWidth && y <= top + cornerMargin)) { - s = Qt::TopLeftSection; - } else if (y >= bottom - windowFrameWidth || (x <= left + windowFrameWidth && y >= bottom - windowFrameWidth)) { - s = Qt::BottomLeftSection; - } else if (x <= left + windowFrameWidth) { - s = Qt::LeftSection; - } - } else if (x >= right - cornerMargin) { - if (y <= top + windowFrameWidth || (x >= right - windowFrameWidth && y <= top + cornerMargin)) { - s = Qt::TopRightSection; - } else if (y >= bottom - windowFrameWidth || (x >= right - windowFrameWidth && y >= bottom - windowFrameWidth)) { - s = Qt::BottomRightSection; - } else if (x >= right - windowFrameWidth) { - s = Qt::RightSection; - } - } else if (y <= top + windowFrameWidth) { - s = Qt::TopSection; - } else if (y >= bottom - windowFrameWidth) { - s = Qt::BottomSection; - } - if (s == Qt::NoSection) { - QRectF r1 = r; - r1.setHeight(d->windowFrameMargins - ? d->windowFrameMargins[d->Top] : 0); - if (r1.contains(pos)) - s = Qt::TitleBarArea; - } - return s; -} - -/*! - \reimp - - Handles the \a event. QGraphicsWidget handles the following - events: - - \table \o Event \o Usage - \row \o Polish - \o Delivered to the widget some time after it has been - shown. - \row \o GraphicsSceneMove - \o Delivered to the widget after its local position has - changed. - \row \o GraphicsSceneResize - \o Delivered to the widget after its size has changed. - \row \o Show - \o Delivered to the widget before it has been shown. - \row \o Hide - \o Delivered to the widget after it has been hidden. - \row \o PaletteChange - \o Delivered to the widget after its palette has changed. - \row \o FontChange - \o Delivered to the widget after its font has changed. - \row \o EnabledChange - \o Delivered to the widget after its enabled state has - changed. - \row \o StyleChange - \o Delivered to the widget after its style has changed. - \row \o LayoutDirectionChange - \o Delivered to the widget after its layout direction has - changed. - \row \o ContentsRectChange - \o Delivered to the widget after its contents margins/ - contents rect has changed. - \endtable -*/ -bool QGraphicsWidget::event(QEvent *event) -{ - Q_D(QGraphicsWidget); - // Forward the event to the layout first. - if (d->layout) - d->layout->widgetEvent(event); - - // Handle the event itself. - switch (event->type()) { - case QEvent::GraphicsSceneMove: - moveEvent(static_cast<QGraphicsSceneMoveEvent *>(event)); - break; - case QEvent::GraphicsSceneResize: - resizeEvent(static_cast<QGraphicsSceneResizeEvent *>(event)); - break; - case QEvent::Show: - showEvent(static_cast<QShowEvent *>(event)); - break; - case QEvent::Hide: - hideEvent(static_cast<QHideEvent *>(event)); - break; - case QEvent::Polish: - polishEvent(); - d->polished = true; - if (!d->font.isCopyOf(QApplication::font())) - d->updateFont(d->font); - break; - case QEvent::WindowActivate: - case QEvent::WindowDeactivate: - update(); - break; - // Taken from QWidget::event - case QEvent::ActivationChange: - case QEvent::EnabledChange: - case QEvent::FontChange: - case QEvent::StyleChange: - case QEvent::PaletteChange: - case QEvent::ParentChange: - case QEvent::ContentsRectChange: - case QEvent::LayoutDirectionChange: - changeEvent(event); - break; - case QEvent::Close: - closeEvent((QCloseEvent *)event); - break; - case QEvent::GrabMouse: - grabMouseEvent(event); - break; - case QEvent::UngrabMouse: - ungrabMouseEvent(event); - break; - case QEvent::GrabKeyboard: - grabKeyboardEvent(event); - break; - case QEvent::UngrabKeyboard: - ungrabKeyboardEvent(event); - break; - case QEvent::GraphicsSceneMousePress: - if (d->hasDecoration() && windowFrameEvent(event)) - return true; - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseDoubleClick: - d->ensureWindowData(); - if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection) - return windowFrameEvent(event); - break; - case QEvent::GraphicsSceneHoverEnter: - case QEvent::GraphicsSceneHoverMove: - case QEvent::GraphicsSceneHoverLeave: - if (d->hasDecoration()) { - windowFrameEvent(event); - // Filter out hover events if they were sent to us only because of the - // decoration (special case in QGraphicsScenePrivate::dispatchHoverEvent). - if (!acceptsHoverEvents()) - return true; - } - break; - default: - break; - } - return QObject::event(event); -} - -/*! - This event handler can be reimplemented to handle state changes. - - The state being changed in this event can be retrieved through \a event. - - Change events include: QEvent::ActivationChange, QEvent::EnabledChange, - QEvent::FontChange, QEvent::StyleChange, QEvent::PaletteChange, - QEvent::ParentChange, QEvent::LayoutDirectionChange, and - QEvent::ContentsRectChange. -*/ -void QGraphicsWidget::changeEvent(QEvent *event) -{ - Q_D(QGraphicsWidget); - switch (event->type()) { - case QEvent::StyleChange: - // ### Don't unset if the margins are explicitly set. - unsetWindowFrameMargins(); - if (d->layout) - d->layout->invalidate(); - case QEvent::FontChange: - update(); - updateGeometry(); - break; - case QEvent::PaletteChange: - update(); - break; - case QEvent::ParentChange: - d->resolveFont(d->inheritedFontResolveMask); - d->resolvePalette(d->inheritedPaletteResolveMask); - break; - default: - break; - } -} - -/*! - This event handler, for \a event, can be reimplemented in a subclass to - receive widget close events. The default implementation accepts the - event. - - \sa close(), QCloseEvent -*/ -void QGraphicsWidget::closeEvent(QCloseEvent *event) -{ - event->accept(); -} - -/*! - \reimp -*/ -void QGraphicsWidget::focusInEvent(QFocusEvent *event) -{ - Q_UNUSED(event); - if (focusPolicy() != Qt::NoFocus) - update(); -} - -/*! - Finds a new widget to give the keyboard focus to, as appropriate for Tab - and Shift+Tab, and returns true if it can find a new widget; returns false - otherwise. If \a next is true, this function searches forward; if \a next - is false, it searches backward. - - Sometimes, you will want to reimplement this function to provide special - focus handling for your widget and its subwidgets. For example, a web - browser might reimplement it to move its current active link forward or - backward, and call the base implementation only when it reaches the last - or first link on the page. - - Child widgets call focusNextPrevChild() on their parent widgets, but only - the window that contains the child widgets decides where to redirect - focus. By reimplementing this function for an object, you gain control of - focus traversal for all child widgets. - - \sa focusPolicy() -*/ -bool QGraphicsWidget::focusNextPrevChild(bool next) -{ - Q_D(QGraphicsWidget); - // Let the parent's focusNextPrevChild implementation decide what to do. - QGraphicsWidget *parent = 0; - if (!isWindow() && (parent = parentWidget())) - return parent->focusNextPrevChild(next); - if (!d->scene) - return false; - if (d->scene->focusNextPrevChild(next)) - return true; - if (isWindow()) { - setFocus(next ? Qt::TabFocusReason : Qt::BacktabFocusReason); - if (hasFocus()) - return true; - } - return false; -} - -/*! - \reimp -*/ -void QGraphicsWidget::focusOutEvent(QFocusEvent *event) -{ - Q_UNUSED(event); - if (focusPolicy() != Qt::NoFocus) - update(); -} - -/*! - This event handler, for \l{QEvent::Hide}{Hide} events, is delivered after - the widget has been hidden, for example, setVisible(false) has been called - for the widget or one of its ancestors when the widget was previously - shown. - - You can reimplement this event handler to detect when your widget is - hidden. Calling QEvent::accept() or QEvent::ignore() on \a event has no - effect. - - \sa showEvent(), QWidget::hideEvent(), ItemVisibleChange -*/ -void QGraphicsWidget::hideEvent(QHideEvent *event) -{ - ///### focusNextPrevChild(true), don't lose focus when the focus widget - // is hidden. - Q_UNUSED(event); -} - -/*! - This event handler, for \l{QEvent::GraphicsSceneMove}{GraphicsSceneMove} - events, is delivered after the widget has moved (e.g., its local position - has changed). - - This event is only delivered when the item is moved locally. Calling - setTransform() or moving any of the item's ancestors does not affect the - item's local position. - - You can reimplement this event handler to detect when your widget has - moved. Calling QEvent::accept() or QEvent::ignore() on \a event has no - effect. - - \sa ItemPositionChange, ItemPositionHasChanged -*/ -void QGraphicsWidget::moveEvent(QGraphicsSceneMoveEvent *event) -{ - // ### Last position is always == current position - Q_UNUSED(event); -} - -/*! - This event is delivered to the item by the scene at some point after it - has been constructed, but before it is shown or otherwise accessed through - the scene. You can use this event handler to do last-minute initializations - of the widget which require the item to be fully constructed. - - The base implementation does nothing. -*/ -void QGraphicsWidget::polishEvent() -{ -} - -/*! - This event handler, for - \l{QEvent::GraphicsSceneResize}{GraphicsSceneResize} events, is - delivered after the widget has been resized (i.e., its local size has - changed). \a event contains both the old and the new size. - - This event is only delivered when the widget is resized locally; calling - setTransform() on the widget or any of its ancestors or view, does not - affect the widget's local size. - - You can reimplement this event handler to detect when your widget has been - resized. Calling QEvent::accept() or QEvent::ignore() on \a event has no - effect. - - \sa geometry(), setGeometry() -*/ -void QGraphicsWidget::resizeEvent(QGraphicsSceneResizeEvent *event) -{ - Q_UNUSED(event); -} - -/*! - This event handler, for \l{QEvent::Show}{Show} events, is delivered before - the widget has been shown, for example, setVisible(true) has been called - for the widget or one of its ancestors when the widget was previously - hidden. - - You can reimplement this event handler to detect when your widget is - shown. Calling QEvent::accept() or QEvent::ignore() on \a event has no - effect. - - \sa hideEvent(), QWidget::showEvent(), ItemVisibleChange -*/ -void QGraphicsWidget::showEvent(QShowEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QGraphicsWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); -} - -/*! - \reimp -*/ -void QGraphicsWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); -} - -/*! - This event handler, for \a event, can be reimplemented in a subclass to - receive notifications for Qt::GrabMouse events. - - \sa grabMouse(), grabKeyboard() -*/ -void QGraphicsWidget::grabMouseEvent(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - This event handler, for \a event, can be reimplemented in a subclass to - receive notifications for Qt::UngrabMouse events. - - \sa ungrabMouse(), ungrabKeyboard() -*/ -void QGraphicsWidget::ungrabMouseEvent(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - This event handler, for \a event, can be reimplemented in a subclass to - receive notifications for Qt::GrabKeyboard events. - - \sa grabKeyboard(), grabMouse() -*/ -void QGraphicsWidget::grabKeyboardEvent(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - This event handler, for \a event, can be reimplemented in a subclass to - receive notifications for Qt::UngrabKeyboard events. - - \sa ungrabKeyboard(), ungrabMouse() -*/ -void QGraphicsWidget::ungrabKeyboardEvent(QEvent *event) -{ - Q_UNUSED(event); -} - -/*! - Returns the widgets window type. - - \sa windowFlags(), isWindow(), isPanel() -*/ -Qt::WindowType QGraphicsWidget::windowType() const -{ - return Qt::WindowType(int(windowFlags()) & Qt::WindowType_Mask); -} - -/*! - \property QGraphicsWidget::windowFlags - \brief the widget's window flags - - Window flags are a combination of a window type (e.g., Qt::Dialog) and - several flags giving hints on the behavior of the window. The behavior - is platform-dependent. - - By default, this property contains no window flags. - - Windows are panels. If you set the Qt::Window flag, the ItemIsPanel flag - will be set automatically. If you clear the Qt::Window flag, the - ItemIsPanel flag is also cleared. Note that the ItemIsPanel flag can be - set independently of Qt::Window. - - \sa isWindow(), isPanel() -*/ -Qt::WindowFlags QGraphicsWidget::windowFlags() const -{ - Q_D(const QGraphicsWidget); - return d->windowFlags; -} -void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags) -{ - Q_D(QGraphicsWidget); - if (d->windowFlags == wFlags) - return; - bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup; - - d->adjustWindowFlags(&wFlags); - d->windowFlags = wFlags; - if (!d->setWindowFrameMargins) - unsetWindowFrameMargins(); - - setFlag(ItemIsPanel, d->windowFlags & Qt::Window); - - bool isPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup; - if (d->scene && isVisible() && wasPopup != isPopup) { - // Popup state changed; update implicit mouse grab. - if (!isPopup) - d->scene->d_func()->removePopup(this); - else - d->scene->d_func()->addPopup(this); - } - - if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) { - d->scene->d_func()->allItemsIgnoreHoverEvents = false; - d->scene->d_func()->enableMouseTrackingOnViews(); - } -} - -/*! - Returns true if this widget's window is in the active window, or if the - widget does not have a window but is in an active scene (i.e., a scene - that currently has focus). - - The active window is the window that either contains a child widget that - currently has input focus, or that itself has input focus. - - \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow(), isActive() -*/ -bool QGraphicsWidget::isActiveWindow() const -{ - return isActive(); -} - -/*! - \property QGraphicsWidget::windowTitle - \brief This property holds the window title (caption). - - This property is only used for windows. - - By default, if no title has been set, this property contains an - empty string. -*/ -void QGraphicsWidget::setWindowTitle(const QString &title) -{ - Q_D(QGraphicsWidget); - d->ensureWindowData(); - d->windowData->windowTitle = title; -} -QString QGraphicsWidget::windowTitle() const -{ - Q_D(const QGraphicsWidget); - return d->windowData ? d->windowData->windowTitle : QString(); -} - -/*! - \property QGraphicsWidget::focusPolicy - \brief the way the widget accepts keyboard focus - - The focus policy is Qt::TabFocus if the widget accepts keyboard focus by - tabbing, Qt::ClickFocus if the widget accepts focus by clicking, - Qt::StrongFocus if it accepts both, and Qt::NoFocus (the default) if it - does not accept focus at all. - - You must enable keyboard focus for a widget if it processes keyboard - events. This is normally done from the widget's constructor. For instance, - the QLineEdit constructor calls setFocusPolicy(Qt::StrongFocus). - - If you enable a focus policy (i.e., not Qt::NoFocus), QGraphicsWidget will - automatically enable the ItemIsFocusable flag. Setting Qt::NoFocus on a - widget will clear the ItemIsFocusable flag. If the widget currently has - keyboard focus, the widget will automatically lose focus. - - \sa focusInEvent(), focusOutEvent(), keyPressEvent(), keyReleaseEvent(), enabled -*/ -Qt::FocusPolicy QGraphicsWidget::focusPolicy() const -{ - Q_D(const QGraphicsWidget); - return d->focusPolicy; -} -void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy) -{ - Q_D(QGraphicsWidget); - if (d->focusPolicy == policy) - return; - d->focusPolicy = policy; - if (hasFocus() && policy == Qt::NoFocus) - clearFocus(); - setFlag(ItemIsFocusable, policy != Qt::NoFocus); -} - -/*! - If this widget, a child or descendant of this widget currently has input - focus, this function will return a pointer to that widget. If - no descendant widget has input focus, 0 is returned. - - \sa QGraphicsItem::focusItem(), QWidget::focusWidget() -*/ -QGraphicsWidget *QGraphicsWidget::focusWidget() const -{ - Q_D(const QGraphicsWidget); - if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget) - return static_cast<QGraphicsWidget *>(d->subFocusItem); - return 0; -} - -#ifndef QT_NO_SHORTCUT -/*! - \since 4.5 - - Adds a shortcut to Qt's shortcut system that watches for the given key \a - sequence in the given \a context. If the \a context is - Qt::ApplicationShortcut, the shortcut applies to the application as a - whole. Otherwise, it is either local to this widget, Qt::WidgetShortcut, - or to the window itself, Qt::WindowShortcut. For widgets that are not part - of a window (i.e., top-level widgets and their children), - Qt::WindowShortcut shortcuts apply to the scene. - - If the same key \a sequence has been grabbed by several widgets, - when the key \a sequence occurs a QEvent::Shortcut event is sent - to all the widgets to which it applies in a non-deterministic - order, but with the ``ambiguous'' flag set to true. - - \warning You should not normally need to use this function; - instead create \l{QAction}s with the shortcut key sequences you - require (if you also want equivalent menu options and toolbar - buttons), or create \l{QShortcut}s if you just need key sequences. - Both QAction and QShortcut handle all the event filtering for you, - and provide signals which are triggered when the user triggers the - key sequence, so are much easier to use than this low-level - function. - - \sa releaseShortcut() setShortcutEnabled() QWidget::grabShortcut() -*/ -int QGraphicsWidget::grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context) -{ - Q_ASSERT(qApp); - if (sequence.isEmpty()) - return 0; - // ### setAttribute(Qt::WA_GrabbedShortcut); - return qApp->d_func()->shortcutMap.addShortcut(this, sequence, context); -} - -/*! - \since 4.5 - - Removes the shortcut with the given \a id from Qt's shortcut - system. The widget will no longer receive QEvent::Shortcut events - for the shortcut's key sequence (unless it has other shortcuts - with the same key sequence). - - \warning You should not normally need to use this function since - Qt's shortcut system removes shortcuts automatically when their - parent widget is destroyed. It is best to use QAction or - QShortcut to handle shortcuts, since they are easier to use than - this low-level function. Note also that this is an expensive - operation. - - \sa grabShortcut() setShortcutEnabled() , QWidget::releaseShortcut() -*/ -void QGraphicsWidget::releaseShortcut(int id) -{ - Q_ASSERT(qApp); - if (id) - qApp->d_func()->shortcutMap.removeShortcut(id, this, 0); -} - -/*! - \since 4.5 - - If \a enabled is true, the shortcut with the given \a id is - enabled; otherwise the shortcut is disabled. - - \warning You should not normally need to use this function since - Qt's shortcut system enables/disables shortcuts automatically as - widgets become hidden/visible and gain or lose focus. It is best - to use QAction or QShortcut to handle shortcuts, since they are - easier to use than this low-level function. - - \sa grabShortcut() releaseShortcut(), QWidget::setShortcutEnabled() -*/ -void QGraphicsWidget::setShortcutEnabled(int id, bool enabled) -{ - Q_ASSERT(qApp); - if (id) - qApp->d_func()->shortcutMap.setShortcutEnabled(enabled, id, this, 0); -} - -/*! - \since 4.5 - - If \a enabled is true, auto repeat of the shortcut with the - given \a id is enabled; otherwise it is disabled. - - \sa grabShortcut() releaseShortcut() QWidget::setShortcutAutoRepeat() -*/ -void QGraphicsWidget::setShortcutAutoRepeat(int id, bool enabled) -{ - Q_ASSERT(qApp); - if (id) - qApp->d_func()->shortcutMap.setShortcutAutoRepeat(enabled, id, this, 0); -} -#endif - -#ifndef QT_NO_ACTION -/*! - \since 4.5 - - Appends the action \a action to this widget's list of actions. - - All QGraphicsWidgets have a list of \l{QAction}s, however they can be - represented graphically in many different ways. The default use of the - QAction list (as returned by actions()) is to create a context QMenu. - - A QGraphicsWidget should only have one of each action and adding an action - it already has will not cause the same action to be in the widget twice. - - \sa removeAction(), insertAction(), actions(), QWidget::addAction() -*/ -void QGraphicsWidget::addAction(QAction *action) -{ - insertAction(0, action); -} - -/*! - \since 4.5 - - Appends the actions \a actions to this widget's list of actions. - - \sa removeAction(), QMenu, addAction(), QWidget::addActions() -*/ -void QGraphicsWidget::addActions(QList<QAction *> actions) -{ - for (int i = 0; i < actions.count(); ++i) - insertAction(0, actions.at(i)); -} - -/*! - \since 4.5 - - Inserts the action \a action to this widget's list of actions, - before the action \a before. It appends the action if \a before is 0 or - \a before is not a valid action for this widget. - - A QGraphicsWidget should only have one of each action. - - \sa removeAction(), addAction(), QMenu, actions(), - QWidget::insertActions() -*/ -void QGraphicsWidget::insertAction(QAction *before, QAction *action) -{ - if (!action) { - qWarning("QWidget::insertAction: Attempt to insert null action"); - return; - } - - Q_D(QGraphicsWidget); - int index = d->actions.indexOf(action); - if (index != -1) - d->actions.removeAt(index); - - int pos = d->actions.indexOf(before); - if (pos < 0) { - before = 0; - pos = d->actions.size(); - } - d->actions.insert(pos, action); - - if (index == -1) { - QActionPrivate *apriv = action->d_func(); - apriv->graphicsWidgets.append(this); - } - - QActionEvent e(QEvent::ActionAdded, action, before); - QApplication::sendEvent(this, &e); -} - -/*! - \since 4.5 - - Inserts the actions \a actions to this widget's list of actions, - before the action \a before. It appends the action if \a before is 0 or - \a before is not a valid action for this widget. - - A QGraphicsWidget can have at most one of each action. - - \sa removeAction(), QMenu, insertAction(), QWidget::insertActions() -*/ -void QGraphicsWidget::insertActions(QAction *before, QList<QAction *> actions) -{ - for (int i = 0; i < actions.count(); ++i) - insertAction(before, actions.at(i)); -} - -/*! - \since 4.5 - - Removes the action \a action from this widget's list of actions. - - \sa insertAction(), actions(), insertAction(), QWidget::removeAction() -*/ -void QGraphicsWidget::removeAction(QAction *action) -{ - if (!action) - return; - - Q_D(QGraphicsWidget); - - QActionPrivate *apriv = action->d_func(); - apriv->graphicsWidgets.removeAll(this); - - if (d->actions.removeAll(action)) { - QActionEvent e(QEvent::ActionRemoved, action); - QApplication::sendEvent(this, &e); - } -} - -/*! - \since 4.5 - - Returns the (possibly empty) list of this widget's actions. - - \sa insertAction(), removeAction(), QWidget::actions(), - QAction::associatedWidgets(), QAction::associatedGraphicsWidgets() -*/ -QList<QAction *> QGraphicsWidget::actions() const -{ - Q_D(const QGraphicsWidget); - return d->actions; -} -#endif - -/*! - Moves the \a second widget around the ring of focus widgets so that - keyboard focus moves from the \a first widget to the \a second widget when - the Tab key is pressed. - - Note that since the tab order of the \a second widget is changed, you - should order a chain like this: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicswidget.cpp 1 - - \e not like this: - - \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicswidget.cpp 2 - - If \a first is 0, this indicates that \a second should be the first widget - to receive input focus should the scene gain Tab focus (i.e., the user - hits Tab so that focus passes into the scene). If \a second is 0, this - indicates that \a first should be the first widget to gain focus if the - scene gained BackTab focus. - - By default, tab order is defined implicitly using widget creation order. - - \sa focusPolicy, {Keyboard Focus} -*/ -void QGraphicsWidget::setTabOrder(QGraphicsWidget *first, QGraphicsWidget *second) -{ - if (!first && !second) { - qWarning("QGraphicsWidget::setTabOrder(0, 0) is undefined"); - return; - } - if ((first && second) && first->scene() != second->scene()) { - qWarning("QGraphicsWidget::setTabOrder: scenes %p and %p are different", - first->scene(), second->scene()); - return; - } - QGraphicsScene *scene = first ? first->scene() : second->scene(); - if (!scene && (!first || !second)) { - qWarning("QGraphicsWidget::setTabOrder: assigning tab order from/to the" - " scene requires the item to be in a scene."); - return; - } - - // If either first or second are 0, the scene's tabFocusFirst is updated - // to point to the first item in the scene's focus chain. Then first or - // second are set to point to tabFocusFirst. - QGraphicsScenePrivate *sceneD = scene->d_func(); - if (!first) { - sceneD->tabFocusFirst = second; - return; - } - if (!second) { - sceneD->tabFocusFirst = first->d_func()->focusNext; - return; - } - - // Both first and second are != 0. - QGraphicsWidget *firstFocusNext = first->d_func()->focusNext; - if (firstFocusNext == second) { - // Nothing to do. - return; - } - - // Update the focus chain. - QGraphicsWidget *secondFocusPrev = second->d_func()->focusPrev; - QGraphicsWidget *secondFocusNext = second->d_func()->focusNext; - firstFocusNext->d_func()->focusPrev = second; - first->d_func()->focusNext = second; - second->d_func()->focusNext = firstFocusNext; - second->d_func()->focusPrev = first; - secondFocusPrev->d_func()->focusNext = secondFocusNext; - secondFocusNext->d_func()->focusPrev = secondFocusPrev; - - Q_ASSERT(first->d_func()->focusNext->d_func()->focusPrev == first); - Q_ASSERT(first->d_func()->focusPrev->d_func()->focusNext == first); - - Q_ASSERT(second->d_func()->focusNext->d_func()->focusPrev == second); - Q_ASSERT(second->d_func()->focusPrev->d_func()->focusNext == second); - -} - -/*! - If \a on is true, this function enables \a attribute; otherwise - \a attribute is disabled. - - See the class documentation for QGraphicsWidget for a complete list of - which attributes are supported, and what they are for. - - \sa testAttribute(), QWidget::setAttribute() -*/ -void QGraphicsWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) -{ - Q_D(QGraphicsWidget); - // ### most flags require some immediate action - // ### we might want to qWarn use of unsupported attributes - // ### we might want to not use Qt::WidgetAttribute, but roll our own instead - d->setAttribute(attribute, on); -} - -/*! - Returns true if \a attribute is enabled for this widget; otherwise, - returns false. - - \sa setAttribute() -*/ -bool QGraphicsWidget::testAttribute(Qt::WidgetAttribute attribute) const -{ - Q_D(const QGraphicsWidget); - return d->testAttribute(attribute); -} - -/*! - \reimp -*/ -int QGraphicsWidget::type() const -{ - return Type; -} - -/*! - \reimp -*/ -void QGraphicsWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - Q_UNUSED(painter); - Q_UNUSED(option); - Q_UNUSED(widget); -} - -/*! - This virtual function is called by QGraphicsScene to draw the window frame - for windows using \a painter, \a option, and \a widget, in local - coordinates. The base implementation uses the current style to render the - frame and title bar. - - You can reimplement this function in a subclass of QGraphicsWidget to - provide custom rendering of the widget's window frame. - - \sa QGraphicsItem::paint() -*/ -void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) -{ - const bool fillBackground = !testAttribute(Qt::WA_OpaquePaintEvent) - && !testAttribute(Qt::WA_NoSystemBackground); - QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(this); - const bool embeddedWidgetFillsOwnBackground = proxy && proxy->widget(); - - if (rect().contains(option->exposedRect)) { - if (fillBackground && !embeddedWidgetFillsOwnBackground) - painter->fillRect(option->exposedRect, palette().window()); - return; - } - - Q_D(QGraphicsWidget); - - QRect windowFrameRect = QRect(QPoint(), windowFrameGeometry().size().toSize()); - QStyleOptionTitleBar bar; - bar.QStyleOption::operator=(*option); - d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state - d->ensureWindowData(); - if (d->windowData->buttonMouseOver) - bar.state |= QStyle::State_MouseOver; - else - bar.state &= ~QStyle::State_MouseOver; - if (d->windowData->buttonSunken) - bar.state |= QStyle::State_Sunken; - else - bar.state &= ~QStyle::State_Sunken; - - bar.rect = windowFrameRect; - - // translate painter to make the style happy - const QPointF styleOrigin = this->windowFrameRect().topLeft(); - painter->translate(styleOrigin); - -#ifdef Q_WS_MAC - const QSize pixmapSize = windowFrameRect.size(); - if (pixmapSize.width() <= 0 || pixmapSize.height() <= 0) - return; - QPainter *realPainter = painter; - QPixmap pm(pixmapSize); - painter = new QPainter(&pm); -#endif - - // Fill background - QStyleHintReturnMask mask; - bool setMask = style()->styleHint(QStyle::SH_WindowFrame_Mask, &bar, widget, &mask) && !mask.region.isEmpty(); - bool hasBorder = !style()->styleHint(QStyle::SH_TitleBar_NoBorder, &bar, widget); - int frameWidth = style()->pixelMetric(QStyle::PM_MDIFrameWidth, &bar, widget); - if (setMask) { - painter->save(); - painter->setClipRegion(mask.region, Qt::IntersectClip); - } - if (fillBackground) { - if (embeddedWidgetFillsOwnBackground) { - // Don't fill the background twice. - QPainterPath windowFrameBackground; - windowFrameBackground.addRect(windowFrameRect); - // Adjust with 0.5 to avoid border artifacts between - // widget background and frame background. - windowFrameBackground.addRect(rect().translated(-styleOrigin).adjusted(0.5, 0.5, -0.5, -0.5)); - painter->fillPath(windowFrameBackground, palette().window()); - } else { - painter->fillRect(windowFrameRect, palette().window()); - } - } - painter->setRenderHint(QPainter::NonCosmeticDefaultPen); - - // Draw title - int height = (int)d->titleBarHeight(bar); - bar.rect.setHeight(height); - if (hasBorder) // Frame is painted by PE_FrameWindow - bar.rect.adjust(frameWidth, frameWidth, -frameWidth, 0); - - painter->save(); - painter->setFont(QApplication::font("QWorkspaceTitleBar")); - style()->drawComplexControl(QStyle::CC_TitleBar, &bar, painter, widget); - painter->restore(); - if (setMask) - painter->restore(); - // Draw window frame - QStyleOptionFrame frameOptions; - frameOptions.QStyleOption::operator=(*option); - initStyleOption(&frameOptions); - if (!hasBorder) - painter->setClipRect(windowFrameRect.adjusted(0, +height, 0, 0), Qt::IntersectClip); - if (hasFocus()) { - frameOptions.state |= QStyle::State_HasFocus; - } else { - frameOptions.state &= ~QStyle::State_HasFocus; - } - bool isActive = isActiveWindow(); - if (isActive) { - frameOptions.state |= QStyle::State_Active; - } else { - frameOptions.state &= ~QStyle::State_Active; - } - - frameOptions.palette.setCurrentColorGroup(isActive ? QPalette::Active : QPalette::Normal); - frameOptions.rect = windowFrameRect; - frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, widget); - frameOptions.midLineWidth = 1; - style()->drawPrimitive(QStyle::PE_FrameWindow, &frameOptions, painter, widget); - -#ifdef Q_WS_MAC - realPainter->drawPixmap(QPoint(), pm); - delete painter; -#endif -} - -/*! - \reimp -*/ -QRectF QGraphicsWidget::boundingRect() const -{ - return windowFrameRect(); -} - -/*! - \reimp -*/ -QPainterPath QGraphicsWidget::shape() const -{ - QPainterPath path; - path.addRect(rect()); - return path; -} - -/*! - Call this function to close the widget. - - Returns true if the widget was closed; otherwise returns false. - This slot will first send a QCloseEvent to the widget, which may or may - not accept the event. If the event was ignored, nothing happens. If the - event was accepted, it will hide() the widget. - - If the widget has the Qt::WA_DeleteOnClose attribute set it will be - deleted. -*/ -bool QGraphicsWidget::close() -{ - QCloseEvent closeEvent; - QApplication::sendEvent(this, &closeEvent); - if (!closeEvent.isAccepted()) { - return false; - } - // hide - if (isVisible()) { - hide(); - } - if (testAttribute(Qt::WA_DeleteOnClose)) { - deleteLater(); - } - return true; -} - -#ifdef Q_NO_USING_KEYWORD -/*! - \fn const QObjectList &QGraphicsWidget::children() const - \internal - - This function returns the same value as QObject::children(). It's - provided to differentiate between the obsolete member - QGraphicsItem::children() and QObject::children(). QGraphicsItem now - provides childItems() instead. -*/ -#endif - -#if 0 -void QGraphicsWidget::dumpFocusChain() -{ - qDebug() << "=========== Dumping focus chain =============="; - int i = 0; - QGraphicsWidget *next = this; - QSet<QGraphicsWidget*> visited; - do { - if (!next) { - qWarning("Found a focus chain that is not circular, (next == 0)"); - break; - } - qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? '1' : '0') << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0); - if (visited.contains(next)) { - qWarning("Already visited this node. However, I expected to dump until I found myself."); - break; - } - visited << next; - next = next->d_func()->focusNext; - } while (next != this); -} -#endif - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h deleted file mode 100644 index 063be2d102..0000000000 --- a/src/gui/graphicsview/qgraphicswidget.h +++ /dev/null @@ -1,257 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSWIDGET_H -#define QGRAPHICSWIDGET_H - -#include <QtGui/qfont.h> -#include <QtGui/qgraphicslayoutitem.h> -#include <QtGui/qgraphicsitem.h> -#include <QtGui/qpalette.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QFont; -class QFontMetrics; -class QGraphicsLayout; -class QGraphicsSceneMoveEvent; -class QGraphicsWidgetPrivate; -class QGraphicsSceneResizeEvent; -class QStyle; -class QStyleOption; - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsWidgetPrivate; - -class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem -{ - Q_OBJECT - Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem) - Q_PROPERTY(QPalette palette READ palette WRITE setPalette) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) - Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY geometryChanged) - Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize) - Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize) - Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize) - Q_PROPERTY(QSizePolicy sizePolicy READ sizePolicy WRITE setSizePolicy) - Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy) - Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags) - Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) - Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged) - Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground) - Q_PROPERTY(QGraphicsLayout* layout READ layout WRITE setLayout NOTIFY layoutChanged) -public: - QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); - ~QGraphicsWidget(); - QGraphicsLayout *layout() const; - void setLayout(QGraphicsLayout *layout); - void adjustSize(); - - Qt::LayoutDirection layoutDirection() const; - void setLayoutDirection(Qt::LayoutDirection direction); - void unsetLayoutDirection(); - - QStyle *style() const; - void setStyle(QStyle *style); - - QFont font() const; - void setFont(const QFont &font); - - QPalette palette() const; - void setPalette(const QPalette &palette); - - bool autoFillBackground() const; - void setAutoFillBackground(bool enabled); - - void resize(const QSizeF &size); - inline void resize(qreal w, qreal h) { resize(QSizeF(w, h)); } - QSizeF size() const; - - void setGeometry(const QRectF &rect); - inline void setGeometry(qreal x, qreal y, qreal w, qreal h); - inline QRectF rect() const { return QRectF(QPointF(), size()); } - - void setContentsMargins(qreal left, qreal top, qreal right, qreal bottom); - void getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const; - - void setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom); - void getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const; - void unsetWindowFrameMargins(); - QRectF windowFrameGeometry() const; - QRectF windowFrameRect() const; - - // Window handling - Qt::WindowFlags windowFlags() const; - Qt::WindowType windowType() const; - void setWindowFlags(Qt::WindowFlags wFlags); - bool isActiveWindow() const; - void setWindowTitle(const QString &title); - QString windowTitle() const; - - // Focus handling - Qt::FocusPolicy focusPolicy() const; - void setFocusPolicy(Qt::FocusPolicy policy); - static void setTabOrder(QGraphicsWidget *first, QGraphicsWidget *second); - QGraphicsWidget *focusWidget() const; - -#ifndef QT_NO_SHORTCUT - int grabShortcut(const QKeySequence &sequence, Qt::ShortcutContext context = Qt::WindowShortcut); - void releaseShortcut(int id); - void setShortcutEnabled(int id, bool enabled = true); - void setShortcutAutoRepeat(int id, bool enabled = true); -#endif - -#ifndef QT_NO_ACTION - //actions - void addAction(QAction *action); - void addActions(QList<QAction*> actions); - void insertAction(QAction *before, QAction *action); - void insertActions(QAction *before, QList<QAction*> actions); - void removeAction(QAction *action); - QList<QAction*> actions() const; -#endif - - void setAttribute(Qt::WidgetAttribute attribute, bool on = true); - bool testAttribute(Qt::WidgetAttribute attribute) const; - - enum { - Type = 11 - }; - int type() const; - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - QRectF boundingRect() const; - QPainterPath shape() const; - -#if 0 - void dumpFocusChain(); -#endif - - // ### Qt 5: Disambiguate -#ifdef Q_NO_USING_KEYWORD - const QObjectList &children() const { return QObject::children(); } -#else - using QObject::children; -#endif - -Q_SIGNALS: - void geometryChanged(); - void layoutChanged(); - -public Q_SLOTS: - bool close(); - -protected: - virtual void initStyleOption(QStyleOption *option) const; - - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - void updateGeometry(); - - // Notification - QVariant itemChange(GraphicsItemChange change, const QVariant &value); - virtual QVariant propertyChange(const QString &propertyName, const QVariant &value); - - // Scene events - bool sceneEvent(QEvent *event); - virtual bool windowFrameEvent(QEvent *e); - virtual Qt::WindowFrameSection windowFrameSectionAt(const QPointF& pos) const; - - // Base event handlers - bool event(QEvent *event); - //virtual void actionEvent(QActionEvent *event); - virtual void changeEvent(QEvent *event); - virtual void closeEvent(QCloseEvent *event); - //void create(WId window = 0, bool initializeWindow = true, bool destroyOldWindow = true); - //void destroy(bool destroyWindow = true, bool destroySubWindows = true); - void focusInEvent(QFocusEvent *event); - virtual bool focusNextPrevChild(bool next); - void focusOutEvent(QFocusEvent *event); - virtual void hideEvent(QHideEvent *event); - //virtual bool macEvent(EventHandlerCallRef caller, EventRef event); - //virtual int metric(PaintDeviceMetric m ) const; - virtual void moveEvent(QGraphicsSceneMoveEvent *event); - virtual void polishEvent(); - //virtual bool qwsEvent(QWSEvent *event); - //void resetInputContext (); - virtual void resizeEvent(QGraphicsSceneResizeEvent *event); - virtual void showEvent(QShowEvent *event); - //virtual void tabletEvent(QTabletEvent *event); - //virtual bool winEvent(MSG *message, long *result); - //virtual bool x11Event(XEvent *event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - virtual void grabMouseEvent(QEvent *event); - virtual void ungrabMouseEvent(QEvent *event); - virtual void grabKeyboardEvent(QEvent *event); - virtual void ungrabKeyboardEvent(QEvent *event); - QGraphicsWidget(QGraphicsWidgetPrivate &, QGraphicsItem *parent, QGraphicsScene *, Qt::WindowFlags wFlags = 0); - -private: - Q_DISABLE_COPY(QGraphicsWidget) - Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsWidget) - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; - friend class QGraphicsView; - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - friend class QGraphicsLayout; - friend class QWidget; - friend class QApplication; -}; - -inline void QGraphicsWidget::setGeometry(qreal ax, qreal ay, qreal aw, qreal ah) -{ setGeometry(QRectF(ax, ay, aw, ah)); } - -#endif - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif - diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp deleted file mode 100644 index 8649dec29a..0000000000 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ /dev/null @@ -1,906 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include <QtCore/qdebug.h> -#include <QtCore/qnumeric.h> -#include "qgraphicswidget_p.h" -#include "qgraphicslayoutitem_p.h" -#include "qgraphicslayout.h" -#include "qgraphicsscene_p.h" -#include <QtGui/qapplication.h> -#include <QtGui/qgraphicsscene.h> -#include <QtGui/qstyleoption.h> -#include <QtGui/QStyleOptionTitleBar> -#include <QtGui/QGraphicsSceneMouseEvent> -#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) -# include <QMacStyle> -#endif - -QT_BEGIN_NAMESPACE - -void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags) -{ - Q_Q(QGraphicsWidget); - - attributes = 0; - isWidget = 1; // QGraphicsItem::isWidget() returns true. - focusNext = focusPrev = q; - focusPolicy = Qt::NoFocus; - - adjustWindowFlags(&wFlags); - windowFlags = wFlags; - - if (parentItem) - setParentItemHelper(parentItem, 0, 0); - - q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType)); - q->setGraphicsItem(q); - - resolveLayoutDirection(); - q->unsetWindowFrameMargins(); - flags |= QGraphicsItem::ItemUsesExtendedStyleOption; - flags |= QGraphicsItem::ItemSendsGeometryChanges; - if (windowFlags & Qt::Window) - flags |= QGraphicsItem::ItemIsPanel; -} - -qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const -{ - Q_Q(const QGraphicsWidget); - int height = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options); -#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) - if (qobject_cast<QMacStyle*>(q->style())) { - height -=4; - } -#endif - return (qreal)height; -} - -/*! - \internal -*/ -QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate() -{ - // Remove any lazily allocated data - delete[] margins; - delete[] windowFrameMargins; - delete windowData; -} - -/*! - \internal - - Ensures that margins is allocated. - This function must be called before any dereferencing. -*/ -void QGraphicsWidgetPrivate::ensureMargins() const -{ - if (!margins) { - margins = new qreal[4]; - for (int i = 0; i < 4; ++i) - margins[i] = 0; - } -} - -/*! - \internal - - Ensures that windowFrameMargins is allocated. - This function must be called before any dereferencing. -*/ -void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const -{ - if (!windowFrameMargins) { - windowFrameMargins = new qreal[4]; - for (int i = 0; i < 4; ++i) - windowFrameMargins[i] = 0; - } -} - -/*! - \internal - - Ensures that windowData is allocated. - This function must be called before any dereferencing. -*/ -void QGraphicsWidgetPrivate::ensureWindowData() -{ - if (!windowData) - windowData = new WindowData; -} - -void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette) -{ - if (this->palette == palette && this->palette.resolve() == palette.resolve()) - return; - updatePalette(palette); -} - -void QGraphicsWidgetPrivate::resolvePalette(uint inheritedMask) -{ - inheritedPaletteResolveMask = inheritedMask; - QPalette naturalPalette = naturalWidgetPalette(); - QPalette resolvedPalette = palette.resolve(naturalPalette); - updatePalette(resolvedPalette); -} - -void QGraphicsWidgetPrivate::updatePalette(const QPalette &palette) -{ - Q_Q(QGraphicsWidget); - // Update local palette setting. - this->palette = palette; - - // Calculate new mask. - if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) - inheritedPaletteResolveMask = 0; - int mask = palette.resolve() | inheritedPaletteResolveMask; - - // Propagate to children. - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->isWidget()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item); - if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) - w->d_func()->resolvePalette(mask); - } else { - item->d_ptr->resolvePalette(mask); - } - } - - // Notify change. - QEvent event(QEvent::PaletteChange); - QApplication::sendEvent(q, &event); -} - -void QGraphicsWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction) -{ - Q_Q(QGraphicsWidget); - if ((direction == Qt::RightToLeft) == (testAttribute(Qt::WA_RightToLeft))) - return; - q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft)); - - // Propagate this change to all children. - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->isWidget()) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); - if (widget->parentWidget() && !widget->testAttribute(Qt::WA_SetLayoutDirection)) - widget->d_func()->setLayoutDirection_helper(direction); - } - } - - // Send the notification event to this widget item. - QEvent e(QEvent::LayoutDirectionChange); - QApplication::sendEvent(q, &e); -} - -void QGraphicsWidgetPrivate::resolveLayoutDirection() -{ - Q_Q(QGraphicsWidget); - if (q->testAttribute(Qt::WA_SetLayoutDirection)) { - return; - } - if (QGraphicsWidget *parentWidget = q->parentWidget()) { - setLayoutDirection_helper(parentWidget->layoutDirection()); - } else if (scene) { - // ### shouldn't the scene have a layoutdirection really? how does - // ### QGraphicsWidget get changes from QApplication::layoutDirection? - setLayoutDirection_helper(QApplication::layoutDirection()); - } else { - setLayoutDirection_helper(QApplication::layoutDirection()); - } -} - -QPalette QGraphicsWidgetPrivate::naturalWidgetPalette() const -{ - Q_Q(const QGraphicsWidget); - QPalette palette; - if (QGraphicsWidget *parent = q->parentWidget()) { - palette = parent->palette(); - } else if (scene) { - palette = scene->palette(); - } - palette.resolve(0); - return palette; -} - -void QGraphicsWidgetPrivate::setFont_helper(const QFont &font) -{ - if (this->font == font && this->font.resolve() == font.resolve()) - return; - updateFont(font); -} - -void QGraphicsWidgetPrivate::resolveFont(uint inheritedMask) -{ - Q_Q(QGraphicsWidget); - inheritedFontResolveMask = inheritedMask; - if (QGraphicsWidget *p = q->parentWidget()) - inheritedFontResolveMask |= p->d_func()->inheritedFontResolveMask; - QFont naturalFont = naturalWidgetFont(); - QFont resolvedFont = font.resolve(naturalFont); - updateFont(resolvedFont); -} - -void QGraphicsWidgetPrivate::updateFont(const QFont &font) -{ - Q_Q(QGraphicsWidget); - // Update the local font setting. - this->font = font; - - // Calculate new mask. - if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) - inheritedFontResolveMask = 0; - int mask = font.resolve() | inheritedFontResolveMask; - - // Propagate to children. - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->isWidget()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item); - if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) - w->d_func()->resolveFont(mask); - } else { - item->d_ptr->resolveFont(mask); - } - } - - if (!polished) - return; - // Notify change. - QEvent event(QEvent::FontChange); - QApplication::sendEvent(q, &event); -} - -QFont QGraphicsWidgetPrivate::naturalWidgetFont() const -{ - Q_Q(const QGraphicsWidget); - QFont naturalFont; // ### no application font support - if (QGraphicsWidget *parent = q->parentWidget()) { - naturalFont = parent->font(); - } else if (scene) { - naturalFont = scene->font(); - } - naturalFont.resolve(0); - return naturalFont; -} - -void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *option) -{ - Q_Q(QGraphicsWidget); - ensureWindowData(); - q->initStyleOption(option); - option->rect.setHeight(titleBarHeight(*option)); - option->titleBarFlags = windowFlags; - option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu; - option->activeSubControls = windowData->hoveredSubControl; - bool isActive = q->isActiveWindow(); - if (isActive) { - option->state |= QStyle::State_Active; - option->titleBarState = Qt::WindowActive; - option->titleBarState |= QStyle::State_Active; - } else { - option->state &= ~QStyle::State_Active; - option->titleBarState = Qt::WindowNoState; - } - QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar"); - QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0); - option->text = QFontMetrics(windowTitleFont).elidedText( - windowData->windowTitle, Qt::ElideRight, textRect.width()); -} - -void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags) -{ - bool customize = (*flags & (Qt::CustomizeWindowHint - | Qt::FramelessWindowHint - | Qt::WindowTitleHint - | Qt::WindowSystemMenuHint - | Qt::WindowMinimizeButtonHint - | Qt::WindowMaximizeButtonHint - | Qt::WindowContextHelpButtonHint)); - - uint type = (*flags & Qt::WindowType_Mask); - if (customize) - ; - else if (type == Qt::Dialog || type == Qt::Sheet) - *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint; - else if (type == Qt::Tool) - *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint; - else if (type == Qt::Window || type == Qt::SubWindow) - *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint - | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint; -} - -void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - Q_Q(QGraphicsWidget); - ensureWindowData(); - if (windowData->grabbedSection != Qt::NoSection) { - if (windowData->grabbedSection == Qt::TitleBarArea) { - windowData->buttonSunken = false; - QStyleOptionTitleBar bar; - initStyleOptionTitleBar(&bar); - // make sure that the coordinates (rect and pos) we send to the style are positive. - bar.rect = q->windowFrameRect().toRect(); - bar.rect.moveTo(0,0); - bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar)); - QPointF pos = event->pos(); - if (windowFrameMargins) { - pos.rx() += windowFrameMargins[Left]; - pos.ry() += windowFrameMargins[Top]; - } - bar.subControls = QStyle::SC_TitleBarCloseButton; - if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar, - QStyle::SC_TitleBarCloseButton, - event->widget()).contains(pos.toPoint())) { - q->close(); - } - } - if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons())) - windowData->grabbedSection = Qt::NoSection; - event->accept(); - } -} - -void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent *event) -{ - Q_Q(QGraphicsWidget); - if (event->button() != Qt::LeftButton) - return; - - ensureWindowData(); - windowData->startGeometry = q->geometry(); - windowData->grabbedSection = q->windowFrameSectionAt(event->pos()); - ensureWindowData(); - if (windowData->grabbedSection == Qt::TitleBarArea - && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) { - windowData->buttonSunken = true; - q->update(); - } - event->setAccepted(windowData->grabbedSection != Qt::NoSection); -} - -/*! - Used to calculate the - Precondition: - \a widget should support either hfw or wfh - - If \a heightForWidth is set to false, this function will query the width for height - instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted - as minimum width and maximum width. - */ -static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh, - const QGraphicsWidget *widget, - bool heightForWidth = true) -{ - qreal minimumHeightForWidth = -1; - const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth(); - if (hasHFW == heightForWidth) { - minimumHeightForWidth = hasHFW - ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height() - : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width(); //"width" is here height! - } else { - // widthForHeight - const qreal constraint = width; - while (maxh - minh > 0.1) { - qreal middle = minh + (maxh - minh)/2; - // ### really bad, if we are a widget with a layout it will call - // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call - // sizeHint three times because of how the cache works - qreal hfw = hasHFW - ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height() - : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width(); - if (hfw > constraint) { - minh = middle; - } else if (hfw <= constraint) { - maxh = middle; - } - } - minimumHeightForWidth = maxh; - } - return minimumHeightForWidth; -} - -static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw, - const QGraphicsWidget *widget) -{ - return minimumHeightForWidth(height, minw, maxw, widget, false); -} - -static QSizeF closestAcceptableSize(const QSizeF &proposed, - const QGraphicsWidget *widget) -{ - const QSizeF current = widget->size(); - - qreal minw = proposed.width(); - qreal maxw = current.width(); - qreal minh = proposed.height(); - qreal maxh = current.height(); - - qreal middlew = maxw; - qreal middleh = maxh; - qreal min_hfw; - min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget); - - do { - if (maxw - minw < 0.1) { - // we still havent found anything, cut off binary search - minw = maxw; - minh = maxh; - } - middlew = minw + (maxw - minw)/2.0; - middleh = minh + (maxh - minh)/2.0; - - min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget); - - if (min_hfw > middleh) { - minw = middlew; - minh = middleh; - } else if (min_hfw <= middleh) { - maxw = middlew; - maxh = middleh; - } - } while (maxw != minw); - - min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget); - - QSizeF result; - if (min_hfw < maxh) { - result = QSizeF(middlew, min_hfw); - } else { - // Needed because of the cut-off we do above. - result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh); - } - return result; -} - -static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, - QRectF *rect, Qt::WindowFrameSection section, - const QSizeF &min, const QSizeF &max, - const QGraphicsWidget *widget) -{ - const QRectF proposedRect = *rect; - qreal width = qBound(min.width(), proposedRect.width(), max.width()); - qreal height = qBound(min.height(), proposedRect.height(), max.height()); - - const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth(); - const bool hasWFH = QGraphicsLayoutItemPrivate::get(widget)->hasWidthForHeight(); - - const bool widthChanged = proposedRect.width() != widget->size().width(); - const bool heightChanged = proposedRect.height() != widget->size().height(); - - if (hasHFW || hasWFH) { - if (widthChanged || heightChanged) { - qreal minExtent; - qreal maxExtent; - qreal constraint; - qreal proposed; - if (hasHFW) { - minExtent = min.height(); - maxExtent = max.height(); - constraint = width; - proposed = proposedRect.height(); - } else { - // width for height - minExtent = min.width(); - maxExtent = max.width(); - constraint = height; - proposed = proposedRect.width(); - } - if (minimumHeightForWidth(constraint, minExtent, maxExtent, widget, hasHFW) > proposed) { - QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget); - width = effectiveSize.width(); - height = effectiveSize.height(); - } - } - } - - switch (section) { - case Qt::LeftSection: - rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(), - qRound(width), startGeometry.height()); - break; - case Qt::TopLeftSection: - rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height), - qRound(width), qRound(height)); - break; - case Qt::TopSection: - rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height), - startGeometry.width(), qRound(height)); - break; - case Qt::TopRightSection: - rect->setTop(rect->bottom() - qRound(height)); - rect->setWidth(qRound(width)); - break; - case Qt::RightSection: - rect->setWidth(qRound(width)); - break; - case Qt::BottomRightSection: - rect->setWidth(qRound(width)); - rect->setHeight(qRound(height)); - break; - case Qt::BottomSection: - rect->setHeight(qRound(height)); - break; - case Qt::BottomLeftSection: - rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(), - qRound(width), qRound(height)); - break; - default: - break; - } -} - -void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - Q_Q(QGraphicsWidget); - ensureWindowData(); - if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel) - return; - - QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos()); - QLineF parentDelta(q->mapToParent(delta.p1()), q->mapToParent(delta.p2())); - QLineF parentXDelta(q->mapToParent(QPointF(delta.p1().x(), 0)), q->mapToParent(QPointF(delta.p2().x(), 0))); - QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y()))); - - QRectF newGeometry; - switch (windowData->grabbedSection) { - case Qt::LeftSection: - newGeometry = QRectF(windowData->startGeometry.topLeft() - + QPointF(parentXDelta.dx(), parentXDelta.dy()), - windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy())); - break; - case Qt::TopLeftSection: - newGeometry = QRectF(windowData->startGeometry.topLeft() - + QPointF(parentDelta.dx(), parentDelta.dy()), - windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy())); - break; - case Qt::TopSection: - newGeometry = QRectF(windowData->startGeometry.topLeft() - + QPointF(parentYDelta.dx(), parentYDelta.dy()), - windowData->startGeometry.size() - QSizeF(0, delta.dy())); - break; - case Qt::TopRightSection: - newGeometry = QRectF(windowData->startGeometry.topLeft() - + QPointF(parentYDelta.dx(), parentYDelta.dy()), - windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy())); - break; - case Qt::RightSection: - newGeometry = QRectF(windowData->startGeometry.topLeft(), - windowData->startGeometry.size() + QSizeF(delta.dx(), 0)); - break; - case Qt::BottomRightSection: - newGeometry = QRectF(windowData->startGeometry.topLeft(), - windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy())); - break; - case Qt::BottomSection: - newGeometry = QRectF(windowData->startGeometry.topLeft(), - windowData->startGeometry.size() + QSizeF(0, delta.dy())); - break; - case Qt::BottomLeftSection: - newGeometry = QRectF(windowData->startGeometry.topLeft() - + QPointF(parentXDelta.dx(), parentXDelta.dy()), - windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy())); - break; - case Qt::TitleBarArea: - newGeometry = QRectF(windowData->startGeometry.topLeft() - + QPointF(parentDelta.dx(), parentDelta.dy()), - windowData->startGeometry.size()); - break; - case Qt::NoSection: - break; - } - - if (windowData->grabbedSection != Qt::NoSection) { - _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry, - windowData->grabbedSection, - q->effectiveSizeHint(Qt::MinimumSize), - q->effectiveSizeHint(Qt::MaximumSize), - q); - q->setGeometry(newGeometry); - } -} - -void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_Q(QGraphicsWidget); - if (!hasDecoration()) - return; - - ensureWindowData(); - - if (q->rect().contains(event->pos())) { - if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None) - windowFrameHoverLeaveEvent(event); - return; - } - - bool wasMouseOver = windowData->buttonMouseOver; - QRect oldButtonRect = windowData->buttonRect; - windowData->buttonRect = QRect(); - windowData->buttonMouseOver = false; - QPointF pos = event->pos(); - QStyleOptionTitleBar bar; - // make sure that the coordinates (rect and pos) we send to the style are positive. - if (windowFrameMargins) { - pos.rx() += windowFrameMargins[Left]; - pos.ry() += windowFrameMargins[Top]; - } - initStyleOptionTitleBar(&bar); - bar.rect = q->windowFrameRect().toRect(); - bar.rect.moveTo(0,0); - bar.rect.setHeight(int(titleBarHeight(bar))); - - Qt::CursorShape cursorShape = Qt::ArrowCursor; - bool needsSetCursorCall = true; - switch (q->windowFrameSectionAt(event->pos())) { - case Qt::TopLeftSection: - case Qt::BottomRightSection: - cursorShape = Qt::SizeFDiagCursor; - break; - case Qt::TopRightSection: - case Qt::BottomLeftSection: - cursorShape = Qt::SizeBDiagCursor; - break; - case Qt::LeftSection: - case Qt::RightSection: - cursorShape = Qt::SizeHorCursor; - break; - case Qt::TopSection: - case Qt::BottomSection: - cursorShape = Qt::SizeVerCursor; - break; - case Qt::TitleBarArea: - windowData->buttonRect = q->style()->subControlRect( - QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0); -#ifdef Q_WS_MAC - // On mac we should hover if we are in the 'area' of the buttons - windowData->buttonRect |= q->style()->subControlRect( - QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0); - windowData->buttonRect |= q->style()->subControlRect( - QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0); -#endif - if (windowData->buttonRect.contains(pos.toPoint())) - windowData->buttonMouseOver = true; - event->ignore(); - break; - default: - needsSetCursorCall = false; - event->ignore(); - } -#ifndef QT_NO_CURSOR - if (needsSetCursorCall) - q->setCursor(cursorShape); -#endif - // update buttons if we hover over them - windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0); - if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton) - windowData->hoveredSubControl = QStyle::SC_TitleBarLabel; - - if (windowData->buttonMouseOver != wasMouseOver) { - if (!oldButtonRect.isNull()) - q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft())); - if (!windowData->buttonRect.isNull()) - q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft())); - } -} - -void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); - Q_Q(QGraphicsWidget); - if (hasDecoration()) { - // ### restore the cursor, don't override it -#ifndef QT_NO_CURSOR - q->unsetCursor(); -#endif - - ensureWindowData(); - - bool needsUpdate = false; - if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton - || windowData->buttonMouseOver) - needsUpdate = true; - - // update the hover state (of buttons etc...) - windowData->hoveredSubControl = QStyle::SC_None; - windowData->buttonMouseOver = false; - windowData->buttonRect = QRect(); - if (needsUpdate) - q->update(windowData->buttonRect); - } -} - -bool QGraphicsWidgetPrivate::hasDecoration() const -{ - return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint); -} - -/** - * is called after a reparent has taken place to fix up the focus chain(s) - */ -void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene) -{ - Q_Q(QGraphicsWidget); - - Q_ASSERT(focusNext && focusPrev); - - QGraphicsWidget *n = q; //last one in 'new' list - QGraphicsWidget *o = 0; //last one in 'old' list - - QGraphicsWidget *w = focusNext; - - QGraphicsWidget *firstOld = 0; - bool wasPreviousNew = true; - - while (w != q) { - bool isCurrentNew = q->isAncestorOf(w); - if (isCurrentNew) { - if (!wasPreviousNew) { - n->d_func()->focusNext = w; - w->d_func()->focusPrev = n; - } - n = w; - } else /*if (!isCurrentNew)*/ { - if (wasPreviousNew) { - if (o) { - o->d_func()->focusNext = w; - w->d_func()->focusPrev = o; - } else { - firstOld = w; - } - } - o = w; - } - w = w->d_func()->focusNext; - wasPreviousNew = isCurrentNew; - } - - // repair the 'old' chain - if (firstOld) { - o->d_func()->focusNext = firstOld; - firstOld->d_func()->focusPrev = o; - } - - // update tabFocusFirst for oldScene if the item is going to be removed from oldScene - if (newParent) - newScene = newParent->scene(); - - if (oldScene && newScene != oldScene) - oldScene->d_func()->tabFocusFirst = (firstOld && firstOld->scene() == oldScene) ? firstOld : 0; - - QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0; - QGraphicsWidget *topLevel = 0; - if (topLevelItem && topLevelItem->isWidget()) - topLevel = static_cast<QGraphicsWidget *>(topLevelItem); - - if (topLevel && newParent) { - QGraphicsWidget *last = topLevel->d_func()->focusPrev; - // link last with new chain - last->d_func()->focusNext = q; - focusPrev = last; - - // link last in chain with - topLevel->d_func()->focusPrev = n; - n->d_func()->focusNext = topLevel; - } else { - // q is the start of the focus chain - n->d_func()->focusNext = q; - focusPrev = n; - } - -} - -void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l) -{ - delete (this->layout); - layout = l; - if (!l) { - Q_Q(QGraphicsWidget); - q->updateGeometry(); - } -} - -qreal QGraphicsWidgetPrivate::width() const -{ - Q_Q(const QGraphicsWidget); - return q->geometry().width(); -} - -void QGraphicsWidgetPrivate::setWidth(qreal w) -{ - if (qIsNaN(w)) - return; - Q_Q(QGraphicsWidget); - if (q->geometry().width() == w) - return; - - q->setGeometry(QRectF(q->x(), q->y(), w, height())); -} - -void QGraphicsWidgetPrivate::resetWidth() -{ - Q_Q(QGraphicsWidget); - q->setGeometry(QRectF(q->x(), q->y(), 0, height())); -} - -qreal QGraphicsWidgetPrivate::height() const -{ - Q_Q(const QGraphicsWidget); - return q->geometry().height(); -} - -void QGraphicsWidgetPrivate::setHeight(qreal h) -{ - if (qIsNaN(h)) - return; - Q_Q(QGraphicsWidget); - if (q->geometry().height() == h) - return; - - q->setGeometry(QRectF(q->x(), q->y(), width(), h)); -} - -void QGraphicsWidgetPrivate::resetHeight() -{ - Q_Q(QGraphicsWidget); - q->setGeometry(QRectF(q->x(), q->y(), width(), 0)); -} - -void QGraphicsWidgetPrivate::setGeometryFromSetPos() -{ - if (inSetGeometry) - return; - Q_Q(QGraphicsWidget); - inSetPos = 1; - // Ensure setGeometry is called (avoid recursion when setPos is - // called from within setGeometry). - q->setGeometry(QRectF(pos, q->size())); - inSetPos = 0 ; -} - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h deleted file mode 100644 index 398abc33ef..0000000000 --- a/src/gui/graphicsview/qgraphicswidget_p.h +++ /dev/null @@ -1,226 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSWIDGET_P_H -#define QGRAPHICSWIDGET_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qobject_p.h> -#include "qgraphicsitem_p.h" -#include "qgraphicswidget.h" -#include <QtGui/qfont.h> -#include <QtGui/qpalette.h> -#include <QtGui/qsizepolicy.h> -#include <QtGui/qstyle.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsLayout; -class QStyleOptionTitleBar; - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsWidgetPrivate : public QGraphicsItemPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsWidget) -public: - QGraphicsWidgetPrivate() - : margins(0), - layout(0), - inheritedPaletteResolveMask(0), - inheritedFontResolveMask(0), - inSetGeometry(0), - polished(0), - inSetPos(0), - autoFillBackground(0), - focusPolicy(Qt::NoFocus), - focusNext(0), - focusPrev(0), - windowFlags(0), - windowData(0), - setWindowFrameMargins(false), - windowFrameMargins(0) - { } - virtual ~QGraphicsWidgetPrivate(); - - void init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags); - qreal titleBarHeight(const QStyleOptionTitleBar &options) const; - - // Margins - enum {Left, Top, Right, Bottom}; - mutable qreal *margins; - void ensureMargins() const; - - void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene = 0); - void setLayout_helper(QGraphicsLayout *l); - - // Layouts - QGraphicsLayout *layout; - void setLayoutDirection_helper(Qt::LayoutDirection direction); - void resolveLayoutDirection(); - - // Style - QPalette palette; - uint inheritedPaletteResolveMask; - void setPalette_helper(const QPalette &palette); - void resolvePalette(uint inheritedMask); - void updatePalette(const QPalette &palette); - QPalette naturalWidgetPalette() const; - QFont font; - uint inheritedFontResolveMask; - void setFont_helper(const QFont &font); - void resolveFont(uint inheritedMask); - void updateFont(const QFont &font); - QFont naturalWidgetFont() const; - - // Window specific - void initStyleOptionTitleBar(QStyleOptionTitleBar *option); - void adjustWindowFlags(Qt::WindowFlags *wFlags); - void windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event); - void windowFrameMousePressEvent(QGraphicsSceneMouseEvent *event); - void windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event); - void windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent *event); - void windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event); - bool hasDecoration() const; - - // Private Properties - qreal width() const; - void setWidth(qreal); - void resetWidth(); - - qreal height() const; - void setHeight(qreal); - void resetHeight(); - void setGeometryFromSetPos(); - - // State - inline int attributeToBitIndex(Qt::WidgetAttribute att) const - { - int bit = -1; - switch (att) { - case Qt::WA_SetLayoutDirection: bit = 0; break; - case Qt::WA_RightToLeft: bit = 1; break; - case Qt::WA_SetStyle: bit = 2; break; - case Qt::WA_Resized: bit = 3; break; - case Qt::WA_DeleteOnClose: bit = 4; break; - case Qt::WA_NoSystemBackground: bit = 5; break; - case Qt::WA_OpaquePaintEvent: bit = 6; break; - case Qt::WA_SetPalette: bit = 7; break; - case Qt::WA_SetFont: bit = 8; break; - case Qt::WA_WindowPropagation: bit = 9; break; - default: break; - } - return bit; - } - inline void setAttribute(Qt::WidgetAttribute att, bool value) - { - int bit = attributeToBitIndex(att); - if (bit == -1) { - qWarning("QGraphicsWidget::setAttribute: unsupported attribute %d", int(att)); - return; - } - if (value) - attributes |= (1 << bit); - else - attributes &= ~(1 << bit); - } - inline bool testAttribute(Qt::WidgetAttribute att) const - { - int bit = attributeToBitIndex(att); - if (bit == -1) - return false; - return (attributes & (1 << bit)) != 0; - } - quint32 attributes : 10; - quint32 inSetGeometry : 1; - quint32 polished: 1; - quint32 inSetPos : 1; - quint32 autoFillBackground : 1; - - // Focus - Qt::FocusPolicy focusPolicy; - QGraphicsWidget *focusNext; - QGraphicsWidget *focusPrev; - - // Windows - Qt::WindowFlags windowFlags; - struct WindowData { - QString windowTitle; - QStyle::SubControl hoveredSubControl; - Qt::WindowFrameSection grabbedSection; - uint buttonMouseOver : 1; - uint buttonSunken : 1; - QRectF startGeometry; - QRect buttonRect; - WindowData() - : hoveredSubControl(QStyle::SC_None) - , grabbedSection(Qt::NoSection) - , buttonMouseOver(false) - , buttonSunken(false) - {} - } *windowData; - void ensureWindowData(); - - bool setWindowFrameMargins; - mutable qreal *windowFrameMargins; - void ensureWindowFrameMargins() const; - -#ifndef QT_NO_ACTION - QList<QAction *> actions; -#endif -}; - -#endif //!defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -QT_END_NAMESPACE - -#endif //QGRAPHICSWIDGET_P_H - diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp deleted file mode 100644 index 66b4a5b6b4..0000000000 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ /dev/null @@ -1,1742 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qglobal.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include <math.h> - -#include "qgraphicslayoutitem.h" -#include "qgridlayoutengine_p.h" -#include "qstyleoption.h" -#include "qvarlengtharray.h" - -#include <QtDebug> -#include <QtCore/qmath.h> - -QT_BEGIN_NAMESPACE - -template <typename T> -static void insertOrRemoveItems(QVector<T> &items, int index, int delta) -{ - int count = items.count(); - if (index < count) { - if (delta > 0) { - items.insert(index, delta, T()); - } else if (delta < 0) { - items.remove(index, qMin(-delta, count - index)); - } - } -} - -static qreal growthFactorBelowPreferredSize(qreal desired, qreal sumAvailable, qreal sumDesired) -{ - Q_ASSERT(sumDesired != 0.0); - return desired * qPow(sumAvailable / sumDesired, desired / sumDesired); -} - -static qreal fixedDescent(qreal descent, qreal ascent, qreal targetSize) -{ - if (descent < 0.0) - return -1.0; - - Q_ASSERT(descent >= 0.0); - Q_ASSERT(ascent >= 0.0); - Q_ASSERT(targetSize >= ascent + descent); - - qreal extra = targetSize - (ascent + descent); - return descent + (extra / 2.0); -} - -static qreal compare(const QGridLayoutBox &box1, const QGridLayoutBox &box2, int which) -{ - qreal size1 = box1.q_sizes(which); - qreal size2 = box2.q_sizes(which); - - if (which == MaximumSize) { - return size2 - size1; - } else { - return size1 - size2; - } -} - -void QGridLayoutBox::add(const QGridLayoutBox &other, int stretch, qreal spacing) -{ - Q_ASSERT(q_minimumDescent < 0.0); - - q_minimumSize += other.q_minimumSize + spacing; - q_preferredSize += other.q_preferredSize + spacing; - q_maximumSize += ((stretch == 0) ? other.q_preferredSize : other.q_maximumSize) + spacing; -} - -void QGridLayoutBox::combine(const QGridLayoutBox &other) -{ - q_minimumDescent = qMax(q_minimumDescent, other.q_minimumDescent); - q_minimumAscent = qMax(q_minimumAscent, other.q_minimumAscent); - - q_minimumSize = qMax(q_minimumAscent + q_minimumDescent, - qMax(q_minimumSize, other.q_minimumSize)); - qreal maxMax; - if (q_maximumSize == FLT_MAX && other.q_maximumSize != FLT_MAX) - maxMax = other.q_maximumSize; - else if (other.q_maximumSize == FLT_MAX && q_maximumSize != FLT_MAX) - maxMax = q_maximumSize; - else - maxMax = qMax(q_maximumSize, other.q_maximumSize); - - q_maximumSize = qMax(q_minimumSize, maxMax); - q_preferredSize = qBound(q_minimumSize, qMax(q_preferredSize, other.q_preferredSize), - q_maximumSize); -} - -void QGridLayoutBox::normalize() -{ - q_maximumSize = qMax(qreal(0.0), q_maximumSize); - q_minimumSize = qBound(qreal(0.0), q_minimumSize, q_maximumSize); - q_preferredSize = qBound(q_minimumSize, q_preferredSize, q_maximumSize); - q_minimumDescent = qMin(q_minimumDescent, q_minimumSize); - - Q_ASSERT((q_minimumDescent < 0.0) == (q_minimumAscent < 0.0)); -} - -#ifdef QT_DEBUG -void QGridLayoutBox::dump(int indent) const -{ - qDebug("%*sBox (%g <= %g <= %g [%g/%g])", indent, "", q_minimumSize, q_preferredSize, - q_maximumSize, q_minimumAscent, q_minimumDescent); -} -#endif - -bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2) -{ - for (int i = 0; i < NSizes; ++i) { - if (box1.q_sizes(i) != box2.q_sizes(i)) - return false; - } - return box1.q_minimumDescent == box2.q_minimumDescent - && box1.q_minimumAscent == box2.q_minimumAscent; -} - -void QGridLayoutRowData::reset(int count) -{ - ignore.fill(false, count); - boxes.fill(QGridLayoutBox(), count); - multiCellMap.clear(); - stretches.fill(0, count); - spacings.fill(0.0, count); - hasIgnoreFlag = false; -} - -void QGridLayoutRowData::distributeMultiCells(const QGridLayoutRowInfo &rowInfo) -{ - MultiCellMap::const_iterator i = multiCellMap.constBegin(); - for (; i != multiCellMap.constEnd(); ++i) { - int start = i.key().first; - int span = i.key().second; - int end = start + span; - const QGridLayoutBox &box = i.value().q_box; - int stretch = i.value().q_stretch; - - QGridLayoutBox totalBox = this->totalBox(start, end); - QVarLengthArray<QGridLayoutBox> extras(span); - QVarLengthArray<qreal> dummy(span); - QVarLengthArray<qreal> newSizes(span); - - for (int j = 0; j < NSizes; ++j) { - qreal extra = compare(box, totalBox, j); - if (extra > 0.0) { - calculateGeometries(start, end, box.q_sizes(j), dummy.data(), newSizes.data(), - 0, totalBox, rowInfo); - - for (int k = 0; k < span; ++k) - extras[k].q_sizes(j) = newSizes[k]; - } - } - - for (int k = 0; k < span; ++k) { - boxes[start + k].combine(extras[k]); - if (stretch != 0) - stretches[start + k] = qMax(stretches[start + k], stretch); - } - } - multiCellMap.clear(); -} - -void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSize, qreal *positions, - qreal *sizes, qreal *descents, - const QGridLayoutBox &totalBox, - const QGridLayoutRowInfo &rowInfo) -{ - Q_ASSERT(end > start); - - targetSize = qMax(totalBox.q_minimumSize, targetSize); - - int n = end - start; - QVarLengthArray<qreal> newSizes(n); - QVarLengthArray<qreal> factors(n); - qreal sumFactors = 0.0; - int sumStretches = 0; - qreal sumAvailable; - - for (int i = 0; i < n; ++i) { - if (stretches[start + i] > 0) - sumStretches += stretches[start + i]; - } - - if (targetSize < totalBox.q_preferredSize) { - stealBox(start, end, MinimumSize, positions, sizes); - - sumAvailable = targetSize - totalBox.q_minimumSize; - if (sumAvailable > 0.0) { - qreal sumDesired = totalBox.q_preferredSize - totalBox.q_minimumSize; - - for (int i = 0; i < n; ++i) { - if (ignore.testBit(start + i)) { - factors[i] = 0.0; - continue; - } - - const QGridLayoutBox &box = boxes.at(start + i); - qreal desired = box.q_preferredSize - box.q_minimumSize; - factors[i] = growthFactorBelowPreferredSize(desired, sumAvailable, sumDesired); - sumFactors += factors[i]; - } - - for (int i = 0; i < n; ++i) { - Q_ASSERT(sumFactors > 0.0); - qreal delta = sumAvailable * factors[i] / sumFactors; - newSizes[i] = sizes[i] + delta; - } - } - } else { - bool isLargerThanMaximum = (targetSize > totalBox.q_maximumSize); - if (isLargerThanMaximum) { - stealBox(start, end, MaximumSize, positions, sizes); - sumAvailable = targetSize - totalBox.q_maximumSize; - } else { - stealBox(start, end, PreferredSize, positions, sizes); - sumAvailable = targetSize - totalBox.q_preferredSize; - } - - if (sumAvailable > 0.0) { - qreal sumCurrentAvailable = sumAvailable; - bool somethingHasAMaximumSize = false; - - qreal sumSizes = 0.0; - for (int i = 0; i < n; ++i) - sumSizes += sizes[i]; - - for (int i = 0; i < n; ++i) { - if (ignore.testBit(start + i)) { - newSizes[i] = 0.0; - factors[i] = 0.0; - continue; - } - - const QGridLayoutBox &box = boxes.at(start + i); - qreal boxSize; - - qreal desired; - if (isLargerThanMaximum) { - boxSize = box.q_maximumSize; - desired = rowInfo.boxes.value(start + i).q_maximumSize - boxSize; - } else { - boxSize = box.q_preferredSize; - desired = box.q_maximumSize - boxSize; - } - if (desired == 0.0) { - newSizes[i] = sizes[i]; - factors[i] = 0.0; - } else { - Q_ASSERT(desired > 0.0); - - int stretch = stretches[start + i]; - if (sumStretches == 0) { - if (hasIgnoreFlag) { - factors[i] = (stretch < 0) ? 1.0 : 0.0; - } else { - factors[i] = (stretch < 0) ? sizes[i] : 0.0; - } - } else if (stretch == sumStretches) { - factors[i] = 1.0; - } else if (stretch <= 0) { - factors[i] = 0.0; - } else { - qreal ultimateSize; - qreal ultimateSumSizes; - qreal x = ((stretch * sumSizes) - - (sumStretches * boxSize)) - / (sumStretches - stretch); - if (x >= 0.0) { - ultimateSize = boxSize + x; - ultimateSumSizes = sumSizes + x; - } else { - ultimateSize = boxSize; - ultimateSumSizes = (sumStretches * boxSize) - / stretch; - } - - /* - We multiply these by 1.5 to give some space for a smooth transition - (at the expense of the stretch factors, which are not fully respected - during the transition). - */ - ultimateSize = ultimateSize * 3 / 2; - ultimateSumSizes = ultimateSumSizes * 3 / 2; - - qreal beta = ultimateSumSizes - sumSizes; - if (!beta) { - factors[i] = 1; - } else { - qreal alpha = qMin(sumCurrentAvailable, beta); - qreal ultimateFactor = (stretch * ultimateSumSizes / sumStretches) - - (boxSize); - qreal transitionalFactor = sumCurrentAvailable * (ultimateSize - boxSize) / beta; - - factors[i] = ((alpha * ultimateFactor) - + ((beta - alpha) * transitionalFactor)) / beta; - } - - } - sumFactors += factors[i]; - if (desired < sumCurrentAvailable) - somethingHasAMaximumSize = true; - - newSizes[i] = -1.0; - } - } - - bool keepGoing = somethingHasAMaximumSize; - while (keepGoing) { - keepGoing = false; - - for (int i = 0; i < n; ++i) { - if (newSizes[i] >= 0.0) - continue; - - qreal maxBoxSize; - if (isLargerThanMaximum) - maxBoxSize = rowInfo.boxes.value(start + i).q_maximumSize; - else - maxBoxSize = boxes.at(start + i).q_maximumSize; - - qreal avail = sumCurrentAvailable * factors[i] / sumFactors; - if (sizes[i] + avail >= maxBoxSize) { - newSizes[i] = maxBoxSize; - sumCurrentAvailable -= maxBoxSize - sizes[i]; - sumFactors -= factors[i]; - keepGoing = (sumCurrentAvailable > 0.0); - if (!keepGoing) - break; - } - } - } - - for (int i = 0; i < n; ++i) { - if (newSizes[i] < 0.0) { - qreal delta = (sumFactors == 0.0) ? 0.0 - : sumCurrentAvailable * factors[i] / sumFactors; - newSizes[i] = sizes[i] + delta; - } - } - } - } - - if (sumAvailable > 0) { - qreal offset = 0; - for (int i = 0; i < n; ++i) { - qreal delta = newSizes[i] - sizes[i]; - positions[i] += offset; - sizes[i] += delta; - offset += delta; - } - -#if 0 // some "pixel allocation" - int surplus = targetSize - (positions[n - 1] + sizes[n - 1]); - Q_ASSERT(surplus >= 0 && surplus <= n); - - int prevSurplus = -1; - while (surplus > 0 && surplus != prevSurplus) { - prevSurplus = surplus; - - int offset = 0; - for (int i = 0; i < n; ++i) { - const QGridLayoutBox &box = boxes.at(start + i); - int delta = (!ignore.testBit(start + i) && surplus > 0 - && factors[i] > 0 && sizes[i] < box.q_maximumSize) - ? 1 : 0; - - positions[i] += offset; - sizes[i] += delta; - offset += delta; - surplus -= delta; - } - } - Q_ASSERT(surplus == 0); -#endif - } - - if (descents) { - for (int i = 0; i < n; ++i) { - if (ignore.testBit(start + i)) - continue; - const QGridLayoutBox &box = boxes.at(start + i); - descents[i] = fixedDescent(box.q_minimumDescent, box.q_minimumAscent, sizes[i]); - } - } -} - -QGridLayoutBox QGridLayoutRowData::totalBox(int start, int end) const -{ - QGridLayoutBox result; - if (start < end) { - result.q_maximumSize = 0.0; - qreal nextSpacing = 0.0; - for (int i = start; i < end; ++i) { - result.add(boxes.at(i), stretches.at(i), nextSpacing); - nextSpacing = spacings.at(i); - } - } - return result; -} - -void QGridLayoutRowData::stealBox(int start, int end, int which, qreal *positions, qreal *sizes) -{ - qreal offset = 0.0; - qreal nextSpacing = 0.0; - - for (int i = start; i < end; ++i) { - qreal avail = 0.0; - - if (!ignore.testBit(i)) { - const QGridLayoutBox &box = boxes.at(i); - avail = box.q_sizes(which); - offset += nextSpacing; - nextSpacing = spacings.at(i); - } - - *positions++ = offset; - *sizes++ = avail; - offset += avail; - } -} - -#ifdef QT_DEBUG -void QGridLayoutRowData::dump(int indent) const -{ - qDebug("%*sData", indent, ""); - - for (int i = 0; i < ignore.count(); ++i) { - qDebug("%*s Row %d (stretch %d, spacing %g)", indent, "", i, stretches.at(i), - spacings.at(i)); - if (ignore.testBit(i)) - qDebug("%*s Ignored", indent, ""); - boxes.at(i).dump(indent + 2); - } - - MultiCellMap::const_iterator it = multiCellMap.constBegin(); - while (it != multiCellMap.constEnd()) { - qDebug("%*s Multi-cell entry <%d, %d> (stretch %d)", indent, "", it.key().first, - it.key().second, it.value().q_stretch); - it.value().q_box.dump(indent + 2); - } -} -#endif - -QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, - int row, int column, int rowSpan, int columnSpan, - Qt::Alignment alignment, int itemAtIndex) - : q_engine(engine), q_layoutItem(layoutItem), q_alignment(alignment) -{ - q_firstRows[Hor] = column; - q_firstRows[Ver] = row; - q_rowSpans[Hor] = columnSpan; - q_rowSpans[Ver] = rowSpan; - q_stretches[Hor] = -1; - q_stretches[Ver] = -1; - - q_engine->insertItem(this, itemAtIndex); -} - -int QGridLayoutItem::firstRow(Qt::Orientation orientation) const -{ - return q_firstRows[orientation == Qt::Vertical]; -} - -int QGridLayoutItem::firstColumn(Qt::Orientation orientation) const -{ - return q_firstRows[orientation == Qt::Horizontal]; -} - -int QGridLayoutItem::lastRow(Qt::Orientation orientation) const -{ - return firstRow(orientation) + rowSpan(orientation) - 1; -} - -int QGridLayoutItem::lastColumn(Qt::Orientation orientation) const -{ - return firstColumn(orientation) + columnSpan(orientation) - 1; -} - -int QGridLayoutItem::rowSpan(Qt::Orientation orientation) const -{ - return q_rowSpans[orientation == Qt::Vertical]; -} - -int QGridLayoutItem::columnSpan(Qt::Orientation orientation) const -{ - return q_rowSpans[orientation == Qt::Horizontal]; -} - -void QGridLayoutItem::setFirstRow(int row, Qt::Orientation orientation) -{ - q_firstRows[orientation == Qt::Vertical] = row; -} - -void QGridLayoutItem::setRowSpan(int rowSpan, Qt::Orientation orientation) -{ - q_rowSpans[orientation == Qt::Vertical] = rowSpan; -} - -int QGridLayoutItem::stretchFactor(Qt::Orientation orientation) const -{ - int stretch = q_stretches[orientation == Qt::Vertical]; - if (stretch >= 0) - return stretch; - - QSizePolicy::Policy policy = sizePolicy(orientation); - - if (policy & QSizePolicy::ExpandFlag) { - return 1; - } else if (policy & QSizePolicy::GrowFlag) { - return -1; // because we max it up - } else { - return 0; - } -} - -void QGridLayoutItem::setStretchFactor(int stretch, Qt::Orientation orientation) -{ - Q_ASSERT(stretch >= 0); // ### deal with too big stretches - q_stretches[orientation == Qt::Vertical] = stretch; -} - -QSizePolicy::Policy QGridLayoutItem::sizePolicy(Qt::Orientation orientation) const -{ - QSizePolicy sizePolicy(q_layoutItem->sizePolicy()); - return (orientation == Qt::Horizontal) ? sizePolicy.horizontalPolicy() - : sizePolicy.verticalPolicy(); -} - -/* - returns true if the size policy returns true for either hasHeightForWidth() - or hasWidthForHeight() - */ -bool QGridLayoutItem::hasDynamicConstraint() const -{ - return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth() - || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight(); -} - -Qt::Orientation QGridLayoutItem::dynamicConstraintOrientation() const -{ - if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()) - return Qt::Vertical; - else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight()) - return Qt::Horizontal; -} - -QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const -{ - return q_layoutItem->sizePolicy().controlType(); -} - -QSizeF QGridLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - return q_layoutItem->effectiveSizeHint(which, constraint); -} - -QGridLayoutBox QGridLayoutItem::box(Qt::Orientation orientation, qreal constraint) const -{ - QGridLayoutBox result; - QSizePolicy::Policy policy = sizePolicy(orientation); - - if (orientation == Qt::Horizontal) { - QSizeF constraintSize(-1.0, constraint); - - result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).width(); - - if (policy & QSizePolicy::ShrinkFlag) { - result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).width(); - } else { - result.q_minimumSize = result.q_preferredSize; - } - - if (policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag)) { - result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).width(); - } else { - result.q_maximumSize = result.q_preferredSize; - } - } else { - QSizeF constraintSize(constraint, -1.0); - - result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).height(); - - if (policy & QSizePolicy::ShrinkFlag) { - result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).height(); - } else { - result.q_minimumSize = result.q_preferredSize; - } - - if (policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag)) { - result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).height(); - } else { - result.q_maximumSize = result.q_preferredSize; - } - - result.q_minimumDescent = sizeHint(Qt::MinimumDescent, constraintSize).height(); - if (result.q_minimumDescent >= 0.0) - result.q_minimumAscent = result.q_minimumSize - result.q_minimumDescent; - } - if (policy & QSizePolicy::IgnoreFlag) - result.q_preferredSize = result.q_minimumSize; - - return result; -} - -QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal height, - qreal rowDescent) const -{ - rowDescent = -1.0; // ### This disables the descent - - QGridLayoutBox vBox = box(Qt::Vertical); - if (vBox.q_minimumDescent < 0.0 || rowDescent < 0.0) { - qreal cellWidth = width; - qreal cellHeight = height; - - - QSizeF size = effectiveMaxSize(QSizeF(-1,-1)); - if (hasDynamicConstraint()) { - if (dynamicConstraintOrientation() == Qt::Vertical) { - if (size.width() > cellWidth) - size = effectiveMaxSize(QSizeF(cellWidth, -1)); - } else if (size.height() > cellHeight) { - size = effectiveMaxSize(QSizeF(-1, cellHeight)); - } - } - size = size.boundedTo(QSizeF(cellWidth, cellHeight)); - width = size.width(); - height = size.height(); - - Qt::Alignment align = q_engine->effectiveAlignment(this); - switch (align & Qt::AlignHorizontal_Mask) { - case Qt::AlignHCenter: - x += (cellWidth - width)/2; - break; - case Qt::AlignRight: - x += cellWidth - width; - break; - default: - break; - } - switch (align & Qt::AlignVertical_Mask) { - case Qt::AlignVCenter: - y += (cellHeight - height)/2; - break; - case Qt::AlignBottom: - y += cellHeight - height; - break; - default: - break; - } - return QRectF(x, y, width, height); - } else { - qreal descent = vBox.q_minimumDescent; - qreal ascent = vBox.q_minimumSize - descent; - return QRectF(x, y + height - rowDescent - ascent, width, ascent + descent); - } -} - -void QGridLayoutItem::setGeometry(const QRectF &rect) -{ - q_layoutItem->setGeometry(rect); -} - -void QGridLayoutItem::transpose() -{ - qSwap(q_firstRows[Hor], q_firstRows[Ver]); - qSwap(q_rowSpans[Hor], q_rowSpans[Ver]); - qSwap(q_stretches[Hor], q_stretches[Ver]); -} - -void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation orientation) -{ - int oldFirstRow = firstRow(orientation); - if (oldFirstRow >= row) { - setFirstRow(oldFirstRow + delta, orientation); - } else if (lastRow(orientation) >= row) { - setRowSpan(rowSpan(orientation) + delta, orientation); - } -} -/*! - \internal - returns the effective maximumSize, will take the sizepolicy into - consideration. (i.e. if sizepolicy does not have QSizePolicy::Grow, then - maxSizeHint will be the preferredSize) - Note that effectiveSizeHint does not take sizePolicy into consideration, - (since it only evaluates the hints, as the name implies) -*/ -QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const -{ - QSizeF size = constraint; - bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; - bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag; - if (!vGrow || !hGrow) { - QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint); - if (!vGrow) - size.setHeight(pref.height()); - if (!hGrow) - size.setWidth(pref.width()); - } - - if (!size.isValid()) { - QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, size); - if (size.width() == -1) - size.setWidth(maxSize.width()); - if (size.height() == -1) - size.setHeight(maxSize.height()); - } - return size; -} - -#ifdef QT_DEBUG -void QGridLayoutItem::dump(int indent) const -{ - qDebug("%*s%p (%d, %d) %d x %d", indent, "", q_layoutItem, firstRow(), firstColumn(), - rowSpan(), columnSpan()); - - if (q_stretches[Hor] >= 0) - qDebug("%*s Horizontal stretch: %d", indent, "", q_stretches[Hor]); - if (q_stretches[Ver] >= 0) - qDebug("%*s Vertical stretch: %d", indent, "", q_stretches[Ver]); - if (q_alignment != 0) - qDebug("%*s Alignment: %x", indent, "", uint(q_alignment)); - qDebug("%*s Horizontal size policy: %x Vertical size policy: %x", - indent, "", sizePolicy(Qt::Horizontal), sizePolicy(Qt::Vertical)); -} -#endif - -void QGridLayoutRowInfo::insertOrRemoveRows(int row, int delta) -{ - count += delta; - - insertOrRemoveItems(stretches, row, delta); - insertOrRemoveItems(spacings, row, delta); - insertOrRemoveItems(alignments, row, delta); - insertOrRemoveItems(boxes, row, delta); -} - -#ifdef QT_DEBUG -void QGridLayoutRowInfo::dump(int indent) const -{ - qDebug("%*sInfo (count: %d)", indent, "", count); - for (int i = 0; i < count; ++i) { - QString message; - - if (stretches.value(i).value() >= 0) - message += QString::fromAscii(" stretch %1").arg(stretches.value(i).value()); - if (spacings.value(i).value() >= 0.0) - message += QString::fromAscii(" spacing %1").arg(spacings.value(i).value()); - if (alignments.value(i) != 0) - message += QString::fromAscii(" alignment %1").arg(int(alignments.value(i)), 16); - - if (!message.isEmpty() || boxes.value(i) != QGridLayoutBox()) { - qDebug("%*s Row %d:%s", indent, "", i, qPrintable(message)); - if (boxes.value(i) != QGridLayoutBox()) - boxes.value(i).dump(indent + 1); - } - } -} -#endif - -QGridLayoutEngine::QGridLayoutEngine() -{ - m_visualDirection = Qt::LeftToRight; - invalidate(); -} - -int QGridLayoutEngine::rowCount(Qt::Orientation orientation) const -{ - return q_infos[orientation == Qt::Vertical].count; -} - -int QGridLayoutEngine::columnCount(Qt::Orientation orientation) const -{ - return q_infos[orientation == Qt::Horizontal].count; -} - -int QGridLayoutEngine::itemCount() const -{ - return q_items.count(); -} - -QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const -{ - Q_ASSERT(index >= 0 && index < itemCount()); - return q_items.at(index); -} - -int QGridLayoutEngine::indexOf(QGraphicsLayoutItem *item) const -{ - for (int i = 0; i < q_items.size(); ++i) { - if (item == q_items.at(i)->layoutItem()) - return i; - } - return -1; -} - -int QGridLayoutEngine::effectiveFirstRow(Qt::Orientation orientation) const -{ - ensureEffectiveFirstAndLastRows(); - return q_cachedEffectiveFirstRows[orientation == Qt::Vertical]; -} - -int QGridLayoutEngine::effectiveLastRow(Qt::Orientation orientation) const -{ - ensureEffectiveFirstAndLastRows(); - return q_cachedEffectiveLastRows[orientation == Qt::Vertical]; -} - -void QGridLayoutEngine::setSpacing(qreal spacing, Qt::Orientations orientations) -{ - Q_ASSERT(spacing >= 0.0); - if (orientations & Qt::Horizontal) - q_defaultSpacings[Hor].setUserValue(spacing); - if (orientations & Qt::Vertical) - q_defaultSpacings[Ver].setUserValue(spacing); - - invalidate(); -} - -qreal QGridLayoutEngine::spacing(const QLayoutStyleInfo &styleInfo, Qt::Orientation orientation) const -{ - if (q_defaultSpacings[orientation == Qt::Vertical].isDefault()) { - QStyle *style = styleInfo.style(); - QStyleOption option; - option.initFrom(styleInfo.widget()); - qreal defaultSpacing = (qreal)style->pixelMetric(orientation == Qt::Vertical ? QStyle::PM_LayoutVerticalSpacing - : QStyle::PM_LayoutHorizontalSpacing, &option, styleInfo.widget()); - q_defaultSpacings[orientation == Qt::Vertical].setCachedValue(defaultSpacing); - } - return q_defaultSpacings[orientation == Qt::Vertical].value(); -} - -void QGridLayoutEngine::setRowSpacing(int row, qreal spacing, Qt::Orientation orientation) -{ - Q_ASSERT(row >= 0); - - QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; - if (row >= rowInfo.spacings.count()) - rowInfo.spacings.resize(row + 1); - if (spacing >= 0) - rowInfo.spacings[row].setUserValue(spacing); - else - rowInfo.spacings[row] = QLayoutParameter<qreal>(); - invalidate(); -} - -qreal QGridLayoutEngine::rowSpacing(int row, Qt::Orientation orientation) const -{ - QLayoutParameter<qreal> spacing = q_infos[orientation == Qt::Vertical].spacings.value(row); - if (!spacing.isDefault()) - return spacing.value(); - return q_defaultSpacings[orientation == Qt::Vertical].value(); -} - -void QGridLayoutEngine::setRowStretchFactor(int row, int stretch, Qt::Orientation orientation) -{ - Q_ASSERT(row >= 0); - Q_ASSERT(stretch >= 0); - - maybeExpandGrid(row, -1, orientation); - - QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; - if (row >= rowInfo.stretches.count()) - rowInfo.stretches.resize(row + 1); - rowInfo.stretches[row].setUserValue(stretch); -} - -int QGridLayoutEngine::rowStretchFactor(int row, Qt::Orientation orientation) const -{ - QStretchParameter stretch = q_infos[orientation == Qt::Vertical].stretches.value(row); - if (!stretch.isDefault()) - return stretch.value(); - return 0; -} - -void QGridLayoutEngine::setStretchFactor(QGraphicsLayoutItem *layoutItem, int stretch, - Qt::Orientation orientation) -{ - Q_ASSERT(stretch >= 0); - - if (QGridLayoutItem *item = findLayoutItem(layoutItem)) - item->setStretchFactor(stretch, orientation); -} - -int QGridLayoutEngine::stretchFactor(QGraphicsLayoutItem *layoutItem, Qt::Orientation orientation) const -{ - if (QGridLayoutItem *item = findLayoutItem(layoutItem)) - return item->stretchFactor(orientation); - return 0; -} - -void QGridLayoutEngine::setRowSizeHint(Qt::SizeHint which, int row, qreal size, - Qt::Orientation orientation) -{ - Q_ASSERT(row >= 0); - Q_ASSERT(size >= 0.0); - - maybeExpandGrid(row, -1, orientation); - - QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; - if (row >= rowInfo.boxes.count()) - rowInfo.boxes.resize(row + 1); - rowInfo.boxes[row].q_sizes(which) = size; -} - -qreal QGridLayoutEngine::rowSizeHint(Qt::SizeHint which, int row, Qt::Orientation orientation) const -{ - return q_infos[orientation == Qt::Vertical].boxes.value(row).q_sizes(which); -} - -void QGridLayoutEngine::setRowAlignment(int row, Qt::Alignment alignment, - Qt::Orientation orientation) -{ - Q_ASSERT(row >= 0); - - maybeExpandGrid(row, -1, orientation); - - QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; - if (row >= rowInfo.alignments.count()) - rowInfo.alignments.resize(row + 1); - rowInfo.alignments[row] = alignment; -} - -Qt::Alignment QGridLayoutEngine::rowAlignment(int row, Qt::Orientation orientation) const -{ - Q_ASSERT(row >= 0); - return q_infos[orientation == Qt::Vertical].alignments.value(row); -} - -void QGridLayoutEngine::setAlignment(QGraphicsLayoutItem *layoutItem, Qt::Alignment alignment) -{ - if (QGridLayoutItem *item = findLayoutItem(layoutItem)) - item->setAlignment(alignment); - invalidate(); -} - -Qt::Alignment QGridLayoutEngine::alignment(QGraphicsLayoutItem *layoutItem) const -{ - if (QGridLayoutItem *item = findLayoutItem(layoutItem)) - return item->alignment(); - return 0; -} - -Qt::Alignment QGridLayoutEngine::effectiveAlignment(const QGridLayoutItem *layoutItem) const -{ - Qt::Alignment align = layoutItem->alignment(); - if (!(align & Qt::AlignVertical_Mask)) { - // no vertical alignment, respect the row alignment - int y = layoutItem->firstRow(); - align |= (rowAlignment(y, Qt::Vertical) & Qt::AlignVertical_Mask); - } - if (!(align & Qt::AlignHorizontal_Mask)) { - // no horizontal alignment, respect the column alignment - int x = layoutItem->firstColumn(); - align |= (rowAlignment(x, Qt::Horizontal) & Qt::AlignHorizontal_Mask); - } - return align; -} - -/*! - \internal - The \a index is only used by QGraphicsLinearLayout to ensure that itemAt() reflects the order - of visual arrangement. Strictly speaking it does not have to, but most people expect it to. - (And if it didn't we would have to add itemArrangedAt(int index) or something..) - */ -void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index) -{ - maybeExpandGrid(item->lastRow(), item->lastColumn()); - - if (index == -1) - q_items.append(item); - else - q_items.insert(index, item); - - for (int i = item->firstRow(); i <= item->lastRow(); ++i) { - for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) { - if (itemAt(i, j)) - qWarning("QGridLayoutEngine::addItem: Cell (%d, %d) already taken", i, j); - setItemAt(i, j, item); - } - } -} - -void QGridLayoutEngine::addItem(QGridLayoutItem *item) -{ - insertItem(item, -1); -} - -void QGridLayoutEngine::removeItem(QGridLayoutItem *item) -{ - Q_ASSERT(q_items.contains(item)); - - invalidate(); - - for (int i = item->firstRow(); i <= item->lastRow(); ++i) { - for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) { - if (itemAt(i, j) == item) - setItemAt(i, j, 0); - } - } - - q_items.removeAll(item); -} - -QGridLayoutItem *QGridLayoutEngine::findLayoutItem(QGraphicsLayoutItem *layoutItem) const -{ - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - if (item->layoutItem() == layoutItem) - return item; - } - return 0; -} - -QGridLayoutItem *QGridLayoutEngine::itemAt(int row, int column, Qt::Orientation orientation) const -{ - if (orientation == Qt::Horizontal) - qSwap(row, column); - if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount())) - return 0; - return q_grid.at((row * internalGridColumnCount()) + column); -} - -void QGridLayoutEngine::invalidate() -{ - q_cachedEffectiveFirstRows[Hor] = -1; - q_cachedEffectiveFirstRows[Ver] = -1; - q_cachedEffectiveLastRows[Hor] = -1; - q_cachedEffectiveLastRows[Ver] = -1; - q_cachedDataForStyleInfo.invalidate(); - q_cachedSize = QSizeF(); - q_cachedConstraintOrientation = UnknownConstraint; -} - -static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect) -{ - if (dir == Qt::RightToLeft) - geom->moveRight(contentsRect.right() - (geom->left() - contentsRect.left())); -} - -void QGridLayoutEngine::setGeometries(const QLayoutStyleInfo &styleInfo, - const QRectF &contentsGeometry) -{ - if (rowCount() < 1 || columnCount() < 1) - return; - - ensureGeometries(styleInfo, contentsGeometry.size()); - - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - - qreal x = q_xx[item->firstColumn()]; - qreal y = q_yy[item->firstRow()]; - qreal width = q_widths[item->lastColumn()]; - qreal height = q_heights[item->lastRow()]; - - if (item->columnSpan() != 1) - width += q_xx[item->lastColumn()] - x; - if (item->rowSpan() != 1) - height += q_yy[item->lastRow()] - y; - - QRectF geom = item->geometryWithin(contentsGeometry.x() + x, contentsGeometry.y() + y, - width, height, q_descents[item->lastRow()]); - visualRect(&geom, visualDirection(), contentsGeometry); - item->setGeometry(geom); - } -} - -// ### candidate for deletion -QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo, - const QRectF &contentsGeometry, int row, int column, int rowSpan, - int columnSpan) const -{ - if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount()) - || rowSpan < 1 || columnSpan < 1) - return QRectF(); - - ensureGeometries(styleInfo, contentsGeometry.size()); - - int lastColumn = qMax(column + columnSpan, columnCount()) - 1; - int lastRow = qMax(row + rowSpan, rowCount()) - 1; - - qreal x = q_xx[column]; - qreal y = q_yy[row]; - qreal width = q_widths[lastColumn]; - qreal height = q_heights[lastRow]; - - if (columnSpan != 1) - width += q_xx[lastColumn] - x; - if (rowSpan != 1) - height += q_yy[lastRow] - y; - - return QRectF(contentsGeometry.x() + x, contentsGeometry.y() + y, width, height); -} - -QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, - const QSizeF &constraint) const -{ - QGridLayoutBox sizehint_totalBoxes[NOrientations]; - - bool sizeHintCalculated = false; - - if (hasDynamicConstraint() && rowCount() > 0 && columnCount() > 0) { - if (constraintOrientation() == Qt::Vertical) { - //We have items whose height depends on their width - if (constraint.width() >= 0) { - if (q_cachedDataForStyleInfo != styleInfo) - ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); - else - sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; - QVector<qreal> sizehint_xx; - QVector<qreal> sizehint_widths; - - sizehint_xx.resize(columnCount()); - sizehint_widths.resize(columnCount()); - qreal width = constraint.width(); - //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as - //constraints to find the row heights - q_columnData.calculateGeometries(0, columnCount(), width, sizehint_xx.data(), sizehint_widths.data(), - 0, sizehint_totalBoxes[Hor], q_infos[Hor]); - ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical); - sizeHintCalculated = true; - } - } else { - if (constraint.height() >= 0) { - //We have items whose width depends on their height - ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); - QVector<qreal> sizehint_yy; - QVector<qreal> sizehint_heights; - - sizehint_yy.resize(rowCount()); - sizehint_heights.resize(rowCount()); - qreal height = constraint.height(); - //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as - //constraints to find the column widths - q_rowData.calculateGeometries(0, rowCount(), height, sizehint_yy.data(), sizehint_heights.data(), - 0, sizehint_totalBoxes[Ver], q_infos[Ver]); - ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, sizehint_yy.data(), sizehint_heights.data(), Qt::Horizontal); - sizeHintCalculated = true; - } - } - } - - if (!sizeHintCalculated) { - //No items with height for width, so it doesn't matter which order we do these in - if (q_cachedDataForStyleInfo != styleInfo) { - ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); - ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); - } else { - sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; - sizehint_totalBoxes[Ver] = q_totalBoxes[Ver]; - } - } - - switch (which) { - case Qt::MinimumSize: - return QSizeF(sizehint_totalBoxes[Hor].q_minimumSize, sizehint_totalBoxes[Ver].q_minimumSize); - case Qt::PreferredSize: - return QSizeF(sizehint_totalBoxes[Hor].q_preferredSize, sizehint_totalBoxes[Ver].q_preferredSize); - case Qt::MaximumSize: - return QSizeF(sizehint_totalBoxes[Hor].q_maximumSize, sizehint_totalBoxes[Ver].q_maximumSize); - case Qt::MinimumDescent: - return QSizeF(-1.0, sizehint_totalBoxes[Hor].q_minimumDescent); // ### doesn't work - default: - break; - } - return QSizeF(); -} - -QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const -{ - Qt::Orientation orientation = (side == Top || side == Bottom) ? Qt::Vertical : Qt::Horizontal; - int row = (side == Top || side == Left) ? effectiveFirstRow(orientation) - : effectiveLastRow(orientation); - QSizePolicy::ControlTypes result = 0; - - for (int column = columnCount(orientation) - 1; column >= 0; --column) { - if (QGridLayoutItem *item = itemAt(row, column, orientation)) - result |= item->controlTypes(side); - } - return result; -} - -void QGridLayoutEngine::transpose() -{ - invalidate(); - - for (int i = q_items.count() - 1; i >= 0; --i) - q_items.at(i)->transpose(); - - qSwap(q_defaultSpacings[Hor], q_defaultSpacings[Ver]); - qSwap(q_infos[Hor], q_infos[Ver]); - - regenerateGrid(); -} - -void QGridLayoutEngine::setVisualDirection(Qt::LayoutDirection direction) -{ - m_visualDirection = direction; -} - -Qt::LayoutDirection QGridLayoutEngine::visualDirection() const -{ - return m_visualDirection; -} - -#ifdef QT_DEBUG -void QGridLayoutEngine::dump(int indent) const -{ - qDebug("%*sEngine", indent, ""); - - qDebug("%*s Items (%d)", indent, "", q_items.count()); - int i; - for (i = 0; i < q_items.count(); ++i) - q_items.at(i)->dump(indent + 2); - - qDebug("%*s Grid (%d x %d)", indent, "", internalGridRowCount(), - internalGridColumnCount()); - for (int row = 0; row < internalGridRowCount(); ++row) { - QString message = QLatin1String("[ "); - for (int column = 0; column < internalGridColumnCount(); ++column) { - message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3); - message += QLatin1Char(' '); - } - message += QLatin1Char(']'); - qDebug("%*s %s", indent, "", qPrintable(message)); - } - - if (q_defaultSpacings[Hor].value() >= 0.0 || q_defaultSpacings[Ver].value() >= 0.0) - qDebug("%*s Default spacings: %g %g", indent, "", q_defaultSpacings[Hor].value(), - q_defaultSpacings[Ver].value()); - - qDebug("%*s Column and row info", indent, ""); - q_infos[Hor].dump(indent + 2); - q_infos[Ver].dump(indent + 2); - - qDebug("%*s Column and row data", indent, ""); - q_columnData.dump(indent + 2); - q_rowData.dump(indent + 2); - - qDebug("%*s Geometries output", indent, ""); - QVector<qreal> *cellPos = &q_yy; - for (int pass = 0; pass < 2; ++pass) { - QString message; - for (i = 0; i < cellPos->count(); ++i) { - message += QLatin1String((message.isEmpty() ? "[" : ", ")); - message += QString::number(cellPos->at(i)); - } - message += QLatin1Char(']'); - qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message)); - cellPos = &q_xx; - } -} -#endif - -void QGridLayoutEngine::maybeExpandGrid(int row, int column, Qt::Orientation orientation) -{ - invalidate(); // ### move out of here? - - if (orientation == Qt::Horizontal) - qSwap(row, column); - - if (row < rowCount() && column < columnCount()) - return; - - int oldGridRowCount = internalGridRowCount(); - int oldGridColumnCount = internalGridColumnCount(); - - q_infos[Ver].count = qMax(row + 1, rowCount()); - q_infos[Hor].count = qMax(column + 1, columnCount()); - - int newGridRowCount = internalGridRowCount(); - int newGridColumnCount = internalGridColumnCount(); - - int newGridSize = newGridRowCount * newGridColumnCount; - if (newGridSize != q_grid.count()) { - q_grid.resize(newGridSize); - - if (newGridColumnCount != oldGridColumnCount) { - for (int i = oldGridRowCount - 1; i >= 1; --i) { - for (int j = oldGridColumnCount - 1; j >= 0; --j) { - int oldIndex = (i * oldGridColumnCount) + j; - int newIndex = (i * newGridColumnCount) + j; - - Q_ASSERT(newIndex > oldIndex); - q_grid[newIndex] = q_grid[oldIndex]; - q_grid[oldIndex] = 0; - } - } - } - } -} - -void QGridLayoutEngine::regenerateGrid() -{ - q_grid.fill(0); - - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - - for (int j = item->firstRow(); j <= item->lastRow(); ++j) { - for (int k = item->firstColumn(); k <= item->lastColumn(); ++k) { - setItemAt(j, k, item); - } - } - } -} - -void QGridLayoutEngine::setItemAt(int row, int column, QGridLayoutItem *item) -{ - Q_ASSERT(row >= 0 && row < rowCount()); - Q_ASSERT(column >= 0 && column < columnCount()); - q_grid[(row * internalGridColumnCount()) + column] = item; -} - -void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation orientation) -{ - int oldRowCount = rowCount(orientation); - Q_ASSERT(uint(row) <= uint(oldRowCount)); - - invalidate(); - - // appending rows (or columns) is easy - if (row == oldRowCount && delta > 0) { - maybeExpandGrid(oldRowCount + delta - 1, -1, orientation); - return; - } - - q_infos[orientation == Qt::Vertical].insertOrRemoveRows(row, delta); - - for (int i = q_items.count() - 1; i >= 0; --i) - q_items.at(i)->insertOrRemoveRows(row, delta, orientation); - - q_grid.resize(internalGridRowCount() * internalGridColumnCount()); - regenerateGrid(); -} - -void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo, - qreal *colPositions, qreal *colSizes, - Qt::Orientation orientation) const -{ - const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; - const QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; - const QGridLayoutRowInfo &columnInfo = q_infos[orientation == Qt::Horizontal]; - LayoutSide top = (orientation == Qt::Vertical) ? Top : Left; - LayoutSide bottom = (orientation == Qt::Vertical) ? Bottom : Right; - - QStyle *style = styleInfo.style(); - QStyleOption option; - option.initFrom(styleInfo.widget()); - - const QLayoutParameter<qreal> &defaultSpacing = q_defaultSpacings[orientation == Qt::Vertical]; - qreal innerSpacing = 0.0; - if (style) - innerSpacing = (qreal)style->pixelMetric(orientation == Qt::Vertical ? QStyle::PM_LayoutVerticalSpacing - : QStyle::PM_LayoutHorizontalSpacing, - &option, styleInfo.widget()); - if (innerSpacing >= 0.0) - defaultSpacing.setCachedValue(innerSpacing); - - for (int row = 0; row < rowInfo.count; ++row) { - bool rowIsEmpty = true; - bool rowIsIdenticalToPrevious = (row > 0); - - for (int column = 0; column < columnInfo.count; ++column) { - QGridLayoutItem *item = itemAt(row, column, orientation); - - if (rowIsIdenticalToPrevious && item != itemAt(row - 1, column, orientation)) - rowIsIdenticalToPrevious = false; - - if (item) - rowIsEmpty = false; - } - - if ((rowIsEmpty || rowIsIdenticalToPrevious) - && rowInfo.spacings.value(row).isDefault() - && rowInfo.stretches.value(row).isDefault() - && rowInfo.boxes.value(row) == QGridLayoutBox()) - rowData->ignore.setBit(row, true); - - if (rowInfo.spacings.value(row).isUser()) { - rowData->spacings[row] = rowInfo.spacings.at(row).value(); - } else if (!defaultSpacing.isDefault()) { - rowData->spacings[row] = defaultSpacing.value(); - } - - rowData->stretches[row] = rowInfo.stretches.value(row).value(); - } - - struct RowAdHocData { - int q_row; - unsigned int q_hasButtons : 8; - unsigned int q_hasNonButtons : 8; - - inline RowAdHocData() : q_row(-1), q_hasButtons(false), q_hasNonButtons(false) {} - inline void init(int row) { - this->q_row = row; - q_hasButtons = false; - q_hasNonButtons = false; - } - inline bool hasOnlyButtons() const { return q_hasButtons && !q_hasNonButtons; } - inline bool hasOnlyNonButtons() const { return q_hasNonButtons && !q_hasButtons; } - }; - RowAdHocData lastRowAdHocData; - RowAdHocData nextToLastRowAdHocData; - RowAdHocData nextToNextToLastRowAdHocData; - - rowData->hasIgnoreFlag = false; - for (int row = 0; row < rowInfo.count; ++row) { - if (rowData->ignore.testBit(row)) - continue; - - QGridLayoutBox &rowBox = rowData->boxes[row]; - if (option.state & QStyle::State_Window) { - nextToNextToLastRowAdHocData = nextToLastRowAdHocData; - nextToLastRowAdHocData = lastRowAdHocData; - lastRowAdHocData.init(row); - } - - bool userRowStretch = rowInfo.stretches.value(row).isUser(); - int &rowStretch = rowData->stretches[row]; - - bool hasIgnoreFlag = true; - for (int column = 0; column < columnInfo.count; ++column) { - QGridLayoutItem *item = itemAt(row, column, orientation); - if (item) { - int itemRow = item->firstRow(orientation); - int itemColumn = item->firstColumn(orientation); - - if (itemRow == row && itemColumn == column) { - int itemStretch = item->stretchFactor(orientation); - if (!(item->sizePolicy(orientation) & QSizePolicy::IgnoreFlag)) - hasIgnoreFlag = false; - int itemRowSpan = item->rowSpan(orientation); - - int effectiveRowSpan = 1; - for (int i = 1; i < itemRowSpan; ++i) { - if (!rowData->ignore.testBit(i)) - ++effectiveRowSpan; - } - - QGridLayoutBox *box; - if (effectiveRowSpan == 1) { - box = &rowBox; - if (!userRowStretch && itemStretch != 0) - rowStretch = qMax(rowStretch, itemStretch); - } else { - QGridLayoutMultiCellData &multiCell = - rowData->multiCellMap[qMakePair(row, effectiveRowSpan)]; - box = &multiCell.q_box; - multiCell.q_stretch = itemStretch; - } - // Items with constraints need to be passed the constraint - if (colSizes && colPositions && item->hasDynamicConstraint() && orientation == item->dynamicConstraintOrientation()) { - /* Get the width of the item by summing up the widths of the columns that it spans. - * We need to have already calculated the widths of the columns by calling - * q_columns->calculateGeometries() before hand and passing the value in the colSizes - * and colPositions parameters. - * The variable name is still colSizes even when it actually has the row sizes - */ - qreal length = colSizes[item->lastColumn(orientation)]; - if (item->columnSpan(orientation) != 1) - length += colPositions[item->lastColumn(orientation)] - colPositions[item->firstColumn(orientation)]; - box->combine(item->box(orientation, length)); - } else { - box->combine(item->box(orientation)); - } - - if (effectiveRowSpan == 1) { - QSizePolicy::ControlTypes controls = item->controlTypes(top); - if (controls & ButtonMask) - lastRowAdHocData.q_hasButtons = true; - if (controls & ~ButtonMask) - lastRowAdHocData.q_hasNonButtons = true; - } - } - } - } - if (row < rowInfo.boxes.count()) { - QGridLayoutBox rowBoxInfo = rowInfo.boxes.at(row); - rowBoxInfo.normalize(); - rowBox.q_minimumSize = qMax(rowBox.q_minimumSize, rowBoxInfo.q_minimumSize); - rowBox.q_maximumSize = qMax(rowBox.q_minimumSize, - (rowBoxInfo.q_maximumSize != FLT_MAX ? - rowBoxInfo.q_maximumSize : rowBox.q_maximumSize)); - rowBox.q_preferredSize = qBound(rowBox.q_minimumSize, - qMax(rowBox.q_preferredSize, rowBoxInfo.q_preferredSize), - rowBox.q_maximumSize); - } - if (hasIgnoreFlag) - rowData->hasIgnoreFlag = true; - } - - /* - Heuristic: Detect button boxes that don't use QSizePolicy::ButtonBox. - This is somewhat ad hoc but it usually does the trick. - */ - bool lastRowIsButtonBox = (lastRowAdHocData.hasOnlyButtons() - && nextToLastRowAdHocData.hasOnlyNonButtons()); - bool lastTwoRowsIsButtonBox = (lastRowAdHocData.hasOnlyButtons() - && nextToLastRowAdHocData.hasOnlyButtons() - && nextToNextToLastRowAdHocData.hasOnlyNonButtons() - && orientation == Qt::Vertical); - - if (defaultSpacing.isDefault()) { - int prevRow = -1; - for (int row = 0; row < rowInfo.count; ++row) { - if (rowData->ignore.testBit(row)) - continue; - - if (prevRow != -1 && !rowInfo.spacings.value(prevRow).isUser()) { - qreal &rowSpacing = rowData->spacings[prevRow]; - for (int column = 0; column < columnInfo.count; ++column) { - QGridLayoutItem *item1 = itemAt(prevRow, column, orientation); - QGridLayoutItem *item2 = itemAt(row, column, orientation); - - if (item1 && item2 && item1 != item2) { - QSizePolicy::ControlTypes controls1 = item1->controlTypes(bottom); - QSizePolicy::ControlTypes controls2 = item2->controlTypes(top); - - if (controls2 & QSizePolicy::PushButton) { - if ((row == nextToLastRowAdHocData.q_row && lastTwoRowsIsButtonBox) - || (row == lastRowAdHocData.q_row && lastRowIsButtonBox)) { - controls2 &= ~QSizePolicy::PushButton; - controls2 |= QSizePolicy::ButtonBox; - } - } - - qreal spacing = style->combinedLayoutSpacing(controls1, controls2, - orientation, &option, - styleInfo.widget()); - if (orientation == Qt::Horizontal) { - qreal width1 = rowData->boxes.at(prevRow).q_minimumSize; - qreal width2 = rowData->boxes.at(row).q_minimumSize; - QRectF rect1 = item1->geometryWithin(0.0, 0.0, width1, FLT_MAX, -1.0); - QRectF rect2 = item2->geometryWithin(0.0, 0.0, width2, FLT_MAX, -1.0); - spacing -= (width1 - (rect1.x() + rect1.width())) + rect2.x(); - } else { - const QGridLayoutBox &box1 = rowData->boxes.at(prevRow); - const QGridLayoutBox &box2 = rowData->boxes.at(row); - qreal height1 = box1.q_minimumSize; - qreal height2 = box2.q_minimumSize; - qreal rowDescent1 = fixedDescent(box1.q_minimumDescent, - box1.q_minimumAscent, height1); - qreal rowDescent2 = fixedDescent(box2.q_minimumDescent, - box2.q_minimumAscent, height2); - QRectF rect1 = item1->geometryWithin(0.0, 0.0, FLT_MAX, height1, - rowDescent1); - QRectF rect2 = item2->geometryWithin(0.0, 0.0, FLT_MAX, height2, - rowDescent2); - spacing -= (height1 - (rect1.y() + rect1.height())) + rect2.y(); - } - rowSpacing = qMax(spacing, rowSpacing); - } - } - } - prevRow = row; - } - } else if (lastRowIsButtonBox || lastTwoRowsIsButtonBox) { - /* - Even for styles that define a uniform spacing, we cheat a - bit and use the window margin as the spacing. This - significantly improves the look of dialogs. - */ - int prevRow = lastRowIsButtonBox ? nextToLastRowAdHocData.q_row - : nextToNextToLastRowAdHocData.q_row; - if (!defaultSpacing.isUser() && !rowInfo.spacings.value(prevRow).isUser()) { - qreal windowMargin = style->pixelMetric(orientation == Qt::Vertical - ? QStyle::PM_LayoutBottomMargin - : QStyle::PM_LayoutRightMargin, - &option, styleInfo.widget()); - - qreal &rowSpacing = rowData->spacings[prevRow]; - rowSpacing = qMax(windowMargin, rowSpacing); - } - } -} - -void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const -{ - if (q_cachedEffectiveFirstRows[Hor] == -1 && !q_items.isEmpty()) { - int rowCount = this->rowCount(); - int columnCount = this->columnCount(); - - q_cachedEffectiveFirstRows[Ver] = rowCount; - q_cachedEffectiveFirstRows[Hor] = columnCount; - q_cachedEffectiveLastRows[Ver] = -1; - q_cachedEffectiveLastRows[Hor] = -1; - - for (int i = q_items.count() - 1; i >= 0; --i) { - const QGridLayoutItem *item = q_items.at(i); - - for (int j = 0; j < NOrientations; ++j) { - Qt::Orientation orientation = (j == Hor) ? Qt::Horizontal : Qt::Vertical; - if (item->firstRow(orientation) < q_cachedEffectiveFirstRows[j]) - q_cachedEffectiveFirstRows[j] = item->firstRow(orientation); - if (item->lastRow(orientation) > q_cachedEffectiveLastRows[j]) - q_cachedEffectiveLastRows[j] = item->lastRow(orientation); - } - } - } -} - -void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox, - const QLayoutStyleInfo &styleInfo, - qreal *colPositions, qreal *colSizes, - Qt::Orientation orientation) const -{ - rowData->reset(rowCount(orientation)); - fillRowData(rowData, styleInfo, colPositions, colSizes, orientation); - const QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; - rowData->distributeMultiCells(rowInfo); - *totalBox = rowData->totalBox(0, rowCount(orientation)); - //We have items whose width depends on their height -} - -/** - returns false if the layout has contradicting constraints (i.e. some items with a horizontal - constraint and other items with a vertical constraint) - */ -bool QGridLayoutEngine::ensureDynamicConstraint() const -{ - if (q_cachedConstraintOrientation == UnknownConstraint) { - for (int i = q_items.count() - 1; i >= 0; --i) { - QGridLayoutItem *item = q_items.at(i); - if (item->hasDynamicConstraint()) { - Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation(); - if (q_cachedConstraintOrientation == UnknownConstraint) { - q_cachedConstraintOrientation = itemConstraintOrientation; - } else if (q_cachedConstraintOrientation != itemConstraintOrientation) { - q_cachedConstraintOrientation = UnfeasibleConstraint; - qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and" - " vertical constraint in the same layout"); - return false; - } - } - } - if (q_cachedConstraintOrientation == UnknownConstraint) - q_cachedConstraintOrientation = NoConstraint; - } - return true; -} - -bool QGridLayoutEngine::hasDynamicConstraint() const -{ - if (!ensureDynamicConstraint()) - return false; - return q_cachedConstraintOrientation != NoConstraint; -} - -/* - * return value is only valid if hasConstraint() returns true - */ -Qt::Orientation QGridLayoutEngine::constraintOrientation() const -{ - (void)ensureDynamicConstraint(); - return (Qt::Orientation)q_cachedConstraintOrientation; -} - -void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, - const QSizeF &size) const -{ - if (q_cachedDataForStyleInfo == styleInfo && q_cachedSize == size) - return; - - q_cachedDataForStyleInfo = styleInfo; - q_cachedSize = size; - - q_xx.resize(columnCount()); - q_widths.resize(columnCount()); - q_yy.resize(rowCount()); - q_heights.resize(rowCount()); - q_descents.resize(rowCount()); - - if (constraintOrientation() != Qt::Horizontal) { - //We might have items whose width depends on their height - ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); - //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as - //constraints to find the row heights - q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), - 0, q_totalBoxes[Hor], q_infos[Hor] ); - ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, q_xx.data(), q_widths.data(), Qt::Vertical); - //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() - q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), - q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]); - } else { - //We have items whose height depends on their width - ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); - //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as - //constraints to find the column widths - q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(), - q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]); - ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, q_yy.data(), q_heights.data(), Qt::Horizontal); - //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() - q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(), - 0, q_totalBoxes[Hor], q_infos[Hor]); - } -} - -QT_END_NAMESPACE - -#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h deleted file mode 100644 index f947d67d5a..0000000000 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ /dev/null @@ -1,458 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRIDLAYOUTENGINE_P_H -#define QGRIDLAYOUTENGINE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the graphics view layout classes. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qalgorithms.h" -#include "qbitarray.h" -#include "qlist.h" -#include "qmap.h" -#include "qpair.h" -#include "qvector.h" -#include "qgraphicslayout_p.h" -#include <float.h> - -QT_BEGIN_NAMESPACE - -class QGraphicsLayoutItem; -class QStyle; -class QWidget; - -// ### deal with Descent in a similar way -enum { - MinimumSize = Qt::MinimumSize, - PreferredSize = Qt::PreferredSize, - MaximumSize = Qt::MaximumSize, - NSizes -}; - -// do not reorder -enum { - Hor, - Ver, - NOrientations -}; - -// do not reorder -enum LayoutSide { - Left, - Top, - Right, - Bottom -}; - -enum { - NoConstraint, - HorizontalConstraint, // Width depends on the height - VerticalConstraint, // Height depends on the width - UnknownConstraint, // need to update cache - UnfeasibleConstraint // not feasible, it be has some items with Vertical and others with Horizontal constraints -}; - -template <typename T> -class QLayoutParameter -{ -public: - enum State { Default, User, Cached }; - - inline QLayoutParameter() : q_value(T()), q_state(Default) {} - inline QLayoutParameter(T value, State state = Default) : q_value(value), q_state(state) {} - - inline void setUserValue(T value) { - q_value = value; - q_state = User; - } - inline void setCachedValue(T value) const { - if (q_state != User) { - q_value = value; - q_state = Cached; - } - } - inline T value() const { return q_value; } - inline T value(T defaultValue) const { return isUser() ? q_value : defaultValue; } - inline bool isDefault() const { return q_state == Default; } - inline bool isUser() const { return q_state == User; } - inline bool isCached() const { return q_state == Cached; } - -private: - mutable T q_value; - mutable State q_state; -}; - -class QStretchParameter : public QLayoutParameter<int> -{ -public: - QStretchParameter() : QLayoutParameter<int>(-1) {} - -}; - -class QGridLayoutBox -{ -public: - inline QGridLayoutBox() - : q_minimumSize(0), q_preferredSize(0), q_maximumSize(FLT_MAX), - q_minimumDescent(-1), q_minimumAscent(-1) {} - - void add(const QGridLayoutBox &other, int stretch, qreal spacing); - void combine(const QGridLayoutBox &other); - void normalize(); - -#ifdef QT_DEBUG - void dump(int indent = 0) const; -#endif - // This code could use the union-struct-array trick, but a compiler - // bug prevents this from working. - qreal q_minimumSize; - qreal q_preferredSize; - qreal q_maximumSize; - qreal q_minimumDescent; - qreal q_minimumAscent; - inline qreal &q_sizes(int which) - { - qreal *t; - switch (which) { - case Qt::MinimumSize: - t = &q_minimumSize; - break; - case Qt::PreferredSize: - t = &q_preferredSize; - break; - case Qt::MaximumSize: - t = &q_maximumSize; - break; - case Qt::MinimumDescent: - t = &q_minimumDescent; - break; - case (Qt::MinimumDescent + 1): - t = &q_minimumAscent; - break; - default: - t = 0; - break; - } - return *t; - } - inline const qreal &q_sizes(int which) const - { - const qreal *t; - switch (which) { - case Qt::MinimumSize: - t = &q_minimumSize; - break; - case Qt::PreferredSize: - t = &q_preferredSize; - break; - case Qt::MaximumSize: - t = &q_maximumSize; - break; - case Qt::MinimumDescent: - t = &q_minimumDescent; - break; - case (Qt::MinimumDescent + 1): - t = &q_minimumAscent; - break; - default: - t = 0; - break; - } - return *t; - } -}; - -bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2); -inline bool operator!=(const QGridLayoutBox &box1, const QGridLayoutBox &box2) - { return !operator==(box1, box2); } - -class QGridLayoutMultiCellData -{ -public: - inline QGridLayoutMultiCellData() : q_stretch(-1) {} - - QGridLayoutBox q_box; - int q_stretch; -}; - -typedef QMap<QPair<int, int>, QGridLayoutMultiCellData> MultiCellMap; - -class QGridLayoutRowInfo; - -class QGridLayoutRowData -{ -public: - void reset(int count); - void distributeMultiCells(const QGridLayoutRowInfo &rowInfo); - void calculateGeometries(int start, int end, qreal targetSize, qreal *positions, qreal *sizes, - qreal *descents, const QGridLayoutBox &totalBox, - const QGridLayoutRowInfo &rowInfo); - QGridLayoutBox totalBox(int start, int end) const; - void stealBox(int start, int end, int which, qreal *positions, qreal *sizes); - -#ifdef QT_DEBUG - void dump(int indent = 0) const; -#endif - - QBitArray ignore; // ### rename q_ - QVector<QGridLayoutBox> boxes; - MultiCellMap multiCellMap; - QVector<int> stretches; - QVector<qreal> spacings; - bool hasIgnoreFlag; -}; - -class QGridLayoutEngine; - -class QGridLayoutItem -{ -public: - QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, int row, int column, - int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0, - int itemAtIndex = -1); - - inline int firstRow() const { return q_firstRows[Ver]; } - inline int firstColumn() const { return q_firstRows[Hor]; } - inline int rowSpan() const { return q_rowSpans[Ver]; } - inline int columnSpan() const { return q_rowSpans[Hor]; } - inline int lastRow() const { return firstRow() + rowSpan() - 1; } - inline int lastColumn() const { return firstColumn() + columnSpan() - 1; } - - int firstRow(Qt::Orientation orientation) const; - int firstColumn(Qt::Orientation orientation) const; - int lastRow(Qt::Orientation orientation) const; - int lastColumn(Qt::Orientation orientation) const; - int rowSpan(Qt::Orientation orientation) const; - int columnSpan(Qt::Orientation orientation) const; - void setFirstRow(int row, Qt::Orientation orientation = Qt::Vertical); - void setRowSpan(int rowSpan, Qt::Orientation orientation = Qt::Vertical); - - int stretchFactor(Qt::Orientation orientation) const; - void setStretchFactor(int stretch, Qt::Orientation orientation); - - inline Qt::Alignment alignment() const { return q_alignment; } - inline void setAlignment(Qt::Alignment alignment) { q_alignment = alignment; } - - QSizePolicy::Policy sizePolicy(Qt::Orientation orientation) const; - - bool hasDynamicConstraint() const; - Qt::Orientation dynamicConstraintOrientation() const; - - QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; - QGridLayoutBox box(Qt::Orientation orientation, qreal constraint = -1.0) const; - QRectF geometryWithin(qreal x, qreal y, qreal width, qreal height, qreal rowDescent) const; - - QGraphicsLayoutItem *layoutItem() const { return q_layoutItem; } - - void setGeometry(const QRectF &rect); - void transpose(); - void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical); - QSizeF effectiveMaxSize(const QSizeF &constraint) const; - -#ifdef QT_DEBUG - void dump(int indent = 0) const; -#endif - -private: - QGridLayoutEngine *q_engine; // ### needed? - QGraphicsLayoutItem *q_layoutItem; - int q_firstRows[NOrientations]; - int q_rowSpans[NOrientations]; - int q_stretches[NOrientations]; - Qt::Alignment q_alignment; -}; - -class QGridLayoutRowInfo -{ -public: - inline QGridLayoutRowInfo() : count(0) {} - - void insertOrRemoveRows(int row, int delta); - -#ifdef QT_DEBUG - void dump(int indent = 0) const; -#endif - - int count; - QVector<QStretchParameter> stretches; - QVector<QLayoutParameter<qreal> > spacings; - QVector<Qt::Alignment> alignments; - QVector<QGridLayoutBox> boxes; -}; - -class QGridLayoutEngine -{ -public: - QGridLayoutEngine(); - inline ~QGridLayoutEngine() { qDeleteAll(q_items); } - - int rowCount(Qt::Orientation orientation) const; - int columnCount(Qt::Orientation orientation) const; - inline int rowCount() const { return q_infos[Ver].count; } - inline int columnCount() const { return q_infos[Hor].count; } - // returns the number of items inserted, which may be less than (rowCount * columnCount) - int itemCount() const; - QGridLayoutItem *itemAt(int index) const; - int indexOf(QGraphicsLayoutItem *item) const; - - int effectiveFirstRow(Qt::Orientation orientation = Qt::Vertical) const; - int effectiveLastRow(Qt::Orientation orientation = Qt::Vertical) const; - - void setSpacing(qreal spacing, Qt::Orientations orientations); - qreal spacing(const QLayoutStyleInfo &styleInfo, Qt::Orientation orientation) const; - // ### setSpacingAfterRow(), spacingAfterRow() - void setRowSpacing(int row, qreal spacing, Qt::Orientation orientation = Qt::Vertical); - qreal rowSpacing(int row, Qt::Orientation orientation = Qt::Vertical) const; - - void setRowStretchFactor(int row, int stretch, Qt::Orientation orientation = Qt::Vertical); - int rowStretchFactor(int row, Qt::Orientation orientation = Qt::Vertical) const; - - void setStretchFactor(QGraphicsLayoutItem *layoutItem, int stretch, - Qt::Orientation orientation); - int stretchFactor(QGraphicsLayoutItem *layoutItem, Qt::Orientation orientation) const; - - void setRowSizeHint(Qt::SizeHint which, int row, qreal size, - Qt::Orientation orientation = Qt::Vertical); - qreal rowSizeHint(Qt::SizeHint which, int row, - Qt::Orientation orientation = Qt::Vertical) const; - - void setRowAlignment(int row, Qt::Alignment alignment, Qt::Orientation orientation); - Qt::Alignment rowAlignment(int row, Qt::Orientation orientation) const; - - void setAlignment(QGraphicsLayoutItem *layoutItem, Qt::Alignment alignment); - Qt::Alignment alignment(QGraphicsLayoutItem *layoutItem) const; - Qt::Alignment effectiveAlignment(const QGridLayoutItem *layoutItem) const; - - - void insertItem(QGridLayoutItem *item, int index); - void addItem(QGridLayoutItem *item); - void removeItem(QGridLayoutItem *item); - QGridLayoutItem *findLayoutItem(QGraphicsLayoutItem *layoutItem) const; - QGridLayoutItem *itemAt(int row, int column, Qt::Orientation orientation = Qt::Vertical) const; - inline void insertRow(int row, Qt::Orientation orientation = Qt::Vertical) - { insertOrRemoveRows(row, +1, orientation); } - inline void removeRows(int row, int count, Qt::Orientation orientation) - { insertOrRemoveRows(row, -count, orientation); } - - void invalidate(); - void setGeometries(const QLayoutStyleInfo &styleInfo, const QRectF &contentsGeometry); - QRectF cellRect(const QLayoutStyleInfo &styleInfo, const QRectF &contentsGeometry, int row, - int column, int rowSpan, int columnSpan) const; - QSizeF sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, - const QSizeF &constraint) const; - - // heightForWidth / widthForHeight support - QSizeF dynamicallyConstrainedSizeHint(Qt::SizeHint which, const QSizeF &constraint) const; - bool ensureDynamicConstraint() const; - bool hasDynamicConstraint() const; - Qt::Orientation constraintOrientation() const; - - - QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; - void transpose(); - void setVisualDirection(Qt::LayoutDirection direction); - Qt::LayoutDirection visualDirection() const; -#ifdef QT_DEBUG - void dump(int indent = 0) const; -#endif - -private: - static int grossRoundUp(int n) { return ((n + 2) | 0x3) - 2; } - - void maybeExpandGrid(int row, int column, Qt::Orientation orientation = Qt::Vertical); - void regenerateGrid(); - inline int internalGridRowCount() const { return grossRoundUp(rowCount()); } - inline int internalGridColumnCount() const { return grossRoundUp(columnCount()); } - void setItemAt(int row, int column, QGridLayoutItem *item); - void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical); - void fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo, - qreal *colPositions, qreal *colSizes, - Qt::Orientation orientation = Qt::Vertical) const; - void ensureEffectiveFirstAndLastRows() const; - void ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox, - const QLayoutStyleInfo &styleInfo, - qreal *colPositions, qreal *colSizes, - Qt::Orientation orientation) const; - - void ensureGeometries(const QLayoutStyleInfo &styleInfo, const QSizeF &size) const; - - // User input - QVector<QGridLayoutItem *> q_grid; - QList<QGridLayoutItem *> q_items; - QLayoutParameter<qreal> q_defaultSpacings[NOrientations]; - QGridLayoutRowInfo q_infos[NOrientations]; - Qt::LayoutDirection m_visualDirection; - - // Lazily computed from the above user input - mutable int q_cachedEffectiveFirstRows[NOrientations]; - mutable int q_cachedEffectiveLastRows[NOrientations]; - mutable quint8 q_cachedConstraintOrientation : 3; - - // Layout item input - mutable QLayoutStyleInfo q_cachedDataForStyleInfo; - mutable QGridLayoutRowData q_columnData; - mutable QGridLayoutRowData q_rowData; - mutable QGridLayoutBox q_totalBoxes[NOrientations]; - - // Output - mutable QSizeF q_cachedSize; - mutable QVector<qreal> q_xx; - mutable QVector<qreal> q_yy; - mutable QVector<qreal> q_widths; - mutable QVector<qreal> q_heights; - mutable QVector<qreal> q_descents; - - friend class QGridLayoutItem; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp deleted file mode 100644 index eb8bcb8c1f..0000000000 --- a/src/gui/graphicsview/qsimplex_p.cpp +++ /dev/null @@ -1,673 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsimplex_p.h" - -#include <QtCore/qset.h> -#include <QtCore/qdebug.h> - -#include <stdlib.h> - -QT_BEGIN_NAMESPACE - -/*! - \internal - \class QSimplex - - The QSimplex class is a Linear Programming problem solver based on the two-phase - simplex method. - - It takes a set of QSimplexConstraints as its restrictive constraints and an - additional QSimplexConstraint as its objective function. Then methods to maximize - and minimize the problem solution are provided. - - The two-phase simplex method is based on the following steps: - First phase: - 1.a) Modify the original, complex, and possibly not feasible problem, into a new, - easy to solve problem. - 1.b) Set as the objective of the new problem, a feasible solution for the original - complex problem. - 1.c) Run simplex to optimize the modified problem and check whether a solution for - the original problem exists. - - Second phase: - 2.a) Go back to the original problem with the feasibl (but not optimal) solution - found in the first phase. - 2.b) Set the original objective. - 3.c) Run simplex to optimize the original problem towards its optimal solution. -*/ - -/*! - \internal -*/ -QSimplex::QSimplex() : objective(0), rows(0), columns(0), firstArtificial(0), matrix(0) -{ -} - -/*! - \internal -*/ -QSimplex::~QSimplex() -{ - clearDataStructures(); -} - -/*! - \internal -*/ -void QSimplex::clearDataStructures() -{ - if (matrix == 0) - return; - - // Matrix - rows = 0; - columns = 0; - firstArtificial = 0; - free(matrix); - matrix = 0; - - // Constraints - for (int i = 0; i < constraints.size(); ++i) { - delete constraints[i]->helper.first; - delete constraints[i]->artificial; - delete constraints[i]; - } - constraints.clear(); - - // Other - variables.clear(); - objective = 0; -} - -/*! - \internal - Sets the new constraints in the simplex solver and returns whether the problem - is feasible. - - This method sets the new constraints, normalizes them, creates the simplex matrix - and runs the first simplex phase. -*/ -bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) -{ - //////////////////////////// - // Reset to initial state // - //////////////////////////// - clearDataStructures(); - - if (newConstraints.isEmpty()) - return true; // we are ok with no constraints - - // Make deep copy of constraints. We need this copy because we may change - // them in the simplification method. - for (int i = 0; i < newConstraints.size(); ++i) { - QSimplexConstraint *c = new QSimplexConstraint; - c->constant = newConstraints[i]->constant; - c->ratio = newConstraints[i]->ratio; - c->variables = newConstraints[i]->variables; - constraints << c; - } - - // Remove constraints of type Var == K and replace them for their value. - if (!simplifyConstraints(&constraints)) { - qWarning() << "QSimplex: No feasible solution!"; - clearDataStructures(); - return false; - } - - /////////////////////////////////////// - // Prepare variables and constraints // - /////////////////////////////////////// - - // Set Variables direct mapping. - // "variables" is a list that provides a stable, indexed list of all variables - // used in this problem. - QSet<QSimplexVariable *> variablesSet; - for (int i = 0; i < constraints.size(); ++i) - variablesSet += \ - QSet<QSimplexVariable *>::fromList(constraints[i]->variables.keys()); - variables = variablesSet.toList(); - - // Set Variables reverse mapping - // We also need to be able to find the index for a given variable, to do that - // we store in each variable its index. - for (int i = 0; i < variables.size(); ++i) { - // The variable "0" goes at the column "1", etc... - variables[i]->index = i + 1; - } - - // Normalize Constraints - // In this step, we prepare the constraints in two ways: - // Firstly, we modify all constraints of type "LessOrEqual" or "MoreOrEqual" - // by the adding slack or surplus variables and making them "Equal" constraints. - // Secondly, we need every single constraint to have a direct, easy feasible - // solution. Constraints that have slack variables are already easy to solve, - // to all the others we add artificial variables. - // - // At the end we modify the constraints as follows: - // - LessOrEqual: SLACK variable is added. - // - Equal: ARTIFICIAL variable is added. - // - More or Equal: ARTIFICIAL and SURPLUS variables are added. - int variableIndex = variables.size(); - QList <QSimplexVariable *> artificialList; - - for (int i = 0; i < constraints.size(); ++i) { - QSimplexVariable *slack; - QSimplexVariable *surplus; - QSimplexVariable *artificial; - - Q_ASSERT(constraints[i]->helper.first == 0); - Q_ASSERT(constraints[i]->artificial == 0); - - switch(constraints[i]->ratio) { - case QSimplexConstraint::LessOrEqual: - slack = new QSimplexVariable; - slack->index = ++variableIndex; - constraints[i]->helper.first = slack; - constraints[i]->helper.second = 1.0; - break; - case QSimplexConstraint::MoreOrEqual: - surplus = new QSimplexVariable; - surplus->index = ++variableIndex; - constraints[i]->helper.first = surplus; - constraints[i]->helper.second = -1.0; - // fall through - case QSimplexConstraint::Equal: - artificial = new QSimplexVariable; - constraints[i]->artificial = artificial; - artificialList += constraints[i]->artificial; - break; - } - } - - // All original, slack and surplus have already had its index set - // at this point. We now set the index of the artificial variables - // as to ensure they are at the end of the variable list and therefore - // can be easily removed at the end of this method. - firstArtificial = variableIndex + 1; - for (int i = 0; i < artificialList.size(); ++i) - artificialList[i]->index = ++variableIndex; - artificialList.clear(); - - ///////////////////////////// - // Fill the Simplex matrix // - ///////////////////////////// - - // One for each variable plus the Basic and BFS columns (first and last) - columns = variableIndex + 2; - // One for each constraint plus the objective function - rows = constraints.size() + 1; - - matrix = (qreal *)malloc(sizeof(qreal) * columns * rows); - if (!matrix) { - qWarning() << "QSimplex: Unable to allocate memory!"; - return false; - } - for (int i = columns * rows - 1; i >= 0; --i) - matrix[i] = 0.0; - - // Fill Matrix - for (int i = 1; i <= constraints.size(); ++i) { - QSimplexConstraint *c = constraints[i - 1]; - - if (c->artificial) { - // Will use artificial basic variable - setValueAt(i, 0, c->artificial->index); - setValueAt(i, c->artificial->index, 1.0); - - if (c->helper.second != 0.0) { - // Surplus variable - setValueAt(i, c->helper.first->index, c->helper.second); - } - } else { - // Slack is used as the basic variable - Q_ASSERT(c->helper.second == 1.0); - setValueAt(i, 0, c->helper.first->index); - setValueAt(i, c->helper.first->index, 1.0); - } - - QHash<QSimplexVariable *, qreal>::const_iterator iter; - for (iter = c->variables.constBegin(); - iter != c->variables.constEnd(); - ++iter) { - setValueAt(i, iter.key()->index, iter.value()); - } - - setValueAt(i, columns - 1, c->constant); - } - - // Set objective for the first-phase Simplex. - // Z = -1 * sum_of_artificial_vars - for (int j = firstArtificial; j < columns - 1; ++j) - setValueAt(0, j, 1.0); - - // Maximize our objective (artificial vars go to zero) - solveMaxHelper(); - - // If there is a solution where the sum of all artificial - // variables is zero, then all of them can be removed and yet - // we will have a feasible (but not optimal) solution for the - // original problem. - // Otherwise, we clean up our structures and report there is - // no feasible solution. - if ((valueAt(0, columns - 1) != 0.0) && (qAbs(valueAt(0, columns - 1)) > 0.00001)) { - qWarning() << "QSimplex: No feasible solution!"; - clearDataStructures(); - return false; - } - - // Remove artificial variables. We already have a feasible - // solution for the first problem, thus we don't need them - // anymore. - clearColumns(firstArtificial, columns - 2); - - return true; -} - -/*! - \internal - - Run simplex on the current matrix with the current objective. - - This is the iterative method. The matrix lines are combined - as to modify the variable values towards the best solution possible. - The method returns when the matrix is in the optimal state. -*/ -void QSimplex::solveMaxHelper() -{ - reducedRowEchelon(); - while (iterate()) ; -} - -/*! - \internal -*/ -void QSimplex::setObjective(QSimplexConstraint *newObjective) -{ - objective = newObjective; -} - -/*! - \internal -*/ -void QSimplex::clearRow(int rowIndex) -{ - qreal *item = matrix + rowIndex * columns; - for (int i = 0; i < columns; ++i) - item[i] = 0.0; -} - -/*! - \internal -*/ -void QSimplex::clearColumns(int first, int last) -{ - for (int i = 0; i < rows; ++i) { - qreal *row = matrix + i * columns; - for (int j = first; j <= last; ++j) - row[j] = 0.0; - } -} - -/*! - \internal -*/ -void QSimplex::dumpMatrix() -{ - qDebug("---- Simplex Matrix ----\n"); - - QString str(QLatin1String(" ")); - for (int j = 0; j < columns; ++j) - str += QString::fromAscii(" <%1 >").arg(j, 2); - qDebug("%s", qPrintable(str)); - for (int i = 0; i < rows; ++i) { - str = QString::fromAscii("Row %1:").arg(i, 2); - - qreal *row = matrix + i * columns; - for (int j = 0; j < columns; ++j) - str += QString::fromAscii("%1").arg(row[j], 7, 'f', 2); - qDebug("%s", qPrintable(str)); - } - qDebug("------------------------\n"); -} - -/*! - \internal -*/ -void QSimplex::combineRows(int toIndex, int fromIndex, qreal factor) -{ - if (!factor) - return; - - qreal *from = matrix + fromIndex * columns; - qreal *to = matrix + toIndex * columns; - - for (int j = 1; j < columns; ++j) { - qreal value = from[j]; - - // skip to[j] = to[j] + factor*0.0 - if (value == 0.0) - continue; - - to[j] += factor * value; - - // ### Avoid Numerical errors - if (qAbs(to[j]) < 0.0000000001) - to[j] = 0.0; - } -} - -/*! - \internal -*/ -int QSimplex::findPivotColumn() -{ - qreal min = 0; - int minIndex = -1; - - for (int j = 0; j < columns-1; ++j) { - if (valueAt(0, j) < min) { - min = valueAt(0, j); - minIndex = j; - } - } - - return minIndex; -} - -/*! - \internal - - For a given pivot column, find the pivot row. That is, the row with the - minimum associated "quotient" where: - - - quotient is the division of the value in the last column by the value - in the pivot column. - - rows with value less or equal to zero are ignored - - if two rows have the same quotient, lines are chosen based on the - highest variable index (value in the first column) - - The last condition avoids a bug where artificial variables would be - left behind for the second-phase simplex, and with 'good' - constraints would be removed before it, what would lead to incorrect - results. -*/ -int QSimplex::pivotRowForColumn(int column) -{ - qreal min = qreal(999999999999.0); // ### - int minIndex = -1; - - for (int i = 1; i < rows; ++i) { - qreal divisor = valueAt(i, column); - if (divisor <= 0) - continue; - - qreal quotient = valueAt(i, columns - 1) / divisor; - if (quotient < min) { - min = quotient; - minIndex = i; - } else if ((quotient == min) && (valueAt(i, 0) > valueAt(minIndex, 0))) { - minIndex = i; - } - } - - return minIndex; -} - -/*! - \internal -*/ -void QSimplex::reducedRowEchelon() -{ - for (int i = 1; i < rows; ++i) { - int factorInObjectiveRow = valueAt(i, 0); - combineRows(0, i, -1 * valueAt(0, factorInObjectiveRow)); - } -} - -/*! - \internal - - Does one iteration towards a better solution for the problem. - See 'solveMaxHelper'. -*/ -bool QSimplex::iterate() -{ - // Find Pivot column - int pivotColumn = findPivotColumn(); - if (pivotColumn == -1) - return false; - - // Find Pivot row for column - int pivotRow = pivotRowForColumn(pivotColumn); - if (pivotRow == -1) { - qWarning() << "QSimplex: Unbounded problem!"; - return false; - } - - // Normalize Pivot Row - qreal pivot = valueAt(pivotRow, pivotColumn); - if (pivot != 1.0) - combineRows(pivotRow, pivotRow, (1.0 - pivot) / pivot); - - // Update other rows - for (int row=0; row < rows; ++row) { - if (row == pivotRow) - continue; - - combineRows(row, pivotRow, -1 * valueAt(row, pivotColumn)); - } - - // Update first column - setValueAt(pivotRow, 0, pivotColumn); - - // dumpMatrix(); - // qDebug("------------ end of iteration --------------\n"); - return true; -} - -/*! - \internal - - Both solveMin and solveMax are interfaces to this method. - - The enum solverFactor admits 2 values: Minimum (-1) and Maximum (+1). - - This method sets the original objective and runs the second phase - Simplex to obtain the optimal solution for the problem. As the internal - simplex solver is only able to _maximize_ objectives, we handle the - minimization case by inverting the original objective and then - maximizing it. -*/ -qreal QSimplex::solver(solverFactor factor) -{ - // Remove old objective - clearRow(0); - - // Set new objective in the first row of the simplex matrix - qreal resultOffset = 0; - QHash<QSimplexVariable *, qreal>::const_iterator iter; - for (iter = objective->variables.constBegin(); - iter != objective->variables.constEnd(); - ++iter) { - - // Check if the variable was removed in the simplification process. - // If so, we save its offset to the objective function and skip adding - // it to the matrix. - if (iter.key()->index == -1) { - resultOffset += iter.value() * iter.key()->result; - continue; - } - - setValueAt(0, iter.key()->index, -1 * factor * iter.value()); - } - - solveMaxHelper(); - collectResults(); - -#ifdef QT_DEBUG - for (int i = 0; i < constraints.size(); ++i) { - Q_ASSERT(constraints[i]->isSatisfied()); - } -#endif - - // Return the value calculated by the simplex plus the value of the - // fixed variables. - return (factor * valueAt(0, columns - 1)) + resultOffset; -} - -/*! - \internal - Minimize the original objective. -*/ -qreal QSimplex::solveMin() -{ - return solver(Minimum); -} - -/*! - \internal - Maximize the original objective. -*/ -qreal QSimplex::solveMax() -{ - return solver(Maximum); -} - -/*! - \internal - - Reads results from the simplified matrix and saves them in the - "result" member of each QSimplexVariable. -*/ -void QSimplex::collectResults() -{ - // All variables are zero unless overridden below. - - // ### Is this really needed? Is there any chance that an - // important variable remains as non-basic at the end of simplex? - for (int i = 0; i < variables.size(); ++i) - variables[i]->result = 0; - - // Basic variables - // Update the variable indicated in the first column with the value - // in the last column. - for (int i = 1; i < rows; ++i) { - int index = valueAt(i, 0) - 1; - if (index < variables.size()) - variables[index]->result = valueAt(i, columns - 1); - } -} - -/*! - \internal - - Looks for single-valued variables and remove them from the constraints list. -*/ -bool QSimplex::simplifyConstraints(QList<QSimplexConstraint *> *constraints) -{ - QHash<QSimplexVariable *, qreal> results; // List of single-valued variables - bool modified = true; // Any chance more optimization exists? - - while (modified) { - modified = false; - - // For all constraints - QList<QSimplexConstraint *>::iterator iter = constraints->begin(); - while (iter != constraints->end()) { - QSimplexConstraint *c = *iter; - if ((c->ratio == QSimplexConstraint::Equal) && (c->variables.count() == 1)) { - // Check whether this is a constraint of type Var == K - // If so, save its value to "results". - QSimplexVariable *variable = c->variables.constBegin().key(); - qreal result = c->constant / c->variables.value(variable); - - results.insert(variable, result); - variable->result = result; - variable->index = -1; - modified = true; - - } - - // Replace known values among their variables - QHash<QSimplexVariable *, qreal>::const_iterator r; - for (r = results.constBegin(); r != results.constEnd(); ++r) { - if (c->variables.contains(r.key())) { - c->constant -= r.value() * c->variables.take(r.key()); - modified = true; - } - } - - // Keep it normalized - if (c->constant < 0) - c->invert(); - - if (c->variables.isEmpty()) { - // If constraint became empty due to substitution, delete it. - if (c->isSatisfied() == false) - // We must ensure that the constraint soon to be deleted would not - // make the problem unfeasible if left behind. If that's the case, - // we return false so the simplex solver can properly report that. - return false; - - delete c; - iter = constraints->erase(iter); - } else { - ++iter; - } - } - } - - return true; -} - -void QSimplexConstraint::invert() -{ - constant = -constant; - ratio = Ratio(2 - ratio); - - QHash<QSimplexVariable *, qreal>::iterator iter; - for (iter = variables.begin(); iter != variables.end(); ++iter) { - iter.value() = -iter.value(); - } -} - -QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h deleted file mode 100644 index 3df82c6ccf..0000000000 --- a/src/gui/graphicsview/qsimplex_p.h +++ /dev/null @@ -1,208 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSIMPLEX_P_H -#define QSIMPLEX_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qhash.h> -#include <QtCore/qpair.h> - -QT_BEGIN_NAMESPACE - -struct QSimplexVariable -{ - QSimplexVariable() : result(0), index(0) {} - - qreal result; - int index; -}; - - -/*! - \internal - - Representation of a LP constraint like: - - (c1 * X1) + (c2 * X2) + ... = K - or <= K - or >= K - - Where (ci, Xi) are the pairs in "variables" and K the real "constant". -*/ -struct QSimplexConstraint -{ - QSimplexConstraint() : constant(0), ratio(Equal), artificial(0) {} - - enum Ratio { - LessOrEqual = 0, - Equal, - MoreOrEqual - }; - - QHash<QSimplexVariable *, qreal> variables; - qreal constant; - Ratio ratio; - - QPair<QSimplexVariable *, qreal> helper; - QSimplexVariable * artificial; - - void invert(); - - bool isSatisfied() { - qreal leftHandSide(0); - - QHash<QSimplexVariable *, qreal>::const_iterator iter; - for (iter = variables.constBegin(); iter != variables.constEnd(); ++iter) { - leftHandSide += iter.value() * iter.key()->result; - } - - Q_ASSERT(constant > 0 || qFuzzyCompare(1, 1 + constant)); - - if ((leftHandSide == constant) || qAbs(leftHandSide - constant) < 0.0000001) - return true; - - switch (ratio) { - case LessOrEqual: - return leftHandSide < constant; - case MoreOrEqual: - return leftHandSide > constant; - default: - return false; - } - } - -#ifdef QT_DEBUG - QString toString() { - QString result; - result += QString::fromAscii("-- QSimplexConstraint %1 --").arg(quintptr(this), 0, 16); - - QHash<QSimplexVariable *, qreal>::const_iterator iter; - for (iter = variables.constBegin(); iter != variables.constEnd(); ++iter) { - result += QString::fromAscii(" %1 x %2").arg(iter.value()).arg(quintptr(iter.key()), 0, 16); - } - - switch (ratio) { - case LessOrEqual: - result += QString::fromAscii(" (less) <= %1").arg(constant); - break; - case MoreOrEqual: - result += QString::fromAscii(" (more) >= %1").arg(constant); - break; - default: - result += QString::fromAscii(" (eqal) == %1").arg(constant); - } - - return result; - } -#endif -}; - -class QSimplex -{ -public: - QSimplex(); - virtual ~QSimplex(); - - qreal solveMin(); - qreal solveMax(); - - bool setConstraints(const QList<QSimplexConstraint *> constraints); - void setObjective(QSimplexConstraint *objective); - - void dumpMatrix(); - -private: - // Matrix handling - qreal valueAt(int row, int column); - void setValueAt(int row, int column, qreal value); - void clearRow(int rowIndex); - void clearColumns(int first, int last); - void combineRows(int toIndex, int fromIndex, qreal factor); - - // Simplex - bool simplifyConstraints(QList<QSimplexConstraint *> *constraints); - int findPivotColumn(); - int pivotRowForColumn(int column); - void reducedRowEchelon(); - bool iterate(); - - // Helpers - void clearDataStructures(); - void solveMaxHelper(); - enum solverFactor { Minimum = -1, Maximum = 1 }; - qreal solver(solverFactor factor); - void collectResults(); - - QList<QSimplexConstraint *> constraints; - QList<QSimplexVariable *> variables; - QSimplexConstraint *objective; - - int rows; - int columns; - int firstArtificial; - - qreal *matrix; -}; - -inline qreal QSimplex::valueAt(int rowIndex, int columnIndex) -{ - return matrix[rowIndex * columns + columnIndex]; -} - -inline void QSimplex::setValueAt(int rowIndex, int columnIndex, qreal value) -{ - matrix[rowIndex * columns + columnIndex] = value; -} - -QT_END_NAMESPACE - -#endif // QSIMPLEX_P_H |