FindInPageWidget.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "FindInPageWidget.h"
  7. #include "Icon.h"
  8. #include "StringUtils.h"
  9. #include <Ladybird/Qt/Tab.h>
  10. #include <QKeyEvent>
  11. namespace Ladybird {
  12. FindInPageWidget::FindInPageWidget(Tab* tab, WebContentView* content_view)
  13. : QWidget(static_cast<QWidget*>(tab), Qt::Widget)
  14. , m_tab(tab)
  15. , m_content_view(content_view)
  16. {
  17. setFocusPolicy(Qt::FocusPolicy::StrongFocus);
  18. auto* layout = new QHBoxLayout(this);
  19. setLayout(layout);
  20. layout->setContentsMargins(5, 5, 5, 5);
  21. layout->setAlignment(Qt::AlignmentFlag::AlignLeft);
  22. m_find_text = new QLineEdit(this);
  23. m_find_text->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
  24. m_find_text->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Fixed);
  25. m_find_text->setPlaceholderText("Search");
  26. m_find_text->setMinimumWidth(50);
  27. m_find_text->setMaximumWidth(250);
  28. connect(m_find_text, &QLineEdit::textChanged, this, &FindInPageWidget::find_text_changed);
  29. m_previous_button = new QPushButton(this);
  30. m_previous_button->setFixedWidth(30);
  31. m_previous_button->setIcon(create_tvg_icon_with_theme_colors("up", palette()));
  32. m_previous_button->setToolTip("Find Previous Match");
  33. m_previous_button->setFlat(true);
  34. connect(m_previous_button, &QPushButton::clicked, this, [this] {
  35. m_content_view->find_in_page_previous_match();
  36. });
  37. m_next_button = new QPushButton(this);
  38. m_next_button->setFixedWidth(30);
  39. m_next_button->setIcon(create_tvg_icon_with_theme_colors("down", palette()));
  40. m_next_button->setToolTip("Find Next Match");
  41. m_next_button->setFlat(true);
  42. connect(m_next_button, &QPushButton::clicked, this, [this] {
  43. m_content_view->find_in_page_next_match();
  44. });
  45. m_exit_button = new QPushButton(this);
  46. m_exit_button->setFixedWidth(30);
  47. m_exit_button->setIcon(create_tvg_icon_with_theme_colors("close", palette()));
  48. m_exit_button->setToolTip("Close Search Bar");
  49. m_exit_button->setFlat(true);
  50. connect(m_exit_button, &QPushButton::clicked, this, [this] {
  51. setVisible(false);
  52. });
  53. m_match_case = new QCheckBox(this);
  54. m_match_case->setText("Match &Case");
  55. m_match_case->setChecked(false);
  56. connect(m_match_case, &QCheckBox::stateChanged, this, [this] {
  57. find_text_changed();
  58. });
  59. m_result_label = new QLabel(this);
  60. m_result_label->setVisible(false);
  61. m_result_label->setStyleSheet("font-weight: bold;");
  62. layout->addWidget(m_find_text, 1);
  63. layout->addWidget(m_previous_button);
  64. layout->addWidget(m_next_button);
  65. layout->addWidget(m_match_case);
  66. layout->addWidget(m_result_label);
  67. layout->addStretch(1);
  68. layout->addWidget(m_exit_button);
  69. }
  70. FindInPageWidget::~FindInPageWidget() = default;
  71. void FindInPageWidget::find_text_changed()
  72. {
  73. auto query = ak_string_from_qstring(m_find_text->text());
  74. auto case_sensitive = m_match_case->isChecked() ? CaseSensitivity::CaseSensitive : CaseSensitivity::CaseInsensitive;
  75. m_content_view->find_in_page(query, case_sensitive);
  76. }
  77. void FindInPageWidget::keyPressEvent(QKeyEvent* event)
  78. {
  79. switch (event->key()) {
  80. case Qt::Key_Escape:
  81. setVisible(false);
  82. break;
  83. case Qt::Key_Return:
  84. if (event->modifiers().testFlag(Qt::ShiftModifier))
  85. m_previous_button->click();
  86. else
  87. m_next_button->click();
  88. break;
  89. default:
  90. event->ignore();
  91. break;
  92. }
  93. }
  94. void FindInPageWidget::focusInEvent(QFocusEvent* event)
  95. {
  96. QWidget::focusInEvent(event);
  97. m_find_text->setFocus();
  98. auto selected_text = m_content_view->selected_text();
  99. if (!selected_text.is_empty())
  100. m_find_text->setText(qstring_from_ak_string(selected_text));
  101. m_find_text->selectAll();
  102. }
  103. void FindInPageWidget::showEvent(QShowEvent*)
  104. {
  105. if (m_tab && m_tab->isVisible())
  106. m_tab->update_hover_label();
  107. }
  108. void FindInPageWidget::hideEvent(QHideEvent*)
  109. {
  110. if (m_tab && m_tab->isVisible())
  111. m_tab->update_hover_label();
  112. }
  113. void FindInPageWidget::update_result_label(size_t current_match_index, Optional<size_t> const& total_match_count)
  114. {
  115. if (total_match_count.has_value()) {
  116. auto label_text = "Phrase not found"_string;
  117. if (total_match_count.value() > 0)
  118. label_text = MUST(String::formatted("{} of {} matches", current_match_index + 1, total_match_count.value()));
  119. m_result_label->setText(qstring_from_ak_string(label_text));
  120. m_result_label->setVisible(true);
  121. } else {
  122. m_result_label->setVisible(false);
  123. }
  124. }
  125. }