summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/qiosdocumentpickercontroller.mm
blob: fca0432426eacbb590b5f10d8024c8fb7525a284 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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