diff options
author | Alexis Menard <alexis.menard@nokia.com> | 2009-04-17 10:40:52 (GMT) |
---|---|---|
committer | Alexis Menard <alexis.menard@nokia.com> | 2009-04-17 10:40:52 (GMT) |
commit | bb2e4df9bee3148e819c98410aa36e22dad95d7a (patch) | |
tree | a6e6e8c070a72378d4b2e5f39ad3cc9c368b61ab /src/gui/dialogs/qfiledialog_win.cpp | |
download | Qt-bb2e4df9bee3148e819c98410aa36e22dad95d7a.zip Qt-bb2e4df9bee3148e819c98410aa36e22dad95d7a.tar.gz Qt-bb2e4df9bee3148e819c98410aa36e22dad95d7a.tar.bz2 |
Initial import of kinetic-animations branch from the old kinetic
repository to the new repository
Diffstat (limited to 'src/gui/dialogs/qfiledialog_win.cpp')
-rw-r--r-- | src/gui/dialogs/qfiledialog_win.cpp | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp new file mode 100644 index 0000000..8431488 --- /dev/null +++ b/src/gui/dialogs/qfiledialog_win.cpp @@ -0,0 +1,821 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfiledialog.h" + +#ifndef QT_NO_FILEDIALOG + +#include <private/qfiledialog_p.h> +#include <qapplication.h> +#include <private/qapplication_p.h> +#include <qt_windows.h> +#include <qglobal.h> +#include <qregexp.h> +#include <qbuffer.h> +#include <qdir.h> +#include <qstringlist.h> +#include <qlibrary.h> + +#ifndef QT_NO_THREAD +# include <private/qmutexpool_p.h> +#endif + +#include <shlobj.h> + +#ifdef Q_OS_WINCE +#include <commdlg.h> +# 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; + LPTSTR pszDisplayName; + LPCTSTR 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; + +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 (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { +#if !defined(Q_OS_WINCE) + QLibrary lib(QLatin1String("shell32")); + ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW"); + ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW"); +#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"); + if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList) + 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) +{ + QStringList filterLst = qt_win_make_filters_list(filter); + QStringList::Iterator it = filterLst.begin(); + QString winfilters; + for (; it != filterLst.end(); ++it) { + QString subfilter = *it; + if (!subfilter.isEmpty()) { + 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); +} + +#ifndef Q_OS_WINCE +// Static vars for OFNA funcs: +static QByteArray aInitDir; +static QByteArray aInitSel; +static QByteArray aTitle; +static QByteArray aFilter; +// Use ANSI strings and API + +// If you change this, then make sure you change qt_win_make_OFN (below) too +static OPENFILENAMEA *qt_win_make_OFNA(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 = qApp->activeWindow(); + + aTitle = title.toLocal8Bit(); + aInitDir = QDir::toNativeSeparators(initialDirectory).toLocal8Bit(); + if (initialSelection.isEmpty()) { + aInitSel = ""; + } else { + aInitSel = QDir::toNativeSeparators(initialSelection).toLocal8Bit(); + aInitSel.replace("<", ""); + aInitSel.replace(">", ""); + aInitSel.replace("\"", ""); + aInitSel.replace("|", ""); + } + int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen; + aInitSel.resize(maxLen + 1); // make room for return value + aFilter = filters.toLocal8Bit(); + + OPENFILENAMEA* ofn = new OPENFILENAMEA; + memset(ofn, 0, sizeof(OPENFILENAMEA)); + +#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500) + // according to the MSDN, this should also be necessary for MSVC, but + // OPENFILENAME_SIZE_VERSION_400A is in not Microsoft header, as it seems + if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) { + ofn->lStructSize = OPENFILENAME_SIZE_VERSION_400A; + } else { + ofn->lStructSize = sizeof(OPENFILENAMEA); + } +#else + ofn->lStructSize = sizeof(OPENFILENAMEA); +#endif + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); + ofn->hwndOwner = parent ? parent->winId() : 0; + ofn->lpstrFilter = aFilter; + ofn->lpstrFile = aInitSel.data(); + ofn->nMaxFile = maxLen; + ofn->lpstrInitialDir = aInitDir.data(); + ofn->lpstrTitle = aTitle.data(); + ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER); + + if (mode == QFileDialog::ExistingFile || + mode == QFileDialog::ExistingFiles) + ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST); + if (mode == QFileDialog::ExistingFiles) + ofn->Flags |= (OFN_ALLOWMULTISELECT); + if (!(options & QFileDialog::DontConfirmOverwrite)) + ofn->Flags |= OFN_OVERWRITEPROMPT; + + return ofn; +} + +static void qt_win_clean_up_OFNA(OPENFILENAMEA **ofn) +{ + delete *ofn; + *ofn = 0; +} +#endif + +static QString tFilters, tTitle, tInitDir; + +#ifdef UNICODE +// If you change this, then make sure you change qt_win_make_OFNA (above) too +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 = qApp->activeWindow(); + + tInitDir = QDir::toNativeSeparators(initialDirectory); + tFilters = filters; + tTitle = title; + QString initSel = QDir::toNativeSeparators(initialSelection); + if (!initSel.isEmpty()) { + initSel.replace(QLatin1String("<"), QLatin1String("")); + initSel.replace(QLatin1String(">"), QLatin1String("")); + initSel.replace(QLatin1String("\""), QLatin1String("")); + initSel.replace(QLatin1String("|"), QLatin1String("")); + } + + int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen; + TCHAR *tInitSel = new TCHAR[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)); + +#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500) + // according to the MSDN, this should also be necessary for MSVC, but + // OPENFILENAME_SIZE_VERSION_400 is in not Microsoft header, as it seems + if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) { + ofn->lStructSize= OPENFILENAME_SIZE_VERSION_400; + } else { + ofn->lStructSize = sizeof(OPENFILENAME); + } +#else + ofn->lStructSize = sizeof(OPENFILENAME); +#endif + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); + ofn->hwndOwner = parent ? parent->winId() : 0; + ofn->lpstrFilter = (TCHAR *)tFilters.utf16(); + ofn->lpstrFile = tInitSel; + ofn->nMaxFile = maxLen; + ofn->lpstrInitialDir = (TCHAR *)tInitDir.utf16(); + ofn->lpstrTitle = (TCHAR *)tTitle.utf16(); + ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER); + if (mode == QFileDialog::ExistingFile || + mode == QFileDialog::ExistingFiles) + ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST); + 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; +} + +#endif // UNICODE + +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); + QT_WA({ + // Use Unicode strings and API + OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::ExistingFile, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + result = QString::fromUtf16((ushort*)ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFN(&ofn); + } , { + // Use ANSI strings and API + OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::ExistingFile, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileNameA(ofn)) { + result = QString::fromLocal8Bit(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFNA(&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); + + // 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(); + } + } + + QT_WA({ + // Use Unicode strings and API + OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::AnyFile, + args.options); + + ofn->lpstrDefExt = (TCHAR *)defaultSaveExt.utf16(); + + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetSaveFileName(ofn)) { + result = QString::fromUtf16((ushort*)ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFN(&ofn); + } , { + // Use ANSI strings and API + OPENFILENAMEA *ofn = qt_win_make_OFNA(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::AnyFile, + args.options); + QByteArray asciiExt = defaultSaveExt.toAscii(); + ofn->lpstrDefExt = asciiExt.data(); + + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetSaveFileNameA(ofn)) { + result = QString::fromLocal8Bit(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFNA(&ofn); + }); +#if defined(Q_OS_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(); +} + +QStringList qt_win_get_open_file_names(const QFileDialogArgs &args, + QString *initialDirectory, + QString *selectedFilter) +{ + QStringList result; + QFileInfo fi; + QDir dir; + QString isel; + + if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:")) + initialDirectory->remove(0, 5); + fi = QFileInfo(*initialDirectory); + + if (initialDirectory && !fi.isDir()) { + *initialDirectory = fi.absolutePath(); + 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); + QT_WA({ + OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::ExistingFiles, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + QString fileOrDir = QString::fromUtf16((ushort*)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::fromUtf16((ushort*)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); + } , { + OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::ExistingFiles, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileNameA(ofn)) { + QByteArray fileOrDir(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + int offset = fileOrDir.length() + 1; + if (ofn->lpstrFile[offset] == '\0') { + // Only one file selected; has full path + fi.setFile(QString::fromLocal8Bit(fileOrDir)); + QString res = fi.absoluteFilePath(); + if (!res.isEmpty()) + result.append(res); + } + else { + // Several files selected; first string is path + dir.setPath(QString::fromLocal8Bit(fileOrDir)); + QByteArray f; + while (!(f = QByteArray(ofn->lpstrFile + offset)).isEmpty()) { + fi.setFile(dir, QString::fromLocal8Bit(f)); + QString res = fi.absoluteFilePath(); + if (!res.isEmpty()) + result.append(res); + offset += f.length() + 1; + } + } + qt_win_clean_up_OFNA(&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()) { + // ### Lars asks: is this correct for the A version???? + QT_WA({ + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); + } , { + SendMessageA(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); + }); + } + } else if (uMsg == BFFM_SELCHANGED) { + QT_WA({ + qt_win_resolve_libs(); + TCHAR path[MAX_PATH]; + ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path); + QString tmpStr = QString::fromUtf16((ushort*)path); + if (!tmpStr.isEmpty()) + SendMessage(hwnd, BFFM_ENABLEOK, 1, 1); + else + SendMessage(hwnd, BFFM_ENABLEOK, 0, 0); + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path)); + } , { + char path[MAX_PATH]; + SHGetPathFromIDListA(LPITEMIDLIST(lParam), path); + QString tmpStr = QString::fromLocal8Bit(path); + if (!tmpStr.isEmpty()) + SendMessageA(hwnd, BFFM_ENABLEOK, 1, 1); + else + SendMessageA(hwnd, BFFM_ENABLEOK, 0, 0); + SendMessageA(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 = qApp->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); +#if !defined(Q_OS_WINCE) + QT_WA({ + qt_win_resolve_libs(); + QString initDir = QDir::toNativeSeparators(args.directory); + TCHAR path[MAX_PATH]; + TCHAR initPath[MAX_PATH]; + initPath[0] = 0; + path[0] = 0; + tTitle = args.caption; + BROWSEINFO bi; + 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 = (TCHAR*)tTitle.utf16(); + bi.pszDisplayName = initPath; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; + bi.lpfn = winGetExistDirCallbackProc; + bi.lParam = LPARAM(&initDir); + if (ptrSHBrowseForFolder) { + LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi); + if (pItemIDList && ptrSHGetPathFromIDList) { + ptrSHGetPathFromIDList(pItemIDList, path); + IMalloc *pMalloc; + if (SHGetMalloc(&pMalloc) != NOERROR) + result = QString(); + else { + pMalloc->Free(pItemIDList); + pMalloc->Release(); + result = QString::fromUtf16((ushort*)path); + } + } else + result = QString(); + } + tTitle = QString(); + } , { + QString initDir = QDir::toNativeSeparators(args.directory); + char path[MAX_PATH]; + char initPath[MAX_PATH]; + QByteArray ctitle = args.caption.toLocal8Bit(); + initPath[0]=0; + path[0]=0; + BROWSEINFOA bi; + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); + bi.hwndOwner = (parent ? parent->winId() : 0); + bi.pidlRoot = NULL; + bi.lpszTitle = ctitle; + bi.pszDisplayName = initPath; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; + bi.lpfn = winGetExistDirCallbackProc; + bi.lParam = LPARAM(&initDir); + LPITEMIDLIST pItemIDList = SHBrowseForFolderA(&bi); + if (pItemIDList) { + SHGetPathFromIDListA(pItemIDList, path); + IMalloc *pMalloc; + if (SHGetMalloc(&pMalloc) != NOERROR) + result = QString(); + else { + pMalloc->Free(pItemIDList); + pMalloc->Release(); + result = QString::fromLocal8Bit(path); + } + } else + result = QString(); + }); +#else + qt_win_resolve_libs(); + QString initDir = QDir::toNativeSeparators(args.directory); + TCHAR path[MAX_PATH]; + TCHAR initPath[MAX_PATH]; + memset(initPath, 0 , MAX_PATH*sizeof(TCHAR)); + memset(path, 0, MAX_PATH*sizeof(TCHAR)); + tTitle = args.caption; + qt_BROWSEINFO bi; + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); + bi.hwndOwner = (parent ? parent->winId() : 0); + bi.pidlRoot = NULL; + bi.lpszTitle = (TCHAR*)tTitle.utf16(); + bi.pszDisplayName = initPath; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; + bi.lpfn = winGetExistDirCallbackProc; + bi.lParam = LPARAM(&initDir); + if (ptrSHBrowseForFolder) { + LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi); + if (pItemIDList && ptrSHGetPathFromIDList) { + ptrSHGetPathFromIDList(pItemIDList, path); + IMalloc *pMalloc; + if (SHGetMalloc(&pMalloc) != NOERROR) + result = QString(); + else { + pMalloc->Free(pItemIDList); + pMalloc->Release(); + result = QString::fromUtf16((ushort*)path); + } + } else + result = QString(); + } + tTitle = QString(); + +#endif + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + // Due to a bug on Windows Me, we need to reset the current + // directory + if ((QSysInfo::WindowsVersion == QSysInfo::WV_98 || QSysInfo::WindowsVersion == QSysInfo::WV_Me) + && QDir::currentPath() != currentDir) + QDir::setCurrent(currentDir); + + if (!result.isEmpty()) + result.replace(QLatin1String("\\"), QLatin1String("/")); + return result; +} + + +QT_END_NAMESPACE + +#endif |