QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
17 #include "qgslayoutguidewidget.h"
18 #include "qgslayout.h"
19 #include "qgslayoutview.h"
20 #include "qgsdoublespinbox.h"
21 #include "qgslayoutunitscombobox.h"
23 #include "qgslayoutundostack.h"
24 
25 QgsLayoutGuideWidget::QgsLayoutGuideWidget( QWidget *parent, QgsLayout *layout, QgsLayoutView *layoutView )
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 
69 void 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 
75 void 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 
81 void 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 
94 void 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 
131 void 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 
151 void QgsLayoutGuideWidget::applyToAll()
152 {
153  mLayout->guides().applyGuidesToAllOtherPages( mPage );
154 }
155 
156 void 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 
174 QWidget *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 
189 void QgsLayoutGuidePositionDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
190 {
191  QgsDoubleSpinBox *spin = qobject_cast< QgsDoubleSpinBox * >( editor );
192  model->setData( index, spin->value(), QgsLayoutGuideCollection::PositionRole );
193 }
194 
196  : QStyledItemDelegate( parent )
197 {
198 }
199 
200 QWidget *QgsLayoutGuideUnitDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
201 {
202  QgsLayoutUnitsComboBox *unitsCb = new QgsLayoutUnitsComboBox( parent );
203  connect( unitsCb, &QgsLayoutUnitsComboBox::changed, this, [ = ]( int )
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 
211 void QgsLayoutGuideUnitDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
212 {
213  QgsLayoutUnitsComboBox *cb = qobject_cast< QgsLayoutUnitsComboBox *>( editor );
214  model->setData( index, cb->unit(), QgsLayoutGuideCollection::UnitsRole );
215 }
216 
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.
void applyGuidesToAllOtherPages(int sourcePage)
Resets all other pages' guides to match the guides from the specified sourcePage.
@ PositionRole
Guide position role.
@ UnitsRole
Guide position units role.
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 changed(QgsUnitTypes::LayoutUnit unit)
Emitted when the unit is changed.
QgsUnitTypes::LayoutUnit unit
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:51
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
Definition: qgslayout.cpp:459
QgsLayoutGuideCollection & guides()
Returns a reference to the layout's guide collection, which manages page snap guides.
Definition: qgslayout.cpp:385
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
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:537