diff options
Diffstat (limited to 'src/widgets/graphicsview')
-rw-r--r-- | src/widgets/graphicsview/graphicsview.pri | 6 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsgridlayout.cpp | 55 | ||||
-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 | 48 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgridlayoutengine.cpp | 1745 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgridlayoutengine_p.h | 458 | ||||
-rw-r--r-- | src/widgets/graphicsview/qsimplex_p.h | 7 |
10 files changed, 498 insertions, 2251 deletions
diff --git a/src/widgets/graphicsview/graphicsview.pri b/src/widgets/graphicsview/graphicsview.pri index a0fc4bc8d3..b81f736ef4 100644 --- a/src/widgets/graphicsview/graphicsview.pri +++ b/src/widgets/graphicsview/graphicsview.pri @@ -23,7 +23,8 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsview_p.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 \ @@ -47,7 +48,8 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsview.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..0ecb4af6bd 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; - QGridLayoutEngine engine; -#ifdef QT_DEBUG + mutable QGraphicsLayoutStyleInfo *m_styleInfo; + QGraphicsGridLayoutEngine engine; + +#ifdef QGRIDLAYOUTENGINE_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,10 +626,12 @@ void QGraphicsGridLayout::invalidate() { Q_D(QGraphicsGridLayout); d->engine.invalidate(); + if (d->m_styleInfo) + d->m_styleInfo->invalidate(); QGraphicsLayout::invalidate(); } -#ifdef QT_DEBUG +#ifdef QGRIDLAYOUTENGINE_DEBUG void QGraphicsGridLayoutPrivate::dump(int indent) const { if (qt_graphicsLayoutDebug()) { @@ -646,8 +655,8 @@ 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); -#ifdef QT_DEBUG + d->engine.setGeometries(effectiveRect, d->styleInfo()); +#ifdef QGRIDLAYOUTENGINE_DEBUG if (qt_graphicsLayoutDebug()) { static int counter = 0; qDebug("==== BEGIN DUMP OF QGraphicsGridLayout (%d)====", counter++); @@ -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..1e987e30d2 --- /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 <QtGui/private/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..5c438e0495 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; } @@ -505,15 +511,15 @@ void QGraphicsLinearLayout::setGeometry(const QRectF &rect) if (visualDir == Qt::RightToLeft) qSwap(left, right); effectiveRect.adjust(+left, +top, -right, -bottom); -#ifdef QT_DEBUG +#ifdef QGRIDLAYOUTENGINE_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 + d->engine.setGeometries(effectiveRect, d->styleInfo()); +#ifdef QGRIDLAYOUTENGINE_DEBUG if (qt_graphicsLayoutDebug()) { qDebug() << "post dump"; dump(1); @@ -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(); } @@ -548,7 +556,7 @@ void QGraphicsLinearLayout::invalidate() */ void QGraphicsLinearLayout::dump(int indent) const { -#ifdef QT_DEBUG +#ifdef QGRIDLAYOUTENGINE_DEBUG if (qt_graphicsLayoutDebug()) { Q_D(const QGraphicsLinearLayout); qDebug("%*s%s layout", indent, "", diff --git a/src/widgets/graphicsview/qgridlayoutengine.cpp b/src/widgets/graphicsview/qgridlayoutengine.cpp deleted file mode 100644 index a1affdb55e..0000000000 --- a/src/widgets/graphicsview/qgridlayoutengine.cpp +++ /dev/null @@ -1,1745 +0,0 @@ -/**************************************************************************** -** -** 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 "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 || sizes[i] == 0.0) { - 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) { - if (ignore.testBit(i)) - continue; - 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 \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 -{ - 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::fromLatin1(" stretch %1").arg(stretches.value(i).value()); - if (spacings.value(i).value() >= 0.0) - message += QString::fromLatin1(" spacing %1").arg(spacings.value(i).value()); - if (alignments.value(i) != 0) - message += QString::fromLatin1(" 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 + itemRow)) - ++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 \c 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 \c 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 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); - //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 width depends on their height - 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/widgets/graphicsview/qgridlayoutengine_p.h b/src/widgets/graphicsview/qgridlayoutengine_p.h deleted file mode 100644 index fbc5bd6ad2..0000000000 --- a/src/widgets/graphicsview/qgridlayoutengine_p.h +++ /dev/null @@ -1,458 +0,0 @@ -/**************************************************************************** -** -** 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 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/widgets/graphicsview/qsimplex_p.h b/src/widgets/graphicsview/qsimplex_p.h index 842044fa7f..3fa3417eaf 100644 --- a/src/widgets/graphicsview/qsimplex_p.h +++ b/src/widgets/graphicsview/qsimplex_p.h @@ -149,9 +149,10 @@ struct QSimplexConstraint class QSimplex { + Q_DISABLE_COPY(QSimplex) public: QSimplex(); - virtual ~QSimplex(); + ~QSimplex(); qreal solveMin(); qreal solveMax(); @@ -163,8 +164,8 @@ public: private: // Matrix handling - qreal valueAt(int row, int column); - void setValueAt(int row, int column, qreal value); + inline qreal valueAt(int row, int column); + inline 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); |