0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 |
** All rights reserved.
|
|
5 |
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
6 |
**
|
|
7 |
** This file is part of the QtGui module of the Qt Toolkit.
|
|
8 |
**
|
|
9 |
** $QT_BEGIN_LICENSE:LGPL$
|
|
10 |
** No Commercial Usage
|
|
11 |
** This file contains pre-release code and may not be distributed.
|
|
12 |
** You may use this file in accordance with the terms and conditions
|
|
13 |
** contained in the Technology Preview License Agreement accompanying
|
|
14 |
** this package.
|
|
15 |
**
|
|
16 |
** GNU Lesser General Public License Usage
|
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
18 |
** General Public License version 2.1 as published by the Free Software
|
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
20 |
** packaging of this file. Please review the following information to
|
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
23 |
**
|
|
24 |
** In addition, as a special exception, Nokia gives you certain additional
|
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
27 |
**
|
|
28 |
** If you have questions regarding the use of this file, please contact
|
|
29 |
** Nokia at qt-info@nokia.com.
|
|
30 |
**
|
|
31 |
**
|
|
32 |
**
|
|
33 |
**
|
|
34 |
**
|
|
35 |
**
|
|
36 |
**
|
|
37 |
**
|
|
38 |
** $QT_END_LICENSE$
|
|
39 |
**
|
|
40 |
****************************************************************************/
|
|
41 |
|
|
42 |
#include "qclipboard.h"
|
|
43 |
#include "qapplication.h"
|
|
44 |
#include "qbitmap.h"
|
|
45 |
#include "qdatetime.h"
|
|
46 |
#include "qdebug.h"
|
|
47 |
#include "qapplication_p.h"
|
|
48 |
#include <private/qt_mac_p.h>
|
|
49 |
#include "qevent.h"
|
|
50 |
#include "qurl.h"
|
|
51 |
#include <stdlib.h>
|
|
52 |
#include <string.h>
|
|
53 |
#include "qt_cocoa_helpers_mac_p.h"
|
|
54 |
|
|
55 |
QT_BEGIN_NAMESPACE
|
|
56 |
|
|
57 |
QT_USE_NAMESPACE
|
|
58 |
|
|
59 |
/*****************************************************************************
|
|
60 |
QClipboard debug facilities
|
|
61 |
*****************************************************************************/
|
|
62 |
//#define DEBUG_PASTEBOARD
|
|
63 |
|
|
64 |
#ifndef QT_NO_CLIPBOARD
|
|
65 |
|
|
66 |
/*****************************************************************************
|
|
67 |
QClipboard member functions for mac.
|
|
68 |
*****************************************************************************/
|
|
69 |
|
|
70 |
static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0};
|
|
71 |
|
|
72 |
static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode)
|
|
73 |
{
|
|
74 |
Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer);
|
|
75 |
if (mode == QClipboard::Clipboard)
|
|
76 |
return qt_mac_pasteboards[0];
|
|
77 |
else
|
|
78 |
return qt_mac_pasteboards[1];
|
|
79 |
}
|
|
80 |
|
|
81 |
static void qt_mac_cleanupPasteboard() {
|
|
82 |
delete qt_mac_pasteboards[0];
|
|
83 |
delete qt_mac_pasteboards[1];
|
|
84 |
qt_mac_pasteboards[0] = 0;
|
|
85 |
qt_mac_pasteboards[1] = 0;
|
|
86 |
}
|
|
87 |
|
|
88 |
static bool qt_mac_updateScrap(QClipboard::Mode mode)
|
|
89 |
{
|
|
90 |
if(!qt_mac_pasteboards[0]) {
|
|
91 |
qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP);
|
|
92 |
qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP);
|
|
93 |
qAddPostRoutine(qt_mac_cleanupPasteboard);
|
|
94 |
return true;
|
|
95 |
}
|
|
96 |
return qt_mac_pasteboard(mode)->sync();
|
|
97 |
}
|
|
98 |
|
|
99 |
void QClipboard::clear(Mode mode)
|
|
100 |
{
|
|
101 |
if (!supportsMode(mode))
|
|
102 |
return;
|
|
103 |
qt_mac_updateScrap(mode);
|
|
104 |
qt_mac_pasteboard(mode)->clear();
|
|
105 |
setMimeData(0, mode);
|
|
106 |
}
|
|
107 |
|
|
108 |
void QClipboard::ownerDestroyed()
|
|
109 |
{
|
|
110 |
}
|
|
111 |
|
|
112 |
|
|
113 |
void QClipboard::connectNotify(const char *signal)
|
|
114 |
{
|
|
115 |
Q_UNUSED(signal);
|
|
116 |
}
|
|
117 |
|
|
118 |
bool QClipboard::event(QEvent *e)
|
|
119 |
{
|
|
120 |
if(e->type() != QEvent::Clipboard)
|
|
121 |
return QObject::event(e);
|
|
122 |
|
|
123 |
if (qt_mac_updateScrap(QClipboard::Clipboard)) {
|
|
124 |
emitChanged(QClipboard::Clipboard);
|
|
125 |
}
|
|
126 |
|
|
127 |
if (qt_mac_updateScrap(QClipboard::FindBuffer)) {
|
|
128 |
emitChanged(QClipboard::FindBuffer);
|
|
129 |
}
|
|
130 |
|
|
131 |
return QObject::event(e);
|
|
132 |
}
|
|
133 |
|
|
134 |
const QMimeData *QClipboard::mimeData(Mode mode) const
|
|
135 |
{
|
|
136 |
if (!supportsMode(mode))
|
|
137 |
return 0;
|
|
138 |
qt_mac_updateScrap(mode);
|
|
139 |
return qt_mac_pasteboard(mode)->mimeData();
|
|
140 |
}
|
|
141 |
|
|
142 |
void QClipboard::setMimeData(QMimeData *src, Mode mode)
|
|
143 |
{
|
|
144 |
if (!supportsMode(mode))
|
|
145 |
return;
|
|
146 |
qt_mac_updateScrap(mode);
|
|
147 |
qt_mac_pasteboard(mode)->setMimeData(src);
|
|
148 |
emitChanged(mode);
|
|
149 |
}
|
|
150 |
|
|
151 |
bool QClipboard::supportsMode(Mode mode) const
|
|
152 |
{
|
|
153 |
return (mode == Clipboard || mode == FindBuffer);
|
|
154 |
}
|
|
155 |
|
|
156 |
bool QClipboard::ownsMode(Mode mode) const
|
|
157 |
{
|
|
158 |
Q_UNUSED(mode);
|
|
159 |
return false;
|
|
160 |
}
|
|
161 |
|
|
162 |
#endif // QT_NO_CLIPBOARD
|
|
163 |
|
|
164 |
/*****************************************************************************
|
|
165 |
QMacPasteboard code
|
|
166 |
*****************************************************************************/
|
|
167 |
|
|
168 |
QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
|
|
169 |
{
|
|
170 |
mac_mime_source = false;
|
|
171 |
mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
|
|
172 |
paste = p;
|
|
173 |
CFRetain(paste);
|
|
174 |
}
|
|
175 |
|
|
176 |
QMacPasteboard::QMacPasteboard(uchar mt)
|
|
177 |
{
|
|
178 |
mac_mime_source = false;
|
|
179 |
mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
|
|
180 |
paste = 0;
|
|
181 |
OSStatus err = PasteboardCreate(0, &paste);
|
|
182 |
if(err == noErr) {
|
|
183 |
PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
|
|
184 |
} else {
|
|
185 |
qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err);
|
|
186 |
}
|
|
187 |
}
|
|
188 |
|
|
189 |
QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
|
|
190 |
{
|
|
191 |
mac_mime_source = false;
|
|
192 |
mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
|
|
193 |
paste = 0;
|
|
194 |
OSStatus err = PasteboardCreate(name, &paste);
|
|
195 |
if(err == noErr) {
|
|
196 |
PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
|
|
197 |
} else {
|
|
198 |
qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err);
|
|
199 |
}
|
|
200 |
}
|
|
201 |
|
|
202 |
QMacPasteboard::~QMacPasteboard()
|
|
203 |
{
|
|
204 |
// commit all promises for paste after exit close
|
|
205 |
for (int i = 0; i < promises.count(); ++i) {
|
|
206 |
const Promise &promise = promises.at(i);
|
|
207 |
QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
|
|
208 |
promiseKeeper(paste, (PasteboardItemID)promise.itemId, flavor, this);
|
|
209 |
}
|
|
210 |
|
|
211 |
if(paste)
|
|
212 |
CFRelease(paste);
|
|
213 |
}
|
|
214 |
|
|
215 |
PasteboardRef
|
|
216 |
QMacPasteboard::pasteBoard() const
|
|
217 |
{
|
|
218 |
return paste;
|
|
219 |
}
|
|
220 |
|
|
221 |
OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, CFStringRef flavor, void *_qpaste)
|
|
222 |
{
|
|
223 |
QMacPasteboard *qpaste = (QMacPasteboard*)_qpaste;
|
|
224 |
const long promise_id = (long)id;
|
|
225 |
|
|
226 |
// Find the kept promise
|
|
227 |
const QString flavorAsQString = QCFString::toQString(flavor);
|
|
228 |
QMacPasteboard::Promise promise;
|
|
229 |
for (int i = 0; i < qpaste->promises.size(); i++){
|
|
230 |
QMacPasteboard::Promise tmp = qpaste->promises[i];
|
|
231 |
if (tmp.itemId == promise_id && tmp.convertor->canConvert(tmp.mime, flavorAsQString)){
|
|
232 |
promise = tmp;
|
|
233 |
break;
|
|
234 |
}
|
|
235 |
}
|
|
236 |
|
|
237 |
if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) {
|
|
238 |
// we have promised this data, but wont be able to convert, so return null data.
|
|
239 |
// This helps in making the application/x-qt-mime-type-name hidden from normal use.
|
|
240 |
QByteArray ba;
|
|
241 |
QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
|
|
242 |
PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
|
|
243 |
return noErr;
|
|
244 |
}
|
|
245 |
|
|
246 |
if (!promise.itemId) {
|
|
247 |
// There was no promise that could deliver data for the
|
|
248 |
// given id and flavor. This should not happend.
|
|
249 |
qDebug("Pasteboard: %d: Request for %ld, %s, but no promise found!", __LINE__, promise_id, qPrintable(flavorAsQString));
|
|
250 |
return cantGetFlavorErr;
|
|
251 |
}
|
|
252 |
|
|
253 |
#ifdef DEBUG_PASTEBOARD
|
|
254 |
qDebug("PasteBoard: Calling in promise for %s[%ld] [%s] (%s) [%d]", qPrintable(promise.mime), promise_id,
|
|
255 |
qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset);
|
|
256 |
#endif
|
|
257 |
|
|
258 |
QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString);
|
|
259 |
if (md.size() <= promise.offset)
|
|
260 |
return cantGetFlavorErr;
|
|
261 |
const QByteArray &ba = md[promise.offset];
|
|
262 |
QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
|
|
263 |
PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
|
|
264 |
return noErr;
|
|
265 |
}
|
|
266 |
|
|
267 |
bool
|
|
268 |
QMacPasteboard::hasOSType(int c_flavor) const
|
|
269 |
{
|
|
270 |
if (!paste)
|
|
271 |
return false;
|
|
272 |
|
|
273 |
sync();
|
|
274 |
|
|
275 |
ItemCount cnt = 0;
|
|
276 |
if(PasteboardGetItemCount(paste, &cnt) || !cnt)
|
|
277 |
return false;
|
|
278 |
|
|
279 |
#ifdef DEBUG_PASTEBOARD
|
|
280 |
qDebug("PasteBoard: hasOSType [%c%c%c%c]", (c_flavor>>24)&0xFF, (c_flavor>>16)&0xFF,
|
|
281 |
(c_flavor>>8)&0xFF, (c_flavor>>0)&0xFF);
|
|
282 |
#endif
|
|
283 |
for(uint index = 1; index <= cnt; ++index) {
|
|
284 |
|
|
285 |
PasteboardItemID id;
|
|
286 |
if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
|
|
287 |
return false;
|
|
288 |
|
|
289 |
QCFType<CFArrayRef> types;
|
|
290 |
if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
|
|
291 |
return false;
|
|
292 |
|
|
293 |
const int type_count = CFArrayGetCount(types);
|
|
294 |
for(int i = 0; i < type_count; ++i) {
|
|
295 |
CFStringRef flavor = (CFStringRef)CFArrayGetValueAtIndex(types, i);
|
|
296 |
const int os_flavor = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(flavor, kUTTagClassOSType));
|
|
297 |
if(os_flavor == c_flavor) {
|
|
298 |
#ifdef DEBUG_PASTEBOARD
|
|
299 |
qDebug(" - Found!");
|
|
300 |
#endif
|
|
301 |
return true;
|
|
302 |
}
|
|
303 |
}
|
|
304 |
}
|
|
305 |
#ifdef DEBUG_PASTEBOARD
|
|
306 |
qDebug(" - NotFound!");
|
|
307 |
#endif
|
|
308 |
return false;
|
|
309 |
}
|
|
310 |
|
|
311 |
bool
|
|
312 |
QMacPasteboard::hasFlavor(QString c_flavor) const
|
|
313 |
{
|
|
314 |
if (!paste)
|
|
315 |
return false;
|
|
316 |
|
|
317 |
sync();
|
|
318 |
|
|
319 |
ItemCount cnt = 0;
|
|
320 |
if(PasteboardGetItemCount(paste, &cnt) || !cnt)
|
|
321 |
return false;
|
|
322 |
|
|
323 |
#ifdef DEBUG_PASTEBOARD
|
|
324 |
qDebug("PasteBoard: hasFlavor [%s]", qPrintable(c_flavor));
|
|
325 |
#endif
|
|
326 |
for(uint index = 1; index <= cnt; ++index) {
|
|
327 |
|
|
328 |
PasteboardItemID id;
|
|
329 |
if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
|
|
330 |
return false;
|
|
331 |
|
|
332 |
PasteboardFlavorFlags flags;
|
|
333 |
if(PasteboardGetItemFlavorFlags(paste, id, QCFString(c_flavor), &flags) == noErr) {
|
|
334 |
#ifdef DEBUG_PASTEBOARD
|
|
335 |
qDebug(" - Found!");
|
|
336 |
#endif
|
|
337 |
return true;
|
|
338 |
}
|
|
339 |
}
|
|
340 |
#ifdef DEBUG_PASTEBOARD
|
|
341 |
qDebug(" - NotFound!");
|
|
342 |
#endif
|
|
343 |
return false;
|
|
344 |
}
|
|
345 |
|
|
346 |
class QMacPasteboardMimeSource : public QMimeData {
|
|
347 |
const QMacPasteboard *paste;
|
|
348 |
public:
|
|
349 |
QMacPasteboardMimeSource(const QMacPasteboard *p) : QMimeData(), paste(p) { }
|
|
350 |
~QMacPasteboardMimeSource() { }
|
|
351 |
virtual QStringList formats() const { return paste->formats(); }
|
|
352 |
virtual QVariant retrieveData(const QString &format, QVariant::Type type) const { return paste->retrieveData(format, type); }
|
|
353 |
};
|
|
354 |
|
|
355 |
QMimeData
|
|
356 |
*QMacPasteboard::mimeData() const
|
|
357 |
{
|
|
358 |
if(!mime) {
|
|
359 |
mac_mime_source = true;
|
|
360 |
mime = new QMacPasteboardMimeSource(this);
|
|
361 |
|
|
362 |
}
|
|
363 |
return mime;
|
|
364 |
}
|
|
365 |
|
|
366 |
class QMacMimeData : public QMimeData
|
|
367 |
{
|
|
368 |
public:
|
|
369 |
QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
|
|
370 |
private:
|
|
371 |
QMacMimeData();
|
|
372 |
};
|
|
373 |
|
|
374 |
void
|
|
375 |
QMacPasteboard::setMimeData(QMimeData *mime_src)
|
|
376 |
{
|
|
377 |
if (!paste)
|
|
378 |
return;
|
|
379 |
|
|
380 |
if (mime == mime_src || (!mime_src && mime && mac_mime_source))
|
|
381 |
return;
|
|
382 |
mac_mime_source = false;
|
|
383 |
delete mime;
|
|
384 |
mime = mime_src;
|
|
385 |
|
|
386 |
QList<QMacPasteboardMime*> availableConverters = QMacPasteboardMime::all(mime_type);
|
|
387 |
if (mime != 0) {
|
|
388 |
clear_helper();
|
|
389 |
QStringList formats = mime_src->formats();
|
|
390 |
|
|
391 |
for(int f = 0; f < formats.size(); ++f) {
|
|
392 |
QString mimeType = formats.at(f);
|
|
393 |
for (QList<QMacPasteboardMime *>::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) {
|
|
394 |
QMacPasteboardMime *c = (*it);
|
|
395 |
QString flavor(c->flavorFor(mimeType));
|
|
396 |
if(!flavor.isEmpty()) {
|
|
397 |
QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType);
|
|
398 |
#if 0
|
|
399 |
//### Grrr, why didn't I put in a virtual int QMacPasteboardMime::count()? --Sam
|
|
400 |
const int numItems = c->convertFromMime(mimeType, mimeData, flavor).size();
|
|
401 |
#else
|
|
402 |
int numItems = 1; //this is a hack but it is much faster than allowing conversion above
|
|
403 |
if(c->convertorName() == QLatin1String("FileURL"))
|
|
404 |
numItems = mime_src->urls().count();
|
|
405 |
#endif
|
|
406 |
for(int item = 0; item < numItems; ++item) {
|
|
407 |
const int itemID = item+1; //id starts at 1
|
|
408 |
promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item));
|
|
409 |
PasteboardPutItemFlavor(paste, (PasteboardItemID)itemID, QCFString(flavor), 0, kPasteboardFlavorNoFlags);
|
|
410 |
#ifdef DEBUG_PASTEBOARD
|
|
411 |
qDebug(" - adding %d %s [%s] <%s> [%d]",
|
|
412 |
itemID, qPrintable(mimeType), qPrintable(flavor), qPrintable(c->convertorName()), item);
|
|
413 |
#endif
|
|
414 |
}
|
|
415 |
}
|
|
416 |
}
|
|
417 |
}
|
|
418 |
}
|
|
419 |
}
|
|
420 |
|
|
421 |
QStringList
|
|
422 |
QMacPasteboard::formats() const
|
|
423 |
{
|
|
424 |
if (!paste)
|
|
425 |
return QStringList();
|
|
426 |
|
|
427 |
sync();
|
|
428 |
|
|
429 |
QStringList ret;
|
|
430 |
ItemCount cnt = 0;
|
|
431 |
if(PasteboardGetItemCount(paste, &cnt) || !cnt)
|
|
432 |
return ret;
|
|
433 |
|
|
434 |
#ifdef DEBUG_PASTEBOARD
|
|
435 |
qDebug("PasteBoard: Formats [%d]", (int)cnt);
|
|
436 |
#endif
|
|
437 |
for(uint index = 1; index <= cnt; ++index) {
|
|
438 |
|
|
439 |
PasteboardItemID id;
|
|
440 |
if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
|
|
441 |
continue;
|
|
442 |
|
|
443 |
QCFType<CFArrayRef> types;
|
|
444 |
if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
|
|
445 |
continue;
|
|
446 |
|
|
447 |
const int type_count = CFArrayGetCount(types);
|
|
448 |
for(int i = 0; i < type_count; ++i) {
|
|
449 |
const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
|
|
450 |
#ifdef DEBUG_PASTEBOARD
|
|
451 |
qDebug(" -%s", qPrintable(QString(flavor)));
|
|
452 |
#endif
|
|
453 |
QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
|
|
454 |
if(!mimeType.isEmpty() && !ret.contains(mimeType)) {
|
|
455 |
#ifdef DEBUG_PASTEBOARD
|
|
456 |
qDebug(" -<%d> %s [%s]", ret.size(), qPrintable(mimeType), qPrintable(QString(flavor)));
|
|
457 |
#endif
|
|
458 |
ret << mimeType;
|
|
459 |
}
|
|
460 |
}
|
|
461 |
}
|
|
462 |
return ret;
|
|
463 |
}
|
|
464 |
|
|
465 |
bool
|
|
466 |
QMacPasteboard::hasFormat(const QString &format) const
|
|
467 |
{
|
|
468 |
if (!paste)
|
|
469 |
return false;
|
|
470 |
|
|
471 |
sync();
|
|
472 |
|
|
473 |
ItemCount cnt = 0;
|
|
474 |
if(PasteboardGetItemCount(paste, &cnt) || !cnt)
|
|
475 |
return false;
|
|
476 |
|
|
477 |
#ifdef DEBUG_PASTEBOARD
|
|
478 |
qDebug("PasteBoard: hasFormat [%s]", qPrintable(format));
|
|
479 |
#endif
|
|
480 |
for(uint index = 1; index <= cnt; ++index) {
|
|
481 |
|
|
482 |
PasteboardItemID id;
|
|
483 |
if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
|
|
484 |
continue;
|
|
485 |
|
|
486 |
QCFType<CFArrayRef> types;
|
|
487 |
if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
|
|
488 |
continue;
|
|
489 |
|
|
490 |
const int type_count = CFArrayGetCount(types);
|
|
491 |
for(int i = 0; i < type_count; ++i) {
|
|
492 |
const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
|
|
493 |
#ifdef DEBUG_PASTEBOARD
|
|
494 |
qDebug(" -%s [0x%x]", qPrintable(QString(flavor)), mime_type);
|
|
495 |
#endif
|
|
496 |
QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
|
|
497 |
#ifdef DEBUG_PASTEBOARD
|
|
498 |
if(!mimeType.isEmpty())
|
|
499 |
qDebug(" - %s", qPrintable(mimeType));
|
|
500 |
#endif
|
|
501 |
if(mimeType == format)
|
|
502 |
return true;
|
|
503 |
}
|
|
504 |
}
|
|
505 |
return false;
|
|
506 |
}
|
|
507 |
|
|
508 |
QVariant
|
|
509 |
QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
|
|
510 |
{
|
|
511 |
if (!paste)
|
|
512 |
return QVariant();
|
|
513 |
|
|
514 |
sync();
|
|
515 |
|
|
516 |
ItemCount cnt = 0;
|
|
517 |
if(PasteboardGetItemCount(paste, &cnt) || !cnt)
|
|
518 |
return QByteArray();
|
|
519 |
|
|
520 |
#ifdef DEBUG_PASTEBOARD
|
|
521 |
qDebug("Pasteboard: retrieveData [%s]", qPrintable(format));
|
|
522 |
#endif
|
|
523 |
const QList<QMacPasteboardMime *> mimes = QMacPasteboardMime::all(mime_type);
|
|
524 |
for(int mime = 0; mime < mimes.size(); ++mime) {
|
|
525 |
QMacPasteboardMime *c = mimes.at(mime);
|
|
526 |
QString c_flavor = c->flavorFor(format);
|
|
527 |
if(!c_flavor.isEmpty()) {
|
|
528 |
// Handle text/plain a little differently. Try handling Unicode first.
|
|
529 |
bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
|
|
530 |
|| c_flavor == QLatin1String("public.utf8-plain-text"));
|
|
531 |
if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) {
|
|
532 |
// Try to get the NSStringPboardType from NSPasteboard, newlines are mapped
|
|
533 |
// correctly (as '\n') in this data. The 'public.utf16-plain-text' type
|
|
534 |
// usually maps newlines to '\r' instead.
|
|
535 |
QString str = qt_mac_get_pasteboardString();
|
|
536 |
if (!str.isEmpty())
|
|
537 |
return str;
|
|
538 |
}
|
|
539 |
if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text")))
|
|
540 |
c_flavor = QLatin1String("public.utf16-plain-text");
|
|
541 |
|
|
542 |
QVariant ret;
|
|
543 |
QList<QByteArray> retList;
|
|
544 |
for(uint index = 1; index <= cnt; ++index) {
|
|
545 |
PasteboardItemID id;
|
|
546 |
if(PasteboardGetItemIdentifier(paste, index, &id) != noErr)
|
|
547 |
continue;
|
|
548 |
|
|
549 |
QCFType<CFArrayRef> types;
|
|
550 |
if(PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
|
|
551 |
continue;
|
|
552 |
|
|
553 |
const int type_count = CFArrayGetCount(types);
|
|
554 |
for(int i = 0; i < type_count; ++i) {
|
|
555 |
CFStringRef flavor = static_cast<CFStringRef>(CFArrayGetValueAtIndex(types, i));
|
|
556 |
if(c_flavor == QCFString::toQString(flavor)) {
|
|
557 |
QCFType<CFDataRef> macBuffer;
|
|
558 |
if(PasteboardCopyItemFlavorData(paste, id, flavor, &macBuffer) == noErr) {
|
|
559 |
QByteArray buffer((const char *)CFDataGetBytePtr(macBuffer), CFDataGetLength(macBuffer));
|
|
560 |
if(!buffer.isEmpty()) {
|
|
561 |
#ifdef DEBUG_PASTEBOARD
|
|
562 |
qDebug(" - %s [%s] (%s)", qPrintable(format), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
|
|
563 |
#endif
|
|
564 |
buffer.detach(); //detach since we release the macBuffer
|
|
565 |
retList.append(buffer);
|
|
566 |
break; //skip to next element
|
|
567 |
}
|
|
568 |
}
|
|
569 |
} else {
|
|
570 |
#ifdef DEBUG_PASTEBOARD
|
|
571 |
qDebug(" - NoMatch %s [%s] (%s)", qPrintable(c_flavor), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
|
|
572 |
#endif
|
|
573 |
}
|
|
574 |
}
|
|
575 |
}
|
|
576 |
|
|
577 |
if (!retList.isEmpty()) {
|
|
578 |
ret = c->convertToMime(format, retList, c_flavor);
|
|
579 |
return ret;
|
|
580 |
}
|
|
581 |
}
|
|
582 |
}
|
|
583 |
return QVariant();
|
|
584 |
}
|
|
585 |
|
|
586 |
void QMacPasteboard::clear_helper()
|
|
587 |
{
|
|
588 |
if (paste)
|
|
589 |
PasteboardClear(paste);
|
|
590 |
promises.clear();
|
|
591 |
}
|
|
592 |
|
|
593 |
void
|
|
594 |
QMacPasteboard::clear()
|
|
595 |
{
|
|
596 |
#ifdef DEBUG_PASTEBOARD
|
|
597 |
qDebug("PasteBoard: clear!");
|
|
598 |
#endif
|
|
599 |
clear_helper();
|
|
600 |
}
|
|
601 |
|
|
602 |
bool
|
|
603 |
QMacPasteboard::sync() const
|
|
604 |
{
|
|
605 |
if (!paste)
|
|
606 |
return false;
|
|
607 |
const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified;
|
|
608 |
|
|
609 |
if (fromGlobal)
|
|
610 |
const_cast<QMacPasteboard *>(this)->setMimeData(0);
|
|
611 |
|
|
612 |
#ifdef DEBUG_PASTEBOARD
|
|
613 |
if(fromGlobal)
|
|
614 |
qDebug("Pasteboard: Syncronize!");
|
|
615 |
#endif
|
|
616 |
return fromGlobal;
|
|
617 |
}
|
|
618 |
|
|
619 |
|
|
620 |
|
|
621 |
|
|
622 |
QT_END_NAMESPACE
|