#include "dialogs.h" #include "singletons.h" #include "juci.h" #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 class Win32Dialog { public: Win32Dialog() {}; ~Win32Dialog() { if(dialog!=nullptr) dialog->Release(); } /** Returns the selected item's path as a string */ std::string open(const std::wstring &title, unsigned option=0) { if(!init(CLSID_FileOpenDialog)) return ""; if(!set_title(title) || !add_option(option)) return ""; if(!set_folder()) return ""; return show(); } std::string save(const std::wstring &title, const boost::filesystem::path &file_path="", unsigned option=0) { if(!init(CLSID_FileSaveDialog)) return ""; if(!set_title(title) || !add_option(option)) return ""; if(!set_folder()) return ""; std::vector extensions; if(!file_path.empty()) { if(file_path.has_extension() && file_path.filename()!=file_path.extension()) { auto extension=(L"*"+file_path.extension().native()).c_str(); extensions.emplace_back(COMDLG_FILTERSPEC{extension, extension}); if(!set_default_file_extension(extension)) return ""; } } extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"}); if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK) return ""; return show(); } private: IFileDialog *dialog=nullptr; DWORD options; bool init(CLSID type) { if(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog))!=S_OK) return false; if(dialog->GetOptions(&options)!=S_OK) return false; return true; } /** available options are listed at https://msdn.microsoft.com/en-gb/library/windows/desktop/dn457282(v=vs.85).aspx */ bool add_option(unsigned option) { if(dialog->SetOptions(options | option)!=S_OK) return false; return true; } bool set_title(const std::wstring &title) { if(dialog->SetTitle(title.c_str())!=S_OK) return false; return true; } /** Sets the extensions the browser can find */ bool set_default_file_extension(const std::wstring &file_extension) { if(dialog->SetDefaultExtension(file_extension.c_str())!=S_OK) return false; return true; } /** Sets the directory to start browsing */ bool set_folder() { auto g_application=g_application_get_default(); //TODO: Post issue that Gio::Application::get_default should return pointer and not Glib::RefPtr auto gio_application=Glib::wrap(g_application, true); auto application=Glib::RefPtr::cast_static(gio_application); auto current_path=application->window->notebook.get_current_folder(); boost::system::error_code ec; if(current_path.empty()) current_path=boost::filesystem::current_path(ec); if(ec) return false; std::wstring path=current_path.native(); size_t pos=0; while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2 path.replace(pos, 1, L"\\"); pos++; } IShellItem *folder = nullptr; if(SHCreateItemFromParsingName(path.c_str(), nullptr, IID_PPV_ARGS(&folder))!=S_OK) return false; if(dialog->SetFolder(folder)!=S_OK) return false; folder->Release(); return true; } std::string show() { if(dialog->Show(nullptr)!=S_OK) return ""; IShellItem *result = nullptr; if(dialog->GetResult(&result)!=S_OK) return ""; LPWSTR file_path = nullptr; auto hresult=result->GetDisplayName(SIGDN_FILESYSPATH, &file_path); result->Release(); if(hresult!=S_OK) return ""; std::wstring file_path_wstring(file_path); std::string file_path_string(file_path_wstring.begin(), file_path_wstring.end()); CoTaskMemFree(file_path); return file_path_string; } }; std::string Dialog::open_folder() { return Win32Dialog().open(L"Open Folder", FOS_PICKFOLDERS); } std::string Dialog::new_file() { return Win32Dialog().save(L"New File"); } std::string Dialog::new_folder() { //Win32 (IFileDialog) does not support create folder... return gtk_dialog("New Folder", {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)}, Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER); } std::string Dialog::open_file() { return Win32Dialog().open(L"Open File"); } std::string Dialog::save_file_as(const boost::filesystem::path &file_path) { return Win32Dialog().save(L"Save File As", file_path); }