Warning, file /office/skrooge/skgbasegui/skgflowlayout.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: 2022 S. MANKOWSKI stephane@mankowski.fr 0003 * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 ***************************************************************************/ 0006 /** @file 0007 * This file defines classes SKGFlowLayout. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgflowlayout.h" 0012 #include "skgdefine.h" 0013 0014 #include <qlayout.h> 0015 #include <qwidget.h> 0016 0017 SKGFlowLayout::SKGFlowLayout(QWidget* iParent, int iMargin, int hSpacing, int vSpacing) 0018 : QLayout(iParent), m_hSpace(hSpacing), m_vSpace(vSpacing) 0019 { 0020 setContentsMargins(iMargin, iMargin, iMargin, iMargin); 0021 } 0022 0023 SKGFlowLayout::SKGFlowLayout(int iMargin, int hSpacing, int vSpacing) 0024 : m_hSpace(hSpacing), m_vSpace(vSpacing) 0025 { 0026 setContentsMargins(iMargin, iMargin, iMargin, iMargin); 0027 } 0028 0029 SKGFlowLayout::~SKGFlowLayout() 0030 { 0031 while (count() != 0) { 0032 QLayoutItem* child = takeAt(0); 0033 if (child != nullptr) { 0034 QWidget* w = child->widget(); 0035 delete w; 0036 delete child; 0037 } 0038 } 0039 } 0040 0041 void SKGFlowLayout::addItem(QLayoutItem* item) 0042 { 0043 m_itemList.append(item); 0044 } 0045 0046 void SKGFlowLayout::setSpacing(int space) 0047 { 0048 m_hSpace = space; 0049 m_vSpace = space; 0050 } 0051 0052 int SKGFlowLayout::horizontalSpacing() const 0053 { 0054 if (m_hSpace >= 0) { 0055 return m_hSpace; 0056 } 0057 return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); 0058 } 0059 0060 int SKGFlowLayout::verticalSpacing() const 0061 { 0062 if (m_vSpace >= 0) { 0063 return m_vSpace; 0064 } 0065 return smartSpacing(QStyle::PM_LayoutVerticalSpacing); 0066 } 0067 0068 int SKGFlowLayout::count() const 0069 { 0070 return m_itemList.size(); 0071 } 0072 0073 QLayoutItem* SKGFlowLayout::itemAt(int index) const 0074 { 0075 return m_itemList.value(index); 0076 } 0077 0078 QLayoutItem* SKGFlowLayout::takeAt(int index) 0079 { 0080 if (index >= 0 && index < m_itemList.size()) { 0081 return m_itemList.takeAt(index); 0082 } 0083 return nullptr; 0084 } 0085 0086 Qt::Orientations SKGFlowLayout::expandingDirections() const 0087 { 0088 return Qt::Orientations(); 0089 } 0090 0091 bool SKGFlowLayout::hasHeightForWidth() const 0092 { 0093 return true; 0094 } 0095 0096 int SKGFlowLayout::heightForWidth(int width) const 0097 { 0098 int height = doLayout(QRect(0, 0, width, 0), true); 0099 return height; 0100 } 0101 0102 void SKGFlowLayout::setGeometry(const QRect& rect) // clazy:exclude=function-args-by-value 0103 { 0104 QLayout::setGeometry(rect); 0105 doLayout(rect, false); 0106 } 0107 0108 QSize SKGFlowLayout::sizeHint() const 0109 { 0110 return minimumSize(); 0111 } 0112 0113 QSize SKGFlowLayout::minimumSize() const 0114 { 0115 QSize size; 0116 for (auto item : qAsConst(m_itemList)) { 0117 size = size.expandedTo(item->minimumSize()); 0118 } 0119 0120 size += QSize(2 * margin(), 2 * margin()); 0121 return size; 0122 } 0123 0124 int SKGFlowLayout::doLayout(const QRect rect, bool testOnly) const 0125 { 0126 int left, top, right, bottom; 0127 getContentsMargins(&left, &top, &right, &bottom); 0128 QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); 0129 int x = effectiveRect.x(); 0130 int y = effectiveRect.y(); 0131 int lineHeight = 0; 0132 int x1 = x; 0133 int y1 = y; 0134 0135 for (auto item : qAsConst(m_itemList)) { 0136 QWidget* wid = item->widget(); 0137 if (wid != nullptr) { 0138 // Get spaces 0139 int spaceX = horizontalSpacing(); 0140 if (spaceX == -1) { 0141 spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal); 0142 } 0143 0144 int spaceY = verticalSpacing(); 0145 if (spaceY == -1) { 0146 spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical); 0147 } 0148 0149 // Try option 0150 bool optionUsed = false; 0151 if ((lineHeight != 0) && (x1 != 0)) { 0152 int nextX = x1 + item->sizeHint().width() + spaceX; 0153 if (nextX <= x && y1 - y + item->sizeHint().height() <= lineHeight) { 0154 optionUsed = true; 0155 0156 // Position item 0157 if (!testOnly) { 0158 item->setGeometry(QRect(QPoint(x1, y1), item->sizeHint())); 0159 } 0160 0161 x1 = nextX; 0162 } 0163 } 0164 0165 if (!optionUsed) { 0166 int nextX = x + item->sizeHint().width() + spaceX; 0167 if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) { 0168 x = effectiveRect.x(); 0169 y = y + lineHeight + spaceY; 0170 nextX = x + item->sizeHint().width() + spaceX; 0171 lineHeight = 0; 0172 } 0173 0174 // Position item 0175 if (!testOnly) { 0176 item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); 0177 } 0178 0179 x1 = x; 0180 y1 = y + item->sizeHint().height() + spaceY; 0181 x = nextX; 0182 lineHeight = qMax(lineHeight, item->sizeHint().height()); 0183 } 0184 } 0185 } 0186 return y + lineHeight - rect.y() + bottom; 0187 } 0188 0189 int SKGFlowLayout::smartSpacing(QStyle::PixelMetric pm) const 0190 { 0191 QObject* p = this->parent(); 0192 if (p == nullptr) { 0193 return -1; 0194 } 0195 if (p->isWidgetType()) { 0196 auto* pw = qobject_cast<QWidget*>(p); 0197 return pw->style()->pixelMetric(pm, nullptr, pw); 0198 } 0199 return qobject_cast<QLayout*>(p)->spacing(); 0200 }