Serenity Operating System
at master 189 lines 4.9 kB view raw
1/* 2 * Copyright (c) 2022, Jakub Berkop <jakub.berkop@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "FilesystemEventModel.h" 8#include "Profile.h" 9#include <AK/StringBuilder.h> 10#include <LibGUI/FileIconProvider.h> 11#include <LibSymbolication/Symbolication.h> 12#include <stdio.h> 13 14namespace Profiler { 15 16FileEventModel::FileEventModel(Profile& profile) 17 : m_profile(profile) 18{ 19} 20 21FileEventModel::~FileEventModel() 22{ 23} 24 25FileEventNode& FileEventNode::find_or_create_node(DeprecatedString const& searched_path) 26{ 27 // TODO: Optimize this function. 28 29 if (searched_path == ""sv) { 30 return *this; 31 } 32 33 auto lex_path = LexicalPath(searched_path); 34 auto parts = lex_path.parts(); 35 auto current = parts.take_first(); 36 37 StringBuilder sb; 38 sb.join('/', parts); 39 auto new_s = sb.to_deprecated_string(); 40 41 for (auto& child : m_children) { 42 if (child->m_path == current) { 43 return child->find_or_create_node(new_s); 44 } 45 } 46 47 if (m_parent) { 48 for (auto& child : m_children) { 49 if (child->m_path == current) { 50 return child->find_or_create_node(new_s); 51 } 52 } 53 return create_recursively(searched_path); 54 } else { 55 if (!searched_path.starts_with("/"sv)) { 56 m_children.append(create(searched_path, this)); 57 return *m_children.last(); 58 } 59 60 return create_recursively(searched_path); 61 } 62} 63 64FileEventNode& FileEventNode::create_recursively(DeprecatedString new_path) 65{ 66 auto const lex_path = LexicalPath(new_path); 67 auto parts = lex_path.parts(); 68 69 if (parts.size() == 1) { 70 auto new_node = FileEventNode::create(new_path, this); 71 m_children.append(new_node); 72 return *new_node.ptr(); 73 } else { 74 auto new_node = FileEventNode::create(parts.take_first(), this); 75 m_children.append(new_node); 76 77 StringBuilder sb; 78 sb.join('/', parts); 79 80 return new_node->create_recursively(sb.to_deprecated_string()); 81 } 82} 83 84void FileEventNode::for_each_parent_node(Function<void(FileEventNode&)> callback) 85{ 86 auto* current = this; 87 while (current) { 88 callback(*current); 89 current = current->m_parent; 90 } 91} 92 93GUI::ModelIndex FileEventModel::index(int row, int column, GUI::ModelIndex const& parent) const 94{ 95 if (!parent.is_valid()) { 96 return create_index(row, column, m_profile.file_event_nodes()->children()[row].ptr()); 97 } 98 auto& remote_parent = *static_cast<FileEventNode*>(parent.internal_data()); 99 return create_index(row, column, remote_parent.children().at(row).ptr()); 100} 101 102GUI::ModelIndex FileEventModel::parent_index(GUI::ModelIndex const& index) const 103{ 104 if (!index.is_valid()) 105 return {}; 106 auto& node = *static_cast<FileEventNode*>(index.internal_data()); 107 if (!node.parent()) 108 return {}; 109 110 if (node.parent()->parent()) { 111 auto const& children = node.parent()->parent()->children(); 112 113 for (size_t row = 0; row < children.size(); ++row) { 114 if (children.at(row).ptr() == node.parent()) { 115 return create_index(row, index.column(), node.parent()); 116 } 117 } 118 } 119 120 auto const& children = node.parent()->children(); 121 122 for (size_t row = 0; row < children.size(); ++row) { 123 if (children.at(row).ptr() == &node) { 124 return create_index(row, index.column(), node.parent()); 125 } 126 } 127 128 VERIFY_NOT_REACHED(); 129 return {}; 130} 131 132int FileEventModel::row_count(GUI::ModelIndex const& index) const 133{ 134 if (!index.is_valid()) 135 return m_profile.file_event_nodes()->children().size(); 136 auto& node = *static_cast<FileEventNode*>(index.internal_data()); 137 return node.children().size(); 138} 139 140int FileEventModel::column_count(GUI::ModelIndex const&) const 141{ 142 return Column::__Count; 143} 144 145DeprecatedString FileEventModel::column_name(int column) const 146{ 147 switch (column) { 148 case Column::Path: 149 return "Path"; 150 case Column::Count: 151 return "Event Count"; 152 case Column::Duration: 153 return "Duration [ms]"; 154 default: 155 VERIFY_NOT_REACHED(); 156 return {}; 157 } 158} 159 160GUI::Variant FileEventModel::data(GUI::ModelIndex const& index, GUI::ModelRole role) const 161{ 162 if (role == GUI::ModelRole::TextAlignment) { 163 if (index.column() == Path) 164 return Gfx::TextAlignment::CenterLeft; 165 return Gfx::TextAlignment::CenterRight; 166 } 167 168 auto* node = static_cast<FileEventNode*>(index.internal_data()); 169 170 if (role == GUI::ModelRole::Display) { 171 if (index.column() == Column::Count) { 172 return node->count(); 173 } 174 175 if (index.column() == Column::Path) { 176 return node->path(); 177 } 178 179 if (index.column() == Column::Duration) { 180 return node->duration(); 181 } 182 183 return {}; 184 } 185 186 return {}; 187} 188 189}