QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgslayoutview.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutview.cpp
3  -----------------
4  Date : July 2017
5  Copyright : (C) 2017 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgslayoutview.h"
19 #include "qgslayout.h"
20 #include "qgslayoutframe.h"
21 #include "qgslayoutmultiframe.h"
22 #include "qgslayoutviewtool.h"
27 #include "qgslayoutmousehandles.h"
28 #include "qgslayoutruler.h"
29 #include "qgslayoutmodel.h"
30 #include "qgssettings.h"
31 #include "qgsrectangle.h"
32 #include "qgsapplication.h"
34 #include "qgsproject.h"
35 #include "qgslayoutitemgroup.h"
37 #include "qgslayoutundostack.h"
39 #include "qgsreadwritecontext.h"
40 #include <memory>
41 #include <QMenu>
42 #include <QClipboard>
43 #include <QMimeData>
44 #include <QWindow>
45 #include <QScreen>
46 
47 #define MIN_VIEW_SCALE 0.05
48 #define MAX_VIEW_SCALE 1000.0
49 
50 QgsLayoutView::QgsLayoutView( QWidget *parent )
51  : QGraphicsView( parent )
52 {
53  setResizeAnchor( QGraphicsView::AnchorViewCenter );
54  setMouseTracking( true );
55  viewport()->setMouseTracking( true );
56 
57  // set the "scene" background on the view using stylesheets
58  // we don't want to use QGraphicsScene::setBackgroundBrush because we want to keep
59  // a transparent background for exports, and it's only a cosmetic thing for the view only
60  // ALSO - only set it on the viewport - we don't want scrollbars/etc affected by this
61  viewport()->setStyleSheet( QStringLiteral( "background-color:#d7d7d7;" ) );
62 
63  mSpacePanTool = new QgsLayoutViewToolTemporaryKeyPan( this );
64  mMidMouseButtonPanTool = new QgsLayoutViewToolTemporaryMousePan( this );
65  mSpaceZoomTool = new QgsLayoutViewToolTemporaryKeyZoom( this );
66 
67  mPreviewEffect = new QgsPreviewEffect( this );
68  viewport()->setGraphicsEffect( mPreviewEffect );
69 
70  connect( this, &QgsLayoutView::zoomLevelChanged, this, &QgsLayoutView::invalidateCachedRenders );
71 }
72 
74 {
75  emit willBeDeleted();
76 }
77 
79 {
80  return qobject_cast<QgsLayout *>( scene() );
81 }
82 
84 {
85  return qobject_cast<const QgsLayout *>( scene() );
86 }
87 
89 {
90  setScene( layout );
91 
94 
95  viewChanged();
96 
97  // IMPORTANT!
98  // previous snap markers, snap lines are owned by previous layout - so don't delete them here!
99  mSnapMarker = new QgsLayoutViewSnapMarker();
100  mSnapMarker->hide();
101  layout->addItem( mSnapMarker );
102  mHorizontalSnapLine = createSnapLine();
103  mHorizontalSnapLine->hide();
104  layout->addItem( mHorizontalSnapLine );
105  mVerticalSnapLine = createSnapLine();
106  mVerticalSnapLine->hide();
107  layout->addItem( mVerticalSnapLine );
108  mSectionLabel = nullptr;
109 
110  if ( mHorizontalRuler )
111  {
112  connect( &layout->guides(), &QAbstractItemModel::dataChanged, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
113  connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
114  connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
115  connect( &layout->guides(), &QAbstractItemModel::modelReset, mHorizontalRuler, [ = ] { mHorizontalRuler->update(); } );
116  }
117  if ( mVerticalRuler )
118  {
119  connect( &layout->guides(), &QAbstractItemModel::dataChanged, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
120  connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
121  connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
122  connect( &layout->guides(), &QAbstractItemModel::modelReset, mVerticalRuler, [ = ] { mVerticalRuler->update(); } );
123  }
124 
125  //emit layoutSet, so that designer dialogs can update for the new layout
126  emit layoutSet( layout );
127 }
128 
130 {
131  return mTool;
132 }
133 
135 {
136  if ( !tool )
137  return;
138 
139  if ( mTool )
140  {
141  mTool->deactivate();
142  disconnect( mTool, &QgsLayoutViewTool::itemFocused, this, &QgsLayoutView::itemFocused );
143  }
144 
145  if ( mSnapMarker )
146  mSnapMarker->hide();
147  if ( mHorizontalSnapLine )
148  mHorizontalSnapLine->hide();
149  if ( mVerticalSnapLine )
150  mVerticalSnapLine->hide();
151 
152  // activate new tool before setting it - gives tools a chance
153  // to respond to whatever the current tool is
154  tool->activate();
155  mTool = tool;
157  emit toolSet( mTool );
158 }
159 
161 {
162  if ( mTool && mTool == tool )
163  {
164  mTool->deactivate();
165  emit toolSet( nullptr );
166  setCursor( Qt::ArrowCursor );
167  }
168 }
169 
171 {
172  mPreviewEffect->setEnabled( enabled );
173 }
174 
176 {
177  return mPreviewEffect->isEnabled();
178 }
179 
181 {
182  mPreviewEffect->setMode( mode );
183 }
184 
186 {
187  return mPreviewEffect->mode();
188 }
189 
190 void QgsLayoutView::scaleSafe( double scale )
191 {
192  double currentScale = transform().m11();
193  scale *= currentScale;
194  scale = std::clamp( scale, MIN_VIEW_SCALE, MAX_VIEW_SCALE );
195  setTransform( QTransform::fromScale( scale, scale ) );
196  emit zoomLevelChanged();
197  viewChanged();
198 }
199 
200 void QgsLayoutView::setZoomLevel( double level )
201 {
202  if ( !currentLayout() )
203  return;
204 
205  if ( currentLayout()->units() == QgsUnitTypes::LayoutPixels )
206  {
207  setTransform( QTransform::fromScale( level, level ) );
208  }
209  else
210  {
211  double dpi = mScreenDpi;
212  //monitor dpi is not always correct - so make sure the value is sane
213  if ( ( dpi < 60 ) || ( dpi > 1200 ) )
214  dpi = 72;
215 
216  //desired pixel width for 1mm on screen
217  level = std::clamp( level, MIN_VIEW_SCALE, MAX_VIEW_SCALE );
218  double mmLevel = currentLayout()->convertFromLayoutUnits( level, QgsUnitTypes::LayoutMillimeters ).length() * dpi / 25.4;
219  setTransform( QTransform::fromScale( mmLevel, mmLevel ) );
220  }
221  emit zoomLevelChanged();
222  viewChanged();
223 }
224 
226 {
227  mHorizontalRuler = ruler;
228  ruler->setLayoutView( this );
229  if ( QgsLayout *layout = currentLayout() )
230  {
231  connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mHorizontalRuler->update(); } );
232  connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mHorizontalRuler->update(); } );
233  connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mHorizontalRuler->update(); } );
234  connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [ = ] { mHorizontalRuler->update(); } );
235  }
236  viewChanged();
237 }
238 
240 {
241  mVerticalRuler = ruler;
242  ruler->setLayoutView( this );
243  if ( QgsLayout *layout = currentLayout() )
244  {
245  connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mVerticalRuler->update(); } );
246  connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mVerticalRuler->update(); } );
247  connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mVerticalRuler->update(); } );
248  connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [ = ] { mVerticalRuler->update(); } );
249  }
250  viewChanged();
251 }
252 
254 {
255  mMenuProvider.reset( provider );
256 }
257 
259 {
260  return mMenuProvider.get();
261 }
262 
263 QList<QgsLayoutItemPage *> QgsLayoutView::visiblePages() const
264 {
265  if ( !currentLayout() )
266  return QList< QgsLayoutItemPage *>();
267 
268  //get current visible part of scene
269  QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
270  QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
271  return currentLayout()->pageCollection()->visiblePages( visibleRect );
272 }
273 
275 {
276  if ( !currentLayout() )
277  return QList< int >();
278 
279  //get current visible part of scene
280  QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
281  QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
282  return currentLayout()->pageCollection()->visiblePageNumbers( visibleRect );
283 }
284 
286 {
287  if ( !currentLayout() )
288  return;
289 
290  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
291  QgsLayoutAligner::alignItems( currentLayout(), selectedItems, alignment );
292 }
293 
295 {
296  if ( !currentLayout() )
297  return;
298 
299  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
300  QgsLayoutAligner::distributeItems( currentLayout(), selectedItems, distribution );
301 }
302 
304 {
305  if ( !currentLayout() )
306  return;
307 
308  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
309  QgsLayoutAligner::resizeItems( currentLayout(), selectedItems, resize );
310 }
311 
313 {
314  copyItems( currentLayout()->selectedLayoutItems(), operation );
315 }
316 
317 void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutView::ClipboardOperation operation )
318 {
319  if ( !currentLayout() )
320  return;
321 
322  QgsReadWriteContext context;
323  QDomDocument doc;
324  QDomElement documentElement = doc.createElement( QStringLiteral( "LayoutItemClipboard" ) );
325  if ( operation == ClipboardCut )
326  currentLayout()->undoStack()->beginMacro( tr( "Cut Items" ) );
327 
328  QSet< QgsLayoutMultiFrame * > copiedMultiFrames;
329 
330  for ( QgsLayoutItem *item : items )
331  {
332  // copy every child from a group
333  if ( QgsLayoutItemGroup *itemGroup = qobject_cast<QgsLayoutItemGroup *>( item ) )
334  {
335  const QList<QgsLayoutItem *> groupedItems = itemGroup->items();
336  for ( const QgsLayoutItem *groupedItem : groupedItems )
337  {
338  groupedItem->writeXml( documentElement, doc, context );
339  }
340  }
341  else if ( QgsLayoutFrame *frame = qobject_cast<QgsLayoutFrame *>( item ) )
342  {
343  // copy multiframe too
344  if ( frame->multiFrame() && !copiedMultiFrames.contains( frame->multiFrame() ) )
345  {
346  frame->multiFrame()->writeXml( documentElement, doc, context );
347  copiedMultiFrames.insert( frame->multiFrame() );
348  }
349  }
350  item->writeXml( documentElement, doc, context );
351  if ( operation == ClipboardCut )
352  currentLayout()->removeLayoutItem( item );
353  }
354  doc.appendChild( documentElement );
355  if ( operation == ClipboardCut )
356  {
358  currentLayout()->update();
359  }
360 
361  //remove the UUIDs since we don't want any duplicate UUID
362  QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral( "LayoutItem" ) );
363  for ( int i = 0; i < itemsNodes.count(); ++i )
364  {
365  QDomNode itemNode = itemsNodes.at( i );
366  if ( itemNode.isElement() )
367  {
368  itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
369  itemNode.toElement().removeAttribute( QStringLiteral( "groupUuid" ) );
370  }
371  }
372  QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral( "LayoutMultiFrame" ) );
373  for ( int i = 0; i < multiFrameNodes.count(); ++i )
374  {
375  QDomNode multiFrameNode = multiFrameNodes.at( i );
376  if ( multiFrameNode.isElement() )
377  {
378  multiFrameNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
379  QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral( "childFrame" ) );
380  for ( int j = 0; j < frameNodes.count(); ++j )
381  {
382  QDomNode itemNode = frameNodes.at( j );
383  if ( itemNode.isElement() )
384  {
385  itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
386  }
387  }
388  }
389  }
390 
391  QMimeData *mimeData = new QMimeData;
392  mimeData->setData( QStringLiteral( "text/xml" ), doc.toByteArray() );
393  QClipboard *clipboard = QApplication::clipboard();
394  clipboard->setMimeData( mimeData );
395 }
396 
397 QList< QgsLayoutItem * > QgsLayoutView::pasteItems( QgsLayoutView::PasteMode mode )
398 {
399  if ( !currentLayout() )
400  return QList< QgsLayoutItem * >();
401 
402  QList< QgsLayoutItem * > pastedItems;
403  QDomDocument doc;
404  QClipboard *clipboard = QApplication::clipboard();
405  if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
406  {
407  QDomElement docElem = doc.documentElement();
408  if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
409  {
410  QPointF pt;
411  switch ( mode )
412  {
413  case PasteModeCursor:
414  case PasteModeInPlace:
415  {
416  // place items at cursor position
417  pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
418  break;
419  }
420  case PasteModeCenter:
421  {
422  // place items in center of viewport
423  pt = mapToScene( viewport()->rect().center() );
424  break;
425  }
426  }
427  bool pasteInPlace = ( mode == PasteModeInPlace );
428  currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
429  currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
430  pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &pt, pasteInPlace );
433  }
434  }
435  return pastedItems;
436 }
437 
438 QList<QgsLayoutItem *> QgsLayoutView::pasteItems( QPointF layoutPoint )
439 {
440  if ( !currentLayout() )
441  return QList<QgsLayoutItem *>();
442 
443  QList< QgsLayoutItem * > pastedItems;
444  QDomDocument doc;
445  QClipboard *clipboard = QApplication::clipboard();
446  if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
447  {
448  QDomElement docElem = doc.documentElement();
449  if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
450  {
451  currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
452  currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
453  pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &layoutPoint, false );
456  }
457  }
458  return pastedItems;
459 }
460 
462 {
463  QDomDocument doc;
464  QClipboard *clipboard = QApplication::clipboard();
465  if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
466  {
467  QDomElement docElem = doc.documentElement();
468  if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
469  return true;
470  }
471  return false;
472 }
473 
474 QPointF QgsLayoutView::deltaForKeyEvent( QKeyEvent *event )
475 {
476  // increment used for cursor key item movement
477  double increment = 1.0;
478  if ( event->modifiers() & Qt::ShiftModifier )
479  {
480  //holding shift while pressing cursor keys results in a big step
481  increment = 10.0;
482  }
483  else if ( event->modifiers() & Qt::AltModifier )
484  {
485  //holding alt while pressing cursor keys results in a 1 pixel step
486  double viewScale = transform().m11();
487  if ( viewScale > 0 )
488  {
489  increment = 1 / viewScale;
490  }
491  }
492 
493  double deltaX = 0;
494  double deltaY = 0;
495  switch ( event->key() )
496  {
497  case Qt::Key_Left:
498  deltaX = -increment;
499  break;
500  case Qt::Key_Right:
501  deltaX = increment;
502  break;
503  case Qt::Key_Up:
504  deltaY = -increment;
505  break;
506  case Qt::Key_Down:
507  deltaY = increment;
508  break;
509  default:
510  break;
511  }
512 
513  return QPointF( deltaX, deltaY );
514 }
515 
517 {
518  mPaintingEnabled = enabled;
519  if ( enabled )
520  update();
521 }
522 
523 void QgsLayoutView::setSectionLabel( const QString &label )
524 {
525  if ( !currentLayout() )
526  return;
527 
528  if ( !mSectionLabel )
529  {
530  mSectionLabel = new QgsLayoutReportSectionLabel( currentLayout(), this );
531  currentLayout()->addItem( mSectionLabel );
532  mSectionLabel->setRect( 0, -200, 1000, 200 );
533  mSectionLabel->setZValue( -1 );
534  }
535  mSectionLabel->setLabel( label );
536 }
537 
539 {
540  if ( !scene() )
541  return;
542 
543  fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
544  viewChanged();
545  emit zoomLevelChanged();
546 }
547 
549 {
550  if ( !scene() )
551  return;
552 
553  //get current visible part of scene
554  QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
555  QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
556 
557  double verticalCenter = ( visibleRect.top() + visibleRect.bottom() ) / 2.0;
558  // expand out visible rect to include left/right edges of scene
559  // centered on current visible vertical center
560  // note that we can't have a 0 height rect - fitInView doesn't handle that
561  // so we just set a very small height instead.
562  const double tinyHeight = 0.01;
563  QRectF targetRect( scene()->sceneRect().left(),
564  verticalCenter - tinyHeight,
565  scene()->sceneRect().width(),
566  tinyHeight * 2 );
567 
568  fitInView( targetRect, Qt::KeepAspectRatio );
569  emit zoomLevelChanged();
570  viewChanged();
571 }
572 
574 {
575  scaleSafe( 2 );
576 }
577 
579 {
580  scaleSafe( 0.5 );
581 }
582 
584 {
585  setZoomLevel( 1.0 );
586 }
587 
589 {
590  emit zoomLevelChanged();
591 }
592 
594 {
595  if ( !currentLayout() )
596  {
597  return;
598  }
599 
600  //select all items in layout
601  QgsLayoutItem *focusedItem = nullptr;
602  const QList<QGraphicsItem *> itemList = currentLayout()->items();
603  for ( QGraphicsItem *graphicsItem : itemList )
604  {
605  QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
606  QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
607  if ( item && !paperItem )
608  {
609  if ( !item->isLocked() )
610  {
611  item->setSelected( true );
612  if ( !focusedItem )
613  focusedItem = item;
614  }
615  else
616  {
617  //deselect all locked items
618  item->setSelected( false );
619  }
620  }
621  }
622  emit itemFocused( focusedItem );
623 }
624 
626 {
627  if ( !currentLayout() )
628  {
629  return;
630  }
631 
633 }
634 
636 {
637  if ( !currentLayout() )
638  {
639  return;
640  }
641 
642  QgsLayoutItem *focusedItem = nullptr;
643  //check all items in layout
644  const QList<QGraphicsItem *> itemList = currentLayout()->items();
645  for ( QGraphicsItem *graphicsItem : itemList )
646  {
647  QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
648  QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
649  if ( item && !paperItem )
650  {
651  //flip selected state for items (and deselect any locked items)
652  if ( item->isSelected() || item->isLocked() )
653  {
654  item->setSelected( false );
655  }
656  else
657  {
658  item->setSelected( true );
659  if ( !focusedItem )
660  focusedItem = item;
661  }
662  }
663  }
664  if ( focusedItem )
665  emit itemFocused( focusedItem );
666 }
667 
668 
669 void selectNextByZOrder( QgsLayout *layout, bool above )
670 {
671  if ( !layout )
672  return;
673 
674  QgsLayoutItem *previousSelectedItem = nullptr;
675  const QList<QgsLayoutItem *> selectedItems = layout->selectedLayoutItems();
676  if ( !selectedItems.isEmpty() )
677  {
678  previousSelectedItem = selectedItems.at( 0 );
679  }
680 
681  if ( !previousSelectedItem )
682  {
683  return;
684  }
685 
686  //select item with target z value
687  QgsLayoutItem *selectedItem = nullptr;
688  if ( !above )
689  selectedItem = layout->itemsModel()->findItemBelow( previousSelectedItem );
690  else
691  selectedItem = layout->itemsModel()->findItemAbove( previousSelectedItem );
692 
693  if ( !selectedItem )
694  {
695  return;
696  }
697 
698  //OK, found a good target item
699  layout->setSelectedItem( selectedItem );
700 }
701 
703 {
705 }
706 
708 {
709  selectNextByZOrder( currentLayout(), false );
710 }
711 
713 {
714  if ( !currentLayout() )
715  return;
716 
717  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
718  bool itemsRaised = false;
719  for ( QgsLayoutItem *item : selectedItems )
720  {
721  itemsRaised = itemsRaised | currentLayout()->raiseItem( item, true );
722  }
723 
724  if ( !itemsRaised )
725  {
726  //no change
727  return;
728  }
729 
730  //update all positions
732  currentLayout()->update();
733 }
734 
736 {
737  if ( !currentLayout() )
738  return;
739 
740  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
741  bool itemsLowered = false;
742  for ( QgsLayoutItem *item : selectedItems )
743  {
744  itemsLowered = itemsLowered | currentLayout()->lowerItem( item, true );
745  }
746 
747  if ( !itemsLowered )
748  {
749  //no change
750  return;
751  }
752 
753  //update all positions
755  currentLayout()->update();
756 }
757 
759 {
760  if ( !currentLayout() )
761  return;
762 
763  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
764  bool itemsRaised = false;
765  for ( QgsLayoutItem *item : selectedItems )
766  {
767  itemsRaised = itemsRaised | currentLayout()->moveItemToTop( item, true );
768  }
769 
770  if ( !itemsRaised )
771  {
772  //no change
773  return;
774  }
775 
776  //update all positions
778  currentLayout()->update();
779 }
780 
782 {
783  if ( !currentLayout() )
784  return;
785 
786  const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
787  bool itemsLowered = false;
788  for ( QgsLayoutItem *item : selectedItems )
789  {
790  itemsLowered = itemsLowered | currentLayout()->moveItemToBottom( item, true );
791  }
792 
793  if ( !itemsLowered )
794  {
795  //no change
796  return;
797  }
798 
799  //update all positions
801  currentLayout()->update();
802 }
803 
805 {
806  if ( !currentLayout() )
807  return;
808 
809  currentLayout()->undoStack()->beginMacro( tr( "Lock Items" ) );
810  const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
811  for ( QgsLayoutItem *item : selectionList )
812  {
813  item->setLocked( true );
814  }
815 
818 }
819 
821 {
822  if ( !currentLayout() )
823  return;
824 
825  //unlock all items in layout
826  currentLayout()->undoStack()->beginMacro( tr( "Unlock Items" ) );
827 
828  //first, clear the selection
830 
831  QgsLayoutItem *focusItem = nullptr;
832 
833  const QList<QGraphicsItem *> itemList = currentLayout()->items();
834  for ( QGraphicsItem *graphicItem : itemList )
835  {
836  QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicItem );
837  if ( item && item->isLocked() )
838  {
839  focusItem = item;
840  item->setLocked( false );
841  //select unlocked items, same behavior as illustrator
842  item->setSelected( true );
843  }
844  }
846 
847  emit itemFocused( focusItem );
848 }
849 
851 {
852  if ( !currentLayout() )
853  return;
854 
855  deleteItems( currentLayout()->selectedLayoutItems() );
856 }
857 
858 void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
859 {
860  if ( !currentLayout() )
861  return;
862 
863  if ( items.empty() )
864  return;
865 
866  currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
867  //delete selected items
868  for ( QgsLayoutItem *item : items )
869  {
870  currentLayout()->removeLayoutItem( item );
871  }
873  currentLayout()->project()->setDirty( true );
874 }
875 
877 {
878  if ( !currentLayout() )
879  {
880  return;
881  }
882 
883  //group selected items
884  const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
885  QgsLayoutItemGroup *itemGroup = currentLayout()->groupItems( selectionList );
886 
887  if ( !itemGroup )
888  {
889  //group could not be created
890  return;
891  }
892 
893  for ( QgsLayoutItem *item : selectionList )
894  {
895  item->setSelected( false );
896  }
897 
898  currentLayout()->setSelectedItem( itemGroup );
899 }
900 
902 {
903  if ( !currentLayout() )
904  {
905  return;
906  }
907 
908  QList< QgsLayoutItem * > ungroupedItems;
909  //hunt through selection for any groups, and ungroup them
910  const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
911  for ( QgsLayoutItem *item : selectionList )
912  {
913  if ( item->type() == QgsLayoutItemRegistry::LayoutGroup )
914  {
915  QgsLayoutItemGroup *itemGroup = static_cast<QgsLayoutItemGroup *>( item );
916  ungroupedItems.append( currentLayout()->ungroupItems( itemGroup ) );
917  }
918  }
919 
920  if ( !ungroupedItems.empty() )
921  {
922  for ( QgsLayoutItem *item : std::as_const( ungroupedItems ) )
923  {
924  item->setSelected( true );
925  }
926  emit itemFocused( ungroupedItems.at( 0 ) );
927  }
928 }
929 
930 void QgsLayoutView::mousePressEvent( QMouseEvent *event )
931 {
932  if ( !currentLayout() )
933  return;
934 
935  if ( mSnapMarker )
936  mSnapMarker->setVisible( false );
937 
938  if ( mTool )
939  {
940  std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
941  mTool->layoutPressEvent( me.get() );
942  event->setAccepted( me->isAccepted() );
943  }
944 
945  if ( !mTool || !event->isAccepted() )
946  {
947  if ( event->button() == Qt::MiddleButton )
948  {
949  // Pan layout with middle mouse button
950  setTool( mMidMouseButtonPanTool );
951  event->accept();
952  }
953  else if ( event->button() == Qt::RightButton && mMenuProvider )
954  {
955  QMenu *menu = mMenuProvider->createContextMenu( this, currentLayout(), mapToScene( event->pos() ) );
956  if ( menu )
957  {
958  menu->exec( event->globalPos() );
959  delete menu;
960  }
961  }
962  else
963  {
964  QGraphicsView::mousePressEvent( event );
965  }
966  }
967 }
968 
969 void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
970 {
971  if ( !currentLayout() )
972  return;
973 
974  if ( mTool )
975  {
976  std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
977  mTool->layoutReleaseEvent( me.get() );
978  event->setAccepted( me->isAccepted() );
979  }
980 
981  if ( !mTool || !event->isAccepted() )
982  QGraphicsView::mouseReleaseEvent( event );
983 }
984 
985 void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )
986 {
987  if ( !currentLayout() )
988  return;
989 
990  mMouseCurrentXY = event->pos();
991 
992  QPointF cursorPos = mapToScene( mMouseCurrentXY );
993  if ( mTool )
994  {
995  std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, false ) );
996  if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
997  {
998  me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() );
999  }
1000  if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
1001  {
1002  //draw snapping point indicator
1003  if ( me->isSnapped() )
1004  {
1005  cursorPos = me->snappedPoint();
1006  if ( mSnapMarker )
1007  {
1008  mSnapMarker->setPos( me->snappedPoint() );
1009  mSnapMarker->setVisible( true );
1010  }
1011  }
1012  else if ( mSnapMarker )
1013  {
1014  mSnapMarker->setVisible( false );
1015  }
1016  }
1017  mTool->layoutMoveEvent( me.get() );
1018  event->setAccepted( me->isAccepted() );
1019  }
1020 
1021  //update cursor position in status bar
1022  emit cursorPosChanged( cursorPos );
1023 
1024  if ( !mTool || !event->isAccepted() )
1025  QGraphicsView::mouseMoveEvent( event );
1026 }
1027 
1028 void QgsLayoutView::mouseDoubleClickEvent( QMouseEvent *event )
1029 {
1030  if ( !currentLayout() )
1031  return;
1032 
1033  if ( mTool )
1034  {
1035  std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
1036  mTool->layoutDoubleClickEvent( me.get() );
1037  event->setAccepted( me->isAccepted() );
1038  }
1039 
1040  if ( !mTool || !event->isAccepted() )
1041  QGraphicsView::mouseDoubleClickEvent( event );
1042 }
1043 
1044 void QgsLayoutView::wheelEvent( QWheelEvent *event )
1045 {
1046  if ( !currentLayout() )
1047  return;
1048 
1049  if ( mTool )
1050  {
1051  mTool->wheelEvent( event );
1052  }
1053 
1054  if ( !mTool || !event->isAccepted() )
1055  {
1056  event->accept();
1057  wheelZoom( event );
1058  }
1059 }
1060 
1061 void QgsLayoutView::keyPressEvent( QKeyEvent *event )
1062 {
1063  if ( !currentLayout() )
1064  return;
1065 
1066  if ( mTool )
1067  {
1068  mTool->keyPressEvent( event );
1069  }
1070 
1071  if ( mTool && event->isAccepted() )
1072  return;
1073 
1074  if ( event->key() == Qt::Key_Space && ! event->isAutoRepeat() )
1075  {
1076  if ( !( event->modifiers() & Qt::ControlModifier ) )
1077  {
1078  // Pan layout with space bar
1079  setTool( mSpacePanTool );
1080  }
1081  else
1082  {
1083  //ctrl+space pressed, so switch to temporary keyboard based zoom tool
1084  setTool( mSpaceZoomTool );
1085  }
1086  event->accept();
1087  }
1088  else if ( event->key() == Qt::Key_Left
1089  || event->key() == Qt::Key_Right
1090  || event->key() == Qt::Key_Up
1091  || event->key() == Qt::Key_Down )
1092  {
1093  QgsLayout *l = currentLayout();
1094  const QList<QgsLayoutItem *> layoutItemList = l->selectedLayoutItems();
1095 
1096  QPointF delta = deltaForKeyEvent( event );
1097 
1098  l->undoStack()->beginMacro( tr( "Move Item" ) );
1099  for ( QgsLayoutItem *item : layoutItemList )
1100  {
1101  l->undoStack()->beginCommand( item, tr( "Move Item" ), QgsLayoutItem::UndoIncrementalMove );
1102  item->attemptMoveBy( delta.x(), delta.y() );
1103  l->undoStack()->endCommand();
1104  }
1105  l->undoStack()->endMacro();
1106  event->accept();
1107  }
1108 }
1109 
1110 void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
1111 {
1112  if ( !currentLayout() )
1113  return;
1114 
1115  if ( mTool )
1116  {
1117  mTool->keyReleaseEvent( event );
1118  }
1119 
1120  if ( !mTool || !event->isAccepted() )
1121  QGraphicsView::keyReleaseEvent( event );
1122 }
1123 
1124 void QgsLayoutView::resizeEvent( QResizeEvent *event )
1125 {
1126  QGraphicsView::resizeEvent( event );
1127  emit zoomLevelChanged();
1128  viewChanged();
1129 }
1130 
1131 void QgsLayoutView::scrollContentsBy( int dx, int dy )
1132 {
1133  QGraphicsView::scrollContentsBy( dx, dy );
1134  viewChanged();
1135 }
1136 
1137 void QgsLayoutView::dragEnterEvent( QDragEnterEvent *e )
1138 {
1139  // By default graphics view delegates the drag events to graphics items.
1140  // But we do not want that and by ignoring the drag enter we let the
1141  // parent (e.g. QgsLayoutDesignerDialog) to handle drops of files.
1142  e->ignore();
1143 }
1144 
1145 void QgsLayoutView::paintEvent( QPaintEvent *event )
1146 {
1147  if ( mPaintingEnabled )
1148  {
1149  QGraphicsView::paintEvent( event );
1150  event->accept();
1151  }
1152  else
1153  {
1154  event->ignore();
1155  }
1156 }
1157 
1158 void QgsLayoutView::showEvent( QShowEvent *event )
1159 {
1160  QGraphicsView::showEvent( event );
1161 
1162  updateDevicePixelFromScreen();
1163  // keep device pixel ratio up to date on screen or resolution change
1164  if ( window()->windowHandle() )
1165  {
1166  connect( window()->windowHandle(), &QWindow::screenChanged, this, [ = ]( QScreen * )
1167  {
1168  disconnect( mScreenDpiChangedConnection );
1169  mScreenDpiChangedConnection = connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, &QgsLayoutView::updateDevicePixelFromScreen );
1170  updateDevicePixelFromScreen();
1171  } );
1172 
1173  mScreenDpiChangedConnection = connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, &QgsLayoutView::updateDevicePixelFromScreen );
1174  }
1175 }
1176 
1177 void QgsLayoutView::invalidateCachedRenders()
1178 {
1179  if ( !currentLayout() )
1180  return;
1181 
1182  //redraw cached map items
1183  QList< QgsLayoutItem *> items;
1184  currentLayout()->layoutItems( items );
1185 
1186  for ( QgsLayoutItem *item : std::as_const( items ) )
1187  {
1188  item->invalidateCache();
1189  }
1190 }
1191 
1192 void QgsLayoutView::updateDevicePixelFromScreen()
1193 {
1194  if ( window()->windowHandle() )
1195  mScreenDpi = window()->windowHandle()->screen()->physicalDotsPerInch();
1196 }
1197 
1199 {
1200  if ( mHorizontalRuler )
1201  {
1202  mHorizontalRuler->setSceneTransform( viewportTransform() );
1203  }
1204  if ( mVerticalRuler )
1205  {
1206  mVerticalRuler->setSceneTransform( viewportTransform() );
1207  }
1208 
1209  // determine page at center of view
1210  QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1211  QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
1212  QPointF centerVisible = visibleRect.center();
1213 
1214  if ( currentLayout() && currentLayout()->pageCollection() )
1215  {
1216  int newPage = currentLayout()->pageCollection()->pageNumberForPoint( centerVisible );
1217  if ( newPage != mCurrentPage )
1218  {
1219  mCurrentPage = newPage;
1220  emit pageChanged( mCurrentPage );
1221  }
1222  }
1223 }
1224 
1225 void QgsLayoutView::pushStatusMessage( const QString &message )
1226 {
1227  emit statusMessage( message );
1228 }
1229 
1230 void QgsLayoutView::wheelZoom( QWheelEvent *event )
1231 {
1232  //get mouse wheel zoom behavior settings
1233  QgsSettings settings;
1234  double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
1235 
1236  // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
1237  zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
1238 
1239  if ( event->modifiers() & Qt::ControlModifier )
1240  {
1241  //holding ctrl while wheel zooming results in a finer zoom
1242  zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1243  }
1244 
1245  //calculate zoom scale factor
1246  bool zoomIn = event->angleDelta().y() > 0;
1247  double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
1248 
1249  //get current visible part of scene
1250  QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1251  QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
1252 
1253  //transform the mouse pos to scene coordinates
1254 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1255  QPointF scenePoint = mapToScene( event->pos() );
1256 #else
1257  QPointF scenePoint = mapToScene( event->position().x(), event->position().y() );
1258 #endif
1259 
1260  //adjust view center
1261  QgsPointXY oldCenter( visibleRect.center() );
1262  QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ),
1263  scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
1264  centerOn( newCenter.x(), newCenter.y() );
1265 
1266  //zoom layout
1267  if ( zoomIn )
1268  {
1269  scaleSafe( zoomFactor );
1270  }
1271  else
1272  {
1273  scaleSafe( 1 / zoomFactor );
1274  }
1275 }
1276 
1277 QGraphicsLineItem *QgsLayoutView::createSnapLine() const
1278 {
1279  std::unique_ptr< QGraphicsLineItem> item( new QGraphicsLineItem( nullptr ) );
1280  QPen pen = QPen( QColor( Qt::blue ) );
1281  pen.setStyle( Qt::DotLine );
1282  pen.setWidthF( 0.0 );
1283  item->setPen( pen );
1284  item->setZValue( QgsLayout::ZSmartGuide );
1285  return item.release();
1286 }
1287 
1288 //
1289 // QgsLayoutViewSnapMarker
1290 //
1291 
1293 QgsLayoutViewSnapMarker::QgsLayoutViewSnapMarker()
1294  : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
1295 {
1296  QFont f;
1297  QFontMetrics fm( f );
1298  mSize = fm.horizontalAdvance( 'X' );
1299  setPen( QPen( Qt::transparent, mSize ) );
1300 
1301  setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
1302  setZValue( QgsLayout::ZSnapIndicator );
1303 }
1304 
1305 void QgsLayoutViewSnapMarker::paint( QPainter *p, const QStyleOptionGraphicsItem *, QWidget * )
1306 {
1307  QPen pen( QColor( 255, 0, 0 ) );
1308  pen.setWidth( 0 );
1309  p->setPen( pen );
1310  p->setBrush( Qt::NoBrush );
1311 
1312  double halfSize = mSize / 2.0;
1313  p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
1314  p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );
1315 }
1316 
QgsLayoutView::visiblePageNumbers
QList< int > visiblePageNumbers() const
Returns a list of page numbers for pages which are currently visible in the view.
Definition: qgslayoutview.cpp:274
QgsLayout::deselectAll
void deselectAll()
Clears any selected items in the layout.
Definition: qgslayout.cpp:169
QgsLayoutView::hasItemsInClipboard
bool hasItemsInClipboard() const
Returns true if the current clipboard contains layout items.
Definition: qgslayoutview.cpp:461
qgslayoutviewtool.h
qgslayoutitemgroup.h
QgsLayoutView::setCurrentLayout
void setCurrentLayout(QgsLayout *layout)
Sets the current layout to edit in the view.
Definition: qgslayoutview.cpp:88
QgsLayoutView::zoomFull
void zoomFull()
Zooms the view to the full extent of the layout.
Definition: qgslayoutview.cpp:538
QgsLayoutView::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: qgslayoutview.cpp:1061
qgslayoutundostack.h
QgsLayoutItemPage
Item representing the paper in a layout.
Definition: qgslayoutitempage.h:58
QgsLayoutView::setPreviewModeEnabled
void setPreviewModeEnabled(bool enabled)
Sets whether a preview effect should be used to alter the view's appearance.
Definition: qgslayoutview.cpp:170
QgsLayoutView::setMenuProvider
void setMenuProvider(QgsLayoutViewMenuProvider *provider)
Sets a provider for context menus.
Definition: qgslayoutview.cpp:253
selectNextByZOrder
void selectNextByZOrder(QgsLayout *layout, bool above)
Definition: qgslayoutview.cpp:669
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsLayoutView::menuProvider
QgsLayoutViewMenuProvider * menuProvider() const
Returns the provider for context menus.
Definition: qgslayoutview.cpp:258
QgsLayoutView::setSectionLabel
void setSectionLabel(const QString &label)
Sets a section label, to display above the first page shown in the view.
Definition: qgslayoutview.cpp:523
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
qgsrectangle.h
QgsUnitTypes::LayoutPixels
@ LayoutPixels
Pixels.
Definition: qgsunittypes.h:190
QgsLayoutViewToolTemporaryKeyZoom
Layout view tool for temporarily zooming a layout while a key is depressed.
Definition: qgslayoutviewtooltemporarykeyzoom.h:30
QgsLayout::setSelectedItem
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:159
QgsLayoutView::cursorPosChanged
void cursorPosChanged(QPointF layoutPoint)
Emitted when the mouse cursor coordinates change within the view.
QgsLayout::selectedLayoutItems
QList< QgsLayoutItem * > selectedLayoutItems(bool includeLockedItems=true)
Returns list of selected layout items.
Definition: qgslayout.cpp:142
QgsLayout::layoutItems
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:122
QgsLayout::raiseItem
bool raiseItem(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up the z-order.
Definition: qgslayout.cpp:186
QgsLayoutViewTool::FlagSnaps
@ FlagSnaps
Tool utilizes snapped coordinates.
Definition: qgslayoutviewtool.h:65
QgsLayoutViewToolTemporaryKeyPan
Layout view tool for temporarily panning a layout while a key is depressed.
Definition: qgslayoutviewtooltemporarykeypan.h:28
QgsLayoutView::ungroupSelectedItems
void ungroupSelectedItems()
Ungroups all selected items.
Definition: qgslayoutview.cpp:901
QgsLayoutMeasurement::length
double length() const
Returns the length of the measurement.
Definition: qgslayoutmeasurement.h:48
QgsLayoutView::invertSelection
void invertSelection()
Inverts the current selection, selecting deselected items and deselecting and selected items.
Definition: qgslayoutview.cpp:635
QgsLayoutView::paintEvent
void paintEvent(QPaintEvent *event) override
Definition: qgslayoutview.cpp:1145
qgsreadwritecontext.h
QgsRectangle::center
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
QgsLayoutView::keyReleaseEvent
void keyReleaseEvent(QKeyEvent *event) override
Definition: qgslayoutview.cpp:1110
QgsLayoutView::pasteItems
QList< QgsLayoutItem * > pasteItems(PasteMode mode)
Pastes items from clipboard, using the specified mode.
Definition: qgslayoutview.cpp:397
QgsLayoutView::PasteMode
PasteMode
Paste modes.
Definition: qgslayoutview.h:76
QgsLayoutAligner::alignItems
static void alignItems(QgsLayout *layout, const QList< QgsLayoutItem * > &items, Alignment alignment)
Aligns a set of items from a layout in place.
Definition: qgslayoutaligner.cpp:22
QgsLayoutUndoStack::endMacro
void endMacro()
Ends a macro command.
Definition: qgslayoutundostack.cpp:36
QgsLayoutView::setVerticalRuler
void setVerticalRuler(QgsLayoutRuler *ruler)
Sets a vertical ruler to synchronize with the view state.
Definition: qgslayoutview.cpp:239
QgsLayoutItem::UndoIncrementalMove
@ UndoIncrementalMove
Layout item incremental movement, e.g. as a result of a keypress.
Definition: qgslayoutitem.h:218
QgsLayoutView::PasteModeCenter
@ PasteModeCenter
Paste items in center of view.
Definition: qgslayoutview.h:79
QgsLayoutView::ClipboardOperation
ClipboardOperation
Clipboard operations.
Definition: qgslayoutview.h:69
qgslayoutview.h
qgslayoutmultiframe.h
QgsLayout::ungroupItems
QList< QgsLayoutItem * > ungroupItems(QgsLayoutItemGroup *group)
Ungroups items by removing them from an item group and removing the group from the layout.
Definition: qgslayout.cpp:764
qgslayoutviewtooltemporarymousepan.h
QgsLayoutAligner::distributeItems
static void distributeItems(QgsLayout *layout, const QList< QgsLayoutItem * > &items, Distribution distribution)
Distributes a set of items from a layout in place.
Definition: qgslayoutaligner.cpp:95
QgsLayoutView::visiblePages
QList< QgsLayoutItemPage * > visiblePages() const
Returns a list of page items which are currently visible in the view.
Definition: qgslayoutview.cpp:263
QgsLayoutView::deselectAll
void deselectAll()
Deselects all items in the view.
Definition: qgslayoutview.cpp:625
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsLayoutView::unsetTool
void unsetTool(QgsLayoutViewTool *tool)
Unsets the current view tool, if it matches the specified tool.
Definition: qgslayoutview.cpp:160
QgsLayoutView::selectNextItemBelow
void selectNextItemBelow()
Selects the next item below the existing selection, by item z order.
Definition: qgslayoutview.cpp:707
qgslayoutitemundocommand.h
QgsLayoutView::selectAll
void selectAll()
Selects all items in the view.
Definition: qgslayoutview.cpp:593
qgslayoutviewmouseevent.h
QgsLayoutView::zoomWidth
void zoomWidth()
Zooms the view to the full width of the layout.
Definition: qgslayoutview.cpp:548
QgsLayout::pageCollection
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
Definition: qgslayout.cpp:459
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsLayoutView::setHorizontalRuler
void setHorizontalRuler(QgsLayoutRuler *ruler)
Sets a horizontal ruler to synchronize with the view state.
Definition: qgslayoutview.cpp:225
QgsLayout::ZSmartGuide
@ ZSmartGuide
Z-value for smart (item bounds based) guides.
Definition: qgslayout.h:63
QgsLayoutView::showEvent
void showEvent(QShowEvent *event) override
Definition: qgslayoutview.cpp:1158
QgsLayoutViewToolTemporaryMousePan
Layout view tool for temporarily panning a layout while a mouse button is depressed.
Definition: qgslayoutviewtooltemporarymousepan.h:28
QgsLayoutView::moveSelectedItemsToTop
void moveSelectedItemsToTop()
Raises the selected items to the top of the z-order.
Definition: qgslayoutview.cpp:758
QgsLayoutView::deleteItems
void deleteItems(const QList< QgsLayoutItem * > &items)
Delete the specified items.
Definition: qgslayoutview.cpp:858
QgsLayoutItem::setSelected
virtual void setSelected(bool selected)
Sets whether the item should be selected.
Definition: qgslayoutitem.cpp:160
QgsLayoutView::deltaForKeyEvent
QPointF deltaForKeyEvent(QKeyEvent *event)
Returns the delta (in layout coordinates) by which to move items for the given key event.
Definition: qgslayoutview.cpp:474
QgsLayoutItemRegistry::LayoutGroup
@ LayoutGroup
Grouped item.
Definition: qgslayoutitemregistry.h:339
qgslayoutframe.h
QgsLayoutView::alignSelectedItems
void alignSelectedItems(QgsLayoutAligner::Alignment alignment)
Aligns all selected items using the specified alignment.
Definition: qgslayoutview.cpp:285
qgsapplication.h
QgsLayout::addItemsFromXml
QList< QgsLayoutItem * > addItemsFromXml(const QDomElement &parentElement, const QDomDocument &document, const QgsReadWriteContext &context, QPointF *position=nullptr, bool pasteInPlace=false)
Add items from an XML representation to the layout.
Definition: qgslayout.cpp:989
QgsLayoutView::scrollContentsBy
void scrollContentsBy(int dx, int dy) override
Definition: qgslayoutview.cpp:1131
QgsLayoutView::lockSelectedItems
void lockSelectedItems()
Locks any selected items, preventing them from being interacted with by mouse interactions.
Definition: qgslayoutview.cpp:804
QgsLayoutView::emitZoomLevelChanged
void emitZoomLevelChanged()
Emits the zoomLevelChanged() signal.
Definition: qgslayoutview.cpp:588
QgsLayoutPageCollection::pageNumberForPoint
int pageNumberForPoint(QPointF point) const
Returns the page number corresponding to a point in the layout (in layout units).
Definition: qgslayoutpagecollection.cpp:167
QgsPreviewEffect::PreviewMode
PreviewMode
Definition: qgsprevieweffect.h:49
QgsLayout::moveItemToTop
bool moveItemToTop(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up to the top of the z-order.
Definition: qgslayout.cpp:212
QgsLayoutView::zoomActual
void zoomActual()
Zooms to the actual size of the layout.
Definition: qgslayoutview.cpp:583
QgsLayout::moveItemToBottom
bool moveItemToBottom(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down to the bottom of the z-order.
Definition: qgslayout.cpp:225
QgsLayoutView::previewModeEnabled
bool previewModeEnabled() const
Returns true if a preview effect is being used to alter the view's appearance.
Definition: qgslayoutview.cpp:175
QgsLayoutFrame
Base class for frame items, which form a layout multiframe item.
Definition: qgslayoutframe.h:31
QgsLayoutView::~QgsLayoutView
~QgsLayoutView() override
Definition: qgslayoutview.cpp:73
QgsLayoutView::setPreviewMode
void setPreviewMode(QgsPreviewEffect::PreviewMode mode)
Sets the preview mode which should be used to modify the view's appearance.
Definition: qgslayoutview.cpp:180
QgsLayoutView::zoomIn
void zoomIn()
Zooms in to the view by a preset amount.
Definition: qgslayoutview.cpp:573
QgsLayoutRuler
A custom ruler widget for use with QgsLayoutView, displaying the current zoom and position of the vis...
Definition: qgslayoutruler.h:38
QgsLayoutPageCollection::visiblePageNumbers
QList< int > visiblePageNumbers(const QRectF &region) const
Returns a list of the page numbers which are visible within the specified region (in layout coordinat...
Definition: qgslayoutpagecollection.cpp:499
MIN_VIEW_SCALE
#define MIN_VIEW_SCALE
Definition: qgslayoutview.cpp:47
QgsLayoutView::zoomOut
void zoomOut()
Zooms out of the view by a preset amount.
Definition: qgslayoutview.cpp:578
QgsLayoutView::deleteSelectedItems
void deleteSelectedItems()
Deletes all selected items.
Definition: qgslayoutview.cpp:850
qgslayoutviewtooltemporarykeypan.h
QgsLayoutItem::setLocked
void setLocked(bool locked)
Sets whether the item is locked, preventing mouse interactions with the item.
Definition: qgslayoutitem.cpp:200
QgsLayoutView::toolSet
void toolSet(QgsLayoutViewTool *tool)
Emitted when the current tool is changed.
QgsLayoutView::raiseSelectedItems
void raiseSelectedItems()
Raises the selected items up the z-order.
Definition: qgslayoutview.cpp:712
QgsLayoutPageCollection::changed
void changed()
Emitted when pages are added or removed from the collection.
qgslayoutruler.h
QgsLayoutView::moveSelectedItemsToBottom
void moveSelectedItemsToBottom()
Lowers the selected items to the bottom of the z-order.
Definition: qgslayoutview.cpp:781
QgsLayoutRuler::setLayoutView
void setLayoutView(QgsLayoutView *view)
Sets the current layout view to synchronize the ruler with.
Definition: qgslayoutruler.cpp:563
QgsLayoutView::setPaintingEnabled
void setPaintingEnabled(bool enabled)
Sets whether widget repainting should be allowed for the view.
Definition: qgslayoutview.cpp:516
QgsLayoutView::wheelEvent
void wheelEvent(QWheelEvent *event) override
Definition: qgslayoutview.cpp:1044
QgsProject::setDirty
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:576
QgsLayoutViewTool::itemFocused
void itemFocused(QgsLayoutItem *item)
Emitted when an item is "focused" by the tool, i.e.
QgsLayoutView::setTool
void setTool(QgsLayoutViewTool *tool)
Sets the tool currently being used in the view.
Definition: qgslayoutview.cpp:134
QgsLayoutViewMenuProvider
Interface for a QgsLayoutView context menu.
Definition: qgslayoutview.h:604
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
QgsLayoutView::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *e) override
Definition: qgslayoutview.cpp:1137
QgsLayoutView::tool
QgsLayoutViewTool tool
Definition: qgslayoutview.h:64
qgslayout.h
QgsLayoutView::mousePressEvent
void mousePressEvent(QMouseEvent *event) override
Definition: qgslayoutview.cpp:930
QgsLayoutView::lowerSelectedItems
void lowerSelectedItems()
Lowers the selected items down the z-order.
Definition: qgslayoutview.cpp:735
QgsLayoutItemGroup
A container for grouping several QgsLayoutItems.
Definition: qgslayoutitemgroup.h:28
QgsLayoutView::PasteModeInPlace
@ PasteModeInPlace
Paste items in place.
Definition: qgslayoutview.h:80
QgsLayoutView::previewMode
QgsPreviewEffect::PreviewMode previewMode() const
Returns the preview mode which may be used to modify the view's appearance.
Definition: qgslayoutview.cpp:185
QgsLayoutView::currentLayout
QgsLayout currentLayout
Definition: qgslayoutview.h:63
QgsLayoutUndoStack::beginMacro
void beginMacro(const QString &commandText)
Starts a macro command, with the given descriptive commandText.
Definition: qgslayoutundostack.cpp:30
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsLayoutPageCollection::visiblePages
QList< QgsLayoutItemPage * > visiblePages(const QRectF &region) const
Returns a list of the pages which are visible within the specified region (in layout coordinates).
Definition: qgslayoutpagecollection.cpp:487
QgsLayoutAligner::Alignment
Alignment
Alignment options.
Definition: qgslayoutaligner.h:42
QgsLayout::groupItems
QgsLayoutItemGroup * groupItems(const QList< QgsLayoutItem * > &items)
Creates a new group from a list of layout items and adds the group to the layout.
Definition: qgslayout.cpp:738
QgsLayoutView::viewChanged
void viewChanged()
Updates associated rulers and other widgets after view extent or zoom has changed.
Definition: qgslayoutview.cpp:1198
QgsLayoutAligner::Distribution
Distribution
Distribution options.
Definition: qgslayoutaligner.h:53
QgsLayout::lowerItem
bool lowerItem(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down the z-order.
Definition: qgslayout.cpp:199
QgsLayoutView::ClipboardCut
@ ClipboardCut
Cut items.
Definition: qgslayoutview.h:71
QgsLayoutView::copySelectedItems
void copySelectedItems(ClipboardOperation operation)
Cuts or copies the selected items, respecting the specified operation.
Definition: qgslayoutview.cpp:312
QgsLayoutView::distributeSelectedItems
void distributeSelectedItems(QgsLayoutAligner::Distribution distribution)
Distributes all selected items using the specified distribution.
Definition: qgslayoutview.cpp:294
QgsLayoutUndoStack::endCommand
void endCommand()
Saves final state of an object and pushes the active command to the undo history.
Definition: qgslayoutundostack.cpp:53
QgsLayoutView::itemFocused
void itemFocused(QgsLayoutItem *item)
Emitted when an item is "focused" in the view, i.e.
QgsLayoutAligner::Resize
Resize
Resize options.
Definition: qgslayoutaligner.h:66
QgsLayoutView::willBeDeleted
void willBeDeleted()
Emitted in the destructor when the view is about to be deleted, but is still in a perfectly valid sta...
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
QgsLayoutView::zoomLevelChanged
void zoomLevelChanged()
Emitted whenever the zoom level of the view is changed.
QgsLayout::updateZValues
void updateZValues(bool addUndoCommands=true)
Resets the z-values of items based on their position in the internal z order list.
Definition: qgslayout.cpp:919
QgsLayout::selectedItemChanged
void selectedItemChanged(QgsLayoutItem *selected)
Emitted whenever the selected item changes.
QgsLayoutView::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: qgslayoutview.cpp:1124
QgsLayoutView::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event) override
Definition: qgslayoutview.cpp:985
QgsLayoutViewTool
Abstract base class for all layout view tools. Layout view tools are user interactive tools for manip...
Definition: qgslayoutviewtool.h:46
qgssettings.h
QgsLayoutUndoStack::beginCommand
void beginCommand(QgsLayoutUndoObjectInterface *object, const QString &commandText, int id=0)
Begins a new undo command for the specified object.
Definition: qgslayoutundostack.cpp:42
QgsLayout::ZSnapIndicator
@ ZSnapIndicator
Z-value for snapping indicator.
Definition: qgslayout.h:66
MAX_VIEW_SCALE
#define MAX_VIEW_SCALE
Definition: qgslayoutview.cpp:48
QgsLayoutView::setZoomLevel
void setZoomLevel(double level)
Sets the zoom level for the view, where a zoom level of 1.0 corresponds to 100%.
Definition: qgslayoutview.cpp:200
QgsLayoutView::copyItems
void copyItems(const QList< QgsLayoutItem * > &items, ClipboardOperation operation)
Cuts or copies the a list of items, respecting the specified operation.
Definition: qgslayoutview.cpp:317
qgslayoutpagecollection.h
QgsPreviewEffect::setMode
void setMode(PreviewMode mode)
Sets the mode for the preview effect, which controls how the effect modifies a widgets appearance.
Definition: qgsprevieweffect.cpp:30
QgsLayout::guides
QgsLayoutGuideCollection & guides()
Returns a reference to the layout's guide collection, which manages page snap guides.
Definition: qgslayout.cpp:385
QgsLayoutView::QgsLayoutView
QgsLayoutView(QWidget *parent=nullptr)
Constructor for QgsLayoutView.
Definition: qgslayoutview.cpp:50
QgsPreviewEffect
A graphics effect which can be applied to a widget to simulate various printing and color blindness m...
Definition: qgsprevieweffect.h:31
QgsUnitTypes::LayoutMillimeters
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:183
qgslayoutmousehandles.h
QgsLayoutView::pushStatusMessage
void pushStatusMessage(const QString &message)
Pushes a new status bar message to the view.
Definition: qgslayoutview.cpp:1225
QgsLayoutAligner::resizeItems
static void resizeItems(QgsLayout *layout, const QList< QgsLayoutItem * > &items, Resize resize)
Resizes a set of items from a layout in place.
Definition: qgslayoutaligner.cpp:195
QgsLayout::project
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:132
QgsLayoutView::unlockAllItems
void unlockAllItems()
Unlocks all locked items in the layout.
Definition: qgslayoutview.cpp:820
QgsLayoutView::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *event) override
Definition: qgslayoutview.cpp:969
QgsLayout::removeLayoutItem
void removeLayoutItem(QgsLayoutItem *item)
Removes an item from the layout.
Definition: qgslayout.cpp:556
QgsLayoutViewTool::activate
virtual void activate()
Called when tool is set as the currently active layout tool.
Definition: qgslayoutviewtool.cpp:120
QgsLayoutRuler::setSceneTransform
void setSceneTransform(const QTransform &transform)
Sets the current scene transform.
Definition: qgslayoutruler.cpp:557
QgsLayoutViewMouseEvent
A QgsLayoutViewMouseEvent is the result of a user interaction with the mouse on a QgsLayoutView.
Definition: qgslayoutviewmouseevent.h:35
QgsLayoutView::resizeSelectedItems
void resizeSelectedItems(QgsLayoutAligner::Resize resize)
Resizes all selected items using the specified resize mode.
Definition: qgslayoutview.cpp:303
QgsLayoutView::PasteModeCursor
@ PasteModeCursor
Paste items at cursor position.
Definition: qgslayoutview.h:78
qgslayoutmodel.h
QgsLayoutView::layoutSet
void layoutSet(QgsLayout *layout)
Emitted when a layout is set for the view.
qgslayoutreportsectionlabel.h
qgsproject.h
QgsLayout::itemsModel
QgsLayoutModel * itemsModel()
Returns the items model attached to the layout.
Definition: qgslayout.cpp:137
QgsLayoutItem::isLocked
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
Definition: qgslayoutitem.h:402
QgsLayout::convertFromLayoutUnits
QgsLayoutMeasurement convertFromLayoutUnits(double length, QgsUnitTypes::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
Definition: qgslayout.cpp:344
QgsLayoutView::mouseDoubleClickEvent
void mouseDoubleClickEvent(QMouseEvent *event) override
Definition: qgslayoutview.cpp:1028
qgslayoutviewtooltemporarykeyzoom.h
QgsLayoutView::pageChanged
void pageChanged(int page)
Emitted when the page visible in the view is changed.
QgsLayoutView::groupSelectedItems
void groupSelectedItems()
Groups all selected items.
Definition: qgslayoutview.cpp:876
QgsPreviewEffect::mode
PreviewMode mode() const
Returns the mode used for the preview effect.
Definition: qgsprevieweffect.h:74
QgsLayoutView::selectNextItemAbove
void selectNextItemAbove()
Selects the next item above the existing selection, by item z order.
Definition: qgslayoutview.cpp:702
QgsLayoutView::scaleSafe
void scaleSafe(double scale)
Scales the view in a safe way, by limiting the acceptable range of the scale applied.
Definition: qgslayoutview.cpp:190
QgsLayoutView::statusMessage
void statusMessage(const QString &message)
Emitted when the view has a message for display in a parent window's status bar.
QgsLayout::undoStack
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout and it's ...
Definition: qgslayout.cpp:686