QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgslayoutitemmanualtable.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutitemmanualtable.cpp
3  ---------------------------
4  begin : January 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsconditionalstyle.h"
20 #include "qgslayoutitemregistry.h"
21 #include "qgslayouttablecolumn.h"
22 #include "qgsnumericformat.h"
23 #include "qgsxmlutils.h"
24 
25 //
26 // QgsLayoutItemManualTable
27 //
28 
30  : QgsLayoutTable( layout )
31 {
34 }
35 
37 {
38 }
39 
41 {
43 }
44 
46 {
47  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemTable.svg" ) );
48 }
49 
51 {
52  return new QgsLayoutItemManualTable( layout );
53 }
54 
56 {
57  return tr( "<Table frame>" );
58 }
59 
61 {
62  contents.clear();
63 
64  QgsNumericFormatContext numericContext;
65 
66  for ( const QgsTableRow &row : qgis::as_const( mContents ) )
67  {
68  QgsLayoutTableRow currentRow;
69 
70  for ( int i = 0; i < mColumns.count(); ++i )
71  {
72  if ( i < row.count() )
73  {
74  if ( row.at( i ).numericFormat() )
75  currentRow << row.at( i ).numericFormat()->formatDouble( row.at( i ).content().toDouble(), numericContext );
76  else
77  currentRow << row.at( i ).content().toString();
78  }
79  else
80  {
81  currentRow << QString();
82  }
83  }
84  contents << currentRow;
85  }
86 
88  return true;
89 }
90 
92 {
93  if ( row < 0 || row >= mContents.size() )
94  return QgsConditionalStyle();
95 
96  const QgsTableRow &rowContents = mContents[ row ];
97  if ( column < 0 || column > rowContents.size() )
98  return QgsConditionalStyle();
99 
100  const QgsTableCell &c = rowContents[ column ];
102  if ( c.foregroundColor().isValid() )
103  res.setTextColor( c.foregroundColor() );
104  if ( c.backgroundColor().isValid() )
105  res.setBackgroundColor( c.backgroundColor() );
106 
107  return res;
108 }
109 
111 {
112  mContents = contents;
113 
114  refreshColumns();
116 }
117 
119 {
120  return mContents;
121 }
122 
123 void QgsLayoutItemManualTable::setRowHeights( const QList<double> &heights )
124 {
125  mRowHeights = heights;
126 
128 }
129 
130 void QgsLayoutItemManualTable::setColumnWidths( const QList<double> &widths )
131 {
132  mColumnWidths = widths;
133 
134  refreshColumns();
136 }
137 
139 {
140  return mIncludeHeader;
141 }
142 
144 {
145  mIncludeHeader = included;
146 
147  if ( !mIncludeHeader )
149  else
151  refreshColumns();
153 }
154 
156 {
157  return mHeaders;
158 }
159 
161 {
162  mHeaders.clear();
163 
164  mHeaders.append( headers );
165  refreshColumns();
167 }
168 
169 bool QgsLayoutItemManualTable::writePropertiesToElement( QDomElement &tableElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
170 {
171  if ( !QgsLayoutTable::writePropertiesToElement( tableElem, doc, context ) )
172  return false;
173 
174  tableElem.setAttribute( QStringLiteral( "includeHeader" ), mIncludeHeader ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
175 
176  //headers
177  QDomElement headersElem = doc.createElement( QStringLiteral( "headers" ) );
178  for ( const QgsLayoutTableColumn &header : qgis::as_const( mHeaders ) )
179  {
180  QDomElement headerElem = doc.createElement( QStringLiteral( "header" ) );
181  header.writeXml( headerElem, doc );
182  headersElem.appendChild( headerElem );
183  }
184  tableElem.appendChild( headersElem );
185 
186  QDomElement contentsElement = doc.createElement( QStringLiteral( "contents" ) );
187  for ( const QgsTableRow &row : mContents )
188  {
189  QDomElement rowElement = doc.createElement( QStringLiteral( "row" ) );
190  for ( int i = 0; i < mColumns.count(); ++i )
191  {
192  if ( i < row.count() )
193  {
194  rowElement.appendChild( QgsXmlUtils::writeVariant( row.at( i ).properties( context ), doc ) );
195  }
196  }
197  contentsElement.appendChild( rowElement );
198  }
199  tableElem.appendChild( contentsElement );
200 
201  QDomElement rowHeightsElement = doc.createElement( QStringLiteral( "rowHeights" ) );
202  for ( double height : mRowHeights )
203  {
204  QDomElement rowElement = doc.createElement( QStringLiteral( "row" ) );
205  rowElement.setAttribute( QStringLiteral( "height" ), height );
206  rowHeightsElement.appendChild( rowElement );
207  }
208  tableElem.appendChild( rowHeightsElement );
209 
210  QDomElement columnWidthsElement = doc.createElement( QStringLiteral( "columnWidths" ) );
211  for ( double width : mColumnWidths )
212  {
213  QDomElement columnElement = doc.createElement( QStringLiteral( "column" ) );
214  columnElement.setAttribute( QStringLiteral( "width" ), width );
215  columnWidthsElement.appendChild( columnElement );
216  }
217  tableElem.appendChild( columnWidthsElement );
218 
219  return true;
220 }
221 
222 bool QgsLayoutItemManualTable::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context )
223 {
224  if ( !QgsLayoutTable::readPropertiesFromElement( itemElem, doc, context ) )
225  return false;
226 
227  mIncludeHeader = itemElem.attribute( QStringLiteral( "includeHeader" ) ).toInt();
228  //restore header specifications
229  mHeaders.clear();
230  QDomNodeList headersList = itemElem.elementsByTagName( QStringLiteral( "headers" ) );
231  if ( !headersList.isEmpty() )
232  {
233  QDomElement headersElem = headersList.at( 0 ).toElement();
234  QDomNodeList headerEntryList = headersElem.elementsByTagName( QStringLiteral( "header" ) );
235  for ( int i = 0; i < headerEntryList.size(); ++i )
236  {
237  QDomElement headerElem = headerEntryList.at( i ).toElement();
238  QgsLayoutTableColumn header;
239  header.readXml( headerElem );
240  mHeaders.append( header );
241  }
242  }
243 
244  mRowHeights.clear();
245  const QDomNodeList rowHeightNodeList = itemElem.firstChildElement( QStringLiteral( "rowHeights" ) ).childNodes();
246  mRowHeights.reserve( rowHeightNodeList.size() );
247  for ( int r = 0; r < rowHeightNodeList.size(); ++r )
248  {
249  const QDomElement rowHeightElement = rowHeightNodeList.at( r ).toElement();
250  mRowHeights.append( rowHeightElement.attribute( QStringLiteral( "height" ) ).toDouble() );
251  }
252 
253  mColumnWidths.clear();
254  const QDomNodeList columnWidthNodeList = itemElem.firstChildElement( QStringLiteral( "columnWidths" ) ).childNodes();
255  mColumnWidths.reserve( columnWidthNodeList.size() );
256  for ( int r = 0; r < columnWidthNodeList.size(); ++r )
257  {
258  const QDomElement columnWidthElement = columnWidthNodeList.at( r ).toElement();
259  mColumnWidths.append( columnWidthElement.attribute( QStringLiteral( "width" ) ).toDouble() );
260  }
261 
262  QgsTableContents newContents;
263  const QDomElement contentsElement = itemElem.firstChildElement( QStringLiteral( "contents" ) );
264  const QDomNodeList rowNodeList = contentsElement.childNodes();
265  newContents.reserve( rowNodeList.size() );
266  for ( int r = 0; r < rowNodeList.size(); ++r )
267  {
268  QgsTableRow row;
269  const QDomElement rowElement = rowNodeList.at( r ).toElement();
270  const QDomNodeList cellNodeList = rowElement.childNodes();
271  row.reserve( cellNodeList.size() );
272  for ( int c = 0; c < cellNodeList.size(); ++c )
273  {
274  const QDomElement cellElement = cellNodeList.at( c ).toElement();
275  QgsTableCell newCell;
276  newCell.setProperties( QgsXmlUtils::readVariant( cellElement ).toMap(), context );
277  row << newCell;
278  }
279  newContents << row;
280  }
281  setTableContents( newContents );
282 
283  emit changed();
284  return true;
285 }
286 
288 {
290  return false;
291 
292  QMap<int, double> newHeights;
293  for ( auto it = mMaxRowHeightMap.constBegin(); it != mMaxRowHeightMap.constEnd(); ++it )
294  {
295  // first row in mMaxRowHeightMap corresponds to header, which we ignore here
296  const int row = it.key() - 1;
297  const double presetHeight = mRowHeights.value( row );
298  double thisRowHeight = it.value();
299  if ( presetHeight > 0 )
300  thisRowHeight = presetHeight;
301  newHeights.insert( row + 1, thisRowHeight );
302  }
303  mMaxRowHeightMap = newHeights;
304  return true;
305 }
306 
307 void QgsLayoutItemManualTable::refreshColumns()
308 {
309  // refresh columns
311  if ( !mContents.empty() )
312  {
313  int colIndex = 0;
314  const QgsTableRow &firstRow = mContents[ 0 ];
315  columns.reserve( firstRow.size() );
316  for ( const QgsTableCell &cell : firstRow )
317  {
318  ( void )cell;
319  QgsLayoutTableColumn newCol( mHeaders.value( colIndex ).heading() );
320  newCol.setWidth( mColumnWidths.value( colIndex ) );
321  columns << newCol;
322  colIndex++;
323  }
324  }
325  setColumns( columns );
326 }
QgsLayoutItemManualTable::headers
QgsLayoutTableColumns & headers()
Returns a reference to the list of headers shown in the table.
Definition: qgslayoutitemmanualtable.cpp:155
QgsLayoutTable::setHeaderMode
void setHeaderMode(HeaderMode mode)
Sets the display mode for headers in the table.
Definition: qgslayouttable.cpp:656
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:118
qgsconditionalstyle.h
QgsLayoutTableColumns
QVector< QgsLayoutTableColumn > QgsLayoutTableColumns
Definition: qgslayouttable.h:57
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
QgsLayoutItemManualTable::tableContents
QgsTableContents tableContents() const
Returns the contents of the table.
Definition: qgslayoutitemmanualtable.cpp:118
QgsLayoutTableContents
QVector< QgsLayoutTableRow > QgsLayoutTableContents
Definition: qgslayouttable.h:46
QgsReadWriteContext
Definition: qgsreadwritecontext.h:34
QgsConditionalStyle::setBackgroundColor
void setBackgroundColor(const QColor &value)
Set the background color for the style.
Definition: qgsconditionalstyle.h:155
QgsConditionalStyle::setTextColor
void setTextColor(const QColor &value)
Set the text color for the style.
Definition: qgsconditionalstyle.h:161
QgsLayoutItemManualTable::setRowHeights
void setRowHeights(const QList< double > &heights)
Sets the list of row heights (in millimeters) to use when rendering the table.
Definition: qgslayoutitemmanualtable.cpp:123
QgsLayoutTable::columns
QgsLayoutTableColumns & columns()
Returns a reference to the list of QgsLayoutTableColumns shown in the table.
Definition: qgslayouttable.h:441
QgsLayoutItemManualTable::QgsLayoutItemManualTable
QgsLayoutItemManualTable(QgsLayout *layout)
Constructor for QgsLayoutItemManualTable, attached to the specified layout.
Definition: qgslayoutitemmanualtable.cpp:29
QgsLayoutItemManualTable::conditionalCellStyle
QgsConditionalStyle conditionalCellStyle(int row, int column) const override
Returns the conditional style to use for the cell at row, column.
Definition: qgslayoutitemmanualtable.cpp:91
QgsLayoutItemManualTable::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets multiframe state from a DOM element.
Definition: qgslayoutitemmanualtable.cpp:222
QgsLayoutTable::writePropertiesToElement
bool writePropertiesToElement(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Stores multiframe state within an XML DOM element.
Definition: qgslayouttable.cpp:76
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsLayoutItemManualTable::setTableContents
void setTableContents(const QgsTableContents &contents)
Sets the contents of the table.
Definition: qgslayoutitemmanualtable.cpp:110
QgsConditionalStyle
Definition: qgsconditionalstyle.h:112
QgsLayoutTableColumn::readXml
bool readXml(const QDomElement &columnElem)
Reads the column's properties from xml.
Definition: qgslayouttablecolumn.cpp:50
QgsTableContents
QVector< QgsTableRow > QgsTableContents
A set of table rows.
Definition: qgstablecell.h:158
QgsLayoutTable::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context) override
Sets multiframe state from a DOM element.
Definition: qgslayouttable.cpp:134
QgsTableCell
Encapsulates the contents and formatting of a single table cell.
Definition: qgstablecell.h:34
QgsLayoutTable::contents
QgsLayoutTableContents & contents()
Returns the current contents of the table.
Definition: qgslayouttable.h:502
QgsXmlUtils::readVariant
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
Definition: qgsxmlutils.cpp:251
QgsLayoutItemManualTable::getTableContents
bool getTableContents(QgsLayoutTableContents &contents) override
Fetches the contents used for the cells in the table.
Definition: qgslayoutitemmanualtable.cpp:60
QgsLayoutItemManualTable::displayName
QString displayName() const override
Returns the multiframe display name.
Definition: qgslayoutitemmanualtable.cpp:55
QgsLayoutTable::NoHeaders
@ NoHeaders
No headers shown for table.
Definition: qgslayouttable.h:135
QgsLayoutItemManualTable::includeTableHeader
bool includeTableHeader() const
Returns true if the table includes a header row.
Definition: qgslayoutitemmanualtable.cpp:138
QgsLayoutItemManualTable::setHeaders
void setHeaders(const QgsLayoutTableColumns &headers)
Replaces the headers in the table with a specified list of QgsLayoutTableColumns.
Definition: qgslayoutitemmanualtable.cpp:160
QgsLayoutItemManualTable::setIncludeTableHeader
void setIncludeTableHeader(bool included)
Sets whether the table includes a header row.
Definition: qgslayoutitemmanualtable.cpp:143
QgsLayoutItemManualTable::writePropertiesToElement
bool writePropertiesToElement(QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context) const override
Stores multiframe state within an XML DOM element.
Definition: qgslayoutitemmanualtable.cpp:169
QgsLayoutItemManualTable::icon
QIcon icon() const override
Returns the item's icon.
Definition: qgslayoutitemmanualtable.cpp:45
QgsLayoutTable
A class to display a table in the print layout, and allow the table to span over multiple frames.
Definition: qgslayouttable.h:111
QgsLayoutTable::refreshAttributes
virtual void refreshAttributes()
Refreshes the contents shown in the table by querying for new data.
Definition: qgslayouttable.cpp:866
qgsxmlutils.h
QgsLayoutTable::recalculateTableSize
void recalculateTableSize()
Recalculates and updates the size of the table and all table frames.
Definition: qgslayouttable.cpp:1353
qgsnumericformat.h
qgslayoutitemmanualtable.h
QgsLayoutTable::calculateMaxRowHeights
virtual bool calculateMaxRowHeights()
Calculates the maximum height of text shown in rows.
Definition: qgslayouttable.cpp:992
QgsTableCell::setProperties
void setProperties(const QVariantMap &properties, const QgsReadWriteContext &context)
Sets the properties for the cell.
Definition: qgstablecell.cpp:67
QgsLayoutItemManualTable::type
int type() const override
Returns unique multiframe type id.
Definition: qgslayoutitemmanualtable.cpp:40
QgsLayoutTable::setColumns
void setColumns(const QgsLayoutTableColumns &columns)
Replaces the columns in the table with a specified list of QgsLayoutTableColumns.
Definition: qgslayouttable.cpp:791
QgsTableRow
QVector< QgsTableCell > QgsTableRow
A row of table cells.
Definition: qgstablecell.h:149
c
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
Definition: porting_processing.dox:1
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
qgslayouttablecolumn.h
QgsLayoutTable::mMaxRowHeightMap
QMap< int, double > mMaxRowHeightMap
Map of maximum height for each row.
Definition: qgslayouttable.h:587
QgsLayoutTableRow
QVector< QVariant > QgsLayoutTableRow
Definition: qgslayouttable.h:29
QgsLayoutItemManualTable::~QgsLayoutItemManualTable
~QgsLayoutItemManualTable() override
Definition: qgslayoutitemmanualtable.cpp:36
QgsLayoutTable::mColumns
QgsLayoutTableColumns mColumns
Columns to show in table.
Definition: qgslayouttable.h:575
QgsLayoutTableColumn
Definition: qgslayouttablecolumn.h:36
QgsLayoutItemManualTable::setColumnWidths
void setColumnWidths(const QList< double > &widths)
Sets the list of column widths (in millimeters) to use when rendering the table.
Definition: qgslayoutitemmanualtable.cpp:130
QgsLayoutItemManualTable::create
static QgsLayoutItemManualTable * create(QgsLayout *layout)
Returns a new QgsLayoutItemManualTable for the specified parent layout.
Definition: qgslayoutitemmanualtable.cpp:50
QgsXmlUtils::writeVariant
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
Definition: qgsxmlutils.cpp:106
qgslayoutitemregistry.h
QgsLayoutItemRegistry::LayoutManualTable
@ LayoutManualTable
Manual (fixed) table.
Definition: qgslayoutitemregistry.h:338
QgsLayoutTable::AllFrames
@ AllFrames
Headers shown on all frames.
Definition: qgslayouttable.h:134
QgsLayoutItemManualTable
Definition: qgslayoutitemmanualtable.h:31
QgsLayoutItemManualTable::calculateMaxRowHeights
bool calculateMaxRowHeights() override
Calculates the maximum height of text shown in rows.
Definition: qgslayoutitemmanualtable.cpp:287
QgsNumericFormatContext
Definition: qgsnumericformat.h:34