From b078110aed14517e3858e3455049529be8db7a9d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 3 May 2016 23:52:46 +0530 Subject: [PATCH] Initial path --- setup/installer/windows/file_dialogs.cpp | 18 +++++++--- src/calibre/gui2/win_file_dialogs.py | 42 +++++++++++++++++++----- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/setup/installer/windows/file_dialogs.cpp b/setup/installer/windows/file_dialogs.cpp index dc39b8be7f..64d3105f7e 100644 --- a/setup/installer/windows/file_dialogs.cpp +++ b/setup/installer/windows/file_dialogs.cpp @@ -16,10 +16,10 @@ #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, LPWSTR folder, bool multiselect, bool confirm_overwrite, bool only_dirs, bool no_symlinks) { +int show_dialog(HWND parent, bool save_dialog, LPWSTR title, LPWSTR folder, LPWSTR filename, LPWSTR save_path, bool multiselect, bool confirm_overwrite, bool only_dirs, bool no_symlinks) { int ret = 0; IFileDialog *pfd = NULL; - IShellItem *result = NULL, *folder_item = NULL; + IShellItem *result = NULL, *folder_item = NULL, *save_path_item = NULL; DWORD options; HRESULT hr = S_OK; hr = CoInitialize(NULL); @@ -35,6 +35,11 @@ int show_dialog(HWND parent, bool save_dialog, LPWSTR title, LPWSTR folder, bool if (save_dialog) { options |= FOS_NOREADONLYRETURN; if (confirm_overwrite) options |= FOS_OVERWRITEPROMPT; + if (save_path != NULL) { + hr = SHCreateItemFromParsingName(save_path, NULL, IID_IShellItem, reinterpret_cast(&save_path_item)); + // Failure to set initial save path is not critical + if (SUCCEEDED(hr)) ((IFileSaveDialog*)pfd)->SetSaveAsItem(save_path_item); + } } else { if (multiselect) options |= FOS_ALLOWMULTISELECT; if (only_dirs) options |= FOS_PICKFOLDERS; @@ -47,6 +52,7 @@ int show_dialog(HWND parent, bool save_dialog, LPWSTR title, LPWSTR folder, bool // Failure to set initial folder is not critical if (SUCCEEDED(hr)) pfd->SetFolder(folder_item); } + if (filename != NULL) pfd->SetFileName(filename); // Failure is not critical hr = pfd->Show(parent); if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) goto error; if (FAILED(hr)) REPORTERR("Failed to show dialog") @@ -104,7 +110,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine HWND parent = NULL; bool save_dialog = false, multiselect = false, confirm_overwrite = false, only_dirs = false, no_symlinks = false; unsigned short len = 0; - LPWSTR title = NULL, folder = NULL; + LPWSTR title = NULL, folder = NULL, filename = NULL, save_path = NULL; SETBINARY(stdout); SETBINARY(stdin); SETBINARY(stderr); // The calibre executables call SetDllDirectory, we unset it here just in @@ -127,6 +133,10 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine else if CHECK_KEY("FOLDER") { READSTR(folder) } + else if CHECK_KEY("FILENAME") { READSTR(filename) } + + else if CHECK_KEY("SAVE_PATH") { READSTR(save_path) } + else if CHECK_KEY("SAVE_AS") { READBOOL(save_dialog) } else if CHECK_KEY("MULTISELECT") { READBOOL(multiselect) } @@ -143,5 +153,5 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine } } - return show_dialog(parent, save_dialog, title, folder, multiselect, confirm_overwrite, only_dirs, no_symlinks); + return show_dialog(parent, save_dialog, title, folder, filename, save_path, 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 e6955121b4..5bd0cbd11f 100644 --- a/src/calibre/gui2/win_file_dialogs.py +++ b/src/calibre/gui2/win_file_dialogs.py @@ -68,8 +68,23 @@ class Loop(QEventLoop): QEventLoop.__init__(self) self.dialog_closed.connect(self.exit, type=Qt.QueuedConnection) +def process_path(x): + if isinstance(x, bytes): + x = x.decode(filesystem_encoding) + return os.path.abspath(expanduser(x)) + +def select_initial_dir(q): + while q: + c = os.path.dirname(q) + if c == q: + break + if os.path.exists(c): + return c + q = c + return expanduser('~') + def run_file_dialog( - parent=None, title=None, initial_folder=None, + parent=None, title=None, initial_folder=None, filename=None, save_path=None, allow_multiples=False, only_dirs=False, confirm_overwrite=True, save_as=False, no_symlinks=False ): data = [] @@ -77,23 +92,34 @@ def run_file_dialog( data.append(serialize_hwnd(get_hwnd(parent))) if title is not None: data.append(serialize_string('TITLE', title)) - if initial_folder is not None: - if isinstance(initial_folder, bytes): - initial_folder = initial_folder.decode(filesystem_encoding) - initial_folder = os.path.abspath(expanduser(initial_folder)) - if os.path.isdir(initial_folder): - data.append(serialize_string('FOLDER', initial_folder)) 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)) + if save_path is not None: + save_path = process_path(save_path) + if os.path.exists(save_path): + data.append(serialize_string('SAVE_PATH', save_path)) + else: + if not initial_folder: + initial_folder = select_initial_dir(save_path) + if not filename: + filename = os.path.basename(save_path) else: if allow_multiples: data.append(serialize_binary('MULTISELECT', allow_multiples)) if only_dirs: data.append(serialize_binary('ONLY_DIRS', only_dirs)) + if initial_folder is not None: + initial_folder = process_path(initial_folder) + if os.path.isdir(initial_folder): + data.append(serialize_string('FOLDER', initial_folder)) + if filename: + if isinstance(filename, bytes): + filename = filename.decode(filesystem_encoding) + data.append(serialize_string('FILENAME', filename)) loop = Loop() h = Helper(subprocess.Popen( [HELPER], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE), @@ -112,7 +138,7 @@ if __name__ == '__main__': q = QMainWindow() def clicked(): - print(run_file_dialog(b, 'Testing dialogs', '~')), sys.stdout.flush() + print(run_file_dialog(b, 'Testing dialogs', save_as=True, save_path='~/xxx.fdgdfg')), sys.stdout.flush() b = QPushButton('click me') b.clicked.connect(clicked)