FilteringProxyModel.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGUI/FilteringProxyModel.h>
  7. namespace GUI {
  8. ModelIndex FilteringProxyModel::index(int row, int column, ModelIndex const& parent_index) const
  9. {
  10. int parent_row = parent_index.row();
  11. if (!parent_index.is_valid())
  12. parent_row = 0;
  13. return create_index(parent_row + row, column);
  14. }
  15. int FilteringProxyModel::row_count(ModelIndex const&) const
  16. {
  17. return m_matching_indices.size();
  18. }
  19. int FilteringProxyModel::column_count(ModelIndex const& index) const
  20. {
  21. if (!index.is_valid())
  22. return m_model->column_count({});
  23. if ((size_t)index.row() > m_matching_indices.size() || index.row() < 0)
  24. return 0;
  25. return m_model->column_count(m_matching_indices[index.row()]);
  26. }
  27. String FilteringProxyModel::column_name(int column) const
  28. {
  29. return m_model->column_name(column);
  30. }
  31. Variant FilteringProxyModel::data(ModelIndex const& index, ModelRole role) const
  32. {
  33. if (!index.is_valid())
  34. return {};
  35. if ((size_t)index.row() > m_matching_indices.size() || index.row() < 0)
  36. return {};
  37. auto matching_index = m_matching_indices[index.row()];
  38. auto underlying_index = m_model->index(matching_index.row(), index.column(), matching_index.parent());
  39. return underlying_index.data(role);
  40. }
  41. void FilteringProxyModel::invalidate()
  42. {
  43. filter();
  44. did_update();
  45. }
  46. void FilteringProxyModel::filter()
  47. {
  48. m_matching_indices.clear();
  49. Function<void(ModelIndex&)> add_matching = [&](ModelIndex& parent_index) {
  50. for (auto i = 0; i < m_model->row_count(parent_index); ++i) {
  51. auto index = m_model->index(i, 0, parent_index);
  52. if (!index.is_valid())
  53. continue;
  54. auto filter_matches = m_model->data_matches(index, m_filter_term);
  55. bool matches = filter_matches == TriState::True;
  56. if (filter_matches == TriState::Unknown) {
  57. auto data = index.data();
  58. if (data.is_string() && data.as_string().contains(m_filter_term))
  59. matches = true;
  60. }
  61. if (matches)
  62. m_matching_indices.append(index);
  63. add_matching(index);
  64. }
  65. };
  66. ModelIndex parent_index;
  67. add_matching(parent_index);
  68. }
  69. void FilteringProxyModel::set_filter_term(StringView term)
  70. {
  71. if (m_filter_term == term)
  72. return;
  73. m_filter_term = term;
  74. invalidate();
  75. }
  76. ModelIndex FilteringProxyModel::map(ModelIndex const& index) const
  77. {
  78. if (!index.is_valid())
  79. return {};
  80. auto row = index.row();
  81. if (m_matching_indices.size() > (size_t)row)
  82. return m_matching_indices[row];
  83. return {};
  84. }
  85. bool FilteringProxyModel::is_searchable() const
  86. {
  87. return m_model->is_searchable();
  88. }
  89. Vector<ModelIndex> FilteringProxyModel::matches(StringView searching, unsigned flags, ModelIndex const& index)
  90. {
  91. auto found_indices = m_model->matches(searching, flags, index);
  92. for (size_t i = 0; i < found_indices.size(); i++)
  93. found_indices[i] = map(found_indices[i]);
  94. return found_indices;
  95. }
  96. }