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 #include "SheetPrint_p.h" 0024 0025 #include "PrintSettings.h" 0026 #include "Region.h" 0027 #include "RowColumnFormat.h" 0028 #include "RowFormatStorage.h" 0029 #include "Sheet.h" 0030 0031 using namespace Calligra::Sheets; 0032 0033 void SheetPrint::Private::calculateHorizontalPageParameters(int _column) 0034 { 0035 // Zoom the print width ONCE here, instead for each column width. 0036 const double printWidth = m_settings->printWidth() / m_settings->zoom(); 0037 0038 float offset = 0.0; 0039 0040 //Are these the edges of the print range? 0041 const QRect printRange = m_settings->printRegion().lastRange(); 0042 #if 0 0043 if (_column == printRange.left() || _column == printRange.right()) { 0044 if (_column > m_maxCheckedNewPageX) 0045 m_maxCheckedNewPageX = _column; 0046 return; 0047 } 0048 0049 //We don't check beyond the print range 0050 if (_column < printRange.left() || _column > printRange.right()) { 0051 if (_column > m_maxCheckedNewPageX) 0052 m_maxCheckedNewPageX = _column; 0053 if (_column > printRange.right()) { 0054 if (m_lnewPageListX.last().endItem() == 0) 0055 m_lnewPageListX.last().setEndItem(printRange.right()); 0056 } 0057 return; 0058 } 0059 #endif 0060 0061 // Check if the pre-calculated width matches the repeated columns setting. 0062 const bool repetitions = m_settings->repeatedColumns().first != 0; 0063 if (repetitions != (m_dPrintRepeatColumnsWidth == 0.0)) { 0064 // Existing column repetitions, but their pre-calculated width is zero? 0065 // Must be the first run. Or the other way around? Seem to be orphaned. 0066 // Either way, seems they do not match. Calculate them! 0067 updateRepeatedColumnsWidth(); 0068 } 0069 0070 // The end of the last item (zero, if list is empty). 0071 const int end = m_lnewPageListX.empty() ? 0 : m_lnewPageListX.last().endItem(); 0072 0073 //If _column is greater than the last entry, we need to calculate the result 0074 if (_column > end && 0075 _column > m_maxCheckedNewPageX) { //this columns hasn't been calculated before 0076 int startCol = end + 1; 0077 int col = startCol; 0078 double x = m_pSheet->columnFormat(col)->width(); 0079 0080 // Add a new page. 0081 m_lnewPageListX.append(PrintNewPageEntry(startCol)); 0082 0083 //Add repeated column width, when necessary 0084 const QPair<int, int> repeatedColumns = m_settings->repeatedColumns(); 0085 if (col > repeatedColumns.first) { 0086 x += m_dPrintRepeatColumnsWidth; 0087 offset = m_dPrintRepeatColumnsWidth; 0088 } 0089 debugSheets << "startCol:" << startCol << "col:" << col << "x:" << x 0090 << "offset:" << offset << repeatedColumns; 0091 0092 while ((col <= _column) && (col < printRange.right())) { 0093 debugSheets << "loop:" << "startCol:" << startCol << "col:" << col 0094 << "x:" << x << "offset:" << offset; 0095 // end of page? 0096 if (x > printWidth || m_pSheet->columnFormat(col)->hasPageBreak()) { 0097 //Now store into the previous entry the enditem and the width 0098 m_lnewPageListX.last().setEndItem(col - 1); 0099 m_lnewPageListX.last().setSize(x - m_pSheet->columnFormat(col)->width()); 0100 m_lnewPageListX.last().setOffset(offset); 0101 0102 //start a new page 0103 m_lnewPageListX.append(PrintNewPageEntry(col)); 0104 startCol = col; 0105 x = m_pSheet->columnFormat(col)->width(); 0106 if (col >= repeatedColumns.first) { 0107 debugSheets << "col >= repeatedColumns.first:" << col << repeatedColumns.first; 0108 x += m_dPrintRepeatColumnsWidth; 0109 offset = m_dPrintRepeatColumnsWidth; 0110 } 0111 } 0112 col++; 0113 x += m_pSheet->columnFormat(col)->width(); 0114 } 0115 0116 // Iterate to the end of the page. 0117 while (m_lnewPageListX.last().endItem() == 0) { 0118 debugSheets << "loop to end" << "col:" << col << "x:" << x << "offset:" << offset 0119 << "m_maxCheckedNewPageX:" << m_maxCheckedNewPageX; 0120 if (x > printWidth || m_pSheet->columnFormat(col)->hasPageBreak()) { 0121 // Now store into the previous entry the enditem and the width 0122 m_lnewPageListX.last().setEndItem(col - 1); 0123 m_lnewPageListX.last().setSize(x - m_pSheet->columnFormat(col)->width()); 0124 m_lnewPageListX.last().setOffset(offset); 0125 0126 if (col - 1 > m_maxCheckedNewPageX) { 0127 m_maxCheckedNewPageX = col - 1; 0128 } 0129 return; 0130 } 0131 ++col; 0132 x += m_pSheet->columnFormat(col)->width(); 0133 } 0134 } 0135 0136 debugSheets << "m_maxCheckedNewPageX:" << m_maxCheckedNewPageX; 0137 if (_column > m_maxCheckedNewPageX) { 0138 m_maxCheckedNewPageX = _column; 0139 m_lnewPageListX.last().setEndItem(_column); 0140 } 0141 } 0142 0143 void SheetPrint::Private::calculateVerticalPageParameters(int _row) 0144 { 0145 // Zoom the print height ONCE here, instead for each row height. 0146 const double printHeight = m_settings->printHeight() / m_settings->zoom(); 0147 0148 float offset = 0.0; 0149 0150 //Are these the edges of the print range? 0151 const QRect printRange = m_settings->printRegion().lastRange(); 0152 #if 0 0153 if (_row == printRange.top() || _row == printRange.bottom()) { 0154 if (_row > m_maxCheckedNewPageY) 0155 m_maxCheckedNewPageY = _row; 0156 return; 0157 } 0158 0159 //beyond the print range it's always false 0160 if (_row < printRange.top() || _row > printRange.bottom()) { 0161 if (_row > m_maxCheckedNewPageY) 0162 m_maxCheckedNewPageY = _row; 0163 if (_row > printRange.bottom()) { 0164 if (m_lnewPageListY.last().endItem() == 0) 0165 m_lnewPageListY.last().setEndItem(printRange.bottom()); 0166 } 0167 return; 0168 } 0169 #endif 0170 0171 // Check if the pre-calculated height matches the repeated rows setting. 0172 const bool repetitions = m_settings->repeatedRows().first != 0; 0173 if (repetitions != (m_dPrintRepeatRowsHeight == 0.0)) { 0174 // Existing row repetitions, but their pre-calculated height is zero? 0175 // Must be the first run. Or the other way around? Seem to be orphaned. 0176 // Either way, seems they do not match. Calculate them! 0177 updateRepeatedRowsHeight(); 0178 } 0179 0180 // The end of the last item (zero, if list is empty). 0181 const int end = m_lnewPageListY.empty() ? 0 : m_lnewPageListY.last().endItem(); 0182 0183 //If _column is greater than the last entry, we need to calculate the result 0184 if (_row > end && 0185 _row > m_maxCheckedNewPageY) { //this columns hasn't been calculated before 0186 int startRow = end + 1; 0187 int row = startRow; 0188 double y = m_pSheet->rowFormats()->rowHeight(row); 0189 0190 // Add a new page. 0191 m_lnewPageListY.append(PrintNewPageEntry(startRow)); 0192 0193 //Add repeated row height, when necessary 0194 const QPair<int, int> repeatedRows = m_settings->repeatedRows(); 0195 if (row > repeatedRows.first) { 0196 y += m_dPrintRepeatRowsHeight; 0197 offset = m_dPrintRepeatRowsHeight; 0198 } 0199 0200 while ((row <= _row) && (row < printRange.bottom())) { 0201 // end of page? 0202 if (y > printHeight || m_pSheet->rowFormats()->hasPageBreak(row)) { 0203 //Now store into the previous entry the enditem and the width 0204 m_lnewPageListY.last().setEndItem(row - 1); 0205 m_lnewPageListY.last().setSize(y - m_pSheet->rowFormats()->rowHeight(row)); 0206 m_lnewPageListY.last().setOffset(offset); 0207 0208 //start a new page 0209 m_lnewPageListY.append(PrintNewPageEntry(row)); 0210 startRow = row; 0211 y = m_pSheet->rowFormats()->rowHeight(row); 0212 if (row >= repeatedRows.first) { 0213 y += m_dPrintRepeatRowsHeight; 0214 offset = m_dPrintRepeatRowsHeight; 0215 } 0216 } 0217 row++; 0218 y += m_pSheet->rowFormats()->rowHeight(row); 0219 } 0220 0221 // Iterate to the end of the page. 0222 while (m_lnewPageListY.last().endItem() == 0) { 0223 if (y > printHeight || m_pSheet->rowFormats()->hasPageBreak(row)) { 0224 // Now store into the previous entry the enditem and the width 0225 m_lnewPageListY.last().setEndItem(row - 1); 0226 m_lnewPageListY.last().setSize(y - m_pSheet->rowFormats()->rowHeight(row)); 0227 m_lnewPageListY.last().setOffset(offset); 0228 0229 if (row - 1 > m_maxCheckedNewPageY) { 0230 m_maxCheckedNewPageY = row - 1; 0231 } 0232 return; 0233 } 0234 ++row; 0235 y += m_pSheet->rowFormats()->rowHeight(row); 0236 } 0237 } 0238 0239 if (_row > m_maxCheckedNewPageY) { 0240 m_maxCheckedNewPageY = _row; 0241 m_lnewPageListY.last().setEndItem(_row); 0242 } 0243 } 0244 0245 void SheetPrint::Private::calculateZoomForPageLimitX() 0246 { 0247 debugSheets << "Calculating zoom for X limit"; 0248 const int horizontalPageLimit = m_settings->pageLimits().width(); 0249 if (horizontalPageLimit == 0) 0250 return; 0251 0252 const double origZoom = m_settings->zoom(); 0253 0254 if (m_settings->zoom() < 1.0) { 0255 q->updateHorizontalPageParameters(0); // clear all parameters 0256 m_settings->setZoom(1.0); 0257 } 0258 0259 QRect printRange = m_pSheet->usedArea(true); 0260 calculateHorizontalPageParameters(printRange.right()); 0261 int currentPages = m_lnewPageListX.count(); 0262 0263 if (currentPages <= horizontalPageLimit) 0264 return; 0265 0266 //calculating a factor for scaling the zoom down makes it lots faster 0267 double factor = (double)horizontalPageLimit / (double)currentPages + 0268 1 - (double)currentPages / ((double)currentPages + 1); //add possible error; 0269 debugSheets << "Calculated factor for scaling m_settings->zoom():" << factor; 0270 m_settings->setZoom(m_settings->zoom()*factor); 0271 0272 debugSheets << "New exact zoom:" << m_settings->zoom(); 0273 0274 if (m_settings->zoom() < 0.01) 0275 m_settings->setZoom(0.01); 0276 if (m_settings->zoom() > 1.0) 0277 m_settings->setZoom(1.0); 0278 0279 m_settings->setZoom((((int)(m_settings->zoom()*100 + 0.5)) / 100.0)); 0280 0281 debugSheets << "New rounded zoom:" << m_settings->zoom(); 0282 0283 q->updateHorizontalPageParameters(0); // clear all parameters 0284 calculateHorizontalPageParameters(printRange.right()); 0285 currentPages = m_lnewPageListX.count(); 0286 0287 debugSheets << "Number of pages with this zoom:" << currentPages; 0288 0289 while ((currentPages > horizontalPageLimit) && (m_settings->zoom() > 0.01)) { 0290 m_settings->setZoom(m_settings->zoom() - 0.01); 0291 q->updateHorizontalPageParameters(0); // clear all parameters 0292 calculateHorizontalPageParameters(printRange.right()); 0293 currentPages = m_lnewPageListX.count(); 0294 debugSheets << "Looping -0.01; current zoom:" << m_settings->zoom(); 0295 } 0296 0297 if (m_settings->zoom() < origZoom) { 0298 // Trigger an update of the vertical page parameters. 0299 q->updateVerticalPageParameters(0); // clear all parameters 0300 calculateVerticalPageParameters(printRange.bottom()); 0301 } else 0302 m_settings->setZoom(origZoom); 0303 } 0304 0305 void SheetPrint::Private::calculateZoomForPageLimitY() 0306 { 0307 debugSheets << "Calculating zoom for Y limit"; 0308 const int verticalPageLimit = m_settings->pageLimits().height(); 0309 if (verticalPageLimit == 0) 0310 return; 0311 0312 const double origZoom = m_settings->zoom(); 0313 0314 if (m_settings->zoom() < 1.0) { 0315 q->updateVerticalPageParameters(0); // clear all parameters 0316 m_settings->setZoom(1.0); 0317 } 0318 0319 QRect printRange = m_pSheet->usedArea(true); 0320 calculateVerticalPageParameters(printRange.bottom()); 0321 int currentPages = m_lnewPageListY.count(); 0322 0323 if (currentPages <= verticalPageLimit) 0324 return; 0325 0326 double factor = (double)verticalPageLimit / (double)currentPages + 0327 1 - (double)currentPages / ((double)currentPages + 1); //add possible error 0328 debugSheets << "Calculated factor for scaling m_settings->zoom():" << factor; 0329 m_settings->setZoom(m_settings->zoom()*factor); 0330 0331 debugSheets << "New exact zoom:" << m_settings->zoom(); 0332 0333 if (m_settings->zoom() < 0.01) 0334 m_settings->setZoom(0.01); 0335 if (m_settings->zoom() > 1.0) 0336 m_settings->setZoom(1.0); 0337 0338 m_settings->setZoom((((int)(m_settings->zoom()*100 + 0.5)) / 100.0)); 0339 0340 debugSheets << "New rounded zoom:" << m_settings->zoom(); 0341 0342 q->updateVerticalPageParameters(0); // clear all parameters 0343 calculateVerticalPageParameters(printRange.bottom()); 0344 currentPages = m_lnewPageListY.count(); 0345 0346 debugSheets << "Number of pages with this zoom:" << currentPages; 0347 0348 while ((currentPages > verticalPageLimit) && (m_settings->zoom() > 0.01)) { 0349 m_settings->setZoom(m_settings->zoom() - 0.01); 0350 q->updateVerticalPageParameters(0); // clear all parameters 0351 calculateVerticalPageParameters(printRange.bottom()); 0352 currentPages = m_lnewPageListY.count(); 0353 debugSheets << "Looping -0.01; current zoom:" << m_settings->zoom(); 0354 } 0355 0356 if (m_settings->zoom() < origZoom) { 0357 // Trigger an update of the horizontal page parameters. 0358 q->updateHorizontalPageParameters(0); // clear all parameters 0359 calculateHorizontalPageParameters(printRange.right()); 0360 } else 0361 m_settings->setZoom(origZoom); 0362 } 0363 0364 void SheetPrint::Private::updateRepeatedColumnsWidth() 0365 { 0366 m_dPrintRepeatColumnsWidth = 0.0; 0367 const QPair<int, int> repeatedColumns = m_settings->repeatedColumns(); 0368 if (repeatedColumns.first != 0) { 0369 for (int i = repeatedColumns.first; i <= repeatedColumns.second; i++) { 0370 m_dPrintRepeatColumnsWidth += m_pSheet->columnFormat(i)->width(); 0371 } 0372 } 0373 } 0374 0375 void SheetPrint::Private::updateRepeatedRowsHeight() 0376 { 0377 m_dPrintRepeatRowsHeight = 0.0; 0378 const QPair<int, int> repeatedRows = m_settings->repeatedRows(); 0379 if (repeatedRows.first != 0) { 0380 m_dPrintRepeatRowsHeight += m_pSheet->rowFormats()->totalRowHeight(repeatedRows.first, repeatedRows.second); 0381 } 0382 } 0383 0384 bool PrintNewPageEntry::operator==(PrintNewPageEntry const & entry) const 0385 { 0386 return m_iStartItem == entry.m_iStartItem; 0387 }