mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-24 00:49:46 +00:00
LibWebView+UI: Add structures to hold context menu and action data
We currently duplicate a lot of code to handle application/context menus and actions. The goal here is to hold the data for the menus and actions in LibWebView. Each UI will then be able to generate menus from the data on-the-fly. The structures added here are meant to support generic and checkable actions, action groups, submenus, etc.
This commit is contained in:
parent
2632b1375b
commit
a5be0f0a18
Notes:
github-actions[bot]
2025-09-11 18:25:23 +00:00
Author: https://github.com/trflynn89
Commit: a5be0f0a18
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6062
10 changed files with 619 additions and 1 deletions
130
UI/Qt/Menu.cpp
Normal file
130
UI/Qt/Menu.cpp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <UI/Qt/Icon.h>
|
||||
#include <UI/Qt/Menu.h>
|
||||
#include <UI/Qt/StringUtils.h>
|
||||
#include <UI/Qt/WebContentView.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class ActionObserver final : public WebView::Action::Observer {
|
||||
public:
|
||||
static NonnullOwnPtr<ActionObserver> create(WebView::Action& action, QAction& qaction)
|
||||
{
|
||||
return adopt_own(*new ActionObserver(action, qaction));
|
||||
}
|
||||
|
||||
virtual void on_text_changed(WebView::Action& action) override
|
||||
{
|
||||
if (m_action)
|
||||
m_action->setText(qstring_from_ak_string(action.text()));
|
||||
}
|
||||
|
||||
virtual void on_tooltip_changed(WebView::Action& action) override
|
||||
{
|
||||
if (m_action)
|
||||
m_action->setToolTip(qstring_from_ak_string(action.tooltip()));
|
||||
}
|
||||
|
||||
virtual void on_enabled_state_changed(WebView::Action& action) override
|
||||
{
|
||||
if (m_action)
|
||||
m_action->setEnabled(action.enabled());
|
||||
}
|
||||
|
||||
virtual void on_visible_state_changed(WebView::Action& action) override
|
||||
{
|
||||
if (m_action)
|
||||
m_action->setVisible(action.visible());
|
||||
}
|
||||
|
||||
virtual void on_checked_state_changed(WebView::Action& action) override
|
||||
{
|
||||
if (m_action)
|
||||
m_action->setChecked(action.checked());
|
||||
}
|
||||
|
||||
private:
|
||||
ActionObserver(WebView::Action& action, QAction& qaction)
|
||||
: m_action(&qaction)
|
||||
{
|
||||
QObject::connect(m_action, &QAction::triggered, [weak_action = action.make_weak_ptr()](bool checked) {
|
||||
if (auto action = weak_action.strong_ref()) {
|
||||
if (action->is_checkable())
|
||||
action->set_checked(checked);
|
||||
action->activate();
|
||||
}
|
||||
});
|
||||
QObject::connect(m_action->parent(), &QObject::destroyed, [this, weak_action = action.make_weak_ptr()]() {
|
||||
if (auto action = weak_action.strong_ref())
|
||||
action->remove_observer(*this);
|
||||
});
|
||||
}
|
||||
|
||||
QPointer<QAction> m_action;
|
||||
};
|
||||
|
||||
static void initialize_native_control(WebView::Action& action, QAction& qaction)
|
||||
{
|
||||
if (action.is_checkable())
|
||||
qaction.setCheckable(true);
|
||||
|
||||
action.add_observer(ActionObserver::create(action, qaction));
|
||||
}
|
||||
|
||||
static void add_items_to_menu(QMenu& menu, QWidget& parent, Span<WebView::Menu::MenuItem> menu_items)
|
||||
{
|
||||
for (auto& menu_item : menu_items) {
|
||||
menu_item.visit(
|
||||
[&](NonnullRefPtr<WebView::Action>& action) {
|
||||
auto* qaction = create_application_action(parent, action);
|
||||
menu.addAction(qaction);
|
||||
},
|
||||
[&](NonnullRefPtr<WebView::Menu> const& submenu) {
|
||||
auto* qsubmenu = new QMenu(qstring_from_ak_string(submenu->title()), &menu);
|
||||
add_items_to_menu(*qsubmenu, parent, submenu->items());
|
||||
|
||||
menu.addMenu(qsubmenu);
|
||||
},
|
||||
[&](WebView::Separator) {
|
||||
menu.addSeparator();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
QMenu* create_application_menu(QWidget& parent, WebView::Menu& menu)
|
||||
{
|
||||
auto* application_menu = new QMenu(qstring_from_ak_string(menu.title()), &parent);
|
||||
add_items_to_menu(*application_menu, parent, menu.items());
|
||||
return application_menu;
|
||||
}
|
||||
|
||||
QMenu* create_context_menu(QWidget& parent, WebContentView& view, WebView::Menu& menu)
|
||||
{
|
||||
auto* application_menu = create_application_menu(parent, menu);
|
||||
|
||||
menu.on_activation = [view = QPointer { &view }, application_menu = QPointer { application_menu }](Gfx::IntPoint position) {
|
||||
if (view && application_menu)
|
||||
application_menu->exec(view->map_point_to_global_position(position));
|
||||
};
|
||||
|
||||
return application_menu;
|
||||
}
|
||||
|
||||
QAction* create_application_action(QWidget& parent, WebView::Action& action)
|
||||
{
|
||||
auto* qaction = new QAction(&parent);
|
||||
initialize_native_control(action, *qaction);
|
||||
return qaction;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue