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