QGIS API Documentation 3.99.0-Master (d270888f95f)
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
20#include <memory>
21
22#include "qgslayoutframe.h"
23#include "qgslayoutitemgroup.h"
24#include "qgslayoutmodel.h"
25#include "qgslayoutmultiframe.h"
28#include "qgslayoutruler.h"
29#include "qgslayoutundostack.h"
31#include "qgslayoutviewtool.h"
35#include "qgsproject.h"
36#include "qgsreadwritecontext.h"
37#include "qgsrectangle.h"
38#include "qgsscreenhelper.h"
39#include "qgssettings.h"
40
41#include <QClipboard>
42#include <QMenu>
43#include <QMimeData>
44#include <QString>
45
46#include "moc_qgslayoutview.cpp"
47
48using namespace Qt::StringLiterals;
49
50#define MIN_VIEW_SCALE 0.05
51#define MAX_VIEW_SCALE 1000.0
52
54 : QGraphicsView( parent )
55{
56 setResizeAnchor( QGraphicsView::AnchorViewCenter );
57 setMouseTracking( true );
58 viewport()->setMouseTracking( true );
59
60 // set the "scene" background on the view using stylesheets
61 // we don't want to use QGraphicsScene::setBackgroundBrush because we want to keep
62 // a transparent background for exports, and it's only a cosmetic thing for the view only
63 // ALSO - only set it on the viewport - we don't want scrollbars/etc affected by this
64 viewport()->setStyleSheet( u"background-color:#d7d7d7;"_s );
65
66 mSpacePanTool = new QgsLayoutViewToolTemporaryKeyPan( this );
67 mMidMouseButtonPanTool = new QgsLayoutViewToolTemporaryMousePan( this );
68 mSpaceZoomTool = new QgsLayoutViewToolTemporaryKeyZoom( this );
69
70 mPreviewEffect = new QgsPreviewEffect( this );
71 viewport()->setGraphicsEffect( mPreviewEffect );
72
73 connect( this, &QgsLayoutView::zoomLevelChanged, this, &QgsLayoutView::invalidateCachedRenders );
74
75 mScreenHelper = new QgsScreenHelper( this );
76}
77
82
84{
85 return qobject_cast<QgsLayout *>( scene() );
86}
87
89{
90 return qobject_cast<const QgsLayout *>( scene() );
91}
92
94{
95 setScene( layout );
96
99
100 viewChanged();
101
102 // IMPORTANT!
103 // previous snap markers, snap lines are owned by previous layout - so don't delete them here!
104 mSnapMarker = new QgsLayoutViewSnapMarker();
105 mSnapMarker->hide();
106 layout->addItem( mSnapMarker );
107 mHorizontalSnapLine = createSnapLine();
108 mHorizontalSnapLine->hide();
109 layout->addItem( mHorizontalSnapLine );
110 mVerticalSnapLine = createSnapLine();
111 mVerticalSnapLine->hide();
112 layout->addItem( mVerticalSnapLine );
113 mSectionLabel = nullptr;
114
115 if ( mHorizontalRuler )
116 {
117 connect( &layout->guides(), &QAbstractItemModel::dataChanged, mHorizontalRuler, [this] { mHorizontalRuler->update(); } );
118 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mHorizontalRuler, [this] { mHorizontalRuler->update(); } );
119 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mHorizontalRuler, [this] { mHorizontalRuler->update(); } );
120 connect( &layout->guides(), &QAbstractItemModel::modelReset, mHorizontalRuler, [this] { mHorizontalRuler->update(); } );
121 }
122 if ( mVerticalRuler )
123 {
124 connect( &layout->guides(), &QAbstractItemModel::dataChanged, mVerticalRuler, [this] { mVerticalRuler->update(); } );
125 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, mVerticalRuler, [this] { mVerticalRuler->update(); } );
126 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, mVerticalRuler, [this] { mVerticalRuler->update(); } );
127 connect( &layout->guides(), &QAbstractItemModel::modelReset, mVerticalRuler, [this] { mVerticalRuler->update(); } );
128 }
129
130 //emit layoutSet, so that designer dialogs can update for the new layout
131 emit layoutSet( layout );
132}
133
135{
136 return mTool;
137}
138
140{
141 if ( !tool )
142 return;
143
144 if ( mTool )
145 {
146 mTool->deactivate();
148 }
149
150 if ( mSnapMarker )
151 mSnapMarker->hide();
152 if ( mHorizontalSnapLine )
153 mHorizontalSnapLine->hide();
154 if ( mVerticalSnapLine )
155 mVerticalSnapLine->hide();
156
157 // activate new tool before setting it - gives tools a chance
158 // to respond to whatever the current tool is
159 tool->activate();
160 mTool = tool;
162 emit toolSet( mTool );
163}
164
166{
167 if ( mTool && mTool == tool )
168 {
169 mTool->deactivate();
170 emit toolSet( nullptr );
171 setCursor( Qt::ArrowCursor );
172 }
173}
174
176{
177 mPreviewEffect->setEnabled( enabled );
178}
179
181{
182 return mPreviewEffect->isEnabled();
183}
184
186{
187 mPreviewEffect->setMode( mode );
188}
189
191{
192 return mPreviewEffect->mode();
193}
194
195void QgsLayoutView::scaleSafe( double scale )
196{
197 double currentScale = transform().m11();
198 scale *= currentScale;
199 scale = std::clamp( scale, MIN_VIEW_SCALE, MAX_VIEW_SCALE );
200 setTransform( QTransform::fromScale( scale, scale ) );
201 emit zoomLevelChanged();
202 viewChanged();
203}
204
205void QgsLayoutView::setZoomLevel( double level )
206{
207 if ( !currentLayout() )
208 return;
209
210 if ( currentLayout()->units() == Qgis::LayoutUnit::Pixels )
211 {
212 setTransform( QTransform::fromScale( level, level ) );
213 }
214 else
215 {
216 const double dpi = mScreenHelper->screenDpi();
217
218 //desired pixel width for 1mm on screen
219 level = std::clamp( level, MIN_VIEW_SCALE, MAX_VIEW_SCALE );
220 double mmLevel = currentLayout()->convertFromLayoutUnits( level, Qgis::LayoutUnit::Millimeters ).length() * dpi / 25.4;
221 setTransform( QTransform::fromScale( mmLevel, mmLevel ) );
222 }
223 emit zoomLevelChanged();
224 viewChanged();
225}
226
228{
229 mHorizontalRuler = ruler;
230 ruler->setLayoutView( this );
231 if ( QgsLayout *layout = currentLayout() )
232 {
233 connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [this] { mHorizontalRuler->update(); } );
234 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [this] { mHorizontalRuler->update(); } );
235 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [this] { mHorizontalRuler->update(); } );
236 connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [this] { mHorizontalRuler->update(); } );
237 }
238 viewChanged();
239}
240
242{
243 mVerticalRuler = ruler;
244 ruler->setLayoutView( this );
245 if ( QgsLayout *layout = currentLayout() )
246 {
247 connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [this] { mVerticalRuler->update(); } );
248 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [this] { mVerticalRuler->update(); } );
249 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [this] { mVerticalRuler->update(); } );
250 connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [this] { mVerticalRuler->update(); } );
251 }
252 viewChanged();
253}
254
256{
257 mMenuProvider.reset( provider );
258}
259
261{
262 return mMenuProvider.get();
263}
264
265QList<QgsLayoutItemPage *> QgsLayoutView::visiblePages() const
266{
267 if ( !currentLayout() )
268 return QList<QgsLayoutItemPage *>();
269
270 //get current visible part of scene
271 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
272 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
273 return currentLayout()->pageCollection()->visiblePages( visibleRect );
274}
275
277{
278 if ( !currentLayout() )
279 return QList<int>();
280
281 //get current visible part of scene
282 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
283 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
284 return currentLayout()->pageCollection()->visiblePageNumbers( visibleRect );
285}
286
288{
289 if ( !currentLayout() )
290 return;
291
292 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
293 QgsLayoutAligner::alignItems( currentLayout(), selectedItems, alignment );
294}
295
297{
298 if ( !currentLayout() )
299 return;
300
301 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
302 QgsLayoutAligner::distributeItems( currentLayout(), selectedItems, distribution );
303}
304
306{
307 if ( !currentLayout() )
308 return;
309
310 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
311 QgsLayoutAligner::resizeItems( currentLayout(), selectedItems, resize );
312}
313
315{
316 copyItems( currentLayout()->selectedLayoutItems(), operation );
317}
318
319void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutView::ClipboardOperation operation )
320{
321 if ( !currentLayout() )
322 return;
323
324 QgsReadWriteContext context;
325 QDomDocument doc;
326 QDomElement documentElement = doc.createElement( u"LayoutItemClipboard"_s );
327 if ( operation == ClipboardCut )
328 currentLayout()->undoStack()->beginMacro( tr( "Cut Items" ) );
329
330 QSet<QgsLayoutMultiFrame *> copiedMultiFrames;
331
332 for ( QgsLayoutItem *item : items )
333 {
334 // copy every child from a group
335 if ( QgsLayoutItemGroup *itemGroup = qobject_cast<QgsLayoutItemGroup *>( item ) )
336 {
337 const QList<QgsLayoutItem *> groupedItems = itemGroup->items();
338 for ( const QgsLayoutItem *groupedItem : groupedItems )
339 {
340 groupedItem->writeXml( documentElement, doc, context );
341 }
342 }
343 else if ( QgsLayoutFrame *frame = qobject_cast<QgsLayoutFrame *>( item ) )
344 {
345 // copy multiframe too
346 if ( frame->multiFrame() && !copiedMultiFrames.contains( frame->multiFrame() ) )
347 {
348 frame->multiFrame()->writeXml( documentElement, doc, context );
349 copiedMultiFrames.insert( frame->multiFrame() );
350 }
351 }
352 item->writeXml( documentElement, doc, context );
353 if ( operation == ClipboardCut )
355 }
356 doc.appendChild( documentElement );
357 if ( operation == ClipboardCut )
358 {
360 currentLayout()->update();
361 }
362
363 //remove the UUIDs since we don't want any duplicate UUID
364 QDomNodeList itemsNodes = doc.elementsByTagName( u"LayoutItem"_s );
365 for ( int i = 0; i < itemsNodes.count(); ++i )
366 {
367 QDomNode itemNode = itemsNodes.at( i );
368 if ( itemNode.isElement() )
369 {
370 itemNode.toElement().removeAttribute( u"uuid"_s );
371 itemNode.toElement().removeAttribute( u"groupUuid"_s );
372 }
373 }
374 QDomNodeList multiFrameNodes = doc.elementsByTagName( u"LayoutMultiFrame"_s );
375 for ( int i = 0; i < multiFrameNodes.count(); ++i )
376 {
377 QDomNode multiFrameNode = multiFrameNodes.at( i );
378 if ( multiFrameNode.isElement() )
379 {
380 multiFrameNode.toElement().removeAttribute( u"uuid"_s );
381 QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( u"childFrame"_s );
382 for ( int j = 0; j < frameNodes.count(); ++j )
383 {
384 QDomNode itemNode = frameNodes.at( j );
385 if ( itemNode.isElement() )
386 {
387 itemNode.toElement().removeAttribute( u"uuid"_s );
388 }
389 }
390 }
391 }
392
393 QMimeData *mimeData = new QMimeData;
394 mimeData->setData( u"text/xml"_s, doc.toByteArray() );
395 QClipboard *clipboard = QApplication::clipboard();
396 clipboard->setMimeData( mimeData );
397}
398
400{
401 if ( !currentLayout() )
402 return QList<QgsLayoutItem *>();
403
404 QList<QgsLayoutItem *> pastedItems;
405 QDomDocument doc;
406 QClipboard *clipboard = QApplication::clipboard();
407 const QMimeData *mimeData = clipboard->mimeData();
408 if ( !mimeData )
409 return {};
410
411 if ( doc.setContent( mimeData->data( u"text/xml"_s ) ) )
412 {
413 QDomElement docElem = doc.documentElement();
414 if ( docElem.tagName() == "LayoutItemClipboard"_L1 )
415 {
416 QPointF pt;
417 switch ( mode )
418 {
419 case PasteModeCursor:
420 case PasteModeInPlace:
421 {
422 // place items at cursor position
423 pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
424 break;
425 }
426 case PasteModeCenter:
427 {
428 // place items in center of viewport
429 pt = mapToScene( viewport()->rect().center() );
430 break;
431 }
432 }
433 bool pasteInPlace = ( mode == PasteModeInPlace );
434 currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
435 currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
436 pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &pt, pasteInPlace );
439 }
440 }
441 return pastedItems;
442}
443
444QList<QgsLayoutItem *> QgsLayoutView::pasteItems( QPointF layoutPoint )
445{
446 if ( !currentLayout() )
447 return QList<QgsLayoutItem *>();
448
449 QList<QgsLayoutItem *> pastedItems;
450 QDomDocument doc;
451 QClipboard *clipboard = QApplication::clipboard();
452 const QMimeData *mimeData = clipboard->mimeData();
453 if ( !mimeData )
454 return {};
455
456 if ( doc.setContent( mimeData->data( u"text/xml"_s ) ) )
457 {
458 QDomElement docElem = doc.documentElement();
459 if ( docElem.tagName() == "LayoutItemClipboard"_L1 )
460 {
461 currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
462 currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
463 pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &layoutPoint, false );
466 }
467 }
468 return pastedItems;
469}
470
472{
473 QDomDocument doc;
474 QClipboard *clipboard = QApplication::clipboard();
475 const QMimeData *mimeData = clipboard->mimeData();
476 if ( !mimeData )
477 return false;
478
479 if ( doc.setContent( mimeData->data( u"text/xml"_s ) ) )
480 {
481 QDomElement docElem = doc.documentElement();
482 if ( docElem.tagName() == "LayoutItemClipboard"_L1 )
483 return true;
484 }
485 return false;
486}
487
488QPointF QgsLayoutView::deltaForKeyEvent( QKeyEvent *event )
489{
490 // increment used for cursor key item movement
491 double increment = 1.0;
492 if ( event->modifiers() & Qt::ShiftModifier )
493 {
494 //holding shift while pressing cursor keys results in a big step
495 increment = 10.0;
496 }
497 else if ( event->modifiers() & Qt::AltModifier )
498 {
499 //holding alt while pressing cursor keys results in a 1 pixel step
500 double viewScale = transform().m11();
501 if ( viewScale > 0 )
502 {
503 increment = 1 / viewScale;
504 }
505 }
506
507 double deltaX = 0;
508 double deltaY = 0;
509 switch ( event->key() )
510 {
511 case Qt::Key_Left:
512 deltaX = -increment;
513 break;
514 case Qt::Key_Right:
515 deltaX = increment;
516 break;
517 case Qt::Key_Up:
518 deltaY = -increment;
519 break;
520 case Qt::Key_Down:
521 deltaY = increment;
522 break;
523 default:
524 break;
525 }
526
527 return QPointF( deltaX, deltaY );
528}
529
531{
532 mPaintingEnabled = enabled;
533 if ( enabled )
534 update();
535}
536
537void QgsLayoutView::setSectionLabel( const QString &label )
538{
539 if ( !currentLayout() )
540 return;
541
542 if ( !mSectionLabel )
543 {
544 mSectionLabel = new QgsLayoutReportSectionLabel( currentLayout(), this );
545 currentLayout()->addItem( mSectionLabel );
546 mSectionLabel->setRect( 0, -200, 1000, 200 );
547 mSectionLabel->setZValue( -1 );
548 }
549 mSectionLabel->setLabel( label );
550}
551
553{
554 if ( !scene() )
555 return;
556
557 fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
558 viewChanged();
559 emit zoomLevelChanged();
560}
561
563{
564 if ( !scene() )
565 return;
566
567 //get current visible part of scene
568 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
569 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
570
571 double verticalCenter = ( visibleRect.top() + visibleRect.bottom() ) / 2.0;
572 // expand out visible rect to include left/right edges of scene
573 // centered on current visible vertical center
574 // note that we can't have a 0 height rect - fitInView doesn't handle that
575 // so we just set a very small height instead.
576 const double tinyHeight = 0.01;
577 QRectF targetRect( scene()->sceneRect().left(), verticalCenter - tinyHeight, scene()->sceneRect().width(), tinyHeight * 2 );
578
579 fitInView( targetRect, Qt::KeepAspectRatio );
580 emit zoomLevelChanged();
581 viewChanged();
582}
583
585{
586 scaleSafe( 2 );
587}
588
590{
591 scaleSafe( 0.5 );
592}
593
595{
596 setZoomLevel( 1.0 );
597}
598
603
605{
606 if ( !currentLayout() )
607 {
608 return;
609 }
610
611 //select all items in layout
612 QgsLayoutItem *focusedItem = nullptr;
613 const QList<QGraphicsItem *> itemList = currentLayout()->items();
614 for ( QGraphicsItem *graphicsItem : itemList )
615 {
616 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
617 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
618 if ( item && !paperItem )
619 {
620 if ( !item->isLocked() )
621 {
622 item->setSelected( true );
623 if ( !focusedItem )
624 focusedItem = item;
625 }
626 else
627 {
628 //deselect all locked items
629 item->setSelected( false );
630 }
631 }
632 }
633 emit itemFocused( focusedItem );
634}
635
637{
638 if ( !currentLayout() )
639 {
640 return;
641 }
642
644}
645
647{
648 if ( !currentLayout() )
649 {
650 return;
651 }
652
653 QgsLayoutItem *focusedItem = nullptr;
654 //check all items in layout
655 const QList<QGraphicsItem *> itemList = currentLayout()->items();
656 for ( QGraphicsItem *graphicsItem : itemList )
657 {
658 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
659 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
660 if ( item && !paperItem )
661 {
662 //flip selected state for items (and deselect any locked items)
663 if ( item->isSelected() || item->isLocked() )
664 {
665 item->setSelected( false );
666 }
667 else
668 {
669 item->setSelected( true );
670 if ( !focusedItem )
671 focusedItem = item;
672 }
673 }
674 }
675 if ( focusedItem )
676 emit itemFocused( focusedItem );
677}
678
679
680void selectNextByZOrder( QgsLayout *layout, bool above )
681{
682 if ( !layout )
683 return;
684
685 QgsLayoutItem *previousSelectedItem = nullptr;
686 const QList<QgsLayoutItem *> selectedItems = layout->selectedLayoutItems();
687 if ( !selectedItems.isEmpty() )
688 {
689 previousSelectedItem = selectedItems.at( 0 );
690 }
691
692 if ( !previousSelectedItem )
693 {
694 return;
695 }
696
697 //select item with target z value
698 QgsLayoutItem *selectedItem = nullptr;
699 if ( !above )
700 selectedItem = layout->itemsModel()->findItemBelow( previousSelectedItem );
701 else
702 selectedItem = layout->itemsModel()->findItemAbove( previousSelectedItem );
703
704 if ( !selectedItem )
705 {
706 return;
707 }
708
709 //OK, found a good target item
710 layout->setSelectedItem( selectedItem );
711}
712
717
722
724{
725 if ( !currentLayout() )
726 return;
727
728 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
729 bool itemsRaised = false;
730 for ( QgsLayoutItem *item : selectedItems )
731 {
732 itemsRaised = itemsRaised | currentLayout()->raiseItem( item, true );
733 }
734
735 if ( !itemsRaised )
736 {
737 //no change
738 return;
739 }
740
741 //update all positions
743 currentLayout()->update();
744}
745
747{
748 if ( !currentLayout() )
749 return;
750
751 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
752 bool itemsLowered = false;
753 for ( QgsLayoutItem *item : selectedItems )
754 {
755 itemsLowered = itemsLowered | currentLayout()->lowerItem( item, true );
756 }
757
758 if ( !itemsLowered )
759 {
760 //no change
761 return;
762 }
763
764 //update all positions
766 currentLayout()->update();
767}
768
770{
771 if ( !currentLayout() )
772 return;
773
774 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
775 bool itemsRaised = false;
776 for ( QgsLayoutItem *item : selectedItems )
777 {
778 itemsRaised = itemsRaised | currentLayout()->moveItemToTop( item, true );
779 }
780
781 if ( !itemsRaised )
782 {
783 //no change
784 return;
785 }
786
787 //update all positions
789 currentLayout()->update();
790}
791
793{
794 if ( !currentLayout() )
795 return;
796
797 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
798 bool itemsLowered = false;
799 for ( QgsLayoutItem *item : selectedItems )
800 {
801 itemsLowered = itemsLowered | currentLayout()->moveItemToBottom( item, true );
802 }
803
804 if ( !itemsLowered )
805 {
806 //no change
807 return;
808 }
809
810 //update all positions
812 currentLayout()->update();
813}
814
816{
817 if ( !currentLayout() )
818 return;
819
820 currentLayout()->undoStack()->beginMacro( tr( "Lock Items" ) );
821 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
822 for ( QgsLayoutItem *item : selectionList )
823 {
824 item->setLocked( true );
825 }
826
829}
830
832{
833 if ( !currentLayout() )
834 return;
835
836 //unlock all items in layout
837 currentLayout()->undoStack()->beginMacro( tr( "Unlock Items" ) );
838
839 //first, clear the selection
841
842 QgsLayoutItem *focusItem = nullptr;
843
844 const QList<QGraphicsItem *> itemList = currentLayout()->items();
845 for ( QGraphicsItem *graphicItem : itemList )
846 {
847 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicItem );
848 if ( item && item->isLocked() )
849 {
850 focusItem = item;
851 item->setLocked( false );
852 //select unlocked items, same behavior as illustrator
853 item->setSelected( true );
854 }
855 }
857
858 emit itemFocused( focusItem );
859}
860
862{
863 if ( !currentLayout() )
864 return;
865
866 deleteItems( currentLayout()->selectedLayoutItems() );
867}
868
869void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
870{
871 if ( !currentLayout() )
872 return;
873
874 if ( items.empty() )
875 return;
876
877 currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
878 //delete selected items
879 for ( QgsLayoutItem *item : items )
880 {
882 }
884 currentLayout()->project()->setDirty( true );
885}
886
888{
889 if ( !currentLayout() )
890 {
891 return;
892 }
893
894 //group selected items
895 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
896 QgsLayoutItemGroup *itemGroup = currentLayout()->groupItems( selectionList );
897
898 if ( !itemGroup )
899 {
900 //group could not be created
901 return;
902 }
903
904 for ( QgsLayoutItem *item : selectionList )
905 {
906 item->setSelected( false );
907 }
908
909 currentLayout()->setSelectedItem( itemGroup );
910}
911
913{
914 if ( !currentLayout() )
915 {
916 return;
917 }
918
919 QList<QgsLayoutItem *> ungroupedItems;
920 //hunt through selection for any groups, and ungroup them
921 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
922 for ( QgsLayoutItem *item : selectionList )
923 {
924 if ( item->type() == QgsLayoutItemRegistry::LayoutGroup )
925 {
926 QgsLayoutItemGroup *itemGroup = static_cast<QgsLayoutItemGroup *>( item );
927 ungroupedItems.append( currentLayout()->ungroupItems( itemGroup ) );
928 }
929 }
930
931 if ( !ungroupedItems.empty() )
932 {
933 for ( QgsLayoutItem *item : std::as_const( ungroupedItems ) )
934 {
935 item->setSelected( true );
936 }
937 emit itemFocused( ungroupedItems.at( 0 ) );
938 }
939}
940
941void QgsLayoutView::mousePressEvent( QMouseEvent *event )
942{
943 if ( !currentLayout() )
944 return;
945
946 if ( mSnapMarker )
947 mSnapMarker->setVisible( false );
948
949 if ( mTool )
950 {
951 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps );
952 mTool->layoutPressEvent( me.get() );
953 event->setAccepted( me->isAccepted() );
954 }
955
956 if ( !mTool || !event->isAccepted() )
957 {
958 if ( event->button() == Qt::MiddleButton && mTool != mSpacePanTool && mTool != mSpaceZoomTool )
959 {
960 // Pan layout with middle mouse button
961 setTool( mMidMouseButtonPanTool );
962 event->accept();
963 }
964 else if ( event->button() == Qt::RightButton && mMenuProvider )
965 {
966 QMenu *menu = mMenuProvider->createContextMenu( this, currentLayout(), mapToScene( event->pos() ) );
967 if ( menu )
968 {
969 menu->exec( event->globalPos() );
970 delete menu;
971 }
972 }
973 else
974 {
975 QGraphicsView::mousePressEvent( event );
976 }
977 }
978}
979
980void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
981{
982 if ( !currentLayout() )
983 return;
984
985 if ( mTool )
986 {
987 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps );
988 mTool->layoutReleaseEvent( me.get() );
989 event->setAccepted( me->isAccepted() );
990 }
991
992 if ( !mTool || !event->isAccepted() )
993 QGraphicsView::mouseReleaseEvent( event );
994}
995
996void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )
997{
998 if ( !currentLayout() )
999 return;
1000
1001 mMouseCurrentXY = event->pos();
1002
1003 QPointF cursorPos = mapToScene( mMouseCurrentXY );
1004 if ( mTool )
1005 {
1006 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, false );
1007 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
1008 {
1009 me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() );
1010 }
1011 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
1012 {
1013 //draw snapping point indicator
1014 if ( me->isSnapped() )
1015 {
1016 cursorPos = me->snappedPoint();
1017 if ( mSnapMarker )
1018 {
1019 mSnapMarker->setPos( me->snappedPoint() );
1020 mSnapMarker->setVisible( true );
1021 }
1022 }
1023 else if ( mSnapMarker )
1024 {
1025 mSnapMarker->setVisible( false );
1026 }
1027 }
1028 mTool->layoutMoveEvent( me.get() );
1029 event->setAccepted( me->isAccepted() );
1030 }
1031
1032 //update cursor position in status bar
1033 emit cursorPosChanged( cursorPos );
1034
1035 if ( !mTool || !event->isAccepted() )
1036 QGraphicsView::mouseMoveEvent( event );
1037}
1038
1040{
1041 if ( !currentLayout() )
1042 return;
1043
1044 if ( mTool )
1045 {
1046 auto me = std::make_unique<QgsLayoutViewMouseEvent>( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps );
1047 mTool->layoutDoubleClickEvent( me.get() );
1048 event->setAccepted( me->isAccepted() );
1049 }
1050
1051 if ( !mTool || !event->isAccepted() )
1052 QGraphicsView::mouseDoubleClickEvent( event );
1053}
1054
1055void QgsLayoutView::wheelEvent( QWheelEvent *event )
1056{
1057 if ( !currentLayout() )
1058 return;
1059
1060 if ( mTool )
1061 {
1062 mTool->wheelEvent( event );
1063 }
1064
1065 if ( !mTool || !event->isAccepted() )
1066 {
1067 event->accept();
1068 wheelZoom( event );
1069 }
1070}
1071
1072void QgsLayoutView::keyPressEvent( QKeyEvent *event )
1073{
1074 if ( !currentLayout() )
1075 return;
1076
1077 if ( mTool )
1078 {
1079 mTool->keyPressEvent( event );
1080 }
1081
1082 if ( mTool && event->isAccepted() )
1083 return;
1084
1085 if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() && mTool != mMidMouseButtonPanTool )
1086 {
1087 if ( !( event->modifiers() & Qt::ControlModifier ) )
1088 {
1089 // Pan layout with space bar
1090 setTool( mSpacePanTool );
1091 }
1092 else
1093 {
1094 //ctrl+space pressed, so switch to temporary keyboard based zoom tool
1095 setTool( mSpaceZoomTool );
1096 }
1097 event->accept();
1098 }
1099 else if ( event->key() == Qt::Key_Left
1100 || event->key() == Qt::Key_Right
1101 || event->key() == Qt::Key_Up
1102 || event->key() == Qt::Key_Down )
1103 {
1104 QgsLayout *l = currentLayout();
1105 const QList<QgsLayoutItem *> layoutItemList = l->selectedLayoutItems();
1106
1107 QPointF delta = deltaForKeyEvent( event );
1108
1109 l->undoStack()->beginMacro( tr( "Move Item" ) );
1110 for ( QgsLayoutItem *item : layoutItemList )
1111 {
1112 l->undoStack()->beginCommand( item, tr( "Move Item" ), QgsLayoutItem::UndoIncrementalMove );
1113 item->attemptMoveBy( delta.x(), delta.y() );
1114 l->undoStack()->endCommand();
1115 }
1116 l->undoStack()->endMacro();
1117 event->accept();
1118 }
1119}
1120
1121void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
1122{
1123 if ( !currentLayout() )
1124 return;
1125
1126 if ( mTool )
1127 {
1128 mTool->keyReleaseEvent( event );
1129 }
1130
1131 if ( !mTool || !event->isAccepted() )
1132 QGraphicsView::keyReleaseEvent( event );
1133}
1134
1135void QgsLayoutView::resizeEvent( QResizeEvent *event )
1136{
1137 QGraphicsView::resizeEvent( event );
1138 emit zoomLevelChanged();
1139 viewChanged();
1140}
1141
1143{
1144 QGraphicsView::scrollContentsBy( dx, dy );
1145 viewChanged();
1146}
1147
1148void QgsLayoutView::dragEnterEvent( QDragEnterEvent *e )
1149{
1150 // By default graphics view delegates the drag events to graphics items.
1151 // But we do not want that and by ignoring the drag enter we let the
1152 // parent (e.g. QgsLayoutDesignerDialog) to handle drops of files.
1153 e->ignore();
1154}
1155
1156void QgsLayoutView::paintEvent( QPaintEvent *event )
1157{
1158 if ( mPaintingEnabled )
1159 {
1160 QGraphicsView::paintEvent( event );
1161 event->accept();
1162 }
1163 else
1164 {
1165 event->ignore();
1166 }
1167}
1168
1169void QgsLayoutView::invalidateCachedRenders()
1170{
1171 if ( !currentLayout() )
1172 return;
1173
1174 //redraw cached map items
1175 QList<QgsLayoutItem *> items;
1176 currentLayout()->layoutItems( items );
1177
1178 for ( QgsLayoutItem *item : std::as_const( items ) )
1179 {
1180 item->invalidateCache();
1181 }
1182}
1183
1185{
1186 if ( mHorizontalRuler )
1187 {
1188 mHorizontalRuler->setSceneTransform( viewportTransform() );
1189 }
1190 if ( mVerticalRuler )
1191 {
1192 mVerticalRuler->setSceneTransform( viewportTransform() );
1193 }
1194
1195 // determine page at center of view
1196 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1197 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
1198 QPointF centerVisible = visibleRect.center();
1199
1200 if ( currentLayout() && currentLayout()->pageCollection() )
1201 {
1202 int newPage = currentLayout()->pageCollection()->pageNumberForPoint( centerVisible );
1203 if ( newPage != mCurrentPage )
1204 {
1205 mCurrentPage = newPage;
1206 emit pageChanged( mCurrentPage );
1207 }
1208 }
1209}
1210
1211void QgsLayoutView::pushStatusMessage( const QString &message )
1212{
1213 emit statusMessage( message );
1214}
1215
1216void QgsLayoutView::wheelZoom( QWheelEvent *event )
1217{
1218 //get mouse wheel zoom behavior settings
1219 QgsSettings settings;
1220 double zoomFactor = settings.value( u"qgis/zoom_factor"_s, 2 ).toDouble();
1221 bool reverseZoom = settings.value( u"qgis/reverse_wheel_zoom"_s, false ).toBool();
1222 bool zoomIn = reverseZoom ? event->angleDelta().y() < 0 : event->angleDelta().y() > 0;
1223
1224 // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
1225 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
1226
1227 if ( event->modifiers() & Qt::ControlModifier )
1228 {
1229 //holding ctrl while wheel zooming results in a finer zoom
1230 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1231 }
1232
1233 //calculate zoom scale factor
1234 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
1235
1236 //get current visible part of scene
1237 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1238 QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
1239
1240 //transform the mouse pos to scene coordinates
1241 QPointF scenePoint = mapToScene( event->position().x(), event->position().y() );
1242
1243 //adjust view center
1244 QgsPointXY oldCenter( visibleRect.center() );
1245 QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ), scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
1246 centerOn( newCenter.x(), newCenter.y() );
1247
1248 //zoom layout
1249 if ( zoomIn )
1250 {
1251 scaleSafe( zoomFactor );
1252 }
1253 else
1254 {
1255 scaleSafe( 1 / zoomFactor );
1256 }
1257}
1258
1259QGraphicsLineItem *QgsLayoutView::createSnapLine() const
1260{
1261 auto item = std::make_unique<QGraphicsLineItem>( nullptr );
1262 QPen pen = QPen( QColor( Qt::blue ) );
1263 pen.setStyle( Qt::DotLine );
1264 pen.setWidthF( 0.0 );
1265 item->setPen( pen );
1266 item->setZValue( QgsLayout::ZSmartGuide );
1267 return item.release();
1268}
1269
1270//
1271// QgsLayoutViewSnapMarker
1272//
1273
1275QgsLayoutViewSnapMarker::QgsLayoutViewSnapMarker()
1276 : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
1277{
1278 QFont f;
1279 QFontMetrics fm( f );
1280 mSize = fm.horizontalAdvance( 'X' );
1281 setPen( QPen( Qt::transparent, mSize ) );
1282
1283 setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
1284 setZValue( QgsLayout::ZSnapIndicator );
1285}
1286
1287void QgsLayoutViewSnapMarker::paint( QPainter *p, const QStyleOptionGraphicsItem *, QWidget * )
1288{
1289 QPen pen( QColor( 255, 0, 0 ) );
1290 pen.setWidth( 0 );
1291 p->setPen( pen );
1292 p->setBrush( Qt::NoBrush );
1293
1294 double halfSize = mSize / 2.0;
1295 p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
1296 p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );
1297}
1298
@ Millimeters
Millimeters.
Definition qgis.h:5276
@ Pixels
Pixels.
Definition qgis.h:5283
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 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.
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:50
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:121
QgsLayoutGuideCollection & guides()
Returns a reference to the layout's guide collection, which manages page snap guides.
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:62
@ ZSnapIndicator
Z-value for snapping indicator.
Definition qgslayout.h:65
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 graphics effect which can be applied to a widget to simulate various printing and color blindness m...
void setDirty(bool b=true)
Flag the project as dirty (modified).
A container for the context for various read/write operations on objects.
QgsPointXY center
A utility class for dynamic handling of changes to screen properties.
Stores settings for use within QGIS.
Definition qgssettings.h:68
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