#include "../../plugins/FileManager.hpp" #include "../../include/FileAnalyzer.hpp" #include "../../include/QuickMedia.hpp" namespace QuickMedia { // Returns empty string if no extension static const char* get_ext(const std::filesystem::path &path) { const char *path_c = path.c_str(); int len = strlen(path_c); for(int i = len - 1; i >= 0; --i) { if(path_c[i] == '.') return path_c + i; } return ""; } static std::filesystem::file_time_type file_get_last_modified_time(const std::filesystem::directory_entry &path, std::filesystem::file_time_type default_value) { std::error_code err; auto last_write_time = path.last_write_time(err); if(err) return default_value; else return last_write_time; } PluginResult FileManagerPage::submit(const std::string &title, const std::string &url, std::vector &result_tabs) { (void)url; std::filesystem::path new_path; if(title == "..") new_path = current_dir.parent_path(); else new_path = current_dir / title; if(std::filesystem::is_regular_file(new_path)) { program->select_file(new_path); if(selection_handler) result_tabs = selection_handler(this, new_path); return PluginResult::OK; } if(!std::filesystem::is_directory(new_path)) return PluginResult::ERR; current_dir = std::move(new_path); BodyItems result_items; PluginResult result = get_files_in_directory(result_items); if(result != PluginResult::OK) return result; auto body = create_body(); body->items = std::move(result_items); result_tabs.push_back(Tab{std::move(body), nullptr, nullptr}); return PluginResult::OK; } bool FileManagerPage::set_current_directory(const std::string &path) { if(!std::filesystem::is_directory(path)) return false; current_dir = path; return true; } PluginResult FileManagerPage::get_files_in_directory(BodyItems &result_items) { std::vector paths; try { for(auto &p : std::filesystem::directory_iterator(current_dir)) { paths.push_back(p); } } catch(const std::filesystem::filesystem_error &err) { fprintf(stderr, "Failed to list files in directory %s, error: %s\n", current_dir.c_str(), err.what()); return PluginResult::ERR; } std::sort(paths.begin(), paths.end(), [](const std::filesystem::directory_entry &path1, std::filesystem::directory_entry &path2) { return file_get_last_modified_time(path1, std::filesystem::file_time_type::min()) > file_get_last_modified_time(path2, std::filesystem::file_time_type::min()); }); if(current_dir != "/") { auto parent_item = BodyItem::create(".."); result_items.push_back(std::move(parent_item)); } char time_str[128] = {0}; for(auto &p : paths) { std::error_code regular_file_err; bool is_regular_file = p.is_regular_file(regular_file_err); if(regular_file_err) is_regular_file = true; // TODO: Check file magic number instead of extension? const char *ext = get_ext(p.path()); FileManagerMimeType file_mime_type = FILE_MANAGER_MIME_TYPE_OTHER; if(is_regular_file) { if(is_image_ext(ext)) file_mime_type = FILE_MANAGER_MIME_TYPE_IMAGE; else if(is_video_ext(ext)) file_mime_type = FILE_MANAGER_MIME_TYPE_VIDEO; } if(is_regular_file && !(mime_type & file_mime_type)) continue; auto body_item = BodyItem::create(p.path().filename().string()); if(file_mime_type == FILE_MANAGER_MIME_TYPE_IMAGE || file_mime_type == FILE_MANAGER_MIME_TYPE_VIDEO) { body_item->thumbnail_is_local = true; body_item->thumbnail_url = p.path().string(); } time_t last_modified_time = std::chrono::duration_cast(file_get_last_modified_time(p, std::filesystem::file_time_type::min()).time_since_epoch()).count(); struct tm last_modified_tm; localtime_r(&last_modified_time, &last_modified_tm); strftime(time_str, sizeof(time_str) - 1, "%a %b %d %H:%M", &last_modified_tm); std::error_code file_size_err; size_t file_size = p.file_size(file_size_err); if(file_size_err) file_size = 0; std::string description = "Modified: "; description += time_str; if(is_regular_file) { description += "\n"; description += "Size: " + file_size_to_human_readable_string(file_size); } body_item->set_description(std::move(description)); body_item->set_description_color(sf::Color(179, 179, 179)); result_items.push_back(std::move(body_item)); } return PluginResult::OK; } }