File indexing completed on 2024-12-01 04:29:20
0001 /* 0002 SPDX-FileCopyrightText: 2013 Digia Plc and /or its subsidiary(-ies) <http://www.qt-project.org/legal> 0003 SPDX-License-Identifier: BSD-3-Clause 0004 This file is part of the examples of the Qt Toolkit. 0005 */ 0006 0007 #include "flowlayout.h" 0008 #include <QDebug> 0009 #include <QTimer> 0010 #include <QWidget> 0011 #include <QtMath> 0012 0013 FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) 0014 : QLayout(parent) 0015 , m_hSpace(hSpacing) 0016 , m_vSpace(vSpacing) 0017 , m_minimumSize(200, 200) 0018 { 0019 setContentsMargins(margin, margin, margin, margin); 0020 } 0021 0022 FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) 0023 : m_hSpace(hSpacing) 0024 , m_vSpace(vSpacing) 0025 , m_minimumSize(200, 200) 0026 { 0027 setContentsMargins(margin, margin, margin, margin); 0028 } 0029 0030 FlowLayout::~FlowLayout() 0031 { 0032 QLayoutItem *item; 0033 while ((item = takeAt(0)) != nullptr) { 0034 delete item; 0035 } 0036 } 0037 0038 void FlowLayout::addItem(QLayoutItem *item) 0039 { 0040 m_itemList.append(item); 0041 } 0042 0043 int FlowLayout::horizontalSpacing() const 0044 { 0045 if (m_hSpace >= 0) { 0046 return m_hSpace; 0047 } 0048 return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); 0049 } 0050 0051 int FlowLayout::verticalSpacing() const 0052 { 0053 if (m_vSpace >= 0) { 0054 return m_vSpace; 0055 } 0056 return smartSpacing(QStyle::PM_LayoutVerticalSpacing); 0057 } 0058 0059 int FlowLayout::count() const 0060 { 0061 return m_itemList.size(); 0062 } 0063 0064 QLayoutItem *FlowLayout::itemAt(int index) const 0065 { 0066 return m_itemList.value(index); 0067 } 0068 0069 QLayoutItem *FlowLayout::takeAt(int index) 0070 { 0071 if (index >= 0 && index < m_itemList.size()) { 0072 return m_itemList.takeAt(index); 0073 } 0074 return nullptr; 0075 } 0076 0077 Qt::Orientations FlowLayout::expandingDirections() const 0078 { 0079 return Qt::Horizontal | Qt::Vertical; 0080 } 0081 0082 bool FlowLayout::hasHeightForWidth() const 0083 { 0084 return true; 0085 } 0086 0087 int FlowLayout::heightForWidth(int width) const 0088 { 0089 int height = doLayout(QRect(0, 0, width, 0), true); 0090 return height; 0091 } 0092 0093 void FlowLayout::setGeometry(const QRect &rect) 0094 { 0095 if (m_itemList.size() < 3) { 0096 return; 0097 } 0098 doLayout(rect, false); 0099 QLayout::setGeometry(rect); 0100 } 0101 0102 QSize FlowLayout::sizeHint() const 0103 { 0104 return m_minimumSize; 0105 } 0106 0107 QSize FlowLayout::minimumSize() const 0108 { 0109 return m_minimumSize; 0110 } 0111 0112 int FlowLayout::doLayout(const QRect &rect, bool testOnly) const 0113 { 0114 QMargins mrg = contentsMargins(); 0115 QRect effectiveRect = rect.adjusted(mrg.left(), mrg.top(), -mrg.right(), -mrg.bottom()); 0116 if (m_itemList.isEmpty() || effectiveRect.width() <= 0) { 0117 return 0; 0118 } 0119 int x = effectiveRect.x(); 0120 int y = effectiveRect.y(); 0121 int itemCount = 0; 0122 QWidget *wid = m_itemList.at(0)->widget(); 0123 QSize min = wid->minimumSize(); 0124 int columns = qMin(qFloor(double(rect.width()) / min.width()), m_itemList.size()); 0125 columns = qMax(1, columns); 0126 int realWidth = qMin(wid->maximumWidth(), rect.width() / columns - horizontalSpacing()); 0127 realWidth -= realWidth % 40; 0128 realWidth = qMax(realWidth, wid->minimumWidth()); 0129 int totalHeight = y - rect.y() + mrg.bottom() + qCeil(double(m_itemList.size()) / columns) * (realWidth + verticalSpacing()); 0130 m_minimumSize = QSize(columns * realWidth, totalHeight); 0131 QSize hint = QSize(realWidth, realWidth); 0132 if (testOnly) { 0133 return totalHeight; 0134 } 0135 for (QLayoutItem *item : m_itemList) { 0136 // We consider all items have the same dimensions 0137 item->setGeometry(QRect(QPoint(x, y), hint)); 0138 itemCount++; 0139 // qDebug()<<"=== ITEM: "<<itemCount<<", POS: "<<x<<"x"<<y<<", SIZE: "<<hint; 0140 x = effectiveRect.x() + (itemCount % columns) * (realWidth + horizontalSpacing()); 0141 y = effectiveRect.y() + qFloor(double(itemCount) / columns) * (realWidth + verticalSpacing()); 0142 } 0143 return totalHeight; 0144 } 0145 int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const 0146 { 0147 QObject *parent = this->parent(); 0148 if (!parent) { 0149 return -1; 0150 } 0151 if (parent->isWidgetType()) { 0152 auto *pw = static_cast<QWidget *>(parent); 0153 return pw->style()->pixelMetric(pm, nullptr, pw); 0154 } 0155 return static_cast<QLayout *>(parent)->spacing(); 0156 } 0157 0158 int FlowLayout::miniHeight() const 0159 { 0160 return m_minimumSize.height(); 0161 }