From ece696c3b5267971979dc26343c5bd508a89c9a1 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 20 Jan 2016 01:06:16 +0800 Subject: [PATCH] update filesystem and remove fs_utility --- build/codeblocks/nana.cbp | 1 - build/codeblocks/nana.depend | 27 +- build/vc2013/nana.vcxproj | 2 - build/vc2013/nana.vcxproj.filters | 6 - build/vc2015/nana.vcxproj | 1 - build/vc2015/nana.vcxproj.filters | 3 - include/nana/filesystem/filesystem.hpp | 11 +- include/nana/filesystem/fs_utility.hpp | 35 -- include/nana/gui/detail/general_events.hpp | 32 +- include/nana/gui/widgets/checkbox.hpp | 25 +- .../paint/detail/image_impl_interface.hpp | 1 + include/nana/paint/image.hpp | 16 +- source/filesystem/filesystem.cpp | 337 ++++++++++-------- source/filesystem/fs_utility.cpp | 145 -------- source/gui/filebox.cpp | 1 - source/gui/widgets/checkbox.cpp | 70 +++- source/paint/detail/image_ico.hpp | 1 + source/paint/image.cpp | 161 +++++---- 18 files changed, 403 insertions(+), 472 deletions(-) delete mode 100644 include/nana/filesystem/fs_utility.hpp delete mode 100644 source/filesystem/fs_utility.cpp diff --git a/build/codeblocks/nana.cbp b/build/codeblocks/nana.cbp index b5d4b09b..18e276ca 100644 --- a/build/codeblocks/nana.cbp +++ b/build/codeblocks/nana.cbp @@ -52,7 +52,6 @@ - diff --git a/build/codeblocks/nana.depend b/build/codeblocks/nana.depend index 765af40b..8d95a36f 100644 --- a/build/codeblocks/nana.depend +++ b/build/codeblocks/nana.depend @@ -745,8 +745,8 @@ 1447167067 source:d:\git.repo\nana\source\gui\detail\events_operation.cpp -1444647213 source:d:\git.repo\nana\source\gui\detail\native_window_interface.cpp - +1453137865 source:d:\git.repo\nana\source\gui\detail\native_window_interface.cpp + @@ -755,9 +755,11 @@ "../../paint/detail/image_ico.hpp" + -1452100459 d:\git.repo\nana\source\paint\detail\image_ico.hpp +1453189013 d:\git.repo\nana\source\paint\detail\image_ico.hpp + 1451801884 source:d:\git.repo\nana\source\gui\detail\window_layout.cpp @@ -802,10 +804,9 @@ -1453128893 source:d:\git.repo\nana\source\gui\filebox.cpp +1453222083 source:d:\git.repo\nana\source\gui\filebox.cpp - @@ -909,7 +910,7 @@ -1452100459 source:d:\git.repo\nana\source\gui\widgets\checkbox.cpp +1453214888 source:d:\git.repo\nana\source\gui\widgets\checkbox.cpp @@ -1319,9 +1320,8 @@ "../basic_types.hpp" "../traits.hpp" -1453125056 d:\git.repo\nana\include\nana\paint\image.hpp +1453215024 d:\git.repo\nana\include\nana\paint\image.hpp "graphics.hpp" - 1452100458 d:\git.repo\nana\include\nana\paint\graphics.hpp "../basic_types.hpp" @@ -1333,7 +1333,7 @@ -1453129811 d:\git.repo\nana\include\nana\filesystem\filesystem.hpp +1453221913 d:\git.repo\nana\include\nana\filesystem\filesystem.hpp @@ -1391,7 +1391,7 @@ "color_schemes.hpp" "internal_scope_guard.hpp" -1452100458 d:\git.repo\nana\include\nana\gui\detail\general_events.hpp +1453221339 d:\git.repo\nana\include\nana\gui\detail\general_events.hpp "event_code.hpp" "internal_scope_guard.hpp" @@ -1615,7 +1615,7 @@ -1453130060 source:d:\git.repo\nana\source\filesystem\filesystem.cpp +1453221942 source:d:\git.repo\nana\source\filesystem\filesystem.cpp @@ -1753,7 +1753,7 @@ 1452100757 d:\git.repo\nana\include\nana\gui\tooltip.hpp "widgets/widget.hpp" -1452100458 d:\git.repo\nana\include\nana\gui\widgets\checkbox.hpp +1453214821 d:\git.repo\nana\include\nana\gui\widgets\checkbox.hpp "widget.hpp" @@ -1843,8 +1843,9 @@ 1452100458 d:\git.repo\nana\include\nana\paint\detail\native_paint_interface.hpp -1452100458 d:\git.repo\nana\include\nana\paint\detail\image_impl_interface.hpp +1453189097 d:\git.repo\nana\include\nana\paint\detail\image_impl_interface.hpp "../image.hpp" + 1447167068 d:\git.repo\nana\source\paint\detail\image_jpeg.hpp "image_pixbuf.hpp" diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj index 2771c133..c52001e4 100644 --- a/build/vc2013/nana.vcxproj +++ b/build/vc2013/nana.vcxproj @@ -189,7 +189,6 @@ - @@ -274,7 +273,6 @@ - diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters index 14265033..dd9f87a2 100644 --- a/build/vc2013/nana.vcxproj.filters +++ b/build/vc2013/nana.vcxproj.filters @@ -111,9 +111,6 @@ Source Files\nana\filesystem - - Source Files\nana\filesystem - Source Files\nana\gui\detail @@ -613,9 +610,6 @@ Header Files\filesystem - - Header Files\filesystem - Header Files\paint diff --git a/build/vc2015/nana.vcxproj b/build/vc2015/nana.vcxproj index 100336ef..e9c0aa02 100644 --- a/build/vc2015/nana.vcxproj +++ b/build/vc2015/nana.vcxproj @@ -183,7 +183,6 @@ - diff --git a/build/vc2015/nana.vcxproj.filters b/build/vc2015/nana.vcxproj.filters index 2ab6736a..0f547b4e 100644 --- a/build/vc2015/nana.vcxproj.filters +++ b/build/vc2015/nana.vcxproj.filters @@ -87,9 +87,6 @@ Source Files\filesystem - - Source Files\filesystem - Source Files\gui\detail diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index f157aadd..c60976dc 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -282,6 +282,7 @@ namespace filesystem file_status status(const path& p); + file_status status(const path& p, std::error_code&); std::uintmax_t file_size(const path& p); //uintmax_t file_size(const path& p, error_code& ec) noexcept; @@ -315,7 +316,8 @@ 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 std::wstring& file, struct tm&); + bool modified_file_time(const path& p, struct tm&); + path path_user(); path current_path(); @@ -324,14 +326,13 @@ namespace filesystem //void current_path(const path& p, error_code& ec) noexcept; - //bool remove(const path& p); - //bool remove(const path& p, error_code& ec) noexcept; - bool rmfile(const path& p); + bool remove(const path& p); + bool remove(const path& p, std::error_code& ec); // noexcept; //uintmax_t remove_all(const path& p); //uintmax_t remove_all(const path& p, error_code& ec) noexcept; - bool rmdir(const path& p, bool fails_if_not_empty); + //bool rmdir(const path& p, bool fails_if_not_empty); //deprecated template std::basic_string parent_path(const std::basic_string& path) diff --git a/include/nana/filesystem/fs_utility.hpp b/include/nana/filesystem/fs_utility.hpp deleted file mode 100644 index 923be5ce..00000000 --- a/include/nana/filesystem/fs_utility.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef NANA_FILESYSTEM_FS_UTILITY_HPP -#define NANA_FILESYSTEM_FS_UTILITY_HPP - -#include -#include - -namespace nana -{ -namespace filesystem -{ - struct error - { - enum - { - none = 0 - }; - }; - - struct attribute - { - long long bytes; - bool is_directory; - tm modified; - }; - - bool modified_file_time(const ::std::string& file, struct tm&); - - std::string path_user(); - - bool rmfile(const char* file_utf8); -}//end namespace filesystem -}//end namespace nana - -#endif diff --git a/include/nana/gui/detail/general_events.hpp b/include/nana/gui/detail/general_events.hpp index 8437f84d..8d75dc9e 100644 --- a/include/nana/gui/detail/general_events.hpp +++ b/include/nana/gui/detail/general_events.hpp @@ -1,7 +1,7 @@ /** * Definition of General Events * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -111,7 +111,7 @@ namespace nana evt_->deleted_flags_ = false; for (auto i = evt_->dockers_->begin(); i != evt_->dockers_->end();) { - if (i->get()->flag_deleted) + if (static_cast(i->get())->flag_deleted) i = evt_->dockers_->erase(i); else ++i; @@ -128,11 +128,11 @@ namespace nana { internal_scope_guard lock; if (nullptr == dockers_) - dockers_.reset(new std::vector>); + dockers_.reset(new std::vector>); using prototype = typename std::remove_reference::type; - std::unique_ptr dck(new docker(this, factory::value>::build(std::forward(fn)), false)); - auto evt = reinterpret_cast(static_cast(dck.get())); + std::unique_ptr dck(new docker(this, factory::value>::build(std::forward(fn)), false)); + auto evt = reinterpret_cast(dck.get()); dockers_->emplace(dockers_->begin(), std::move(dck)); detail::events_operation_register(evt); return evt; @@ -151,11 +151,11 @@ namespace nana { internal_scope_guard lock; if (nullptr == dockers_) - dockers_.reset(new std::vector>); + dockers_.reset(new std::vector>); using prototype = typename std::remove_reference::type; - std::unique_ptr dck(new docker(this, factory::value>::build(std::forward(fn)), false)); - auto evt = reinterpret_cast(static_cast(dck.get())); + std::unique_ptr dck(new docker(this, factory::value>::build(std::forward(fn)), false)); + auto evt = reinterpret_cast(dck.get()); dockers_->emplace_back(std::move(dck)); detail::events_operation_register(evt); return evt; @@ -174,11 +174,11 @@ namespace nana { internal_scope_guard lock; if (nullptr == dockers_) - dockers_.reset(new std::vector>); + dockers_.reset(new std::vector>); using prototype = typename std::remove_reference::type; - std::unique_ptr dck(new docker(this, factory::value>::build(std::forward(fn)), true)); - auto evt = reinterpret_cast(static_cast(dck.get())); + std::unique_ptr dck(new docker(this, factory::value>::build(std::forward(fn)), true)); + auto evt = reinterpret_cast(dck.get()); if (in_front) dockers_->emplace(dockers_->begin(), std::move(dck)); else @@ -208,7 +208,7 @@ namespace nana //Traverses with position can avaid crash error which caused by a iterator which becomes invalid. for (std::size_t pos = 0; pos < dockers_len; ++pos) { - auto docker_ptr = dockers[pos].get(); + auto docker_ptr = static_cast(dockers[pos].get()); if (docker_ptr->flag_deleted) continue; @@ -217,7 +217,7 @@ namespace nana { for (++pos; pos < dockers_len; ++pos) { - auto docker_ptr = dockers[pos].get(); + auto docker_ptr = static_cast(dockers[pos].get()); if (!docker_ptr->unignorable || docker_ptr->flag_deleted) continue; @@ -247,7 +247,7 @@ namespace nana //Checks whether this event is working now. if (emitting_count_ > 1) { - i->get()->flag_deleted = true; + static_cast(i->get())->flag_deleted = true; deleted_flags_ = true; } else @@ -416,7 +416,7 @@ namespace nana private: unsigned emitting_count_{ 0 }; bool deleted_flags_{ false }; - std::unique_ptr>> dockers_; + std::unique_ptr>> dockers_; }; struct arg_mouse @@ -528,7 +528,7 @@ namespace nana /// provides some fundamental events that every widget owns. struct general_events { - virtual ~general_events(){} + virtual ~general_events() = default; basic_event mouse_enter; ///< the cursor enters the window basic_event mouse_move; ///< the cursor moves on the window basic_event mouse_leave; ///< the cursor leaves the window diff --git a/include/nana/gui/widgets/checkbox.hpp b/include/nana/gui/widgets/checkbox.hpp index 16af0d5e..4f89b422 100644 --- a/include/nana/gui/widgets/checkbox.hpp +++ b/include/nana/gui/widgets/checkbox.hpp @@ -1,7 +1,7 @@ /** * A CheckBox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -17,10 +17,30 @@ #include namespace nana { + + //forward-declaration + class checkbox; + + struct arg_checkbox + : public event_arg + { + checkbox * const widget; + + arg_checkbox(checkbox* wdg) + : widget(wdg) + {} + }; + namespace drawerbase { namespace checkbox { + struct events_type + : public general_events + { + basic_event checked; + }; + class drawer : public drawer_trigger { @@ -51,7 +71,7 @@ namespace drawerbase class checkbox - : public widget_object + : public widget_object { public: checkbox(); @@ -81,6 +101,7 @@ namespace drawerbase checkbox * uiobj; event_handle eh_checked; event_handle eh_destroy; + event_handle eh_keyboard; }; public: ~radio_group(); diff --git a/include/nana/paint/detail/image_impl_interface.hpp b/include/nana/paint/detail/image_impl_interface.hpp index 379e8027..4a0a1722 100644 --- a/include/nana/paint/detail/image_impl_interface.hpp +++ b/include/nana/paint/detail/image_impl_interface.hpp @@ -2,6 +2,7 @@ #define NANA_PAINT_DETAIL_IMAGE_IMPL_INTERFACE_HPP #include "../image.hpp" +#include namespace nana{ namespace paint{ diff --git a/include/nana/paint/image.hpp b/include/nana/paint/image.hpp index 4a443b02..1a02fc30 100644 --- a/include/nana/paint/image.hpp +++ b/include/nana/paint/image.hpp @@ -1,7 +1,7 @@ /* * Paint Image Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -16,8 +16,6 @@ #include "graphics.hpp" -#include - namespace nana { namespace paint @@ -33,18 +31,14 @@ namespace paint image(); image(const image&); image(image&&); - image(const ::nana::experimental::filesystem::path& file); - - template - image(const Source& source) - { - open(source); - } + explicit image(const ::std::string& file); + explicit image(const ::std::wstring& file); ~image(); image& operator=(const image& rhs); image& operator=(image&&); - bool open(const ::nana::experimental::filesystem::path& file); + bool open(const ::std::string& file); + bool open(const ::std::wstring& file); /// Opens an icon from a specified buffer bool open_icon(const void* data, std::size_t bytes); diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index 0b32df7d..af47ab80 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -347,7 +347,7 @@ namespace nana { namespace experimental { return filesystem::status(path_); } - directory_entry::operator const filesystem::path&() const + directory_entry::operator const filesystem::path&() const { return path_; } @@ -518,8 +518,53 @@ namespace nana { namespace experimental { } //end class directory_iterator + bool not_found_error(int errval) + { +#if defined(NANA_WINDOWS) + switch (errval) + { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_INVALID_NAME: + case ERROR_INVALID_DRIVE: + case ERROR_NOT_READY: + case ERROR_INVALID_PARAMETER: + case ERROR_BAD_PATHNAME: + case ERROR_BAD_NETPATH: + return true; + } + return false; +#elif defined(NANA_POSIX) + return (errval == ENOENT || errval == ENOTDIR); +#else + static_assert(false, "Only Windows and Unix are supported now (Mac OS is experimental)"); +#endif + } + namespace detail { + bool rm_file(const path& p) + { + if (p.empty()) + return false; +#if defined(NANA_WINDOWS) + return (FALSE != ::DeleteFileW(p.c_str())); +#elif defined(NANA_POSIX) + return (!std::remove(p.c_str())); +#endif + } + + bool rm_dir(const path& p) + { +#if defined(NANA_WINDOWS) + return (FALSE != ::RemoveDirectoryW(p.c_str())) || not_found_error(static_cast(::GetLastError())); +#elif defined(NANA_POSIX) + return (!::rmdir(p.c_str())) || not_found_error(errno); +#endif + } + + bool rm_dir(const path& p, bool fails_if_not_empty); + //rm_dir_recursive //@brief: remove a directory, if it is not empty, recursively remove it's subfiles and sub directories template @@ -538,9 +583,34 @@ namespace nana { namespace experimental { if (is_directory(f)) rm_dir_recursive(subpath.c_str()); else - rmfile(subpath.c_str()); + rm_file(subpath.c_str()); } - return rmdir(dir, true); + return rm_dir(dir, true); + } + + bool rm_dir(const path& p, bool fails_if_not_empty) + { + if (p.empty()) + return false; + +#if defined(NANA_WINDOWS) + if (FALSE != ::RemoveDirectoryW(p.c_str())) + return true; + + if (!fails_if_not_empty && (ERROR_DIR_NOT_EMPTY == ::GetLastError())) + return detail::rm_dir_recursive(p.c_str()); + + return false; +#elif defined(NANA_POSIX) + if (::rmdir(p.c_str())) + { + if (!fails_if_not_empty && (errno == EEXIST || errno == ENOTEMPTY)) + return detail::rm_dir_recursive(p.c_str()); + + return false; + } + return true; +#endif } #if defined(NANA_WINDOWS) @@ -565,154 +635,143 @@ namespace nana { namespace experimental { #endif }//end namespace detail - bool not_found_error(int errval) - { -#if defined(NANA_WINDOWS) - switch (errval) - { - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - case ERROR_INVALID_NAME: - case ERROR_INVALID_DRIVE: - case ERROR_NOT_READY: - case ERROR_INVALID_PARAMETER: - case ERROR_BAD_PATHNAME: - case ERROR_BAD_NETPATH: - return true; - } - return false; -#elif defined(NANA_POSIX) - return (errval == ENOENT || errval == ENOTDIR); -#else - static_assert(false, "Only Windows and Unix are supported now (Mac OS is experimental)"); -#endif - } file_status status(const path& p) { + std::error_code err; + auto stat = status(p, err); + + if (err != std::error_code()) + throw filesystem_error("nana::filesystem::status", p, err); + + return stat; + } + + file_status status(const path& p, std::error_code& ec) + { + ec = std::error_code(); #if defined(NANA_WINDOWS) auto attr = ::GetFileAttributesW(p.c_str()); if (INVALID_FILE_ATTRIBUTES == attr) { if (not_found_error(static_cast(::GetLastError()))) - return file_status{file_type::not_found}; + return file_status{ file_type::not_found }; return file_status{ file_type::unknown }; } - return file_status{(FILE_ATTRIBUTE_DIRECTORY & attr) ? file_type::directory : file_type::regular, perms::all}; + return file_status{ (FILE_ATTRIBUTE_DIRECTORY & attr) ? file_type::directory : file_type::regular, perms::all }; #elif defined(NANA_POSIX) struct stat path_stat; - if(0 != ::stat(p.c_str(), &path_stat)) + if (0 != ::stat(p.c_str(), &path_stat)) { - if(errno == ENOENT || errno == ENOTDIR) - return file_status{file_type::not_found}; - - return file_status{file_type::unknown}; + if (errno == ENOENT || errno == ENOTDIR) + return file_status{ file_type::not_found }; + + return file_status{ file_type::unknown }; } auto prms = static_cast(path_stat.st_mode & static_cast(perms::mask)); - if(S_ISREG(path_stat.st_mode)) - return file_status{file_type::regular, prms}; + if (S_ISREG(path_stat.st_mode)) + return file_status{ file_type::regular, prms }; - if(S_ISDIR(path_stat.st_mode)) - return file_status{file_type::directory, prms}; + if (S_ISDIR(path_stat.st_mode)) + return file_status{ file_type::directory, prms }; - if(S_ISLNK(path_stat.st_mode)) - return file_status{file_type::symlink, prms}; + if (S_ISLNK(path_stat.st_mode)) + return file_status{ file_type::symlink, prms }; - if(S_ISBLK(path_stat.st_mode)) - return file_status{file_type::block, prms}; + if (S_ISBLK(path_stat.st_mode)) + return file_status{ file_type::block, prms }; - if(S_ISCHR(path_stat.st_mode)) - return file_status{file_type::character, prms}; + if (S_ISCHR(path_stat.st_mode)) + return file_status{ file_type::character, prms }; - if(S_ISFIFO(path_stat.st_mode)) - return file_status{file_type::fifo, prms}; + if (S_ISFIFO(path_stat.st_mode)) + return file_status{ file_type::fifo, prms }; - if(S_ISSOCK(path_stat.st_mode)) - return file_status{file_type::socket, prms}; + if (S_ISSOCK(path_stat.st_mode)) + return file_status{ file_type::socket, prms }; - return file_status{file_type::unknown}; + return file_status{ file_type::unknown }; +#endif + } + + bool is_directory(const path& p) + { + return (status(p).type() == file_type::directory); + } + + std::uintmax_t file_size(const path& p) + { +#if defined(NANA_WINDOWS) + //Some compilation environment may fail to link to GetFileSizeEx + typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER); + GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx")); + if (get_file_size_ex) + { + HANDLE handle = ::CreateFile(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (INVALID_HANDLE_VALUE != handle) + { + LARGE_INTEGER li; + if (!get_file_size_ex(handle, &li)) + li.QuadPart = 0; + + ::CloseHandle(handle); + return li.QuadPart; + } + } + return 0; +#elif defined(NANA_POSIX) + FILE * stream = ::fopen(p.c_str(), "rb"); + long long size = 0; + if (stream) + { +# if defined(NANA_LINUX) + fseeko64(stream, 0, SEEK_END); + size = ftello64(stream); +# elif defined(NANA_MACOS) + fseeko(stream, 0, SEEK_END); + size = ftello(stream); +# endif + ::fclose(stream); + } + return size; #endif } - bool is_directory(const path& p) - { - return (status(p).type() == file_type::directory); - } - - std::uintmax_t file_size(const path& p) - { + bool modified_file_time(const path& p, struct tm& t) + { #if defined(NANA_WINDOWS) - //Some compilation environment may fail to link to GetFileSizeEx - typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER); - GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx")); - if (get_file_size_ex) - { - HANDLE handle = ::CreateFile(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (INVALID_HANDLE_VALUE != handle) - { - LARGE_INTEGER li; - if (!get_file_size_ex(handle, &li)) - li.QuadPart = 0; - - ::CloseHandle(handle); - return li.QuadPart; - } - } - return 0; -#elif defined(NANA_POSIX) - FILE * stream = ::fopen(p.c_str(), "rb"); - long long size = 0; - if (stream) - { -# if defined(NANA_LINUX) - fseeko64(stream, 0, SEEK_END); - size = ftello64(stream); -# elif defined(NANA_MACOS) - fseeko(stream, 0, SEEK_END); - size = ftello(stream); -# endif - ::fclose(stream); - } - return size; -#endif - } - - - bool modified_file_time(const std::wstring& file, struct tm& t) + WIN32_FILE_ATTRIBUTE_DATA attr; + if (::GetFileAttributesEx(p.c_str(), GetFileExInfoStandard, &attr)) { -#if defined(NANA_WINDOWS) - WIN32_FILE_ATTRIBUTE_DATA attr; - if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &attr)) + FILETIME local_file_time; + if (::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time)) { - 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); + 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_LINUX) || defined(NANA_MACOS) - struct stat attr; - if (0 == ::stat(static_cast(nana::charset(file)).c_str(), &attr)) - { - t = *(::localtime(&attr.st_ctime)); + t.tm_hour = st.wHour; + t.tm_min = st.wMinute; + t.tm_sec = st.wSecond; return true; } -#endif - return false; } +#elif defined(NANA_POSIX) + struct stat attr; + if (0 == ::stat(p.c_str(), &attr)) + { + t = *(::localtime(&attr.st_ctime)); + return true; + } +#endif + return false; + } bool create_directory(const path& p) @@ -724,46 +783,22 @@ namespace nana { namespace experimental { #endif } - bool rmfile(const path& p) + bool remove(const path& p) { - if(p.empty()) - return false; -#if defined(NANA_WINDOWS) - if (FALSE == ::DeleteFileW(p.c_str())) - return (ERROR_FILE_NOT_FOUND == ::GetLastError()); + auto stat = status(p); + if (stat.type() == file_type::directory) + return detail::rm_dir(p); - return true; -#elif defined(NANA_POSIX) - if (std::remove(p.c_str())) - return (errno == ENOENT); - return true; -#endif + return detail::rm_file(p); } - - bool rmdir(const path& p, bool fails_if_not_empty) + bool remove(const path& p, std::error_code & ec) { - if(p.empty()) - return false; + auto stat = status(p); + if (stat.type() == file_type::directory) + return detail::rm_dir(p); -#if defined(NANA_WINDOWS) - if(FALSE != ::RemoveDirectoryW(p.c_str())) - return true; - - if(!fails_if_not_empty && (ERROR_DIR_NOT_EMPTY == ::GetLastError())) - return detail::rm_dir_recursive(p.c_str()); - - return false; -#elif defined(NANA_POSIX) - if(::rmdir(p.c_str())) - { - if (!fails_if_not_empty && (errno == EEXIST || errno == ENOTEMPTY)) - return detail::rm_dir_recursive(p.c_str()); - - return false; - } - return true; -#endif + return detail::rm_file(p); } path path_user() diff --git a/source/filesystem/fs_utility.cpp b/source/filesystem/fs_utility.cpp deleted file mode 100644 index c56ac523..00000000 --- a/source/filesystem/fs_utility.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * A FileSystem Utility Implementation - * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - * @file: nana/filesystem/fs_utility.cpp - * @description: - * provide some interface for file managment - */ - -#include -#include -#include -#if defined(NANA_WINDOWS) - #include - - #if defined(NANA_MINGW) - #ifndef _WIN32_IE - #define _WIN32_IE 0x0500 - #endif - #endif - - #include - #include -#elif defined(NANA_LINUX) || defined(NANA_MACOS) - #include - #include - #include - #include - #include - #include - #include - #include - #include -#endif - -namespace nana -{ -namespace filesystem -{ -//Because of No wide character version of POSIX -#if defined(NANA_LINUX) || defined(NANA_MACOS) - typedef std::string string_t; - const char* splstr = "/\\"; -#else - typedef std::wstring string_t; - const wchar_t* splstr = L"/\\"; -#endif - - namespace detail - { -#if defined(NANA_WINDOWS) - void filetime_to_c_tm(FILETIME& ft, struct tm& t) - { - FILETIME local_file_time; - if(::FileTimeToLocalFileTime(&ft, &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; - } - } -#endif - }//end namespace detail - - - bool modified_file_time(const ::std::string& file, struct tm& t) - { -#if defined(NANA_WINDOWS) - WIN32_FILE_ATTRIBUTE_DATA attr; - if(::GetFileAttributesExW(to_nstring(file).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_LINUX) || defined(NANA_MACOS) - struct stat attr; - if(0 == ::stat(file.c_str(), &attr)) - { - t = *(::localtime(&attr.st_ctime)); - return true; - } -#endif - return false; - } - - bool rmfile(const char* file) - { -#if defined(NANA_WINDOWS) - bool ret = false; - if(file) - { - ret = (::DeleteFile(utf8_cast(file).c_str()) == TRUE); - if(!ret) - ret = (ERROR_FILE_NOT_FOUND == ::GetLastError()); - } - - return ret; -#elif defined(NANA_LINUX) || defined(NANA_MACOS) - if(std::remove(file)) - return (errno == ENOENT); - return true; -#endif - } - - std::string path_user() - { -#if defined(NANA_WINDOWS) - wchar_t path[MAX_PATH]; - if(SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, path))) - return to_utf8(path); -#elif defined(NANA_LINUX) || defined(NANA_MACOS) - const char * s = ::getenv("HOME"); - if(s) - return s; -#endif - return std::string(); - } -}//end namespace filesystem -}//end namespace nana diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index f73b1ce7..60303d62 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #if defined(NANA_WINDOWS) diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 9373e5f7..104c54a0 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -1,7 +1,7 @@ /* * A CheckBox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -60,8 +60,12 @@ namespace checkbox void drawer::mouse_up(graph_reference graph, const arg_mouse&) { - if(impl_->react) + if (impl_->react) + { impl_->crook.reverse(); + arg_checkbox arg{ static_cast(widget_) }; + API::events(widget_->handle()).checked.emit(arg); + } refresh(graph); API::lazy_refresh(); } @@ -164,9 +168,15 @@ namespace checkbox void checkbox::check(bool chk) { - typedef drawerbase::checkbox::crook_state crook_state; - get_drawer_trigger().impl()->crook.check(chk ? crook_state::checked : crook_state::unchecked); - API::refresh_window(handle()); + using crook_state = drawerbase::checkbox::crook_state; + if (checked() != chk) + { + get_drawer_trigger().impl()->crook.check(chk ? crook_state::checked : crook_state::unchecked); + API::refresh_window(handle()); + + arg_checkbox arg(this); + this->events().checked.emit(arg); + } } void checkbox::radio(bool is_radio) @@ -208,15 +218,28 @@ namespace checkbox uiobj.check(false); uiobj.react(false); - element_tag el; + element_tag el = {}; el.uiobj = &uiobj; + + uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg) + { + if (arg.widget->checked()) + { + for (auto & ck : ui_container_) + { + if (ck.uiobj->handle() != arg.widget->handle()) + ck.uiobj->check(false); + } + } + }, true); + el.eh_checked = uiobj.events().click.connect_unignorable([this](const arg_click& arg) { for (auto & i : ui_container_) i.uiobj->check(arg.window_handle == i.uiobj->handle()); }, true); - + el.eh_destroy = uiobj.events().destroy.connect_unignorable([this](const arg_destroy& arg) { for (auto i = ui_container_.begin(); i != ui_container_.end(); ++i) @@ -229,6 +252,39 @@ namespace checkbox } }); + el.eh_keyboard = uiobj.events().key_press.connect_unignorable([this](const arg_keyboard& arg) + { + auto window_handle = arg.window_handle; + + auto i = std::find_if(ui_container_.begin(), ui_container_.end(), [window_handle](const element_tag& e){ + return (e.uiobj->handle() == window_handle); + }); + + if (ui_container_.end() == i) + return; + + checkbox * target; + + if (keyboard::os_arrow_up == arg.key) + { + if (ui_container_.begin() != i) + target = (i - 1)->uiobj; + else + target = ui_container_.back().uiobj; + } + else if (keyboard::os_arrow_down == arg.key) + { + if (ui_container_.end() - 1 != i) + target = (i + 1)->uiobj; + else + target = ui_container_.front().uiobj; + } + + target->check(true); + target->focus(); + }); + + ui_container_.push_back(el); } diff --git a/source/paint/detail/image_ico.hpp b/source/paint/detail/image_ico.hpp index a00c2820..debabac5 100644 --- a/source/paint/detail/image_ico.hpp +++ b/source/paint/detail/image_ico.hpp @@ -2,6 +2,7 @@ #define NANA_PAINT_DETAIL_IMAGE_ICO_HPP #include +#include namespace nana{ namespace paint { diff --git a/source/paint/image.cpp b/source/paint/image.cpp index 06204ef6..7902b864 100644 --- a/source/paint/image.cpp +++ b/source/paint/image.cpp @@ -1,7 +1,7 @@ /* * Paint Image Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -19,6 +19,7 @@ #include #include +#include #if defined(NANA_ENABLE_JPEG) #include "detail/image_jpeg.hpp" @@ -173,7 +174,12 @@ namespace paint : image_ptr_(std::move(r.image_ptr_)) {} - image::image(const ::nana::experimental::filesystem::path& file) + image::image(const std::string& file) + { + open(file); + } + + image::image(const std::wstring& file) { open(file); } @@ -187,7 +193,7 @@ namespace paint { if(this != &r) image_ptr_ = r.image_ptr_; - + return * this; } @@ -198,90 +204,99 @@ namespace paint return *this; } - bool image::open(const ::nana::experimental::filesystem::path& file) + std::shared_ptr create_image(const ::nana::experimental::filesystem::path & p) { - image_ptr_.reset(); + std::shared_ptr ptr; - auto extension = file.extension().native(); - if (extension.empty()) - return false; - - image::image_impl_interface * helper = nullptr; + auto ext = p.extension().native(); + if (ext.empty()) + return ptr; + std::transform(ext.begin(), ext.end(), ext.begin(), [](int ch) { - std::transform(extension.begin(), extension.end(), extension.begin(), [](int ch) - { - if('A' <= ch && ch <= 'Z') - ch -= ('A' - 'a'); - return ch; - }); + if ('A' <= ch && ch <= 'Z') + ch -= ('A' - 'a'); + return ch; + }); #if defined(NANA_WINDOWS) - const wchar_t* ext_ico = L".ico"; - const wchar_t* ext_png = L".png"; - const wchar_t* ext_jpg = L".jpg"; - const wchar_t* ext_jpeg = L".jpeg"; + const wchar_t* ext_ico = L".ico"; + const wchar_t* ext_png = L".png"; + const wchar_t* ext_jpg = L".jpg"; + const wchar_t* ext_jpeg = L".jpeg"; #else - const char* ext_ico = ".ico"; - const char* ext_png = ".png"; - const char* ext_jpg = ".jpg"; - const char* ext_jpeg = ".jpeg"; + const char* ext_ico = ".ico"; + const char* ext_png = ".png"; + const char* ext_jpg = ".jpg"; + const char* ext_jpeg = ".jpeg"; #endif - do - { - if (ext_ico == extension) - { -#if defined(NANA_WINDOWS) - helper = new detail::image_ico(true); -#else - return false; -#endif - break; - } - - if (ext_png == extension) - { -#if defined(NANA_ENABLE_PNG) - helper = new detail::image_png; -#else - return false; -#endif - break; - } - - if (ext_jpg == extension || ext_jpeg == extension) - { -#if defined(NANA_ENABLE_JPEG) - helper = new detail::image_jpeg; -#else - return false; -#endif - break; - } - } while (false); - - //Check for BMP - if (!helper) + do + { + if (ext_ico == ext) { - std::ifstream ifs(file.string(), std::ios::binary); - if (ifs) - { - unsigned short meta = 0; - ifs.read(reinterpret_cast(&meta), 2); - if (*reinterpret_cast("BM") == meta) - helper = new detail::image_bmp; - else if (*reinterpret_cast("MZ") == meta) - helper = new detail::image_ico(false); - } +#if defined(NANA_WINDOWS) + ptr = std::make_shared(true); +#else + return false; +#endif + break; } - if (helper) + if (ext_png == ext) { - image_ptr_ = std::shared_ptr(helper); - return helper->open(file.c_str()); +#if defined(NANA_ENABLE_PNG) + ptr = std::make_shared; +#else + return false; +#endif + break; + } + + if (ext_jpg == ext || ext_jpeg == ext) + { +#if defined(NANA_ENABLE_JPEG) + ptr = std::make_shared(); +#else + return false; +#endif + break; + } + } while (false); + + //Check for BMP + if (!ptr) + { +#ifndef NANA_MINGW + std::ifstream ifs(p.c_str(), std::ios::binary); +#else + std::ifstream ifs(to_osmbstr(to_utf8(p.native())).c_str(), std::ios::binary); +#endif + if (ifs) + { + unsigned short meta = 0; + ifs.read(reinterpret_cast(&meta), 2); + if (*reinterpret_cast("BM") == meta) + ptr = std::make_shared(); + else if (*reinterpret_cast("MZ") == meta) + ptr = std::make_shared(false); } } - return false; + + return ptr; + } + + bool image::open(const ::std::string& file) + { + ::nana::experimental::filesystem::path path(file); + image_ptr_ = create_image(path); + return (image_ptr_ ? image_ptr_->open(path) : false); + } + + bool image::open(const std::wstring& file) + { + ::nana::experimental::filesystem::path path(file); + image_ptr_ = create_image(path); + return (image_ptr_ ? image_ptr_->open(path) : false); } bool image::open_icon(const void* data, std::size_t bytes)