Example #1
0
// 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;
}
// 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 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<quint32> 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<<currentOffset;
            //Here the COMMON_ITEM_DIALOG API always add the details for the filter (e.g. *.txt)
            //so we don't need to handle the flag HideNameFilterDetails.
            winfilters += subfilter; // The name of the filter.
            winfilters += QChar();
            currentOffset += subfilter.size()+1;
            offsets<<currentOffset;
            QString spec = qt_win_extract_filter(subfilter);
            winfilters += spec; // The actual filter spec.
            winfilters += QChar();
            currentOffset += spec.size()+1;
            numFilters++;
        }
    }
    // Add the filters to the file dialog.
    if (numFilters) {
        wchar_t *szData = (wchar_t*)winfilters.utf16();
        COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[numFilters];
        for(int i = 0; i<numFilters; i++) {
            filterSpec[i].pszName = szData+offsets[i*2];
            filterSpec[i].pszSpec = szData+offsets[(i*2)+1];
        }
        hr = pfd->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;
        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);
}
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();
}