diff --git a/Ladybird/AppKit/UI/Inspector.mm b/Ladybird/AppKit/UI/Inspector.mm index acaf7943a1..1e71b2cb8f 100644 --- a/Ladybird/AppKit/UI/Inspector.mm +++ b/Ladybird/AppKit/UI/Inspector.mm @@ -186,6 +186,11 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; m_inspector_client->context_menu_create_child_text_node(); } +- (void)cloneDOMNode:(id)sender +{ + m_inspector_client->context_menu_clone_dom_node(); +} + - (void)deleteDOMNode:(id)sender { m_inspector_client->context_menu_remove_dom_node(); @@ -265,6 +270,9 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; action:@selector(addDOMAttribute:) keyEquivalent:@""]]; [_dom_node_tag_context_menu addItem:[Inspector make_create_child_menu]]; + [_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Clone node" + action:@selector(cloneDOMNode:) + keyEquivalent:@""]]; [_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node" action:@selector(deleteDOMNode:) keyEquivalent:@""]]; @@ -311,6 +319,9 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; action:@selector(addDOMAttribute:) keyEquivalent:@""]]; [_dom_node_attribute_context_menu addItem:[Inspector make_create_child_menu]]; + [_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Clone node" + action:@selector(cloneDOMNode:) + keyEquivalent:@""]]; [_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node" action:@selector(deleteDOMNode:) keyEquivalent:@""]]; diff --git a/Ladybird/Qt/InspectorWidget.cpp b/Ladybird/Qt/InspectorWidget.cpp index 9ce350821f..76a699f0ce 100644 --- a/Ladybird/Qt/InspectorWidget.cpp +++ b/Ladybird/Qt/InspectorWidget.cpp @@ -42,6 +42,9 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) m_create_child_text_node_action = new QAction("Create child &text node", this); connect(m_create_child_text_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_create_child_text_node(); }); + m_clone_node_action = new QAction("C&lone node", this); + connect(m_clone_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_clone_dom_node(); }); + m_delete_node_action = new QAction("&Delete node", this); connect(m_delete_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_remove_dom_node(); }); @@ -69,6 +72,7 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) m_dom_node_tag_context_menu->addSeparator(); m_dom_node_tag_context_menu->addAction(m_add_attribute_action); m_dom_node_tag_context_menu->addMenu(create_child_menu); + m_dom_node_tag_context_menu->addAction(m_clone_node_action); m_dom_node_tag_context_menu->addAction(m_delete_node_action); m_dom_node_tag_context_menu->addSeparator(); m_dom_node_tag_context_menu->addAction(m_copy_node_action); @@ -81,6 +85,7 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) m_dom_node_attribute_context_menu->addSeparator(); m_dom_node_attribute_context_menu->addAction(m_add_attribute_action); m_dom_node_attribute_context_menu->addMenu(create_child_menu); + m_dom_node_attribute_context_menu->addAction(m_clone_node_action); m_dom_node_attribute_context_menu->addAction(m_delete_node_action); m_dom_node_attribute_context_menu->addSeparator(); m_dom_node_attribute_context_menu->addAction(m_copy_node_action); diff --git a/Ladybird/Qt/InspectorWidget.h b/Ladybird/Qt/InspectorWidget.h index 25646bfd37..1e38e36123 100644 --- a/Ladybird/Qt/InspectorWidget.h +++ b/Ladybird/Qt/InspectorWidget.h @@ -48,6 +48,7 @@ private: QAction* m_screenshot_node_action { nullptr }; QAction* m_create_child_element_action { nullptr }; QAction* m_create_child_text_node_action { nullptr }; + QAction* m_clone_node_action { nullptr }; QAction* m_delete_node_action { nullptr }; QAction* m_add_attribute_action { nullptr }; QAction* m_remove_attribute_action { nullptr }; diff --git a/Userland/Applications/Browser/InspectorWidget.cpp b/Userland/Applications/Browser/InspectorWidget.cpp index f19d6393fe..b67b77dbcb 100644 --- a/Userland/Applications/Browser/InspectorWidget.cpp +++ b/Userland/Applications/Browser/InspectorWidget.cpp @@ -34,6 +34,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) m_screenshot_node_action = GUI::Action::create("Take node &screenshot"sv, [this](auto&) { m_inspector_client->context_menu_screenshot_dom_node(); }); m_create_child_element_action = GUI::Action::create("Create child &element"sv, [this](auto&) { m_inspector_client->context_menu_create_child_element(); }); m_create_child_text_node_action = GUI::Action::create("Create child &text node"sv, [this](auto&) { m_inspector_client->context_menu_create_child_text_node(); }); + m_clone_node_action = GUI::Action::create("C&lone node"sv, [this](auto&) { m_inspector_client->context_menu_clone_dom_node(); }); m_delete_node_action = GUI::Action::create("&Delete node"sv, [this](auto&) { m_inspector_client->context_menu_remove_dom_node(); }); m_add_attribute_action = GUI::Action::create("&Add attribute"sv, [this](auto&) { m_inspector_client->context_menu_add_dom_node_attribute(); }); m_remove_attribute_action = GUI::Action::create("&Remove attribute"sv, [this](auto&) { m_inspector_client->context_menu_remove_dom_node_attribute(); }); @@ -56,6 +57,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) m_dom_node_tag_context_menu->add_separator(); m_dom_node_tag_context_menu->add_action(*m_add_attribute_action); add_create_child_menu(*m_dom_node_tag_context_menu); + m_dom_node_tag_context_menu->add_action(*m_clone_node_action); m_dom_node_tag_context_menu->add_action(*m_delete_node_action); m_dom_node_tag_context_menu->add_separator(); m_dom_node_tag_context_menu->add_action(*m_copy_node_action); @@ -68,6 +70,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) m_dom_node_attribute_context_menu->add_separator(); m_dom_node_attribute_context_menu->add_action(*m_add_attribute_action); add_create_child_menu(*m_dom_node_attribute_context_menu); + m_dom_node_attribute_context_menu->add_action(*m_clone_node_action); m_dom_node_attribute_context_menu->add_action(*m_delete_node_action); m_dom_node_attribute_context_menu->add_separator(); m_dom_node_attribute_context_menu->add_action(*m_copy_node_action); diff --git a/Userland/Applications/Browser/InspectorWidget.h b/Userland/Applications/Browser/InspectorWidget.h index b3718d8816..8a84bd19d3 100644 --- a/Userland/Applications/Browser/InspectorWidget.h +++ b/Userland/Applications/Browser/InspectorWidget.h @@ -44,6 +44,7 @@ private: RefPtr m_screenshot_node_action; RefPtr m_create_child_element_action; RefPtr m_create_child_text_node_action; + RefPtr m_clone_node_action; RefPtr m_delete_node_action; RefPtr m_add_attribute_action; RefPtr m_remove_attribute_action; diff --git a/Userland/Libraries/LibWebView/InspectorClient.cpp b/Userland/Libraries/LibWebView/InspectorClient.cpp index 060b944316..d4f824baa4 100644 --- a/Userland/Libraries/LibWebView/InspectorClient.cpp +++ b/Userland/Libraries/LibWebView/InspectorClient.cpp @@ -274,6 +274,16 @@ void InspectorClient::context_menu_create_child_text_node() m_context_menu_data.clear(); } +void InspectorClient::context_menu_clone_dom_node() +{ + VERIFY(m_context_menu_data.has_value()); + + m_pending_selection = m_content_web_view.clone_dom_node(m_context_menu_data->dom_node_id); + inspect(); + + m_context_menu_data.clear(); +} + void InspectorClient::context_menu_remove_dom_node() { VERIFY(m_context_menu_data.has_value()); diff --git a/Userland/Libraries/LibWebView/InspectorClient.h b/Userland/Libraries/LibWebView/InspectorClient.h index a1d998f17e..96cfb2b85a 100644 --- a/Userland/Libraries/LibWebView/InspectorClient.h +++ b/Userland/Libraries/LibWebView/InspectorClient.h @@ -31,6 +31,7 @@ public: void context_menu_screenshot_dom_node(); void context_menu_create_child_element(); void context_menu_create_child_text_node(); + void context_menu_clone_dom_node(); void context_menu_remove_dom_node(); void context_menu_add_dom_node_attribute(); void context_menu_remove_dom_node_attribute();