Serenity Operating System
at master 181 lines 6.0 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, the SerenityOS developers. 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <AK/HashMap.h> 11#include <LibCore/DateTime.h> 12#include <LibCore/FileWatcher.h> 13#include <LibGUI/Model.h> 14#include <string.h> 15#include <sys/stat.h> 16#include <time.h> 17 18namespace GUI { 19 20class FileSystemModel 21 : public Model 22 , public Weakable<FileSystemModel> { 23 friend struct Node; 24 25public: 26 enum Mode { 27 Invalid, 28 DirectoriesOnly, 29 FilesAndDirectories 30 }; 31 32 enum Column { 33 Icon = 0, 34 Name, 35 Size, 36 User, 37 Group, 38 Permissions, 39 ModificationTime, 40 Inode, 41 SymlinkTarget, 42 __Count, 43 }; 44 45 struct Node { 46 ~Node() = default; 47 48 DeprecatedString name; 49 DeprecatedString symlink_target; 50 size_t size { 0 }; 51 mode_t mode { 0 }; 52 uid_t uid { 0 }; 53 gid_t gid { 0 }; 54 ino_t inode { 0 }; 55 time_t mtime { 0 }; 56 bool is_accessible_directory { false }; 57 58 size_t total_size { 0 }; 59 60 mutable RefPtr<Gfx::Bitmap> thumbnail; 61 bool is_directory() const { return S_ISDIR(mode); } 62 bool is_symlink_to_directory() const; 63 bool is_executable() const { return mode & (S_IXUSR | S_IXGRP | S_IXOTH); } 64 65 bool is_selected() const { return m_selected; } 66 void set_selected(bool selected); 67 68 bool has_error() const { return m_error != 0; } 69 int error() const { return m_error; } 70 char const* error_string() const { return strerror(m_error); } 71 72 DeprecatedString full_path() const; 73 74 private: 75 friend class FileSystemModel; 76 77 explicit Node(FileSystemModel& model) 78 : m_model(model) 79 { 80 } 81 82 FileSystemModel& m_model; 83 84 Node* m_parent { nullptr }; 85 Vector<NonnullOwnPtr<Node>> m_children; 86 bool m_has_traversed { false }; 87 88 bool m_selected { false }; 89 90 int m_error { 0 }; 91 bool m_parent_of_root { false }; 92 93 ModelIndex index(int column) const; 94 void traverse_if_needed(); 95 void reify_if_needed(); 96 bool fetch_data(DeprecatedString const& full_path, bool is_root); 97 98 OwnPtr<Node> create_child(DeprecatedString const& child_name); 99 }; 100 101 static NonnullRefPtr<FileSystemModel> create(DeprecatedString root_path = "/", Mode mode = Mode::FilesAndDirectories) 102 { 103 return adopt_ref(*new FileSystemModel(root_path, mode)); 104 } 105 virtual ~FileSystemModel() override = default; 106 107 DeprecatedString root_path() const { return m_root_path; } 108 void set_root_path(DeprecatedString); 109 DeprecatedString full_path(ModelIndex const&) const; 110 ModelIndex index(DeprecatedString path, int column) const; 111 112 void update_node_on_selection(ModelIndex const&, bool const); 113 ModelIndex m_previously_selected_index {}; 114 115 Node const& node(ModelIndex const& index) const; 116 117 Function<void(int done, int total)> on_thumbnail_progress; 118 Function<void()> on_complete; 119 Function<void(int error, char const* error_string)> on_directory_change_error; 120 Function<void(int error, char const* error_string)> on_rename_error; 121 Function<void(DeprecatedString const& old_name, DeprecatedString const& new_name)> on_rename_successful; 122 Function<void()> on_root_path_removed; 123 124 virtual int tree_column() const override { return Column::Name; } 125 virtual int row_count(ModelIndex const& = ModelIndex()) const override; 126 virtual int column_count(ModelIndex const& = ModelIndex()) const override; 127 virtual DeprecatedString column_name(int column) const override; 128 virtual Variant data(ModelIndex const&, ModelRole = ModelRole::Display) const override; 129 virtual ModelIndex parent_index(ModelIndex const&) const override; 130 virtual ModelIndex index(int row, int column = 0, ModelIndex const& parent = ModelIndex()) const override; 131 virtual StringView drag_data_type() const override { return "text/uri-list"sv; } 132 virtual bool accepts_drag(ModelIndex const&, Vector<DeprecatedString> const& mime_types) const override; 133 virtual bool is_column_sortable(int column_index) const override { return column_index != Column::Icon; } 134 virtual bool is_editable(ModelIndex const&) const override; 135 virtual bool is_searchable() const override { return true; } 136 virtual void set_data(ModelIndex const&, Variant const&) override; 137 virtual Vector<ModelIndex> matches(StringView, unsigned = MatchesFlag::AllMatching, ModelIndex const& = ModelIndex()) override; 138 virtual void invalidate() override; 139 140 static DeprecatedString timestamp_string(time_t timestamp) 141 { 142 return Core::DateTime::from_timestamp(timestamp).to_deprecated_string(); 143 } 144 145 bool should_show_dotfiles() const { return m_should_show_dotfiles; } 146 void set_should_show_dotfiles(bool); 147 148 Optional<Vector<DeprecatedString>> allowed_file_extensions() const { return m_allowed_file_extensions; } 149 void set_allowed_file_extensions(Optional<Vector<DeprecatedString>> const& allowed_file_extensions); 150 151private: 152 FileSystemModel(DeprecatedString root_path, Mode); 153 154 DeprecatedString name_for_uid(uid_t) const; 155 DeprecatedString name_for_gid(gid_t) const; 156 157 Optional<Node const&> node_for_path(DeprecatedString const&) const; 158 159 HashMap<uid_t, DeprecatedString> m_user_names; 160 HashMap<gid_t, DeprecatedString> m_group_names; 161 162 bool fetch_thumbnail_for(Node const& node); 163 GUI::Icon icon_for(Node const& node) const; 164 165 void handle_file_event(Core::FileWatcherEvent const& event); 166 167 DeprecatedString m_root_path; 168 Mode m_mode { Invalid }; 169 OwnPtr<Node> m_root { nullptr }; 170 171 unsigned m_thumbnail_progress { 0 }; 172 unsigned m_thumbnail_progress_total { 0 }; 173 174 Optional<Vector<DeprecatedString>> m_allowed_file_extensions; 175 176 bool m_should_show_dotfiles { false }; 177 178 RefPtr<Core::FileWatcher> m_file_watcher; 179}; 180 181}