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 <QScroller> | ||||
40 | #include <QGestureEvent> | ||||
41 | #include <QStyleHints> | ||||
39 | 42 | | |||
ngraham: Unnecessary whitespace change | |||||
40 | // KDE | 43 | // KDE | ||
41 | #include <KDirModel> | 44 | #include <KDirModel> | ||
42 | #include <KIconLoader> | 45 | #include <KIconLoader> | ||
43 | #include <KPixmapSequence> | 46 | #include <KPixmapSequence> | ||
44 | #include <KUrlMimeData> | 47 | #include <KUrlMimeData> | ||
45 | 48 | | |||
46 | // Local | 49 | // Local | ||
47 | #include "abstractdocumentinfoprovider.h" | 50 | #include "abstractdocumentinfoprovider.h" | ||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Line(s) | 171 | { | |||
181 | QPixmap mWaitingThumbnail; | 184 | QPixmap mWaitingThumbnail; | ||
182 | QPointer<ThumbnailProvider> mThumbnailProvider; | 185 | QPointer<ThumbnailProvider> mThumbnailProvider; | ||
183 | 186 | | |||
184 | PersistentModelIndexSet mBusyIndexSet; | 187 | PersistentModelIndexSet mBusyIndexSet; | ||
185 | KPixmapSequence mBusySequence; | 188 | KPixmapSequence mBusySequence; | ||
186 | QTimeLine* mBusyAnimationTimeLine; | 189 | QTimeLine* mBusyAnimationTimeLine; | ||
187 | 190 | | |||
188 | bool mCreateThumbnailsForRemoteUrls; | 191 | bool mCreateThumbnailsForRemoteUrls; | ||
192 | bool isOnlyTab; | ||||
193 | qint64 timestamp; | ||||
194 | bool firstMoving; | ||||
195 | bool dragIsStarted; | ||||
196 | QScroller* mScroller; | ||||
197 | QPointF startCenterPoint; | ||||
198 | bool dontZoom; | ||||
189 | 199 | | |||
190 | void setupBusyAnimation() | 200 | void setupBusyAnimation() | ||
191 | { | 201 | { | ||
192 | mBusySequence = KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22); | 202 | mBusySequence = KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22); | ||
193 | mBusyAnimationTimeLine = new QTimeLine(100 * mBusySequence.frameCount(), q); | 203 | mBusyAnimationTimeLine = new QTimeLine(100 * mBusySequence.frameCount(), q); | ||
194 | mBusyAnimationTimeLine->setCurveShape(QTimeLine::LinearCurve); | 204 | mBusyAnimationTimeLine->setCurveShape(QTimeLine::LinearCurve); | ||
195 | mBusyAnimationTimeLine->setEndFrame(mBusySequence.frameCount() - 1); | 205 | mBusyAnimationTimeLine->setEndFrame(mBusySequence.frameCount() - 1); | ||
196 | mBusyAnimationTimeLine->setLoopCount(0); | 206 | mBusyAnimationTimeLine->setLoopCount(0); | ||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Line(s) | 292 | { | |||
301 | setUniformItemSizes(true); | 311 | setUniformItemSizes(true); | ||
302 | setEditTriggers(QAbstractItemView::EditKeyPressed); | 312 | setEditTriggers(QAbstractItemView::EditKeyPressed); | ||
303 | 313 | | |||
304 | d->setupBusyAnimation(); | 314 | d->setupBusyAnimation(); | ||
305 | 315 | | |||
306 | setVerticalScrollMode(ScrollPerPixel); | 316 | setVerticalScrollMode(ScrollPerPixel); | ||
307 | setHorizontalScrollMode(ScrollPerPixel); | 317 | setHorizontalScrollMode(ScrollPerPixel); | ||
308 | 318 | | |||
319 | d->mScroller = QScroller::scroller(this->viewport()); | ||||
320 | QScrollerProperties scrollerProp = d->mScroller->scrollerProperties(); | ||||
321 | scrollerProp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy,1); | ||||
322 | scrollerProp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy,1); | ||||
323 | d->mScroller->setScrollerProperties(scrollerProp); | ||||
324 | d->mScroller->grabGesture(this->viewport(), QScroller::TouchGesture); | ||||
325 | viewport()->setAttribute(Qt::WA_AcceptTouchEvents); | ||||
326 | viewport()->grabGesture(Qt::PinchGesture); | ||||
327 | | ||||
309 | d->mScheduledThumbnailGenerationTimer.setSingleShot(true); | 328 | d->mScheduledThumbnailGenerationTimer.setSingleShot(true); | ||
310 | d->mScheduledThumbnailGenerationTimer.setInterval(500); | 329 | d->mScheduledThumbnailGenerationTimer.setInterval(500); | ||
311 | connect(&d->mScheduledThumbnailGenerationTimer, &QTimer::timeout, this, &ThumbnailView::generateThumbnailsForItems); | 330 | connect(&d->mScheduledThumbnailGenerationTimer, &QTimer::timeout, this, &ThumbnailView::generateThumbnailsForItems); | ||
312 | 331 | | |||
313 | d->mSmoothThumbnailTimer.setSingleShot(true); | 332 | d->mSmoothThumbnailTimer.setSingleShot(true); | ||
314 | connect(&d->mSmoothThumbnailTimer, &QTimer::timeout, this, &ThumbnailView::smoothNextThumbnail); | 333 | connect(&d->mSmoothThumbnailTimer, &QTimer::timeout, this, &ThumbnailView::smoothNextThumbnail); | ||
315 | 334 | | |||
316 | setContextMenuPolicy(Qt::CustomContextMenu); | 335 | setContextMenuPolicy(Qt::CustomContextMenu); | ||
▲ Show 20 Lines • Show All 371 Lines • ▼ Show 20 Line(s) | 698 | { | |||
688 | } | 707 | } | ||
689 | 708 | | |||
690 | QDrag* drag = new QDrag(this); | 709 | QDrag* drag = new QDrag(this); | ||
691 | drag->setMimeData(MimeTypeUtils::selectionMimeData(selectedFiles, MimeTypeUtils::DropTarget)); | 710 | drag->setMimeData(MimeTypeUtils::selectionMimeData(selectedFiles, MimeTypeUtils::DropTarget)); | ||
692 | d->initDragPixmap(drag, indexes); | 711 | d->initDragPixmap(drag, indexes); | ||
693 | drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::CopyAction); | 712 | drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::CopyAction); | ||
694 | } | 713 | } | ||
695 | 714 | | |||
715 | 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… | |||||
716 | { | ||||
717 | switch (event->type()) { | ||||
718 | case QEvent::TouchBegin: { | ||||
719 | QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); | ||||
720 | event->accept(); | ||||
721 | d->timestamp = touchEvent->timestamp(); | ||||
722 | d->firstMoving = true; | ||||
723 | d->dragIsStarted = false; | ||||
724 | d->isOnlyTab = true; | ||||
725 | QModelIndex index = indexAt(touchEvent->touchPoints().at(0).pos().toPoint()); | ||||
726 | setCurrentIndex(index); | ||||
727 | return true; | ||||
728 | } | ||||
729 | | ||||
730 | case QEvent::TouchUpdate: { | ||||
731 | event->accept(); | ||||
732 | QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); | ||||
733 | qreal now = touchEvent->timestamp(); | ||||
734 | QPointF distance = touchEvent->touchPoints().at(0).startPos() - touchEvent->touchPoints().at(0).pos(); | ||||
735 | if (d->isOnlyTab && now - d->timestamp < 100 && distance.manhattanLength() < 40 && touchEvent->touchPoints().size() == 1) { | ||||
736 | d->isOnlyTab = true; | ||||
737 | } else { | ||||
738 | d->isOnlyTab = false; | ||||
739 | } | ||||
740 | if (touchEvent->touchPoints().size() == 2) { | ||||
741 | d->dontZoom = true; | ||||
742 | if (now - d->timestamp >= 300) { | ||||
743 | QPointF startone = touchEvent->touchPoints().at(0).startPos(); | ||||
744 | QPointF starttwo = touchEvent->touchPoints().at(1).startPos(); | ||||
745 | QPointF endone = touchEvent->touchPoints().at(0).pos(); | ||||
746 | QPointF endtwo = touchEvent->touchPoints().at(1).pos(); | ||||
747 | QPointF vectorone = startone - endone; | ||||
748 | QPointF vectortwo = starttwo - endtwo; | ||||
749 | int x = (vectorone).x() * (vectortwo).x(); | ||||
750 | int y = (vectorone).y() * (vectortwo).y(); | ||||
751 | if (x == 0 && y>0) x=1; | ||||
752 | if (y == 0 && x>0) y=1; | ||||
753 | if (x >= -500 && x<0 && y>0) x=1; | ||||
754 | if (y >= -500 && y<0 && x>0) y=1; | ||||
755 | if (x>0 && y>0) { | ||||
756 | d->dontZoom = true; | ||||
757 | } else { | ||||
758 | if (vectorone.manhattanLength() > 50 || vectortwo.manhattanLength() > 50){ | ||||
759 | d->dontZoom = false; | ||||
760 | } | ||||
761 | } | ||||
762 | } | ||||
763 | } | ||||
764 | if (touchEvent->touchPoints().size() == 1) { | ||||
765 | qint64 now = touchEvent->timestamp(); | ||||
766 | QPointF startPos = touchEvent->touchPoints().at(0).startPos(); | ||||
767 | QPointF nowPos = touchEvent->touchPoints().at(0).pos(); | ||||
768 | if (d->firstMoving && now - d->timestamp >= 400 && (nowPos - startPos).manhattanLength() <= 20) { | ||||
769 | if (!d->dragIsStarted) { | ||||
770 | d->mScroller->stop(); | ||||
771 | d->dragIsStarted = true; | ||||
772 | d->firstMoving = false; | ||||
773 | startDrag(Qt::CopyAction); | ||||
774 | } | ||||
775 | } | ||||
776 | } | ||||
777 | if (d->dragIsStarted) { | ||||
778 | QWidget *receiver = this->viewport(); | ||||
779 | QPoint pos = touchEvent->touchPoints().at(0).pos().toPoint(); | ||||
780 | QMouseEvent* evt = new QMouseEvent(QEvent::MouseMove,pos, Qt::NoButton, Qt::LeftButton,0); | ||||
781 | QCoreApplication::postEvent(receiver,evt); | ||||
782 | } | ||||
783 | d->firstMoving = false; | ||||
784 | return true; | ||||
785 | } | ||||
786 | | ||||
787 | case QEvent::TouchEnd: { | ||||
788 | event->accept(); | ||||
789 | QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); | ||||
790 | if (d->dragIsStarted) { | ||||
791 | QWidget *receiver = this->viewport(); | ||||
792 | QPoint pos = touchEvent->touchPoints().at(0).pos().toPoint(); | ||||
793 | QMouseEvent* evt = new QMouseEvent(QEvent::MouseButtonRelease,pos, Qt::LeftButton, Qt::LeftButton,0); | ||||
794 | QCoreApplication::postEvent(receiver,evt); | ||||
795 | d->dragIsStarted = false; | ||||
796 | return true; | ||||
797 | } | ||||
798 | QPointF startPos = touchEvent->touchPoints().at(0).startPos(); | ||||
799 | QPointF endPos = touchEvent->touchPoints().at(0).pos(); | ||||
800 | qreal diff = (endPos-startPos).manhattanLength(); | ||||
801 | if (d->isOnlyTab && touchEvent->touchPoints().size() == 1 && diff <= 20) { | ||||
802 | QPoint pos = touchEvent->touchPoints().at(0).startPos().toPoint(); | ||||
803 | QWidget *receiver = this->viewport(); | ||||
804 | QMouseEvent* evt = new QMouseEvent(QEvent::MouseButtonPress,pos, Qt::LeftButton, Qt::LeftButton,0); | ||||
805 | QCoreApplication::postEvent(receiver,evt); | ||||
806 | QMouseEvent* evtr = new QMouseEvent(QEvent::MouseButtonRelease,pos, Qt::LeftButton, Qt::LeftButton,0); | ||||
807 | QCoreApplication::postEvent(receiver,evtr); | ||||
808 | if (!QGuiApplication::styleHints()->singleClickActivation()) { | ||||
809 | QMouseEvent* evt = new QMouseEvent(QEvent::MouseButtonDblClick,pos, Qt::LeftButton, Qt::LeftButton,0); | ||||
810 | QCoreApplication::postEvent(receiver,evt); | ||||
811 | } | ||||
812 | } | ||||
813 | return true; | ||||
814 | } | ||||
815 | case QEvent::Gesture: { | ||||
816 | if (gestureEvent(static_cast<QGestureEvent*>( event ))) { | ||||
817 | return true; | ||||
818 | } | ||||
819 | } | ||||
820 | default: | ||||
821 | break; | ||||
822 | } | ||||
823 | | ||||
824 | return QListView::viewportEvent(event); | ||||
825 | } | ||||
826 | | ||||
827 | bool ThumbnailView::gestureEvent( QGestureEvent* event) | ||||
828 | { | ||||
829 | static int zoomCounter; | ||||
830 | QPinchGesture *pinch = static_cast<QPinchGesture*>(event->gesture(Qt::PinchGesture)); | ||||
831 | if (pinch) | ||||
832 | { | ||||
833 | | ||||
834 | event->accept(); | ||||
835 | if (pinch->state() == Qt::GestureStarted) { | ||||
836 | d->startCenterPoint = pinch->centerPoint(); | ||||
837 | zoomCounter = 0; | ||||
838 | return true; | ||||
839 | } | ||||
840 | | ||||
841 | if (pinch->state() == Qt::GestureUpdated) { | ||||
842 | if (!d->dontZoom) { | ||||
843 | zoomCounter++; | ||||
844 | if (zoomCounter == 1) { | ||||
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… | |||||
845 | int width = d->mThumbnailSize.width() + ((pinch->scaleFactor() > 1 ? 1 : -1) * 1); | ||||
846 | width = qMax(int(MinThumbnailSize), qMin(width, int(MaxThumbnailSize))); | ||||
rkflx: Use `qBound`. | |||||
847 | setThumbnailWidth(width); | ||||
848 | zoomCounter = 0; | ||||
849 | } | ||||
850 | return true; | ||||
851 | } | ||||
852 | } | ||||
853 | if (pinch->state() == Qt::GestureFinished) { | ||||
854 | return true; | ||||
855 | } | ||||
856 | } | ||||
857 | return false; | ||||
858 | } | ||||
859 | | ||||
696 | void ThumbnailView::dragEnterEvent(QDragEnterEvent* event) | 860 | void ThumbnailView::dragEnterEvent(QDragEnterEvent* event) | ||
697 | { | 861 | { | ||
698 | QAbstractItemView::dragEnterEvent(event); | 862 | QAbstractItemView::dragEnterEvent(event); | ||
699 | if (event->mimeData()->hasUrls()) { | 863 | if (event->mimeData()->hasUrls()) { | ||
700 | event->acceptProposedAction(); | 864 | event->acceptProposedAction(); | ||
701 | } | 865 | } | ||
702 | } | 866 | } | ||
703 | 867 | | |||
▲ Show 20 Lines • Show All 270 Lines • Show Last 20 Lines |
Unnecessary whitespace change