28using namespace Qt::StringLiterals;
32QgsAbstractReportSection::QgsAbstractReportSection( QgsAbstractReportSection *parent )
36QgsAbstractReportSection::~QgsAbstractReportSection()
38 qDeleteAll( mChildren );
43 if ( QgsReport *report =
dynamic_cast< QgsReport *
>(
this ) )
44 return report->layoutProject();
46 QgsAbstractReportSection *current =
this;
47 while ( QgsAbstractReportSection *parent = current->parentSection() )
49 if ( QgsReport *report =
dynamic_cast< QgsReport *
>( parent ) )
50 return report->layoutProject();
57void QgsAbstractReportSection::setContext(
const QgsReportSectionContext &context )
59 auto setReportContext = [&context](
QgsLayout *layout ) {
60 if ( context.currentLayer )
62 layout->reportContext().blockSignals(
true );
63 layout->reportContext().setLayer( context.currentLayer );
64 layout->reportContext().blockSignals(
false );
66 layout->reportContext().setFeature( context.feature );
71 setReportContext( mHeader.get() );
73 setReportContext( mFooter.get() );
75 for ( QgsAbstractReportSection *section : std::as_const( mChildren ) )
77 section->setContext( mContext );
81bool QgsAbstractReportSection::writeXml( QDomElement &parentElement, QDomDocument &doc,
const QgsReadWriteContext &context )
const
83 QDomElement element = doc.createElement( u
"Section"_s );
84 element.setAttribute( u
"type"_s, type() );
86 element.setAttribute( u
"headerEnabled"_s, mHeaderEnabled ? u
"1"_s : u
"0"_s );
89 QDomElement headerElement = doc.createElement( u
"header"_s );
90 headerElement.appendChild( mHeader->writeXml( doc, context ) );
91 element.appendChild( headerElement );
93 element.setAttribute( u
"footerEnabled"_s, mFooterEnabled ? u
"1"_s : u
"0"_s );
96 QDomElement footerElement = doc.createElement( u
"footer"_s );
97 footerElement.appendChild( mFooter->writeXml( doc, context ) );
98 element.appendChild( footerElement );
101 for ( QgsAbstractReportSection *section : mChildren )
103 section->writeXml( element, doc, context );
106 writePropertiesToElement( element, doc, context );
108 parentElement.appendChild( element );
112bool QgsAbstractReportSection::readXml(
const QDomElement &element,
const QDomDocument &doc,
const QgsReadWriteContext &context )
114 if ( element.nodeName() !=
"Section"_L1 )
119 mHeaderEnabled = element.attribute( u
"headerEnabled"_s, u
"0"_s ).toInt();
120 mFooterEnabled = element.attribute( u
"footerEnabled"_s, u
"0"_s ).toInt();
121 const QDomElement headerElement = element.firstChildElement( u
"header"_s );
122 if ( !headerElement.isNull() )
124 const QDomElement headerLayoutElem = headerElement.firstChild().toElement();
125 auto header = std::make_unique< QgsLayout >( project() );
126 header->readXml( headerLayoutElem, doc, context );
127 mHeader = std::move( header );
129 const QDomElement footerElement = element.firstChildElement( u
"footer"_s );
130 if ( !footerElement.isNull() )
132 const QDomElement footerLayoutElem = footerElement.firstChild().toElement();
133 auto footer = std::make_unique< QgsLayout >( project() );
134 footer->readXml( footerLayoutElem, doc, context );
135 mFooter = std::move( footer );
138 const QDomNodeList sectionItemList = element.childNodes();
139 for (
int i = 0; i < sectionItemList.size(); ++i )
141 const QDomElement currentSectionElem = sectionItemList.at( i ).toElement();
142 if ( currentSectionElem.nodeName() !=
"Section"_L1 )
145 const QString sectionType = currentSectionElem.attribute( u
"type"_s );
148 std::unique_ptr< QgsAbstractReportSection > section;
149 if ( sectionType ==
"SectionFieldGroup"_L1 )
151 section = std::make_unique< QgsReportSectionFieldGroup >();
153 else if ( sectionType ==
"SectionLayout"_L1 )
155 section = std::make_unique< QgsReportSectionLayout >();
160 appendChild( section.get() );
161 section->readXml( currentSectionElem, doc, context );
162 ( void ) section.release();
166 bool result = readPropertiesFromElement( element, doc, context );
170void QgsAbstractReportSection::reloadSettings()
173 mHeader->reloadSettings();
175 mFooter->reloadSettings();
189 if ( !mHeader->accept( visitor ) )
197 for (
const QgsAbstractReportSection *child : mChildren )
199 if ( !child->accept( visitor ) )
208 if ( !mFooter->accept( visitor ) )
222QString QgsAbstractReportSection::filePath(
const QString &baseFilePath,
const QString &extension )
224 QString base = u
"%1_%2"_s.arg( baseFilePath ).arg( mSectionNumber, 4, 10, QChar(
'0' ) );
225 if ( !extension.startsWith(
'.' ) )
231QgsLayout *QgsAbstractReportSection::layout()
233 return mCurrentLayout;
236bool QgsAbstractReportSection::beginRender()
244 for ( QgsAbstractReportSection *child : std::as_const( mChildren ) )
246 result = result && child->beginRender();
251bool QgsAbstractReportSection::next()
255 if ( mNextSection == Header )
261 if ( mHeaderEnabled && mHeader )
263 if ( prepareHeader() )
265 mCurrentLayout = mHeader.get();
274 if ( mNextSection == Body )
276 mNextSection = Children;
284 mCurrentLayout = body;
289 if ( mNextSection == Children )
291 bool bodiesAvailable =
false;
295 while ( mNextChild < mChildren.count() )
298 if ( mChildren.at( mNextChild )->next() )
300 mCurrentLayout = mChildren.at( mNextChild )->layout();
312 QgsLayout *body = nextBody( bodiesAvailable );
313 if ( bodiesAvailable )
317 for ( QgsAbstractReportSection *section : std::as_const( mChildren ) )
324 mCurrentLayout = body;
327 }
while ( bodiesAvailable );
330 mNextSection = Footer;
333 if ( mNextSection == Footer )
339 if ( mFooterEnabled && mFooter )
341 if ( prepareFooter() )
343 mCurrentLayout = mFooter.get();
351 mCurrentLayout =
nullptr;
355bool QgsAbstractReportSection::endRender()
362 for ( QgsAbstractReportSection *child : std::as_const( mChildren ) )
364 result = result && child->endRender();
369void QgsAbstractReportSection::reset()
371 mCurrentLayout =
nullptr;
373 mNextSection = Header;
374 for ( QgsAbstractReportSection *section : std::as_const( mChildren ) )
380bool QgsAbstractReportSection::prepareHeader()
385bool QgsAbstractReportSection::prepareFooter()
390void QgsAbstractReportSection::setHeader(
QgsLayout *header )
392 mHeader.reset( header );
395void QgsAbstractReportSection::setFooter(
QgsLayout *footer )
397 mFooter.reset( footer );
400int QgsAbstractReportSection::row()
const
403 return mParent->childSections().indexOf(
const_cast<QgsAbstractReportSection *
>(
this ) );
408QgsAbstractReportSection *QgsAbstractReportSection::childSection(
int index )
410 return mChildren.value( index );
413void QgsAbstractReportSection::appendChild( QgsAbstractReportSection *section )
415 section->setParentSection(
this );
416 mChildren.append( section );
419void QgsAbstractReportSection::insertChild(
int index, QgsAbstractReportSection *section )
421 section->setParentSection(
this );
422 index = std::max( 0, index );
423 index = std::min( index,
static_cast<int>( mChildren.count() ) );
424 mChildren.insert( index, section );
427void QgsAbstractReportSection::removeChild( QgsAbstractReportSection *section )
429 mChildren.removeAll( section );
433void QgsAbstractReportSection::removeChildAt(
int index )
435 if ( index < 0 || index >= mChildren.count() )
438 QgsAbstractReportSection *section = mChildren.at( index );
439 removeChild( section );
442void QgsAbstractReportSection::copyCommonProperties( QgsAbstractReportSection *destination )
const
444 destination->mHeaderEnabled = mHeaderEnabled;
446 destination->mHeader.reset( mHeader->clone() );
448 destination->mHeader.reset();
450 destination->mFooterEnabled = mFooterEnabled;
452 destination->mFooter.reset( mFooter->clone() );
454 destination->mFooter.reset();
456 qDeleteAll( destination->mChildren );
457 destination->mChildren.clear();
459 for ( QgsAbstractReportSection *child : std::as_const( mChildren ) )
461 destination->appendChild( child->clone() );
465bool QgsAbstractReportSection::writePropertiesToElement( QDomElement &, QDomDocument &,
const QgsReadWriteContext & )
const
470bool QgsAbstractReportSection::readPropertiesFromElement(
const QDomElement &,
const QDomDocument &,
const QgsReadWriteContext & )
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
A container for the context for various read/write operations on objects.
An interface for classes which can visit style entity (e.g.
@ ReportFooter
Report footer section.
@ ReportSection
Report sub section.
@ ReportHeader
Report header section.
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.