Explorar o código

Ladybird/Qt: Add a find in page widget

Tim Ledbetter hai 1 ano
pai
achega
389a55fe36

+ 1 - 0
Ladybird/CMakeLists.txt

@@ -115,6 +115,7 @@ if (ENABLE_QT)
         Qt/BrowserWindow.cpp
         Qt/EventLoopImplementationQt.cpp
         Qt/EventLoopImplementationQtEventTarget.cpp
+        Qt/FindInPageWidget.cpp
         Qt/Icon.cpp
         Qt/InspectorWidget.cpp
         Qt/LocationEdit.cpp

BIN=BIN
Ladybird/Icons/down.tvg


BIN=BIN
Ladybird/Icons/up.tvg


+ 17 - 0
Ladybird/Qt/BrowserWindow.cpp

@@ -152,6 +152,15 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
 
     edit_menu->addSeparator();
 
+    m_find_in_page_action = new QAction("&Find in Page...", this);
+    m_find_in_page_action->setIcon(load_icon_from_uri("resource://icons/16x16/find.png"sv));
+    m_find_in_page_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Find));
+
+    edit_menu->addAction(m_find_in_page_action);
+    QObject::connect(m_find_in_page_action, &QAction::triggered, this, &BrowserWindow::show_find_in_page);
+
+    edit_menu->addSeparator();
+
     auto* settings_action = new QAction("&Settings", this);
     settings_action->setIcon(load_icon_from_uri("resource://icons/16x16/settings.png"sv));
     settings_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Preferences));
@@ -894,6 +903,14 @@ void BrowserWindow::select_all()
     m_current_tab->view().select_all();
 }
 
+void BrowserWindow::show_find_in_page()
+{
+    if (!m_current_tab)
+        return;
+
+    m_current_tab->show_find_in_page();
+}
+
 void BrowserWindow::paste()
 {
     if (!m_current_tab)

+ 8 - 0
Ladybird/Qt/BrowserWindow.h

@@ -8,6 +8,7 @@
 #pragma once
 
 #include "Tab.h"
+#include <Ladybird/Qt/FindInPageWidget.h>
 #include <Ladybird/Types.h>
 #include <LibCore/Forward.h>
 #include <LibWeb/HTML/ActivateTab.h>
@@ -78,6 +79,11 @@ public:
         return *m_select_all_action;
     }
 
+    QAction& find_action()
+    {
+        return *m_find_in_page_action;
+    }
+
     QAction& paste_action()
     {
         return *m_paste_action;
@@ -119,6 +125,7 @@ public slots:
     void reset_zoom();
     void update_zoom_menu();
     void select_all();
+    void show_find_in_page();
     void paste();
     void copy_selected_text();
 
@@ -172,6 +179,7 @@ private:
     QAction* m_copy_selection_action { nullptr };
     QAction* m_paste_action { nullptr };
     QAction* m_select_all_action { nullptr };
+    QAction* m_find_in_page_action { nullptr };
     QAction* m_view_source_action { nullptr };
     QAction* m_inspect_dom_node_action { nullptr };
 

+ 104 - 0
Ladybird/Qt/FindInPageWidget.cpp

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "FindInPageWidget.h"
+#include "Icon.h"
+#include "StringUtils.h"
+#include <Ladybird/Qt/Tab.h>
+#include <QKeyEvent>
+
+namespace Ladybird {
+
+FindInPageWidget::FindInPageWidget(Tab* tab, WebContentView* content_view)
+    : QWidget(static_cast<QWidget*>(tab), Qt::Widget)
+    , m_tab(tab)
+    , m_content_view(content_view)
+{
+    setFocusPolicy(Qt::FocusPolicy::StrongFocus);
+
+    auto* layout = new QHBoxLayout(this);
+    setLayout(layout);
+    layout->setContentsMargins(5, 5, 5, 5);
+    layout->setAlignment(Qt::AlignmentFlag::AlignLeft);
+
+    m_find_text = new QLineEdit(this);
+    m_find_text->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
+    m_find_text->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Fixed);
+    m_find_text->setMinimumWidth(50);
+    m_find_text->setMaximumWidth(250);
+    connect(m_find_text, &QLineEdit::textChanged, this, &FindInPageWidget::find_text_changed);
+
+    m_previous_button = new QPushButton(this);
+    m_previous_button->setFixedWidth(30);
+    m_previous_button->setIcon(create_tvg_icon_with_theme_colors("up", palette()));
+    connect(m_previous_button, &QPushButton::clicked, this, [this] {
+        m_content_view->find_in_page_previous_match();
+    });
+
+    m_next_button = new QPushButton(this);
+    m_next_button->setFixedWidth(30);
+    m_next_button->setIcon(create_tvg_icon_with_theme_colors("down", palette()));
+    connect(m_next_button, &QPushButton::clicked, this, [this] {
+        m_content_view->find_in_page_next_match();
+    });
+
+    m_exit_button = new QPushButton(this);
+    m_exit_button->setFixedWidth(30);
+    m_exit_button->setIcon(create_tvg_icon_with_theme_colors("close", palette()));
+    connect(m_exit_button, &QPushButton::clicked, this, [this] {
+        setVisible(false);
+    });
+
+    layout->addWidget(m_find_text, 1);
+    layout->addWidget(m_previous_button);
+    layout->addWidget(m_next_button);
+    layout->addStretch(1);
+    layout->addWidget(m_exit_button);
+}
+
+FindInPageWidget::~FindInPageWidget() = default;
+
+void FindInPageWidget::find_text_changed()
+{
+    auto converted_text = ak_string_from_qstring(m_find_text->text());
+    m_content_view->find_in_page(converted_text);
+}
+
+void FindInPageWidget::keyPressEvent(QKeyEvent* event)
+{
+    switch (event->key()) {
+    case Qt::Key_Escape:
+        setVisible(false);
+        break;
+    case Qt::Key_Return:
+        m_next_button->click();
+        break;
+    default:
+        event->ignore();
+        break;
+    }
+}
+
+void FindInPageWidget::focusInEvent(QFocusEvent* event)
+{
+    QWidget::focusInEvent(event);
+    m_find_text->setFocus();
+    m_find_text->selectAll();
+}
+
+void FindInPageWidget::showEvent(QShowEvent*)
+{
+    if (m_tab && m_tab->isVisible())
+        m_tab->update_hover_label();
+}
+
+void FindInPageWidget::hideEvent(QHideEvent*)
+{
+    if (m_tab && m_tab->isVisible())
+        m_tab->update_hover_label();
+}
+
+}

+ 47 - 0
Ladybird/Qt/FindInPageWidget.h

@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include "WebContentView.h"
+#include <LibWebView/Forward.h>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QWidget>
+
+namespace Ladybird {
+
+class WebContentView;
+
+class FindInPageWidget final : public QWidget {
+    Q_OBJECT
+
+public:
+    FindInPageWidget(Tab* tab, WebContentView* content_view);
+
+    virtual ~FindInPageWidget() override;
+
+public slots:
+
+private:
+    virtual void keyPressEvent(QKeyEvent*) override;
+    virtual void focusInEvent(QFocusEvent*) override;
+    virtual void showEvent(QShowEvent*) override;
+    virtual void hideEvent(QHideEvent*) override;
+
+    void find_text_changed();
+
+    Tab* m_tab { nullptr };
+    WebContentView* m_content_view { nullptr };
+
+    QLineEdit* m_find_text { nullptr };
+    QPushButton* m_previous_button { nullptr };
+    QPushButton* m_next_button { nullptr };
+    QPushButton* m_exit_button { nullptr };
+    QAction* m_copy_attribute_value_action { nullptr };
+};
+
+}

+ 14 - 1
Ladybird/Qt/Tab.cpp

@@ -56,6 +56,8 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
     m_layout->setContentsMargins(0, 0, 0, 0);
 
     m_view = new WebContentView(this, web_content_options, webdriver_content_ipc_path, parent_client, page_index);
+    m_find_in_page = new FindInPageWidget(this, m_view);
+    m_find_in_page->setVisible(false);
     m_toolbar = new QToolBar(this);
     m_location_edit = new LocationEdit(this);
 
@@ -70,6 +72,7 @@ Tab::Tab(BrowserWindow* window, WebContentOptions const& web_content_options, St
 
     m_layout->addWidget(m_toolbar);
     m_layout->addWidget(m_view);
+    m_layout->addWidget(m_find_in_page);
 
     m_hamburger_button = new QToolButton(m_toolbar);
     m_hamburger_button->setText("Show &Menu");
@@ -887,7 +890,11 @@ void Tab::resizeEvent(QResizeEvent* event)
 void Tab::update_hover_label()
 {
     m_hover_label->resize(QFontMetrics(m_hover_label->font()).boundingRect(m_hover_label->text()).adjusted(-4, -2, 4, 2).size());
-    m_hover_label->move(6, height() - m_hover_label->height() - 8);
+    auto hover_label_height = height() - m_hover_label->height() - 8;
+    if (m_find_in_page->isVisible())
+        hover_label_height -= m_find_in_page->height() - 4;
+
+    m_hover_label->move(6, hover_label_height);
     m_hover_label->raise();
 }
 
@@ -933,6 +940,12 @@ void Tab::show_inspector_window(InspectorTarget inspector_target)
         m_inspector_widget->select_default_node();
 }
 
+void Tab::show_find_in_page()
+{
+    m_find_in_page->setVisible(true);
+    m_find_in_page->setFocus();
+}
+
 void Tab::close_sub_widgets()
 {
     auto close_widget_window = [](auto* widget) {

+ 6 - 1
Ladybird/Qt/Tab.h

@@ -9,6 +9,7 @@
 
 #include "LocationEdit.h"
 #include "WebContentView.h"
+#include <Ladybird/Qt/FindInPageWidget.h>
 #include <LibWeb/HTML/AudioPlayState.h>
 #include <QBoxLayout>
 #include <QLabel>
@@ -51,6 +52,8 @@ public:
     };
     void show_inspector_window(InspectorTarget = InspectorTarget::Document);
 
+    void show_find_in_page();
+
     QIcon const& favicon() const { return m_favicon; }
     QString const& title() const { return m_title; }
 
@@ -60,6 +63,8 @@ public:
 
     QToolButton* hamburger_button() const { return m_hamburger_button; }
 
+    void update_hover_label();
+
 public slots:
     void focus_location_editor();
     void location_edit_return_pressed();
@@ -76,7 +81,6 @@ private:
     virtual bool event(QEvent*) override;
 
     void recreate_toolbar_icons();
-    void update_hover_label();
 
     void open_link(URL::URL const&);
     void open_link_in_new_tab(URL::URL const&);
@@ -92,6 +96,7 @@ private:
     QAction* m_reset_zoom_button_action { nullptr };
     LocationEdit* m_location_edit { nullptr };
     WebContentView* m_view { nullptr };
+    FindInPageWidget* m_find_in_page { nullptr };
     BrowserWindow* m_window { nullptr };
     QString m_title;
     QLabel* m_hover_label { nullptr };

+ 2 - 0
Ladybird/Qt/ladybird.qrc

@@ -7,5 +7,7 @@
         <file>../Icons/hamburger.tvg</file>
         <file>../Icons/new_tab.tvg</file>
         <file>../Icons/reload.tvg</file>
+        <file>../Icons/up.tvg</file>
+        <file>../Icons/down.tvg</file>
     </qresource>
 </RCC>