Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qiosclipboard.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
7#ifndef QT_NO_CLIPBOARD
8
9#include <QtCore/qurl.h>
10#include <QtGui/private/qmacmimeregistry_p.h>
11#include <QtGui/qutimimeconverter.h>
12#include <QtCore/QMimeData>
13#include <QtGui/QGuiApplication>
14
15// --------------------------------------------------------------------
16
17@interface QUIClipboard : NSObject
18@end
19
20@implementation QUIClipboard {
21 QIOSClipboard *m_qiosClipboard;
22 NSInteger m_changeCountClipboard;
23}
24
25- (instancetype)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
26{
27 self = [super init];
28 if (self) {
29 m_qiosClipboard = qiosClipboard;
30 m_changeCountClipboard = UIPasteboard.generalPasteboard.changeCount;
31
32 [[NSNotificationCenter defaultCenter]
33 addObserver:self
34 selector:@selector(updatePasteboardChanged:)
35 name:UIPasteboardChangedNotification object:nil];
36 [[NSNotificationCenter defaultCenter]
37 addObserver:self
38 selector:@selector(updatePasteboardChanged:)
39 name:UIPasteboardRemovedNotification object:nil];
40 [[NSNotificationCenter defaultCenter]
41 addObserver:self
42 selector:@selector(updatePasteboardChanged:)
43 name:UIApplicationDidBecomeActiveNotification
44 object:nil];
45 }
46 return self;
47}
48
49- (void)dealloc
50{
51 [[NSNotificationCenter defaultCenter]
52 removeObserver:self
53 name:UIPasteboardChangedNotification object:nil];
54 [[NSNotificationCenter defaultCenter]
55 removeObserver:self
56 name:UIPasteboardRemovedNotification object:nil];
57 [[NSNotificationCenter defaultCenter]
58 removeObserver:self
59 name:UIApplicationDidBecomeActiveNotification
60 object:nil];
61 [super dealloc];
62}
63
64- (void)updatePasteboardChanged:(NSNotification *)notification
65{
66 Q_UNUSED(notification);
67 NSInteger changeCountClipboard = UIPasteboard.generalPasteboard.changeCount;
68
69 if (m_changeCountClipboard != changeCountClipboard) {
70 m_changeCountClipboard = changeCountClipboard;
71 m_qiosClipboard->emitChanged(QClipboard::Clipboard);
72 }
73}
74
75@end
76
77// --------------------------------------------------------------------
78
79QT_BEGIN_NAMESPACE
80
81class QIOSMimeData : public QMimeData {
82public:
83 QIOSMimeData() : QMimeData() { }
84 ~QIOSMimeData() { }
85
86 QStringList formats() const override;
87 QVariant retrieveData(const QString &mimeType, QMetaType type) const override;
88};
89
90QStringList QIOSMimeData::formats() const
91{
92 QStringList foundMimeTypes;
93 UIPasteboard *pb = UIPasteboard.generalPasteboard;
94 NSArray<NSString *> *pasteboardTypes = [pb pasteboardTypes];
95
96 for (NSUInteger i = 0; i < [pasteboardTypes count]; ++i) {
97 const QString uti = QString::fromNSString([pasteboardTypes objectAtIndex:i]);
98 const QString mimeType = QMacMimeRegistry::flavorToMime(QUtiMimeConverter::HandlerScopeFlag::All, uti);
99 if (!mimeType.isEmpty() && !foundMimeTypes.contains(mimeType))
100 foundMimeTypes << mimeType;
101 }
102
103 return foundMimeTypes;
104}
105
106QVariant QIOSMimeData::retrieveData(const QString &mimeType, QMetaType) const
107{
108 UIPasteboard *pb = UIPasteboard.generalPasteboard;
109 NSArray<NSString *> *pasteboardTypes = [pb pasteboardTypes];
110
111 const auto converters = QMacMimeRegistry::all(QUtiMimeConverter::HandlerScopeFlag::All);
112 for (QUtiMimeConverter *converter : converters) {
113 for (NSUInteger i = 0; i < [pasteboardTypes count]; ++i) {
114 NSString *availableUtiNSString = [pasteboardTypes objectAtIndex:i];
115 const QString availableUti = QString::fromNSString(availableUtiNSString);
116 if (!converter->canConvert(mimeType, availableUti))
117 continue;
118
119 NSData *nsData = [pb dataForPasteboardType:availableUtiNSString];
120 QList<QByteArray> dataList;
121 dataList << QByteArray(reinterpret_cast<const char *>([nsData bytes]), [nsData length]);
122 return converter->convertToMime(mimeType, dataList, availableUti);
123 }
124 }
125
126 return QVariant();
127}
128
129// --------------------------------------------------------------------
130
131QIOSClipboard::QIOSClipboard()
132 : m_clipboard([[QUIClipboard alloc] initWithQIOSClipboard:this])
133{
134}
135
136QIOSClipboard::~QIOSClipboard()
137{
138 qDeleteAll(m_mimeData);
139}
140
141QMimeData *QIOSClipboard::mimeData(QClipboard::Mode mode)
142{
143 Q_ASSERT(supportsMode(mode));
144 if (!m_mimeData.contains(mode))
145 return *m_mimeData.insert(mode, new QIOSMimeData);
146 return m_mimeData[mode];
147}
148
149void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
150{
151 Q_ASSERT(supportsMode(mode));
152
153 UIPasteboard *pb = UIPasteboard.generalPasteboard;
154 if (!mimeData) {
155 pb.items = [NSArray<NSDictionary<NSString *, id> *> array];
156 return;
157 }
158
159 mimeData->deleteLater();
160 NSMutableDictionary<NSString *, id> *pbItem = [NSMutableDictionary<NSString *, id> dictionaryWithCapacity:mimeData->formats().size()];
161
162 const auto formats = mimeData->formats();
163 for (const QString &mimeType : formats) {
164 const auto converters = QMacMimeRegistry::all(QUtiMimeConverter::HandlerScopeFlag::All);
165 for (const QUtiMimeConverter *converter : converters) {
166 const QString uti = converter->utiForMime(mimeType);
167 if (uti.isEmpty())
168 continue;
169
170 QVariant mimeDataAsVariant;
171 if (mimeData->hasImage()) {
172 mimeDataAsVariant = mimeData->imageData();
173 } else if (mimeData->hasUrls()) {
174 const auto urls = mimeData->urls();
175 QVariantList urlList;
176 urlList.reserve(urls.size());
177 for (const QUrl& url : urls)
178 urlList << url;
179 mimeDataAsVariant = QVariant(urlList);
180 } else {
181 mimeDataAsVariant = QVariant(mimeData->data(mimeType));
182 }
183
184 QByteArray byteArray = converter->convertFromMime(mimeType, mimeDataAsVariant, uti).constFirst();
185 NSData *nsData = [NSData dataWithBytes:byteArray.constData() length:byteArray.size()];
186 [pbItem setValue:nsData forKey:uti.toNSString()];
187 break;
188 }
189 }
190
191 pb.items = @[pbItem];
192}
193
194bool QIOSClipboard::supportsMode(QClipboard::Mode mode) const
195{
196 return mode == QClipboard::Clipboard;
197}
198
199bool QIOSClipboard::ownsMode(QClipboard::Mode mode) const
200{
201 Q_UNUSED(mode);
202 return false;
203}
204
205QT_END_NAMESPACE
206
207#endif // QT_NO_CLIPBOARD