Serenity Operating System
1/*
2 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibGUI/TreeViewModel.h>
8
9namespace GUI {
10
11ModelIndex TreeViewModel::index(int row, int column, ModelIndex const& parent) const
12{
13 if (!parent.is_valid()) {
14 if (static_cast<size_t>(row) >= m_nodes.size())
15 return {};
16 return create_index(row, column, &m_nodes[row]);
17 }
18 auto const& parent_node = *static_cast<Node const*>(parent.internal_data());
19 if (static_cast<size_t>(row) >= parent_node.child_nodes().size())
20 return {};
21 auto const* child = &parent_node.child_nodes()[row];
22 return create_index(row, column, child);
23}
24
25ModelIndex TreeViewModel::parent_index(ModelIndex const& index) const
26{
27 if (!index.is_valid())
28 return {};
29 auto const& child_node = *static_cast<Node const*>(index.internal_data());
30 auto const* parent_node = child_node.parent_node();
31 if (parent_node == nullptr)
32 return {};
33 if (parent_node->parent_node() == nullptr) {
34 for (size_t row = 0; row < m_nodes.size(); row++)
35 if (m_nodes[row] == parent_node)
36 return create_index(static_cast<int>(row), 0, parent_node);
37 VERIFY_NOT_REACHED();
38 }
39 for (size_t row = 0; row < parent_node->parent_node()->child_nodes().size(); row++) {
40 auto const* child_node_at_row = parent_node->parent_node()->child_nodes()[row].ptr();
41 if (child_node_at_row == parent_node)
42 return create_index(static_cast<int>(row), 0, parent_node);
43 }
44 VERIFY_NOT_REACHED();
45}
46
47int TreeViewModel::row_count(ModelIndex const& index) const
48{
49 if (!index.is_valid())
50 return static_cast<int>(m_nodes.size());
51 auto const& node = *static_cast<Node const*>(index.internal_data());
52 return static_cast<int>(node.child_nodes().size());
53}
54
55Variant TreeViewModel::data(ModelIndex const& index, ModelRole role) const
56{
57 auto const& node = *static_cast<Node const*>(index.internal_data());
58 switch (role) {
59 case ModelRole::Display:
60 return node.text();
61 case ModelRole::Icon:
62 if (node.icon().has_value())
63 return *node.icon();
64 return {};
65 default:
66 return {};
67 }
68}
69
70Optional<ModelIndex> TreeViewModel::index_for_node(Node const& node, ModelIndex const& parent) const
71{
72 for (int row = 0; row < row_count(parent); ++row) {
73 auto row_index = this->index(row, 0);
74 auto const* row_node = static_cast<TreeViewModel::Node const*>(row_index.internal_data());
75 if (&node == row_node)
76 return row_index;
77 if (auto index = index_for_node(node, row_index); index.has_value())
78 return index;
79 }
80 return {};
81}
82
83}