-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[layout] allow sorting attribute table by field not listed in the table #36236
Changes from 9 commits
fcea343
03f4cb9
525661c
e7fe141
ee686b5
ab4e179
2b252c8
971d107
28c20cf
51b0d5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -170,19 +170,19 @@ void QgsLayoutItemAttributeTable::resetColumns() | |
} | ||
|
||
//remove existing columns | ||
qDeleteAll( mColumns ); | ||
mColumns.clear(); | ||
mSortColumns.clear(); | ||
|
||
//rebuild columns list from vector layer fields | ||
int idx = 0; | ||
const QgsFields sourceFields = source->fields(); | ||
for ( const auto &field : sourceFields ) | ||
{ | ||
QString currentAlias = source->attributeDisplayName( idx ); | ||
std::unique_ptr< QgsLayoutTableColumn > col = qgis::make_unique< QgsLayoutTableColumn >(); | ||
col->setAttribute( field.name() ); | ||
col->setHeading( currentAlias ); | ||
mColumns.append( col.release() ); | ||
QgsLayoutTableColumn col; | ||
col.setAttribute( field.name() ); | ||
col.setHeading( currentAlias ); | ||
mColumns.append( col ); | ||
idx++; | ||
} | ||
} | ||
|
@@ -319,7 +319,6 @@ void QgsLayoutItemAttributeTable::setDisplayedFields( const QStringList &fields, | |
} | ||
|
||
//rebuild columns list, taking only fields contained in supplied list | ||
qDeleteAll( mColumns ); | ||
mColumns.clear(); | ||
|
||
const QgsFields layerFields = source->fields(); | ||
|
@@ -333,10 +332,10 @@ void QgsLayoutItemAttributeTable::setDisplayedFields( const QStringList &fields, | |
continue; | ||
|
||
QString currentAlias = source->attributeDisplayName( attrIdx ); | ||
std::unique_ptr< QgsLayoutTableColumn > col = qgis::make_unique< QgsLayoutTableColumn >(); | ||
col->setAttribute( layerFields.at( attrIdx ).name() ); | ||
col->setHeading( currentAlias ); | ||
mColumns.append( col.release() ); | ||
QgsLayoutTableColumn col; | ||
col.setAttribute( layerFields.at( attrIdx ).name() ); | ||
col.setHeading( currentAlias ); | ||
mColumns.append( col ); | ||
} | ||
} | ||
else | ||
|
@@ -346,10 +345,10 @@ void QgsLayoutItemAttributeTable::setDisplayedFields( const QStringList &fields, | |
for ( const QgsField &field : layerFields ) | ||
{ | ||
QString currentAlias = source->attributeDisplayName( idx ); | ||
std::unique_ptr< QgsLayoutTableColumn > col = qgis::make_unique< QgsLayoutTableColumn >(); | ||
col->setAttribute( field.name() ); | ||
col->setHeading( currentAlias ); | ||
mColumns.append( col.release() ); | ||
QgsLayoutTableColumn col; | ||
col.setAttribute( field.name() ); | ||
col.setHeading( currentAlias ); | ||
mColumns.append( col ); | ||
idx++; | ||
} | ||
} | ||
|
@@ -368,16 +367,16 @@ void QgsLayoutItemAttributeTable::restoreFieldAliasMap( const QMap<int, QString> | |
return; | ||
} | ||
|
||
for ( QgsLayoutTableColumn *column : qgis::as_const( mColumns ) ) | ||
for ( QgsLayoutTableColumn &column : mColumns ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that you're NOT allowed to modify a qt container inside a range based loop. Can you confirm that this is safe? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. correct, I will fix this |
||
{ | ||
int attrIdx = source->fields().lookupField( column->attribute() ); | ||
int attrIdx = source->fields().lookupField( column.attribute() ); | ||
if ( map.contains( attrIdx ) ) | ||
{ | ||
column->setHeading( map.value( attrIdx ) ); | ||
column.setHeading( map.value( attrIdx ) ); | ||
} | ||
else | ||
{ | ||
column->setHeading( source->attributeDisplayName( attrIdx ) ); | ||
column.setHeading( source->attributeDisplayName( attrIdx ) ); | ||
} | ||
} | ||
} | ||
|
@@ -480,10 +479,9 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont | |
req.setFilterFid( atlasFeature.id() ); | ||
} | ||
|
||
QVector< QPair<int, bool> > sortColumns = sortAttributes(); | ||
for ( int i = sortColumns.size() - 1; i >= 0; --i ) | ||
for ( const QgsLayoutTableColumn &column : qgis::as_const( mSortColumns ) ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there's an api break here -- if someone is using the old api to set a list of columns with their sort order contained, then that won't be respected here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then setColumns would be used, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about that too- but wouldn't it be hard to differentiate between a call to setColumns using the old API, vs correct use of the new api and calling setSortColumns and then later setColumns? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, if you correctly use the API there is no sorting info (rank) in the list when calling setColumns. If there is, then you're using the old API and we call setSortColumns. |
||
{ | ||
req = req.addOrderBy( mColumns.at( sortColumns.at( i ).first )->attribute(), sortColumns.at( i ).second ); | ||
req = req.addOrderBy( column.attribute(), column.sortOrder() == Qt::AscendingOrder ); | ||
} | ||
|
||
QgsFeature f; | ||
|
@@ -549,9 +547,9 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont | |
QgsLayoutTableRow rowContents; | ||
rowContents.reserve( mColumns.count() ); | ||
|
||
for ( QgsLayoutTableColumn *column : qgis::as_const( mColumns ) ) | ||
for ( const QgsLayoutTableColumn &column : qgis::as_const( mColumns ) ) | ||
{ | ||
int idx = layer->fields().lookupField( column->attribute() ); | ||
int idx = layer->fields().lookupField( column.attribute() ); | ||
|
||
QgsConditionalStyle style; | ||
|
||
|
@@ -574,7 +572,7 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont | |
else | ||
{ | ||
// Lets assume it's an expression | ||
std::unique_ptr< QgsExpression > expression = qgis::make_unique< QgsExpression >( column->attribute() ); | ||
std::unique_ptr< QgsExpression > expression = qgis::make_unique< QgsExpression >( column.attribute() ); | ||
context.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "row_number" ), counter + 1, true ) ); | ||
expression->prepare( &context ); | ||
QVariant value = expression->evaluate( &context ); | ||
|
@@ -716,45 +714,11 @@ void QgsLayoutItemAttributeTable::removeLayer( const QString &layerId ) | |
{ | ||
mVectorLayer.setLayer( nullptr ); | ||
//remove existing columns | ||
qDeleteAll( mColumns ); | ||
mColumns.clear(); | ||
} | ||
} | ||
} | ||
|
||
static bool columnsBySortRank( QPair<int, QgsLayoutTableColumn * > a, QPair<int, QgsLayoutTableColumn * > b ) | ||
{ | ||
return a.second->sortByRank() < b.second->sortByRank(); | ||
} | ||
|
||
QVector<QPair<int, bool> > QgsLayoutItemAttributeTable::sortAttributes() const | ||
{ | ||
//generate list of all sorted columns | ||
QVector< QPair<int, QgsLayoutTableColumn * > > sortedColumns; | ||
int idx = 0; | ||
for ( QgsLayoutTableColumn *column : mColumns ) | ||
{ | ||
if ( column->sortByRank() > 0 ) | ||
{ | ||
sortedColumns.append( qMakePair( idx, column ) ); | ||
} | ||
idx++; | ||
} | ||
|
||
//sort columns by rank | ||
std::sort( sortedColumns.begin(), sortedColumns.end(), columnsBySortRank ); | ||
|
||
//generate list of column index, bool for sort direction (to match 2.0 api) | ||
QVector<QPair<int, bool> > attributesBySortRank; | ||
attributesBySortRank.reserve( sortedColumns.size() ); | ||
for ( auto &column : qgis::as_const( sortedColumns ) ) | ||
{ | ||
attributesBySortRank.append( qMakePair( column.first, | ||
column.second->sortOrder() == Qt::AscendingOrder ) ); | ||
} | ||
return attributesBySortRank; | ||
} | ||
|
||
void QgsLayoutItemAttributeTable::setWrapString( const QString &wrapString ) | ||
{ | ||
if ( wrapString == mWrapString ) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this would be easier to read/safer if you enclosed the loop contents in { / }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will switch back to
std::copy_if
then