Skip to content

Commit 05ea7d7

Browse files
committed
frontend: Improve source context menus
1 parent 84b8d16 commit 05ea7d7

24 files changed

Lines changed: 449 additions & 158 deletions

frontend/cmake/ui-components.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ target_sources(
5252
components/MenuButton.hpp
5353
components/MenuCheckBox.cpp
5454
components/MenuCheckBox.hpp
55+
components/MenuRadioButton.cpp
56+
components/MenuRadioButton.hpp
5557
components/Multiview.cpp
5658
components/Multiview.hpp
5759
components/MuteCheckBox.hpp

frontend/components/MenuCheckBox.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,25 @@ MenuCheckBox::MenuCheckBox(const QString &text, QWidget *parent) : QCheckBox(tex
2828
setContentsMargins(0, 0, 0, 0);
2929

3030
if (auto menu = qobject_cast<QMenu *>(parent)) {
31-
connect(menu, &QMenu::hovered, this, [this, menu](QAction *action) {
32-
if (action != menuAction) {
33-
setHovered(false);
34-
update();
35-
}
31+
connect(menu, &QMenu::aboutToShow, this, [this]() {
32+
setHovered(false);
33+
update();
34+
});
35+
connect(menu, &QMenu::aboutToHide, this, [this]() {
36+
setHovered(false);
37+
update();
3638
});
37-
connect(menu, &QMenu::aboutToHide, this, [this]() { setHovered(false); });
3839
}
3940
}
4041

41-
void MenuCheckBox::setAction(QAction *action)
42+
void MenuCheckBox::focusInEvent(QFocusEvent *)
4243
{
43-
menuAction = action;
44+
setHovered(true);
4445
}
4546

46-
void MenuCheckBox::focusInEvent(QFocusEvent *)
47+
void MenuCheckBox::focusOutEvent(QFocusEvent *)
4748
{
48-
setHovered(true);
49+
setHovered(false);
4950
}
5051

5152
void MenuCheckBox::mousePressEvent(QMouseEvent *event)

frontend/components/MenuCheckBox.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ class MenuCheckBox : public QCheckBox {
3030
public:
3131
explicit MenuCheckBox(const QString &text, QWidget *parent = nullptr);
3232

33-
void setAction(QAction *action);
34-
3533
protected:
3634
void focusInEvent(QFocusEvent *event) override;
35+
void focusOutEvent(QFocusEvent *event) override;
3736
void mousePressEvent(QMouseEvent *event) override;
3837
void mouseMoveEvent(QMouseEvent *event) override;
3938
void mouseReleaseEvent(QMouseEvent *event) override;
@@ -42,7 +41,6 @@ class MenuCheckBox : public QCheckBox {
4241
void paintEvent(QPaintEvent *event) override;
4342

4443
private:
45-
QPointer<QAction> menuAction = nullptr;
4644
bool mousePressInside = false;
4745

4846
bool isHovered = false;
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/******************************************************************************
2+
Copyright (C) 2026 by Taylor Giampaolo <warchamp7@obsproject.com>
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
******************************************************************************/
17+
18+
#include "MenuRadioButton.hpp"
19+
20+
#include <QMenu>
21+
#include <QMouseEvent>
22+
#include <QStyleOptionButton>
23+
#include <QStylePainter>
24+
25+
MenuRadioButton::MenuRadioButton(const QString &text, QWidget *parent) : QRadioButton(text, parent)
26+
{
27+
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
28+
setContentsMargins(0, 0, 0, 0);
29+
30+
if (auto menu = qobject_cast<QMenu *>(parent)) {
31+
connect(menu, &QMenu::aboutToShow, this, [this]() {
32+
setHovered(false);
33+
update();
34+
});
35+
connect(menu, &QMenu::aboutToHide, this, [this]() {
36+
setHovered(false);
37+
update();
38+
});
39+
}
40+
}
41+
42+
void MenuRadioButton::focusInEvent(QFocusEvent *)
43+
{
44+
setHovered(true);
45+
}
46+
47+
void MenuRadioButton::focusOutEvent(QFocusEvent *)
48+
{
49+
setHovered(false);
50+
}
51+
52+
void MenuRadioButton::mousePressEvent(QMouseEvent *event)
53+
{
54+
if (event->button() == Qt::LeftButton) {
55+
mousePressInside = true;
56+
event->accept();
57+
} else {
58+
QRadioButton::mousePressEvent(event);
59+
}
60+
}
61+
62+
void MenuRadioButton::mouseMoveEvent(QMouseEvent *event)
63+
{
64+
if (!rect().contains(event->pos())) {
65+
mousePressInside = false;
66+
}
67+
event->accept();
68+
}
69+
70+
void MenuRadioButton::mouseReleaseEvent(QMouseEvent *event)
71+
{
72+
if (event->button() == Qt::LeftButton) {
73+
if (mousePressInside && rect().contains(event->pos())) {
74+
toggle();
75+
}
76+
event->accept();
77+
} else {
78+
QRadioButton::mouseReleaseEvent(event);
79+
}
80+
81+
mousePressInside = false;
82+
}
83+
84+
void MenuRadioButton::enterEvent(QEnterEvent *)
85+
{
86+
setHovered(true);
87+
update();
88+
}
89+
90+
void MenuRadioButton::leaveEvent(QEvent *)
91+
{
92+
setHovered(false);
93+
update();
94+
}
95+
96+
void MenuRadioButton::paintEvent(QPaintEvent *)
97+
{
98+
QStylePainter p(this);
99+
QStyleOptionButton opt;
100+
initStyleOption(&opt);
101+
102+
if (isHovered) {
103+
opt.state |= QStyle::State_MouseOver;
104+
opt.state |= QStyle::State_Selected;
105+
}
106+
107+
p.drawControl(QStyle::CE_RadioButton, opt);
108+
}
109+
110+
void MenuRadioButton::setHovered(bool hovered)
111+
{
112+
isHovered = hovered;
113+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/******************************************************************************
2+
Copyright (C) 2026 by Taylor Giampaolo <warchamp7@obsproject.com>
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
******************************************************************************/
17+
18+
#pragma once
19+
20+
#include <QRadioButton>
21+
#include <QPointer>
22+
23+
class QStyleOptionButton;
24+
class QStylePainter;
25+
class QMouseEvent;
26+
27+
class MenuRadioButton : public QRadioButton {
28+
Q_OBJECT
29+
30+
public:
31+
explicit MenuRadioButton(const QString &text, QWidget *parent = nullptr);
32+
33+
protected:
34+
void focusInEvent(QFocusEvent *event) override;
35+
void focusOutEvent(QFocusEvent *event) override;
36+
void mousePressEvent(QMouseEvent *event) override;
37+
void mouseMoveEvent(QMouseEvent *event) override;
38+
void mouseReleaseEvent(QMouseEvent *event) override;
39+
void enterEvent(QEnterEvent *event) override;
40+
void leaveEvent(QEvent *event) override;
41+
void paintEvent(QPaintEvent *event) override;
42+
43+
bool isHovered = false;
44+
void setHovered(bool hovered);
45+
46+
private:
47+
bool mousePressInside = false;
48+
};
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)