DOMTreeModel.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include "DOMTreeModel.h"
  2. #include <AK/StringBuilder.h>
  3. #include <LibHTML/DOM/Document.h>
  4. #include <LibHTML/DOM/Text.h>
  5. #include <ctype.h>
  6. #include <stdio.h>
  7. DOMTreeModel::DOMTreeModel(Document& document)
  8. : m_document(document)
  9. {
  10. m_document_icon.set_bitmap_for_size(16, GraphicsBitmap::load_from_file("/res/icons/16x16/filetype-html.png"));
  11. m_element_icon.set_bitmap_for_size(16, GraphicsBitmap::load_from_file("/res/icons/16x16/inspector-object.png"));
  12. m_text_icon.set_bitmap_for_size(16, GraphicsBitmap::load_from_file("/res/icons/16x16/filetype-unknown.png"));
  13. }
  14. DOMTreeModel::~DOMTreeModel()
  15. {
  16. }
  17. GModelIndex DOMTreeModel::index(int row, int column, const GModelIndex& parent) const
  18. {
  19. if (!parent.is_valid()) {
  20. return create_index(row, column, m_document.ptr());
  21. }
  22. auto& parent_node = *static_cast<Node*>(parent.internal_data());
  23. return create_index(row, column, parent_node.child_at_index(row));
  24. }
  25. GModelIndex DOMTreeModel::parent_index(const GModelIndex& index) const
  26. {
  27. if (!index.is_valid())
  28. return {};
  29. auto& node = *static_cast<Node*>(index.internal_data());
  30. if (!node.parent())
  31. return {};
  32. // No grandparent? Parent is the document!
  33. if (!node.parent()->parent()) {
  34. return create_index(0, 0, m_document.ptr());
  35. }
  36. // Walk the grandparent's children to find the index of node's parent in its parent.
  37. // (This is needed to produce the row number of the GModelIndex corresponding to node's parent.)
  38. int grandparent_child_index = 0;
  39. for (auto* grandparent_child = node.parent()->parent()->first_child(); grandparent_child; grandparent_child = grandparent_child->next_sibling()) {
  40. if (grandparent_child == node.parent())
  41. return create_index(grandparent_child_index, 0, node.parent());
  42. ++grandparent_child_index;
  43. }
  44. ASSERT_NOT_REACHED();
  45. return {};
  46. }
  47. int DOMTreeModel::row_count(const GModelIndex& index) const
  48. {
  49. if (!index.is_valid())
  50. return 1;
  51. auto& node = *static_cast<Node*>(index.internal_data());
  52. return node.child_count();
  53. }
  54. int DOMTreeModel::column_count(const GModelIndex&) const
  55. {
  56. return 1;
  57. }
  58. static String with_whitespace_collapsed(const StringView& string)
  59. {
  60. StringBuilder builder;
  61. for (int i = 0; i < string.length(); ++i) {
  62. if (isspace(string[i])) {
  63. builder.append(' ');
  64. while (i < string.length()) {
  65. if (isspace(string[i])) {
  66. ++i;
  67. continue;
  68. }
  69. builder.append(string[i]);
  70. break;
  71. }
  72. continue;
  73. }
  74. builder.append(string[i]);
  75. }
  76. return builder.to_string();
  77. }
  78. GVariant DOMTreeModel::data(const GModelIndex& index, Role role) const
  79. {
  80. auto* node = static_cast<Node*>(index.internal_data());
  81. if (role == Role::Icon) {
  82. if (node->is_document())
  83. return m_document_icon;
  84. if (node->is_element())
  85. return m_element_icon;
  86. // FIXME: More node type icons?
  87. return m_text_icon;
  88. }
  89. if (role == Role::Display) {
  90. if (node->is_text()) {
  91. return String::format("%s", with_whitespace_collapsed(to<Text>(*node).data()).characters());
  92. }
  93. return String::format("<%s>", node->tag_name().characters());
  94. }
  95. return {};
  96. }
  97. void DOMTreeModel::update()
  98. {
  99. did_update();
  100. }