ladybird/UI/Qt/FindInPageWidget.cpp
Andreas Kling 2ace898858 UI/Qt: Stop using TVG icons
Draw the remaining Qt chrome icons through the existing generated icon
path instead of loading TinyVG resources. Add generated folder and
chevron icons for menus, the bookmarks bar, and find-in-page controls,
and use the generated globe icon for bookmarks without favicons.

Remove the Qt TinyVG icon engine and drop the unused TVG resources from
the Qt resource file.
2026-05-31 19:20:59 +02:00

189 lines
5.7 KiB
C++

/*
* Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <UI/Qt/ChromeStyle.h>
#include <UI/Qt/FindInPageWidget.h>
#include <UI/Qt/Icon.h>
#include <UI/Qt/StringUtils.h>
#include <UI/Qt/Tab.h>
#include <QEvent>
#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)
{
setObjectName("LadybirdFindInPageBar");
setAttribute(Qt::WA_StyledBackground);
setFocusPolicy(Qt::FocusPolicy::StrongFocus);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
update_chrome_style();
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->setPlaceholderText("Search");
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_chrome_icon(ChromeIcon::ChevronUp, palette()));
m_previous_button->setToolTip("Find Previous Match");
m_previous_button->setFlat(true);
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_chrome_icon(ChromeIcon::ChevronDown, palette()));
m_next_button->setToolTip("Find Next Match");
m_next_button->setFlat(true);
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_chrome_icon(ChromeIcon::Close, palette()));
m_exit_button->setToolTip("Close Search Bar");
m_exit_button->setFlat(true);
connect(m_exit_button, &QPushButton::clicked, this, [this] {
setVisible(false);
});
m_match_case = new QCheckBox(this);
m_match_case->setText("Match &Case");
m_match_case->setChecked(false);
#if (QT_VERSION > QT_VERSION_CHECK(6, 7, 0))
connect(m_match_case, &QCheckBox::checkStateChanged, this, [this] {
#else
connect(m_match_case, &QCheckBox::stateChanged, this, [this] {
#endif
find_text_changed();
});
m_result_label = new QLabel(this);
m_result_label->setVisible(false);
m_result_label->setStyleSheet("font-weight: bold;");
layout->addWidget(m_find_text, 1);
layout->addWidget(m_previous_button);
layout->addWidget(m_next_button);
layout->addWidget(m_match_case);
layout->addWidget(m_result_label);
layout->addStretch(1);
layout->addWidget(m_exit_button);
}
FindInPageWidget::~FindInPageWidget() = default;
bool FindInPageWidget::event(QEvent* event)
{
if (event->type() == QEvent::PaletteChange) {
update_chrome_style();
m_previous_button->setIcon(create_chrome_icon(ChromeIcon::ChevronUp, palette()));
m_next_button->setIcon(create_chrome_icon(ChromeIcon::ChevronDown, palette()));
m_exit_button->setIcon(create_chrome_icon(ChromeIcon::Close, palette()));
}
return QWidget::event(event);
}
void FindInPageWidget::update_chrome_style()
{
if (m_is_updating_chrome_style)
return;
m_is_updating_chrome_style = true;
setStyleSheet(ChromeStyle::find_in_page_style_sheet(palette()));
m_is_updating_chrome_style = false;
}
void FindInPageWidget::find_text_changed()
{
auto query = ak_string_from_qstring(m_find_text->text());
auto case_sensitive = m_match_case->isChecked() ? CaseSensitivity::CaseSensitive : CaseSensitivity::CaseInsensitive;
m_content_view->find_in_page(query, case_sensitive);
}
void FindInPageWidget::keyPressEvent(QKeyEvent* event)
{
switch (event->key()) {
case Qt::Key_Escape:
setVisible(false);
break;
case Qt::Key_Return:
if (event->modifiers().testFlag(Qt::ShiftModifier))
m_previous_button->click();
else
m_next_button->click();
break;
default:
event->ignore();
break;
}
}
void FindInPageWidget::focusInEvent(QFocusEvent* event)
{
QWidget::focusInEvent(event);
m_find_text->setFocus();
auto selected_text = m_content_view->selected_text();
if (!selected_text.is_empty())
m_find_text->setText(qstring_from_ak_string(selected_text));
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();
}
void FindInPageWidget::update_result_label(size_t current_match_index, Optional<size_t> const& total_match_count)
{
if (total_match_count.has_value()) {
auto label_text = "Phrase not found"_string;
if (total_match_count.value() > 0)
label_text = MUST(String::formatted("{} of {} matches", current_match_index + 1, total_match_count.value()));
m_result_label->setText(qstring_from_ak_string(label_text));
m_result_label->setVisible(true);
} else {
m_result_label->setVisible(false);
}
}
void FindInPageWidget::find_previous()
{
m_previous_button->click();
}
void FindInPageWidget::find_next()
{
m_next_button->click();
}
}