FilteringProxyModel.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. Variant FilteringProxyModel::data(ModelIndex const& index, ModelRole role) const
  28. {
  29. if (!index.is_valid())
  30. return {};
  31. if ((size_t)index.row() > m_matching_indices.size() || index.row() < 0)
  32. return {};
  33. return m_matching_indices[index.row()].data(role);
  34. }
  35. void FilteringProxyModel::invalidate()
  36. {
  37. filter();
  38. did_update();
  39. }
  40. void FilteringProxyModel::filter()
  41. {
  42. m_matching_indices.clear();
  43. Function<void(ModelIndex&)> add_matching = [&](ModelIndex& parent_index) {
  44. for (auto i = 0; i < m_model->row_count(parent_index); ++i) {
  45. auto index = m_model->index(i, 0, parent_index);
  46. if (!index.is_valid())
  47. continue;
  48. auto filter_matches = m_model->data_matches(index, m_filter_term);
  49. bool matches = filter_matches == TriState::True;
  50. if (filter_matches == TriState::Unknown) {
  51. auto data = index.data();
  52. if (data.is_string() && data.as_string().contains(m_filter_term))
  53. matches = true;
  54. }
  55. if (matches)
  56. m_matching_indices.append(index);
  57. add_matching(index);
  58. }
  59. };
  60. ModelIndex parent_index;
  61. add_matching(parent_index);
  62. }
  63. void FilteringProxyModel::set_filter_term(StringView term)
  64. {
  65. if (m_filter_term == term)
  66. return;
  67. m_filter_term = term;
  68. invalidate();
  69. }
  70. ModelIndex FilteringProxyModel::map(ModelIndex const& index) const
  71. {
  72. if (!index.is_valid())
  73. return {};
  74. auto row = index.row();
  75. if (m_matching_indices.size() > (size_t)row)
  76. return m_matching_indices[row];
  77. return {};
  78. }
  79. bool FilteringProxyModel::is_searchable() const
  80. {
  81. return m_model->is_searchable();
  82. }
  83. Vector<ModelIndex> FilteringProxyModel::matches(StringView searching, unsigned flags, ModelIndex const& index)
  84. {
  85. auto found_indices = m_model->matches(searching, flags, index);
  86. for (size_t i = 0; i < found_indices.size(); i++)
  87. found_indices[i] = map(found_indices[i]);
  88. return found_indices;
  89. }
  90. }