File indexing completed on 2024-05-12 16:37:11
0001 /* This file is part of the Calligra project 0002 * Copyright (C) 2005, 2007-2008, 2010 Thomas Zander <zander@kde.org> 0003 * Copyright (C) 2008 Pierre Ducroquet <pinaraf@pinaraf.info> 0004 * Copyright (C) 2005, 2007-2008, 2011 Sebastian Sauer <mail@dipe.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KWPage.h" 0023 #include "KWPageManager_p.h" 0024 #include <KoShapeManager.h> 0025 #include <KoZoomHandler.h> 0026 #include <KoShape.h> 0027 #include <QPainter> 0028 0029 #include <WordsDebug.h> 0030 0031 void KWPage::setVisiblePageNumber(int pageNumber) 0032 { 0033 if (isValid()) 0034 priv->setVisiblePageNumber(n, pageNumber); 0035 } 0036 0037 bool KWPage::isValid() const 0038 { 0039 return priv && priv->pages.contains(n); 0040 } 0041 0042 int KWPage::pageNumber() const 0043 { 0044 if (! isValid()) 0045 return -1; // invalid 0046 return priv->pages[n].pageNumber; 0047 } 0048 0049 KWPageStyle KWPage::pageStyle() const 0050 { 0051 if (! isValid()) 0052 return KWPageStyle(); // invalid 0053 0054 return priv->pages[n].style; 0055 } 0056 0057 void KWPage::setPageStyle(const KWPageStyle style) 0058 { 0059 if (! isValid()) 0060 return; 0061 if (! style.isValid()) { 0062 warnWords << "Passing invalid style to KWPage::setPageStyle()"; 0063 return; 0064 } 0065 if (! priv->pageStyles.contains(style.name())) 0066 priv->pageStyles.insert(style.name(), style); 0067 0068 KWPageManagerPrivate::Page page = priv->pages[n]; 0069 page.style = style; 0070 priv->pages.insert(n, page); 0071 } 0072 0073 void KWPage::setPageSide(PageSide ps) 0074 { 0075 if (! isValid()) 0076 return; 0077 KWPageManagerPrivate::Page page = priv->pages[n]; 0078 0079 if (page.pageSide == ps) 0080 return; 0081 0082 page.pageSide = ps; 0083 priv->pages.insert(n, page); 0084 } 0085 0086 KWPage::PageSide KWPage::pageSide() const 0087 { 0088 if (! isValid()) 0089 return KWPage::Left; // invalid 0090 0091 return priv->pages[n].pageSide; 0092 } 0093 0094 bool KWPage::operator==(const KWPage &other) const 0095 { 0096 return other.n == n && other.priv == priv; 0097 } 0098 0099 uint KWPage::hash() const 0100 { 0101 return n + qHash(priv); 0102 } 0103 0104 qreal KWPage::width() const 0105 { 0106 if (! isValid()) 0107 return 0; 0108 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0109 return page.style.pageLayout().width; 0110 } 0111 0112 qreal KWPage::height() const 0113 { 0114 if (! isValid()) 0115 return 0; 0116 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0117 return page.style.pageLayout().height; 0118 } 0119 0120 qreal KWPage::topMargin() const 0121 { 0122 if (! isValid()) 0123 return 0; 0124 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0125 return page.style.pageLayout().topMargin; 0126 } 0127 0128 qreal KWPage::bottomMargin() const 0129 { 0130 if (! isValid()) 0131 return 0; 0132 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0133 return page.style.pageLayout().bottomMargin; 0134 } 0135 0136 qreal KWPage::leftMargin() const 0137 { 0138 if (! isValid()) 0139 return 0; 0140 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0141 qreal answer = page.pageSide == Left ? pageEdgeMargin() : marginClosestBinding(); 0142 if (answer != -1) 0143 return answer; 0144 return page.style.pageLayout().leftMargin; 0145 } 0146 0147 qreal KWPage::rightMargin() const 0148 { 0149 if (! isValid()) 0150 return 0; 0151 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0152 qreal answer = page.pageSide == Right ? pageEdgeMargin() : marginClosestBinding(); 0153 if (answer != -1) 0154 return answer; 0155 return page.style.pageLayout().rightMargin; 0156 } 0157 0158 qreal KWPage::topPadding() const 0159 { 0160 if (! isValid()) 0161 return 0; 0162 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0163 return page.style.pageLayout().topPadding; 0164 } 0165 0166 qreal KWPage::bottomPadding() const 0167 { 0168 if (! isValid()) 0169 return 0; 0170 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0171 return page.style.pageLayout().bottomPadding; 0172 } 0173 0174 qreal KWPage::leftPadding() const 0175 { 0176 if (! isValid()) 0177 return 0; 0178 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0179 return page.style.pageLayout().leftPadding; 0180 } 0181 0182 qreal KWPage::rightPadding() const 0183 { 0184 if (! isValid()) 0185 return 0; 0186 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0187 return page.style.pageLayout().rightPadding; 0188 } 0189 0190 qreal KWPage::pageEdgeMargin() const 0191 { 0192 if (! isValid()) 0193 return 0; 0194 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0195 return page.style.pageLayout().pageEdge; 0196 } 0197 0198 qreal KWPage::marginClosestBinding() const 0199 { 0200 if (! isValid()) 0201 return 0; 0202 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0203 return page.style.pageLayout().bindingSide; 0204 } 0205 0206 qreal KWPage::offsetInDocument() const 0207 { 0208 // the y coordinate 0209 return isValid() ? priv->pageOffset(priv->pages[n].pageNumber) : 0.; 0210 } 0211 0212 void KWPage::setOffsetInDocument(qreal offset) 0213 { 0214 priv->setPageOffset(priv->pages[n].pageNumber, offset); 0215 } 0216 0217 QRectF KWPage::rect() const 0218 { 0219 if (! isValid()) 0220 return QRectF(); 0221 return QRectF(0, offsetInDocument(), width(), height()); 0222 } 0223 0224 QRectF KWPage::contentRect() const 0225 { 0226 if (! isValid()) 0227 return QRectF(); 0228 return priv->pages[n].contentRect; 0229 } 0230 0231 void KWPage::setContentRect(const QRectF &rect) 0232 { 0233 if (isValid()) { 0234 priv->pages[n].contentRect = rect; 0235 } 0236 } 0237 0238 KoPageFormat::Orientation KWPage::orientationHint() const 0239 { 0240 if (! isValid()) 0241 return KoPageFormat::Landscape; 0242 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0243 return page.orientation; 0244 } 0245 0246 void KWPage::setOrientationHint(KoPageFormat::Orientation orientation) 0247 { 0248 if (! isValid()) 0249 return; 0250 KWPageManagerPrivate::Page page = priv->pages[n]; 0251 page.orientation = orientation; 0252 priv->pages.insert(n, page); 0253 } 0254 0255 const KWPage KWPage::previous() const 0256 { 0257 if (! isValid()) 0258 return KWPage(); 0259 QMap<int,int>::const_iterator iter = priv->pageNumbers.constFind(pageNumber()); 0260 if (iter == priv->pageNumbers.constBegin()) 0261 return KWPage(); 0262 --iter; 0263 return KWPage(priv, iter.value()); 0264 } 0265 0266 const KWPage KWPage::next() const 0267 { 0268 if (! isValid()) 0269 return KWPage(); 0270 QMap<int,int>::const_iterator iter = priv->pageNumbers.constFind(pageNumber()); 0271 Q_ASSERT(iter != priv->pageNumbers.constEnd()); 0272 ++iter; 0273 if (iter == priv->pageNumbers.constEnd()) 0274 return KWPage(); 0275 return KWPage(priv, iter.value()); 0276 } 0277 0278 void KWPage::setDirectionHint(KoText::Direction direction) 0279 { 0280 if (!isValid()) 0281 return; 0282 KWPageManagerPrivate::Page page = priv->pages[n]; 0283 page.textDirection = direction; 0284 priv->pages.insert(n, page); 0285 } 0286 0287 KoText::Direction KWPage::directionHint() const 0288 { 0289 if (! isValid()) 0290 return KoText::AutoDirection; 0291 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0292 KoText::Direction dir = page.textDirection; 0293 if (dir != KoText::InheritDirection) 0294 return dir; 0295 return page.style.direction(); 0296 } 0297 0298 void KWPage::setAutoGenerated(bool on) 0299 { 0300 if (!isValid()) 0301 return; 0302 KWPageManagerPrivate::Page page = priv->pages[n]; 0303 page.autoGenerated = on; 0304 priv->pages.insert(n, page); 0305 } 0306 0307 bool KWPage::isAutoGenerated() const 0308 { 0309 if (!isValid()) 0310 return false; 0311 const KWPageManagerPrivate::Page &page = priv->pages[n]; 0312 return page.autoGenerated; 0313 } 0314 0315 0316 QImage KWPage::thumbnail(const QSize &size, KoShapeManager *shapeManager, bool asPrint) const 0317 { 0318 KoZoomHandler zoomHandler; 0319 const qreal realWidth = zoomHandler.resolutionX() * width(); 0320 const qreal realHeight = zoomHandler.resolutionX() * height(); 0321 0322 const qreal widthScale = size.width() / realWidth; 0323 const qreal heightScale = size.height() / realHeight; 0324 0325 const qreal zoom = (widthScale > heightScale) ? heightScale : widthScale; 0326 // adapt thumbnailSize to match the rendered page 0327 QSize thumbnailSize(size); 0328 if (widthScale > heightScale) { 0329 const int thumbnailWidth = qMin(thumbnailSize.width(), qRound(realWidth*heightScale)); 0330 thumbnailSize.setWidth(thumbnailWidth); 0331 } else { 0332 const int thumbnailHeight = qMin(thumbnailSize.height(), qRound(realHeight*widthScale)); 0333 thumbnailSize.setHeight(thumbnailHeight); 0334 } 0335 0336 zoomHandler.setZoom(zoom); 0337 0338 foreach(KoShape* shape, shapeManager->shapes()) { 0339 shape->waitUntilReady(zoomHandler, false); 0340 } 0341 0342 QImage img(thumbnailSize, QImage::Format_ARGB32); 0343 // paint white as default page background 0344 img.fill(QColor(Qt::white).rgb()); 0345 QPainter gc(&img); 0346 gc.setRenderHint(QPainter::Antialiasing, true); 0347 gc.translate(0, -zoomHandler.documentToViewY(offsetInDocument())); 0348 gc.setClipRect(zoomHandler.documentToView(rect())); 0349 shapeManager->paint(gc, zoomHandler, asPrint); 0350 gc.end(); 0351 0352 return img; 0353 } 0354 0355 int KWPage::visiblePageNumber(PageSelection select, int adjustment) const 0356 { 0357 KWPage page = *(const_cast<KWPage*>(this)); 0358 switch (select) { 0359 case KoTextPage::CurrentPage: break; 0360 case KoTextPage::PreviousPage: 0361 page = page.previous(); 0362 break; 0363 case KoTextPage::NextPage: 0364 page = page.next(); 0365 break; 0366 } 0367 0368 if (! page.isValid()) 0369 return -1; 0370 0371 int pageNumber = 0; 0372 if (select != KoTextPage::CurrentPage) { 0373 pageNumber = page.visiblePageNumber(); 0374 } else { 0375 int n = page.pageNumber(); 0376 if (priv->visiblePageNumbers.contains(n)) 0377 pageNumber = priv->visiblePageNumbers[n]; 0378 } 0379 0380 if (pageNumber == 0) { 0381 page = page.previous(); 0382 pageNumber = page.isValid() ? qMax(1, page.visiblePageNumber() + 1) : 1; 0383 } 0384 0385 if (adjustment != 0) { 0386 pageNumber += adjustment; 0387 if (page.priv && !page.priv->pageNumbers.contains(pageNumber)) 0388 pageNumber = -1; // doesn't exist. 0389 } 0390 0391 return pageNumber; 0392 } 0393 0394 QString KWPage::masterPageName() const 0395 { 0396 KWPageStyle pagestyle = pageStyle(); 0397 if (pagestyle.isValid()) { 0398 QString name = pagestyle.name(); 0399 if (!name.isEmpty()) 0400 return name; 0401 } 0402 KWPage prevpage = previous(); 0403 while (prevpage.isValid()) { 0404 KWPageStyle prevpagestyle = prevpage.pageStyle(); 0405 if (prevpagestyle.isValid()) { 0406 if (!prevpagestyle.nextStyleName().isEmpty()) 0407 return prevpagestyle.nextStyleName(); 0408 if (!prevpagestyle.name().isEmpty()) 0409 return prevpagestyle.name(); 0410 } 0411 } 0412 return QString(); 0413 }