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