25 #include <QMessageBox> 41 if ( !layout || mLayouts.contains( layout ) )
47 if ( l->name() == layout->
name() )
55 if (
QgsPrintLayout *l = dynamic_cast< QgsPrintLayout * >( layout ) )
62 else if ( QgsReport *r = dynamic_cast< QgsReport * >( layout ) )
64 connect( r, &QgsReport::nameChanged,
this, [
this, r](
const QString & newName )
82 if ( !mLayouts.contains( layout ) )
85 QString name = layout->
name();
87 mLayouts.removeAll( layout );
96 const QList< QgsMasterLayoutInterface * >
layouts = mLayouts;
110 QList<QgsPrintLayout *> result;
111 const QList<QgsMasterLayoutInterface *> _layouts( mLayouts );
112 result.reserve( _layouts.size() );
113 for (
const auto &layout : _layouts )
115 QgsPrintLayout *_item( dynamic_cast<QgsPrintLayout *>( layout ) );
117 result.push_back( _item );
126 if ( l->name() == name )
136 QDomElement layoutsElem = element;
137 if ( element.tagName() != QStringLiteral(
"Layouts" ) )
139 layoutsElem = element.firstChildElement( QStringLiteral(
"Layouts" ) );
141 if ( layoutsElem.isNull() )
144 layoutsElem = doc.documentElement();
149 QDomNodeList composerNodes = element.elementsByTagName( QStringLiteral(
"Composer" ) );
150 for (
int i = 0; i < composerNodes.size(); ++i )
153 QString legacyTitle = composerNodes.at( i ).toElement().attribute( QStringLiteral(
"title" ) );
155 QDomNodeList compositionNodes = composerNodes.at( i ).toElement().elementsByTagName( QStringLiteral(
"Composition" ) );
156 for (
int j = 0; j < compositionNodes.size(); ++j )
161 if ( l->name().isEmpty() )
162 l->setName( legacyTitle );
167 bool isDuplicateName =
false;
168 QString originalName = l->name();
171 isDuplicateName =
false;
174 if ( l->name() == layout->name() )
176 isDuplicateName =
true;
180 if ( isDuplicateName )
182 l->setName( QStringLiteral(
"%1 %2" ).arg( originalName ).arg(
id ) );
186 while ( isDuplicateName );
189 result = added && result;
198 const QDomNodeList layoutNodes = layoutsElem.childNodes();
199 for (
int i = 0; i < layoutNodes.size(); ++i )
201 if ( layoutNodes.at( i ).nodeName() != QStringLiteral(
"Layout" ) )
204 std::unique_ptr< QgsPrintLayout > l = qgis::make_unique< QgsPrintLayout >( mProject );
205 l->undoStack()->blockCommands(
true );
206 if ( !l->readLayoutXml( layoutNodes.at( i ).toElement(), doc, context ) )
211 l->undoStack()->blockCommands(
false );
222 const QDomNodeList reportNodes = element.elementsByTagName( QStringLiteral(
"Report" ) );
223 for (
int i = 0; i < reportNodes.size(); ++i )
225 std::unique_ptr< QgsReport > r = qgis::make_unique< QgsReport >( mProject );
226 if ( !r->readLayoutXml( reportNodes.at( i ).toElement(), doc, context ) )
245 QDomElement layoutsElem = doc.createElement( QStringLiteral(
"Layouts" ) );
251 QDomElement layoutElem = l->writeLayoutXml( doc, context );
252 layoutsElem.appendChild( layoutElem );
262 std::unique_ptr< QgsMasterLayoutInterface > newLayout( layout->
clone() );
283 names.reserve( mLayouts.size() );
290 while ( name.isEmpty() || names.contains( name ) )
295 name = tr(
"Layout %1" ).arg(
id );
298 name = tr(
"Report %1" ).arg(
id );
313 : QAbstractListModel( parent )
314 , mLayoutManager( manager )
326 return ( mLayoutManager ? mLayoutManager->
layouts().count() : 0 ) + ( mAllowEmpty ? 1 : 0 );
331 if ( index.row() < 0 || index.row() >=
rowCount( QModelIndex() ) )
334 const bool isEmpty = index.row() == 0 && mAllowEmpty;
335 const int layoutRow = mAllowEmpty ? index.row() - 1 : index.row();
339 case Qt::DisplayRole:
340 case Qt::ToolTipRole:
342 return !isEmpty && mLayoutManager ? mLayoutManager->
layouts().at( layoutRow )->name() : QVariant();
346 if ( isEmpty || !mLayoutManager )
348 else if (
QgsLayout *l = dynamic_cast< QgsLayout * >( mLayoutManager->
layouts().at( layoutRow ) ) )
349 return QVariant::fromValue( l );
350 else if ( QgsReport *r = dynamic_cast< QgsReport * >( mLayoutManager->
layouts().at( layoutRow ) ) )
351 return QVariant::fromValue( r );
356 case Qt::DecorationRole:
358 return isEmpty || !mLayoutManager ? QIcon() : mLayoutManager->
layouts().at( layoutRow )->icon();
368 if ( !index.isValid() || role != Qt::EditRole )
372 if ( index.row() >= mLayoutManager->
layouts().count() )
377 if ( index.row() == 0 && mAllowEmpty )
380 if ( value.toString().isEmpty() )
388 bool changed = layout->
name() != value.toString();
393 QStringList layoutNames;
397 layoutNames << l->name();
399 if ( layoutNames.contains( value.toString() ) )
402 QMessageBox::warning(
nullptr, tr(
"Rename Layout" ), tr(
"There is already a layout named “%1”." ).arg( value.toString() ) );
406 layout->
setName( value.toString() );
412 Qt::ItemFlags
flags = QAbstractListModel::flags( index );
413 #if 0 // double-click is now used for opening the layout 414 if ( index.isValid() )
416 return flags | Qt::ItemIsEditable;
428 if ( index.row() == 0 && mAllowEmpty )
433 else if ( QgsReport *r = qobject_cast< QgsReport * >( qvariant_cast<QObject *>(
data( index,
LayoutRole ) ) ) )
441 if ( !mLayoutManager )
443 return QModelIndex();
446 const int r = mLayoutManager->
layouts().indexOf( layout );
448 return QModelIndex();
450 QModelIndex idx = index( mAllowEmpty ? r + 1 : r, 0, QModelIndex() );
456 return QModelIndex();
461 if ( allowEmpty == mAllowEmpty )
466 beginInsertRows( QModelIndex(), 0, 0 );
472 beginRemoveRows( QModelIndex(), 0, 0 );
478 void QgsLayoutManagerModel::layoutAboutToBeAdded(
const QString & )
480 int row = mLayoutManager->
layouts().count() + ( mAllowEmpty ? 1 : 0 );
481 beginInsertRows( QModelIndex(), row, row );
484 void QgsLayoutManagerModel::layoutAboutToBeRemoved(
const QString &name )
487 int row = mLayoutManager->
layouts().indexOf( l ) + ( mAllowEmpty ? 1 : 0 );
489 beginRemoveRows( QModelIndex(), row, row );
492 void QgsLayoutManagerModel::layoutAdded(
const QString & )
497 void QgsLayoutManagerModel::layoutRemoved(
const QString & )
504 int row = mLayoutManager->
layouts().indexOf( layout ) + ( mAllowEmpty ? 1 : 0 );
505 QModelIndex index = createIndex( row, 0 );
506 emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
514 : QSortFilterProxyModel( parent )
516 setDynamicSortFilter(
true );
518 setSortCaseSensitivity( Qt::CaseInsensitive );
523 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
524 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
525 if ( leftText.isEmpty() )
527 if ( rightText.isEmpty() )
530 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. ...
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...
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.
virtual QgsMasterLayoutInterface::Type layoutType() const =0
Returns the master layout type.
Reads and writes project states.
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.
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.
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.