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 )
61 if ( context.currentLayer )
63 layout->reportContext().blockSignals(
true );
64 layout->reportContext().setLayer( context.currentLayer );
65 layout->reportContext().blockSignals(
false );
67 layout->reportContext().setFeature( context.feature );
72 setReportContext( mHeader.get() );
74 setReportContext( mFooter.get() );
76 for ( QgsAbstractReportSection *section : std::as_const( mChildren ) )
78 section->setContext( mContext );
82bool QgsAbstractReportSection::writeXml( QDomElement &parentElement, QDomDocument &doc,
const QgsReadWriteContext &context )
const
84 QDomElement element = doc.createElement( u
"Section"_s );
85 element.setAttribute( u
"type"_s, type() );
87 element.setAttribute( u
"headerEnabled"_s, mHeaderEnabled ? u
"1"_s : u
"0"_s );
90 QDomElement headerElement = doc.createElement( u
"header"_s );
91 headerElement.appendChild( mHeader->writeXml( doc, context ) );
92 element.appendChild( headerElement );
94 element.setAttribute( u
"footerEnabled"_s, mFooterEnabled ? u
"1"_s : u
"0"_s );
97 QDomElement footerElement = doc.createElement( u
"footer"_s );
98 footerElement.appendChild( mFooter->writeXml( doc, context ) );
99 element.appendChild( footerElement );
102 for ( QgsAbstractReportSection *section : mChildren )
104 section->writeXml( element, doc, context );
107 writePropertiesToElement( element, doc, context );
109 parentElement.appendChild( element );
113bool QgsAbstractReportSection::readXml(
const QDomElement &element,
const QDomDocument &doc,
const QgsReadWriteContext &context )
115 if ( element.nodeName() !=
"Section"_L1 )
120 mHeaderEnabled = element.attribute( u
"headerEnabled"_s, u
"0"_s ).toInt();
121 mFooterEnabled = element.attribute( u
"footerEnabled"_s, u
"0"_s ).toInt();
122 const QDomElement headerElement = element.firstChildElement( u
"header"_s );
123 if ( !headerElement.isNull() )
125 const QDomElement headerLayoutElem = headerElement.firstChild().toElement();
126 auto header = std::make_unique< QgsLayout >( project() );
127 header->readXml( headerLayoutElem, doc, context );
128 mHeader = std::move( header );
130 const QDomElement footerElement = element.firstChildElement( u
"footer"_s );
131 if ( !footerElement.isNull() )
133 const QDomElement footerLayoutElem = footerElement.firstChild().toElement();
134 auto footer = std::make_unique< QgsLayout >( project() );
135 footer->readXml( footerLayoutElem, doc, context );
136 mFooter = std::move( footer );
139 const QDomNodeList sectionItemList = element.childNodes();
140 for (
int i = 0; i < sectionItemList.size(); ++i )
142 const QDomElement currentSectionElem = sectionItemList.at( i ).toElement();
143 if ( currentSectionElem.nodeName() !=
"Section"_L1 )
146 const QString sectionType = currentSectionElem.attribute( u
"type"_s );
149 std::unique_ptr< QgsAbstractReportSection > section;
150 if ( sectionType ==
"SectionFieldGroup"_L1 )
152 section = std::make_unique< QgsReportSectionFieldGroup >();
154 else if ( sectionType ==
"SectionLayout"_L1 )
156 section = std::make_unique< QgsReportSectionLayout >();
161 appendChild( section.get() );
162 section->readXml( currentSectionElem, doc, context );
163 ( void )section.release();
167 bool result = readPropertiesFromElement( element, doc, context );
171void QgsAbstractReportSection::reloadSettings()
174 mHeader->reloadSettings();
176 mFooter->reloadSettings();
190 if ( !mHeader->accept( visitor ) )
198 for (
const QgsAbstractReportSection *child : mChildren )
200 if ( !child->accept( visitor ) )
209 if ( !mFooter->accept( visitor ) )
223QString QgsAbstractReportSection::filePath(
const QString &baseFilePath,
const QString &extension )
225 QString base = u
"%1_%2"_s.arg( baseFilePath ).arg( mSectionNumber, 4, 10, QChar(
'0' ) );
226 if ( !extension.startsWith(
'.' ) )
232QgsLayout *QgsAbstractReportSection::layout()
234 return mCurrentLayout;
237bool QgsAbstractReportSection::beginRender()
245 for ( QgsAbstractReportSection *child : std::as_const( mChildren ) )
247 result = result && child->beginRender();
252bool QgsAbstractReportSection::next()
256 if ( mNextSection == Header )
262 if ( mHeaderEnabled && mHeader )
264 if ( prepareHeader() )
266 mCurrentLayout = mHeader.get();
275 if ( mNextSection == Body )
277 mNextSection = Children;
285 mCurrentLayout = body;
290 if ( mNextSection == Children )
292 bool bodiesAvailable =
false;
296 while ( mNextChild < mChildren.count() )
299 if ( mChildren.at( mNextChild )->next() )
301 mCurrentLayout = mChildren.at( mNextChild )->layout();
313 QgsLayout *body = nextBody( bodiesAvailable );
314 if ( bodiesAvailable )
318 for ( QgsAbstractReportSection *section : std::as_const( mChildren ) )
325 mCurrentLayout = body;
329 while ( bodiesAvailable );
332 mNextSection = Footer;
335 if ( mNextSection == Footer )
341 if ( mFooterEnabled && mFooter )
343 if ( prepareFooter() )
345 mCurrentLayout = mFooter.get();
353 mCurrentLayout =
nullptr;
357bool QgsAbstractReportSection::endRender()
364 for ( QgsAbstractReportSection *child : std::as_const( mChildren ) )
366 result = result && child->endRender();
371void QgsAbstractReportSection::reset()
373 mCurrentLayout =
nullptr;
375 mNextSection = Header;
376 for ( QgsAbstractReportSection *section : std::as_const( mChildren ) )
382bool QgsAbstractReportSection::prepareHeader()
387bool QgsAbstractReportSection::prepareFooter()
392void QgsAbstractReportSection::setHeader(
QgsLayout *header )
394 mHeader.reset( header );
397void QgsAbstractReportSection::setFooter(
QgsLayout *footer )
399 mFooter.reset( footer );
402int QgsAbstractReportSection::row()
const
405 return mParent->childSections().indexOf(
const_cast<QgsAbstractReportSection *
>(
this ) );
410QgsAbstractReportSection *QgsAbstractReportSection::childSection(
int index )
412 return mChildren.value( index );
415void QgsAbstractReportSection::appendChild( QgsAbstractReportSection *section )
417 section->setParentSection(
this );
418 mChildren.append( section );
421void QgsAbstractReportSection::insertChild(
int index, QgsAbstractReportSection *section )
423 section->setParentSection(
this );
424 index = std::max( 0, index );
425 index = std::min( index,
static_cast<int>( mChildren.count() ) );
426 mChildren.insert( index, section );
429void QgsAbstractReportSection::removeChild( QgsAbstractReportSection *section )
431 mChildren.removeAll( section );
435void QgsAbstractReportSection::removeChildAt(
int index )
437 if ( index < 0 || index >= mChildren.count() )
440 QgsAbstractReportSection *section = mChildren.at( index );
441 removeChild( section );
444void QgsAbstractReportSection::copyCommonProperties( QgsAbstractReportSection *destination )
const
446 destination->mHeaderEnabled = mHeaderEnabled;
448 destination->mHeader.reset( mHeader->clone() );
450 destination->mHeader.reset();
452 destination->mFooterEnabled = mFooterEnabled;
454 destination->mFooter.reset( mFooter->clone() );
456 destination->mFooter.reset();
458 qDeleteAll( destination->mChildren );
459 destination->mChildren.clear();
461 for ( QgsAbstractReportSection *child : std::as_const( mChildren ) )
463 destination->appendChild( child->clone() );
467bool QgsAbstractReportSection::writePropertiesToElement( QDomElement &, QDomDocument &,
const QgsReadWriteContext & )
const
472bool 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.