39 styleElem.setAttribute( QStringLiteral(
"enabled" ),
enabled );
46 enabled = ( styleElem.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
72 elem.setAttribute( QStringLiteral(
"cellMargin" ), QString::number(
mCellMargin ) );
73 elem.setAttribute( QStringLiteral(
"emptyTableMode" ), QString::number(
static_cast< int >(
mEmptyTableMode ) ) );
75 elem.setAttribute( QStringLiteral(
"showEmptyRows" ),
mShowEmptyRows );
77 QDomElement headerElem = doc.createElement( QStringLiteral(
"headerTextFormat" ) );
79 headerElem.appendChild( headerTextElem );
80 elem.appendChild( headerElem );
81 elem.setAttribute( QStringLiteral(
"headerHAlignment" ), QString::number(
static_cast< int >(
mHeaderHAlignment ) ) );
82 elem.setAttribute( QStringLiteral(
"headerMode" ), QString::number(
static_cast< int >(
mHeaderMode ) ) );
84 QDomElement contentElem = doc.createElement( QStringLiteral(
"contentTextFormat" ) );
86 contentElem.appendChild( contentTextElem );
87 elem.appendChild( contentElem );
88 elem.setAttribute( QStringLiteral(
"gridStrokeWidth" ), QString::number(
mGridStrokeWidth ) );
90 elem.setAttribute( QStringLiteral(
"horizontalGrid" ),
mHorizontalGrid );
91 elem.setAttribute( QStringLiteral(
"verticalGrid" ),
mVerticalGrid );
92 elem.setAttribute( QStringLiteral(
"showGrid" ),
mShowGrid );
94 elem.setAttribute( QStringLiteral(
"wrapBehavior" ), QString::number(
static_cast< int >(
mWrapBehavior ) ) );
97 QDomElement displayColumnsElem = doc.createElement( QStringLiteral(
"displayColumns" ) );
100 QDomElement columnElem = doc.createElement( QStringLiteral(
"column" ) );
101 column.writeXml( columnElem, doc );
102 displayColumnsElem.appendChild( columnElem );
104 elem.appendChild( displayColumnsElem );
106 QDomElement sortColumnsElem = doc.createElement( QStringLiteral(
"sortColumns" ) );
109 QDomElement columnElem = doc.createElement( QStringLiteral(
"column" ) );
110 column.writeXml( columnElem, doc );
111 sortColumnsElem.appendChild( columnElem );
113 elem.appendChild( sortColumnsElem );
117 QDomElement stylesElem = doc.createElement( QStringLiteral(
"cellStyles" ) );
118 QMap< CellStyleGroup, QString >::const_iterator it = mCellStyleNames.constBegin();
119 for ( ; it != mCellStyleNames.constEnd(); ++it )
121 QString styleName = it.value();
122 QDomElement styleElem = doc.createElement( styleName );
127 stylesElem.appendChild( styleElem );
130 elem.appendChild( stylesElem );
137 mEmptyTableMessage = itemElem.attribute( QStringLiteral(
"emptyTableMessage" ), tr(
"No matching records" ) );
138 mShowEmptyRows = itemElem.attribute( QStringLiteral(
"showEmptyRows" ), QStringLiteral(
"0" ) ).toInt();
140 const QDomElement
headerTextFormat = itemElem.firstChildElement( QStringLiteral(
"headerTextFormat" ) );
143 QDomNodeList textFormatNodeList =
headerTextFormat.elementsByTagName( QStringLiteral(
"text-style" ) );
144 QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement();
152 headerFont.fromString( itemElem.attribute( QStringLiteral(
"headerFont" ), QString() ) );
172 const QDomElement
contentTextFormat = itemElem.firstChildElement( QStringLiteral(
"contentTextFormat" ) );
175 QDomNodeList textFormatNodeList =
contentTextFormat.elementsByTagName( QStringLiteral(
"text-style" ) );
176 QDomElement textFormatElem = textFormatNodeList.at( 0 ).toElement();
184 contentFont.fromString( itemElem.attribute( QStringLiteral(
"contentFont" ), QString() ) );
201 mCellMargin = itemElem.attribute( QStringLiteral(
"cellMargin" ), QStringLiteral(
"1.0" ) ).toDouble();
202 mGridStrokeWidth = itemElem.attribute( QStringLiteral(
"gridStrokeWidth" ), QStringLiteral(
"0.5" ) ).toDouble();
203 mHorizontalGrid = itemElem.attribute( QStringLiteral(
"horizontalGrid" ), QStringLiteral(
"1" ) ).toInt();
204 mVerticalGrid = itemElem.attribute( QStringLiteral(
"verticalGrid" ), QStringLiteral(
"1" ) ).toInt();
205 mShowGrid = itemElem.attribute( QStringLiteral(
"showGrid" ), QStringLiteral(
"1" ) ).toInt();
212 QDomNodeList columnsList = itemElem.elementsByTagName( QStringLiteral(
"displayColumns" ) );
213 if ( !columnsList.isEmpty() )
215 QDomElement columnsElem = columnsList.at( 0 ).toElement();
216 QDomNodeList columnEntryList = columnsElem.elementsByTagName( QStringLiteral(
"column" ) );
217 for (
int i = 0; i < columnEntryList.size(); ++i )
219 QDomElement columnElem = columnEntryList.at( i ).toElement();
227 QDomNodeList sortColumnsList = itemElem.elementsByTagName( QStringLiteral(
"sortColumns" ) );
228 if ( !sortColumnsList.isEmpty() )
230 QDomElement columnsElem = sortColumnsList.at( 0 ).toElement();
231 QDomNodeList columnEntryList = columnsElem.elementsByTagName( QStringLiteral(
"column" ) );
232 for (
int i = 0; i < columnEntryList.size(); ++i )
234 QDomElement columnElem = columnEntryList.at( i ).toElement();
251 QDomNodeList stylesList = itemElem.elementsByTagName( QStringLiteral(
"cellStyles" ) );
252 if ( !stylesList.isEmpty() )
254 QDomElement stylesElem = stylesList.at( 0 ).toElement();
256 QMap< CellStyleGroup, QString >::const_iterator it = mCellStyleNames.constBegin();
257 for ( ; it != mCellStyleNames.constEnd(); ++it )
259 QString styleName = it.value();
260 QDomNodeList styleList = stylesElem.elementsByTagName( styleName );
261 if ( !styleList.isEmpty() )
263 QDomElement styleElem = styleList.at( 0 ).toElement();
289 double headerHeight = 0;
301 double contentHeight = frameHeight - headerHeight;
305 int currentRow = firstRow;
306 while ( contentHeight > 0 && currentRow <=
mTableContents.count() )
309 contentHeight -= currentRowHeight;
313 if ( includeEmptyRows && contentHeight > 0 )
317 currentRow += std::max( std::floor( contentHeight / rowHeight ), 0.0 );
320 return currentRow - firstRow - 1;
332 bool includeHeader =
false;
336 includeHeader =
true;
338 return rowsVisible( context, frameExtent.height(), firstRow, includeHeader, includeEmptyRows );
347 return qMakePair( 0, 0 );
352 int rowsAlreadyShown = 0;
355 rowsAlreadyShown +=
rowsVisible( context, idx, rowsAlreadyShown,
false );
359 int firstVisible = std::min( rowsAlreadyShown,
static_cast<int>(
mTableContents.length() ) );
361 int lastVisible = std::min( firstVisible + possibleRowsVisible,
static_cast<int>(
mTableContents.length() ) );
363 return qMakePair( firstVisible, lastVisible );
375 if ( !
mLayout->renderContext().isPreviewRender() )
400 int numberRowsToDraw = rowsToShow.second - rowsToShow.first;
401 int numberEmptyRows = 0;
405 numberEmptyRows = numberRowsToDraw - rowsToShow.second + rowsToShow.first;
407 bool mergeCells =
false;
422 p->setPen( Qt::SolidLine );
424 double currentX = gridSizeX;
425 double currentY = gridSizeY;
432 std::unique_ptr< QgsExpressionContextScope > headerCellScope = std::make_unique< QgsExpressionContextScope >();
433 headerCellScope->setVariable( QStringLiteral(
"column_number" ), col + 1,
true );
439 p->setPen( Qt::NoPen );
468 const QStringList
str = column.heading().split(
'\n' );
484 currentX += gridSizeX;
488 currentY += cellHeaderHeight;
489 currentY += gridSizeY;
497 for (
int row = rowsToShow.first; row < rowsToShow.second; ++row )
500 currentX = gridSizeX;
512 p->setPen( Qt::NoPen );
514 p->drawRect( fullCell );
521 const QString localizedString { QgsExpressionUtils::toLocalizedString( cellContents ) };
522 const QStringList
str = localizedString.split(
'\n' );
529 p->setClipRect( fullCell );
533 QColor foreColor = cellFormat.
color();
554 currentX += gridSizeX;
557 currentY += rowHeight;
558 currentY += gridSizeY;
562 if ( numberRowsToDraw > rowsDrawn )
565 p->setPen( Qt::NoPen );
568 for (
int row = rowsDrawn; row < numberRowsToDraw; ++row )
570 currentX = gridSizeX;
576 p->drawRect( QRectF( gridSizeX, currentY,
mTableSize.width() - 2 * gridSizeX, cellBodyHeightForEmptyRows ) );
592 currentX += gridSizeX;
596 currentY += cellBodyHeightForEmptyRows + gridSizeY;
607 gridPen.setJoinStyle( Qt::MiterJoin );
608 p->setPen( gridPen );
623 double messageY = gridSizeY + ( drawHeader ? cellHeaderHeight + gridSizeY : 0 );
624 cell = QRectF( messageX, messageY,
mTableSize.width() - messageX, cellBodyHeightForEmptyRows );
700 if ( font.pointSizeF() > 0 )
705 else if ( font.pixelSize() > 0 )
784 if ( font.pointSizeF() > 0 )
789 else if ( font.pixelSize() > 0 )
944 if ( !newSortColumns.isEmpty() )
975 QMap<int, QString> headers;
980 headers.insert( i, col.heading() );
988 std::unique_ptr< QgsExpressionContextScope > cellScope = std::make_unique< QgsExpressionContextScope >();
989 cellScope->setVariable( QStringLiteral(
"row_number" ), row + 1,
true );
990 cellScope->setVariable( QStringLiteral(
"column_number" ), column + 1,
true );
991 return cellScope.release();
1015 for (
int col = 0; col <
mColumns.size(); ++ col )
1020 return QSizeF( 0, height );
1042 void QgsLayoutTable::initStyles()
1054 mCellStyleNames.insert(
OddColumns, QStringLiteral(
"oddColumns" ) );
1055 mCellStyleNames.insert(
EvenColumns, QStringLiteral(
"evenColumns" ) );
1056 mCellStyleNames.insert(
OddRows, QStringLiteral(
"oddRows" ) );
1057 mCellStyleNames.insert(
EvenRows, QStringLiteral(
"evenRows" ) );
1058 mCellStyleNames.insert(
FirstColumn, QStringLiteral(
"firstColumn" ) );
1059 mCellStyleNames.insert(
LastColumn, QStringLiteral(
"lastColumn" ) );
1060 mCellStyleNames.insert(
HeaderRow, QStringLiteral(
"headerRow" ) );
1061 mCellStyleNames.insert(
FirstRow, QStringLiteral(
"firstRow" ) );
1062 mCellStyleNames.insert(
LastRow, QStringLiteral(
"lastRow" ) );
1072 QVector< double > widths( cells );
1074 double currentCellTextWidth;
1083 if ( col.width() > 0 )
1086 widths[i] = col.width();
1090 std::unique_ptr< QgsExpressionContextScope > headerCellScope = std::make_unique< QgsExpressionContextScope >();
1091 headerCellScope->setVariable( QStringLiteral(
"column_number" ), i + 1,
true );
1095 const QStringList multiLineSplit = col.heading().split(
'\n' );
1097 widths[i] = currentCellTextWidth;
1107 QgsLayoutTableContents::const_iterator rowIt =
mTableContents.constBegin();
1111 QgsLayoutTableRow::const_iterator colIt = rowIt->constBegin();
1113 for ( ; colIt != rowIt->constEnd(); ++colIt )
1115 if (
mColumns.at( col ).width() <= 0 )
1118 const QStringList multiLineSplit = QgsExpressionUtils::toLocalizedString( *colIt ).split(
'\n' );
1125 widths[ row * cols + col ] = currentCellTextWidth;
1129 widths[ row * cols + col ] = 0;
1138 for (
int col = 0; col < cols; ++col )
1140 double maxColWidth = 0;
1143 maxColWidth = std::max( widths[ row * cols + col ], maxColWidth );
1158 QVector< double > heights( cells );
1167 std::unique_ptr< QgsExpressionContextScope > headerCellScope = std::make_unique< QgsExpressionContextScope >();
1168 headerCellScope->setVariable( QStringLiteral(
"column_number" ), i + 1,
true );
1194 QgsLayoutTableContents::const_iterator rowIt =
mTableContents.constBegin();
1198 QgsLayoutTableRow::const_iterator colIt = rowIt->constBegin();
1200 for ( ; colIt != rowIt->constEnd(); ++colIt )
1206 const QString localizedString { QgsExpressionUtils::toLocalizedString( *colIt ) };
1210 QStringList() << localizedString.split(
'\n' ),
1225 double maxRowHeight = 0;
1226 for (
int col = 0; col < cols; ++col )
1228 maxRowHeight = std::max( heights[ row * cols + col ], maxRowHeight );
1272 int rowsAlreadyShown = 0;
1274 int rowsVisibleInLastFrame = 0;
1275 double heightOfLastFrame = 0;
1276 for (
int idx = 0; idx < numberExistingFrames; ++idx )
1280 heightOfLastFrame =
frame( idx )->rect().height();
1281 rowsVisibleInLastFrame =
rowsVisible( context, heightOfLastFrame, rowsAlreadyShown, hasHeader,
false );
1282 rowsAlreadyShown += rowsVisibleInLastFrame;
1283 height += heightOfLastFrame;
1294 if ( remainingRows <= 0 )
1310 int numberFramesMissing = 0;
1311 while ( remainingRows > 0 )
1313 numberFramesMissing++;
1315 rowsVisibleInLastFrame =
rowsVisible( context, heightOfLastFrame, rowsAlreadyShown, hasHeader,
false );
1316 if ( rowsVisibleInLastFrame < 1 )
1323 rowsAlreadyShown += rowsVisibleInLastFrame;
1329 height += heightOfLastFrame * numberFramesMissing;
1336 if ( lastRow - firstRow < 1 && !drawHeaderLines )
1345 double currentY = 0;
1346 currentY = halfGridStrokeWidth;
1347 if ( drawHeaderLines )
1349 painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF(
mTableSize.width() - halfGridStrokeWidth, currentY ) );
1353 for (
int row = firstRow; row < lastRow; ++row )
1355 painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF(
mTableSize.width() - halfGridStrokeWidth, currentY ) );
1360 painter->drawLine( QPointF( halfGridStrokeWidth, currentY ), QPointF(
mTableSize.width() - halfGridStrokeWidth, currentY ) );
1367 if ( style->enabled && column % 2 == 0 )
1368 color = style->cellBackgroundColor;
1370 if ( style->enabled && column % 2 == 1 )
1371 color = style->cellBackgroundColor;
1373 if ( style->enabled && row % 2 == 0 )
1374 color = style->cellBackgroundColor;
1376 if ( style->enabled && row % 2 == 1 )
1377 color = style->cellBackgroundColor;
1379 if ( style->enabled && column == 0 )
1380 color = style->cellBackgroundColor;
1382 if ( style->enabled && column ==
mColumns.count() - 1 )
1383 color = style->cellBackgroundColor;
1385 if ( style->enabled && row == -1 )
1386 color = style->cellBackgroundColor;
1388 if ( style->enabled && row == 0 )
1389 color = style->cellBackgroundColor;
1392 color = style->cellBackgroundColor;
1407 if ( lastRow - firstRow < 1 && !hasHeader )
1415 double tableHeight = 0;
1421 double headerHeight = tableHeight;
1424 for (
int row = firstRow; row < lastRow; ++row )
1431 double currentX = halfGridStrokeWidth;
1432 painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, tableHeight - halfGridStrokeWidth ) );
1434 QMap<int, double>::const_iterator maxColWidthIt = maxWidthMap.constBegin();
1436 for ( ; maxColWidthIt != maxWidthMap.constEnd(); ++maxColWidthIt )
1438 currentX += ( maxColWidthIt.value() + 2 *
mCellMargin );
1439 if ( col == maxWidthMap.size() || !mergeCells )
1441 painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, tableHeight - halfGridStrokeWidth ) );
1443 else if ( hasHeader )
1445 painter->drawLine( QPointF( currentX, halfGridStrokeWidth ), QPointF( currentX, headerHeight - halfGridStrokeWidth ) );
1464 return (
contents.indexOf( row ) >= 0 );
1479 return mColumns.value( column ).hAlignment();
1484 return mColumns.value( column ).vAlignment();