21 #include <QAbstractItemModel>
30 : m_tableBreakingPageOrder(
Report::DownThenRight)
31 , m_numHorizontalPages(1)
32 , m_numVerticalPages(0)
34 , m_userRequestedFontScalingFactor(1.0)
48 m_tableLayout.m_cellFont = font;
49 m_tableLayout.m_horizontalHeaderFont = font;
50 m_tableLayout.m_verticalHeaderFont = font;
56 return m_tableLayout.m_cellFont;
59 qreal KDReports::SpreadsheetReportLayout::paintTableVerticalHeader(qreal x, qreal y,
QPainter &painter,
int row)
63 const QRectF cellRect(x, y, m_tableLayout.vHeaderWidth(), m_tableLayout.rowHeight());
65 painter.
setFont(m_tableLayout.verticalHeaderScaledFont());
66 painter.
fillRect(cellRect, m_tableSettings.m_headerBackground);
67 drawBorder(cellRect, painter);
71 painter.
setPen(foreground);
74 const qreal padding = m_tableLayout.scaledCellPadding();
79 const QRectF cellContentsRect = cellRect.
adjusted(padding, padding, -padding, -padding);
81 paintTextAndIcon(painter, cellContentsRect, cellText, cellDecoration, decorationAlignment, alignment);
86 x += cellRect.width();
90 void KDReports::SpreadsheetReportLayout::paintTableHorizontalHeader(
const QRectF &cellRect,
QPainter &painter,
int col)
94 painter.
setFont(m_tableLayout.horizontalHeaderScaledFont());
96 painter.
fillRect(cellRect.
adjusted(-0.5, -0.5, -0.5, -0.5), m_tableSettings.m_headerBackground);
97 drawBorder(cellRect, painter);
101 painter.
setPen(foreground);
104 const qreal padding = m_tableLayout.scaledCellPadding();
109 const QRectF cellContentsRect = cellRect.
adjusted(padding, padding, -padding, -padding);
111 paintTextAndIcon(painter, cellContentsRect, cellText, cellDecoration, decorationAlignment, alignment);
117 void KDReports::SpreadsheetReportLayout::paintIcon(
QPainter &painter,
const QRectF &cellContentsRect,
const QVariant &cellDecoration)
const
119 QPixmap pix = qvariant_cast<QPixmap>(cellDecoration);
121 pix = qvariant_cast<QIcon>(cellDecoration).pixmap(m_tableLayout.m_iconSize);
123 qreal height = pix.
height();
126 img = qvariant_cast<QImage>(cellDecoration);
135 if (m_tableLayout.scalingFactor() != 1.) {
146 const int y = qMax(0,
int((cellContentsRect.
height() - height) / 2.0));
158 void KDReports::SpreadsheetReportLayout::paintTextAndIcon(
QPainter &painter,
const QRectF &cellContentsRect,
const QString &cellText,
const QVariant &cellDecoration,
161 QRectF textRect = cellContentsRect;
163 const bool hasIcon = !cellDecoration.
isNull();
167 iconWidth = m_tableLayout.decorationSize(cellDecoration).width() * m_tableLayout.scalingFactor();
169 if (!iconAfterText) {
170 paintIcon(painter, cellContentsRect, cellDecoration);
178 painter.
drawText(textRect, alignment, cellText);
180 if (hasIcon && iconAfterText) {
181 QRectF iconRect = cellContentsRect;
184 paintIcon(painter, iconRect, cellDecoration);
188 void KDReports::SpreadsheetReportLayout::drawBorder(
const QRectF &cellRect,
QPainter &painter)
const
190 if (m_tableSettings.m_border > 0) {
191 const QPen oldPen = painter.
pen();
195 painter.
setPen(
QPen(m_tableSettings.m_borderBrush.color(), m_tableSettings.m_border));
205 const qreal padding = m_tableLayout.scaledCellPadding();
206 const QRect cellCoords = m_pageRects[pageNumber];
209 const qreal rowHeight = m_tableLayout.rowHeight();
211 if (m_tableLayout.m_horizontalHeaderVisible) {
213 if (m_tableLayout.m_verticalHeaderVisible) {
214 x += m_tableLayout.vHeaderWidth();
216 for (
int col = cellCoords.
left(); col <= cellCoords.
right(); ++col) {
217 const QRectF cellRect(x, y, m_tableLayout.m_columnWidths[col], m_tableLayout.hHeaderHeight());
218 paintTableHorizontalHeader(cellRect, painter, col);
219 x += cellRect.
width();
221 y += m_tableLayout.hHeaderHeight();
224 const int firstRow = cellCoords.
top();
225 const int firstColumn = cellCoords.
left();
226 const int numRows = cellCoords.
height();
227 const int numColumns = cellCoords.
width();
231 coveredCells.
resize(numRows);
232 for (
int row = firstRow; row <= cellCoords.
bottom(); ++row)
233 coveredCells[row - firstRow].resize(numColumns);
235 for (
int row = firstRow; row <= cellCoords.
bottom(); ++row) {
237 if (m_tableLayout.m_verticalHeaderVisible) {
238 x = paintTableVerticalHeader(x, y, painter, row);
240 painter.
setFont(m_tableLayout.scaledFont());
241 for (
int col = cellCoords.
left(); col <= cellCoords.
right(); ++col) {
242 if (coveredCells[row - firstRow].testBit(col - firstColumn)) {
243 x += m_tableLayout.m_columnWidths[col];
251 for (
int r = row; r < row + span.
height() && r < numRows; ++r) {
252 for (
int c = col; c < col + span.
width() && c < numColumns; ++c) {
253 coveredCells[r - firstRow].setBit(c - firstColumn);
258 const QRectF cellRect(x, y, cellWidth(col, span.
width()), qMax(1, span.
height()) * rowHeight);
259 const QRectF cellContentsRect = cellRect.
adjusted(padding, padding, -padding, -padding);
274 drawBorder(cellRect, painter);
286 painter.
setPen(foreground);
288 paintTextAndIcon(painter, cellContentsRect, cellText, cellDecoration, decorationAlignment, alignment);
293 x += m_tableLayout.m_columnWidths[col];
303 return m_pageRects.count();
308 m_tableLayout.setInitialFontScalingFactor(m_userRequestedFontScalingFactor);
312 m_tableLayout.updateColumnWidths();
313 const qreal total = totalWidth();
315 qDebug() <<
"idealWidth:" << total <<
"pixels";
321 qreal KDReports::SpreadsheetReportLayout::totalWidth()
const
323 qreal totalWidth = 0;
324 for (
int col = 0; col < m_tableLayout.m_columnWidths.size(); ++col) {
325 totalWidth += m_tableLayout.m_columnWidths[col];
327 if (m_tableLayout.m_verticalHeaderVisible)
328 totalWidth += m_tableLayout.vHeaderWidth();
332 qreal KDReports::SpreadsheetReportLayout::cellWidth(
int col,
int horizSpan)
const
334 qreal cellWidth = m_tableLayout.m_columnWidths[col];
335 for (
int extraCol = 1; extraCol < horizSpan; ++extraCol) {
336 cellWidth += m_tableLayout.m_columnWidths[col + extraCol];
343 m_pageContentSize = size;
345 qDebug() <<
"page content size" << m_pageContentSize;
354 if (m_pageContentSize.isEmpty()) {
355 qWarning(
"No paper size specified!");
359 m_tableLayout.setInitialFontScalingFactor(m_userRequestedFontScalingFactor);
370 m_tableLayout.updateColumnWidths();
380 const int horizPages = columnsPerPage.
count();
385 const qreal horizMargins = 0 + 0 ;
386 const qreal verticalMargins = 0 + 0 ;
387 const qreal usablePageWidth = m_pageContentSize.width() - horizMargins;
388 const qreal usablePageHeight = m_pageContentSize.height() - verticalMargins - m_tableLayout.hHeaderHeight();
391 qDebug() <<
"usablePageHeight=" << m_pageContentSize.height() <<
"minus hHeaderHeight" << m_tableLayout.hHeaderHeight();
397 qreal bestScalingFactor = 1000000;
398 for (
int page = 0; page < horizPages; ++page) {
399 const qreal width = widthPerPage[page] + m_tableLayout.vHeaderWidth();
400 if (width > usablePageWidth) {
401 const qreal scalingFactor = usablePageWidth / width;
403 qDebug() <<
"page" << page <<
"sum of column widths:" << width <<
"usablePageWidth=" << usablePageWidth;
404 qDebug() <<
"scaling factor so that it fits horizontally:" << scalingFactor;
406 bestScalingFactor = qMin(bestScalingFactor, scalingFactor);
412 m_tableLayout.ensureScalingFactorForWidth(bestScalingFactor);
417 const int rowCount = m_tableLayout.m_model->rowCount();
418 if (m_numVerticalPages > 0) {
419 const qreal rowHeight = m_tableLayout.rowHeight();
429 const int maxRowsPerPage = qCeil(
static_cast<qreal
>(rowCount) / m_numVerticalPages);
430 const qreal maxRowHeight = usablePageHeight / maxRowsPerPage;
432 qDebug() <<
"usablePageHeight=" << usablePageHeight <<
"rowHeight=" << rowHeight <<
"maxRowsPerPage=" << maxRowsPerPage <<
"maxRowHeight=" << usablePageHeight <<
"/" << maxRowsPerPage <<
"="
435 if (rowHeight > maxRowHeight) {
436 m_tableLayout.ensureScalingFactorForHeight(maxRowHeight);
444 qDebug() <<
"final scaling factor" << m_tableLayout.scalingFactor();
445 qDebug() <<
"final fonts: cells:" << m_tableLayout.scaledFont().pointSizeF() <<
"hHeader:" << m_tableLayout.horizontalHeaderScaledFont().pointSizeF()
446 <<
"vHeader:" << m_tableLayout.verticalHeaderScaledFont().pointSizeF();
453 m_tableLayout.updateColumnWidths();
456 qDebug() <<
"New total width:" << totalWidth();
459 #if 0 // not used right now, but could be useful, especially if we want to goto step 3 again, to resize down
462 for (
int page = 0; page < horizPages; ++page ) {
463 const int numColumnsInPage = columnsPerPage[page];
464 widthPerPage[page] = 0;
465 for (
int col = column; col < column + numColumnsInPage; ++col) {
466 widthPerPage[page] += m_tableLayout.m_columnWidths[col];
469 const qreal width = widthPerPage[page] + m_tableLayout.vHeaderWidth();
470 if ( width > usablePageWidth ) {
471 qWarning() <<
"Too much width on page" << page;
474 column += numColumnsInPage;
476 qDebug() <<
"widthPerPage:" << widthPerPage;
480 const qreal rowHeight = m_tableLayout.rowHeight();
484 const int maxRowsPerPage = qFloor(usablePageHeight / rowHeight);
485 int verticPages = qCeil(qreal(rowCount) / qreal(maxRowsPerPage));
488 qDebug() <<
"maxRowsPerPage=" << usablePageHeight <<
"/" << rowHeight <<
"=" << maxRowsPerPage;
489 qDebug() <<
"pages:" << horizPages <<
"x" << verticPages;
490 qDebug() <<
"verticPages = qCeil(" << rowCount <<
"/" << maxRowsPerPage <<
") =" << verticPages;
495 if (m_numVerticalPages > 0) {
496 Q_ASSERT(verticPages <= m_numVerticalPages);
505 for (
int y = 0; y < verticPages; ++y) {
507 const int numRowsInPage = qMin(maxRowsPerPage, rowCount - row);
508 for (
int x = 0; x < horizPages; ++x) {
509 const int numColumnsInPage = columnsPerPage[x];
510 m_pageRects.
append(
QRect(column, row, numColumnsInPage, numRowsInPage));
511 column += numColumnsInPage;
513 row += maxRowsPerPage;
518 for (
int x = 0; x < horizPages; ++x) {
520 const int numColumnsInPage = columnsPerPage[x];
521 for (
int y = 0; y < verticPages; ++y) {
522 const int numRowsInPage = qMin(maxRowsPerPage, rowCount - row);
523 m_pageRects.append(
QRect(column, row, numColumnsInPage, numRowsInPage));
524 row += maxRowsPerPage;
526 column += numColumnsInPage;
530 m_layoutDirty =
false;
542 m_tableLayout.setInitialFontScalingFactor(m_userRequestedFontScalingFactor);
543 const int rowCount = m_tableLayout.m_model->rowCount();
544 const qreal usableTotalHeight = m_tableLayout.rowHeight() * rowCount;
545 const qreal pageContentHeight = usableTotalHeight + 0 + m_tableLayout.hHeaderHeight();
547 m_pageContentSize =
QSizeF(width, pageContentHeight);
549 qDebug() <<
"layoutAsOnePage: page content size" << m_pageContentSize << rowCount <<
"*" << m_tableLayout.rowHeight() <<
"+" << m_tableLayout.hHeaderHeight();
552 return pageContentHeight;
557 return QStringLiteral(
"Not implemented");
565 m_numHorizontalPages = numPagesHorizontally;
566 m_numVerticalPages = numPagesVertically;
573 m_tableLayout.m_fixedRowHeight = height;
578 return m_numHorizontalPages;
583 return m_numVerticalPages;
589 m_userRequestedFontScalingFactor = factor;
590 m_numHorizontalPages = 1;
591 m_numVerticalPages = 0;
597 return m_userRequestedFontScalingFactor;
610 m_tableBreakingPageOrder = order;
617 m_tableLayout.m_horizontalHeaderFont = font;
623 m_tableLayout.m_verticalHeaderFont = font;
630 m_tableLayout.m_model = model;
636 m_tableLayout.m_verticalHeaderVisible = visible;
642 m_tableLayout.m_horizontalHeaderVisible = visible;
656 m_tableLayout.m_iconSize = iconSize;
661 m_tableSettings.m_border = border;
662 m_tableSettings.m_borderBrush = borderBrush;
668 m_tableSettings.m_headerBackground = headerBackground;