Skip to content
Permalink
Browse files

allow sorting attribute table by field not listed in the table

fixes #25671

Instead of using a sort filter proxy model on top of the columns model, this uses a dedicated model for the sorting columns
  • Loading branch information
3nids committed May 6, 2020
1 parent b1873a4 commit fcea343f79a95bc0d0e23665ed04f89eac1a0823
@@ -270,7 +270,6 @@ Sets the attributes to display in the table.
to accommodate the new displayed feature attributes.
%End


void setWrapString( const QString &wrapString );
%Docstring
Sets a string to wrap the contents of the table cells by. Occurrences of this string will
@@ -17,6 +17,9 @@ typedef QVector< QVector< QVariant > > QgsLayoutTableContents;

typedef QVector< QgsLayoutTableColumn * > QgsLayoutTableColumns;

typedef QVector< QgsLayoutTableSortColumn * > QgsLayoutTableSortColumns;




class QgsLayoutTableStyle
@@ -473,6 +476,26 @@ Replaces the columns in the table with a specified list of QgsLayoutTableColumns
:param columns: list of QgsLayoutTableColumns to show in table.

.. seealso:: :py:func:`columns`
%End

QgsLayoutTableSortColumns &sortColumns();
%Docstring
Returns a reference to the list of QgsLayoutTableSortColumns shown in the table

.. seealso:: :py:func:`setSortColumns`

.. versionadded:: 3.14
%End

void setSortColumns( const QgsLayoutTableSortColumns &sortColumns );
%Docstring
Replaces the sorting columns in the table with a specified list of QgsLayoutTableSortColumns.

:param columns: list of QgsLayoutTableColumns used to sort the table.

.. seealso:: :py:func:`sortColumns`

.. versionadded:: 3.14
%End

void setCellStyle( CellStyleGroup group, const QgsLayoutTableStyle &style );
@@ -562,6 +585,7 @@ new data.






virtual bool calculateMaxColumnWidths();
@@ -13,9 +13,10 @@
class QgsLayoutTableColumn : QObject
{
%Docstring
Stores properties of a column for a QgsLayoutTable. Some properties of aQgsLayoutTableColumn
are applicable only in certain contexts. For instance, the attribute and setAttribute methods only
have an effect for QgsLayoutItemAttributeTables, and have no effect for QgsLayoutItemTextTables.
Stores properties of a column for a QgsLayoutTable.
Some properties of a QgsLayoutTableColumn are applicable only in certain contexts.
For instance, the attribute and setAttribute methods only have an effect
for QgsLayoutItemAttributeTables, and have no effect for QgsLayoutItemTextTables.

.. versionadded:: 3.0
%End
@@ -146,7 +147,7 @@ is only used when the column is part of a :py:class:`QgsLayoutItemAttributeTable
.. seealso:: :py:func:`attribute`
%End

Qt::SortOrder sortOrder() const;
Qt::SortOrder sortOrder() const /Deprecated/;
%Docstring
Returns the sort order for the column. This property is only used when the column
is part of a QgsLayoutItemAttributeTable and when sortByRank is > 0.
@@ -158,9 +159,12 @@ is part of a QgsLayoutItemAttributeTable and when sortByRank is > 0.
.. seealso:: :py:func:`setSortOrder`

.. seealso:: :py:func:`sortByRank`

.. deprecated:: QGIS 3.14
the order is now hold in a distinct model
%End

void setSortOrder( Qt::SortOrder order );
void setSortOrder( Qt::SortOrder order ) /Deprecated/;
%Docstring
Sets the sort ``order`` for the column. This property is only used when the column
is part of a QgsLayoutItemAttributeTable and when sortByRank() is > 0.
@@ -172,9 +176,12 @@ is part of a QgsLayoutItemAttributeTable and when sortByRank() is > 0.
.. seealso:: :py:func:`sortOrder`

.. seealso:: :py:func:`setSortByRank`

.. deprecated:: QGIS 3.14
the order is now hold in a distinct model
%End

int sortByRank() const;
int sortByRank() const /Deprecated/;
%Docstring
Returns the sort rank for the column. If the sort rank is > 0 then the column
will be sorted in the table. The sort rank specifies the priority given to the
@@ -191,9 +198,12 @@ If sort rank is <= 0 then the column is not being sorted.
.. seealso:: :py:func:`setSortByRank`

.. seealso:: :py:func:`sortOrder`

.. deprecated:: QGIS 3.14
the order is now hold in a distinct model
%End

void setSortByRank( int rank );
void setSortByRank( int rank ) /Deprecated/;
%Docstring
Sets the sort ``rank`` for the column. If the sort rank is > 0 then the column
will be sorted in the table. The sort rank specifies the priority given to the
@@ -209,6 +219,9 @@ If the sort ``rank`` is <= 0 then the column is not being sorted.
.. seealso:: :py:func:`sortByRank`

.. seealso:: :py:func:`setSortOrder`

.. deprecated:: QGIS 3.14
the order is now hold in a distinct model
%End

QgsLayoutTableColumn *clone() /Factory/;
@@ -220,6 +233,106 @@ Creates a duplicate column which is a deep copy of this column.

};

class QgsLayoutTableSortColumn : QObject
{
%Docstring
Stores properties of a column for the sorting of a :py:class:`QgsLayoutTable`.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgslayouttablecolumn.h"
%End
public:

QgsLayoutTableSortColumn();
%Docstring
Constructor for :py:class:`QgsLayoutTableColumn`.

:param heading: column heading
%End

bool writeXml( QDomElement &columnElem, QDomDocument &doc ) const;
%Docstring
Writes the column's properties to xml for storage.

:param columnElem: an existing QDomElement in which to store the column's properties.
:param doc: QDomDocument for the destination xml.

.. seealso:: :py:func:`readXml`
%End

bool readXml( const QDomElement &columnElem );
%Docstring
Reads the column's properties from xml.

:param columnElem: a QDomElement holding the column's desired properties.

.. seealso:: :py:func:`writeXml`
%End

QString attribute() const;
%Docstring
Returns the attribute name or expression used for the column's values. This property
is only used when the column is part of a :py:class:`QgsLayoutItemAttributeTable`.

.. note::

only applicable when used in a :py:class:`QgsLayoutItemAttributeTable`

.. seealso:: :py:func:`setAttribute`
%End

void setAttribute( const QString &attribute );
%Docstring
Sets the ``attribute`` name or expression used for the column's values. This property
is only used when the column is part of a :py:class:`QgsLayoutItemAttributeTable`.

.. note::

only applicable when used in a :py:class:`QgsLayoutItemAttributeTable`

.. seealso:: :py:func:`attribute`
%End

Qt::SortOrder sortOrder() const;
%Docstring
Returns the sort order for the column. This property is only used when the column
is part of a QgsLayoutItemAttributeTable and when sortByRank is > 0.

.. note::

only applicable when used in a :py:class:`QgsLayoutItemAttributeTable`

.. seealso:: :py:func:`setSortOrder`

.. seealso:: :py:func:`sortByRank`
%End

void setSortOrder( Qt::SortOrder order );
%Docstring
Sets the sort ``order`` for the column. This property is only used when the column
is part of a QgsLayoutItemAttributeTable and when sortByRank() is > 0.

.. note::

only applicable when used in a :py:class:`QgsLayoutItemAttributeTable`

.. seealso:: :py:func:`sortOrder`

.. seealso:: :py:func:`setSortByRank`
%End

QgsLayoutTableSortColumn *clone() /Factory/;
%Docstring
Creates a duplicate column which is a deep copy of this column.

:return: a new QgsLayoutTableSortColumn with same properties as this column.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
@@ -1462,6 +1462,14 @@ bool QgsCompositionConverter::readTableXml( QgsLayoutItemAttributeTable *layoutI
}
}
layoutItem->mColumns.append( column );

// sorting columns are now (QGIS 3.14+) handled in a dedicated list
QVector<QgsLayoutTableColumn *> sortColumns;
Q_NOWARN_DEPRECATED_PUSH
std::copy_if( layoutItem->mColumns.begin(), layoutItem->mColumns.end(), std::back_inserter( sortColumns ), []( QgsLayoutTableColumn * col ) {return col->sortByRank() > 0;} );
std::sort( sortColumns.begin(), sortColumns.end(), []( QgsLayoutTableColumn * a, QgsLayoutTableColumn * b ) {return a->sortByRank() < b->sortByRank();} );
Q_NOWARN_DEPRECATED_POP
// TODO remove comment: layoutItem->mSortColumns = sortColumns;
}
}

@@ -172,6 +172,8 @@ void QgsLayoutItemAttributeTable::resetColumns()
//remove existing columns
qDeleteAll( mColumns );
mColumns.clear();
qDeleteAll( mSortColumns );
mSortColumns.clear();

//rebuild columns list from vector layer fields
int idx = 0;
@@ -480,10 +482,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 QgsLayoutTableSortColumn *column : qgis::as_const( mSortColumns ) )
{
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;
@@ -722,39 +723,6 @@ void QgsLayoutItemAttributeTable::removeLayer( const QString &layerId )
}
}

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 )
@@ -256,15 +256,6 @@ class CORE_EXPORT QgsLayoutItemAttributeTable: public QgsLayoutTable
*/
void setDisplayedFields( const QStringList &fields, bool refresh = true );

/**
* Returns the attributes used to sort the table's features.
* \returns a QList of integer/bool pairs, where the integer refers to the attribute index and
* the bool to the sort order for the attribute. If TRUE the attribute is sorted ascending,
* if FALSE, the attribute is sorted in descending order.
* \note not available in Python bindings
*/
QVector< QPair<int, bool> > sortAttributes() const SIP_SKIP;

/**
* Sets a string to wrap the contents of the table cells by. Occurrences of this string will
* be replaced by a line break.

0 comments on commit fcea343

Please sign in to comment.
You can’t perform that action at this time.