File: KoTextDocumentLayout.h

package info (click to toggle)
calligra 1%3A3.2.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 260,432 kB
  • sloc: cpp: 650,911; xml: 27,662; python: 6,044; perl: 2,724; yacc: 1,817; ansic: 1,325; sh: 1,277; lex: 1,107; ruby: 1,010; javascript: 495; makefile: 24
file content (329 lines) | stat: -rw-r--r-- 12,062 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/* This file is part of the KDE project
 * Copyright (C) 2006-2007, 2009 Thomas Zander <zander@kde.org>
 * Copyright (C) 2006, 2011 Sebastian Sauer <mail@dipe.org>
 * Copyright (C) 2011 C. Boemann <cbo@kogmbh.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef KOTEXTDOCUMENTLAYOUT_H
#define KOTEXTDOCUMENTLAYOUT_H

#include "kotextlayout_export.h"

#include <QAbstractTextDocumentLayout>
#include <QList>
#include <QTextFrame>

class KoShape;
class KoStyleManager;
class KoChangeTracker;
class KoTextRangeManager;
class KoInlineTextObjectManager;
class KoViewConverter;
class KoImageCollection;
class KoShapeAnchor;
class KoTextLayoutRootArea;
class KoTextLayoutRootAreaProvider;
class KoTextLayoutObstruction;

class QRectF;
class QSizeF;

class KOTEXTLAYOUT_EXPORT KoInlineObjectExtent
{
public:
    explicit KoInlineObjectExtent(qreal ascent = 0, qreal descent = 0);
    qreal m_ascent;
    qreal m_descent;
};


/**
 * Text layouter that allows text to flow in multiple root area and around
 * obstructions.
 */
class KOTEXTLAYOUT_EXPORT KoTextDocumentLayout : public QAbstractTextDocumentLayout
{
    Q_OBJECT
public:
    /// This struct is a helper for painting of kotext texts.
    struct PaintContext {
        PaintContext()
            : viewConverter(0)
            , imageCollection(0)
            , showFormattingCharacters(false)
            , showSectionBounds(false)
            , showSpellChecking(false)
            , showSelections(true)
            , background(Qt::white)
        {
        }

        /// the QText context
        QAbstractTextDocumentLayout::PaintContext textContext;
        /// A view converter, when set, is used to find out when the zoom is so low that painting of text is unneeded
        const KoViewConverter *viewConverter;

        KoImageCollection *imageCollection;
        bool showFormattingCharacters;
        bool showTableBorders;
        bool showSectionBounds;
        bool showSpellChecking;
        bool showSelections;
        QColor background;
    };

    /// constructor
    explicit KoTextDocumentLayout(QTextDocument *doc, KoTextLayoutRootAreaProvider *provider = 0);
    ~KoTextDocumentLayout() override;

    /// return the rootAreaProvider.
    KoTextLayoutRootAreaProvider *provider() const;

    /// return the currently set manager, or 0 if none is set.
    KoInlineTextObjectManager *inlineTextObjectManager() const;
    void setInlineTextObjectManager(KoInlineTextObjectManager *manager);

    /// return the currently set manager, or 0 if none is set.
    KoTextRangeManager *textRangeManager() const;
    void setTextRangeManager(KoTextRangeManager *manager);

    /// return the currently set changeTracker, or 0 if none is set.
    KoChangeTracker *changeTracker() const;
    void setChangeTracker(KoChangeTracker *tracker);

    /// return the currently set styleManager, or 0 if none is set.
    KoStyleManager *styleManager() const;
    void setStyleManager(KoStyleManager *manager);

    /// Returns the bounding rectangle of block.
    QRectF blockBoundingRect(const QTextBlock &block) const override;
    /**
     * Returns the total size of the document. This is useful to display
     * widgets since they can use to information to update their scroll bars
     * correctly
     */
    QSizeF documentSize() const override;

    QRectF frameBoundingRect(QTextFrame*) const override;

    /// the default tab size for this document
    qreal defaultTabSpacing() const;

    /// set default tab size for this document
    void setTabSpacing(qreal spacing);

    /// set if this is for a word processor (slight changes in layout may occur)
    void setWordprocessingMode();

    /// is it for a word processor (slight changes in layout may occur)
    bool wordprocessingMode() const;

    /// are the tabs relative to indent or not
    bool relativeTabs(const QTextBlock &block) const;

    /// visualize inline objects during paint
    void showInlineObjectVisualization(bool show);

    /// Calc a bounding box rect of the selection
    QRectF selectionBoundingBox(QTextCursor &cursor) const;

    /// Draws the layout on the given painter with the given context.
    void draw(QPainter * painter, const QAbstractTextDocumentLayout::PaintContext & context) override;

    /// reimplemented DO NOT CALL - USE HITTEST IN THE ROOTAREAS INSTEAD
    int hitTest(const QPointF & point, Qt::HitTestAccuracy accuracy) const override;

    /// reimplemented to always return 1
    int pageCount() const override;

    QList<KoShapeAnchor *> textAnchors() const;

    /**
     * Register the anchored obstruction  for run around
     *
     * We have the concept of Obstructions which text has to run around in various ways.
     * We maintain two collections of obstructions. The free which are tied to just a position
     * (tied to pages), and the anchored obstructions which are each anchored to a KoShapeAnchor
     *
     * The free obstructions are collected from the KoTextLayoutRootAreaProvider during layout
     *
     * The anchored obstructions are created in the FloatingAnchorStrategy and registered using
     * this method.
     */
    void registerAnchoredObstruction(KoTextLayoutObstruction *obstruction);


    /**
     * Anchors are special InlineObjects that we detect in positionInlineObject()
     * We save those for later so we can position them during layout instead.
     * During KoTextLayoutArea::layout() we call positionAnchoredObstructions()
     */
    /// remove all anchors and associated obstructions and set up for collecting new ones
    void beginAnchorCollecting(KoTextLayoutRootArea *rootArea);

    /// allow  positionInlineObject() to do anything (incl saving anchors)
    void allowPositionInlineObject(bool allow);

    /// Sets the paragraph rect that will be applied to anchorStrategies being created in
    /// positionInlineObject()
    void setAnchoringParagraphRect(const QRectF &paragraphRect);

    /// Sets the paragraph content rect that will be applied to anchorStrategies being created in
    /// positionInlineObject()
    void setAnchoringParagraphContentRect(const QRectF &paragraphContentRect);

    /// Sets the layoutEnvironment rect that will be applied to anchorStrategies being created in
    /// positionInlineObject()
    void setAnchoringLayoutEnvironmentRect(const QRectF &layoutEnvironmentRect);

    /// Calculates the maximum y of anchored obstructions
    qreal maxYOfAnchoredObstructions(int firstCursorPosition, int lastCursorPosition) const;

    int anchoringSoftBreak() const;

    /// Positions all anchored obstructions
    /// the paragraphRect should be in textDocument coords and not global/document coords
    void positionAnchoredObstructions();

    /// remove inline object
    void removeInlineObject(KoShapeAnchor *textAnchor);

    void clearInlineObjectRegistry(const QTextBlock& block);

    KoInlineObjectExtent inlineObjectExtent(const QTextFragment&);

    /**
     * We allow a text document to be distributed onto a sequence of KoTextLayoutRootArea;
     * which brings up the need to figure out which KoTextLayoutRootArea is used for a certain
     * text.
     * @param position the position of the character in the text document we want to locate.
     * @return the KoTextLayoutRootArea the text is laid-out in. Or 0 if there is no shape for that text character.
     */
    KoTextLayoutRootArea *rootAreaForPosition(int position) const;


    KoTextLayoutRootArea *rootAreaForPoint(const QPointF &point) const;

    /**
     * Remove the root-areas \p rootArea from the list of \a rootAreas() .
     * \param rootArea root-area to remove. If NULL then all root-areas are removed.
     */
    void removeRootArea(KoTextLayoutRootArea *rootArea = 0);

    /// reimplemented from QAbstractTextDocumentLayout
    void documentChanged(int position, int charsRemoved, int charsAdded) override;

    void setContinuationObstruction(KoTextLayoutObstruction *continuationObstruction);

    /// Return a list of obstructions intersecting current root area (during layout)
    QList<KoTextLayoutObstruction *> currentObstructions();

    QList<KoTextLayoutRootArea *> rootAreas() const;
    QList<KoShape*> shapes() const;

    /// Set should layout be continued when done with current root area
    void setContinuousLayout(bool continuous);

    /// Set \a layout() to be blocked (no layouting will happen)
    void setBlockLayout(bool block);
    bool layoutBlocked() const;

    /// Set \a documentChanged() to be blocked (changes will not result in root-areas being marked dirty)
    void setBlockChanges(bool block);
    bool changesBlocked() const;

    KoTextDocumentLayout* referencedLayout() const;
    void setReferencedLayout(KoTextDocumentLayout *layout);

    /**
     * To be called during layout by KoTextLayoutArea - similar to how qt calls positionInlineObject
     *
     * It searches for anchor text ranges in the given span
     */
    void positionAnchorTextRanges(int pos, int length, const QTextDocument *effectiveDocument);

Q_SIGNALS:
    /**
     * Signal that is emitted during layouting to inform about the progress done so far.
     */
    void layoutProgressChanged(int percent);

    /**
     * Signal is emitted every time a layout run has completely finished (all text is positioned).
     */
    void finishedLayout();

    /**
     * Signal is emitted when emitLayoutIsDirty() is called which happens at
     * least when a root area is marked as dirty.
     * @see emitLayoutIsDirty
     */
    void layoutIsDirty();

    void foundAnnotation(KoShape *annotationShape, const QPointF &refPosition);

public Q_SLOTS:
    /**
     * Does the layout of the text.
     * This method will layout the text into sections, tables and textlines,
     * chunk by chunk.
     * It may interrupt itself, @see contiuousLayout
     * calling this method when the layout is not dirty, doesn't take that much
     * time as it doesn't do much, although it does check every root area
     */
    virtual void layout();

    /**
     * Schedules a \a layout call for later using a QTimer::singleShot. Multiple calls
     * to this slot will be compressed into one layout-call to prevent calling layouting
     * to much. Also if meanwhile \a layout was called then the scheduled layout won't
     * be executed.
     */
    virtual void scheduleLayout();

    /**
     * Emits the \a layoutIsDirty signal.
     */
    void emitLayoutIsDirty();

private Q_SLOTS:
    /// Called by \a scheduleLayout to start a \a layout run if not done already meanwhile.
    void executeScheduledLayout();

protected:
    /// reimplemented
    void drawInlineObject(QPainter *painter, const QRectF &rect, QTextInlineObject object, int position, const QTextFormat &format) override;
    /// reimplemented
    void positionInlineObject(QTextInlineObject item, int position, const QTextFormat &format) override;
    /// reimplemented
    void resizeInlineObject(QTextInlineObject item, int position, const QTextFormat &format) override;

    /// should we continue layout when done with current root area
    bool continuousLayout() const;

    void registerInlineObject(const QTextInlineObject &inlineObject);

private:
    class Private;
    Private * const d;

    bool doLayout();
    void updateProgress(const QTextFrame::iterator &it);
};

#endif