QGIS API Documentation 3.41.0-Master (3440c17df1d)
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(),
560 verticalCenter - tinyHeight,
561 scene()->sceneRect().width(),
562 tinyHeight * 2 );
563
564 fitInView( targetRect, Qt::KeepAspectRatio );
565 emit zoomLevelChanged();
566 viewChanged();
567}
568
570{
571 scaleSafe( 2 );
572}
573
575{
576 scaleSafe( 0.5 );
577}
578
580{
581 setZoomLevel( 1.0 );
582}
583
588
590{
591 if ( !currentLayout() )
592 {
593 return;
594 }
595
596 //select all items in layout
597 QgsLayoutItem *focusedItem = nullptr;
598 const QList<QGraphicsItem *> itemList = currentLayout()->items();
599 for ( QGraphicsItem *graphicsItem : itemList )
600 {
601 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
602 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
603 if ( item && !paperItem )
604 {
605 if ( !item->isLocked() )
606 {
607 item->setSelected( true );
608 if ( !focusedItem )
609 focusedItem = item;
610 }
611 else
612 {
613 //deselect all locked items
614 item->setSelected( false );
615 }
616 }
617 }
618 emit itemFocused( focusedItem );
619}
620
622{
623 if ( !currentLayout() )
624 {
625 return;
626 }
627
629}
630
632{
633 if ( !currentLayout() )
634 {
635 return;
636 }
637
638 QgsLayoutItem *focusedItem = nullptr;
639 //check all items in layout
640 const QList<QGraphicsItem *> itemList = currentLayout()->items();
641 for ( QGraphicsItem *graphicsItem : itemList )
642 {
643 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
644 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
645 if ( item && !paperItem )
646 {
647 //flip selected state for items (and deselect any locked items)
648 if ( item->isSelected() || item->isLocked() )
649 {
650 item->setSelected( false );
651 }
652 else
653 {
654 item->setSelected( true );
655 if ( !focusedItem )
656 focusedItem = item;
657 }
658 }
659 }
660 if ( focusedItem )
661 emit itemFocused( focusedItem );
662}
663
664
665void selectNextByZOrder( QgsLayout *layout, bool above )
666{
667 if ( !layout )
668 return;
669
670 QgsLayoutItem *previousSelectedItem = nullptr;
671 const QList<QgsLayoutItem *> selectedItems = layout->selectedLayoutItems();
672 if ( !selectedItems.isEmpty() )
673 {
674 previousSelectedItem = selectedItems.at( 0 );
675 }
676
677 if ( !previousSelectedItem )
678 {
679 return;
680 }
681
682 //select item with target z value
683 QgsLayoutItem *selectedItem = nullptr;
684 if ( !above )
685 selectedItem = layout->itemsModel()->findItemBelow( previousSelectedItem );
686 else
687 selectedItem = layout->itemsModel()->findItemAbove( previousSelectedItem );
688
689 if ( !selectedItem )
690 {
691 return;
692 }
693
694 //OK, found a good target item
695 layout->setSelectedItem( selectedItem );
696}
697
702
707
709{
710 if ( !currentLayout() )
711 return;
712
713 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
714 bool itemsRaised = false;
715 for ( QgsLayoutItem *item : selectedItems )
716 {
717 itemsRaised = itemsRaised | currentLayout()->raiseItem( item, true );
718 }
719
720 if ( !itemsRaised )
721 {
722 //no change
723 return;
724 }
725
726 //update all positions
728 currentLayout()->update();
729}
730
732{
733 if ( !currentLayout() )
734 return;
735
736 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
737 bool itemsLowered = false;
738 for ( QgsLayoutItem *item : selectedItems )
739 {
740 itemsLowered = itemsLowered | currentLayout()->lowerItem( item, true );
741 }
742
743 if ( !itemsLowered )
744 {
745 //no change
746 return;
747 }
748
749 //update all positions
751 currentLayout()->update();
752}
753
755{
756 if ( !currentLayout() )
757 return;
758
759 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
760 bool itemsRaised = false;
761 for ( QgsLayoutItem *item : selectedItems )
762 {
763 itemsRaised = itemsRaised | currentLayout()->moveItemToTop( item, true );
764 }
765
766 if ( !itemsRaised )
767 {
768 //no change
769 return;
770 }
771
772 //update all positions
774 currentLayout()->update();
775}
776
778{
779 if ( !currentLayout() )
780 return;
781
782 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
783 bool itemsLowered = false;
784 for ( QgsLayoutItem *item : selectedItems )
785 {
786 itemsLowered = itemsLowered | currentLayout()->moveItemToBottom( item, true );
787 }
788
789 if ( !itemsLowered )
790 {
791 //no change
792 return;
793 }
794
795 //update all positions
797 currentLayout()->update();
798}
799
801{
802 if ( !currentLayout() )
803 return;
804
805 currentLayout()->undoStack()->beginMacro( tr( "Lock Items" ) );
806 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
807 for ( QgsLayoutItem *item : selectionList )
808 {
809 item->setLocked( true );
810 }
811
814}
815
817{
818 if ( !currentLayout() )
819 return;
820
821 //unlock all items in layout
822 currentLayout()->undoStack()->beginMacro( tr( "Unlock Items" ) );
823
824 //first, clear the selection
826
827 QgsLayoutItem *focusItem = nullptr;
828
829 const QList<QGraphicsItem *> itemList = currentLayout()->items();
830 for ( QGraphicsItem *graphicItem : itemList )
831 {
832 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicItem );
833 if ( item && item->isLocked() )
834 {
835 focusItem = item;
836 item->setLocked( false );
837 //select unlocked items, same behavior as illustrator
838 item->setSelected( true );
839 }
840 }
842
843 emit itemFocused( focusItem );
844}
845
847{
848 if ( !currentLayout() )
849 return;
850
851 deleteItems( currentLayout()->selectedLayoutItems() );
852}
853
854void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
855{
856 if ( !currentLayout() )
857 return;
858
859 if ( items.empty() )
860 return;
861
862 currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
863 //delete selected items
864 for ( QgsLayoutItem *item : items )
865 {
867 }
869 currentLayout()->project()->setDirty( true );
870}
871
873{
874 if ( !currentLayout() )
875 {
876 return;
877 }
878
879 //group selected items
880 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
881 QgsLayoutItemGroup *itemGroup = currentLayout()->groupItems( selectionList );
882
883 if ( !itemGroup )
884 {
885 //group could not be created
886 return;
887 }
888
889 for ( QgsLayoutItem *item : selectionList )
890 {
891 item->setSelected( false );
892 }
893
894 currentLayout()->setSelectedItem( itemGroup );
895}
896
898{
899 if ( !currentLayout() )
900 {
901 return;
902 }
903
904 QList< QgsLayoutItem * > ungroupedItems;
905 //hunt through selection for any groups, and ungroup them
906 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
907 for ( QgsLayoutItem *item : selectionList )
908 {
909 if ( item->type() == QgsLayoutItemRegistry::LayoutGroup )
910 {
911 QgsLayoutItemGroup *itemGroup = static_cast<QgsLayoutItemGroup *>( item );
912 ungroupedItems.append( currentLayout()->ungroupItems( itemGroup ) );
913 }
914 }
915
916 if ( !ungroupedItems.empty() )
917 {
918 for ( QgsLayoutItem *item : std::as_const( ungroupedItems ) )
919 {
920 item->setSelected( true );
921 }
922 emit itemFocused( ungroupedItems.at( 0 ) );
923 }
924}
925
926void QgsLayoutView::mousePressEvent( QMouseEvent *event )
927{
928 if ( !currentLayout() )
929 return;
930
931 if ( mSnapMarker )
932 mSnapMarker->setVisible( false );
933
934 if ( mTool )
935 {
936 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
937 mTool->layoutPressEvent( me.get() );
938 event->setAccepted( me->isAccepted() );
939 }
940
941 if ( !mTool || !event->isAccepted() )
942 {
943 if ( event->button() == Qt::MiddleButton )
944 {
945 // Pan layout with middle mouse button
946 setTool( mMidMouseButtonPanTool );
947 event->accept();
948 }
949 else if ( event->button() == Qt::RightButton && mMenuProvider )
950 {
951 QMenu *menu = mMenuProvider->createContextMenu( this, currentLayout(), mapToScene( event->pos() ) );
952 if ( menu )
953 {
954 menu->exec( event->globalPos() );
955 delete menu;
956 }
957 }
958 else
959 {
960 QGraphicsView::mousePressEvent( event );
961 }
962 }
963}
964
965void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
966{
967 if ( !currentLayout() )
968 return;
969
970 if ( mTool )
971 {
972 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
973 mTool->layoutReleaseEvent( me.get() );
974 event->setAccepted( me->isAccepted() );
975 }
976
977 if ( !mTool || !event->isAccepted() )
978 QGraphicsView::mouseReleaseEvent( event );
979}
980
981void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )
982{
983 if ( !currentLayout() )
984 return;
985
986 mMouseCurrentXY = event->pos();
987
988 QPointF cursorPos = mapToScene( mMouseCurrentXY );
989 if ( mTool )
990 {
991 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, false ) );
992 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
993 {
994 me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() );
995 }
996 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
997 {
998 //draw snapping point indicator
999 if ( me->isSnapped() )
1000 {
1001 cursorPos = me->snappedPoint();
1002 if ( mSnapMarker )
1003 {
1004 mSnapMarker->setPos( me->snappedPoint() );
1005 mSnapMarker->setVisible( true );
1006 }
1007 }
1008 else if ( mSnapMarker )
1009 {
1010 mSnapMarker->setVisible( false );
1011 }
1012 }
1013 mTool->layoutMoveEvent( me.get() );
1014 event->setAccepted( me->isAccepted() );
1015 }
1016
1017 //update cursor position in status bar
1018 emit cursorPosChanged( cursorPos );
1019
1020 if ( !mTool || !event->isAccepted() )
1021 QGraphicsView::mouseMoveEvent( event );
1022}
1023
1025{
1026 if ( !currentLayout() )
1027 return;
1028
1029 if ( mTool )
1030 {
1031 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
1032 mTool->layoutDoubleClickEvent( me.get() );
1033 event->setAccepted( me->isAccepted() );
1034 }
1035
1036 if ( !mTool || !event->isAccepted() )
1037 QGraphicsView::mouseDoubleClickEvent( event );
1038}
1039
1040void QgsLayoutView::wheelEvent( QWheelEvent *event )
1041{
1042 if ( !currentLayout() )
1043 return;
1044
1045 if ( mTool )
1046 {
1047 mTool->wheelEvent( event );
1048 }
1049
1050 if ( !mTool || !event->isAccepted() )
1051 {
1052 event->accept();
1053 wheelZoom( event );
1054 }
1055}
1056
1057void QgsLayoutView::keyPressEvent( QKeyEvent *event )
1058{
1059 if ( !currentLayout() )
1060 return;
1061
1062 if ( mTool )
1063 {
1064 mTool->keyPressEvent( event );
1065 }
1066
1067 if ( mTool && event->isAccepted() )
1068 return;
1069
1070 if ( event->key() == Qt::Key_Space && ! event->isAutoRepeat() )
1071 {
1072 if ( !( event->modifiers() & Qt::ControlModifier ) )
1073 {
1074 // Pan layout with space bar
1075 setTool( mSpacePanTool );
1076 }
1077 else
1078 {
1079 //ctrl+space pressed, so switch to temporary keyboard based zoom tool
1080 setTool( mSpaceZoomTool );
1081 }
1082 event->accept();
1083 }
1084 else if ( event->key() == Qt::Key_Left
1085 || event->key() == Qt::Key_Right
1086 || event->key() == Qt::Key_Up
1087 || event->key() == Qt::Key_Down )
1088 {
1089 QgsLayout *l = currentLayout();
1090 const QList<QgsLayoutItem *> layoutItemList = l->selectedLayoutItems();
1091
1092 QPointF delta = deltaForKeyEvent( event );
1093
1094 l->undoStack()->beginMacro( tr( "Move Item" ) );
1095 for ( QgsLayoutItem *item : layoutItemList )
1096 {
1097 l->undoStack()->beginCommand( item, tr( "Move Item" ), QgsLayoutItem::UndoIncrementalMove );
1098 item->attemptMoveBy( delta.x(), delta.y() );
1099 l->undoStack()->endCommand();
1100 }
1101 l->undoStack()->endMacro();
1102 event->accept();
1103 }
1104}
1105
1106void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
1107{
1108 if ( !currentLayout() )
1109 return;
1110
1111 if ( mTool )
1112 {
1113 mTool->keyReleaseEvent( event );
1114 }
1115
1116 if ( !mTool || !event->isAccepted() )
1117 QGraphicsView::keyReleaseEvent( event );
1118}
1119
1120void QgsLayoutView::resizeEvent( QResizeEvent *event )
1121{
1122 QGraphicsView::resizeEvent( event );
1123 emit zoomLevelChanged();
1124 viewChanged();
1125}
1126
1128{
1129 QGraphicsView::scrollContentsBy( dx, dy );
1130 viewChanged();
1131}
1132
1133void QgsLayoutView::dragEnterEvent( QDragEnterEvent *e )
1134{
1135 // By default graphics view delegates the drag events to graphics items.
1136 // But we do not want that and by ignoring the drag enter we let the
1137 // parent (e.g. QgsLayoutDesignerDialog) to handle drops of files.
1138 e->ignore();
1139}
1140
1141void QgsLayoutView::paintEvent( QPaintEvent *event )
1142{
1143 if ( mPaintingEnabled )
1144 {
1145 QGraphicsView::paintEvent( event );
1146 event->accept();
1147 }
1148 else
1149 {
1150 event->ignore();
1151 }
1152}
1153
1154void QgsLayoutView::invalidateCachedRenders()
1155{
1156 if ( !currentLayout() )
1157 return;
1158
1159 //redraw cached map items
1160 QList< QgsLayoutItem *> items;
1161 currentLayout()->layoutItems( items );
1162
1163 for ( QgsLayoutItem *item : std::as_const( items ) )
1164 {
1165 item->invalidateCache();
1166 }
1167}
1168
1170{
1171 if ( mHorizontalRuler )
1172 {
1173 mHorizontalRuler->setSceneTransform( viewportTransform() );
1174 }
1175 if ( mVerticalRuler )
1176 {
1177 mVerticalRuler->setSceneTransform( viewportTransform() );
1178 }
1179
1180 // determine page at center of view
1181 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1182 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
1183 QPointF centerVisible = visibleRect.center();
1184
1185 if ( currentLayout() && currentLayout()->pageCollection() )
1186 {
1187 int newPage = currentLayout()->pageCollection()->pageNumberForPoint( centerVisible );
1188 if ( newPage != mCurrentPage )
1189 {
1190 mCurrentPage = newPage;
1191 emit pageChanged( mCurrentPage );
1192 }
1193 }
1194}
1195
1196void QgsLayoutView::pushStatusMessage( const QString &message )
1197{
1198 emit statusMessage( message );
1199}
1200
1201void QgsLayoutView::wheelZoom( QWheelEvent *event )
1202{
1203 //get mouse wheel zoom behavior settings
1204 QgsSettings settings;
1205 double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
1206 bool reverseZoom = settings.value( QStringLiteral( "qgis/reverse_wheel_zoom" ), false ).toBool();
1207 bool zoomIn = reverseZoom ? event->angleDelta().y() < 0 : event->angleDelta().y() > 0;
1208
1209 // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
1210 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
1211
1212 if ( event->modifiers() & Qt::ControlModifier )
1213 {
1214 //holding ctrl while wheel zooming results in a finer zoom
1215 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1216 }
1217
1218 //calculate zoom scale factor
1219 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
1220
1221 //get current visible part of scene
1222 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1223 QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
1224
1225 //transform the mouse pos to scene coordinates
1226#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1227 QPointF scenePoint = mapToScene( event->pos() );
1228#else
1229 QPointF scenePoint = mapToScene( event->position().x(), event->position().y() );
1230#endif
1231
1232 //adjust view center
1233 QgsPointXY oldCenter( visibleRect.center() );
1234 QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ),
1235 scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
1236 centerOn( newCenter.x(), newCenter.y() );
1237
1238 //zoom layout
1239 if ( zoomIn )
1240 {
1241 scaleSafe( zoomFactor );
1242 }
1243 else
1244 {
1245 scaleSafe( 1 / zoomFactor );
1246 }
1247}
1248
1249QGraphicsLineItem *QgsLayoutView::createSnapLine() const
1250{
1251 std::unique_ptr< QGraphicsLineItem> item( new QGraphicsLineItem( nullptr ) );
1252 QPen pen = QPen( QColor( Qt::blue ) );
1253 pen.setStyle( Qt::DotLine );
1254 pen.setWidthF( 0.0 );
1255 item->setPen( pen );
1256 item->setZValue( QgsLayout::ZSmartGuide );
1257 return item.release();
1258}
1259
1260//
1261// QgsLayoutViewSnapMarker
1262//
1263
1265QgsLayoutViewSnapMarker::QgsLayoutViewSnapMarker()
1266 : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
1267{
1268 QFont f;
1269 QFontMetrics fm( f );
1270 mSize = fm.horizontalAdvance( 'X' );
1271 setPen( QPen( Qt::transparent, mSize ) );
1272
1273 setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
1274 setZValue( QgsLayout::ZSnapIndicator );
1275}
1276
1277void QgsLayoutViewSnapMarker::paint( QPainter *p, const QStyleOptionGraphicsItem *, QWidget * )
1278{
1279 QPen pen( QColor( 255, 0, 0 ) );
1280 pen.setWidth( 0 );
1281 p->setPen( pen );
1282 p->setBrush( Qt::NoBrush );
1283
1284 double halfSize = mSize / 2.0;
1285 p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
1286 p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );
1287}
1288
@ 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