diff --git a/Ladybird/Qt/InspectorWidget.cpp b/Ladybird/Qt/InspectorWidget.cpp index 43e3b3f845..ce9d214c8c 100644 --- a/Ladybird/Qt/InspectorWidget.cpp +++ b/Ladybird/Qt/InspectorWidget.cpp @@ -6,48 +6,56 @@ #include "InspectorWidget.h" #include +#include #include #include #include -#include #include #include -#include #include namespace Ladybird { -InspectorWidget::InspectorWidget() -{ - setLayout(new QVBoxLayout); - auto splitter = new QSplitter(this); - layout()->addWidget(splitter); - splitter->setOrientation(Qt::Vertical); +extern bool is_using_dark_system_theme(QWidget&); - auto add_tab = [&](auto* tab_widget, auto* widget, auto name) { - auto container = new QWidget; - container->setLayout(new QVBoxLayout); - container->layout()->addWidget(widget); - tab_widget->addTab(container, name); +InspectorWidget::InspectorWidget(WebContentView& content_view) +{ + m_inspector_view = make(StringView {}, WebView::EnableCallgrindProfiling::No, UseLagomNetworking::No, WebView::EnableGPUPainting::No); + + if (is_using_dark_system_theme(*this)) + m_inspector_view->update_palette(WebContentView::PaletteMode::Dark); + + m_inspector_client = make(content_view, *m_inspector_view); + + m_inspector_client->on_dom_node_properties_received = [this](auto properties_or_error) { + if (properties_or_error.is_error()) { + clear_style_json(); + } else { + auto properties = properties_or_error.release_value(); + load_style_json(properties.computed_style_json, properties.resolved_style_json, properties.custom_properties_json); + } }; - auto* top_tab_widget = new QTabWidget; - splitter->addWidget(top_tab_widget); + setLayout(new QVBoxLayout); - m_dom_tree_view = new QTreeView; - m_dom_tree_view->setHeaderHidden(true); - add_tab(top_tab_widget, m_dom_tree_view, "DOM"); + auto* splitter = new QSplitter(this); + splitter->setOrientation(Qt::Vertical); + layout()->addWidget(splitter); - m_accessibility_tree_view = new QTreeView; - m_accessibility_tree_view->setHeaderHidden(true); - add_tab(top_tab_widget, m_accessibility_tree_view, "Accessibility"); + splitter->addWidget(m_inspector_view.ptr()); + splitter->setStretchFactor(0, 2); auto add_table_tab = [&](auto* tab_widget, auto name) { auto* table_view = new QTableView; table_view->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); table_view->verticalHeader()->setVisible(false); table_view->horizontalHeader()->setVisible(false); - add_tab(tab_widget, table_view, name); + + auto* container = new QWidget; + container->setLayout(new QVBoxLayout); + container->layout()->addWidget(table_view); + tab_widget->addTab(container, name); + return table_view; }; @@ -56,44 +64,32 @@ InspectorWidget::InspectorWidget() m_resolved_style_table = add_table_tab(node_tabs, "Resolved"); m_custom_properties_table = add_table_tab(node_tabs, "Variables"); splitter->addWidget(node_tabs); + + setWindowTitle("Inspector"); + resize(875, 825); } -void InspectorWidget::set_dom_json(StringView dom_json) +InspectorWidget::~InspectorWidget() = default; + +void InspectorWidget::inspect() { - m_dom_model = TreeModel::create(TreeModel::Type::DOMTree, dom_json).release_value_but_fixme_should_propagate_errors(); - m_dom_tree_view->setModel(m_dom_model); - m_dom_loaded = true; - - QObject::connect(m_dom_tree_view->selectionModel(), &QItemSelectionModel::selectionChanged, - [this](QItemSelection const& selected, QItemSelection const&) { - if (auto indexes = selected.indexes(); !indexes.empty()) - set_selection(indexes.first()); - }); - - if (m_pending_selection.has_value()) - set_selection(m_pending_selection.release_value()); - else - select_default_node(); + m_inspector_client->inspect(); } -void InspectorWidget::set_accessibility_json(StringView accessibility_json) +void InspectorWidget::reset() { - m_accessibility_model = TreeModel::create(TreeModel::Type::AccessibilityTree, accessibility_json).release_value_but_fixme_should_propagate_errors(); - m_accessibility_tree_view->setModel(m_accessibility_model); -} - -void InspectorWidget::clear_dom_json() -{ - m_dom_tree_view->setModel(nullptr); - m_dom_model = nullptr; - - // The accessibility tree is pretty much another form of the DOM tree, so should be cleared at the time time. - m_accessibility_tree_view->setModel(nullptr); - m_accessibility_model = nullptr; - + m_inspector_client->reset(); clear_style_json(); - clear_selection(); - m_dom_loaded = false; +} + +void InspectorWidget::select_hovered_node() +{ + m_inspector_client->select_hovered_node(); +} + +void InspectorWidget::select_default_node() +{ + m_inspector_client->select_default_node(); } void InspectorWidget::load_style_json(StringView computed_style_json, StringView resolved_style_json, StringView custom_properties_json) @@ -118,76 +114,12 @@ void InspectorWidget::clear_style_json() m_custom_properties_table->setModel(nullptr); m_custom_properties_model = nullptr; - - clear_selection(); } void InspectorWidget::closeEvent(QCloseEvent* event) { event->accept(); - if (on_close) - on_close(); - clear_selection(); -} - -void InspectorWidget::clear_selection() -{ - m_selection = {}; - m_dom_tree_view->clearSelection(); -} - -void InspectorWidget::set_selection(Selection selection) -{ - if (!m_dom_loaded) { - m_pending_selection = selection; - return; - } - - auto index = m_dom_model->index_for_node(selection.dom_node_id, selection.pseudo_element); - if (!index.isValid()) { - dbgln("Failed to set DOM inspector selection! Could not find valid model index for node: {}", selection.dom_node_id); - return; - } - - m_dom_tree_view->scrollTo(index); - m_dom_tree_view->setCurrentIndex(index); -} - -void InspectorWidget::select_default_node() -{ - clear_style_json(); - m_dom_tree_view->collapseAll(); - m_dom_tree_view->setCurrentIndex({}); -} - -void InspectorWidget::set_selection(QModelIndex const& index) -{ - if (!index.isValid()) - return; - - auto const* json = static_cast(index.constInternalPointer()); - VERIFY(json); - - Selection selection {}; - if (json->has_u32("pseudo-element"sv)) { - selection.dom_node_id = json->get_i32("parent-id"sv).value(); - selection.pseudo_element = static_cast(json->get_u32("pseudo-element"sv).value()); - } else { - selection.dom_node_id = json->get_i32("id"sv).value(); - } - - if (selection == m_selection) - return; - m_selection = selection; - - VERIFY(on_dom_node_inspected); - auto maybe_inspected_node_properties = on_dom_node_inspected(m_selection.dom_node_id, m_selection.pseudo_element); - if (!maybe_inspected_node_properties.is_error()) { - auto properties = maybe_inspected_node_properties.release_value(); - load_style_json(properties.computed_style_json, properties.resolved_style_json, properties.custom_properties_json); - } else { - clear_style_json(); - } + m_inspector_client->clear_selection(); } } diff --git a/Ladybird/Qt/InspectorWidget.h b/Ladybird/Qt/InspectorWidget.h index 8d3bb63677..c2097c2f67 100644 --- a/Ladybird/Qt/InspectorWidget.h +++ b/Ladybird/Qt/InspectorWidget.h @@ -8,66 +8,45 @@ #include "ModelAdapter.h" #include "WebContentView.h" -#include #include -#include +#include #include -class QTreeView; class QTableView; namespace Ladybird { +class WebContentView; + class InspectorWidget final : public QWidget { Q_OBJECT + public: - InspectorWidget(); - virtual ~InspectorWidget() = default; + explicit InspectorWidget(WebContentView& content_view); + virtual ~InspectorWidget() override; - struct Selection { - i32 dom_node_id { 0 }; - Optional pseudo_element {}; - bool operator==(Selection const& other) const = default; - }; - - bool dom_loaded() const { return m_dom_loaded; } - - void set_selection(Selection); - void clear_selection(); + void inspect(); + void reset(); + void select_hovered_node(); void select_default_node(); - void clear_dom_json(); - void set_dom_json(StringView dom_json); - - void set_accessibility_json(StringView accessibility_json); - +private: void load_style_json(StringView computed_style_json, StringView resolved_style_json, StringView custom_properties_json); void clear_style_json(); - Function(i32, Optional)> on_dom_node_inspected; - Function on_close; - -private: - void set_selection(QModelIndex const&); void closeEvent(QCloseEvent*) override; - Selection m_selection; + OwnPtr m_inspector_view; + OwnPtr m_inspector_client; - OwnPtr m_dom_model; - OwnPtr m_accessibility_model; OwnPtr m_computed_style_model; OwnPtr m_resolved_style_model; OwnPtr m_custom_properties_model; - QTreeView* m_dom_tree_view { nullptr }; - QTreeView* m_accessibility_tree_view { nullptr }; QTableView* m_computed_style_table { nullptr }; QTableView* m_resolved_style_table { nullptr }; QTableView* m_custom_properties_table { nullptr }; - - bool m_dom_loaded { false }; - Optional m_pending_selection {}; }; } diff --git a/Ladybird/Qt/Tab.cpp b/Ladybird/Qt/Tab.cpp index e0f0157cb8..e7f959d02a 100644 --- a/Ladybird/Qt/Tab.cpp +++ b/Ladybird/Qt/Tab.cpp @@ -138,17 +138,15 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView:: m_window->reload_action().setEnabled(!m_history.is_empty()); if (m_inspector_widget) - m_inspector_widget->clear_dom_json(); + m_inspector_widget->reset(); if (m_console_widget) m_console_widget->reset(); }; view().on_load_finish = [this](auto&) { - if (m_inspector_widget != nullptr && m_inspector_widget->isVisible()) { - view().inspect_dom_tree(); - view().inspect_accessibility_tree(); - } + if (m_inspector_widget != nullptr && m_inspector_widget->isVisible()) + m_inspector_widget->inspect(); }; QObject::connect(m_location_edit, &QLineEdit::returnPressed, this, &Tab::location_edit_return_pressed); @@ -280,16 +278,6 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView:: return Gfx::IntRect { m_window->x(), m_window->y(), m_window->width(), m_window->height() }; }; - view().on_received_dom_tree = [this](auto& dom_tree) { - if (m_inspector_widget) - m_inspector_widget->set_dom_json(dom_tree); - }; - - view().on_received_accessibility_tree = [this](auto& accessibility_tree) { - if (m_inspector_widget) - m_inspector_widget->set_accessibility_json(accessibility_tree); - }; - view().on_insert_clipboard_entry = [](auto const& data, auto const&, auto const& mime_type) { QByteArray qdata { data.bytes_as_string_view().characters_without_null_termination(), static_cast(data.bytes_as_string_view().length()) }; @@ -705,34 +693,17 @@ void Tab::recreate_toolbar_icons() void Tab::show_inspector_window(InspectorTarget inspector_target) { - bool inspector_previously_loaded = m_inspector_widget != nullptr; - - if (!m_inspector_widget) { - m_inspector_widget = new Ladybird::InspectorWidget; - m_inspector_widget->setWindowTitle("Inspector"); - m_inspector_widget->resize(640, 480); - m_inspector_widget->on_close = [this] { - view().clear_inspected_dom_node(); - }; - - m_inspector_widget->on_dom_node_inspected = [&](auto id, auto pseudo_element) { - return view().inspect_dom_node(id, pseudo_element); - }; - } - - if (!inspector_previously_loaded || !m_inspector_widget->dom_loaded()) { - view().inspect_dom_tree(); - view().inspect_accessibility_tree(); - } + if (!m_inspector_widget) + m_inspector_widget = new Ladybird::InspectorWidget(view()); m_inspector_widget->show(); + m_inspector_widget->activateWindow(); + m_inspector_widget->raise(); - if (inspector_target == InspectorTarget::HoveredElement) { - auto hovered_node = view().get_hovered_node_id(); - m_inspector_widget->set_selection({ hovered_node }); - } else { + if (inspector_target == InspectorTarget::HoveredElement) + m_inspector_widget->select_hovered_node(); + else m_inspector_widget->select_default_node(); - } } void Tab::show_console_window()