QGIS API Documentation 3.43.0-Master (a6cade80589)
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 const QMimeData *mimeData = clipboard->mimeData();
402 if ( !mimeData )
403 return {};
404
405 if ( doc.setContent( mimeData->data( QStringLiteral( "text/xml" ) ) ) )
406 {
407 QDomElement docElem = doc.documentElement();
408 if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
409 {
410 QPointF pt;
411 switch ( mode )
412 {
413 case PasteModeCursor:
414 case PasteModeInPlace:
415 {
416 // place items at cursor position
417 pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
418 break;
419 }
420 case PasteModeCenter:
421 {
422 // place items in center of viewport
423 pt = mapToScene( viewport()->rect().center() );
424 break;
425 }
426 }
427 bool pasteInPlace = ( mode == PasteModeInPlace );
428 currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
429 currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
430 pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &pt, pasteInPlace );
433 }
434 }
435 return pastedItems;
436}
437
438QList<QgsLayoutItem *> QgsLayoutView::pasteItems( QPointF layoutPoint )
439{
440 if ( !currentLayout() )
441 return QList<QgsLayoutItem *>();
442
443 QList<QgsLayoutItem *> pastedItems;
444 QDomDocument doc;
445 QClipboard *clipboard = QApplication::clipboard();
446 const QMimeData *mimeData = clipboard->mimeData();
447 if ( !mimeData )
448 return {};
449
450 if ( doc.setContent( mimeData->data( QStringLiteral( "text/xml" ) ) ) )
451 {
452 QDomElement docElem = doc.documentElement();
453 if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
454 {
455 currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
456 currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
457 pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &layoutPoint, false );
460 }
461 }
462 return pastedItems;
463}
464
466{
467 QDomDocument doc;
468 QClipboard *clipboard = QApplication::clipboard();
469 const QMimeData *mimeData = clipboard->mimeData();
470 if ( !mimeData )
471 return false;
472
473 if ( doc.setContent( mimeData->data( QStringLiteral( "text/xml" ) ) ) )
474 {
475 QDomElement docElem = doc.documentElement();
476 if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
477 return true;
478 }
479 return false;
480}
481
482QPointF QgsLayoutView::deltaForKeyEvent( QKeyEvent *event )
483{
484 // increment used for cursor key item movement
485 double increment = 1.0;
486 if ( event->modifiers() & Qt::ShiftModifier )
487 {
488 //holding shift while pressing cursor keys results in a big step
489 increment = 10.0;
490 }
491 else if ( event->modifiers() & Qt::AltModifier )
492 {
493 //holding alt while pressing cursor keys results in a 1 pixel step
494 double viewScale = transform().m11();
495 if ( viewScale > 0 )
496 {
497 increment = 1 / viewScale;
498 }
499 }
500
501 double deltaX = 0;
502 double deltaY = 0;
503 switch ( event->key() )
504 {
505 case Qt::Key_Left:
506 deltaX = -increment;
507 break;
508 case Qt::Key_Right:
509 deltaX = increment;
510 break;
511 case Qt::Key_Up:
512 deltaY = -increment;
513 break;
514 case Qt::Key_Down:
515 deltaY = increment;
516 break;
517 default:
518 break;
519 }
520
521 return QPointF( deltaX, deltaY );
522}
523
525{
526 mPaintingEnabled = enabled;
527 if ( enabled )
528 update();
529}
530
531void QgsLayoutView::setSectionLabel( const QString &label )
532{
533 if ( !currentLayout() )
534 return;
535
536 if ( !mSectionLabel )
537 {
538 mSectionLabel = new QgsLayoutReportSectionLabel( currentLayout(), this );
539 currentLayout()->addItem( mSectionLabel );
540 mSectionLabel->setRect( 0, -200, 1000, 200 );
541 mSectionLabel->setZValue( -1 );
542 }
543 mSectionLabel->setLabel( label );
544}
545
547{
548 if ( !scene() )
549 return;
550
551 fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
552 viewChanged();
553 emit zoomLevelChanged();
554}
555
557{
558 if ( !scene() )
559 return;
560
561 //get current visible part of scene
562 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
563 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
564
565 double verticalCenter = ( visibleRect.top() + visibleRect.bottom() ) / 2.0;
566 // expand out visible rect to include left/right edges of scene
567 // centered on current visible vertical center
568 // note that we can't have a 0 height rect - fitInView doesn't handle that
569 // so we just set a very small height instead.
570 const double tinyHeight = 0.01;
571 QRectF targetRect( scene()->sceneRect().left(), verticalCenter - tinyHeight, scene()->sceneRect().width(), tinyHeight * 2 );
572
573 fitInView( targetRect, Qt::KeepAspectRatio );
574 emit zoomLevelChanged();
575 viewChanged();
576}
577
579{
580 scaleSafe( 2 );
581}
582
584{
585 scaleSafe( 0.5 );
586}
587
589{
590 setZoomLevel( 1.0 );
591}
592
597
599{
600 if ( !currentLayout() )
601 {
602 return;
603 }
604
605 //select all items in layout
606 QgsLayoutItem *focusedItem = nullptr;
607 const QList<QGraphicsItem *> itemList = currentLayout()->items();
608 for ( QGraphicsItem *graphicsItem : itemList )
609 {
610 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
611 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
612 if ( item && !paperItem )
613 {
614 if ( !item->isLocked() )
615 {
616 item->setSelected( true );
617 if ( !focusedItem )
618 focusedItem = item;
619 }
620 else
621 {
622 //deselect all locked items
623 item->setSelected( false );
624 }
625 }
626 }
627 emit itemFocused( focusedItem );
628}
629
631{
632 if ( !currentLayout() )
633 {
634 return;
635 }
636
638}
639
641{
642 if ( !currentLayout() )
643 {
644 return;
645 }
646
647 QgsLayoutItem *focusedItem = nullptr;
648 //check all items in layout
649 const QList<QGraphicsItem *> itemList = currentLayout()->items();
650 for ( QGraphicsItem *graphicsItem : itemList )
651 {
652 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
653 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
654 if ( item && !paperItem )
655 {
656 //flip selected state for items (and deselect any locked items)
657 if ( item->isSelected() || item->isLocked() )
658 {
659 item->setSelected( false );
660 }
661 else
662 {
663 item->setSelected( true );
664 if ( !focusedItem )
665 focusedItem = item;
666 }
667 }
668 }
669 if ( focusedItem )
670 emit itemFocused( focusedItem );
671}
672
673
674void selectNextByZOrder( QgsLayout *layout, bool above )
675{
676 if ( !layout )
677 return;
678
679 QgsLayoutItem *previousSelectedItem = nullptr;
680 const QList<QgsLayoutItem *> selectedItems = layout->selectedLayoutItems();
681 if ( !selectedItems.isEmpty() )
682 {
683 previousSelectedItem = selectedItems.at( 0 );
684 }
685
686 if ( !previousSelectedItem )
687 {
688 return;
689 }
690
691 //select item with target z value
692 QgsLayoutItem *selectedItem = nullptr;
693 if ( !above )
694 selectedItem = layout->itemsModel()->findItemBelow( previousSelectedItem );
695 else
696 selectedItem = layout->itemsModel()->findItemAbove( previousSelectedItem );
697
698 if ( !selectedItem )
699 {
700 return;
701 }
702
703 //OK, found a good target item
704 layout->setSelectedItem( selectedItem );
705}
706
711
716
718{
719 if ( !currentLayout() )
720 return;
721
722 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
723 bool itemsRaised = false;
724 for ( QgsLayoutItem *item : selectedItems )
725 {
726 itemsRaised = itemsRaised | currentLayout()->raiseItem( item, true );
727 }
728
729 if ( !itemsRaised )
730 {
731 //no change
732 return;
733 }
734
735 //update all positions
737 currentLayout()->update();
738}
739
741{
742 if ( !currentLayout() )
743 return;
744
745 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
746 bool itemsLowered = false;
747 for ( QgsLayoutItem *item : selectedItems )
748 {
749 itemsLowered = itemsLowered | currentLayout()->lowerItem( item, true );
750 }
751
752 if ( !itemsLowered )
753 {
754 //no change
755 return;
756 }
757
758 //update all positions
760 currentLayout()->update();
761}
762
764{
765 if ( !currentLayout() )
766 return;
767
768 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
769 bool itemsRaised = false;
770 for ( QgsLayoutItem *item : selectedItems )
771 {
772 itemsRaised = itemsRaised | currentLayout()->moveItemToTop( item, true );
773 }
774
775 if ( !itemsRaised )
776 {
777 //no change
778 return;
779 }
780
781 //update all positions
783 currentLayout()->update();
784}
785
787{
788 if ( !currentLayout() )
789 return;
790
791 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
792 bool itemsLowered = false;
793 for ( QgsLayoutItem *item : selectedItems )
794 {
795 itemsLowered = itemsLowered | currentLayout()->moveItemToBottom( item, true );
796 }
797
798 if ( !itemsLowered )
799 {
800 //no change
801 return;
802 }
803
804 //update all positions
806 currentLayout()->update();
807}
808
810{
811 if ( !currentLayout() )
812 return;
813
814 currentLayout()->undoStack()->beginMacro( tr( "Lock Items" ) );
815 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
816 for ( QgsLayoutItem *item : selectionList )
817 {
818 item->setLocked( true );
819 }
820
823}
824
826{
827 if ( !currentLayout() )
828 return;
829
830 //unlock all items in layout
831 currentLayout()->undoStack()->beginMacro( tr( "Unlock Items" ) );
832
833 //first, clear the selection
835
836 QgsLayoutItem *focusItem = nullptr;
837
838 const QList<QGraphicsItem *> itemList = currentLayout()->items();
839 for ( QGraphicsItem *graphicItem : itemList )
840 {
841 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicItem );
842 if ( item && item->isLocked() )
843 {
844 focusItem = item;
845 item->setLocked( false );
846 //select unlocked items, same behavior as illustrator
847 item->setSelected( true );
848 }
849 }
851
852 emit itemFocused( focusItem );
853}
854
856{
857 if ( !currentLayout() )
858 return;
859
860 deleteItems( currentLayout()->selectedLayoutItems() );
861}
862
863void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
864{
865 if ( !currentLayout() )
866 return;
867
868 if ( items.empty() )
869 return;
870
871 currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
872 //delete selected items
873 for ( QgsLayoutItem *item : items )
874 {
876 }
878 currentLayout()->project()->setDirty( true );
879}
880
882{
883 if ( !currentLayout() )
884 {
885 return;
886 }
887
888 //group selected items
889 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
890 QgsLayoutItemGroup *itemGroup = currentLayout()->groupItems( selectionList );
891
892 if ( !itemGroup )
893 {
894 //group could not be created
895 return;
896 }
897
898 for ( QgsLayoutItem *item : selectionList )
899 {
900 item->setSelected( false );
901 }
902
903 currentLayout()->setSelectedItem( itemGroup );
904}
905
907{
908 if ( !currentLayout() )
909 {
910 return;
911 }
912
913 QList<QgsLayoutItem *> ungroupedItems;
914 //hunt through selection for any groups, and ungroup them
915 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
916 for ( QgsLayoutItem *item : selectionList )
917 {
918 if ( item->type() == QgsLayoutItemRegistry::LayoutGroup )
919 {
920 QgsLayoutItemGroup *itemGroup = static_cast<QgsLayoutItemGroup *>( item );
921 ungroupedItems.append( currentLayout()->ungroupItems( itemGroup ) );
922 }
923 }
924
925 if ( !ungroupedItems.empty() )
926 {
927 for ( QgsLayoutItem *item : std::as_const( ungroupedItems ) )
928 {
929 item->setSelected( true );
930 }
931 emit itemFocused( ungroupedItems.at( 0 ) );
932 }
933}
934
935void QgsLayoutView::mousePressEvent( QMouseEvent *event )
936{
937 if ( !currentLayout() )
938 return;
939
940 if ( mSnapMarker )
941 mSnapMarker->setVisible( false );
942
943 if ( mTool )
944 {
945 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps );
946 mTool->layoutPressEvent( me.get() );
947 event->setAccepted( me->isAccepted() );
948 }
949
950 if ( !mTool || !event->isAccepted() )
951 {
952 if ( event->button() == Qt::MiddleButton )
953 {
954 // Pan layout with middle mouse button
955 setTool( mMidMouseButtonPanTool );
956 event->accept();
957 }
958 else if ( event->button() == Qt::RightButton && mMenuProvider )
959 {
960 QMenu *menu = mMenuProvider->createContextMenu( this, currentLayout(), mapToScene( event->pos() ) );
961 if ( menu )
962 {
963 menu->exec( event->globalPos() );
964 delete menu;
965 }
966 }
967 else
968 {
969 QGraphicsView::mousePressEvent( event );
970 }
971 }
972}
973
974void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
975{
976 if ( !currentLayout() )
977 return;
978
979 if ( mTool )
980 {
981 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps );
982 mTool->layoutReleaseEvent( me.get() );
983 event->setAccepted( me->isAccepted() );
984 }
985
986 if ( !mTool || !event->isAccepted() )
987 QGraphicsView::mouseReleaseEvent( event );
988}
989
990void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )
991{
992 if ( !currentLayout() )
993 return;
994
995 mMouseCurrentXY = event->pos();
996
997 QPointF cursorPos = mapToScene( mMouseCurrentXY );
998 if ( mTool )
999 {
1000 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, false );
1001 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
1002 {
1003 me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() );
1004 }
1005 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
1006 {
1007 //draw snapping point indicator
1008 if ( me->isSnapped() )
1009 {
1010 cursorPos = me->snappedPoint();
1011 if ( mSnapMarker )
1012 {
1013 mSnapMarker->setPos( me->snappedPoint() );
1014 mSnapMarker->setVisible( true );
1015 }
1016 }
1017 else if ( mSnapMarker )
1018 {
1019 mSnapMarker->setVisible( false );
1020 }
1021 }
1022 mTool->layoutMoveEvent( me.get() );
1023 event->setAccepted( me->isAccepted() );
1024 }
1025
1026 //update cursor position in status bar
1027 emit cursorPosChanged( cursorPos );
1028
1029 if ( !mTool || !event->isAccepted() )
1030 QGraphicsView::mouseMoveEvent( event );
1031}
1032
1034{
1035 if ( !currentLayout() )
1036 return;
1037
1038 if ( mTool )
1039 {
1040 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps );
1041 mTool->layoutDoubleClickEvent( me.get() );
1042 event->setAccepted( me->isAccepted() );
1043 }
1044
1045 if ( !mTool || !event->isAccepted() )
1046 QGraphicsView::mouseDoubleClickEvent( event );
1047}
1048
1049void QgsLayoutView::wheelEvent( QWheelEvent *event )
1050{
1051 if ( !currentLayout() )
1052 return;
1053
1054 if ( mTool )
1055 {
1056 mTool->wheelEvent( event );
1057 }
1058
1059 if ( !mTool || !event->isAccepted() )
1060 {
1061 event->accept();
1062 wheelZoom( event );
1063 }
1064}
1065
1066void QgsLayoutView::keyPressEvent( QKeyEvent *event )
1067{
1068 if ( !currentLayout() )
1069 return;
1070
1071 if ( mTool )
1072 {
1073 mTool->keyPressEvent( event );
1074 }
1075
1076 if ( mTool && event->isAccepted() )
1077 return;
1078
1079 if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() )
1080 {
1081 if ( !( event->modifiers() & Qt::ControlModifier ) )
1082 {
1083 // Pan layout with space bar
1084 setTool( mSpacePanTool );
1085 }
1086 else
1087 {
1088 //ctrl+space pressed, so switch to temporary keyboard based zoom tool
1089 setTool( mSpaceZoomTool );
1090 }
1091 event->accept();
1092 }
1093 else if ( event->key() == Qt::Key_Left
1094 || event->key() == Qt::Key_Right
1095 || event->key() == Qt::Key_Up
1096 || event->key() == Qt::Key_Down )
1097 {
1098 QgsLayout *l = currentLayout();
1099 const QList<QgsLayoutItem *> layoutItemList = l->selectedLayoutItems();
1100
1101 QPointF delta = deltaForKeyEvent( event );
1102
1103 l->undoStack()->beginMacro( tr( "Move Item" ) );
1104 for ( QgsLayoutItem *item : layoutItemList )
1105 {
1106 l->undoStack()->beginCommand( item, tr( "Move Item" ), QgsLayoutItem::UndoIncrementalMove );
1107 item->attemptMoveBy( delta.x(), delta.y() );
1108 l->undoStack()->endCommand();
1109 }
1110 l->undoStack()->endMacro();
1111 event->accept();
1112 }
1113}
1114
1115void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
1116{
1117 if ( !currentLayout() )
1118 return;
1119
1120 if ( mTool )
1121 {
1122 mTool->keyReleaseEvent( event );
1123 }
1124
1125 if ( !mTool || !event->isAccepted() )
1126 QGraphicsView::keyReleaseEvent( event );
1127}
1128
1129void QgsLayoutView::resizeEvent( QResizeEvent *event )
1130{
1131 QGraphicsView::resizeEvent( event );
1132 emit zoomLevelChanged();
1133 viewChanged();
1134}
1135
1137{
1138 QGraphicsView::scrollContentsBy( dx, dy );
1139 viewChanged();
1140}
1141
1142void QgsLayoutView::dragEnterEvent( QDragEnterEvent *e )
1143{
1144 // By default graphics view delegates the drag events to graphics items.
1145 // But we do not want that and by ignoring the drag enter we let the
1146 // parent (e.g. QgsLayoutDesignerDialog) to handle drops of files.
1147 e->ignore();
1148}
1149
1150void QgsLayoutView::paintEvent( QPaintEvent *event )
1151{
1152 if ( mPaintingEnabled )
1153 {
1154 QGraphicsView::paintEvent( event );
1155 event->accept();
1156 }
1157 else
1158 {
1159 event->ignore();
1160 }
1161}
1162
1163void QgsLayoutView::invalidateCachedRenders()
1164{
1165 if ( !currentLayout() )
1166 return;
1167
1168 //redraw cached map items
1169 QList<QgsLayoutItem *> items;
1170 currentLayout()->layoutItems( items );
1171
1172 for ( QgsLayoutItem *item : std::as_const( items ) )
1173 {
1174 item->invalidateCache();
1175 }
1176}
1177
1179{
1180 if ( mHorizontalRuler )
1181 {
1182 mHorizontalRuler->setSceneTransform( viewportTransform() );
1183 }
1184 if ( mVerticalRuler )
1185 {
1186 mVerticalRuler->setSceneTransform( viewportTransform() );
1187 }
1188
1189 // determine page at center of view
1190 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1191 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
1192 QPointF centerVisible = visibleRect.center();
1193
1194 if ( currentLayout() && currentLayout()->pageCollection() )
1195 {
1196 int newPage = currentLayout()->pageCollection()->pageNumberForPoint( centerVisible );
1197 if ( newPage != mCurrentPage )
1198 {
1199 mCurrentPage = newPage;
1200 emit pageChanged( mCurrentPage );
1201 }
1202 }
1203}
1204
1205void QgsLayoutView::pushStatusMessage( const QString &message )
1206{
1207 emit statusMessage( message );
1208}
1209
1210void QgsLayoutView::wheelZoom( QWheelEvent *event )
1211{
1212 //get mouse wheel zoom behavior settings
1213 QgsSettings settings;
1214 double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
1215 bool reverseZoom = settings.value( QStringLiteral( "qgis/reverse_wheel_zoom" ), false ).toBool();
1216 bool zoomIn = reverseZoom ? event->angleDelta().y() < 0 : event->angleDelta().y() > 0;
1217
1218 // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
1219 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
1220
1221 if ( event->modifiers() & Qt::ControlModifier )
1222 {
1223 //holding ctrl while wheel zooming results in a finer zoom
1224 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1225 }
1226
1227 //calculate zoom scale factor
1228 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
1229
1230 //get current visible part of scene
1231 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1232 QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
1233
1234 //transform the mouse pos to scene coordinates
1235#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1236 QPointF scenePoint = mapToScene( event->pos() );
1237#else
1238 QPointF scenePoint = mapToScene( event->position().x(), event->position().y() );
1239#endif
1240
1241 //adjust view center
1242 QgsPointXY oldCenter( visibleRect.center() );
1243 QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ), scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
1244 centerOn( newCenter.x(), newCenter.y() );
1245
1246 //zoom layout
1247 if ( zoomIn )
1248 {
1249 scaleSafe( zoomFactor );
1250 }
1251 else
1252 {
1253 scaleSafe( 1 / zoomFactor );
1254 }
1255}
1256
1257QGraphicsLineItem *QgsLayoutView::createSnapLine() const
1258{
1259 auto item = std::make_unique<QGraphicsLineItem>( nullptr );
1260 QPen pen = QPen( QColor( Qt::blue ) );
1261 pen.setStyle( Qt::DotLine );
1262 pen.setWidthF( 0.0 );
1263 item->setPen( pen );
1264 item->setZValue( QgsLayout::ZSmartGuide );
1265 return item.release();
1266}
1267
1268//
1269// QgsLayoutViewSnapMarker
1270//
1271
1273QgsLayoutViewSnapMarker::QgsLayoutViewSnapMarker()
1274 : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
1275{
1276 QFont f;
1277 QFontMetrics fm( f );
1278 mSize = fm.horizontalAdvance( 'X' );
1279 setPen( QPen( Qt::transparent, mSize ) );
1280
1281 setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
1282 setZValue( QgsLayout::ZSnapIndicator );
1283}
1284
1285void QgsLayoutViewSnapMarker::paint( QPainter *p, const QStyleOptionGraphicsItem *, QWidget * )
1286{
1287 QPen pen( QColor( 255, 0, 0 ) );
1288 pen.setWidth( 0 );
1289 p->setPen( pen );
1290 p->setBrush( Qt::NoBrush );
1291
1292 double halfSize = mSize / 2.0;
1293 p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
1294 p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );
1295}
1296
@ 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.
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 ...
Represents 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).
A container for the context for various read/write operations on 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.
Stores settings for use within QGIS.
Definition qgssettings.h:65
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