~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to kspread/SheetPrint_p.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2010-10-27 17:52:57 UTC
  • mfrom: (0.12.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101027175257-s04zqqk5bs8ckm9o
Tags: 1:2.2.83-0ubuntu1
* Merge with Debian git remaining changes:
 - Add build-deps on librcps-dev, opengtl-dev, libqtgtl-dev, freetds-dev,
   create-resources, libspnav-dev
 - Remove needless build-dep on libwv2-dev
 - koffice-libs recommends create-resources
 - krita recommends pstoedit
 - Keep our patches
* New upstream release 2.3 beta 3
  - Remove debian/patches fixed by upstream
  - Update install files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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.
 
21
*/
 
22
 
 
23
#include "SheetPrint.h"
 
24
#include "SheetPrint_p.h"
 
25
 
 
26
#include "PrintSettings.h"
 
27
#include "Region.h"
 
28
#include "RowColumnFormat.h"
 
29
#include "Sheet.h"
 
30
 
 
31
using namespace KSpread;
 
32
 
 
33
void SheetPrint::Private::calculateHorizontalPageParameters(int _column)
 
34
{
 
35
    // Zoom the print width ONCE here, instead for each column width.
 
36
    const double printWidth = m_settings->printWidth() / m_settings->zoom();
 
37
 
 
38
    float offset = 0.0;
 
39
 
 
40
    //Are these the edges of the print range?
 
41
    const QRect printRange = m_settings->printRegion().lastRange();
 
42
#if 0
 
43
    if (_column == printRange.left() || _column == printRange.right()) {
 
44
        if (_column > m_maxCheckedNewPageX)
 
45
            m_maxCheckedNewPageX = _column;
 
46
        return;
 
47
    }
 
48
 
 
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());
 
56
        }
 
57
        return;
 
58
    }
 
59
#endif
 
60
 
 
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();
 
68
    }
 
69
 
 
70
    // The end of the last item (zero, if list is empty).
 
71
    const int end = m_lnewPageListX.empty() ? 0 : m_lnewPageListX.last().endItem();
 
72
 
 
73
    //If _column is greater than the last entry, we need to calculate the result
 
74
    if (_column > end &&
 
75
            _column > m_maxCheckedNewPageX) { //this columns hasn't been calculated before
 
76
        int startCol = end + 1;
 
77
        int col = startCol;
 
78
        double x = m_pSheet->columnFormat(col)->width();
 
79
 
 
80
        // Add a new page.
 
81
        m_lnewPageListX.append(PrintNewPageEntry(startCol));
 
82
 
 
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;
 
88
        }
 
89
        kDebug() << "startCol:" << startCol << "col:" << col << "x:" << x
 
90
                 << "offset:" << offset << repeatedColumns;
 
91
 
 
92
        while ((col <= _column) && (col < printRange.right())) {
 
93
            kDebug() << "loop:" << "startCol:" << startCol << "col:" << col
 
94
                     << "x:" << x << "offset:" << offset;
 
95
            // end of page?
 
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);
 
101
 
 
102
                //start a new page
 
103
                m_lnewPageListX.append(PrintNewPageEntry(col));
 
104
                startCol = 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;
 
110
                }
 
111
            }
 
112
            col++;
 
113
            x += m_pSheet->columnFormat(col)->width();
 
114
        }
 
115
 
 
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);
 
125
 
 
126
                if (col - 1 > m_maxCheckedNewPageX) {
 
127
                    m_maxCheckedNewPageX = col - 1;
 
128
                }
 
129
                return;
 
130
            }
 
131
            ++col;
 
132
            x += m_pSheet->columnFormat(col)->width();
 
133
        }
 
134
    }
 
135
 
 
136
    kDebug() << "m_maxCheckedNewPageX:" << m_maxCheckedNewPageX;
 
137
    if (_column > m_maxCheckedNewPageX) {
 
138
        m_maxCheckedNewPageX = _column;
 
139
        m_lnewPageListX.last().setEndItem(_column);
 
140
    }
 
141
}
 
142
 
 
143
void SheetPrint::Private::calculateVerticalPageParameters(int _row)
 
144
{
 
145
    // Zoom the print height ONCE here, instead for each row height.
 
146
    const double printHeight = m_settings->printHeight() / m_settings->zoom();
 
147
 
 
148
    float offset = 0.0;
 
149
 
 
150
    //Are these the edges of the print range?
 
151
    const QRect printRange = m_settings->printRegion().lastRange();
 
152
#if 0
 
153
    if (_row == printRange.top() || _row == printRange.bottom()) {
 
154
        if (_row > m_maxCheckedNewPageY)
 
155
            m_maxCheckedNewPageY = _row;
 
156
        return;
 
157
    }
 
158
 
 
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());
 
166
        }
 
167
        return;
 
168
    }
 
169
#endif
 
170
 
 
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();
 
178
    }
 
179
 
 
180
    // The end of the last item (zero, if list is empty).
 
181
    const int end = m_lnewPageListY.empty() ? 0 : m_lnewPageListY.last().endItem();
 
182
 
 
183
    //If _column is greater than the last entry, we need to calculate the result
 
184
    if (_row > end &&
 
185
            _row > m_maxCheckedNewPageY) { //this columns hasn't been calculated before
 
186
        int startRow = end + 1;
 
187
        int row = startRow;
 
188
        double y = m_pSheet->rowFormat(row)->height();
 
189
 
 
190
        // Add a new page.
 
191
        m_lnewPageListY.append(PrintNewPageEntry(startRow));
 
192
 
 
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;
 
198
        }
 
199
 
 
200
        while ((row <= _row) && (row < printRange.bottom())) {
 
201
            // end of page?
 
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);
 
207
 
 
208
                //start a new page
 
209
                m_lnewPageListY.append(PrintNewPageEntry(row));
 
210
                startRow = row;
 
211
                y = m_pSheet->rowFormat(row)->height();
 
212
                if (row >= repeatedRows.first) {
 
213
                    y += m_dPrintRepeatRowsHeight;
 
214
                    offset = m_dPrintRepeatRowsHeight;
 
215
                }
 
216
            }
 
217
            row++;
 
218
            y += m_pSheet->rowFormat(row)->height();
 
219
        }
 
220
 
 
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);
 
228
 
 
229
                if (row - 1 > m_maxCheckedNewPageY) {
 
230
                    m_maxCheckedNewPageY = row - 1;
 
231
                }
 
232
                return;
 
233
            }
 
234
            ++row;
 
235
            y += m_pSheet->rowFormat(row)->height();
 
236
        }
 
237
    }
 
238
 
 
239
    if (_row > m_maxCheckedNewPageY) {
 
240
        m_maxCheckedNewPageY = _row;
 
241
        m_lnewPageListY.last().setEndItem(_row);
 
242
    }
 
243
}
 
244
 
 
245
void SheetPrint::Private::calculateZoomForPageLimitX()
 
246
{
 
247
    kDebug() << "Calculating zoom for X limit";
 
248
    const int horizontalPageLimit = m_settings->pageLimits().width();
 
249
    if (horizontalPageLimit == 0)
 
250
        return;
 
251
 
 
252
    const double origZoom = m_settings->zoom();
 
253
 
 
254
    if (m_settings->zoom() < 1.0) {
 
255
        q->updateHorizontalPageParameters(0);   // clear all parameters
 
256
        m_settings->setZoom(1.0);
 
257
    }
 
258
 
 
259
    QRect printRange = m_pSheet->usedArea(true);
 
260
    calculateHorizontalPageParameters(printRange.right());
 
261
    int currentPages = m_lnewPageListX.count();
 
262
 
 
263
    if (currentPages <= horizontalPageLimit)
 
264
        return;
 
265
 
 
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);
 
271
 
 
272
    kDebug() << "New exact zoom:" << m_settings->zoom();
 
273
 
 
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);
 
278
 
 
279
    m_settings->setZoom((((int)(m_settings->zoom()*100 + 0.5)) / 100.0));
 
280
 
 
281
    kDebug() << "New rounded zoom:" << m_settings->zoom();
 
282
 
 
283
    q->updateHorizontalPageParameters(0);   // clear all parameters
 
284
    calculateHorizontalPageParameters(printRange.right());
 
285
    currentPages = m_lnewPageListX.count();
 
286
 
 
287
    kDebug() << "Number of pages with this zoom:" << currentPages;
 
288
 
 
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();
 
295
    }
 
296
 
 
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());
 
301
    } else
 
302
        m_settings->setZoom(origZoom);
 
303
}
 
304
 
 
305
void SheetPrint::Private::calculateZoomForPageLimitY()
 
306
{
 
307
    kDebug() << "Calculating zoom for Y limit";
 
308
    const int verticalPageLimit = m_settings->pageLimits().height();
 
309
    if (verticalPageLimit == 0)
 
310
        return;
 
311
 
 
312
    const double origZoom = m_settings->zoom();
 
313
 
 
314
    if (m_settings->zoom() < 1.0) {
 
315
        q->updateVerticalPageParameters(0);   // clear all parameters
 
316
        m_settings->setZoom(1.0);
 
317
    }
 
318
 
 
319
    QRect printRange = m_pSheet->usedArea(true);
 
320
    calculateVerticalPageParameters(printRange.bottom());
 
321
    int currentPages = m_lnewPageListY.count();
 
322
 
 
323
    if (currentPages <= verticalPageLimit)
 
324
        return;
 
325
 
 
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);
 
330
 
 
331
    kDebug() << "New exact zoom:" << m_settings->zoom();
 
332
 
 
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);
 
337
 
 
338
    m_settings->setZoom((((int)(m_settings->zoom()*100 + 0.5)) / 100.0));
 
339
 
 
340
    kDebug() << "New rounded zoom:" << m_settings->zoom();
 
341
 
 
342
    q->updateVerticalPageParameters(0);   // clear all parameters
 
343
    calculateVerticalPageParameters(printRange.bottom());
 
344
    currentPages = m_lnewPageListY.count();
 
345
 
 
346
    kDebug() << "Number of pages with this zoom:" << currentPages;
 
347
 
 
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();
 
354
    }
 
355
 
 
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());
 
360
    } else
 
361
        m_settings->setZoom(origZoom);
 
362
}
 
363
 
 
364
void SheetPrint::Private::updateRepeatedColumnsWidth()
 
365
{
 
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();
 
371
        }
 
372
    }
 
373
}
 
374
 
 
375
void SheetPrint::Private::updateRepeatedRowsHeight()
 
376
{
 
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();
 
382
        }
 
383
    }
 
384
}
 
385
 
 
386
bool PrintNewPageEntry::operator==(PrintNewPageEntry const & entry) const
 
387
{
 
388
    return m_iStartItem == entry.m_iStartItem;
 
389
}