41 #include <QDesktopWidget>
45 #define MIN_VIEW_SCALE 0.05
46 #define MAX_VIEW_SCALE 1000.0
49 : QGraphicsView( parent )
51 setResizeAnchor( QGraphicsView::AnchorViewCenter );
52 setMouseTracking(
true );
53 viewport()->setMouseTracking(
true );
59 viewport()->setStyleSheet( QStringLiteral(
"background-color:#d7d7d7;" ) );
66 viewport()->setGraphicsEffect( mPreviewEffect );
78 return qobject_cast<QgsLayout *>( scene() );
83 return qobject_cast<const QgsLayout *>( scene() );
97 mSnapMarker =
new QgsLayoutViewSnapMarker();
99 layout->addItem( mSnapMarker );
100 mHorizontalSnapLine = createSnapLine();
101 mHorizontalSnapLine->hide();
102 layout->addItem( mHorizontalSnapLine );
103 mVerticalSnapLine = createSnapLine();
104 mVerticalSnapLine->hide();
105 layout->addItem( mVerticalSnapLine );
106 mSectionLabel =
nullptr;
108 if ( mHorizontalRuler )
110 connect( &layout->
guides(), &QAbstractItemModel::dataChanged, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
111 connect( &layout->
guides(), &QAbstractItemModel::rowsInserted, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
112 connect( &layout->
guides(), &QAbstractItemModel::rowsRemoved, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
113 connect( &layout->
guides(), &QAbstractItemModel::modelReset, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
115 if ( mVerticalRuler )
117 connect( &layout->
guides(), &QAbstractItemModel::dataChanged, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
118 connect( &layout->
guides(), &QAbstractItemModel::rowsInserted, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
119 connect( &layout->
guides(), &QAbstractItemModel::rowsRemoved, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
120 connect( &layout->
guides(), &QAbstractItemModel::modelReset, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
145 if ( mHorizontalSnapLine )
146 mHorizontalSnapLine->hide();
147 if ( mVerticalSnapLine )
148 mVerticalSnapLine->hide();
160 if ( mTool && mTool ==
tool )
164 setCursor( Qt::ArrowCursor );
170 mPreviewEffect->setEnabled( enabled );
175 return mPreviewEffect->isEnabled();
180 mPreviewEffect->
setMode( mode );
185 return mPreviewEffect->
mode();
190 double currentScale = transform().m11();
191 scale *= currentScale;
193 setTransform( QTransform::fromScale( scale, scale ) );
205 setTransform( QTransform::fromScale( level, level ) );
209 double dpi = QgsApplication::desktop()->logicalDpiX();
211 if ( ( dpi < 60 ) || ( dpi > 1200 ) )
217 setTransform( QTransform::fromScale( mmLevel, mmLevel ) );
225 mHorizontalRuler = ruler;
229 connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mHorizontalRuler->update(); } );
230 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mHorizontalRuler->update(); } );
231 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mHorizontalRuler->update(); } );
232 connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [ = ] { mHorizontalRuler->update(); } );
239 mVerticalRuler = ruler;
243 connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mVerticalRuler->update(); } );
244 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mVerticalRuler->update(); } );
245 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mVerticalRuler->update(); } );
246 connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [ = ] { mVerticalRuler->update(); } );
253 mMenuProvider.reset( provider );
258 return mMenuProvider.get();
264 return QList< QgsLayoutItemPage *>();
267 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
268 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
275 return QList< int >();
278 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
279 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
322 QDomElement documentElement = doc.createElement( QStringLiteral(
"LayoutItemClipboard" ) );
326 QSet< QgsLayoutMultiFrame * > copiedMultiFrames;
333 const QList<QgsLayoutItem *> groupedItems = itemGroup->items();
336 groupedItem->writeXml( documentElement, doc, context );
339 else if (
QgsLayoutFrame *frame = qobject_cast<QgsLayoutFrame *>( item ) )
342 if ( frame->multiFrame() && !copiedMultiFrames.contains( frame->multiFrame() ) )
344 frame->multiFrame()->writeXml( documentElement, doc, context );
345 copiedMultiFrames.insert( frame->multiFrame() );
348 item->writeXml( documentElement, doc, context );
352 doc.appendChild( documentElement );
360 QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
361 for (
int i = 0; i < itemsNodes.count(); ++i )
363 QDomNode itemNode = itemsNodes.at( i );
364 if ( itemNode.isElement() )
366 itemNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
367 itemNode.toElement().removeAttribute( QStringLiteral(
"groupUuid" ) );
370 QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral(
"LayoutMultiFrame" ) );
371 for (
int i = 0; i < multiFrameNodes.count(); ++i )
373 QDomNode multiFrameNode = multiFrameNodes.at( i );
374 if ( multiFrameNode.isElement() )
376 multiFrameNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
377 QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral(
"childFrame" ) );
378 for (
int j = 0; j < frameNodes.count(); ++j )
380 QDomNode itemNode = frameNodes.at( j );
381 if ( itemNode.isElement() )
383 itemNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
389 QMimeData *mimeData =
new QMimeData;
390 mimeData->setData( QStringLiteral(
"text/xml" ), doc.toByteArray() );
391 QClipboard *clipboard = QApplication::clipboard();
392 clipboard->setMimeData( mimeData );
398 return QList< QgsLayoutItem * >();
400 QList< QgsLayoutItem * > pastedItems;
402 QClipboard *clipboard = QApplication::clipboard();
403 if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral(
"text/xml" ) ) ) )
405 QDomElement docElem = doc.documentElement();
406 if ( docElem.tagName() == QLatin1String(
"LayoutItemClipboard" ) )
415 pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
421 pt = mapToScene( viewport()->rect().center() );
439 return QList<QgsLayoutItem *>();
441 QList< QgsLayoutItem * > pastedItems;
443 QClipboard *clipboard = QApplication::clipboard();
444 if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral(
"text/xml" ) ) ) )
446 QDomElement docElem = doc.documentElement();
447 if ( docElem.tagName() == QLatin1String(
"LayoutItemClipboard" ) )
462 QClipboard *clipboard = QApplication::clipboard();
463 if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral(
"text/xml" ) ) ) )
465 QDomElement docElem = doc.documentElement();
466 if ( docElem.tagName() == QLatin1String(
"LayoutItemClipboard" ) )
475 double increment = 1.0;
476 if ( event->modifiers() & Qt::ShiftModifier )
481 else if ( event->modifiers() & Qt::AltModifier )
484 double viewScale = transform().m11();
487 increment = 1 / viewScale;
493 switch ( event->key() )
511 return QPointF( deltaX, deltaY );
516 mPaintingEnabled = enabled;
526 if ( !mSectionLabel )
528 mSectionLabel =
new QgsLayoutReportSectionLabel(
currentLayout(),
this );
530 mSectionLabel->setRect( 0, -200, 1000, 200 );
531 mSectionLabel->setZValue( -1 );
533 mSectionLabel->setLabel( label );
541 fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
552 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
553 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
555 double verticalCenter = ( visibleRect.top() + visibleRect.bottom() ) / 2.0;
560 const double tinyHeight = 0.01;
561 QRectF targetRect( scene()->sceneRect().left(),
562 verticalCenter - tinyHeight,
563 scene()->sceneRect().width(),
566 fitInView( targetRect, Qt::KeepAspectRatio );
600 const QList<QGraphicsItem *> itemList =
currentLayout()->items();
601 for ( QGraphicsItem *graphicsItem : itemList )
605 if ( item && !paperItem )
642 const QList<QGraphicsItem *> itemList =
currentLayout()->items();
643 for ( QGraphicsItem *graphicsItem : itemList )
647 if ( item && !paperItem )
650 if ( item->isSelected() || item->
isLocked() )
674 if ( !selectedItems.isEmpty() )
676 previousSelectedItem = selectedItems.at( 0 );
679 if ( !previousSelectedItem )
687 selectedItem = layout->
itemsModel()->findItemBelow( previousSelectedItem );
689 selectedItem = layout->
itemsModel()->findItemAbove( previousSelectedItem );
716 bool itemsRaised =
false;
739 bool itemsLowered =
false;
762 bool itemsRaised =
false;
785 bool itemsLowered =
false;
811 item->setLocked(
true );
831 const QList<QGraphicsItem *> itemList =
currentLayout()->items();
832 for ( QGraphicsItem *graphicItem : itemList )
906 QList< QgsLayoutItem * > ungroupedItems;
918 if ( !ungroupedItems.empty() )
920 for (
QgsLayoutItem *item : qgis::as_const( ungroupedItems ) )
934 mSnapMarker->setVisible(
false );
939 mTool->layoutPressEvent( me.get() );
940 event->setAccepted( me->isAccepted() );
943 if ( !mTool || !event->isAccepted() )
945 if ( event->button() == Qt::MidButton )
948 setTool( mMidMouseButtonPanTool );
951 else if ( event->button() == Qt::RightButton && mMenuProvider )
953 QMenu *menu = mMenuProvider->createContextMenu(
this,
currentLayout(), mapToScene( event->pos() ) );
956 menu->exec( event->globalPos() );
962 QGraphicsView::mousePressEvent( event );
975 mTool->layoutReleaseEvent( me.get() );
976 event->setAccepted( me->isAccepted() );
979 if ( !mTool || !event->isAccepted() )
980 QGraphicsView::mouseReleaseEvent( event );
988 mMouseCurrentXY =
event->pos();
990 QPointF cursorPos = mapToScene( mMouseCurrentXY );
996 me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() );
1001 if ( me->isSnapped() )
1003 cursorPos = me->snappedPoint();
1006 mSnapMarker->setPos( me->snappedPoint() );
1007 mSnapMarker->setVisible(
true );
1010 else if ( mSnapMarker )
1012 mSnapMarker->setVisible(
false );
1015 mTool->layoutMoveEvent( me.get() );
1016 event->setAccepted( me->isAccepted() );
1022 if ( !mTool || !event->isAccepted() )
1023 QGraphicsView::mouseMoveEvent( event );
1034 mTool->layoutDoubleClickEvent( me.get() );
1035 event->setAccepted( me->isAccepted() );
1038 if ( !mTool || !event->isAccepted() )
1039 QGraphicsView::mouseDoubleClickEvent( event );
1049 mTool->wheelEvent( event );
1052 if ( !mTool || !event->isAccepted() )
1066 mTool->keyPressEvent( event );
1069 if ( mTool && event->isAccepted() )
1072 if ( event->key() == Qt::Key_Space && ! event->isAutoRepeat() )
1074 if ( !( event->modifiers() & Qt::ControlModifier ) )
1086 else if ( event->key() == Qt::Key_Left
1087 || event->key() == Qt::Key_Right
1088 || event->key() == Qt::Key_Up
1089 || event->key() == Qt::Key_Down )
1100 item->attemptMoveBy( delta.x(), delta.y() );
1115 mTool->keyReleaseEvent( event );
1118 if ( !mTool || !event->isAccepted() )
1119 QGraphicsView::keyReleaseEvent( event );
1124 QGraphicsView::resizeEvent( event );
1131 QGraphicsView::scrollContentsBy( dx, dy );
1145 if ( mPaintingEnabled )
1147 QGraphicsView::paintEvent( event );
1156 void QgsLayoutView::invalidateCachedRenders()
1162 QList< QgsLayoutItem *> items;
1167 item->invalidateCache();
1173 if ( mHorizontalRuler )
1177 if ( mVerticalRuler )
1183 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1184 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
1185 QPointF centerVisible = visibleRect.center();
1190 if ( newPage != mCurrentPage )
1192 mCurrentPage = newPage;
1203 void QgsLayoutView::wheelZoom( QWheelEvent *event )
1207 double zoomFactor = settings.
value( QStringLiteral(
"qgis/zoom_factor" ), 2 ).toDouble();
1210 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
1212 if ( event->modifiers() & Qt::ControlModifier )
1215 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1219 bool zoomIn =
event->angleDelta().y() > 0;
1220 double scaleFactor = (
zoomIn ? 1 / zoomFactor : zoomFactor );
1223 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1227 QPointF scenePoint = mapToScene( event->pos() );
1231 QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ),
1232 scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
1233 centerOn( newCenter.x(), newCenter.y() );
1246 QGraphicsLineItem *QgsLayoutView::createSnapLine()
const
1248 std::unique_ptr< QGraphicsLineItem> item(
new QGraphicsLineItem(
nullptr ) );
1249 QPen pen = QPen( QColor( Qt::blue ) );
1250 pen.setStyle( Qt::DotLine );
1251 pen.setWidthF( 0.0 );
1252 item->setPen( pen );
1254 return item.release();
1262 QgsLayoutViewSnapMarker::QgsLayoutViewSnapMarker()
1263 : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
1266 QFontMetrics fm( f );
1267 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
1268 mSize = fm.width( QStringLiteral(
"X" ) );
1270 mSize = fm.horizontalAdvance(
'X' );
1272 setPen( QPen( Qt::transparent, mSize ) );
1274 setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
1278 void QgsLayoutViewSnapMarker::paint( QPainter *p,
const QStyleOptionGraphicsItem *, QWidget * )
1280 QPen pen( QColor( 255, 0, 0 ) );
1283 p->setBrush( Qt::NoBrush );
1285 double halfSize = mSize / 2.0;
1286 p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
1287 p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );