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 }