File indexing completed on 2024-04-28 16:21:31
0001 /* This file is part of the KDE project 0002 Copyright 2007, 2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0003 Copyright 2005 Raphael Langerhorst <raphael.langerhorst@kdemail.net> 0004 Copyright 2003 Philipp Müller <philipp.mueller@gmx.de> 0005 Copyright 1998, 1999 Torben Weis <weis@kde.org> 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 // Local 0024 #include "SheetPrint.h" 0025 #include "SheetPrint_p.h" 0026 0027 #include "HeaderFooter.h" 0028 #include "PrintSettings.h" 0029 #include "calligra_sheets_limits.h" 0030 #include "Region.h" 0031 #include "Sheet.h" 0032 #include "SheetsDebug.h" 0033 0034 using namespace Calligra::Sheets; 0035 0036 SheetPrint::SheetPrint(Sheet *sheet) 0037 : d(new Private(this)) 0038 { 0039 d->m_pSheet = sheet; 0040 0041 d->m_settings = new PrintSettings(); 0042 d->m_headerFooter = new HeaderFooter(sheet); 0043 0044 d->m_maxCheckedNewPageX = 0; 0045 d->m_maxCheckedNewPageY = 0; 0046 d->m_dPrintRepeatColumnsWidth = 0.0; 0047 d->m_dPrintRepeatRowsHeight = 0.0; 0048 } 0049 0050 SheetPrint::SheetPrint(const SheetPrint &other) 0051 : d(new Private(this)) 0052 { 0053 d->m_pSheet = other.d->m_pSheet; 0054 0055 d->m_settings = new PrintSettings(*other.d->m_settings); 0056 d->m_headerFooter = new HeaderFooter(*other.d->m_headerFooter); 0057 0058 d->m_maxCheckedNewPageX = other.d->m_maxCheckedNewPageX; 0059 d->m_maxCheckedNewPageY = other.d->m_maxCheckedNewPageY; 0060 d->m_dPrintRepeatColumnsWidth = other.d->m_dPrintRepeatColumnsWidth; 0061 d->m_dPrintRepeatRowsHeight = other.d->m_dPrintRepeatRowsHeight; 0062 d->m_lnewPageListX = other.d->m_lnewPageListX; 0063 d->m_lnewPageListY = other.d->m_lnewPageListY; 0064 } 0065 0066 SheetPrint::~SheetPrint() 0067 { 0068 delete d->m_headerFooter; 0069 delete d->m_settings; 0070 delete d; 0071 } 0072 0073 PrintSettings *SheetPrint::settings() const 0074 { 0075 return d->m_settings; 0076 } 0077 0078 void SheetPrint::setSettings(const PrintSettings &settings, bool force) 0079 { 0080 // Relayout forced? 0081 if (force) { 0082 *d->m_settings = settings; 0083 d->updateRepeatedColumnsWidth(); 0084 d->updateRepeatedRowsHeight(); 0085 const QSize pageLimits = settings.pageLimits(); 0086 const QSize usedArea = d->m_pSheet->usedArea(true).size(); 0087 if (pageLimits.width() > 0) { 0088 d->calculateZoomForPageLimitX(); 0089 } else { 0090 updateHorizontalPageParameters(0); 0091 d->calculateHorizontalPageParameters(usedArea.width()); 0092 } 0093 if (pageLimits.height() > 0) { 0094 d->calculateZoomForPageLimitY(); 0095 } else { 0096 updateVerticalPageParameters(0); 0097 d->calculateVerticalPageParameters(usedArea.height()); 0098 } 0099 return; 0100 } 0101 0102 const KoPageLayout oldPageLayout = d->m_settings->pageLayout(); 0103 const KoPageLayout pageLayout = settings.pageLayout(); 0104 const QRect oldPrintRange = d->m_settings->printRegion().lastRange(); 0105 const QRect printRange = settings.printRegion().lastRange(); 0106 const QSize oldPageLimits = d->m_settings->pageLimits(); 0107 const QSize pageLimits = settings.pageLimits(); 0108 const QPair<int, int> oldRepeatedColumns = d->m_settings->repeatedColumns(); 0109 const QPair<int, int> repeatedColumns = settings.repeatedColumns(); 0110 const QPair<int, int> oldRepeatedRows = d->m_settings->repeatedRows(); 0111 const QPair<int, int> repeatedRows = settings.repeatedRows(); 0112 0113 const bool pageWidthChanged = oldPageLayout.width != pageLayout.width; 0114 const bool pageHeightChanged = oldPageLayout.height != pageLayout.height; 0115 const bool horizontalLimitChanged = oldPageLimits.width() != pageLimits.width(); 0116 const bool verticalLimitChanged = oldPageLimits.height() != pageLimits.height(); 0117 const bool repeatedColumnsChanged = oldRepeatedColumns != repeatedColumns; 0118 const bool repeatedRowsChanged = oldRepeatedRows != repeatedRows; 0119 const bool zoomChanged = d->m_settings->zoom() != settings.zoom(); 0120 0121 *d->m_settings = settings; 0122 0123 // The starting column/row for the page parameter updates. 0124 int column = KS_colMax + 1; 0125 int row = KS_rowMax + 1; 0126 0127 // The print range. 0128 if (oldPrintRange.left() != printRange.left()) { 0129 column = qMin(oldPrintRange.left(), printRange.left()); 0130 } 0131 if (oldPrintRange.top() != printRange.top()) { 0132 row = qMin(oldPrintRange.top(), printRange.top()); 0133 } 0134 0135 // The zoom. 0136 if (zoomChanged) { 0137 column = 0; 0138 row = 0; 0139 } 0140 0141 // The page limits. 0142 if (horizontalLimitChanged && pageLimits.width() <= 0) { 0143 column = 0; 0144 } 0145 if (verticalLimitChanged && pageLimits.height() <= 0) { 0146 row = 0; 0147 } 0148 0149 // The page dimensions. 0150 if (pageWidthChanged) { 0151 column = 0; 0152 } 0153 if (pageHeightChanged) { 0154 row = 0; 0155 } 0156 0157 // The column/row repetitions. 0158 if (repeatedColumnsChanged) { 0159 d->updateRepeatedColumnsWidth(); 0160 column = qMin(column, oldRepeatedColumns.first); 0161 column = qMin(column, repeatedColumns.first); 0162 } 0163 if (repeatedRowsChanged) { 0164 d->updateRepeatedRowsHeight(); 0165 row = qMin(row, oldRepeatedRows.first); 0166 row = qMin(row, repeatedRows.first); 0167 } 0168 0169 // Update the page parameters. 0170 // If page limits are set to non-zero, call the special methods. 0171 if (horizontalLimitChanged && pageLimits.width() > 0) { 0172 d->calculateZoomForPageLimitX(); 0173 } else if (column <= KS_colMax) { 0174 updateHorizontalPageParameters(column); 0175 } 0176 if (verticalLimitChanged && pageLimits.height() > 0) { 0177 d->calculateZoomForPageLimitY(); 0178 } else if (row <= KS_rowMax) { 0179 updateVerticalPageParameters(row); 0180 } 0181 } 0182 0183 HeaderFooter *SheetPrint::headerFooter() const 0184 { 0185 return d->m_headerFooter; 0186 } 0187 0188 bool SheetPrint::isColumnOnNewPage(int _column) 0189 { 0190 if (_column > d->m_maxCheckedNewPageX) 0191 d->calculateHorizontalPageParameters(_column); 0192 0193 //Are these the edges of the print range? 0194 const QRect printRange = d->m_settings->printRegion().lastRange(); 0195 if (_column == printRange.left() || _column == printRange.right()) { 0196 return true; 0197 } 0198 0199 //beyond the print range it's always false 0200 if (_column < printRange.left() || _column > printRange.right()) { 0201 return false; 0202 } 0203 0204 //Now check if we find the column already in the list 0205 if (d->m_lnewPageListX.indexOf(PrintNewPageEntry(_column)) != -1) { 0206 if (_column > d->m_maxCheckedNewPageX) 0207 d->m_maxCheckedNewPageX = _column; 0208 return true; 0209 } 0210 return false; 0211 } 0212 0213 0214 0215 bool SheetPrint::isRowOnNewPage(int _row) 0216 { 0217 if (_row > d->m_maxCheckedNewPageY) 0218 d->calculateVerticalPageParameters(_row); 0219 0220 //Are these the edges of the print range? 0221 const QRect printRange = d->m_settings->printRegion().lastRange(); 0222 if (_row == printRange.top() || _row == printRange.bottom()) { 0223 return true; 0224 } 0225 0226 //beyond the print range it's always false 0227 if (_row < printRange.top() || _row > printRange.bottom()) { 0228 return false; 0229 } 0230 0231 //Now check if we find the row already in the list 0232 if (d->m_lnewPageListY.indexOf(PrintNewPageEntry(_row)) != -1) { 0233 if (_row > d->m_maxCheckedNewPageY) 0234 d->m_maxCheckedNewPageY = _row; 0235 return true; 0236 } 0237 0238 return false; 0239 } 0240 0241 void SheetPrint::updateHorizontalPageParameters(int _col) 0242 { 0243 //If the new range is after the first entry, we need to delete the whole list 0244 const QRect printRange = d->m_settings->printRegion().lastRange(); 0245 if (d->m_lnewPageListX.isEmpty() || d->m_lnewPageListX.first().startItem() != printRange.left() || _col == 0) { 0246 d->m_lnewPageListX.clear(); 0247 d->m_maxCheckedNewPageX = 0; 0248 d->updateRepeatedColumnsWidth(); 0249 return; 0250 } 0251 0252 if (_col <= d->m_lnewPageListX.last().endItem()) { 0253 // Find the page entry for this column 0254 int index = d->m_lnewPageListX.count() - 1; 0255 while (_col < d->m_lnewPageListX[index].startItem()) { 0256 --index; 0257 } 0258 0259 //Remove later pages 0260 while (index != d->m_lnewPageListX.count()) 0261 d->m_lnewPageListX.removeAt(index); 0262 0263 d->m_maxCheckedNewPageX = d->m_lnewPageListX.isEmpty() ? 0 : d->m_lnewPageListX.last().endItem(); 0264 } 0265 0266 // The column is not beyond the repeated columns? 0267 if (_col <= d->m_settings->repeatedColumns().second) { 0268 d->updateRepeatedColumnsWidth(); 0269 } 0270 } 0271 0272 void SheetPrint::updateVerticalPageParameters(int _row) 0273 { 0274 //If the new range is after the first entry, we need to delete the whole list 0275 const QRect printRange = d->m_settings->printRegion().lastRange(); 0276 if (d->m_lnewPageListY.isEmpty() || d->m_lnewPageListY.first().startItem() != printRange.top() || _row == 0) { 0277 d->m_lnewPageListY.clear(); 0278 d->m_maxCheckedNewPageY = 0; 0279 d->updateRepeatedRowsHeight(); 0280 return; 0281 } 0282 0283 if (_row <= d->m_lnewPageListY.last().endItem()) { 0284 // Find the page entry for this row 0285 int index = d->m_lnewPageListY.count() - 1; 0286 while (_row < d->m_lnewPageListY[index].startItem()) { 0287 --index; 0288 } 0289 0290 //Remove later pages 0291 while (index != d->m_lnewPageListY.count()) 0292 d->m_lnewPageListY.removeAt(index); 0293 0294 d->m_maxCheckedNewPageY = d->m_lnewPageListY.isEmpty() ? 0 : d->m_lnewPageListY.last().endItem(); 0295 } 0296 0297 // The row is not beyond the repeated rows? 0298 if (_row <= d->m_settings->repeatedRows().second) { 0299 d->updateRepeatedRowsHeight(); 0300 } 0301 } 0302 0303 void SheetPrint::insertColumn(int col, int nbCol) 0304 { 0305 //update print range, when it has been defined 0306 const QRect printRange = d->m_settings->printRegion().lastRange(); 0307 if (printRange != QRect(QPoint(1, 1), QPoint(KS_colMax, KS_rowMax))) { 0308 int left = printRange.left(); 0309 int right = printRange.right(); 0310 0311 for (int i = 0; i < nbCol; i++) { 0312 if (left >= col) left++; 0313 if (right >= col) right++; 0314 } 0315 //Validity checks 0316 if (left > KS_colMax) left = KS_colMax; 0317 if (right > KS_colMax) right = KS_colMax; 0318 const Region region(QRect(QPoint(left, printRange.top()), 0319 QPoint(right, printRange.bottom())), d->m_pSheet); 0320 // Trigger an update by setting it indirectly. 0321 PrintSettings settings = *d->m_settings; 0322 settings.setPrintRegion(region); 0323 setSettings(settings); 0324 } 0325 } 0326 0327 void SheetPrint::insertRow(int row, int nbRow) 0328 { 0329 //update print range, when it has been defined 0330 const QRect printRange = d->m_settings->printRegion().lastRange(); 0331 if (printRange != QRect(QPoint(1, 1), QPoint(KS_colMax, KS_rowMax))) { 0332 int top = printRange.top(); 0333 int bottom = printRange.bottom(); 0334 0335 for (int i = 0; i < nbRow; i++) { 0336 if (top >= row) top++; 0337 if (bottom >= row) bottom++; 0338 } 0339 //Validity checks 0340 if (top > KS_rowMax) top = KS_rowMax; 0341 if (bottom > KS_rowMax) bottom = KS_rowMax; 0342 const Region region(QRect(QPoint(printRange.left(), top), 0343 QPoint(printRange.right(), bottom)), d->m_pSheet); 0344 // Trigger an update by setting it indirectly. 0345 PrintSettings settings = *d->m_settings; 0346 settings.setPrintRegion(region); 0347 setSettings(settings); 0348 } 0349 } 0350 0351 void SheetPrint::removeColumn(int col, int nbCol) 0352 { 0353 PrintSettings settings = *d->m_settings; 0354 //update print range, when it has been defined 0355 const QRect printRange = d->m_settings->printRegion().lastRange(); 0356 if (printRange != QRect(QPoint(1, 1), QPoint(KS_colMax, KS_rowMax))) { 0357 int left = printRange.left(); 0358 int right = printRange.right(); 0359 0360 for (int i = 0; i < nbCol; i++) { 0361 if (left > col) left--; 0362 if (right >= col) right--; 0363 } 0364 //Validity checks 0365 if (left < 1) left = 1; 0366 if (right < 1) right = 1; 0367 const Region region(QRect(QPoint(left, printRange.top()), 0368 QPoint(right, printRange.bottom())), d->m_pSheet); 0369 settings.setPrintRegion(region); 0370 } 0371 0372 //update repeat columns, when it has been defined 0373 const QPair<int, int> repeatedColumns = d->m_settings->repeatedColumns(); 0374 if (repeatedColumns.first != 0) { 0375 int left = repeatedColumns.first; 0376 int right = repeatedColumns.second; 0377 0378 for (int i = 0; i < nbCol; i++) { 0379 if (left > col) left--; 0380 if (right >= col) right--; 0381 } 0382 //Validity checks 0383 if (left < 1) left = 1; 0384 if (right < 1) right = 1; 0385 settings.setRepeatedColumns(qMakePair(left, right)); 0386 } 0387 // Trigger an update by setting them indirectly. 0388 setSettings(settings); 0389 } 0390 0391 void SheetPrint::removeRow(int row, int nbRow) 0392 { 0393 PrintSettings settings = *d->m_settings; 0394 //update print range, when it has been defined 0395 const QRect printRange = d->m_settings->printRegion().lastRange(); 0396 if (printRange != QRect(QPoint(1, 1), QPoint(KS_colMax, KS_rowMax))) { 0397 int top = printRange.top(); 0398 int bottom = printRange.bottom(); 0399 0400 for (int i = 0; i < nbRow; i++) { 0401 if (top > row) top--; 0402 if (bottom >= row) bottom--; 0403 } 0404 //Validity checks 0405 if (top < 1) top = 1; 0406 if (bottom < 1) bottom = 1; 0407 const Region region(QRect(QPoint(printRange.left(), top), 0408 QPoint(printRange.right(), bottom)), d->m_pSheet); 0409 settings.setPrintRegion(region); 0410 } 0411 0412 //update repeat rows, when it has been defined 0413 const QPair<int, int> repeatedRows = d->m_settings->repeatedRows(); 0414 if (repeatedRows.first != 0) { 0415 int top = repeatedRows.first; 0416 int bottom = repeatedRows.second; 0417 0418 for (int i = 0; i < nbRow; i++) { 0419 if (top > row) top--; 0420 if (bottom >= row) bottom--; 0421 } 0422 //Validity checks 0423 if (top < 1) top = 1; 0424 if (bottom < 1) bottom = 1; 0425 settings.setRepeatedRows(qMakePair(top, bottom)); 0426 } 0427 // Trigger an update by setting them indirectly. 0428 setSettings(settings); 0429 } 0430 0431 int SheetPrint::pageCount() const 0432 { 0433 return d->m_lnewPageListX.count() * d->m_lnewPageListY.count(); 0434 } 0435 0436 QRect SheetPrint::cellRange(int page) const 0437 { 0438 if (d->m_lnewPageListX.isEmpty() || d->m_lnewPageListY.isEmpty()) { 0439 return QRect(); 0440 } 0441 if (page - 1 > pageCount()) { 0442 return QRect(); 0443 } 0444 debugSheets << "page:" << page << "of" << pageCount(); 0445 0446 int horizontalIndex = 0; 0447 int verticalIndex = 0; 0448 if (d->m_settings->pageOrder() == PrintSettings::LeftToRight) { 0449 horizontalIndex = (page - 1) % d->m_lnewPageListX.count(); 0450 verticalIndex = (page - 1) / d->m_lnewPageListX.count(); 0451 } else { 0452 horizontalIndex = (page - 1) / d->m_lnewPageListY.count(); 0453 verticalIndex = (page - 1) % d->m_lnewPageListY.count(); 0454 } 0455 debugSheets << "horizontal:" << horizontalIndex + 1 << "of" << d->m_lnewPageListX.count(); 0456 debugSheets << "vertical:" << verticalIndex + 1 << "of" << d->m_lnewPageListY.count(); 0457 0458 const PrintNewPageEntry horizontalParameters = d->m_lnewPageListX[horizontalIndex]; 0459 const PrintNewPageEntry verticalParameters = d->m_lnewPageListY[verticalIndex]; 0460 0461 QRect cellRange; 0462 cellRange.setLeft(horizontalParameters.startItem()); 0463 cellRange.setRight(horizontalParameters.endItem()); 0464 cellRange.setTop(verticalParameters.startItem()); 0465 cellRange.setBottom(verticalParameters.endItem()); 0466 return cellRange; 0467 } 0468 0469 QRectF SheetPrint::documentArea(int page) const 0470 { 0471 if (d->m_lnewPageListX.isEmpty() || d->m_lnewPageListY.isEmpty()) { 0472 return QRectF(); 0473 } 0474 if (page - 1 > pageCount()) { 0475 return QRectF(); 0476 } 0477 0478 int horizontalIndex = 0; 0479 int verticalIndex = 0; 0480 if (d->m_settings->pageOrder() == PrintSettings::LeftToRight) { 0481 horizontalIndex = (page - 1) % d->m_lnewPageListX.count(); 0482 verticalIndex = (page - 1) / d->m_lnewPageListX.count(); 0483 } else { 0484 horizontalIndex = (page - 1) / d->m_lnewPageListY.count(); 0485 verticalIndex = (page - 1) % d->m_lnewPageListY.count(); 0486 } 0487 0488 const PrintNewPageEntry horizontalParameters = d->m_lnewPageListX[horizontalIndex]; 0489 const PrintNewPageEntry verticalParameters = d->m_lnewPageListY[verticalIndex]; 0490 0491 QRectF documentArea; 0492 documentArea.setLeft(horizontalParameters.offset()); 0493 documentArea.setWidth(horizontalParameters.size()); 0494 documentArea.setTop(verticalParameters.offset()); 0495 documentArea.setHeight(verticalParameters.size()); 0496 return documentArea; 0497 } 0498 0499 void SheetPrint::operator=(const SheetPrint & other) 0500 { 0501 d->m_pSheet = other.d->m_pSheet; 0502 0503 *d->m_settings = *other.d->m_settings; 0504 *d->m_headerFooter = *other.d->m_headerFooter; 0505 0506 d->m_maxCheckedNewPageX = other.d->m_maxCheckedNewPageX; 0507 d->m_maxCheckedNewPageY = other.d->m_maxCheckedNewPageY; 0508 d->m_dPrintRepeatColumnsWidth = other.d->m_dPrintRepeatColumnsWidth; 0509 d->m_dPrintRepeatRowsHeight = other.d->m_dPrintRepeatRowsHeight; 0510 d->m_lnewPageListX = other.d->m_lnewPageListX; 0511 d->m_lnewPageListY = other.d->m_lnewPageListY; 0512 }