25#include <QGraphicsLineItem>
27#include "moc_qgslayoutguidecollection.cpp"
42 if ( mLayout && mLineItem )
44 mLayout->removeItem( mLineItem );
74 if ( !mLayout || !mLineItem )
84 double layoutPos = mLayout->convertToLayoutUnits( mPosition );
85 bool showGuide = mLayout->guides().visible();
86 switch ( mOrientation )
89 if ( layoutPos > mPage->rect().height() )
95 mLineItem->setLine( 0, layoutPos + mPage->y(), mPage->rect().width(), layoutPos + mPage->y() );
96 mLineItem->setVisible( showGuide );
102 if ( layoutPos > mPage->rect().width() )
108 mLineItem->setLine( layoutPos, mPage->y(), layoutPos, mPage->y() + mPage->rect().height() );
109 mLineItem->setVisible( showGuide );
126 switch ( mOrientation )
129 return mLineItem->mapToScene( mLineItem->line().p1() ).y();
132 return mLineItem->mapToScene( mLineItem->line().p1() ).x();
143 switch ( mOrientation )
146 p = mPage->mapFromScene( QPointF( 0,
position ) ).y();
150 p = mPage->mapFromScene( QPointF(
position, 0 ) ).x();
153 mPosition = mLayout->convertFromLayoutUnits( p, mPosition.units() );
169 mLineItem =
new QGraphicsLineItem();
172 QPen linePen( Qt::DotLine );
173 linePen.setColor( Qt::red );
176 linePen.setWidthF( 0 );
177 mLineItem->setPen( linePen );
180 mLayout->addItem( mLineItem );
196 : QAbstractTableModel(
layout )
198 , mPageCollection( pageCollection )
201 mHeaderSize = QFontMetrics( f ).boundingRect( QStringLiteral(
"XX" ) ).width();
208 qDeleteAll( mGuides );
218 return mGuides.count();
223 if ( parent.isValid() )
231 if ( !index.isValid() )
234 if ( index.row() >= mGuides.count() || index.row() < 0 )
240 case Qt::DisplayRole:
243 if ( index.column() == 0 )
250 return QVariant::fromValue( guide->
orientation() );
256 return static_cast< int >( guide->
position().units() );
259 return mPageCollection->pageNumber( guide->
page() );
271 if ( !index.isValid() )
274 if ( index.row() >= mGuides.count() || index.row() < 0 )
284 double newPos = value.toDouble( &ok );
290 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
293 mLayout->undoStack()->endCommand();
294 emit dataChanged( index, index, QVector<int>() << role );
300 double newPos = value.toDouble( &ok );
309 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
312 mLayout->undoStack()->endCommand();
313 emit dataChanged( index, index, QVector<int>() << role );
320 double newPos = value.toDouble( &ok );
324 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
326 mLayout->undoStack()->endCommand();
327 emit dataChanged( index, index, QVector<int>() << role );
334 int units = value.toInt( &ok );
340 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Move Guide" ), Move + index.row() );
343 mLayout->undoStack()->endCommand();
344 emit dataChanged( index, index, QVector<int>() << role );
357 if ( !index.isValid() )
358 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
359 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
364 if ( role == Qt::DisplayRole )
366 else if ( role == Qt::SizeHintRole )
368 return QSize( mHeaderSize, mHeaderSize );
370 return QAbstractTableModel::headerData( section, orientation, role );
375 if ( parent.isValid() )
378 if ( !mBlockUndoCommands )
379 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Remove Guide(s)" ), Remove + row );
380 beginRemoveRows( parent, row, row + count - 1 );
381 for (
int i = 0; i < count; ++ i )
383 delete mGuides.takeAt( row );
386 if ( !mBlockUndoCommands )
387 mLayout->undoStack()->endCommand();
393 if ( guide->
layout() != mLayout )
396 if ( !mBlockUndoCommands )
397 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Create Guide" ) );
398 beginInsertRows( QModelIndex(), mGuides.count(), mGuides.count() );
399 mGuides.append( guide );
401 if ( !mBlockUndoCommands )
402 mLayout->undoStack()->endCommand();
404 QModelIndex index = createIndex( mGuides.length() - 1, 0 );
407 emit dataChanged( index, index );
413 int row = mGuides.indexOf( guide );
422 int row = mGuides.indexOf( guide );
431 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Clear Guides" ) );
433 qDeleteAll( mGuides );
436 mLayout->undoStack()->endCommand();
441 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Apply Guides" ) );
442 mBlockUndoCommands =
true;
445 const auto constMGuides = mGuides;
448 if ( guide->page() != page )
453 const auto constMGuidesNew = mGuides;
456 for (
int p = 0; p < mPageCollection->pageCount(); ++p )
458 if ( p == sourcePage )
461 auto newGuide = std::make_unique<QgsLayoutGuide>( guide->orientation(), guide->position(), mPageCollection->page( p ) );
462 newGuide->setLayout( mLayout );
463 if ( newGuide->item()->isVisible() )
470 mLayout->undoStack()->endCommand();
471 mBlockUndoCommands =
false;
476 const auto constMGuides = mGuides;
490 QList<QgsLayoutGuide *> res;
491 const auto constMGuides = mGuides;
494 if ( guide->orientation() == orientation && guide->item()->isVisible() &&
495 ( page < 0 || mPageCollection->page( page ) == guide->page() ) )
503 QList<QgsLayoutGuide *> res;
504 const auto constMGuides = mGuides;
507 if ( mPageCollection->page( page ) == guide->page() )
515 return mGuidesVisible;
520 mLayout->undoStack()->beginCommand( mPageCollection, tr(
"Change Guide Visibility" ) );
522 mLayout->undoStack()->endCommand();
526void QgsLayoutGuideCollection::pageAboutToBeRemoved(
int pageNumber )
528 mBlockUndoCommands =
true;
529 const auto constGuidesOnPage =
guidesOnPage( pageNumber );
534 mBlockUndoCommands =
false;
539 QDomElement element = document.createElement( QStringLiteral(
"GuideCollection" ) );
540 element.setAttribute( QStringLiteral(
"visible" ), mGuidesVisible );
541 const auto constMGuides = mGuides;
544 QDomElement guideElement = document.createElement( QStringLiteral(
"Guide" ) );
545 guideElement.setAttribute( QStringLiteral(
"orientation" ), guide->orientation() );
546 guideElement.setAttribute( QStringLiteral(
"page" ), mPageCollection->pageNumber( guide->page() ) );
547 guideElement.setAttribute( QStringLiteral(
"position" ), guide->position().length() );
549 element.appendChild( guideElement );
552 parentElement.appendChild( element );
558 QDomElement element = e;
559 if ( element.nodeName() != QLatin1String(
"GuideCollection" ) )
561 element = element.firstChildElement( QStringLiteral(
"GuideCollection" ) );
564 if ( element.nodeName() != QLatin1String(
"GuideCollection" ) )
569 mBlockUndoCommands =
true;
571 qDeleteAll( mGuides );
574 mGuidesVisible = element.attribute( QStringLiteral(
"visible" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" );
575 QDomNodeList guideNodeList = element.elementsByTagName( QStringLiteral(
"Guide" ) );
576 for (
int i = 0; i < guideNodeList.size(); ++i )
578 QDomElement element = guideNodeList.at( i ).toElement();
579 Qt::Orientation orientation =
static_cast< Qt::Orientation
>( element.attribute( QStringLiteral(
"orientation" ), QStringLiteral(
"1" ) ).toInt() );
580 double pos = element.attribute( QStringLiteral(
"position" ), QStringLiteral(
"0" ) ).toDouble();
582 int page = element.attribute( QStringLiteral(
"page" ), QStringLiteral(
"0" ) ).toInt();
583 auto guide = std::make_unique<QgsLayoutGuide>( orientation,
QgsLayoutMeasurement( pos, unit ), mPageCollection->page( page ) );
589 mBlockUndoCommands =
false;
598 : QSortFilterProxyModel( parent )
599 , mOrientation( orientation )
602 setDynamicSortFilter(
true );
614 QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
616 if ( orientation != mOrientation )
620 return page == mPage;
627 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.