diff options
Diffstat (limited to 'src/plugins/platforms/ios/qiosdocumentpickercontroller.mm')
-rw-r--r-- | src/plugins/platforms/ios/qiosdocumentpickercontroller.mm | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm new file mode 100644 index 0000000000..fca0432426 --- /dev/null +++ b/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm @@ -0,0 +1,115 @@ +// Copyright (C) 2020 Harald Meyer. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#import <UIKit/UIKit.h> +#import <MobileCoreServices/MobileCoreServices.h> + +#include "qiosdocumentpickercontroller.h" + +@implementation QIOSDocumentPickerController { + QIOSFileDialog *m_fileDialog; +} + +- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog +{ + NSMutableArray <UTType *> *docTypes = [[[NSMutableArray alloc] init] autorelease]; + + QStringList nameFilters = fileDialog->options()->nameFilters(); + if (!nameFilters.isEmpty() && (fileDialog->options()->fileMode() != QFileDialogOptions::Directory + || fileDialog->options()->fileMode() != QFileDialogOptions::DirectoryOnly)) + { + QStringList results; + for (const QString &filter : nameFilters) + results.append(QPlatformFileDialogHelper::cleanFilterList(filter)); + + docTypes = [self computeAllowedFileTypes:results]; + } + + if (!docTypes.count) { + switch (fileDialog->options()->fileMode()) { + case QFileDialogOptions::AnyFile: + case QFileDialogOptions::ExistingFile: + case QFileDialogOptions::ExistingFiles: + [docTypes addObject:[UTType typeWithIdentifier:(__bridge NSString *)UTTypeContent]]; + [docTypes addObject:[UTType typeWithIdentifier:(__bridge NSString *)UTTypeItem]]; + [docTypes addObject:[UTType typeWithIdentifier:(__bridge NSString *)UTTypeData]]; + break; + // Showing files is not supported in Directory mode in iOS + case QFileDialogOptions::Directory: + case QFileDialogOptions::DirectoryOnly: + [docTypes addObject:[UTType typeWithIdentifier:(__bridge NSString *)UTTypeFolder]]; + break; + } + } + + if (self = [super initForOpeningContentTypes:docTypes]) { + m_fileDialog = fileDialog; + self.modalPresentationStyle = UIModalPresentationFormSheet; + self.delegate = self; + self.presentationController.delegate = self; + + if (m_fileDialog->options()->fileMode() == QFileDialogOptions::ExistingFiles) + self.allowsMultipleSelection = YES; + + self.directoryURL = m_fileDialog->options()->initialDirectory().toNSURL(); + } + return self; +} + +- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray <NSURL *>*)urls +{ + Q_UNUSED(controller); + + QList<QUrl> files; + for (NSURL* url in urls) + files.append(QUrl::fromNSURL(url)); + + m_fileDialog->selectedFilesChanged(files); + emit m_fileDialog->accept(); +} + +- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller +{ + Q_UNUSED(controller); + emit m_fileDialog->reject(); +} + +- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController +{ + Q_UNUSED(presentationController); + + // "Called on the delegate when the user has taken action to dismiss the + // presentation successfully, after all animations are finished. + // This is not called if the presentation is dismissed programmatically." + + // So if document picker's view was dismissed, for example by swiping it away, + // we got this method called. But not if the dialog was cancelled or a file + // was selected. + emit m_fileDialog->reject(); +} + +- (NSMutableArray<UTType*>*)computeAllowedFileTypes:(QStringList)filters +{ + QStringList fileTypes; + for (const QString &filter : filters) { + if (filter == (QLatin1String("*"))) + continue; + + if (filter.contains(u'?')) + continue; + + if (filter.count(u'*') != 1) + continue; + + auto extensions = filter.split('.', Qt::SkipEmptyParts); + fileTypes += extensions.last(); + } + + NSMutableArray<UTType *> *result = [NSMutableArray<UTType *> arrayWithCapacity:fileTypes.size()]; + for (const QString &string : fileTypes) + [result addObject:[UTType typeWithFilenameExtension:string.toNSString()]]; + + return result; +} + +@end |