Ladybird/Qt: Add a find in page widget

This commit is contained in:
Tim Ledbetter 2024-05-29 20:12:21 +01:00 committed by Andreas Kling
parent 7aea87c9df
commit 389a55fe36
10 changed files with 199 additions and 2 deletions

View File

@ -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
Ladybird/Icons/down.tvg Normal file

Binary file not shown.

BIN
Ladybird/Icons/up.tvg Normal file

Binary file not shown.

View File

@ -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)

View File

@ -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 };

View File

@ -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();
}
}

View File

@ -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 };
};
}

View File

@ -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) {

View File

@ -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 };

View File

@ -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>