#include "file_dialog.hpp" #include "imgui_context.hpp" #include #include namespace bookmouse { using fud::FudStatus; DialogEntry::DialogEntry(fud::DirectoryEntry&& entry) : fud::DirectoryEntry(std::move(entry)), timeInfo{}, niceTime{}, selected{false}, valid{false}, gotTime{false} { auto timeInfoPtr = localtime_r(&this->modificationTime, &timeInfo); if (timeInfoPtr == nullptr) { return; } valid = true; } FudStatus DialogEntry::formatTime(TimeFormat& format) { if (!valid) { return FudStatus::ObjectInvalid; } auto result = format.format(this->timeInfo); if (result.isError()) { return result.getError(); } this->niceTime = result.getOkay(); return FudStatus::Success; } FileDialog::FileDialog(const fud::String& directoryName, TimeFormat& timeFormat) : m_directoryName{directoryName}, m_directory{directoryName}, m_timeFormat{timeFormat} { auto status = getDirectoryContents(); if (status != FudStatus::Success) { return; } m_valid = true; } FudStatus FileDialog::getDirectoryContents() { auto directoryStatsResult = m_directory.info(); if (directoryStatsResult.isError()) { return directoryStatsResult.getError(); } auto directoryStats = directoryStatsResult.getOkay(); m_directoryContents.clear(); size_t count{0}; m_directoryContents.reserve(directoryStats.links); while (true && count < SIZE_MAX) { auto dirEntryResult = m_directory.getNextEntry(); if (dirEntryResult.isError()) { break; } auto dirEntryOpt = dirEntryResult.getOkay(); if (dirEntryOpt == std::nullopt) { break; } if (dirEntryOpt->inode == directoryStats.inode) { continue; } m_directoryContents.emplace_back(std::move(*dirEntryOpt)); auto status = m_directoryContents.back().formatTime(m_timeFormat); if (status != FudStatus::Success) { spdlog::error("Could not convert time: {}", fud::FudStatusToString(status)); } } return FudStatus::Success; } FilePickerResult FileDialog::pickFiles() { ImText("%s %zu", m_directory.name().c_str(), m_directoryContents.size()); size_t selected{0}; if (ImTable table{"Entries", 4, ImGuiTableFlags_Borders}) { auto colFlags = ImGuiSelectableFlags_NoAutoClosePopups; IM_ASSERT(table); ImNextColumn(); ImSelectable("T", &m_typeSelected, colFlags); ImNextColumn(); ImSelectable("Name", &m_nameSelectede, colFlags); ImNextColumn(); ImSelectable("Size", &m_sizeSelected, colFlags); ImNextColumn(); ImSelectable("Date", &m_dateSelected, colFlags); for (auto& entry : m_directoryContents) { ImNextRow(); const char entryLetter = DirEntryTypeToChar(entry.entryType); ImNextColumn(); ImText("%c", entryLetter); ImNextColumn(); ImSelectable(entry.name.c_str(), &entry.selected, colFlags | ImGuiSelectableFlags_SpanAllColumns); ImNextColumn(); ImText("%zu\n", entry.isDirectory() ? entry.links : entry.size); ImNextColumn(); ImText("%s", entry.niceTime.c_str()); if (entry.selected && entry.isDirectory()) { selected++; } } } if (selected == 0) { ImGui::BeginDisabled(); } if (ImButton("Accept")) { std::vector files{}; files.reserve(selected); for (const auto& entry: m_directoryContents) { if (!entry.selected) { continue; } if (entry.isDirectory()) { spdlog::info("Skipping directory {}", entry.name.c_str()); continue; } files.emplace_back(m_directory.name().catenate(entry.name)); } return files; } if (selected == 0) { ImGui::EndDisabled(); } ImSameLine(); if (ImButton("Cancel")) { m_canceled = true; return std::nullopt; } return std::nullopt; } } // namespace bookmouse