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