|
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 |