File indexing completed on 2024-04-28 04:18:50
0001 /**************************************************************************** 0002 ** 0003 ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). 0004 ** Contact: Qt Software Information (qt-info@nokia.com) 0005 ** 0006 ** This file is part of the example classes of the Qt Toolkit. 0007 ** 0008 ** Commercial Usage 0009 ** Licensees holding valid Qt Commercial licenses may use this file in 0010 ** accordance with the Qt Commercial License Agreement provided with the 0011 ** Software or, alternatively, in accordance with the terms contained in 0012 ** a written agreement between you and Nokia. 0013 ** 0014 ** 0015 ** GNU General Public License Usage 0016 ** Alternatively, this file may be used under the terms of the GNU 0017 ** General Public License versions 2.0 or 3.0 as published by the Free 0018 ** Software Foundation and appearing in the file LICENSE.GPL included in 0019 ** the packaging of this file. Please review the following information 0020 ** to ensure GNU General Public Licensing requirements will be met: 0021 ** https://www.fsf.org/licensing/licenses/info/GPLv2.html and 0022 ** https://www.gnu.org/copyleft/gpl.html. In addition, as a special 0023 ** exception, Nokia gives you certain additional rights. These rights 0024 ** are described in the Nokia Qt GPL Exception version 1.3, included in 0025 ** the file GPL_EXCEPTION.txt in this package. 0026 ** 0027 ** Qt for Windows(R) Licensees 0028 ** As a special exception, Nokia, as the sole copyright holder for Qt 0029 ** Designer, grants users of the Qt/Eclipse Integration plug-in the 0030 ** right for the Qt/Eclipse Integration to link to functionality 0031 ** provided by Qt Designer and its related libraries. 0032 ** 0033 ** If you are unsure which license is appropriate for your use, please 0034 ** contact the sales department at qt-sales@nokia.com. 0035 ** 0036 ****************************************************************************/ 0037 0038 // Self 0039 #include "flowlayout.h" 0040 0041 // Qt 0042 #include <QHash> 0043 0044 FlowLayout::FlowLayout(QWidget *parent, int margin, int spacing) 0045 : QLayout(parent) 0046 { 0047 setContentsMargins(margin, margin, margin, margin); 0048 setHorizontalSpacing(spacing); 0049 setVerticalSpacing(spacing); 0050 } 0051 0052 FlowLayout::FlowLayout(int spacing) 0053 { 0054 setHorizontalSpacing(spacing); 0055 setVerticalSpacing(spacing); 0056 } 0057 0058 FlowLayout::~FlowLayout() 0059 { 0060 QLayoutItem *item; 0061 while ((item = takeAt(0))) 0062 delete item; 0063 } 0064 0065 int FlowLayout::horizontalSpacing() const 0066 { 0067 return mHorizontalSpacing; 0068 } 0069 0070 void FlowLayout::setHorizontalSpacing(const int spacing) 0071 { 0072 mHorizontalSpacing = spacing; 0073 } 0074 0075 int FlowLayout::verticalSpacing() const 0076 { 0077 return mVerticalSpacing; 0078 } 0079 0080 void FlowLayout::setVerticalSpacing(const int spacing) 0081 { 0082 mVerticalSpacing = spacing; 0083 } 0084 0085 void FlowLayout::addItem(QLayoutItem *item) 0086 { 0087 itemList.append(item); 0088 } 0089 0090 int FlowLayout::count() const 0091 { 0092 return itemList.size(); 0093 } 0094 0095 QLayoutItem *FlowLayout::itemAt(int index) const 0096 { 0097 return itemList.value(index); 0098 } 0099 0100 QLayoutItem *FlowLayout::takeAt(int index) 0101 { 0102 if (index >= 0 && index < itemList.size()) 0103 return itemList.takeAt(index); 0104 else 0105 return nullptr; 0106 } 0107 0108 Qt::Orientations FlowLayout::expandingDirections() const 0109 { 0110 return {}; 0111 } 0112 0113 bool FlowLayout::hasHeightForWidth() const 0114 { 0115 return true; 0116 } 0117 0118 int FlowLayout::heightForWidth(int width) const 0119 { 0120 int height = doLayout(QRect(0, 0, width, 0), true); 0121 return height; 0122 } 0123 0124 void FlowLayout::setGeometry(const QRect &rect) 0125 { 0126 QLayout::setGeometry(rect); 0127 doLayout(rect, false); 0128 } 0129 0130 QSize FlowLayout::sizeHint() const 0131 { 0132 return minimumSize(); 0133 } 0134 0135 int FlowLayout::getMargin() const 0136 { 0137 int left, top, right, bottom; 0138 getContentsMargins(&left, &top, &right, &bottom); 0139 if (left == top && top == right && right == bottom) { 0140 return left; 0141 } else { 0142 return -1; 0143 } 0144 } 0145 0146 QSize FlowLayout::minimumSize() const 0147 { 0148 QSize size; 0149 for (QLayoutItem *item : qAsConst(itemList)) 0150 size = size.expandedTo(item->minimumSize()); 0151 0152 size += QSize(2 * getMargin(), 2 * getMargin()); 0153 return size; 0154 } 0155 0156 void FlowLayout::addSpacing(const int size) 0157 { 0158 addItem(new QSpacerItem(size, 0, QSizePolicy::Fixed, QSizePolicy::Minimum)); 0159 } 0160 0161 int FlowLayout::doLayout(const QRect &rect, bool testOnly) const 0162 { 0163 const int left = rect.x() + getMargin(); 0164 int x = left; 0165 int y = rect.y() + getMargin(); 0166 int lineHeight = 0; 0167 bool lastItemIsSpacer = false; 0168 QHash<int, int> widthForY; 0169 0170 for (QLayoutItem *item : qAsConst(itemList)) { 0171 const bool itemIsSpacer = item->spacerItem() != nullptr; 0172 // Don't add invisible items or succeeding spacer items 0173 if (item->sizeHint().width() == 0 || (itemIsSpacer && lastItemIsSpacer)) { 0174 continue; 0175 } 0176 0177 int nextX = x + item->sizeHint().width() + horizontalSpacing(); 0178 if (nextX - horizontalSpacing() > rect.right() - getMargin() && lineHeight > 0) { 0179 x = left; 0180 y = y + lineHeight + verticalSpacing(); 0181 nextX = x + item->sizeHint().width() + horizontalSpacing(); 0182 lineHeight = 0; 0183 } 0184 0185 // Don't place spacer items at start of line 0186 if (itemIsSpacer && x == left) { 0187 continue; 0188 } 0189 0190 if (!testOnly) 0191 item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); 0192 0193 x = nextX; 0194 // Don't add spacer items at end of line 0195 if (!itemIsSpacer) { 0196 widthForY[y] = x - getMargin(); 0197 } 0198 lineHeight = qMax(lineHeight, item->sizeHint().height()); 0199 lastItemIsSpacer = itemIsSpacer; 0200 } 0201 0202 if (!testOnly) { 0203 const int contentWidth = rect.width() - 2 * getMargin(); 0204 for (auto item : itemList) { 0205 QRect itemRect = item->geometry(); 0206 // Center lines horizontally if flag AlignHCenter is set 0207 if (alignment() & Qt::AlignHCenter) { 0208 if (widthForY.contains(itemRect.y())) { 0209 const int offset = (contentWidth - widthForY[itemRect.y()]) / 2; 0210 itemRect.translate(offset, 0); 0211 } 0212 } 0213 // Center items vertically if flag AlignVCenter is set 0214 if (alignment() & Qt::AlignVCenter) { 0215 const int offset = (lineHeight - itemRect.height()) / 2; 0216 itemRect.translate(0, offset); 0217 } 0218 item->setGeometry(itemRect); 0219 } 0220 } 0221 0222 return y + lineHeight - rect.y() + getMargin(); 0223 } 0224 0225 #include "moc_flowlayout.cpp"