Skip to content

Commit 51a0673

Browse files
trflynn89awesomekling
authored andcommitted
Ladybird+LibWebView: Add an Inspector action to copy an attribute value
1 parent f7de136 commit 51a0673

File tree

7 files changed

+51
-1
lines changed

7 files changed

+51
-1
lines changed

Ladybird/AppKit/UI/Inspector.mm

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
static constexpr NSInteger CONTEXT_MENU_EDIT_NODE_TAG = 1;
2525
static constexpr NSInteger CONTEXT_MENU_REMOVE_ATTRIBUTE_TAG = 2;
26+
static constexpr NSInteger CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG = 3;
2627

2728
@interface Inspector ()
2829
{
@@ -98,15 +99,23 @@ - (instancetype)init:(Tab*)tab
9899
return;
99100
}
100101

102+
static constexpr size_t MAX_ATTRIBUTE_VALUE_LENGTH = 32;
103+
101104
auto edit_attribute_text = MUST(String::formatted("Edit attribute \"{}\"", attribute.name));
102105
auto remove_attribute_text = MUST(String::formatted("Remove attribute \"{}\"", attribute.name));
106+
auto copy_attribute_value_text = MUST(String::formatted("Copy attribute value \"{:.{}}{}\"",
107+
attribute.value, MAX_ATTRIBUTE_VALUE_LENGTH,
108+
attribute.value.bytes_as_string_view().length() > MAX_ATTRIBUTE_VALUE_LENGTH ? "..."sv : ""sv));
103109

104110
auto* edit_node_menu_item = [strong_self.dom_node_attribute_context_menu itemWithTag:CONTEXT_MENU_EDIT_NODE_TAG];
105111
[edit_node_menu_item setTitle:Ladybird::string_to_ns_string(edit_attribute_text)];
106112

107113
auto* remove_attribute_menu_item = [strong_self.dom_node_attribute_context_menu itemWithTag:CONTEXT_MENU_REMOVE_ATTRIBUTE_TAG];
108114
[remove_attribute_menu_item setTitle:Ladybird::string_to_ns_string(remove_attribute_text)];
109115

116+
auto* copy_attribute_value_menu_item = [strong_self.dom_node_attribute_context_menu itemWithTag:CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG];
117+
[copy_attribute_value_menu_item setTitle:Ladybird::string_to_ns_string(copy_attribute_value_text)];
118+
110119
auto* event = Ladybird::create_context_menu_mouse_event(strong_self.web_view, position);
111120
[NSMenu popUpContextMenu:strong_self.dom_node_attribute_context_menu withEvent:event forView:strong_self.web_view];
112121
};
@@ -172,6 +181,11 @@ - (void)removeDOMAttribute:(id)sender
172181
m_inspector_client->context_menu_remove_dom_node_attribute();
173182
}
174183

184+
- (void)copyDOMAttributeValue:(id)sender
185+
{
186+
m_inspector_client->context_menu_copy_dom_node_attribute_value();
187+
}
188+
175189
#pragma mark - Properties
176190

177191
- (NSMenu*)dom_node_text_context_menu
@@ -234,6 +248,12 @@ - (NSMenu*)dom_node_attribute_context_menu
234248
[remove_attribute_menu_item setTag:CONTEXT_MENU_REMOVE_ATTRIBUTE_TAG];
235249
[_dom_node_attribute_context_menu addItem:remove_attribute_menu_item];
236250

251+
auto* copy_attribute_value_menu_item = [[NSMenuItem alloc] initWithTitle:@"Copy attribute value"
252+
action:@selector(copyDOMAttributeValue:)
253+
keyEquivalent:@""];
254+
[copy_attribute_value_menu_item setTag:CONTEXT_MENU_COPY_ATTRIBUTE_VALUE_TAG];
255+
[_dom_node_attribute_context_menu addItem:copy_attribute_value_menu_item];
256+
237257
[_dom_node_attribute_context_menu addItem:[NSMenuItem separatorItem]];
238258

239259
[_dom_node_attribute_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Add attribute"

Ladybird/Qt/InspectorWidget.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view)
3939
m_remove_attribute_action = new QAction("&Remove attribute", this);
4040
connect(m_remove_attribute_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_remove_dom_node_attribute(); });
4141

42+
m_copy_attribute_value_action = new QAction("Copy attribute &value", this);
43+
connect(m_copy_attribute_value_action, &QAction::triggered, [this]() { m_inspector_client->context_menu_copy_dom_node_attribute_value(); });
44+
4245
m_dom_node_text_context_menu = new QMenu("DOM text context menu", this);
4346
m_dom_node_text_context_menu->addAction(m_edit_node_action);
4447
m_dom_node_text_context_menu->addSeparator();
@@ -52,6 +55,7 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view)
5255

5356
m_dom_node_attribute_context_menu = new QMenu("DOM attribute context menu", this);
5457
m_dom_node_attribute_context_menu->addAction(m_edit_node_action);
58+
m_dom_node_attribute_context_menu->addAction(m_copy_attribute_value_action);
5559
m_dom_node_attribute_context_menu->addAction(m_remove_attribute_action);
5660
m_dom_node_attribute_context_menu->addSeparator();
5761
m_dom_node_attribute_context_menu->addAction(m_add_attribute_action);
@@ -69,9 +73,14 @@ InspectorWidget::InspectorWidget(QWidget* tab, WebContentView& content_view)
6973
m_dom_node_tag_context_menu->exec(to_widget_position(position));
7074
};
7175

72-
m_inspector_client->on_requested_dom_node_attribute_context_menu = [this](auto position, auto const&, auto const& attribute) {
76+
m_inspector_client->on_requested_dom_node_attribute_context_menu = [this](auto position, auto const&, WebView::Attribute const& attribute) {
77+
static constexpr size_t MAX_ATTRIBUTE_VALUE_LENGTH = 32;
78+
7379
m_edit_node_action->setText(qstring_from_ak_string(MUST(String::formatted("&Edit attribute \"{}\"", attribute.name))));
7480
m_remove_attribute_action->setText(qstring_from_ak_string(MUST(String::formatted("&Remove attribute \"{}\"", attribute.name))));
81+
m_copy_attribute_value_action->setText(qstring_from_ak_string(MUST(String::formatted("Copy attribute &value \"{:.{}}{}\"",
82+
attribute.value, MAX_ATTRIBUTE_VALUE_LENGTH,
83+
attribute.value.bytes_as_string_view().length() > MAX_ATTRIBUTE_VALUE_LENGTH ? "..."sv : ""sv))));
7584

7685
m_dom_node_attribute_context_menu->exec(to_widget_position(position));
7786
};

Ladybird/Qt/InspectorWidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class InspectorWidget final : public QWidget {
4747
QAction* m_delete_node_action { nullptr };
4848
QAction* m_add_attribute_action { nullptr };
4949
QAction* m_remove_attribute_action { nullptr };
50+
QAction* m_copy_attribute_value_action { nullptr };
5051
};
5152

5253
}

Userland/Applications/Browser/InspectorWidget.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view)
3333
m_delete_node_action = GUI::Action::create("&Delete node"sv, [this](auto&) { m_inspector_client->context_menu_remove_dom_node(); });
3434
m_add_attribute_action = GUI::Action::create("&Add attribute"sv, [this](auto&) { m_inspector_client->context_menu_add_dom_node_attribute(); });
3535
m_remove_attribute_action = GUI::Action::create("&Remove attribute"sv, [this](auto&) { m_inspector_client->context_menu_remove_dom_node_attribute(); });
36+
m_copy_attribute_value_action = GUI::Action::create("Copy attribute &value"sv, [this](auto&) { m_inspector_client->context_menu_copy_dom_node_attribute_value(); });
3637

3738
m_dom_node_text_context_menu = GUI::Menu::construct();
3839
m_dom_node_text_context_menu->add_action(*m_edit_node_action);
@@ -47,6 +48,7 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view)
4748

4849
m_dom_node_attribute_context_menu = GUI::Menu::construct();
4950
m_dom_node_attribute_context_menu->add_action(*m_edit_node_action);
51+
m_dom_node_attribute_context_menu->add_action(*m_copy_attribute_value_action);
5052
m_dom_node_attribute_context_menu->add_action(*m_remove_attribute_action);
5153
m_dom_node_attribute_context_menu->add_separator();
5254
m_dom_node_attribute_context_menu->add_action(*m_add_attribute_action);
@@ -65,8 +67,13 @@ InspectorWidget::InspectorWidget(WebView::OutOfProcessWebView& content_view)
6567
};
6668

6769
m_inspector_client->on_requested_dom_node_attribute_context_menu = [this](auto position, auto const&, auto const& attribute) {
70+
static constexpr size_t MAX_ATTRIBUTE_VALUE_LENGTH = 32;
71+
6872
m_edit_node_action->set_text(DeprecatedString::formatted("&Edit attribute \"{}\"", attribute.name));
6973
m_remove_attribute_action->set_text(DeprecatedString::formatted("&Remove attribute \"{}\"", attribute.name));
74+
m_copy_attribute_value_action->set_text(DeprecatedString::formatted("Copy attribute &value \"{:.{}}{}\"",
75+
attribute.value, MAX_ATTRIBUTE_VALUE_LENGTH,
76+
attribute.value.bytes_as_string_view().length() > MAX_ATTRIBUTE_VALUE_LENGTH ? "..."sv : ""sv));
7077

7178
m_dom_node_attribute_context_menu->popup(to_widget_position(position));
7279
};

Userland/Applications/Browser/InspectorWidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class InspectorWidget final : public GUI::Widget {
4343
RefPtr<GUI::Action> m_delete_node_action;
4444
RefPtr<GUI::Action> m_add_attribute_action;
4545
RefPtr<GUI::Action> m_remove_attribute_action;
46+
RefPtr<GUI::Action> m_copy_attribute_value_action;
4647
};
4748

4849
}

Userland/Libraries/LibWebView/InspectorClient.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,17 @@ void InspectorClient::context_menu_remove_dom_node_attribute()
268268
m_context_menu_data.clear();
269269
}
270270

271+
void InspectorClient::context_menu_copy_dom_node_attribute_value()
272+
{
273+
VERIFY(m_context_menu_data.has_value());
274+
VERIFY(m_context_menu_data->attribute.has_value());
275+
276+
if (m_content_web_view.on_insert_clipboard_entry)
277+
m_content_web_view.on_insert_clipboard_entry(m_context_menu_data->attribute->value, "unspecified"_string, "text/plain"_string);
278+
279+
m_context_menu_data.clear();
280+
}
281+
271282
void InspectorClient::load_inspector()
272283
{
273284
StringBuilder builder;

Userland/Libraries/LibWebView/InspectorClient.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class InspectorClient {
3030
void context_menu_remove_dom_node();
3131
void context_menu_add_dom_node_attribute();
3232
void context_menu_remove_dom_node_attribute();
33+
void context_menu_copy_dom_node_attribute_value();
3334

3435
Function<void(Gfx::IntPoint)> on_requested_dom_node_text_context_menu;
3536
Function<void(Gfx::IntPoint, String const&)> on_requested_dom_node_tag_context_menu;

0 commit comments

Comments
 (0)