Add Utility Layouts and corresponding Widgets (#5177)

* Add FlowWidget class with flexible layout and scroll handling

- Implemented FlowWidget class to organize widgets in a flow layout with scrollable options.
- Integrated QScrollArea to handle overflow with configurable horizontal and vertical scroll policies.
- Incorporated dynamic layout selection (FlowLayout, HorizontalFlowLayout, VerticalFlowLayout) based on scroll policy.

* Add OverlapWidget and OverlapLayout for managing overlapping child widgets

- Implemented the OverlapWidget class to manage child widgets in an overlapping manner, supporting configurable overlap percentage, maximum columns, maximum rows, and layout direction.
- Introduced the OverlapLayout class, which arranges widgets with overlapping positions, allowing flexible stacking based on specified parameters.

* Add OverlapControlWidget.

* Delete FlowLayout items later to allow them to finish their event loop.

* Allow OverlapWidgets to adjust their rows/columns on resize.

* Clamp vertical FlowLayout to any available parent scrollAreas.

* Implement margins and spacing for FlowLayouts.

* Adjust/revert some things.

* Address pull request comments (nullptr checks and additional comments, mostly.)

* Reformat code so the linter will stop yelling at me.

* Remove undefined methods from FlowLayouts.

* Fix the build.

* Revert FlowLayout::takeAt to index check.

* Commits will continue until linter morale improves.

* Fix various warnings in FlowLayout.

* Fix various warnings in FlowLayout.h.

* Fix various warnings in the FlowLayout classes.

* Fix [[nodiscard]] warning.

* Fix more warnings.

* Final round of yellow squiggle fixing.

* Linter formatting.

* Refactor column/row calculation to be more readable.

* Code style.

* Address PR comments.

* Combine if-statements.

* Replace std::math functions with Qt equivalents.

* Fix non-consts and QtMath.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2024-11-17 19:32:31 +01:00 committed by GitHub
parent c8336df49d
commit 8ef92d26c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 1832 additions and 42 deletions

View file

@ -66,7 +66,7 @@ void CardInfoPictureWithTextOverlayWidget::setOutlineColor(const QColor &color)
*/
void CardInfoPictureWithTextOverlayWidget::setFontSize(const int size)
{
fontSize = size;
fontSize = size > 0 ? size : 1;
update();
}
@ -109,48 +109,50 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event)
// Get the pixmap from the base class using the getter
const QPixmap &pixmap = getResizedPixmap();
if (!pixmap.isNull()) {
// Calculate size and position for drawing
const QSize scaledSize = pixmap.size().scaled(size(), Qt::KeepAspectRatio);
const QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2};
const QRect pixmapRect(topLeft, scaledSize);
// Prepare text wrapping
const QFontMetrics fontMetrics(font);
const int lineHeight = fontMetrics.height();
const int textWidth = pixmapRect.width();
QString wrappedText;
// Break the text into multiple lines to fit within the pixmap width
QString currentLine;
QStringList words = overlayText.split(' ');
for (const QString &word : words) {
if (fontMetrics.horizontalAdvance(currentLine + " " + word) > textWidth) {
wrappedText += currentLine + '\n';
currentLine = word;
} else {
if (!currentLine.isEmpty()) {
currentLine += " ";
}
currentLine += word;
}
}
wrappedText += currentLine;
// Calculate total text block height
const int totalTextHeight = static_cast<int>(wrappedText.count('\n')) * lineHeight + lineHeight;
// Set up the text layout options
QTextOption textOption;
textOption.setAlignment(textAlignment);
// Create a text rectangle centered within the pixmap rect
auto textRect = QRect(pixmapRect.left(), pixmapRect.top(), pixmapRect.width(), totalTextHeight);
textRect.moveTop((pixmapRect.height() - totalTextHeight) / 2 + pixmapRect.top());
// Draw the outlined text
drawOutlinedText(painter, textRect, wrappedText, textOption);
if (pixmap.isNull()) {
return;
}
// Calculate size and position for drawing
const QSize scaledSize = pixmap.size().scaled(size(), Qt::KeepAspectRatio);
const QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2};
const QRect pixmapRect(topLeft, scaledSize);
// Prepare text wrapping
const QFontMetrics fontMetrics(font);
const int lineHeight = fontMetrics.height();
const int textWidth = pixmapRect.width();
QString wrappedText;
// Break the text into multiple lines to fit within the pixmap width
QString currentLine;
QStringList words = overlayText.split(' ');
for (const QString &word : words) {
if (fontMetrics.horizontalAdvance(currentLine + " " + word) > textWidth) {
wrappedText += currentLine + '\n';
currentLine = word;
} else {
if (!currentLine.isEmpty()) {
currentLine += " ";
}
currentLine += word;
}
}
wrappedText += currentLine;
// Calculate total text block height
const int totalTextHeight = static_cast<int>(wrappedText.count('\n')) * lineHeight + lineHeight;
// Set up the text layout options
QTextOption textOption;
textOption.setAlignment(textAlignment);
// Create a text rectangle centered within the pixmap rect
auto textRect = QRect(pixmapRect.left(), pixmapRect.top(), pixmapRect.width(), totalTextHeight);
textRect.moveTop((pixmapRect.height() - totalTextHeight) / 2 + pixmapRect.top());
// Draw the outlined text
drawOutlinedText(painter, textRect, wrappedText, textOption);
}
/**