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