|
|
|
|
@ -13,71 +13,44 @@
|
|
|
|
|
#include <iostream> //TODO: remove |
|
|
|
|
using namespace std; //TODO: remove
|
|
|
|
|
|
|
|
|
|
class CommonDialog { |
|
|
|
|
class Win32Dialog { |
|
|
|
|
public: |
|
|
|
|
CommonDialog(CLSID type); |
|
|
|
|
~CommonDialog() { |
|
|
|
|
if(dialog!=nullptr) |
|
|
|
|
dialog->Release(); |
|
|
|
|
} |
|
|
|
|
/** available options are listed at https://msdn.microsoft.com/en-gb/library/windows/desktop/dn457282(v=vs.85).aspx */ |
|
|
|
|
void add_option(unsigned option); |
|
|
|
|
void set_title(const std::wstring &title); |
|
|
|
|
/** Sets the extensions the browser can find */ |
|
|
|
|
void set_default_file_extension(const std::wstring &file_extension); |
|
|
|
|
/** Sets the directory to start browsing */ |
|
|
|
|
void set_folder(const std::wstring &directory_path); |
|
|
|
|
/** Returns the selected item's path as a string */ |
|
|
|
|
std::string show(); |
|
|
|
|
Win32Dialog() {}; |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
IFileDialog *dialog=nullptr; |
|
|
|
|
DWORD options; |
|
|
|
|
bool error=false; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class OpenDialog : public CommonDialog { |
|
|
|
|
public: |
|
|
|
|
OpenDialog(const std::wstring &title, unsigned option=0); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class SaveDialog : public CommonDialog { |
|
|
|
|
public: |
|
|
|
|
SaveDialog(const std::wstring &title, const boost::filesystem::path &file_path="", unsigned option=0); |
|
|
|
|
private: |
|
|
|
|
std::vector<COMDLG_FILTERSPEC> extensions; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
CommonDialog::CommonDialog(CLSID type) { |
|
|
|
|
if(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog))!=S_OK) { |
|
|
|
|
error=true; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
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) |
|
|
|
|
error=true; |
|
|
|
|
return false; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CommonDialog::set_title(const std::wstring &title) { |
|
|
|
|
if(error) return; |
|
|
|
|
if(dialog->SetTitle(title.c_str())!=S_OK) |
|
|
|
|
error=true; |
|
|
|
|
~Win32Dialog() { |
|
|
|
|
if(dialog!=nullptr) |
|
|
|
|
dialog->Release(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CommonDialog::add_option(unsigned option) { |
|
|
|
|
if(error) return; |
|
|
|
|
/** 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) |
|
|
|
|
error=true; |
|
|
|
|
return false; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CommonDialog::set_default_file_extension(const std::wstring &file_extension) { |
|
|
|
|
if(error) return; |
|
|
|
|
if(dialog->SetDefaultExtension(file_extension.c_str())!=S_OK) |
|
|
|
|
error=true; |
|
|
|
|
bool set_title(const std::wstring &title) { |
|
|
|
|
if(dialog->SetTitle(title.c_str())!=S_OK) |
|
|
|
|
return false; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CommonDialog::set_folder(const std::wstring &directory_path) { |
|
|
|
|
if(error) return; |
|
|
|
|
|
|
|
|
|
/** 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(const std::wstring &directory_path) { |
|
|
|
|
std::wstring path=directory_path; |
|
|
|
|
size_t pos=0; |
|
|
|
|
while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2
|
|
|
|
|
@ -86,82 +59,95 @@ void CommonDialog::set_folder(const std::wstring &directory_path) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IShellItem *folder = nullptr; |
|
|
|
|
if(SHCreateItemFromParsingName(path.c_str(), nullptr, IID_PPV_ARGS(&folder))!=S_OK) { |
|
|
|
|
error=true; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
auto hresult=dialog->SetFolder(folder); |
|
|
|
|
if(SHCreateItemFromParsingName(path.c_str(), nullptr, IID_PPV_ARGS(&folder))!=S_OK) |
|
|
|
|
return false; |
|
|
|
|
if(dialog->SetFolder(folder)!=S_OK) |
|
|
|
|
return false; |
|
|
|
|
folder->Release(); |
|
|
|
|
if(hresult!=S_OK) |
|
|
|
|
error=true; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string CommonDialog::show() { |
|
|
|
|
if(error) return ""; |
|
|
|
|
if(dialog->Show(nullptr)!=S_OK) { |
|
|
|
|
/** Returns the selected item's path as a string */ |
|
|
|
|
std::string open(const std::wstring &title, unsigned option=0) { |
|
|
|
|
if(!init(CLSID_FileOpenDialog)) |
|
|
|
|
return ""; |
|
|
|
|
} |
|
|
|
|
IShellItem *result = nullptr; |
|
|
|
|
if(dialog->GetResult(&result)!=S_OK) { |
|
|
|
|
result->Release(); |
|
|
|
|
|
|
|
|
|
if(!set_title(title) || !add_option(option)) |
|
|
|
|
return ""; |
|
|
|
|
} |
|
|
|
|
LPWSTR str = nullptr;
|
|
|
|
|
auto hresult=result->GetDisplayName(SIGDN_FILESYSPATH, &str); |
|
|
|
|
result->Release(); |
|
|
|
|
if(hresult!=S_OK) |
|
|
|
|
auto dirs = Singleton::directories->current_path; |
|
|
|
|
if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native())) |
|
|
|
|
return ""; |
|
|
|
|
std::wstring wstr(str); |
|
|
|
|
std::string res(wstr.begin(), wstr.end()); |
|
|
|
|
CoTaskMemFree(str); |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
OpenDialog::OpenDialog(const std::wstring &title, unsigned option) : CommonDialog(CLSID_FileOpenDialog) { |
|
|
|
|
set_title(title); |
|
|
|
|
add_option(option); |
|
|
|
|
auto dirs = Singleton::directories->current_path; |
|
|
|
|
set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native()); |
|
|
|
|
return show(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SaveDialog::SaveDialog(const std::wstring &title, const boost::filesystem::path &file_path, unsigned option) : CommonDialog(CLSID_FileSaveDialog) { |
|
|
|
|
set_title(title); |
|
|
|
|
add_option(option); |
|
|
|
|
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 ""; |
|
|
|
|
std::vector<COMDLG_FILTERSPEC> extensions; |
|
|
|
|
if(!file_path.empty()) { |
|
|
|
|
set_folder(file_path.parent_path().native()); |
|
|
|
|
if(!set_folder(file_path.parent_path().native())) |
|
|
|
|
return ""; |
|
|
|
|
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}); |
|
|
|
|
set_default_file_extension(extension); |
|
|
|
|
if(!set_default_file_extension(extension)) |
|
|
|
|
return ""; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
auto dirs = Singleton::directories->current_path; |
|
|
|
|
set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native()); |
|
|
|
|
if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native())) |
|
|
|
|
return ""; |
|
|
|
|
} |
|
|
|
|
extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"}); |
|
|
|
|
if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK) { |
|
|
|
|
error=true; |
|
|
|
|
return; |
|
|
|
|
if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK) |
|
|
|
|
return ""; |
|
|
|
|
|
|
|
|
|
return show(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IFileDialog *dialog=nullptr; |
|
|
|
|
DWORD options; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
std::string Dialog::open_folder() { |
|
|
|
|
return (OpenDialog(L"Open Folder", FOS_PICKFOLDERS)).show(); |
|
|
|
|
return Win32Dialog().open(L"Open Folder", FOS_PICKFOLDERS); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string Dialog::new_file() { |
|
|
|
|
return (SaveDialog(L"New File")).show(); |
|
|
|
|
return Win32Dialog().save(L"New File"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string Dialog::new_folder() { |
|
|
|
|
return (OpenDialog(L"New Folder", FOS_PICKFOLDERS)).show(); |
|
|
|
|
return Win32Dialog().open(L"New Folder", FOS_PICKFOLDERS); //TODO: this is not working correctly yet
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string Dialog::open_file() { |
|
|
|
|
return (OpenDialog(L"Open File")).show(); |
|
|
|
|
return Win32Dialog().open(L"Open File"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string Dialog::save_file_as(const boost::filesystem::path &file_path) { |
|
|
|
|
return (SaveDialog(L"Save File As", file_path)).show(); |
|
|
|
|
return Win32Dialog().save(L"Save File As", file_path); |
|
|
|
|
} |
|
|
|
|
|