File indexing completed on 2024-05-19 16:09:59

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2010-2012 C. Boemann <cbo@boemann.dk>
0003  * Copyright (C) 2006,2011 Sebastian Sauer <mail@dipe.org>
0004  * Copyright (C) 2006-2007, 2010 Thomas Zander <zander@kde.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 "KWRootAreaProviderTextBox.h"
0023 #include "KWRootAreaProvider.h"
0024 #include "KWPageManager.h"
0025 #include "KWDocument.h"
0026 #include "frames/KWTextFrameSet.h"
0027 #include "frames/KWCopyShape.h"
0028 #include "frames/KWFrameLayout.h"
0029 
0030 #include <KoTextLayoutRootArea.h>
0031 #include <KoShape.h>
0032 #include <KoShapeContainer.h>
0033 #include <KoTextShapeData.h>
0034 #include <KoTextDocumentLayout.h>
0035 
0036 #include <WordsDebug.h>
0037 
0038 KWRootAreaProviderTextBox::KWRootAreaProviderTextBox(KWTextFrameSet *textFrameSet)
0039     : KWRootAreaProviderBase(textFrameSet)
0040 {
0041 }
0042 
0043 KWRootAreaProviderTextBox::~KWRootAreaProviderTextBox()
0044 {
0045     //FIXME : this code crashes so far, why ?
0046     /*foreach (QList<KoTextLayoutRootArea*> areaList, m_rootAreaCache.values())
0047         qDeleteAll(areaList);*/
0048     m_rootAreaCache.clear();
0049 }
0050 
0051 void KWRootAreaProviderTextBox::clearPages(int /*pageNumber*/)
0052 {
0053     KoTextDocumentLayout *lay = dynamic_cast<KoTextDocumentLayout*>(frameSet()->document()->documentLayout());
0054     Q_ASSERT(lay);
0055     foreach(KoTextLayoutRootArea *area, m_rootAreaCache) {
0056         releaseAllAfter(area);
0057         lay->removeRootArea(area);
0058     }
0059 }
0060 
0061 void KWRootAreaProviderTextBox::setPageDirty(int /*pageNumber*/)
0062 {
0063     foreach(KoTextLayoutRootArea *rootArea, m_rootAreaCache) {
0064         rootArea->setDirty(); // be sure the root-areas are relayouted
0065     }
0066 }
0067 
0068 
0069 KoTextLayoutRootArea *KWRootAreaProviderTextBox::provide(KoTextDocumentLayout *documentLayout, const RootAreaConstraint &, int requestedPosition, bool *isNewArea)
0070 {
0071     KWPageManager *pageManager = frameSet()->wordsDocument()->pageManager();
0072     Q_ASSERT(pageManager);
0073     if (pageManager->pageCount() == 0) { // not ready yet (may happen e.g. on loading a document)
0074         return 0;
0075     }
0076 
0077     if (m_rootAreaCache.size() > requestedPosition)
0078     {
0079         KoTextLayoutRootArea *rootArea = m_rootAreaCache[requestedPosition];
0080         Q_ASSERT(rootArea);
0081 
0082         // No constraints except for the main frame set
0083         *isNewArea = false;
0084         return rootArea;
0085     }
0086 
0087     if (!documentLayout->referencedLayout()) {
0088         KoTextDocumentLayout *reflay = dynamic_cast<KoTextDocumentLayout*>(frameSet()->wordsDocument()->frameLayout()->mainFrameSet()->document()->documentLayout());
0089         documentLayout->setReferencedLayout(reflay);
0090     }
0091 
0092     if (frameSet()->shapeCount() > requestedPosition) {
0093         KoShape *shape = frameSet()->shapes()[requestedPosition];
0094         Q_ASSERT(shape);
0095 
0096         KoTextLayoutRootArea *area = new KoTextLayoutRootArea(documentLayout);
0097         m_rootAreaCache.append(area);
0098         Q_ASSERT(m_rootAreaCache.size() > requestedPosition);
0099 
0100         KoTextShapeData *data = qobject_cast<KoTextShapeData*>(shape->userData());
0101         if (data) {
0102             data->setRootArea(area);
0103             area->setAssociatedShape(shape);
0104         } else {
0105             warnWords << "shape has no KoTextShapeData";
0106         }
0107 
0108         if ((!shape->anchor()) || shape->anchor()->anchorType() == KoShapeAnchor::AnchorPage) {
0109             KWPage *page = new KWPage(pageManager->page(shape));
0110             area->setPage(page);
0111         }
0112 
0113 
0114         area->setLayoutEnvironmentResctictions(true, true);
0115 
0116         *isNewArea = true;
0117         return area;
0118     }
0119 
0120     *isNewArea = true;
0121 
0122     return 0;
0123 }
0124 
0125 // afterThis==nullptr means delete everything
0126 void KWRootAreaProviderTextBox::releaseAllAfter(KoTextLayoutRootArea *afterThis)
0127 {
0128     while (m_rootAreaCache.count() != 0 && m_rootAreaCache.back() != afterThis){
0129         m_rootAreaCache.removeLast();
0130     }
0131 }
0132 
0133 void KWRootAreaProviderTextBox::doPostLayout(KoTextLayoutRootArea *rootArea, bool isNewRootArea)
0134 {
0135     KWDocument *kwdoc = const_cast<KWDocument*>(frameSet()->wordsDocument());
0136     KWPageManager *pageManager = kwdoc->pageManager();
0137     Q_ASSERT(pageManager);
0138 
0139     KoShape *shape = rootArea->associatedShape();
0140     if (!shape) {
0141         return;
0142     }
0143 
0144     KWPage page = pageManager->page(shape);
0145     Q_ASSERT(page.isValid());
0146 
0147     if (false){//FIXME m_pages.count() > pageManager->pageCount()) {
0148         // we need to wait for the mainFrameSet to finish till we are able to continue
0149         KWRootAreaProvider *provider = (KWRootAreaProvider *)kwdoc->frameLayout()->mainFrameSet()->rootAreaProvider();
0150         provider->addDependentProvider(this, page.pageNumber());
0151     }
0152 
0153 
0154     KoTextShapeData *data = qobject_cast<KoTextShapeData*>(shape->userData());
0155     Q_ASSERT(data);
0156 
0157     debugWords << "pageNumber=" << page.pageNumber() << "frameSetType=" << "isNewRootArea=" << isNewRootArea << "rootArea=" << rootArea << "isDirty=" << rootArea->isDirty();
0158 
0159     QRectF updateRect = shape->outlineRect();
0160 
0161     QSizeF newSize = shape->size()
0162                     - QSizeF(data->leftPadding() + data->rightPadding(),
0163                              data->topPadding() + data->bottomPadding());
0164 
0165     KoBorder *border = shape->border();
0166 
0167     if (border) {
0168         newSize -= QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder));
0169     }
0170 
0171     if (data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight
0172         ||data->resizeMethod() == KoTextShapeData::AutoGrowWidth) {
0173         newSize.setWidth(rootArea->right() - rootArea->left());
0174     }
0175 
0176     newSize += QSizeF(data->leftPadding() + data->rightPadding(),
0177                       data->topPadding() + data->bottomPadding());
0178     if (border) {
0179         newSize += QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder));
0180     }
0181 
0182     if (newSize != rootArea->associatedShape()->size()) {
0183         rootArea->associatedShape()->setSize(newSize);
0184 
0185         // transfer the new size to the copy-shapes
0186         foreach(KWCopyShape *cs, frameSet()->copyShapes()) {
0187             cs->setSize(newSize);
0188         }
0189     }
0190 
0191     updateRect |= rootArea->associatedShape()->outlineRect();
0192     rootArea->associatedShape()->update(updateRect);
0193 }
0194 
0195 QRectF KWRootAreaProviderTextBox::suggestRect(KoTextLayoutRootArea *rootArea)
0196 {
0197     KoShape *shape = rootArea->associatedShape();
0198     if (!shape) { // no shape => nothing to draw => no space needed
0199         return QRectF(0., 0., 0.,0.);
0200     }
0201 
0202     QRectF rect = KWRootAreaProviderBase::suggestRect(rootArea);
0203 
0204     if (frameSet()->shapes().back() == shape) {
0205         rect.setHeight(1E6);
0206     }
0207 
0208     return rect;
0209 }
0210