Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickdroparea.cpp
Go to the documentation of this file.
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
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
14
15QQuickDropAreaDrag::QQuickDropAreaDrag(QQuickDropAreaPrivate *d, QObject *parent)
17 , d(d)
18{
19}
20
24
26{
27 Q_DECLARE_PUBLIC(QQuickDropArea)
28
29public:
32
33 bool hasMatchingKey(const QStringList &keys) const;
34
35 QStringList getKeys(const QMimeData *mimeData) const;
36
43};
44
45QQuickDropAreaPrivate::QQuickDropAreaPrivate()
46 : drag(nullptr)
47 , containsDrag(false)
48{
49}
50
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
79QQuickDropArea::QQuickDropArea(QQuickItem *parent)
80 : QQuickItem(*new QQuickDropAreaPrivate, parent)
81{
82 setFlags(ItemAcceptsDrops);
83}
84
85QQuickDropArea::~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
96bool 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
113QStringList QQuickDropArea::keys() const
114{
115 Q_D(const QQuickDropArea);
116 return d->keys;
117}
118
119void 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(keys.first());
129 for (int i = 1; i < keys.size(); ++i)
130 pattern += QLatin1Char('|') + QRegularExpression::escape(keys.at(i));
131 pattern += QLatin1Char(')');
132 d->keyRegExp = QRegularExpression(
133 QRegularExpression::anchoredPattern(pattern.replace(QLatin1String("\\*"),
134 QLatin1String(".+"))));
135 }
136 emit keysChanged();
137 }
138}
139
140QQuickDropAreaDrag *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
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
168{
169 return d->dragPosition.x();
170}
171
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
183void 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(&dragTargetEvent);
196}
197
198bool 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(keyRegExp))
205 return true;
206 }
207 return false;
208}
209
210QStringList QQuickDropAreaPrivate::getKeys(const QMimeData *mimeData) const
211{
212 if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(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
223void QQuickDropArea::dragEnterEvent(QDragEnterEvent *event)
224{
225 Q_D(QQuickDropArea);
226 const QMimeData *mimeData = event->mimeData();
227 if (!d->effectiveEnable || d->containsDrag || !mimeData || !d->hasMatchingKey(d->getKeys(mimeData)))
228 return;
229
230 const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(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 *>(dragSource)) {
236 if (dragSourceItem->isAncestorOf(this))
237 return;
238 }
239
240 d->dragPosition = event->position().toPoint();
241
242 event->accept();
243
244 QQuickDragEvent dragTargetEvent(d, event);
245 emit entered(&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
265void 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
287void QQuickDropArea::dropEvent(QDropEvent *event)
288{
289 Q_D(QQuickDropArea);
290 if (!d->containsDrag)
291 return;
292
293 QQuickDragEvent dragTargetEvent(d, event);
294 emit dropped(&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
480QObject *QQuickDragEvent::source() const
481{
482 if (const QQuickDragMimeData *dragMime = qobject_cast<const QQuickDragMimeData *>(event->mimeData()))
483 return dragMime->source();
484 else
485 return event->source();
486}
487
489{
490 return d->getKeys(event->mimeData());
491}
492
494{
495 return event->mimeData()->hasColor();
496}
497
499{
500 return event->mimeData()->hasHtml();
501}
502
504{
505 return event->mimeData()->hasText();
506}
507
509{
510 return event->mimeData()->hasUrls();
511}
512
514{
515 return event->mimeData()->colorData();
516}
517
519{
520 return event->mimeData()->html();
521}
522
524{
525 return event->mimeData()->text();
526}
527
529{
530 return event->mimeData()->urls();
531}
532
534{
535 return event->mimeData()->formats();
536}
537
538QString QQuickDragEvent::getDataAsString(const QString &format) const
539{
540 return QString::fromUtf8(event->mimeData()->data(format));
541}
542
543QByteArray QQuickDragEvent::getDataAsArrayBuffer(const QString &format) const
544{
545 return event->mimeData()->data(format);
546}
547
549{
550 event->acceptProposedAction();
551}
552
554{
555 Qt::DropAction action = event->dropAction();
556 event->setDropAction(action);
557 event->accept();
558}
559
560void QQuickDragEvent::accept(Qt::DropAction action)
561{
562 // get action from arguments.
563 event->setDropAction(action);
564 event->accept();
565}
566
567
568QT_END_NAMESPACE
569
570#include "moc_qquickdroparea_p.cpp"
QObject * parent
Definition qobject.h:73
Q_INVOKABLE void accept()
QVariant colorData() const
bool hasUrls() const
QStringList formats() const
QString text() const
bool hasColor() const
bool hasText() const
QStringList keys() const
QList< QUrl > urls() const
QString html() const
bool hasHtml() const
Q_INVOKABLE void acceptProposedAction()
qreal x() const
\qmlpropertygroup QtQuick::DropArea::drag \qmlproperty qreal QtQuick::DropArea::drag....
QObject * source() const
\qmlproperty QtObject QtQuick::DropArea::drag.source
QPointer< QObject > source
QStringList getKeys(const QMimeData *mimeData) const
QRegularExpression keyRegExp
bool hasMatchingKey(const QStringList &keys) const
QQuickDropAreaDrag * drag
Combined button and popup list for selecting options.