/****************************************************************************+ −
**+ −
** Copyright (C) 2010 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 "qapplication.h"+ −
+ −
#ifndef QT_NO_DRAGANDDROP+ −
+ −
#include "qwidget.h"+ −
#include "qdatetime.h"+ −
#include "qbitmap.h"+ −
#include "qcursor.h"+ −
#include "qevent.h"+ −
#include "qpainter.h"+ −
#include "qdnd_p.h"+ −
#include "qt_s60_p.h"+ −
+ −
#include <coecntrl.h>+ −
// pointer cursor+ −
#include <w32std.h>+ −
#include <gdi.h>+ −
#include <QCursor>+ −
+ −
QT_BEGIN_NAMESPACE+ −
//### artistic impression of Symbians default DnD cursor ?+ −
+ −
static QPixmap *defaultPm = 0;+ −
static const int default_pm_hotx = -50;+ −
static const int default_pm_hoty = -50;+ −
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",+ −
};+ −
//### actions need to be redefined for S60+ −
// Shift/Ctrl handling, and final drop status+ −
static Qt::DropAction global_accepted_action = Qt::MoveAction;+ −
static Qt::DropActions possible_actions = Qt::IgnoreAction;+ −
+ −
+ −
// static variables in place of a proper cross-process solution+ −
static QDrag *drag_object;+ −
static bool qt_symbian_dnd_dragging = false;+ −
+ −
+ −
static Qt::KeyboardModifiers oldstate;+ −
+ −
void QDragManager::updatePixmap()+ −
{+ −
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;+ −
}+ −
#ifndef QT_NO_CURSOR+ −
QCursor cursor(pm, pm_hot.x(), pm_hot.y());+ −
overrideCursor = cursor;+ −
#endif+ −
}+ −
+ −
void QDragManager::timerEvent(QTimerEvent *) { }+ −
+ −
void QDragManager::move(const QPoint&) {+ −
}+ −
+ −
void QDragManager::updateCursor()+ −
{+ −
#ifndef QT_NO_CURSOR+ −
QCursor cursor = willDrop ? overrideCursor : Qt::ForbiddenCursor;+ −
if (!restoreCursor) {+ −
QApplication::setOverrideCursor(cursor);+ −
restoreCursor = true;+ −
}+ −
else {+ −
QApplication::changeOverrideCursor(cursor);+ −
}+ −
#endif+ −
}+ −
+ −
+ −
bool QDragManager::eventFilter(QObject *o, QEvent *e)+ −
{+ −
if (beingCancelled) {+ −
return false;+ −
}+ −
if (!o->isWidgetType())+ −
return false;+ −
+ −
switch(e->type()) {+ −
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());+ −
// map the Coords relative to the window.+ −
if (!cw)+ −
return true;+ −
+ −
while (cw && !cw->acceptDrops() && !cw->isWindow())+ −
cw = cw->parentWidget();+ −
+ −
bool oldWillDrop = willDrop;+ −
if (object->target() != cw) {+ −
if (object->target()) {+ −
QDragLeaveEvent dle;+ −
QApplication::sendEvent(object->target(), &dle);+ −
willDrop = false;+ −
global_accepted_action = Qt::IgnoreAction;+ −
if (oldWillDrop != willDrop)+ −
updateCursor();+ −
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());+ −
QApplication::sendEvent(object->target(), &dee);+ −
willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;+ −
global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;+ −
if (oldWillDrop != willDrop)+ −
updateCursor();+ −
}+ −
} 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();+ −
}+ −
QApplication::sendEvent(cw, &dme);+ −
willDrop = dme.isAccepted();+ −
global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;+ −
if (oldWillDrop != willDrop) {+ −
updatePixmap();+ −
updateCursor();+ −
}+ −
}+ −
if (global_accepted_action != prevAction)+ −
emitActionChanged(global_accepted_action);+ −
}+ −
return true; // Eat all mouse events+ −
}+ −
+ −
case QEvent::MouseButtonRelease:+ −
{+ −
qApp->removeEventFilter(this);+ −
#ifndef QT_NO_CURSOR+ −
if (restoreCursor) {+ −
QApplication::restoreOverrideCursor();+ −
willDrop = false;+ −
restoreCursor = false;+ −
}+ −
#endif+ −
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());+ −
QApplication::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;+ −
}+ −
return false;+ −
}+ −
+ −
Qt::DropAction QDragManager::drag(QDrag *o)+ −
{+ −
Q_ASSERT(!qt_symbian_dnd_dragging);+ −
if (object == o || !o || !o->source())+ −
return Qt::IgnoreAction;+ −
+ −
if (object) {+ −
cancel();+ −
qApp->removeEventFilter(this);+ −
beingCancelled = false;+ −
}+ −
+ −
object = drag_object = o;+ −
+ −
oldstate = Qt::NoModifier; // #### Should use state that caused the drag+ −
willDrop = false;+ −
updatePixmap();+ −
updateCursor();+ −
+ −
#ifndef QT_NO_CURSOR+ −
qt_symbian_set_cursor_visible(true); //force cursor on even for touch phone+ −
#endif+ −
+ −
object->d_func()->target = 0;+ −
+ −
qApp->installEventFilter(this);+ −
+ −
global_accepted_action = defaultAction(dragPrivate()->possible_actions, Qt::NoModifier);+ −
qt_symbian_dnd_dragging = true;+ −
+ −
eventLoop = new QEventLoop;+ −
// block+ −
(void) eventLoop->exec(QEventLoop::AllEvents);+ −
delete eventLoop;+ −
eventLoop = 0;+ −
+ −
#ifndef QT_NO_CURSOR+ −
qt_symbian_set_cursor_visible(false);+ −
+ −
overrideCursor = QCursor(); //deref the cursor data+ −
qt_symbian_dnd_dragging = false;+ −
#endif+ −
+ −
return global_accepted_action;+ −
}+ −
+ −
+ −
void QDragManager::cancel(bool deleteSource)+ −
{+ −
beingCancelled = true;+ −
+ −
if (object->target()) {+ −
QDragLeaveEvent dle;+ −
QApplication::sendEvent(object->target(), &dle);+ −
}+ −
+ −
if (drag_object) {+ −
if (deleteSource)+ −
object->deleteLater();+ −
drag_object = object = 0;+ −
}+ −
+ −
#ifndef QT_NO_CURSOR+ −
if (restoreCursor) {+ −
QApplication::restoreOverrideCursor();+ −
restoreCursor = false;+ −
}+ −
#endif+ −
+ −
global_accepted_action = Qt::IgnoreAction;+ −
}+ −
+ −
+ −
void QDragManager::drop()+ −
{+ −
#ifndef QT_NO_CURSOR+ −
if (restoreCursor) {+ −
QApplication::restoreOverrideCursor();+ −
restoreCursor = false;+ −
}+ −
#endif+ −
}+ −
+ −
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();+ −
}+ −
+ −
QT_END_NAMESPACE+ −
#endif // QT_NO_DRAGANDDROP+ −