1 /***************************************************************************
2 qgslayoutviewtoolmoveitemcontent.cpp
3 ------------------------------------
4 Date : October 2017
5 Copyright : (C) 2017 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "qgslayoutviewtoolmoveitemcontent.h"
17 #include "qgslayoutviewmouseevent.h"
18 #include "qgslayoutview.h"
19 #include "qgslayout.h"
20 #include "qgslayoutitemnodeitem.h"
21 #include "qgssettings.h"
22 #include "qgslayoutundostack.h"
23
QgsLayoutViewToolMoveItemContent(QgsLayoutView * view)24 QgsLayoutViewToolMoveItemContent::QgsLayoutViewToolMoveItemContent( QgsLayoutView *view )
25 : QgsLayoutViewTool( view, tr( "Select" ) )
26 {
27 setCursor( Qt::ArrowCursor );
28 }
29
layoutPressEvent(QgsLayoutViewMouseEvent * event)30 void QgsLayoutViewToolMoveItemContent::layoutPressEvent( QgsLayoutViewMouseEvent *event )
31 {
32 if ( event->button() != Qt::LeftButton )
33 {
34 event->ignore();
35 return;
36 }
37
38 const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos() );
39 if ( itemsAtCursorPos.isEmpty() )
40 return;
41
42 //find highest non-locked QgsLayoutItem at clicked position
43 //(other graphics items may be higher, e.g., selection handles)
44 for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
45 {
46 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
47 if ( item && !item->isLocked() )
48 {
49 //we've found the highest QgsLayoutItem
50 mMoveContentStartPos = event->layoutPoint();
51 mMoveContentItem = item;
52 mMovingItemContent = true;
53 break;
54 }
55 }
56 }
57
layoutMoveEvent(QgsLayoutViewMouseEvent * event)58 void QgsLayoutViewToolMoveItemContent::layoutMoveEvent( QgsLayoutViewMouseEvent *event )
59 {
60 if ( !mMovingItemContent || !mMoveContentItem )
61 {
62 event->ignore();
63 return;
64 }
65
66 //update item preview
67 mMoveContentItem->setMoveContentPreviewOffset( event->layoutPoint().x() - mMoveContentStartPos.x(),
68 event->layoutPoint().y() - mMoveContentStartPos.y() );
69 mMoveContentItem->update();
70 }
71
layoutReleaseEvent(QgsLayoutViewMouseEvent * event)72 void QgsLayoutViewToolMoveItemContent::layoutReleaseEvent( QgsLayoutViewMouseEvent *event )
73 {
74 if ( event->button() != Qt::LeftButton || !mMovingItemContent || !mMoveContentItem )
75 {
76 event->ignore();
77 return;
78 }
79
80 //update item preview
81 mMoveContentItem->setMoveContentPreviewOffset( 0, 0 );
82
83 const double moveX = event->layoutPoint().x() - mMoveContentStartPos.x();
84 const double moveY = event->layoutPoint().y() - mMoveContentStartPos.y();
85
86 mMoveContentItem->layout()->undoStack()->beginCommand( mMoveContentItem, tr( "Move Item Content" ) );
87 mMoveContentItem->moveContent( -moveX, -moveY );
88 mMoveContentItem->layout()->undoStack()->endCommand();
89 mMoveContentItem = nullptr;
90 mMovingItemContent = false;
91 }
92
wheelEvent(QWheelEvent * event)93 void QgsLayoutViewToolMoveItemContent::wheelEvent( QWheelEvent *event )
94 {
95 event->accept();
96
97 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
98 QPointF scenePoint = view()->mapToScene( event->pos().x(), event->pos().y() );
99 #else
100 const QPointF scenePoint = view()->mapToScene( event->position().x(), event->position().y() );
101 #endif
102
103 //select topmost item at position of event
104 QgsLayoutItem *item = layout()->layoutItemAt( scenePoint, true );
105 if ( !item || !item->isSelected() )
106 return;
107
108 const QgsSettings settings;
109 double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2.0 ).toDouble();
110
111 // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
112 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
113
114 if ( event->modifiers() & Qt::ControlModifier )
115 {
116 //holding ctrl while wheel zooming results in a finer zoom
117 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
118 }
119
120 //calculate zoom scale factor
121 const bool zoomIn = event->angleDelta().y() > 0;
122 const double scaleFactor = ( zoomIn ? zoomFactor : 1 / zoomFactor );
123
124 const QPointF itemPoint = item->mapFromScene( scenePoint );
125 item->layout()->undoStack()->beginCommand( item, tr( "Zoom Item Content" ), QgsLayoutItem::UndoZoomContent );
126 item->zoomContent( scaleFactor, itemPoint );
127 item->layout()->undoStack()->endCommand();
128 }
129