From 3e5cd44fd50e36af39e3bacebd3d0209f2e22e60 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Fri, 10 Oct 2025 13:06:16 -0400 Subject: [PATCH] frontend: Add Menu Checkbox widget Update MenuCheckBox.hpp --- frontend/cmake/ui-components.cmake | 2 + frontend/components/MenuCheckBox.cpp | 109 +++++++++++++++++++++++++++ frontend/components/MenuCheckBox.hpp | 50 ++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 frontend/components/MenuCheckBox.cpp create mode 100644 frontend/components/MenuCheckBox.hpp diff --git a/frontend/cmake/ui-components.cmake b/frontend/cmake/ui-components.cmake index c15dba6f7..b9bd0feb6 100644 --- a/frontend/cmake/ui-components.cmake +++ b/frontend/cmake/ui-components.cmake @@ -48,6 +48,8 @@ target_sources( components/MediaControls.hpp components/MenuButton.cpp components/MenuButton.hpp + components/MenuCheckBox.cpp + components/MenuCheckBox.hpp components/Multiview.cpp components/Multiview.hpp components/MuteCheckBox.hpp diff --git a/frontend/components/MenuCheckBox.cpp b/frontend/components/MenuCheckBox.cpp new file mode 100644 index 000000000..f2229a58f --- /dev/null +++ b/frontend/components/MenuCheckBox.cpp @@ -0,0 +1,109 @@ +/****************************************************************************** + Copyright (C) 2025 by Taylor Giampaolo + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#include "MenuCheckBox.hpp" + +#include + +MenuCheckBox::MenuCheckBox(const QString &text, QWidget *parent) : QCheckBox(text, parent) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + setContentsMargins(0, 0, 0, 0); + + if (auto menu = qobject_cast(parent)) { + connect(menu, &QMenu::hovered, this, [this, menu](QAction *action) { + if (action != menuAction) { + setHovered(false); + update(); + } + }); + connect(menu, &QMenu::aboutToHide, this, [this]() { setHovered(false); }); + } +} + +void MenuCheckBox::setAction(QAction *action) +{ + menuAction = action; +} + +void MenuCheckBox::focusInEvent(QFocusEvent *) +{ + setHovered(true); +} + +void MenuCheckBox::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + mousePressInside = true; + event->accept(); + } else { + QCheckBox::mousePressEvent(event); + } +} + +void MenuCheckBox::mouseMoveEvent(QMouseEvent *event) +{ + if (!rect().contains(event->pos())) { + mousePressInside = false; + } + event->accept(); +} + +void MenuCheckBox::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (mousePressInside && rect().contains(event->pos())) { + toggle(); + } + event->accept(); + } else { + QCheckBox::mouseReleaseEvent(event); + } + + mousePressInside = false; +} + +void MenuCheckBox::enterEvent(QEnterEvent *) +{ + setHovered(true); + update(); +} + +void MenuCheckBox::leaveEvent(QEvent *) +{ + setHovered(false); + update(); +} + +void MenuCheckBox::paintEvent(QPaintEvent *) +{ + QStylePainter p(this); + QStyleOptionButton opt; + initStyleOption(&opt); + + if (isHovered) { + opt.state |= QStyle::State_MouseOver; + opt.state |= QStyle::State_Selected; + } + + p.drawControl(QStyle::CE_CheckBox, opt); +} + +void MenuCheckBox::setHovered(bool hovered) +{ + isHovered = hovered; +} diff --git a/frontend/components/MenuCheckBox.hpp b/frontend/components/MenuCheckBox.hpp new file mode 100644 index 000000000..550dd654e --- /dev/null +++ b/frontend/components/MenuCheckBox.hpp @@ -0,0 +1,50 @@ +/****************************************************************************** + Copyright (C) 2025 by Taylor Giampaolo + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + +#pragma once + +#include +#include + +class QStyleOptionButton; +class QStylePainter; +class QMouseEvent; + +class MenuCheckBox : public QCheckBox { + Q_OBJECT + +public: + explicit MenuCheckBox(const QString &text, QWidget *parent = nullptr); + + void setAction(QAction *action); + +protected: + void focusInEvent(QFocusEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void enterEvent(QEnterEvent *event) override; + void leaveEvent(QEvent *event) override; + void paintEvent(QPaintEvent *event) override; + +private: + QPointer menuAction = nullptr; + bool mousePressInside = false; + + bool isHovered = false; + void setHovered(bool hovered); +};