KD Reports API Documentation  2.2
KDReportsSpreadsheetReportLayout.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Reports library.
4 **
5 ** SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 
15 #include <QAbstractItemModel>
16 
17 #include <QBitArray>
18 #include <QDebug>
19 #include <QIcon>
20 #include <QPainter>
21 #include <qmath.h> // qCeil
22 
24  : m_tableBreakingPageOrder(Report::DownThenRight)
25  , m_numHorizontalPages(1)
26  , m_numVerticalPages(0)
27  , m_layoutDirty(true)
28  , m_userRequestedFontScalingFactor(1.0)
29  , m_tableSettings()
30 
31 {
32  Q_UNUSED(report); // for later
33 }
34 
36 {
37  m_layoutDirty = true;
38 }
39 
41 {
42  m_tableLayout.m_cellFont = font;
43  m_tableLayout.m_horizontalHeaderFont = font;
44  m_tableLayout.m_verticalHeaderFont = font;
45  setLayoutDirty();
46 }
47 
49 {
50  return m_tableLayout.m_cellFont;
51 }
52 
53 qreal KDReports::SpreadsheetReportLayout::paintTableVerticalHeader(qreal x, qreal y, QPainter &painter, int row)
54 {
55  QAbstractItemModel *model = m_tableLayout.m_model;
56 
57  const QRectF cellRect(x, y, m_tableLayout.vHeaderWidth(), m_tableLayout.rowHeight());
58 
59  painter.setFont(m_tableLayout.verticalHeaderScaledFont());
60  painter.fillRect(cellRect, m_tableSettings.m_headerBackground);
61  drawBorder(cellRect, painter);
62 
63  const QColor foreground = qvariant_cast<QColor>(model->headerData(row, Qt::Vertical, Qt::ForegroundRole));
64  if (foreground.isValid())
65  painter.setPen(foreground);
66 
67  const QString cellText = model->headerData(row, Qt::Vertical).toString();
68  const qreal padding = m_tableLayout.scaledCellPadding();
69  const Qt::Alignment alignment(model->headerData(row, Qt::Vertical, Qt::TextAlignmentRole).toInt());
70  const QVariant cellDecoration = model->headerData(row, Qt::Vertical, Qt::DecorationRole);
71  const QVariant decorationAlignment = model->headerData(row, Qt::Vertical, KDReports::AutoTableElement::DecorationAlignmentRole);
72 
73  const QRectF cellContentsRect = cellRect.adjusted(padding, padding, -padding, -padding);
74  // painter.drawText( cellContentsRect, alignment, cellText );
75  paintTextAndIcon(painter, cellContentsRect, cellText, cellDecoration, decorationAlignment, alignment);
76 
77  if (foreground.isValid())
78  painter.setPen(Qt::black);
79 
80  x += cellRect.width();
81  return x;
82 }
83 
84 void KDReports::SpreadsheetReportLayout::paintTableHorizontalHeader(const QRectF &cellRect, QPainter &painter, int col)
85 {
86  QAbstractItemModel *model = m_tableLayout.m_model;
87 
88  painter.setFont(m_tableLayout.horizontalHeaderScaledFont());
89  // adjust rect so that it's really under the lines; we get some white space otherwise, sometimes
90  painter.fillRect(cellRect.adjusted(-0.5, -0.5, -0.5, -0.5), m_tableSettings.m_headerBackground);
91  drawBorder(cellRect, painter);
92 
93  const QColor foreground = qvariant_cast<QColor>(model->headerData(col, Qt::Horizontal, Qt::ForegroundRole));
94  if (foreground.isValid())
95  painter.setPen(foreground);
96 
97  const QString cellText = model->headerData(col, Qt::Horizontal).toString();
98  const qreal padding = m_tableLayout.scaledCellPadding();
99  const Qt::Alignment alignment(model->headerData(col, Qt::Horizontal, Qt::TextAlignmentRole).toInt());
100  const QVariant cellDecoration = model->headerData(col, Qt::Horizontal, Qt::DecorationRole);
101  const QVariant decorationAlignment = model->headerData(col, Qt::Horizontal, KDReports::AutoTableElement::DecorationAlignmentRole);
102 
103  const QRectF cellContentsRect = cellRect.adjusted(padding, padding, -padding, -padding);
104  // painter.drawText( cellContentsRect, alignment, cellText );
105  paintTextAndIcon(painter, cellContentsRect, cellText, cellDecoration, decorationAlignment, alignment);
106 
107  if (foreground.isValid())
108  painter.setPen(Qt::black);
109 }
110 
111 void KDReports::SpreadsheetReportLayout::paintIcon(QPainter &painter, const QRectF &cellContentsRect, const QVariant &cellDecoration) const
112 {
113  QPixmap pix = qvariant_cast<QPixmap>(cellDecoration);
114  if (pix.isNull()) {
115  pix = qvariant_cast<QIcon>(cellDecoration).pixmap(m_tableLayout.m_iconSize);
116  }
117  qreal height = pix.height();
118  QImage img;
119  if (pix.isNull()) {
120  img = qvariant_cast<QImage>(cellDecoration);
121  if (img.isNull())
122  return;
123  height = img.height();
124  }
125 
126  // Now either img or pix is set.
127 
128  // Apply scaling factor
129  if (m_tableLayout.scalingFactor() != 1.) {
130  if (!pix.isNull()) {
131  pix = pix.scaledToWidth(qRound(pix.width() * m_tableLayout.scalingFactor()));
132  height = pix.height();
133  } else {
134  img = img.scaledToWidth(qRound(img.width() * m_tableLayout.scalingFactor()));
135  height = img.height();
136  }
137  }
138 
139  // Vertical centering
140  const int y = qMax(0, int((cellContentsRect.height() - height) / 2.0));
141  const QPoint topLeft = cellContentsRect.topLeft().toPoint() + QPoint(0, y);
142  if (!img.isNull()) {
143  // Draw img
144  painter.drawImage(topLeft, img);
145  } else {
146  // Draw pix
147  painter.drawPixmap(topLeft, pix);
148  }
149 }
150 
151 // We could use QItemDelegate::paint instead, but it does so much more, it looks slow.
152 void KDReports::SpreadsheetReportLayout::paintTextAndIcon(QPainter &painter, const QRectF &cellContentsRect, const QString &cellText, const QVariant &cellDecoration,
153  const QVariant &decorationAlignment, Qt::Alignment alignment)
154 {
155  QRectF textRect = cellContentsRect;
156 
157  const bool hasIcon = !cellDecoration.isNull();
158  qreal iconWidth = 0;
159  const bool iconAfterText = decorationAlignment.isValid() && (decorationAlignment.toInt() & Qt::AlignRight);
160  if (hasIcon) {
161  iconWidth = m_tableLayout.decorationSize(cellDecoration).width() * m_tableLayout.scalingFactor();
162  // qDebug() << "row" << row << "hasIcon=" << hasIcon << "iconAfterText=" << iconAfterText << "iconWidth=" << iconWidth;
163  if (!iconAfterText) {
164  paintIcon(painter, cellContentsRect, cellDecoration);
165  textRect.setLeft(textRect.left() + iconWidth + 2);
166  } else {
167  textRect.setWidth(textRect.width() - iconWidth - 2);
168  }
169  }
170 
171  // qDebug() << "Drawing text in" << textRect;
172  painter.drawText(textRect, alignment, cellText);
173 
174  if (hasIcon && iconAfterText) {
175  QRectF iconRect = cellContentsRect;
176  iconRect.setLeft(iconRect.right() - iconWidth);
177  // qDebug() << "iconRect=" << iconRect;
178  paintIcon(painter, iconRect, cellDecoration);
179  }
180 }
181 
182 void KDReports::SpreadsheetReportLayout::drawBorder(const QRectF &cellRect, QPainter &painter) const
183 {
184  if (m_tableSettings.m_border > 0) {
185  const QPen oldPen = painter.pen();
186  // QTextDocumentLayoutPrivate::drawBorder draws 4 rects using a brush
187  // But that's more work, and it doesn't always look good anyway.
188  // So we just use it as a color for now.
189  painter.setPen(QPen(m_tableSettings.m_borderBrush.color(), m_tableSettings.m_border));
190  painter.drawRect(cellRect);
191  painter.setPen(oldPen);
192  }
193 }
194 
195 void KDReports::SpreadsheetReportLayout::paintPageContent(int pageNumber, QPainter &painter)
196 {
197  // qDebug() << "painting with" << m_tableLayout.scaledFont();
198  QAbstractItemModel *model = m_tableLayout.m_model;
199  const qreal padding = m_tableLayout.scaledCellPadding();
200  const QRect cellCoords = m_pageRects[pageNumber];
201  // qDebug() << "painting page" << pageNumber << "cellCoords=" << cellCoords;
202  qreal y = 0 /*m_topMargin*/; // in pixels
203  const qreal rowHeight = m_tableLayout.rowHeight();
204 
205  if (m_tableLayout.m_horizontalHeaderVisible) {
206  qreal x = 0 /*m_leftMargin*/;
207  if (m_tableLayout.m_verticalHeaderVisible) {
208  x += m_tableLayout.vHeaderWidth();
209  }
210  for (int col = cellCoords.left(); col <= cellCoords.right(); ++col) {
211  const QRectF cellRect(x, y, m_tableLayout.m_columnWidths[col], m_tableLayout.hHeaderHeight());
212  paintTableHorizontalHeader(cellRect, painter, col);
213  x += cellRect.width();
214  }
215  y += m_tableLayout.hHeaderHeight();
216  }
217 
218  const int firstRow = cellCoords.top();
219  const int firstColumn = cellCoords.left();
220  const int numRows = cellCoords.height();
221  const int numColumns = cellCoords.width();
222 
223  // This won't work across page breaks....
224  QVector<QBitArray> coveredCells;
225  coveredCells.resize(numRows);
226  for (int row = firstRow; row <= cellCoords.bottom(); ++row)
227  coveredCells[row - firstRow].resize(numColumns);
228 
229  for (int row = firstRow; row <= cellCoords.bottom(); ++row) {
230  qreal x = 0 /*m_leftMargin*/;
231  if (m_tableLayout.m_verticalHeaderVisible) {
232  x = paintTableVerticalHeader(x, y, painter, row);
233  }
234  painter.setFont(m_tableLayout.scaledFont());
235  for (int col = cellCoords.left(); col <= cellCoords.right(); ++col) {
236  if (coveredCells[row - firstRow].testBit(col - firstColumn)) {
237  x += m_tableLayout.m_columnWidths[col];
238  continue;
239  }
240 
241  const QModelIndex index = model->index(row, col);
242 
243  const QSize span = model->span(index);
244  if (span.isValid()) {
245  for (int r = row; r < row + span.height() && r < numRows; ++r) {
246  for (int c = col; c < col + span.width() && c < numColumns; ++c) {
247  coveredCells[r - firstRow].setBit(c - firstColumn);
248  }
249  }
250  }
251 
252  const QRectF cellRect(x, y, cellWidth(col, span.width()), qMax(1, span.height()) * rowHeight);
253  const QRectF cellContentsRect = cellRect.adjusted(padding, padding, -padding, -padding);
254  // qDebug() << "cell" << row << col << "rect=" << cellRect;
255 
256  const QString cellText = model->data(index, Qt::DisplayRole).toString();
257  const QColor foreground = qvariant_cast<QColor>(model->data(index, Qt::ForegroundRole));
258  const QVariant background = model->data(index, Qt::BackgroundRole);
259  const Qt::Alignment alignment(model->data(index, Qt::TextAlignmentRole).toInt());
260  const QVariant decorationAlignment(model->data(index, KDReports::AutoTableElement::DecorationAlignmentRole));
261  const QVariant cellDecoration(model->data(index, Qt::DecorationRole));
262 
263  if (background.canConvert<QBrush>()) {
264  painter.fillRect(cellRect, background.value<QBrush>());
265  } else if (span.isValid()) {
266  painter.fillRect(cellRect, Qt::white);
267  }
268  drawBorder(cellRect, painter);
269 
270  // Per-cell font is not supported, on purpose. All rows use the same font,
271  // otherwise the calculations for making things fit into a number of pages
272  // become quite complex and slow.
273  // const QVariant cellFont = model->data( index, Qt::FontRole );
274  // if ( cellFont.isValid() )
275  // painter.setFont( qvariant_cast<QFont>( cellFont ) );
276  // else
277  // painter.setFont( scaledFont );
278 
279  if (foreground.isValid())
280  painter.setPen(foreground);
281 
282  paintTextAndIcon(painter, cellContentsRect, cellText, cellDecoration, decorationAlignment, alignment);
283 
284  if (foreground.isValid())
285  painter.setPen(Qt::black);
286 
287  x += m_tableLayout.m_columnWidths[col];
288  }
289  y += rowHeight;
290  }
291 }
292 
293 //@cond PRIVATE
295 {
296  ensureLayouted();
297  return m_pageRects.count();
298 }
299 
301 {
302  m_tableLayout.setInitialFontScalingFactor(m_userRequestedFontScalingFactor);
303  QAbstractItemModel *model = m_tableLayout.m_model;
304  if (!model)
305  return -1;
306  m_tableLayout.updateColumnWidths();
307  const qreal total = totalWidth();
308 #ifdef DEBUG_LAYOUT
309  qDebug() << "idealWidth:" << total << "pixels";
310 #endif
311  return total;
312 }
313 //@endcond
314 
315 qreal KDReports::SpreadsheetReportLayout::totalWidth() const
316 {
317  qreal totalWidth = 0;
318  for (int col = 0; col < m_tableLayout.m_columnWidths.size(); ++col) {
319  totalWidth += m_tableLayout.m_columnWidths[col];
320  }
321  if (m_tableLayout.m_verticalHeaderVisible)
322  totalWidth += m_tableLayout.vHeaderWidth();
323  return totalWidth;
324 }
325 
326 qreal KDReports::SpreadsheetReportLayout::cellWidth(int col, int horizSpan) const
327 {
328  qreal cellWidth = m_tableLayout.m_columnWidths[col];
329  for (int extraCol = 1; extraCol < horizSpan; ++extraCol) {
330  cellWidth += m_tableLayout.m_columnWidths[col + extraCol];
331  }
332  return cellWidth;
333 }
334 
336 {
337  m_pageContentSize = size;
338 #ifdef DEBUG_LAYOUT
339  qDebug() << "page content size" << m_pageContentSize;
340 #endif
341  setLayoutDirty();
342 }
343 
345 {
346  if (!m_layoutDirty)
347  return;
348  if (m_pageContentSize.isEmpty()) {
349  qWarning("No paper size specified!");
350  return;
351  }
352 
353  m_tableLayout.setInitialFontScalingFactor(m_userRequestedFontScalingFactor);
354  m_pageRects.clear();
355 
356  QAbstractItemModel *model = m_tableLayout.m_model;
357  if (!model)
358  return;
359 
360  // Here's the whole layouting logic
361 
362  // Step 1: determine "ideal" column widths, based on contents
363 
364  m_tableLayout.updateColumnWidths();
365 
366  // Step 2: based on that and the number of horiz pages wanted,
367  // determine actual column widths (horizontal table breaking)
368 
370  optimizer.setColumnWidths(m_tableLayout.m_columnWidths);
371  optimizer.setPageCount(m_numHorizontalPages);
372  const QVector<int> columnsPerPage = optimizer.columnsPerPage();
373  QVector<qreal> widthPerPage = optimizer.widthPerPage(columnsPerPage);
374  const int horizPages = columnsPerPage.count();
375  bool scaled = false;
376 
377  // Step 3: check everything fits horizontally, otherwise calculate font scaling factor for this
378 
379  const qreal horizMargins = 0 /*m_leftMargin*/ + 0 /*m_rightMargin*/;
380  const qreal verticalMargins = 0 /*m_topMargin*/ + 0 /*m_bottomMargin*/;
381  const qreal usablePageWidth = m_pageContentSize.width() - horizMargins;
382  const qreal usablePageHeight = m_pageContentSize.height() - verticalMargins - m_tableLayout.hHeaderHeight();
383 
384 #ifdef DEBUG_LAYOUT
385  qDebug() << "usablePageHeight=" << m_pageContentSize.height() << "minus hHeaderHeight" << m_tableLayout.hHeaderHeight();
386 #endif
387 
388  // for each page, if (sum of column widths) > usablePageWidth,
389  // then we need to scale everything (font and padding)
390  // by the ratio of those two numbers.
391  qreal bestScalingFactor = 1000000;
392  for (int page = 0; page < horizPages; ++page) {
393  const qreal width = widthPerPage[page] + m_tableLayout.vHeaderWidth();
394  if (width > usablePageWidth) {
395  const qreal scalingFactor = usablePageWidth / width;
396 #ifdef DEBUG_LAYOUT
397  qDebug() << "page" << page << "sum of column widths:" << width << "usablePageWidth=" << usablePageWidth;
398  qDebug() << "scaling factor so that it fits horizontally:" << scalingFactor;
399 #endif
400  bestScalingFactor = qMin(bestScalingFactor, scalingFactor);
401  scaled = true;
402  }
403  }
404 
405  if (scaled) {
406  m_tableLayout.ensureScalingFactorForWidth(bestScalingFactor);
407  }
408 
409  // Step 4: check everything fits vertically, otherwise calculate font scaling factor for this
410 
411  const int rowCount = m_tableLayout.m_model->rowCount();
412  if (m_numVerticalPages > 0) {
413  const qreal rowHeight = m_tableLayout.rowHeight();
414 
415  // We can't do a global division of heights, it assumes rows can be over page borders, partially truncated
416  // const qreal maxTotalHeight = m_numVerticalPages * usablePageHeight;
417  // const qreal maxRowHeight = maxTotalHeight / rowCount;
418 
419  // Example: 5 rows over 2 pages, and the usablePageHeight is 100. What do you do?
420  // 2.5 rows per page means truncation. 2 rows per page (as in the division above) is not enough.
421  // The right solution is qCeil, i.e. max 3 rows per page, and maxRowHeight = 100 / 3 = 33.3.
422 
423  const int maxRowsPerPage = qCeil(static_cast<qreal>(rowCount) / m_numVerticalPages);
424  const qreal maxRowHeight = usablePageHeight / maxRowsPerPage;
425 #ifdef DEBUG_LAYOUT
426  qDebug() << "usablePageHeight=" << usablePageHeight << "rowHeight=" << rowHeight << "maxRowsPerPage=" << maxRowsPerPage << "maxRowHeight=" << usablePageHeight << "/" << maxRowsPerPage << "="
427  << maxRowHeight;
428 #endif
429  if (rowHeight > maxRowHeight) { // more than authorized maximum
430  m_tableLayout.ensureScalingFactorForHeight(maxRowHeight);
431  scaled = true;
432  }
433  }
434 
435  // Step 5: update font and calculations based on final font scaling
436  if (scaled) {
437 #ifdef DEBUG_LAYOUT
438  qDebug() << "final scaling factor" << m_tableLayout.scalingFactor();
439  qDebug() << "final fonts: cells:" << m_tableLayout.scaledFont().pointSizeF() << "hHeader:" << m_tableLayout.horizontalHeaderScaledFont().pointSizeF()
440  << "vHeader:" << m_tableLayout.verticalHeaderScaledFont().pointSizeF();
441 #endif
442  // With this new scaling factor [when step 4 changed the factor], what should be the column widths?
443  // If we just call
444  // m_tableLayout.updateColumnWidthsByFactor( m_tableLayout.scalingFactor() / m_userRequestedFontScalingFactor );
445  // then we risk truncating column text (because fonts are not proportional).
446  // Testcase: LongReport with font size 8, padding 3, 10 columns, 300 rows, and scaleTo(1,10) (or none);
447  m_tableLayout.updateColumnWidths();
448 
449 #ifdef DEBUG_LAYOUT
450  qDebug() << "New total width:" << totalWidth();
451 #endif
452 
453 #if 0 // not used right now, but could be useful, especially if we want to goto step 3 again, to resize down
454  // Update the widthPerPage array
455  int column = 0;
456  for ( int page = 0; page < horizPages; ++page ) {
457  const int numColumnsInPage = columnsPerPage[page];
458  widthPerPage[page] = 0;
459  for ( int col = column; col < column + numColumnsInPage; ++col) {
460  widthPerPage[page] += m_tableLayout.m_columnWidths[col];
461  }
462 
463  const qreal width = widthPerPage[page] + m_tableLayout.vHeaderWidth();
464  if ( width > usablePageWidth ) {
465  qWarning() << "Too much width on page" << page;
466  }
467 
468  column += numColumnsInPage;
469  }
470  qDebug() << "widthPerPage:" << widthPerPage;
471 #endif
472  }
473 
474  const qreal rowHeight = m_tableLayout.rowHeight(); // do it now so that the scaling is included
475 
476  // Step 6: determine number of pages for all rows to fit
477 
478  const int maxRowsPerPage = qFloor(usablePageHeight / rowHeight); // no qCeil here, the last row would be truncated...
479  int verticPages = qCeil(qreal(rowCount) / qreal(maxRowsPerPage));
480 
481 #ifdef DEBUG_LAYOUT
482  qDebug() << "maxRowsPerPage=" << usablePageHeight << "/" << rowHeight << "=" << maxRowsPerPage;
483  qDebug() << "pages:" << horizPages << "x" << verticPages;
484  qDebug() << "verticPages = qCeil(" << rowCount << "/" << maxRowsPerPage << ") =" << verticPages;
485 #endif
486 
487  // avoid rounding problems (or the font not zooming down enough vertically),
488  // obey m_numVerticalPages in all cases
489  if (m_numVerticalPages > 0) {
490  Q_ASSERT(verticPages <= m_numVerticalPages);
491  // verticPages = qMin( m_numVerticalPages, verticPages );
492  }
493 
494  // Step 7: now we can record all this in terms of cell areas
495 
496  if (m_tableBreakingPageOrder == Report::RightThenDown) {
497  // qDebug() << "Doing right then down layout";
498  int row = 0;
499  for (int y = 0; y < verticPages; ++y) {
500  int column = 0;
501  const int numRowsInPage = qMin(maxRowsPerPage, rowCount - row);
502  for (int x = 0; x < horizPages; ++x) {
503  const int numColumnsInPage = columnsPerPage[x];
504  m_pageRects.append(QRect(column, row, numColumnsInPage, numRowsInPage));
505  column += numColumnsInPage;
506  }
507  row += maxRowsPerPage;
508  }
509  } else {
510  // qDebug() << "Doing down then right layout";
511  int column = 0;
512  for (int x = 0; x < horizPages; ++x) {
513  int row = 0;
514  const int numColumnsInPage = columnsPerPage[x];
515  for (int y = 0; y < verticPages; ++y) {
516  const int numRowsInPage = qMin(maxRowsPerPage, rowCount - row);
517  m_pageRects.append(QRect(column, row, numColumnsInPage, numRowsInPage));
518  row += maxRowsPerPage;
519  }
520  column += numColumnsInPage;
521  }
522  }
523 
524  m_layoutDirty = false;
525 }
526 
527 void KDReports::SpreadsheetReportLayout::updateTextValue(const QString &id, const QString &newValue)
528 {
529  // Not implemented, there is no support for this in spreadsheet mode currently.
530  Q_UNUSED(id);
531  Q_UNUSED(newValue);
532 }
533 
535 {
536  m_tableLayout.setInitialFontScalingFactor(m_userRequestedFontScalingFactor);
537  const int rowCount = m_tableLayout.m_model->rowCount();
538  const qreal usableTotalHeight = m_tableLayout.rowHeight() * rowCount;
539  const qreal pageContentHeight = usableTotalHeight + 0 /*verticalMargins*/ + m_tableLayout.hHeaderHeight();
540 
541  m_pageContentSize = QSizeF(width, pageContentHeight);
542 #ifdef DEBUG_LAYOUT
543  qDebug() << "layoutAsOnePage: page content size" << m_pageContentSize << rowCount << "*" << m_tableLayout.rowHeight() << "+" << m_tableLayout.hHeaderHeight();
544 #endif
545  setLayoutDirty();
546  return pageContentHeight;
547 }
548 
550 {
551  return QStringLiteral("Not implemented");
552 }
553 
555 {
556 }
557 
558 //@cond PRIVATE
559 bool KDReports::SpreadsheetReportLayout::scaleTo(int numPagesHorizontally, int numPagesVertically)
560 {
561  m_numHorizontalPages = numPagesHorizontally;
562  m_numVerticalPages = numPagesVertically;
563  setLayoutDirty();
564  return true;
565 }
566 
568 {
569  m_tableLayout.m_fixedRowHeight = height;
570 }
571 
573 {
574  return m_numHorizontalPages;
575 }
576 
578 {
579  return m_numVerticalPages;
580 }
581 //@endcond
582 
584 {
585  m_userRequestedFontScalingFactor = factor;
586  m_numHorizontalPages = 1;
587  m_numVerticalPages = 0;
588  setLayoutDirty();
589 }
590 
592 {
593  return m_userRequestedFontScalingFactor;
594 }
595 
596 QString KDReports::SpreadsheetReportLayout::anchorAt(int pageNumber, QPoint pos)
597 {
598  // Not implemented
599  Q_UNUSED(pageNumber)
600  Q_UNUSED(pos)
601  return {};
602 }
603 
605 {
606  m_tableBreakingPageOrder = order;
607  setLayoutDirty();
608 }
609 
610 //@cond PRIVATE
612 {
613  m_tableLayout.m_horizontalHeaderFont = font;
614  setLayoutDirty();
615 }
616 
618 {
619  m_tableLayout.m_verticalHeaderFont = font;
620  setLayoutDirty();
621 }
622 //@endcond
623 
624 void KDReports::SpreadsheetReportLayout::setModel(QAbstractItemModel *model)
625 {
626  m_tableLayout.m_model = model;
627 }
628 
629 //@cond PRIVATE
631 {
632  m_tableLayout.m_verticalHeaderVisible = visible;
633  setLayoutDirty();
634 }
635 
637 {
638  m_tableLayout.m_horizontalHeaderVisible = visible;
639  setLayoutDirty();
640 }
641 
643 {
644  m_tableLayout.m_cellPadding = KDReports::mmToPixels(padding);
645  // qDebug() << "setting cellpadding: mm=" << padding << "pixels=" << m_tableLayout.m_cellPadding;
646  setLayoutDirty();
647 }
648 //@endcond
649 
651 {
652  m_tableLayout.m_iconSize = iconSize;
653 }
654 
655 void KDReports::SpreadsheetReportLayout::setCellBorder(qreal border, const QBrush &borderBrush)
656 {
657  m_tableSettings.m_border = border;
658  m_tableSettings.m_borderBrush = borderBrush;
659 }
660 
661 //@cond PRIVATE
662 void KDReports::SpreadsheetReportLayout::setHeaderBackground(const QBrush &headerBackground)
663 {
664  m_tableSettings.m_headerBackground = headerBackground;
665 }
666 //@endcond
@ DecorationAlignmentRole
This model role allows to specify whether the icon should go before the text (Qt::AlignLeft) or after...
int maximumNumberOfPagesForVerticalScaling() const override
Reimplemented for internal purposes. .
void setTableBreakingPageOrder(KDReports::Report::TableBreakingPageOrder order)
int maximumNumberOfPagesForHorizontalScaling() const override
Reimplemented for internal purposes. .
QString toHtml() const override
Reimplemented for internal purposes. .
int numberOfPages() override
Reimplemented for internal purposes. .
void setVerticalHeaderVisible(bool visible)
void setCellBorder(qreal border, const QBrush &borderBrush)
void setUserRequestedFontScalingFactor(qreal factor) override
Reimplemented for internal purposes. .
void ensureLayouted() override
Reimplemented for internal purposes. .
bool scaleTo(int numPagesHorizontally, int numPagesVertically) override
Reimplemented for internal purposes. .
void setPageContentSize(QSizeF size) override
Reimplemented for internal purposes. .
void updateTextValue(const QString &id, const QString &newValue) override
Reimplemented for internal purposes. .
void setHorizontalHeaderFont(const QFont &font)
QFont defaultFont() const override
Reimplemented for internal purposes. .
void setHeaderBackground(const QBrush &headerBackground)
qreal idealWidth() override
Reimplemented for internal purposes. .
void paintPageContent(int pageNumber, QPainter &painter) override
Reimplemented for internal purposes. .
QString anchorAt(int pageNumber, QPoint pos) override
Reimplemented for internal purposes. .
void setCellPadding(qreal padding)
void finishHtmlExport() override
Reimplemented for internal purposes. .
void setDefaultFont(const QFont &font) override
Reimplemented for internal purposes. .
qreal userRequestedFontScalingFactor() const override
Reimplemented for internal purposes. .
qreal layoutAsOnePage(qreal width) override
Reimplemented for internal purposes. .
void setVerticalHeaderFont(const QFont &font)
void setFixedRowHeight(qreal height) override
Reimplemented for internal purposes. .
void setHorizontalHeaderVisible(bool visible)
void setLayoutDirty() override
Reimplemented for internal purposes. .
void setColumnWidths(const WidthVector &widths)
WidthVector widthPerPage(const QVector< int > &colPerPage) const
KDREPORTS_EXPORT qreal mmToPixels(qreal mm)

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-reports/
Generated by doxygen 1.9.1