diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 7fddc3bb..1a447abf 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -359,7 +359,6 @@ namespace nana { namespace experimental { namespace filesystem bool create_directory(const path& p, const path& attributes); //bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept; - bool modified_file_time(const path& p, struct tm&); ///< extention ? /// The time of last data modification of p, determined as if by the value of the POSIX /// stat structure member st_mtime obtained as if by POSIX stat(). @@ -367,7 +366,6 @@ namespace nana { namespace experimental { namespace filesystem /// returns file_time_type::min() if an error occurs //file_time_type last_write_time(const path& p, error_code& ec) noexcept; - path path_user(); ///< extention ? path current_path(); //path current_path(error_code& ec); diff --git a/include/nana/filesystem/filesystem_ext.hpp b/include/nana/filesystem/filesystem_ext.hpp index 3711eb59..115c3dd1 100644 --- a/include/nana/filesystem/filesystem_ext.hpp +++ b/include/nana/filesystem/filesystem_ext.hpp @@ -34,15 +34,14 @@ namespace filesystem_ext constexpr auto def_rootstr = "/"; constexpr auto def_rootname = "Root/"; #endif - -// nana::experimental::filesystem::path_user()); + +std::experimental::filesystem::path path_user(); ///< extention ? inline bool is_directory(const std::experimental::filesystem::directory_entry& dir) noexcept { return is_directory(dir.status()); } - //template // DI = directory_iterator from std, boost, or nana : return directory_entry class directory_only_iterator : public std::experimental::filesystem::directory_iterator { @@ -84,7 +83,6 @@ inline directory_only_iterator end(const directory_only_iterator&) noexcept return{}; } - //template // DI = directory_iterator from std, boost, or nana : value_type directory_entry class regular_file_only_iterator : public std::experimental::filesystem::directory_iterator { @@ -121,60 +119,11 @@ inline regular_file_only_iterator end(const regular_file_only_iterator&) noexcep return{}; } -inline std::string pretty_file_size(const std::experimental::filesystem::path& path) // todo: move to .cpp -{ - try { - auto bytes = std::experimental::filesystem::file_size ( path ); - const char * ustr[] = { " KB", " MB", " GB", " TB" }; - std::stringstream ss; - if (bytes < 1024) - ss << bytes << " Bytes"; - else - { - double cap = bytes / 1024.0; - std::size_t uid = 0; - while ((cap >= 1024.0) && (uid < sizeof(ustr) / sizeof(char *))) - { - cap /= 1024.0; - ++uid; - } - ss << cap; - auto s = ss.str(); - auto pos = s.find('.'); - if (pos != s.npos) - { - if (pos + 2 < s.size()) - s.erase(pos + 2); - } - return s + ustr[uid]; - } +std::string pretty_file_size(const std::experimental::filesystem::path& path); - return ss.str(); - } - catch (...) {} - return {}; -} +std::string pretty_file_date(const std::experimental::filesystem::path& path); -inline std::string pretty_file_date(const std::experimental::filesystem::path& path) // todo: move to .cpp -{ - try { - auto ftime = std::experimental::filesystem::last_write_time(path); - - // crash: VS2015 will not read the time for some files (for example: C:/hiberfil.sys) - // and will return file_time_type(-1) without throwing - // https://msdn.microsoft.com/en-us/library/dn823784.aspx - - if (ftime == ((std::experimental::filesystem::file_time_type::min)())) return {}; - - std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime); - std::stringstream tm; - tm << std::put_time(std::localtime(&cftime), "%Y-%m-%d, %H:%M:%S"); - return tm.str(); - } - catch (...) { - return {}; - } -} +bool modified_file_time(const std::experimental::filesystem::path& p, struct tm&); ///< extention ? } // filesystem_ext } // nana diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index fec154d2..8a810f3a 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -12,7 +12,6 @@ */ #include -#if NANA_USING_NANA_FILESYSTEM #include #if defined(NANA_WINDOWS) #include @@ -37,6 +36,120 @@ #include #endif +namespace fs = std::experimental::filesystem; + +namespace nana +{ + namespace filesystem_ext + { + + fs::path path_user() + { +#if defined(NANA_WINDOWS) + wchar_t pstr[MAX_PATH]; + if (SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, pstr))) + return pstr; +#elif defined(NANA_LINUX) || defined(NANA_MACOS) + const char * pstr = ::getenv("HOME"); + if (pstr) + return pstr; +#endif + return fs::path(); + } + + std::string pretty_file_size(const fs::path& path) + { + try { + auto bytes = fs::file_size(path); + const char * ustr[] = { " KB", " MB", " GB", " TB" }; + std::stringstream ss; + if (bytes < 1024) + ss << bytes << " Bytes"; + else + { + double cap = bytes / 1024.0; + std::size_t uid = 0; + while ((cap >= 1024.0) && (uid < sizeof(ustr) / sizeof(char *))) + { + cap /= 1024.0; + ++uid; + } + ss << cap; + auto s = ss.str(); + auto pos = s.find('.'); + if (pos != s.npos) + { + if (pos + 2 < s.size()) + s.erase(pos + 2); + } + return s + ustr[uid]; + } + + return ss.str(); + } + catch (...) {} + return{}; + } + + std::string pretty_file_date(const fs::path& path) // todo: move to .cpp + { + try { + auto ftime = fs::last_write_time(path); + + // crash: VS2015 will not read the time for some files (for example: C:/hiberfil.sys) + // and will return file_time_type(-1) without throwing + // https://msdn.microsoft.com/en-us/library/dn823784.aspx + + if (ftime == ((fs::file_time_type::min)())) return{}; + + std::time_t cftime = decltype(ftime)::clock::to_time_t(ftime); + std::stringstream tm; + tm << std::put_time(std::localtime(&cftime), "%Y-%m-%d, %H:%M:%S"); + return tm.str(); + } + catch (...) { + return{}; + } + } + + bool modified_file_time(const fs::path& p, struct tm& t) + { +#if defined(NANA_WINDOWS) + WIN32_FILE_ATTRIBUTE_DATA attr; + if (::GetFileAttributesEx(p.c_str(), GetFileExInfoStandard, &attr)) + { + FILETIME local_file_time; + if (::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time)) + { + SYSTEMTIME st; + ::FileTimeToSystemTime(&local_file_time, &st); + t.tm_year = st.wYear - 1900; + t.tm_mon = st.wMonth - 1; + t.tm_mday = st.wDay; + t.tm_wday = st.wDayOfWeek - 1; + t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay); + + t.tm_hour = st.wHour; + t.tm_min = st.wMinute; + t.tm_sec = st.wSecond; + return true; + } + } +#elif defined(NANA_POSIX) + struct stat attr; + if (0 == ::stat(p.c_str(), &attr)) + { + t = *(::localtime(&attr.st_ctime)); + return true; + } +#endif + return false; + } + } +} + +#if NANA_USING_NANA_FILESYSTEM + namespace nana_fs = nana::experimental::filesystem; namespace nana { namespace experimental { namespace filesystem @@ -753,44 +866,11 @@ namespace nana { namespace experimental { namespace filesystem #endif } - bool modified_file_time(const path& p, struct tm& t) - { -#if defined(NANA_WINDOWS) - WIN32_FILE_ATTRIBUTE_DATA attr; - if (::GetFileAttributesEx(p.c_str(), GetFileExInfoStandard, &attr)) - { - FILETIME local_file_time; - if (::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time)) - { - SYSTEMTIME st; - ::FileTimeToSystemTime(&local_file_time, &st); - t.tm_year = st.wYear - 1900; - t.tm_mon = st.wMonth - 1; - t.tm_mday = st.wDay; - t.tm_wday = st.wDayOfWeek - 1; - t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay); - - t.tm_hour = st.wHour; - t.tm_min = st.wMinute; - t.tm_sec = st.wSecond; - return true; - } - } -#elif defined(NANA_POSIX) - struct stat attr; - if (0 == ::stat(p.c_str(), &attr)) - { - t = *(::localtime(&attr.st_ctime)); - return true; - } -#endif - return false; - } file_time_type last_write_time(const path& p) { struct tm t; - modified_file_time(p, t); + nana::filesystem_ext::modified_file_time(p, t); std::chrono::system_clock::time_point dateTime =std::chrono::system_clock::from_time_t( mktime(&t) ); return dateTime; } @@ -823,20 +903,6 @@ namespace nana { namespace experimental { namespace filesystem return detail::rm_file(p); } - path path_user() - { -#if defined(NANA_WINDOWS) - wchar_t pstr[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, pstr))) - return pstr; -#elif defined(NANA_LINUX) || defined(NANA_MACOS) - const char * pstr = ::getenv("HOME"); - if (pstr) - return pstr; -#endif - return path(); - } - path current_path() { #if defined(NANA_WINDOWS) diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index 2644d910..c18c7a83 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -30,6 +30,8 @@ #endif namespace fs = std::experimental::filesystem; +namespace fs_ext = nana::filesystem_ext; + namespace nana { @@ -55,7 +57,7 @@ namespace nana friend listbox::oresolver& operator<<(listbox::oresolver& ores, const item_fs& item) { std::wstringstream tm; - tm<<(item.modified_time.tm_year + 1900)<<'-'; + tm<<(item.modified_time.tm_year + 1900)<<'-'; /// \todo : use nana::filesystem_ext:: pretty_file_date _m_add(tm, item.modified_time.tm_mon + 1)<<'-'; _m_add(tm, item.modified_time.tm_mday)<<' '; @@ -88,7 +90,7 @@ namespace nana return ss; } - static std::string _m_trans(std::size_t bytes) + static std::string _m_trans(std::size_t bytes) /// \todo : use nana::filesystem_ext::pretty_file_size { const char * ustr[] = {" KB", " MB", " GB", " TB"}; std::stringstream ss; @@ -143,13 +145,13 @@ namespace nana auto path = path_.caption(); auto root = path.substr(0, path.find('/')); if(root == "HOME") - path.replace(0, 4, fs::path_user().native()); + path.replace(0, 4, fs_ext::path_user().native()); else if(root == "FILESYSTEM") path.erase(0, 10); else throw std::runtime_error("Nana.GUI.Filebox: Wrong categorize path"); - if(path.size() == 0) path = "/"; + if(path.size() == 0) path = "/"; /// \todo : use nana::filesystem_ext::def_rootstr? _m_load_cat_path(path); }); @@ -345,7 +347,7 @@ namespace nana else dir = saved_selected_path; - _m_load_cat_path(dir.size() ? dir : fs::path_user().native()); + _m_load_cat_path(dir.size() ? dir : fs_ext::path_user().native()); tb_file_.caption(file_with_path_removed); } @@ -429,7 +431,7 @@ namespace nana nodes_.filesystem.value(kind::filesystem); std::vector paths; - paths.emplace_back(fs::path_user().native()); + paths.emplace_back(fs_ext::path_user().native()); paths.emplace_back("/"); fs::directory_iterator end; @@ -473,7 +475,7 @@ namespace nana { auto begstr = path.substr(0, pos); if(begstr == "FS.HOME") - path.replace(0, 7, fs::path_user().native()); + path.replace(0, 7, fs_ext::path_user().native()); else path.erase(0, pos); return begstr; @@ -505,13 +507,13 @@ namespace nana { m.bytes = fs::file_size(path + m.name); m.directory = fs::is_directory(fattr); - fs::modified_file_time(path + m.name, m.modified_time); + fs_ext::modified_file_time(path + m.name, m.modified_time); } else { m.bytes = 0; m.directory = fs::is_directory(*i); - fs::modified_file_time(path + i->path().filename().native(), m.modified_time); + fs_ext::modified_file_time(path + i->path().filename().native(), m.modified_time); } file_container_.push_back(m); @@ -531,7 +533,7 @@ namespace nana while(!beg_node.empty() && (beg_node != nodes_.home) && (beg_node != nodes_.filesystem)) beg_node = beg_node.owner(); - auto head = fs::path_user().native(); + auto head = fs_ext::path_user().native(); if(path.size() >= head.size() && (path.substr(0, head.size()) == head)) {//This is HOME path_.caption("HOME");