Warning, file /office/calligra/libs/textlayout/KoTextDocumentLayout.h 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) 2006-2007, 2009 Thomas Zander <zander@kde.org>
0003  * Copyright (C) 2006, 2011 Sebastian Sauer <mail@dipe.org>
0004  * Copyright (C) 2011 C. Boemann <cbo@kogmbh.com>
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 #ifndef KOTEXTDOCUMENTLAYOUT_H
0023 #define KOTEXTDOCUMENTLAYOUT_H
0024 
0025 #include "kotextlayout_export.h"
0026 
0027 #include <QAbstractTextDocumentLayout>
0028 #include <QList>
0029 #include <QTextFrame>
0030 
0031 class KoShape;
0032 class KoStyleManager;
0033 class KoChangeTracker;
0034 class KoTextRangeManager;
0035 class KoInlineTextObjectManager;
0036 class KoViewConverter;
0037 class KoImageCollection;
0038 class KoShapeAnchor;
0039 class KoTextLayoutRootArea;
0040 class KoTextLayoutRootAreaProvider;
0041 class KoTextLayoutObstruction;
0042 
0043 class QRectF;
0044 class QSizeF;
0045 
0046 class KOTEXTLAYOUT_EXPORT KoInlineObjectExtent
0047 {
0048 public:
0049     explicit KoInlineObjectExtent(qreal ascent = 0, qreal descent = 0);
0050     qreal m_ascent;
0051     qreal m_descent;
0052 };
0053 
0054 
0055 /**
0056  * Text layouter that allows text to flow in multiple root area and around
0057  * obstructions.
0058  */
0059 class KOTEXTLAYOUT_EXPORT KoTextDocumentLayout : public QAbstractTextDocumentLayout
0060 {
0061     Q_OBJECT
0062 public:
0063     /// This struct is a helper for painting of kotext texts.
0064     struct PaintContext {
0065         PaintContext()
0066             : viewConverter(0)
0067             , imageCollection(0)
0068             , showFormattingCharacters(false)
0069             , showSectionBounds(false)
0070             , showSpellChecking(false)
0071             , showSelections(true)
0072             , background(Qt::white)
0073         {
0074         }
0075 
0076         /// the QText context
0077         QAbstractTextDocumentLayout::PaintContext textContext;
0078         /// A view converter, when set, is used to find out when the zoom is so low that painting of text is unneeded
0079         const KoViewConverter *viewConverter;
0080 
0081         KoImageCollection *imageCollection;
0082         bool showFormattingCharacters;
0083         bool showTableBorders;
0084         bool showSectionBounds;
0085         bool showSpellChecking;
0086         bool showSelections;
0087         QColor background;
0088     };
0089 
0090     /// constructor
0091     explicit KoTextDocumentLayout(QTextDocument *doc, KoTextLayoutRootAreaProvider *provider = 0);
0092     ~KoTextDocumentLayout() override;
0093 
0094     /// return the rootAreaProvider.
0095     KoTextLayoutRootAreaProvider *provider() const;
0096 
0097     /// return the currently set manager, or 0 if none is set.
0098     KoInlineTextObjectManager *inlineTextObjectManager() const;
0099     void setInlineTextObjectManager(KoInlineTextObjectManager *manager);
0100 
0101     /// return the currently set manager, or 0 if none is set.
0102     KoTextRangeManager *textRangeManager() const;
0103     void setTextRangeManager(KoTextRangeManager *manager);
0104 
0105     /// return the currently set changeTracker, or 0 if none is set.
0106     KoChangeTracker *changeTracker() const;
0107     void setChangeTracker(KoChangeTracker *tracker);
0108 
0109     /// return the currently set styleManager, or 0 if none is set.
0110     KoStyleManager *styleManager() const;
0111     void setStyleManager(KoStyleManager *manager);
0112 
0113     /// Returns the bounding rectangle of block.
0114     QRectF blockBoundingRect(const QTextBlock &block) const override;
0115     /**
0116      * Returns the total size of the document. This is useful to display
0117      * widgets since they can use to information to update their scroll bars
0118      * correctly
0119      */
0120     QSizeF documentSize() const override;
0121 
0122     QRectF frameBoundingRect(QTextFrame*) const override;
0123 
0124     /// the default tab size for this document
0125     qreal defaultTabSpacing() const;
0126 
0127     /// set default tab size for this document
0128     void setTabSpacing(qreal spacing);
0129 
0130     /// set if this is for a word processor (slight changes in layout may occur)
0131     void setWordprocessingMode();
0132 
0133     /// is it for a word processor (slight changes in layout may occur)
0134     bool wordprocessingMode() const;
0135 
0136     /// are the tabs relative to indent or not
0137     bool relativeTabs(const QTextBlock &block) const;
0138 
0139     /// visualize inline objects during paint
0140     void showInlineObjectVisualization(bool show);
0141 
0142     /// Calc a bounding box rect of the selection
0143     QRectF selectionBoundingBox(QTextCursor &cursor) const;
0144 
0145     /// Draws the layout on the given painter with the given context.
0146     void draw(QPainter * painter, const QAbstractTextDocumentLayout::PaintContext & context) override;
0147 
0148     /// reimplemented DO NOT CALL - USE HITTEST IN THE ROOTAREAS INSTEAD
0149     int hitTest(const QPointF & point, Qt::HitTestAccuracy accuracy) const override;
0150 
0151     /// reimplemented to always return 1
0152     int pageCount() const override;
0153 
0154     QList<KoShapeAnchor *> textAnchors() const;
0155 
0156     /**
0157      * Register the anchored obstruction  for run around
0158      *
0159      * We have the concept of Obstructions which text has to run around in various ways.
0160      * We maintain two collections of obstructions. The free which are tied to just a position
0161      * (tied to pages), and the anchored obstructions which are each anchored to a KoShapeAnchor
0162      *
0163      * The free obstructions are collected from the KoTextLayoutRootAreaProvider during layout
0164      *
0165      * The anchored obstructions are created in the FloatingAnchorStrategy and registered using
0166      * this method.
0167      */
0168     void registerAnchoredObstruction(KoTextLayoutObstruction *obstruction);
0169 
0170 
0171     /**
0172      * Anchors are special InlineObjects that we detect in positionInlineObject()
0173      * We save those for later so we can position them during layout instead.
0174      * During KoTextLayoutArea::layout() we call positionAnchoredObstructions()
0175      */
0176     /// remove all anchors and associated obstructions and set up for collecting new ones
0177     void beginAnchorCollecting(KoTextLayoutRootArea *rootArea);
0178 
0179     /// allow  positionInlineObject() to do anything (incl saving anchors)
0180     void allowPositionInlineObject(bool allow);
0181 
0182     /// Sets the paragraph rect that will be applied to anchorStrategies being created in
0183     /// positionInlineObject()
0184     void setAnchoringParagraphRect(const QRectF &paragraphRect);
0185 
0186     /// Sets the paragraph content rect that will be applied to anchorStrategies being created in
0187     /// positionInlineObject()
0188     void setAnchoringParagraphContentRect(const QRectF &paragraphContentRect);
0189 
0190     /// Sets the layoutEnvironment rect that will be applied to anchorStrategies being created in
0191     /// positionInlineObject()
0192     void setAnchoringLayoutEnvironmentRect(const QRectF &layoutEnvironmentRect);
0193 
0194     /// Calculates the maximum y of anchored obstructions
0195     qreal maxYOfAnchoredObstructions(int firstCursorPosition, int lastCursorPosition) const;
0196 
0197     int anchoringSoftBreak() const;
0198 
0199     /// Positions all anchored obstructions
0200     /// the paragraphRect should be in textDocument coords and not global/document coords
0201     void positionAnchoredObstructions();
0202 
0203     /// remove inline object
0204     void removeInlineObject(KoShapeAnchor *textAnchor);
0205 
0206     void clearInlineObjectRegistry(const QTextBlock& block);
0207 
0208     KoInlineObjectExtent inlineObjectExtent(const QTextFragment&);
0209 
0210     /**
0211      * We allow a text document to be distributed onto a sequence of KoTextLayoutRootArea;
0212      * which brings up the need to figure out which KoTextLayoutRootArea is used for a certain
0213      * text.
0214      * @param position the position of the character in the text document we want to locate.
0215      * @return the KoTextLayoutRootArea the text is laid-out in. Or 0 if there is no shape for that text character.
0216      */
0217     KoTextLayoutRootArea *rootAreaForPosition(int position) const;
0218 
0219 
0220     KoTextLayoutRootArea *rootAreaForPoint(const QPointF &point) const;
0221 
0222     /**
0223      * Remove the root-areas \p rootArea from the list of \a rootAreas() .
0224      * \param rootArea root-area to remove. If NULL then all root-areas are removed.
0225      */
0226     void removeRootArea(KoTextLayoutRootArea *rootArea = 0);
0227 
0228     /// reimplemented from QAbstractTextDocumentLayout
0229     void documentChanged(int position, int charsRemoved, int charsAdded) override;
0230 
0231     void setContinuationObstruction(KoTextLayoutObstruction *continuationObstruction);
0232 
0233     /// Return a list of obstructions intersecting current root area (during layout)
0234     QList<KoTextLayoutObstruction *> currentObstructions();
0235 
0236     QList<KoTextLayoutRootArea *> rootAreas() const;
0237     QList<KoShape*> shapes() const;
0238 
0239     /// Set should layout be continued when done with current root area
0240     void setContinuousLayout(bool continuous);
0241 
0242     /// Set \a layout() to be blocked (no layouting will happen)
0243     void setBlockLayout(bool block);
0244     bool layoutBlocked() const;
0245 
0246     /// Set \a documentChanged() to be blocked (changes will not result in root-areas being marked dirty)
0247     void setBlockChanges(bool block);
0248     bool changesBlocked() const;
0249 
0250     KoTextDocumentLayout* referencedLayout() const;
0251     void setReferencedLayout(KoTextDocumentLayout *layout);
0252 
0253     /**
0254      * To be called during layout by KoTextLayoutArea - similar to how qt calls positionInlineObject
0255      *
0256      * It searches for anchor text ranges in the given span
0257      */
0258     void positionAnchorTextRanges(int pos, int length, const QTextDocument *effectiveDocument);
0259 
0260 Q_SIGNALS:
0261     /**
0262      * Signal that is emitted during layouting to inform about the progress done so far.
0263      */
0264     void layoutProgressChanged(int percent);
0265 
0266     /**
0267      * Signal is emitted every time a layout run has completely finished (all text is positioned).
0268      */
0269     void finishedLayout();
0270 
0271     /**
0272      * Signal is emitted when emitLayoutIsDirty() is called which happens at
0273      * least when a root area is marked as dirty.
0274      * @see emitLayoutIsDirty
0275      */
0276     void layoutIsDirty();
0277 
0278     void foundAnnotation(KoShape *annotationShape, const QPointF &refPosition);
0279 
0280 public Q_SLOTS:
0281     /**
0282      * Does the layout of the text.
0283      * This method will layout the text into sections, tables and textlines,
0284      * chunk by chunk.
0285      * It may interrupt itself, @see contiuousLayout
0286      * calling this method when the layout is not dirty, doesn't take that much
0287      * time as it doesn't do much, although it does check every root area
0288      */
0289     virtual void layout();
0290 
0291     /**
0292      * Schedules a \a layout call for later using a QTimer::singleShot. Multiple calls
0293      * to this slot will be compressed into one layout-call to prevent calling layouting
0294      * to much. Also if meanwhile \a layout was called then the scheduled layout won't
0295      * be executed.
0296      */
0297     virtual void scheduleLayout();
0298 
0299     /**
0300      * Emits the \a layoutIsDirty signal.
0301      */
0302     void emitLayoutIsDirty();
0303 
0304 private Q_SLOTS:
0305     /// Called by \a scheduleLayout to start a \a layout run if not done already meanwhile.
0306     void executeScheduledLayout();
0307 
0308 protected:
0309     /// reimplemented
0310     void drawInlineObject(QPainter *painter, const QRectF &rect, QTextInlineObject object, int position, const QTextFormat &format) override;
0311     /// reimplemented
0312     void positionInlineObject(QTextInlineObject item, int position, const QTextFormat &format) override;
0313     /// reimplemented
0314     void resizeInlineObject(QTextInlineObject item, int position, const QTextFormat &format) override;
0315 
0316     /// should we continue layout when done with current root area
0317     bool continuousLayout() const;
0318 
0319     void registerInlineObject(const QTextInlineObject &inlineObject);
0320 
0321 private:
0322     class Private;
0323     Private * const d;
0324 
0325     bool doLayout();
0326     void updateProgress(const QTextFrame::iterator &it);
0327 };
0328 
0329 #endif