FilteringProxyModel.cpp 2.8 KB

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