~loic.molinari/+junk/qtdeclarative-shadereffectsource-changes

« back to all changes in this revision

Viewing changes to tests/auto/quick/qquickdrag/tst_qquickdrag.cpp

  • Committer: Loïc Molinari
  • Date: 2012-04-21 17:59:51 UTC
  • Revision ID: loic.molinari@canonical.com-20120421175951-bqx68caaf5zrp76l
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/
 
5
**
 
6
** This file is part of the test suite of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** GNU Lesser General Public License Usage
 
10
** This file may be used under the terms of the GNU Lesser General Public
 
11
** License version 2.1 as published by the Free Software Foundation and
 
12
** appearing in the file LICENSE.LGPL included in the packaging of this
 
13
** file. Please review the following information to ensure the GNU Lesser
 
14
** General Public License version 2.1 requirements will be met:
 
15
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
16
**
 
17
** In addition, as a special exception, Nokia gives you certain additional
 
18
** rights. These rights are described in the Nokia Qt LGPL Exception
 
19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
20
**
 
21
** GNU General Public License Usage
 
22
** Alternatively, this file may be used under the terms of the GNU General
 
23
** Public License version 3.0 as published by the Free Software Foundation
 
24
** and appearing in the file LICENSE.GPL included in the packaging of this
 
25
** file. Please review the following information to ensure the GNU General
 
26
** Public License version 3.0 requirements will be met:
 
27
** http://www.gnu.org/copyleft/gpl.html.
 
28
**
 
29
** Other Usage
 
30
** Alternatively, this file may be used in accordance with the terms and
 
31
** conditions contained in a signed written agreement between you and Nokia.
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include <QtTest/QtTest>
 
43
#include <QtTest/QSignalSpy>
 
44
#include <QtQuick/qquickitem.h>
 
45
#include <QtQuick/qquickview.h>
 
46
#include <QtQml/qqmlcontext.h>
 
47
#include <QtQml/qqmlengine.h>
 
48
#include <QtQml/qqmlexpression.h>
 
49
 
 
50
template <typename T> static T evaluate(QObject *scope, const QString &expression)
 
51
{
 
52
    QQmlExpression expr(qmlContext(scope), scope, expression);
 
53
    QVariant result = expr.evaluate();
 
54
    if (expr.hasError())
 
55
        qWarning() << expr.error().toString();
 
56
    return result.value<T>();
 
57
}
 
58
 
 
59
template <> void evaluate<void>(QObject *scope, const QString &expression)
 
60
{
 
61
    QQmlExpression expr(qmlContext(scope), scope, expression);
 
62
    expr.evaluate();
 
63
    if (expr.hasError())
 
64
        qWarning() << expr.error().toString();
 
65
}
 
66
 
 
67
Q_DECLARE_METATYPE(Qt::DropActions)
 
68
 
 
69
class TestDropTarget : public QQuickItem
 
70
{
 
71
    Q_OBJECT
 
72
public:
 
73
    TestDropTarget(QQuickItem *parent = 0)
 
74
        : QQuickItem(parent)
 
75
        , enterEvents(0)
 
76
        , moveEvents(0)
 
77
        , leaveEvents(0)
 
78
        , dropEvents(0)
 
79
        , acceptAction(Qt::MoveAction)
 
80
        , defaultAction(Qt::IgnoreAction)
 
81
        , proposedAction(Qt::IgnoreAction)
 
82
        , accept(true)
 
83
    {
 
84
        setFlags(ItemAcceptsDrops);
 
85
    }
 
86
 
 
87
    void reset()
 
88
    {
 
89
        enterEvents = 0;
 
90
        moveEvents = 0;
 
91
        leaveEvents = 0;
 
92
        dropEvents = 0;
 
93
        defaultAction = Qt::IgnoreAction;
 
94
        proposedAction = Qt::IgnoreAction;
 
95
        supportedActions = Qt::IgnoreAction;
 
96
    }
 
97
 
 
98
    void dragEnterEvent(QDragEnterEvent *event)
 
99
    {
 
100
        ++enterEvents;
 
101
        position = event->pos();
 
102
        defaultAction = event->dropAction();
 
103
        proposedAction = event->proposedAction();
 
104
        supportedActions = event->possibleActions();
 
105
        event->setAccepted(accept);
 
106
    }
 
107
 
 
108
    void dragMoveEvent(QDragMoveEvent *event)
 
109
    {
 
110
        ++moveEvents;
 
111
        position = event->pos();
 
112
        defaultAction = event->dropAction();
 
113
        proposedAction = event->proposedAction();
 
114
        supportedActions = event->possibleActions();
 
115
        event->setAccepted(accept);
 
116
    }
 
117
 
 
118
    void dragLeaveEvent(QDragLeaveEvent *event)
 
119
    {
 
120
        ++leaveEvents;
 
121
        event->setAccepted(accept);
 
122
    }
 
123
 
 
124
    void dropEvent(QDropEvent *event)
 
125
    {
 
126
        ++dropEvents;
 
127
        position = event->pos();
 
128
        defaultAction = event->dropAction();
 
129
        proposedAction = event->proposedAction();
 
130
        supportedActions = event->possibleActions();
 
131
        event->setDropAction(acceptAction);
 
132
        event->setAccepted(accept);
 
133
    }
 
134
 
 
135
    int enterEvents;
 
136
    int moveEvents;
 
137
    int leaveEvents;
 
138
    int dropEvents;
 
139
    Qt::DropAction acceptAction;
 
140
    Qt::DropAction defaultAction;
 
141
    Qt::DropAction proposedAction;
 
142
    Qt::DropActions supportedActions;
 
143
    QPointF position;
 
144
    bool accept;
 
145
};
 
146
 
 
147
class tst_QQuickDrag: public QObject
 
148
{
 
149
    Q_OBJECT
 
150
private slots:
 
151
    void initTestCase();
 
152
    void cleanupTestCase();
 
153
 
 
154
    void active();
 
155
    void drop();
 
156
    void move();
 
157
    void hotSpot();
 
158
    void supportedActions();
 
159
    void proposedAction();
 
160
    void keys();
 
161
    void source();
 
162
    void recursion_data();
 
163
    void recursion();
 
164
 
 
165
private:
 
166
    QQmlEngine engine;
 
167
};
 
168
 
 
169
void tst_QQuickDrag::initTestCase()
 
170
{
 
171
 
 
172
}
 
173
 
 
174
void tst_QQuickDrag::cleanupTestCase()
 
175
{
 
176
 
 
177
}
 
178
 
 
179
void tst_QQuickDrag::active()
 
180
{
 
181
    QQuickCanvas canvas;
 
182
    TestDropTarget dropTarget(canvas.rootItem());
 
183
    dropTarget.setSize(QSizeF(100, 100));
 
184
    QQmlComponent component(&engine);
 
185
    component.setData(
 
186
            "import QtQuick 2.0\n"
 
187
            "Item {\n"
 
188
                "property bool dragActive: Drag.active\n"
 
189
                "property Item dragTarget: Drag.target\n"
 
190
                "x: 50; y: 50\n"
 
191
                "width: 10; height: 10\n"
 
192
            "}", QUrl());
 
193
    QScopedPointer<QObject> object(component.create());
 
194
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
195
    QVERIFY(item);
 
196
    item->setParentItem(&dropTarget);
 
197
 
 
198
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
199
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
200
 
 
201
    evaluate<void>(item, "Drag.active = true");
 
202
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
203
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
204
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
 
205
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
 
206
    QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
 
207
 
 
208
    dropTarget.reset();
 
209
    evaluate<void>(item, "Drag.active = false");
 
210
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
211
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
212
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
213
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
214
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
 
215
 
 
216
    dropTarget.reset();
 
217
    evaluate<void>(item, "Drag.cancel()");
 
218
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
219
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
220
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
221
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
222
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
223
 
 
224
    dropTarget.reset();
 
225
    evaluate<void>(item, "Drag.start()");
 
226
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
227
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
228
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
 
229
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
 
230
    QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
 
231
 
 
232
    // Start while a drag is active, cancels the previous drag and starts a new one.
 
233
    dropTarget.reset();
 
234
    evaluate<void>(item, "Drag.start()");
 
235
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
236
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
237
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
 
238
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
 
239
    QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 1);
 
240
 
 
241
    dropTarget.reset();
 
242
    evaluate<void>(item, "Drag.cancel()");
 
243
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
244
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
245
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
246
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
247
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
 
248
 
 
249
    // Enter events aren't sent to items without the QQuickItem::ItemAcceptsDrops flag.
 
250
    dropTarget.setFlags(QQuickItem::Flags());
 
251
 
 
252
    dropTarget.reset();
 
253
    evaluate<void>(item, "Drag.active = true");
 
254
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
255
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
256
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
257
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
258
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
259
 
 
260
    dropTarget.reset();
 
261
    evaluate<void>(item, "Drag.active = false");
 
262
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
263
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
264
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
265
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
266
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
267
 
 
268
    dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
 
269
 
 
270
    dropTarget.reset();
 
271
    evaluate<void>(item, "Drag.active = true");
 
272
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
273
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
274
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
 
275
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
 
276
    QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
 
277
 
 
278
    dropTarget.setFlags(QQuickItem::Flags());
 
279
 
 
280
    dropTarget.reset();
 
281
    evaluate<void>(item, "Drag.active = false");
 
282
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
283
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
284
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
285
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
286
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
 
287
 
 
288
    // Follow up events aren't sent to items if the enter event isn't accepted.
 
289
    dropTarget.setFlags(QQuickItem::ItemAcceptsDrops);
 
290
    dropTarget.accept = false;
 
291
 
 
292
    dropTarget.reset();
 
293
    evaluate<void>(item, "Drag.active = true");
 
294
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
295
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
296
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
297
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
298
    QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
 
299
 
 
300
    dropTarget.reset();
 
301
    evaluate<void>(item, "Drag.active = false");
 
302
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
303
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
304
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
305
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
306
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
307
 
 
308
    dropTarget.accept = true;
 
309
 
 
310
    dropTarget.reset();
 
311
    evaluate<void>(item, "Drag.active = true");
 
312
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
313
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
314
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&dropTarget));
 
315
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&dropTarget));
 
316
    QCOMPARE(dropTarget.enterEvents, 1); QCOMPARE(dropTarget.leaveEvents, 0);
 
317
 
 
318
    dropTarget.accept = false;
 
319
 
 
320
    dropTarget.reset();
 
321
    evaluate<void>(item, "Drag.active = false");
 
322
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
323
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
324
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
325
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
326
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 1);
 
327
 
 
328
    // Events are sent to hidden or disabled items.
 
329
    dropTarget.accept = true;
 
330
    dropTarget.setVisible(false);
 
331
    dropTarget.reset();
 
332
    evaluate<void>(item, "Drag.active = true");
 
333
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
334
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
335
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
336
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
337
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
338
 
 
339
    evaluate<void>(item, "Drag.active = false");
 
340
    dropTarget.setVisible(true);
 
341
 
 
342
    dropTarget.setOpacity(0.0);
 
343
    dropTarget.reset();
 
344
    evaluate<void>(item, "Drag.active = true");
 
345
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
346
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
347
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
348
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
349
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
350
 
 
351
    evaluate<void>(item, "Drag.active = false");
 
352
    dropTarget.setOpacity(1.0);
 
353
 
 
354
    dropTarget.setEnabled(false);
 
355
    dropTarget.reset();
 
356
    evaluate<void>(item, "Drag.active = true");
 
357
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
358
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
359
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
360
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
361
    QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0);
 
362
}
 
363
 
 
364
void tst_QQuickDrag::drop()
 
365
{
 
366
    QQuickCanvas canvas;
 
367
    TestDropTarget outerTarget(canvas.rootItem());
 
368
    outerTarget.setSize(QSizeF(100, 100));
 
369
    outerTarget.acceptAction = Qt::CopyAction;
 
370
    TestDropTarget innerTarget(&outerTarget);
 
371
    innerTarget.setSize(QSizeF(100, 100));
 
372
    innerTarget.acceptAction = Qt::MoveAction;
 
373
    QQmlComponent component(&engine);
 
374
    component.setData(
 
375
            "import QtQuick 2.0\n"
 
376
            "Item {\n"
 
377
                "property bool dragActive: Drag.active\n"
 
378
                "property Item dragTarget: Drag.target\n"
 
379
                "x: 50; y: 50\n"
 
380
                "width: 10; height: 10\n"
 
381
            "}", QUrl());
 
382
    QScopedPointer<QObject> object(component.create());
 
383
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
384
    QVERIFY(item);
 
385
    item->setParentItem(&outerTarget);
 
386
 
 
387
    innerTarget.reset(); outerTarget.reset();
 
388
    evaluate<void>(item, "Drag.active = true");
 
389
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
390
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
391
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
 
392
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
 
393
    QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
 
394
    QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
395
 
 
396
    innerTarget.reset(); outerTarget.reset();
 
397
    QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.MoveAction"), true);
 
398
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
399
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
400
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
 
401
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
 
402
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.dropEvents, 0);
 
403
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
 
404
 
 
405
    innerTarget.reset(); outerTarget.reset();
 
406
    evaluate<void>(item, "Drag.active = true");
 
407
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
408
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
409
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
 
410
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
 
411
    QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
 
412
    QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
413
 
 
414
    // Inner target declines the drop so it is propagated to the outer target.
 
415
    innerTarget.accept = false;
 
416
 
 
417
    innerTarget.reset(); outerTarget.reset();
 
418
    QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
 
419
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
420
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
421
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
422
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
423
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
 
424
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
 
425
 
 
426
 
 
427
    // Inner target doesn't accept enter so drop goes directly to outer.
 
428
    innerTarget.accept = true;
 
429
    innerTarget.setFlags(QQuickItem::Flags());
 
430
 
 
431
    innerTarget.reset(); outerTarget.reset();
 
432
    evaluate<void>(item, "Drag.active = true");
 
433
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
434
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
435
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
436
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
437
    QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
 
438
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
439
 
 
440
    innerTarget.reset(); outerTarget.reset();
 
441
    QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
 
442
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
443
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
444
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
445
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
446
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
 
447
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
448
 
 
449
    // Neither target accepts drop so Qt::IgnoreAction is returned.
 
450
    innerTarget.reset(); outerTarget.reset();
 
451
    evaluate<void>(item, "Drag.active = true");
 
452
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
453
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
454
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
455
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
456
    QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
 
457
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
458
 
 
459
    outerTarget.accept = false;
 
460
 
 
461
    innerTarget.reset(); outerTarget.reset();
 
462
    QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
 
463
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
464
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
465
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
466
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
467
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
 
468
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
469
 
 
470
    // drop doesn't send an event and returns Qt.IgnoreAction if not active.
 
471
    innerTarget.accept = true;
 
472
    outerTarget.accept = true;
 
473
    innerTarget.reset(); outerTarget.reset();
 
474
    QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.IgnoreAction"), true);
 
475
    QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
 
476
    QCOMPARE(evaluate<bool>(item, "dragActive"), false);
 
477
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
478
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
479
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
 
480
    QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
 
481
}
 
482
 
 
483
void tst_QQuickDrag::move()
 
484
{
 
485
    QQuickCanvas canvas;
 
486
    TestDropTarget outerTarget(canvas.rootItem());
 
487
    outerTarget.setSize(QSizeF(100, 100));
 
488
    TestDropTarget leftTarget(&outerTarget);
 
489
    leftTarget.setPos(QPointF(0, 35));
 
490
    leftTarget.setSize(QSizeF(30, 30));
 
491
    TestDropTarget rightTarget(&outerTarget);
 
492
    rightTarget.setPos(QPointF(70, 35));
 
493
    rightTarget.setSize(QSizeF(30, 30));
 
494
    QQmlComponent component(&engine);
 
495
    component.setData(
 
496
            "import QtQuick 2.0\n"
 
497
            "Item {\n"
 
498
                "property bool dragActive: Drag.active\n"
 
499
                "property Item dragTarget: Drag.target\n"
 
500
                "x: 50; y: 50\n"
 
501
                "width: 10; height: 10\n"
 
502
            "}", QUrl());
 
503
    QScopedPointer<QObject> object(component.create());
 
504
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
505
    QVERIFY(item);
 
506
    item->setParentItem(&outerTarget);
 
507
 
 
508
    evaluate<void>(item, "Drag.active = true");
 
509
    QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
 
510
    QCOMPARE(evaluate<bool>(item, "dragActive"), true);
 
511
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
512
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
513
    QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
 
514
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
515
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
516
    QCOMPARE(outerTarget.position.x(), qreal(50)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
517
 
 
518
    // Move within the outer target.
 
519
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
520
    item->setPos(QPointF(60, 50));
 
521
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
522
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
523
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
524
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
525
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
526
    QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
527
 
 
528
    // Move into the right target.
 
529
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
530
    item->setPos(QPointF(75, 50));
 
531
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&rightTarget));
 
532
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&rightTarget));
 
533
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
534
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
535
    QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
536
    QCOMPARE(outerTarget.position.x(), qreal(75)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
537
    QCOMPARE(rightTarget.position.x(), qreal(5)); QCOMPARE(rightTarget.position.y(), qreal(15));
 
538
 
 
539
    // Move into the left target.
 
540
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
541
    item->setPos(QPointF(25, 50));
 
542
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
 
543
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
 
544
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
545
    QCOMPARE(leftTarget .enterEvents, 1); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
546
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 1); QCOMPARE(rightTarget.moveEvents, 0);
 
547
    QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
548
    QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(15));
 
549
 
 
550
    // Move within the left target.
 
551
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
552
    item->setPos(QPointF(25, 40));
 
553
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
 
554
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
 
555
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
556
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 1);
 
557
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
558
    QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(40));
 
559
    QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(5));
 
560
 
 
561
    // Move out of all targets.
 
562
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
563
    item->setPos(QPointF(110, 50));
 
564
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(0));
 
565
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(0));
 
566
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.moveEvents, 0);
 
567
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 1); QCOMPARE(leftTarget .moveEvents, 0);
 
568
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
569
 
 
570
    // Stop the right target accepting drag events and move into it.
 
571
    rightTarget.accept = false;
 
572
 
 
573
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
574
    item->setPos(QPointF(80, 50));
 
575
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
576
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
577
    QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
 
578
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
579
    QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
580
    QCOMPARE(outerTarget.position.x(), qreal(80)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
581
 
 
582
    // Stop the outer target accepting drag events after it has accepted an enter event.
 
583
    outerTarget.accept = false;
 
584
 
 
585
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
586
    item->setPos(QPointF(60, 50));
 
587
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
588
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
589
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
590
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
591
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
592
    QCOMPARE(outerTarget.position.x(), qreal(60)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
593
 
 
594
    // Clear the QQuickItem::ItemAcceptsDrops flag from the outer target after it accepted an enter event.
 
595
    outerTarget.setFlags(QQuickItem::Flags());
 
596
 
 
597
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
598
    item->setPos(QPointF(40, 50));
 
599
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
600
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
601
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
602
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
603
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
604
    QCOMPARE(outerTarget.position.x(), qreal(40)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
605
 
 
606
    // Clear the QQuickItem::ItemAcceptsDrops flag from the left target before it accepts an enter event.
 
607
    leftTarget.setFlags(QQuickItem::Flags());
 
608
 
 
609
    outerTarget.reset(); leftTarget.reset(); rightTarget.reset();
 
610
    item->setPos(QPointF(25, 50));
 
611
    QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
 
612
    QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
 
613
    QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
 
614
    QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
 
615
    QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
 
616
    QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
 
617
}
 
618
 
 
619
 
 
620
void tst_QQuickDrag::hotSpot()
 
621
{
 
622
    QQuickCanvas canvas;
 
623
    TestDropTarget dropTarget(canvas.rootItem());
 
624
    dropTarget.setSize(QSizeF(100, 100));
 
625
    QQmlComponent component(&engine);
 
626
    component.setData(
 
627
            "import QtQuick 2.0\n"
 
628
            "Item {\n"
 
629
                "property real hotSpotX: Drag.hotSpot.x\n"
 
630
                "property real hotSpotY: Drag.hotSpot.y\n"
 
631
                "x: 50; y: 50\n"
 
632
                "width: 10; height: 10\n"
 
633
            "}", QUrl());
 
634
    QScopedPointer<QObject> object(component.create());
 
635
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
636
    QVERIFY(item);
 
637
    item->setParentItem(&dropTarget);
 
638
 
 
639
    QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(0));
 
640
    QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(0));
 
641
    QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(0));
 
642
    QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(0));
 
643
 
 
644
    evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
 
645
    QCOMPARE(dropTarget.position.x(), qreal(50));
 
646
    QCOMPARE(dropTarget.position.y(), qreal(50));
 
647
 
 
648
    evaluate<void>(item, "{ Drag.hotSpot.x = 5, Drag.hotSpot.y = 5 }");
 
649
    QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(5));
 
650
    QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(5));
 
651
    QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(5));
 
652
    QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(5));
 
653
 
 
654
    evaluate<void>(item, "Drag.start()");
 
655
    QCOMPARE(dropTarget.position.x(), qreal(55));
 
656
    QCOMPARE(dropTarget.position.y(), qreal(55));
 
657
 
 
658
    item->setPos(QPointF(30, 20));
 
659
    QCOMPARE(dropTarget.position.x(), qreal(35));
 
660
    QCOMPARE(dropTarget.position.y(), qreal(25));
 
661
 
 
662
    evaluate<void>(item, "{ Drag.hotSpot.x = 10; Drag.hotSpot.y = 10 }");
 
663
    QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.x"), qreal(10));
 
664
    QCOMPARE(evaluate<qreal>(item, "Drag.hotSpot.y"), qreal(10));
 
665
    QCOMPARE(evaluate<qreal>(item, "hotSpotX"), qreal(10));
 
666
    QCOMPARE(evaluate<qreal>(item, "hotSpotY"), qreal(10));
 
667
    // Changing the hotSpot won't generate a move event so the position is unchanged.  Should it?
 
668
    QCOMPARE(dropTarget.position.x(), qreal(35));
 
669
    QCOMPARE(dropTarget.position.y(), qreal(25));
 
670
 
 
671
    item->setPos(QPointF(10, 20));
 
672
    QCOMPARE(dropTarget.position.x(), qreal(20));
 
673
    QCOMPARE(dropTarget.position.y(), qreal(30));
 
674
}
 
675
 
 
676
void tst_QQuickDrag::supportedActions()
 
677
{
 
678
    QQuickCanvas canvas;
 
679
    TestDropTarget dropTarget(canvas.rootItem());
 
680
    dropTarget.setSize(QSizeF(100, 100));
 
681
    QQmlComponent component(&engine);
 
682
    component.setData(
 
683
            "import QtQuick 2.0\n"
 
684
            "Item {\n"
 
685
                "property int supportedActions: Drag.supportedActions\n"
 
686
                "x: 50; y: 50\n"
 
687
                "width: 10; height: 10\n"
 
688
            "}", QUrl());
 
689
    QScopedPointer<QObject> object(component.create());
 
690
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
691
    QVERIFY(item);
 
692
    item->setParentItem(&dropTarget);
 
693
 
 
694
    QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
 
695
    QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction | Qt.LinkAction"), true);
 
696
    evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
 
697
    QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction | Qt::LinkAction);
 
698
 
 
699
    evaluate<void>(item, "Drag.supportedActions = Qt.CopyAction | Qt.MoveAction");
 
700
    QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
 
701
    QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.CopyAction | Qt.MoveAction"), true);
 
702
    evaluate<void>(item, "Drag.start()");
 
703
    QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
 
704
 
 
705
    // Once a drag is started the proposed actions are locked in for future events.
 
706
    evaluate<void>(item, "Drag.supportedActions = Qt.MoveAction");
 
707
    QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
 
708
    QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
 
709
    item->setPos(QPointF(60, 60));
 
710
    QCOMPARE(dropTarget.supportedActions, Qt::CopyAction | Qt::MoveAction);
 
711
 
 
712
    // Calling start with proposed actions will override the current actions for the next sequence.
 
713
    evaluate<void>(item, "Drag.start(Qt.CopyAction)");
 
714
    QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
 
715
    QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
 
716
    QCOMPARE(dropTarget.supportedActions, Qt::CopyAction);
 
717
 
 
718
    evaluate<void>(item, "Drag.start()");
 
719
    QCOMPARE(evaluate<bool>(item, "Drag.supportedActions == Qt.MoveAction"), true);
 
720
    QCOMPARE(evaluate<bool>(item, "supportedActions == Qt.MoveAction"), true);
 
721
    QCOMPARE(dropTarget.supportedActions, Qt::MoveAction);
 
722
}
 
723
 
 
724
void tst_QQuickDrag::proposedAction()
 
725
{
 
726
    QQuickCanvas canvas;
 
727
    TestDropTarget dropTarget(canvas.rootItem());
 
728
    dropTarget.setSize(QSizeF(100, 100));
 
729
    QQmlComponent component(&engine);
 
730
    component.setData(
 
731
            "import QtQuick 2.0\n"
 
732
            "Item {\n"
 
733
                "property int proposedAction: Drag.proposedAction\n"
 
734
                "x: 50; y: 50\n"
 
735
                "width: 10; height: 10\n"
 
736
            "}", QUrl());
 
737
    QScopedPointer<QObject> object(component.create());
 
738
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
739
    QVERIFY(item);
 
740
    item->setParentItem(&dropTarget);
 
741
 
 
742
 
 
743
    QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
 
744
    QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
 
745
    evaluate<void>(item, "{ Drag.start(); Drag.cancel() }");
 
746
    QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
 
747
    QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
 
748
 
 
749
    evaluate<void>(item, "Drag.proposedAction = Qt.CopyAction");
 
750
    QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.CopyAction"), true);
 
751
    QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.CopyAction"), true);
 
752
    evaluate<void>(item, "Drag.start()");
 
753
    QCOMPARE(dropTarget.defaultAction, Qt::CopyAction);
 
754
    QCOMPARE(dropTarget.proposedAction, Qt::CopyAction);
 
755
 
 
756
    // The proposed action can change during a drag.
 
757
    evaluate<void>(item, "Drag.proposedAction = Qt.MoveAction");
 
758
    QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.MoveAction"), true);
 
759
    QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.MoveAction"), true);
 
760
    item->setPos(QPointF(60, 60));
 
761
    QCOMPARE(dropTarget.defaultAction, Qt::MoveAction);
 
762
    QCOMPARE(dropTarget.proposedAction, Qt::MoveAction);
 
763
 
 
764
    evaluate<void>(item, "Drag.proposedAction = Qt.LinkAction");
 
765
    QCOMPARE(evaluate<bool>(item, "Drag.proposedAction == Qt.LinkAction"), true);
 
766
    QCOMPARE(evaluate<bool>(item, "proposedAction == Qt.LinkAction"), true);
 
767
    evaluate<void>(item, "Drag.drop()");
 
768
    QCOMPARE(dropTarget.defaultAction, Qt::LinkAction);
 
769
    QCOMPARE(dropTarget.proposedAction, Qt::LinkAction);
 
770
}
 
771
 
 
772
void tst_QQuickDrag::keys()
 
773
{
 
774
    QQmlComponent component(&engine);
 
775
    component.setData(
 
776
            "import QtQuick 2.0\n"
 
777
            "Item {\n"
 
778
                "property variant keys: Drag.keys\n"
 
779
                "x: 50; y: 50\n"
 
780
                "width: 10; height: 10\n"
 
781
            "}", QUrl());
 
782
    QScopedPointer<QObject> object(component.create());
 
783
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
784
    QVERIFY(item);
 
785
 
 
786
//    QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList());
 
787
//    QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList());
 
788
    QCOMPARE(item->property("keys").toStringList(), QStringList());
 
789
 
 
790
    evaluate<void>(item, "Drag.keys = [\"red\", \"blue\"]");
 
791
//    QCOMPARE(evaluate<QStringList>(item, "Drag.keys"), QStringList() << "red" << "blue");
 
792
//    QCOMPARE(evaluate<QStringList>(item, "keys"), QStringList() << "red" << "blue");
 
793
    QCOMPARE(item->property("keys").toStringList(), QStringList() << "red" << "blue");
 
794
}
 
795
 
 
796
void tst_QQuickDrag::source()
 
797
{
 
798
 
 
799
    QQmlComponent component(&engine);
 
800
    component.setData(
 
801
            "import QtQuick 2.0\n"
 
802
            "Item {\n"
 
803
                "property Item source: Drag.source\n"
 
804
                "x: 50; y: 50\n"
 
805
                "width: 10; height: 10\n"
 
806
                "Item { id: proxySource; objectName: \"proxySource\" }\n"
 
807
            "}", QUrl());
 
808
    QScopedPointer<QObject> object(component.create());
 
809
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
810
    QVERIFY(item);
 
811
 
 
812
    QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
 
813
    QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
 
814
 
 
815
    QQuickItem *proxySource = item->findChild<QQuickItem *>("proxySource");
 
816
    QVERIFY(proxySource);
 
817
 
 
818
    evaluate<void>(item, "Drag.source = proxySource");
 
819
    QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(proxySource));
 
820
    QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(proxySource));
 
821
 
 
822
    evaluate<void>(item, "Drag.source = undefined");
 
823
    QCOMPARE(evaluate<QObject *>(item, "Drag.source"), static_cast<QObject *>(item));
 
824
    QCOMPARE(evaluate<QObject *>(item, "source"), static_cast<QObject *>(item));
 
825
}
 
826
 
 
827
class RecursingDropTarget : public TestDropTarget
 
828
{
 
829
public:
 
830
    RecursingDropTarget(const QString &script, int type, QQuickItem *parent)
 
831
        : TestDropTarget(parent), script(script), type(type), item(0) {}
 
832
 
 
833
    void setItem(QQuickItem *i) { item = i; }
 
834
 
 
835
protected:
 
836
    void dragEnterEvent(QDragEnterEvent *event)
 
837
    {
 
838
        TestDropTarget::dragEnterEvent(event);
 
839
        if (type == QEvent::DragEnter && enterEvents < 2)
 
840
            evaluate<void>(item, script);
 
841
    }
 
842
 
 
843
    void dragMoveEvent(QDragMoveEvent *event)
 
844
    {
 
845
        TestDropTarget::dragMoveEvent(event);
 
846
        if (type == QEvent::DragMove && moveEvents < 2)
 
847
            evaluate<void>(item, script);
 
848
    }
 
849
 
 
850
    void dragLeaveEvent(QDragLeaveEvent *event)
 
851
    {
 
852
        TestDropTarget::dragLeaveEvent(event);
 
853
        if (type == QEvent::DragLeave && leaveEvents < 2)
 
854
            evaluate<void>(item, script);
 
855
    }
 
856
 
 
857
    void dropEvent(QDropEvent *event)
 
858
    {
 
859
        TestDropTarget::dropEvent(event);
 
860
        if (type == QEvent::Drop && dropEvents < 2)
 
861
            evaluate<void>(item, script);
 
862
    }
 
863
 
 
864
private:
 
865
    QString script;
 
866
    int type;
 
867
    QQuickItem *item;
 
868
 
 
869
};
 
870
 
 
871
void tst_QQuickDrag::recursion_data()
 
872
{
 
873
    QTest::addColumn<QString>("script");
 
874
    QTest::addColumn<int>("type");
 
875
    QTest::addColumn<QByteArray>("warning");
 
876
 
 
877
    QTest::newRow("Drag.start() in Enter")
 
878
            << QString("Drag.start()")
 
879
            << int(QEvent::DragEnter)
 
880
            << QByteArray("<Unknown File>: QML QQuickDragAttached: start() cannot be called from within a drag event handler");
 
881
    QTest::newRow("Drag.cancel() in Enter")
 
882
            << QString("Drag.cancel()")
 
883
            << int(QEvent::DragEnter)
 
884
            << QByteArray("<Unknown File>: QML QQuickDragAttached: cancel() cannot be called from within a drag event handler");
 
885
    QTest::newRow("Drag.drop() in Enter")
 
886
            << QString("Drag.drop()")
 
887
            << int(QEvent::DragEnter)
 
888
            << QByteArray("<Unknown File>: QML QQuickDragAttached: drop() cannot be called from within a drag event handler");
 
889
    QTest::newRow("Drag.active = true in Enter")
 
890
            << QString("Drag.active = true")
 
891
            << int(QEvent::DragEnter)
 
892
            << QByteArray();
 
893
    QTest::newRow("Drag.active = false in Enter")
 
894
            << QString("Drag.active = false")
 
895
            << int(QEvent::DragEnter)
 
896
            << QByteArray("<Unknown File>: QML QQuickDragAttached: active cannot be changed from within a drag event handler");
 
897
    QTest::newRow("move in Enter")
 
898
            << QString("x = 23")
 
899
            << int(QEvent::DragEnter)
 
900
            << QByteArray();
 
901
 
 
902
    QTest::newRow("Drag.start() in Move")
 
903
            << QString("Drag.start()")
 
904
            << int(QEvent::DragMove)
 
905
            << QByteArray("<Unknown File>: QML QQuickDragAttached: start() cannot be called from within a drag event handler");
 
906
    QTest::newRow("Drag.cancel() in Move")
 
907
            << QString("Drag.cancel()")
 
908
            << int(QEvent::DragMove)
 
909
            << QByteArray("<Unknown File>: QML QQuickDragAttached: cancel() cannot be called from within a drag event handler");
 
910
    QTest::newRow("Drag.drop() in Move")
 
911
            << QString("Drag.drop()")
 
912
            << int(QEvent::DragMove)
 
913
            << QByteArray("<Unknown File>: QML QQuickDragAttached: drop() cannot be called from within a drag event handler");
 
914
    QTest::newRow("Drag.active = true in Move")
 
915
            << QString("Drag.active = true")
 
916
            << int(QEvent::DragMove)
 
917
            << QByteArray();
 
918
    QTest::newRow("Drag.active = false in Move")
 
919
            << QString("Drag.active = false")
 
920
            << int(QEvent::DragMove)
 
921
            << QByteArray("<Unknown File>: QML QQuickDragAttached: active cannot be changed from within a drag event handler");
 
922
    QTest::newRow("move in Move")
 
923
            << QString("x = 23")
 
924
            << int(QEvent::DragMove)
 
925
            << QByteArray();
 
926
 
 
927
    QTest::newRow("Drag.start() in Leave")
 
928
            << QString("Drag.start()")
 
929
            << int(QEvent::DragLeave)
 
930
            << QByteArray("<Unknown File>: QML QQuickDragAttached: start() cannot be called from within a drag event handler");
 
931
    QTest::newRow("Drag.cancel() in Leave")
 
932
            << QString("Drag.cancel()")
 
933
            << int(QEvent::DragLeave)
 
934
            << QByteArray("<Unknown File>: QML QQuickDragAttached: cancel() cannot be called from within a drag event handler");
 
935
    QTest::newRow("Drag.drop() in Leave")
 
936
            << QString("Drag.drop()")
 
937
            << int(QEvent::DragLeave)
 
938
            << QByteArray("<Unknown File>: QML QQuickDragAttached: drop() cannot be called from within a drag event handler");
 
939
    QTest::newRow("Drag.active = true in Leave")
 
940
            << QString("Drag.active = true")
 
941
            << int(QEvent::DragLeave)
 
942
            << QByteArray("<Unknown File>: QML QQuickDragAttached: active cannot be changed from within a drag event handler");
 
943
    QTest::newRow("Drag.active = false in Leave")
 
944
            << QString("Drag.active = false")
 
945
            << int(QEvent::DragLeave)
 
946
            << QByteArray();
 
947
    QTest::newRow("move in Leave")
 
948
            << QString("x = 23")
 
949
            << int(QEvent::DragLeave)
 
950
            << QByteArray();
 
951
 
 
952
    QTest::newRow("Drag.start() in Drop")
 
953
            << QString("Drag.start()")
 
954
            << int(QEvent::Drop)
 
955
            << QByteArray("<Unknown File>: QML QQuickDragAttached: start() cannot be called from within a drag event handler");
 
956
    QTest::newRow("Drag.cancel() in Drop")
 
957
            << QString("Drag.cancel()")
 
958
            << int(QEvent::Drop)
 
959
            << QByteArray("<Unknown File>: QML QQuickDragAttached: cancel() cannot be called from within a drag event handler");
 
960
    QTest::newRow("Drag.drop() in Drop")
 
961
            << QString("Drag.drop()")
 
962
            << int(QEvent::Drop)
 
963
            << QByteArray("<Unknown File>: QML QQuickDragAttached: drop() cannot be called from within a drag event handler");
 
964
    QTest::newRow("Drag.active = true in Drop")
 
965
            << QString("Drag.active = true")
 
966
            << int(QEvent::Drop)
 
967
            << QByteArray("<Unknown File>: QML QQuickDragAttached: active cannot be changed from within a drag event handler");
 
968
    QTest::newRow("Drag.active = false in Drop")
 
969
            << QString("Drag.active = false")
 
970
            << int(QEvent::Drop)
 
971
            << QByteArray();
 
972
    QTest::newRow("move in Drop")
 
973
            << QString("x = 23")
 
974
            << int(QEvent::Drop)
 
975
            << QByteArray();
 
976
}
 
977
 
 
978
void tst_QQuickDrag::recursion()
 
979
{
 
980
    QFETCH(QString, script);
 
981
    QFETCH(int, type);
 
982
    QFETCH(QByteArray, warning);
 
983
 
 
984
    if (!warning.isEmpty())
 
985
        QTest::ignoreMessage(QtWarningMsg, warning.constData());
 
986
 
 
987
    QQuickCanvas canvas;
 
988
    RecursingDropTarget dropTarget(script, type, canvas.rootItem());
 
989
    dropTarget.setSize(QSizeF(100, 100));
 
990
    QQmlComponent component(&engine);
 
991
    component.setData(
 
992
            "import QtQuick 2.0\n"
 
993
            "Item {\n"
 
994
                "x: 50; y: 50\n"
 
995
                "width: 10; height: 10\n"
 
996
            "}", QUrl());
 
997
    QScopedPointer<QObject> object(component.create());
 
998
    QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
 
999
    QVERIFY(item);
 
1000
    item->setParentItem(canvas.rootItem());
 
1001
 
 
1002
    dropTarget.setItem(item);
 
1003
 
 
1004
    evaluate<void>(item, "Drag.start()");
 
1005
    QCOMPARE(dropTarget.enterEvents, 1);
 
1006
    QCOMPARE(dropTarget.moveEvents, 0);
 
1007
    QCOMPARE(dropTarget.dropEvents, 0);
 
1008
    QCOMPARE(dropTarget.leaveEvents, 0);
 
1009
 
 
1010
    evaluate<void>(item, "y = 15");
 
1011
    QCOMPARE(dropTarget.enterEvents, 1);
 
1012
    QCOMPARE(dropTarget.moveEvents, 1);
 
1013
    QCOMPARE(dropTarget.dropEvents, 0);
 
1014
    QCOMPARE(dropTarget.leaveEvents, 0);
 
1015
 
 
1016
    if (type == QEvent::Drop) {
 
1017
        QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.MoveAction"), true);
 
1018
        QCOMPARE(dropTarget.enterEvents, 1);
 
1019
        QCOMPARE(dropTarget.moveEvents, 1);
 
1020
        QCOMPARE(dropTarget.dropEvents, 1);
 
1021
        QCOMPARE(dropTarget.leaveEvents, 0);
 
1022
    } else {
 
1023
        evaluate<void>(item, "Drag.cancel()");
 
1024
        QCOMPARE(dropTarget.enterEvents, 1);
 
1025
        QCOMPARE(dropTarget.moveEvents, 1);
 
1026
        QCOMPARE(dropTarget.dropEvents, 0);
 
1027
        QCOMPARE(dropTarget.leaveEvents, 1);
 
1028
    }
 
1029
}
 
1030
 
 
1031
 
 
1032
QTEST_MAIN(tst_QQuickDrag)
 
1033
 
 
1034
#include "tst_qquickdrag.moc"