summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-05-18 12:56:51 +0200
committerLars Knoll <lars.knoll@nokia.com>2011-05-20 12:21:02 +0200
commit82bba7e4efc369f75f09eb96846d733cd99ba95b (patch)
tree210f73a2df63e626f471452ed3fce5578ed17ae1 /src/gui/kernel
parent1f572c694b6801e9f706ce2c67cc3b1b50f32a5e (diff)
move drag handling back to Gui
Move the DnD related classes back into QtGui. Parts of the implementation is currently commented out and needs to be moved to QWidgetWindow. SC incompatible change: APIs taking QWidget * now take QObject *
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri5
-rw-r--r--src/gui/kernel/qdnd.cpp490
-rw-r--r--src/gui/kernel/qdnd_p.h333
-rw-r--r--src/gui/kernel/qdnd_qpa.cpp434
-rw-r--r--src/gui/kernel/qdrag.cpp358
-rw-r--r--src/gui/kernel/qdrag.h101
6 files changed, 1721 insertions, 0 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 6fda4fd62f..8662329a2d 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -9,6 +9,8 @@ HEADERS += \
kernel/qclipboard.h \
kernel/qcursor.h \
kernel/qcursor_p.h \
+ kernel/qdrag.h \
+ kernel/qdnd_p.h \
kernel/qevent.h \
kernel/qevent_p.h \
kernel/qkeysequence.h \
@@ -22,6 +24,9 @@ HEADERS += \
SOURCES += \
kernel/qclipboard.cpp \
kernel/qcursor.cpp \
+ kernel/qdrag.cpp \
+ kernel/qdnd.cpp \
+ kernel/qdnd_qpa.cpp \
kernel/qevent.cpp \
kernel/qkeysequence.cpp \
kernel/qkeymapper.cpp \
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
new file mode 100644
index 0000000000..55fc3b09fc
--- /dev/null
+++ b/src/gui/kernel/qdnd.cpp
@@ -0,0 +1,490 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qbitmap.h"
+#include "qdrag.h"
+#include "qpixmap.h"
+#include "qevent.h"
+#include "qfile.h"
+#include "qtextcodec.h"
+#include "qguiapplication.h"
+#include "qpoint.h"
+#include "qbuffer.h"
+#include "qimage.h"
+#include "qregexp.h"
+#include "qdir.h"
+#include "qdnd_p.h"
+#include "qimagereader.h"
+#include "qimagewriter.h"
+#include "qdebug.h"
+#include <ctype.h>
+
+#include <private/qguiapplication_p.h>
+
+#ifndef QT_NO_DRAGANDDROP
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_DRAGANDDROP
+
+//#define QDND_DEBUG
+
+#ifdef QDND_DEBUG
+QString dragActionsToString(Qt::DropActions actions)
+{
+ QString str;
+ if (actions == Qt::IgnoreAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "IgnoreAction";
+ }
+ if (actions & Qt::LinkAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "LinkAction";
+ }
+ if (actions & Qt::CopyAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "CopyAction";
+ }
+ if (actions & Qt::MoveAction) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "MoveAction";
+ }
+ if ((actions & Qt::TargetMoveAction) == Qt::TargetMoveAction ) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += "TargetMoveAction";
+ }
+ return str;
+}
+
+QString KeyboardModifiersToString(Qt::KeyboardModifiers moderfies)
+{
+ QString str;
+ if (moderfies & Qt::ControlModifier) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += Qt::ControlModifier;
+ }
+ if (moderfies & Qt::AltModifier) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += Qt::AltModifier;
+ }
+ if (moderfies & Qt::ShiftModifier) {
+ if (!str.isEmpty())
+ str += " | ";
+ str += Qt::ShiftModifier;
+ }
+ return str;
+}
+#endif
+
+
+// the universe's only drag manager
+QDragManager *QDragManager::instance = 0;
+
+
+QDragManager::QDragManager()
+ : QObject(qApp)
+{
+ Q_ASSERT(!instance);
+
+#ifdef Q_WS_QWS
+ currentActionForOverrideCursor = Qt::IgnoreAction;
+#endif
+ object = 0;
+ beingCancelled = false;
+ restoreCursor = false;
+ willDrop = false;
+ eventLoop = 0;
+ dropData = new QDropData();
+ currentDropTarget = 0;
+#ifdef Q_WS_X11
+ xdndMimeTransferedPixmapIndex = 0;
+#endif
+}
+
+
+QDragManager::~QDragManager()
+{
+#ifndef QT_NO_CURSOR
+ if (restoreCursor)
+ QGuiApplication::restoreOverrideCursor();
+#endif
+ instance = 0;
+ delete dropData;
+}
+
+QDragManager *QDragManager::self()
+{
+ if (!instance && !QGuiApplication::closingDown())
+ instance = new QDragManager;
+ return instance;
+}
+
+QPixmap QDragManager::dragCursor(Qt::DropAction action) const
+{
+ QDragPrivate * d = dragPrivate();
+ if (d && d->customCursors.contains(action))
+ return d->customCursors[action];
+ else if (action == Qt::MoveAction)
+ return QGuiApplicationPrivate::instance()->getPixmapCursor(Qt::DragMoveCursor);
+ else if (action == Qt::CopyAction)
+ return QGuiApplicationPrivate::instance()->getPixmapCursor(Qt::DragCopyCursor);
+ else if (action == Qt::LinkAction)
+ return QGuiApplicationPrivate::instance()->getPixmapCursor(Qt::DragLinkCursor);
+#ifdef Q_WS_WIN
+ else if (action == Qt::IgnoreAction)
+ return QGuiApplicationPrivate::instance()->getPixmapCursor(Qt::ForbiddenCursor);
+#endif
+ return QPixmap();
+}
+
+bool QDragManager::hasCustomDragCursors() const
+{
+ QDragPrivate * d = dragPrivate();
+ return d && !d->customCursors.isEmpty();
+}
+
+Qt::DropAction QDragManager::defaultAction(Qt::DropActions possibleActions,
+ Qt::KeyboardModifiers modifiers) const
+{
+#ifdef QDND_DEBUG
+ qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)");
+ qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1());
+#endif
+
+ QDragPrivate *d = dragPrivate();
+ Qt::DropAction defaultAction = d ? d->defaultDropAction : Qt::IgnoreAction;
+
+ if (defaultAction == Qt::IgnoreAction) {
+ //This means that the drag was initiated by QDrag::start and we need to
+ //preserve the old behavior
+#ifdef Q_WS_MAC
+ defaultAction = Qt::MoveAction;
+#else
+ defaultAction = Qt::CopyAction;
+#endif
+ }
+
+#ifdef Q_WS_MAC
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::AltModifier)
+ defaultAction = Qt::LinkAction;
+ else if (modifiers & Qt::AltModifier)
+ defaultAction = Qt::CopyAction;
+ else if (modifiers & Qt::ControlModifier)
+ defaultAction = Qt::MoveAction;
+#else
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier)
+ defaultAction = Qt::LinkAction;
+ else if (modifiers & Qt::ControlModifier)
+ defaultAction = Qt::CopyAction;
+ else if (modifiers & Qt::ShiftModifier)
+ defaultAction = Qt::MoveAction;
+ else if (modifiers & Qt::AltModifier)
+ defaultAction = Qt::LinkAction;
+#endif
+
+ // if the object is set take the list of possibles from it
+ if (object)
+ possibleActions = object->d_func()->possible_actions;
+
+#ifdef QDND_DEBUG
+ qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1());
+#endif
+
+ // Check if the action determined is allowed
+ if (!(possibleActions & defaultAction)) {
+ if (possibleActions & Qt::CopyAction)
+ defaultAction = Qt::CopyAction;
+ else if (possibleActions & Qt::MoveAction)
+ defaultAction = Qt::MoveAction;
+ else if (possibleActions & Qt::LinkAction)
+ defaultAction = Qt::LinkAction;
+ else
+ defaultAction = Qt::IgnoreAction;
+ }
+
+#ifdef QDND_DEBUG
+ qDebug("default action : %s", dragActionsToString(defaultAction).latin1());
+#endif
+
+ return defaultAction;
+}
+
+void QDragManager::setCurrentTarget(QObject *target, bool dropped)
+{
+ if (currentDropTarget == target)
+ return;
+
+ currentDropTarget = target;
+ if (!dropped && object) {
+ object->d_func()->target = target;
+ emit object->targetChanged(target);
+ }
+
+}
+
+QObject *QDragManager::currentTarget()
+{
+ return currentDropTarget;
+}
+
+#endif
+
+QDropData::QDropData()
+ : QInternalMimeData()
+{
+}
+
+QDropData::~QDropData()
+{
+}
+#endif // QT_NO_DRAGANDDROP
+
+#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
+
+static QStringList imageReadMimeFormats()
+{
+ QStringList formats;
+ QList<QByteArray> imageFormats = QImageReader::supportedImageFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ QString format = QLatin1String("image/");
+ format += QString::fromLatin1(imageFormats.at(i).toLower());
+ formats.append(format);
+ }
+
+ //put png at the front because it is best
+ int pngIndex = formats.indexOf(QLatin1String("image/png"));
+ if (pngIndex != -1 && pngIndex != 0)
+ formats.move(pngIndex, 0);
+
+ return formats;
+}
+
+
+static QStringList imageWriteMimeFormats()
+{
+ QStringList formats;
+ QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ QString format = QLatin1String("image/");
+ format += QString::fromLatin1(imageFormats.at(i).toLower());
+ formats.append(format);
+ }
+
+ //put png at the front because it is best
+ int pngIndex = formats.indexOf(QLatin1String("image/png"));
+ if (pngIndex != -1 && pngIndex != 0)
+ formats.move(pngIndex, 0);
+
+ return formats;
+}
+
+QInternalMimeData::QInternalMimeData()
+ : QMimeData()
+{
+}
+
+QInternalMimeData::~QInternalMimeData()
+{
+}
+
+bool QInternalMimeData::hasFormat(const QString &mimeType) const
+{
+ bool foundFormat = hasFormat_sys(mimeType);
+ if (!foundFormat && mimeType == QLatin1String("application/x-qt-image")) {
+ QStringList imageFormats = imageReadMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if ((foundFormat = hasFormat_sys(imageFormats.at(i))))
+ break;
+ }
+ }
+ return foundFormat;
+}
+
+QStringList QInternalMimeData::formats() const
+{
+ QStringList realFormats = formats_sys();
+ if (!realFormats.contains(QLatin1String("application/x-qt-image"))) {
+ QStringList imageFormats = imageReadMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if (realFormats.contains(imageFormats.at(i))) {
+ realFormats += QLatin1String("application/x-qt-image");
+ break;
+ }
+ }
+ }
+ return realFormats;
+}
+
+QVariant QInternalMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant data = retrieveData_sys(mimeType, type);
+ if (mimeType == QLatin1String("application/x-qt-image")) {
+ if (data.isNull() || (data.type() == QVariant::ByteArray && data.toByteArray().isEmpty())) {
+ // try to find an image
+ QStringList imageFormats = imageReadMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ data = retrieveData_sys(imageFormats.at(i), type);
+ if (data.isNull() || (data.type() == QVariant::ByteArray && data.toByteArray().isEmpty()))
+ continue;
+ break;
+ }
+ }
+ // we wanted some image type, but all we got was a byte array. Convert it to an image.
+ if (data.type() == QVariant::ByteArray
+ && (type == QVariant::Image || type == QVariant::Pixmap || type == QVariant::Bitmap))
+ data = QImage::fromData(data.toByteArray());
+
+ } else if (mimeType == QLatin1String("application/x-color") && data.type() == QVariant::ByteArray) {
+ QColor c;
+ QByteArray ba = data.toByteArray();
+ if (ba.size() == 8) {
+ ushort * colBuf = (ushort *)ba.data();
+ c.setRgbF(qreal(colBuf[0]) / qreal(0xFFFF),
+ qreal(colBuf[1]) / qreal(0xFFFF),
+ qreal(colBuf[2]) / qreal(0xFFFF),
+ qreal(colBuf[3]) / qreal(0xFFFF));
+ data = c;
+ } else {
+ qWarning("Qt: Invalid color format");
+ }
+ } else if (data.type() != type && data.type() == QVariant::ByteArray) {
+ // try to use mime data's internal conversion stuf.
+ QInternalMimeData *that = const_cast<QInternalMimeData *>(this);
+ that->setData(mimeType, data.toByteArray());
+ data = QMimeData::retrieveData(mimeType, type);
+ that->clear();
+ }
+ return data;
+}
+
+bool QInternalMimeData::canReadData(const QString &mimeType)
+{
+ return imageReadMimeFormats().contains(mimeType);
+}
+
+// helper functions for rendering mimedata to the system, this is needed because QMimeData is in core.
+QStringList QInternalMimeData::formatsHelper(const QMimeData *data)
+{
+ QStringList realFormats = data->formats();
+ if (realFormats.contains(QLatin1String("application/x-qt-image"))) {
+ // add all supported image formats
+ QStringList imageFormats = imageWriteMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if (!realFormats.contains(imageFormats.at(i)))
+ realFormats.append(imageFormats.at(i));
+ }
+ }
+ return realFormats;
+}
+
+bool QInternalMimeData::hasFormatHelper(const QString &mimeType, const QMimeData *data)
+{
+
+ bool foundFormat = data->hasFormat(mimeType);
+ if (!foundFormat) {
+ if (mimeType == QLatin1String("application/x-qt-image")) {
+ // check all supported image formats
+ QStringList imageFormats = imageWriteMimeFormats();
+ for (int i = 0; i < imageFormats.size(); ++i) {
+ if ((foundFormat = data->hasFormat(imageFormats.at(i))))
+ break;
+ }
+ } else if (mimeType.startsWith(QLatin1String("image/"))) {
+ return data->hasImage() && imageWriteMimeFormats().contains(mimeType);
+ }
+ }
+ return foundFormat;
+}
+
+QByteArray QInternalMimeData::renderDataHelper(const QString &mimeType, const QMimeData *data)
+{
+ QByteArray ba;
+ if (mimeType == QLatin1String("application/x-color")) {
+ /* QMimeData can only provide colors as QColor or the name
+ of a color as a QByteArray or a QString. So we need to do
+ the conversion to application/x-color here.
+ The application/x-color format is :
+ type: application/x-color
+ format: 16
+ data[0]: red
+ data[1]: green
+ data[2]: blue
+ data[3]: opacity
+ */
+ ba.resize(8);
+ ushort * colBuf = (ushort *)ba.data();
+ QColor c = qvariant_cast<QColor>(data->colorData());
+ colBuf[0] = ushort(c.redF() * 0xFFFF);
+ colBuf[1] = ushort(c.greenF() * 0xFFFF);
+ colBuf[2] = ushort(c.blueF() * 0xFFFF);
+ colBuf[3] = ushort(c.alphaF() * 0xFFFF);
+ } else {
+ ba = data->data(mimeType);
+ if (ba.isEmpty()) {
+ if (mimeType == QLatin1String("application/x-qt-image") && data->hasImage()) {
+ QImage image = qvariant_cast<QImage>(data->imageData());
+ QBuffer buf(&ba);
+ buf.open(QBuffer::WriteOnly);
+ // would there not be PNG ??
+ image.save(&buf, "PNG");
+ } else if (mimeType.startsWith(QLatin1String("image/")) && data->hasImage()) {
+ QImage image = qvariant_cast<QImage>(data->imageData());
+ QBuffer buf(&ba);
+ buf.open(QBuffer::WriteOnly);
+ image.save(&buf, mimeType.mid(mimeType.indexOf(QLatin1Char('/')) + 1).toLatin1().toUpper());
+ }
+ }
+ }
+ return ba;
+}
+
+#endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
new file mode 100644
index 0000000000..cc74889bcb
--- /dev/null
+++ b/src/gui/kernel/qdnd_p.h
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDND_P_H
+#define QDND_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+#include "QtCore/qmap.h"
+#include "QtGui/qmime.h"
+#include "QtGui/qdrag.h"
+#include "QtGui/qpixmap.h"
+#include "QtGui/qcursor.h"
+#include "QtCore/qpoint.h"
+#include "private/qobject_p.h"
+#ifdef Q_WS_MAC
+# include "private/qt_mac_p.h"
+#endif
+
+#if defined(Q_WS_WIN)
+# include <qt_windows.h>
+# include <objidl.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QEventLoop;
+
+#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
+
+class Q_GUI_EXPORT QInternalMimeData : public QMimeData
+{
+ Q_OBJECT
+public:
+ QInternalMimeData();
+ ~QInternalMimeData();
+
+ bool hasFormat(const QString &mimeType) const;
+ QStringList formats() const;
+ static bool canReadData(const QString &mimeType);
+
+
+ static QStringList formatsHelper(const QMimeData *data);
+ static bool hasFormatHelper(const QString &mimeType, const QMimeData *data);
+ static QByteArray renderDataHelper(const QString &mimeType, const QMimeData *data);
+
+protected:
+ QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
+
+ virtual bool hasFormat_sys(const QString &mimeType) const = 0;
+ virtual QStringList formats_sys() const = 0;
+ virtual QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const = 0;
+};
+
+#ifdef Q_WS_WIN
+class QOleDataObject : public IDataObject
+{
+public:
+ explicit QOleDataObject(QMimeData *mimeData);
+ virtual ~QOleDataObject();
+
+ void releaseQt();
+ const QMimeData *mimeData() const;
+ DWORD reportedPerformedEffect() const;
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IDataObject methods
+ STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
+ STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium);
+ STDMETHOD(QueryGetData)(LPFORMATETC pformatetc);
+ STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData)(LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease);
+ STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc);
+ STDMETHOD(DAdvise)(FORMATETC FAR* pFormatetc, DWORD advf,
+ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection);
+ STDMETHOD(DUnadvise)(DWORD dwConnection);
+ STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise);
+
+private:
+ ULONG m_refs;
+ QPointer<QMimeData> data;
+ int CF_PERFORMEDDROPEFFECT;
+ DWORD performedEffect;
+};
+
+class QOleEnumFmtEtc : public IEnumFORMATETC
+{
+public:
+ explicit QOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs);
+ explicit QOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs);
+ virtual ~QOleEnumFmtEtc();
+
+ bool isNull() const;
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IEnumFORMATETC methods
+ STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(LPENUMFORMATETC FAR* newEnum);
+
+private:
+ bool copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const;
+
+ ULONG m_dwRefs;
+ ULONG m_nIndex;
+ QVector<LPFORMATETC> m_lpfmtetcs;
+ bool m_isNull;
+};
+
+#endif
+
+#endif //QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
+
+#ifndef QT_NO_DRAGANDDROP
+
+class QDragPrivate : public QObjectPrivate
+{
+public:
+ QObject *source;
+ QObject *target;
+ QMimeData *data;
+ QPixmap pixmap;
+ QPoint hotspot;
+ Qt::DropActions possible_actions;
+ Qt::DropAction executed_action;
+ QMap<Qt::DropAction, QPixmap> customCursors;
+ Qt::DropAction defaultDropAction;
+};
+
+class QDropData : public QInternalMimeData
+{
+ Q_OBJECT
+public:
+ QDropData();
+ ~QDropData();
+
+protected:
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+
+#if defined(Q_WS_WIN)
+public:
+ LPDATAOBJECT currentDataObject;
+#endif
+};
+
+class Q_GUI_EXPORT QDragManager: public QObject {
+ Q_OBJECT
+
+ QDragManager();
+ ~QDragManager();
+ // only friend classes can use QDragManager.
+ friend class QDrag;
+ friend class QDragMoveEvent;
+ friend class QDropEvent;
+ friend class QApplication;
+
+ bool eventFilter(QObject *, QEvent *);
+ void timerEvent(QTimerEvent*);
+
+public:
+ Qt::DropAction drag(QDrag *);
+
+ void cancel(bool deleteSource = true);
+ void move(const QPoint &);
+ void drop();
+ void updatePixmap();
+ QObject *source() const { return object ? object->d_func()->source : 0; }
+ QDragPrivate *dragPrivate() const { return object ? object->d_func() : 0; }
+ static QDragPrivate *dragPrivate(QDrag *drag) { return drag ? drag->d_func() : 0; }
+
+ static QDragManager *self();
+ Qt::DropAction defaultAction(Qt::DropActions possibleActions,
+ Qt::KeyboardModifiers modifiers) const;
+
+ QDrag *object;
+
+ void updateCursor();
+
+ bool beingCancelled;
+ bool restoreCursor;
+ bool willDrop;
+ QEventLoop *eventLoop;
+
+ QPixmap dragCursor(Qt::DropAction action) const;
+
+ bool hasCustomDragCursors() const;
+
+ QDropData *dropData;
+
+ void emitActionChanged(Qt::DropAction newAction) { if (object) emit object->actionChanged(newAction); }
+
+ void setCurrentTarget(QObject *target, bool dropped = false);
+ QObject *currentTarget();
+
+#ifdef Q_WS_X11
+ QPixmap xdndMimeTransferedPixmap[2];
+ int xdndMimeTransferedPixmapIndex;
+#endif
+
+private:
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ Qt::DropAction currentActionForOverrideCursor;
+#endif
+#ifdef Q_OS_SYMBIAN
+#ifndef QT_NO_CURSOR
+ QCursor overrideCursor;
+#endif
+#endif
+ QObject *currentDropTarget;
+
+ static QDragManager *instance;
+ Q_DISABLE_COPY(QDragManager)
+};
+
+
+#if defined(Q_WS_WIN)
+
+class QOleDropTarget : public IDropTarget
+{
+public:
+ QOleDropTarget(QWidget* w);
+ virtual ~QOleDropTarget() {}
+
+ void releaseQt();
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IDropTarget methods
+ STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+ STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+ STDMETHOD(DragLeave)();
+ STDMETHOD(Drop)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+
+private:
+ ULONG m_refs;
+ QWidget* widget;
+ QPointer<QWidget> currentWidget;
+ QRect answerRect;
+ QPoint lastPoint;
+ DWORD chosenEffect;
+ DWORD lastKeyState;
+
+ void sendDragEnterEvent(QWidget *to, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+};
+
+#endif
+
+#if defined (Q_WS_MAC)
+class QCocoaDropData : public QInternalMimeData
+{
+ Q_OBJECT
+public:
+ QCocoaDropData(CFStringRef pasteboard);
+ ~QCocoaDropData();
+
+protected:
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+public:
+ CFStringRef dropPasteboard;
+};
+#endif
+
+#endif // !QT_NO_DRAGANDDROP
+
+
+QT_END_NAMESPACE
+
+#endif // QDND_P_H
diff --git a/src/gui/kernel/qdnd_qpa.cpp b/src/gui/kernel/qdnd_qpa.cpp
new file mode 100644
index 0000000000..e5715bb568
--- /dev/null
+++ b/src/gui/kernel/qdnd_qpa.cpp
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qguiapplication.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+#include "qdatetime.h"
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qdnd_p.h"
+#include "qwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+static QPixmap *defaultPm = 0;
+static const int default_pm_hotx = -2;
+static const int default_pm_hoty = -16;
+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",
+};
+
+// Shift/Ctrl handling, and final drop status
+static Qt::DropAction global_accepted_action = Qt::CopyAction;
+static Qt::DropActions possible_actions = Qt::IgnoreAction;
+
+
+// static variables in place of a proper cross-process solution
+static QDrag *drag_object;
+static bool qt_qws_dnd_dragging = false;
+
+
+static Qt::KeyboardModifiers oldstate;
+
+class QShapedPixmapWindow : public QWindow {
+ QPixmap pixmap;
+public:
+ QShapedPixmapWindow() :
+ QWindow(0)
+ {
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
+ // ### Should we set the surface type to raster?
+ // ### FIXME
+// setAttribute(Qt::WA_TransparentForMouseEvents);
+ }
+
+ void move(const QPoint &p) {
+ QRect g = geometry();
+ g.setTopLeft(p);
+ setGeometry(g);
+ }
+ void setPixmap(QPixmap pm)
+ {
+ pixmap = pm;
+ // ###
+// if (!pixmap.mask().isNull()) {
+// setMask(pixmap.mask());
+// } else {
+// clearMask();
+// }
+// resize(pm.width(),pm.height());
+ }
+
+ // ### Get it painted again!
+// void paintEvent(QPaintEvent*)
+// {
+// QPainter p(this);
+// p.drawPixmap(0,0,pixmap);
+// }
+};
+
+
+static QShapedPixmapWindow *qt_qws_dnd_deco = 0;
+
+
+void QDragManager::updatePixmap()
+{
+ if (qt_qws_dnd_deco) {
+ QPixmap pm;
+ QPoint pm_hot(default_pm_hotx,default_pm_hoty);
+ if (drag_object) {
+ pm = drag_object->pixmap();
+ if (!pm.isNull())
+ pm_hot = drag_object->hotSpot();
+ }
+ if (pm.isNull()) {
+ if (!defaultPm)
+ defaultPm = new QPixmap(default_pm);
+ pm = *defaultPm;
+ }
+ qt_qws_dnd_deco->setPixmap(pm);
+ qt_qws_dnd_deco->move(QCursor::pos()-pm_hot);
+ if (willDrop) {
+ qt_qws_dnd_deco->show();
+ } else {
+ qt_qws_dnd_deco->hide();
+ }
+ }
+}
+
+void QDragManager::timerEvent(QTimerEvent *) { }
+
+void QDragManager::move(const QPoint &) { }
+
+void QDragManager::updateCursor()
+{
+#ifndef QT_NO_CURSOR
+ if (willDrop) {
+ if (qt_qws_dnd_deco)
+ qt_qws_dnd_deco->show();
+ if (currentActionForOverrideCursor != global_accepted_action) {
+ QGuiApplication::changeOverrideCursor(QCursor(dragCursor(global_accepted_action), 0, 0));
+ currentActionForOverrideCursor = global_accepted_action;
+ }
+ } else {
+ QCursor *overrideCursor = QGuiApplication::overrideCursor();
+ if (!overrideCursor || overrideCursor->shape() != Qt::ForbiddenCursor) {
+ QGuiApplication::changeOverrideCursor(QCursor(Qt::ForbiddenCursor));
+ currentActionForOverrideCursor = Qt::IgnoreAction;
+ }
+ if (qt_qws_dnd_deco)
+ qt_qws_dnd_deco->hide();
+ }
+#endif
+}
+
+
+bool QDragManager::eventFilter(QObject *o, QEvent *e)
+{
+#if 0
+ // ###
+ if (beingCancelled) {
+ if (e->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
+ qApp->removeEventFilter(this);
+ Q_ASSERT(object == 0);
+ beingCancelled = false;
+ eventLoop->exit();
+ return true; // block the key release
+ }
+ return false;
+ }
+
+
+
+ if (!o->isWidgetType())
+ return false;
+
+ switch(e->type()) {
+ case QEvent::ShortcutOverride:
+ // prevent accelerators from firing while dragging
+ e->accept();
+ return true;
+
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ {
+ QKeyEvent *ke = ((QKeyEvent*)e);
+ if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ eventLoop->exit();
+ } else {
+ updateCursor();
+ }
+ return true; // Eat all key events
+ }
+
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ {
+ if (!object) { //#### this should not happen
+ qWarning("QDragManager::eventFilter: No object");
+ return true;
+ }
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+ if (manager->object)
+ possible_actions = manager->dragPrivate()->possible_actions;
+ else
+ possible_actions = Qt::IgnoreAction;
+
+ QMouseEvent *me = (QMouseEvent *)e;
+ if (me->buttons()) {
+ Qt::DropAction prevAction = global_accepted_action;
+ QWidget *cw = QApplication::widgetAt(me->globalPos());
+
+ // Fix for when we move mouse on to the deco widget
+ if (qt_qws_dnd_deco && cw == qt_qws_dnd_deco)
+ cw = object->target();
+
+ while (cw && !cw->acceptDrops() && !cw->isWindow())
+ cw = cw->parentWidget();
+
+ if (object->target() != cw) {
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QCoreApplication::sendEvent(object->target(), &dle);
+ willDrop = false;
+ global_accepted_action = Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ object->d_func()->target = 0;
+ }
+ if (cw && cw->acceptDrops()) {
+ object->d_func()->target = cw;
+ QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QCoreApplication::sendEvent(object->target(), &dee);
+ willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
+ global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ }
+ } else if (cw) {
+ QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ if (global_accepted_action != Qt::IgnoreAction) {
+ dme.setDropAction(global_accepted_action);
+ dme.accept();
+ }
+ QCoreApplication::sendEvent(cw, &dme);
+ willDrop = dme.isAccepted();
+ global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;
+ updatePixmap();
+ updateCursor();
+ }
+ if (global_accepted_action != prevAction)
+ emitActionChanged(global_accepted_action);
+ }
+ return true; // Eat all mouse events
+ }
+
+ case QEvent::MouseButtonRelease:
+ {
+ qApp->removeEventFilter(this);
+ if (restoreCursor) {
+ willDrop = false;
+#ifndef QT_NO_CURSOR
+ QGuiApplication::restoreOverrideCursor();
+#endif
+ restoreCursor = false;
+ }
+ if (object && object->target()) {
+ QMouseEvent *me = (QMouseEvent *)e;
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+
+ QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QCoreApplication::sendEvent(object->target(), &de);
+ if (de.isAccepted())
+ global_accepted_action = de.dropAction();
+ else
+ global_accepted_action = Qt::IgnoreAction;
+
+ if (object)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+ eventLoop->exit();
+ return true; // Eat all mouse events
+ }
+
+ default:
+ break;
+ }
+#endif
+ return false;
+}
+
+Qt::DropAction QDragManager::drag(QDrag *o)
+{
+ if (object == o || !o || !o->source())
+ return Qt::IgnoreAction;
+
+ if (object) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ }
+
+ object = drag_object = o;
+ qt_qws_dnd_deco = new QShapedPixmapWindow();
+ oldstate = Qt::NoModifier; // #### Should use state that caused the drag
+// drag_mode = mode;
+
+ willDrop = false;
+ updatePixmap();
+ updateCursor();
+ restoreCursor = true;
+ object->d_func()->target = 0;
+ qApp->installEventFilter(this);
+
+ global_accepted_action = Qt::CopyAction;
+#ifndef QT_NO_CURSOR
+ qApp->setOverrideCursor(Qt::ArrowCursor);
+ restoreCursor = true;
+ updateCursor();
+#endif
+
+ qt_qws_dnd_dragging = true;
+
+ eventLoop = new QEventLoop;
+ (void) eventLoop->exec();
+ delete eventLoop;
+ eventLoop = 0;
+
+ delete qt_qws_dnd_deco;
+ qt_qws_dnd_deco = 0;
+ qt_qws_dnd_dragging = false;
+
+
+ return global_accepted_action;
+}
+
+
+void QDragManager::cancel(bool deleteSource)
+{
+// qDebug("QDragManager::cancel");
+ beingCancelled = true;
+
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QCoreApplication::sendEvent(object->target(), &dle);
+ }
+
+#ifndef QT_NO_CURSOR
+ if (restoreCursor) {
+ QGuiApplication::restoreOverrideCursor();
+ restoreCursor = false;
+ }
+#endif
+
+ if (drag_object) {
+ if (deleteSource)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+
+ delete qt_qws_dnd_deco;
+ qt_qws_dnd_deco = 0;
+
+ global_accepted_action = Qt::IgnoreAction;
+}
+
+
+void QDragManager::drop()
+{
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
+{
+ if (!drag_object)
+ return QVariant();
+ QByteArray data = drag_object->mimeData()->data(mimetype);
+ if (type == QVariant::String)
+ return QString::fromUtf8(data);
+ return data;
+}
+
+bool QDropData::hasFormat_sys(const QString &format) const
+{
+ return formats().contains(format);
+}
+
+QStringList QDropData::formats_sys() const
+{
+ if (drag_object)
+ return drag_object->mimeData()->formats();
+ return QStringList();
+}
+
+
+#endif // QT_NO_DRAGANDDROP
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp
new file mode 100644
index 0000000000..bb56d061c1
--- /dev/null
+++ b/src/gui/kernel/qdrag.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdrag.h>
+#include <qpixmap.h>
+#include <qpoint.h>
+#include "qdnd_p.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDrag
+ \brief The QDrag class provides support for MIME-based drag and drop data
+ transfer.
+
+ Drag and drop is an intuitive way for users to copy or move data around in an
+ application, and is used in many desktop environments as a mechanism for copying
+ data between applications. Drag and drop support in Qt is centered around the
+ QDrag class that handles most of the details of a drag and drop operation.
+
+ The data to be transferred by the drag and drop operation is contained in a
+ QMimeData object. This is specified with the setMimeData() function in the
+ following way:
+
+ \snippet doc/src/snippets/dragging/mainwindow.cpp 1
+
+ Note that setMimeData() assigns ownership of the QMimeData object to the
+ QDrag object. The QDrag must be constructed on the heap with a parent QObject
+ to ensure that Qt can clean up after the drag and drop operation has been
+ completed.
+
+ A pixmap can be used to represent the data while the drag is in
+ progress, and will move with the cursor to the drop target. This
+ pixmap typically shows an icon that represents the MIME type of
+ the data being transferred, but any pixmap can be set with
+ setPixmap(). The cursor's hot spot can be given a position
+ relative to the top-left corner of the pixmap with the
+ setHotSpot() function. The following code positions the pixmap so
+ that the cursor's hot spot points to the center of its bottom
+ edge:
+
+ \snippet doc/src/snippets/separations/finalwidget.cpp 2
+
+ \note On X11, the pixmap may not be able to keep up with the mouse
+ movements if the hot spot causes the pixmap to be displayed
+ directly under the cursor.
+
+ The source and target widgets can be found with source() and target().
+ These functions are often used to determine whether drag and drop operations
+ started and finished at the same widget, so that special behavior can be
+ implemented.
+
+ QDrag only deals with the drag and drop operation itself. It is up to the
+ developer to decide when a drag operation begins, and how a QDrag object should
+ be constructed and used. For a given widget, it is often necessary to
+ reimplement \l{QWidget::mousePressEvent()}{mousePressEvent()} to determine
+ whether the user has pressed a mouse button, and reimplement
+ \l{QWidget::mouseMoveEvent()}{mouseMoveEvent()} to check whether a QDrag is
+ required.
+
+ \sa {Drag and Drop}, QClipboard, QMimeData, QWindowsMime, QMacPasteboardMime,
+ {Draggable Icons Example}, {Draggable Text Example}, {Drop Site Example},
+ {Fridge Magnets Example}
+*/
+
+/*!
+ Constructs a new drag object for the widget specified by \a dragSource.
+*/
+QDrag::QDrag(QObject *dragSource)
+ : QObject(*new QDragPrivate, dragSource)
+{
+ Q_D(QDrag);
+ d->source = dragSource;
+ d->target = 0;
+ d->data = 0;
+ d->hotspot = QPoint(-10, -10);
+ d->possible_actions = Qt::CopyAction;
+ d->executed_action = Qt::IgnoreAction;
+ d->defaultDropAction = Qt::IgnoreAction;
+}
+
+/*!
+ Destroys the drag object.
+*/
+QDrag::~QDrag()
+{
+ Q_D(QDrag);
+ delete d->data;
+ QDragManager *manager = QDragManager::self();
+ if (manager && manager->object == this)
+ manager->cancel(false);
+}
+
+/*!
+ Sets the data to be sent to the given MIME \a data. Ownership of the data is
+ transferred to the QDrag object.
+*/
+void QDrag::setMimeData(QMimeData *data)
+{
+ Q_D(QDrag);
+ if (d->data == data)
+ return;
+ if (d->data != 0)
+ delete d->data;
+ d->data = data;
+}
+
+/*!
+ Returns the MIME data that is encapsulated by the drag object.
+*/
+QMimeData *QDrag::mimeData() const
+{
+ Q_D(const QDrag);
+ return d->data;
+}
+
+/*!
+ Sets \a pixmap as the pixmap used to represent the data in a drag
+ and drop operation. You can only set a pixmap before the drag is
+ started.
+*/
+void QDrag::setPixmap(const QPixmap &pixmap)
+{
+ Q_D(QDrag);
+ d->pixmap = pixmap;
+}
+
+/*!
+ Returns the pixmap used to represent the data in a drag and drop operation.
+*/
+QPixmap QDrag::pixmap() const
+{
+ Q_D(const QDrag);
+ return d->pixmap;
+}
+
+/*!
+ Sets the position of the hot spot relative to the top-left corner of the
+ pixmap used to the point specified by \a hotspot.
+
+ \bold{Note:} on X11, the pixmap may not be able to keep up with the mouse
+ movements if the hot spot causes the pixmap to be displayed
+ directly under the cursor.
+*/
+void QDrag::setHotSpot(const QPoint& hotspot)
+{
+ Q_D(QDrag);
+ d->hotspot = hotspot;
+}
+
+/*!
+ Returns the position of the hot spot relative to the top-left corner of the
+ cursor.
+*/
+QPoint QDrag::hotSpot() const
+{
+ Q_D(const QDrag);
+ return d->hotspot;
+}
+
+/*!
+ Returns the source of the drag object. This is the widget where the drag
+ and drop operation originated.
+*/
+QObject *QDrag::source() const
+{
+ Q_D(const QDrag);
+ return d->source;
+}
+
+/*!
+ Returns the target of the drag and drop operation. This is the widget where
+ the drag object was dropped.
+*/
+QObject *QDrag::target() const
+{
+ Q_D(const QDrag);
+ return d->target;
+}
+
+/*!
+ \since 4.3
+
+ Starts the drag and drop operation and returns a value indicating the requested
+ drop action when it is completed. The drop actions that the user can choose
+ from are specified in \a supportedActions. The default proposed action will be selected
+ among the allowed actions in the following order: Move, Copy and Link.
+
+ \bold{Note:} On Linux and Mac OS X, the drag and drop operation
+ can take some time, but this function does not block the event
+ loop. Other events are still delivered to the application while
+ the operation is performed. On Windows, the Qt event loop is
+ blocked while during the operation.
+*/
+
+Qt::DropAction QDrag::exec(Qt::DropActions supportedActions)
+{
+ return exec(supportedActions, Qt::IgnoreAction);
+}
+
+/*!
+ \since 4.3
+
+ Starts the drag and drop operation and returns a value indicating the requested
+ drop action when it is completed. The drop actions that the user can choose
+ from are specified in \a supportedActions.
+
+ The \a defaultDropAction determines which action will be proposed when the user performs a
+ drag without using modifier keys.
+
+ \bold{Note:} On Linux and Mac OS X, the drag and drop operation
+ can take some time, but this function does not block the event
+ loop. Other events are still delivered to the application while
+ the operation is performed. On Windows, the Qt event loop is
+ blocked during the operation. However, QDrag::exec() on
+ Windows causes processEvents() to be called frequently to keep the GUI responsive.
+ If any loops or operations are called while a drag operation is active, it will block the drag operation.
+*/
+
+Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)
+{
+ Q_D(QDrag);
+ if (!d->data) {
+ qWarning("QDrag: No mimedata set before starting the drag");
+ return d->executed_action;
+ }
+ QDragManager *manager = QDragManager::self();
+ d->defaultDropAction = Qt::IgnoreAction;
+ d->possible_actions = supportedActions;
+
+ if (manager) {
+ if (defaultDropAction == Qt::IgnoreAction) {
+ if (supportedActions & Qt::MoveAction) {
+ d->defaultDropAction = Qt::MoveAction;
+ } else if (supportedActions & Qt::CopyAction) {
+ d->defaultDropAction = Qt::CopyAction;
+ } else if (supportedActions & Qt::LinkAction) {
+ d->defaultDropAction = Qt::LinkAction;
+ }
+ } else {
+ d->defaultDropAction = defaultDropAction;
+ }
+ d->executed_action = manager->drag(this);
+ }
+
+ return d->executed_action;
+}
+
+/*!
+ \obsolete
+
+ \bold{Note:} It is recommended to use exec() instead of this function.
+
+ Starts the drag and drop operation and returns a value indicating the requested
+ drop action when it is completed. The drop actions that the user can choose
+ from are specified in \a request. Qt::CopyAction is always allowed.
+
+ \bold{Note:} Although the drag and drop operation can take some time, this function
+ does not block the event loop. Other events are still delivered to the application
+ while the operation is performed.
+
+ \sa exec()
+*/
+Qt::DropAction QDrag::start(Qt::DropActions request)
+{
+ Q_D(QDrag);
+ if (!d->data) {
+ qWarning("QDrag: No mimedata set before starting the drag");
+ return d->executed_action;
+ }
+ QDragManager *manager = QDragManager::self();
+ d->defaultDropAction = Qt::IgnoreAction;
+ d->possible_actions = request | Qt::CopyAction;
+ if (manager)
+ d->executed_action = manager->drag(this);
+ return d->executed_action;
+}
+
+/*!
+ Sets the drag \a cursor for the \a action. This allows you
+ to override the default native cursors. To revert to using the
+ native cursor for \a action pass in a null QPixmap as \a cursor.
+
+ The \a action can only be CopyAction, MoveAction or LinkAction.
+ All other values of DropAction are ignored.
+*/
+void QDrag::setDragCursor(const QPixmap &cursor, Qt::DropAction action)
+{
+ Q_D(QDrag);
+ if (action != Qt::CopyAction && action != Qt::MoveAction && action != Qt::LinkAction)
+ return;
+ if (cursor.isNull())
+ d->customCursors.remove(action);
+ else
+ d->customCursors[action] = cursor;
+}
+
+/*!
+ \fn void QDrag::actionChanged(Qt::DropAction action)
+
+ This signal is emitted when the \a action associated with the
+ drag changes.
+
+ \sa targetChanged()
+*/
+
+/*!
+ \fn void QDrag::targetChanged(QObject *newTarget)
+
+ This signal is emitted when the target of the drag and drop
+ operation changes, with \a newTarget the new target.
+
+ \sa target(), actionChanged()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h
new file mode 100644
index 0000000000..d014382e8c
--- /dev/null
+++ b/src/gui/kernel/qdrag.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDRAG_H
+#define QDRAG_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_DRAGANDDROP
+class QMimeData;
+class QDragPrivate;
+class QPixmap;
+class QPoint;
+class QDragManager;
+
+class Q_GUI_EXPORT QDrag : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDrag)
+public:
+ explicit QDrag(QObject *dragSource);
+ ~QDrag();
+
+ void setMimeData(QMimeData *data);
+ QMimeData *mimeData() const;
+
+ void setPixmap(const QPixmap &);
+ QPixmap pixmap() const;
+
+ void setHotSpot(const QPoint &hotspot);
+ QPoint hotSpot() const;
+
+ QObject *source() const;
+ QObject *target() const;
+
+ Qt::DropAction start(Qt::DropActions supportedActions = Qt::CopyAction);
+ Qt::DropAction exec(Qt::DropActions supportedActions = Qt::MoveAction);
+ Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultAction);
+
+ void setDragCursor(const QPixmap &cursor, Qt::DropAction action);
+
+Q_SIGNALS:
+ void actionChanged(Qt::DropAction action);
+ void targetChanged(QObject *newTarget);
+
+private:
+ friend class QDragManager;
+ Q_DISABLE_COPY(QDrag)
+};
+
+#endif // QT_NO_DRAGANDDROP
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDRAG_H