Warning, file /libraries/baloo-widgets/src/kblocklayout.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2006-2007 Sebastian Trueg <trueg@kde.org> 0003 0004 KBlockLayout is based on the FlowLayout example from QT4. 0005 SPDX-FileCopyrightText: 2004-2006 Trolltech ASA 0006 SPDX-FileCopyrightText: 2010 Nokia Corporation and /or its subsidiary(-ies) <qt-info@nokia.com> 0007 0008 SPDX-License-Identifier: LGPL-2.0-or-later 0009 */ 0010 0011 #include "kblocklayout.h" 0012 0013 #include <QList> 0014 #include <QStyle> 0015 #include <QWidget> 0016 0017 class KBlockLayout::Private 0018 { 0019 public: 0020 Private() 0021 : alignment(Qt::AlignLeft | Qt::AlignTop) 0022 { 0023 } 0024 0025 int smartSpacing(QStyle::PixelMetric pm) const 0026 { 0027 QObject *parent = q->parent(); 0028 if (!parent) { 0029 return -1; 0030 } else if (parent->isWidgetType()) { 0031 auto pw = static_cast<QWidget *>(parent); 0032 return pw->style()->pixelMetric(pm, nullptr, pw); 0033 } else { 0034 return static_cast<QLayout *>(parent)->spacing(); 0035 } 0036 } 0037 0038 QList<QLayoutItem *> itemList; 0039 0040 int m_hSpace; 0041 int m_vSpace; 0042 0043 Qt::Alignment alignment; 0044 0045 KBlockLayout *q = nullptr; 0046 }; 0047 0048 KBlockLayout::KBlockLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) 0049 : QLayout(parent) 0050 , d(new Private()) 0051 { 0052 d->q = this; 0053 setContentsMargins(margin, margin, margin, margin); 0054 setSpacing(hSpacing, vSpacing); 0055 } 0056 0057 KBlockLayout::KBlockLayout(int margin, int hSpacing, int vSpacing) 0058 : d(new Private()) 0059 { 0060 d->q = this; 0061 setContentsMargins(margin, margin, margin, margin); 0062 setSpacing(hSpacing, vSpacing); 0063 } 0064 0065 KBlockLayout::~KBlockLayout() 0066 { 0067 QLayoutItem *item; 0068 while ((item = takeAt(0))) 0069 delete item; 0070 delete d; 0071 } 0072 0073 void KBlockLayout::setAlignment(Qt::Alignment a) 0074 { 0075 d->alignment = a; 0076 } 0077 0078 Qt::Alignment KBlockLayout::alignment() const 0079 { 0080 return d->alignment; 0081 } 0082 0083 int KBlockLayout::horizontalSpacing() const 0084 { 0085 if (d->m_hSpace >= 0) { 0086 return d->m_hSpace; 0087 } else { 0088 return d->smartSpacing(QStyle::PM_LayoutHorizontalSpacing); 0089 } 0090 } 0091 0092 int KBlockLayout::verticalSpacing() const 0093 { 0094 if (d->m_vSpace >= 0) { 0095 return d->m_vSpace; 0096 } else { 0097 return d->smartSpacing(QStyle::PM_LayoutVerticalSpacing); 0098 } 0099 } 0100 0101 void KBlockLayout::setSpacing(int h, int v) 0102 { 0103 d->m_hSpace = h; 0104 d->m_vSpace = v; 0105 QLayout::setSpacing(h); 0106 } 0107 0108 void KBlockLayout::addItem(QLayoutItem *item) 0109 { 0110 d->itemList.append(item); 0111 } 0112 0113 int KBlockLayout::count() const 0114 { 0115 return d->itemList.size(); 0116 } 0117 0118 QLayoutItem *KBlockLayout::itemAt(int index) const 0119 { 0120 return d->itemList.value(index); 0121 } 0122 0123 QLayoutItem *KBlockLayout::takeAt(int index) 0124 { 0125 if (index >= 0 && index < d->itemList.size()) 0126 return d->itemList.takeAt(index); 0127 else 0128 return nullptr; 0129 } 0130 0131 Qt::Orientations KBlockLayout::expandingDirections() const 0132 { 0133 return {}; 0134 } 0135 0136 bool KBlockLayout::hasHeightForWidth() const 0137 { 0138 return true; 0139 } 0140 0141 int KBlockLayout::heightForWidth(int width) const 0142 { 0143 int height = doLayout(QRect(0, 0, width, 0), true); 0144 return height; 0145 } 0146 0147 void KBlockLayout::setGeometry(const QRect &rect) 0148 { 0149 QLayout::setGeometry(rect); 0150 doLayout(rect, false); 0151 } 0152 0153 int KBlockLayout::getMargin() const 0154 { 0155 int left, top, right, bottom; 0156 getContentsMargins(&left, &top, &right, &bottom); 0157 if (left == top && top == right && right == bottom) { 0158 return left; 0159 } else { 0160 return -1; 0161 } 0162 } 0163 0164 QSize KBlockLayout::sizeHint() const 0165 { 0166 // TODO: try to get the items into a square 0167 QSize size; 0168 for (QLayoutItem *item : std::as_const(d->itemList)) { 0169 const QSize itemSize = item->minimumSize(); 0170 size.rwidth() += itemSize.width(); 0171 if (itemSize.height() > size.height()) { 0172 size.setHeight(itemSize.height()); 0173 } 0174 } 0175 0176 size.rwidth() += horizontalSpacing() * d->itemList.count(); 0177 size += QSize(2 * getMargin(), 2 * getMargin()); 0178 return size; 0179 } 0180 0181 QSize KBlockLayout::minimumSize() const 0182 { 0183 QSize size; 0184 for (QLayoutItem *item : std::as_const(d->itemList)) { 0185 size = size.expandedTo(item->minimumSize()); 0186 } 0187 0188 size += QSize(2 * getMargin(), 2 * getMargin()); 0189 return size; 0190 } 0191 0192 struct Row { 0193 Row(const QList<QLayoutItem *> &i, int h, int w) 0194 : items(i) 0195 , height(h) 0196 , width(w) 0197 { 0198 } 0199 0200 QList<QLayoutItem *> items; 0201 int height; 0202 int width; 0203 }; 0204 0205 int KBlockLayout::doLayout(const QRect &rect, bool testOnly) const 0206 { 0207 int x = rect.x(); 0208 int y = rect.y(); 0209 int lineHeight = 0; 0210 0211 // 1. calculate lines 0212 QList<Row> rows; 0213 QList<QLayoutItem *> rowItems; 0214 for (int i = 0; i < d->itemList.count(); ++i) { 0215 QLayoutItem *item = d->itemList[i]; 0216 int nextX = x + item->sizeHint().width() + horizontalSpacing(); 0217 if (nextX - horizontalSpacing() > rect.right() && lineHeight > 0) { 0218 rows.append(Row(rowItems, lineHeight, x - horizontalSpacing())); 0219 rowItems.clear(); 0220 0221 x = rect.x(); 0222 y = y + lineHeight + verticalSpacing(); 0223 nextX = x + item->sizeHint().width() + horizontalSpacing(); 0224 lineHeight = 0; 0225 } 0226 0227 rowItems.append(item); 0228 0229 x = nextX; 0230 lineHeight = qMax(lineHeight, item->sizeHint().height()); 0231 } 0232 // append the last row 0233 rows.append(Row(rowItems, lineHeight, x - horizontalSpacing())); 0234 0235 int finalHeight = y + lineHeight - rect.y(); 0236 if (testOnly) 0237 return finalHeight; 0238 0239 // 2. place the items 0240 y = rect.y(); 0241 for (const Row &row : std::as_const(rows)) { 0242 x = rect.x(); 0243 if (alignment() & Qt::AlignRight) 0244 x += (rect.width() - row.width); 0245 else if (alignment() & Qt::AlignHCenter) 0246 x += (rect.width() - row.width) / 2; 0247 0248 for (QLayoutItem *item : std::as_const(row.items)) { 0249 int yy = y; 0250 if (alignment() & Qt::AlignBottom) 0251 yy += (row.height - item->sizeHint().height()); 0252 else if (alignment() & Qt::AlignVCenter) 0253 yy += (row.height - item->sizeHint().height()) / 2; 0254 item->setGeometry(QRect(QPoint(x, yy), item->sizeHint())); 0255 0256 x += item->sizeHint().width() + horizontalSpacing(); 0257 0258 if (alignment() & Qt::AlignJustify) 0259 x += (rect.width() - row.width) / qMax(row.items.count() - 1, 1); 0260 } 0261 0262 y = y + row.height + verticalSpacing(); 0263 } 0264 0265 return finalHeight; 0266 }