103void QQuickDragAttachedPrivate::deliverEnterEvent()
105 dragRestarted =
false;
108 window = attachedItem->window();
110 mimeData->m_source = source;
111 if (!overrideActions)
112 mimeData->m_supportedActions = supportedActions;
113 mimeData->m_keys = keys;
116 QDragEnterEvent event(attachedItem->mapToScene(hotSpot), mimeData->m_supportedActions,
117 mimeData, Qt::NoButton, Qt::NoModifier);
118 QQuickDropEventEx::setProposedAction(&event, proposedAction);
119 deliverEvent(window, &event);
123void QQuickDragAttachedPrivate::deliverMoveEvent()
125 Q_Q(QQuickDragAttached);
129 QDragMoveEvent event(attachedItem->mapToScene(hotSpot), mimeData->m_supportedActions,
130 mimeData, Qt::NoButton, Qt::NoModifier);
131 QQuickDropEventEx::setProposedAction(&event, proposedAction);
132 deliverEvent(window, &event);
133 if (target != dragGrabber.target()) {
134 target = dragGrabber.target();
135 emit q->targetChanged();
182QQuickDragAttached::QQuickDragAttached(QObject *parent)
183 : QObject(*
new QQuickDragAttachedPrivate, parent)
185 Q_D(QQuickDragAttached);
186 d->attachedItem = qobject_cast<QQuickItem *>(parent);
187 d->source = d->attachedItem;
218void QQuickDragAttached::setActive(
bool active)
220 Q_D(QQuickDragAttached);
221 if (d->active != active) {
223 qmlWarning(
this) <<
"active cannot be changed from within a drag event handler";
224 else if (d->executingNativeDrag) {
229 if (d->dragType == QQuickDrag::Internal) {
230 d->start(d->supportedActions);
233 emit activeChanged();
234 if (d->dragType == QQuickDrag::Automatic) {
239 QMetaObject::invokeMethod(
this, [
this]() {
240 Q_D(QQuickDragAttached);
242 d->startDrag(d->supportedActions);
243 }, Qt::QueuedConnection);
395QSize QQuickDragAttached::imageSourceSize()
const
397 Q_D(
const QQuickDragAttached);
398 int width = d->imageSourceSize.width();
399 int height = d->imageSourceSize.height();
403 width = d->pixmapLoader.width();
408 height = d->pixmapLoader.height();
412 return QSize(width, height);
415void QQuickDragAttached::setImageSourceSize(
const QSize &size)
417 Q_D(QQuickDragAttached);
418 if (d->imageSourceSize != size) {
419 d->imageSourceSize = size;
421 if (!d->imageSource.isEmpty())
424 Q_EMIT imageSourceSizeChanged();
567void QQuickDragAttachedPrivate::start(Qt::DropActions supportedActions)
569 Q_Q(QQuickDragAttached);
573 mimeData =
new QQuickDragMimeData;
575 QQuickItemPrivate::get(attachedItem)->addItemChangeListener(
576 this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Parent);
580 mimeData->m_supportedActions = supportedActions;
583 dragRestarted =
false;
587 if (target != dragGrabber.target()) {
588 target = dragGrabber.target();
589 emit q->targetChanged();
592 emit q->activeChanged();
605void QQuickDragAttached::start(QQmlV4FunctionPtr args)
607 Q_D(QQuickDragAttached);
609 qmlWarning(
this) <<
"start() cannot be called from within a drag event handler";
616 d->overrideActions =
false;
617 Qt::DropActions supportedActions = d->supportedActions;
619 if (args->length() >= 1) {
620 QV4::Scope scope(args->v4engine());
621 QV4::ScopedValue v(scope, (*args)[0]);
623 supportedActions = Qt::DropActions(v->integerValue());
624 d->overrideActions =
true;
628 d->start(supportedActions);
647int QQuickDragAttached::drop()
649 Q_D(QQuickDragAttached);
650 Qt::DropAction acceptedAction = Qt::IgnoreAction;
653 qmlWarning(
this) <<
"drop() cannot be called from within a drag event handler";
654 return acceptedAction;
658 d->deliverMoveEvent();
661 return acceptedAction;
664 QObject *target =
nullptr;
667 QPoint scenePos = d->attachedItem->mapToScene(d->hotSpot).toPoint();
670 scenePos, d->mimeData->m_supportedActions, d->mimeData, Qt::NoButton, Qt::NoModifier);
671 QQuickDropEventEx::setProposedAction(&event, d->proposedAction);
672 d->deliverEvent(d->window, &event);
674 if (event.isAccepted()) {
675 acceptedAction = event.dropAction();
676 target = d->dragGrabber.target();
680 if (d->target != target) {
682 emit targetChanged();
685 emit activeChanged();
686 return acceptedAction;
735QMimeData *QQuickDragAttachedPrivate::createMimeData()
const
737 Q_Q(
const QQuickDragAttached);
738 QMimeData *mimeData =
new QMimeData();
740 for (
const auto [mimeType, value] : externalMimeData.asKeyValueRange()) {
741 switch (value.typeId()) {
742 case QMetaType::QByteArray:
744 mimeData->setData(mimeType, value.toByteArray());
746 case QMetaType::QString: {
747 const QString text = value.toString();
748 if (mimeType == u"text/plain"_s) {
749 mimeData->setText(text);
750 }
else if (mimeType == u"text/html"_s) {
751 mimeData->setHtml(text);
752 }
else if (mimeType == u"text/uri-list"_s) {
755 const auto lines = text.split(u"\r\n"_s, Qt::SkipEmptyParts);
756 for (
const auto &line : lines) {
757 const QUrl url(line);
761 qmlWarning(q) << line <<
" is not a valid URI";
764 mimeData->setUrls(urls);
765 }
else if (mimeType.startsWith(u"text/"_s)) {
766 if (qsizetype charsetIdx = mimeType.lastIndexOf(u";charset="_s); charsetIdx != -1) {
767 charsetIdx +=
sizeof(
";charset=") - 1;
768 const QByteArray encoding = mimeType.mid(charsetIdx).toUtf8();
769 QStringEncoder encoder(encoding);
770 if (encoder.isValid())
771 mimeData->setData(mimeType, encoder.encode(text));
773 qmlWarning(q) <<
"Don't know how to encode text as " << mimeType;
775 mimeData->setData(mimeType, text.toUtf8());
778 mimeData->setData(mimeType, text.toUtf8());
782 case QMetaType::QVariantList:
783 case QMetaType::QStringList:
784 if (mimeType == u"text/uri-list"_s) {
785 const QVariantList values = value.toList();
787 urls.reserve(values.size());
789 for (qsizetype index = 0; index < values.size(); ++index) {
790 const QUrl url = values.at(index).value<QUrl>();
795 qmlWarning(q) <<
"Value '" << values.at(index) <<
"' at index " << index
796 <<
" is not a valid URI";
800 mimeData->setUrls(urls);
803 case QMetaType::QColor:
804 if (mimeType == u"application/x-color"_s)
805 mimeData->setColorData(value);
807 case QMetaType::QImage:
808 if (
const QByteArray mimeTypeUtf8 = mimeType.toUtf8();
809 QImageWriter::supportedMimeTypes().contains(mimeTypeUtf8)) {
810 const auto imageFormats = QImageWriter::imageFormatsForMimeType(mimeTypeUtf8);
811 if (imageFormats.isEmpty()) {
812 mimeData->setImageData(value);
815 const QImage image = value.value<QImage>();
818 QBuffer buffer(&bytes);
819 QImageWriter encoder(&buffer, imageFormats.first());
820 encoder.write(image);
822 mimeData->setData(mimeType, bytes);
827 qmlWarning(q) <<
"Don't know how to encode variant of type " << value.metaType()
828 <<
" as mime type " << mimeType;
830 mimeData->setData(mimeType, value.toString().toUtf8());
838void QQuickDragAttachedPrivate::loadPixmap()
840 Q_Q(QQuickDragAttached);
842 QUrl loadUrl = imageSource;
843 const QQmlContext *context = qmlContext(q->parent());
845 loadUrl = context->resolvedUrl(imageSource);
846 pixmapLoader.load(context ? context->engine() :
nullptr, loadUrl, QRect(), q->imageSourceSize());
849Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedActions)
851 Q_Q(QQuickDragAttached);
853 QDrag *drag =
new QDrag(source ? source : q);
855 drag->setMimeData(createMimeData());
856 if (pixmapLoader.isReady())
857 drag->setPixmap(QPixmap::fromImage(pixmapLoader.image()));
859 drag->setHotSpot(hotSpot.toPoint());
860 emit q->dragStarted();
862 executingNativeDrag =
true;
863 Qt::DropAction dropAction = drag->exec(supportedActions);
864 executingNativeDrag =
false;
866 if (!QGuiApplicationPrivate::platformIntegration()->drag()->ownsDragObject())
873 emit q->targetChanged();
876 emit q->dragFinished(dropAction);
879 emit q->activeChanged();
894void QQuickDragAttached::startDrag(QQmlV4FunctionPtr args)
896 Q_D(QQuickDragAttached);
899 qmlWarning(
this) <<
"startDrag() cannot be called from within a drag event handler";
904 qmlWarning(
this) <<
"startDrag() drag must be active";
908 Qt::DropActions supportedActions = d->supportedActions;
911 if (args->length() >= 1) {
912 QV4::Scope scope(args->v4engine());
913 QV4::ScopedValue v(scope, (*args)[0]);
915 supportedActions = Qt::DropActions(v->integerValue());
919 Qt::DropAction dropAction = d->startDrag(supportedActions);
921 args->setReturnValue(QV4::Encode((
int)dropAction));
924QQuickDrag::QQuickDrag(QObject *parent)
925: QObject(parent), _target(
nullptr), _axis(XAndYAxis), _xmin(-FLT_MAX),
926_xmax(FLT_MAX), _ymin(-FLT_MAX), _ymax(FLT_MAX), _active(
false), _filterChildren(
false),
927 _smoothed(
true), _threshold(QGuiApplication::styleHints()->startDragDistance())