mirror of https://gitlab.com/cppit/jucipp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.7 KiB
163 lines
4.7 KiB
#include "dialogs.h" |
|
#include "juci.h" |
|
#include "singletons.h" |
|
|
|
#undef NTDDI_VERSION |
|
#define NTDDI_VERSION NTDDI_VISTA |
|
#undef _WIN32_WINNT |
|
#define _WIN32_WINNT _WIN32_WINNT_VISTA |
|
|
|
#include <shobjidl.h> |
|
#include <vector> |
|
#include <windows.h> |
|
|
|
#include <iostream> //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<COMDLG_FILTERSPEC> 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<Application>::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); |
|
}
|
|
|