diff --git a/lib/documentview/abstractimageview.h b/lib/documentview/abstractimageview.h --- a/lib/documentview/abstractimageview.h +++ b/lib/documentview/abstractimageview.h @@ -144,6 +144,7 @@ void keyReleaseEvent(QKeyEvent* event) Q_DECL_OVERRIDE; void mousePressEvent(QGraphicsSceneMouseEvent* event) Q_DECL_OVERRIDE; void mouseMoveEvent(QGraphicsSceneMouseEvent* event) Q_DECL_OVERRIDE; + void hoverMoveEvent(QGraphicsSceneHoverEvent* event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) Q_DECL_OVERRIDE; void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) Q_DECL_OVERRIDE; diff --git a/lib/documentview/abstractimageview.cpp b/lib/documentview/abstractimageview.cpp --- a/lib/documentview/abstractimageview.cpp +++ b/lib/documentview/abstractimageview.cpp @@ -402,6 +402,15 @@ d->setScrollPos(newScrollPos); } +void AbstractImageView::hoverMoveEvent(QGraphicsSceneHoverEvent* event) +{ + QGraphicsItem::hoverMoveEvent(event); + if (!d->mLastDragPos.isNull()) { + d->mLastDragPos = QPointF(); + } + updateCursor(); +} + void AbstractImageView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { QGraphicsItem::mouseReleaseEvent(event); diff --git a/lib/documentview/documentview.h b/lib/documentview/documentview.h --- a/lib/documentview/documentview.h +++ b/lib/documentview/documentview.h @@ -222,6 +222,8 @@ void slotFadeInFinished(); + void slotGotDragPixmap(const KFileItem&, const QPixmap&); + private: friend struct DocumentViewPrivate; DocumentViewPrivate* const d; diff --git a/lib/documentview/documentview.cpp b/lib/documentview/documentview.cpp --- a/lib/documentview/documentview.cpp +++ b/lib/documentview/documentview.cpp @@ -38,9 +38,13 @@ #include #include #include +#include +#include // KDE #include +#include +#include // Local #include @@ -103,6 +107,9 @@ bool mCompareMode; int controlWheelAccumulatedDelta; + QPixmap dragPixmap; + const int dragPixmapMaxPixelSize = 100; + void setCurrentAdapter(AbstractDocumentViewAdapter* adapter) { Q_ASSERT(adapter); @@ -336,6 +343,61 @@ q->isAnimatedChanged(); anim->start(QAbstractAnimation::DeleteWhenStopped); } + + void generateDragPixmap() + { + const QUrl url = q->document()->url(); + const MimeTypeUtils::Kind mimeKind = MimeTypeUtils::urlKind(url); + if (mimeKind == MimeTypeUtils::KIND_RASTER_IMAGE) { + return; + } + + const KFileItem item = KFileItem(url, MimeTypeUtils::urlMimeType(url)); + KFileItemList itemList; + itemList.append(item); + const QStringList availPlugins = KIO::PreviewJob::availablePlugins(); + KIO::Job* job = KIO::filePreview(itemList, QSize(dragPixmapMaxPixelSize, dragPixmapMaxPixelSize), &availPlugins); + KIO::Job::connect(job, SIGNAL(gotPreview(KFileItem,QPixmap)), + q, SLOT(slotGotDragPixmap(KFileItem,QPixmap))); + job->start(); + } + + void startDragIfSensible() + { + if (q->currentTool()) { + return; + } + + // Is the image pannable (actual size > viewport size)? + const QSize zoomedImageSize = mDocument->size() * q->zoom(); + const QSize viewPortSize = q->boundingRect().size().toSize(); + if (q->canZoom() && (zoomedImageSize.width() > viewPortSize.width() || zoomedImageSize.height() > viewPortSize.height())) { + return; + } + + QDrag* drag = new QDrag(q); + QMimeData* mimeData = new QMimeData; + const QUrl url = q->document()->url(); + mimeData->setUrls(QList {url}); + mimeData->setData(QStringLiteral("application/x-kde-suggestedfilename"), QFile::encodeName(url.fileName())); + + // Set image data + // - Raster images: current image (could be edited but unsaved) + // - SVGs: raw data + const MimeTypeUtils::Kind mimeKind = MimeTypeUtils::urlKind(url); + if (mimeKind == MimeTypeUtils::KIND_RASTER_IMAGE) { + mimeData->setImageData(q->document()->image()); + const QSize size = QSize(dragPixmapMaxPixelSize, dragPixmapMaxPixelSize); + dragPixmap = QPixmap::fromImage(q->document()->image().scaled(size, Qt::KeepAspectRatio)); + } else if (mimeKind == MimeTypeUtils::KIND_SVG_IMAGE) { + mimeData->setData(MimeTypeUtils::urlMimeType(url), q->document()->rawData()); + } + + drag->setPixmap(dragPixmap); + + drag->setMimeData(mimeData); + drag->exec(Qt::CopyAction); + } }; DocumentView::DocumentView(QGraphicsScene* scene) @@ -372,6 +434,11 @@ delete d; } +void DocumentView::slotGotDragPixmap(const KFileItem& /*item*/, const QPixmap& pixmap) +{ + d->dragPixmap = pixmap; +} + void DocumentView::createAdapterForDocument() { const MimeTypeUtils::Kind documentKind = d->mDocument->kind(); @@ -451,6 +518,8 @@ SLOT(slotLoadingFailed())); d->mAdapter->setDocument(d->mDocument); d->updateCaption(); + + d->generateDragPixmap(); } void DocumentView::loadAdapterConfig() @@ -797,6 +866,8 @@ if (d->mBirdEyeView) { d->mBirdEyeView->onMouseMoved(); } + } else if (event->type() == QEvent::GraphicsSceneMouseMove) { + d->startDragIfSensible(); } return false; } diff --git a/lib/documentview/svgviewadapter.cpp b/lib/documentview/svgviewadapter.cpp --- a/lib/documentview/svgviewadapter.cpp +++ b/lib/documentview/svgviewadapter.cpp @@ -29,6 +29,7 @@ #include #include #include +#include // KDE