diff options
author | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
commit | 8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch) | |
tree | a17e1a767a89542ab59907462206d7dcf2e504b2 /src/gui/kernel/qdnd_mac.mm | |
download | Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2 |
Long live Qt for S60!
Diffstat (limited to 'src/gui/kernel/qdnd_mac.mm')
-rw-r--r-- | src/gui/kernel/qdnd_mac.mm | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/src/gui/kernel/qdnd_mac.mm b/src/gui/kernel/qdnd_mac.mm new file mode 100644 index 0000000..0b8a485 --- /dev/null +++ b/src/gui/kernel/qdnd_mac.mm @@ -0,0 +1,749 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qapplication.h" +#ifndef QT_NO_DRAGANDDROP +#include "qbitmap.h" +#include "qcursor.h" +#include "qevent.h" +#include "qpainter.h" +#include "qurl.h" +#include "qwidget.h" +#include "qfile.h" +#include "qfileinfo.h" +#include <stdlib.h> +#include <string.h> +#ifndef QT_NO_ACCESSIBILITY +# include "qaccessible.h" +#endif + +#include <private/qapplication_p.h> +#include <private/qwidget_p.h> +#include <private/qdnd_p.h> +#include <private/qt_mac_p.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +QMacDndAnswerRecord qt_mac_dnd_answer_rec; + +/***************************************************************************** + QDnD debug facilities + *****************************************************************************/ +//#define DEBUG_DRAG_EVENTS +//#define DEBUG_DRAG_PROMISES + +/***************************************************************************** + QDnD globals + *****************************************************************************/ +bool qt_mac_in_drag = false; +#ifndef QT_MAC_USE_COCOA +static DragReference qt_mac_current_dragRef = 0; +#endif + +/***************************************************************************** + Externals + *****************************************************************************/ +extern void qt_mac_send_modifiers_changed(quint32, QObject *); //qapplication_mac.cpp +extern uint qGlobalPostedEventsCount(); //qapplication.cpp +extern RgnHandle qt_mac_get_rgn(); // qregion_mac.cpp +extern void qt_mac_dispose_rgn(RgnHandle); // qregion_mac.cpp +/***************************************************************************** + QDnD utility functions + *****************************************************************************/ + +//default pixmap +static const int default_pm_hotx = -2; +static const int default_pm_hoty = -16; +#ifndef QT_MAC_USE_COCOA +static const char * const default_pm[] = { + "13 9 3 1", + ". c None", + " c #000000", + "X c #FFFFFF", + "X X X X X X X", + " X X X X X X ", + "X ......... X", + " X.........X ", + "X ......... X", + " X.........X ", + "X ......... X", + " X X X X X X ", + "X X X X X X X", +}; +#endif + +//action management +#ifdef DEBUG_DRAG_EVENTS +# define MAP_MAC_ENUM(x) x, #x +#else +# define MAP_MAC_ENUM(x) x +#endif +struct mac_enum_mapper +{ + int mac_code; + int qt_code; +#ifdef DEBUG_DRAG_EVENTS + char *qt_desc; +#endif +}; +#ifndef QT_MAC_USE_COCOA +static mac_enum_mapper dnd_action_symbols[] = { + { kDragActionAlias, MAP_MAC_ENUM(Qt::LinkAction) }, + { kDragActionMove, MAP_MAC_ENUM(Qt::MoveAction) }, + { kDragActionGeneric, MAP_MAC_ENUM(Qt::CopyAction) }, + { kDragActionCopy, MAP_MAC_ENUM(Qt::CopyAction) }, + { 0, MAP_MAC_ENUM(0) } +}; +static DragActions qt_mac_dnd_map_qt_actions(Qt::DropActions qActions) +{ + DragActions ret = kDragActionNothing; + for(int i = 0; dnd_action_symbols[i].qt_code; ++i) { + if(qActions & dnd_action_symbols[i].qt_code) + ret |= dnd_action_symbols[i].mac_code; + } + return ret; +} +static Qt::DropActions qt_mac_dnd_map_mac_actions(DragActions macActions) +{ +#ifdef DEBUG_DRAG_EVENTS + qDebug("Converting DND ActionList: 0x%lx", macActions); +#endif + Qt::DropActions ret = Qt::IgnoreAction; + for(int i = 0; dnd_action_symbols[i].qt_code; ++i) { +#ifdef DEBUG_DRAG_EVENTS + qDebug(" %d) [%s] : %s", i, dnd_action_symbols[i].qt_desc, + (macActions & dnd_action_symbols[i].mac_code) ? "true" : "false"); +#endif + if(macActions & dnd_action_symbols[i].mac_code) + ret |= Qt::DropAction(dnd_action_symbols[i].qt_code); + } + return ret; +} +static Qt::DropAction qt_mac_dnd_map_mac_default_action(DragActions macActions) +{ + static Qt::DropAction preferred_actions[] = { Qt::CopyAction, Qt::LinkAction, //in order + Qt::MoveAction, Qt::IgnoreAction }; + Qt::DropAction ret = Qt::IgnoreAction; + const Qt::DropActions qtActions = qt_mac_dnd_map_mac_actions(macActions); + for(int i = 0; preferred_actions[i] != Qt::IgnoreAction; ++i) { + if(qtActions & preferred_actions[i]) { + ret = preferred_actions[i]; + break; + } + } +#ifdef DEBUG_DRAG_EVENTS + for(int i = 0; dnd_action_symbols[i].qt_code; ++i) { + if(dnd_action_symbols[i].qt_code == ret) { + qDebug("Got default action: %s [0x%lx]", dnd_action_symbols[i].qt_desc, macActions); + break; + } + } +#endif + return ret; +} +static void qt_mac_dnd_update_action(DragReference dragRef) { + SInt16 modifiers; + GetDragModifiers(dragRef, &modifiers, 0, 0); + qt_mac_send_modifiers_changed(modifiers, qApp); + + Qt::DropAction qtAction = Qt::IgnoreAction; + { + DragActions macAllowed = kDragActionNothing; + GetDragDropAction(dragRef, &macAllowed); + Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(macAllowed); + qtAction = QDragManager::self()->defaultAction(qtAllowed, QApplication::keyboardModifiers()); +#if 1 + if(!(qtAllowed & qtAction)) + qtAction = qt_mac_dnd_map_mac_default_action(macAllowed); +#endif + } + DragActions macAction = qt_mac_dnd_map_qt_actions(qtAction); + + DragActions currentActions; + GetDragDropAction(dragRef, ¤tActions); + if(currentActions != macAction) { + SetDragDropAction(dragRef, macAction); + QDragManager::self()->emitActionChanged(qtAction); + } +} +#endif // !QT_MAC_USE_COCOA + +/***************************************************************************** + DnD functions + *****************************************************************************/ +bool QDropData::hasFormat_sys(const QString &mime) const +{ +#ifndef QT_MAC_USE_COCOA + OSPasteboardRef board; + if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return false; + } + return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mime); +#else + Q_UNUSED(mime); + return false; +#endif // !QT_MAC_USE_COCOA +} + +QVariant QDropData::retrieveData_sys(const QString &mime, QVariant::Type type) const +{ +#ifndef QT_MAC_USE_COCOA + OSPasteboardRef board; + if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return QVariant(); + } + return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mime, type); +#else + Q_UNUSED(mime); + Q_UNUSED(type); + return QVariant(); +#endif // !QT_MAC_USE_COCOA +} + +QStringList QDropData::formats_sys() const +{ +#ifndef QT_MAC_USE_COCOA + OSPasteboardRef board; + if(GetDragPasteboard(qt_mac_current_dragRef, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return QStringList(); + } + return QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats(); +#else + return QStringList(); +#endif +} + +void QDragManager::timerEvent(QTimerEvent*) +{ +} + +bool QDragManager::eventFilter(QObject *, QEvent *) +{ + return false; +} + +void QDragManager::updateCursor() +{ +} + +void QDragManager::cancel(bool) +{ + if(object) { + beingCancelled = true; + object = 0; + } +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd); +#endif +} + +void QDragManager::move(const QPoint &) +{ +} + +void QDragManager::drop() +{ +} + +/** + If a drop action is already set on the carbon event + (from e.g. an earlier enter event), we insert the same + action on the new Qt event that has yet to be sendt. +*/ +static inline bool qt_mac_set_existing_drop_action(const DragRef &dragRef, QDropEvent &event) +{ +#ifndef QT_MAC_USE_COCOA + DragActions currentAction = kDragActionNothing; + OSStatus err = GetDragDropAction(dragRef, ¤tAction); + if (err == noErr && currentAction != kDragActionNothing) { + // This looks a bit evil, but we only ever set one action, so it's OK. + event.setDropAction(Qt::DropAction(int(qt_mac_dnd_map_mac_actions(currentAction)))); + return true; + } +#else + Q_UNUSED(dragRef); + Q_UNUSED(event); +#endif + return false; +} + +/** + If an answer rect has been set on the event (after being sent + to the global event processor), we store that rect so we can + check if the mouse is in the same area upon next drag move event. +*/ +void qt_mac_copy_answer_rect(const QDragMoveEvent &event) +{ + if (!event.answerRect().isEmpty()) { + qt_mac_dnd_answer_rec.rect = event.answerRect(); + qt_mac_dnd_answer_rec.buttons = event.mouseButtons(); + qt_mac_dnd_answer_rec.modifiers = event.keyboardModifiers(); + qt_mac_dnd_answer_rec.lastAction = event.dropAction(); + } +} + +bool qt_mac_mouse_inside_answer_rect(QPoint mouse) +{ + if (!qt_mac_dnd_answer_rec.rect.isEmpty() + && qt_mac_dnd_answer_rec.rect.contains(mouse) + && QApplication::mouseButtons() == qt_mac_dnd_answer_rec.buttons + && QApplication::keyboardModifiers() == qt_mac_dnd_answer_rec.modifiers) + return true; + else + return false; +} + +bool QWidgetPrivate::qt_mac_dnd_event(uint kind, DragRef dragRef) +{ +#ifndef QT_MAC_USE_COCOA + Q_Q(QWidget); + qt_mac_current_dragRef = dragRef; + if (kind != kEventControlDragLeave) + qt_mac_dnd_update_action(dragRef); + + Point mouse; + GetDragMouse(dragRef, &mouse, 0L); + if(!mouse.h && !mouse.v) + GetGlobalMouse(&mouse); + + if(QApplicationPrivate::modalState()) { + for(QWidget *modal = q; modal; modal = modal->parentWidget()) { + if(modal->isWindow()) { + if(modal != QApplication::activeModalWidget()) + return noErr; + break; + } + } + } + + //lookup the possible actions + DragActions allowed = kDragActionNothing; + GetDragAllowableActions(dragRef, &allowed); + Qt::DropActions qtAllowed = qt_mac_dnd_map_mac_actions(allowed); + + //lookup the source dragAccepted + QMimeData *dropdata = QDragManager::self()->dropData; + if(QDragManager::self()->source()) + dropdata = QDragManager::self()->dragPrivate()->data; + + // 'interrestedInDrag' should end up being 'true' if a later drop + // will be accepted by the widget for the current mouse position + bool interrestedInDrag = true; + + //Dispatch events + if (kind == kEventControlDragWithin) { + if (qt_mac_mouse_inside_answer_rect(q->mapFromGlobal(QPoint(mouse.h, mouse.v)))) + return qt_mac_dnd_answer_rec.lastAction == Qt::IgnoreAction; + else + qt_mac_dnd_answer_rec.clear(); + + QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, + QApplication::mouseButtons(), QApplication::keyboardModifiers()); + + // Accept the event by default if a + // drag action exists on the carbon event + if (qt_mac_set_existing_drop_action(dragRef, qDMEvent)) + qDMEvent.accept(); + + QApplication::sendEvent(q, &qDMEvent); + if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) + interrestedInDrag = false; + + qt_mac_copy_answer_rect(qDMEvent); + SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction())); + + } else if (kind == kEventControlDragEnter) { + qt_mac_dnd_answer_rec.clear(); + + QDragEnterEvent qDEEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, + QApplication::mouseButtons(), QApplication::keyboardModifiers()); + qt_mac_set_existing_drop_action(dragRef, qDEEvent); + QApplication::sendEvent(q, &qDEEvent); + SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDEEvent.dropAction())); + + if (!qDEEvent.isAccepted()) + // The widget is simply not interrested in this + // drag. So tell carbon this by returning 'false'. We will then + // not receive any further move, drop or leave events for this widget. + return false; + else { + // Documentation states that a drag move event is sendt immidiatly after + // a drag enter event. So we do that. This will honor widgets overriding + // 'dragMoveEvent' only, and not 'dragEnterEvent' + QDragMoveEvent qDMEvent(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, + QApplication::mouseButtons(), QApplication::keyboardModifiers()); + qDMEvent.accept(); // accept by default, since enter event was accepted. + qDMEvent.setDropAction(qDEEvent.dropAction()); + QApplication::sendEvent(q, &qDMEvent); + if (!qDMEvent.isAccepted() || qDMEvent.dropAction() == Qt::IgnoreAction) + interrestedInDrag = false; + + qt_mac_copy_answer_rect(qDMEvent); + SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(qDMEvent.dropAction())); + } + + } else if(kind == kEventControlDragLeave) { + QDragLeaveEvent de; + QApplication::sendEvent(q, &de); + } else if(kind == kEventControlDragReceive) { + QDropEvent de(q->mapFromGlobal(QPoint(mouse.h, mouse.v)), qtAllowed, dropdata, + QApplication::mouseButtons(), QApplication::keyboardModifiers()); + if(QDragManager::self()->object) + QDragManager::self()->dragPrivate()->target = q; + QApplication::sendEvent(q, &de); + if(!de.isAccepted()) { + interrestedInDrag = false; + SetDragDropAction(dragRef, kDragActionNothing); + } else { + if(QDragManager::self()->object) + QDragManager::self()->dragPrivate()->executed_action = de.dropAction(); + SetDragDropAction(dragRef, qt_mac_dnd_map_qt_actions(de.dropAction())); + } + } + +#ifdef DEBUG_DRAG_EVENTS + { + const char *desc = 0; + switch(kind) { + case kEventControlDragWithin: desc = "DragMove"; break; + case kEventControlDragEnter: desc = "DragEnter"; break; + case kEventControlDragLeave: desc = "DragLeave"; break; + case kEventControlDragReceive: desc = "DragDrop"; break; + } + if(desc) { + QPoint pos(q->mapFromGlobal(QPoint(mouse.h, mouse.v))); + qDebug("Sending <%s>(%d, %d) event to %p(%s::%s) [%d] (%p)", + desc, pos.x(), pos.y(), q, q->metaObject()->className(), + q->objectName().toLocal8Bit().constData(), ret, dragRef); + } + } +#endif + + //set the cursor + bool found_cursor = false; + if(kind == kEventControlDragWithin || kind == kEventControlDragEnter) { + ThemeCursor cursor = kThemeNotAllowedCursor; + found_cursor = true; + if (interrestedInDrag) { + DragActions action = kDragActionNothing; + GetDragDropAction(dragRef, &action); + switch(qt_mac_dnd_map_mac_default_action(action)) { + case Qt::IgnoreAction: + cursor = kThemeNotAllowedCursor; + break; + case Qt::MoveAction: + cursor = kThemeArrowCursor; + break; + case Qt::CopyAction: + cursor = kThemeCopyArrowCursor; + break; + case Qt::LinkAction: + cursor = kThemeAliasArrowCursor; + break; + default: + cursor = kThemeNotAllowedCursor; + break; + } + } + SetThemeCursor(cursor); + } + if(found_cursor) { + qt_mac_set_cursor(0, QPoint()); //just use our's + } else { + QCursor cursor(Qt::ArrowCursor); + if(qApp && qApp->overrideCursor()) { + cursor = *qApp->overrideCursor(); + } else if(q) { + for(QWidget *p = q; p; p = p->parentWidget()) { + if(p->isEnabled() && p->testAttribute(Qt::WA_SetCursor)) { + cursor = p->cursor(); + break; + } + } + } + qt_mac_set_cursor(&cursor, QPoint(mouse.h, mouse.v)); + } + + //idle things + if(qGlobalPostedEventsCount()) { + QApplication::sendPostedEvents(); + QApplication::flush(); + } + + // If this was not a drop, tell carbon that we will be interresed in receiving more + // events for the current drag. We do that by returning true. + if (kind == kEventControlDragReceive) + return interrestedInDrag; + else + return true; +#else + Q_UNUSED(kind); + Q_UNUSED(dragRef); + return false; +#endif // !QT_MAC_USE_COCOA +} + +#ifndef QT_MAC_USE_COCOA +Qt::DropAction QDragManager::drag(QDrag *o) +{ + + if(qt_mac_in_drag) { //just make sure.. + qWarning("Qt: Internal error: WH0A, unexpected condition reached"); + return Qt::IgnoreAction; + } + if(object == o) + return Qt::IgnoreAction; + /* At the moment it seems clear that Mac OS X does not want to drag with a non-left button + so we just bail early to prevent it */ + if(!(GetCurrentEventButtonState() & kEventMouseButtonPrimary)) + return Qt::IgnoreAction; + + if(object) { + dragPrivate()->source->removeEventFilter(this); + cancel(); + beingCancelled = false; + } + + object = o; + dragPrivate()->target = 0; + +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart); +#endif + + //setup the data + QMacPasteboard dragBoard(QMacPasteboardMime::MIME_DND); + dragBoard.setMimeData(dragPrivate()->data); + + //create the drag + OSErr result; + DragRef dragRef; + if((result = NewDragWithPasteboard(dragBoard.pasteBoard(), &dragRef))) + return Qt::IgnoreAction; + //setup the actions + DragActions possibleActions = qt_mac_dnd_map_qt_actions(dragPrivate()->possible_actions); + SetDragAllowableActions(dragRef, //local + possibleActions, + true); + SetDragAllowableActions(dragRef, //remote (same as local) + possibleActions, + false); + + + QPoint hotspot; + QPixmap pix = dragPrivate()->pixmap; + if(pix.isNull()) { + if(dragPrivate()->data->hasText() || dragPrivate()->data->hasUrls()) { + //get the string + QString s = dragPrivate()->data->hasText() ? dragPrivate()->data->text() + : dragPrivate()->data->urls().first().toString(); + if(s.length() > 26) + s = s.left(23) + QChar(0x2026); + if(!s.isEmpty()) { + //draw it + QFont f(qApp->font()); + f.setPointSize(12); + QFontMetrics fm(f); + const int width = fm.width(s); + const int height = fm.height(); + if(width > 0 && height > 0) { + QPixmap tmp(width, height); + QPainter p(&tmp); + p.fillRect(0, 0, tmp.width(), tmp.height(), Qt::color0); + p.setPen(Qt::color1); + p.setFont(f); + p.drawText(0, fm.ascent(), s); + p.end(); + //save it + pix = tmp; + hotspot = QPoint(tmp.width() / 2, tmp.height() / 2); + } + } + } else { + pix = QPixmap(default_pm); + hotspot = QPoint(default_pm_hotx, default_pm_hoty); + } + } else { + hotspot = dragPrivate()->hotspot; + } + + //so we must fake an event + EventRecord fakeEvent; + GetGlobalMouse(&(fakeEvent.where)); + fakeEvent.message = 0; + fakeEvent.what = mouseDown; + fakeEvent.when = EventTimeToTicks(GetCurrentEventTime()); + fakeEvent.modifiers = GetCurrentKeyModifiers(); + if(GetCurrentEventButtonState() & 2) + fakeEvent.modifiers |= controlKey; + + //find the hotspot in relation to the pixmap + Point boundsPoint; + boundsPoint.h = fakeEvent.where.h - hotspot.x(); + boundsPoint.v = fakeEvent.where.v - hotspot.y(); + Rect boundsRect; + SetRect(&boundsRect, boundsPoint.h, boundsPoint.v, boundsPoint.h + pix.width(), boundsPoint.v + pix.height()); + + //set the drag image + QRegion dragRegion(boundsPoint.h, boundsPoint.v, pix.width(), pix.height()), pixRegion; + if(!pix.isNull()) { + HIPoint hipoint = { -hotspot.x(), -hotspot.y() }; + CGImageRef img = (CGImageRef)pix.macCGHandle(); + SetDragImageWithCGImage(dragRef, img, &hipoint, 0); + CGImageRelease(img); + } + + SetDragItemBounds(dragRef, (ItemReference)1 , &boundsRect); + { //do the drag + qt_mac_in_drag = true; + qt_mac_dnd_update_action(dragRef); + result = TrackDrag(dragRef, &fakeEvent, QMacSmartQuickDrawRegion(dragRegion.toQDRgn())); + qt_mac_in_drag = false; + } + object = 0; + if(result == noErr) { + // Check if the receiver points us to + // a file location. If so, we need to do + // the file copy/move ourselves: + QCFType<CFURLRef> pasteLocation = 0; + PasteboardCopyPasteLocation(dragBoard.pasteBoard(), &pasteLocation); + if (pasteLocation){ + Qt::DropAction action = o->d_func()->defaultDropAction; + if (action == Qt::IgnoreAction){ + if (o->d_func()->possible_actions & Qt::MoveAction) + action = Qt::MoveAction; + else if (o->d_func()->possible_actions & Qt::CopyAction) + action = Qt::CopyAction; + + } + bool atleastOne = false; + QList<QUrl> urls = o->mimeData()->urls(); + for (int i = 0; i < urls.size(); ++i){ + QUrl fromUrl = urls.at(i); + QString filename = QFileInfo(fromUrl.path()).fileName(); + QUrl toUrl(QCFString::toQString(CFURLGetString(pasteLocation)) + filename); + if (action == Qt::MoveAction){ + if (QFile::rename(fromUrl.path(), toUrl.path())) + atleastOne = true; + } else if (action == Qt::CopyAction){ + if (QFile::copy(fromUrl.path(), toUrl.path())) + atleastOne = true; + } + } + if (atleastOne){ + DisposeDrag(dragRef); + return action; + } + } + + DragActions ret = kDragActionNothing; + GetDragDropAction(dragRef, &ret); + DisposeDrag(dragRef); //cleanup + return qt_mac_dnd_map_mac_default_action(ret); + } + DisposeDrag(dragRef); //cleanup + return Qt::IgnoreAction; +} +#endif + +void QDragManager::updatePixmap() +{ +} + +QCocoaDropData::QCocoaDropData(CFStringRef pasteboard) + : QInternalMimeData() +{ + NSString* pasteboardName = (NSString*)pasteboard; + [pasteboardName retain]; + dropPasteboard = pasteboard; +} + +QCocoaDropData::~QCocoaDropData() +{ + NSString* pasteboardName = (NSString*)dropPasteboard; + [pasteboardName release]; +} + +QStringList QCocoaDropData::formats_sys() const +{ + QStringList formats; + OSPasteboardRef board; + if (PasteboardCreate(dropPasteboard, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return formats; + } + formats = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats(); + return formats; +} + +QVariant QCocoaDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const +{ + QVariant data; + OSPasteboardRef board; + if (PasteboardCreate(dropPasteboard, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return data; + } + data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type); + CFRelease(board); + return data; +} + +bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const +{ + bool has = false; + OSPasteboardRef board; + if (PasteboardCreate(dropPasteboard, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return has; + } + has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType); + CFRelease(board); + return has; +} + +#endif // QT_NO_DRAGANDDROP +QT_END_NAMESPACE |