FileSystemModel.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/HashMap.h>
  8. #include <AK/NonnullOwnPtrVector.h>
  9. #include <LibCore/DateTime.h>
  10. #include <LibCore/FileWatcher.h>
  11. #include <LibGUI/Model.h>
  12. #include <string.h>
  13. #include <sys/stat.h>
  14. #include <time.h>
  15. namespace GUI {
  16. class FileSystemModel
  17. : public Model
  18. , public Weakable<FileSystemModel> {
  19. friend struct Node;
  20. public:
  21. enum Mode {
  22. Invalid,
  23. DirectoriesOnly,
  24. FilesAndDirectories
  25. };
  26. enum Column {
  27. Icon = 0,
  28. Name,
  29. Size,
  30. Owner,
  31. Group,
  32. Permissions,
  33. ModificationTime,
  34. Inode,
  35. SymlinkTarget,
  36. __Count,
  37. };
  38. struct Node {
  39. ~Node() { }
  40. String name;
  41. String symlink_target;
  42. size_t size { 0 };
  43. mode_t mode { 0 };
  44. uid_t uid { 0 };
  45. gid_t gid { 0 };
  46. ino_t inode { 0 };
  47. time_t mtime { 0 };
  48. bool is_accessible_directory { false };
  49. size_t total_size { 0 };
  50. mutable RefPtr<Gfx::Bitmap> thumbnail;
  51. bool is_directory() const { return S_ISDIR(mode); }
  52. bool is_symlink_to_directory() const;
  53. bool is_executable() const { return mode & (S_IXUSR | S_IXGRP | S_IXOTH); }
  54. bool is_selected() const { return m_selected; }
  55. void set_selected(bool selected);
  56. bool has_error() const { return m_error != 0; }
  57. int error() const { return m_error; }
  58. const char* error_string() const { return strerror(m_error); }
  59. String full_path() const;
  60. private:
  61. friend class FileSystemModel;
  62. explicit Node(FileSystemModel& model)
  63. : m_model(model)
  64. {
  65. }
  66. FileSystemModel& m_model;
  67. Node* parent { nullptr };
  68. NonnullOwnPtrVector<Node> children;
  69. bool has_traversed { false };
  70. bool m_selected { false };
  71. int m_error { 0 };
  72. bool m_parent_of_root { false };
  73. ModelIndex index(int column) const;
  74. void traverse_if_needed();
  75. void reify_if_needed();
  76. bool fetch_data(const String& full_path, bool is_root);
  77. };
  78. static NonnullRefPtr<FileSystemModel> create(String root_path = "/", Mode mode = Mode::FilesAndDirectories)
  79. {
  80. return adopt_ref(*new FileSystemModel(root_path, mode));
  81. }
  82. virtual ~FileSystemModel() override;
  83. String root_path() const { return m_root_path; }
  84. void set_root_path(String);
  85. String full_path(const ModelIndex&) const;
  86. ModelIndex index(String path, int column) const;
  87. void update_node_on_selection(const ModelIndex&, const bool);
  88. ModelIndex m_previously_selected_index {};
  89. const Node& node(const ModelIndex& index) const;
  90. Function<void(int done, int total)> on_thumbnail_progress;
  91. Function<void()> on_complete;
  92. Function<void(int error, const char* error_string)> on_directory_change_error;
  93. Function<void(int error, const char* error_string)> on_rename_error;
  94. virtual int tree_column() const override { return Column::Name; }
  95. virtual int row_count(const ModelIndex& = ModelIndex()) const override;
  96. virtual int column_count(const ModelIndex& = ModelIndex()) const override;
  97. virtual String column_name(int column) const override;
  98. virtual Variant data(const ModelIndex&, ModelRole = ModelRole::Display) const override;
  99. virtual ModelIndex parent_index(const ModelIndex&) const override;
  100. virtual ModelIndex index(int row, int column = 0, const ModelIndex& parent = ModelIndex()) const override;
  101. virtual StringView drag_data_type() const override { return "text/uri-list"; }
  102. virtual bool accepts_drag(const ModelIndex&, const Vector<String>& mime_types) const override;
  103. virtual bool is_column_sortable(int column_index) const override { return column_index != Column::Icon; }
  104. virtual bool is_editable(const ModelIndex&) const override;
  105. virtual bool is_searchable() const override { return true; }
  106. virtual void set_data(const ModelIndex&, const Variant&) override;
  107. virtual Vector<ModelIndex, 1> matches(const StringView&, unsigned = MatchesFlag::AllMatching, const ModelIndex& = ModelIndex()) override;
  108. virtual void invalidate() override;
  109. static String timestamp_string(time_t timestamp)
  110. {
  111. return Core::DateTime::from_timestamp(timestamp).to_string();
  112. }
  113. bool should_show_dotfiles() const { return m_should_show_dotfiles; }
  114. void set_should_show_dotfiles(bool);
  115. private:
  116. FileSystemModel(String root_path, Mode);
  117. String name_for_uid(uid_t) const;
  118. String name_for_gid(gid_t) const;
  119. Node const* node_for_path(String const&) const;
  120. HashMap<uid_t, String> m_user_names;
  121. HashMap<gid_t, String> m_group_names;
  122. bool fetch_thumbnail_for(const Node& node);
  123. GUI::Icon icon_for(const Node& node) const;
  124. String m_root_path;
  125. Mode m_mode { Invalid };
  126. OwnPtr<Node> m_root { nullptr };
  127. unsigned m_thumbnail_progress { 0 };
  128. unsigned m_thumbnail_progress_total { 0 };
  129. bool m_should_show_dotfiles { false };
  130. RefPtr<Core::FileWatcher> m_file_watcher;
  131. };
  132. }