File indexing completed on 2024-05-12 16:37:13
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2010-2015 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 "KWRootAreaProvider.h" 0023 #include "KWPageManager.h" 0024 #include "KWDocument.h" 0025 #include "KWView.h" 0026 #include "KWPage.h" 0027 #include "frames/KWCopyShape.h" 0028 #include "frames/KWTextFrameSet.h" 0029 #include "frames/KWFrameLayout.h" 0030 0031 #include <KoTextLayoutRootArea.h> 0032 #include <KoShape.h> 0033 #include <KoShapeContainer.h> 0034 #include <KoShapeFactoryBase.h> 0035 #include <KoTextShapeData.h> 0036 #include <KoTextDocumentLayout.h> 0037 #include <KoTextLayoutObstruction.h> 0038 #include <KoSelection.h> 0039 #include <KoCanvasBase.h> 0040 #include <KoShapeAnchor.h> 0041 #include <KoColumns.h> 0042 0043 #include <QTimer> 0044 #include <WordsDebug.h> 0045 0046 class KWTextLayoutRootArea : public KoTextLayoutRootArea 0047 { 0048 public: 0049 KWTextLayoutRootArea(KoTextDocumentLayout *documentLayout, KWTextFrameSet *frameSet, int pageNumber) : KoTextLayoutRootArea(documentLayout), m_frameSet(frameSet), m_pageNumber(pageNumber) { 0050 //debugWords; 0051 } 0052 ~KWTextLayoutRootArea() override { 0053 //debugWords; 0054 } 0055 virtual bool layout(FrameIterator *cursor) { 0056 //debugWords << "pageNumber=" << m_pageNumber << "frameSetType=" << Words::frameSetTypeName(m_frameSet->textFrameSetType()) << "isDirty=" << isDirty(); 0057 bool ok = KoTextLayoutRootArea::layout(cursor); 0058 return ok; 0059 } 0060 KWTextFrameSet *m_frameSet; 0061 int m_pageNumber; 0062 }; 0063 0064 KWRootAreaProvider::KWRootAreaProvider(KWTextFrameSet *textFrameSet) 0065 : KWRootAreaProviderBase(textFrameSet) 0066 { 0067 } 0068 0069 KWRootAreaProvider::~KWRootAreaProvider() 0070 { 0071 qDeleteAll(m_rootAreaCache); 0072 m_rootAreaCache.clear(); 0073 qDeleteAll(m_pages); 0074 m_pages.clear(); 0075 } 0076 0077 void KWRootAreaProvider::clearPages(int pageNumber) 0078 { 0079 if (pageNumber > pages().count()) { 0080 return; 0081 } 0082 0083 KoTextDocumentLayout *lay = dynamic_cast<KoTextDocumentLayout*>(frameSet()->document()->documentLayout()); 0084 Q_ASSERT(lay); 0085 int prevPageIndex = pageNumber - 2; 0086 do { 0087 KWRootAreaPage *prevPage = prevPageIndex >= 0 && prevPageIndex < pages().count() ? pages()[prevPageIndex] : 0; 0088 if (prevPage) { 0089 if (prevPage->rootAreas.isEmpty()) { 0090 --prevPageIndex; 0091 continue; // this page doesn't have any root-areas so try the next previous page 0092 } 0093 QList<KoTextLayoutRootArea *> rootAreas = prevPage->rootAreas; 0094 foreach(KoTextLayoutRootArea *area, rootAreas) { 0095 releaseAllAfter(area); 0096 lay->removeRootArea(area); 0097 } 0098 } else { 0099 releaseAllAfter(0); 0100 lay->removeRootArea(0); 0101 } 0102 } while(false); 0103 } 0104 0105 void KWRootAreaProvider::addDependentProvider(KWRootAreaProviderBase *provider, int pageNumber) 0106 { 0107 debugWords; 0108 KoTextDocumentLayout *lay = dynamic_cast<KoTextDocumentLayout*>(provider->frameSet()->document()->documentLayout()); 0109 Q_ASSERT(lay); 0110 lay->setContinuousLayout(false); // to abort the current layout-loop 0111 lay->setBlockLayout(true); // to prevent a new layout-loop from being started 0112 0113 m_dependentProviders.append(QPair<KWRootAreaProviderBase *, int>(provider, pageNumber)); 0114 } 0115 0116 void KWRootAreaProvider::setPageDirty(int pageNumber) 0117 { 0118 if (pageNumber - 1 < m_pages.count()) { 0119 KWRootAreaPage *page = m_pages[pageNumber - 1]; 0120 foreach(KoTextLayoutRootArea *rootArea, page->rootAreas) { 0121 rootArea->setDirty(); // be sure the root-areas from the page are relayouted 0122 } 0123 } 0124 } 0125 0126 void KWRootAreaProvider::handleDependentProviders(int pageNumber) 0127 { 0128 QList<KoTextDocumentLayout *> layouts; 0129 for(int i = m_dependentProviders.count() - 1; i >= 0; --i) { 0130 QPair<KWRootAreaProviderBase *, int> p = m_dependentProviders[i]; 0131 if (p.second > pageNumber) { // only handle providers which would continue layouting at the page we just processed 0132 continue; 0133 } 0134 m_dependentProviders.removeAt(i); // this one is handled now 0135 p.first->setPageDirty(pageNumber); 0136 KoTextDocumentLayout *lay = dynamic_cast<KoTextDocumentLayout*>(p.first->frameSet()->document()->documentLayout()); 0137 Q_ASSERT(lay); 0138 if (!layouts.contains(lay)) { 0139 layouts.append(lay); 0140 } 0141 } 0142 0143 foreach(KoTextDocumentLayout *lay, layouts) { 0144 lay->setContinuousLayout(true); // to not abort the current layout-loop any longer 0145 lay->setBlockLayout(false); // allow layouting again 0146 lay->layout(); // continue layouting but don't schedule so we are sure it's done instantly 0147 } 0148 } 0149 0150 KoTextLayoutRootArea* KWRootAreaProvider::provideNext(KoTextDocumentLayout *documentLayout, const RootAreaConstraint &constraints) 0151 { 0152 KWDocument *kwdoc = frameSet()->wordsDocument(); 0153 KWPageManager *pageManager = kwdoc->pageManager(); 0154 Q_ASSERT(pageManager); 0155 0156 int pageNumber = 1; 0157 KWRootAreaPage *rootAreaPage = m_pages.isEmpty() ? 0 : m_pages.last(); 0158 int requiredRootAreaCount = 1; 0159 if (rootAreaPage && frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0160 Q_ASSERT(rootAreaPage->page.isValid()); 0161 Q_ASSERT(rootAreaPage->page.pageStyle().isValid()); 0162 requiredRootAreaCount = rootAreaPage->page.pageStyle().columns().count; 0163 if (constraints.newPageForced) { 0164 requiredRootAreaCount = 1; 0165 } 0166 } 0167 if (rootAreaPage && rootAreaPage->rootAreas.count() < requiredRootAreaCount) { 0168 pageNumber = m_pages.count(); // the root-area is still on the same page 0169 } else { 0170 pageNumber = m_pages.count() + 1; // the root-area is the first on a new page 0171 0172 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0173 // Create missing KWPage's (they will also create a KWFrame and TextShape per page) 0174 for(int i = pageManager->pageCount(); i < pageNumber; ++i) { 0175 KWPage page = kwdoc->appendPage(constraints.masterPageName); 0176 Q_ASSERT(page.isValid()); 0177 if (constraints.visiblePageNumber >= 0) 0178 page.setVisiblePageNumber(constraints.visiblePageNumber); 0179 } 0180 } else if (pageNumber > pageManager->pageCount()) { 0181 if (Words::isHeaderFooter(frameSet())) { 0182 // Headers and footers are special in that they continue with every page what is why they depend on the mainframe. 0183 KWRootAreaProvider *provider = (KWRootAreaProvider *)kwdoc->frameLayout()->mainFrameSet()->rootAreaProvider(); 0184 provider->addDependentProvider(this, pageNumber); 0185 } 0186 return 0; // not ready to layout this yet 0187 } 0188 0189 KWPage page = pageManager->page(pageNumber); 0190 Q_ASSERT(page.isValid()); 0191 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0192 if (constraints.visiblePageNumber >= 0) 0193 page.setVisiblePageNumber(constraints.visiblePageNumber); 0194 else 0195 page.setVisiblePageNumber(0); 0196 } 0197 rootAreaPage = new KWRootAreaPage(page); 0198 m_pages.append(rootAreaPage); 0199 } 0200 0201 debugWords << "pageNumber=" << pageNumber << "frameSet=" << Words::frameSetTypeName(frameSet()->textFrameSetType()); 0202 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0203 handleDependentProviders(pageNumber); 0204 } 0205 // Determinate the frames that are on the page. Note that the KWFrameLayout only knows 0206 // about header, footer and the mainframes but not about all other framesets. 0207 QList<KoShape *> shapes; 0208 0209 if (frameSet()->type() == Words::OtherFrameSet || frameSet()->textFrameSetType() == Words::OtherTextFrameSet) { 0210 if (KoShape *s = frameSet()->shapes().value(pageNumber - 1)) 0211 shapes = QList<KoShape *>() << s; 0212 } else { 0213 shapes = kwdoc->frameLayout()->sequencedShapesOn(frameSet(), pageNumber); 0214 } 0215 0216 // position OtherFrameSet's which are anchored to this page 0217 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0218 foreach(KWFrameSet* fs, kwdoc->frameSets()) { 0219 KWTextFrameSet *tfs = dynamic_cast<KWTextFrameSet*>(fs); 0220 if (tfs && tfs->textFrameSetType() != Words::OtherTextFrameSet) 0221 continue; 0222 foreach (KWFrame *frame, fs->frames()) { 0223 KoShape *shape = frame->shape(); 0224 int anchoredPageNumber = shape->anchor() ? shape->anchor()->pageNumber() : -1; 0225 if (anchoredPageNumber == pageNumber) { 0226 qreal oldOffset = frame->anchoredFrameOffset(); 0227 qreal newOffset = rootAreaPage->page.offsetInDocument(); 0228 if (!qFuzzyCompare(1 + oldOffset, 1 + newOffset)) { 0229 frame->setAnchoredFrameOffset(newOffset); 0230 QPointF pos(shape->position().x(), newOffset - oldOffset + shape->position().y()); 0231 shape->setPosition(pos); 0232 } 0233 0234 // During load we make page anchored shapes invisible, because otherwise 0235 // they leave empty rects in the text if there is run-around 0236 // now is the time to make them visible again 0237 shape->setVisible(true); 0238 0239 QPointF delta; 0240 KWFrameLayout::proposeShapeMove(shape, delta, rootAreaPage->page); 0241 shape->setPosition(shape->position() + delta); 0242 } 0243 } 0244 } 0245 } else { 0246 if (!documentLayout->referencedLayout()) { 0247 KoTextDocumentLayout *reflay = dynamic_cast<KoTextDocumentLayout*>(kwdoc->frameLayout()->mainFrameSet()->document()->documentLayout()); 0248 documentLayout->setReferencedLayout(reflay); 0249 } 0250 } 0251 0252 KoShape *shape = rootAreaPage->rootAreas.count() < shapes.count() ? shapes[rootAreaPage->rootAreas.count()] : 0; 0253 0254 KWTextLayoutRootArea *area = new KWTextLayoutRootArea(documentLayout, frameSet(), pageNumber); 0255 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0256 if (rootAreaPage->page.pageStyle().columns().count > 1) { 0257 area->setAcceptsColumnBreak(true); 0258 } 0259 area->setAcceptsPageBreak(true); 0260 } 0261 0262 if (shape) { // Not every KoTextLayoutRootArea has a KoShape for display purposes. 0263 //Q_ASSERT_X(pageNumber == pageManager->page(shape).pageNumber(), __FUNCTION__, QString("KWPageManager is out-of-sync, pageNumber=%1 vs pageNumber=%2 with offset=%3 vs offset=%4 on frameSetType=%5").arg(pageNumber).arg(pageManager->page(shape).pageNumber()).arg(shape->absolutePosition().y()).arg(pageManager->page(shape).offsetInDocument()).arg(Words::frameSetTypeName(frameSet()->textFrameSetType())).toLocal8Bit()); 0264 KoTextShapeData *data = qobject_cast<KoTextShapeData*>(shape->userData()); 0265 if (data) { 0266 data->setRootArea(area); 0267 area->setAssociatedShape(shape); 0268 } else { 0269 warnWords << "shape has no KoTextShapeData"; 0270 } 0271 if ((!shape->anchor()) || shape->anchor()->anchorType() == KoShapeAnchor::AnchorPage) { 0272 area->setPage(new KWPage(rootAreaPage->page)); 0273 } 0274 } 0275 0276 if (frameSet()->type() != Words::OtherFrameSet && frameSet()->textFrameSetType() != Words::OtherTextFrameSet) { 0277 // Only header, footer and main-frames have an own KoTextPage. All other frames are embedded into them and inherit the KoTextPage from them. 0278 area->setPage(new KWPage(rootAreaPage->page)); 0279 area->setLayoutEnvironmentResctictions(true, false); 0280 } else { 0281 area->setLayoutEnvironmentResctictions(true, true); 0282 } 0283 0284 m_pageHash[area] = rootAreaPage; 0285 rootAreaPage->rootAreas.append(area); 0286 0287 return area; 0288 } 0289 0290 KoTextLayoutRootArea *KWRootAreaProvider::provide(KoTextDocumentLayout* documentLayout, const RootAreaConstraint& constraints, int requestedPosition, bool *isNewArea) 0291 { 0292 KWPageManager *pageManager = frameSet()->wordsDocument()->pageManager(); 0293 Q_ASSERT(pageManager); 0294 if (pageManager->pageCount() == 0) // not ready yet (may happen e.g. on loading a document) 0295 return 0; 0296 0297 QString reallyNeededPageStyle = constraints.masterPageName; 0298 int visiblePageNumber = constraints.visiblePageNumber; 0299 bool newPageForced = constraints.newPageForced; 0300 if (m_rootAreaCache.size() > requestedPosition) 0301 { 0302 KoTextLayoutRootArea *rootArea = m_rootAreaCache[requestedPosition]; 0303 Q_ASSERT(rootArea); 0304 0305 if (frameSet()->textFrameSetType() != Words::MainTextFrameSet) 0306 { 0307 // No constraints except for the main frame set 0308 *isNewArea = false; 0309 return rootArea; 0310 } 0311 0312 KWRootAreaPage *rootAreaPage = m_pageHash.value(rootArea); 0313 Q_ASSERT(rootAreaPage); 0314 0315 if (constraints.visiblePageNumber >= 0) 0316 rootAreaPage->page.setVisiblePageNumber(constraints.visiblePageNumber); 0317 else 0318 rootAreaPage->page.setVisiblePageNumber(0); 0319 0320 QString reallyNeededPageStyle = constraints.masterPageName; 0321 if (reallyNeededPageStyle.isNull()) 0322 { 0323 // We must work using the previous pages... 0324 if (requestedPosition == 0) 0325 { 0326 reallyNeededPageStyle = pageManager->defaultPageStyle().name(); 0327 } 0328 else 0329 { 0330 KWRootAreaPage *previousAreaPage = m_pageHash.value(m_rootAreaCache[requestedPosition - 1]); 0331 reallyNeededPageStyle = previousAreaPage->page.pageStyle().nextStyleName(); 0332 if (reallyNeededPageStyle.isNull()) 0333 reallyNeededPageStyle = previousAreaPage->page.pageStyle().name(); 0334 } 0335 } 0336 0337 if (rootAreaPage->page.masterPageName() != reallyNeededPageStyle) 0338 { 0339 //TODO : recycle pages in order to save us a lot of effort and reduce risks of flickering, especially with very long documents 0340 releaseAllAfter(rootArea); 0341 } 0342 else 0343 { 0344 *isNewArea = false; 0345 return rootArea; 0346 } 0347 } 0348 0349 // We are interested in the first KoTextLayoutRootArea that has a shape associated for display 0350 // purposes. This can mean that multiple KoTextLayoutRootArea are created but only selected 0351 // ones that should be layouted and displayed are passed on to the textlayout-library. 0352 // This is only done for headers and footers cause they are continuous whereas for example 0353 // Words::OtherFrameSet and Words::OtherTextFrameSet framesets may not have the correct position 0354 // or not shape assigned at this point but later. 0355 RootAreaConstraint realConstraints; 0356 realConstraints.masterPageName = reallyNeededPageStyle; 0357 realConstraints.visiblePageNumber = visiblePageNumber; 0358 realConstraints.newPageForced = newPageForced; 0359 KoTextLayoutRootArea *area = 0; 0360 do { 0361 area = provideNext(documentLayout, realConstraints); 0362 if (m_rootAreaCache.size() <= requestedPosition) 0363 m_rootAreaCache.append(area); 0364 } while(Words::isHeaderFooter(frameSet()) && area && !area->associatedShape()); 0365 0366 Q_ASSERT(m_rootAreaCache.size() > requestedPosition); 0367 0368 if (area == 0 && (frameSet()->textFrameSetType() != Words::MainTextFrameSet) && requestedPosition == 0) 0369 m_rootAreaCache.clear(); 0370 *isNewArea = true; 0371 0372 return area; 0373 } 0374 0375 // afterThis==nullptr means delete everything 0376 void KWRootAreaProvider::releaseAllAfter(KoTextLayoutRootArea *afterThis) 0377 { 0378 int afterIndex = -1; 0379 if (afterThis) { 0380 if (!m_pageHash.contains(afterThis)) 0381 return; 0382 KWRootAreaPage *page = m_pageHash.value(afterThis); 0383 afterIndex = m_pages.indexOf(page); 0384 Q_ASSERT(afterIndex >= 0); 0385 0386 int newSize = m_rootAreaCache.indexOf(afterThis) + 1; 0387 while (m_rootAreaCache.size() != newSize) 0388 { 0389 KoTextLayoutRootArea *oldArea = m_rootAreaCache.takeLast(); 0390 delete(oldArea); 0391 } 0392 } 0393 0394 debugWords << "afterPageNumber=" << afterIndex+1; 0395 0396 bool atLeastOnePageRemoved = false; 0397 KWPageManager *pageManager = frameSet()->wordsDocument()->pageManager(); 0398 if (afterIndex >= 0) { 0399 for(int i = m_pages.count() - 1; i > afterIndex; --i) { 0400 KWRootAreaPage *page = m_pages.takeLast(); 0401 foreach(KoTextLayoutRootArea *area, page->rootAreas) 0402 m_pageHash.remove(area); 0403 delete page; 0404 0405 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0406 pageManager->removePage(i+1); 0407 atLeastOnePageRemoved = true; 0408 } 0409 } 0410 0411 // FIXME 0412 for(int i = m_dependentProviders.count() - 1; i >= 0; --i) { 0413 QPair<KWRootAreaProviderBase *, int> p = m_dependentProviders[i]; 0414 if (p.second >= afterIndex) 0415 m_dependentProviders.removeAt(i); 0416 } 0417 } else { 0418 //atLeastOnePageRemoved = !m_pages.isEmpty(); 0419 qDeleteAll(m_pages); 0420 qDeleteAll(m_rootAreaCache); 0421 m_pages.clear(); 0422 m_pageHash.clear(); 0423 m_rootAreaCache.clear(); 0424 0425 /*FIXME that would result in flickering :-/ 0426 for(int i = pageManager->pageCount(); i >= 1; --i) 0427 pageManager->removePage(i); 0428 */ 0429 0430 /*FIXME 0431 m_dependentProviders.clear(); 0432 */ 0433 } 0434 if (atLeastOnePageRemoved) 0435 frameSet()->wordsDocument()->firePageSetupChanged(); 0436 } 0437 0438 void KWRootAreaProvider::doPostLayout(KoTextLayoutRootArea *rootArea, bool isNewRootArea) 0439 { 0440 KWDocument *kwdoc = const_cast<KWDocument*>(frameSet()->wordsDocument()); 0441 KWPageManager *pageManager = kwdoc->pageManager(); 0442 Q_ASSERT(pageManager); 0443 0444 if (frameSet()->textFrameSetType() != Words::MainTextFrameSet) { 0445 if (m_pages.count() > pageManager->pageCount()) { 0446 // we need to wait for the mainFrameSet to finish till we are able to continue 0447 KWRootAreaProvider *provider = (KWRootAreaProvider *)kwdoc->frameLayout()->mainFrameSet()->rootAreaProvider(); 0448 provider->addDependentProvider(this, m_pages.count()); 0449 } 0450 } 0451 0452 KoShape *shape = rootArea->associatedShape(); 0453 if (!shape) 0454 return; 0455 0456 KWPage page = pageManager->page(shape); 0457 Q_ASSERT(page.isValid()); 0458 KoTextShapeData *data = qobject_cast<KoTextShapeData*>(shape->userData()); 0459 Q_ASSERT(data); 0460 bool isHeaderFooter = Words::isHeaderFooter(frameSet()); 0461 0462 debugWords << "pageNumber=" << page.pageNumber() << "frameSetType=" << Words::frameSetTypeName(frameSet()->textFrameSetType()) << "isNewRootArea=" << isNewRootArea << "rootArea=" << rootArea << "isDirty=" << rootArea->isDirty(); 0463 0464 QRectF updateRect = shape->outlineRect(); 0465 0466 QSizeF newSize = shape->size() 0467 - QSizeF(data->leftPadding() + data->rightPadding(), 0468 data->topPadding() + data->bottomPadding()); 0469 0470 KoBorder *border = shape->border(); 0471 0472 if (border) { 0473 newSize -= QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder)); 0474 } 0475 0476 if (isHeaderFooter 0477 ||data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight 0478 ||data->resizeMethod() == KoTextShapeData::AutoGrowHeight) { 0479 0480 newSize.setHeight(rootArea->bottom() - rootArea->top()); 0481 0482 if (frameSet()->type() == Words::OtherFrameSet || frameSet()->textFrameSetType() == Words::OtherTextFrameSet) { 0483 // adjust size to have at least the defined minimum height 0484 Q_ASSERT(frameSet()->shapeCount() > 0); 0485 KoShape *firstShape = frameSet()->shapes().first(); 0486 if (firstShape->minimumHeight() > newSize.height()) 0487 newSize.setHeight(firstShape->minimumHeight()); 0488 } 0489 } 0490 if (data->resizeMethod() == KoTextShapeData::AutoGrowWidthAndHeight 0491 ||data->resizeMethod() == KoTextShapeData::AutoGrowWidth) { 0492 newSize.setWidth(rootArea->right() - rootArea->left()); 0493 } 0494 0495 // To make sure footnotes always end up at the bottom of the main area we need to set this 0496 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0497 rootArea->setBottom(rootArea->top() + newSize.height()); 0498 } 0499 0500 newSize += QSizeF(data->leftPadding() + data->rightPadding(), 0501 data->topPadding() + data->bottomPadding()); 0502 if (border) { 0503 newSize += QSizeF(border->borderWidth(KoBorder::LeftBorder) + border->borderWidth(KoBorder::RightBorder), border->borderWidth(KoBorder::TopBorder) + border->borderWidth(KoBorder::BottomBorder)); 0504 } 0505 0506 if (newSize != rootArea->associatedShape()->size()) { 0507 rootArea->associatedShape()->setSize(newSize); 0508 0509 // transfer the new size to the copy-shapes 0510 foreach(KWCopyShape *cs, frameSet()->copyShapes()) { 0511 cs->setSize(newSize); 0512 } 0513 0514 if (isHeaderFooter) { 0515 // adjust the minimum shape height for headers and footer 0516 Q_ASSERT(frameSet()->shapeCount() > 0); 0517 KoShape *firstShape = frameSet()->shapes().first(); 0518 if (firstShape->minimumHeight() != newSize.height()) { 0519 firstShape->setMinimumHeight(newSize.height()); 0520 0521 // transfer the new minimumFrameHeight to the copy-shapes too 0522 foreach(KWCopyShape *cs, frameSet()->copyShapes()) { 0523 cs->setMinimumHeight(newSize.height()); 0524 } 0525 // cause the header/footer's height changed we have to relayout the whole page 0526 frameSet()->wordsDocument()->frameLayout()->layoutFramesOnPage(page.pageNumber()); 0527 } 0528 } 0529 } 0530 0531 0532 updateRect |= rootArea->associatedShape()->outlineRect(); 0533 rootArea->associatedShape()->update(updateRect); 0534 0535 if (frameSet()->textFrameSetType() == Words::MainTextFrameSet) { 0536 handleDependentProviders(page.pageNumber()); 0537 } 0538 0539 }