QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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
72{
73 emit willBeDeleted();
74}
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() == QgsUnitTypes::LayoutPixels )
204 {
205 setTransform( QTransform::fromScale( level, level ) );
206 }
207 else
208 {
209 double dpi = mScreenHelper->screenDpi();
210 //monitor dpi is not always correct - so make sure the value is sane
211 if ( ( dpi < 60 ) || ( dpi > 1200 ) )
212 dpi = 72;
213
214 //desired pixel width for 1mm on screen
215 level = std::clamp( level, MIN_VIEW_SCALE, MAX_VIEW_SCALE );
216 double mmLevel = currentLayout()->convertFromLayoutUnits( level, QgsUnitTypes::LayoutMillimeters ).length() * dpi / 25.4;
217 setTransform( QTransform::fromScale( mmLevel, mmLevel ) );
218 }
219 emit zoomLevelChanged();
220 viewChanged();
221}
222
224{
225 mHorizontalRuler = ruler;
226 ruler->setLayoutView( this );
227 if ( QgsLayout *layout = currentLayout() )
228 {
229 connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mHorizontalRuler->update(); } );
230 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mHorizontalRuler->update(); } );
231 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mHorizontalRuler->update(); } );
232 connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [ = ] { mHorizontalRuler->update(); } );
233 }
234 viewChanged();
235}
236
238{
239 mVerticalRuler = ruler;
240 ruler->setLayoutView( this );
241 if ( QgsLayout *layout = currentLayout() )
242 {
243 connect( &layout->guides(), &QAbstractItemModel::dataChanged, ruler, [ = ] { mVerticalRuler->update(); } );
244 connect( &layout->guides(), &QAbstractItemModel::rowsInserted, ruler, [ = ] { mVerticalRuler->update(); } );
245 connect( &layout->guides(), &QAbstractItemModel::rowsRemoved, ruler, [ = ] { mVerticalRuler->update(); } );
246 connect( &layout->guides(), &QAbstractItemModel::modelReset, ruler, [ = ] { mVerticalRuler->update(); } );
247 }
248 viewChanged();
249}
250
252{
253 mMenuProvider.reset( provider );
254}
255
257{
258 return mMenuProvider.get();
259}
260
261QList<QgsLayoutItemPage *> QgsLayoutView::visiblePages() const
262{
263 if ( !currentLayout() )
264 return QList< QgsLayoutItemPage *>();
265
266 //get current visible part of scene
267 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
268 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
269 return currentLayout()->pageCollection()->visiblePages( visibleRect );
270}
271
273{
274 if ( !currentLayout() )
275 return QList< int >();
276
277 //get current visible part of scene
278 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
279 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
280 return currentLayout()->pageCollection()->visiblePageNumbers( visibleRect );
281}
282
284{
285 if ( !currentLayout() )
286 return;
287
288 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
289 QgsLayoutAligner::alignItems( currentLayout(), selectedItems, alignment );
290}
291
293{
294 if ( !currentLayout() )
295 return;
296
297 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
298 QgsLayoutAligner::distributeItems( currentLayout(), selectedItems, distribution );
299}
300
302{
303 if ( !currentLayout() )
304 return;
305
306 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
307 QgsLayoutAligner::resizeItems( currentLayout(), selectedItems, resize );
308}
309
311{
312 copyItems( currentLayout()->selectedLayoutItems(), operation );
313}
314
315void QgsLayoutView::copyItems( const QList<QgsLayoutItem *> &items, QgsLayoutView::ClipboardOperation operation )
316{
317 if ( !currentLayout() )
318 return;
319
320 QgsReadWriteContext context;
321 QDomDocument doc;
322 QDomElement documentElement = doc.createElement( QStringLiteral( "LayoutItemClipboard" ) );
323 if ( operation == ClipboardCut )
324 currentLayout()->undoStack()->beginMacro( tr( "Cut Items" ) );
325
326 QSet< QgsLayoutMultiFrame * > copiedMultiFrames;
327
328 for ( QgsLayoutItem *item : items )
329 {
330 // copy every child from a group
331 if ( QgsLayoutItemGroup *itemGroup = qobject_cast<QgsLayoutItemGroup *>( item ) )
332 {
333 const QList<QgsLayoutItem *> groupedItems = itemGroup->items();
334 for ( const QgsLayoutItem *groupedItem : groupedItems )
335 {
336 groupedItem->writeXml( documentElement, doc, context );
337 }
338 }
339 else if ( QgsLayoutFrame *frame = qobject_cast<QgsLayoutFrame *>( item ) )
340 {
341 // copy multiframe too
342 if ( frame->multiFrame() && !copiedMultiFrames.contains( frame->multiFrame() ) )
343 {
344 frame->multiFrame()->writeXml( documentElement, doc, context );
345 copiedMultiFrames.insert( frame->multiFrame() );
346 }
347 }
348 item->writeXml( documentElement, doc, context );
349 if ( operation == ClipboardCut )
351 }
352 doc.appendChild( documentElement );
353 if ( operation == ClipboardCut )
354 {
356 currentLayout()->update();
357 }
358
359 //remove the UUIDs since we don't want any duplicate UUID
360 QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral( "LayoutItem" ) );
361 for ( int i = 0; i < itemsNodes.count(); ++i )
362 {
363 QDomNode itemNode = itemsNodes.at( i );
364 if ( itemNode.isElement() )
365 {
366 itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
367 itemNode.toElement().removeAttribute( QStringLiteral( "groupUuid" ) );
368 }
369 }
370 QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral( "LayoutMultiFrame" ) );
371 for ( int i = 0; i < multiFrameNodes.count(); ++i )
372 {
373 QDomNode multiFrameNode = multiFrameNodes.at( i );
374 if ( multiFrameNode.isElement() )
375 {
376 multiFrameNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
377 QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral( "childFrame" ) );
378 for ( int j = 0; j < frameNodes.count(); ++j )
379 {
380 QDomNode itemNode = frameNodes.at( j );
381 if ( itemNode.isElement() )
382 {
383 itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
384 }
385 }
386 }
387 }
388
389 QMimeData *mimeData = new QMimeData;
390 mimeData->setData( QStringLiteral( "text/xml" ), doc.toByteArray() );
391 QClipboard *clipboard = QApplication::clipboard();
392 clipboard->setMimeData( mimeData );
393}
394
396{
397 if ( !currentLayout() )
398 return QList< QgsLayoutItem * >();
399
400 QList< QgsLayoutItem * > pastedItems;
401 QDomDocument doc;
402 QClipboard *clipboard = QApplication::clipboard();
403 if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
404 {
405 QDomElement docElem = doc.documentElement();
406 if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
407 {
408 QPointF pt;
409 switch ( mode )
410 {
411 case PasteModeCursor:
412 case PasteModeInPlace:
413 {
414 // place items at cursor position
415 pt = mapToScene( mapFromGlobal( QCursor::pos() ) );
416 break;
417 }
418 case PasteModeCenter:
419 {
420 // place items in center of viewport
421 pt = mapToScene( viewport()->rect().center() );
422 break;
423 }
424 }
425 bool pasteInPlace = ( mode == PasteModeInPlace );
426 currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
427 currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
428 pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &pt, pasteInPlace );
431 }
432 }
433 return pastedItems;
434}
435
436QList<QgsLayoutItem *> QgsLayoutView::pasteItems( QPointF layoutPoint )
437{
438 if ( !currentLayout() )
439 return QList<QgsLayoutItem *>();
440
441 QList< QgsLayoutItem * > pastedItems;
442 QDomDocument doc;
443 QClipboard *clipboard = QApplication::clipboard();
444 if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
445 {
446 QDomElement docElem = doc.documentElement();
447 if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
448 {
449 currentLayout()->undoStack()->beginMacro( tr( "Paste Items" ) );
450 currentLayout()->undoStack()->beginCommand( currentLayout(), tr( "Paste Items" ) );
451 pastedItems = currentLayout()->addItemsFromXml( docElem, doc, QgsReadWriteContext(), &layoutPoint, false );
454 }
455 }
456 return pastedItems;
457}
458
460{
461 QDomDocument doc;
462 QClipboard *clipboard = QApplication::clipboard();
463 if ( doc.setContent( clipboard->mimeData()->data( QStringLiteral( "text/xml" ) ) ) )
464 {
465 QDomElement docElem = doc.documentElement();
466 if ( docElem.tagName() == QLatin1String( "LayoutItemClipboard" ) )
467 return true;
468 }
469 return false;
470}
471
472QPointF QgsLayoutView::deltaForKeyEvent( QKeyEvent *event )
473{
474 // increment used for cursor key item movement
475 double increment = 1.0;
476 if ( event->modifiers() & Qt::ShiftModifier )
477 {
478 //holding shift while pressing cursor keys results in a big step
479 increment = 10.0;
480 }
481 else if ( event->modifiers() & Qt::AltModifier )
482 {
483 //holding alt while pressing cursor keys results in a 1 pixel step
484 double viewScale = transform().m11();
485 if ( viewScale > 0 )
486 {
487 increment = 1 / viewScale;
488 }
489 }
490
491 double deltaX = 0;
492 double deltaY = 0;
493 switch ( event->key() )
494 {
495 case Qt::Key_Left:
496 deltaX = -increment;
497 break;
498 case Qt::Key_Right:
499 deltaX = increment;
500 break;
501 case Qt::Key_Up:
502 deltaY = -increment;
503 break;
504 case Qt::Key_Down:
505 deltaY = increment;
506 break;
507 default:
508 break;
509 }
510
511 return QPointF( deltaX, deltaY );
512}
513
515{
516 mPaintingEnabled = enabled;
517 if ( enabled )
518 update();
519}
520
521void QgsLayoutView::setSectionLabel( const QString &label )
522{
523 if ( !currentLayout() )
524 return;
525
526 if ( !mSectionLabel )
527 {
528 mSectionLabel = new QgsLayoutReportSectionLabel( currentLayout(), this );
529 currentLayout()->addItem( mSectionLabel );
530 mSectionLabel->setRect( 0, -200, 1000, 200 );
531 mSectionLabel->setZValue( -1 );
532 }
533 mSectionLabel->setLabel( label );
534}
535
537{
538 if ( !scene() )
539 return;
540
541 fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
542 viewChanged();
543 emit zoomLevelChanged();
544}
545
547{
548 if ( !scene() )
549 return;
550
551 //get current visible part of scene
552 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
553 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
554
555 double verticalCenter = ( visibleRect.top() + visibleRect.bottom() ) / 2.0;
556 // expand out visible rect to include left/right edges of scene
557 // centered on current visible vertical center
558 // note that we can't have a 0 height rect - fitInView doesn't handle that
559 // so we just set a very small height instead.
560 const double tinyHeight = 0.01;
561 QRectF targetRect( scene()->sceneRect().left(),
562 verticalCenter - tinyHeight,
563 scene()->sceneRect().width(),
564 tinyHeight * 2 );
565
566 fitInView( targetRect, Qt::KeepAspectRatio );
567 emit zoomLevelChanged();
568 viewChanged();
569}
570
572{
573 scaleSafe( 2 );
574}
575
577{
578 scaleSafe( 0.5 );
579}
580
582{
583 setZoomLevel( 1.0 );
584}
585
587{
588 emit zoomLevelChanged();
589}
590
592{
593 if ( !currentLayout() )
594 {
595 return;
596 }
597
598 //select all items in layout
599 QgsLayoutItem *focusedItem = nullptr;
600 const QList<QGraphicsItem *> itemList = currentLayout()->items();
601 for ( QGraphicsItem *graphicsItem : itemList )
602 {
603 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
604 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
605 if ( item && !paperItem )
606 {
607 if ( !item->isLocked() )
608 {
609 item->setSelected( true );
610 if ( !focusedItem )
611 focusedItem = item;
612 }
613 else
614 {
615 //deselect all locked items
616 item->setSelected( false );
617 }
618 }
619 }
620 emit itemFocused( focusedItem );
621}
622
624{
625 if ( !currentLayout() )
626 {
627 return;
628 }
629
631}
632
634{
635 if ( !currentLayout() )
636 {
637 return;
638 }
639
640 QgsLayoutItem *focusedItem = nullptr;
641 //check all items in layout
642 const QList<QGraphicsItem *> itemList = currentLayout()->items();
643 for ( QGraphicsItem *graphicsItem : itemList )
644 {
645 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
646 QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
647 if ( item && !paperItem )
648 {
649 //flip selected state for items (and deselect any locked items)
650 if ( item->isSelected() || item->isLocked() )
651 {
652 item->setSelected( false );
653 }
654 else
655 {
656 item->setSelected( true );
657 if ( !focusedItem )
658 focusedItem = item;
659 }
660 }
661 }
662 if ( focusedItem )
663 emit itemFocused( focusedItem );
664}
665
666
667void selectNextByZOrder( QgsLayout *layout, bool above )
668{
669 if ( !layout )
670 return;
671
672 QgsLayoutItem *previousSelectedItem = nullptr;
673 const QList<QgsLayoutItem *> selectedItems = layout->selectedLayoutItems();
674 if ( !selectedItems.isEmpty() )
675 {
676 previousSelectedItem = selectedItems.at( 0 );
677 }
678
679 if ( !previousSelectedItem )
680 {
681 return;
682 }
683
684 //select item with target z value
685 QgsLayoutItem *selectedItem = nullptr;
686 if ( !above )
687 selectedItem = layout->itemsModel()->findItemBelow( previousSelectedItem );
688 else
689 selectedItem = layout->itemsModel()->findItemAbove( previousSelectedItem );
690
691 if ( !selectedItem )
692 {
693 return;
694 }
695
696 //OK, found a good target item
697 layout->setSelectedItem( selectedItem );
698}
699
701{
703}
704
706{
708}
709
711{
712 if ( !currentLayout() )
713 return;
714
715 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
716 bool itemsRaised = false;
717 for ( QgsLayoutItem *item : selectedItems )
718 {
719 itemsRaised = itemsRaised | currentLayout()->raiseItem( item, true );
720 }
721
722 if ( !itemsRaised )
723 {
724 //no change
725 return;
726 }
727
728 //update all positions
730 currentLayout()->update();
731}
732
734{
735 if ( !currentLayout() )
736 return;
737
738 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
739 bool itemsLowered = false;
740 for ( QgsLayoutItem *item : selectedItems )
741 {
742 itemsLowered = itemsLowered | currentLayout()->lowerItem( item, true );
743 }
744
745 if ( !itemsLowered )
746 {
747 //no change
748 return;
749 }
750
751 //update all positions
753 currentLayout()->update();
754}
755
757{
758 if ( !currentLayout() )
759 return;
760
761 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
762 bool itemsRaised = false;
763 for ( QgsLayoutItem *item : selectedItems )
764 {
765 itemsRaised = itemsRaised | currentLayout()->moveItemToTop( item, true );
766 }
767
768 if ( !itemsRaised )
769 {
770 //no change
771 return;
772 }
773
774 //update all positions
776 currentLayout()->update();
777}
778
780{
781 if ( !currentLayout() )
782 return;
783
784 const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
785 bool itemsLowered = false;
786 for ( QgsLayoutItem *item : selectedItems )
787 {
788 itemsLowered = itemsLowered | currentLayout()->moveItemToBottom( item, true );
789 }
790
791 if ( !itemsLowered )
792 {
793 //no change
794 return;
795 }
796
797 //update all positions
799 currentLayout()->update();
800}
801
803{
804 if ( !currentLayout() )
805 return;
806
807 currentLayout()->undoStack()->beginMacro( tr( "Lock Items" ) );
808 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
809 for ( QgsLayoutItem *item : selectionList )
810 {
811 item->setLocked( true );
812 }
813
816}
817
819{
820 if ( !currentLayout() )
821 return;
822
823 //unlock all items in layout
824 currentLayout()->undoStack()->beginMacro( tr( "Unlock Items" ) );
825
826 //first, clear the selection
828
829 QgsLayoutItem *focusItem = nullptr;
830
831 const QList<QGraphicsItem *> itemList = currentLayout()->items();
832 for ( QGraphicsItem *graphicItem : itemList )
833 {
834 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicItem );
835 if ( item && item->isLocked() )
836 {
837 focusItem = item;
838 item->setLocked( false );
839 //select unlocked items, same behavior as illustrator
840 item->setSelected( true );
841 }
842 }
844
845 emit itemFocused( focusItem );
846}
847
849{
850 if ( !currentLayout() )
851 return;
852
853 deleteItems( currentLayout()->selectedLayoutItems() );
854}
855
856void QgsLayoutView::deleteItems( const QList<QgsLayoutItem *> &items )
857{
858 if ( !currentLayout() )
859 return;
860
861 if ( items.empty() )
862 return;
863
864 currentLayout()->undoStack()->beginMacro( tr( "Delete Items" ) );
865 //delete selected items
866 for ( QgsLayoutItem *item : items )
867 {
869 }
871 currentLayout()->project()->setDirty( true );
872}
873
875{
876 if ( !currentLayout() )
877 {
878 return;
879 }
880
881 //group selected items
882 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
883 QgsLayoutItemGroup *itemGroup = currentLayout()->groupItems( selectionList );
884
885 if ( !itemGroup )
886 {
887 //group could not be created
888 return;
889 }
890
891 for ( QgsLayoutItem *item : selectionList )
892 {
893 item->setSelected( false );
894 }
895
896 currentLayout()->setSelectedItem( itemGroup );
897}
898
900{
901 if ( !currentLayout() )
902 {
903 return;
904 }
905
906 QList< QgsLayoutItem * > ungroupedItems;
907 //hunt through selection for any groups, and ungroup them
908 const QList<QgsLayoutItem *> selectionList = currentLayout()->selectedLayoutItems();
909 for ( QgsLayoutItem *item : selectionList )
910 {
911 if ( item->type() == QgsLayoutItemRegistry::LayoutGroup )
912 {
913 QgsLayoutItemGroup *itemGroup = static_cast<QgsLayoutItemGroup *>( item );
914 ungroupedItems.append( currentLayout()->ungroupItems( itemGroup ) );
915 }
916 }
917
918 if ( !ungroupedItems.empty() )
919 {
920 for ( QgsLayoutItem *item : std::as_const( ungroupedItems ) )
921 {
922 item->setSelected( true );
923 }
924 emit itemFocused( ungroupedItems.at( 0 ) );
925 }
926}
927
928void QgsLayoutView::mousePressEvent( QMouseEvent *event )
929{
930 if ( !currentLayout() )
931 return;
932
933 if ( mSnapMarker )
934 mSnapMarker->setVisible( false );
935
936 if ( mTool )
937 {
938 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
939 mTool->layoutPressEvent( me.get() );
940 event->setAccepted( me->isAccepted() );
941 }
942
943 if ( !mTool || !event->isAccepted() )
944 {
945 if ( event->button() == Qt::MiddleButton )
946 {
947 // Pan layout with middle mouse button
948 setTool( mMidMouseButtonPanTool );
949 event->accept();
950 }
951 else if ( event->button() == Qt::RightButton && mMenuProvider )
952 {
953 QMenu *menu = mMenuProvider->createContextMenu( this, currentLayout(), mapToScene( event->pos() ) );
954 if ( menu )
955 {
956 menu->exec( event->globalPos() );
957 delete menu;
958 }
959 }
960 else
961 {
962 QGraphicsView::mousePressEvent( event );
963 }
964 }
965}
966
967void QgsLayoutView::mouseReleaseEvent( QMouseEvent *event )
968{
969 if ( !currentLayout() )
970 return;
971
972 if ( mTool )
973 {
974 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
975 mTool->layoutReleaseEvent( me.get() );
976 event->setAccepted( me->isAccepted() );
977 }
978
979 if ( !mTool || !event->isAccepted() )
980 QGraphicsView::mouseReleaseEvent( event );
981}
982
983void QgsLayoutView::mouseMoveEvent( QMouseEvent *event )
984{
985 if ( !currentLayout() )
986 return;
987
988 mMouseCurrentXY = event->pos();
989
990 QPointF cursorPos = mapToScene( mMouseCurrentXY );
991 if ( mTool )
992 {
993 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, false ) );
994 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
995 {
996 me->snapPoint( mHorizontalSnapLine, mVerticalSnapLine, mTool->ignoredSnapItems() );
997 }
998 if ( mTool->flags() & QgsLayoutViewTool::FlagSnaps )
999 {
1000 //draw snapping point indicator
1001 if ( me->isSnapped() )
1002 {
1003 cursorPos = me->snappedPoint();
1004 if ( mSnapMarker )
1005 {
1006 mSnapMarker->setPos( me->snappedPoint() );
1007 mSnapMarker->setVisible( true );
1008 }
1009 }
1010 else if ( mSnapMarker )
1011 {
1012 mSnapMarker->setVisible( false );
1013 }
1014 }
1015 mTool->layoutMoveEvent( me.get() );
1016 event->setAccepted( me->isAccepted() );
1017 }
1018
1019 //update cursor position in status bar
1020 emit cursorPosChanged( cursorPos );
1021
1022 if ( !mTool || !event->isAccepted() )
1023 QGraphicsView::mouseMoveEvent( event );
1024}
1025
1027{
1028 if ( !currentLayout() )
1029 return;
1030
1031 if ( mTool )
1032 {
1033 std::unique_ptr<QgsLayoutViewMouseEvent> me( new QgsLayoutViewMouseEvent( this, event, mTool->flags() & QgsLayoutViewTool::FlagSnaps ) );
1034 mTool->layoutDoubleClickEvent( me.get() );
1035 event->setAccepted( me->isAccepted() );
1036 }
1037
1038 if ( !mTool || !event->isAccepted() )
1039 QGraphicsView::mouseDoubleClickEvent( event );
1040}
1041
1042void QgsLayoutView::wheelEvent( QWheelEvent *event )
1043{
1044 if ( !currentLayout() )
1045 return;
1046
1047 if ( mTool )
1048 {
1049 mTool->wheelEvent( event );
1050 }
1051
1052 if ( !mTool || !event->isAccepted() )
1053 {
1054 event->accept();
1055 wheelZoom( event );
1056 }
1057}
1058
1059void QgsLayoutView::keyPressEvent( QKeyEvent *event )
1060{
1061 if ( !currentLayout() )
1062 return;
1063
1064 if ( mTool )
1065 {
1066 mTool->keyPressEvent( event );
1067 }
1068
1069 if ( mTool && event->isAccepted() )
1070 return;
1071
1072 if ( event->key() == Qt::Key_Space && ! event->isAutoRepeat() )
1073 {
1074 if ( !( event->modifiers() & Qt::ControlModifier ) )
1075 {
1076 // Pan layout with space bar
1077 setTool( mSpacePanTool );
1078 }
1079 else
1080 {
1081 //ctrl+space pressed, so switch to temporary keyboard based zoom tool
1082 setTool( mSpaceZoomTool );
1083 }
1084 event->accept();
1085 }
1086 else if ( event->key() == Qt::Key_Left
1087 || event->key() == Qt::Key_Right
1088 || event->key() == Qt::Key_Up
1089 || event->key() == Qt::Key_Down )
1090 {
1091 QgsLayout *l = currentLayout();
1092 const QList<QgsLayoutItem *> layoutItemList = l->selectedLayoutItems();
1093
1094 QPointF delta = deltaForKeyEvent( event );
1095
1096 l->undoStack()->beginMacro( tr( "Move Item" ) );
1097 for ( QgsLayoutItem *item : layoutItemList )
1098 {
1099 l->undoStack()->beginCommand( item, tr( "Move Item" ), QgsLayoutItem::UndoIncrementalMove );
1100 item->attemptMoveBy( delta.x(), delta.y() );
1101 l->undoStack()->endCommand();
1102 }
1103 l->undoStack()->endMacro();
1104 event->accept();
1105 }
1106}
1107
1108void QgsLayoutView::keyReleaseEvent( QKeyEvent *event )
1109{
1110 if ( !currentLayout() )
1111 return;
1112
1113 if ( mTool )
1114 {
1115 mTool->keyReleaseEvent( event );
1116 }
1117
1118 if ( !mTool || !event->isAccepted() )
1119 QGraphicsView::keyReleaseEvent( event );
1120}
1121
1122void QgsLayoutView::resizeEvent( QResizeEvent *event )
1123{
1124 QGraphicsView::resizeEvent( event );
1125 emit zoomLevelChanged();
1126 viewChanged();
1127}
1128
1130{
1131 QGraphicsView::scrollContentsBy( dx, dy );
1132 viewChanged();
1133}
1134
1135void QgsLayoutView::dragEnterEvent( QDragEnterEvent *e )
1136{
1137 // By default graphics view delegates the drag events to graphics items.
1138 // But we do not want that and by ignoring the drag enter we let the
1139 // parent (e.g. QgsLayoutDesignerDialog) to handle drops of files.
1140 e->ignore();
1141}
1142
1143void QgsLayoutView::paintEvent( QPaintEvent *event )
1144{
1145 if ( mPaintingEnabled )
1146 {
1147 QGraphicsView::paintEvent( event );
1148 event->accept();
1149 }
1150 else
1151 {
1152 event->ignore();
1153 }
1154}
1155
1156void QgsLayoutView::invalidateCachedRenders()
1157{
1158 if ( !currentLayout() )
1159 return;
1160
1161 //redraw cached map items
1162 QList< QgsLayoutItem *> items;
1163 currentLayout()->layoutItems( items );
1164
1165 for ( QgsLayoutItem *item : std::as_const( items ) )
1166 {
1167 item->invalidateCache();
1168 }
1169}
1170
1172{
1173 if ( mHorizontalRuler )
1174 {
1175 mHorizontalRuler->setSceneTransform( viewportTransform() );
1176 }
1177 if ( mVerticalRuler )
1178 {
1179 mVerticalRuler->setSceneTransform( viewportTransform() );
1180 }
1181
1182 // determine page at center of view
1183 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1184 QRectF visibleRect = mapToScene( viewportRect ).boundingRect();
1185 QPointF centerVisible = visibleRect.center();
1186
1187 if ( currentLayout() && currentLayout()->pageCollection() )
1188 {
1189 int newPage = currentLayout()->pageCollection()->pageNumberForPoint( centerVisible );
1190 if ( newPage != mCurrentPage )
1191 {
1192 mCurrentPage = newPage;
1193 emit pageChanged( mCurrentPage );
1194 }
1195 }
1196}
1197
1198void QgsLayoutView::pushStatusMessage( const QString &message )
1199{
1200 emit statusMessage( message );
1201}
1202
1203void QgsLayoutView::wheelZoom( QWheelEvent *event )
1204{
1205 //get mouse wheel zoom behavior settings
1206 QgsSettings settings;
1207 double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
1208
1209 // "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
1210 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( event->angleDelta().y() );
1211
1212 if ( event->modifiers() & Qt::ControlModifier )
1213 {
1214 //holding ctrl while wheel zooming results in a finer zoom
1215 zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 20.0;
1216 }
1217
1218 //calculate zoom scale factor
1219 bool zoomIn = event->angleDelta().y() > 0;
1220 double scaleFactor = ( zoomIn ? 1 / zoomFactor : zoomFactor );
1221
1222 //get current visible part of scene
1223 QRect viewportRect( 0, 0, viewport()->width(), viewport()->height() );
1224 QgsRectangle visibleRect = QgsRectangle( mapToScene( viewportRect ).boundingRect() );
1225
1226 //transform the mouse pos to scene coordinates
1227#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1228 QPointF scenePoint = mapToScene( event->pos() );
1229#else
1230 QPointF scenePoint = mapToScene( event->position().x(), event->position().y() );
1231#endif
1232
1233 //adjust view center
1234 QgsPointXY oldCenter( visibleRect.center() );
1235 QgsPointXY newCenter( scenePoint.x() + ( ( oldCenter.x() - scenePoint.x() ) * scaleFactor ),
1236 scenePoint.y() + ( ( oldCenter.y() - scenePoint.y() ) * scaleFactor ) );
1237 centerOn( newCenter.x(), newCenter.y() );
1238
1239 //zoom layout
1240 if ( zoomIn )
1241 {
1242 scaleSafe( zoomFactor );
1243 }
1244 else
1245 {
1246 scaleSafe( 1 / zoomFactor );
1247 }
1248}
1249
1250QGraphicsLineItem *QgsLayoutView::createSnapLine() const
1251{
1252 std::unique_ptr< QGraphicsLineItem> item( new QGraphicsLineItem( nullptr ) );
1253 QPen pen = QPen( QColor( Qt::blue ) );
1254 pen.setStyle( Qt::DotLine );
1255 pen.setWidthF( 0.0 );
1256 item->setPen( pen );
1257 item->setZValue( QgsLayout::ZSmartGuide );
1258 return item.release();
1259}
1260
1261//
1262// QgsLayoutViewSnapMarker
1263//
1264
1266QgsLayoutViewSnapMarker::QgsLayoutViewSnapMarker()
1267 : QGraphicsRectItem( QRectF( 0, 0, 0, 0 ) )
1268{
1269 QFont f;
1270 QFontMetrics fm( f );
1271 mSize = fm.horizontalAdvance( 'X' );
1272 setPen( QPen( Qt::transparent, mSize ) );
1273
1274 setFlags( flags() | QGraphicsItem::ItemIgnoresTransformations );
1275 setZValue( QgsLayout::ZSnapIndicator );
1276}
1277
1278void QgsLayoutViewSnapMarker::paint( QPainter *p, const QStyleOptionGraphicsItem *, QWidget * )
1279{
1280 QPen pen( QColor( 255, 0, 0 ) );
1281 pen.setWidth( 0 );
1282 p->setPen( pen );
1283 p->setBrush( Qt::NoBrush );
1284
1285 double halfSize = mSize / 2.0;
1286 p->drawLine( QLineF( -halfSize, -halfSize, halfSize, halfSize ) );
1287 p->drawLine( QLineF( -halfSize, halfSize, halfSize, -halfSize ) );
1288}
1289
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.
Definition: qgslayoutview.h:78
@ PasteModeCenter
Paste items in center of view.
Definition: qgslayoutview.h:80
@ PasteModeInPlace
Paste items in place.
Definition: qgslayoutview.h:81
@ PasteModeCursor
Paste items at cursor position.
Definition: qgslayoutview.h:79
void unlockAllItems()
Unlocks all locked items in the layout.
void deleteSelectedItems()
Deletes all selected items.
void mouseMoveEvent(QMouseEvent *event) override
QgsLayout * currentLayout
Definition: qgslayoutview.h:64
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.
Definition: qgslayoutview.h:71
@ ClipboardCut
Cut items.
Definition: qgslayoutview.h:72
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
Definition: qgslayoutview.h:65
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:51
QgsLayoutModel * itemsModel()
Returns the items model attached to the layout.
Definition: qgslayout.cpp:137
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
Definition: qgslayout.cpp:459
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:122
QgsLayoutGuideCollection & guides()
Returns a reference to the layout's guide collection, which manages page snap guides.
Definition: qgslayout.cpp:385
QList< QgsLayoutItem * > ungroupItems(QgsLayoutItemGroup *group)
Ungroups items by removing them from an item group and removing the group from the layout.
Definition: qgslayout.cpp:764
bool moveItemToTop(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up to the top of the z-order.
Definition: qgslayout.cpp:212
bool moveItemToBottom(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down to the bottom of the z-order.
Definition: qgslayout.cpp:225
QgsLayoutItemGroup * groupItems(const QList< QgsLayoutItem * > &items)
Creates a new group from a list of layout items and adds the group to the layout.
Definition: qgslayout.cpp:738
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.
Definition: qgslayout.cpp:989
bool lowerItem(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down the z-order.
Definition: qgslayout.cpp:199
bool raiseItem(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up the z-order.
Definition: qgslayout.cpp:186
QList< QgsLayoutItem * > selectedLayoutItems(bool includeLockedItems=true)
Returns list of selected layout items.
Definition: qgslayout.cpp:142
void selectedItemChanged(QgsLayoutItem *selected)
Emitted whenever the selected item changes.
void deselectAll()
Clears any selected items in the layout.
Definition: qgslayout.cpp:169
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:159
void removeLayoutItem(QgsLayoutItem *item)
Removes an item from the layout.
Definition: qgslayout.cpp:556
QgsLayoutMeasurement convertFromLayoutUnits(double length, QgsUnitTypes::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
Definition: qgslayout.cpp:344
void updateZValues(bool addUndoCommands=true)
Resets the z-values of items based on their position in the internal z order list.
Definition: qgslayout.cpp:919
@ ZSmartGuide
Z-value for smart (item bounds based) guides.
Definition: qgslayout.h:63
@ ZSnapIndicator
Z-value for snapping indicator.
Definition: qgslayout.h:66
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:132
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout and it's ...
Definition: qgslayout.cpp:686
A class to represent a 2D point.
Definition: qgspointxy.h:59
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).
Definition: qgsproject.cpp:573
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
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:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:183
@ LayoutPixels
Pixels.
Definition: qgsunittypes.h:190
void selectNextByZOrder(QgsLayout *layout, bool above)
#define MAX_VIEW_SCALE
#define MIN_VIEW_SCALE