Skip to content
Permalink
Browse files

[layouts] Improve Manual Table handling of header cells

Instead of hiding this functionality from users, we instead add an explicit
toggle to the Table Designer dialog "Table" menu to hide or show
the header cells in the designer, and re-add the widgets which
allow users to customise the header appearance back into the
item configuration widget.

Whenever a header cell is selected in the table designer, the formatting
widgets are disabled since the item's header configuration widgets
are used to set the background/foreground color and other properties
of these cells instead.
  • Loading branch information
nyalldawson committed Feb 13, 2020
1 parent 82324ec commit 756cb6f592b8793ddfc72c7e24327c9198213d78
@@ -29,6 +29,8 @@ Constructor for QgsLayoutItemManualTable, attached to the specified ``layout``.
Ownership is transferred to the layout.
%End

~QgsLayoutItemManualTable();

virtual int type() const;

virtual QIcon icon() const;
@@ -99,6 +101,34 @@ A width of 0 indicates that the column width should be automatically calculated.
.. seealso:: :py:func:`columnWidths`

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

bool includeTableHeader() const;
%Docstring
Returns ``True`` if the table includes a header row.

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

void setIncludeTableHeader( bool included );
%Docstring
Sets whether the table includes a header row.

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

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

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

void setHeaders( const QgsLayoutTableColumns &headers );
%Docstring
Replaces the headers in the table with a specified list of :py:class:`QgsLayoutTableColumns`.

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

protected:
@@ -78,13 +78,46 @@ if an automatic width should be used for the column.
This should be called after a call to setTableContents().

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

bool includeTableHeader() const;
%Docstring
Returns ``True`` if the table includes a header row.

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

void setIncludeTableHeader( bool included );
%Docstring
Sets whether the table includes a header row.

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

QVariantList tableHeaders() const;
%Docstring
Returns the table header values.

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

void setTableHeaders( const QVariantList &headers );
%Docstring
Sets the table ``headers``.

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

signals:

void tableChanged();
%Docstring
Emitted whenever the table contents are changed.
%End

void includeHeaderChanged( bool included );
%Docstring
Emitted whenever the "include table header" setting is changed.
%End

};
@@ -160,6 +160,18 @@ Returns a list of the rows associated with the current table selected cells.
Returns a list of the columns associated with the current table selected cells.

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

QVariantList tableHeaders() const;
%Docstring
Returns the table header values.

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

bool isHeaderCellSelected();
%Docstring
Returns ``True`` if any header cells are selected.
%End

public slots:
@@ -257,6 +269,20 @@ Sets the row ``height`` (in millimeters) for the currently selected rows, or 0 f
Sets the column ``width`` (in millimeters) for the currently selected columns, or 0 for automatic column width.

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

void setIncludeTableHeader( bool included );
%Docstring
Sets whether the table includes a header row.

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

void setTableHeaders( const QVariantList &headers );
%Docstring
Sets the table ``headers``.

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

protected:
@@ -33,6 +33,11 @@ QgsLayoutItemManualTable::QgsLayoutItemManualTable( QgsLayout *layout )
refreshAttributes();
}

QgsLayoutItemManualTable::~QgsLayoutItemManualTable()
{
qDeleteAll( mHeaders );
}

int QgsLayoutItemManualTable::type() const
{
return QgsLayoutItemRegistry::LayoutManualTable;
@@ -131,11 +136,55 @@ void QgsLayoutItemManualTable::setColumnWidths( const QList<double> &widths )
refreshAttributes();
}

bool QgsLayoutItemManualTable::includeTableHeader() const
{
return mIncludeHeader;
}

void QgsLayoutItemManualTable::setIncludeTableHeader( bool included )
{
mIncludeHeader = included;

if ( !mIncludeHeader )
setHeaderMode( NoHeaders );
else
setHeaderMode( AllFrames );
refreshColumns();
refreshAttributes();
}

QgsLayoutTableColumns &QgsLayoutItemManualTable::headers()
{
return mHeaders;
}

void QgsLayoutItemManualTable::setHeaders( const QgsLayoutTableColumns &headers )
{
qDeleteAll( mHeaders );
mHeaders.clear();

mHeaders.append( headers );
refreshColumns();
refreshAttributes();
}

bool QgsLayoutItemManualTable::writePropertiesToElement( QDomElement &tableElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
{
if ( !QgsLayoutTable::writePropertiesToElement( tableElem, doc, context ) )
return false;

tableElem.setAttribute( QStringLiteral( "includeHeader" ), mIncludeHeader ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );

//headers
QDomElement headersElem = doc.createElement( QStringLiteral( "headers" ) );
for ( QgsLayoutTableColumn *header : mHeaders )
{
QDomElement headerElem = doc.createElement( QStringLiteral( "header" ) );
header->writeXml( headerElem, doc );
headersElem.appendChild( headerElem );
}
tableElem.appendChild( headersElem );

QDomElement contentsElement = doc.createElement( QStringLiteral( "contents" ) );
for ( const QgsTableRow &row : mContents )
{
@@ -177,6 +226,24 @@ bool QgsLayoutItemManualTable::readPropertiesFromElement( const QDomElement &ite
if ( !QgsLayoutTable::readPropertiesFromElement( itemElem, doc, context ) )
return false;

mIncludeHeader = itemElem.attribute( QStringLiteral( "includeHeader" ) ).toInt();
//restore header specifications
qDeleteAll( mHeaders );
mHeaders.clear();
QDomNodeList headersList = itemElem.elementsByTagName( QStringLiteral( "headers" ) );
if ( !headersList.isEmpty() )
{
QDomElement headersElem = headersList.at( 0 ).toElement();
QDomNodeList headerEntryList = headersElem.elementsByTagName( QStringLiteral( "header" ) );
for ( int i = 0; i < headerEntryList.size(); ++i )
{
QDomElement headerElem = headerEntryList.at( i ).toElement();
QgsLayoutTableColumn *header = new QgsLayoutTableColumn;
header->readXml( headerElem );
mHeaders.append( header );
}
}

mRowHeights.clear();
const QDomNodeList rowHeightNodeList = itemElem.firstChildElement( QStringLiteral( "rowHeights" ) ).childNodes();
mRowHeights.reserve( rowHeightNodeList.size() );
@@ -252,7 +319,7 @@ void QgsLayoutItemManualTable::refreshColumns()
for ( const QgsTableCell &cell : firstRow )
{
( void )cell;
std::unique_ptr< QgsLayoutTableColumn > newCol = qgis::make_unique< QgsLayoutTableColumn >( QString() );
std::unique_ptr< QgsLayoutTableColumn > newCol = qgis::make_unique< QgsLayoutTableColumn >( mHeaders.value( colIndex ) ? mHeaders.value( colIndex )->heading() : QString() );
newCol->setWidth( mColumnWidths.value( colIndex ) );
columns << newCol.release();
colIndex++;
@@ -41,6 +41,8 @@ class CORE_EXPORT QgsLayoutItemManualTable: public QgsLayoutTable
*/
QgsLayoutItemManualTable( QgsLayout *layout SIP_TRANSFERTHIS );

~QgsLayoutItemManualTable() override;

int type() const override;
QIcon icon() const override;
QString displayName() const override;
@@ -106,6 +108,32 @@ class CORE_EXPORT QgsLayoutItemManualTable: public QgsLayoutTable
*/
void setColumnWidths( const QList< double > &widths );

/**
* Returns TRUE if the table includes a header row.
*
* \see setIncludeTableHeader()
*/
bool includeTableHeader() const;

/**
* Sets whether the table includes a header row.
*
* \see includeTableHeader()
*/
void setIncludeTableHeader( bool included );

/**
* Returns a reference to the list of headers shown in the table
* \see setHeaders()
*/
QgsLayoutTableColumns &headers();

/**
* Replaces the headers in the table with a specified list of QgsLayoutTableColumns.
* \see headers()
*/
void setHeaders( const QgsLayoutTableColumns &headers );

protected:

bool writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
@@ -115,9 +143,11 @@ class CORE_EXPORT QgsLayoutItemManualTable: public QgsLayoutTable
private:

QgsTableContents mContents;
QgsLayoutTableColumns mHeaders;

QList< double > mRowHeights;
QList< double > mColumnWidths;
bool mIncludeHeader = false;

void refreshColumns();

0 comments on commit 756cb6f

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