Changeset View
Changeset View
Standalone View
Standalone View
lib/thumbnailview/thumbnailview.cpp
Show All 30 Lines | |||||
31 | #include <QQueue> | 31 | #include <QQueue> | ||
32 | #include <QScrollBar> | 32 | #include <QScrollBar> | ||
33 | #include <QTimeLine> | 33 | #include <QTimeLine> | ||
34 | #include <QTimer> | 34 | #include <QTimer> | ||
35 | #include <QDrag> | 35 | #include <QDrag> | ||
36 | #include <QMimeData> | 36 | #include <QMimeData> | ||
37 | #include <QDebug> | 37 | #include <QDebug> | ||
38 | #include <QDateTime> | 38 | #include <QDateTime> | ||
39 | #include <QGestureEvent> | ||||
40 | #include <QScroller> | ||||
39 | 41 | | |||
ngraham: Unnecessary whitespace change | |||||
40 | // KDE | 42 | // KDE | ||
41 | #include <KDirModel> | 43 | #include <KDirModel> | ||
42 | #include <KIconLoader> | 44 | #include <KIconLoader> | ||
43 | #include <KPixmapSequence> | 45 | #include <KPixmapSequence> | ||
44 | #include <KUrlMimeData> | 46 | #include <KUrlMimeData> | ||
45 | 47 | | |||
46 | // Local | 48 | // Local | ||
47 | #include "abstractdocumentinfoprovider.h" | 49 | #include "abstractdocumentinfoprovider.h" | ||
48 | #include "abstractthumbnailviewhelper.h" | 50 | #include "abstractthumbnailviewhelper.h" | ||
49 | #include "archiveutils.h" | 51 | #include "archiveutils.h" | ||
50 | #include "dragpixmapgenerator.h" | 52 | #include "dragpixmapgenerator.h" | ||
51 | #include "mimetypeutils.h" | 53 | #include "mimetypeutils.h" | ||
52 | #include "urlutils.h" | 54 | #include "urlutils.h" | ||
53 | #include <lib/gvdebug.h> | 55 | #include <lib/gvdebug.h> | ||
54 | #include <lib/thumbnailprovider/thumbnailprovider.h> | 56 | #include <lib/thumbnailprovider/thumbnailprovider.h> | ||
57 | #include <lib/scrollerutils.h> | ||||
58 | #include <lib/touch/touch.h> | ||||
55 | 59 | | |||
56 | namespace Gwenview | 60 | namespace Gwenview | ||
57 | { | 61 | { | ||
58 | 62 | | |||
59 | #undef ENABLE_LOG | 63 | #undef ENABLE_LOG | ||
60 | #undef LOG | 64 | #undef LOG | ||
61 | //#define ENABLE_LOG | 65 | //#define ENABLE_LOG | ||
62 | #ifdef ENABLE_LOG | 66 | #ifdef ENABLE_LOG | ||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Line(s) | 172 | { | |||
182 | QPointer<ThumbnailProvider> mThumbnailProvider; | 186 | QPointer<ThumbnailProvider> mThumbnailProvider; | ||
183 | 187 | | |||
184 | PersistentModelIndexSet mBusyIndexSet; | 188 | PersistentModelIndexSet mBusyIndexSet; | ||
185 | KPixmapSequence mBusySequence; | 189 | KPixmapSequence mBusySequence; | ||
186 | QTimeLine* mBusyAnimationTimeLine; | 190 | QTimeLine* mBusyAnimationTimeLine; | ||
187 | 191 | | |||
188 | bool mCreateThumbnailsForRemoteUrls; | 192 | bool mCreateThumbnailsForRemoteUrls; | ||
189 | 193 | | |||
194 | QScroller* mScroller; | ||||
195 | Touch* mTouch; | ||||
196 | | ||||
190 | void setupBusyAnimation() | 197 | void setupBusyAnimation() | ||
191 | { | 198 | { | ||
192 | mBusySequence = KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22); | 199 | mBusySequence = KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22); | ||
193 | mBusyAnimationTimeLine = new QTimeLine(100 * mBusySequence.frameCount(), q); | 200 | mBusyAnimationTimeLine = new QTimeLine(100 * mBusySequence.frameCount(), q); | ||
194 | mBusyAnimationTimeLine->setCurveShape(QTimeLine::LinearCurve); | 201 | mBusyAnimationTimeLine->setCurveShape(QTimeLine::LinearCurve); | ||
195 | mBusyAnimationTimeLine->setEndFrame(mBusySequence.frameCount() - 1); | 202 | mBusyAnimationTimeLine->setEndFrame(mBusySequence.frameCount() - 1); | ||
196 | mBusyAnimationTimeLine->setLoopCount(0); | 203 | mBusyAnimationTimeLine->setLoopCount(0); | ||
197 | QObject::connect(mBusyAnimationTimeLine, &QTimeLine::frameChanged, q, &ThumbnailView::updateBusyIndexes); | 204 | QObject::connect(mBusyAnimationTimeLine, &QTimeLine::frameChanged, q, &ThumbnailView::updateBusyIndexes); | ||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Line(s) | 289 | { | |||
312 | 319 | | |||
313 | d->mSmoothThumbnailTimer.setSingleShot(true); | 320 | d->mSmoothThumbnailTimer.setSingleShot(true); | ||
314 | connect(&d->mSmoothThumbnailTimer, &QTimer::timeout, this, &ThumbnailView::smoothNextThumbnail); | 321 | connect(&d->mSmoothThumbnailTimer, &QTimer::timeout, this, &ThumbnailView::smoothNextThumbnail); | ||
315 | 322 | | |||
316 | setContextMenuPolicy(Qt::CustomContextMenu); | 323 | setContextMenuPolicy(Qt::CustomContextMenu); | ||
317 | connect(this, &ThumbnailView::customContextMenuRequested, this, &ThumbnailView::showContextMenu); | 324 | connect(this, &ThumbnailView::customContextMenuRequested, this, &ThumbnailView::showContextMenu); | ||
318 | 325 | | |||
319 | connect(this, &ThumbnailView::activated, this, &ThumbnailView::emitIndexActivatedIfNoModifiers); | 326 | connect(this, &ThumbnailView::activated, this, &ThumbnailView::emitIndexActivatedIfNoModifiers); | ||
327 | | ||||
328 | d->mScroller = ScrollerUtils::setQScroller(this->viewport()); | ||||
329 | d->mTouch = new Touch(this, viewport()); | ||||
320 | } | 330 | } | ||
321 | 331 | | |||
322 | ThumbnailView::~ThumbnailView() | 332 | ThumbnailView::~ThumbnailView() | ||
323 | { | 333 | { | ||
334 | delete d->mTouch; | ||||
324 | delete d; | 335 | delete d; | ||
325 | } | 336 | } | ||
326 | 337 | | |||
327 | ThumbnailView::ThumbnailScaleMode ThumbnailView::thumbnailScaleMode() const | 338 | ThumbnailView::ThumbnailScaleMode ThumbnailView::thumbnailScaleMode() const | ||
328 | { | 339 | { | ||
329 | return d->mScaleMode; | 340 | return d->mScaleMode; | ||
330 | } | 341 | } | ||
331 | 342 | | |||
▲ Show 20 Lines • Show All 356 Lines • ▼ Show 20 Line(s) | 690 | { | |||
688 | } | 699 | } | ||
689 | 700 | | |||
690 | QDrag* drag = new QDrag(this); | 701 | QDrag* drag = new QDrag(this); | ||
691 | drag->setMimeData(MimeTypeUtils::selectionMimeData(selectedFiles, MimeTypeUtils::DropTarget)); | 702 | drag->setMimeData(MimeTypeUtils::selectionMimeData(selectedFiles, MimeTypeUtils::DropTarget)); | ||
692 | d->initDragPixmap(drag, indexes); | 703 | d->initDragPixmap(drag, indexes); | ||
693 | drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::CopyAction); | 704 | drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::CopyAction); | ||
694 | } | 705 | } | ||
695 | 706 | | |||
707 | bool ThumbnailView::viewportEvent(QEvent* event) | ||||
This also seems to duplicate code, but again, is there any mechanism in Qt for handling this instead of having to code so much manual handling of the touch events? rkflx: This also seems to duplicate code, but again, is there any mechanism in Qt for handling this… | |||||
708 | { | ||||
709 | //necessary, otherwise, Qt makes mouse clicks from touch events | ||||
710 | if (event->type() == QEvent::TouchBegin) { | ||||
711 | return true; | ||||
712 | } | ||||
713 | | ||||
714 | if (event->type() == QEvent::Gesture) { | ||||
715 | gestureEvent(static_cast<QGestureEvent*>(event)); | ||||
716 | } | ||||
717 | | ||||
718 | return QListView::viewportEvent(event); | ||||
719 | } | ||||
720 | | ||||
721 | void ThumbnailView::gestureEvent(QGestureEvent* event) | ||||
722 | { | ||||
723 | if (event->gesture(d->mTouch->getTwoFingerPanGesture())) { | ||||
724 | d->mTouch->setLastPanGestureState(event); | ||||
725 | } | ||||
726 | | ||||
727 | if (QGesture* twoFingerTap = event->gesture(d->mTouch->getTwoFingerTapGesture())) { | ||||
728 | event->accept(); | ||||
729 | if (twoFingerTap->state() == Qt::GestureFinished) { | ||||
730 | showContextMenu(); | ||||
731 | return; | ||||
732 | } | ||||
733 | } | ||||
734 | | ||||
735 | if (QGesture* pinchGesture = event->gesture(Qt::PinchGesture)) { | ||||
736 | | ||||
737 | //we don't want a pinch gesture if a pan gesture is active | ||||
738 | //only exception is, if the pinch gesture state is Qt::GestureStarted | ||||
739 | if (d->mTouch->getLastPanGestureState() == Qt::GestureCanceled || pinchGesture->state() == Qt::GestureStarted) { | ||||
740 | event->accept(); | ||||
741 | pinchGestureTriggered(static_cast<QPinchGesture*>(pinchGesture)); | ||||
742 | //if pinch gesture is active, we don't want a other gesture | ||||
743 | return; | ||||
744 | } | ||||
745 | } | ||||
746 | | ||||
747 | if (QGesture* tapGesture = event->gesture(Qt::TapGesture)) { | ||||
748 | event->accept(); | ||||
749 | tapGestureTriggered(static_cast<QTapGesture*>(tapGesture)); | ||||
750 | } | ||||
751 | | ||||
752 | if (QGesture* tapHoldAndMovingGesture = event->gesture(d->mTouch->getTapHoldandMovingGesture())) { | ||||
753 | event->accept(); | ||||
754 | tapHoldAndMovingGestureTriggered(tapHoldAndMovingGesture); | ||||
755 | } | ||||
756 | return; | ||||
757 | } | ||||
758 | | ||||
759 | void ThumbnailView::pinchGestureTriggered(QPinchGesture* pinch) | ||||
760 | { | ||||
761 | static int startThumbnailSizeWidth; | ||||
762 | static bool firstGestureUpdatedCompleted; | ||||
763 | if (pinch->state() == Qt::GestureStarted) { | ||||
764 | startThumbnailSizeWidth = d->mThumbnailSize.width(); | ||||
765 | firstGestureUpdatedCompleted = false; | ||||
766 | return; | ||||
767 | } | ||||
768 | | ||||
769 | if (pinch->state() == Qt::GestureUpdated) { | ||||
770 | if (!firstGestureUpdatedCompleted) { | ||||
771 | firstGestureUpdatedCompleted = true; | ||||
772 | return; | ||||
773 | } | ||||
774 | | ||||
775 | int width; | ||||
776 | float sensitivModifier = 0.25; | ||||
777 | if (pinch->totalScaleFactor() >= 1.0) { | ||||
778 | width = ((pinch->totalScaleFactor() - 1.0) * sensitivModifier + 1.0) * startThumbnailSizeWidth; | ||||
779 | } else { | ||||
780 | width = (1.0 - (1.0 - pinch->totalScaleFactor()) * sensitivModifier) * startThumbnailSizeWidth; | ||||
781 | } | ||||
782 | width = qBound (int(MinThumbnailSize), width, int(MaxThumbnailSize)); | ||||
783 | setThumbnailWidth(width); | ||||
784 | return; | ||||
785 | } | ||||
786 | } | ||||
787 | | ||||
788 | void ThumbnailView::tapHoldAndMovingGestureTriggered(QGesture* gesture) | ||||
789 | { | ||||
790 | const QPoint pos = gesture->property("pos").toPoint(); | ||||
791 | | ||||
792 | switch (gesture->state()) { | ||||
793 | case Qt::GestureStarted: { | ||||
794 | QModelIndex index = indexAt(pos); | ||||
795 | if (index.isValid()) { | ||||
796 | setCurrentIndex(index); | ||||
797 | d->mScroller->stop(); | ||||
798 | startDrag(Qt::CopyAction); | ||||
799 | } | ||||
800 | break; | ||||
801 | } | ||||
802 | | ||||
803 | case Qt::GestureUpdated: { | ||||
804 | QWidget* receiver = this->viewport(); | ||||
805 | QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier); | ||||
806 | QCoreApplication::postEvent(receiver, mouseEvent); | ||||
807 | break; | ||||
808 | } | ||||
809 | | ||||
810 | case Qt::GestureCanceled: | ||||
811 | case Qt::GestureFinished: { | ||||
812 | QWidget* receiver = this->viewport(); | ||||
813 | QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); | ||||
814 | QCoreApplication::postEvent(receiver, mouseEvent); | ||||
815 | break; | ||||
816 | } | ||||
817 | | ||||
818 | default: | ||||
819 | break; | ||||
820 | } | ||||
821 | } | ||||
822 | | ||||
823 | void ThumbnailView::tapGestureTriggered(QTapGesture* gesture) | ||||
824 | { | ||||
825 | if (gesture->state() == Qt::GestureFinished) { | ||||
826 | const QPoint pos = gesture->position().toPoint(); | ||||
827 | const QRect rect = QRect(pos, QSize(1, 1)); | ||||
828 | setSelection(rect, QItemSelectionModel::ClearAndSelect); | ||||
829 | emit activated(indexAt(pos)); | ||||
830 | } | ||||
831 | } | ||||
832 | | ||||
696 | void ThumbnailView::dragEnterEvent(QDragEnterEvent* event) | 833 | void ThumbnailView::dragEnterEvent(QDragEnterEvent* event) | ||
697 | { | 834 | { | ||
698 | QAbstractItemView::dragEnterEvent(event); | 835 | QAbstractItemView::dragEnterEvent(event); | ||
699 | if (event->mimeData()->hasUrls()) { | 836 | if (event->mimeData()->hasUrls()) { | ||
rkflx: So essentially this is a `bool`? Also, what is it needed for? | |||||
I know it is a little bit crude, the aim was, to lower the sensitivity of the zoom. I wanted to use only every second gesture event to zoom the size of the thumbnail. Because the thumbnail size is an integer, I cannot modify the size in 0.5 steps. steffenh: I know it is a little bit crude, the aim was, to lower the sensitivity of the zoom. I wanted to… | |||||
700 | event->acceptProposedAction(); | 837 | event->acceptProposedAction(); | ||
701 | } | 838 | } | ||
rkflx: Use `qBound`. | |||||
702 | } | 839 | } | ||
703 | 840 | | |||
704 | void ThumbnailView::dragMoveEvent(QDragMoveEvent* event) | 841 | void ThumbnailView::dragMoveEvent(QDragMoveEvent* event) | ||
705 | { | 842 | { | ||
706 | // Necessary, otherwise we don't reach dropEvent() | 843 | // Necessary, otherwise we don't reach dropEvent() | ||
707 | QAbstractItemView::dragMoveEvent(event); | 844 | QAbstractItemView::dragMoveEvent(event); | ||
708 | event->acceptProposedAction(); | 845 | event->acceptProposedAction(); | ||
709 | } | 846 | } | ||
▲ Show 20 Lines • Show All 264 Lines • Show Last 20 Lines |
Unnecessary whitespace change