DolphinQt: Use non-autodismissable menus in menu bar.

A new class that derives from `QMenu` has been introduced. Menus of this
`NonAutodismissibleMenu` type will stay visible when a _checkable_
action is triggered.

This is convenient in menus that feature a series of check boxes that
toggle visibility of third components (e.g. the **List Columns** menu),
allowing the user to toggle several actions at once.

For now, the new type is used in the top menu bar.
This commit is contained in:
cristian64 2025-04-12 16:04:40 +01:00
parent 5285b1168a
commit eb825bbf4c
5 changed files with 64 additions and 5 deletions

View File

@ -314,6 +314,8 @@ add_executable(dolphin-emu
QtUtils/ImageConverter.h
QtUtils/ModalMessageBox.cpp
QtUtils/ModalMessageBox.h
QtUtils/NonAutodismissibleMenu.cpp
QtUtils/NonAutodismissibleMenu.h
QtUtils/NonDefaultQPushButton.cpp
QtUtils/NonDefaultQPushButton.h
QtUtils/ParallelProgressDialog.h

View File

@ -195,6 +195,7 @@
<ClCompile Include="QtUtils\FileOpenEventFilter.cpp" />
<ClCompile Include="QtUtils\ImageConverter.cpp" />
<ClCompile Include="QtUtils\ModalMessageBox.cpp" />
<ClCompile Include="QtUtils\NonAutodismissibleMenu.cpp" />
<ClCompile Include="QtUtils\NonDefaultQPushButton.cpp" />
<ClCompile Include="QtUtils\PartiallyClosableTabWidget.cpp" />
<ClCompile Include="QtUtils\QtUtils.cpp" />

View File

@ -63,6 +63,7 @@
#include "DolphinQt/NANDRepairDialog.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonAutodismissibleMenu.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
@ -450,7 +451,8 @@ void MenuBar::UpdateStateSlotMenu()
void MenuBar::AddViewMenu()
{
QMenu* view_menu = addMenu(tr("&View"));
auto* const view_menu{new QtUtils::NonAutodismissibleMenu(tr("&View"), this)};
addMenu(view_menu);
QAction* show_log = view_menu->addAction(tr("Show &Log"));
show_log->setCheckable(true);
show_log->setChecked(Settings::Instance().IsLogVisible());
@ -705,7 +707,8 @@ void MenuBar::AddListColumnsMenu(QMenu* view_menu)
{tr("Tags"), &Config::MAIN_GAMELIST_COLUMN_TAGS}};
QActionGroup* column_group = new QActionGroup(this);
m_cols_menu = view_menu->addMenu(tr("List Columns"));
m_cols_menu = new QtUtils::NonAutodismissibleMenu(tr("List Columns"), view_menu);
view_menu->addMenu(m_cols_menu);
column_group->setExclusive(false);
for (const auto& key : columns.keys())
@ -730,7 +733,8 @@ void MenuBar::AddShowPlatformsMenu(QMenu* view_menu)
{tr("Show ELF/DOL"), &Config::MAIN_GAMELIST_LIST_ELF_DOL}};
QActionGroup* platform_group = new QActionGroup(this);
QMenu* plat_menu = view_menu->addMenu(tr("Show Platforms"));
auto* const plat_menu{new QtUtils::NonAutodismissibleMenu(tr("Show Platforms"), view_menu)};
view_menu->addMenu(plat_menu);
platform_group->setExclusive(false);
for (const auto& key : platform_map.keys())
@ -764,7 +768,8 @@ void MenuBar::AddShowRegionsMenu(QMenu* view_menu)
{tr("Show World"), &Config::MAIN_GAMELIST_LIST_WORLD},
{tr("Show Unknown"), &Config::MAIN_GAMELIST_LIST_UNKNOWN}};
QMenu* const region_menu = view_menu->addMenu(tr("Show Regions"));
auto* const region_menu{new QtUtils::NonAutodismissibleMenu(tr("Show Regions"), view_menu)};
view_menu->addMenu(region_menu);
const QAction* const show_all_regions = region_menu->addAction(tr("Show All"));
const QAction* const hide_all_regions = region_menu->addAction(tr("Hide All"));
region_menu->addSeparator();
@ -792,7 +797,8 @@ void MenuBar::AddShowRegionsMenu(QMenu* view_menu)
void MenuBar::AddMovieMenu()
{
auto* movie_menu = addMenu(tr("&Movie"));
auto* const movie_menu{new QtUtils::NonAutodismissibleMenu(tr("&Movie"), this)};
addMenu(movie_menu);
m_recording_start =
movie_menu->addAction(tr("Start Re&cording Input"), this, [this] { emit StartRecording(); });
m_recording_play =

View File

@ -0,0 +1,28 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/QtUtils/NonAutodismissibleMenu.h"
#include <QAction>
#include <QMouseEvent>
namespace QtUtils
{
void NonAutodismissibleMenu::mouseReleaseEvent(QMouseEvent* const event)
{
if (!event)
return;
QAction* const action{activeAction()};
if (action && action->isEnabled() && action->isCheckable())
{
action->trigger();
event->accept();
return;
}
QMenu::mouseReleaseEvent(event);
}
} // namespace QtUtils

View File

@ -0,0 +1,22 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QMenu>
namespace QtUtils
{
/// A menu widget based on \c QMenu that will not be automatically dismissed when one of its
/// \em checkable actions are triggered.
class NonAutodismissibleMenu : public QMenu
{
public:
using QMenu::QMenu;
protected:
void mouseReleaseEvent(QMouseEvent* event) override;
};
} // namespace QtUtils