Changeset 561 for trunk/src/gui/dialogs/qfiledialog_win.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/dialogs/qfiledialog_win.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you 37 ** @nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 60 60 61 61 #include <shlobj.h> 62 63 #ifdef Q_OS_WINCE 62 //At some point we can hope that mingw will support that interface 63 #if !defined(Q_WS_WINCE) && !defined(Q_CC_MINGW) 64 #include <shobjidl.h> 65 #endif 66 67 #include <objbase.h> 68 69 #if defined(__IFileDialog_INTERFACE_DEFINED__) \ 70 && defined(__IFileOpenDialog_INTERFACE_DEFINED__) 71 #define USE_COMMON_ITEM_DIALOG 72 #endif 73 74 #ifdef Q_WS_WINCE 64 75 #include <commdlg.h> 65 76 # ifndef BFFM_SETSELECTION … … 71 82 HWND hwndOwner; 72 83 LPCITEMIDLIST pidlRoot; 73 LP TSTR pszDisplayName;74 LPC TSTR lpszTitle;84 LPSTR pszDisplayName; 85 LPCSTR lpszTitle; 75 86 UINT ulFlags; 76 87 BFFCALLBACK lpfn; … … 91 102 typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR); 92 103 static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0; 104 105 106 93 107 94 108 QT_BEGIN_NAMESPACE … … 112 126 113 127 triedResolve = true; 114 if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { 115 #if !defined(Q_OS_WINCE) 116 QLibrary lib(QLatin1String("shell32"));117 ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW");118 ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW");128 #if !defined(Q_WS_WINCE) 129 QLibrary lib(QLatin1String("shell32")); 130 ); 131 W"); 132 "); 119 133 #else 120 121 122 123 124 if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList)125 qt_priv_ptr_valid = true;126 #endif 127 } 134 // CE stores them in a different lib and does not use unicode version 135 HINSTANCE handle = LoadLibraryW(L"Ceshell"); 136 ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder"); 137 ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList"); 138 139 140 qt_priv_ptr_valid = true; 141 #endif 128 142 } 129 143 } … … 164 178 165 179 // Makes a NUL-oriented Windows filter from a Qt filter. 166 static QString qt_win_filter(const QString &filter )180 static QString qt_win_filter(const QString &filter) 167 181 { 168 182 QStringList filterLst = qt_win_make_filters_list(filter); 169 183 QStringList::Iterator it = filterLst.begin(); 170 184 QString winfilters; 185 171 186 for (; it != filterLst.end(); ++it) { 172 187 QString subfilter = *it; 173 188 if (!subfilter.isEmpty()) { 174 winfilters += subfilter; 189 if (hideFiltersDetails) { 190 int index = r.indexIn(subfilter); 191 if (index >= 0) 192 winfilters += r.cap(1); 193 } else { 194 winfilters += subfilter; 195 } 175 196 winfilters += QChar(); 176 197 winfilters += qt_win_extract_filter(subfilter); … … 187 208 } 188 209 189 #ifndef Q_OS_WINCE190 // Static vars for OFNA funcs:191 static QByteArray aInitDir;192 static QByteArray aInitSel;193 static QByteArray aTitle;194 static QByteArray aFilter;195 // Use ANSI strings and API196 197 // If you change this, then make sure you change qt_win_make_OFN (below) too198 static OPENFILENAMEA *qt_win_make_OFNA(QWidget *parent,199 const QString &initialSelection,200 const QString &initialDirectory,201 const QString &title,202 const QString &filters,203 QFileDialog::FileMode mode,204 QFileDialog::Options options)205 {206 if (parent)207 parent = parent->window();208 else209 parent = qApp->activeWindow();210 211 aTitle = title.toLocal8Bit();212 aInitDir = QDir::toNativeSeparators(initialDirectory).toLocal8Bit();213 if (initialSelection.isEmpty()) {214 aInitSel = "";215 } else {216 aInitSel = QDir::toNativeSeparators(initialSelection).toLocal8Bit();217 aInitSel.replace("<", "");218 aInitSel.replace(">", "");219 aInitSel.replace("\"", "");220 aInitSel.replace("|", "");221 }222 int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;223 aInitSel.resize(maxLen + 1); // make room for return value224 aFilter = filters.toLocal8Bit();225 226 OPENFILENAMEA* ofn = new OPENFILENAMEA;227 memset(ofn, 0, sizeof(OPENFILENAMEA));228 229 #if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500)230 // according to the MSDN, this should also be necessary for MSVC, but231 // OPENFILENAME_SIZE_VERSION_400A is in not Microsoft header, as it seems232 if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) {233 ofn->lStructSize = OPENFILENAME_SIZE_VERSION_400A;234 } else {235 ofn->lStructSize = sizeof(OPENFILENAMEA);236 }237 #else238 ofn->lStructSize = sizeof(OPENFILENAMEA);239 #endif240 Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));241 ofn->hwndOwner = parent ? parent->winId() : 0;242 ofn->lpstrFilter = aFilter;243 ofn->lpstrFile = aInitSel.data();244 ofn->nMaxFile = maxLen;245 ofn->lpstrInitialDir = aInitDir.data();246 ofn->lpstrTitle = aTitle.data();247 ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER);248 249 if (mode == QFileDialog::ExistingFile ||250 mode == QFileDialog::ExistingFiles)251 ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);252 if (mode == QFileDialog::ExistingFiles)253 ofn->Flags |= (OFN_ALLOWMULTISELECT);254 if (!(options & QFileDialog::DontConfirmOverwrite))255 ofn->Flags |= OFN_OVERWRITEPROMPT;256 257 return ofn;258 }259 260 static void qt_win_clean_up_OFNA(OPENFILENAMEA **ofn)261 {262 delete *ofn;263 *ofn = 0;264 }265 #endif266 267 210 static QString tFilters, tTitle, tInitDir; 268 211 269 #ifdef UNICODE270 // If you change this, then make sure you change qt_win_make_OFNA (above) too271 212 static OPENFILENAME* qt_win_make_OFN(QWidget *parent, 272 213 const QString& initialSelection, … … 275 216 const QString& filters, 276 217 QFileDialog::FileMode mode, 277 218 QFileDialog::Options options) 278 219 { 279 220 if (parent) 280 221 parent = parent->window(); 281 222 else 282 parent = qApp->activeWindow();223 parent = activeWindow(); 283 224 284 225 tInitDir = QDir::toNativeSeparators(initialDirectory); … … 287 228 QString initSel = QDir::toNativeSeparators(initialSelection); 288 229 if (!initSel.isEmpty()) { 289 initSel.replace(QLatin1String("<"), QLatin1String(""));290 initSel.replace(QLatin1String(">"), QLatin1String(""));291 initSel.replace(QLatin1String("\""), QLatin1String(""));292 initSel.replace(QLatin1String("|"), QLatin1String(""));230 )); 231 )); 232 )); 233 )); 293 234 } 294 235 295 236 int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen; 296 TCHAR *tInitSel = new TCHAR[maxLen+1];237 1]; 297 238 if (initSel.length() > 0 && initSel.length() <= maxLen) 298 239 memcpy(tInitSel, initSel.utf16(), (initSel.length()+1)*sizeof(QChar)); … … 303 244 memset(ofn, 0, sizeof(OPENFILENAME)); 304 245 305 #if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500)306 // according to the MSDN, this should also be necessary for MSVC, but307 // OPENFILENAME_SIZE_VERSION_400 is in not Microsoft header, as it seems308 if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) {309 ofn->lStructSize= OPENFILENAME_SIZE_VERSION_400;310 } else {311 ofn->lStructSize = sizeof(OPENFILENAME);312 }313 #else314 246 ofn->lStructSize = sizeof(OPENFILENAME); 315 #endif316 247 Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); 317 248 ofn->hwndOwner = parent ? parent->winId() : 0; 318 ofn->lpstrFilter = ( TCHAR*)tFilters.utf16();249 ofn->lpstrFilter = (*)tFilters.utf16(); 319 250 ofn->lpstrFile = tInitSel; 320 251 ofn->nMaxFile = maxLen; 321 ofn->lpstrInitialDir = ( TCHAR*)tInitDir.utf16();322 ofn->lpstrTitle = ( TCHAR*)tTitle.utf16();323 ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER );252 ofn->lpstrInitialDir = (*)tInitDir.utf16(); 253 ofn->lpstrTitle = (*)tTitle.utf16(); 254 ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER); 324 255 if (mode == QFileDialog::ExistingFile || 325 256 mode == QFileDialog::ExistingFiles) 326 ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);257 ofn->Flags |= (OFN_FILEMUSTEXIST); 327 258 if (mode == QFileDialog::ExistingFiles) 328 259 ofn->Flags |= (OFN_ALLOWMULTISELECT); … … 333 264 } 334 265 335 336 266 static void qt_win_clean_up_OFN(OPENFILENAME **ofn) 337 267 { … … 340 270 *ofn = 0; 341 271 } 342 343 #endif // UNICODE344 272 345 273 extern void qt_win_eatMouseMove(); … … 378 306 modal_widget.setParent(args.parent, Qt::Window); 379 307 QApplicationPrivate::enterModal(&modal_widget); 380 QT_WA({ 381 // Use Unicode strings and API 382 OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, 383 args.directory, args.caption, 384 qt_win_filter(args.filter), 385 QFileDialog::ExistingFile, 386 args.options); 387 if (idx) 388 ofn->nFilterIndex = idx + 1; 389 if (GetOpenFileName(ofn)) { 390 result = QString::fromUtf16((ushort*)ofn->lpstrFile); 391 selFilIdx = ofn->nFilterIndex; 392 } 393 qt_win_clean_up_OFN(&ofn); 394 } , { 395 // Use ANSI strings and API 396 OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection, 397 args.directory, args.caption, 398 qt_win_filter(args.filter), 399 QFileDialog::ExistingFile, 400 args.options); 401 if (idx) 402 ofn->nFilterIndex = idx + 1; 403 if (GetOpenFileNameA(ofn)) { 404 result = QString::fromLocal8Bit(ofn->lpstrFile); 405 selFilIdx = ofn->nFilterIndex; 406 } 407 qt_win_clean_up_OFNA(&ofn); 408 }); 308 309 bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails; 310 OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, 311 args.directory, args.caption, 312 qt_win_filter(args.filter, hideFiltersDetails), 313 QFileDialog::ExistingFile, 314 args.options); 315 if (idx) 316 ofn->nFilterIndex = idx + 1; 317 if (GetOpenFileName(ofn)) { 318 result = QString::fromWCharArray(ofn->lpstrFile); 319 selFilIdx = ofn->nFilterIndex; 320 } 321 qt_win_clean_up_OFN(&ofn); 322 409 323 QApplicationPrivate::leaveModal(&modal_widget); 410 324 … … 423 337 QString qt_win_get_save_file_name(const QFileDialogArgs &args, 424 338 QString *initialDirectory, 425 339 QString *selectedFilter) 426 340 { 427 341 QString result; … … 453 367 modal_widget.setParent(args.parent, Qt::Window); 454 368 QApplicationPrivate::enterModal(&modal_widget); 455 369 bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails; 456 370 // This block is used below for the lpstrDefExt member. 457 371 // Note that the current MSDN docs document this member wrong. … … 471 385 } 472 386 473 QT_WA({ 474 // Use Unicode strings and API 475 OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection, 476 args.directory, args.caption, 477 qt_win_filter(args.filter), 478 QFileDialog::AnyFile, 479 args.options); 480 481 ofn->lpstrDefExt = (TCHAR *)defaultSaveExt.utf16(); 482 483 if (idx) 484 ofn->nFilterIndex = idx + 1; 485 if (GetSaveFileName(ofn)) { 486 result = QString::fromUtf16((ushort*)ofn->lpstrFile); 487 selFilIdx = ofn->nFilterIndex; 488 } 489 qt_win_clean_up_OFN(&ofn); 490 } , { 491 // Use ANSI strings and API 492 OPENFILENAMEA *ofn = qt_win_make_OFNA(args.parent, args.selection, 493 args.directory, args.caption, 494 qt_win_filter(args.filter), 495 QFileDialog::AnyFile, 496 args.options); 497 QByteArray asciiExt = defaultSaveExt.toAscii(); 498 ofn->lpstrDefExt = asciiExt.data(); 499 500 if (idx) 501 ofn->nFilterIndex = idx + 1; 502 if (GetSaveFileNameA(ofn)) { 503 result = QString::fromLocal8Bit(ofn->lpstrFile); 504 selFilIdx = ofn->nFilterIndex; 505 } 506 qt_win_clean_up_OFNA(&ofn); 507 }); 508 #if defined(Q_OS_WINCE) 387 OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection, 388 args.directory, args.caption, 389 qt_win_filter(args.filter, hideFiltersDetails), 390 QFileDialog::AnyFile, 391 args.options); 392 393 ofn->lpstrDefExt = (wchar_t*)defaultSaveExt.utf16(); 394 395 if (idx) 396 ofn->nFilterIndex = idx + 1; 397 if (GetSaveFileName(ofn)) { 398 result = QString::fromWCharArray(ofn->lpstrFile); 399 selFilIdx = ofn->nFilterIndex; 400 } 401 qt_win_clean_up_OFN(&ofn); 402 403 #if defined(Q_WS_WINCE) 509 404 int semIndex = result.indexOf(QLatin1Char(';')); 510 405 if (semIndex >= 0) … … 526 421 } 527 422 528 QStringList qt_win_get_open_file_names(const QFileDialogArgs &args, 423 424 #if defined(USE_COMMON_ITEM_DIALOG) 425 426 typedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv); 427 static PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0; 428 429 static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd, 430 const QString& initialSelection, 431 const QString& initialDirectory, 432 const QString& title, 433 const QStringList& filterLst, 434 QFileDialog::FileMode mode, 435 QFileDialog::Options options) 436 { 437 if (!pSHCreateItemFromParsingName) { 438 // This function is available only in Vista & above. 439 QLibrary shellLib(QLatin1String("Shell32")); 440 pSHCreateItemFromParsingName = (PtrSHCreateItemFromParsingName) 441 shellLib.resolve("SHCreateItemFromParsingName"); 442 if (!pSHCreateItemFromParsingName) 443 return false; 444 } 445 HRESULT hr; 446 QString winfilters; 447 int numFilters = 0; 448 quint32 currentOffset = 0; 449 QList<quint32> offsets; 450 QStringList::ConstIterator it = filterLst.begin(); 451 // Create the native filter string and save offset to each entry. 452 for (; it != filterLst.end(); ++it) { 453 QString subfilter = *it; 454 if (!subfilter.isEmpty()) { 455 offsets<<currentOffset; 456 //Here the COMMON_ITEM_DIALOG API always add the details for the filter (e.g. *.txt) 457 //so we don't need to handle the flag HideNameFilterDetails. 458 winfilters += subfilter; // The name of the filter. 459 winfilters += QChar(); 460 currentOffset += subfilter.size()+1; 461 offsets<<currentOffset; 462 QString spec = qt_win_extract_filter(subfilter); 463 winfilters += spec; // The actual filter spec. 464 winfilters += QChar(); 465 currentOffset += spec.size()+1; 466 numFilters++; 467 } 468 } 469 // Add the filters to the file dialog. 470 if (numFilters) { 471 wchar_t *szData = (wchar_t*)winfilters.utf16(); 472 COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[numFilters]; 473 for(int i = 0; i<numFilters; i++) { 474 filterSpec[i].pszName = szData+offsets[i*2]; 475 filterSpec[i].pszSpec = szData+offsets[(i*2)+1]; 476 } 477 hr = pfd->SetFileTypes(numFilters, filterSpec); 478 delete []filterSpec; 479 } 480 // Set the starting folder. 481 tInitDir = QDir::toNativeSeparators(initialDirectory); 482 if (!tInitDir.isEmpty()) { 483 IShellItem *psiDefaultFolder; 484 hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(), 485 NULL, 486 IID_PPV_ARGS(&psiDefaultFolder)); 487 488 if (SUCCEEDED(hr)) { 489 hr = pfd->SetFolder(psiDefaultFolder); 490 psiDefaultFolder->Release(); 491 } 492 } 493 // Set the currently selected file. 494 QString initSel = QDir::toNativeSeparators(initialSelection); 495 if (!initSel.isEmpty()) { 496 initSel.remove(QLatin1Char('<')); 497 initSel.remove(QLatin1Char('>')); 498 initSel.remove(QLatin1Char('\"')); 499 initSel.remove(QLatin1Char('|')); 500 } 501 if (!initSel.isEmpty()) { 502 hr = pfd->SetFileName((wchar_t*)initSel.utf16()); 503 } 504 // Set the title for the file dialog. 505 if (!title.isEmpty()) { 506 hr = pfd->SetTitle((wchar_t*)title.utf16()); 507 } 508 // Set other flags for the dialog. 509 DWORD newOptions; 510 hr = pfd->GetOptions(&newOptions); 511 if (SUCCEEDED(hr)) { 512 newOptions |= FOS_NOCHANGEDIR; 513 if (mode == QFileDialog::ExistingFile || 514 mode == QFileDialog::ExistingFiles) 515 newOptions |= (FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST); 516 if (mode == QFileDialog::ExistingFiles) 517 newOptions |= FOS_ALLOWMULTISELECT; 518 if (!(options & QFileDialog::DontConfirmOverwrite)) 519 newOptions |= FOS_OVERWRITEPROMPT; 520 hr = pfd->SetOptions(newOptions); 521 } 522 return SUCCEEDED(hr); 523 } 524 525 QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args, 529 526 QString *initialDirectory, 530 QString *selectedFilter) 527 const QStringList &filterList, 528 QString *selectedFilter, 529 int selectedFilterIndex) 531 530 { 532 531 QStringList result; 533 QFileInfo fi;534 QDir dir;535 QString isel;536 537 if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:"))538 initialDirectory->remove(0, 5);539 fi = QFileInfo(*initialDirectory);540 541 if (initialDirectory && !fi.isDir()) {542 *initialDirectory = fi.absolutePath();543 isel = fi.fileName();544 }545 546 if (!fi.exists())547 *initialDirectory = QDir::homePath();548 549 DWORD selFilIdx = 0;550 551 int idx = 0;552 if (selectedFilter) {553 QStringList filterLst = qt_win_make_filters_list(args.filter);554 idx = filterLst.indexOf(*selectedFilter);555 }556 557 532 QDialog modal_widget; 558 533 modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); 559 534 modal_widget.setParent(args.parent, Qt::Window); 560 535 QApplicationPrivate::enterModal(&modal_widget); 561 QT_WA({ 562 OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, 563 args.directory, args.caption, 564 qt_win_filter(args.filter), 565 QFileDialog::ExistingFiles, 566 args.options); 567 if (idx) 568 ofn->nFilterIndex = idx + 1; 569 if (GetOpenFileName(ofn)) { 570 QString fileOrDir = QString::fromUtf16((ushort*)ofn->lpstrFile); 571 selFilIdx = ofn->nFilterIndex; 572 int offset = fileOrDir.length() + 1; 573 if (ofn->lpstrFile[offset] == 0) { 574 // Only one file selected; has full path 575 fi.setFile(fileOrDir); 536 // Multiple selection is allowed only in IFileOpenDialog. 537 IFileOpenDialog *pfd = 0; 538 HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, 539 NULL, 540 CLSCTX_INPROC_SERVER, 541 IID_PPV_ARGS(&pfd)); 542 543 if (SUCCEEDED(hr)) { 544 qt_win_set_IFileDialogOptions(pfd, args.selection, 545 args.directory, args.caption, 546 filterList, QFileDialog::ExistingFiles, 547 args.options); 548 // Set the currently selected filter (one-based index). 549 hr = pfd->SetFileTypeIndex(selectedFilterIndex+1); 550 QWidget *parentWindow = args.parent; 551 if (parentWindow) 552 parentWindow = parentWindow->window(); 553 else 554 parentWindow = QApplication::activeWindow(); 555 // Show the file dialog. 556 hr = pfd->Show(parentWindow ? parentWindow->winId() : 0); 557 if (SUCCEEDED(hr)) { 558 // Retrieve the results. 559 IShellItemArray *psiaResults; 560 hr = pfd->GetResults(&psiaResults); 561 if (SUCCEEDED(hr)) { 562 DWORD numItems = 0; 563 psiaResults->GetCount(&numItems); 564 for (DWORD i = 0; i<numItems; i++) { 565 IShellItem *psi = 0; 566 hr = psiaResults->GetItemAt(i, &psi); 567 if (SUCCEEDED(hr)) { 568 // Retrieve the file name from shell item. 569 wchar_t *pszPath; 570 hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath); 571 if (SUCCEEDED(hr)) { 572 QString fileName = QString::fromWCharArray(pszPath); 573 result.append(fileName); 574 CoTaskMemFree(pszPath); 575 } 576 psi->Release(); // Free the current item. 577 } 578 } 579 psiaResults->Release(); // Free the array of items. 580 } 581 } 582 } 583 QApplicationPrivate::leaveModal(&modal_widget); 584 585 qt_win_eatMouseMove(); 586 587 if (!result.isEmpty()) { 588 // Retrieve the current folder name. 589 IShellItem *psi = 0; 590 hr = pfd->GetFolder(&psi); 591 if (SUCCEEDED(hr)) { 592 wchar_t *pszPath; 593 hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath); 594 if (SUCCEEDED(hr)) { 595 *initialDirectory = QString::fromWCharArray(pszPath); 596 CoTaskMemFree(pszPath); 597 } 598 psi->Release(); 599 } 600 // Retrieve the currently selected filter. 601 if (selectedFilter) { 602 quint32 filetype = 0; 603 hr = pfd->GetFileTypeIndex(&filetype); 604 if (SUCCEEDED(hr) && filetype && filetype <= (quint32)filterList.length()) { 605 // This is a one-based index, not zero-based. 606 *selectedFilter = filterList[filetype-1]; 607 } 608 } 609 } 610 if (pfd) 611 pfd->Release(); 612 return result; 613 } 614 615 #endif 616 617 QStringList qt_win_get_open_file_names(const QFileDialogArgs &args, 618 QString *initialDirectory, 619 QString *selectedFilter) 620 { 621 QFileInfo fi; 622 QDir dir; 623 624 if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:")) 625 initialDirectory->remove(0, 5); 626 fi = QFileInfo(*initialDirectory); 627 628 if (initialDirectory && !fi.isDir()) { 629 *initialDirectory = fi.absolutePath(); 630 } 631 632 if (!fi.exists()) 633 *initialDirectory = QDir::homePath(); 634 635 DWORD selFilIdx = 0; 636 637 QStringList filterLst = qt_win_make_filters_list(args.filter); 638 int idx = 0; 639 if (selectedFilter) { 640 idx = filterLst.indexOf(*selectedFilter); 641 } 642 // Windows Vista (& above) allows users to search from file dialogs. If user selects 643 // multiple files belonging to different folders from these search results, the 644 // GetOpenFileName() will return only one folder name for all the files. To retrieve 645 // the correct path for all selected files, we have to use Common Item Dialog interfaces. 646 #if defined(USE_COMMON_ITEM_DIALOG) 647 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) 648 return qt_win_CID_get_open_file_names(args, initialDirectory, filterLst, selectedFilter, idx); 649 #endif 650 651 QStringList result; 652 QDialog modal_widget; 653 modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); 654 modal_widget.setParent(args.parent, Qt::Window); 655 QApplicationPrivate::enterModal(&modal_widget); 656 657 bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails; 658 OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, 659 args.directory, args.caption, 660 qt_win_filter(args.filter, hideFiltersDetails), 661 QFileDialog::ExistingFiles, 662 args.options); 663 if (idx) 664 ofn->nFilterIndex = idx + 1; 665 if (GetOpenFileName(ofn)) { 666 QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile); 667 selFilIdx = ofn->nFilterIndex; 668 int offset = fileOrDir.length() + 1; 669 if (ofn->lpstrFile[offset] == 0) { 670 // Only one file selected; has full path 671 fi.setFile(fileOrDir); 672 QString res = fi.absoluteFilePath(); 673 if (!res.isEmpty()) 674 result.append(res); 675 } 676 else { 677 // Several files selected; first string is path 678 dir.setPath(fileOrDir); 679 QString f; 680 while(!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) { 681 fi.setFile(dir, f); 576 682 QString res = fi.absoluteFilePath(); 577 683 if (!res.isEmpty()) 578 684 result.append(res); 685 579 686 } 580 else { 581 // Several files selected; first string is path 582 dir.setPath(fileOrDir); 583 QString f; 584 while(!(f = QString::fromUtf16((ushort*)ofn->lpstrFile+offset)).isEmpty()) { 585 fi.setFile(dir, f); 586 QString res = fi.absoluteFilePath(); 587 if (!res.isEmpty()) 588 result.append(res); 589 offset += f.length() + 1; 590 } 591 } 592 } 593 qt_win_clean_up_OFN(&ofn); 594 } , { 595 OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection, 596 args.directory, args.caption, 597 qt_win_filter(args.filter), 598 QFileDialog::ExistingFiles, 599 args.options); 600 if (idx) 601 ofn->nFilterIndex = idx + 1; 602 if (GetOpenFileNameA(ofn)) { 603 QByteArray fileOrDir(ofn->lpstrFile); 604 selFilIdx = ofn->nFilterIndex; 605 int offset = fileOrDir.length() + 1; 606 if (ofn->lpstrFile[offset] == '\0') { 607 // Only one file selected; has full path 608 fi.setFile(QString::fromLocal8Bit(fileOrDir)); 609 QString res = fi.absoluteFilePath(); 610 if (!res.isEmpty()) 611 result.append(res); 612 } 613 else { 614 // Several files selected; first string is path 615 dir.setPath(QString::fromLocal8Bit(fileOrDir)); 616 QByteArray f; 617 while (!(f = QByteArray(ofn->lpstrFile + offset)).isEmpty()) { 618 fi.setFile(dir, QString::fromLocal8Bit(f)); 619 QString res = fi.absoluteFilePath(); 620 if (!res.isEmpty()) 621 result.append(res); 622 offset += f.length() + 1; 623 } 624 } 625 qt_win_clean_up_OFNA(&ofn); 626 } 627 }); 687 } 688 } 689 qt_win_clean_up_OFN(&ofn); 690 628 691 QApplicationPrivate::leaveModal(&modal_widget); 629 692 … … 648 711 QString *initDir = (QString *)(lpData); 649 712 if (!initDir->isEmpty()) { 650 // ### Lars asks: is this correct for the A version???? 651 QT_WA({ 652 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); 653 } , { 654 SendMessageA(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); 655 }); 713 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); 656 714 } 657 715 } else if (uMsg == BFFM_SELCHANGED) { 658 QT_WA({659 qt_win_resolve_libs();660 TCHARpath[MAX_PATH];716 717 718 path[MAX_PATH]; 661 719 ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path); 662 QString tmpStr = QString::from Utf16((ushort*)path);720 QString tmpStr = QString::frompath); 663 721 if (!tmpStr.isEmpty()) 664 722 SendMessage(hwnd, BFFM_ENABLEOK, 1, 1); … … 666 724 SendMessage(hwnd, BFFM_ENABLEOK, 0, 0); 667 725 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path)); 668 } , { 669 char path[MAX_PATH]; 670 SHGetPathFromIDListA(LPITEMIDLIST(lParam), path); 671 QString tmpStr = QString::fromLocal8Bit(path); 672 if (!tmpStr.isEmpty()) 673 SendMessageA(hwnd, BFFM_ENABLEOK, 1, 1); 674 else 675 SendMessageA(hwnd, BFFM_ENABLEOK, 0, 0); 676 SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path)); 677 }); 726 } 678 727 } 679 728 return 0; … … 693 742 parent = parent->window(); 694 743 else 695 parent = qApp->activeWindow();744 parent = activeWindow(); 696 745 if (parent) 697 746 parent->createWinId(); … … 701 750 modal_widget.setParent(parent, Qt::Window); 702 751 QApplicationPrivate::enterModal(&modal_widget); 703 #if !defined(Q_OS_WINCE) 704 QT_WA({ 705 qt_win_resolve_libs(); 706 QString initDir = QDir::toNativeSeparators(args.directory); 707 TCHAR path[MAX_PATH]; 708 TCHAR initPath[MAX_PATH]; 709 initPath[0] = 0; 710 path[0] = 0; 711 tTitle = args.caption; 712 BROWSEINFO bi; 713 Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); 714 bi.hwndOwner = (parent ? parent->winId() : 0); 715 bi.pidlRoot = NULL; 716 //### This does not seem to be respected? - the dialog always displays "Browse for folder" 717 bi.lpszTitle = (TCHAR*)tTitle.utf16(); 718 bi.pszDisplayName = initPath; 719 bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; 720 bi.lpfn = winGetExistDirCallbackProc; 721 bi.lParam = LPARAM(&initDir); 722 if (ptrSHBrowseForFolder) { 723 LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi); 724 if (pItemIDList && ptrSHGetPathFromIDList) { 725 ptrSHGetPathFromIDList(pItemIDList, path); 726 IMalloc *pMalloc; 727 if (SHGetMalloc(&pMalloc) != NOERROR) 728 result = QString(); 729 else { 730 pMalloc->Free(pItemIDList); 731 pMalloc->Release(); 732 result = QString::fromUtf16((ushort*)path); 733 } 734 } else 735 result = QString(); 736 } 737 tTitle = QString(); 738 } , { 739 QString initDir = QDir::toNativeSeparators(args.directory); 740 char path[MAX_PATH]; 741 char initPath[MAX_PATH]; 742 QByteArray ctitle = args.caption.toLocal8Bit(); 743 initPath[0]=0; 744 path[0]=0; 745 BROWSEINFOA bi; 746 Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); 747 bi.hwndOwner = (parent ? parent->winId() : 0); 748 bi.pidlRoot = NULL; 749 bi.lpszTitle = ctitle; 750 bi.pszDisplayName = initPath; 751 bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; 752 bi.lpfn = winGetExistDirCallbackProc; 753 bi.lParam = LPARAM(&initDir); 754 LPITEMIDLIST pItemIDList = SHBrowseForFolderA(&bi); 755 if (pItemIDList) { 756 SHGetPathFromIDListA(pItemIDList, path); 757 IMalloc *pMalloc; 758 if (SHGetMalloc(&pMalloc) != NOERROR) 759 result = QString(); 760 else { 761 pMalloc->Free(pItemIDList); 762 pMalloc->Release(); 763 result = QString::fromLocal8Bit(path); 764 } 765 } else 766 result = QString(); 767 }); 752 753 QString initDir = QDir::toNativeSeparators(args.directory); 754 wchar_t path[MAX_PATH]; 755 wchar_t initPath[MAX_PATH]; 756 initPath[0] = 0; 757 path[0] = 0; 758 tTitle = args.caption; 759 760 #if !defined(Q_WS_WINCE) 761 BROWSEINFO bi; 768 762 #else 769 qt_win_resolve_libs();770 QString initDir = QDir::toNativeSeparators(args.directory);771 TCHAR path[MAX_PATH];772 TCHAR initPath[MAX_PATH];773 memset(initPath, 0 , MAX_PATH*sizeof(TCHAR));774 memset(path, 0, MAX_PATH*sizeof(TCHAR));775 tTitle = args.caption;776 763 qt_BROWSEINFO bi; 764 765 777 766 Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); 778 767 bi.hwndOwner = (parent ? parent->winId() : 0); 779 768 bi.pidlRoot = NULL; 780 bi.lpszTitle = (TCHAR*)tTitle.utf16(); 769 //### This does not seem to be respected? - the dialog always displays "Browse for folder" 770 bi.lpszTitle = (wchar_t*)tTitle.utf16(); 781 771 bi.pszDisplayName = initPath; 782 772 bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; 783 773 bi.lpfn = winGetExistDirCallbackProc; 784 774 bi.lParam = LPARAM(&initDir); 775 776 785 777 if (ptrSHBrowseForFolder) { 786 778 LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi); 787 if (pItemIDList && ptrSHGetPathFromIDList) {779 if (pItemIDList) { 788 780 ptrSHGetPathFromIDList(pItemIDList, path); 789 781 IMalloc *pMalloc; 790 if (SHGetMalloc(&pMalloc) != NOERROR) 791 result = QString(); 792 else { 782 if (ptrSHGetMalloc(&pMalloc) == NOERROR) { 793 783 pMalloc->Free(pItemIDList); 794 784 pMalloc->Release(); 795 result = QString::from Utf16((ushort*)path);785 result = QString::frompath); 796 786 } 797 } else 798 result = QString(); 787 } 799 788 } 800 789 tTitle = QString(); 801 790 802 #endif803 791 QApplicationPrivate::leaveModal(&modal_widget); 804 792 805 793 qt_win_eatMouseMove(); 806 794 807 // Due to a bug on Windows Me, we need to reset the current808 // directory809 if ((QSysInfo::WindowsVersion == QSysInfo::WV_98 || QSysInfo::WindowsVersion == QSysInfo::WV_Me)810 && QDir::currentPath() != currentDir)811 QDir::setCurrent(currentDir);812 813 795 if (!result.isEmpty()) 814 result.replace(QLatin1 String("\\"), QLatin1String("/"));796 result.replace(QLatin1)); 815 797 return result; 816 798 }
Note:
See TracChangeset
for help on using the changeset viewer.