a811d01865d155269b704ce9a7a469d36e0326d8
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickdroparea.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickdroparea_p.h"
43 #include "qquickdrag_p.h"
44 #include "qquickitem_p.h"
45 #include "qquickcanvas.h"
46
47 #include <private/qdeclarativeengine_p.h>
48
49 QT_BEGIN_NAMESPACE
50
51 QQuickDropAreaDrag::QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent)
52     : QObject(parent)
53     , d(d)
54 {
55 }
56
57 QQuickDropAreaDrag::~QQuickDropAreaDrag()
58 {
59 }
60
61 class QQuickDropAreaPrivate : public QQuickItemPrivate
62 {
63     Q_DECLARE_PUBLIC(QQuickDropArea)
64
65 public:
66     QQuickDropAreaPrivate();
67     ~QQuickDropAreaPrivate();
68
69     bool hasMatchingKey(const QStringList &keys) const;
70
71     QStringList getKeys(const QMimeData *mimeData) const;
72
73     QStringList keys;
74     QRegExp keyRegExp;
75     QPointF dragPosition;
76     QQuickDropAreaDrag *drag;
77     QDeclarativeGuard<QObject> source;
78     QDeclarativeGuard<QMimeData> mimeData;
79 };
80
81 QQuickDropAreaPrivate::QQuickDropAreaPrivate()
82     : drag(0)
83 {
84 }
85
86 QQuickDropAreaPrivate::~QQuickDropAreaPrivate()
87 {
88     delete drag;
89 }
90
91 /*!
92     \qmlclass DropArea QQuickDropArea
93     \inqmlmodule QtQuick 2
94     \brief The DropArea item provides drag and drop handling.
95
96     A DropArea is an invisible item which receives events when other items are
97     dragged over it.
98
99     The Drag attached property can be used to notify the DropArea when an Item is
100     dragged over it.
101
102     The \l keys property can be used to filter drag events which don't include
103     a matching key.
104
105     The \l dropItem property is communicated to the source of a drag event as
106     the recipient of a drop on the drag target.
107
108     The \l delegate property provides a means to specify a component to be
109     instantiated for each active drag over a drag target.
110 */
111
112 QQuickDropArea::QQuickDropArea(QQuickItem *parent)
113     : QQuickItem(*new QQuickDropAreaPrivate, parent)
114 {
115     setFlags(ItemAcceptsDrops);
116 }
117
118 QQuickDropArea::~QQuickDropArea()
119 {
120 }
121
122 /*!
123     \qmlproperty bool QtQuick2::DropArea::containsDrag
124
125     This property identifies whether the DropArea currently contains any
126     dragged items.
127 */
128
129 bool QQuickDropArea::containsDrag() const
130 {
131     Q_D(const QQuickDropArea);
132     return d->mimeData;
133 }
134
135 /*!
136     \qmlproperty stringlist QtQuick2::DropArea::keys
137
138     This property holds a list of drag keys a DropArea will accept.
139
140     If no keys are listed the DropArea will accept events from any drag source,
141     otherwise the drag source must have at least one compatible key.
142
143     \sa QtQuick2::Drag::keys
144 */
145
146 QStringList QQuickDropArea::keys() const
147 {
148     Q_D(const QQuickDropArea);
149     return d->keys;
150 }
151
152 void QQuickDropArea::setKeys(const QStringList &keys)
153 {
154     Q_D(QQuickDropArea);
155     if (d->keys != keys) {
156         d->keys = keys;
157
158         if (keys.isEmpty()) {
159             d->keyRegExp = QRegExp();
160         } else {
161             QString pattern = QLatin1Char('(') + QRegExp::escape(keys.first());
162             for (int i = 1; i < keys.count(); ++i)
163                 pattern += QLatin1Char('|') + QRegExp::escape(keys.at(i));
164             pattern += QLatin1Char(')');
165             d->keyRegExp = QRegExp(pattern.replace(QLatin1String("\\*"), QLatin1String(".+")));
166         }
167         emit keysChanged();
168     }
169 }
170
171 QQuickDropAreaDrag *QQuickDropArea::drag()
172 {
173     Q_D(QQuickDropArea);
174     if (!d->drag)
175         d->drag = new QQuickDropAreaDrag(d);
176     return d->drag;
177 }
178
179 /*!
180     \qmlproperty Object QtQuick2::DropArea::drag.source
181
182     This property holds the source of a drag.
183 */
184
185 QObject *QQuickDropAreaDrag::source() const
186 {
187     return d->source;
188 }
189
190 /*!
191     \qmlproperty qreal QtQuick2::DropArea::drag.x
192     \qmlproperty qreal QtQuick2::DropArea::drag.y
193
194     These properties hold the coordinates of the last drag event.
195 */
196
197 qreal QQuickDropAreaDrag::x() const
198 {
199     return d->dragPosition.x();
200 }
201
202 qreal QQuickDropAreaDrag::y() const
203 {
204     return d->dragPosition.y();
205 }
206
207 /*!
208     \qmlsignal QtQuick2::DropArea::onPositionChanged(DragEvent drag)
209
210     This handler is called when the position of a drag has changed.
211 */
212
213 void QQuickDropArea::dragMoveEvent(QDragMoveEvent *event)
214 {
215     Q_D(QQuickDropArea);
216     if (!d->mimeData)
217         return;
218
219     d->dragPosition = event->pos();
220     if (d->drag)
221         emit d->drag->positionChanged();
222
223     event->accept();
224     QQuickDropEvent dragTargetEvent(d, event);
225     emit positionChanged(&dragTargetEvent);
226 }
227
228 bool QQuickDropAreaPrivate::hasMatchingKey(const QStringList &keys) const
229 {
230     if (keyRegExp.isEmpty())
231         return true;
232
233     foreach (const QString &key, keys) {
234         if (keyRegExp.exactMatch(key))
235             return true;
236     }
237     return false;
238 }
239
240 QStringList QQuickDropAreaPrivate::getKeys(const QMimeData *mimeData) const
241 {
242     if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(mimeData))
243         return dragMime->keys();
244     return mimeData->formats();
245 }
246
247 /*!
248     \qmlsignal QtQuick2::DropArea::onEntered(DragEvent drag)
249
250     This handler is called when a \a drag enters the bounds of a DropArea.
251 */
252
253 void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event)
254 {
255     Q_D(QQuickDropArea);
256     const QMimeData *mimeData = event->mimeData();
257     if (!d->effectiveEnable || d->mimeData || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
258         return;
259
260     d->dragPosition = event->pos();
261
262     event->accept();
263     QQuickDropEvent dragTargetEvent(d, event);
264     emit entered(&dragTargetEvent);
265
266     if (event->isAccepted()) {
267         d->mimeData = const_cast<QMimeData *>(mimeData);
268         if (QQuickDragMimeData *dragMime = qobject_cast<QQuickDragMimeData *>(d->mimeData))
269             d->source = dragMime->source();
270         else
271             d->source = event->source();
272         d->dragPosition = event->pos();
273         if (d->drag) {
274             emit d->drag->positionChanged();
275             emit d->drag->sourceChanged();
276         }
277         emit containsDragChanged();
278     }
279 }
280
281 /*!
282     \qmlsignal QtQuick2::DropArea::onExited()
283
284     This handler is called when a drag exits the bounds of a DropArea.
285 */
286
287 void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *)
288 {
289     Q_D(QQuickDropArea);
290     if (!d->mimeData)
291         return;
292
293     emit exited();
294
295     d->mimeData = 0;
296     d->source = 0;
297     emit containsDragChanged();
298     if (d->drag)
299         emit d->drag->sourceChanged();
300 }
301
302 /*!
303     \qmlsignal QtQuick2::DropArea::onDropped(DragEvent drop)
304
305     This handler is called when a drop event occurs within the bounds of a
306     a DropArea.
307 */
308
309 void QQuickDropArea::dropEvent(QDropEvent *event)
310 {
311     Q_D(QQuickDropArea);
312     if (!d->mimeData)
313         return;
314
315     QQuickDropEvent dragTargetEvent(d, event);
316     emit dropped(&dragTargetEvent);
317
318     d->mimeData = 0;
319     d->source = 0;
320     emit containsDragChanged();
321     if (d->drag)
322         emit d->drag->sourceChanged();
323 }
324
325 /*!
326     \qmlclass DragEvent QQuickDragEvent
327     \inqmlmodule QtQuick 2
328     \brief The DragEvent object provides information about a drag event.
329
330     The position of the drag event can be obtained from the \l x and \l y
331     properties, and the \l keys property identifies the drag keys of the event
332     \l source.
333 */
334
335 /*!
336     \qmlproperty real QtQuick2::DragEvent::x
337
338     This property holds the x coordinate of a drag event.
339 */
340
341 /*!
342     \qmlproperty real QtQuick2::DragEvent::y
343
344     This property holds the y coordinate of a drag event.
345 */
346
347 /*!
348     \qmlproperty Object QtQuick2::DragEvent::drag.source
349
350     This property holds the source of a drag event.
351 */
352
353 QObject *QQuickDropEvent::source()
354 {
355     if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData()))
356         return dragMime->source();
357     else
358         return event->source();
359 }
360
361 /*!
362     \qmlproperty stringlist QtQuick2::DragEvent::keys
363
364     This property holds a list of keys identifying the data type or source of a
365     drag event.
366 */
367
368 QStringList QQuickDropEvent::keys() const
369 {
370     return d->getKeys(event->mimeData());
371 }
372
373 /*!
374     \qmlproperty enum QtQuick2::DragEvent::action
375
376     This property holds the action that the \l source is to perform on an accepted drop.
377
378     The drop action may be one of:
379
380     \list
381     \o Qt.CopyAction Copy the data to the target
382     \o Qt.MoveAction Move the data from the source to the target
383     \o Qt.LinkAction Create a link from the source to the target.
384     \o Qt.IgnoreAction Ignore the action (do nothing with the data).
385     \endlist
386 */
387
388 /*!
389     \qmlproperty flags QtQuick2::DragEvent::supportedActions
390
391     This property holds the set of \l {action}{actions} supported by the
392     drag source.
393 */
394
395 /*!
396     \qmlproperty real QtQuick2::DragEvent::accepted
397
398     This property holds whether the drag event was accepted by a handler.
399
400     The default value is true.
401 */
402
403 /*!
404     \qmlmethod void QtQuick2::DragEvent::accept()
405     \qmlmethod void QtQuick2::DragEvent::accept(enum action)
406
407     Accepts the drag event.
408
409     If an \a action is specified it will overwrite the value of the \l action property.
410 */
411
412 void QQuickDropEvent::accept(QDeclarativeV8Function *args)
413 {
414     Qt::DropAction action = event->dropAction();
415
416     if (args->Length() >= 1) {
417         v8::Local<v8::Value> v = (*args)[0];
418         if (v->IsInt32())
419             action = Qt::DropAction(v->Int32Value());
420     }
421     // get action from arguments.
422     event->setDropAction(action);
423     event->accept();
424 }
425
426
427 QT_END_NAMESPACE
428