25#include <QGraphicsLineItem>
28#include "moc_qgslayoutguidecollection.cpp"
30using namespace Qt::StringLiterals;
45 if ( mLayout && mLineItem )
47 mLayout->removeItem( mLineItem );
77 if ( !mLayout || !mLineItem )
87 double layoutPos = mLayout->convertToLayoutUnits( mPosition );
88 bool showGuide = mLayout->guides().visible();
89 switch ( mOrientation )
92 if ( layoutPos > mPage->rect().height() )
98 mLineItem->setLine( 0, layoutPos + mPage->y(), mPage->rect().width(), layoutPos + mPage->y() );
99 mLineItem->setVisible( showGuide );
105 if ( layoutPos > mPage->rect().width() )
111 mLineItem->setLine( layoutPos, mPage->y(), layoutPos, mPage->y() + mPage->rect().height() );
112 mLineItem->setVisible( showGuide );
129 switch ( mOrientation )
132 return mLineItem->mapToScene( mLineItem->line().p1() ).y();
135 return mLineItem->mapToScene( mLineItem->line().p1() ).x();
146 switch ( mOrientation )
149 p = mPage->mapFromScene( QPointF( 0,
position ) ).y();
153 p = mPage->mapFromScene( QPointF(
position, 0 ) ).x();
156 mPosition = mLayout->convertFromLayoutUnits( p, mPosition.units() );
172 mLineItem =
new QGraphicsLineItem();
175 QPen linePen( Qt::DotLine );
176 linePen.setColor( Qt::red );
179 linePen.setWidthF( 0 );
180 mLineItem->setPen( linePen );
183 mLayout->addItem( mLineItem );
199 : QAbstractTableModel(
layout )
201 , mPageCollection( pageCollection )
204 mHeaderSize = QFontMetrics( f ).boundingRect( u
"XX"_s ).width();
211 qDeleteAll( mGuides );
221 return mGuides.count();
226 if ( parent.isValid() )
234 if ( !index.isValid() )
237 if ( index.row() >= mGuides.count() || index.row() < 0 )
243 case Qt::DisplayRole:
246 if ( index.column() == 0 )
253 return QVariant::fromValue( guide->
orientation() );
259 return static_cast< int >( guide->
position().units() );
262 return mPageCollection->pageNumber( guide->
page() );
274 if ( !index.isValid() )
277 if ( index.row() >= mGuides.count() || index.row() < 0 )
287 double newPos = value.toDouble( &ok );
293 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
296 mLayout->undoStack()->endCommand();
297 emit dataChanged( index, index, QVector<int>() << role );
303 double newPos = value.toDouble( &ok );
312 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
315 mLayout->undoStack()->endCommand();
316 emit dataChanged( index, index, QVector<int>() << role );
323 double newPos = value.toDouble( &ok );
327 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
329 mLayout->undoStack()->endCommand();
330 emit dataChanged( index, index, QVector<int>() << role );
337 int units = value.toInt( &ok );
343 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
346 mLayout->undoStack()->endCommand();
347 emit dataChanged( index, index, QVector<int>() << role );
360 if ( !index.isValid() )
361 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
362 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
367 if ( role == Qt::DisplayRole )
369 else if ( role == Qt::SizeHintRole )
371 return QSize( mHeaderSize, mHeaderSize );
373 return QAbstractTableModel::headerData( section, orientation, role );
378 if ( parent.isValid() )
381 if ( !mBlockUndoCommands )
382 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Remove Guide(s)" ), Remove + row );
383 beginRemoveRows( parent, row, row + count - 1 );
384 for (
int i = 0; i < count; ++ i )
386 delete mGuides.takeAt( row );
389 if ( !mBlockUndoCommands )
390 mLayout->undoStack()->endCommand();
396 if ( guide->
layout() != mLayout )
399 if ( !mBlockUndoCommands )
400 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Create Guide" ) );
401 beginInsertRows( QModelIndex(), mGuides.count(), mGuides.count() );
402 mGuides.append( guide );
404 if ( !mBlockUndoCommands )
405 mLayout->undoStack()->endCommand();
407 QModelIndex index = createIndex( mGuides.length() - 1, 0 );
410 emit dataChanged( index, index );
416 int row = mGuides.indexOf( guide );
425 int row = mGuides.indexOf( guide );
434 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Clear Guides" ) );
436 qDeleteAll( mGuides );
439 mLayout->undoStack()->endCommand();
444 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Apply Guides" ) );
445 mBlockUndoCommands =
true;
448 const auto constMGuides = mGuides;
451 if ( guide->page() != page )
456 const auto constMGuidesNew = mGuides;
459 for (
int p = 0; p < mPageCollection->pageCount(); ++p )
461 if ( p == sourcePage )
464 auto newGuide = std::make_unique<QgsLayoutGuide>( guide->orientation(), guide->position(), mPageCollection->page( p ) );
465 newGuide->setLayout( mLayout );
466 if ( newGuide->item()->isVisible() )
473 mLayout->undoStack()->endCommand();
474 mBlockUndoCommands =
false;
479 const auto constMGuides = mGuides;
493 QList<QgsLayoutGuide *> res;
494 const auto constMGuides = mGuides;
497 if ( guide->orientation() == orientation && guide->item()->isVisible() &&
498 ( page < 0 || mPageCollection->page( page ) == guide->page() ) )
506 QList<QgsLayoutGuide *> res;
507 const auto constMGuides = mGuides;
510 if ( mPageCollection->page( page ) == guide->page() )
518 return mGuidesVisible;
523 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Change Guide Visibility" ) );
525 mLayout->undoStack()->endCommand();
529void QgsLayoutGuideCollection::pageAboutToBeRemoved(
int pageNumber )
531 mBlockUndoCommands =
true;
532 const auto constGuidesOnPage =
guidesOnPage( pageNumber );
537 mBlockUndoCommands =
false;
542 QDomElement element = document.createElement( u
"GuideCollection"_s );
543 element.setAttribute( u
"visible"_s, mGuidesVisible );
544 const auto constMGuides = mGuides;
547 QDomElement guideElement = document.createElement( u
"Guide"_s );
548 guideElement.setAttribute( u
"orientation"_s, guide->orientation() );
549 guideElement.setAttribute( u
"page"_s, mPageCollection->pageNumber( guide->page() ) );
550 guideElement.setAttribute( u
"position"_s, guide->position().length() );
552 element.appendChild( guideElement );
555 parentElement.appendChild( element );
561 QDomElement element = e;
562 if ( element.nodeName() !=
"GuideCollection"_L1 )
564 element = element.firstChildElement( u
"GuideCollection"_s );
567 if ( element.nodeName() !=
"GuideCollection"_L1 )
572 mBlockUndoCommands =
true;
574 qDeleteAll( mGuides );
577 mGuidesVisible = element.attribute( u
"visible"_s, u
"0"_s ) !=
"0"_L1;
578 QDomNodeList guideNodeList = element.elementsByTagName( u
"Guide"_s );
579 for (
int i = 0; i < guideNodeList.size(); ++i )
581 QDomElement element = guideNodeList.at( i ).toElement();
582 Qt::Orientation orientation =
static_cast< Qt::Orientation
>( element.attribute( u
"orientation"_s, u
"1"_s ).toInt() );
583 double pos = element.attribute( u
"position"_s, u
"0"_s ).toDouble();
585 int page = element.attribute( u
"page"_s, u
"0"_s ).toInt();
586 auto guide = std::make_unique<QgsLayoutGuide>( orientation,
QgsLayoutMeasurement( pos, unit ), mPageCollection->page( page ) );
592 mBlockUndoCommands =
false;
601 : QSortFilterProxyModel( parent )
602 , mOrientation( orientation )
605 setDynamicSortFilter(
true );
617 QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
619 if ( orientation != mOrientation )
623 return page == mPage;
630 return leftPos < rightPos;
LayoutUnit
Layout measurement units.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores the collection's state in a DOM element.
int columnCount(const QModelIndex &) const override
void addGuide(QgsLayoutGuide *guide)
Adds a guide to the collection.
bool setData(const QModelIndex &index, const QVariant &value, int role) override
QgsLayout * layout() override
Returns the layout the object belongs to.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QgsLayoutGuideCollection(QgsLayout *layout, QgsLayoutPageCollection *pageCollection)
Constructor for QgsLayoutGuideCollection belonging to the specified layout, and linked to the specifi...
bool readXml(const QDomElement &collectionElement, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets the collection's state from a DOM element.
@ Position
Guide position role.
@ LayoutPosition
Guide position in layout coordinates.
@ Orientation
Guide orientation role.
@ Units
Guide position units role.
QVariant data(const QModelIndex &index, int role) const override
void applyGuidesToAllOtherPages(int sourcePage)
Resets all other pages' guides to match the guides from the specified sourcePage.
void removeGuide(QgsLayoutGuide *guide)
Removes the specified guide, and deletes it.
QList< QgsLayoutGuide * > guidesOnPage(int page)
Returns the list of guides contained on a matching page.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
~QgsLayoutGuideCollection() override
void setGuideLayoutPosition(QgsLayoutGuide *guide, double position)
Sets the absolute position (in layout coordinates) for guide within the layout.
QList< QgsLayoutGuide * > guides()
Returns a list of all guides contained in the collection.
int rowCount(const QModelIndex &) const override
void clear()
Removes all guides from the collection.
Qt::ItemFlags flags(const QModelIndex &index) const override
bool visible() const
Returns true if the guide lines should be drawn.
void update()
Updates the position (and visibility) of all guide line items.
void setVisible(bool visible)
Sets whether the guide lines should be visible.
void setPage(int page)
Sets the current page for filtering matching guides.
QgsLayoutGuideProxyModel(QObject *parent, Qt::Orientation orientation, int page)
Constructor for QgsLayoutGuideProxyModel, filtered to guides of the specified orientation and page on...
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Contains the configuration for a single snap guide used by a layout.
QgsLayoutMeasurement position() const
Returns the guide's position within the page.
QgsLayoutItemPage * page()
Returns the page the guide is contained within.
Qt::Orientation orientation() const
Returns the guide's orientation.
QgsLayout * layout() const
Returns the layout the guide belongs to.
void setLayout(QgsLayout *layout)
Sets the layout the guide belongs to.
~QgsLayoutGuide() override
void setLayoutPosition(double position)
Sets the guide's position in absolute layout units.
void setPage(QgsLayoutItemPage *page)
Sets the page the guide is contained within.
void setPosition(QgsLayoutMeasurement position)
Sets the guide's position within the page.
QgsLayoutGuide(Qt::Orientation orientation, QgsLayoutMeasurement position, QgsLayoutItemPage *page)
Constructor for a new guide with the specified orientation and initial position.
double layoutPosition() const
Returns the guide's position in absolute layout units.
void positionChanged()
Emitted when the guide's position is changed.
void update()
Updates the position of the guide's line item.
QGraphicsLineItem * item()
Returns the guide's line item.
Item representing the paper in a layout.
int page() const
Returns the page the item is currently on, with the first page returning 0.
Provides a method of storing measurements for use in QGIS layouts using a variety of different measur...
void setLength(const double length)
Sets the length of the measurement.
Qgis::LayoutUnit units() const
Returns the units for the measurement.
void setUnits(const Qgis::LayoutUnit units)
Sets the units for the measurement.
double length() const
Returns the length of the measurement.
A manager for a collection of pages in a layout.
void pageAboutToBeRemoved(int pageNumber)
Emitted just before a page is removed from the collection.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
@ ZGuide
Z-value for page guides.
A container for the context for various read/write operations on objects.
static Q_INVOKABLE QString toAbbreviatedString(Qgis::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
static Q_INVOKABLE Qgis::LayoutUnit decodeLayoutUnit(const QString &string, bool *ok=nullptr)
Decodes a layout unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.