/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** 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 The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "flowlayout.h" #include FlowLayout::FlowLayout(QGraphicsLayoutItem *parent) : QGraphicsLayout(parent) { QSizePolicy sp = sizePolicy(); sp.setHeightForWidth(true); setSizePolicy(sp); } void FlowLayout::insertItem(int index, QGraphicsLayoutItem *item) { item->setParentLayoutItem(this); if (index > m_items.count() || index < 0) index = m_items.count(); m_items.insert(index, item); invalidate(); } int FlowLayout::count() const { return m_items.count(); } QGraphicsLayoutItem *FlowLayout::itemAt(int index) const { return m_items.value(index); } void FlowLayout::removeAt(int index) { m_items.removeAt(index); invalidate(); } qreal FlowLayout::spacing(Qt::Orientation o) const { return m_spacing[int(o) - 1]; } void FlowLayout::setSpacing(Qt::Orientations o, qreal spacing) { if (o & Qt::Horizontal) m_spacing[0] = spacing; if (o & Qt::Vertical) m_spacing[1] = spacing; } void FlowLayout::setGeometry(const QRectF &geom) { QGraphicsLayout::setGeometry(geom); doLayout(geom, true); } qreal FlowLayout::doLayout(const QRectF &geom, bool applyNewGeometry) const { qreal left, top, right, bottom; getContentsMargins(&left, &top, &right, &bottom); const qreal maxw = geom.width() - left - right; qreal x = 0; qreal y = 0; qreal maxRowHeight = 0; QSizeF pref; for (QGraphicsLayoutItem *item : m_items) { pref = item->effectiveSizeHint(Qt::PreferredSize); maxRowHeight = qMax(maxRowHeight, pref.height()); qreal next_x; next_x = x + pref.width(); if (next_x > maxw) { if (qFuzzyIsNull(x)) { pref.setWidth(maxw); } else { x = 0; next_x = pref.width(); } y += maxRowHeight + spacing(Qt::Vertical); maxRowHeight = 0; } if (applyNewGeometry) item->setGeometry(QRectF(QPointF(left + x, top + y), pref)); x = next_x + spacing(Qt::Horizontal); } maxRowHeight = qMax(maxRowHeight, pref.height()); return top + y + maxRowHeight + bottom; } QSizeF FlowLayout::minSize(const QSizeF &constraint) const { QSizeF size(0, 0); qreal left, top, right, bottom; getContentsMargins(&left, &top, &right, &bottom); if (constraint.width() >= 0) { // height for width const qreal height = doLayout(QRectF(QPointF(0,0), constraint), false); size = QSizeF(constraint.width(), height); } else if (constraint.height() >= 0) { // width for height? // not supported } else { for (const QGraphicsLayoutItem *item : qAsConst(m_items)) size = size.expandedTo(item->effectiveSizeHint(Qt::MinimumSize)); size += QSizeF(left + right, top + bottom); } return size; } QSizeF FlowLayout::prefSize() const { qreal left, right; getContentsMargins(&left, nullptr, &right, nullptr); qreal maxh = 0; qreal totalWidth = 0; for (const QGraphicsLayoutItem *item : qAsConst(m_items)) { if (totalWidth > 0) totalWidth += spacing(Qt::Horizontal); QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize); totalWidth += pref.width(); maxh = qMax(maxh, pref.height()); } maxh += spacing(Qt::Vertical); const qreal goldenAspectRatio = 1.61803399; qreal w = qSqrt(totalWidth * maxh * goldenAspectRatio) + left + right; return minSize(QSizeF(w, -1)); } QSizeF FlowLayout::maxSize() const { qreal totalWidth = 0; qreal totalHeight = 0; for (const QGraphicsLayoutItem *item : qAsConst(m_items)) { if (totalWidth > 0) totalWidth += spacing(Qt::Horizontal); if (totalHeight > 0) totalHeight += spacing(Qt::Vertical); QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize); totalWidth += pref.width(); totalHeight += pref.height(); } qreal left, top, right, bottom; getContentsMargins(&left, &top, &right, &bottom); return QSizeF(left + totalWidth + right, top + totalHeight + bottom); } QSizeF FlowLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const { QSizeF sh = constraint; switch (which) { case Qt::PreferredSize: sh = prefSize(); break; case Qt::MinimumSize: sh = minSize(constraint); break; case Qt::MaximumSize: sh = maxSize(); break; default: break; } return sh; }