FindInFilesWidget.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include "FindInFilesWidget.h"
  2. #include "Project.h"
  3. #include <LibGUI/GBoxLayout.h>
  4. #include <LibGUI/GButton.h>
  5. #include <LibGUI/GListView.h>
  6. #include <LibGUI/GTextBox.h>
  7. extern GTextEditor& current_editor();
  8. extern void open_file(const String&);
  9. extern OwnPtr<Project> g_project;
  10. struct FilenameAndLineNumber {
  11. String filename;
  12. int line_number { -1 };
  13. };
  14. class SearchResultsModel final : public GModel {
  15. public:
  16. explicit SearchResultsModel(const Vector<FilenameAndLineNumber>&& matches)
  17. : m_matches(move(matches))
  18. {
  19. }
  20. virtual int row_count(const GModelIndex& = GModelIndex()) const override { return m_matches.size(); }
  21. virtual int column_count(const GModelIndex& = GModelIndex()) const override { return 1; }
  22. virtual GVariant data(const GModelIndex& index, Role role = Role::Display) const override
  23. {
  24. if (role == Role::Display) {
  25. auto& match = m_matches.at(index.row());
  26. return String::format("%s:%d", match.filename.characters(), match.line_number);
  27. }
  28. return {};
  29. }
  30. virtual void update() override {}
  31. private:
  32. Vector<FilenameAndLineNumber> m_matches;
  33. };
  34. static RefPtr<SearchResultsModel> find_in_files(const StringView& text)
  35. {
  36. Vector<FilenameAndLineNumber> matches;
  37. g_project->for_each_text_file([&](auto& file) {
  38. auto matches_in_file = file.find(text);
  39. for (int match : matches_in_file) {
  40. matches.append({ file.name(), match });
  41. }
  42. });
  43. return adopt(*new SearchResultsModel(move(matches)));
  44. }
  45. FindInFilesWidget::FindInFilesWidget(GWidget* parent)
  46. : GWidget(parent)
  47. {
  48. set_layout(make<GBoxLayout>(Orientation::Vertical));
  49. m_textbox = GTextBox::construct(this);
  50. m_textbox->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
  51. m_textbox->set_preferred_size(0, 20);
  52. m_button = GButton::construct("Find in files", this);
  53. m_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
  54. m_button->set_preferred_size(0, 20);
  55. m_result_view = GListView::construct(this);
  56. m_result_view->on_activation = [this](auto& index) {
  57. auto match_string = m_result_view->model()->data(index).to_string();
  58. auto parts = match_string.split(':');
  59. ASSERT(parts.size() == 2);
  60. bool ok;
  61. int line_number = parts[1].to_int(ok);
  62. ASSERT(ok);
  63. open_file(parts[0]);
  64. current_editor().set_cursor(line_number - 1, 0);
  65. current_editor().set_focus(true);
  66. };
  67. m_button->on_click = [this](auto&) {
  68. auto results_model = find_in_files(m_textbox->text());
  69. m_result_view->set_model(results_model);
  70. };
  71. m_textbox->on_return_pressed = [this] {
  72. m_button->click();
  73. };
  74. }
  75. void FindInFilesWidget::focus_textbox_and_select_all()
  76. {
  77. m_textbox->select_all();
  78. m_textbox->set_focus(true);
  79. }