This repository was archived by the owner on Jun 25, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 96
/
Copy pathdialogs_win.cc
163 lines (137 loc) · 4.72 KB
/
dialogs_win.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#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 <windows.h>
#include <shobjidl.h>
#include <vector>
#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);
}