diff -r 000000000000 -r 1918ee327afb src/gui/dialogs/qfiledialog_win.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui/dialogs/qfiledialog_win.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,801 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfiledialog.h" + +#ifndef QT_NO_FILEDIALOG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_THREAD +# include +#endif + +#include +//At some point we can hope that mingw will support that interface +#if !defined(Q_WS_WINCE) && !defined(Q_CC_MINGW) +#include +#endif + +#include + +#if defined(__IFileDialog_INTERFACE_DEFINED__) \ + && defined(__IFileOpenDialog_INTERFACE_DEFINED__) +#define USE_COMMON_ITEM_DIALOG +#endif + +#ifdef Q_WS_WINCE +#include +# ifndef BFFM_SETSELECTION +# define BFFM_SETSELECTION (WM_USER + 102) +# endif +// Windows Mobile has a broken definition for BROWSEINFO +// Only compile fix +typedef struct qt_priv_browseinfo { + HWND hwndOwner; + LPCITEMIDLIST pidlRoot; + LPWSTR pszDisplayName; + LPCWSTR lpszTitle; + UINT ulFlags; + BFFCALLBACK lpfn; + LPARAM lParam; + int iImage; +} qt_BROWSEINFO; +bool qt_priv_ptr_valid = false; +#endif + + +// Don't remove the lines below! +// +// resolving the W methods manually is needed, because Windows 95 doesn't include +// these methods in Shell32.lib (not even stubs!), so you'd get an unresolved symbol +// when Qt calls getExistingDirectory(), etc. +typedef LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(BROWSEINFO*); +static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0; +typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR); +static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0; +typedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *); +static PtrSHGetMalloc ptrSHGetMalloc = 0; + + +QT_BEGIN_NAMESPACE + +static void qt_win_resolve_libs() +{ + static bool triedResolve = false; + + if (!triedResolve) { +#ifndef QT_NO_THREAD + // protect initialization + QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); + // check triedResolve again, since another thread may have already + // done the initialization + if (triedResolve) { + // another thread did initialize the security function pointers, + // so we shouldn't do it again. + return; + } +#endif + + triedResolve = true; +#if !defined(Q_WS_WINCE) + QLibrary lib(QLatin1String("shell32")); + ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW"); + ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW"); + ptrSHGetMalloc = (PtrSHGetMalloc) lib.resolve("SHGetMalloc"); +#else + // CE stores them in a different lib and does not use unicode version + HINSTANCE handle = LoadLibraryW(L"Ceshell"); + ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder"); + ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList"); + ptrSHGetMalloc = (PtrSHGetMalloc)GetProcAddress(handle, L"SHGetMalloc"); + if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList && ptrSHGetMalloc) + qt_priv_ptr_valid = true; +#endif + } +} + +extern const char* qt_file_dialog_filter_reg_exp; // defined in qfiledialog.cpp +extern QStringList qt_make_filter_list(const QString &filter); + +const int maxNameLen = 1023; +const int maxMultiLen = 65535; + +// Returns the wildcard part of a filter. +static QString qt_win_extract_filter(const QString &rawFilter) +{ + QString result = rawFilter; + QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); + int index = r.indexIn(result); + if (index >= 0) + result = r.cap(2); + QStringList list = result.split(QLatin1Char(' ')); + for(QStringList::iterator it = list.begin(); it < list.end(); ++it) { + if (*it == QLatin1String("*")) { + *it = QLatin1String("*.*"); + break; + } + } + return list.join(QLatin1String(";")); +} + +static QStringList qt_win_make_filters_list(const QString &filter) +{ + QString f(filter); + + if (f.isEmpty()) + f = QFileDialog::tr("All Files (*.*)"); + + return qt_make_filter_list(f); +} + +// Makes a NUL-oriented Windows filter from a Qt filter. +static QString qt_win_filter(const QString &filter, bool hideFiltersDetails) +{ + QStringList filterLst = qt_win_make_filters_list(filter); + QStringList::Iterator it = filterLst.begin(); + QString winfilters; + QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); + for (; it != filterLst.end(); ++it) { + QString subfilter = *it; + if (!subfilter.isEmpty()) { + if (hideFiltersDetails) { + int index = r.indexIn(subfilter); + if (index >= 0) + winfilters += r.cap(1); + } else { + winfilters += subfilter; + } + winfilters += QChar(); + winfilters += qt_win_extract_filter(subfilter); + winfilters += QChar(); + } + } + winfilters += QChar(); + return winfilters; +} + +static QString qt_win_selected_filter(const QString &filter, DWORD idx) +{ + return qt_win_make_filters_list(filter).at((int)idx - 1); +} + +static QString tFilters, tTitle, tInitDir; + +static OPENFILENAME* qt_win_make_OFN(QWidget *parent, + const QString& initialSelection, + const QString& initialDirectory, + const QString& title, + const QString& filters, + QFileDialog::FileMode mode, + QFileDialog::Options options) +{ + if (parent) + parent = parent->window(); + else + parent = QApplication::activeWindow(); + + tInitDir = QDir::toNativeSeparators(initialDirectory); + tFilters = filters; + tTitle = title; + QString initSel = QDir::toNativeSeparators(initialSelection); + if (!initSel.isEmpty()) { + initSel.remove(QLatin1Char('<')); + initSel.remove(QLatin1Char('>')); + initSel.remove(QLatin1Char('\"')); + initSel.remove(QLatin1Char('|')); + } + + int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen; + wchar_t *tInitSel = new wchar_t[maxLen + 1]; + if (initSel.length() > 0 && initSel.length() <= maxLen) + memcpy(tInitSel, initSel.utf16(), (initSel.length()+1)*sizeof(QChar)); + else + tInitSel[0] = 0; + + OPENFILENAME* ofn = new OPENFILENAME; + memset(ofn, 0, sizeof(OPENFILENAME)); + + ofn->lStructSize = sizeof(OPENFILENAME); + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); + ofn->hwndOwner = parent ? parent->winId() : 0; + ofn->lpstrFilter = (wchar_t*)tFilters.utf16(); + ofn->lpstrFile = tInitSel; + ofn->nMaxFile = maxLen; + ofn->lpstrInitialDir = (wchar_t*)tInitDir.utf16(); + ofn->lpstrTitle = (wchar_t*)tTitle.utf16(); + ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_PATHMUSTEXIST); + if (mode == QFileDialog::ExistingFile || + mode == QFileDialog::ExistingFiles) + ofn->Flags |= (OFN_FILEMUSTEXIST); + if (mode == QFileDialog::ExistingFiles) + ofn->Flags |= (OFN_ALLOWMULTISELECT); + if (!(options & QFileDialog::DontConfirmOverwrite)) + ofn->Flags |= OFN_OVERWRITEPROMPT; + + return ofn; +} + +static void qt_win_clean_up_OFN(OPENFILENAME **ofn) +{ + delete [] (*ofn)->lpstrFile; + delete *ofn; + *ofn = 0; +} + +extern void qt_win_eatMouseMove(); + +QString qt_win_get_open_file_name(const QFileDialogArgs &args, + QString *initialDirectory, + QString *selectedFilter) +{ + QString result; + + QString isel = args.selection; + + if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:")) + initialDirectory->remove(0, 5); + QFileInfo fi(*initialDirectory); + + if (initialDirectory && !fi.isDir()) { + *initialDirectory = fi.absolutePath(); + if (isel.isEmpty()) + isel = fi.fileName(); + } + + if (!fi.exists()) + *initialDirectory = QDir::homePath(); + + DWORD selFilIdx = 0; + + int idx = 0; + if (selectedFilter) { + QStringList filterLst = qt_win_make_filters_list(args.filter); + idx = filterLst.indexOf(*selectedFilter); + } + + QDialog modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(args.parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails; + OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter, hideFiltersDetails), + QFileDialog::ExistingFile, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + result = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFN(&ofn); + + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + if (result.isEmpty()) + return result; + + fi = result; + *initialDirectory = fi.path(); + if (selectedFilter) + *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx); + return fi.absoluteFilePath(); +} + +QString qt_win_get_save_file_name(const QFileDialogArgs &args, + QString *initialDirectory, + QString *selectedFilter) +{ + QString result; + + QString isel = args.selection; + if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:")) + initialDirectory->remove(0, 5); + QFileInfo fi(*initialDirectory); + + if (initialDirectory && !fi.isDir()) { + *initialDirectory = fi.absolutePath(); + if (isel.isEmpty()) + isel = fi.fileName(); + } + + if (!fi.exists()) + *initialDirectory = QDir::homePath(); + + DWORD selFilIdx = 0; + + int idx = 0; + if (selectedFilter) { + QStringList filterLst = qt_win_make_filters_list(args.filter); + idx = filterLst.indexOf(*selectedFilter); + } + + QDialog modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(args.parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails; + // This block is used below for the lpstrDefExt member. + // Note that the current MSDN docs document this member wrong. + // It should rather be documented as "the default extension if no extension was given and if the + // current filter does not have a extension (e.g (*)). If the current filter have an extension, use + // the extension of the current filter" + QString defaultSaveExt; + if (selectedFilter && !selectedFilter->isEmpty()) { + defaultSaveExt = qt_win_extract_filter(*selectedFilter); + // make sure we only have the extension + int firstDot = defaultSaveExt.indexOf(QLatin1Char('.')); + if (firstDot != -1) { + defaultSaveExt.remove(0, firstDot + 1); + } else { + defaultSaveExt.clear(); + } + } + + OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter, hideFiltersDetails), + QFileDialog::AnyFile, + args.options); + + ofn->lpstrDefExt = (wchar_t*)defaultSaveExt.utf16(); + + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetSaveFileName(ofn)) { + result = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFN(&ofn); + +#if defined(Q_WS_WINCE) + int semIndex = result.indexOf(QLatin1Char(';')); + if (semIndex >= 0) + result = result.left(semIndex); +#endif + + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + if (result.isEmpty()) + return result; + + fi = result; + *initialDirectory = fi.path(); + if (selectedFilter) + *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx); + return fi.absoluteFilePath(); +} + + +#if defined(USE_COMMON_ITEM_DIALOG) + +typedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); +static PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0; + +static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd, + const QString& initialSelection, + const QString& initialDirectory, + const QString& title, + const QStringList& filterLst, + QFileDialog::FileMode mode, + QFileDialog::Options options) +{ + if (!pSHCreateItemFromParsingName) { + // This function is available only in Vista & above. + QLibrary shellLib(QLatin1String("Shell32")); + pSHCreateItemFromParsingName = (PtrSHCreateItemFromParsingName) + shellLib.resolve("SHCreateItemFromParsingName"); + if (!pSHCreateItemFromParsingName) + return false; + } + HRESULT hr; + QString winfilters; + int numFilters = 0; + quint32 currentOffset = 0; + QList offsets; + QStringList::ConstIterator it = filterLst.begin(); + // Create the native filter string and save offset to each entry. + for (; it != filterLst.end(); ++it) { + QString subfilter = *it; + if (!subfilter.isEmpty()) { + offsets<SetFileTypes(numFilters, filterSpec); + delete []filterSpec; + } + // Set the starting folder. + tInitDir = QDir::toNativeSeparators(initialDirectory); + if (!tInitDir.isEmpty()) { + IShellItem *psiDefaultFolder; + hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(), + NULL, + IID_PPV_ARGS(&psiDefaultFolder)); + + if (SUCCEEDED(hr)) { + hr = pfd->SetFolder(psiDefaultFolder); + psiDefaultFolder->Release(); + } + } + // Set the currently selected file. + QString initSel = QDir::toNativeSeparators(initialSelection); + if (!initSel.isEmpty()) { + initSel.remove(QLatin1Char('<')); + initSel.remove(QLatin1Char('>')); + initSel.remove(QLatin1Char('\"')); + initSel.remove(QLatin1Char('|')); + } + if (!initSel.isEmpty()) { + hr = pfd->SetFileName((wchar_t*)initSel.utf16()); + } + // Set the title for the file dialog. + if (!title.isEmpty()) { + hr = pfd->SetTitle((wchar_t*)title.utf16()); + } + // Set other flags for the dialog. + DWORD newOptions; + hr = pfd->GetOptions(&newOptions); + if (SUCCEEDED(hr)) { + newOptions |= (FOS_NOCHANGEDIR | FOS_NOREADONLYRETURN); + if (mode == QFileDialog::ExistingFile || + mode == QFileDialog::ExistingFiles) + newOptions |= (FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST); + if (mode == QFileDialog::ExistingFiles) + newOptions |= FOS_ALLOWMULTISELECT; + if (!(options & QFileDialog::DontConfirmOverwrite)) + newOptions |= FOS_OVERWRITEPROMPT; + hr = pfd->SetOptions(newOptions); + } + return SUCCEEDED(hr); +} + +QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args, + QString *initialDirectory, + const QStringList &filterList, + QString *selectedFilter, + int selectedFilterIndex) +{ + QStringList result; + QDialog modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(args.parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + // Multiple selection is allowed only in IFileOpenDialog. + IFileOpenDialog *pfd; + HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&pfd)); + + if (SUCCEEDED(hr)) { + qt_win_set_IFileDialogOptions(pfd, args.selection, + args.directory, args.caption, + filterList, QFileDialog::ExistingFiles, + args.options); + // Set the currently selected filter (one-based index). + hr = pfd->SetFileTypeIndex(selectedFilterIndex+1); + QWidget *parentWindow = args.parent; + if (parentWindow) + parentWindow = parentWindow->window(); + else + parentWindow = QApplication::activeWindow(); + // Show the file dialog. + hr = pfd->Show(parentWindow ? parentWindow->winId() : 0); + if (SUCCEEDED(hr)) { + // Retrieve the results. + IShellItemArray *psiaResults; + hr = pfd->GetResults(&psiaResults); + if (SUCCEEDED(hr)) { + DWORD numItems = 0; + psiaResults->GetCount(&numItems); + for (DWORD i = 0; iGetItemAt(i, &psi); + if (SUCCEEDED(hr)) { + // Retrieve the file name from shell item. + wchar_t *pszPath; + hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath); + if (SUCCEEDED(hr)) { + QString fileName = QString::fromWCharArray(pszPath); + result.append(fileName); + CoTaskMemFree(pszPath); + } + psi->Release(); // Free the current item. + } + } + psiaResults->Release(); // Free the array of items. + } + } + } + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + if (!result.isEmpty()) { + // Retrieve the current folder name. + IShellItem *psi = 0; + hr = pfd->GetFolder(&psi); + if (SUCCEEDED(hr)) { + wchar_t *pszPath; + hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath); + if (SUCCEEDED(hr)) { + *initialDirectory = QString::fromWCharArray(pszPath); + CoTaskMemFree(pszPath); + } + psi->Release(); + } + // Retrieve the currently selected filter. + if (selectedFilter) { + quint32 filetype = 0; + hr = pfd->GetFileTypeIndex(&filetype); + if (SUCCEEDED(hr) && filetype && filetype <= (quint32)filterList.length()) { + // This is a one-based index, not zero-based. + *selectedFilter = filterList[filetype-1]; + } + } + } + return result; +} + +#endif + +QStringList qt_win_get_open_file_names(const QFileDialogArgs &args, + QString *initialDirectory, + QString *selectedFilter) +{ + QFileInfo fi; + QDir dir; + + if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:")) + initialDirectory->remove(0, 5); + fi = QFileInfo(*initialDirectory); + + if (initialDirectory && !fi.isDir()) { + *initialDirectory = fi.absolutePath(); + } + + if (!fi.exists()) + *initialDirectory = QDir::homePath(); + + DWORD selFilIdx = 0; + + QStringList filterLst = qt_win_make_filters_list(args.filter); + int idx = 0; + if (selectedFilter) { + idx = filterLst.indexOf(*selectedFilter); + } + // Windows Vista (& above) allows users to search from file dialogs. If user selects + // multiple files belonging to different folders from these search results, the + // GetOpenFileName() will return only one folder name for all the files. To retrieve + // the correct path for all selected files, we have to use Common Item Dialog interfaces. +#if defined(USE_COMMON_ITEM_DIALOG) + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) + return qt_win_CID_get_open_file_names(args, initialDirectory, filterLst, selectedFilter, idx); +#endif + + QStringList result; + QDialog modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(args.parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails; + OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter, hideFiltersDetails), + QFileDialog::ExistingFiles, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + int offset = fileOrDir.length() + 1; + if (ofn->lpstrFile[offset] == 0) { + // Only one file selected; has full path + fi.setFile(fileOrDir); + QString res = fi.absoluteFilePath(); + if (!res.isEmpty()) + result.append(res); + } + else { + // Several files selected; first string is path + dir.setPath(fileOrDir); + QString f; + while(!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) { + fi.setFile(dir, f); + QString res = fi.absoluteFilePath(); + if (!res.isEmpty()) + result.append(res); + offset += f.length() + 1; + } + } + } + qt_win_clean_up_OFN(&ofn); + + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + if (!result.isEmpty()) { + *initialDirectory = fi.path(); // only save the path if there is a result + if (selectedFilter) + *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx); + } + return result; +} + +// MFC Directory Dialog. Contrib: Steve Williams (minor parts from Scott Powers) + +static int __stdcall winGetExistDirCallbackProc(HWND hwnd, + UINT uMsg, + LPARAM lParam, + LPARAM lpData) +{ + if (uMsg == BFFM_INITIALIZED && lpData != 0) { + QString *initDir = (QString *)(lpData); + if (!initDir->isEmpty()) { + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); + } + } else if (uMsg == BFFM_SELCHANGED) { + qt_win_resolve_libs(); + if (ptrSHGetPathFromIDList) { + wchar_t path[MAX_PATH]; + ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path); + QString tmpStr = QString::fromWCharArray(path); + if (!tmpStr.isEmpty()) + SendMessage(hwnd, BFFM_ENABLEOK, 1, 1); + else + SendMessage(hwnd, BFFM_ENABLEOK, 0, 0); + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path)); + } + } + return 0; +} + +#ifndef BIF_NEWDIALOGSTYLE +#define BIF_NEWDIALOGSTYLE 0x0040 // Use the new dialog layout with the ability to resize +#endif + + +QString qt_win_get_existing_directory(const QFileDialogArgs &args) +{ + QString currentDir = QDir::currentPath(); + QString result; + QWidget *parent = args.parent; + if (parent) + parent = parent->window(); + else + parent = QApplication::activeWindow(); + if (parent) + parent->createWinId(); + + QDialog modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString initDir = QDir::toNativeSeparators(args.directory); + wchar_t path[MAX_PATH]; + wchar_t initPath[MAX_PATH]; + initPath[0] = 0; + path[0] = 0; + tTitle = args.caption; + +#if !defined(Q_WS_WINCE) + BROWSEINFO bi; +#else + qt_BROWSEINFO bi; +#endif + + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); + bi.hwndOwner = (parent ? parent->winId() : 0); + bi.pidlRoot = NULL; + //### This does not seem to be respected? - the dialog always displays "Browse for folder" + bi.lpszTitle = (wchar_t*)tTitle.utf16(); + bi.pszDisplayName = initPath; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; + bi.lpfn = winGetExistDirCallbackProc; + bi.lParam = LPARAM(&initDir); + + qt_win_resolve_libs(); + if (ptrSHBrowseForFolder) { + LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi); + if (pItemIDList) { + ptrSHGetPathFromIDList(pItemIDList, path); + IMalloc *pMalloc; + if (ptrSHGetMalloc(&pMalloc) == NOERROR) { + pMalloc->Free(pItemIDList); + pMalloc->Release(); + result = QString::fromWCharArray(path); + } + } + } + tTitle = QString(); + + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + if (!result.isEmpty()) + result.replace(QLatin1Char('\\'), QLatin1Char('/')); + return result; +} + + +QT_END_NAMESPACE + +#endif