diff options
-rw-r--r-- | src/gui/util/qabstractlayoutstyleinfo.cpp | 53 | ||||
-rw-r--r-- | src/gui/util/qabstractlayoutstyleinfo_p.h | 97 | ||||
-rw-r--r-- | src/gui/util/qlayoutpolicy.cpp | 136 | ||||
-rw-r--r-- | src/gui/util/qlayoutpolicy_p.h | 185 | ||||
-rw-r--r-- | src/gui/util/util.pri | 8 | ||||
-rw-r--r-- | src/widgets/graphicsview/graphicsview.pri | 4 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsgridlayout.cpp | 49 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp | 101 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h | 125 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp | 108 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h | 96 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicslinearlayout.cpp | 42 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgridlayoutengine.cpp | 267 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgridlayoutengine_p.h | 113 | ||||
-rw-r--r-- | tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp | 2 |
15 files changed, 1101 insertions, 285 deletions
diff --git a/src/gui/util/qabstractlayoutstyleinfo.cpp b/src/gui/util/qabstractlayoutstyleinfo.cpp new file mode 100644 index 0000000000..4f7c635594 --- /dev/null +++ b/src/gui/util/qabstractlayoutstyleinfo.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qabstractlayoutstyleinfo_p.h" + +QT_BEGIN_NAMESPACE + +bool QAbstractLayoutStyleInfo::hasChanged() const +{ + if (m_changed == Unknown) + m_changed = hasChangedCore() ? Changed : Unchanged; + return m_changed == Changed; +} + +QT_END_NAMESPACE diff --git a/src/gui/util/qabstractlayoutstyleinfo_p.h b/src/gui/util/qabstractlayoutstyleinfo_p.h new file mode 100644 index 0000000000..52f151c5d2 --- /dev/null +++ b/src/gui/util/qabstractlayoutstyleinfo_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTLAYOUTSTYLEINFO_P_H +#define QABSTRACTLAYOUTSTYLEINFO_P_H + +#include <QtCore/qnamespace.h> +#include "qlayoutpolicy_p.h" + +QT_BEGIN_NAMESPACE + + +class Q_GUI_EXPORT QAbstractLayoutStyleInfo { +public: + typedef enum { + Unknown = 0, + Changed, + Unchanged + } ChangedState; + + QAbstractLayoutStyleInfo() : m_isWindow(false), m_changed(Changed) {} + virtual ~QAbstractLayoutStyleInfo() {} + virtual qreal combinedLayoutSpacing(QLayoutPolicy::ControlTypes /*controls1*/, + QLayoutPolicy::ControlTypes /*controls2*/, Qt::Orientation /*orientation*/) const { + return -1; + } + + virtual qreal perItemSpacing(QLayoutPolicy::ControlType /*control1*/, + QLayoutPolicy::ControlType /*control2*/, + Qt::Orientation /*orientation*/) const { + return -1; + } + + virtual qreal spacing(Qt::Orientation orientation) const = 0; + + virtual bool hasChangedCore() const = 0; + + void updateChanged(ChangedState change) { + m_changed = change; + } + + bool hasChanged() const; + + virtual void invalidate() { updateChanged(Changed);} + + virtual qreal windowMargin(Qt::Orientation orientation) const = 0; + + bool isWindow() const { + return m_isWindow; + } + +protected: + unsigned m_isWindow : 1; + mutable unsigned m_changed : 2; +}; + +QT_END_NAMESPACE + +#endif // QABSTRACTLAYOUTSTYLEINFO_P_H diff --git a/src/gui/util/qlayoutpolicy.cpp b/src/gui/util/qlayoutpolicy.cpp new file mode 100644 index 0000000000..9a154768eb --- /dev/null +++ b/src/gui/util/qlayoutpolicy.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Layouts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlayoutpolicy_p.h" +#include <QtCore/qdebug.h> +#include <QtCore/qdatastream.h> + +QT_BEGIN_NAMESPACE + +void QLayoutPolicy::setControlType(ControlType type) +{ + /* + The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10, + etc. In memory, we pack it onto the available bits (CTSize) in + setControlType(), and unpack it here. + + Example: + + 0x00000001 maps to 0 + 0x00000002 maps to 1 + 0x00000004 maps to 2 + 0x00000008 maps to 3 + etc. + */ + + int i = 0; + while (true) { + if (type & (0x1 << i)) { + bits.ctype = i; + return; + } + ++i; + } +} + +QLayoutPolicy::ControlType QLayoutPolicy::controlType() const +{ + return QLayoutPolicy::ControlType(1 << bits.ctype); +} + +#ifndef QT_NO_DATASTREAM + +/*! + \relates QLayoutPolicy + + Writes the size \a policy to the data stream \a stream. + + \sa{Serializing Qt Data Types}{Format of the QDataStream operators} +*/ +QDataStream &operator<<(QDataStream &stream, const QLayoutPolicy &policy) +{ + // The order here is for historical reasons. (compatibility with Qt4) + quint32 data = (policy.bits.horPolicy | // [0, 3] + policy.bits.verPolicy << 4 | // [4, 7] + policy.bits.hfw << 8 | // [8] + policy.bits.ctype << 9 | // [9, 13] + policy.bits.wfh << 14 | // [14] + //policy.bits.padding << 15 | // [15] + policy.bits.verStretch << 16 | // [16, 23] + policy.bits.horStretch << 24); // [24, 31] + return stream << data; +} + +#define VALUE_OF_BITS(data, bitstart, bitcount) ((data >> bitstart) & ((1 << bitcount) -1)) + +/*! + \relates QLayoutPolicy + + Reads the size \a policy from the data stream \a stream. + + \sa{Serializing Qt Data Types}{Format of the QDataStream operators} +*/ +QDataStream &operator>>(QDataStream &stream, QLayoutPolicy &policy) +{ + quint32 data; + stream >> data; + policy.bits.horPolicy = VALUE_OF_BITS(data, 0, 4); + policy.bits.verPolicy = VALUE_OF_BITS(data, 4, 4); + policy.bits.hfw = VALUE_OF_BITS(data, 8, 1); + policy.bits.ctype = VALUE_OF_BITS(data, 9, 5); + policy.bits.wfh = VALUE_OF_BITS(data, 14, 1); + policy.bits.padding = 0; + policy.bits.verStretch = VALUE_OF_BITS(data, 16, 8); + policy.bits.horStretch = VALUE_OF_BITS(data, 24, 8); + return stream; +} +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QLayoutPolicy &p) +{ + dbg.nospace() << "QLayoutPolicy(horizontalPolicy = " << p.horizontalPolicy() + << ", verticalPolicy = " << p.verticalPolicy() << ')'; + return dbg.space(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/gui/util/qlayoutpolicy_p.h b/src/gui/util/qlayoutpolicy_p.h new file mode 100644 index 0000000000..664afef1a4 --- /dev/null +++ b/src/gui/util/qlayoutpolicy_p.h @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Layouts module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLAYOUTPOLICY_H +#define QLAYOUTPOLICY_H + +#include <QtCore/qobject.h> +#include <QtCore/qnamespace.h> + +#ifndef QT_NO_DATASTREAM +# include <QtCore/qdatastream.h> +#endif + +QT_BEGIN_NAMESPACE + + +class QVariant; + +class Q_GUI_EXPORT QLayoutPolicy +{ + Q_ENUMS(Policy) + +public: + enum PolicyFlag { + GrowFlag = 1, + ExpandFlag = 2, + ShrinkFlag = 4, + IgnoreFlag = 8 + }; + + enum Policy { + Fixed = 0, + Minimum = GrowFlag, + Maximum = ShrinkFlag, + Preferred = GrowFlag | ShrinkFlag, + MinimumExpanding = GrowFlag | ExpandFlag, + Expanding = GrowFlag | ShrinkFlag | ExpandFlag, + Ignored = ShrinkFlag | GrowFlag | IgnoreFlag + }; + + enum ControlType { + DefaultType = 0x00000001, + ButtonBox = 0x00000002, + CheckBox = 0x00000004, + ComboBox = 0x00000008, + Frame = 0x00000010, + GroupBox = 0x00000020, + Label = 0x00000040, + Line = 0x00000080, + LineEdit = 0x00000100, + PushButton = 0x00000200, + RadioButton = 0x00000400, + Slider = 0x00000800, + SpinBox = 0x00001000, + TabWidget = 0x00002000, + ToolButton = 0x00004000 + }; + Q_DECLARE_FLAGS(ControlTypes, ControlType) + + QLayoutPolicy() : data(0) { } + + QLayoutPolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) + : data(0) { + bits.horPolicy = horizontal; + bits.verPolicy = vertical; + setControlType(type); + } + Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); } + Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); } + ControlType controlType() const; + + void setHorizontalPolicy(Policy d) { bits.horPolicy = d; } + void setVerticalPolicy(Policy d) { bits.verPolicy = d; } + void setControlType(ControlType type); + + Qt::Orientations expandingDirections() const { + Qt::Orientations result; + if (verticalPolicy() & ExpandFlag) + result |= Qt::Vertical; + if (horizontalPolicy() & ExpandFlag) + result |= Qt::Horizontal; + return result; + } + + void setHeightForWidth(bool b) { bits.hfw = b; } + bool hasHeightForWidth() const { return bits.hfw; } + void setWidthForHeight(bool b) { bits.wfh = b; } + bool hasWidthForHeight() const { return bits.wfh; } + + bool operator==(const QLayoutPolicy& s) const { return data == s.data; } + bool operator!=(const QLayoutPolicy& s) const { return data != s.data; } + + int horizontalStretch() const { return static_cast<int>(bits.horStretch); } + int verticalStretch() const { return static_cast<int>(bits.verStretch); } + void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } + void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } + + void transpose(); + + +private: +#ifndef QT_NO_DATASTREAM + friend QDataStream &operator<<(QDataStream &, const QLayoutPolicy &); + friend QDataStream &operator>>(QDataStream &, QLayoutPolicy &); +#endif + QLayoutPolicy(int i) : data(i) { } + + union { + struct { + quint32 horStretch : 8; + quint32 verStretch : 8; + quint32 horPolicy : 4; + quint32 verPolicy : 4; + quint32 ctype : 5; + quint32 hfw : 1; + quint32 wfh : 1; + quint32 padding : 1; // feel free to use + } bits; + quint32 data; + }; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QLayoutPolicy::ControlTypes) + +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &, const QLayoutPolicy &); +QDataStream &operator>>(QDataStream &, QLayoutPolicy &); +#endif + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QLayoutPolicy &); +#endif + +inline void QLayoutPolicy::transpose() { + Policy hData = horizontalPolicy(); + Policy vData = verticalPolicy(); + int hStretch = horizontalStretch(); + int vStretch = verticalStretch(); + setHorizontalPolicy(vData); + setVerticalPolicy(hData); + setHorizontalStretch(vStretch); + setVerticalStretch(hStretch); +} + +QT_END_NAMESPACE + +#endif // QLAYOUTPOLICY_H diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri index dfb221667e..96027dd954 100644 --- a/src/gui/util/util.pri +++ b/src/gui/util/util.pri @@ -3,8 +3,12 @@ HEADERS += \ util/qdesktopservices.h \ util/qhexstring_p.h \ - util/qvalidator.h + util/qvalidator.h \ + util/qabstractlayoutstyleinfo_p.h \ + util/qlayoutpolicy_p.h SOURCES += \ util/qdesktopservices.cpp \ - util/qvalidator.cpp + util/qvalidator.cpp \ + util/qabstractlayoutstyleinfo.cpp \ + util/qlayoutpolicy.cpp diff --git a/src/widgets/graphicsview/graphicsview.pri b/src/widgets/graphicsview/graphicsview.pri index a0fc4bc8d3..f8cbe18493 100644 --- a/src/widgets/graphicsview/graphicsview.pri +++ b/src/widgets/graphicsview/graphicsview.pri @@ -24,6 +24,8 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ graphicsview/qgridlayoutengine_p.h \ + graphicsview/qgraphicslayoutstyleinfo_p.h \ + graphicsview/qgraphicsgridlayoutengine_p.h \ graphicsview/qgraph_p.h \ graphicsview/qsimplex_p.h \ graphicsview/qgraphicsanchorlayout_p.h \ @@ -48,6 +50,8 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicswidget.cpp \ graphicsview/qgraphicswidget_p.cpp \ graphicsview/qgridlayoutengine.cpp \ + graphicsview/qgraphicslayoutstyleinfo.cpp \ + graphicsview/qgraphicsgridlayoutengine.cpp \ graphicsview/qsimplex_p.cpp \ graphicsview/qgraphicsanchorlayout_p.cpp \ graphicsview/qgraphicsanchorlayout.cpp diff --git a/src/widgets/graphicsview/qgraphicsgridlayout.cpp b/src/widgets/graphicsview/qgraphicsgridlayout.cpp index 6d9dd98839..59f3d891f2 100644 --- a/src/widgets/graphicsview/qgraphicsgridlayout.cpp +++ b/src/widgets/graphicsview/qgraphicsgridlayout.cpp @@ -89,30 +89,35 @@ #include "qgraphicslayoutitem.h" #include "qgraphicsgridlayout.h" #include "qgraphicswidget.h" -#include "qgridlayoutengine_p.h" -#include <QtCore/qdebug.h> +#include "qgraphicsgridlayoutengine_p.h" +#include "qgraphicslayoutstyleinfo_p.h" +#ifdef QT_DEBUG +# include <QtCore/qdebug.h> +#endif QT_BEGIN_NAMESPACE class QGraphicsGridLayoutPrivate : public QGraphicsLayoutPrivate { public: - QGraphicsGridLayoutPrivate() { } - QLayoutStyleInfo styleInfo() const; + QGraphicsGridLayoutPrivate(): m_styleInfo(0) { } + QGraphicsLayoutStyleInfo *styleInfo() const; + + mutable QGraphicsLayoutStyleInfo *m_styleInfo; + QGraphicsGridLayoutEngine engine; - QGridLayoutEngine engine; #ifdef QT_DEBUG void dump(int indent) const; #endif }; -Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget); -QLayoutStyleInfo QGraphicsGridLayoutPrivate::styleInfo() const +QGraphicsLayoutStyleInfo *QGraphicsGridLayoutPrivate::styleInfo() const { - QGraphicsItem *item = parentItem(); - QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); - return QLayoutStyleInfo(style, globalStyleInfoWidget()); + if (!m_styleInfo) + m_styleInfo = new QGraphicsLayoutStyleInfo(this); + m_styleInfo->updateChanged(QAbstractLayoutStyleInfo::Unknown); + return m_styleInfo; } /*! @@ -172,7 +177,8 @@ void QGraphicsGridLayout::addItem(QGraphicsLayoutItem *item, int row, int column d->addChildLayoutItem(item); - new QGridLayoutItem(&d->engine, item, row, column, rowSpan, columnSpan, alignment); + QGraphicsGridLayoutEngineItem *gridEngineItem = new QGraphicsGridLayoutEngineItem(item, row, column, rowSpan, columnSpan, alignment); + d->engine.insertItem(gridEngineItem, -1); invalidate(); } @@ -199,7 +205,7 @@ void QGraphicsGridLayout::setHorizontalSpacing(qreal spacing) qreal QGraphicsGridLayout::horizontalSpacing() const { Q_D(const QGraphicsGridLayout); - return d->engine.spacing(d->styleInfo(), Qt::Horizontal); + return d->engine.spacing(Qt::Horizontal, d->styleInfo()); } /*! @@ -218,7 +224,7 @@ void QGraphicsGridLayout::setVerticalSpacing(qreal spacing) qreal QGraphicsGridLayout::verticalSpacing() const { Q_D(const QGraphicsGridLayout); - return d->engine.spacing(d->styleInfo(), Qt::Vertical); + return d->engine.spacing(Qt::Vertical, d->styleInfo()); } /*! @@ -535,8 +541,8 @@ QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int row, int column) const qWarning("QGraphicsGridLayout::itemAt: invalid row, column %d, %d", row, column); return 0; } - if (QGridLayoutItem *item = d->engine.itemAt(row, column)) - return item->layoutItem(); + if (QGraphicsGridLayoutEngineItem *engineItem = static_cast<QGraphicsGridLayoutEngineItem*>(d->engine.itemAt(row, column))) + return engineItem->layoutItem(); return 0; } @@ -561,8 +567,8 @@ QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int index) const return 0; } QGraphicsLayoutItem *item = 0; - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) - item = gridItem->layoutItem(); + if (QGraphicsGridLayoutEngineItem *engineItem = static_cast<QGraphicsGridLayoutEngineItem*>(d->engine.itemAt(index))) + item = engineItem->layoutItem(); return item; } @@ -579,7 +585,8 @@ void QGraphicsGridLayout::removeAt(int index) qWarning("QGraphicsGridLayout::removeAt: invalid index %d", index); return; } - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) { + + if (QGraphicsGridLayoutEngineItem *gridItem = static_cast<QGraphicsGridLayoutEngineItem*>(d->engine.itemAt(index))) { if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem()) layoutItem->setParentLayoutItem(0); d->engine.removeItem(gridItem); @@ -619,6 +626,8 @@ void QGraphicsGridLayout::invalidate() { Q_D(QGraphicsGridLayout); d->engine.invalidate(); + if (d->m_styleInfo) + d->m_styleInfo->invalidate(); QGraphicsLayout::invalidate(); } @@ -646,7 +655,7 @@ void QGraphicsGridLayout::setGeometry(const QRectF &rect) if (visualDir == Qt::RightToLeft) qSwap(left, right); effectiveRect.adjust(+left, +top, -right, -bottom); - d->engine.setGeometries(d->styleInfo(), effectiveRect); + d->engine.setGeometries(effectiveRect, d->styleInfo()); #ifdef QT_DEBUG if (qt_graphicsLayoutDebug()) { static int counter = 0; @@ -666,7 +675,7 @@ QSizeF QGraphicsGridLayout::sizeHint(Qt::SizeHint which, const QSizeF &constrain 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; + return d->engine.sizeHint(which , constraint - extraMargins, d->styleInfo()) + extraMargins; } diff --git a/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp b/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp new file mode 100644 index 0000000000..6de41c308b --- /dev/null +++ b/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicsgridlayoutengine_p.h" +#include "qgraphicslayoutitem_p.h" +#include "qgraphicslayout_p.h" +#include "qgraphicswidget.h" + +QT_BEGIN_NAMESPACE + +/* + returns \c true if the size policy returns \c true for either hasHeightForWidth() + or hasWidthForHeight() + */ +bool QGraphicsGridLayoutEngineItem::hasDynamicConstraint() const +{ + return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth() + || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight(); +} + +Qt::Orientation QGraphicsGridLayoutEngineItem::dynamicConstraintOrientation() const +{ + if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()) + return Qt::Vertical; + else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight()) + return Qt::Horizontal; +} + + +void QGraphicsGridLayoutEngine::setAlignment(QGraphicsLayoutItem *graphicsLayoutItem, Qt::Alignment alignment) +{ + if (QGraphicsGridLayoutEngineItem *gridEngineItem = findLayoutItem(graphicsLayoutItem)) { + gridEngineItem->setAlignment(alignment); + invalidate(); + } +} + +Qt::Alignment QGraphicsGridLayoutEngine::alignment(QGraphicsLayoutItem *graphicsLayoutItem) const +{ + if (QGraphicsGridLayoutEngineItem *gridEngineItem = findLayoutItem(graphicsLayoutItem)) + return gridEngineItem->alignment(); + return 0; +} + + +void QGraphicsGridLayoutEngine::setStretchFactor(QGraphicsLayoutItem *layoutItem, int stretch, + Qt::Orientation orientation) +{ + Q_ASSERT(stretch >= 0); + + if (QGraphicsGridLayoutEngineItem *item = findLayoutItem(layoutItem)) + item->setStretchFactor(stretch, orientation); +} + +int QGraphicsGridLayoutEngine::stretchFactor(QGraphicsLayoutItem *layoutItem, Qt::Orientation orientation) const +{ + if (QGraphicsGridLayoutEngineItem *item = findLayoutItem(layoutItem)) + return item->stretchFactor(orientation); + return 0; +} + + +QT_END_NAMESPACE diff --git a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h new file mode 100644 index 0000000000..3d34f99977 --- /dev/null +++ b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSGRIDLAYOUTENGINE_P_H +#define QGRAPHICSGRIDLAYOUTENGINE_P_H + +#include "qgridlayoutengine_p.h" + +#include <QtWidgets/qsizepolicy.h> +#include <QtWidgets/qstyle.h> +#include <QtWidgets/qstyleoption.h> +#include "qgraphicslayoutitem.h" + +QT_BEGIN_NAMESPACE + +class QGraphicsLayoutPrivate; + +class QGraphicsGridLayoutEngineItem : public QGridLayoutItem { +public: + QGraphicsGridLayoutEngineItem(QGraphicsLayoutItem *item, int row, int columns, int rowSpan = 1, int columnSpan = 1, + Qt::Alignment alignment = 0) + : QGridLayoutItem(row, columns, rowSpan, columnSpan, alignment), q_layoutItem(item) {} + + virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const Q_DECL_OVERRIDE + { + QSizePolicy sizePolicy(q_layoutItem->sizePolicy()); + return (QLayoutPolicy::Policy)((orientation == Qt::Horizontal) ? sizePolicy.horizontalPolicy() + : sizePolicy.verticalPolicy()); + } + + virtual QLayoutPolicy::ControlTypes controlTypes(LayoutSide) const Q_DECL_OVERRIDE + { + const QSizePolicy::ControlType ct = q_layoutItem->sizePolicy().controlType(); + return (QLayoutPolicy::ControlTypes)ct; + } + + virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const Q_DECL_OVERRIDE + { + return q_layoutItem->effectiveSizeHint(which, constraint); + } + + virtual void setGeometry(const QRectF &rect) Q_DECL_OVERRIDE + { + q_layoutItem->setGeometry(rect); + } + + virtual bool hasDynamicConstraint() const Q_DECL_OVERRIDE; + virtual Qt::Orientation dynamicConstraintOrientation() const Q_DECL_OVERRIDE; + + QGraphicsLayoutItem *layoutItem() const { return q_layoutItem; } + +protected: + QGraphicsLayoutItem *q_layoutItem; +}; + + +class QGraphicsGridLayoutEngine : public QGridLayoutEngine +{ +public: + QGraphicsGridLayoutEngineItem *findLayoutItem(QGraphicsLayoutItem *layoutItem) const + { + const int index = indexOf(layoutItem); + if (index < 0) + return 0; + return static_cast<QGraphicsGridLayoutEngineItem*>(q_items.at(index)); + } + + int indexOf(QGraphicsLayoutItem *item) const + { + for (int i = 0; i < q_items.count(); ++i) { + if (item == static_cast<QGraphicsGridLayoutEngineItem*>(q_items.at(i))->layoutItem()) + return i; + } + return -1; + } + + void setAlignment(QGraphicsLayoutItem *graphicsLayoutItem, Qt::Alignment alignment); + Qt::Alignment alignment(QGraphicsLayoutItem *graphicsLayoutItem) const; + + void setStretchFactor(QGraphicsLayoutItem *layoutItem, int stretch, Qt::Orientation orientation); + int stretchFactor(QGraphicsLayoutItem *layoutItem, Qt::Orientation orientation) const; + +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSGRIDLAYOUTENGINE_P_H diff --git a/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp b/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp new file mode 100644 index 0000000000..3270fc20a3 --- /dev/null +++ b/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qgraphicslayoutstyleinfo_p.h" +#include "qgraphicslayout_p.h" +#include "qgraphicswidget.h" +#include <QtWidgets/qstyle.h> +#include <QtWidgets/qwidget.h> +#include <QtWidgets/qapplication.h> + +QT_BEGIN_NAMESPACE + +QGraphicsLayoutStyleInfo::QGraphicsLayoutStyleInfo(const QGraphicsLayoutPrivate *layout) + : m_layout(layout), m_style(0) +{ + m_widget = new QWidget; // pixelMetric might need a widget ptr + if (m_widget) + m_styleOption.initFrom(m_widget); + m_isWindow = m_styleOption.state & QStyle::State_Window; +} + +QGraphicsLayoutStyleInfo::~QGraphicsLayoutStyleInfo() +{ + delete m_widget; +} + +qreal QGraphicsLayoutStyleInfo::combinedLayoutSpacing(QLayoutPolicy::ControlTypes controls1, + QLayoutPolicy::ControlTypes controls2, + Qt::Orientation orientation) const +{ + Q_ASSERT(style()); + return style()->combinedLayoutSpacing(QSizePolicy::ControlTypes(int(controls1)), QSizePolicy::ControlTypes(int(controls2)), + orientation, const_cast<QStyleOption*>(&m_styleOption), widget()); +} + +qreal QGraphicsLayoutStyleInfo::perItemSpacing(QLayoutPolicy::ControlType control1, + QLayoutPolicy::ControlType control2, + Qt::Orientation orientation) const +{ + Q_ASSERT(style()); + return style()->layoutSpacing(QSizePolicy::ControlType(control1), QSizePolicy::ControlType(control2), + orientation, const_cast<QStyleOption*>(&m_styleOption), widget()); +} + +qreal QGraphicsLayoutStyleInfo::spacing(Qt::Orientation orientation) const +{ + Q_ASSERT(style()); + return style()->pixelMetric(orientation == Qt::Horizontal ? QStyle::PM_LayoutHorizontalSpacing : QStyle::PM_LayoutVerticalSpacing); +} + +qreal QGraphicsLayoutStyleInfo::windowMargin(Qt::Orientation orientation) const +{ + return style()->pixelMetric(orientation == Qt::Vertical + ? QStyle::PM_LayoutBottomMargin + : QStyle::PM_LayoutRightMargin, + const_cast<QStyleOption*>(&m_styleOption), widget()); +} + +QWidget *QGraphicsLayoutStyleInfo::widget() const { return m_widget; } + +QStyle *QGraphicsLayoutStyleInfo::style() const +{ + if (!m_style) { + Q_ASSERT(m_layout); + QGraphicsItem *item = m_layout->parentItem(); + m_style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); + } + return m_style; +} + +QT_END_NAMESPACE diff --git a/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h b/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h new file mode 100644 index 0000000000..275ebab6a1 --- /dev/null +++ b/src/widgets/graphicsview/qgraphicslayoutstyleinfo_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWidgets module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QGRAPHICSLAYOUTSTYLEINFO_P_H +#define QGRAPHICSLAYOUTSTYLEINFO_P_H + +#include <QtGui/private/qabstractlayoutstyleinfo_p.h> +#include <QtWidgets/qstyleoption.h> + +QT_BEGIN_NAMESPACE + +class QStyle; +class QWidget; +class QGraphicsLayoutPrivate; + +class QGraphicsLayoutStyleInfo : public QAbstractLayoutStyleInfo +{ +public: + QGraphicsLayoutStyleInfo(const QGraphicsLayoutPrivate *layout); + ~QGraphicsLayoutStyleInfo(); + + virtual qreal combinedLayoutSpacing(QLayoutPolicy::ControlTypes controls1, + QLayoutPolicy::ControlTypes controls2, + Qt::Orientation orientation) const Q_DECL_OVERRIDE; + + virtual qreal perItemSpacing(QLayoutPolicy::ControlType control1, + QLayoutPolicy::ControlType control2, + Qt::Orientation orientation) const Q_DECL_OVERRIDE; + + virtual qreal spacing(Qt::Orientation orientation) const Q_DECL_OVERRIDE; + + virtual qreal windowMargin(Qt::Orientation orientation) const Q_DECL_OVERRIDE; + + virtual void invalidate() Q_DECL_OVERRIDE + { + m_style = 0; + QAbstractLayoutStyleInfo::invalidate(); + } + + virtual bool hasChangedCore() const Q_DECL_OVERRIDE + { + QStyle *s = m_style; + // Note that style() will change m_style + return s != style(); + } + + QWidget *widget() const; + QStyle *style() const; + +private: + const QGraphicsLayoutPrivate *m_layout; + mutable QStyle *m_style; + QStyleOption m_styleOption; + QWidget *m_widget; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSLAYOUTSTYLEINFO_P_H
\ No newline at end of file diff --git a/src/widgets/graphicsview/qgraphicslinearlayout.cpp b/src/widgets/graphicsview/qgraphicslinearlayout.cpp index 00076502ea..f506148ea3 100644 --- a/src/widgets/graphicsview/qgraphicslinearlayout.cpp +++ b/src/widgets/graphicsview/qgraphicslinearlayout.cpp @@ -122,7 +122,8 @@ #include "qgraphicslayoutitem.h" #include "qgraphicslinearlayout.h" #include "qgraphicswidget.h" -#include "qgridlayoutengine_p.h" +#include "qgraphicsgridlayoutengine_p.h" +#include "qgraphicslayoutstyleinfo_p.h" #ifdef QT_DEBUG #include <QtCore/qdebug.h> #endif @@ -132,16 +133,20 @@ QT_BEGIN_NAMESPACE class QGraphicsLinearLayoutPrivate : public QGraphicsLayoutPrivate { public: - QGraphicsLinearLayoutPrivate(Qt::Orientation orientation) : orientation(orientation) { } + QGraphicsLinearLayoutPrivate(Qt::Orientation orientation) + : orientation(orientation), + m_styleInfo(0) + { } void removeGridItem(QGridLayoutItem *gridItem); - QLayoutStyleInfo styleInfo() const; + QGraphicsLayoutStyleInfo *styleInfo() const; void fixIndex(int *index) const; int gridRow(int index) const; int gridColumn(int index) const; Qt::Orientation orientation; - QGridLayoutEngine engine; + mutable QGraphicsLayoutStyleInfo *m_styleInfo; + QGraphicsGridLayoutEngine engine; }; void QGraphicsLinearLayoutPrivate::removeGridItem(QGridLayoutItem *gridItem) @@ -172,13 +177,12 @@ int QGraphicsLinearLayoutPrivate::gridColumn(int index) const return int(qMin(uint(index), uint(engine.columnCount()))); } -Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget) - -QLayoutStyleInfo QGraphicsLinearLayoutPrivate::styleInfo() const +QGraphicsLayoutStyleInfo *QGraphicsLinearLayoutPrivate::styleInfo() const { - QGraphicsItem *item = parentItem(); - QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style(); - return QLayoutStyleInfo(style, globalStyleInfoWidget()); + if (!m_styleInfo) + m_styleInfo = new QGraphicsLayoutStyleInfo(this); + m_styleInfo->updateChanged(QAbstractLayoutStyleInfo::Unknown); + return m_styleInfo; } /*! @@ -281,7 +285,8 @@ void QGraphicsLinearLayout::insertItem(int index, QGraphicsLayoutItem *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); + QGraphicsGridLayoutEngineItem *gridEngineItem = new QGraphicsGridLayoutEngineItem(item, d->gridRow(index), d->gridColumn(index), 1, 1, 0); + d->engine.insertItem(gridEngineItem, index); invalidate(); } @@ -309,7 +314,7 @@ void QGraphicsLinearLayout::insertStretch(int index, int stretch) void QGraphicsLinearLayout::removeItem(QGraphicsLayoutItem *item) { Q_D(QGraphicsLinearLayout); - if (QGridLayoutItem *gridItem = d->engine.findLayoutItem(item)) { + if (QGraphicsGridLayoutEngineItem *gridItem = d->engine.findLayoutItem(item)) { item->setParentLayoutItem(0); d->removeGridItem(gridItem); delete gridItem; @@ -330,7 +335,8 @@ void QGraphicsLinearLayout::removeAt(int index) qWarning("QGraphicsLinearLayout::removeAt: invalid index %d", index); return; } - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) { + + if (QGraphicsGridLayoutEngineItem *gridItem = static_cast<QGraphicsGridLayoutEngineItem*>(d->engine.itemAt(index))) { if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem()) layoutItem->setParentLayoutItem(0); d->removeGridItem(gridItem); @@ -365,7 +371,7 @@ void QGraphicsLinearLayout::setSpacing(qreal spacing) qreal QGraphicsLinearLayout::spacing() const { Q_D(const QGraphicsLinearLayout); - return d->engine.spacing(d->styleInfo(), d->orientation); + return d->engine.spacing(d->orientation, d->styleInfo()); } /*! @@ -485,7 +491,7 @@ QGraphicsLayoutItem *QGraphicsLinearLayout::itemAt(int index) const return 0; } QGraphicsLayoutItem *item = 0; - if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) + if (QGraphicsGridLayoutEngineItem *gridItem = static_cast<QGraphicsGridLayoutEngineItem *>(d->engine.itemAt(index))) item = gridItem->layoutItem(); return item; } @@ -512,7 +518,7 @@ void QGraphicsLinearLayout::setGeometry(const QRectF &rect) dump(1); } #endif - d->engine.setGeometries(d->styleInfo(), effectiveRect); + d->engine.setGeometries(effectiveRect, d->styleInfo()); #ifdef QT_DEBUG if (qt_graphicsLayoutDebug()) { qDebug() << "post dump"; @@ -530,7 +536,7 @@ QSizeF QGraphicsLinearLayout::sizeHint(Qt::SizeHint which, const QSizeF &constra 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; + return d->engine.sizeHint(which , constraint - extraMargins, d->styleInfo()) + extraMargins; } /*! @@ -540,6 +546,8 @@ void QGraphicsLinearLayout::invalidate() { Q_D(QGraphicsLinearLayout); d->engine.invalidate(); + if (d->m_styleInfo) + d->m_styleInfo->invalidate(); QGraphicsLayout::invalidate(); } diff --git a/src/widgets/graphicsview/qgridlayoutengine.cpp b/src/widgets/graphicsview/qgridlayoutengine.cpp index bac8d52c9a..2fabf98cf8 100644 --- a/src/widgets/graphicsview/qgridlayoutengine.cpp +++ b/src/widgets/graphicsview/qgridlayoutengine.cpp @@ -45,9 +45,7 @@ #include <math.h> -#include "qgraphicslayoutitem.h" #include "qgridlayoutengine_p.h" -#include "qstyleoption.h" #include "qvarlengtharray.h" #include <QtDebug> @@ -484,10 +482,9 @@ void QGridLayoutRowData::dump(int indent) const } #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) +QGridLayoutItem::QGridLayoutItem(int row, int column, int rowSpan, int columnSpan, + Qt::Alignment alignment) + : q_alignment(alignment) { q_firstRows[Hor] = column; q_firstRows[Ver] = row; @@ -495,8 +492,6 @@ QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem q_rowSpans[Ver] = rowSpan; q_stretches[Hor] = -1; q_stretches[Ver] = -1; - - q_engine->insertItem(this, itemAtIndex); } int QGridLayoutItem::firstRow(Qt::Orientation orientation) const @@ -545,11 +540,11 @@ int QGridLayoutItem::stretchFactor(Qt::Orientation orientation) const if (stretch >= 0) return stretch; - QSizePolicy::Policy policy = sizePolicy(orientation); + QLayoutPolicy::Policy policy = sizePolicy(orientation); - if (policy & QSizePolicy::ExpandFlag) { + if (policy & QLayoutPolicy::ExpandFlag) { return 1; - } else if (policy & QSizePolicy::GrowFlag) { + } else if (policy & QLayoutPolicy::GrowFlag) { return -1; // because we max it up } else { return 0; @@ -562,58 +557,28 @@ void QGridLayoutItem::setStretchFactor(int stretch, Qt::Orientation orientation) 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 \c true if the size policy returns \c 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 +QLayoutPolicy::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); + return QLayoutPolicy::DefaultType; } QGridLayoutBox QGridLayoutItem::box(Qt::Orientation orientation, qreal constraint) const { QGridLayoutBox result; - QSizePolicy::Policy policy = sizePolicy(orientation); + QLayoutPolicy::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) { + if (policy & QLayoutPolicy::ShrinkFlag) { result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).width(); } else { result.q_minimumSize = result.q_preferredSize; } - if (policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag)) { + if (policy & (QLayoutPolicy::GrowFlag | QLayoutPolicy::ExpandFlag)) { result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).width(); } else { result.q_maximumSize = result.q_preferredSize; @@ -623,13 +588,13 @@ QGridLayoutBox QGridLayoutItem::box(Qt::Orientation orientation, qreal constrain result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).height(); - if (policy & QSizePolicy::ShrinkFlag) { + if (policy & QLayoutPolicy::ShrinkFlag) { result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).height(); } else { result.q_minimumSize = result.q_preferredSize; } - if (policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag)) { + if (policy & (QLayoutPolicy::GrowFlag | QLayoutPolicy::ExpandFlag)) { result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).height(); } else { result.q_maximumSize = result.q_preferredSize; @@ -639,14 +604,14 @@ QGridLayoutBox QGridLayoutItem::box(Qt::Orientation orientation, qreal constrain if (result.q_minimumDescent >= 0.0) result.q_minimumAscent = result.q_minimumSize - result.q_minimumDescent; } - if (policy & QSizePolicy::IgnoreFlag) + if (policy & QLayoutPolicy::IgnoreFlag) result.q_preferredSize = result.q_minimumSize; return result; } QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal height, - qreal rowDescent) const + qreal rowDescent, Qt::Alignment align) const { rowDescent = -1.0; // ### This disables the descent @@ -669,7 +634,6 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig 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; @@ -698,11 +662,6 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig } } -void QGridLayoutItem::setGeometry(const QRectF &rect) -{ - q_layoutItem->setGeometry(rect); -} - void QGridLayoutItem::transpose() { qSwap(q_firstRows[Hor], q_firstRows[Ver]); @@ -722,7 +681,7 @@ void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation ori /*! \internal returns the effective maximumSize, will take the sizepolicy into - consideration. (i.e. if sizepolicy does not have QSizePolicy::Grow, then + consideration. (i.e. if sizepolicy does not have QLayoutPolicy::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) @@ -730,10 +689,10 @@ void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation ori 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; + bool vGrow = (sizePolicy(Qt::Vertical) & QLayoutPolicy::GrowFlag) == QLayoutPolicy::GrowFlag; + bool hGrow = (sizePolicy(Qt::Horizontal) & QLayoutPolicy::GrowFlag) == QLayoutPolicy::GrowFlag; if (!vGrow || !hGrow) { - QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint); + QSizeF pref = sizeHint(Qt::PreferredSize, constraint); if (!vGrow) size.setHeight(pref.height()); if (!hGrow) @@ -741,7 +700,7 @@ QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const } if (!size.isValid()) { - QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, size); + QSizeF maxSize = sizeHint(Qt::MaximumSize, size); if (size.width() == -1) size.setWidth(maxSize.width()); if (size.height() == -1) @@ -753,7 +712,7 @@ QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const #ifdef QT_DEBUG void QGridLayoutItem::dump(int indent) const { - qDebug("%*s%p (%d, %d) %d x %d", indent, "", q_layoutItem, firstRow(), firstColumn(), + qDebug("%*s (%d, %d) %d x %d", indent, "", firstRow(), firstColumn(), //### rowSpan(), columnSpan()); if (q_stretches[Hor] >= 0) @@ -828,15 +787,6 @@ QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const 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(); @@ -860,14 +810,10 @@ void QGridLayoutEngine::setSpacing(qreal spacing, Qt::Orientations orientations) invalidate(); } -qreal QGridLayoutEngine::spacing(const QLayoutStyleInfo &styleInfo, Qt::Orientation orientation) const +qreal QGridLayoutEngine::spacing(Qt::Orientation orientation, const QAbstractLayoutStyleInfo *styleInfo) 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()); + if (!q_defaultSpacings[orientation == Qt::Vertical].isUser()) { + qreal defaultSpacing = styleInfo->spacing(orientation); q_defaultSpacings[orientation == Qt::Vertical].setCachedValue(defaultSpacing); } return q_defaultSpacings[orientation == Qt::Vertical].value(); @@ -916,22 +862,6 @@ int QGridLayoutEngine::rowStretchFactor(int row, Qt::Orientation orientation) co 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) { @@ -970,20 +900,6 @@ Qt::Alignment QGridLayoutEngine::rowAlignment(int row, Qt::Orientation orientati 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(); @@ -999,6 +915,7 @@ Qt::Alignment QGridLayoutEngine::effectiveAlignment(const QGridLayoutItem *layou int x = layoutItem->firstColumn(); align |= (rowAlignment(x, Qt::Horizontal) & Qt::AlignHorizontal_Mask); } + return align; } @@ -1047,15 +964,6 @@ void QGridLayoutEngine::removeItem(QGridLayoutItem *item) 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 { @@ -1072,7 +980,7 @@ void QGridLayoutEngine::invalidate() q_cachedEffectiveFirstRows[Ver] = -1; q_cachedEffectiveLastRows[Hor] = -1; q_cachedEffectiveLastRows[Ver] = -1; - q_cachedDataForStyleInfo.invalidate(); + q_totalBoxesValid = false; q_cachedSize = QSizeF(); q_cachedConstraintOrientation = UnknownConstraint; } @@ -1083,13 +991,12 @@ static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &cont geom->moveRight(contentsRect.right() - (geom->left() - contentsRect.left())); } -void QGridLayoutEngine::setGeometries(const QLayoutStyleInfo &styleInfo, - const QRectF &contentsGeometry) +void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbstractLayoutStyleInfo *styleInfo) { if (rowCount() < 1 || columnCount() < 1) return; - ensureGeometries(styleInfo, contentsGeometry.size()); + ensureGeometries(contentsGeometry.size(), styleInfo); for (int i = q_items.count() - 1; i >= 0; --i) { QGridLayoutItem *item = q_items.at(i); @@ -1105,22 +1012,21 @@ void QGridLayoutEngine::setGeometries(const QLayoutStyleInfo &styleInfo, height += q_yy[item->lastRow()] - y; QRectF geom = item->geometryWithin(contentsGeometry.x() + x, contentsGeometry.y() + y, - width, height, q_descents[item->lastRow()]); + width, height, q_descents[item->lastRow()], effectiveAlignment(item)); 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 +QRectF QGridLayoutEngine::cellRect(const QRectF &contentsGeometry, int row, int column, int rowSpan, + int columnSpan, const QAbstractLayoutStyleInfo *styleInfo) const { if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount()) || rowSpan < 1 || columnSpan < 1) return QRectF(); - ensureGeometries(styleInfo, contentsGeometry.size()); + ensureGeometries(contentsGeometry.size(), styleInfo); int lastColumn = qMax(column + columnSpan, columnCount()) - 1; int lastRow = qMax(row + rowSpan, rowCount()) - 1; @@ -1138,8 +1044,8 @@ QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo, return QRectF(contentsGeometry.x() + x, contentsGeometry.y() + y, width, height); } -QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which, - const QSizeF &constraint) const +QSizeF QGridLayoutEngine::sizeHint(Qt::SizeHint which, const QSizeF &constraint, + const QAbstractLayoutStyleInfo *styleInfo) const { QGridLayoutBox sizehint_totalBoxes[NOrientations]; @@ -1149,8 +1055,8 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi 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); + if (styleInfo->hasChanged() || !q_totalBoxesValid) + ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], NULL, NULL, Qt::Horizontal, styleInfo); else sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; QVector<qreal> sizehint_xx; @@ -1163,13 +1069,13 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi //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); + ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical, styleInfo); 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); + ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], NULL, NULL, Qt::Vertical, styleInfo); QVector<qreal> sizehint_yy; QVector<qreal> sizehint_heights; @@ -1180,7 +1086,7 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi //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); + ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], sizehint_yy.data(), sizehint_heights.data(), Qt::Horizontal, styleInfo); sizeHintCalculated = true; } } @@ -1188,9 +1094,9 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi 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); + if (styleInfo->hasChanged() || !q_totalBoxesValid) { + ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], NULL, NULL, Qt::Horizontal, styleInfo); + ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], NULL, NULL, Qt::Vertical, styleInfo); } else { sizehint_totalBoxes[Hor] = q_totalBoxes[Hor]; sizehint_totalBoxes[Ver] = q_totalBoxes[Ver]; @@ -1212,12 +1118,12 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi return QSizeF(); } -QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const +QLayoutPolicy::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; + QLayoutPolicy::ControlTypes result = 0; for (int column = columnCount(orientation) - 1; column >= 0; --column) { if (QGridLayoutItem *item = itemAt(row, column, orientation)) @@ -1380,26 +1286,19 @@ void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation o regenerateGrid(); } -void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo, +void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, qreal *colPositions, qreal *colSizes, - Qt::Orientation orientation) const + Qt::Orientation orientation, + const QAbstractLayoutStyleInfo *styleInfo) const { - const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; + const int ButtonMask = QLayoutPolicy::ButtonBox | QLayoutPolicy::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()); + qreal innerSpacing = styleInfo->spacing(orientation); if (innerSpacing >= 0.0) defaultSpacing.setCachedValue(innerSpacing); @@ -1456,7 +1355,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt continue; QGridLayoutBox &rowBox = rowData->boxes[row]; - if (option.state & QStyle::State_Window) { + if (styleInfo->isWindow()) { nextToNextToLastRowAdHocData = nextToLastRowAdHocData; nextToLastRowAdHocData = lastRowAdHocData; lastRowAdHocData.init(row); @@ -1474,7 +1373,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt if (itemRow == row && itemColumn == column) { int itemStretch = item->stretchFactor(orientation); - if (!(item->sizePolicy(orientation) & QSizePolicy::IgnoreFlag)) + if (!(item->sizePolicy(orientation) & QLayoutPolicy::IgnoreFlag)) hasIgnoreFlag = false; int itemRowSpan = item->rowSpan(orientation); @@ -1512,7 +1411,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt } if (effectiveRowSpan == 1) { - QSizePolicy::ControlTypes controls = item->controlTypes(top); + QLayoutPolicy::ControlTypes controls = item->controlTypes(top); if (controls & ButtonMask) lastRowAdHocData.q_hasButtons = true; if (controls & ~ButtonMask) @@ -1537,7 +1436,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt } /* - Heuristic: Detect button boxes that don't use QSizePolicy::ButtonBox. + Heuristic: Detect button boxes that don't use QLayoutPolicy::ButtonBox. This is somewhat ad hoc but it usually does the trick. */ bool lastRowIsButtonBox = (lastRowAdHocData.hasOnlyButtons() @@ -1560,25 +1459,24 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt QGridLayoutItem *item2 = itemAt(row, column, orientation); if (item1 && item2 && item1 != item2) { - QSizePolicy::ControlTypes controls1 = item1->controlTypes(bottom); - QSizePolicy::ControlTypes controls2 = item2->controlTypes(top); + QLayoutPolicy::ControlTypes controls1 = item1->controlTypes(bottom); + QLayoutPolicy::ControlTypes controls2 = item2->controlTypes(top); - if (controls2 & QSizePolicy::PushButton) { + if (controls2 & QLayoutPolicy::PushButton) { if ((row == nextToLastRowAdHocData.q_row && lastTwoRowsIsButtonBox) || (row == lastRowAdHocData.q_row && lastRowIsButtonBox)) { - controls2 &= ~QSizePolicy::PushButton; - controls2 |= QSizePolicy::ButtonBox; + controls2 &= ~QLayoutPolicy::PushButton; + controls2 |= QLayoutPolicy::ButtonBox; } } - qreal spacing = style->combinedLayoutSpacing(controls1, controls2, - orientation, &option, - styleInfo.widget()); + qreal spacing = styleInfo->combinedLayoutSpacing(controls1, controls2, + orientation); 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); + QRectF rect1 = item1->geometryWithin(0.0, 0.0, width1, FLT_MAX, -1.0, effectiveAlignment(item1)); + QRectF rect2 = item2->geometryWithin(0.0, 0.0, width2, FLT_MAX, -1.0, effectiveAlignment(item2)); spacing -= (width1 - (rect1.x() + rect1.width())) + rect2.x(); } else { const QGridLayoutBox &box1 = rowData->boxes.at(prevRow); @@ -1590,9 +1488,9 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt qreal rowDescent2 = fixedDescent(box2.q_minimumDescent, box2.q_minimumAscent, height2); QRectF rect1 = item1->geometryWithin(0.0, 0.0, FLT_MAX, height1, - rowDescent1); + rowDescent1, effectiveAlignment(item1)); QRectF rect2 = item2->geometryWithin(0.0, 0.0, FLT_MAX, height2, - rowDescent2); + rowDescent2, effectiveAlignment(item2)); spacing -= (height1 - (rect1.y() + rect1.height())) + rect2.y(); } rowSpacing = qMax(spacing, rowSpacing); @@ -1610,11 +1508,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt 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 windowMargin = styleInfo->windowMargin(orientation); qreal &rowSpacing = rowData->spacings[prevRow]; rowSpacing = qMax(windowMargin, rowSpacing); } @@ -1647,12 +1541,12 @@ void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const } void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox, - const QLayoutStyleInfo &styleInfo, - qreal *colPositions, qreal *colSizes, - Qt::Orientation orientation) const + qreal *colPositions, qreal *colSizes, + Qt::Orientation orientation, + const QAbstractLayoutStyleInfo *styleInfo) const { rowData->reset(rowCount(orientation)); - fillRowData(rowData, styleInfo, colPositions, colSizes, orientation); + fillRowData(rowData, colPositions, colSizes, orientation, styleInfo); const QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical]; rowData->distributeMultiCells(rowInfo); *totalBox = rowData->totalBox(0, rowCount(orientation)); @@ -1660,7 +1554,7 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri } /** - returns \c false if the layout has contradicting constraints (i.e. some items with a horizontal + 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 @@ -1702,13 +1596,13 @@ Qt::Orientation QGridLayoutEngine::constraintOrientation() const return (Qt::Orientation)q_cachedConstraintOrientation; } -void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, - const QSizeF &size) const +void QGridLayoutEngine::ensureGeometries(const QSizeF &size, + const QAbstractLayoutStyleInfo *styleInfo) const { - if (q_cachedDataForStyleInfo == styleInfo && q_cachedSize == size) + if (!styleInfo->hasChanged() && q_totalBoxesValid && q_cachedSize == size) return; - q_cachedDataForStyleInfo = styleInfo; + q_totalBoxesValid = true; q_cachedSize = size; q_xx.resize(columnCount()); @@ -1718,25 +1612,24 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo, q_descents.resize(rowCount()); if (constraintOrientation() != Qt::Horizontal) { - // We might have items whose height depends on their width, - // or none of the items has a dynamic constraint. - ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal); + //We might have items whose width depends on their height + ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], NULL, NULL, Qt::Horizontal, styleInfo); //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); + ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], q_xx.data(), q_widths.data(), Qt::Vertical, styleInfo); //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 width depends on their height - ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical); + //We have items whose height depends on their width + ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], NULL, NULL, Qt::Vertical, styleInfo); //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); + ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], q_yy.data(), q_heights.data(), Qt::Horizontal, styleInfo); //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]); diff --git a/src/widgets/graphicsview/qgridlayoutengine_p.h b/src/widgets/graphicsview/qgridlayoutengine_p.h index 309b58b3d9..e864294a4a 100644 --- a/src/widgets/graphicsview/qgridlayoutengine_p.h +++ b/src/widgets/graphicsview/qgridlayoutengine_p.h @@ -59,12 +59,14 @@ #include "qmap.h" #include "qpair.h" #include "qvector.h" -#include "qgraphicslayout_p.h" +#include <QtCore/qsize.h> +#include <QtCore/qrect.h> #include <float.h> +#include <QtGui/private/qlayoutpolicy_p.h> +#include <QtGui/private/qabstractlayoutstyleinfo_p.h> QT_BEGIN_NAMESPACE -class QGraphicsLayoutItem; class QStyle; class QWidget; @@ -249,14 +251,31 @@ public: bool hasIgnoreFlag; }; -class QGridLayoutEngine; +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 QGridLayoutItem { public: - QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, int row, int column, - int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0, - int itemAtIndex = -1); + QGridLayoutItem(int row, int column, int rowSpan = 1, int columnSpan = 1, + Qt::Alignment alignment = 0); + virtual ~QGridLayoutItem() {} inline int firstRow() const { return q_firstRows[Ver]; } inline int firstColumn() const { return q_firstRows[Hor]; } @@ -280,19 +299,24 @@ public: inline Qt::Alignment alignment() const { return q_alignment; } inline void setAlignment(Qt::Alignment alignment) { q_alignment = alignment; } - QSizePolicy::Policy sizePolicy(Qt::Orientation orientation) const; + virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const = 0; + virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0; + + virtual void setGeometry(const QRectF &rect) = 0; + /* + returns true if the size policy returns true for either hasHeightForWidth() + or hasWidthForHeight() + */ + virtual bool hasDynamicConstraint() const { return false; } + virtual Qt::Orientation dynamicConstraintOrientation() const { return Qt::Horizontal; } - bool hasDynamicConstraint() const; - Qt::Orientation dynamicConstraintOrientation() const; - QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + virtual QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const; + + QRectF geometryWithin(qreal x, qreal y, qreal width, qreal height, qreal rowDescent, Qt::Alignment align) 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; @@ -302,30 +326,11 @@ public: #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 @@ -341,13 +346,12 @@ public: // 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; + qreal spacing(Qt::Orientation orientation, const QAbstractLayoutStyleInfo *styleInfo) const; // ### setSpacingAfterRow(), spacingAfterRow() void setRowSpacing(int row, qreal spacing, Qt::Orientation orientation = Qt::Vertical); qreal rowSpacing(int row, Qt::Orientation orientation = Qt::Vertical) const; @@ -355,10 +359,6 @@ public: 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, @@ -367,15 +367,12 @@ public: 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); } @@ -383,11 +380,11 @@ public: { 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; + void setGeometries(const QRectF &contentsGeometry, const QAbstractLayoutStyleInfo *styleInfo); + QRectF cellRect(const QRectF &contentsGeometry, int row, int column, int rowSpan, int columnSpan, + const QAbstractLayoutStyleInfo *styleInfo) const; + QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint, + const QAbstractLayoutStyleInfo *styleInfo) const; // heightForWidth / widthForHeight support QSizeF dynamicallyConstrainedSizeHint(Qt::SizeHint which, const QSizeF &constraint) const; @@ -396,7 +393,7 @@ public: Qt::Orientation constraintOrientation() const; - QSizePolicy::ControlTypes controlTypes(LayoutSide side) const; + QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const; void transpose(); void setVisualDirection(Qt::LayoutDirection direction); Qt::LayoutDirection visualDirection() const; @@ -413,20 +410,22 @@ private: 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 fillRowData(QGridLayoutRowData *rowData, + qreal *colPositions, qreal *colSizes, + Qt::Orientation orientation, + const QAbstractLayoutStyleInfo *styleInfo) 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; + Qt::Orientation orientation, + const QAbstractLayoutStyleInfo *styleInfo) const; + void ensureGeometries(const QSizeF &size, const QAbstractLayoutStyleInfo *styleInfo) const; +protected: + QList<QGridLayoutItem *> q_items; +private: // User input QVector<QGridLayoutItem *> q_grid; - QList<QGridLayoutItem *> q_items; QLayoutParameter<qreal> q_defaultSpacings[NOrientations]; QGridLayoutRowInfo q_infos[NOrientations]; Qt::LayoutDirection m_visualDirection; @@ -438,13 +437,13 @@ private: 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 bool q_totalBoxesValid; mutable QVector<qreal> q_xx; mutable QVector<qreal> q_yy; mutable QVector<qreal> q_widths; diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp index 19e8819a7b..8f7a3a3255 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp @@ -971,7 +971,6 @@ void tst_QGraphicsLinearLayout::defaultSpacing() layout->invalidate(); styleSpacing = (qreal)style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); QCOMPARE(styleSpacing, qreal(15)); - QSKIP("invalidating the layout does not reevaluate the default spacing (QTBUG-35099)"); QCOMPARE(styleSpacing, layout->spacing()); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).width(), qreal(115)); widget->setStyle(style2); @@ -991,7 +990,6 @@ void tst_QGraphicsLinearLayout::defaultSpacing() layout->invalidate(); styleSpacing = (qreal)style->pixelMetric(QStyle::PM_LayoutVerticalSpacing); QCOMPARE(styleSpacing, qreal(13)); - QSKIP("invalidating the layout does not reevaluate the default spacing (QTBUG-35099)"); QCOMPARE(styleSpacing, layout->spacing()); QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize).height(), qreal(113)); widget->setStyle(style2); |