|
|
|
@ -1,5 +1,15 @@ |
|
|
|
#include "dialogs.h" |
|
|
|
#include "dialogs.h" |
|
|
|
#include "singletons.h" |
|
|
|
#include "singletons.h" |
|
|
|
|
|
|
|
#include <boost/locale.hpp> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef NTDDI_VERSION |
|
|
|
|
|
|
|
#define NTDDI_VERSION NTDDI_VISTA |
|
|
|
|
|
|
|
#undef _WIN32_WINNT |
|
|
|
|
|
|
|
#define _WIN32_WINNT _WIN32_WINNT_VISTA |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <windows.h> |
|
|
|
|
|
|
|
#include <shobjidl.h> |
|
|
|
|
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
|
|
#include <iostream> //TODO: remove |
|
|
|
#include <iostream> //TODO: remove |
|
|
|
using namespace std; //TODO: remove
|
|
|
|
using namespace std; //TODO: remove
|
|
|
|
@ -14,107 +24,78 @@ HRESULT __hr__; |
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // CHECK
|
|
|
|
#endif // CHECK
|
|
|
|
|
|
|
|
|
|
|
|
#undef NTDDI_VERSION |
|
|
|
|
|
|
|
#define NTDDI_VERSION NTDDI_VISTA |
|
|
|
|
|
|
|
#undef _WIN32_WINNT |
|
|
|
|
|
|
|
#define _WIN32_WINNT _WIN32_WINNT_VISTA |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <windows.h> |
|
|
|
|
|
|
|
#include <shobjidl.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <memory> |
|
|
|
|
|
|
|
#include <sstream> |
|
|
|
|
|
|
|
#include <codecvt> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WinString { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
WinString() : str(nullptr) { } |
|
|
|
|
|
|
|
WinString(const std::string &string); |
|
|
|
|
|
|
|
~WinString() { CoTaskMemFree(static_cast<void*>(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 { |
|
|
|
class CommonDialog { |
|
|
|
public: |
|
|
|
public: |
|
|
|
CommonDialog(CLSID type); |
|
|
|
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 add_option(unsigned option); |
|
|
|
void set_title(const std::string &title); |
|
|
|
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(); |
|
|
|
std::string show(); |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
protected: |
|
|
|
IFileDialog * dialog; |
|
|
|
IFileDialog * dialog; |
|
|
|
DWORD options; |
|
|
|
DWORD options; |
|
|
|
|
|
|
|
bool error=false; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class OpenDialog : public CommonDialog { |
|
|
|
class OpenDialog : public CommonDialog { |
|
|
|
public: |
|
|
|
public: |
|
|
|
OpenDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileOpenDialog) { |
|
|
|
OpenDialog(const std::string &title, unsigned option); |
|
|
|
set_title(title); |
|
|
|
|
|
|
|
add_option(option); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class SaveDialog : public CommonDialog { |
|
|
|
class SaveDialog : public CommonDialog { |
|
|
|
public: |
|
|
|
public: |
|
|
|
SaveDialog(const std::string &title, unsigned option) : CommonDialog(CLSID_FileSaveDialog) { |
|
|
|
SaveDialog(const std::string &title, unsigned option); |
|
|
|
set_title(title); |
|
|
|
private: |
|
|
|
add_option(option); |
|
|
|
std::vector<COMDLG_FILTERSPEC> 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<wchar_t> convert_typeX; |
|
|
|
|
|
|
|
std::wstring_convert<convert_typeX, wchar_t> converterX; |
|
|
|
|
|
|
|
return converterX.from_bytes(str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string WinString::ws2s(const std::wstring& wstr) { |
|
|
|
|
|
|
|
typedef std::codecvt_utf8<wchar_t> convert_typeX; |
|
|
|
|
|
|
|
std::wstring_convert<convert_typeX, wchar_t> converterX; |
|
|
|
|
|
|
|
return converterX.to_bytes(wstr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// WINSTRING }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// { COMMON_DIALOG
|
|
|
|
// { COMMON_DIALOG
|
|
|
|
CommonDialog::CommonDialog(CLSID type) : dialog(nullptr) { |
|
|
|
CommonDialog::CommonDialog(CLSID type) : dialog(nullptr) { |
|
|
|
check(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog)), "Failed to create instance"); |
|
|
|
if(CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dialog))!=S_OK) { |
|
|
|
check(dialog->GetOptions(&options), "Failed to get options from instance"); |
|
|
|
error=true; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(dialog->GetOptions(&options)!=S_OK) |
|
|
|
|
|
|
|
error=true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CommonDialog::set_title(const std::string &title) { |
|
|
|
void CommonDialog::set_title(const std::string &title) { |
|
|
|
auto tmp = std::wstring(title.begin(), title.end()); |
|
|
|
if(error) return; |
|
|
|
auto t = tmp.data(); |
|
|
|
auto ptr = boost::locale::conv::utf_to_utf<wchar_t>(title).data(); |
|
|
|
check(dialog->SetTitle(t), "Failed to set dialog title"); |
|
|
|
if(dialog->SetTitle(ptr)!=S_OK) |
|
|
|
|
|
|
|
error=true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CommonDialog::add_option(unsigned option) { |
|
|
|
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<wchar_t>(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<wchar_t>(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() { |
|
|
|
std::string CommonDialog::show() { |
|
|
|
|
|
|
|
if(error) return ""; |
|
|
|
if(dialog->Show(nullptr)!=S_OK) { |
|
|
|
if(dialog->Show(nullptr)!=S_OK) { |
|
|
|
dialog->Release(); |
|
|
|
dialog->Release(); |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
|
@ -122,16 +103,41 @@ std::string CommonDialog::show() { |
|
|
|
IShellItem *result = nullptr; |
|
|
|
IShellItem *result = nullptr; |
|
|
|
if(dialog->GetResult(&result)!=S_OK) { |
|
|
|
if(dialog->GetResult(&result)!=S_OK) { |
|
|
|
result->Release(); |
|
|
|
result->Release(); |
|
|
|
|
|
|
|
dialog->Release(); |
|
|
|
return ""; |
|
|
|
return ""; |
|
|
|
} |
|
|
|
} |
|
|
|
WinString str; |
|
|
|
LPWSTR str = nullptr;
|
|
|
|
if(result->GetDisplayName(SIGDN_FILESYSPATH, &str)!=S_OK) |
|
|
|
auto result=result->GetDisplayName(SIGDN_FILESYSPATH, &str); |
|
|
|
return ""; |
|
|
|
|
|
|
|
result->Release(); |
|
|
|
result->Release(); |
|
|
|
dialog->Release(); |
|
|
|
dialog->Release(); |
|
|
|
return str(); |
|
|
|
if(result!=S_OK) |
|
|
|
|
|
|
|
return ""; |
|
|
|
|
|
|
|
auto res = boost::locale::conv::utf_to_utf<char>(str); |
|
|
|
|
|
|
|
CoTaskMemFree(str); |
|
|
|
|
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
// COMMON_DIALOG }}
|
|
|
|
|
|
|
|
|
|
|
|
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()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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() { |
|
|
|
std::string Dialog::select_folder() { |
|
|
|
return (OpenDialog("Select folder", FOS_PICKFOLDERS)).show(); |
|
|
|
return (OpenDialog("Select folder", FOS_PICKFOLDERS)).show(); |
|
|
|
} |
|
|
|
} |
|
|
|
|