示例#1
0
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;
}
示例#4
0
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);