diff --git a/lib/documentview/abstractdocumentviewadapter.h b/lib/documentview/abstractdocumentviewadapter.h --- a/lib/documentview/abstractdocumentviewadapter.h +++ b/lib/documentview/abstractdocumentviewadapter.h @@ -26,6 +26,7 @@ // Qt #include #include +#include // KDE @@ -139,6 +140,17 @@ */ virtual QRectF visibleDocumentRect() const; + /** + * Returns a QPixmap representation of the document, scaled to @size + * E.g. images may return a thumbnail of the image, where a video might return an icon + * Note: requesting a large size may result in a blurry image if the document is a raster + * image and has not loaded yet + */ + virtual QPixmap thumbnailRepresentation(QSize /*size*/) const + { + return QPixmap(); + } + protected: void setWidget(QGraphicsWidget* widget) { 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 @@ -398,6 +398,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.cpp b/lib/documentview/documentview.cpp --- a/lib/documentview/documentview.cpp +++ b/lib/documentview/documentview.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include // KDE #include @@ -336,6 +338,31 @@ q->isAnimatedChanged(); anim->start(QAbstractAnimation::DeleteWhenStopped); } + + void startDragIfSensible() + { + // Usually dragging = panning an image. We only want to start a drag operation if panning is currently impossible. + // If the document can be zoomed, and it's zoomed enough that not all the image is visible, then panning is possible + // and we abort the drag operation. + 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; + } + + // Drag allows Move/Copy/Link to external application (e.g. Dolphin) + QDrag* drag = new QDrag(q); + QMimeData* mimeData = new QMimeData; + const QUrl url = mDocument.data()->url(); + mimeData->setUrls(QList {url}); + mimeData->setData(QStringLiteral("application/x-kde-suggestedfilename"), QFile::encodeName(url.fileName())); + drag->setMimeData(mimeData); + const QPixmap pix = mAdapter->thumbnailRepresentation(QSize(100, 100)); + if (!pix.isNull()) { + drag->setPixmap(pix); + } + drag->exec(Qt::CopyAction); + } }; DocumentView::DocumentView(QGraphicsScene* scene) @@ -794,6 +821,8 @@ if (d->mBirdEyeView) { d->mBirdEyeView->onMouseMoved(); } + } else if (event->type() == QEvent::GraphicsSceneMouseMove) { + d->startDragIfSensible(); } return false; } diff --git a/lib/documentview/rasterimageviewadapter.h b/lib/documentview/rasterimageviewadapter.h --- a/lib/documentview/rasterimageviewadapter.h +++ b/lib/documentview/rasterimageviewadapter.h @@ -84,6 +84,8 @@ virtual QRectF visibleDocumentRect() const Q_DECL_OVERRIDE; + virtual QPixmap thumbnailRepresentation(QSize size) const override; + private Q_SLOTS: void slotLoadingFailed(); diff --git a/lib/documentview/rasterimageviewadapter.cpp b/lib/documentview/rasterimageviewadapter.cpp --- a/lib/documentview/rasterimageviewadapter.cpp +++ b/lib/documentview/rasterimageviewadapter.cpp @@ -162,5 +162,13 @@ return QRectF(d->mView->imageOffset(), d->mView->visibleImageSize()); } +QPixmap RasterImageViewAdapter::thumbnailRepresentation(QSize size) const +{ + // We need to get the downsampled image here because the image may not have been loaded + // and therefore document()->image() would be null. + const QImage image = document()->downSampledImageForZoom(zoom()); + return QPixmap::fromImage(image).scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); +} + } // namespace diff --git a/lib/documentview/svgviewadapter.h b/lib/documentview/svgviewadapter.h --- a/lib/documentview/svgviewadapter.h +++ b/lib/documentview/svgviewadapter.h @@ -114,6 +114,8 @@ virtual QRectF visibleDocumentRect() const override; + virtual QPixmap thumbnailRepresentation(QSize size) const override; + private: SvgViewAdapterPrivate* const d; }; 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 @@ -259,4 +260,14 @@ return QRectF(d->mView->imageOffset(), d->mView->visibleImageSize()); } +QPixmap SvgViewAdapter::thumbnailRepresentation(QSize size) const +{ + QPixmap pix = QPixmap(size); + pix.fill(Qt::transparent); + QPainter painter(&pix); + QSvgRenderer* r = document()->svgRenderer(); + r->render(&painter); + return pix; +} + } // namespace diff --git a/lib/documentview/videoviewadapter.h b/lib/documentview/videoviewadapter.h --- a/lib/documentview/videoviewadapter.h +++ b/lib/documentview/videoviewadapter.h @@ -50,6 +50,8 @@ virtual void setDocument(Document::Ptr) Q_DECL_OVERRIDE; + virtual QPixmap thumbnailRepresentation(QSize size) const override; + Q_SIGNALS: void videoFinished(); diff --git a/lib/documentview/videoviewadapter.cpp b/lib/documentview/videoviewadapter.cpp --- a/lib/documentview/videoviewadapter.cpp +++ b/lib/documentview/videoviewadapter.cpp @@ -245,6 +245,13 @@ QMetaObject::invokeMethod(this, "completed", Qt::QueuedConnection); } +QPixmap VideoViewAdapter::thumbnailRepresentation(QSize size) const +{ + // Thumbnail of video is not very useful, so return an icon instead + const QIcon icon = QIcon::fromTheme("video-x-generic"); + return icon.pixmap(size); +} + Document::Ptr VideoViewAdapter::document() const { return d->mDocument;