FlowLayout: Add support for vertically expanding widgets and vertical alignment.

pull/1414/head
Jon Beniston 2022-09-16 08:50:21 +01:00
rodzic 880fde3480
commit 19fa10d71d
1 zmienionych plików z 45 dodań i 29 usunięć

Wyświetl plik

@ -51,7 +51,7 @@
#include <QtWidgets> #include <QtWidgets>
#include "flowlayout.h" #include "flowlayout.h"
//! [1]
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{ {
@ -63,25 +63,19 @@ FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
{ {
setContentsMargins(margin, margin, margin, margin); setContentsMargins(margin, margin, margin, margin);
} }
//! [1]
//! [2]
FlowLayout::~FlowLayout() FlowLayout::~FlowLayout()
{ {
QLayoutItem *item; QLayoutItem *item;
while ((item = takeAt(0))) while ((item = takeAt(0)))
delete item; delete item;
} }
//! [2]
//! [3]
void FlowLayout::addItem(QLayoutItem *item) void FlowLayout::addItem(QLayoutItem *item)
{ {
itemList.append(item); itemList.append(item);
} }
//! [3]
//! [4]
int FlowLayout::horizontalSpacing() const int FlowLayout::horizontalSpacing() const
{ {
if (m_hSpace >= 0) { if (m_hSpace >= 0) {
@ -99,9 +93,7 @@ int FlowLayout::verticalSpacing() const
return smartSpacing(QStyle::PM_LayoutVerticalSpacing); return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
} }
} }
//! [4]
//! [5]
int FlowLayout::count() const int FlowLayout::count() const
{ {
return itemList.size(); return itemList.size();
@ -118,16 +110,12 @@ QLayoutItem *FlowLayout::takeAt(int index)
return itemList.takeAt(index); return itemList.takeAt(index);
return nullptr; return nullptr;
} }
//! [5]
//! [6]
Qt::Orientations FlowLayout::expandingDirections() const Qt::Orientations FlowLayout::expandingDirections() const
{ {
return { }; return { };
} }
//! [6]
//! [7]
bool FlowLayout::hasHeightForWidth() const bool FlowLayout::hasHeightForWidth() const
{ {
return true; return true;
@ -138,9 +126,7 @@ int FlowLayout::heightForWidth(int width) const
int height = doLayout(QRect(0, 0, width, 0), true); int height = doLayout(QRect(0, 0, width, 0), true);
return height; return height;
} }
//! [7]
//! [8]
void FlowLayout::setGeometry(const QRect &rect) void FlowLayout::setGeometry(const QRect &rect)
{ {
QLayout::setGeometry(rect); QLayout::setGeometry(rect);
@ -162,9 +148,7 @@ QSize FlowLayout::minimumSize() const
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom()); size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
return size; return size;
} }
//! [8]
//! [9]
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{ {
int left, top, right, bottom; int left, top, right, bottom;
@ -173,39 +157,72 @@ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
int x = effectiveRect.x(); int x = effectiveRect.x();
int y = effectiveRect.y(); int y = effectiveRect.y();
int lineHeight = 0; int lineHeight = 0;
//! [9] QList<int> maxLineHeights;
int maxLineHeight = 0;
//! [10] // In order to support vertical alignment and expanding widgets, we need to first calculate maxLineHeight
// for each row of widgets
if (!testOnly) {
for (QLayoutItem *item : qAsConst(itemList)) {
const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
nextX = x + item->sizeHint().width() + spaceX;
maxLineHeights.append(lineHeight);
lineHeight = 0;
}
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
maxLineHeights.append(lineHeight);
maxLineHeight = maxLineHeights.takeFirst();
x = effectiveRect.x();
y = effectiveRect.y();
}
// Now do layout
for (QLayoutItem *item : qAsConst(itemList)) { for (QLayoutItem *item : qAsConst(itemList)) {
const QWidget *wid = item->widget(); const QWidget *wid = item->widget();
int spaceX = horizontalSpacing(); int spaceX = horizontalSpacing();
if (spaceX == -1) if (spaceX == -1)
spaceX = wid->style()->layoutSpacing( spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing(); int spaceY = verticalSpacing();
if (spaceY == -1) if (spaceY == -1)
spaceY = wid->style()->layoutSpacing( spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
//! [10]
//! [11]
int nextX = x + item->sizeHint().width() + spaceX; int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) { if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x(); x = effectiveRect.x();
y = y + lineHeight + spaceY; y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX; nextX = x + item->sizeHint().width() + spaceX;
if (maxLineHeights.size() > 0) {
maxLineHeight = maxLineHeights.takeFirst();
}
lineHeight = 0; lineHeight = 0;
} }
if (!testOnly) if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); {
QSize size = item->sizeHint();
if (wid && (wid->sizePolicy().verticalPolicy() != QSizePolicy::Fixed)) {
size.setHeight(maxLineHeight);
}
QRect r(QPoint(x, y), size);
item->setGeometry(r);
}
x = nextX; x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height()); lineHeight = qMax(lineHeight, item->sizeHint().height());
} }
return y + lineHeight - rect.y() + bottom; return y + lineHeight - rect.y() + bottom;
} }
//! [11]
//! [12]
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{ {
QObject *parent = this->parent(); QObject *parent = this->parent();
@ -218,4 +235,3 @@ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
return static_cast<QLayout *>(parent)->spacing(); return static_cast<QLayout *>(parent)->spacing();
} }
} }
//! [12]