mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-20 15:09:42 +00:00
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.
130 lines
3.9 KiB
C++
130 lines
3.9 KiB
C++
/*
|
|
* 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;
|
|
}
|
|
|
|
}
|