Cockatrice/cockatrice/src/interface/widgets/quick_settings/settings_button_widget.cpp
RickyRister 6766b0af89
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
[SettingsButtonWidget] Fix memory leak from unparented popup (#7055)
2026-07-28 16:12:41 -07:00

121 lines
3.7 KiB
C++

#include "settings_button_widget.h"
#include <QApplication>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QScreen>
SettingsButtonWidget::SettingsButtonWidget(QWidget *parent)
: QWidget(parent), button(new QToolButton(this)), popup(new SettingsPopupWidget(nullptr))
{
button->setIcon(QPixmap("theme:icons/cogwheel"));
button->setCheckable(true);
button->setFixedSize(32, 32);
connect(button, &QToolButton::clicked, this, &SettingsButtonWidget::togglePopup);
connect(popup, &SettingsPopupWidget::aboutToClose, this, &SettingsButtonWidget::onPopupClosed);
layout = new QHBoxLayout(this);
layout->addWidget(button);
layout->setContentsMargins(0, 0, 0, 0);
setLayout(layout);
}
SettingsButtonWidget::~SettingsButtonWidget()
{
// We don't parent the popup because it might lead to better behavior on certain window managers.
// So we have to manually delete it
popup->deleteLater();
}
void SettingsButtonWidget::addSettingsWidget(QWidget *toAdd) const
{
popup->addSettingsWidget(toAdd);
}
void SettingsButtonWidget::removeSettingsWidget(QWidget *toRemove) const
{
popup->removeSettingsWidget(toRemove);
}
void SettingsButtonWidget::setButtonIcon(QPixmap iconMap)
{
button->setIcon(iconMap);
}
void SettingsButtonWidget::setButtonText(const QString &text)
{
buttonText = text;
button->setMinimumSize(QSize(0, 0));
button->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
button->setText(text);
button->setFixedHeight(32);
button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
button->setMinimumWidth(32); // icon-only fallback minimum
}
void SettingsButtonWidget::setCompact(bool _compact)
{
compact = _compact;
if (compact) {
button->setToolButtonStyle(Qt::ToolButtonIconOnly);
button->setFixedWidth(32);
} else {
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
button->setText(buttonText);
button->setFixedWidth(QWIDGETSIZE_MAX); // release fixed width
button->setMinimumWidth(32);
button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
}
}
void SettingsButtonWidget::togglePopup()
{
if (popup->isVisible()) {
popup->close();
} else {
popup->adjustSizeToFitScreen(); // Ensure proper size
QSize popupSize = popup->size();
QPoint buttonGlobalPos = button->mapToGlobal(QPoint(0, button->height()));
QScreen *screen = QApplication::screenAt(buttonGlobalPos);
QRect screenGeom = screen ? screen->availableGeometry() : QApplication::primaryScreen()->availableGeometry();
int x = buttonGlobalPos.x();
int y = buttonGlobalPos.y();
// Adjust position to stay within screen bounds
if (x + popupSize.width() > screenGeom.right()) {
x = buttonGlobalPos.x() - popupSize.width() + button->width();
}
if (y + popupSize.height() > screenGeom.bottom()) {
y = buttonGlobalPos.y() - popupSize.height() - button->height();
}
popup->move(x, y);
popup->show();
popup->setFocus();
button->setChecked(true);
}
}
void SettingsButtonWidget::onPopupClosed() const
{
button->setChecked(false); // Ensure button unchecks when popup closes
}
void SettingsButtonWidget::mousePressEvent(QMouseEvent *event)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (popup->isVisible() && !popup->geometry().contains(event->globalPosition().toPoint())) {
#else
if (popup->isVisible() && !popup->geometry().contains(event->globalPos())) {
#endif
popup->close();
}
QWidget::mousePressEvent(event);
}