1 /***************************************************************************
2                          qgslayouttable.h
3                          ----------------
4     begin                : November 2017
5     copyright            : (C) 2017 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 
18 #ifndef QGSLAYOUTTABLE_H
19 #define QGSLAYOUTTABLE_H
20 
21 #include "qgis_core.h"
22 #include "qgis_sip.h"
23 #include "qgslayoutmultiframe.h"
24 #include "qgsconditionalstyle.h"
25 #include "qgstextformat.h"
26 #include <QFont>
27 #include <QColor>
28 #include <QPair>
29 
30 class QgsLayoutTableColumn;
31 
32 /**
33  * \ingroup core
34  * \brief List of QVariants, representing a the contents of a single row in
35  * a QgsLayoutTable
36  * \since QGIS 3.0
37 */
38 typedef QVector< QVariant > QgsLayoutTableRow;
39 
40 /**
41  * \ingroup core
42  * \brief List of QgsLayoutTableRows, representing rows and column cell contents
43  * for a QgsLayoutTable
44  * \since QGIS 3.0
45 */
46 #ifndef SIP_RUN
47 typedef QVector< QgsLayoutTableRow > QgsLayoutTableContents;
48 #else
49 typedef QVector< QVector< QVariant > > QgsLayoutTableContents;
50 #endif
51 
52 
53 /**
54  * \ingroup core
55  * \brief List of column definitions for a QgsLayoutTable
56  * \since QGIS 3.0
57 */
58 typedef QVector<QgsLayoutTableColumn> QgsLayoutTableColumns;
59 
60 /**
61  * \ingroup core
62  * \brief List of column definitions for sorting a QgsLayoutTable
63  * \since QGIS 3.14
64 */
65 typedef QVector<QgsLayoutTableColumn> QgsLayoutTableSortColumns;
66 
67 
68 
69 /**
70  * \ingroup core
71  *  \class QgsLayoutTableStyle
72  *  \brief Styling option for a layout table cell
73  *  \since QGIS 3.0
74  */
75 
76 class CORE_EXPORT QgsLayoutTableStyle
77 {
78   public:
79 
80     //! Constructor for QgsLayoutTableStyle
81     QgsLayoutTableStyle() = default;
82 
83     //! Whether the styling option is enabled
84     bool enabled = false;
85 
86     //! Cell background color
87     QColor cellBackgroundColor = QColor( 255, 255, 255, 255 );
88 
89     /**
90      * Writes the style's properties to XML for storage.
91      * \param styleElem an existing QDomElement in which to store the style's properties.
92      * \param doc QDomDocument for the destination XML.
93      * \see readXml
94      */
95     bool writeXml( QDomElement &styleElem, QDomDocument &doc ) const;
96 
97     /**
98      * Reads the style's properties from XML.
99      * \param styleElem a QDomElement holding the style's desired properties.
100      * \see writeXml
101      */
102     bool readXml( const QDomElement &styleElem );
103 
104 };
105 
106 /**
107  * \brief A class to display a table in the print layout, and allow
108  * the table to span over multiple frames
109  * \ingroup core
110  * \since QGIS 3.0
111  */
112 class CORE_EXPORT QgsLayoutTable: public QgsLayoutMultiFrame
113 {
114     Q_OBJECT
115 
116   public:
117 
118     /**
119      * Controls how headers are horizontally aligned in a table
120      */
121     enum HeaderHAlignment
122     {
123       FollowColumn, //!< Header uses the same alignment as the column
124       HeaderLeft, //!< Align headers left
125       HeaderCenter, //!< Align headers to center
126       HeaderRight //!< Align headers right
127     };
128 
129     /**
130      * Controls where headers are shown in the table
131      */
132     enum HeaderMode
133     {
134       FirstFrame = 0, //!< Header shown on first frame only
135       AllFrames, //!< Headers shown on all frames
136       NoHeaders //!< No headers shown for table
137     };
138 
139     /**
140      * Controls how empty tables are displayed
141      */
142     enum EmptyTableMode
143     {
144       HeadersOnly = 0, //!< Show header rows only
145       HideTable, //!< Hides entire table if empty
146       ShowMessage //!< Shows preset message instead of table contents
147     };
148 
149     /**
150      * Controls how long strings in the table are handled
151      */
152     enum WrapBehavior
153     {
154       TruncateText = 0, //!< Text which doesn't fit inside the cell is truncated
155       WrapText //!< Text which doesn't fit inside the cell is wrapped. Note that this only applies to text in columns with a fixed width.
156     };
157 
158     /**
159      * Row or column groups for cell styling
160      */
161     enum CellStyleGroup
162     {
163       OddColumns, //!< Style odd numbered columns
164       EvenColumns, //!< Style even numbered columns
165       OddRows, //!< Style odd numbered rows
166       EvenRows, //!< Style even numbered rows
167       FirstColumn, //!< Style first column only
168       LastColumn, //!< Style last column only
169       HeaderRow, //!< Style header row
170       FirstRow, //!< Style first row only
171       LastRow //!< Style last row only
172     };
173 
174     /**
175      * Constructor for QgsLayoutTable, belonging to the specified \a layout.
176      */
177     QgsLayoutTable( QgsLayout *layout );
178 
179     ~QgsLayoutTable() override;
180 
181     /**
182      * Sets the \a margin distance in mm between cell borders and their contents.
183      * \see cellMargin()
184      */
185     void setCellMargin( double margin );
186 
187     /**
188      * Returns the margin distance between cell borders and their contents in mm.
189      * \see setCellMargin()
190      */
cellMargin()191     double cellMargin() const { return mCellMargin; }
192 
193     /**
194      * Sets the behavior \a mode for empty tables with no content rows.
195      * \see emptyTableBehavior()
196      */
197     void setEmptyTableBehavior( EmptyTableMode mode );
198 
199     /**
200      * Returns the behavior mode for empty tables. This property controls
201      * how the table is drawn if it contains no content rows.
202      * \see setEmptyTableBehavior()
203      */
emptyTableBehavior()204     EmptyTableMode emptyTableBehavior() const { return mEmptyTableMode; }
205 
206     /**
207      * Sets the \a message for empty tables with no content rows. This message
208      * is displayed in the table body if the empty table behavior is
209      * set to ShowMessage.
210      * \see emptyTableMessage()
211      * \see setEmptyTableBehavior()
212      */
213     void setEmptyTableMessage( const QString &message );
214 
215     /**
216      * Returns the message for empty tables with no content rows. This message
217      * is displayed in the table body if the empty table behavior is
218      * set to ShowMessage.
219      * \see setEmptyTableMessage()
220      * \see emptyTableBehavior()
221      */
emptyTableMessage()222     QString emptyTableMessage() const { return mEmptyTableMessage; }
223 
224     /**
225      * Sets whether empty rows should be drawn. Tables default to hiding empty rows.
226      * \param showEmpty set to TRUE to show empty rows in the table
227      * \see showEmptyRows()
228      */
229     void setShowEmptyRows( bool showEmpty );
230 
231     /**
232      * Returns whether empty rows are drawn in the table.
233      * \see setShowEmptyRows()
234      */
showEmptyRows()235     bool showEmptyRows() const { return mShowEmptyRows; }
236 
237     /**
238      * Sets the \a font used to draw header text in the table.
239      * \see headerFont()
240      * \see setContentFont()
241      * \deprecated use setHeaderTextFormat() instead
242      */
243     Q_DECL_DEPRECATED void setHeaderFont( const QFont &font ) SIP_DEPRECATED;
244 
245     /**
246      * Returns the font used to draw header text in the table.
247      * \see setHeaderFont()
248      * \see contentFont()
249      * \deprecated use headerTextFormat() instead
250      */
251     Q_DECL_DEPRECATED QFont headerFont() const SIP_DEPRECATED;
252 
253     /**
254      * Sets the \a color used to draw header text in the table.
255      * \see headerFontColor()
256      * \see setHeaderFont()
257      * \see setContentFontColor()
258      * \deprecated use setHeaderTextFormat() instead
259      */
260     Q_DECL_DEPRECATED void setHeaderFontColor( const QColor &color ) SIP_DEPRECATED;
261 
262     /**
263      * Returns the color used to draw header text in the table.
264      * \see setHeaderFontColor()
265      * \see headerFont()
266      * \see contentFontColor()
267      * \deprecated use headerTextFormat() instead
268      */
269     Q_DECL_DEPRECATED QColor headerFontColor() const SIP_DEPRECATED;
270 
271     /**
272      * Sets the \a format used to draw header text in the table.
273      * \see headerTextFormat()
274      * \see setContentTextFormat()
275      * \since QGIS 3.16
276      */
277     void setHeaderTextFormat( const QgsTextFormat &format );
278 
279     /**
280      * Returns the format used to draw header text in the table.
281      * \see setHeaderTextFormat()
282      * \see contentTextFormat()
283      * \since QGIS 3.16
284      */
285     QgsTextFormat headerTextFormat() const;
286 
287     /**
288      * Sets the horizontal \a alignment for table headers.
289      * \see headerHAlignment()
290      */
291     void setHeaderHAlignment( HeaderHAlignment alignment );
292 
293     /**
294      * Returns the horizontal alignment for table headers.
295      * \see setHeaderHAlignment()
296      */
headerHAlignment()297     HeaderHAlignment headerHAlignment() const { return mHeaderHAlignment; }
298 
299     /**
300      * Sets the display \a mode for headers in the table. This property controls
301      * if and where headers are shown in the table.
302      * \see headerMode()
303      */
304     void setHeaderMode( HeaderMode mode );
305 
306     /**
307      * Returns the display mode for headers in the table. This property controls
308      * if and where headers are shown in the table.
309      * \see setHeaderMode()
310      */
headerMode()311     HeaderMode headerMode() const { return mHeaderMode; }
312 
313     /**
314      * Sets the \a font used to draw text in table body cells.
315      * \see contentFont()
316      * \see setHeaderFont()
317      * \deprecated use setContentTextFormat() instead
318      */
319     Q_DECL_DEPRECATED void setContentFont( const QFont &font ) SIP_DEPRECATED;
320 
321     /**
322      * Returns the font used to draw text in table body cells.
323      * \see setContentFont()
324      * \see headerFont()
325      * \deprecated use contextTextFormat() instead
326      */
327     Q_DECL_DEPRECATED QFont contentFont() const SIP_DEPRECATED;
328 
329     /**
330      * Sets the \a color used to draw text in table body cells.
331      * \see contentFontColor()
332      * \see setContentFont()
333      * \see setHeaderFontColor()
334      * \deprecated use setContentTextFormat() instead
335      */
336     Q_DECL_DEPRECATED void setContentFontColor( const QColor &color ) SIP_DEPRECATED;
337 
338     /**
339      * Returns the color used to draw text in table body cells.
340      * \see setContentFontColor()
341      * \see contentFont()
342      * \see headerFontColor()
343      * \deprecated use contextTextFormat() instead
344      */
345     Q_DECL_DEPRECATED QColor contentFontColor() const SIP_DEPRECATED;
346 
347     /**
348      * Sets the \a format used to draw content text in the table.
349      * \see contentTextFormat()
350      * \see setHeaderTextFormat()
351      * \since QGIS 3.16
352      */
353     void setContentTextFormat( const QgsTextFormat &format );
354 
355     /**
356      * Returns the format used to draw content text in the table.
357      * \see setContentTextFormat()
358      * \see headerTextFormat()
359      * \since QGIS 3.16
360      */
361     QgsTextFormat contentTextFormat() const;
362 
363     /**
364      * Sets whether grid lines should be drawn in the table
365      * \param showGrid set to TRUE to show grid lines
366      * \see showGrid()
367      * \see setGridStrokeWidth()
368      * \see setGridColor()
369      */
370     void setShowGrid( bool showGrid );
371 
372     /**
373      * Returns whether grid lines are drawn in the table
374      * \see setShowGrid()
375      * \see gridStrokeWidth()
376      * \see gridColor()
377      */
showGrid()378     bool showGrid() const { return mShowGrid; }
379 
380     /**
381      * Sets the \a width in mm for grid lines in the table.
382      * \see gridStrokeWidth()
383      * \see setShowGrid()
384      * \see setGridColor()
385      */
386     void setGridStrokeWidth( double width );
387 
388     /**
389      * Returns the width of grid lines in the table in mm.
390      * \see setGridStrokeWidth()
391      * \see showGrid()
392      * \see gridColor()
393      */
gridStrokeWidth()394     double gridStrokeWidth() const { return mGridStrokeWidth; }
395 
396     /**
397      * Sets the \a color used for grid lines in the table.
398      * \see gridColor()
399      * \see setShowGrid()
400      * \see setGridStrokeWidth()
401      */
402     void setGridColor( const QColor &color );
403 
404     /**
405      * Returns the color used for grid lines in the table.
406      * \see setGridColor()
407      * \see showGrid()
408      * \see gridStrokeWidth()
409      */
gridColor()410     QColor gridColor() const { return mGridColor; }
411 
412     /**
413      * Sets whether the grid's horizontal lines should be drawn in the table
414      * \param horizontalGrid set to TRUE to draw grid's horizontal lines
415      * \see setShowGrid()
416      * \see setGridStrokeWidth()
417      * \see setGridColor()
418      * \see setVerticalGrid()
419      */
420     void setHorizontalGrid( bool horizontalGrid );
421 
422     /**
423      * Returns whether the grid's horizontal lines are drawn in the table.
424      * \see setShowGrid()
425      * \see setGridStrokeWidth()
426      * \see setGridColor()
427      * \see setVerticalGrid()
428      */
horizontalGrid()429     bool horizontalGrid() const { return mHorizontalGrid; }
430 
431     /**
432      * Sets whether the grid's vertical lines should be drawn in the table
433      * \param verticalGrid set to TRUE to draw grid's vertical lines
434      * \see setShowGrid()
435      * \see setGridStrokeWidth()
436      * \see setGridColor()
437      * \see setHorizontalGrid()
438      */
439     void setVerticalGrid( bool verticalGrid );
440 
441     /**
442      * Returns whether the grid's vertical lines are drawn in the table.
443      * \see setShowGrid()
444      * \see setGridStrokeWidth()
445      * \see setGridColor()
446      * \see setHorizontalGrid()
447      */
verticalGrid()448     bool verticalGrid() const { return mVerticalGrid; }
449 
450     /**
451      * Sets the \a color used for background of table.
452      * \see backgroundColor()
453      * \see setGridColor()
454      */
455     void setBackgroundColor( const QColor &color );
456 
457     /**
458      * Returns the color used for the background of the table.
459      * \see setBackgroundColor()
460      * \see gridColor()
461      */
backgroundColor()462     QColor backgroundColor() const { return mBackgroundColor; }
463 
464     /**
465      * Sets the wrap \a behavior for the table, which controls how text within cells is
466      * automatically wrapped.
467      * \see wrapBehavior()
468      */
469     void setWrapBehavior( WrapBehavior behavior );
470 
471     /**
472      * Returns the wrap behavior for the table, which controls how text within cells is
473      * automatically wrapped.
474      * \see setWrapBehavior()
475      */
wrapBehavior()476     WrapBehavior wrapBehavior() const { return mWrapBehavior; }
477 
478     /**
479      * Returns a reference to the list of QgsLayoutTableColumns shown in the table
480      * \see setColumns()
481      */
columns()482     QgsLayoutTableColumns &columns() { return mColumns; }
483 
484     /**
485      * Replaces the columns in the table with a specified list of QgsLayoutTableColumns.
486      * \param columns list of QgsLayoutTableColumns to show in table.
487      * \see columns()
488      */
489     void setColumns( const QgsLayoutTableColumns &columns );
490 
491     /**
492      * Returns a reference to the list of QgsLayoutTableSortColumns shown in the table
493      * \see setSortColumns()
494      * \since QGIS 3.14
495      */
sortColumns()496     QgsLayoutTableSortColumns &sortColumns() { return mSortColumns; }
497 
498     /**
499      * Replaces the sorting columns in the table with a specified list of QgsLayoutTableSortColumns.
500      * \param sortColumns list of QgsLayoutTableColumns used to sort the table.
501      * \see sortColumns()
502      * \since QGIS 3.14
503      */
504     void setSortColumns( const QgsLayoutTableSortColumns &sortColumns );
505 
506     /**
507      * Sets the cell \a style for a cell \a group.
508      * \see cellStyle()
509      */
510     void setCellStyle( CellStyleGroup group, const QgsLayoutTableStyle &style );
511 
512     /**
513      * Returns the cell style for a cell \a group.
514      * \see setCellStyle()
515      */
516     const QgsLayoutTableStyle *cellStyle( CellStyleGroup group ) const;
517 
518     /**
519      * Returns the text used in the column headers for the table.
520      * \returns QMap of int to QString, where the int is the column index (starting at 0),
521      * and the string is the text to use for the column's header
522      * \note not available in Python bindings
523      */
524     virtual QMap<int, QString> headerLabels() const SIP_SKIP;
525 
526     /**
527      * Fetches the contents used for the cells in the table.
528      * \returns TRUE if table contents were successfully retrieved.
529      * \param contents QgsLayoutTableContents to store retrieved row data in
530      */
531     virtual bool getTableContents( QgsLayoutTableContents &contents ) = 0;
532 
533     /**
534      * Returns the conditional style to use for the cell at \a row, \a column.
535      *
536      * \since QGIS 3.12
537      */
538     virtual QgsConditionalStyle conditionalCellStyle( int row, int column ) const;
539 
540     /**
541      * Creates a new QgsExpressionContextScope for the cell at \a row, \a column.
542      *
543      * \since QGIS 3.16
544      */
545     virtual QgsExpressionContextScope *scopeForCell( int row, int column ) const SIP_FACTORY;
546 
547     /**
548      * Returns the current contents of the table. Excludes header cells.
549      */
contents()550     QgsLayoutTableContents &contents() { return mTableContents; }
551 
552     QSizeF fixedFrameSize( int frameIndex = -1 ) const override;
553     QSizeF minFrameSize( int frameIndex = -1 ) const override;
554 
555     bool writePropertiesToElement( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
556     bool readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context ) override;
557     QSizeF totalSize() const override;
558     void render( QgsLayoutItemRenderContext &context, const QRectF &renderExtent, int frameIndex ) override;
559 
560   public slots:
561 
562     void refresh() override;
563 
564     /**
565      * Refreshes the contents shown in the table by querying for new data.
566      * This also causes the column widths and size of the table to change to accommodate the
567      * new data.
568      */
569     virtual void refreshAttributes();
570 
571     void recalculateFrameSizes() override;
572 
573   protected:
574     //! Margin between cell borders and cell text
575     double mCellMargin = 1.0;
576 
577     //! Behavior for empty tables
578     EmptyTableMode mEmptyTableMode = HeadersOnly;
579 
580     //! String to show in empty tables
581     QString mEmptyTableMessage;
582 
583     //! True if empty rows should be shown in the table
584     bool mShowEmptyRows = false;
585 
586 
587     //! Alignment for table headers
588     HeaderHAlignment mHeaderHAlignment = FollowColumn;
589 
590     //! Header display mode
591     HeaderMode mHeaderMode = FirstFrame;
592 
593     QgsTextFormat mHeaderTextFormat;
594     QgsTextFormat mContentTextFormat;
595 
596     //! True if grid should be shown
597     bool mShowGrid = true;
598 
599     //! Width of grid lines
600     double mGridStrokeWidth = 0.5;
601 
602     //! Color for grid lines
603     QColor mGridColor = Qt::black;
604 
605     //! True if grid should be shown
606     bool mHorizontalGrid = true;
607 
608     //! True if grid should be shown
609     bool mVerticalGrid = true;
610 
611     //! Color for table background
612     QColor mBackgroundColor = Qt::white;
613 
614     //! Columns to show in table
615     QgsLayoutTableColumns mColumns;
616 
617     //! Columns to sort the table
618     QgsLayoutTableSortColumns mSortColumns;
619 
620     //! Contents to show in table
621     QgsLayoutTableContents mTableContents;
622 
623     //! Map of maximum width for each column
624     QMap<int, double> mMaxColumnWidthMap;
625 
626     //! Map of maximum height for each row
627     QMap<int, double> mMaxRowHeightMap;
628 
629     QSizeF mTableSize;
630 
631     WrapBehavior mWrapBehavior = TruncateText;
632 
633     QMap< CellStyleGroup, QgsLayoutTableStyle * > mCellStyles;
634 
635     /**
636      * Calculates the maximum width of text shown in columns.
637      */
638     virtual bool calculateMaxColumnWidths();
639 
640     /**
641      * Calculates the maximum height of text shown in rows.
642      */
643     virtual bool calculateMaxRowHeights();
644 
645     /**
646      * Returns total width of table contents.
647      * \returns table width
648      * \see totalHeight
649      */
650     //not const, as needs to call calculateMaxColumnWidths()
651     double totalWidth();
652 
653     /**
654      * Returns total height of table contents.
655      * \see totalWidth()
656      */
657     //not const, as needs to call calculateMaxRowHeights()
658     double totalHeight();
659 
660     /**
661      * Calculates how many content rows would be visible within a frame of the specified
662      * height.
663      * \param context render context
664      * \param frameHeight height of frame
665      * \param firstRow index of first row visible in frame (where 0 = first row in table)
666      * \param includeHeader set to TRUE if frame would include a header row
667      * \param includeEmptyRows set to TRUE to also include rows which would be empty in the returned count. For instance,
668      * if the frame would include all table content rows and have space left for extra rows then setting this parameter
669      * to TRUE would also include a count of these extra blank rows.
670      * \returns number of visible content rows (excluding header row)
671      */
672     int rowsVisible( QgsRenderContext &context, double frameHeight, int firstRow, bool includeHeader, bool includeEmptyRows ) const;
673 
674     /**
675      * Calculates how many content rows are visible within a given frame.
676      * \param context render context
677      * \param frameIndex index number for frame
678      * \param firstRow index of first row visible in frame (where 0 = first row in table)
679      * \param includeEmptyRows set to TRUE to also include rows which would be empty in the returned count. For instance,
680      * if the frame would include all table content rows and have space left for extra rows then setting this parameter
681      * to TRUE would also include a count of these extra blank rows.
682      * \returns number of visible content rows (excludes header rows)
683      */
684     int rowsVisible( QgsRenderContext &context, int frameIndex, int firstRow, bool includeEmptyRows ) const;
685 
686     /**
687      * Calculates a range of rows which should be visible in a given frame.
688      * \param context render context
689      * \param frameIndex index number for frame
690      * \returns row range
691      */
692     QPair<int, int> rowRange( QgsRenderContext &context, int frameIndex ) const;
693 
694     /**
695      * Draws the horizontal grid lines for the table.
696      * \param context destination render context
697      * \param firstRow index corresponding to first row shown in frame
698      * \param lastRow index corresponding to last row shown in frame. If greater than the number of content rows in the
699      * table, then the default row height will be used for the remaining rows.
700      * \param drawHeaderLines set to TRUE to include for the table header
701      * \see drawVerticalGridLines()
702      */
703     void drawHorizontalGridLines( QgsLayoutItemRenderContext &context, int firstRow, int lastRow, bool drawHeaderLines ) const;
704 
705     /**
706      * Draws the vertical grid lines for the table.
707      * \param context destination render context
708      * \param maxWidthMap QMap of int to double, where the int contains the column number and the double is the
709      * maximum width of text present in the column.
710      * \param firstRow index corresponding to first row shown in frame
711      * \param lastRow index corresponding to last row shown in frame. If greater than the number of content rows in the
712      * table, then the default row height will be used for the remaining rows.
713      * \param hasHeader set to TRUE if table frame includes header cells
714      * \param mergeCells set to TRUE to merge table content cells
715      * \note not available in Python bindings
716      * \see drawVerticalGridLines()
717      * \see calculateMaxColumnWidths()
718      * \note not available in Python bindings
719      */
720     void drawVerticalGridLines( QgsLayoutItemRenderContext &context, const QMap<int, double> &maxWidthMap, int firstRow, int lastRow, bool hasHeader, bool mergeCells = false ) const SIP_SKIP;
721 
722     /**
723      * Recalculates and updates the size of the table and all table frames.
724      */
725     void recalculateTableSize();
726 
727     /**
728      * Checks whether a table contents contains a given row
729      * \param contents table contents to check
730      * \param row row to check for
731      * \returns TRUE if contents contains rows
732      */
733     bool contentsContainsRow( const QgsLayoutTableContents &contents, const QgsLayoutTableRow &row ) const;
734 
735     /**
736      * Returns the text format to use for the cell at the specified \a row and \a column.
737      *
738      * \see textFormatForHeader()
739      * \since QGIS 3.16
740      */
741     virtual QgsTextFormat textFormatForCell( int row, int column ) const;
742 
743     /**
744      * Returns the text format to use for the header cell at the specified \a column.
745      *
746      * \see textFormatForCell()
747      * \since QGIS 3.16
748      */
749     virtual QgsTextFormat textFormatForHeader( int column ) const;
750 
751     /**
752      * Returns the horizontal alignment to use for the cell at the specified \a row and \a column.
753      *
754      * \see verticalAlignmentForCell()
755      * \since QGIS 3.16
756      */
757     virtual Qt::Alignment horizontalAlignmentForCell( int row, int column ) const;
758 
759     /**
760      * Returns the vertical alignment to use for the cell at the specified \a row and \a column.
761      *
762      * \see horizontalAlignmentForCell()
763      * \since QGIS 3.16
764      */
765     virtual Qt::Alignment verticalAlignmentForCell( int row, int column ) const;
766 
767   private:
768 
769     QMap< CellStyleGroup, QString > mCellStyleNames;
770 
771     //! Initializes cell style map
772     void initStyles();
773 
774     bool textRequiresWrapping( QgsRenderContext &context, const QString &text, double columnWidth, const QgsTextFormat &format ) const;
775 
776     QStringList wrappedText( QgsRenderContext &context, const QString &value, double columnWidth, const QgsTextFormat &format ) const;
777 
778     /**
779      * Returns the calculated background color for a row and column combination.
780      * \param row row number, where -1 is the header row, and 0 is the first body row
781      * \param column column number, where 0 is the first column
782      * \returns background color, or invalid QColor if no background should be drawn
783      */
784     QColor backgroundColor( int row, int column ) const;
785 
786     friend class TestQgsLayoutTable;
787     friend class TestQgsLayoutManualTable;
788     friend class QgsCompositionConverter;
789 };
790 
791 #endif // QGSLAYOUTTABLE_H
792