void KWCanvasBase::clipToDocument(const KoShape *shape, QPointF &move) const { Q_ASSERT(shape); const QPointF absPos = shape->absolutePosition(); const QPointF destination = absPos + move; qreal bottomOfPage = 0.0; KWPage page; foreach (const KWPage &p, m_document->pageManager()->pages()) { bottomOfPage += p.height(); if (bottomOfPage >= absPos.y()) page = p; if (bottomOfPage >= destination.y()) { page = p; break; } } if (!page.isValid()) { // shape was not in any page to begin with, can't propose anything sane... move.setX(0); move.setY(0); return; } QRectF pageRect(page.rect().adjusted(5, 5, -5, -5)); QPainterPath path(shape->absoluteTransformation(0).map(shape->outline())); QRectF shapeBounds = path.boundingRect(); shapeBounds.moveTopLeft(shapeBounds.topLeft() + move); if (!shapeBounds.intersects(pageRect)) { if (shapeBounds.left() > pageRect.right()) // need to move to the left some move.setX(move.x() + (pageRect.right() - shapeBounds.left())); else if (shapeBounds.right() < pageRect.left()) // need to move to the right some move.setX(move.x() + pageRect.left() - shapeBounds.right()); if (shapeBounds.top() > pageRect.bottom()) // need to move up some move.setY(move.y() + (pageRect.bottom() - shapeBounds.top())); else if (shapeBounds.bottom() < pageRect.top()) // need to move down some move.setY(move.y() + pageRect.top() - shapeBounds.bottom()); } // Also make sure any anchoring restrictions are adhered to KWFrameLayout::proposeShapeMove(shape, move, page); }
QList<KWViewMode::ViewMap> KWViewModeNormal::mapExposedRects(const QRectF &viewRect, KoViewConverter *viewConverter) const { QList<ViewMap> answer; if (!viewConverter) return answer; #if 1 if (m_pageTops.isEmpty()) return answer; KWPage page = m_pageManager->begin(); const int pageOffset = page.pageNumber(); // Perform a binary search for page-index using our m_pageTops cache. int begin = 0; int end = m_pageTops.count() - 1; int index = 0; const qreal value = viewConverter->viewToDocument(viewRect.topLeft()).y(); if (m_pageTops.value(end) <= value) { // check extremes. Only end is needed since begin is zero. begin = end; index = end; } while (end - begin > 1) { index = begin + (end - begin) / 2; qreal diff = m_pageTops.value(index) - value; if (diff < 0) begin = index; else if (diff > 0) end = index; else break; } // index is now the number of the first possible page that can // contain the viewRect. The next step is to find the // corresponding Page. Since we have no way to get to the Nth // page directly we have to enumerate them from the beginning. // // We use 1 since we might hit a pagespread in the binary search, // so start one page early. while (index > 1) { page = page.next(); --index; } // From here we loop through some more pages after the found one // and see if they intersect with the page in question. When we // have two pages in row that don't intersect we break the loop. qreal offsetX = 0.0; int emptyPages = 0; for(; page.isValid(); page = page.next()) { Q_ASSERT_X(page.pageNumber()-pageOffset < m_pageTops.count(), __FUNCTION__, QString("Pagemanager has more pages than viewmode (%1>%2 with pageOffset=%3 and pageNumber=%4 and pageCount=%5). Make sure you add pages via the document!") .arg(page.pageNumber()-pageOffset).arg(m_pageTops.count()) .arg(pageOffset).arg(page.pageNumber()).arg(m_pageManager->pageCount()).toLocal8Bit()); // Some invariants const QRectF pageRect = page.rect(); const qreal offsetY = m_pageTops[page.pageNumber() - pageOffset] - pageRect.top(); bool pageIntersects = false; // 1. First handle the page itself. const QRectF zoomedPage = viewConverter->documentToView(pageRect); ViewMap vm; vm.page = page; //kDebug(32003) <<"page" << page.pageNumber(); vm.distance = viewConverter->documentToView(QPointF(offsetX, offsetY)); const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width(), zoomedPage.height()); QRectF intersection = targetPage.intersect(viewRect); if (! intersection.isEmpty()) { intersection.moveTopLeft(intersection.topLeft() - vm.distance); vm.clipRect = intersection.toRect(); answer.append(vm); pageIntersects = true; } // 2. Then handle the annotation area if annotations are active. // // The reason we don't do them together with the page // itself is because the pages have a gap between them, but // the annotation area should be unbroken. // // NOTE: 'annotation' below means the annotation area. // // FIXME: We should only do this if the annotation area is // actually shown. How can we inside the KWViewMode // know if annotations are active? if (1 /* annotations are shown */) { const QRectF annotationRect = pageRect.adjusted(page.width(), 0, KWCanvasBase::AnnotationAreaWidth, GAP); const QRectF zoomedAnnotation = viewConverter->documentToView(annotationRect); ViewMap vm2; vm2.page = page; vm2.distance = viewConverter->documentToView(QPointF(offsetX, offsetY)); const QRectF targetAnnotation(zoomedAnnotation.x() + vm2.distance.x(), zoomedAnnotation.y() + vm2.distance.y(), zoomedAnnotation.width(), zoomedAnnotation.height()); intersection = targetAnnotation.intersect(viewRect); if (! intersection.isEmpty()) { intersection.moveTopLeft(intersection.topLeft() - vm2.distance); vm2.clipRect = intersection.toRect(); answer.append(vm2); pageIntersects = true; } } // Record whether this page had an intersection with the view rect. if (pageIntersects) { emptyPages = 0; } else { ++emptyPages; } if (emptyPages > 2) // Since we show at max 2 pages side by side this is an easy rule break; if (m_pageSpreadMode) { if (page.pageSide() == KWPage::Left) offsetX = page.width() + GAP; else offsetX = 0.0; } } #else KWPage page = m_pageManager->begin(); Q_ASSERT(page.isValid()); qreal offsetX = 0.0; const int pageOffset = page.pageNumber(); for(; page.isValid(); page = page.next()) { const QRectF pageRect = page.rect(); const QRectF zoomedPage = viewConverter->documentToView(pageRect); ViewMap vm; vm.page = page; const qreal offsetY = m_pageTops[page.pageNumber() - pageOffset] - pageRect.top(); vm.distance = viewConverter->documentToView(QPointF(offsetX, offsetY)); #if 0 const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width() , zoomedPage.height()); QRectF intersection = targetPage.intersect(viewRect); if (! intersection.isEmpty()) { intersection.moveTopLeft(intersection.topLeft() - vm.distance); vm.clipRect = intersection.toRect(); answer.append(vm); } #else const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width() , zoomedPage.height()); vm.clipRect = targetPage.toRect(); answer.append(vm); #endif } #endif return answer; }
QList<KWViewMode::ViewMap> KWViewModeNormal::mapExposedRects(const QRectF &viewRect, KoViewConverter *viewConverter) const { QList<ViewMap> answer; if (!viewConverter) return answer; #if 1 if (m_pageTops.isEmpty()) return answer; KWPage page = m_pageManager->begin(); qreal offsetX = 0.0; const int pageOffset = page.pageNumber(); int begin = 0; int end = m_pageTops.count() - 1; int index = 0; const qreal value = viewConverter->viewToDocument(viewRect.topLeft()).y(); if (m_pageTops.value(end) <= value) { // check extremes. Only end is needed since begin is zero. begin = end; index = end; } while (end - begin > 1) { // binary search for page-index using our m_pageTops cache. index = begin + (end - begin) / 2; qreal diff = m_pageTops.value(index) - value; if (diff < 0) begin = index; else if (diff > 0) end = index; else break; } while (index > 1) { // 1 since we might hit a pagespread in the binary search, so start one page early page = page.next(); --index; } int emptyPages = 0; for(; page.isValid(); page = page.next()) { Q_ASSERT_X(page.pageNumber()-pageOffset < m_pageTops.count(), __FUNCTION__, QString("Pagemanager has more pages than viewmode (%1>%2 with pageOffset=%3 and pageNumber=%4 and pageCount=%5). Make sure you add pages via the document!") .arg(page.pageNumber()-pageOffset).arg(m_pageTops.count()).arg(pageOffset).arg(page.pageNumber()).arg(m_pageManager->pageCount()).toLocal8Bit()); const QRectF pageRect = page.rect(); const QRectF zoomedPage = viewConverter->documentToView(pageRect); ViewMap vm; vm.page = page; //kDebug(32003) <<"page" << page.pageNumber(); const qreal offsetY = m_pageTops[page.pageNumber() - pageOffset] - pageRect.top(); vm.distance = viewConverter->documentToView(QPointF(offsetX, offsetY)); const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width() , zoomedPage.height()); QRectF intersection = targetPage.intersect(viewRect); if (! intersection.isEmpty()) { intersection.moveTopLeft(intersection.topLeft() - vm.distance); vm.clipRect = intersection.toRect(); answer.append(vm); emptyPages = 0; } else { emptyPages++; } if (emptyPages > 2) // Since we show at max 2 pages side by side this is an easy rule break; if (m_pageSpreadMode) { if (page.pageSide() == KWPage::Left) offsetX = page.width() + GAP; else offsetX = 0.0; } } #else KWPage page = m_pageManager->begin(); Q_ASSERT(page.isValid()); qreal offsetX = 0.0; const int pageOffset = page.pageNumber(); for(; page.isValid(); page = page.next()) { const QRectF pageRect = page.rect(); const QRectF zoomedPage = viewConverter->documentToView(pageRect); ViewMap vm; vm.page = page; const qreal offsetY = m_pageTops[page.pageNumber() - pageOffset] - pageRect.top(); vm.distance = viewConverter->documentToView(QPointF(offsetX, offsetY)); #if 0 const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width() , zoomedPage.height()); QRectF intersection = targetPage.intersect(viewRect); if (! intersection.isEmpty()) { intersection.moveTopLeft(intersection.topLeft() - vm.distance); vm.clipRect = intersection.toRect(); answer.append(vm); } #else const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width() , zoomedPage.height()); vm.clipRect = targetPage.toRect(); answer.append(vm); #endif } #endif return answer; }
QList<KWViewMode::ViewMap> KWViewModeNormal::clipRectToDocument(const QRect &viewRect) const { QList<ViewMap> answer; if (m_pageTops.isEmpty()) return answer; KWPage page = m_pageManager->begin(); qreal offsetX = 0.0; const int pageOffset = page.pageNumber(); int begin = 0; int end = m_pageTops.count() - 1; int index = 0; const qreal value = m_viewConverter->viewToDocument(viewRect.topLeft()).y(); if (m_pageTops.value(end) <= value) { // check extremes. Only end is needed since begin is zero. begin = end; index = end; } while (end - begin > 1) { // binary search for page-index using our m_pageTops cache. index = begin + (end - begin) / 2; qreal diff = m_pageTops.value(index) - value; if (diff < 0) begin = index; else if (diff > 0) end = index; else break; } while (index > 1) { // 1 since we might hit a pagespread in the binary search, so start one page early page = page.next(); --index; if (page.pageSide() == KWPage::PageSpread) --index; } int emptyPages = 0; while (page.isValid()) { #ifndef NDEBUG if (page.pageNumber() - pageOffset >= m_pageTops.count()) { kWarning(32003) << "ERROR; pagemanager has more pages than viewmode (" << m_pageManager->pageCount() << ">" << m_pageTops.count() << "). Make sure you add pages via the document!"; break; } #endif const QRectF pageRect = page.rect(); const QRectF zoomedPage = m_viewConverter->documentToView(pageRect); ViewMap vm; vm.page = page; //kDebug(32003) <<"page" << page.pageNumber(); const qreal offsetY = m_pageTops[page.pageNumber() - pageOffset] - pageRect.top(); vm.distance = m_viewConverter->documentToView(QPointF(offsetX, offsetY)); const QRectF targetPage(zoomedPage.x() + vm.distance.x(), zoomedPage.y() + vm.distance.y(), zoomedPage.width() , zoomedPage.height()); QRectF intersection = targetPage.intersect(viewRect); if (! intersection.isEmpty()) { intersection.moveTopLeft(intersection.topLeft() - vm.distance); vm.clipRect = intersection.toRect(); answer.append(vm); emptyPages = 0; } else { emptyPages++; } if (emptyPages > 2) // Since we show at max 2 pages side by side this is an easy rule break; if (m_pageSpreadMode) { if (page.pageSide() == KWPage::Left) offsetX = page.width() + GAP; else offsetX = 0.0; } page = page.next(); } return answer; }
} m_frames.clear(); KWTextFrameSet tfs(0, (Words::TextFrameSetType) frameSetType); m_frames << &tfs; KWFrameLayout frameLayout(&manager, m_frames); connect(&frameLayout, SIGNAL(newFrameSet(KWFrameSet*)), this, SLOT(addFS(KWFrameSet*))); KWPage page = manager.page(pageNumber); QVERIFY(page.isValid()); tfs.setPageStyle(page.pageStyle()); frameLayout.createNewFramesForPage(pageNumber); QCOMPARE(tfs.frameCount(), expectedFrameCount); foreach(KoShape *shape, tfs.shapes()) { QVERIFY (page.rect().contains(shape->position())); } } void TestFrameLayout::testCopyFramesForPage() { Helper helper; m_frames.clear(); KWPage page = helper.pageManager->begin(); // copyShape MockShape *copyShape = new MockShape(); copyShape->setPosition(QPointF(9, 13)); KWFrameSet *copyShapeFrameSet = new KWFrameSet(); KWFrame *frame = new KWFrame(copyShape, copyShapeFrameSet); frame->setNewFrameBehavior(Words::CopyNewFrame);