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