mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:22:45 +00:00 
			
		
		
		
	Ladybird+LibWebView: Add an Inspector action to copy a node's HTML/text
This commit is contained in:
		
							parent
							
								
									51a0673b5c
								
							
						
					
					
						commit
						e3df035c5d
					
				
					 7 changed files with 55 additions and 0 deletions
				
			
		|  | @ -166,6 +166,11 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; | |||
|     m_inspector_client->context_menu_edit_dom_node(); | ||||
| } | ||||
| 
 | ||||
| - (void)copyDOMNode:(id)sender | ||||
| { | ||||
|     m_inspector_client->context_menu_copy_dom_node(); | ||||
| } | ||||
| 
 | ||||
| - (void)deleteDOMNode:(id)sender | ||||
| { | ||||
|     m_inspector_client->context_menu_remove_dom_node(); | ||||
|  | @ -196,6 +201,9 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; | |||
|         [_dom_node_text_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Edit text" | ||||
|                                                                         action:@selector(editDOMNode:) | ||||
|                                                                  keyEquivalent:@""]]; | ||||
|         [_dom_node_text_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy text" | ||||
|                                                                         action:@selector(copyDOMNode:) | ||||
|                                                                  keyEquivalent:@""]]; | ||||
| 
 | ||||
|         [_dom_node_text_context_menu addItem:[NSMenuItem separatorItem]]; | ||||
| 
 | ||||
|  | @ -226,6 +234,12 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; | |||
|         [_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node" | ||||
|                                                                        action:@selector(deleteDOMNode:) | ||||
|                                                                 keyEquivalent:@""]]; | ||||
| 
 | ||||
|         [_dom_node_tag_context_menu addItem:[NSMenuItem separatorItem]]; | ||||
| 
 | ||||
|         [_dom_node_tag_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy HTML" | ||||
|                                                                        action:@selector(copyDOMNode:) | ||||
|                                                                 keyEquivalent:@""]]; | ||||
|     } | ||||
| 
 | ||||
|     return _dom_node_tag_context_menu; | ||||
|  | @ -262,6 +276,12 @@ static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3; | |||
|         [_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Delete node" | ||||
|                                                                              action:@selector(deleteDOMNode:) | ||||
|                                                                       keyEquivalent:@""]]; | ||||
| 
 | ||||
|         [_dom_node_attribute_context_menu addItem:[NSMenuItem separatorItem]]; | ||||
| 
 | ||||
|         [_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy HTML" | ||||
|                                                                              action:@selector(copyDOMNode:) | ||||
|                                                                       keyEquivalent:@""]]; | ||||
|     } | ||||
| 
 | ||||
|     return _dom_node_attribute_context_menu; | ||||
|  |  | |||
|  | @ -30,6 +30,9 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) | |||
|     m_edit_node_action = new QAction("&Edit node", this); | ||||
|     connect(m_edit_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_edit_dom_node(); }); | ||||
| 
 | ||||
|     m_copy_node_action = new QAction("&Copy HTML", this); | ||||
|     connect(m_copy_node_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_copy_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(); }); | ||||
| 
 | ||||
|  | @ -44,6 +47,7 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) | |||
| 
 | ||||
|     m_dom_node_text_context_menu = new QMenu("DOM text context menu", this); | ||||
|     m_dom_node_text_context_menu->addAction(m_edit_node_action); | ||||
|     m_dom_node_text_context_menu->addAction(m_copy_node_action); | ||||
|     m_dom_node_text_context_menu->addSeparator(); | ||||
|     m_dom_node_text_context_menu->addAction(m_delete_node_action); | ||||
| 
 | ||||
|  | @ -52,6 +56,8 @@ 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->addAction(m_delete_node_action); | ||||
|     m_dom_node_tag_context_menu->addSeparator(); | ||||
|     m_dom_node_tag_context_menu->addAction(m_copy_node_action); | ||||
| 
 | ||||
|     m_dom_node_attribute_context_menu = new QMenu("DOM attribute context menu", this); | ||||
|     m_dom_node_attribute_context_menu->addAction(m_edit_node_action); | ||||
|  | @ -60,15 +66,19 @@ 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->addAction(m_delete_node_action); | ||||
|     m_dom_node_attribute_context_menu->addSeparator(); | ||||
|     m_dom_node_attribute_context_menu->addAction(m_copy_node_action); | ||||
| 
 | ||||
|     m_inspector_client->on_requested_dom_node_text_context_menu = [this](auto position) { | ||||
|         m_edit_node_action->setText("&Edit text"); | ||||
|         m_copy_node_action->setText("&Copy text"); | ||||
| 
 | ||||
|         m_dom_node_text_context_menu->exec(to_widget_position(position)); | ||||
|     }; | ||||
| 
 | ||||
|     m_inspector_client->on_requested_dom_node_tag_context_menu = [this](auto position, auto const& tag) { | ||||
|         m_edit_node_action->setText(qstring_from_ak_string(MUST(String::formatted("&Edit \"{}\"", tag)))); | ||||
|         m_copy_node_action->setText("&Copy HTML"); | ||||
| 
 | ||||
|         m_dom_node_tag_context_menu->exec(to_widget_position(position)); | ||||
|     }; | ||||
|  | @ -76,6 +86,7 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view) | |||
|     m_inspector_client->on_requested_dom_node_attribute_context_menu = [this](auto position, auto const&, WebView::Attribute const& attribute) { | ||||
|         static constexpr size_t MAX_ATTRIBUTE_VALUE_LENGTH = 32; | ||||
| 
 | ||||
|         m_copy_node_action->setText("&Copy HTML"); | ||||
|         m_edit_node_action->setText(qstring_from_ak_string(MUST(String::formatted("&Edit attribute \"{}\"", attribute.name)))); | ||||
|         m_remove_attribute_action->setText(qstring_from_ak_string(MUST(String::formatted("&Remove attribute \"{}\"", attribute.name)))); | ||||
|         m_copy_attribute_value_action->setText(qstring_from_ak_string(MUST(String::formatted("Copy attribute &value \"{:.{}}{}\"", | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ private: | |||
|     QMenu* m_dom_node_attribute_context_menu { nullptr }; | ||||
| 
 | ||||
|     QAction* m_edit_node_action { nullptr }; | ||||
|     QAction* m_copy_node_action { nullptr }; | ||||
|     QAction* m_delete_node_action { nullptr }; | ||||
|     QAction* m_add_attribute_action { nullptr }; | ||||
|     QAction* m_remove_attribute_action { nullptr }; | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) | |||
|     m_inspector_client = make<WebView::InspectorClient>(content_view, *m_inspector_view); | ||||
| 
 | ||||
|     m_edit_node_action = GUI::Action::create("&Edit node"sv, [this](auto&) { m_inspector_client->context_menu_edit_dom_node(); }); | ||||
|     m_copy_node_action = GUI::Action::create("&Copy HTML"sv, [this](auto&) { m_inspector_client->context_menu_copy_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(); }); | ||||
|  | @ -37,6 +38,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) | |||
| 
 | ||||
|     m_dom_node_text_context_menu = GUI::Menu::construct(); | ||||
|     m_dom_node_text_context_menu->add_action(*m_edit_node_action); | ||||
|     m_dom_node_text_context_menu->add_action(*m_copy_node_action); | ||||
|     m_dom_node_text_context_menu->add_separator(); | ||||
|     m_dom_node_text_context_menu->add_action(*m_delete_node_action); | ||||
| 
 | ||||
|  | @ -45,6 +47,8 @@ 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); | ||||
|     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); | ||||
| 
 | ||||
|     m_dom_node_attribute_context_menu = GUI::Menu::construct(); | ||||
|     m_dom_node_attribute_context_menu->add_action(*m_edit_node_action); | ||||
|  | @ -53,15 +57,19 @@ 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); | ||||
|     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); | ||||
| 
 | ||||
|     m_inspector_client->on_requested_dom_node_text_context_menu = [this](auto position) { | ||||
|         m_edit_node_action->set_text("&Edit text"); | ||||
|         m_copy_node_action->set_text("&Copy text"); | ||||
| 
 | ||||
|         m_dom_node_text_context_menu->popup(to_widget_position(position)); | ||||
|     }; | ||||
| 
 | ||||
|     m_inspector_client->on_requested_dom_node_tag_context_menu = [this](auto position, auto const& tag) { | ||||
|         m_edit_node_action->set_text(DeprecatedString::formatted("&Edit \"{}\"", tag)); | ||||
|         m_copy_node_action->set_text("&Copy HTML"); | ||||
| 
 | ||||
|         m_dom_node_tag_context_menu->popup(to_widget_position(position)); | ||||
|     }; | ||||
|  | @ -69,6 +77,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view) | |||
|     m_inspector_client->on_requested_dom_node_attribute_context_menu = [this](auto position, auto const&, auto const& attribute) { | ||||
|         static constexpr size_t MAX_ATTRIBUTE_VALUE_LENGTH = 32; | ||||
| 
 | ||||
|         m_copy_node_action->set_text("&Copy HTML"); | ||||
|         m_edit_node_action->set_text(DeprecatedString::formatted("&Edit attribute \"{}\"", attribute.name)); | ||||
|         m_remove_attribute_action->set_text(DeprecatedString::formatted("&Remove attribute \"{}\"", attribute.name)); | ||||
|         m_copy_attribute_value_action->set_text(DeprecatedString::formatted("Copy attribute &value \"{:.{}}{}\"", | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ private: | |||
|     RefPtr<GUI::Menu> m_dom_node_attribute_context_menu; | ||||
| 
 | ||||
|     RefPtr<GUI::Action> m_edit_node_action; | ||||
|     RefPtr<GUI::Action> m_copy_node_action; | ||||
|     RefPtr<GUI::Action> m_delete_node_action; | ||||
|     RefPtr<GUI::Action> m_add_attribute_action; | ||||
|     RefPtr<GUI::Action> m_remove_attribute_action; | ||||
|  |  | |||
|  | @ -233,6 +233,18 @@ void InspectorClient::context_menu_edit_dom_node() | |||
|     m_context_menu_data.clear(); | ||||
| } | ||||
| 
 | ||||
| void InspectorClient::context_menu_copy_dom_node() | ||||
| { | ||||
|     VERIFY(m_context_menu_data.has_value()); | ||||
| 
 | ||||
|     if (auto html = m_content_web_view.get_dom_node_html(m_context_menu_data->dom_node_id); html.has_value()) { | ||||
|         if (m_content_web_view.on_insert_clipboard_entry) | ||||
|             m_content_web_view.on_insert_clipboard_entry(*html, "unspecified"_string, "text/plain"_string); | ||||
|     } | ||||
| 
 | ||||
|     m_context_menu_data.clear(); | ||||
| } | ||||
| 
 | ||||
| void InspectorClient::context_menu_remove_dom_node() | ||||
| { | ||||
|     VERIFY(m_context_menu_data.has_value()); | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ public: | |||
|     void clear_selection(); | ||||
| 
 | ||||
|     void context_menu_edit_dom_node(); | ||||
|     void context_menu_copy_dom_node(); | ||||
|     void context_menu_remove_dom_node(); | ||||
|     void context_menu_add_dom_node_attribute(); | ||||
|     void context_menu_remove_dom_node_attribute(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy Flynn
						Timothy Flynn