diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2da1c6f..e1e7ef9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,7 +28,15 @@ find_package(LibClang REQUIRED) #find_package(PythonLibs 2.7) #find_package(Boost 1.55 COMPONENTS python thread log system filesystem REQUIRED) -find_package(Boost 1.55 COMPONENTS thread log system filesystem REQUIRED) + +set(BOOST_DEP thread log system filesystem) + +if(MSYS) + list(APPEND BOOST_DEP locale) +endif() + + +find_package(Boost 1.55 COMPONENTS ${BOOST_DEP} REQUIRED) pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED) # The name GTKMM is set here for the variables abouve diff --git a/src/dialogs.h b/src/dialogs.h index 1dfeec2..435e207 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -12,4 +12,4 @@ public: static std::string save_file(const boost::filesystem::path file_path); }; -#endif //JUCI_DIALOG_H_ \ No newline at end of file +#endif //JUCI_DIALOG_H_ diff --git a/src/dialogs_win.cc b/src/dialogs_win.cc index d65bbd6..2c67116 100644 --- a/src/dialogs_win.cc +++ b/src/dialogs_win.cc @@ -1,5 +1,15 @@ #include "dialogs.h" #include "singletons.h" +#include + +#undef NTDDI_VERSION +#define NTDDI_VERSION NTDDI_VISTA +#undef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_VISTA + +#include +#include +#include #include //TODO: remove using namespace std; //TODO: remove @@ -14,107 +24,78 @@ HRESULT __hr__; } #endif // CHECK -#undef NTDDI_VERSION -#define NTDDI_VERSION NTDDI_VISTA -#undef _WIN32_WINNT -#define _WIN32_WINNT _WIN32_WINNT_VISTA - -#include -#include - -#include -#include -#include - -class WinString { -public: - WinString() : str(nullptr) { } - WinString(const std::string &string); - ~WinString() { CoTaskMemFree(static_cast(str)); } - std::string operator()(); - wchar_t** operator&() { return &str; } -private: - wchar_t* str; - std::wstring s2ws(const std::string& str); - std::string ws2s(const std::wstring& wstr); -}; - class CommonDialog { public: CommonDialog(CLSID type); + /** available options are listed https://msdn.microsoft.com/en-gb/library/windows/desktop/dn457282(v=vs.85).aspx */ void add_option(unsigned option); void set_title(const std::string &title); + /** Sets the extensions the browser can find */ + void set_default_file_extension(const std::string &file_extension); + /** Sets the directory to start browsing */ + void set_default_folder(const std::string &directory_path); + /** Returns the selected item's path as a string */ std::string show(); -private: +protected: IFileDialog * dialog; DWORD options; + bool error=false; }; class OpenDialog : public CommonDialog { public: - OpenDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileOpenDialog) { - set_title(title); - add_option(option); - } + OpenDialog(const std::string &title, unsigned option); }; class SaveDialog : public CommonDialog { public: - SaveDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileSaveDialog) { - set_title(title); - add_option(option); - } + SaveDialog(const std::string &title, unsigned option); +private: + std::vector extensions; }; -// { WINSTRING -WinString::WinString(const std::string &string) { - std::wstringstream ss; - ss << s2ws(string); - ss >> str; -} - -std::string WinString::operator()() { - std::string res; - if (str != nullptr) { - std::wstring ss(str); - res = ws2s(ss); - } - return res; -} - -// http://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string -std::wstring WinString::s2ws(const std::string& str) { - typedef std::codecvt_utf8 convert_typeX; - std::wstring_convert converterX; - return converterX.from_bytes(str); -} - -std::string WinString::ws2s(const std::wstring& wstr) { - typedef std::codecvt_utf8 convert_typeX; - std::wstring_convert converterX; - return converterX.to_bytes(wstr); -} - -// WINSTRING } - // { COMMON_DIALOG CommonDialog::CommonDialog(CLSID type) : dialog(nullptr) { - check(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog)), "Failed to create instance"); - check(dialog->GetOptions(&options), "Failed to get options from instance"); + if(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog))!=S_OK) { + error=true; + return; + } + if(dialog->GetOptions(&options)!=S_OK) + error=true; } - void CommonDialog::set_title(const std::string &title) { - auto tmp = std::wstring(title.begin(), title.end()); - auto t = tmp.data(); - check(dialog->SetTitle(t), "Failed to set dialog title"); + if(error) return; + auto ptr = boost::locale::conv::utf_to_utf(title).data(); + if(dialog->SetTitle(ptr)!=S_OK) + error=true; } - void CommonDialog::add_option(unsigned option) { - check(dialog->SetOptions(options | option), "Failed to set options"); + if(error) return; + if(dialog->SetOptions(options | option)!=S_OK) + error=true; +} +void CommonDialog::set_default_file_extension(const std::string &file_extension) { + if(error) return; + auto ptr = boost::locale::conv::utf_to_utf(file_extension).data(); + if(dialog->SetDefaultExtension(ptr)!=S_OK) + error=true; +} +void CommonDialog::set_default_folder(const std::string &directory_path) { + if(error) return; + IShellItem * folder = nullptr; + auto ptr = boost::locale::conv::utf_to_utf(directory_path).data(); + if(SHCreateItemFromParsingName(ptr, nullptr, IID_PPV_ARGS(&folder))!=S_OK) { + error=true; + return; + } + auto result=dialog->SetDefaultFolder(folder) + folder->Release(); + if(result!=S_OK) + error=true; } - std::string CommonDialog::show() { + if(error) return ""; if(dialog->Show(nullptr)!=S_OK) { dialog->Release(); return ""; @@ -122,16 +103,41 @@ std::string CommonDialog::show() { IShellItem *result = nullptr; if(dialog->GetResult(&result)!=S_OK) { result->Release(); + dialog->Release(); return ""; } - WinString str; - if(result->GetDisplayName(SIGDN_FILESYSPATH, &str)!=S_OK) - return ""; + LPWSTR str = nullptr; + auto result=result->GetDisplayName(SIGDN_FILESYSPATH, &str); result->Release(); dialog->Release(); - return str(); + if(result!=S_OK) + return ""; + auto res = boost::locale::conv::utf_to_utf(str); + CoTaskMemFree(str); + return res; +} + +OpenDialog::OpenDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileOpenDialog) { + set_title(title); + add_option(option); + auto dirs = Singleton::directories()->current_path; + set_default_folder(dirs.empty() ? boost::filesystem::current_path().string() : dirs.string()); } -// COMMON_DIALOG }} + +SaveDialog::SaveDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileSaveDialog) { + set_title(title); + add_option(option); + auto dirs = Singleton::directories()->current_path; + set_default_folder(dirs.empty() ? boost::filesystem::current_path().string() : dirs.string()); + //extensions.emplace_back(COMDLG_FILTERSPEC{L"Default", L"*.h;*.cpp"}); + //extensions.emplace_back(COMDLG_FILTERSPEC{L"GoogleStyle", L"*.cc;*.h"}); + //extensions.emplace_back(COMDLG_FILTERSPEC{L"BoostStyle", L"*.hpp;*.cpp"}); + //extensions.emplace_back(COMDLG_FILTERSPEC{L"Other", L"*.cxx;*.c"}); + //check(dialog->SetFileTypes(extensions.size(), extensions.data()), "Failed to set extensions"); + //set_default_file_extension("Default"); +} + +// DIALOGS }} std::string Dialog::select_folder() { return (OpenDialog("Select folder", FOS_PICKFOLDERS)).show(); }