26 #include <QMessageBox> 42 if ( !layout || mLayouts.contains( layout ) )
48 if ( l->name() == layout->
name() )
56 if (
QgsPrintLayout *l = dynamic_cast< QgsPrintLayout * >( layout ) )
63 else if ( QgsReport *r = dynamic_cast< QgsReport * >( layout ) )
65 connect( r, &QgsReport::nameChanged,
this, [
this, r](
const QString & newName )
83 if ( !mLayouts.contains( layout ) )
86 QString name = layout->
name();
88 mLayouts.removeAll( layout );
97 const QList< QgsMasterLayoutInterface * >
layouts = mLayouts;
111 QList<QgsPrintLayout *> result;
112 const QList<QgsMasterLayoutInterface *> _layouts( mLayouts );
113 result.reserve( _layouts.size() );
114 for (
const auto &layout : _layouts )
116 QgsPrintLayout *_item( dynamic_cast<QgsPrintLayout *>( layout ) );
118 result.push_back( _item );
127 if ( l->name() == name )
137 QDomElement layoutsElem = element;
138 if ( element.tagName() != QStringLiteral(
"Layouts" ) )
140 layoutsElem = element.firstChildElement( QStringLiteral(
"Layouts" ) );
142 if ( layoutsElem.isNull() )
145 layoutsElem = doc.documentElement();
150 QDomNodeList composerNodes = element.elementsByTagName( QStringLiteral(
"Composer" ) );
151 for (
int i = 0; i < composerNodes.size(); ++i )
154 QString legacyTitle = composerNodes.at( i ).toElement().attribute( QStringLiteral(
"title" ) );
156 QDomNodeList compositionNodes = composerNodes.at( i ).toElement().elementsByTagName( QStringLiteral(
"Composition" ) );
157 for (
int j = 0; j < compositionNodes.size(); ++j )
162 if ( l->name().isEmpty() )
163 l->setName( legacyTitle );
168 bool isDuplicateName =
false;
169 QString originalName = l->name();
172 isDuplicateName =
false;
175 if ( l->name() == layout->name() )
177 isDuplicateName =
true;
181 if ( isDuplicateName )
183 l->setName( QStringLiteral(
"%1 %2" ).arg( originalName ).arg(
id ) );
187 while ( isDuplicateName );
190 result = added && result;
199 const QDomNodeList layoutNodes = layoutsElem.childNodes();
200 for (
int i = 0; i < layoutNodes.size(); ++i )
202 if ( layoutNodes.at( i ).nodeName() != QStringLiteral(
"Layout" ) )
205 std::unique_ptr< QgsPrintLayout > l = qgis::make_unique< QgsPrintLayout >( mProject );
206 l->undoStack()->blockCommands(
true );
207 if ( !l->readLayoutXml( layoutNodes.at( i ).toElement(), doc, context ) )
212 l->undoStack()->blockCommands(
false );
223 const QDomNodeList reportNodes = element.elementsByTagName( QStringLiteral(
"Report" ) );
224 for (
int i = 0; i < reportNodes.size(); ++i )
226 std::unique_ptr< QgsReport > r = qgis::make_unique< QgsReport >( mProject );
227 if ( !r->readLayoutXml( reportNodes.at( i ).toElement(), doc, context ) )
246 QDomElement layoutsElem = doc.createElement( QStringLiteral(
"Layouts" ) );
252 QDomElement layoutElem = l->writeLayoutXml( doc, context );
253 layoutsElem.appendChild( layoutElem );
263 std::unique_ptr< QgsMasterLayoutInterface > newLayout( layout->
clone() );
284 names.reserve( mLayouts.size() );
291 while ( name.isEmpty() || names.contains( name ) )
296 name = tr(
"Layout %1" ).arg(
id );
299 name = tr(
"Report %1" ).arg(
id );
309 if ( mLayouts.empty() )
318 if ( !l->layoutAccept( visitor ) )
335 : QAbstractListModel( parent )
336 , mLayoutManager( manager )
348 return ( mLayoutManager ? mLayoutManager->
layouts().count() : 0 ) + ( mAllowEmpty ? 1 : 0 );
353 if ( index.row() < 0 || index.row() >=
rowCount( QModelIndex() ) )
356 const bool isEmpty = index.row() == 0 && mAllowEmpty;
357 const int layoutRow = mAllowEmpty ? index.row() - 1 : index.row();
361 case Qt::DisplayRole:
362 case Qt::ToolTipRole:
364 return !isEmpty && mLayoutManager ? mLayoutManager->
layouts().at( layoutRow )->name() : QVariant();
368 if ( isEmpty || !mLayoutManager )
370 else if (
QgsLayout *l = dynamic_cast< QgsLayout * >( mLayoutManager->
layouts().at( layoutRow ) ) )
371 return QVariant::fromValue( l );
372 else if ( QgsReport *r = dynamic_cast< QgsReport * >( mLayoutManager->
layouts().at( layoutRow ) ) )
373 return QVariant::fromValue( r );
378 case Qt::DecorationRole:
380 return isEmpty || !mLayoutManager ? QIcon() : mLayoutManager->
layouts().at( layoutRow )->icon();
390 if ( !index.isValid() || role != Qt::EditRole )
394 if ( index.row() >= mLayoutManager->
layouts().count() )
399 if ( index.row() == 0 && mAllowEmpty )
402 if ( value.toString().isEmpty() )
410 bool changed = layout->
name() != value.toString();
415 QStringList layoutNames;
419 layoutNames << l->name();
421 if ( layoutNames.contains( value.toString() ) )
424 QMessageBox::warning(
nullptr, tr(
"Rename Layout" ), tr(
"There is already a layout named “%1”." ).arg( value.toString() ) );
428 layout->
setName( value.toString() );
434 Qt::ItemFlags
flags = QAbstractListModel::flags( index );
435 #if 0 // double-click is now used for opening the layout 436 if ( index.isValid() )
438 return flags | Qt::ItemIsEditable;
450 if ( index.row() == 0 && mAllowEmpty )
455 else if ( QgsReport *r = qobject_cast< QgsReport * >( qvariant_cast<QObject *>(
data( index,
LayoutRole ) ) ) )
463 if ( !mLayoutManager )
465 return QModelIndex();
468 const int r = mLayoutManager->
layouts().indexOf( layout );
470 return QModelIndex();
472 QModelIndex idx = index( mAllowEmpty ? r + 1 : r, 0, QModelIndex() );
478 return QModelIndex();
483 if ( allowEmpty == mAllowEmpty )
488 beginInsertRows( QModelIndex(), 0, 0 );
494 beginRemoveRows( QModelIndex(), 0, 0 );
500 void QgsLayoutManagerModel::layoutAboutToBeAdded(
const QString & )
502 int row = mLayoutManager->
layouts().count() + ( mAllowEmpty ? 1 : 0 );
503 beginInsertRows( QModelIndex(), row, row );
506 void QgsLayoutManagerModel::layoutAboutToBeRemoved(
const QString &name )
509 int row = mLayoutManager->
layouts().indexOf( l ) + ( mAllowEmpty ? 1 : 0 );
511 beginRemoveRows( QModelIndex(), row, row );
514 void QgsLayoutManagerModel::layoutAdded(
const QString & )
519 void QgsLayoutManagerModel::layoutRemoved(
const QString & )
526 int row = mLayoutManager->
layouts().indexOf( layout ) + ( mAllowEmpty ? 1 : 0 );
527 QModelIndex index = createIndex( row, 0 );
528 emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
536 : QSortFilterProxyModel( parent )
538 setDynamicSortFilter(
true );
540 setSortCaseSensitivity( Qt::CaseInsensitive );
545 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
546 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
547 if ( leftText.isEmpty() )
549 if ( rightText.isEmpty() )
552 return QString::localeAwareCompare( leftText, rightText ) < 0;
void setDirty(bool b=true)
Flag the project as dirty (modified).
QModelIndex indexFromLayout(QgsMasterLayoutInterface *layout) const
Returns the model index corresponding to a layout.
The class is used as a container of context for various read/write operations on other objects...
void layoutAboutToBeRemoved(const QString &name)
Emitted when a layout is about to be removed from the manager.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
QgsMasterLayoutInterface * layoutByName(const QString &name) const
Returns the layout with a matching name, or nullptr if no matching layouts were found.
virtual QgsMasterLayoutInterface * clone() const =0
Creates a clone of the layout.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
bool allowEmptyLayout() const
Returns true if the model allows the empty layout ("not set") choice.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QgsLayoutManagerProxyModel::Filters filters() const
Returns the current filters used for filtering available layouts.
static std::unique_ptr< QgsPrintLayout > createLayoutFromCompositionXml(const QDomElement &composerElement, QgsProject *project)
createLayoutFromCompositionXml is a factory that creates layout instances from a QGIS 2...
virtual void setName(const QString &name)=0
Sets the layout's name.
bool readXml(const QDomElement &element, const QDomDocument &doc)
Reads the manager's state from a DOM element, restoring all layouts present in the XML document...
QList< QgsPrintLayout *> printLayouts() const
Returns a list of all print layouts contained in the manager.
void setAllowEmptyLayout(bool allowEmpty)
Sets whether an optional empty layout ("not set") option is present in the model. ...
An interface for classes which can visit style entity (e.g.
void layoutAboutToBeAdded(const QString &name)
Emitted when a layout is about to be added to the manager.
QgsLayoutManager(QgsProject *project=nullptr)
Constructor for QgsLayoutManager.
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
QDomElement writeXml(QDomDocument &doc) const
Returns a DOM element representing the state of the manager.
List model representing the print layouts and reports available in a layout manager.
Contains information relating to a node (i.e.
virtual QgsMasterLayoutInterface::Type layoutType() const =0
Returns the master layout type.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
void layoutRemoved(const QString &name)
Emitted when a layout was removed from the manager.
void setFilters(QgsLayoutManagerProxyModel::Filters filters)
Sets the current filters used for filtering available layouts.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Manages storage of a set of layouts.
void layoutAdded(const QString &name)
Emitted when a layout has been added to the manager.
void layoutRenamed(QgsMasterLayoutInterface *layout, const QString &newName)
Emitted when a layout is renamed.
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages compositions within the project.
QVariant data(const QModelIndex &index, int role) const override
void clear()
Removes and deletes all layouts from the manager.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
int rowCount(const QModelIndex &parent) const override
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsLayoutManagerProxyModel(QObject *parent=nullptr)
Constructor for QgsLayoutManagerProxyModel.
void nameChanged(const QString &name)
Emitted when the layout's name is changed.
virtual QString name() const =0
Returns the layout's name.
QString generateUniqueTitle(QgsMasterLayoutInterface::Type type=QgsMasterLayoutInterface::PrintLayout) const
Generates a unique title for a new layout of the specified type, which does not clash with any alread...
bool removeLayout(QgsMasterLayoutInterface *layout)
Removes a layout from the manager.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Print layout, a QgsLayout subclass for static or atlas-based layouts.
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated within ...
QList< QgsMasterLayoutInterface *> layouts() const
Returns a list of all layouts contained in the manager.
Interface for master layout type objects, such as print layouts and reports.
QgsMasterLayoutInterface * duplicateLayout(const QgsMasterLayoutInterface *layout, const QString &newName)
Duplicates an existing layout from the manager.
Qt::ItemFlags flags(const QModelIndex &index) const override
QgsMasterLayoutInterface * layoutFromIndex(const QModelIndex &index) const
Returns the layout at the corresponding index.
QgsLayoutManagerModel(QgsLayoutManager *manager, QObject *parent=nullptr)
Constructor for QgsLayoutManagerModel, showing the layouts from the specified manager.
~QgsLayoutManager() override
Individual print layout (QgsPrintLayout)
bool addLayout(QgsMasterLayoutInterface *layout)
Adds a layout to the manager.