1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qquickdroparea_p.h" |
5 | #include "qquickdrag_p.h" |
6 | #include "qquickitem_p.h" |
7 | |
8 | #include <private/qv4arraybuffer_p.h> |
9 | |
10 | #include <QtCore/qpointer.h> |
11 | #include <QtCore/qregularexpression.h> |
12 | |
13 | QT_BEGIN_NAMESPACE |
14 | |
15 | QQuickDropAreaDrag::QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent) |
16 | : QObject(parent) |
17 | , d(d) |
18 | { |
19 | } |
20 | |
21 | QQuickDropAreaDrag::~QQuickDropAreaDrag() |
22 | { |
23 | } |
24 | |
25 | class QQuickDropAreaPrivate : public QQuickItemPrivate |
26 | { |
27 | Q_DECLARE_PUBLIC(QQuickDropArea) |
28 | |
29 | public: |
30 | QQuickDropAreaPrivate(); |
31 | ~QQuickDropAreaPrivate(); |
32 | |
33 | bool hasMatchingKey(const QStringList &keys) const; |
34 | |
35 | QStringList getKeys(const QMimeData *mimeData) const; |
36 | |
37 | QStringList keys; |
38 | QRegularExpression keyRegExp; |
39 | QPointF dragPosition; |
40 | QQuickDropAreaDrag *drag; |
41 | QPointer<QObject> source; |
42 | bool containsDrag; |
43 | }; |
44 | |
45 | QQuickDropAreaPrivate::QQuickDropAreaPrivate() |
46 | : drag(nullptr) |
47 | , containsDrag(false) |
48 | { |
49 | } |
50 | |
51 | QQuickDropAreaPrivate::~QQuickDropAreaPrivate() |
52 | { |
53 | delete drag; |
54 | } |
55 | |
56 | /*! |
57 | \qmltype DropArea |
58 | \nativetype QQuickDropArea |
59 | \inherits Item |
60 | \inqmlmodule QtQuick |
61 | \ingroup qtquick-input |
62 | \brief For specifying drag and drop handling in an area. |
63 | |
64 | A DropArea is an invisible item which receives events when other items are |
65 | dragged over it. |
66 | |
67 | The \l Drag attached property can be used to notify the DropArea when an Item is |
68 | dragged over it. |
69 | |
70 | The \l keys property can be used to filter drag events which don't include |
71 | a matching key. |
72 | |
73 | The \l drag.source property is communicated to the source of a drag event as |
74 | the recipient of a drop on the drag target. |
75 | |
76 | \sa {Qt Quick Examples - Drag and Drop} |
77 | */ |
78 | |
79 | QQuickDropArea::QQuickDropArea(QQuickItem *parent) |
80 | : QQuickItem(*new QQuickDropAreaPrivate, parent) |
81 | { |
82 | setFlags(ItemAcceptsDrops); |
83 | } |
84 | |
85 | QQuickDropArea::~QQuickDropArea() |
86 | { |
87 | } |
88 | |
89 | /*! |
90 | \qmlproperty bool QtQuick::DropArea::containsDrag |
91 | |
92 | This property identifies whether the DropArea currently contains any |
93 | dragged items. |
94 | */ |
95 | |
96 | bool QQuickDropArea::containsDrag() const |
97 | { |
98 | Q_D(const QQuickDropArea); |
99 | return d->containsDrag; |
100 | } |
101 | |
102 | /*! |
103 | \qmlproperty stringlist QtQuick::DropArea::keys |
104 | |
105 | This property holds a list of drag keys a DropArea will accept. |
106 | |
107 | If no keys are listed the DropArea will accept events from any drag source, |
108 | otherwise the drag source must have at least one compatible key. |
109 | |
110 | \sa QtQuick::Drag::keys |
111 | */ |
112 | |
113 | QStringList QQuickDropArea::keys() const |
114 | { |
115 | Q_D(const QQuickDropArea); |
116 | return d->keys; |
117 | } |
118 | |
119 | void QQuickDropArea::setKeys(const QStringList &keys) |
120 | { |
121 | Q_D(QQuickDropArea); |
122 | if (d->keys != keys) { |
123 | d->keys = keys; |
124 | |
125 | if (keys.isEmpty()) { |
126 | d->keyRegExp = QRegularExpression(); |
127 | } else { |
128 | QString pattern = QLatin1Char('(') + QRegularExpression::escape(str: keys.first()); |
129 | for (int i = 1; i < keys.size(); ++i) |
130 | pattern += QLatin1Char('|') + QRegularExpression::escape(str: keys.at(i)); |
131 | pattern += QLatin1Char(')'); |
132 | d->keyRegExp = QRegularExpression( |
133 | QRegularExpression::anchoredPattern(expression: pattern.replace(before: QLatin1String("\\*"), |
134 | after: QLatin1String(".+")))); |
135 | } |
136 | emit keysChanged(); |
137 | } |
138 | } |
139 | |
140 | QQuickDropAreaDrag *QQuickDropArea::drag() |
141 | { |
142 | Q_D(QQuickDropArea); |
143 | if (!d->drag) |
144 | d->drag = new QQuickDropAreaDrag(d); |
145 | return d->drag; |
146 | } |
147 | |
148 | /*! |
149 | \qmlproperty QtObject QtQuick::DropArea::drag.source |
150 | |
151 | This property holds the source of a drag. |
152 | */ |
153 | |
154 | QObject *QQuickDropAreaDrag::source() const |
155 | { |
156 | return d->source; |
157 | } |
158 | |
159 | /*! |
160 | \qmlpropertygroup QtQuick::DropArea::drag |
161 | \qmlproperty qreal QtQuick::DropArea::drag.x |
162 | \qmlproperty qreal QtQuick::DropArea::drag.y |
163 | |
164 | These properties hold the coordinates of the last drag event. |
165 | */ |
166 | |
167 | qreal QQuickDropAreaDrag::x() const |
168 | { |
169 | return d->dragPosition.x(); |
170 | } |
171 | |
172 | qreal QQuickDropAreaDrag::y() const |
173 | { |
174 | return d->dragPosition.y(); |
175 | } |
176 | |
177 | /*! |
178 | \qmlsignal QtQuick::DropArea::positionChanged(DragEvent drag) |
179 | |
180 | This signal is emitted when the position of a \a drag has changed. |
181 | */ |
182 | |
183 | void QQuickDropArea::dragMoveEvent(QDragMoveEvent *event) |
184 | { |
185 | Q_D(QQuickDropArea); |
186 | if (!d->containsDrag) |
187 | return; |
188 | |
189 | d->dragPosition = event->position().toPoint(); |
190 | if (d->drag) |
191 | emit d->drag->positionChanged(); |
192 | |
193 | event->accept(); |
194 | QQuickDragEvent dragTargetEvent(d, event); |
195 | emit positionChanged(drag: &dragTargetEvent); |
196 | } |
197 | |
198 | bool QQuickDropAreaPrivate::hasMatchingKey(const QStringList &keys) const |
199 | { |
200 | if (keyRegExp.pattern().isEmpty()) |
201 | return true; |
202 | |
203 | for (const QString &key : keys) { |
204 | if (key.contains(re: keyRegExp)) |
205 | return true; |
206 | } |
207 | return false; |
208 | } |
209 | |
210 | QStringList QQuickDropAreaPrivate::getKeys(const QMimeData *mimeData) const |
211 | { |
212 | if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(object: mimeData)) |
213 | return dragMime->keys(); |
214 | return mimeData->formats(); |
215 | } |
216 | |
217 | /*! |
218 | \qmlsignal QtQuick::DropArea::entered(DragEvent drag) |
219 | |
220 | This signal is emitted when a \a drag enters the bounds of a DropArea. |
221 | */ |
222 | |
223 | void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event) |
224 | { |
225 | Q_D(QQuickDropArea); |
226 | const QMimeData *mimeData = event->mimeData(); |
227 | if (!d->effectiveEnable || d->containsDrag || !mimeData || !d->hasMatchingKey(keys: d->getKeys(mimeData))) |
228 | return; |
229 | |
230 | const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(object: mimeData); |
231 | auto dragSource = dragMime ? dragMime->source() : event->source(); |
232 | |
233 | // if the source of the drag is an ancestor of the drop area, then dragging |
234 | // also drags the drop area; see QTBUG-64128 |
235 | if (QQuickItem *dragSourceItem = qobject_cast<QQuickItem *>(o: dragSource)) { |
236 | if (dragSourceItem->isAncestorOf(child: this)) |
237 | return; |
238 | } |
239 | |
240 | d->dragPosition = event->position().toPoint(); |
241 | |
242 | event->accept(); |
243 | |
244 | QQuickDragEvent dragTargetEvent(d, event); |
245 | emit entered(drag: &dragTargetEvent); |
246 | if (!event->isAccepted()) |
247 | return; |
248 | |
249 | d->containsDrag = true; |
250 | d->source = dragSource; |
251 | d->dragPosition = event->position().toPoint(); |
252 | if (d->drag) { |
253 | emit d->drag->positionChanged(); |
254 | emit d->drag->sourceChanged(); |
255 | } |
256 | emit containsDragChanged(); |
257 | } |
258 | |
259 | /*! |
260 | \qmlsignal QtQuick::DropArea::exited() |
261 | |
262 | This signal is emitted when a drag exits the bounds of a DropArea. |
263 | */ |
264 | |
265 | void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *) |
266 | { |
267 | Q_D(QQuickDropArea); |
268 | if (!d->containsDrag) |
269 | return; |
270 | |
271 | emit exited(); |
272 | |
273 | d->containsDrag = false; |
274 | d->source = nullptr; |
275 | emit containsDragChanged(); |
276 | if (d->drag) |
277 | emit d->drag->sourceChanged(); |
278 | } |
279 | |
280 | /*! |
281 | \qmlsignal QtQuick::DropArea::dropped(DragEvent drop) |
282 | |
283 | This signal is emitted when a \a drop event occurs within the bounds of |
284 | a DropArea. |
285 | */ |
286 | |
287 | void QQuickDropArea::dropEvent(QDropEvent *event) |
288 | { |
289 | Q_D(QQuickDropArea); |
290 | if (!d->containsDrag) |
291 | return; |
292 | |
293 | QQuickDragEvent dragTargetEvent(d, event); |
294 | emit dropped(drop: &dragTargetEvent); |
295 | |
296 | d->containsDrag = false; |
297 | d->source = nullptr; |
298 | emit containsDragChanged(); |
299 | if (d->drag) |
300 | emit d->drag->sourceChanged(); |
301 | } |
302 | |
303 | /*! |
304 | \qmltype DragEvent |
305 | \nativetype QQuickDragEvent |
306 | \inqmlmodule QtQuick |
307 | \ingroup qtquick-input-events |
308 | \brief Provides information about a drag event. |
309 | |
310 | The position of the drag event can be obtained from the \l x and \l y |
311 | properties, and the \l keys property identifies the drag keys of the event |
312 | \l {drag.source}{source}. |
313 | |
314 | The existence of specific drag types can be determined using the \l hasColor, |
315 | \l hasHtml, \l hasText, and \l hasUrls properties. |
316 | |
317 | The list of all supplied formats can be determined using the \l formats property. |
318 | |
319 | Specific drag types can be obtained using the \l colorData, \l html, \l text, |
320 | and \l urls properties. |
321 | |
322 | A string version of any available mimeType can be obtained using \l getDataAsString. |
323 | */ |
324 | |
325 | /*! |
326 | \qmlproperty real QtQuick::DragEvent::x |
327 | |
328 | This property holds the x coordinate of a drag event. |
329 | */ |
330 | |
331 | /*! |
332 | \qmlproperty real QtQuick::DragEvent::y |
333 | |
334 | This property holds the y coordinate of a drag event. |
335 | */ |
336 | |
337 | /*! |
338 | \qmlproperty QtObject QtQuick::DragEvent::drag.source |
339 | |
340 | This property holds the source of a drag event. |
341 | */ |
342 | |
343 | /*! |
344 | \qmlproperty stringlist QtQuick::DragEvent::keys |
345 | |
346 | This property holds a list of keys identifying the data type or source of a |
347 | drag event. |
348 | */ |
349 | |
350 | /*! |
351 | \qmlproperty enumeration QtQuick::DragEvent::action |
352 | |
353 | This property holds the action that the \l {drag.source}{source} is to perform on an accepted drop. |
354 | |
355 | The drop action may be one of: |
356 | |
357 | \value Qt.CopyAction Copy the data to the target. |
358 | \value Qt.MoveAction Move the data from the source to the target. |
359 | \value Qt.LinkAction Create a link from the source to the target. |
360 | \value Qt.IgnoreAction Ignore the action (do nothing with the data). |
361 | */ |
362 | |
363 | /*! |
364 | \qmlproperty flags QtQuick::DragEvent::supportedActions |
365 | |
366 | This property holds the set of \l {action}{actions} supported by the |
367 | drag source. |
368 | */ |
369 | |
370 | /*! |
371 | \qmlproperty flags QtQuick::DragEvent::proposedAction |
372 | \since 5.2 |
373 | |
374 | This property holds the set of \l {action}{actions} proposed by the |
375 | drag source. |
376 | */ |
377 | |
378 | /*! |
379 | \qmlproperty bool QtQuick::DragEvent::accepted |
380 | |
381 | This property holds whether the drag event was accepted by a handler. |
382 | |
383 | The default value is true. |
384 | */ |
385 | |
386 | /*! |
387 | \qmlmethod QtQuick::DragEvent::accept() |
388 | \qmlmethod QtQuick::DragEvent::accept(enumeration action) |
389 | |
390 | Accepts the drag event. |
391 | |
392 | If an \a action is specified it will overwrite the value of the \l action property. |
393 | */ |
394 | |
395 | /*! |
396 | \qmlmethod QtQuick::DragEvent::acceptProposedAction() |
397 | \since 5.2 |
398 | |
399 | Accepts the drag event with the \l proposedAction. |
400 | */ |
401 | |
402 | /*! |
403 | \qmlproperty bool QtQuick::DragEvent::hasColor |
404 | \since 5.2 |
405 | |
406 | This property holds whether the drag event contains a color item. |
407 | */ |
408 | |
409 | /*! |
410 | \qmlproperty bool QtQuick::DragEvent::hasHtml |
411 | \since 5.2 |
412 | |
413 | This property holds whether the drag event contains a html item. |
414 | */ |
415 | |
416 | /*! |
417 | \qmlproperty bool QtQuick::DragEvent::hasText |
418 | \since 5.2 |
419 | |
420 | This property holds whether the drag event contains a text item. |
421 | */ |
422 | |
423 | /*! |
424 | \qmlproperty bool QtQuick::DragEvent::hasUrls |
425 | \since 5.2 |
426 | |
427 | This property holds whether the drag event contains one or more url items. |
428 | */ |
429 | |
430 | /*! |
431 | \qmlproperty color QtQuick::DragEvent::colorData |
432 | \since 5.2 |
433 | |
434 | This property holds color data, if any. |
435 | */ |
436 | |
437 | /*! |
438 | \qmlproperty string QtQuick::DragEvent::html |
439 | \since 5.2 |
440 | |
441 | This property holds html data, if any. |
442 | */ |
443 | |
444 | /*! |
445 | \qmlproperty string QtQuick::DragEvent::text |
446 | \since 5.2 |
447 | |
448 | This property holds text data, if any. |
449 | */ |
450 | |
451 | /*! |
452 | \qmlproperty urllist QtQuick::DragEvent::urls |
453 | \since 5.2 |
454 | |
455 | This property holds a list of urls, if any. |
456 | */ |
457 | |
458 | /*! |
459 | \qmlproperty stringlist QtQuick::DragEvent::formats |
460 | \since 5.2 |
461 | |
462 | This property holds a list of mime type formats contained in the drag data. |
463 | */ |
464 | |
465 | /*! |
466 | \qmlmethod string QtQuick::DragEvent::getDataAsString(string format) |
467 | \since 5.2 |
468 | |
469 | Returns the data for the given \a format converted to a string. \a format should be one contained in the \l formats property. |
470 | */ |
471 | |
472 | /*! |
473 | \qmlmethod string QtQuick::DragEvent::getDataAsArrayBuffer(string format) |
474 | \since 5.5 |
475 | |
476 | Returns the data for the given \a format into an ArrayBuffer, which can |
477 | easily be translated into a QByteArray. \a format should be one contained in the \l formats property. |
478 | */ |
479 | |
480 | QObject *QQuickDragEvent::source() const |
481 | { |
482 | if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(object: event->mimeData())) |
483 | return dragMime->source(); |
484 | else |
485 | return event->source(); |
486 | } |
487 | |
488 | QStringList QQuickDragEvent::keys() const |
489 | { |
490 | return d->getKeys(mimeData: event->mimeData()); |
491 | } |
492 | |
493 | bool QQuickDragEvent::hasColor() const |
494 | { |
495 | return event->mimeData()->hasColor(); |
496 | } |
497 | |
498 | bool QQuickDragEvent::hasHtml() const |
499 | { |
500 | return event->mimeData()->hasHtml(); |
501 | } |
502 | |
503 | bool QQuickDragEvent::hasText() const |
504 | { |
505 | return event->mimeData()->hasText(); |
506 | } |
507 | |
508 | bool QQuickDragEvent::hasUrls() const |
509 | { |
510 | return event->mimeData()->hasUrls(); |
511 | } |
512 | |
513 | QVariant QQuickDragEvent::colorData() const |
514 | { |
515 | return event->mimeData()->colorData(); |
516 | } |
517 | |
518 | QString QQuickDragEvent::html() const |
519 | { |
520 | return event->mimeData()->html(); |
521 | } |
522 | |
523 | QString QQuickDragEvent::text() const |
524 | { |
525 | return event->mimeData()->text(); |
526 | } |
527 | |
528 | QList<QUrl> QQuickDragEvent::urls() const |
529 | { |
530 | return event->mimeData()->urls(); |
531 | } |
532 | |
533 | QStringList QQuickDragEvent::formats() const |
534 | { |
535 | return event->mimeData()->formats(); |
536 | } |
537 | |
538 | QString QQuickDragEvent::getDataAsString(const QString &format) const |
539 | { |
540 | return QString::fromUtf8(ba: event->mimeData()->data(mimetype: format)); |
541 | } |
542 | |
543 | QByteArray QQuickDragEvent::getDataAsArrayBuffer(const QString &format) const |
544 | { |
545 | return event->mimeData()->data(mimetype: format); |
546 | } |
547 | |
548 | void QQuickDragEvent::acceptProposedAction() |
549 | { |
550 | event->acceptProposedAction(); |
551 | } |
552 | |
553 | void QQuickDragEvent::accept() |
554 | { |
555 | Qt::DropAction action = event->dropAction(); |
556 | event->setDropAction(action); |
557 | event->accept(); |
558 | } |
559 | |
560 | void QQuickDragEvent::accept(Qt::DropAction action) |
561 | { |
562 | // get action from arguments. |
563 | event->setDropAction(action); |
564 | event->accept(); |
565 | } |
566 | |
567 | |
568 | QT_END_NAMESPACE |
569 | |
570 | #include "moc_qquickdroparea_p.cpp" |
571 |
Definitions
- QQuickDropAreaDrag
- ~QQuickDropAreaDrag
- QQuickDropAreaPrivate
- QQuickDropAreaPrivate
- ~QQuickDropAreaPrivate
- QQuickDropArea
- ~QQuickDropArea
- containsDrag
- keys
- setKeys
- drag
- source
- x
- y
- dragMoveEvent
- hasMatchingKey
- getKeys
- dragEnterEvent
- dragLeaveEvent
- dropEvent
- source
- keys
- hasColor
- hasHtml
- hasText
- hasUrls
- colorData
- html
- text
- urls
- formats
- getDataAsString
- getDataAsArrayBuffer
- acceptProposedAction
- accept
Learn Advanced QML with KDAB
Find out more