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 );
219 const QDomNodeList reportNodes = element.elementsByTagName( QStringLiteral(
"Report" ) );
220 for (
int i = 0; i < reportNodes.size(); ++i )
222 std::unique_ptr< QgsReport > r = qgis::make_unique< QgsReport >( mProject );
223 if ( !r->readLayoutXml( reportNodes.at( i ).toElement(), doc, context ) )
238 QDomElement layoutsElem = doc.createElement( QStringLiteral(
"Layouts" ) );
244 QDomElement layoutElem = l->writeLayoutXml( doc, context );
245 layoutsElem.appendChild( layoutElem );
255 std::unique_ptr< QgsMasterLayoutInterface > newLayout( layout->
clone() );
276 names.reserve( mLayouts.size() );
283 while ( name.isEmpty() || names.contains( name ) )
288 name = tr(
"Layout %1" ).arg(
id );
291 name = tr(
"Report %1" ).arg(
id );
301 if ( mLayouts.empty() )
310 if ( !l->layoutAccept( visitor ) )
327 : QAbstractListModel( parent )
328 , mLayoutManager( manager )
340 return ( mLayoutManager ? mLayoutManager->
layouts().count() : 0 ) + ( mAllowEmpty ? 1 : 0 );
345 if ( index.row() < 0 || index.row() >=
rowCount( QModelIndex() ) )
348 const bool isEmpty = index.row() == 0 && mAllowEmpty;
349 const int layoutRow = mAllowEmpty ? index.row() - 1 : index.row();
353 case Qt::DisplayRole:
354 case Qt::ToolTipRole:
356 return !isEmpty && mLayoutManager ? mLayoutManager->
layouts().at( layoutRow )->name() : QVariant();
360 if ( isEmpty || !mLayoutManager )
362 else if (
QgsLayout *l = dynamic_cast< QgsLayout * >( mLayoutManager->
layouts().at( layoutRow ) ) )
363 return QVariant::fromValue( l );
364 else if ( QgsReport *r = dynamic_cast< QgsReport * >( mLayoutManager->
layouts().at( layoutRow ) ) )
365 return QVariant::fromValue( r );
370 case Qt::DecorationRole:
372 return isEmpty || !mLayoutManager ? QIcon() : mLayoutManager->
layouts().at( layoutRow )->icon();
382 if ( !index.isValid() || role != Qt::EditRole )
386 if ( index.row() >= mLayoutManager->
layouts().count() )
391 if ( index.row() == 0 && mAllowEmpty )
394 if ( value.toString().isEmpty() )
402 bool changed = layout->
name() != value.toString();
407 QStringList layoutNames;
411 layoutNames << l->name();
413 if ( layoutNames.contains( value.toString() ) )
416 QMessageBox::warning(
nullptr, tr(
"Rename Layout" ), tr(
"There is already a layout named “%1”." ).arg( value.toString() ) );
420 layout->
setName( value.toString() );
426 Qt::ItemFlags
flags = QAbstractListModel::flags( index );
427 #if 0 // double-click is now used for opening the layout 428 if ( index.isValid() )
430 return flags | Qt::ItemIsEditable;
442 if ( index.row() == 0 && mAllowEmpty )
447 else if ( QgsReport *r = qobject_cast< QgsReport * >( qvariant_cast<QObject *>(
data( index,
LayoutRole ) ) ) )
455 if ( !mLayoutManager )
457 return QModelIndex();
460 const int r = mLayoutManager->
layouts().indexOf( layout );
462 return QModelIndex();
464 QModelIndex idx = index( mAllowEmpty ? r + 1 : r, 0, QModelIndex() );
470 return QModelIndex();
475 if ( allowEmpty == mAllowEmpty )
480 beginInsertRows( QModelIndex(), 0, 0 );
486 beginRemoveRows( QModelIndex(), 0, 0 );
492 void QgsLayoutManagerModel::layoutAboutToBeAdded(
const QString & )
494 int row = mLayoutManager->
layouts().count() + ( mAllowEmpty ? 1 : 0 );
495 beginInsertRows( QModelIndex(), row, row );
498 void QgsLayoutManagerModel::layoutAboutToBeRemoved(
const QString &name )
501 int row = mLayoutManager->
layouts().indexOf( l ) + ( mAllowEmpty ? 1 : 0 );
503 beginRemoveRows( QModelIndex(), row, row );
506 void QgsLayoutManagerModel::layoutAdded(
const QString & )
511 void QgsLayoutManagerModel::layoutRemoved(
const QString & )
518 int row = mLayoutManager->
layouts().indexOf( layout ) + ( mAllowEmpty ? 1 : 0 );
519 QModelIndex index = createIndex( row, 0 );
520 emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
528 : QSortFilterProxyModel( parent )
530 setDynamicSortFilter(
true );
532 setSortCaseSensitivity( Qt::CaseInsensitive );
537 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
538 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
539 if ( leftText.isEmpty() )
541 if ( rightText.isEmpty() )
544 return QString::localeAwareCompare( leftText, rightText ) < 0;
557 if ( !mFilterString.trimmed().isEmpty() )
559 if ( !layout->
name().contains( mFilterString, Qt::CaseInsensitive ) )
586 mFilterString = filter;
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.
void setFilterString(const QString &filter)
Sets a filter string, such that only layouts with names containing the specified string will be shown...
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 print layouts, atlases and reports within the pro...
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.