QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgslayoutguidewidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutguidewidget.cpp
3 ------------------------
4 begin : July 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8/***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "qgslayout.h"
19#include "qgslayoutview.h"
20#include "qgsdoublespinbox.h"
23#include "qgslayoutundostack.h"
24
26 : QgsPanelWidget( parent )
27 , mLayout( layout )
28{
29 setupUi( this );
30 setPanelTitle( tr( "Guides" ) );
31
32 mHozProxyModel = new QgsLayoutGuideProxyModel( mHozGuidesTableView, Qt::Horizontal, 0 );
33 mHozProxyModel->setSourceModel( &mLayout->guides() );
34 mVertProxyModel = new QgsLayoutGuideProxyModel( mVertGuidesTableView, Qt::Vertical, 0 );
35 mVertProxyModel->setSourceModel( &mLayout->guides() );
36
37 mHozGuidesTableView->setModel( mHozProxyModel );
38 mVertGuidesTableView->setModel( mVertProxyModel );
39
40 mHozGuidesTableView->setEditTriggers( QAbstractItemView::AllEditTriggers );
41 mVertGuidesTableView->setEditTriggers( QAbstractItemView::AllEditTriggers );
42
43 mHozGuidesTableView->setItemDelegateForColumn( 0, new QgsLayoutGuidePositionDelegate( mHozGuidesTableView ) );
44 mHozGuidesTableView->setItemDelegateForColumn( 1, new QgsLayoutGuideUnitDelegate( mHozGuidesTableView ) );
45
46 mVertGuidesTableView->setItemDelegateForColumn( 0, new QgsLayoutGuidePositionDelegate( mVertGuidesTableView ) );
47 mVertGuidesTableView->setItemDelegateForColumn( 1, new QgsLayoutGuideUnitDelegate( mVertGuidesTableView ) );
48
49 connect( mAddHozGuideButton, &QPushButton::clicked, this, &QgsLayoutGuideWidget::addHorizontalGuide );
50 connect( mAddVertGuideButton, &QPushButton::clicked, this, &QgsLayoutGuideWidget::addVerticalGuide );
51
52 connect( mDeleteHozGuideButton, &QPushButton::clicked, this, &QgsLayoutGuideWidget::deleteHorizontalGuide );
53 connect( mDeleteVertGuideButton, &QPushButton::clicked, this, &QgsLayoutGuideWidget::deleteVerticalGuide );
54
55 connect( mClearAllButton, &QPushButton::clicked, this, &QgsLayoutGuideWidget::clearAll );
56 connect( mApplyToAllButton, &QPushButton::clicked, this, &QgsLayoutGuideWidget::applyToAll );
57
58 connect( mLayout->pageCollection(), &QgsLayoutPageCollection::changed, this, &QgsLayoutGuideWidget::updatePageCount );
59 updatePageCount();
60 connect( mPageNumberComboBox, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
61 {
62 setCurrentPage( mPageNumberComboBox->currentData().toInt() );
63 } );
64
66 setCurrentPage( 0 );
67}
68
69void QgsLayoutGuideWidget::addHorizontalGuide()
70{
71 std::unique_ptr< QgsLayoutGuide > newGuide( new QgsLayoutGuide( Qt::Horizontal, QgsLayoutMeasurement( 0 ), mLayout->pageCollection()->page( mPage ) ) );
72 mLayout->guides().addGuide( newGuide.release() );
73}
74
75void QgsLayoutGuideWidget::addVerticalGuide()
76{
77 std::unique_ptr< QgsLayoutGuide > newGuide( new QgsLayoutGuide( Qt::Vertical, QgsLayoutMeasurement( 0 ), mLayout->pageCollection()->page( mPage ) ) );
78 mLayout->guides().addGuide( newGuide.release() );
79}
80
81void QgsLayoutGuideWidget::deleteHorizontalGuide()
82{
83 mLayout->undoStack()->beginMacro( tr( "Remove Horizontal Guides" ) );
84 const auto constSelectedIndexes = mHozGuidesTableView->selectionModel()->selectedIndexes();
85 for ( const QModelIndex &index : constSelectedIndexes )
86 {
87 mHozGuidesTableView->closePersistentEditor( index );
88 if ( index.column() == 0 )
89 mHozProxyModel->removeRow( index.row() );
90 }
91 mLayout->undoStack()->endMacro();
92}
93
94void QgsLayoutGuideWidget::deleteVerticalGuide()
95{
96 mLayout->undoStack()->beginMacro( tr( "Remove Vertical Guides" ) );
97 const auto constSelectedIndexes = mVertGuidesTableView->selectionModel()->selectedIndexes();
98 for ( const QModelIndex &index : constSelectedIndexes )
99 {
100 mVertGuidesTableView->closePersistentEditor( index );
101 if ( index.column() == 0 )
102 mVertProxyModel->removeRow( index.row() );
103 }
104 mLayout->undoStack()->endMacro();
105}
106
108{
109 mPage = page;
110
111 // have to close any open editors - or we'll get a crash
112
113 // qt - y u no do this for me?
114 const auto horizontalSelectedIndexes = mHozGuidesTableView->selectionModel()->selectedIndexes();
115 for ( const QModelIndex &index : horizontalSelectedIndexes )
116 {
117 mHozGuidesTableView->closePersistentEditor( index );
118 }
119 const auto verticalSelectedIndexes = mVertGuidesTableView->selectionModel()->selectedIndexes();
120 for ( const QModelIndex &index : verticalSelectedIndexes )
121 {
122 mVertGuidesTableView->closePersistentEditor( index );
123 }
124
125 mHozProxyModel->setPage( page );
126 mVertProxyModel->setPage( page );
127
128 whileBlocking( mPageNumberComboBox )->setCurrentIndex( page );
129}
130
131void QgsLayoutGuideWidget::clearAll()
132{
133 // qt - y u no do this for me?
134 const auto horizontalSelectedIndexes = mHozGuidesTableView->selectionModel()->selectedIndexes();
135 for ( const QModelIndex &index : horizontalSelectedIndexes )
136 {
137 mHozGuidesTableView->closePersistentEditor( index );
138 }
139 const auto verticalSelectedIndexes = mVertGuidesTableView->selectionModel()->selectedIndexes();
140 for ( const QModelIndex &index : verticalSelectedIndexes )
141 {
142 mVertGuidesTableView->closePersistentEditor( index );
143 }
144
145 mLayout->undoStack()->beginMacro( tr( "Remove All Guides" ) );
146 mVertProxyModel->removeRows( 0, mVertProxyModel->rowCount() );
147 mHozProxyModel->removeRows( 0, mHozProxyModel->rowCount() );
148 mLayout->undoStack()->endMacro();
149}
150
151void QgsLayoutGuideWidget::applyToAll()
152{
153 mLayout->guides().applyGuidesToAllOtherPages( mPage );
154}
155
156void QgsLayoutGuideWidget::updatePageCount()
157{
158 const int prevPage = mPageNumberComboBox->currentIndex();
159 mPageNumberComboBox->clear();
160 for ( int i = 0; i < mLayout->pageCollection()->pageCount(); ++ i )
161 mPageNumberComboBox->addItem( QString::number( i + 1 ), i );
162
163 if ( mPageNumberComboBox->count() > prevPage )
164 mPageNumberComboBox->setCurrentIndex( prevPage );
165}
166
167
169 : QStyledItemDelegate( parent )
170{
171
172}
173
174QWidget *QgsLayoutGuidePositionDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
175{
176 QgsDoubleSpinBox *spin = new QgsDoubleSpinBox( parent );
177 spin->setMinimum( 0 );
178 spin->setMaximum( 1000000 );
179 spin->setDecimals( 2 );
180 spin->setShowClearButton( false );
181 connect( spin, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double )
182 {
183 // we want to update on every spin change, not just the final
184 const_cast< QgsLayoutGuidePositionDelegate * >( this )->emit commitData( spin );
185 } );
186 return spin;
187}
188
189void QgsLayoutGuidePositionDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
190{
191 QgsDoubleSpinBox *spin = qobject_cast< QgsDoubleSpinBox * >( editor );
192 model->setData( index, spin->value(), static_cast< int >( QgsLayoutGuideCollection::CustomRole::Position ) );
193}
194
196 : QStyledItemDelegate( parent )
197{
198}
199
200QWidget *QgsLayoutGuideUnitDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
201{
202 QgsLayoutUnitsComboBox *unitsCb = new QgsLayoutUnitsComboBox( parent );
203 connect( unitsCb, &QgsLayoutUnitsComboBox::unitChanged, this, [ = ]( Qgis::LayoutUnit )
204 {
205 // we want to update on every unit change, not just the final
206 const_cast< QgsLayoutGuideUnitDelegate * >( this )->emit commitData( unitsCb );
207 } );
208 return unitsCb;
209}
210
211void QgsLayoutGuideUnitDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
212{
213 QgsLayoutUnitsComboBox *cb = qobject_cast< QgsLayoutUnitsComboBox *>( editor );
214 model->setData( index, static_cast< int >( cb->unit() ), static_cast< int >( QgsLayoutGuideCollection::CustomRole::Units ) );
215}
216
LayoutUnit
Layout measurement units.
Definition: qgis.h:4275
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
void addGuide(QgsLayoutGuide *guide)
Adds a guide to the collection.
@ Units
Guide position units role.
void applyGuidesToAllOtherPages(int sourcePage)
Resets all other pages' guides to match the guides from the specified sourcePage.
View delegate displaying a QgsDoubleSpinBox for the layout guide position.
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const override
QgsLayoutGuidePositionDelegate(QObject *parent)
constructor
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
Filters QgsLayoutGuideCollection models to guides of a single orientation (horizontal or vertical).
void setPage(int page)
Sets the current page for filtering matching guides.
View delegate displaying a QgsLayoutUnitsComboBox for the layout guide unit.
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
QgsLayoutGuideUnitDelegate(QObject *parent)
constructor
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const override
QgsLayoutGuideWidget(QWidget *parent, QgsLayout *layout, QgsLayoutView *layoutView)
constructor
void setCurrentPage(int page)
Sets the current page number to manage the guides for.
Contains the configuration for a single snap guide used by a layout.
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
void changed()
Emitted when pages are added or removed from the collection.
QgsLayoutItemPage * page(int pageNumber)
Returns a specific page (by pageNumber) from the collection.
void beginMacro(const QString &commandText)
Starts a macro command, with the given descriptive commandText.
void endMacro()
Ends a macro command.
A custom combo box for selecting units for layout settings.
void unitChanged(Qgis::LayoutUnit unit)
Emitted when the unit is changed.
A graphical widget to display and interact with QgsLayouts.
Definition: qgslayoutview.h:50
void pageChanged(int page)
Emitted when the page visible in the view is changed.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
Definition: qgslayout.cpp:476
QgsLayoutGuideCollection & guides()
Returns a reference to the layout's guide collection, which manages page snap guides.
Definition: qgslayout.cpp:402
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:703
Base class for any widget that can be shown as a inline panel.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:5111