mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-10 08:14:47 -07:00
[VDD] Fix minimum size by adding a compact mode to quickSettingsButtons (#6890)
* [VDD] Fix minimum size by adding a compact mode to quickSettingsButtons Took 17 minutes Took 5 seconds * Fix and use FlowWidget/FlowLayout Took 35 minutes Took 4 seconds * Set spacings. Took 12 minutes * Make VDE tools flow Took 1 hour 23 minutes Took 5 seconds * Squeeze and flow even more. Took 11 minutes * Make pushbutton compact. Took 54 minutes Took 7 seconds --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
parent
762e742be0
commit
7153f7d4c1
21 changed files with 666 additions and 617 deletions
|
|
@ -1,42 +1,52 @@
|
|||
/**
|
||||
* @file flow_widget.cpp
|
||||
* @brief Implementation of the FlowWidget class for organizing widgets in a flow layout within a scrollable area.
|
||||
* @brief Implementation of FlowWidget — a QWidget hosting a FlowLayout inside an
|
||||
* optional QScrollArea.
|
||||
*/
|
||||
|
||||
#include "flow_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QResizeEvent>
|
||||
#include <QScrollArea>
|
||||
#include <QSizePolicy>
|
||||
#include <QWidget>
|
||||
#include <qscrollarea.h>
|
||||
#include <qsizepolicy.h>
|
||||
|
||||
/**
|
||||
* @brief Constructs a FlowWidget with a scrollable layout.
|
||||
* @brief Constructs a FlowWidget.
|
||||
*
|
||||
* @param parent The parent widget of this FlowWidget.
|
||||
* @param horizontalPolicy The horizontal scroll bar policy for the scroll area.
|
||||
* @param verticalPolicy The vertical scroll bar policy for the scroll area.
|
||||
* When both scroll policies are Qt::ScrollBarAlwaysOff the scroll area is
|
||||
* omitted entirely and the container is placed directly in the main layout.
|
||||
*
|
||||
* @param parent Parent widget.
|
||||
* @param _flowDirection Qt::Horizontal for row-wrapping, Qt::Vertical for column-wrapping.
|
||||
* @param horizontalPolicy Horizontal scroll-bar policy.
|
||||
* @param verticalPolicy Vertical scroll-bar policy.
|
||||
*/
|
||||
FlowWidget::FlowWidget(QWidget *parent,
|
||||
const Qt::Orientation _flowDirection,
|
||||
const Qt::ScrollBarPolicy horizontalPolicy,
|
||||
const Qt::ScrollBarPolicy verticalPolicy)
|
||||
: QWidget(parent), flowDirection(_flowDirection)
|
||||
: QWidget(parent), scrollArea(nullptr), flowDirection(_flowDirection)
|
||||
|
||||
{
|
||||
// Main Widget and Layout
|
||||
if (_flowDirection == Qt::Horizontal) {
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
setMinimumWidth(0);
|
||||
// Top-level size policy
|
||||
// Horizontal flow: expand horizontally, let height be determined by wrapping.
|
||||
// Vertical flow: expand vertically, let width be determined by wrapping.
|
||||
if (flowDirection == Qt::Horizontal) {
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
} else {
|
||||
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
setMinimumHeight(0);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
}
|
||||
|
||||
mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(mainLayout);
|
||||
|
||||
if (horizontalPolicy != Qt::ScrollBarAlwaysOff || verticalPolicy != Qt::ScrollBarAlwaysOff) {
|
||||
// Scroll Area, which should expand as much as possible, since it should be the only direct child widget.
|
||||
const bool useScrollArea = (horizontalPolicy != Qt::ScrollBarAlwaysOff || verticalPolicy != Qt::ScrollBarAlwaysOff);
|
||||
|
||||
// Scroll area (optional)
|
||||
if (useScrollArea) {
|
||||
scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setMinimumSize(0, 0);
|
||||
|
|
@ -48,39 +58,28 @@ FlowWidget::FlowWidget(QWidget *parent,
|
|||
scrollArea = nullptr;
|
||||
}
|
||||
|
||||
// Flow Layout inside the scroll area
|
||||
if (horizontalPolicy == Qt::ScrollBarAlwaysOff && verticalPolicy == Qt::ScrollBarAlwaysOff) {
|
||||
container = new QWidget(this);
|
||||
} else {
|
||||
container = new QWidget(scrollArea);
|
||||
}
|
||||
// Container widget (holds the FlowLayout)
|
||||
container = new QWidget(useScrollArea ? static_cast<QWidget *>(scrollArea) : this);
|
||||
|
||||
// The container should be willing to grow in both axes; its actual size is
|
||||
// governed by the FlowLayout's sizeHint / heightForWidth, not by a fixed policy.
|
||||
container->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
container->setMinimumSize(0, 0);
|
||||
|
||||
flowLayout = new FlowLayout(container, flowDirection);
|
||||
|
||||
container->setLayout(flowLayout);
|
||||
// The container should expand as much as possible, trusting the scrollArea to constrain it.
|
||||
if (_flowDirection == Qt::Horizontal) {
|
||||
container->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
container->setMinimumWidth(0);
|
||||
} else {
|
||||
container->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
container->setMinimumHeight(0);
|
||||
}
|
||||
|
||||
// Use the FlowLayout container directly if we disable the ScrollArea
|
||||
if (horizontalPolicy == Qt::ScrollBarAlwaysOff && verticalPolicy == Qt::ScrollBarAlwaysOff) {
|
||||
mainLayout->addWidget(container);
|
||||
} else {
|
||||
if (useScrollArea) {
|
||||
scrollArea->setWidget(container);
|
||||
mainLayout->addWidget(scrollArea);
|
||||
} else {
|
||||
mainLayout->addWidget(container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a widget to the flow layout within the FlowWidget.
|
||||
*
|
||||
* Adjusts the widget's size policy based on the scroll bar policies.
|
||||
*
|
||||
* @param widget_to_add The widget to add to the flow layout.
|
||||
*/
|
||||
void FlowWidget::addWidget(QWidget *widget_to_add) const
|
||||
|
|
@ -100,77 +99,74 @@ void FlowWidget::removeWidget(QWidget *widgetToRemove) const
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Clears all widgets from the flow layout.
|
||||
* @brief Removes all widgets from the flow layout and deletes them.
|
||||
*
|
||||
* Deletes each widget and layout item, and recreates the flow layout if it was removed.
|
||||
* If the layout pointer has somehow been lost it is recreated before returning.
|
||||
*/
|
||||
void FlowWidget::clearLayout()
|
||||
{
|
||||
if (flowLayout != nullptr) {
|
||||
if (flowLayout) {
|
||||
QLayoutItem *item;
|
||||
while ((item = flowLayout->takeAt(0)) != nullptr) {
|
||||
item->widget()->deleteLater(); // Delete the widget
|
||||
delete item; // Delete the layout item
|
||||
while ((item = flowLayout->takeAt(0))) {
|
||||
if (item->widget())
|
||||
item->widget()->deleteLater();
|
||||
delete item;
|
||||
}
|
||||
} else {
|
||||
// Defensive fallback: recreate the layout if it was deleted externally.
|
||||
flowLayout = new FlowLayout(container, flowDirection);
|
||||
container->setLayout(flowLayout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles resize events for the FlowWidget.
|
||||
* @brief Marks the flow layout as dirty so Qt recomputes item positions.
|
||||
*
|
||||
* Triggers layout recalculation and adjusts the scroll area content size.
|
||||
*
|
||||
* @param event The resize event containing the new size information.
|
||||
* We do NOT call adjustSize() or activate() here:
|
||||
* - adjustSize() would freeze geometry by calling setFixedSize internally.
|
||||
* - activate() called inside a resize event can cause synchronous re-entrancy.
|
||||
* Qt automatically calls setGeometry on the layout after a resize, so simply
|
||||
* invalidating is sufficient.
|
||||
*/
|
||||
void FlowWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
qCDebug(FlowWidgetSizeLog) << "resizeEvent:" << event->size();
|
||||
|
||||
qCDebug(FlowWidgetSizeLog) << event->size();
|
||||
|
||||
// Trigger the layout to recalculate
|
||||
if (flowLayout != nullptr) {
|
||||
flowLayout->invalidate(); // Marks the layout as dirty and requires recalculation
|
||||
flowLayout->activate(); // Recalculate the layout based on the new size
|
||||
}
|
||||
|
||||
// Ensure the scroll area and its content adjust correctly
|
||||
if (scrollArea != nullptr && scrollArea->widget() != nullptr) {
|
||||
qCDebug(FlowWidgetSizeLog) << "Got a scrollarea: " << scrollArea->widget()->size();
|
||||
scrollArea->widget()->adjustSize();
|
||||
} else {
|
||||
container->adjustSize();
|
||||
if (flowLayout) {
|
||||
flowLayout->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowWidget::setSpacing(int hSpacing, int vSpacing)
|
||||
{
|
||||
flowLayout->setHorizontalMargin(hSpacing);
|
||||
flowLayout->setVerticalMargin(vSpacing);
|
||||
flowLayout->invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the minimum size for all widgets inside the FlowWidget to the maximum sizeHint of all of them.
|
||||
* @brief Sets every child widget's minimum size to the largest sizeHint in the layout.
|
||||
*
|
||||
* Useful for toolbars or button bars where all items should be the same size.
|
||||
*/
|
||||
void FlowWidget::setMinimumSizeToMaxSizeHint()
|
||||
{
|
||||
QSize maxSize(0, 0); // Initialize to a zero size
|
||||
QSize maxSize(0, 0);
|
||||
|
||||
// Iterate over all widgets in the flow layout to find the maximum sizeHint
|
||||
for (int i = 0; i < flowLayout->count(); ++i) {
|
||||
if (QLayoutItem *item = flowLayout->itemAt(i)) {
|
||||
if (QWidget *widget = item->widget()) {
|
||||
// Update the max size based on the sizeHint of each widget
|
||||
QSize widgetSizeHint = widget->sizeHint();
|
||||
maxSize.setWidth(qMax(maxSize.width(), widgetSizeHint.width()));
|
||||
maxSize.setHeight(qMax(maxSize.height(), widgetSizeHint.height()));
|
||||
}
|
||||
QLayoutItem *item = flowLayout->itemAt(i);
|
||||
if (item && item->widget()) {
|
||||
maxSize = maxSize.expandedTo(item->widget()->sizeHint());
|
||||
}
|
||||
}
|
||||
|
||||
// Set the minimum size for all widgets to the max sizeHint
|
||||
for (int i = 0; i < flowLayout->count(); ++i) {
|
||||
if (QLayoutItem *item = flowLayout->itemAt(i)) {
|
||||
if (QWidget *widget = item->widget()) {
|
||||
widget->setMinimumSize(maxSize);
|
||||
}
|
||||
QLayoutItem *item = flowLayout->itemAt(i);
|
||||
if (item && item->widget()) {
|
||||
item->widget()->setMinimumSize(maxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue