Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 fcea343
Show file tree
Hide file tree
Showing 14 changed files with 580 additions and 418 deletions.
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions python/core/auto_generated/layout/qgslayouttable.sip.in
Expand Up @@ -17,6 +17,9 @@ typedef QVector< QVector< QVariant > > QgsLayoutTableContents;

typedef QVector< QgsLayoutTableColumn * > QgsLayoutTableColumns;

typedef QVector< QgsLayoutTableSortColumn * > QgsLayoutTableSortColumns;




class QgsLayoutTableStyle
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -562,6 +585,7 @@ new data.






virtual bool calculateMaxColumnWidths();
Expand Down
127 changes: 120 additions & 7 deletions python/core/auto_generated/layout/qgslayouttablecolumn.sip.in
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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/;
Expand All @@ -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 *
* *
Expand Down
8 changes: 8 additions & 0 deletions src/core/layout/qgscompositionconverter.cpp
Expand Up @@ -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;
}
}

Expand Down
40 changes: 4 additions & 36 deletions src/core/layout/qgslayoutitemattributetable.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 )
Expand Down
9 changes: 0 additions & 9 deletions src/core/layout/qgslayoutitemattributetable.h
Expand Up @@ -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.
Expand Down

0 comments on commit fcea343

Please sign in to comment.