FindInFilesWidget.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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 FilenameAndRange {
  11. String filename;
  12. GTextRange range;
  13. };
  14. class SearchResultsModel final : public GModel {
  15. public:
  16. explicit SearchResultsModel(const Vector<FilenameAndRange>&& 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,%d - %d,%d)",
  27. match.filename.characters(),
  28. match.range.start().line() + 1,
  29. match.range.start().column(),
  30. match.range.end().line() + 1,
  31. match.range.end().column());
  32. }
  33. return {};
  34. }
  35. virtual void update() override {}
  36. virtual GModelIndex index(int row, int column = 0, const GModelIndex& = GModelIndex()) const override { return create_index(row, column, &m_matches.at(row)); }
  37. private:
  38. Vector<FilenameAndRange> m_matches;
  39. };
  40. static RefPtr<SearchResultsModel> find_in_files(const StringView& text)
  41. {
  42. Vector<FilenameAndRange> matches;
  43. g_project->for_each_text_file([&](auto& file) {
  44. auto matches_in_file = file.document().find_all(text);
  45. for (auto& range : matches_in_file) {
  46. matches.append({ file.name(), range });
  47. }
  48. });
  49. return adopt(*new SearchResultsModel(move(matches)));
  50. }
  51. FindInFilesWidget::FindInFilesWidget(GWidget* parent)
  52. : GWidget(parent)
  53. {
  54. set_layout(make<GBoxLayout>(Orientation::Vertical));
  55. m_textbox = GTextBox::construct(this);
  56. m_textbox->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
  57. m_textbox->set_preferred_size(0, 20);
  58. m_button = GButton::construct("Find in files", this);
  59. m_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
  60. m_button->set_preferred_size(0, 20);
  61. m_result_view = GListView::construct(this);
  62. m_result_view->on_activation = [](auto& index) {
  63. auto& match = *(const FilenameAndRange*)index.internal_data();
  64. open_file(match.filename);
  65. current_editor().set_selection(match.range);
  66. current_editor().set_focus(true);
  67. };
  68. m_button->on_click = [this](auto&) {
  69. auto results_model = find_in_files(m_textbox->text());
  70. m_result_view->set_model(results_model);
  71. };
  72. m_textbox->on_return_pressed = [this] {
  73. m_button->click();
  74. };
  75. }
  76. void FindInFilesWidget::focus_textbox_and_select_all()
  77. {
  78. m_textbox->select_all();
  79. m_textbox->set_focus(true);
  80. }