ClassViewWidget.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "ClassViewWidget.h"
  7. #include "HackStudio.h"
  8. #include "ProjectDeclarations.h"
  9. #include <AK/StdLibExtras.h>
  10. #include <LibGUI/BoxLayout.h>
  11. #include <string.h>
  12. namespace HackStudio {
  13. ClassViewWidget::ClassViewWidget()
  14. {
  15. set_layout<GUI::VerticalBoxLayout>();
  16. m_class_tree = add<GUI::TreeView>();
  17. m_class_tree->on_selection_change = [this] {
  18. const auto& index = m_class_tree->selection().first();
  19. if (!index.is_valid())
  20. return;
  21. auto* node = static_cast<const ClassViewNode*>(index.internal_data());
  22. if (!node->declaration)
  23. return;
  24. open_file(node->declaration->position.file, node->declaration->position.line, node->declaration->position.column);
  25. };
  26. }
  27. RefPtr<ClassViewModel> ClassViewModel::create()
  28. {
  29. return adopt_ref(*new ClassViewModel());
  30. }
  31. int ClassViewModel::row_count(const GUI::ModelIndex& index) const
  32. {
  33. if (!index.is_valid())
  34. return m_root_scope.size();
  35. auto* node = static_cast<ClassViewNode*>(index.internal_data());
  36. return node->children.size();
  37. }
  38. GUI::Variant ClassViewModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
  39. {
  40. auto* node = static_cast<ClassViewNode const*>(index.internal_data());
  41. switch (role) {
  42. case GUI::ModelRole::Display: {
  43. return node->name;
  44. }
  45. case GUI::ModelRole::Icon: {
  46. if (!node->declaration)
  47. return {};
  48. auto icon = ProjectDeclarations::get_icon_for(node->declaration->type);
  49. if (icon.has_value())
  50. return icon.value();
  51. return {};
  52. }
  53. default:
  54. return {};
  55. }
  56. }
  57. GUI::ModelIndex ClassViewModel::parent_index(const GUI::ModelIndex& index) const
  58. {
  59. if (!index.is_valid())
  60. return {};
  61. auto* child = static_cast<ClassViewNode const*>(index.internal_data());
  62. auto* parent = child->parent;
  63. if (parent == nullptr)
  64. return {};
  65. if (parent->parent == nullptr) {
  66. for (size_t row = 0; row < m_root_scope.size(); row++) {
  67. if (m_root_scope[row].ptr() == parent)
  68. return create_index(row, 0, parent);
  69. }
  70. VERIFY_NOT_REACHED();
  71. }
  72. for (size_t row = 0; row < parent->parent->children.size(); row++) {
  73. ClassViewNode* child_at_row = parent->parent->children[row].ptr();
  74. if (child_at_row == parent)
  75. return create_index(row, 0, parent);
  76. }
  77. VERIFY_NOT_REACHED();
  78. }
  79. GUI::ModelIndex ClassViewModel::index(int row, int column, const GUI::ModelIndex& parent_index) const
  80. {
  81. if (!parent_index.is_valid())
  82. return create_index(row, column, &m_root_scope[row]);
  83. auto* parent = static_cast<ClassViewNode const*>(parent_index.internal_data());
  84. auto* child = &parent->children[row];
  85. return create_index(row, column, child);
  86. }
  87. ClassViewModel::ClassViewModel()
  88. {
  89. m_root_scope.clear();
  90. ProjectDeclarations::the().for_each_declared_symbol([this](auto& decl) {
  91. if (decl.type == CodeComprehension::DeclarationType::Class
  92. || decl.type == CodeComprehension::DeclarationType::Struct
  93. || decl.type == CodeComprehension::DeclarationType::Member
  94. || decl.type == CodeComprehension::DeclarationType::Namespace) {
  95. add_declaration(decl);
  96. }
  97. });
  98. }
  99. static ClassViewNode& add_child_node(Vector<NonnullOwnPtr<ClassViewNode>>& children, NonnullOwnPtr<ClassViewNode>&& node_ptr, ClassViewNode* parent, CodeComprehension::Declaration const* declaration)
  100. {
  101. node_ptr->parent = parent;
  102. node_ptr->declaration = declaration;
  103. size_t inserted_index = 0;
  104. ClassViewNode& node = *node_ptr;
  105. // Insert into parent's children list, sorted lexicographically by name.
  106. children.insert_before_matching(
  107. move(node_ptr), [&node](auto& other_node) {
  108. return strncmp(node.name.characters_without_null_termination(), other_node->name.characters_without_null_termination(), min(node.name.length(), other_node->name.length())) < 0;
  109. },
  110. 0, &inserted_index);
  111. return *children.at(inserted_index);
  112. }
  113. void ClassViewModel::add_declaration(CodeComprehension::Declaration const& decl)
  114. {
  115. ClassViewNode* parent = nullptr;
  116. auto scope_parts = decl.scope.view().split_view("::"sv);
  117. if (!scope_parts.is_empty()) {
  118. // Traverse declarations tree to the parent of 'decl'
  119. for (auto& node : m_root_scope) {
  120. if (node->name == scope_parts.first())
  121. parent = node;
  122. }
  123. if (parent == nullptr) {
  124. m_root_scope.append(make<ClassViewNode>(scope_parts.first()));
  125. parent = m_root_scope.last();
  126. }
  127. for (size_t i = 1; i < scope_parts.size(); ++i) {
  128. auto& scope = scope_parts[i];
  129. ClassViewNode* next { nullptr };
  130. for (auto& child : parent->children) {
  131. if (child->name == scope) {
  132. next = child;
  133. break;
  134. }
  135. }
  136. if (next) {
  137. parent = next;
  138. continue;
  139. }
  140. parent = &add_child_node(parent->children, make<ClassViewNode>(scope), parent, nullptr);
  141. }
  142. }
  143. Vector<NonnullOwnPtr<ClassViewNode>>* children_of_parent = nullptr;
  144. if (parent) {
  145. children_of_parent = &parent->children;
  146. } else {
  147. children_of_parent = &m_root_scope;
  148. }
  149. bool already_exists = false;
  150. for (auto& child : *children_of_parent) {
  151. if (child->name == decl.name) {
  152. already_exists = true;
  153. if (!child->declaration) {
  154. child->declaration = &decl;
  155. }
  156. break;
  157. }
  158. }
  159. if (!already_exists) {
  160. add_child_node(*children_of_parent, make<ClassViewNode>(decl.name), parent, &decl);
  161. }
  162. }
  163. void ClassViewWidget::refresh()
  164. {
  165. m_class_tree->set_model(ClassViewModel::create());
  166. }
  167. }