Make VDE tools flow

Took 1 hour 23 minutes

Took 5 seconds
This commit is contained in:
Lukas Brübach 2026-05-14 14:48:32 +02:00
parent b785574d2f
commit e174dc397f
4 changed files with 64 additions and 23 deletions

View file

@ -151,7 +151,7 @@ int FlowLayout::layoutAllRows(const int originX, const int originY, const int av
if (!rowItems.isEmpty() && rowUsedWidth + spaceX + itemSize.width() > availableWidth) {
// Current item does not fit — flush the current row, begin a new one.
layoutSingleRow(rowItems, originX, currentY);
layoutSingleRow(rowItems, originX, currentY, availableWidth);
rowItems.clear();
currentY += rowHeight + verticalSpacing();
rowUsedWidth = 0;
@ -166,33 +166,67 @@ int FlowLayout::layoutAllRows(const int originX, const int originY, const int av
rowHeight = qMax(rowHeight, itemSize.height());
}
layoutSingleRow(rowItems, originX, currentY); // Flush the final row.
layoutSingleRow(rowItems, originX, currentY, availableWidth); // Flush the final row.
return currentY + rowHeight;
}
/**
* @brief Sets the geometry for every item in @p rowItems, starting at (@p x, @p y).
*
* Each item is placed at its sizeHint, clamped to its maximumSize.
* Items whose horizontal size policy includes the Expand or MinimumExpanding flag
* share the leftover row width proportionally (like QHBoxLayout stretch), so that
* e.g. a QLineEdit can fill remaining space while fixed-size buttons stay compact.
*
* Items without an expanding policy are placed at their sizeHint, clamped to maximumSize.
*/
void FlowLayout::layoutSingleRow(const QVector<QLayoutItem *> &rowItems, int x, const int y)
void FlowLayout::layoutSingleRow(const QVector<QLayoutItem *> &rowItems, int x, const int y, const int availableWidth)
{
if (rowItems.isEmpty())
return;
// ── Pass 1: measure fixed width and count expanding items ────────────────
int fixedWidth = 0;
int expandingCount = 0;
int spacingTotal = (rowItems.size() - 1) * horizontalSpacing();
for (QLayoutItem *item : rowItems) {
if (!item || item->isEmpty()) {
continue;
}
QWidget *widget = item->widget();
if (!widget) {
continue;
}
const QSizePolicy::Policy hPolicy = widget ? widget->sizePolicy().horizontalPolicy() : QSizePolicy::Fixed;
if (hPolicy & QSizePolicy::ExpandFlag) {
++expandingCount;
} else {
const int maxW = widget ? widget->maximumWidth() : QWIDGETSIZE_MAX;
fixedWidth += qMin(item->sizeHint().width(), maxW);
}
}
// Extra pixels to share among expanding items (never negative).
const int extra = qMax(0, availableWidth - spacingTotal - fixedWidth);
const int expandingShare = (expandingCount > 0) ? extra / expandingCount : 0;
// ── Pass 2: place items ──────────────────────────────────────────────────
for (QLayoutItem *item : rowItems) {
if (!item || item->isEmpty())
continue;
QWidget *widget = item->widget();
if (!widget)
continue;
const QSizePolicy::Policy hPolicy = widget->sizePolicy().horizontalPolicy();
const QSize maxSize = widget->maximumSize();
const int itemWidth = qMin(item->sizeHint().width(), maxSize.width());
const bool expands = hPolicy & QSizePolicy::ExpandFlag;
const int itemWidth =
expands ? qMin(expandingShare, maxSize.width()) : qMin(item->sizeHint().width(), maxSize.width());
const int itemHeight = qMin(item->sizeHint().height(), maxSize.height());
item->setGeometry(QRect(QPoint(x, y), QSize(itemWidth, itemHeight)));
// Move the x-position to the right, leaving space for horizontal spacing
x += itemWidth + horizontalSpacing();
}
}

View file

@ -54,7 +54,7 @@ public:
// Layout passes (virtual so subclasses can override placement logic)
virtual int layoutAllRows(int originX, int originY, int availableWidth);
virtual void layoutSingleRow(const QVector<QLayoutItem *> &rowItems, int x, int y);
virtual void layoutSingleRow(const QVector<QLayoutItem *> &rowItems, int x, int y, int availableWidth);
int layoutAllColumns(int originX, int originY, int availableHeight);
void layoutSingleColumn(const QVector<QLayoutItem *> &colItems, int x, int y);

View file

@ -69,7 +69,13 @@ VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent,
void VisualDeckEditorWidget::initializeSearchBarAndCompleter()
{
searchBar = new QLineEdit(this);
searchContainer = new QWidget(this);
searchContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
searchLayout = new QHBoxLayout(searchContainer);
searchContainer->setLayout(searchLayout);
searchBar = new QLineEdit(searchContainer);
searchContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
connect(searchBar, &QLineEdit::returnPressed, this, [=, this]() {
if (!searchBar->hasFocus())
return;
@ -80,6 +86,8 @@ void VisualDeckEditorWidget::initializeSearchBarAndCompleter()
}
});
searchLayout->addWidget(searchBar);
setFocusProxy(searchBar);
setFocusPolicy(Qt::ClickFocus);
@ -133,13 +141,15 @@ void VisualDeckEditorWidget::initializeSearchBarAndCompleter()
});
// Search button functionality
searchPushButton = new QPushButton(this);
searchPushButton = new QPushButton(searchContainer);
connect(searchPushButton, &QPushButton::clicked, this, [=, this]() {
ExactCard card = CardDatabaseManager::query()->getCard({searchBar->text()});
if (card) {
emit cardAdditionRequested(card);
}
});
searchLayout->addWidget(searchPushButton);
}
void VisualDeckEditorWidget::initializeDisplayOptionsWidget()
@ -156,18 +166,14 @@ void VisualDeckEditorWidget::initializeDisplayOptionsWidget()
void VisualDeckEditorWidget::initializeDisplayOptionsAndSearchWidget()
{
initializeSearchBarAndCompleter();
initializeDisplayOptionsWidget();
displayOptionsAndSearch = new QWidget(this);
displayOptionsAndSearchLayout = new QHBoxLayout(displayOptionsAndSearch);
displayOptionsAndSearchLayout->setContentsMargins(0, 0, 0, 0);
displayOptionsAndSearchLayout->setAlignment(Qt::AlignLeft);
displayOptionsAndSearch->setLayout(displayOptionsAndSearchLayout);
displayOptionsAndSearch = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
displayOptionsAndSearchLayout->addWidget(displayOptionsWidget);
displayOptionsAndSearchLayout->addWidget(searchBar);
displayOptionsAndSearchLayout->addWidget(searchPushButton);
// We split into two sub-widgets here so that the searchBar and button wrap together. At this point, we've done
// pretty much all we can and have reached our minimum size.
displayOptionsAndSearch->addWidget(displayOptionsWidget);
displayOptionsAndSearch->addWidget(searchContainer); // Expanding — fills remainder of its row
}
void VisualDeckEditorWidget::initializeScrollAreaAndZoneContainer()

View file

@ -90,9 +90,10 @@ private:
CardDatabaseModel *cardDatabaseModel;
CardDatabaseDisplayModel *cardDatabaseDisplayModel;
CardCompleterProxyModel *proxyModel;
QWidget *searchContainer;
QHBoxLayout *searchLayout;
QCompleter *completer;
QWidget *displayOptionsAndSearch;
QHBoxLayout *displayOptionsAndSearchLayout;
FlowWidget *displayOptionsAndSearch;
VisualDeckDisplayOptionsWidget *displayOptionsWidget;
QPushButton *searchPushButton;
QScrollArea *scrollArea;