17#include "moc_qgslayoutmanager.cpp"
44 if ( !layout || mLayouts.contains( layout ) )
50 if ( l->name() == layout->
name() )
65 else if ( QgsReport *r =
dynamic_cast< QgsReport *
>( layout ) )
67 connect( r, &QgsReport::nameChanged,
this, [
this, r](
const QString & newName )
85 if ( !mLayouts.contains( layout ) )
88 QString name = layout->
name();
90 mLayouts.removeAll( layout );
99 const QList< QgsMasterLayoutInterface * >
layouts = mLayouts;
113 QList<QgsPrintLayout *> result;
114 const QList<QgsMasterLayoutInterface *> _layouts( mLayouts );
115 result.reserve( _layouts.size() );
116 for (
const auto &layout : _layouts )
120 result.push_back( _item );
129 if ( l->name() == name )
139 QDomElement layoutsElem = element;
140 if ( element.tagName() != QLatin1String(
"Layouts" ) )
142 layoutsElem = element.firstChildElement( QStringLiteral(
"Layouts" ) );
144 if ( layoutsElem.isNull() )
147 layoutsElem = doc.documentElement();
152 QDomNodeList composerNodes = element.elementsByTagName( QStringLiteral(
"Composer" ) );
154 for (
int i = 0; i < composerNodes.size(); ++i )
157 QString legacyTitle = composerNodes.at( i ).toElement().attribute( QStringLiteral(
"title" ) );
159 QDomNodeList compositionNodes = composerNodes.at( i ).toElement().elementsByTagName( QStringLiteral(
"Composition" ) );
160 for (
int j = 0; j < compositionNodes.size(); ++j )
165 if ( l->name().isEmpty() )
166 l->setName( legacyTitle );
171 bool isDuplicateName =
false;
172 QString originalName = l->name();
175 isDuplicateName =
false;
178 if ( l->name() == layout->name() )
180 isDuplicateName =
true;
184 if ( isDuplicateName )
186 l->setName( QStringLiteral(
"%1 %2" ).arg( originalName ).arg(
id ) );
190 while ( isDuplicateName );
193 result = added && result;
201 profile.
switchTask( tr(
"Creating layouts" ) );
204 const QDomNodeList layoutNodes = layoutsElem.childNodes();
205 for (
int i = 0; i < layoutNodes.size(); ++i )
207 if ( layoutNodes.at( i ).nodeName() != QLatin1String(
"Layout" ) )
210 const QString layoutName = layoutNodes.at( i ).toElement().attribute( QStringLiteral(
"name" ) );
213 std::unique_ptr< QgsPrintLayout > l = std::make_unique< QgsPrintLayout >( mProject );
214 l->undoStack()->blockCommands(
true );
215 if ( !l->readLayoutXml( layoutNodes.at( i ).toElement(), doc, context ) )
220 l->undoStack()->blockCommands(
false );
227 profile.
switchTask( tr(
"Creating reports" ) );
228 const QDomNodeList reportNodes = element.elementsByTagName( QStringLiteral(
"Report" ) );
229 for (
int i = 0; i < reportNodes.size(); ++i )
231 const QString layoutName = reportNodes.at( i ).toElement().attribute( QStringLiteral(
"name" ) );
234 std::unique_ptr< QgsReport > r = std::make_unique< QgsReport >( mProject );
235 if ( !r->readLayoutXml( reportNodes.at( i ).toElement(), doc, context ) )
250 QDomElement layoutsElem = doc.createElement( QStringLiteral(
"Layouts" ) );
256 QDomElement layoutElem = l->writeLayoutXml( doc, context );
257 layoutsElem.appendChild( layoutElem );
267 std::unique_ptr< QgsMasterLayoutInterface > newLayout( layout->
clone() );
273 newLayout->setName( newName );
289 names.reserve( mLayouts.size() );
296 while ( name.isEmpty() || names.contains( name ) )
301 name = tr(
"Layout %1" ).arg(
id );
304 name = tr(
"Report %1" ).arg(
id );
314 if ( mLayouts.empty() )
323 if ( !l->layoutAccept( visitor ) )
340 : QAbstractListModel( parent )
341 , mLayoutManager( manager )
353 return ( mLayoutManager ? mLayoutManager->
layouts().count() : 0 ) + ( mAllowEmpty ? 1 : 0 );
358 if ( index.row() < 0 || index.row() >=
rowCount( QModelIndex() ) )
361 const bool isEmpty = index.row() == 0 && mAllowEmpty;
362 const int layoutRow = mAllowEmpty ? index.row() - 1 : index.row();
366 case Qt::DisplayRole:
367 case Qt::ToolTipRole:
369 return !isEmpty && mLayoutManager ? mLayoutManager->
layouts().at( layoutRow )->name() : QVariant();
373 if ( isEmpty || !mLayoutManager )
376 return QVariant::fromValue( l );
377 else if ( QgsReport *r =
dynamic_cast< QgsReport *
>( mLayoutManager->
layouts().at( layoutRow ) ) )
378 return QVariant::fromValue( r );
383 case Qt::DecorationRole:
385 return isEmpty || !mLayoutManager ? QIcon() : mLayoutManager->
layouts().at( layoutRow )->icon();
395 if ( !index.isValid() || role != Qt::EditRole )
399 if ( index.row() >= mLayoutManager->
layouts().count() )
404 if ( index.row() == 0 && mAllowEmpty )
407 if ( value.toString().isEmpty() )
415 bool changed = layout->
name() != value.toString();
420 QStringList layoutNames;
424 layoutNames << l->name();
426 if ( layoutNames.contains( value.toString() ) )
429 QMessageBox::warning(
nullptr, tr(
"Rename Layout" ), tr(
"There is already a layout named “%1”." ).arg( value.toString() ) );
433 layout->
setName( value.toString() );
439 Qt::ItemFlags
flags = QAbstractListModel::flags( index );
441 if ( index.isValid() )
443 return flags | Qt::ItemIsEditable;
455 if ( index.row() == 0 && mAllowEmpty )
460 else if ( QgsReport *r = qobject_cast< QgsReport * >( qvariant_cast<QObject *>(
data( index,
static_cast< int >(
CustomRole::Layout ) ) ) ) )
468 if ( !mLayoutManager )
470 return QModelIndex();
473 const int r = mLayoutManager->
layouts().indexOf( layout );
475 return QModelIndex();
477 QModelIndex idx = index( mAllowEmpty ? r + 1 : r, 0, QModelIndex() );
483 return QModelIndex();
488 if ( allowEmpty == mAllowEmpty )
493 beginInsertRows( QModelIndex(), 0, 0 );
499 beginRemoveRows( QModelIndex(), 0, 0 );
505void QgsLayoutManagerModel::layoutAboutToBeAdded(
const QString & )
507 int row = mLayoutManager->
layouts().count() + ( mAllowEmpty ? 1 : 0 );
508 beginInsertRows( QModelIndex(), row, row );
511void QgsLayoutManagerModel::layoutAboutToBeRemoved(
const QString &name )
514 int row = mLayoutManager->
layouts().indexOf( l ) + ( mAllowEmpty ? 1 : 0 );
516 beginRemoveRows( QModelIndex(), row, row );
519void QgsLayoutManagerModel::layoutAdded(
const QString & )
524void QgsLayoutManagerModel::layoutRemoved(
const QString & )
531 int row = mLayoutManager->
layouts().indexOf( layout ) + ( mAllowEmpty ? 1 : 0 );
532 QModelIndex index = createIndex( row, 0 );
533 emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
541 : QSortFilterProxyModel( parent )
543 setDynamicSortFilter(
true );
545 setSortCaseSensitivity( Qt::CaseInsensitive );
550 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
551 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
552 if ( leftText.isEmpty() )
554 if ( rightText.isEmpty() )
557 return QString::localeAwareCompare( leftText, rightText ) < 0;
570 if ( !mFilterString.trimmed().isEmpty() )
572 if ( !layout->
name().contains( mFilterString, Qt::CaseInsensitive ) )
599 mFilterString = filter;
static std::unique_ptr< QgsPrintLayout > createLayoutFromCompositionXml(const QDomElement &composerElement, QgsProject *project)
createLayoutFromCompositionXml is a factory that creates layout instances from a QGIS 2....
List model representing the print layouts and reports available in a layout manager.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QModelIndex indexFromLayout(QgsMasterLayoutInterface *layout) const
Returns the model index corresponding to a layout.
Qt::ItemFlags flags(const QModelIndex &index) const override
QgsMasterLayoutInterface * layoutFromIndex(const QModelIndex &index) const
Returns the layout at the corresponding index.
void setAllowEmptyLayout(bool allowEmpty)
Sets whether an optional empty layout ("not set") option is present in the model.
QVariant data(const QModelIndex &index, int role) const override
bool allowEmptyLayout() const
Returns true if the model allows the empty layout ("not set") choice.
QgsLayoutManagerModel(QgsLayoutManager *manager, QObject *parent=nullptr)
Constructor for QgsLayoutManagerModel, showing the layouts from the specified manager.
int rowCount(const QModelIndex &parent) const override
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
void setFilterString(const QString &filter)
Sets a filter string, such that only layouts with names containing the specified string will be shown...
void setFilters(QgsLayoutManagerProxyModel::Filters filters)
Sets the current filters used for filtering available layouts.
QgsLayoutManagerProxyModel::Filters filters() const
Returns the current filters used for filtering available layouts.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
@ FilterReports
Includes reports.
@ FilterPrintLayouts
Includes print layouts.
QgsLayoutManagerProxyModel(QObject *parent=nullptr)
Constructor for QgsLayoutManagerProxyModel.
Manages storage of a set of layouts.
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.
QgsLayoutManager(QgsProject *project=nullptr)
Constructor for QgsLayoutManager.
QList< QgsMasterLayoutInterface * > layouts() const
Returns a list of all layouts contained in the manager.
QList< QgsPrintLayout * > printLayouts() const
Returns a list of all print layouts contained in the manager.
void layoutAboutToBeRemoved(const QString &name)
Emitted when a layout is about to be removed from the manager.
~QgsLayoutManager() override
bool removeLayout(QgsMasterLayoutInterface *layout)
Removes a layout from the manager.
QgsMasterLayoutInterface * layoutByName(const QString &name) const
Returns the layout with a matching name, or nullptr if no matching layouts were found.
void clear()
Removes and deletes all layouts from the manager.
bool addLayout(QgsMasterLayoutInterface *layout)
Adds a layout to the manager.
void layoutAboutToBeAdded(const QString &name)
Emitted when a layout is about to be added to the manager.
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated within ...
void layoutRenamed(QgsMasterLayoutInterface *layout, const QString &newName)
Emitted when a layout is renamed.
void layoutRemoved(const QString &name)
Emitted when a layout was removed from the manager.
QDomElement writeXml(QDomDocument &doc) const
Returns a DOM element representing the state of the manager.
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...
void layoutAdded(const QString &name)
Emitted when a layout has been added to the manager.
QgsMasterLayoutInterface * duplicateLayout(const QgsMasterLayoutInterface *layout, const QString &newName)
Duplicates an existing layout from the manager.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Interface for master layout type objects, such as print layouts and reports.
virtual QString name() const =0
Returns the layout's name.
virtual QgsMasterLayoutInterface::Type layoutType() const =0
Returns the master layout type.
@ Report
Report (QgsReport)
@ PrintLayout
Individual print layout (QgsPrintLayout)
virtual QgsMasterLayoutInterface * clone() const =0
Creates a clone of the layout.
virtual void setName(const QString &name)=0
Sets the layout's name.
Print layout, a QgsLayout subclass for static or atlas-based layouts.
void nameChanged(const QString &name)
Emitted when the layout's name is changed.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
const QgsLayoutManager * layoutManager() const
Returns the project's layout manager, which manages print layouts, atlases and reports within the pro...
void setDirty(bool b=true)
Flag the project as dirty (modified).
The class is used as a container of context for various read/write operations on other objects.
void setPathResolver(const QgsPathResolver &resolver)
Sets up path resolver for conversion between relative and absolute paths.
Scoped object for logging of the runtime for a single operation or group of operations.
void switchTask(const QString &name)
Switches the current task managed by the scoped profile to a new task with the given name.
An interface for classes which can visit style entity (e.g.
@ Layouts
Layout collection.
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
Contains information relating to a node (i.e.