diff --git a/setup/installer/windows/file_dialogs.cpp b/setup/installer/windows/file_dialogs.cpp index 56b4557900..a14bc6c2b1 100644 --- a/setup/installer/windows/file_dialogs.cpp +++ b/setup/installer/windows/file_dialogs.cpp @@ -16,11 +16,11 @@ #define REPORTERR(x) { PRINTERR(x); ret = 1; goto error; } #define CALLCOM(x, err) hr = x; if(FAILED(hr)) REPORTERR(err) -int show_dialog(HWND parent, bool save_dialog, LPWSTR title) { +int show_dialog(HWND parent, bool save_dialog, LPWSTR title, bool multiselect, bool confirm_overwrite, bool only_dirs, bool no_symlinks) { int ret = 0; IFileDialog *pfd = NULL; IShellItem *psiResult = NULL; - DWORD dwFlags; + DWORD options; HRESULT hr = S_OK; hr = CoInitialize(NULL); if (FAILED(hr)) { PRINTERR("Failed to initialize COM"); return 1; } @@ -29,9 +29,18 @@ int show_dialog(HWND parent, bool save_dialog, LPWSTR title) { NULL, CLSCTX_INPROC_SERVER, (save_dialog ? IID_IFileSaveDialog : IID_IFileOpenDialog), reinterpret_cast(&pfd)), "Failed to create COM object for file dialog") - CALLCOM(pfd->GetOptions(&dwFlags), "Failed to get options") - dwFlags |= FOS_FORCEFILESYSTEM; - CALLCOM(pfd->SetOptions(dwFlags), "Failed to set options") + CALLCOM(pfd->GetOptions(&options), "Failed to get options") + options |= FOS_PATHMUSTEXIST | FOS_FORCESHOWHIDDEN; + if (no_symlinks) options |= FOS_NODEREFERENCELINKS; + if (save_dialog) { + options |= FOS_NOREADONLYRETURN; + if (confirm_overwrite) options |= FOS_OVERWRITEPROMPT; + } else { + if (multiselect) options |= FOS_ALLOWMULTISELECT; + if (only_dirs) options |= FOS_PICKFOLDERS; + options |= FOS_FILEMUSTEXIST; + } + CALLCOM(pfd->SetOptions(options), "Failed to set options") if (title != NULL) { CALLCOM(pfd->SetTitle(title), "Failed to set title") } hr = pfd->Show(parent); if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) goto error; @@ -82,12 +91,13 @@ bool read_string(unsigned short sz, LPWSTR* ans) { #define CHECK_KEY(x) (key_size == sizeof(x) - 1 && memcmp(buf, x, sizeof(x) - 1) == 0) #define READSTR(x) READ(sizeof(unsigned short), buf); if(!read_string(*((unsigned short*)buf), &x)) return 1; #define SETBINARY(x) if(_setmode(_fileno(x), _O_BINARY) == -1) { PRINTERR("Failed to set binary mode"); return 1; } +#define READBOOL(x) READ(1, buf); x = !!buf[0]; int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { char buf[257]; size_t key_size = 0; HWND parent = NULL; - bool save_dialog = false; + bool save_dialog = false, multiselect = false, confirm_overwrite = false, only_dirs = false, no_symlinks = false; unsigned short len = 0; LPWSTR title = NULL; @@ -110,7 +120,15 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine else if CHECK_KEY("TITLE") { READSTR(title) } - else if CHECK_KEY("SAVE_AS") { READ(1, buf); save_dialog = !!buf[0]; } + else if CHECK_KEY("SAVE_AS") { READBOOL(save_dialog) } + + else if CHECK_KEY("MULTISELECT") { READBOOL(multiselect) } + + else if CHECK_KEY("CONFIRM_OVERWRITE") { READBOOL(confirm_overwrite) } + + else if CHECK_KEY("ONLY_DIRS") { READBOOL(only_dirs) } + + else if CHECK_KEY("NO_SYMLINKS") { READBOOL(no_symlinks) } else { PRINTERR("Unknown key"); @@ -118,5 +136,5 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine } } - return show_dialog(parent, save_dialog, title); + return show_dialog(parent, save_dialog, title, multiselect, confirm_overwrite, only_dirs, no_symlinks); } diff --git a/src/calibre/gui2/win_file_dialogs.py b/src/calibre/gui2/win_file_dialogs.py index 9da340f621..6dc18a2e0d 100644 --- a/src/calibre/gui2/win_file_dialogs.py +++ b/src/calibre/gui2/win_file_dialogs.py @@ -61,14 +61,23 @@ class Loop(QEventLoop): QEventLoop.__init__(self) self.dialog_closed.connect(self.exit, type=Qt.QueuedConnection) -def run_file_dialog(parent=None, title=None, save_as=False): +def run_file_dialog(parent=None, title=None, allow_multiples=False, only_dirs=False, confirm_overwrite=True, save_as=False, no_symlinks=False): data = [] if parent is not None: data.append(serialize_hwnd(get_hwnd(parent))) if title is not None: data.append(serialize_string('TITLE', title)) + if no_symlinks: + data.append(serialize_binary('NO_SYMLINKS', no_symlinks)) if save_as: data.append(serialize_binary('SAVE_AS', save_as)) + if confirm_overwrite: + data.append(serialize_binary('CONFIRM_OVERWRITE', confirm_overwrite)) + else: + if allow_multiples: + data.append(serialize_binary('MULTISELECT', allow_multiples)) + if only_dirs: + data.append(serialize_binary('ONLY_DIRS', only_dirs)) loop = Loop() h = Helper(subprocess.Popen( [HELPER], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE), @@ -87,7 +96,7 @@ if __name__ == '__main__': q = QMainWindow() def clicked(): - print(run_file_dialog(b, 'Testing dialogs', True)), sys.stdout.flush() + print(run_file_dialog(b, 'Testing dialogs', only_dirs=True)), sys.stdout.flush() b = QPushButton('click me') b.clicked.connect(clicked)