#ifndef MODORGANIZER_FILETREEITEM_INCLUDED #define MODORGANIZER_FILETREEITEM_INCLUDED #include "shared/fileregisterfwd.h" #include class FileTreeModel; class FileTreeItem { class Sorter; public: using Ptr = std::unique_ptr; using Children = std::vector; enum Flag { NoFlags = 0x00, FromArchive = 0x01, Conflicted = 0x02 }; Q_DECLARE_FLAGS(Flags, Flag); static Ptr createFile(FileTreeModel* model, FileTreeItem* parent, std::wstring dataRelativeParentPath, std::wstring file); static Ptr createDirectory(FileTreeModel* model, FileTreeItem* parent, std::wstring dataRelativeParentPath, std::wstring file); FileTreeItem(const FileTreeItem&) = delete; FileTreeItem& operator=(const FileTreeItem&) = delete; FileTreeItem(FileTreeItem&&) = default; FileTreeItem& operator=(FileTreeItem&&) = default; void setOrigin(int originID, const std::wstring& realPath, Flags flags, const std::wstring& mod); void add(Ptr child) { child->m_indexGuess = m_children.size(); m_children.push_back(std::move(child)); } void insert(Ptr child, std::size_t at); template void insert(Itor begin, Itor end, std::size_t at) { std::size_t nextRowGuess = m_children.size(); for (auto itor = begin; itor != end; ++itor) { (*itor)->m_indexGuess = nextRowGuess++; } m_children.insert(m_children.begin() + at, begin, end); } void remove(std::size_t i); void remove(std::size_t from, std::size_t n); void clear() { m_children.clear(); m_loaded = false; } const Children& children() const { return m_children; } int childIndex(const FileTreeItem& item) const { if (item.m_indexGuess < m_children.size()) { if (m_children[item.m_indexGuess].get() == &item) { return static_cast(item.m_indexGuess); } } for (std::size_t i = 0; i < m_children.size(); ++i) { if (m_children[i].get() == &item) { item.m_indexGuess = i; return static_cast(i); } } return -1; } void sort(int column, Qt::SortOrder order, bool force); void makeSortingStale(); FileTreeItem* parent() { return m_parent; } int originID() const { return m_originID; } const QString& virtualParentPath() const { return m_virtualParentPath; } QString virtualPath() const; const QString& filename() const { return m_file; } const std::wstring& filenameWs() const { return m_wsFile; } const std::wstring& filenameWsLowerCase() const { return m_wsLcFile; } const MOShared::DirectoryEntryFileKey& key() const { return m_key; } const QString& mod() const { return m_mod; } QFont font() const; std::optional fileSize() const; std::optional lastModified() const; std::optional fileType() const; std::optional compressedFileSize() const { return m_compressedFileSize.value; } void setFileSize(uint64_t size) { m_fileSize.override(size); } void setCompressedFileSize(uint64_t compressedSize) { m_compressedFileSize.override(compressedSize); } const QString& realPath() const { return m_realPath; } const QString& dataRelativeParentPath() const { return m_virtualParentPath; } QString dataRelativeFilePath() const; QFileIconProvider::IconType icon() const; bool isDirectory() const { return m_isDirectory; } bool isFromArchive() const { return (m_flags & FromArchive); } bool isConflicted() const { return (m_flags & Conflicted); } bool isHidden() const; bool hasChildren() const { if (!isDirectory()) { return false; } if (isLoaded() && m_children.empty()) { return false; } return true; } void setLoaded(bool b) { m_loaded = b; } bool isLoaded() const { return m_loaded; } void unload(); void setExpanded(bool b) { if (m_expanded == b) { return; } m_expanded = b; if (m_expanded && m_sortingStale) { queueSort(); } } bool isStrictlyExpanded() const { return m_expanded; } bool areChildrenVisible() const; QString debugName() const; private: template struct Cached { std::optional value; bool failed = false; bool overridden = false; bool empty() const { return !failed && !value; } void set(T t) { value = std::move(t); failed = false; overridden = false; } void override(T t) { value = std::move(t); failed = false; overridden = true; } void fail() { value = {}; failed = true; overridden = false; } void reset() { if (!overridden) { value = {}; failed = false; } } }; static constexpr std::size_t NoIndexGuess = std::numeric_limits::max(); FileTreeModel* m_model; FileTreeItem* m_parent; mutable std::size_t m_indexGuess; const QString m_virtualParentPath; const std::wstring m_wsFile, m_wsLcFile; const MOShared::DirectoryEntryFileKey m_key; const QString m_file; const bool m_isDirectory; int m_originID; QString m_realPath; std::wstring m_wsRealPath; Flags m_flags; QString m_mod; mutable Cached m_fileSize; mutable Cached m_lastModified; mutable Cached m_fileType; mutable Cached m_compressedFileSize; bool m_loaded; bool m_expanded; bool m_sortingStale; Children m_children; FileTreeItem(FileTreeModel* model, FileTreeItem* parent, std::wstring dataRelativeParentPath, bool isDirectory, std::wstring file); void getFileType() const; void queueSort(); }; #endif // MODORGANIZER_FILETREEITEM_INCLUDED