Esempio n. 1
0
QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args)
{
    QString result;
    QDialog modal_widget;
    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
    modal_widget.setParent(args.parent, Qt::Window);
    QApplicationPrivate::enterModal(&modal_widget);

    IFileOpenDialog *pfd = 0;
    HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
                                  QT_IID_IFileOpenDialog, reinterpret_cast<void**>(&pfd));

    if (SUCCEEDED(hr)) {
        qt_win_set_IFileDialogOptions(pfd, args.selection,
                                      args.directory, args.caption,
                                      QStringList(), QFileDialog::ExistingFile,
                                      args.options);

        // Set the FOS_PICKFOLDERS flag
        DWORD newOptions;
        hr = pfd->GetOptions(&newOptions);
        newOptions |= (FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
        if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) {
            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 result
                IShellItem *psi = 0;
                hr = pfd->GetResult(&psi);
                if (SUCCEEDED(hr)) {
                    // Retrieve the file name from shell item.
                    wchar_t *pszPath;
                    hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
                    if (SUCCEEDED(hr)) {
                        result = QString::fromWCharArray(pszPath);
                        CoTaskMemFree(pszPath);
                    }
                    psi->Release(); // Free the current item.
                }
            }
        }
    }
    QApplicationPrivate::leaveModal(&modal_widget);

    qt_win_eatMouseMove();

    if (pfd)
        pfd->Release();
    return result;
}
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;
}
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;
}
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 = 0;
    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; i<numItems; i++) {
                    IShellItem *psi = 0;
                    hr = psiaResults->GetItemAt(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];
            }
        }
    }
    if (pfd)
        pfd->Release();
    return result;
}
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();
}
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();
}
int QPrintDialogPrivate::openWindowsPrintDialogModally()
{
    Q_Q(QPrintDialog);
    QWidget *parent = q->parentWidget();
    if (parent)
        parent = parent->window();
    else
        parent = QApplication::activeWindow();

    // If there is no window, fall back to the print dialog itself
    if (parent == 0)
        parent = q;

    QWidget modal_widget;
    modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
    modal_widget.setParent(parent, Qt::Window);
    QApplicationPrivate::enterModal(&modal_widget);

    HGLOBAL *tempDevNames = ep->createDevNames();

    bool done;
    bool result;
    bool doPrinting;

    PRINTPAGERANGE pageRange;
    PRINTDLGEX pd;
    memset(&pd, 0, sizeof(PRINTDLGEX));
    pd.lStructSize = sizeof(PRINTDLGEX);
    pd.lpPageRanges = &pageRange;
    qt_win_setup_PRINTDLGEX(&pd, parent, q, this, tempDevNames);

    do {
        done = true;
        doPrinting = false;
        result = (PrintDlgEx(&pd) == S_OK);
        if (result && (pd.dwResultAction == PD_RESULT_PRINT
                       || pd.dwResultAction == PD_RESULT_APPLY))
        {
            doPrinting = (pd.dwResultAction == PD_RESULT_PRINT);
            if ((pd.Flags & PD_PAGENUMS)
                && (pd.lpPageRanges[0].nFromPage > pd.lpPageRanges[0].nToPage))
            {
                pd.lpPageRanges[0].nFromPage = 1;
                pd.lpPageRanges[0].nToPage = 1;
                done = false;
            }
            if (pd.hDC == 0)
                result = false;
        }

        if (!done) {
            QMessageBox::warning(0, QPrintDialog::tr("Print"),
                                 QPrintDialog::tr("The 'From' value cannot be greater than the 'To' value."),
                                 QPrintDialog::tr("OK"));
        }
    } while (!done);

    QApplicationPrivate::leaveModal(&modal_widget);

    qt_win_eatMouseMove();

    // write values back...
    if (result && (pd.dwResultAction == PD_RESULT_PRINT
                   || pd.dwResultAction == PD_RESULT_APPLY))
    {
        qt_win_read_back_PRINTDLGEX(&pd, q, this);
        // update printer validity
        printer->d_func()->validPrinter = !ep->name.isEmpty();
    }

    // Cleanup...
    GlobalFree(tempDevNames);

    q->done(result && doPrinting);

    return result && doPrinting;
}