1
/* This file is part of the KDE project
2
Copyright 2007, 2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
3
Copyright 2005 Raphael Langerhorst <raphael.langerhorst@kdemail.net>
4
Copyright 2003 Philipp Müller <philipp.mueller@gmx.de>
5
Copyright 1998, 1999 Torben Weis <weis@kde.org>
7
This library is free software; you can redistribute it and/or
8
modify it under the terms of the GNU Library General Public
9
License as published by the Free Software Foundation; either
10
version 2 of the License, or (at your option) any later version.
12
This library is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
Library General Public License for more details.
17
You should have received a copy of the GNU Library General Public License
18
along with this library; see the file COPYING.LIB. If not, write to
19
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
Boston, MA 02110-1301, USA.
23
#include "SheetPrint.h"
24
#include "SheetPrint_p.h"
26
#include "PrintSettings.h"
28
#include "RowColumnFormat.h"
31
using namespace KSpread;
33
void SheetPrint::Private::calculateHorizontalPageParameters(int _column)
35
// Zoom the print width ONCE here, instead for each column width.
36
const double printWidth = m_settings->printWidth() / m_settings->zoom();
40
//Are these the edges of the print range?
41
const QRect printRange = m_settings->printRegion().lastRange();
43
if (_column == printRange.left() || _column == printRange.right()) {
44
if (_column > m_maxCheckedNewPageX)
45
m_maxCheckedNewPageX = _column;
49
//We don't check beyond the print range
50
if (_column < printRange.left() || _column > printRange.right()) {
51
if (_column > m_maxCheckedNewPageX)
52
m_maxCheckedNewPageX = _column;
53
if (_column > printRange.right()) {
54
if (m_lnewPageListX.last().endItem() == 0)
55
m_lnewPageListX.last().setEndItem(printRange.right());
61
// Check if the pre-calculated width matches the repeated columns setting.
62
const bool repetitions = m_settings->repeatedColumns().first != 0;
63
if (repetitions != (m_dPrintRepeatColumnsWidth == 0.0)) {
64
// Existing column repetitions, but their pre-calculated width is zero?
65
// Must be the first run. Or the other way around? Seem to be orphaned.
66
// Either way, seems they do not match. Calculate them!
67
updateRepeatedColumnsWidth();
70
// The end of the last item (zero, if list is empty).
71
const int end = m_lnewPageListX.empty() ? 0 : m_lnewPageListX.last().endItem();
73
//If _column is greater than the last entry, we need to calculate the result
75
_column > m_maxCheckedNewPageX) { //this columns hasn't been calculated before
76
int startCol = end + 1;
78
double x = m_pSheet->columnFormat(col)->width();
81
m_lnewPageListX.append(PrintNewPageEntry(startCol));
83
//Add repeated column width, when necessary
84
const QPair<int, int> repeatedColumns = m_settings->repeatedColumns();
85
if (col > repeatedColumns.first) {
86
x += m_dPrintRepeatColumnsWidth;
87
offset = m_dPrintRepeatColumnsWidth;
89
kDebug() << "startCol:" << startCol << "col:" << col << "x:" << x
90
<< "offset:" << offset << repeatedColumns;
92
while ((col <= _column) && (col < printRange.right())) {
93
kDebug() << "loop:" << "startCol:" << startCol << "col:" << col
94
<< "x:" << x << "offset:" << offset;
96
if (x > printWidth || m_pSheet->columnFormat(col)->hasPageBreak()) {
97
//Now store into the previous entry the enditem and the width
98
m_lnewPageListX.last().setEndItem(col - 1);
99
m_lnewPageListX.last().setSize(x - m_pSheet->columnFormat(col)->width());
100
m_lnewPageListX.last().setOffset(offset);
103
m_lnewPageListX.append(PrintNewPageEntry(col));
105
x = m_pSheet->columnFormat(col)->width();
106
if (col >= repeatedColumns.first) {
107
kDebug() << "col >= repeatedColumns.first:" << col << repeatedColumns.first;
108
x += m_dPrintRepeatColumnsWidth;
109
offset = m_dPrintRepeatColumnsWidth;
113
x += m_pSheet->columnFormat(col)->width();
116
// Iterate to the end of the page.
117
while (m_lnewPageListX.last().endItem() == 0) {
118
kDebug() << "loop to end" << "col:" << col << "x:" << x << "offset:" << offset
119
<< "m_maxCheckedNewPageX:" << m_maxCheckedNewPageX;
120
if (x > printWidth || m_pSheet->columnFormat(col)->hasPageBreak()) {
121
// Now store into the previous entry the enditem and the width
122
m_lnewPageListX.last().setEndItem(col - 1);
123
m_lnewPageListX.last().setSize(x - m_pSheet->columnFormat(col)->width());
124
m_lnewPageListX.last().setOffset(offset);
126
if (col - 1 > m_maxCheckedNewPageX) {
127
m_maxCheckedNewPageX = col - 1;
132
x += m_pSheet->columnFormat(col)->width();
136
kDebug() << "m_maxCheckedNewPageX:" << m_maxCheckedNewPageX;
137
if (_column > m_maxCheckedNewPageX) {
138
m_maxCheckedNewPageX = _column;
139
m_lnewPageListX.last().setEndItem(_column);
143
void SheetPrint::Private::calculateVerticalPageParameters(int _row)
145
// Zoom the print height ONCE here, instead for each row height.
146
const double printHeight = m_settings->printHeight() / m_settings->zoom();
150
//Are these the edges of the print range?
151
const QRect printRange = m_settings->printRegion().lastRange();
153
if (_row == printRange.top() || _row == printRange.bottom()) {
154
if (_row > m_maxCheckedNewPageY)
155
m_maxCheckedNewPageY = _row;
159
//beyond the print range it's always false
160
if (_row < printRange.top() || _row > printRange.bottom()) {
161
if (_row > m_maxCheckedNewPageY)
162
m_maxCheckedNewPageY = _row;
163
if (_row > printRange.bottom()) {
164
if (m_lnewPageListY.last().endItem() == 0)
165
m_lnewPageListY.last().setEndItem(printRange.bottom());
171
// Check if the pre-calculated height matches the repeated rows setting.
172
const bool repetitions = m_settings->repeatedRows().first != 0;
173
if (repetitions != (m_dPrintRepeatRowsHeight == 0.0)) {
174
// Existing row repetitions, but their pre-calculated height is zero?
175
// Must be the first run. Or the other way around? Seem to be orphaned.
176
// Either way, seems they do not match. Calculate them!
177
updateRepeatedRowsHeight();
180
// The end of the last item (zero, if list is empty).
181
const int end = m_lnewPageListY.empty() ? 0 : m_lnewPageListY.last().endItem();
183
//If _column is greater than the last entry, we need to calculate the result
185
_row > m_maxCheckedNewPageY) { //this columns hasn't been calculated before
186
int startRow = end + 1;
188
double y = m_pSheet->rowFormat(row)->height();
191
m_lnewPageListY.append(PrintNewPageEntry(startRow));
193
//Add repeated row height, when necessary
194
const QPair<int, int> repeatedRows = m_settings->repeatedRows();
195
if (row > repeatedRows.first) {
196
y += m_dPrintRepeatRowsHeight;
197
offset = m_dPrintRepeatRowsHeight;
200
while ((row <= _row) && (row < printRange.bottom())) {
202
if (y > printHeight || m_pSheet->rowFormat(row)->hasPageBreak()) {
203
//Now store into the previous entry the enditem and the width
204
m_lnewPageListY.last().setEndItem(row - 1);
205
m_lnewPageListY.last().setSize(y - m_pSheet->rowFormat(row)->height());
206
m_lnewPageListY.last().setOffset(offset);
209
m_lnewPageListY.append(PrintNewPageEntry(row));
211
y = m_pSheet->rowFormat(row)->height();
212
if (row >= repeatedRows.first) {
213
y += m_dPrintRepeatRowsHeight;
214
offset = m_dPrintRepeatRowsHeight;
218
y += m_pSheet->rowFormat(row)->height();
221
// Iterate to the end of the page.
222
while (m_lnewPageListY.last().endItem() == 0) {
223
if (y > printHeight || m_pSheet->rowFormat(row)->hasPageBreak()) {
224
// Now store into the previous entry the enditem and the width
225
m_lnewPageListY.last().setEndItem(row - 1);
226
m_lnewPageListY.last().setSize(y - m_pSheet->rowFormat(row)->height());
227
m_lnewPageListY.last().setOffset(offset);
229
if (row - 1 > m_maxCheckedNewPageY) {
230
m_maxCheckedNewPageY = row - 1;
235
y += m_pSheet->rowFormat(row)->height();
239
if (_row > m_maxCheckedNewPageY) {
240
m_maxCheckedNewPageY = _row;
241
m_lnewPageListY.last().setEndItem(_row);
245
void SheetPrint::Private::calculateZoomForPageLimitX()
247
kDebug() << "Calculating zoom for X limit";
248
const int horizontalPageLimit = m_settings->pageLimits().width();
249
if (horizontalPageLimit == 0)
252
const double origZoom = m_settings->zoom();
254
if (m_settings->zoom() < 1.0) {
255
q->updateHorizontalPageParameters(0); // clear all parameters
256
m_settings->setZoom(1.0);
259
QRect printRange = m_pSheet->usedArea(true);
260
calculateHorizontalPageParameters(printRange.right());
261
int currentPages = m_lnewPageListX.count();
263
if (currentPages <= horizontalPageLimit)
266
//calculating a factor for scaling the zoom down makes it lots faster
267
double factor = (double)horizontalPageLimit / (double)currentPages +
268
1 - (double)currentPages / ((double)currentPages + 1); //add possible error;
269
kDebug() << "Calculated factor for scaling m_settings->zoom():" << factor;
270
m_settings->setZoom(m_settings->zoom()*factor);
272
kDebug() << "New exact zoom:" << m_settings->zoom();
274
if (m_settings->zoom() < 0.01)
275
m_settings->setZoom(0.01);
276
if (m_settings->zoom() > 1.0)
277
m_settings->setZoom(1.0);
279
m_settings->setZoom((((int)(m_settings->zoom()*100 + 0.5)) / 100.0));
281
kDebug() << "New rounded zoom:" << m_settings->zoom();
283
q->updateHorizontalPageParameters(0); // clear all parameters
284
calculateHorizontalPageParameters(printRange.right());
285
currentPages = m_lnewPageListX.count();
287
kDebug() << "Number of pages with this zoom:" << currentPages;
289
while ((currentPages > horizontalPageLimit) && (m_settings->zoom() > 0.01)) {
290
m_settings->setZoom(m_settings->zoom() - 0.01);
291
q->updateHorizontalPageParameters(0); // clear all parameters
292
calculateHorizontalPageParameters(printRange.right());
293
currentPages = m_lnewPageListX.count();
294
kDebug() << "Looping -0.01; current zoom:" << m_settings->zoom();
297
if (m_settings->zoom() < origZoom) {
298
// Trigger an update of the vertical page parameters.
299
q->updateVerticalPageParameters(0); // clear all parameters
300
calculateVerticalPageParameters(printRange.bottom());
302
m_settings->setZoom(origZoom);
305
void SheetPrint::Private::calculateZoomForPageLimitY()
307
kDebug() << "Calculating zoom for Y limit";
308
const int verticalPageLimit = m_settings->pageLimits().height();
309
if (verticalPageLimit == 0)
312
const double origZoom = m_settings->zoom();
314
if (m_settings->zoom() < 1.0) {
315
q->updateVerticalPageParameters(0); // clear all parameters
316
m_settings->setZoom(1.0);
319
QRect printRange = m_pSheet->usedArea(true);
320
calculateVerticalPageParameters(printRange.bottom());
321
int currentPages = m_lnewPageListY.count();
323
if (currentPages <= verticalPageLimit)
326
double factor = (double)verticalPageLimit / (double)currentPages +
327
1 - (double)currentPages / ((double)currentPages + 1); //add possible error
328
kDebug() << "Calculated factor for scaling m_settings->zoom():" << factor;
329
m_settings->setZoom(m_settings->zoom()*factor);
331
kDebug() << "New exact zoom:" << m_settings->zoom();
333
if (m_settings->zoom() < 0.01)
334
m_settings->setZoom(0.01);
335
if (m_settings->zoom() > 1.0)
336
m_settings->setZoom(1.0);
338
m_settings->setZoom((((int)(m_settings->zoom()*100 + 0.5)) / 100.0));
340
kDebug() << "New rounded zoom:" << m_settings->zoom();
342
q->updateVerticalPageParameters(0); // clear all parameters
343
calculateVerticalPageParameters(printRange.bottom());
344
currentPages = m_lnewPageListY.count();
346
kDebug() << "Number of pages with this zoom:" << currentPages;
348
while ((currentPages > verticalPageLimit) && (m_settings->zoom() > 0.01)) {
349
m_settings->setZoom(m_settings->zoom() - 0.01);
350
q->updateVerticalPageParameters(0); // clear all parameters
351
calculateVerticalPageParameters(printRange.bottom());
352
currentPages = m_lnewPageListY.count();
353
kDebug() << "Looping -0.01; current zoom:" << m_settings->zoom();
356
if (m_settings->zoom() < origZoom) {
357
// Trigger an update of the horizontal page parameters.
358
q->updateHorizontalPageParameters(0); // clear all parameters
359
calculateHorizontalPageParameters(printRange.right());
361
m_settings->setZoom(origZoom);
364
void SheetPrint::Private::updateRepeatedColumnsWidth()
366
m_dPrintRepeatColumnsWidth = 0.0;
367
const QPair<int, int> repeatedColumns = m_settings->repeatedColumns();
368
if (repeatedColumns.first != 0) {
369
for (int i = repeatedColumns.first; i <= repeatedColumns.second; i++) {
370
m_dPrintRepeatColumnsWidth += m_pSheet->columnFormat(i)->width();
375
void SheetPrint::Private::updateRepeatedRowsHeight()
377
m_dPrintRepeatRowsHeight = 0.0;
378
const QPair<int, int> repeatedRows = m_settings->repeatedRows();
379
if (repeatedRows.first != 0) {
380
for (int i = repeatedRows.first; i <= repeatedRows.second; i++) {
381
m_dPrintRepeatRowsHeight += m_pSheet->rowFormat(i)->height();
386
bool PrintNewPageEntry::operator==(PrintNewPageEntry const & entry) const
388
return m_iStartItem == entry.m_iStartItem;