| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <QWidget> |
| | #include "FlowLayout.h" |
| |
|
| | using namespace StartGui; |
| |
|
| | FlowLayout::FlowLayout(QWidget* parent, int margin, int hSpacing, int vSpacing) |
| | : QLayout(parent) |
| | , hSpace {hSpacing} |
| | , vSpace {vSpacing} |
| | { |
| | setContentsMargins(margin, margin, margin, margin); |
| | } |
| |
|
| | FlowLayout::~FlowLayout() |
| | { |
| | QLayoutItem* item {}; |
| | while ((item = takeAt(0))) { |
| | delete item; |
| | } |
| | } |
| |
|
| | void FlowLayout::addItem(QLayoutItem* item) |
| | { |
| | itemList.append(item); |
| | } |
| |
|
| | int FlowLayout::horizontalSpacing() const |
| | { |
| | if (hSpace >= 0) { |
| | return hSpace; |
| | } |
| |
|
| | return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); |
| | } |
| |
|
| | int FlowLayout::verticalSpacing() const |
| | { |
| | if (vSpace >= 0) { |
| | return vSpace; |
| | } |
| |
|
| | return smartSpacing(QStyle::PM_LayoutVerticalSpacing); |
| | } |
| |
|
| | int FlowLayout::count() const |
| | { |
| | return itemList.size(); |
| | } |
| |
|
| | QLayoutItem* FlowLayout::itemAt(int index) const |
| | { |
| | if (index >= 0 && index < itemList.size()) { |
| | return itemList[index]; |
| | } |
| |
|
| | return nullptr; |
| | } |
| |
|
| | QLayoutItem* FlowLayout::takeAt(int index) |
| | { |
| | if (index >= 0 && index < itemList.size()) { |
| | return itemList.takeAt(index); |
| | } |
| |
|
| | return nullptr; |
| | } |
| |
|
| | Qt::Orientations FlowLayout::expandingDirections() const |
| | { |
| | return {}; |
| | } |
| |
|
| | bool FlowLayout::hasHeightForWidth() const |
| | { |
| | return true; |
| | } |
| |
|
| | int FlowLayout::heightForWidth(int width) const |
| | { |
| | int height = doLayout(QRect(0, 0, width, 0), true); |
| | return height; |
| | } |
| |
|
| | void FlowLayout::setGeometry(const QRect& rect) |
| | { |
| | QLayout::setGeometry(rect); |
| | doLayout(rect, false); |
| | } |
| |
|
| | QSize FlowLayout::sizeHint() const |
| | { |
| | return minimumSize(); |
| | } |
| |
|
| | QSize FlowLayout::minimumSize() const |
| | { |
| | QSize size; |
| | for (auto item : std::as_const(itemList)) { |
| | size = size.expandedTo(item->minimumSize()); |
| | } |
| |
|
| | QMargins margins = contentsMargins(); |
| | size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom()); |
| | return size; |
| | } |
| |
|
| | int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const |
| | { |
| | QObject* par = parent(); |
| | if (!par) { |
| | return -1; |
| | } |
| |
|
| | if (par->isWidgetType()) { |
| | auto widget = qobject_cast<QWidget*>(par); |
| | return widget->style()->pixelMetric(pm, nullptr, widget); |
| | } |
| |
|
| | return static_cast<QLayout*>(par)->spacing(); |
| | } |
| |
|
| | int FlowLayout::doLayout(const QRect& rect, bool testOnly) const |
| | { |
| | int left {}; |
| | int top {}; |
| | int right {}; |
| | int bottom {}; |
| | getContentsMargins(&left, &top, &right, &bottom); |
| | QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); |
| |
|
| | int x = effectiveRect.x(); |
| | int y = effectiveRect.y(); |
| | int lineHeight = 0; |
| |
|
| | QVector<QLayoutItem*> currentRow; |
| |
|
| | for (auto item : std::as_const(itemList)) { |
| | QWidget* wid = item->widget(); |
| | QSize itemSizeHint = item->sizeHint(); |
| |
|
| | int spaceX = horizontalSpacing(); |
| | if (spaceX == -1) { |
| | spaceX = wid->style()->layoutSpacing( |
| | QSizePolicy::PushButton, |
| | QSizePolicy::PushButton, |
| | Qt::Horizontal |
| | ); |
| | } |
| |
|
| | int spaceY = verticalSpacing(); |
| | if (spaceY == -1) { |
| | spaceY = wid->style()->layoutSpacing( |
| | QSizePolicy::PushButton, |
| | QSizePolicy::PushButton, |
| | Qt::Vertical |
| | ); |
| | } |
| |
|
| | int nextX = x + itemSizeHint.width() + spaceX; |
| |
|
| | |
| | if (nextX - spaceX > effectiveRect.right() && !currentRow.isEmpty()) { |
| | |
| | for (auto rowItem : currentRow) { |
| | if (!testOnly) { |
| | rowItem->setGeometry(QRect( |
| | QPoint(rowItem->geometry().x(), y), |
| | QSize(rowItem->sizeHint().width(), lineHeight) |
| | )); |
| | } |
| | } |
| |
|
| | |
| | y += lineHeight + spaceY; |
| | x = effectiveRect.x(); |
| | currentRow.clear(); |
| | } |
| |
|
| | currentRow.append(item); |
| | lineHeight = std::max(lineHeight, itemSizeHint.height()); |
| |
|
| | if (!testOnly) { |
| | item->setGeometry(QRect(QPoint(x, y), QSize(itemSizeHint.width(), lineHeight))); |
| | } |
| |
|
| | x += itemSizeHint.width() + spaceX; |
| | } |
| |
|
| | |
| | for (auto rowItem : currentRow) { |
| | if (!testOnly) { |
| | rowItem->setGeometry(QRect( |
| | QPoint(rowItem->geometry().x(), y), |
| | QSize(rowItem->sizeHint().width(), lineHeight) |
| | )); |
| | } |
| | } |
| |
|
| | return y + lineHeight - rect.y() + bottom; |
| | } |
| |
|
| | #include "moc_FlowLayout.cpp" |
| |
|