Warning, file /office/calligra/libs/textlayout/KoTextLayoutEndNotesArea.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2011 C. Boemann <cbo@kogmbh.com>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Library General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Library General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Library General Public License
0015  * along with this library; see the file COPYING.LIB.  If not, write to
0016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "KoTextLayoutEndNotesArea.h"
0021 
0022 #include "KoTextLayoutNoteArea.h"
0023 #include "KoInlineTextObjectManager.h"
0024 #include "KoInlineNote.h"
0025 #include "KoPointedAt.h"
0026 #include "FrameIterator.h"
0027 #include "KoCharAreaInfo.h"
0028 
0029 #include <KoTextDocument.h>
0030 
0031 #include <QPainter>
0032 
0033 #include <algorithm>
0034 
0035 static bool beforeThan(KoInlineNote *note1, KoInlineNote *note2)
0036 {
0037     return (note1->getPosInDocument() < note2->getPosInDocument());
0038 }
0039 
0040 class Q_DECL_HIDDEN KoTextLayoutEndNotesArea::Private
0041 {
0042 public:
0043     Private()
0044         : startOfArea(0)
0045     {
0046     }
0047     QList<KoTextLayoutNoteArea *> endNoteAreas;
0048     QList<QTextFrame *> endNoteFrames;
0049     FrameIterator *startOfArea;
0050     FrameIterator *endOfArea;
0051     int endNoteAutoCount;
0052 };
0053 
0054 KoTextLayoutEndNotesArea::KoTextLayoutEndNotesArea(KoTextLayoutArea *parent, KoTextDocumentLayout *documentLayout)
0055   : KoTextLayoutArea(parent, documentLayout)
0056   , d(new Private)
0057 {
0058     d->endNoteAutoCount = 0;
0059 }
0060 
0061 KoTextLayoutEndNotesArea::~KoTextLayoutEndNotesArea()
0062 {
0063     qDeleteAll(d->endNoteAreas);
0064     delete d;
0065 }
0066 
0067 bool KoTextLayoutEndNotesArea::layout(FrameIterator *cursor)
0068 {
0069     qDeleteAll(d->endNoteAreas);
0070     d->endNoteAreas.clear();
0071     d->endNoteFrames.clear();
0072 
0073     d->startOfArea = new FrameIterator(cursor);
0074     d->endOfArea = 0;
0075     int shiftDown = 15;
0076     qreal y = top() + shiftDown;
0077     setBottom(y);
0078 
0079     KoInlineTextObjectManager *manager = KoTextDocument(documentLayout()->document()).inlineTextObjectManager();
0080     QList<KoInlineNote *> list = QList<KoInlineNote *>(manager->endNotes());
0081     std::sort(list.begin(), list.end(), beforeThan); //making a list of endnotes in the order they appear
0082     while (cursor->endNoteIndex < list.length())
0083     {
0084         KoInlineNote *note = list[cursor->endNoteIndex];
0085         if (note->autoNumbering()) {
0086             note->setAutoNumber(d->endNoteAutoCount++);
0087         }
0088         QTextFrame *subFrame = note->textFrame();
0089         KoTextLayoutNoteArea *noteArea = new KoTextLayoutNoteArea(note, this, documentLayout());
0090         d->endNoteAreas.append(noteArea);
0091         d->endNoteFrames.append(subFrame);
0092         noteArea->setReferenceRect(left(), right(), y, maximumAllowedBottom());
0093         if (noteArea->layout(cursor->subFrameIterator(subFrame)) == false) {
0094             d->endOfArea = new FrameIterator(cursor);
0095             setBottom(noteArea->bottom());
0096             return false;
0097         }
0098         y = noteArea->bottom();
0099         setBottom(y);
0100         delete cursor->currentSubFrameIterator;
0101         cursor->currentSubFrameIterator = 0;
0102         cursor->endNoteIndex++;
0103     }
0104     if (cursor->endNoteIndex == 0) {
0105         setBottom(top() + shiftDown);
0106     }
0107     d->endOfArea = new FrameIterator(cursor);
0108     return true;
0109 }
0110 KoPointedAt KoTextLayoutEndNotesArea::hitTest(const QPointF &p, Qt::HitTestAccuracy accuracy) const
0111 {
0112     KoPointedAt pointedAt;
0113     int endNoteIndex = 0;
0114     while (endNoteIndex < d->endNoteAreas.length()) {
0115         // check if p is over end notes area
0116         if (p.y() > d->endNoteAreas[endNoteIndex]->top()
0117                 && p.y() < d->endNoteAreas[endNoteIndex]->bottom()) {
0118             pointedAt = d->endNoteAreas[endNoteIndex]->hitTest(p, accuracy);
0119             return pointedAt;
0120         }
0121         ++endNoteIndex;
0122     }
0123     return KoPointedAt();
0124 }
0125 
0126 QVector<KoCharAreaInfo> KoTextLayoutEndNotesArea::generateCharAreaInfos() const
0127 {
0128     QVector<KoCharAreaInfo> result;
0129 
0130     if (d->startOfArea == 0) {// We have not been layouted yet
0131         return result;
0132     }
0133 
0134     foreach(KoTextLayoutNoteArea *area, d->endNoteAreas) {
0135         result.append(area->generateCharAreaInfos());
0136     }
0137 
0138     return result;
0139 }
0140 
0141 
0142 QRectF KoTextLayoutEndNotesArea::selectionBoundingBox(QTextCursor &cursor) const
0143 {
0144     QTextFrame *subFrame;
0145     int endNoteIndex = 0;
0146     while (endNoteIndex < d->endNoteFrames.length()) {
0147         subFrame = d->endNoteFrames[endNoteIndex];
0148         if (subFrame != 0) {
0149             if (cursor.selectionStart() >= subFrame->firstPosition() && cursor.selectionEnd() <= subFrame->lastPosition()) {
0150                 return d->endNoteAreas[endNoteIndex]->selectionBoundingBox(cursor);
0151             }
0152             ++endNoteIndex;
0153         }
0154     }
0155     return QRectF();
0156 }
0157 
0158 void KoTextLayoutEndNotesArea::paint(QPainter *painter, const KoTextDocumentLayout::PaintContext &context)
0159 {
0160     if (d->startOfArea == 0) // We have not been layouted yet
0161         return;
0162 
0163     if (!d->endNoteAreas.isEmpty()) {
0164         int left = 2;
0165         int right = 150;
0166         int shiftDown = 10;
0167         painter->drawLine(left, top()+shiftDown, right, top()+shiftDown);
0168     }
0169     foreach(KoTextLayoutNoteArea *area, d->endNoteAreas) {
0170         area->paint(painter, context);
0171     }
0172 }