Qt 4.8
qdnd_mac.mm
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qapplication.h"
43 #ifndef QT_NO_DRAGANDDROP
44 #include "qbitmap.h"
45 #include "qcursor.h"
46 #include "qevent.h"
47 #include "qpainter.h"
48 #include "qurl.h"
49 #include "qwidget.h"
50 #include "qfile.h"
51 #include "qfileinfo.h"
52 #include <stdlib.h>
53 #include <string.h>
54 #ifndef QT_NO_ACCESSIBILITY
55 # include "qaccessible.h"
56 #endif
57 
58 #include <private/qapplication_p.h>
59 #include <private/qwidget_p.h>
60 #include <private/qdnd_p.h>
61 #include <private/qt_mac_p.h>
62 
64 
66 
68 
69 /*****************************************************************************
70  QDnD debug facilities
71  *****************************************************************************/
72 //#define DEBUG_DRAG_EVENTS
73 //#define DEBUG_DRAG_PROMISES
74 
75 /*****************************************************************************
76  QDnD globals
77  *****************************************************************************/
78 bool qt_mac_in_drag = false;
79 #ifndef QT_MAC_USE_COCOA
80 static DragReference qt_mac_current_dragRef = 0;
81 #endif
82 
83 /*****************************************************************************
84  Externals
85  *****************************************************************************/
86 extern void qt_mac_send_modifiers_changed(quint32, QObject *); //qapplication_mac.cpp
87 extern uint qGlobalPostedEventsCount(); //qapplication.cpp
88 extern RgnHandle qt_mac_get_rgn(); // qregion_mac.cpp
89 extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp
90 /*****************************************************************************
91  QDnD utility functions
92  *****************************************************************************/
93 
94 //default pixmap
95 static const int default_pm_hotx = -2;
96 static const int default_pm_hoty = -16;
97 #ifndef QT_MAC_USE_COCOA
98 static const char * const default_pm[] = {
99  "13 9 3 1",
100  ". c None",
101  " c #000000",
102  "X c #FFFFFF",
103  "X X X X X X X",
104  " X X X X X X ",
105  "X ......... X",
106  " X.........X ",
107  "X ......... X",
108  " X.........X ",
109  "X ......... X",
110  " X X X X X X ",
111  "X X X X X X X",
112 };
113 #endif
114 
115 //action management
116 #ifdef DEBUG_DRAG_EVENTS
117 # define MAP_MAC_ENUM(x) x, #x
118 #else
119 # define MAP_MAC_ENUM(x) x
120 #endif
122 {
123  int mac_code;
124  int qt_code;
125 #ifdef DEBUG_DRAG_EVENTS
126  char *qt_desc;
127 #endif
128 };
129 #ifndef QT_MAC_USE_COCOA
131  { kDragActionAlias, MAP_MAC_ENUM(Qt::LinkAction) },
132  { kDragActionMove, MAP_MAC_ENUM(Qt::MoveAction) },
133  { kDragActionGeneric, MAP_MAC_ENUM(Qt::CopyAction) },
134  { kDragActionCopy, MAP_MAC_ENUM(Qt::CopyAction) },
135  { 0, MAP_MAC_ENUM(0) }
136 };
137 static DragActions qt_mac_dnd_map_qt_actions(Qt::DropActions qActions)
138 {
139  DragActions ret = kDragActionNothing;
140  for(int i = 0; dnd_action_symbols[i].qt_code; ++i) {
141  if(qActions & dnd_action_symbols[i].qt_code)
142  ret |= dnd_action_symbols[i].mac_code;
143  }
144  return ret;
145 }
146 static Qt::DropActions qt_mac_dnd_map_mac_actions(DragActions macActions)
147 {
148 #ifdef DEBUG_DRAG_EVENTS
149  qDebug("Converting DND ActionList: 0x%lx", macActions);
150 #endif
151  Qt::DropActions ret = Qt::IgnoreAction;
152  for(int i = 0; dnd_action_symbols[i].qt_code; ++i) {
153 #ifdef DEBUG_DRAG_EVENTS
154  qDebug(" %d) [%s] : %s", i, dnd_action_symbols[i].qt_desc,
155  (macActions & dnd_action_symbols[i].mac_code) ? "true" : "false");
156 #endif
157  if(macActions & dnd_action_symbols[i].mac_code)
158  ret |= Qt::DropAction(dnd_action_symbols[i].qt_code);
159  }
160  return ret;
161 }
162 static Qt::DropAction qt_mac_dnd_map_mac_default_action(DragActions macActions)
163 {
164  static Qt::DropAction preferred_actions[] = { Qt::CopyAction, Qt::LinkAction, //in order
167  const Qt::DropActions qtActions = qt_mac_dnd_map_mac_actions(macActions);
168  for(int i = 0; preferred_actions[i] != Qt::IgnoreAction; ++i) {
169  if(qtActions & preferred_actions[i]) {
170  ret = preferred_actions[i];
171  break;
172  }
173  }
174 #ifdef DEBUG_DRAG_EVENTS
175  for(int i = 0; dnd_action_symbols[i].qt_code; ++i) {
176  if(dnd_action_symbols[i].qt_code == ret) {
177  qDebug("Got default action: %s [0x%lx]", dnd_action_symbols[i].qt_desc, macActions);
178  break;
179  }
180  }
181 #endif
182  return ret;
183 }
184 static void qt_mac_dnd_update_action(DragReference dragRef) {
185  SInt16 modifiers;
186  GetDragModifiers(dragRef, &modifiers, 0, 0);
188 
189  Qt::DropAction qtAction = Qt::IgnoreAction;
190  {
191  DragActions macAllowed = kDragActionNothing;
192  GetDragDropAction(dragRef, &macAllowed);
193  Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(macAllowed);
195 #if 1
196  if(!(qtAllowed & qtAction))
197  qtAction = qt_mac_dnd_map_mac_default_action(macAllowed);
198 #endif
199  }
200  DragActions macAction = qt_mac_dnd_map_qt_actions(qtAction);
201 
202  DragActions currentActions;
203  GetDragDropAction(dragRef, &currentActions);
204  if(currentActions != macAction) {
205  SetDragDropAction(dragRef, macAction);
207  }
208 }
209 #endif // !QT_MAC_USE_COCOA
210 
211 /*****************************************************************************
212  DnD functions
213  *****************************************************************************/
215 {
216 #ifndef QT_MAC_USE_COCOA
217  OSPasteboardRef board;
218  if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) {
219  qDebug("DnD: Cannot get PasteBoard!");
220  return false;
221  }
223 #else
224  Q_UNUSED(mime);
225  return false;
226 #endif // !QT_MAC_USE_COCOA
227 }
228 
230 {
231 #ifndef QT_MAC_USE_COCOA
232  OSPasteboardRef board;
233  if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) {
234  qDebug("DnD: Cannot get PasteBoard!");
235  return QVariant();
236  }
237  return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mime, type);
238 #else
239  Q_UNUSED(mime);
240  Q_UNUSED(type);
241  return QVariant();
242 #endif // !QT_MAC_USE_COCOA
243 }
244 
246 {
247 #ifndef QT_MAC_USE_COCOA
248  OSPasteboardRef board;
249  if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) {
250  qDebug("DnD: Cannot get PasteBoard!");
251  return QStringList();
252  }
254 #else
255  return QStringList();
256 #endif
257 }
258 
260 {
261 }
262 
264 {
265  return false;
266 }
267 
269 {
270 }
271 
273 {
274  if(object) {
275  beingCancelled = true;
276  object = 0;
277  }
278 #ifndef QT_NO_ACCESSIBILITY
280 #endif
281 }
282 
284 {
285 }
286 
288 {
289 }
290 
296 static inline bool qt_mac_set_existing_drop_action(const DragRef &dragRef, QDropEvent &event)
297 {
298 #ifndef QT_MAC_USE_COCOA
299  DragActions currentAction = kDragActionNothing;
300  OSStatus err = GetDragDropAction(dragRef, &currentAction);
301  if (err == noErr && currentAction != kDragActionNothing) {
302  // This looks a bit evil, but we only ever set one action, so it's OK.
303  event.setDropAction(Qt::DropAction(int(qt_mac_dnd_map_mac_actions(currentAction))));
304  return true;
305  }
306 #else
307  Q_UNUSED(dragRef);
308  Q_UNUSED(event);
309 #endif
310  return false;
311 }
312 
319 {
320  if (!event.answerRect().isEmpty()) {
321  qt_mac_dnd_answer_rec.rect = event.answerRect();
322  qt_mac_dnd_answer_rec.buttons = event.mouseButtons();
323  qt_mac_dnd_answer_rec.modifiers = event.keyboardModifiers();
324  qt_mac_dnd_answer_rec.lastAction = event.dropAction();
325  }
326 }
327 
329 {
330  if (!qt_mac_dnd_answer_rec.rect.isEmpty()
331  && qt_mac_dnd_answer_rec.rect.contains(mouse)
332  && QApplication::mouseButtons() == qt_mac_dnd_answer_rec.buttons
333  && QApplication::keyboardModifiers() == qt_mac_dnd_answer_rec.modifiers)
334  return true;
335  else
336  return false;
337 }
338 
339 bool QWidgetPrivate::qt_mac_dnd_event(uint kind, DragRef dragRef)
340 {
341 #ifndef QT_MAC_USE_COCOA
342  Q_Q(QWidget);
343  qt_mac_current_dragRef = dragRef;
344  if (kind != kEventControlDragLeave)
345  qt_mac_dnd_update_action(dragRef);
346 
347  Point mouse;
348  GetDragMouse(dragRef, &mouse, 0L);
349  if(!mouse.h && !mouse.v)
350  GetGlobalMouse(&mouse);
351 
353  for(QWidget *modal = q; modal; modal = modal->parentWidget()) {
354  if(modal->isWindow()) {
356  return noErr;
357  break;
358  }
359  }
360  }
361 
362  //lookup the possible actions
363  DragActions allowed = kDragActionNothing;
364  GetDragAllowableActions(dragRef, &allowed);
365  Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(allowed);
366 
367  //lookup the source dragAccepted
368  QMimeData *dropdata = QDragManager::self()->dropData;
369  if(QDragManager::self()->source())
370  dropdata = QDragManager::self()->dragPrivate()->data;
371 
372  // 'interrestedInDrag' should end up being 'true' if a later drop
373  // will be accepted by the widget for the current mouse position
374  bool interrestedInDrag = true;
375 
376  //Dispatch events
377  if (kind == kEventControlDragWithin) {
378  if (qt_mac_mouse_inside_answer_rect(q->mapFromGlobal(QPoint(mouse.h, mouse.v))))
379  return qt_mac_dnd_answer_rec.lastAction == Qt::IgnoreAction;
380  else
381  qt_mac_dnd_answer_rec.clear();
382 
383  QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
385 
386  // Accept the event by default if a
387  // drag action exists on the carbon event
388  if (qt_mac_set_existing_drop_action(dragRef, qDMEvent))
389  qDMEvent.accept();
390 
391  QApplication::sendEvent(q, &qDMEvent);
392  if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction)
393  interrestedInDrag = false;
394 
395  qt_mac_copy_answer_rect(qDMEvent);
396  SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction()));
397 
398  } else if (kind == kEventControlDragEnter) {
399  qt_mac_dnd_answer_rec.clear();
400 
401  QDragEnterEvent qDEEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
403  qt_mac_set_existing_drop_action(dragRef, qDEEvent);
404  QApplication::sendEvent(q, &qDEEvent);
405  SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDEEvent.dropAction()));
406 
407  if (!qDEEvent.isAccepted())
408  // The widget is simply not interested in this
409  // drag. So tell carbon this by returning 'false'. We will then
410  // not receive any further move, drop or leave events for this widget.
411  return false;
412  else {
413  // Documentation states that a drag move event is sent immediately after
414  // a drag enter event. So we do that. This will honor widgets overriding
415  // 'dragMoveEvent' only, and not 'dragEnterEvent'
416  QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
418  qDMEvent.accept(); // accept by default, since enter event was accepted.
419  qDMEvent.setDropAction(qDEEvent.dropAction());
420  QApplication::sendEvent(q, &qDMEvent);
421  if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction)
422  interrestedInDrag = false;
423 
424  qt_mac_copy_answer_rect(qDMEvent);
425  SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction()));
426  }
427 
428  } else if(kind == kEventControlDragLeave) {
429  QDragLeaveEvent de;
430  QApplication::sendEvent(q, &de);
431  } else if(kind == kEventControlDragReceive) {
432  QDropEvent de(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata,
436  QApplication::sendEvent(q, &de);
437  if(!de.isAccepted()) {
438  interrestedInDrag = false;
439  SetDragDropAction(dragRef, kDragActionNothing);
440  } else {
441  if(QDragManager::self()->object)
442  QDragManager::self()->dragPrivate()->executed_action = de.dropAction();
443  SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(de.dropAction()));
444  }
445  }
446 
447 #ifdef DEBUG_DRAG_EVENTS
448  {
449  const char *desc = 0;
450  switch(kind) {
451  case kEventControlDragWithin: desc = "DragMove"; break;
452  case kEventControlDragEnter: desc = "DragEnter"; break;
453  case kEventControlDragLeave: desc = "DragLeave"; break;
454  case kEventControlDragReceive: desc = "DragDrop"; break;
455  }
456  if(desc) {
457  QPoint pos(q->mapFromGlobal(QPoint(mouse.h, mouse.v)));
458  qDebug("Sending <%s>(%d, %d) event to %p(%s::%s) [%d] (%p)",
459  desc, pos.x(), pos.y(), q, q->metaObject()->className(),
460  q->objectName().toLocal8Bit().constData(), ret, dragRef);
461  }
462  }
463 #endif
464 
465  //set the cursor
466  bool found_cursor = false;
467  if(kind == kEventControlDragWithin || kind == kEventControlDragEnter) {
468  ThemeCursor cursor = kThemeNotAllowedCursor;
469  found_cursor = true;
470  if (interrestedInDrag) {
471  DragActions action = kDragActionNothing;
472  GetDragDropAction(dragRef, &action);
473  switch(qt_mac_dnd_map_mac_default_action(action)) {
474  case Qt::IgnoreAction:
475  cursor = kThemeNotAllowedCursor;
476  break;
477  case Qt::MoveAction:
478  cursor = kThemeArrowCursor;
479  break;
480  case Qt::CopyAction:
481  cursor = kThemeCopyArrowCursor;
482  break;
483  case Qt::LinkAction:
484  cursor = kThemeAliasArrowCursor;
485  break;
486  default:
487  cursor = kThemeNotAllowedCursor;
488  break;
489  }
490  }
491  SetThemeCursor(cursor);
492  }
493  if(found_cursor) {
494  qt_mac_set_cursor(0); //just use our's
495  } else {
496  QCursor cursor(Qt::ArrowCursor);
497  if(qApp && qApp->overrideCursor()) {
498  cursor = *qApp->overrideCursor();
499  } else if(q) {
500  for(QWidget *p = q; p; p = p->parentWidget()) {
501  if(p->isEnabled() && p->testAttribute(Qt::WA_SetCursor)) {
502  cursor = p->cursor();
503  break;
504  }
505  }
506  }
507  qt_mac_set_cursor(&cursor);
508  }
509 
510  //idle things
514  }
515 
516  // If this was not a drop, tell carbon that we will be interresed in receiving more
517  // events for the current drag. We do that by returning true.
518  if (kind == kEventControlDragReceive)
519  return interrestedInDrag;
520  else
521  return true;
522 #else
523  Q_UNUSED(kind);
524  Q_UNUSED(dragRef);
525  return false;
526 #endif // !QT_MAC_USE_COCOA
527 }
528 
529 #ifndef QT_MAC_USE_COCOA
531 {
532 
533  if(qt_mac_in_drag) { //just make sure..
534  qWarning("Qt: Internal error: WH0A, unexpected condition reached");
535  return Qt::IgnoreAction;
536  }
537  if(object == o)
538  return Qt::IgnoreAction;
539  /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button
540  so we just bail early to prevent it */
541  if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary))
542  return Qt::IgnoreAction;
543 
544  if(object) {
545  dragPrivate()->source->removeEventFilter(this);
546  cancel();
547  beingCancelled = false;
548  }
549 
550  object = o;
551  dragPrivate()->target = 0;
552 
553 #ifndef QT_NO_ACCESSIBILITY
555 #endif
556 
557  //setup the data
559  dragBoard.setMimeData(dragPrivate()->data);
560 
561  //create the drag
562  OSErr result;
563  DragRef dragRef;
564  if((result = NewDragWithPasteboard(dragBoard.pasteBoard(), &dragRef)))
565  return Qt::IgnoreAction;
566  //setup the actions
567  DragActions possibleActions = qt_mac_dnd_map_qt_actions(dragPrivate()->possible_actions);
568  SetDragAllowableActions(dragRef, //local
569  possibleActions,
570  true);
571  SetDragAllowableActions(dragRef, //remote (same as local)
572  possibleActions,
573  false);
574 
575 
576  QPoint hotspot;
577  QPixmap pix = dragPrivate()->pixmap;
578  if(pix.isNull()) {
579  if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) {
580  //get the string
581  QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text()
582  : dragPrivate()->data->urls().first().toString();
583  if(s.length() > 26)
584  s = s.left(23) + QChar(0x2026);
585  if(!s.isEmpty()) {
586  //draw it
587  QFont f(qApp->font());
588  f.setPointSize(12);
589  QFontMetrics fm(f);
590  const int width = fm.width(s);
591  const int height = fm.height();
592  if(width > 0 && height > 0) {
593  QPixmap tmp(width, height);
594  QPainter p(&tmp);
595  p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0);
596  p.setPen(Qt::color1);
597  p.setFont(f);
598  p.drawText(0, fm.ascent(), s);
599  p.end();
600  //save it
601  pix = tmp;
602  hotspot = QPoint(tmp.width() / 2, tmp.height() / 2);
603  }
604  }
605  } else {
606  pix = QPixmap(default_pm);
608  }
609  } else {
610  hotspot = dragPrivate()->hotspot;
611  }
612 
613  //so we must fake an event
614  EventRecord fakeEvent;
615  GetGlobalMouse(&(fakeEvent.where));
616  fakeEvent.message = 0;
617  fakeEvent.what = mouseDown;
618  fakeEvent.when = EventTimeToTicks(GetCurrentEventTime());
619  fakeEvent.modifiers = GetCurrentKeyModifiers();
620  if(GetCurrentEventButtonState() & 2)
621  fakeEvent.modifiers |= controlKey;
622 
623  //find the hotspot in relation to the pixmap
624  Point boundsPoint;
625  boundsPoint.h = fakeEvent.where.h - hotspot.x();
626  boundsPoint.v = fakeEvent.where.v - hotspot.y();
627  Rect boundsRect;
628  SetRect(&boundsRect, boundsPoint.h, boundsPoint.v, boundsPoint.h + pix.width(), boundsPoint.v + pix.height());
629 
630  //set the drag image
631  QRegion dragRegion(boundsPoint.h, boundsPoint.v, pix.width(), pix.height()), pixRegion;
632  if(!pix.isNull()) {
633  HIPoint hipoint = { -hotspot.x(), -hotspot.y() };
634  CGImageRef img = (CGImageRef)pix.macCGHandle();
635  SetDragImageWithCGImage(dragRef, img, &hipoint, 0);
636  CGImageRelease(img);
637  }
638 
639  SetDragItemBounds(dragRef, (ItemReference)1 , &boundsRect);
640  { //do the drag
641  qt_mac_in_drag = true;
642  qt_mac_dnd_update_action(dragRef);
643  result = TrackDrag(dragRef, &fakeEvent, QMacSmartQuickDrawRegion(dragRegion.toQDRgn()));
644  qt_mac_in_drag = false;
645  }
646  object = 0;
647  if(result == noErr) {
648  // Check if the receiver points us to
649  // a file location. If so, we need to do
650  // the file copy/move ourselves:
651  QCFType<CFURLRef> pasteLocation = 0;
652  PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation);
653  if (pasteLocation){
654  Qt::DropAction action = o->d_func()->defaultDropAction;
655  if (action == Qt::IgnoreAction){
656  if (o->d_func()->possible_actions & Qt::MoveAction)
657  action = Qt::MoveAction;
658  else if (o->d_func()->possible_actions & Qt::CopyAction)
659  action = Qt::CopyAction;
660 
661  }
662  bool atleastOne = false;
663  QList<QUrl> urls = o->mimeData()->urls();
664  for (int i = 0; i < urls.size(); ++i){
665  QUrl fromUrl = urls.at(i);
666  QString filename = QFileInfo(fromUrl.path()).fileName();
667  QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename);
668  if (action == Qt::MoveAction){
669  if (QFile::rename(fromUrl.path(), toUrl.path()))
670  atleastOne = true;
671  } else if (action == Qt::CopyAction){
672  if (QFile::copy(fromUrl.path(), toUrl.path()))
673  atleastOne = true;
674  }
675  }
676  if (atleastOne){
677  DisposeDrag(dragRef);
678  o->setMimeData(0);
679  o->deleteLater();
680  return action;
681  }
682  }
683 
684  DragActions ret = kDragActionNothing;
685  GetDragDropAction(dragRef, &ret);
686  DisposeDrag(dragRef); //cleanup
687  o->setMimeData(0);
688  o->deleteLater();
690  }
691  DisposeDrag(dragRef); //cleanup
692  return Qt::IgnoreAction;
693 }
694 #endif
695 
697 {
698 }
699 
702 {
703  NSString* pasteboardName = (NSString*)pasteboard;
704  [pasteboardName retain];
705  dropPasteboard = pasteboard;
706 }
707 
709 {
710  NSString* pasteboardName = (NSString*)dropPasteboard;
711  [pasteboardName release];
712 }
713 
715 {
717  OSPasteboardRef board;
718  if (PasteboardCreate(dropPasteboard, &board) != noErr) {
719  qDebug("DnD: Cannot get PasteBoard!");
720  return formats;
721  }
723  return formats;
724 }
725 
727 {
728  QVariant data;
729  OSPasteboardRef board;
730  if (PasteboardCreate(dropPasteboard, &board) != noErr) {
731  qDebug("DnD: Cannot get PasteBoard!");
732  return data;
733  }
734  data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type);
735  CFRelease(board);
736  return data;
737 }
738 
739 bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const
740 {
741  bool has = false;
742  OSPasteboardRef board;
743  if (PasteboardCreate(dropPasteboard, &board) != noErr) {
744  qDebug("DnD: Cannot get PasteBoard!");
745  return has;
746  }
747  has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType);
748  CFRelease(board);
749  return has;
750 }
751 
752 #endif // QT_NO_DRAGANDDROP
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
void setPointSize(int)
Sets the point size to pointSize.
Definition: qfont.cpp:1099
void updateCursor()
Definition: qdnd_mac.mm:268
const struct __CFString * CFStringRef
static void updateAccessibility(QObject *, int who, Event reason)
Notifies accessibility clients about a change in object&#39;s accessibility information.
QWidget * parentWidget() const
Returns the parent of this widget, or 0 if it does not have any parent widget.
Definition: qwidget.h:1035
static DragActions qt_mac_dnd_map_qt_actions(Qt::DropActions qActions)
Definition: qdnd_mac.mm:137
int width(const QString &, int len=-1) const
Returns the width in pixels of the first len characters of text.
bool rename(const QString &newName)
Renames the file currently specified by fileName() to newName.
Definition: qfile.cpp:766
bool hasFormat_sys(const QString &mimeType) const
Definition: qdnd_mac.mm:214
bool qt_mac_mouse_inside_answer_rect(QPoint mouse)
Definition: qdnd_mac.mm:328
int type
Definition: qmetatype.cpp:239
QStringList formats_sys() const
Definition: qdnd_mac.mm:245
The QCursor class provides a mouse cursor with an arbitrary shape.
Definition: qcursor.h:89
The QFontMetrics class provides font metrics information.
Definition: qfontmetrics.h:65
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QDrag class provides support for MIME-based drag and drop data transfer.
Definition: qdrag.h:61
int width() const
Returns the width of the pixmap.
Definition: qpixmap.cpp:630
EventRef event
void setMimeData(QMimeData *data)
Sets the data to be sent to the given MIME data.
Definition: qdrag.cpp:142
static mac_enum_mapper dnd_action_symbols[]
Definition: qdnd_mac.mm:130
PasteboardRef OSPasteboardRef
QDrag * object
Definition: qdnd_p.h:238
Qt::DropAction defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const
Definition: qdnd.cpp:194
uint qGlobalPostedEventsCount()
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define MAP_MAC_ENUM(x)
Definition: qdnd_mac.mm:119
static const int default_pm_hotx
Definition: qdnd_mac.mm:95
void qt_mac_set_cursor(const QCursor *)
Definition: qcursor_mac.mm:108
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QWidget * target
Definition: qdnd_p.h:178
static QString toQString(CFStringRef cfstr)
Definition: qcore_mac.cpp:47
const char * mime
void accept()
Calls QDropEvent::accept().
Definition: qevent.h:539
static Qt::DropActions qt_mac_dnd_map_mac_actions(DragActions macActions)
Definition: qdnd_mac.mm:146
struct CGImage * CGImageRef
QByteArray data(const QString &mimetype) const
Returns the data stored in the object in the format described by the MIME type specified by mimeType...
Definition: qmimedata.cpp:524
static const char *const default_pm[]
Definition: qdnd_mac.mm:98
void cancel(bool deleteSource=true)
Definition: qdnd_mac.mm:272
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QDragMoveEvent class provides an event which is sent while a drag and drop action is in progress...
Definition: qevent.h:530
static const int default_pm_hoty
Definition: qdnd_mac.mm:96
void emitActionChanged(Qt::DropAction newAction)
Definition: qdnd_p.h:253
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
Qt::KeyboardModifiers modifiers
Definition: qt_mac_p.h:268
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QChar * data()
Returns a pointer to the data stored in the QString.
Definition: qstring.h:710
bool qt_mac_in_drag
Definition: qdnd_mac.mm:78
QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const
Definition: qdnd_mac.mm:726
OSPasteboardRef pasteBoard() const
QCocoaDropData(CFStringRef pasteboard)
Definition: qdnd_mac.mm:700
QString path() const
Returns the path of the URL.
Definition: qurl.cpp:4977
Qt::DropAction drag(QDrag *)
Definition: qdnd_mac.mm:530
#define Q_Q(Class)
Definition: qglobal.h:2483
int ascent() const
Returns the ascent of the font.
Q_CORE_EXPORT void qDebug(const char *,...)
static Qt::DropAction qt_mac_dnd_map_mac_default_action(DragActions macActions)
Definition: qdnd_mac.mm:162
static QWidget * activeModalWidget()
Returns the active modal widget.
void drawText(const QPointF &p, const QString &s)
Draws the given text with the currently defined text direction, beginning at the given position...
Definition: qpainter.cpp:6231
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
CFStringRef dropPasteboard
Definition: qdnd_p.h:327
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
static bool qt_mac_set_existing_drop_action(const DragRef &dragRef, QDropEvent &event)
Definition: qdnd_mac.mm:296
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QRect answerRect() const
Returns the rectangle in the widget where the drop will occur if accepted.
Definition: qevent.h:537
#define qApp
void updatePixmap()
Definition: qdnd_mac.mm:696
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
QVariant retrieveData(const QString &format, QVariant::Type) const
QStringList formats() const
Returns a list of formats supported by the object.
Definition: qdnd.cpp:351
static Qt::DropActions possible_actions
Definition: qdnd_qws.cpp:79
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static void sendPostedEvents()
The QDragLeaveEvent class provides an event that is sent to a widget when a drag and drop action leav...
Definition: qevent.h:577
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
QList< QUrl > urls() const
Returns a list of URLs contained within the MIME data object.
Definition: qmimedata.cpp:310
DropAction
Definition: qnamespace.h:1597
signed long OSStatus
The QMimeData class provides a container for data that records information about its MIME type...
Definition: qmimedata.h:57
struct OpaqueRgnHandle * RgnHandle
bool hasFormat(const QString &format) const
bool contains(const QPoint &p, bool proper=false) const
Returns true if the given point is inside or on the edge of the rectangle, otherwise returns false...
Definition: qrect.cpp:1101
Qt::MouseButtons buttons
Definition: qt_mac_p.h:269
void qt_mac_copy_answer_rect(const QDragMoveEvent &event)
Definition: qdnd_mac.mm:318
static QDragManager * self()
Definition: qdnd.cpp:163
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const
Definition: qdnd_mac.mm:229
QStringList formats() const
QMacDndAnswerRecord qt_mac_dnd_answer_rec
Definition: qdnd_mac.mm:67
The QDropEvent class provides an event which is sent when a drag and drop action is completed...
Definition: qevent.h:476
static Qt::KeyboardModifiers keyboardModifiers()
Returns the current state of the modifier keys on the keyboard.
static void qt_mac_dnd_update_action(DragReference dragRef)
Definition: qdnd_mac.mm:184
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:341
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
QMimeData * data
Definition: qdnd_p.h:179
QMimeData * mimeData() const
Returns the MIME data that is encapsulated by the drag object.
Definition: qdrag.cpp:155
QDropData * dropData
Definition: qdnd_p.h:251
Qt::DropAction executed_action
Definition: qdnd_p.h:183
static DragReference qt_mac_current_dragRef
Definition: qdnd_mac.mm:80
The QDragEnterEvent class provides an event which is sent to a widget when a drag and drop action ent...
Definition: qevent.h:555
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
unsigned int quint32
Definition: qglobal.h:938
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
void setPen(const QColor &color)
Sets the painter&#39;s pen to have style Qt::SolidLine, width 0 and the specified color.
Definition: qpainter.cpp:4047
void setMimeData(QMimeData *mime)
bool copy(const QString &newName)
Copies the file currently specified by fileName() to a file called newName.
Definition: qfile.cpp:926
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
#define QT_USE_NAMESPACE
This macro expands to using QT_NAMESPACE if QT_NAMESPACE is defined and nothing otherwise.
Definition: qglobal.h:88
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
QStringList formats_sys() const
Definition: qdnd_mac.mm:714
bool modal
Definition: qmenu_mac.mm:99
int height() const
Returns the height of the pixmap.
Definition: qpixmap.cpp:645
RgnHandle qt_mac_get_rgn()
Qt::DropAction lastAction
Definition: qt_mac_p.h:270
void setFont(const QFont &f)
Sets the painter&#39;s font to the given font.
Definition: qpainter.cpp:4288
static Qt::MouseButtons mouseButtons()
Returns the current state of the buttons on the mouse.
void qt_mac_send_modifiers_changed(quint32, QObject *)
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
void move(const QPoint &)
Definition: qdnd_mac.mm:283
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
int height() const
Returns the height of the font.
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
void drop()
Definition: qdnd_mac.mm:287
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok=0)
bool eventFilter(QObject *, QEvent *)
Filters events if this object has been installed as an event filter for the watched object...
Definition: qdnd_mac.mm:263
QDragPrivate * dragPrivate() const
Definition: qdnd_p.h:231
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QString fileName(const QString &fileUrl)
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
bool end()
Ends painting.
Definition: qpainter.cpp:1929
static void flush()
Flushes the platform specific event queues.
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
Definition: qpainter.cpp:7420
bool hasFormat_sys(const QString &mimeType) const
Definition: qdnd_mac.mm:739
void qt_mac_dispose_rgn(RgnHandle)
void timerEvent(QTimerEvent *)
This event handler can be reimplemented in a subclass to receive timer events for the object...
Definition: qdnd_mac.mm:259
QWidget * target() const
Returns the target of the drag and drop operation.
Definition: qdrag.cpp:219