/* * Copyright (c) 2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include namespace Ladybird { class ActionObserver final : public WebView::Action::Observer { public: static NonnullOwnPtr 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 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 menu_items) { for (auto& menu_item : menu_items) { menu_item.visit( [&](NonnullRefPtr& action) { auto* qaction = create_application_action(parent, action); menu.addAction(qaction); }, [&](NonnullRefPtr 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; } }