summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp')
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp596
1 files changed, 0 insertions, 596 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
deleted file mode 100644
index fee8063f13..0000000000
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwinrtfiledialoghelper.h"
-#include "qwinrtfileengine.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/QEventLoop>
-#include <QtCore/QMap>
-#include <QtCore/QVector>
-#include <QtCore/qfunctions_winrt.h>
-#include <private/qeventdispatcher_winrt_p.h>
-
-#include <functional>
-#include <wrl.h>
-#include <windows.foundation.h>
-#include <windows.storage.pickers.h>
-#include <Windows.Applicationmodel.Activation.h>
-
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-using namespace ABI::Windows::ApplicationModel::Activation;
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::Foundation::Collections;
-using namespace ABI::Windows::Storage;
-using namespace ABI::Windows::Storage::Pickers;
-
-typedef IAsyncOperationCompletedHandler<StorageFile *> SingleFileHandler;
-typedef IAsyncOperationCompletedHandler<IVectorView<StorageFile *> *> MultipleFileHandler;
-typedef IAsyncOperationCompletedHandler<StorageFolder *> SingleFolderHandler;
-
-QT_BEGIN_NAMESPACE
-
-// Required for save file picker
-class WindowsStringVector : public RuntimeClass<IVector<HSTRING>>
-{
-public:
- HRESULT __stdcall GetAt(quint32 index, HSTRING *item)
- {
- *item = impl.at(int(index));
- return S_OK;
- }
- HRESULT __stdcall get_Size(quint32 *size)
- {
- *size = quint32(impl.size());
- return S_OK;
- }
- HRESULT __stdcall GetView(IVectorView<HSTRING> **view)
- {
- *view = nullptr;
- return E_NOTIMPL;
- }
- HRESULT __stdcall IndexOf(HSTRING value, quint32 *index, boolean *found)
- {
- *found = false;
- for (int i = 0; i < impl.size(); ++i) {
- qint32 result;
- HRESULT hr = WindowsCompareStringOrdinal(impl.at(i), value, &result);
- if (FAILED(hr))
- return hr;
- if (result == 0) {
- *index = quint32(i);
- *found = true;
- break;
- }
- }
- return S_OK;
- }
- HRESULT __stdcall SetAt(quint32 index, HSTRING item)
- {
- HSTRING newItem;
- HRESULT hr = WindowsDuplicateString(item, &newItem);
- if (FAILED(hr))
- return hr;
- impl[int(index)] = newItem;
- return S_OK;
- }
- HRESULT __stdcall InsertAt(quint32 index, HSTRING item)
- {
- HSTRING newItem;
- HRESULT hr = WindowsDuplicateString(item, &newItem);
- if (FAILED(hr))
- return hr;
- impl.insert(int(index), newItem);
- return S_OK;
- }
- HRESULT __stdcall RemoveAt(quint32 index)
- {
- WindowsDeleteString(impl.takeAt(int(index)));
- return S_OK;
- }
- HRESULT __stdcall Append(HSTRING item)
- {
- HSTRING newItem;
- HRESULT hr = WindowsDuplicateString(item, &newItem);
- if (FAILED(hr))
- return hr;
- impl.append(newItem);
- return S_OK;
- }
- HRESULT __stdcall RemoveAtEnd()
- {
- WindowsDeleteString(impl.takeLast());
- return S_OK;
- }
- HRESULT __stdcall Clear()
- {
- foreach (const HSTRING &item, impl)
- WindowsDeleteString(item);
- impl.clear();
- return S_OK;
- }
-private:
- QVector<HSTRING> impl;
-};
-
-template<typename T>
-static bool initializePicker(HSTRING runtimeId, T **picker, const QSharedPointer<QFileDialogOptions> &options)
-{
- HRESULT hr;
-
- ComPtr<IInspectable> basePicker;
- hr = RoActivateInstance(runtimeId, &basePicker);
- RETURN_FALSE_IF_FAILED("Failed to instantiate file picker");
- hr = basePicker.Get()->QueryInterface(IID_PPV_ARGS(picker));
- RETURN_FALSE_IF_FAILED("Failed to cast file picker");
-
- if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
- const QString labelText = options->labelText(QFileDialogOptions::Accept);
- HStringReference labelTextRef(reinterpret_cast<const wchar_t *>(labelText.utf16()),
- uint(labelText.length()));
- hr = (*picker)->put_CommitButtonText(labelTextRef.Get());
- RETURN_FALSE_IF_FAILED("Failed to set commit button text");
- }
-
- return true;
-}
-
-template<typename T>
-static bool initializeOpenPickerOptions(T *picker, const QSharedPointer<QFileDialogOptions> &options)
-{
- HRESULT hr;
- hr = picker->put_ViewMode(options->viewMode() == QFileDialogOptions::Detail
- ? PickerViewMode_Thumbnail : PickerViewMode_List);
- RETURN_FALSE_IF_FAILED("Failed to set picker view mode");
-
- ComPtr<IVector<HSTRING>> filters;
- hr = picker->get_FileTypeFilter(&filters);
- RETURN_FALSE_IF_FAILED("Failed to get file type filters list");
- for (const QString &namedFilter : options->nameFilters()) {
- for (const QString &filter : QPlatformFileDialogHelper::cleanFilterList(namedFilter)) {
- // Remove leading star
- const int offset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0;
- HStringReference filterRef(reinterpret_cast<const wchar_t *>(filter.utf16() + offset),
- uint(filter.length() - offset));
- hr = filters->Append(filterRef.Get());
- if (FAILED(hr)) {
- qWarning("Failed to add named file filter \"%s\": %s",
- qPrintable(filter), qPrintable(qt_error_string(hr)));
- }
- }
- }
- // The file dialog won't open with an empty list - add a default wildcard
- quint32 size;
- hr = filters->get_Size(&size);
- RETURN_FALSE_IF_FAILED("Failed to get file type filters list size");
- if (!size) {
- hr = filters->Append(HString::MakeReference(L"*").Get());
- RETURN_FALSE_IF_FAILED("Failed to add default wildcard to file type filters list");
- }
-
- return true;
-}
-
-static bool pickFiles(IFileOpenPicker *picker, QWinRTFileDialogHelper *helper, bool singleFile)
-{
- Q_ASSERT(picker);
- Q_ASSERT(helper);
- HRESULT hr;
- hr = QEventDispatcherWinRT::runOnXamlThread([picker, helper, singleFile]() {
- HRESULT hr;
- if (singleFile) {
- ComPtr<IAsyncOperation<StorageFile *>> op;
- hr = picker->PickSingleFileAsync(&op);
- RETURN_HR_IF_FAILED("Failed to open single file picker");
- hr = op->put_Completed(Callback<SingleFileHandler>(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
- RETURN_HR_IF_FAILED("Failed to attach file picker callback");
- } else {
- ComPtr<IAsyncOperation<IVectorView<StorageFile *> *>> op;
- hr = picker->PickMultipleFilesAsync(&op);
- RETURN_HR_IF_FAILED("Failed to open multi file picker");
- hr = op->put_Completed(Callback<MultipleFileHandler>(helper, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get());
- RETURN_HR_IF_FAILED("Failed to attach multi file callback");
- }
- return S_OK;
- });
- return SUCCEEDED(hr);
-}
-
-static bool pickFolder(IFolderPicker *picker, QWinRTFileDialogHelper *helper)
-{
- Q_ASSERT(picker);
- Q_ASSERT(helper);
- HRESULT hr;
- hr = QEventDispatcherWinRT::runOnXamlThread([picker, helper]() {
- HRESULT hr;
- ComPtr<IAsyncOperation<StorageFolder *>> op;
- hr = picker->PickSingleFolderAsync(&op);
- RETURN_HR_IF_FAILED("Failed to open folder picker");
- hr = op->put_Completed(Callback<SingleFolderHandler>(helper, &QWinRTFileDialogHelper::onSingleFolderPicked).Get());
- RETURN_HR_IF_FAILED("Failed to attach folder picker callback");
- return S_OK;
- });
- return SUCCEEDED(hr);
-}
-
-static bool pickSaveFile(IFileSavePicker *picker, QWinRTFileDialogHelper *helper)
-{
- Q_ASSERT(picker);
- Q_ASSERT(helper);
- HRESULT hr;
- hr = QEventDispatcherWinRT::runOnXamlThread([picker, helper]() {
- HRESULT hr;
- ComPtr<IAsyncOperation<StorageFile *>> op;
- hr = picker->PickSaveFileAsync(&op);
- RETURN_HR_IF_FAILED("Failed to open save file picker");
- hr = op->put_Completed(Callback<SingleFileHandler>(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
- RETURN_HR_IF_FAILED("Failed to attach save file picker callback");
- return S_OK;
- });
- return SUCCEEDED(hr);
-}
-
-class QWinRTFileDialogHelperPrivate
-{
-public:
- bool shown;
- QEventLoop loop;
-
- // Input
- QUrl directory;
- QUrl saveFileName;
- QString selectedNameFilter;
-
- // Output
- QList<QUrl> selectedFiles;
-};
-
-QWinRTFileDialogHelper::QWinRTFileDialogHelper()
- : QPlatformFileDialogHelper(), d_ptr(new QWinRTFileDialogHelperPrivate)
-{
- Q_D(QWinRTFileDialogHelper);
-
- d->shown = false;
-}
-
-void QWinRTFileDialogHelper::exec()
-{
- Q_D(QWinRTFileDialogHelper);
-
- if (!d->shown)
- show(Qt::Dialog, Qt::ApplicationModal, nullptr);
- d->loop.exec();
-}
-
-bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
-{
- Q_UNUSED(windowFlags)
- Q_UNUSED(windowModality)
- Q_UNUSED(parent)
- Q_D(QWinRTFileDialogHelper);
-
- HRESULT hr;
- const QSharedPointer<QFileDialogOptions> dialogOptions = options();
- switch (dialogOptions->acceptMode()) {
- default:
- case QFileDialogOptions::AcceptOpen: {
- switch (dialogOptions->fileMode()) {
- case QFileDialogOptions::AnyFile:
- case QFileDialogOptions::ExistingFile:
- case QFileDialogOptions::ExistingFiles: {
- ComPtr<IFileOpenPicker> picker;
- if (!initializePicker(HString::MakeReference(RuntimeClass_Windows_Storage_Pickers_FileOpenPicker).Get(),
- picker.GetAddressOf(), dialogOptions)) {
- return false;
- }
- if (!initializeOpenPickerOptions(picker.Get(), dialogOptions))
- return false;
-
- if (!pickFiles(picker.Get(), this, dialogOptions->fileMode() == QFileDialogOptions::ExistingFile))
- return false;
-
- break;
- }
- case QFileDialogOptions::Directory:
- case QFileDialogOptions::DirectoryOnly: {
- ComPtr<IFolderPicker> picker;
- if (!initializePicker(HString::MakeReference(RuntimeClass_Windows_Storage_Pickers_FolderPicker).Get(),
- picker.GetAddressOf(), dialogOptions)) {
- return false;
- }
- if (!initializeOpenPickerOptions(picker.Get(), dialogOptions))
- return false;
-
- if (!pickFolder(picker.Get(), this))
- return false;
-
- break;
- }
- }
- break;
- }
- case QFileDialogOptions::AcceptSave: {
- ComPtr<IFileSavePicker> picker;
- if (!initializePicker(HString::MakeReference(RuntimeClass_Windows_Storage_Pickers_FileSavePicker).Get(),
- picker.GetAddressOf(), dialogOptions)) {
- return false;
- }
-
- if (!dialogOptions->nameFilters().isEmpty()) {
- ComPtr<IMap<HSTRING, IVector<HSTRING> *>> choices;
- hr = picker->get_FileTypeChoices(&choices);
- RETURN_FALSE_IF_FAILED("Failed to get file extension choices");
- const QStringList nameFilters = dialogOptions->nameFilters();
- for (const QString &namedFilter : nameFilters) {
- ComPtr<IVector<HSTRING>> entry = Make<WindowsStringVector>();
- const QStringList cleanFilter = QPlatformFileDialogHelper::cleanFilterList(namedFilter);
- for (const QString &filter : cleanFilter) {
- // Remove leading star
- const int starOffset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0;
- HStringReference filterRef(reinterpret_cast<const wchar_t *>(filter.utf16() + starOffset),
- uint(filter.length() - starOffset));
- hr = entry->Append(filterRef.Get());
- if (FAILED(hr)) {
- qWarning("Failed to add named file filter \"%s\": %s",
- qPrintable(filter), qPrintable(qt_error_string(hr)));
- }
- }
- const int offset = namedFilter.indexOf(QLatin1String(" ("));
- const QString filterTitle = namedFilter.mid(0, offset);
- HStringReference namedFilterRef(reinterpret_cast<const wchar_t *>(filterTitle.utf16()),
- uint(filterTitle.length()));
- boolean replaced;
- hr = choices->Insert(namedFilterRef.Get(), entry.Get(), &replaced);
- // Only print a warning as * or *.* is not a valid choice on Windows 10
- // but used on a regular basis on all other platforms
- if (FAILED(hr)) {
- qWarning("Failed to insert file extension choice entry: %s: %s",
- qPrintable(filterTitle), qPrintable(qt_error_string(hr)));
- }
- }
- }
-
- QString suffix = dialogOptions->defaultSuffix();
- if (!suffix.isEmpty()) {
- if (!suffix.startsWith(QLatin1Char('.')))
- suffix.prepend(QLatin1Char('.'));
- HStringReference nativeSuffix(reinterpret_cast<const wchar_t *>(suffix.utf16()),
- uint(suffix.length()));
- hr = picker->put_DefaultFileExtension(nativeSuffix.Get());
- RETURN_FALSE_IF_FAILED_WITH_ARGS("Failed to set default file extension \"%s\"", qPrintable(suffix));
- }
-
- QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName();
- if (suggestedName.isEmpty() && dialogOptions->initiallySelectedFiles().size() > 0)
- suggestedName = QFileInfo(dialogOptions->initiallySelectedFiles().first().toLocalFile())
- .fileName();
- if (suggestedName.isEmpty()) {
- const auto fileInfo = QFileInfo(dialogOptions->initialDirectory().toLocalFile());
- if (!fileInfo.isDir())
- suggestedName = fileInfo.fileName();
- }
- if (!suggestedName.isEmpty()) {
- HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()),
- uint(suggestedName.length()));
- hr = picker->put_SuggestedFileName(nativeSuggestedName.Get());
- RETURN_FALSE_IF_FAILED("Failed to set suggested file name");
- }
-
- if (!pickSaveFile(picker.Get(), this))
- return false;
-
- break;
- }
- }
-
- d->shown = true;
- return true;
-}
-
-void QWinRTFileDialogHelper::hide()
-{
- Q_D(QWinRTFileDialogHelper);
-
- if (!d->shown)
- return;
-
- d->shown = false;
-}
-
-void QWinRTFileDialogHelper::setDirectory(const QUrl &directory)
-{
- Q_D(QWinRTFileDialogHelper);
- d->directory = directory;
-}
-
-QUrl QWinRTFileDialogHelper::directory() const
-{
- Q_D(const QWinRTFileDialogHelper);
- return d->directory;
-}
-
-void QWinRTFileDialogHelper::selectFile(const QUrl &saveFileName)
-{
- Q_D(QWinRTFileDialogHelper);
- d->saveFileName = saveFileName;
-}
-
-QList<QUrl> QWinRTFileDialogHelper::selectedFiles() const
-{
- Q_D(const QWinRTFileDialogHelper);
- return d->selectedFiles;
-}
-
-void QWinRTFileDialogHelper::selectNameFilter(const QString &selectedNameFilter)
-{
- Q_D(QWinRTFileDialogHelper);
- d->selectedNameFilter = selectedNameFilter;
-}
-
-QString QWinRTFileDialogHelper::selectedNameFilter() const
-{
- Q_D(const QWinRTFileDialogHelper);
- return d->selectedNameFilter;
-}
-
-HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation<StorageFile *> *args, AsyncStatus status)
-{
- Q_D(QWinRTFileDialogHelper);
-
- QEventLoopLocker locker(&d->loop);
- d->shown = false;
- d->selectedFiles.clear();
- if (status == Canceled || status == Error) {
- emit reject();
- return S_OK;
- }
-
- HRESULT hr;
- ComPtr<IStorageFile> file;
- hr = args->GetResults(&file);
- Q_ASSERT_SUCCEEDED(hr);
- return onFilePicked(file.Get());
-}
-
-HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorView<StorageFile *> *> *args, AsyncStatus status)
-{
- Q_D(QWinRTFileDialogHelper);
-
- QEventLoopLocker locker(&d->loop);
- d->shown = false;
- d->selectedFiles.clear();
- if (status == Canceled || status == Error) {
- emit reject();
- return S_OK;
- }
-
- HRESULT hr;
- ComPtr<IVectorView<StorageFile *>> fileList;
- hr = args->GetResults(&fileList);
- RETURN_HR_IF_FAILED("Failed to get file list");
- return onFilesPicked(fileList.Get());
-}
-
-HRESULT QWinRTFileDialogHelper::onSingleFolderPicked(IAsyncOperation<StorageFolder *> *args, AsyncStatus status)
-{
- Q_D(QWinRTFileDialogHelper);
-
- QEventLoopLocker locker(&d->loop);
- d->shown = false;
- d->selectedFiles.clear();
- if (status == Canceled || status == Error) {
- emit reject();
- return S_OK;
- }
-
- HRESULT hr;
- ComPtr<IStorageFolder> folder;
- hr = args->GetResults(&folder);
- Q_ASSERT_SUCCEEDED(hr);
- return onFolderPicked(folder.Get());
-}
-
-HRESULT QWinRTFileDialogHelper::onFilesPicked(IVectorView<StorageFile *> *files)
-{
- HRESULT hr;
- quint32 size;
- hr = files->get_Size(&size);
- Q_ASSERT_SUCCEEDED(hr);
- if (!size) {
- emit reject();
- return S_OK;
- }
-
- for (quint32 i = 0; i < size; ++i) {
- ComPtr<IStorageFile> file;
- hr = files->GetAt(i, &file);
- Q_ASSERT_SUCCEEDED(hr);
- appendFile(file.Get());
- }
-
- emit accept();
- return S_OK;
-}
-
-HRESULT QWinRTFileDialogHelper::onFolderPicked(IStorageFolder *folder)
-{
- if (!folder) {
- emit reject();
- return S_OK;
- }
-
- appendFile(folder);
- emit accept();
- return S_OK;
-}
-
-HRESULT QWinRTFileDialogHelper::onFilePicked(IStorageFile *file)
-{
- if (!file) {
- emit reject();
- return S_OK;
- }
-
- appendFile(file);
- emit accept();
- return S_OK;
-}
-
-void QWinRTFileDialogHelper::appendFile(IInspectable *file)
-{
- Q_D(QWinRTFileDialogHelper);
-
- HRESULT hr;
- ComPtr<IStorageItem> item;
- hr = file->QueryInterface(IID_PPV_ARGS(&item));
- Q_ASSERT_SUCCEEDED(hr);
-
- HString path;
- hr = item->get_Path(path.GetAddressOf());
- Q_ASSERT_SUCCEEDED(hr);
-
- quint32 pathLen;
- const wchar_t *pathStr = path.GetRawBuffer(&pathLen);
- const QString filePath = QString::fromWCharArray(pathStr, pathLen);
- QWinRTFileEngineHandler::registerFile(filePath, item.Get());
- d->selectedFiles.append(QUrl::fromLocalFile(filePath));
-}
-
-QT_END_NAMESPACE