23using namespace Qt::StringLiterals;
27QgsReportSectionFieldGroup::QgsReportSectionFieldGroup( QgsAbstractReportSection *parent )
28 : QgsAbstractReportSection( parent )
31QString QgsReportSectionFieldGroup::description()
const
34 return QObject::tr(
"Group: %1 - %2" ).arg( mCoverageLayer->name(), mField );
36 return QObject::tr(
"Group" );
39QIcon QgsReportSectionFieldGroup::icon()
const
44QgsReportSectionFieldGroup *QgsReportSectionFieldGroup::clone()
const
46 auto copy = std::make_unique< QgsReportSectionFieldGroup >(
nullptr );
47 copyCommonProperties( copy.get() );
51 copy->mBody.reset( mBody->clone() );
56 copy->setLayer( mCoverageLayer.get() );
57 copy->setField( mField );
58 copy->setSortAscending( mSortAscending );
59 copy->setBodyEnabled( mBodyEnabled );
61 return copy.release();
64bool QgsReportSectionFieldGroup::beginRender()
66 if ( !mCoverageLayer )
69 if ( !mField.isEmpty() )
71 mFieldIndex = mCoverageLayer->fields().lookupField( mField );
72 if ( mFieldIndex < 0 )
76 mBody->reportContext().setLayer( mCoverageLayer.get() );
80 return QgsAbstractReportSection::beginRender();
83bool QgsReportSectionFieldGroup::prepareHeader()
88 if ( !mFeatures.isValid() )
90 mFeatures = mCoverageLayer->getFeatures( buildFeatureRequest() );
93 mHeaderFeature = getNextFeature();
94 header()->reportContext().blockSignals(
true );
95 header()->reportContext().setLayer( mCoverageLayer.get() );
96 header()->reportContext().blockSignals(
false );
97 header()->reportContext().setFeature( mHeaderFeature );
98 mSkipNextRequest =
true;
99 mNoFeatures = !mHeaderFeature.isValid();
100 return mHeaderVisibility == AlwaysInclude || !mNoFeatures;
103bool QgsReportSectionFieldGroup::prepareFooter()
105 return mFooterVisibility == AlwaysInclude || !mNoFeatures;
108QgsLayout *QgsReportSectionFieldGroup::nextBody(
bool &ok )
110 if ( !mFeatures.isValid() )
112 mFeatures = mCoverageLayer->getFeatures( buildFeatureRequest() );
116 if ( !mSkipNextRequest )
118 f = getNextFeature();
123 mSkipNextRequest =
false;
131 if (
auto *lFooter = footer() )
133 lFooter->reportContext().blockSignals(
true );
134 lFooter->reportContext().setLayer( mCoverageLayer.get() );
135 lFooter->reportContext().blockSignals(
false );
136 lFooter->reportContext().setFeature( mLastFeature );
144 updateChildContexts( f );
147 if ( mBody && mBodyEnabled )
149 mBody->reportContext().blockSignals(
true );
150 mBody->reportContext().setLayer( mCoverageLayer.get() );
151 mBody->reportContext().blockSignals(
false );
152 mBody->reportContext().setFeature( f );
155 return mBodyEnabled ? mBody.get() :
nullptr;
158void QgsReportSectionFieldGroup::reset()
160 QgsAbstractReportSection::reset();
161 mEncounteredValues.clear();
162 mSkipNextRequest =
false;
169void QgsReportSectionFieldGroup::setParentSection( QgsAbstractReportSection *parent )
171 QgsAbstractReportSection::setParentSection( parent );
172 if ( !mCoverageLayer )
173 mCoverageLayer.resolveWeakly( project() );
176void QgsReportSectionFieldGroup::reloadSettings()
178 QgsAbstractReportSection::reloadSettings();
180 mBody->reloadSettings();
183bool QgsReportSectionFieldGroup::writePropertiesToElement( QDomElement &element, QDomDocument &doc,
const QgsReadWriteContext &context )
const
185 element.setAttribute( u
"headerVisibility"_s,
static_cast< int >( mHeaderVisibility ) );
186 element.setAttribute( u
"footerVisibility"_s,
static_cast< int >( mFooterVisibility ) );
187 element.setAttribute( u
"field"_s, mField );
188 element.setAttribute( u
"ascending"_s, mSortAscending ? u
"1"_s : u
"0"_s );
189 element.setAttribute( u
"bodyEnabled"_s, mBodyEnabled ? u
"1"_s : u
"0"_s );
190 if ( mCoverageLayer )
192 element.setAttribute( u
"coverageLayer"_s, mCoverageLayer.layerId );
193 element.setAttribute( u
"coverageLayerName"_s, mCoverageLayer.name );
194 element.setAttribute( u
"coverageLayerSource"_s, mCoverageLayer.source );
195 element.setAttribute( u
"coverageLayerProvider"_s, mCoverageLayer.provider );
200 QDomElement bodyElement = doc.createElement( u
"body"_s );
201 bodyElement.appendChild( mBody->writeXml( doc, context ) );
202 element.appendChild( bodyElement );
207bool QgsReportSectionFieldGroup::readPropertiesFromElement(
const QDomElement &element,
const QDomDocument &doc,
const QgsReadWriteContext &context )
209 mHeaderVisibility =
static_cast< SectionVisibility
>( element.attribute( u
"headerVisibility"_s ).toInt() );
210 mFooterVisibility =
static_cast< SectionVisibility
>( element.attribute( u
"footerVisibility"_s ).toInt() );
211 mField = element.attribute( u
"field"_s );
212 mSortAscending = element.attribute( u
"ascending"_s ).toInt();
213 mBodyEnabled = element.attribute( u
"bodyEnabled"_s ).toInt();
214 QString layerId = element.attribute( u
"coverageLayer"_s );
215 QString layerName = element.attribute( u
"coverageLayerName"_s );
216 QString layerSource = element.attribute( u
"coverageLayerSource"_s );
217 QString layerProvider = element.attribute( u
"coverageLayerProvider"_s );
218 mCoverageLayer =
QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
219 mCoverageLayer.resolveWeakly( project() );
221 const QDomElement bodyElement = element.firstChildElement( u
"body"_s );
222 if ( !bodyElement.isNull() )
224 const QDomElement bodyLayoutElem = bodyElement.firstChild().toElement();
225 auto body = std::make_unique< QgsLayout >( project() );
226 body->readXml( bodyLayoutElem, doc, context );
227 mBody = std::move( body );
232bool QgsReportSectionFieldGroup::sortAscending()
const
234 return mSortAscending;
237void QgsReportSectionFieldGroup::setSortAscending(
bool sortAscending )
239 mSortAscending = sortAscending;
245 QVariantMap filter = context().fieldFilters;
247 QStringList filterParts;
248 for (
auto filterIt = filter.constBegin(); filterIt != filter.constEnd(); ++filterIt )
251 int fieldIndex = mCoverageLayer->fields().lookupField( filterIt.key() );
252 if ( fieldIndex >= 0 )
258 if ( !filterParts.empty() )
260 QString filterString = u
"(%1)"_s.arg( filterParts.join(
") AND ("_L1 ) );
268QgsFeature QgsReportSectionFieldGroup::getNextFeature()
271 QVariant currentValue;
273 while ( first || ( ( !mBody || !mBodyEnabled ) && mEncounteredValues.contains( currentValue ) ) )
275 if ( !mFeatures.nextFeature( f ) )
281 currentValue = f.
attribute( mFieldIndex );
284 mEncounteredValues.insert( currentValue );
288void QgsReportSectionFieldGroup::updateChildContexts(
const QgsFeature &feature )
290 QgsReportSectionContext
c = context();
292 if ( mCoverageLayer )
293 c.currentLayer = mCoverageLayer.get();
295 QVariantMap currentFilter =
c.fieldFilters;
296 currentFilter.insert( mField, feature.
attribute( mFieldIndex ) );
297 c.fieldFilters = currentFilter;
299 const QList< QgsAbstractReportSection * > sections = childSections();
300 for ( QgsAbstractReportSection *section : std::as_const( sections ) )
302 section->setContext(
c );
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
Wrapper for iterator of features from vector data provider or vector layer.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
A container for the context for various read/write operations on objects.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
_LayerRef< QgsVectorLayer > QgsVectorLayerRef